dataflow-core 2.1.14rc1__py3-none-any.whl → 2.1.15rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- authenticator/dataflowairflowauthenticator.py +3 -9
- dataflow/secrets_manager/factory.py +14 -8
- dataflow/secrets_manager/providers/gcp_manager.py +332 -0
- {dataflow_core-2.1.14rc1.dist-info → dataflow_core-2.1.15rc1.dist-info}/METADATA +3 -1
- {dataflow_core-2.1.14rc1.dist-info → dataflow_core-2.1.15rc1.dist-info}/RECORD +8 -7
- {dataflow_core-2.1.14rc1.dist-info → dataflow_core-2.1.15rc1.dist-info}/WHEEL +0 -0
- {dataflow_core-2.1.14rc1.dist-info → dataflow_core-2.1.15rc1.dist-info}/entry_points.txt +0 -0
- {dataflow_core-2.1.14rc1.dist-info → dataflow_core-2.1.15rc1.dist-info}/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ from flask_appbuilder.security.views import expose
|
|
|
4
4
|
from flask_login import login_user
|
|
5
5
|
from airflow.www.security import FabAirflowSecurityManagerOverride
|
|
6
6
|
from dataflow.dataflow import Dataflow
|
|
7
|
-
import logging
|
|
7
|
+
import logging
|
|
8
8
|
|
|
9
9
|
logging.basicConfig(
|
|
10
10
|
level=logging.INFO,
|
|
@@ -29,15 +29,9 @@ class DataflowAuthDBView(AuthDBView):
|
|
|
29
29
|
|
|
30
30
|
user_details = dataflow.auth(session_id)
|
|
31
31
|
logger.info(f"User details retrieved for: {user_details['user_name']}")
|
|
32
|
-
if os.getenv("RUNTIME"):
|
|
33
|
-
role = self.appbuilder.sm.find_role(user_details.get("base_role", "user").title())
|
|
34
|
-
else:
|
|
35
|
-
role = self.appbuilder.sm.find_role("Admin")
|
|
36
32
|
user = self.appbuilder.sm.find_user(username=user_details['user_name'])
|
|
37
33
|
if user:
|
|
38
|
-
|
|
39
|
-
user.role = role
|
|
40
|
-
self.appbuilder.sm.update_user(user=user)
|
|
34
|
+
logger.info(f"User found: {user}")
|
|
41
35
|
login_user(user, remember=False)
|
|
42
36
|
else:
|
|
43
37
|
user = self.appbuilder.sm.add_user(
|
|
@@ -45,7 +39,7 @@ class DataflowAuthDBView(AuthDBView):
|
|
|
45
39
|
first_name=user_details.get("first_name", ""),
|
|
46
40
|
last_name=user_details.get("last_name", ""),
|
|
47
41
|
email=user_details.get("email", ""),
|
|
48
|
-
role=
|
|
42
|
+
role=self.appbuilder.sm.find_role(user_details.get("base_role", "user").title())
|
|
49
43
|
)
|
|
50
44
|
logger.info(f"New user created: {user}")
|
|
51
45
|
if user:
|
|
@@ -3,6 +3,7 @@ import os
|
|
|
3
3
|
from .interface import SecretManager
|
|
4
4
|
from .providers.aws_manager import AWSSecretsManager
|
|
5
5
|
from .providers.azure_manager import AzureKeyVault
|
|
6
|
+
from .providers.gcp_manager import GCPSecretsManager
|
|
6
7
|
from ..configuration import ConfigurationManager
|
|
7
8
|
|
|
8
9
|
# A custom exception for clear error messages
|
|
@@ -17,10 +18,6 @@ def get_secret_manager() -> SecretManager:
|
|
|
17
18
|
to determine which cloud provider's secret manager to instantiate.
|
|
18
19
|
"""
|
|
19
20
|
try:
|
|
20
|
-
# dataflow_config = None
|
|
21
|
-
# if os.getenv('HOSTNAME'):
|
|
22
|
-
# dataflow_config = ConfigurationManager('/dataflow/app/auth_config/dataflow_auth.cfg')
|
|
23
|
-
# else:
|
|
24
21
|
dataflow_config = ConfigurationManager('/dataflow/app/config/dataflow.cfg')
|
|
25
22
|
except Exception as e:
|
|
26
23
|
raise SecretProviderError(
|
|
@@ -49,11 +46,20 @@ def get_secret_manager() -> SecretManager:
|
|
|
49
46
|
)
|
|
50
47
|
return AzureKeyVault(vault_url=vault_url)
|
|
51
48
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
elif provider == "gcp":
|
|
50
|
+
project_id = dataflow_config.get_config_value('cloudProvider', 'gcp_project_id')
|
|
51
|
+
region = dataflow_config.get_config_value('cloudProvider', 'gcp_region')
|
|
52
|
+
if not project_id:
|
|
53
|
+
raise SecretProviderError(
|
|
54
|
+
"GCP_PROJECT_ID must be set when using the GCP provider."
|
|
55
|
+
)
|
|
56
|
+
if not region:
|
|
57
|
+
raise SecretProviderError(
|
|
58
|
+
"GCP_REGION must be set when using the GCP provider."
|
|
59
|
+
)
|
|
60
|
+
return GCPSecretsManager(project_id=project_id, region=region)
|
|
55
61
|
|
|
56
62
|
else:
|
|
57
63
|
raise SecretProviderError(
|
|
58
|
-
f"Unsupported secret provider: '{provider}'. Supported providers are: aws, azure
|
|
64
|
+
f"Unsupported secret provider: '{provider}'. Supported providers are: aws, azure and gcp"
|
|
59
65
|
)
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import os, base64, json, atexit
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from google.cloud import secretmanager
|
|
4
|
+
from google.cloud.secretmanager_v1 import SecretManagerServiceClient
|
|
5
|
+
from google.cloud.secretmanager_v1.types import Secret, SecretPayload
|
|
6
|
+
from google.api_core.exceptions import (
|
|
7
|
+
AlreadyExists,
|
|
8
|
+
NotFound,
|
|
9
|
+
PermissionDenied,
|
|
10
|
+
Forbidden,
|
|
11
|
+
ResourceExhausted,
|
|
12
|
+
InvalidArgument,
|
|
13
|
+
FailedPrecondition
|
|
14
|
+
)
|
|
15
|
+
import json
|
|
16
|
+
from ..interface import SecretManager
|
|
17
|
+
from ...utils.exceptions import (
|
|
18
|
+
SecretNotFoundException,
|
|
19
|
+
SecretAlreadyExistsException,
|
|
20
|
+
SecretManagerAuthException,
|
|
21
|
+
SecretManagerServiceException
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def _setup_gcp_credentials():
|
|
25
|
+
"""Setup GCP credentials from base64 encoded JSON environment variable"""
|
|
26
|
+
|
|
27
|
+
# Only run if GOOGLE_APPLICATION_CREDENTIALS is not already set
|
|
28
|
+
if os.getenv('GOOGLE_APPLICATION_CREDENTIALS'):
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
# Get base64 encoded JSON credentials
|
|
32
|
+
encoded_json = os.getenv('GOOGLE_APPLICATION_CREDENTIALS_JSON')
|
|
33
|
+
|
|
34
|
+
if encoded_json:
|
|
35
|
+
try:
|
|
36
|
+
# Decode base64 to JSON string
|
|
37
|
+
json_credentials = base64.b64decode(encoded_json).decode('utf-8')
|
|
38
|
+
|
|
39
|
+
# Validate it's valid JSON
|
|
40
|
+
json.loads(json_credentials) # Just to validate
|
|
41
|
+
|
|
42
|
+
# Create credentials file in home directory
|
|
43
|
+
home_dir = Path.home()
|
|
44
|
+
credentials_dir = home_dir / '.gcp'
|
|
45
|
+
credentials_dir.mkdir(exist_ok=True) # Create .gcp directory if it doesn't exist
|
|
46
|
+
|
|
47
|
+
credentials_path = credentials_dir / 'credentials.json'
|
|
48
|
+
|
|
49
|
+
# Write JSON string to credentials file
|
|
50
|
+
with open(credentials_path, 'w') as f:
|
|
51
|
+
f.write(json_credentials)
|
|
52
|
+
|
|
53
|
+
# Set the standard Google environment variable that the SDK looks for
|
|
54
|
+
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = str(credentials_path)
|
|
55
|
+
|
|
56
|
+
# Clean up file on exit
|
|
57
|
+
atexit.register(lambda: credentials_path.unlink() if credentials_path.exists() else None)
|
|
58
|
+
|
|
59
|
+
print(f"GCP credentials decoded and configured at {credentials_path}")
|
|
60
|
+
|
|
61
|
+
except Exception as e:
|
|
62
|
+
print(f"Error setting up GCP credentials: {e}")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class GCPSecretsManager(SecretManager):
|
|
66
|
+
"""Google Cloud Platform Secrets Manager implementation."""
|
|
67
|
+
|
|
68
|
+
def __init__(self, project_id: str, region: str):
|
|
69
|
+
"""Initialize the GCP Secret Manager client.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
project_id: The GCP project ID where secrets will be stored.
|
|
73
|
+
region: The GCP region where secrets will be stored.
|
|
74
|
+
"""
|
|
75
|
+
self.project_id = project_id
|
|
76
|
+
self.region = region
|
|
77
|
+
try:
|
|
78
|
+
_setup_gcp_credentials()
|
|
79
|
+
self.client = secretmanager.SecretManagerServiceClient()
|
|
80
|
+
except PermissionDenied as e:
|
|
81
|
+
raise SecretManagerAuthException("initialize_gcp_client", original_error=str(e))
|
|
82
|
+
except Exception as e:
|
|
83
|
+
raise SecretManagerServiceException("initialize_gcp_client", original_error=str(e))
|
|
84
|
+
|
|
85
|
+
def _get_secret_path(self, vault_path: str) -> str:
|
|
86
|
+
"""Get the full secret path in GCP format.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
vault_path: The path/name of the secret.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
The full path to the secret in GCP format.
|
|
93
|
+
"""
|
|
94
|
+
return f"projects/{self.project_id}/secrets/{vault_path}"
|
|
95
|
+
|
|
96
|
+
def _get_secret_version_path(self, vault_path: str, version: str = "latest") -> str:
|
|
97
|
+
"""Get the full path to a specific secret version.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
vault_path: The path/name of the secret.
|
|
101
|
+
version: The version of the secret (default is "latest").
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
The full path to the secret version in GCP format.
|
|
105
|
+
"""
|
|
106
|
+
return f"{self._get_secret_path(vault_path)}/versions/{version}"
|
|
107
|
+
|
|
108
|
+
def create_secret(self, vault_path: str, secret_data: dict) -> str:
|
|
109
|
+
"""Create a new secret.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
vault_path: The path/name of the secret.
|
|
113
|
+
region: The region where the secret will be stored.
|
|
114
|
+
secret_data: The data to store in the secret.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
A success message.
|
|
118
|
+
|
|
119
|
+
Raises:
|
|
120
|
+
SecretAlreadyExistsException: If the secret already exists.
|
|
121
|
+
SecretManagerAuthException: If there are permission issues.
|
|
122
|
+
SecretManagerServiceException: For other service errors.
|
|
123
|
+
"""
|
|
124
|
+
try:
|
|
125
|
+
# Convert dictionary to JSON string before saving
|
|
126
|
+
secret_string = json.dumps(secret_data)
|
|
127
|
+
|
|
128
|
+
# First create the secret
|
|
129
|
+
parent = f"projects/{self.project_id}"
|
|
130
|
+
secret = Secret(
|
|
131
|
+
replication={
|
|
132
|
+
"user_managed": {
|
|
133
|
+
"replicas": [
|
|
134
|
+
{"location": self.region }
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
self.client.create_secret(
|
|
141
|
+
request={
|
|
142
|
+
"parent": parent,
|
|
143
|
+
"secret_id": vault_path,
|
|
144
|
+
"secret": secret
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# Then add the secret version with the data
|
|
149
|
+
secret_path = self._get_secret_path(vault_path)
|
|
150
|
+
self.client.add_secret_version(
|
|
151
|
+
request={
|
|
152
|
+
"parent": secret_path,
|
|
153
|
+
"payload": {"data": secret_string.encode("UTF-8")}
|
|
154
|
+
}
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
return "Secret created successfully"
|
|
158
|
+
except AlreadyExists as e:
|
|
159
|
+
raise SecretAlreadyExistsException("secret", vault_path, original_error=str(e))
|
|
160
|
+
except PermissionDenied as e:
|
|
161
|
+
raise SecretManagerAuthException("create_secret", original_error=str(e))
|
|
162
|
+
except Forbidden as e:
|
|
163
|
+
raise SecretManagerAuthException("create_secret", original_error=str(e))
|
|
164
|
+
except FailedPrecondition as e:
|
|
165
|
+
# Handle case where secret might be in recovery/deleted state
|
|
166
|
+
if "pending deletion" in str(e).lower() or "scheduled for deletion" in str(e).lower():
|
|
167
|
+
raise SecretAlreadyExistsException("secret", vault_path, original_error=str(e), is_scheduled_for_deletion=True)
|
|
168
|
+
else:
|
|
169
|
+
raise SecretManagerServiceException("create_secret", original_error=str(e))
|
|
170
|
+
except ResourceExhausted as e:
|
|
171
|
+
raise SecretManagerServiceException("create_secret", original_error=str(e))
|
|
172
|
+
except Exception as e:
|
|
173
|
+
raise SecretManagerServiceException("create_secret", original_error=str(e))
|
|
174
|
+
|
|
175
|
+
def get_secret_by_key(self, vault_path: str) -> dict:
|
|
176
|
+
"""Get a secret by its key.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
vault_path: The path/name of the secret.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
The secret data as a dictionary.
|
|
183
|
+
|
|
184
|
+
Raises:
|
|
185
|
+
SecretNotFoundException: If the secret doesn't exist.
|
|
186
|
+
SecretManagerAuthException: If there are permission issues.
|
|
187
|
+
SecretManagerServiceException: For other service errors.
|
|
188
|
+
"""
|
|
189
|
+
try:
|
|
190
|
+
# Get the latest version of the secret
|
|
191
|
+
name = self._get_secret_version_path(vault_path)
|
|
192
|
+
response = self.client.access_secret_version(request={"name": name})
|
|
193
|
+
|
|
194
|
+
# Decode the payload and convert JSON string back to dictionary
|
|
195
|
+
secret_string = response.payload.data.decode("UTF-8")
|
|
196
|
+
secret_data = json.loads(secret_string)
|
|
197
|
+
return secret_data
|
|
198
|
+
except NotFound as e:
|
|
199
|
+
raise SecretNotFoundException("secret", vault_path, original_error=str(e))
|
|
200
|
+
except PermissionDenied as e:
|
|
201
|
+
raise SecretManagerAuthException("get_secret", original_error=str(e))
|
|
202
|
+
except Forbidden as e:
|
|
203
|
+
raise SecretManagerAuthException("get_secret", original_error=str(e))
|
|
204
|
+
except InvalidArgument as e:
|
|
205
|
+
raise SecretManagerServiceException("get_secret", original_error=str(e))
|
|
206
|
+
except json.JSONDecodeError as e:
|
|
207
|
+
raise SecretManagerServiceException("get_secret", original_error=str(e))
|
|
208
|
+
except Exception as e:
|
|
209
|
+
raise SecretManagerServiceException("get_secret", original_error=str(e))
|
|
210
|
+
|
|
211
|
+
def update_secret(self, vault_path: str, update_data: dict) -> str:
|
|
212
|
+
"""Update an existing secret.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
vault_path: The path/name of the secret.
|
|
216
|
+
update_data: The data to update in the secret.
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
A success message.
|
|
220
|
+
|
|
221
|
+
Raises:
|
|
222
|
+
SecretNotFoundException: If the secret doesn't exist.
|
|
223
|
+
SecretManagerAuthException: If there are permission issues.
|
|
224
|
+
SecretManagerServiceException: For other service errors.
|
|
225
|
+
"""
|
|
226
|
+
try:
|
|
227
|
+
# Get current secret data
|
|
228
|
+
current_data = self.get_secret_by_key(vault_path)
|
|
229
|
+
|
|
230
|
+
# Update with new data
|
|
231
|
+
current_data.update(update_data)
|
|
232
|
+
|
|
233
|
+
# Convert updated dictionary to JSON string
|
|
234
|
+
updated_string = json.dumps(current_data)
|
|
235
|
+
|
|
236
|
+
# Add a new version of the secret with updated data
|
|
237
|
+
secret_path = self._get_secret_path(vault_path)
|
|
238
|
+
self.client.add_secret_version(
|
|
239
|
+
request={
|
|
240
|
+
"parent": secret_path,
|
|
241
|
+
"payload": {"data": updated_string.encode("UTF-8")}
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
return "Secret updated successfully"
|
|
246
|
+
except SecretNotFoundException:
|
|
247
|
+
raise
|
|
248
|
+
except PermissionDenied as e:
|
|
249
|
+
raise SecretManagerAuthException("update_secret", original_error=str(e))
|
|
250
|
+
except Forbidden as e:
|
|
251
|
+
raise SecretManagerAuthException("update_secret", original_error=str(e))
|
|
252
|
+
except NotFound as e:
|
|
253
|
+
raise SecretNotFoundException("secret", vault_path, original_error=str(e))
|
|
254
|
+
except InvalidArgument as e:
|
|
255
|
+
raise SecretManagerServiceException("update_secret", original_error=str(e))
|
|
256
|
+
except json.JSONDecodeError as e:
|
|
257
|
+
raise SecretManagerServiceException("update_secret", original_error=str(e))
|
|
258
|
+
except Exception as e:
|
|
259
|
+
raise SecretManagerServiceException("update_secret", original_error=str(e))
|
|
260
|
+
|
|
261
|
+
def delete_secret(self, vault_path: str) -> str:
|
|
262
|
+
"""Delete a secret.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
vault_path: The path/name of the secret.
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
A success message.
|
|
269
|
+
|
|
270
|
+
Raises:
|
|
271
|
+
SecretNotFoundException: If the secret doesn't exist.
|
|
272
|
+
SecretManagerAuthException: If there are permission issues.
|
|
273
|
+
SecretManagerServiceException: For other service errors.
|
|
274
|
+
"""
|
|
275
|
+
try:
|
|
276
|
+
# Get the full path to the secret
|
|
277
|
+
name = self._get_secret_path(vault_path)
|
|
278
|
+
|
|
279
|
+
# For git-ssh secrets, destroy without recovery
|
|
280
|
+
if "git-ssh" in vault_path:
|
|
281
|
+
# Get all versions to destroy them permanently
|
|
282
|
+
versions = self.client.list_secret_versions(request={"parent": name})
|
|
283
|
+
for version in versions:
|
|
284
|
+
if version.state == secretmanager.SecretVersion.State.ENABLED:
|
|
285
|
+
version_name = f"{name}/versions/{version.name.split('/')[-1]}"
|
|
286
|
+
self.client.destroy_secret_version(request={"name": version_name})
|
|
287
|
+
|
|
288
|
+
# Delete the secret itself
|
|
289
|
+
self.client.delete_secret(request={"name": name})
|
|
290
|
+
else:
|
|
291
|
+
# For regular secrets, use the default 7-day recovery window
|
|
292
|
+
self.client.delete_secret(request={
|
|
293
|
+
"name": name,
|
|
294
|
+
# In GCP, the recovery window is configured at the service level,
|
|
295
|
+
# not per API call, so we don't specify it here
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
return "Secret deleted successfully"
|
|
299
|
+
except NotFound as e:
|
|
300
|
+
raise SecretNotFoundException("secret", vault_path, original_error=str(e))
|
|
301
|
+
except PermissionDenied as e:
|
|
302
|
+
raise SecretManagerAuthException("delete_secret", original_error=str(e))
|
|
303
|
+
except Forbidden as e:
|
|
304
|
+
raise SecretManagerAuthException("delete_secret", original_error=str(e))
|
|
305
|
+
except InvalidArgument as e:
|
|
306
|
+
raise SecretManagerServiceException("delete_secret", original_error=str(e))
|
|
307
|
+
except Exception as e:
|
|
308
|
+
raise SecretManagerServiceException("delete_secret", original_error=str(e))
|
|
309
|
+
|
|
310
|
+
def test_connection(self, vault_path: str) -> str:
|
|
311
|
+
"""Test the connection to the secret manager by attempting to access a secret.
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
vault_path: The path/name of the secret to test.
|
|
315
|
+
|
|
316
|
+
Returns:
|
|
317
|
+
The status of the secret.
|
|
318
|
+
|
|
319
|
+
Raises:
|
|
320
|
+
SecretNotFoundException: If the secret doesn't exist.
|
|
321
|
+
SecretManagerAuthException: If there are permission issues.
|
|
322
|
+
SecretManagerServiceException: For other service errors.
|
|
323
|
+
"""
|
|
324
|
+
try:
|
|
325
|
+
secret = self.get_secret_by_key(vault_path)
|
|
326
|
+
return secret.get('status', 'Unknown')
|
|
327
|
+
except SecretNotFoundException:
|
|
328
|
+
raise
|
|
329
|
+
except (SecretManagerAuthException, SecretManagerServiceException):
|
|
330
|
+
raise
|
|
331
|
+
except Exception as e:
|
|
332
|
+
raise SecretManagerServiceException("test_connection", original_error=str(e))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dataflow-core
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.15rc1
|
|
4
4
|
Summary: Dataflow core package
|
|
5
5
|
Author: Dataflow
|
|
6
6
|
Author-email:
|
|
@@ -11,6 +11,8 @@ Requires-Dist: pymysql
|
|
|
11
11
|
Requires-Dist: requests
|
|
12
12
|
Requires-Dist: azure-identity
|
|
13
13
|
Requires-Dist: azure-keyvault-secrets
|
|
14
|
+
Requires-Dist: google-auth
|
|
15
|
+
Requires-Dist: google-cloud-secret-manager
|
|
14
16
|
Dynamic: author
|
|
15
17
|
Dynamic: requires-dist
|
|
16
18
|
Dynamic: summary
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
authenticator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
authenticator/dataflowairflowauthenticator.py,sha256=
|
|
2
|
+
authenticator/dataflowairflowauthenticator.py,sha256=gEdCiL2yJQ7lYvAwbrjcAkccVMfehoMJldw9eU7cc2s,2243
|
|
3
3
|
authenticator/dataflowhubauthenticator.py,sha256=wI9S-1pcav_WHUL4ibEn-HLhjOtZebQbqXTkcrXXFAA,13463
|
|
4
4
|
authenticator/dataflowsupersetauthenticator.py,sha256=NkAmDaIc-ui-qEolu4xz_UY7P_2g8111hwNjPvAOW1Q,2839
|
|
5
5
|
dataflow/__init__.py,sha256=WTRg8HMpMWSgxYJ9ZGVldx4k07fAbta3mBmZ1hG9mWE,30
|
|
@@ -40,18 +40,19 @@ dataflow/scripts/clone_environment.sh,sha256=Qy0GylsA3kUVUL_L1MirxIWujOFhT1tikKq
|
|
|
40
40
|
dataflow/scripts/create_environment.sh,sha256=3FHgNplJuEZvyTsLqlCJNX9oyfXgsfqn80VZk2xtvso,828
|
|
41
41
|
dataflow/scripts/update_environment.sh,sha256=2dtn2xlNi6frpig-sqlGE1_IKRbbkqYOCpf_qyMKKII,992
|
|
42
42
|
dataflow/secrets_manager/__init__.py,sha256=idGqIDtYl0De2WIK9Obl-N7SDPSYtVM0D-wXfZjCiy4,559
|
|
43
|
-
dataflow/secrets_manager/factory.py,sha256=
|
|
43
|
+
dataflow/secrets_manager/factory.py,sha256=LblshkGG9q2C3RHYp0QykianUtpOOQz7sBdlerutyWY,2479
|
|
44
44
|
dataflow/secrets_manager/interface.py,sha256=HhrKpQrprWIbDsVfU_qc59OXmSIuHXv106OXv6-Epqc,506
|
|
45
45
|
dataflow/secrets_manager/service.py,sha256=SSWgTXJTAwVPqMIc76cB2hR6nghNVOoMpIN9M0i7Su0,7241
|
|
46
46
|
dataflow/secrets_manager/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
47
|
dataflow/secrets_manager/providers/aws_manager.py,sha256=16peXyKeuAjv2RVTMUjrzArPYENK9Zu7jREWVgMfScA,8671
|
|
48
48
|
dataflow/secrets_manager/providers/azure_manager.py,sha256=sWOz-7ALnLt6vyM3lt14GBpzpmDnlH3hkdqtuApqkgU,9430
|
|
49
|
+
dataflow/secrets_manager/providers/gcp_manager.py,sha256=AJgotHZRQraxtmfJX1Z8u2Gcr7KJLRJTN_qbth3A5Xk,13738
|
|
49
50
|
dataflow/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
50
51
|
dataflow/utils/exceptions.py,sha256=8GRFoYZ5dPGQckVm2znaHpPi0ZAs69fK-RGKukEsapk,4432
|
|
51
52
|
dataflow/utils/get_current_user.py,sha256=4nSO3SPVMZhW-MsIgxR3f9ZzrFaIZIuyrM6hvfyE7PQ,1202
|
|
52
53
|
dataflow/utils/logger.py,sha256=7BFrOq5Oiqn8P4XZbgJzMP5O07d2fpdECbbfsjrUuHw,1213
|
|
53
|
-
dataflow_core-2.1.
|
|
54
|
-
dataflow_core-2.1.
|
|
55
|
-
dataflow_core-2.1.
|
|
56
|
-
dataflow_core-2.1.
|
|
57
|
-
dataflow_core-2.1.
|
|
54
|
+
dataflow_core-2.1.15rc1.dist-info/METADATA,sha256=aRoxdVVfP0yY6qPtPuSH_RGHqxAQ13HCTjLq0UxRnR0,443
|
|
55
|
+
dataflow_core-2.1.15rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
56
|
+
dataflow_core-2.1.15rc1.dist-info/entry_points.txt,sha256=ppj_EIbYrJJwCPg1kfdsZk5q1N-Ejfis1neYrnjhO8o,117
|
|
57
|
+
dataflow_core-2.1.15rc1.dist-info/top_level.txt,sha256=SZsUOpSCK9ntUy-3Tusxzf5A2e8ebwD8vouPb1dPt_8,23
|
|
58
|
+
dataflow_core-2.1.15rc1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|