85 lines
3.4 KiB
Python
85 lines
3.4 KiB
Python
|
|
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")
|
|
)
|
|
|