pinecrypt-gateway-backend/pinecrypt/server/api/signed.py

85 lines
3.4 KiB
Python
Raw Normal View History

import falcon
import logging
import json
import hashlib
from pinecrypt.server import authority, errors
from pinecrypt.server.decorators import csrf_protection
from .utils.firewall import login_required, authorize_admin
logger = logging.getLogger(__name__)
class SignedCertificateDetailResource(object):
def on_get_cn(self, req, resp, cn):
try:
id = authority.get_common_name_id(cn)
except ValueError:
raise falcon.HTTPNotFound("Unknown Common name",
"Object not found with common name %s" % cn)
id = authority.get_common_name_id(cn)
url = req.forwarded_uri.replace(cn,"id/%s" % id)
resp.status = falcon.HTTP_307
resp.location = url
def on_get(self, req, resp, id):
preferred_type = req.client_prefers(("application/json", "application/x-pem-file"))
try:
cert, cert_doc, pem_buf = authority.get_signed(mongo_id=id)
except errors.CertificateDoesNotExist:
logger.warning("Failed to serve non-existant certificate %s to %s",
id, req.context["remote"]["addr"])
raise falcon.HTTPNotFound()
cn = cert_doc["common_name"]
if preferred_type == "application/x-pem-file":
resp.set_header("Content-Type", "application/x-pem-file")
resp.set_header("Content-Disposition", ("attachment; filename=%s.pem" % cn))
resp.text = pem_buf
logger.debug("Served certificate %s to %s as application/x-pem-file",
cn, req.context["remote"]["addr"])
elif preferred_type == "application/json":
resp.set_header("Content-Type", "application/json")
resp.set_header("Content-Disposition", ("attachment; filename=%s.json" % cn))
try:
signer_username = cert_doc["user"]["signature"]["username"]
except KeyError:
signer_username = None
resp.text = json.dumps(dict(
common_name=cn,
id=str(cert_doc["_id"]),
signer=signer_username,
serial="%040x" % cert.serial_number,
organizational_unit=cert.subject.native.get("organizational_unit_name"),
signed=cert["tbs_certificate"]["validity"]["not_before"].native.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z",
expires=cert["tbs_certificate"]["validity"]["not_after"].native.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z",
sha256sum=hashlib.sha256(pem_buf).hexdigest(),
attributes=None,
lease=None,
extensions=dict([
(e["extn_id"].native, e["extn_value"].native)
for e in cert["tbs_certificate"]["extensions"]
if e["extn_id"].native in ("extended_key_usage",)])
))
logger.debug("Served certificate %s to %s as application/json",
cn, req.context["remote"]["addr"])
else:
logger.debug("Client did not accept application/json or application/x-pem-file")
raise falcon.HTTPUnsupportedMediaType(
"Client did not accept application/json or application/x-pem-file")
@csrf_protection
@login_required
@authorize_admin
def on_delete(self, req, resp, id):
authority.revoke(id,
reason=req.get_param("reason", default="key_compromise"),
user=req.context.get("user")
)