def __init__(self, module, backend):
        super(AcmeCertificateBackend, self).__init__(module, backend)
        self.accountkey_path = module.params['acme_accountkey_path']
        self.challenge_path = module.params['acme_challenge_path']
        self.use_chain = module.params['acme_chain']
        self.acme_directory = module.params['acme_directory']

        if self.csr_content is None and self.csr_path is None:
            raise CertificateError(
                'csr_path or csr_content is required for ownca provider')
        if self.csr_content is None and not os.path.exists(self.csr_path):
            raise CertificateError(
                'The certificate signing request file %s does not exist' %
                self.csr_path)

        if not os.path.exists(self.accountkey_path):
            raise CertificateError('The account key %s does not exist' %
                                   self.accountkey_path)

        if not os.path.exists(self.challenge_path):
            raise CertificateError('The challenge path %s does not exist' %
                                   self.challenge_path)

        self.acme_tiny_path = self.module.get_bin_path('acme-tiny',
                                                       required=True)
Example #2
0
    def __init__(self, module):
        super(OwnCACertificateBackendCryptography, self).__init__(module, 'cryptography')

        self.create_subject_key_identifier = module.params['ownca_create_subject_key_identifier']
        self.create_authority_key_identifier = module.params['ownca_create_authority_key_identifier']
        self.notBefore = get_relative_time_option(module.params['ownca_not_before'], 'ownca_not_before', backend=self.backend)
        self.notAfter = get_relative_time_option(module.params['ownca_not_after'], 'ownca_not_after', backend=self.backend)
        self.digest = select_message_digest(module.params['ownca_digest'])
        self.version = module.params['ownca_version']
        self.serial_number = x509.random_serial_number()
        self.ca_cert_path = module.params['ownca_path']
        self.ca_cert_content = module.params['ownca_content']
        if self.ca_cert_content is not None:
            self.ca_cert_content = self.ca_cert_content.encode('utf-8')
        self.ca_privatekey_path = module.params['ownca_privatekey_path']
        self.ca_privatekey_content = module.params['ownca_privatekey_content']
        if self.ca_privatekey_content is not None:
            self.ca_privatekey_content = self.ca_privatekey_content.encode('utf-8')
        self.ca_privatekey_passphrase = module.params['ownca_privatekey_passphrase']

        if self.csr_content is None and self.csr_path is None:
            raise CertificateError(
                'csr_path or csr_content is required for ownca provider'
            )
        if self.csr_content is None and not os.path.exists(self.csr_path):
            raise CertificateError(
                'The certificate signing request file {0} does not exist'.format(self.csr_path)
            )
        if self.ca_cert_content is None and not os.path.exists(self.ca_cert_path):
            raise CertificateError(
                'The CA certificate file {0} does not exist'.format(self.ca_cert_path)
            )
        if self.ca_privatekey_content is None and not os.path.exists(self.ca_privatekey_path):
            raise CertificateError(
                'The CA private key file {0} does not exist'.format(self.ca_privatekey_path)
            )

        self._ensure_csr_loaded()
        self.ca_cert = load_certificate(
            path=self.ca_cert_path,
            content=self.ca_cert_content,
            backend=self.backend
        )
        try:
            self.ca_private_key = load_privatekey(
                path=self.ca_privatekey_path,
                content=self.ca_privatekey_content,
                passphrase=self.ca_privatekey_passphrase,
                backend=self.backend
            )
        except OpenSSLBadPassphraseError as exc:
            module.fail_json(msg=str(exc))

        if cryptography_key_needs_digest_for_signing(self.ca_private_key):
            if self.digest is None:
                raise CertificateError(
                    'The digest %s is not supported with the cryptography backend' % module.params['ownca_digest']
                )
        else:
            self.digest = None
Example #3
0
    def __init__(self, module, backend):
        super(EntrustCertificateBackend, self).__init__(module, backend)
        self.trackingId = None
        self.notAfter = get_relative_time_option(module.params['entrust_not_after'], 'entrust_not_after', backend=self.backend)

        if self.csr_content is None and self.csr_path is None:
            raise CertificateError(
                'csr_path or csr_content is required for entrust provider'
            )
        if self.csr_content is None and not os.path.exists(self.csr_path):
            raise CertificateError(
                'The certificate signing request file {0} does not exist'.format(self.csr_path)
            )

        self._ensure_csr_loaded()

        # ECS API defaults to using the validated organization tied to the account.
        # We want to always force behavior of trying to use the organization provided in the CSR.
        # To that end we need to parse out the organization from the CSR.
        self.csr_org = None
        if self.backend == 'pyopenssl':
            csr_subject = self.csr.get_subject()
            csr_subject_components = csr_subject.get_components()
            for k, v in csr_subject_components:
                if k.upper() == 'O':
                    # Entrust does not support multiple validated organizations in a single certificate
                    if self.csr_org is not None:
                        self.module.fail_json(msg=("Entrust provider does not currently support multiple validated organizations. Multiple organizations "
                                                   "found in Subject DN: '{0}'. ".format(csr_subject)))
                    else:
                        self.csr_org = v
        elif self.backend == 'cryptography':
            csr_subject_orgs = self.csr.subject.get_attributes_for_oid(NameOID.ORGANIZATION_NAME)
            if len(csr_subject_orgs) == 1:
                self.csr_org = csr_subject_orgs[0].value
            elif len(csr_subject_orgs) > 1:
                self.module.fail_json(msg=("Entrust provider does not currently support multiple validated organizations. Multiple organizations found in "
                                           "Subject DN: '{0}'. ".format(self.csr.subject)))
        # If no organization in the CSR, explicitly tell ECS that it should be blank in issued cert, not defaulted to
        # organization tied to the account.
        if self.csr_org is None:
            self.csr_org = ''

        try:
            self.ecs_client = ECSClient(
                entrust_api_user=self.module.params['entrust_api_user'],
                entrust_api_key=self.module.params['entrust_api_key'],
                entrust_api_cert=self.module.params['entrust_api_client_cert_path'],
                entrust_api_cert_key=self.module.params['entrust_api_client_cert_key_path'],
                entrust_api_specification_path=self.module.params['entrust_api_specification_path']
            )
        except SessionConfigurationException as e:
            module.fail_json(msg='Failed to initialize Entrust Provider: {0}'.format(to_native(e.message)))
Example #4
0
    def __init__(self, module):
        super(OwnCACertificateBackendPyOpenSSL, self).__init__(module, 'pyopenssl')

        self.notBefore = get_relative_time_option(self.module.params['ownca_not_before'], 'ownca_not_before', backend=self.backend)
        self.notAfter = get_relative_time_option(self.module.params['ownca_not_after'], 'ownca_not_after', backend=self.backend)
        self.digest = self.module.params['ownca_digest']
        self.version = self.module.params['ownca_version']
        self.serial_number = generate_serial_number()
        if self.module.params['ownca_create_subject_key_identifier'] != 'create_if_not_provided':
            self.module.fail_json(msg='ownca_create_subject_key_identifier cannot be used with the pyOpenSSL backend!')
        if self.module.params['ownca_create_authority_key_identifier']:
            self.module.warn('ownca_create_authority_key_identifier is ignored by the pyOpenSSL backend!')
        self.ca_cert_path = self.module.params['ownca_path']
        self.ca_cert_content = self.module.params['ownca_content']
        if self.ca_cert_content is not None:
            self.ca_cert_content = self.ca_cert_content.encode('utf-8')
        self.ca_privatekey_path = self.module.params['ownca_privatekey_path']
        self.ca_privatekey_content = self.module.params['ownca_privatekey_content']
        if self.ca_privatekey_content is not None:
            self.ca_privatekey_content = self.ca_privatekey_content.encode('utf-8')
        self.ca_privatekey_passphrase = self.module.params['ownca_privatekey_passphrase']

        if self.csr_content is None and not os.path.exists(self.csr_path):
            raise CertificateError(
                'The certificate signing request file {0} does not exist'.format(self.csr_path)
            )
        if self.ca_cert_content is None and not os.path.exists(self.ca_cert_path):
            raise CertificateError(
                'The CA certificate file {0} does not exist'.format(self.ca_cert_path)
            )
        if self.ca_privatekey_content is None and not os.path.exists(self.ca_privatekey_path):
            raise CertificateError(
                'The CA private key file {0} does not exist'.format(self.ca_privatekey_path)
            )

        self._ensure_csr_loaded()
        self.ca_cert = load_certificate(
            path=self.ca_cert_path,
            content=self.ca_cert_content,
        )
        try:
            self.ca_privatekey = load_privatekey(
                path=self.ca_privatekey_path,
                content=self.ca_privatekey_content,
                passphrase=self.ca_privatekey_passphrase
            )
        except OpenSSLBadPassphraseError as exc:
            self.module.fail_json(msg=str(exc))
Example #5
0
    def generate_certificate(self):
        """(Re-)Generate certificate."""

        command = [self.acme_tiny_path]
        if self.use_chain:
            command.append('--chain')
        command.extend(['--account-key', self.accountkey_path])
        if self.csr_content is not None:
            # We need to temporarily write the CSR to disk
            fd, tmpsrc = tempfile.mkstemp()
            self.module.add_cleanup_file(tmpsrc)  # Ansible will delete the file on exit
            f = os.fdopen(fd, 'wb')
            try:
                f.write(self.csr_content)
            except Exception as err:
                try:
                    f.close()
                except Exception as dummy:
                    pass
                self.module.fail_json(
                    msg="failed to create temporary CSR file: %s" % to_native(err),
                    exception=traceback.format_exc()
                )
            f.close()
            command.extend(['--csr', tmpsrc])
        else:
            command.extend(['--csr', self.csr_path])
        command.extend(['--acme-dir', self.challenge_path])
        command.extend(['--directory-url', self.acme_directory])

        try:
            self.cert = to_bytes(self.module.run_command(command, check_rc=True)[1])
        except OSError as exc:
            raise CertificateError(exc)
Example #6
0
    def __init__(self, module):
        super(SelfSignedCertificateBackendPyOpenSSL,
              self).__init__(module, 'pyopenssl')

        if module.params[
                'selfsigned_create_subject_key_identifier'] != 'create_if_not_provided':
            module.fail_json(
                msg=
                'selfsigned_create_subject_key_identifier cannot be used with the pyOpenSSL backend!'
            )
        self.notBefore = get_relative_time_option(
            module.params['selfsigned_not_before'],
            'selfsigned_not_before',
            backend=self.backend)
        self.notAfter = get_relative_time_option(
            module.params['selfsigned_not_after'],
            'selfsigned_not_after',
            backend=self.backend)
        self.digest = module.params['selfsigned_digest']
        self.version = module.params['selfsigned_version']
        self.serial_number = generate_serial_number()

        if self.csr_path is not None and not os.path.exists(self.csr_path):
            raise CertificateError(
                'The certificate signing request file {0} does not exist'.
                format(self.csr_path))
        if self.privatekey_content is None and not os.path.exists(
                self.privatekey_path):
            raise CertificateError(
                'The private key file {0} does not exist'.format(
                    self.privatekey_path))

        self._ensure_private_key_loaded()

        self._ensure_csr_loaded()
        if self.csr is None:
            # Create empty CSR on the fly
            self.csr = crypto.X509Req()
            self.csr.set_pubkey(self.privatekey)
            self.csr.sign(self.privatekey, self.digest)
Example #7
0
    def generate_certificate(self):
        """(Re-)Generate certificate."""
        try:
            cert_builder = x509.CertificateBuilder()
            cert_builder = cert_builder.subject_name(self.csr.subject)
            cert_builder = cert_builder.issuer_name(self.csr.subject)
            cert_builder = cert_builder.serial_number(self.serial_number)
            cert_builder = cert_builder.not_valid_before(self.notBefore)
            cert_builder = cert_builder.not_valid_after(self.notAfter)
            cert_builder = cert_builder.public_key(
                self.privatekey.public_key())
            has_ski = False
            for extension in self.csr.extensions:
                if isinstance(extension.value, x509.SubjectKeyIdentifier):
                    if self.create_subject_key_identifier == 'always_create':
                        continue
                    has_ski = True
                cert_builder = cert_builder.add_extension(
                    extension.value, critical=extension.critical)
            if not has_ski and self.create_subject_key_identifier != 'never_create':
                cert_builder = cert_builder.add_extension(
                    x509.SubjectKeyIdentifier.from_public_key(
                        self.privatekey.public_key()),
                    critical=False)
        except ValueError as e:
            raise CertificateError(str(e))

        try:
            certificate = cert_builder.sign(private_key=self.privatekey,
                                            algorithm=self.digest,
                                            backend=default_backend())
        except TypeError as e:
            if str(
                    e
            ) == 'Algorithm must be a registered hash algorithm.' and self.digest is None:
                self.module.fail_json(
                    msg=
                    'Signing with Ed25519 and Ed448 keys requires cryptography 2.8 or newer.'
                )
            raise

        self.cert = certificate
Example #8
0
    def __init__(self, module):
        super(SelfSignedCertificateBackendCryptography,
              self).__init__(module, 'cryptography')

        self.create_subject_key_identifier = module.params[
            'selfsigned_create_subject_key_identifier']
        self.notBefore = get_relative_time_option(
            module.params['selfsigned_not_before'],
            'selfsigned_not_before',
            backend=self.backend)
        self.notAfter = get_relative_time_option(
            module.params['selfsigned_not_after'],
            'selfsigned_not_after',
            backend=self.backend)
        self.digest = select_message_digest(module.params['selfsigned_digest'])
        self.version = module.params['selfsigned_version']
        self.serial_number = x509.random_serial_number()

        if self.csr_path is not None and not os.path.exists(self.csr_path):
            raise CertificateError(
                'The certificate signing request file {0} does not exist'.
                format(self.csr_path))
        if self.privatekey_content is None and not os.path.exists(
                self.privatekey_path):
            raise CertificateError(
                'The private key file {0} does not exist'.format(
                    self.privatekey_path))

        self._module = module

        self._ensure_private_key_loaded()

        self._ensure_csr_loaded()
        if self.csr is None:
            # Create empty CSR on the fly
            csr = cryptography.x509.CertificateSigningRequestBuilder()
            csr = csr.subject_name(cryptography.x509.Name([]))
            digest = None
            if cryptography_key_needs_digest_for_signing(self.privatekey):
                digest = self.digest
                if digest is None:
                    self.module.fail_json(
                        msg='Unsupported digest "{0}"'.format(
                            module.params['selfsigned_digest']))
            try:
                self.csr = csr.sign(self.privatekey, digest, default_backend())
            except TypeError as e:
                if str(
                        e
                ) == 'Algorithm must be a registered hash algorithm.' and digest is None:
                    self.module.fail_json(
                        msg=
                        'Signing with Ed25519 and Ed448 keys requires cryptography 2.8 or newer.'
                    )
                raise

        if cryptography_key_needs_digest_for_signing(self.privatekey):
            if self.digest is None:
                raise CertificateError(
                    'The digest %s is not supported with the cryptography backend'
                    % module.params['selfsigned_digest'])
        else:
            self.digest = None