def upload_push_certificate_private(): """Upload a push certificate pubkey to the MDM. The type of certificate encoding will be guessed from the Content-Type header in the request. TODO: The reason for invalid certificate should be part of a json response :reqheader Accept: application/json :reqheader Content-Type: application/pkcs8 :statuscode 204: no error :statuscode 400: invalid certificate supplied """ if request.headers['Content-Type'] not in [ 'application/x-pem-file', 'application/pkcs8' ]: abort(400, 'Invalid Content-Type supplied for private key') if request.headers['Content-Type'] == 'application/x-pem-file': pk = RSAPrivateKey(pem_key=request.data) else: crypto_key = serialization.rsa_from_der(request.data) pk = RSAPrivateKey(pem_key=serialization.rsa_to_pem(crypto_key)) db.session.add(pk) db.session.commit() return None, 204, None
def generate_push_certificate_csr(): """Generate a signed push certificate for upload to the Apple Push Certificate Portal. :resheader Content-Type: application/x-pem-file :resheader Content-Type: application/x-x509-user-cert :resheader Content-Type: application/x-x509-ca-cert """ private_key, csr = ssl.generate_signing_request('commandment') private_key_model = RSAPrivateKey.from_crypto(private_key) db.session.add(private_key_model) csr_model = CertificateSigningRequest.from_crypto(csr) db.session.add(csr_model) encrypt_with = db.session.query(CACertificate).filter_by( x509_cn='COMMANDMENT-CA').one() base64_csr = b64encode(csr_model.pem_data) base64_recipient = b64encode(encrypt_with.pem_data) mdmcert_dict = { 'csr': base64_csr.decode('utf8'), 'email': '*****@*****.**', 'key': MDMCERT_API_KEY, 'encrypt': base64_recipient.decode('utf8'), }
def test_rsa_privatekey_from_crypto(self, private_key: rsa.RSAPrivateKeyWithSerialization, session): m = RSAPrivateKey.from_crypto(private_key) session.add(m) session.commit() assert m.id is not None assert m.pem_data is not None
def create(cls, common_name: str = 'COMMANDMENT-CA', key_size=2048): ca = cls() ca.common_name = common_name name = x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, common_name), x509.NameAttribute(NameOID.ORGANIZATION_NAME, 'commandment') ]) private_key = rsa.generate_private_key( public_exponent=65537, key_size=key_size, backend=default_backend(), ) ca.rsa_private_key = RSAPrivateKey.from_crypto(private_key) certificate = x509.CertificateBuilder().subject_name(name).issuer_name( name).public_key(private_key.public_key()).serial_number( x509.random_serial_number()).not_valid_before( datetime.datetime.utcnow()).not_valid_after( datetime.datetime.utcnow() + datetime.timedelta(days=365)).add_extension( x509.BasicConstraints(ca=True, path_length=None), True).sign(private_key, hashes.SHA256(), default_backend()) ca_certificate_model = CACertificate.from_crypto(certificate) ca.certificate = ca_certificate_model db.session.add(ca) db.session.commit() return ca
def mdmcert_request(email: str): """Ask the mdmcert.download service to generate a new Certificate Signing Request for the given e-mail address. If an encryption certificate does not exist on the system, one will be generated to process the resulting encrypted and signed CSR. :reqheader Accept: application/json :resheader Content-Type: application/json """ try: apns_csr_model = db.session.query(CertificateSigningRequest).\ filter(CertificateSigningRequest.x509_cn == "commandment-apns").one() except NoResultFound: private_key, csr = cmdssl.generate_signing_request('commandment-apns') private_key_model = RSAPrivateKey.from_crypto(private_key) db.session.add(private_key_model) apns_csr_model = CertificateSigningRequest.from_crypto(csr) apns_csr_model.rsa_private_key = private_key_model db.session.add(apns_csr_model) db.session.commit() try: encrypt_cert_model = db.session.query(EncryptionCertificate).\ filter(EncryptionCertificate.x509_cn == 'MDMCERT-DECRYPT').one() except NoResultFound: encrypt_key, encrypt_with_cert = cmdssl.generate_self_signed_certificate( 'MDMCERT-DECRYPT') encrypt_key_model = RSAPrivateKey.from_crypto(encrypt_key) db.session.add(encrypt_key_model) encrypt_cert_model = EncryptionCertificate.from_crypto( encrypt_with_cert) encrypt_cert_model.rsa_private_key = encrypt_key_model db.session.add(encrypt_cert_model) db.session.commit() mdmcert_result = submit_mdmcert_request( email=email, csr_pem=apns_csr_model.pem_data, encrypt_with_pem=encrypt_cert_model.pem_data, ) return jsonify(mdmcert_result)
def generate_ca(app: Flask): """Generate internal CA certificate for sandbox setups.""" with app.app_context(): try: ca_certificate = db.session.query(CACertificate).filter_by(x509_cn='COMMANDMENT-CA').one() logger.debug("COMMANDMENT-CA already generated") except sqlalchemy.orm.exc.MultipleResultsFound: logger.error("Multiple COMMANDMENT-CA Certificates were found, this should never happen.") except sqlalchemy.orm.exc.NoResultFound: logger.debug("Generating Private Key for COMMANDMENT-CA") # Create CA Certificate if not Available to bootstrap internal CA # Issue a Certificate to receive encrypted replies from mdmcert.download key = rsa.generate_private_key( public_exponent=65537, key_size=2048, backend=default_backend() ) key_model = RSAPrivateKey.from_crypto(key) db.session.add(key_model) subject = issuer = x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, "COMMANDMENT-CA"), x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Commandment") ]) logger.debug("Generating CA Certificate for COMMANDMENT-CA") cert = x509.CertificateBuilder().subject_name( subject ).issuer_name( issuer ).public_key( key.public_key() ).serial_number( x509.random_serial_number() ).not_valid_before( datetime.datetime.utcnow() ).not_valid_after( datetime.datetime.utcnow() + datetime.timedelta(days=900) ).add_extension( x509.BasicConstraints(ca=True, path_length=None), critical=True ).sign(key, hashes.SHA256(), default_backend()) cert_model = CACertificate.from_crypto(cert) db.session.add(cert_model) db.session.commit()
def certificate_download(): """Create a new key/certificate to upload to the DEP/ASM/ABM portal. The private key generated for this certificate will be the key recipient of the DEP S/MIME payload. """ try: certificate_model = db.session.query( DEPServerTokenCertificate).filter_by( x509_cn='COMMANDMENT-DEP').one() except sqlalchemy.orm.exc.NoResultFound: ca = get_ca() private_key = rsa.generate_private_key( public_exponent=65537, key_size=2048, backend=default_backend(), ) private_key_model = RSAPrivateKey.from_crypto(private_key) db.session.add(private_key_model) name = x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, 'COMMANDMENT-DEP'), x509.NameAttribute(NameOID.ORGANIZATION_NAME, 'commandment') ]) builder = x509.CertificateSigningRequestBuilder() builder = builder.subject_name(name) builder = builder.add_extension(x509.BasicConstraints( ca=False, path_length=None), critical=True) request = builder.sign(private_key, hashes.SHA256(), default_backend()) request_model = CertificateSigningRequest.from_crypto(request) db.session.add(request_model) certificate = ca.sign(request) certificate_model = DEPServerTokenCertificate.from_crypto(certificate) db.session.add(certificate_model) db.session.commit() return certificate_model.pem_data, 200, { 'Content-Type': 'application/x-x509-ca-cert', 'Content-Disposition': 'attachment; filename="commandment-dep.cer"' }
def create_device_csr(self, common_name: str) -> (rsa.RSAPrivateKeyWithSerialization, x509.CertificateSigningRequest): """ Create a Certificate Signing Request with the specified Common Name. The private key model is automatically committed to the database. This is also true for the certificate signing request. Args: common_name (str): The certificate Common Name attribute Returns: Tuple[rsa.RSAPrivateKeyWithSerialization, x509.CertificateSigningRequest] - A tuple containing the RSA Private key that was generated, along with the CSR. """ private_key = rsa.generate_private_key( public_exponent=65537, key_size=2048, backend=default_backend(), ) private_key_model = RSAPrivateKey.from_crypto(private_key) db.session.add(private_key_model) db.session.commit() name = x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, common_name), x509.NameAttribute(NameOID.ORGANIZATION_NAME, 'commandment') ]) builder = x509.CertificateSigningRequestBuilder() builder = builder.subject_name(name) builder = builder.add_extension(x509.BasicConstraints(ca=False, path_length=None), critical=True) request = builder.sign( private_key, hashes.SHA256(), default_backend() ) csr_model = CertificateSigningRequest().from_crypto(request) db.session.add(csr_model) db.session.commit() return private_key, request