2018-05-15 07:45:29 +00:00
|
|
|
import click
|
|
|
|
import codecs
|
2017-04-22 11:10:54 +00:00
|
|
|
import falcon
|
2017-04-21 21:22:08 +00:00
|
|
|
import logging
|
2018-05-15 07:45:29 +00:00
|
|
|
import os
|
|
|
|
import string
|
2017-12-30 13:57:48 +00:00
|
|
|
from asn1crypto import pem
|
|
|
|
from asn1crypto.csr import CertificationRequest
|
2018-05-15 07:45:29 +00:00
|
|
|
from datetime import datetime, timedelta
|
2017-04-21 21:22:08 +00:00
|
|
|
from time import time
|
2018-05-15 07:45:29 +00:00
|
|
|
from certidude import mailer, const
|
|
|
|
from certidude.tokens import TokenManager
|
|
|
|
from certidude.relational import RelationalMixin
|
2017-12-30 13:57:48 +00:00
|
|
|
from certidude.decorators import serialize
|
2017-04-21 21:22:08 +00:00
|
|
|
from certidude.user import User
|
2018-02-03 11:00:23 +00:00
|
|
|
from certidude import config
|
2018-02-03 11:10:45 +00:00
|
|
|
from .utils import AuthorityHandler
|
2018-05-02 08:11:01 +00:00
|
|
|
from .utils.firewall import login_required, authorize_admin
|
2017-04-21 21:22:08 +00:00
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2018-02-03 11:10:45 +00:00
|
|
|
class TokenResource(AuthorityHandler):
|
2018-05-15 07:45:29 +00:00
|
|
|
def __init__(self, authority, manager):
|
|
|
|
AuthorityHandler.__init__(self, authority)
|
|
|
|
self.manager = manager
|
2017-04-21 21:22:08 +00:00
|
|
|
|
2018-05-15 07:45:29 +00:00
|
|
|
def on_put(self, req, resp):
|
|
|
|
try:
|
|
|
|
username, mail, created, expires, profile = self.manager.consume(req.get_param("token", required=True))
|
|
|
|
except RelationalMixin.DoesNotExist:
|
|
|
|
raise falcon.HTTPForbidden("Forbidden", "No such token or token expired")
|
2017-12-30 13:57:48 +00:00
|
|
|
body = req.stream.read(req.content_length)
|
|
|
|
header, _, der_bytes = pem.unarmor(body)
|
|
|
|
csr = CertificationRequest.load(der_bytes)
|
|
|
|
common_name = csr["certification_request_info"]["subject"].native["common_name"]
|
2018-05-20 13:46:27 +00:00
|
|
|
if not common_name.startswith(username + "@"):
|
|
|
|
raise falcon.HTTPBadRequest("Bad requst", "Invalid common name %s" % common_name)
|
2017-12-30 13:57:48 +00:00
|
|
|
try:
|
2018-05-15 07:45:29 +00:00
|
|
|
_, resp.body = self.authority._sign(csr, body, profile=config.PROFILES.get(profile),
|
2018-04-09 13:08:12 +00:00
|
|
|
overwrite=config.TOKEN_OVERWRITE_PERMITTED)
|
2017-12-30 13:57:48 +00:00
|
|
|
resp.set_header("Content-Type", "application/x-pem-file")
|
|
|
|
logger.info("Autosigned %s as proven by token ownership", common_name)
|
|
|
|
except FileExistsError:
|
|
|
|
logger.info("Won't autosign duplicate %s", common_name)
|
|
|
|
raise falcon.HTTPConflict(
|
|
|
|
"Certificate with such common name (CN) already exists",
|
|
|
|
"Will not overwrite existing certificate signing request, explicitly delete existing one and try again")
|
2017-04-21 21:22:08 +00:00
|
|
|
|
|
|
|
|
2017-12-30 13:57:48 +00:00
|
|
|
@serialize
|
2017-04-21 21:22:08 +00:00
|
|
|
@login_required
|
|
|
|
@authorize_admin
|
|
|
|
def on_post(self, req, resp):
|
2018-05-15 07:45:29 +00:00
|
|
|
self.manager.issue(
|
|
|
|
issuer = req.context.get("user"),
|
|
|
|
subject = User.objects.get(req.get_param("username", required=True)),
|
|
|
|
subject_mail = req.get_param("mail"))
|