17
17
from __future__ import annotations
18
18
19
19
import base64
20
- import json
21
20
import logging
22
21
import os
23
22
24
- import boto3
25
23
import requests
26
24
from hopsworks_common .client import auth , base , exceptions
27
25
from hopsworks_common .client .exceptions import FeatureStoreException
37
35
38
36
39
37
class Client (base .Client ):
40
- DEFAULT_REGION = "default"
41
- SECRETS_MANAGER = "secretsmanager"
42
- PARAMETER_STORE = "parameterstore"
43
- LOCAL_STORE = "local"
44
-
45
38
def __init__ (
46
39
self ,
47
40
host ,
48
41
port ,
49
42
project ,
50
43
engine ,
51
- region_name ,
52
- secrets_store ,
53
44
hostname_verification ,
54
45
trust_store_path ,
55
46
cert_folder ,
@@ -65,17 +56,14 @@ def __init__(
65
56
self ._port = port
66
57
self ._base_url = "https://" + self ._host + ":" + str (self ._port )
67
58
_logger .info ("Base URL: %s" , self ._base_url )
68
- self ._region_name = region_name or self .DEFAULT_REGION
69
- _logger .debug ("Region name: %s" , self ._region_name )
70
59
71
60
if api_key_value is not None :
72
61
_logger .debug ("Using provided API key value" )
73
62
api_key = api_key_value
74
63
else :
75
- _logger .debug ("Querying secrets store for API key" )
76
- if secrets_store is None :
77
- secrets_store = self .LOCAL_STORE
78
- api_key = self ._get_secret (secrets_store , "api-key" , api_key_file )
64
+ _logger .debug (f"Reading api key from { api_key_file } " )
65
+ with open (api_key_file ) as f :
66
+ api_key = f .readline ().strip ()
79
67
80
68
_logger .debug ("Using api key to setup header authentification" )
81
69
self ._auth = auth .ApiKeyAuth (api_key )
@@ -84,17 +72,16 @@ def __init__(
84
72
self ._session = requests .session ()
85
73
self ._connected = True
86
74
87
- self ._verify = self ._get_verify (self . _host , trust_store_path )
75
+ self ._verify = self ._get_verify (hostname_verification , trust_store_path )
88
76
_logger .debug ("Verify: %s" , self ._verify )
89
77
90
78
self ._cert_key = None
91
79
self ._cert_folder_base = cert_folder
92
80
self ._cert_folder = None
93
81
94
- self ._hsfs_post_init (project , engine , region_name )
82
+ self ._hsfs_post_init (project , engine )
95
83
96
- def _hsfs_post_init (self , project , engine , region_name ):
97
- self ._region_name = region_name or self ._region_name or self .DEFAULT_REGION
84
+ def _hsfs_post_init (self , project , engine ):
98
85
self ._project_name = project
99
86
if project is not None :
100
87
project_info = self ._get_project_info (project )
@@ -295,82 +282,6 @@ def _get_client_key_path(self, project_name=None) -> str:
295
282
_logger .debug (f"Getting client key path { path } " )
296
283
return path
297
284
298
- def _get_secret (self , secrets_store , secret_key = None , api_key_file = None ):
299
- """Returns secret value from the AWS Secrets Manager or Parameter Store.
300
-
301
- :param secrets_store: the underlying secrets storage to be used, e.g. `secretsmanager` or `parameterstore`
302
- :type secrets_store: str
303
- :param secret_key: key for the secret value, e.g. `api-key`, `cert-key`, `trust-store`, `key-store`, defaults to None
304
- :type secret_key: str, optional
305
- :param api_key_file: path to a file containing an api key, defaults to None
306
- :type api_key_file: str optional
307
- :raises hsfs.client.exceptions.ExternalClientError: `api_key_file` needs to be set for local mode
308
- :raises hsfs.client.exceptions.UnknownSecretStorageError: Provided secrets storage not supported
309
- :return: secret
310
- :rtype: str
311
- """
312
- _logger .debug (f"Querying secrets store { secrets_store } for secret { secret_key } " )
313
- if secrets_store == self .SECRETS_MANAGER :
314
- return self ._query_secrets_manager (secret_key )
315
- elif secrets_store == self .PARAMETER_STORE :
316
- return self ._query_parameter_store (secret_key )
317
- elif secrets_store == self .LOCAL_STORE :
318
- if not api_key_file :
319
- raise exceptions .ExternalClientError (
320
- "api_key_file needs to be set for local mode"
321
- )
322
- _logger .debug (f"Reading api key from { api_key_file } " )
323
- with open (api_key_file ) as f :
324
- return f .readline ().strip ()
325
- else :
326
- raise exceptions .UnknownSecretStorageError (
327
- "Secrets storage " + secrets_store + " is not supported."
328
- )
329
-
330
- def _query_secrets_manager (self , secret_key ):
331
- _logger .debug ("Querying secrets manager for secret key: %s" , secret_key )
332
- secret_name = "hopsworks/role/" + self ._assumed_role ()
333
- args = {"service_name" : "secretsmanager" }
334
- region_name = self ._get_region ()
335
- if region_name :
336
- args ["region_name" ] = region_name
337
- client = boto3 .client (** args )
338
- get_secret_value_response = client .get_secret_value (SecretId = secret_name )
339
- return json .loads (get_secret_value_response ["SecretString" ])[secret_key ]
340
-
341
- def _assumed_role (self ):
342
- _logger .debug ("Getting assumed role" )
343
- client = boto3 .client ("sts" )
344
- response = client .get_caller_identity ()
345
- # arns for assumed roles in SageMaker follow the following schema
346
- # arn:aws:sts::123456789012:assumed-role/my-role-name/my-role-session-name
347
- local_identifier = response ["Arn" ].split (":" )[- 1 ].split ("/" )
348
- if len (local_identifier ) != 3 or local_identifier [0 ] != "assumed-role" :
349
- raise Exception (
350
- "Failed to extract assumed role from arn: " + response ["Arn" ]
351
- )
352
- return local_identifier [1 ]
353
-
354
- def _get_region (self ):
355
- if self ._region_name != self .DEFAULT_REGION :
356
- _logger .debug (f"Region name is not default, returning { self ._region_name } " )
357
- return self ._region_name
358
- else :
359
- _logger .debug ("Region name is default, returning None" )
360
- return None
361
-
362
- def _query_parameter_store (self , secret_key ):
363
- _logger .debug ("Querying parameter store for secret key: %s" , secret_key )
364
- args = {"service_name" : "ssm" }
365
- region_name = self ._get_region ()
366
- if region_name :
367
- args ["region_name" ] = region_name
368
- client = boto3 .client (** args )
369
- name = "/hopsworks/role/" + self ._assumed_role () + "/type/" + secret_key
370
- return client .get_parameter (Name = name , WithDecryption = True )["Parameter" ][
371
- "Value"
372
- ]
373
-
374
285
def _get_project_info (self , project_name ):
375
286
"""Makes a REST call to hopsworks to get all metadata of a project for the provided project.
376
287
0 commit comments