Example #1
0
def cms_sign_data(data_to_sign, signing_cert_file_name, signing_key_file_name,
                  outform=PKI_ASN1_FORM,
                  message_digest=DEFAULT_TOKEN_DIGEST_ALGORITHM):
    """Uses OpenSSL to sign a document.

    Produces a Base64 encoding of a DER formatted CMS Document
    http://en.wikipedia.org/wiki/Cryptographic_Message_Syntax

    :param data_to_sign: data to sign
    :param signing_cert_file_name:  path to the X509 certificate containing
        the public key associated with the private key used to sign the data
    :param signing_key_file_name: path to the private key used to sign
        the data
    :param outform: Format for the signed document PKIZ_CMS_FORM or
        PKI_ASN1_FORM
    :param message_digest: Digest algorithm to use when signing or resigning

    """
    _ensure_subprocess()
    if isinstance(data_to_sign, six.string_types):
        data = bytearray(data_to_sign, encoding='utf-8')
    else:
        data = data_to_sign
    process = subprocess.Popen(['openssl', 'cms', '-sign',
                                '-signer', signing_cert_file_name,
                                '-inkey', signing_key_file_name,
                                '-outform', 'PEM',
                                '-nosmimecap', '-nodetach',
                                '-nocerts', '-noattr',
                                '-md', message_digest, ],
                               stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               close_fds=True)

    output, err, retcode = _process_communicate_handle_oserror(
        process, data, (signing_cert_file_name, signing_key_file_name))

    if retcode != OpensslCmsExitStatus.SUCCESS or ('Error' in err):
        if retcode == OpensslCmsExitStatus.CREATE_CMS_READ_MIME_ERROR:
            LOG.error(_LE('Signing error: Unable to load certificate - '
                          'ensure you have configured PKI with '
                          '"keystone-manage pki_setup"'))
        else:
            LOG.error(_LE('Signing error: %s'), err)
        raise subprocess.CalledProcessError(retcode, 'openssl')
    if outform == PKI_ASN1_FORM:
        return output.decode('utf-8')
    else:
        return output
Example #2
0
def cms_sign_data(data_to_sign, signing_cert_file_name, signing_key_file_name,
                  outform=PKI_ASN1_FORM,
                  message_digest=DEFAULT_TOKEN_DIGEST_ALGORITHM):
    """Uses OpenSSL to sign a document.

    Produces a Base64 encoding of a DER formatted CMS Document
    http://en.wikipedia.org/wiki/Cryptographic_Message_Syntax

    :param data_to_sign: data to sign
    :param signing_cert_file_name:  path to the X509 certificate containing
        the public key associated with the private key used to sign the data
    :param signing_key_file_name: path to the private key used to sign
        the data
    :param outform: Format for the signed document PKIZ_CMS_FORM or
        PKI_ASN1_FORM
    :param message_digest: Digest algorithm to use when signing or resigning

    """
    _ensure_subprocess()
    if isinstance(data_to_sign, six.string_types):
        data = bytearray(data_to_sign, encoding='utf-8')
    else:
        data = data_to_sign
    process = subprocess.Popen(['openssl', 'cms', '-sign',
                                '-signer', signing_cert_file_name,
                                '-inkey', signing_key_file_name,
                                '-outform', 'PEM',
                                '-nosmimecap', '-nodetach',
                                '-nocerts', '-noattr',
                                '-md', message_digest, ],
                               stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               close_fds=True)

    output, err, retcode = _process_communicate_handle_oserror(
        process, data, (signing_cert_file_name, signing_key_file_name))

    if retcode != OpensslCmsExitStatus.SUCCESS or ('Error' in err):
        if retcode == OpensslCmsExitStatus.CREATE_CMS_READ_MIME_ERROR:
            LOG.error(_LE('Signing error: Unable to load certificate - '
                          'ensure you have configured PKI with '
                          '"keystone-manage pki_setup"'))
        else:
            LOG.error(_LE('Signing error: %s'), err)
        raise subprocess.CalledProcessError(retcode, 'openssl')
    if outform == PKI_ASN1_FORM:
        return output.decode('utf-8')
    else:
        return output
Example #3
0
    def _check_keystone_extensions(self, url):
        """Call Keystone URL and detects the available extensions."""
        try:
            if not url.endswith("/"):
                url += '/'
            resp, body = self._request("%sextensions" % url, "GET",
                                       headers={'Accept':
                                                'application/json'})
            if resp.status_code in (200, 204):  # some cases we get No Content
                if 'extensions' in body and 'values' in body['extensions']:
                    # Parse correct format (per contract)
                    extensions = body['extensions']['values']
                elif 'extensions' in body:
                    # Support incorrect, but prevalent format
                    extensions = body['extensions']
                else:
                    return dict(message=(
                        _('Unrecognized extensions response from %s') % url))

                return dict(self._get_extension_info(e) for e in extensions)
            elif resp.status_code == 305:
                return self._check_keystone_extensions(resp['location'])
            else:
                raise exceptions.from_response(
                    resp, "GET", "%sextensions" % url)
        except Exception:
            _logger.exception(_LE('Failed to check keystone extensions.'))
Example #4
0
    def _check_keystone_extensions(self, url):
        """Call Keystone URL and detects the available extensions."""
        try:
            if not url.endswith("/"):
                url += '/'
            resp, body = self._request("%sextensions" % url,
                                       "GET",
                                       headers={'Accept': 'application/json'})
            if resp.status_code in (200, 204):  # some cases we get No Content
                if 'extensions' in body and 'values' in body['extensions']:
                    # Parse correct format (per contract)
                    extensions = body['extensions']['values']
                elif 'extensions' in body:
                    # Support incorrect, but prevalent format
                    extensions = body['extensions']
                else:
                    return dict(message=(
                        _('Unrecognized extensions response from %s') % url))

                return dict(self._get_extension_info(e) for e in extensions)
            elif resp.status_code == 305:
                return self._check_keystone_extensions(resp['location'])
            else:
                raise exceptions.from_response(resp, "GET",
                                               "%sextensions" % url)
        except Exception:
            _logger.exception(_LE('Failed to check keystone extensions.'))
Example #5
0
 def _check_keystone_versions(self, url):
     """Call Keystone URL and detects the available API versions."""
     try:
         resp, body = self._request(url,
                                    "GET",
                                    headers={'Accept': 'application/json'})
         # Multiple Choices status code is returned by the root
         # identity endpoint, with references to one or more
         # Identity API versions -- v3 spec
         # some cases we get No Content
         if resp.status_code in (200, 204, 300):
             try:
                 results = {}
                 if 'version' in body:
                     results['message'] = _("Keystone found at %s") % url
                     version = body['version']
                     # Stable/diablo incorrect format
                     id, status, version_url = (self._get_version_info(
                         version, url))
                     results[str(id)] = {
                         "id": id,
                         "status": status,
                         "url": version_url
                     }
                     return results
                 elif 'versions' in body:
                     # Correct format
                     results['message'] = _("Keystone found at %s") % url
                     for version in body['versions']['values']:
                         id, status, version_url = (self._get_version_info(
                             version, url))
                         results[str(id)] = {
                             "id": id,
                             "status": status,
                             "url": version_url
                         }
                     return results
                 else:
                     results['message'] = (
                         _("Unrecognized response from %s") % url)
                 return results
             except KeyError:
                 raise exceptions.AuthorizationFailure()
         elif resp.status_code == 305:
             return self._check_keystone_versions(resp['location'])
         else:
             raise exceptions.from_response(resp, "GET", url)
     except Exception:
         _logger.exception(_LE('Failed to detect available versions.'))
Example #6
0
 def _check_keystone_versions(self, url):
     """Call Keystone URL and detects the available API versions."""
     try:
         resp, body = self._request(url, "GET",
                                    headers={'Accept':
                                             'application/json'})
         # Multiple Choices status code is returned by the root
         # identity endpoint, with references to one or more
         # Identity API versions -- v3 spec
         # some cases we get No Content
         if resp.status_code in (200, 204, 300):
             try:
                 results = {}
                 if 'version' in body:
                     results['message'] = _("Keystone found at %s") % url
                     version = body['version']
                     # Stable/diablo incorrect format
                     id, status, version_url = (
                         self._get_version_info(version, url))
                     results[str(id)] = {"id": id,
                                         "status": status,
                                         "url": version_url}
                     return results
                 elif 'versions' in body:
                     # Correct format
                     results['message'] = _("Keystone found at %s") % url
                     for version in body['versions']['values']:
                         id, status, version_url = (
                             self._get_version_info(version, url))
                         results[str(id)] = {"id": id,
                                             "status": status,
                                             "url": version_url}
                     return results
                 else:
                     results['message'] = (
                         _("Unrecognized response from %s") % url)
                 return results
             except KeyError:
                 raise exceptions.AuthorizationFailure()
         elif resp.status_code == 305:
             return self._check_keystone_versions(resp['location'])
         else:
             raise exceptions.from_response(resp, "GET", url)
     except Exception:
         _logger.exception(_LE('Failed to detect available versions.'))