storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/docs/sts/client_grants/__init__.py (about) 1 # -*- coding: utf-8 -*- 2 # Licensed under the Apache License, Version 2.0 (the "License"); 3 # you may not use this file except in compliance with the License. 4 # You may obtain a copy of the License at 5 # 6 # http://www.apache.org/licenses/LICENSE-2.0 7 # 8 # Unless required by applicable law or agreed to in writing, software 9 # distributed under the License is distributed on an "AS IS" BASIS, 10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 # See the License for the specific language governing permissions and 12 # limitations under the License. 13 14 import json 15 # standard. 16 import os 17 18 import certifi 19 # Dependencies 20 import urllib3 21 from botocore.credentials import CredentialProvider, RefreshableCredentials 22 from botocore.exceptions import CredentialRetrievalError 23 from dateutil.parser import parse 24 25 from .sts_element import STSElement 26 27 28 class ClientGrantsCredentialProvider(CredentialProvider): 29 """ 30 ClientGrantsCredentialProvider implements CredentialProvider compatible 31 implementation to be used with boto_session 32 """ 33 METHOD = 'assume-role-client-grants' 34 CANONICAL_NAME = 'AssumeRoleClientGrants' 35 36 def __init__(self, cid, csec, 37 idp_ep='http://localhost:8080/auth/realms/minio/protocol/openid-connect/token', 38 sts_ep='http://localhost:9000'): 39 self.cid = cid 40 self.csec = csec 41 self.idp_ep = idp_ep 42 self.sts_ep = sts_ep 43 44 # Load CA certificates from SSL_CERT_FILE file if set 45 ca_certs = os.environ.get('SSL_CERT_FILE') 46 if not ca_certs: 47 ca_certs = certifi.where() 48 49 self._http = urllib3.PoolManager( 50 timeout=urllib3.Timeout.DEFAULT_TIMEOUT, 51 maxsize=10, 52 cert_reqs='CERT_NONE', 53 ca_certs=ca_certs, 54 retries=urllib3.Retry( 55 total=5, 56 backoff_factor=0.2, 57 status_forcelist=[500, 502, 503, 504] 58 ) 59 ) 60 61 def load(self): 62 """ 63 Search for credentials with client_grants 64 """ 65 if self.cid is not None: 66 fetcher = self._create_credentials_fetcher() 67 return RefreshableCredentials.create_from_metadata( 68 metadata=fetcher(), 69 refresh_using=fetcher, 70 method=self.METHOD, 71 ) 72 else: 73 return None 74 75 def _create_credentials_fetcher(self): 76 method = self.METHOD 77 78 def fetch_credentials(): 79 # HTTP headers are case insensitive filter out 80 # all duplicate headers and pick one. 81 headers = {} 82 headers['content-type'] = 'application/x-www-form-urlencoded' 83 headers['authorization'] = urllib3.make_headers( 84 basic_auth='%s:%s' % (self.cid, self.csec))['authorization'] 85 86 response = self._http.urlopen('POST', self.idp_ep, 87 body="grant_type=client_credentials", 88 headers=headers, 89 preload_content=True, 90 ) 91 if response.status != 200: 92 message = "Credential refresh failed, response: %s" 93 raise CredentialRetrievalError( 94 provider=method, 95 error_msg=message % response.status, 96 ) 97 98 creds = json.loads(response.data) 99 100 query = {} 101 query['Action'] = 'AssumeRoleWithClientGrants' 102 query['Token'] = creds['access_token'] 103 query['DurationSeconds'] = creds['expires_in'] 104 query['Version'] = '2011-06-15' 105 106 query_components = [] 107 for key in query: 108 if query[key] is not None: 109 query_components.append("%s=%s" % (key, query[key])) 110 111 query_string = '&'.join(query_components) 112 sts_ep_url = self.sts_ep 113 if query_string: 114 sts_ep_url = self.sts_ep + '?' + query_string 115 116 response = self._http.urlopen( 117 'POST', sts_ep_url, preload_content=True) 118 if response.status != 200: 119 message = "Credential refresh failed, response: %s" 120 raise CredentialRetrievalError( 121 provider=method, 122 error_msg=message % response.status, 123 ) 124 125 return parse_grants_response(response.data) 126 127 def parse_grants_response(data): 128 """ 129 Parser for AssumeRoleWithClientGrants response 130 131 :param data: Response data for AssumeRoleWithClientGrants request 132 :return: dict 133 """ 134 root = STSElement.fromstring( 135 'AssumeRoleWithClientGrantsResponse', data) 136 result = root.find('AssumeRoleWithClientGrantsResult') 137 creds = result.find('Credentials') 138 return dict( 139 access_key=creds.get_child_text('AccessKeyId'), 140 secret_key=creds.get_child_text('SecretAccessKey'), 141 token=creds.get_child_text('SessionToken'), 142 expiry_time=parse(creds.get_child_text('Expiration')).isoformat()) 143 144 return fetch_credentials