55
66from .version import get_version
77from .credentials import Profile
8+
89VERSION : str = get_version ()
910DEFAULT_USER_AGENT = "osc-sdk-python/" + VERSION
1011
12+
1113class Authentication :
12- def __init__ (self , credentials : Profile , host : str ,
13- method = 'POST' , service = 'api' ,
14- content_type = 'application/json; charset=utf-8' ,
15- algorithm = 'OSC4-HMAC-SHA256' ,
16- signed_headers = 'content-type;host;x-osc-date' ,
17- user_agent = DEFAULT_USER_AGENT ):
14+ def __init__ (
15+ self ,
16+ credentials : Profile ,
17+ host : str ,
18+ method = "POST" ,
19+ service = "api" ,
20+ content_type = "application/json; charset=utf-8" ,
21+ algorithm = "OSC4-HMAC-SHA256" ,
22+ signed_headers = "content-type;host;x-osc-date" ,
23+ user_agent = DEFAULT_USER_AGENT ,
24+ ):
1825 self .access_key = credentials .access_key
1926 self .secret_key = credentials .secret_key
2027 self .login = credentials .login
@@ -31,34 +38,37 @@ def __init__(self, credentials: Profile, host: str,
3138
3239 def forge_headers_signed (self , uri , request_data ):
3340 date_iso , date = self .build_dates ()
34- credential_scope = '{}/{}/{}/osc4_request' .format (date , self .region , self .service )
41+ credential_scope = "{}/{}/{}/osc4_request" .format (
42+ date , self .region , self .service
43+ )
3544
3645 canonical_request = self .build_canonical_request (date_iso , uri , request_data )
37- str_to_sign = self .create_string_to_sign (date_iso , credential_scope , canonical_request )
46+ str_to_sign = self .create_string_to_sign (
47+ date_iso , credential_scope , canonical_request
48+ )
3849 signature = self .compute_signature (date , str_to_sign )
3950 authorisation = self .build_authorization_header (credential_scope , signature )
4051
4152 return {
42- ' Content-Type' : self .content_type ,
43- ' X-Osc-Date' : date_iso ,
44- ' Authorization' : authorisation ,
45- ' User-Agent' : self .user_agent ,
53+ " Content-Type" : self .content_type ,
54+ " X-Osc-Date" : date_iso ,
55+ " Authorization" : authorisation ,
56+ " User-Agent" : self .user_agent ,
4657 }
4758
4859 def build_dates (self ):
49- '''Return YYYYMMDDTHHmmssZ, YYYYMMDD
50- '''
60+ """Return YYYYMMDDTHHmmssZ, YYYYMMDD"""
5161 t = datetime .datetime .now (datetime .timezone .utc )
52- return t .strftime (' %Y%m%dT%H%M%SZ' ), t .strftime (' %Y%m%d' )
62+ return t .strftime (" %Y%m%dT%H%M%SZ" ), t .strftime (" %Y%m%d" )
5363
5464 def sign (self , key , msg ):
5565 return hmac .new (key , msg .encode ("utf-8" ), hashlib .sha256 ).digest ()
5666
5767 def get_signature_key (self , key , date_stamp_value ):
58- k_date = self .sign ((' OSC4' + key ).encode (' utf-8' ), date_stamp_value )
68+ k_date = self .sign ((" OSC4" + key ).encode (" utf-8" ), date_stamp_value )
5969 k_region = self .sign (k_date , self .region )
6070 k_service = self .sign (k_region , self .service )
61- k_signing = self .sign (k_service , ' osc4_request' )
71+ k_signing = self .sign (k_service , " osc4_request" )
6272 return k_signing
6373
6474 def build_canonical_request (self , date_iso , canonical_uri , request_data ):
@@ -81,44 +91,74 @@ def build_canonical_request(self, date_iso, canonical_uri, request_data):
8191 # Step 6: Create payload hash. In this example, the payload (body of
8292 # the request) contains the request parameters.
8393 # Step 7: Combine elements to create canonical request
84- canonical_querystring = ''
85- canonical_headers = 'content-type:' + self .content_type + '\n ' \
86- + 'host:' + self .host + '\n ' \
87- + 'x-osc-date:' + date_iso + '\n '
88- payload_hash = hashlib .sha256 (request_data .encode ('utf-8' )).hexdigest ()
89- return self .method + '\n ' \
90- + canonical_uri + '\n ' \
91- + canonical_querystring + '\n ' \
92- + canonical_headers + '\n ' \
93- + self .signed_headers + '\n ' \
94- + payload_hash
94+ canonical_querystring = ""
95+ canonical_headers = (
96+ "content-type:"
97+ + self .content_type
98+ + "\n "
99+ + "host:"
100+ + self .host
101+ + "\n "
102+ + "x-osc-date:"
103+ + date_iso
104+ + "\n "
105+ )
106+ payload_hash = hashlib .sha256 (request_data .encode ("utf-8" )).hexdigest ()
107+ return (
108+ self .method
109+ + "\n "
110+ + canonical_uri
111+ + "\n "
112+ + canonical_querystring
113+ + "\n "
114+ + canonical_headers
115+ + "\n "
116+ + self .signed_headers
117+ + "\n "
118+ + payload_hash
119+ )
95120
96121 def create_string_to_sign (self , date_iso , credential_scope , canonical_request ):
97122 # ************* TASK 2: CREATE THE STRING TO SIGN*************
98123 # Match the algorithm to the hashing algorithm you use, either SHA-1 or
99124 # SHA-256 (recommended)
100- return self .algorithm + '\n ' \
101- + date_iso + '\n ' \
102- + credential_scope + '\n ' \
103- + hashlib .sha256 (canonical_request .encode ('utf-8' )).hexdigest ()
104-
125+ return (
126+ self .algorithm
127+ + "\n "
128+ + date_iso
129+ + "\n "
130+ + credential_scope
131+ + "\n "
132+ + hashlib .sha256 (canonical_request .encode ("utf-8" )).hexdigest ()
133+ )
105134
106135 def compute_signature (self , date , string_to_sign ):
107136 # ************* TASK 3: CALCULATE THE SIGNATURE *************
108137 # Create the signing key using the function defined above.
109138 signing_key = self .get_signature_key (self .secret_key , date )
110139
111140 # Sign the string_to_sign using the signing_key
112- return hmac .new (signing_key , string_to_sign . encode ( 'utf-8' ),
113- hashlib .sha256 ). hexdigest ()
114-
141+ return hmac .new (
142+ signing_key , string_to_sign . encode ( "utf-8" ), hashlib .sha256
143+ ). hexdigest ()
115144
116145 def build_authorization_header (self , credential_scope , signature ):
117146 # ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************
118147 # Put the signature information in a header named Authorization.
119- return self .algorithm + ' ' + 'Credential=' + self .access_key + '/' + credential_scope + ', ' \
120- + 'SignedHeaders=' + self .signed_headers + ', ' \
121- + 'Signature=' + signature
148+ return (
149+ self .algorithm
150+ + " "
151+ + "Credential="
152+ + self .access_key
153+ + "/"
154+ + credential_scope
155+ + ", "
156+ + "SignedHeaders="
157+ + self .signed_headers
158+ + ", "
159+ + "Signature="
160+ + signature
161+ )
122162
123163 def is_basic_auth_configured (self ):
124164 return self .login is not None and self .password is not None
@@ -130,7 +170,7 @@ def get_basic_auth_header(self):
130170 b64_creds = str (base64 .b64encode (creds .encode ("utf-8" )), "utf-8" )
131171 date_iso , _ = self .build_dates ()
132172 return {
133- ' Content-Type' : self .content_type ,
134- ' X-Osc-Date' : date_iso ,
135- ' Authorization' : "Basic " + b64_creds
173+ " Content-Type" : self .content_type ,
174+ " X-Osc-Date" : date_iso ,
175+ " Authorization" : "Basic " + b64_creds ,
136176 }
0 commit comments