"Fossies" - the Fresh Open Source Software Archive

Member "keystone-17.0.0/keystone/api/s3tokens.py" (13 May 2020, 4256 Bytes) of package /linux/misc/openstack/keystone-17.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "s3tokens.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 16.0.1_vs_17.0.0.

    1 # Licensed under the Apache License, Version 2.0 (the "License"); you may
    2 # not use this file except in compliance with the License. You may obtain
    3 # a copy of the License at
    4 #
    5 #      http://www.apache.org/licenses/LICENSE-2.0
    6 #
    7 # Unless required by applicable law or agreed to in writing, software
    8 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    9 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   10 # License for the specific language governing permissions and limitations
   11 # under the License.
   12 
   13 # This file handles all flask-restful resources for /v3/s3tokens
   14 
   15 import base64
   16 import hashlib
   17 import hmac
   18 
   19 import flask
   20 import http.client
   21 from oslo_serialization import jsonutils
   22 
   23 from keystone.api._shared import EC2_S3_Resource
   24 from keystone.api._shared import json_home_relations
   25 from keystone.common import render_token
   26 from keystone.common import utils
   27 from keystone import exception
   28 from keystone.i18n import _
   29 from keystone.server import flask as ks_flask
   30 
   31 
   32 def _calculate_signature_v1(string_to_sign, secret_key):
   33     """Calculate a v1 signature.
   34 
   35     :param bytes string_to_sign: String that contains request params and
   36                                  is used for calculate signature of request
   37     :param text secret_key: Second auth key of EC2 account that is used to
   38                             sign requests
   39     """
   40     key = str(secret_key).encode('utf-8')
   41     b64_encode = base64.encodebytes
   42     signed = b64_encode(hmac.new(key, string_to_sign, hashlib.sha1)
   43                         .digest()).decode('utf-8').strip()
   44     return signed
   45 
   46 
   47 def _calculate_signature_v4(string_to_sign, secret_key):
   48     """Calculate a v4 signature.
   49 
   50     :param bytes string_to_sign: String that contains request params and
   51                                  is used for calculate signature of request
   52     :param text secret_key: Second auth key of EC2 account that is used to
   53                             sign requests
   54     """
   55     parts = string_to_sign.split(b'\n')
   56     if len(parts) != 4 or parts[0] != b'AWS4-HMAC-SHA256':
   57         raise exception.Unauthorized(message=_('Invalid EC2 signature.'))
   58     scope = parts[2].split(b'/')
   59     if len(scope) != 4 or scope[2] != b's3' or scope[3] != b'aws4_request':
   60         raise exception.Unauthorized(message=_('Invalid EC2 signature.'))
   61 
   62     def _sign(key, msg):
   63         return hmac.new(key, msg, hashlib.sha256).digest()
   64 
   65     signed = _sign(('AWS4' + secret_key).encode('utf-8'), scope[0])
   66     signed = _sign(signed, scope[1])
   67     signed = _sign(signed, scope[2])
   68     signed = _sign(signed, b'aws4_request')
   69 
   70     signature = hmac.new(signed, string_to_sign, hashlib.sha256)
   71     return signature.hexdigest()
   72 
   73 
   74 class S3Resource(EC2_S3_Resource.ResourceBase):
   75     @staticmethod
   76     def _check_signature(creds_ref, credentials):
   77         string_to_sign = base64.urlsafe_b64decode(str(credentials['token']))
   78 
   79         if string_to_sign[0:4] != b'AWS4':
   80             signature = _calculate_signature_v1(string_to_sign,
   81                                                 creds_ref['secret'])
   82         else:
   83             signature = _calculate_signature_v4(string_to_sign,
   84                                                 creds_ref['secret'])
   85 
   86         if not utils.auth_str_equal(credentials['signature'], signature):
   87             raise exception.Unauthorized(
   88                 message=_('Credential signature mismatch'))
   89 
   90     @ks_flask.unenforced_api
   91     def post(self):
   92         """Authenticate s3token.
   93 
   94         POST /v3/s3tokens
   95         """
   96         token = self.handle_authenticate()
   97         token_reference = render_token.render_token_response_from_model(token)
   98         resp_body = jsonutils.dumps(token_reference)
   99         response = flask.make_response(resp_body, http.client.OK)
  100         response.headers['Content-Type'] = 'application/json'
  101         return response
  102 
  103 
  104 class S3Api(ks_flask.APIBase):
  105     _name = 's3tokens'
  106     _import_name = __name__
  107     resources = []
  108     resource_mapping = [
  109         ks_flask.construct_resource_map(
  110             resource=S3Resource,
  111             url='/s3tokens',
  112             resource_kwargs={},
  113             rel='s3tokens',
  114             resource_relation_func=(
  115                 json_home_relations.s3_token_resource_rel_func))
  116     ]
  117 
  118 
  119 APIs = (S3Api,)