Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get connection URI with AWS Secrets Manager #15104

Closed

Conversation

JavierLopezT
Copy link
Contributor

One of the main advantages of using AWS Secrets Manager is its ability to automatically create secrets of RDS databases and Redshift databases. Those secrets consist of several keys with their values, i.e user, pass, etc. Also, it is normal to store API Keys, sftp, or whatever using different values, as shown in the picture below:
Captura de pantalla 2020-05-22 a las 10 41 07

With the current code, all the keys and values obtained from a secret are stored in the schema attribute of the conn object, unless you have just one key with the conn_uri in the value. Thus, the current situation is forcing to use Secrets Manager in a way it is not intended to.

With this proposed modification, you can use AWS Secrets Manager using keys and values and have some kind of freedom to choose different words for each key to make the get_conn work.

I need help and guidance with tests, please. Thanks

@github-actions
Copy link

github-actions bot commented Apr 1, 2021

The Workflow run is cancelling this PR. It has some failed jobs matching ^Pylint$,^Static checks,^Build docs$,^Spell check docs$,^Provider packages,^Checks: Helm tests$,^Test OpenAPI*.

Comment on lines +108 to +117
counter = 0
for key, value in extra_dict.items():
if counter == 0:
conn_string += f'?{key}={value}'
else:
conn_string += f'&{key}={value}'

counter += 1

return conn_string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
counter = 0
for key, value in extra_dict.items():
if counter == 0:
conn_string += f'?{key}={value}'
else:
conn_string += f'&{key}={value}'
counter += 1
return conn_string
kvs = "&".join([f"{key}={value} for key, value in extra_dict.items()])
return f"{conn_string}?{kvs}"

Comment on lines +129 to +134
try:
secret_string = self._get_secret(conn_id)
secret = ast.literal_eval(secret_string) # json.loads gives error
except ValueError: # 'malformed node or string: ' error, for empty conns
connection = None
secret = None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not convinced that we need ast.literal_eval here. Can you explain a bit more on why we need this?

Copy link
Contributor

@xinbinhuang xinbinhuang Apr 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another note, the signature for is _get_secret(self, path_prefix: str, secret_id: str).

def _get_secret(self, path_prefix: str, secret_id: str) -> Optional[str]:
"""
Get secret value from Secrets Manager
:param path_prefix: Prefix for the Path to get Secret
:type path_prefix: str
:param secret_id: Secret Key
:type secret_id: str
"""
secrets_path = self.build_path(path_prefix, secret_id, self.sep)
try:

Comment on lines +154 to +162
conn_type = conn_d['conn_type']
user = conn_d['user']
password = conn_d['password']
host = conn_d['host']
port = conn_d['port']
schema = conn_d['schema']
conn_string = f'{conn_type}://{user}:{password}@{host}:{port}/{schema}'

connection = self._get_extra(secret, conn_string)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
conn_type = conn_d['conn_type']
user = conn_d['user']
password = conn_d['password']
host = conn_d['host']
port = conn_d['port']
schema = conn_d['schema']
conn_string = f'{conn_type}://{user}:{password}@{host}:{port}/{schema}'
connection = self._get_extra(secret, conn_string)
from airflow.models import Connection
connection_uri = Connection(**conn_d, extra=extra).get_uri()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I would recommend separating this part of logic (if secret: ) into another method for easier testing

@xinbinhuang
Copy link
Contributor

I feel like this PR is also related to #15146, #15146, and #15100 . cc: @dstandish @davlum

@dstandish
Copy link
Contributor

dstandish commented Apr 2, 2021

may i suggest using _create_connection function here
https://github.com/apache/airflow/pull/15013/files#diff-258df8f49a97540963b45ae4ac0e0f71720101134f73b2981b8ab3dd1a4cf5fcR24

i think we ultimately ought to provide a shared way of parsing creds from json and this function could be a good starting point.

PR #15013 is doing the same thing for Vault and is re-using that function.

@github-actions
Copy link

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the stale Stale PRs per the .github/workflows/stale.yml policy file label May 18, 2021
@github-actions github-actions bot closed this May 23, 2021
@JavierLopezT JavierLopezT deleted the aws_secrets_manager_backend branch August 5, 2021 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:providers area:secrets provider:amazon-aws AWS/Amazon - related issues stale Stale PRs per the .github/workflows/stale.yml policy file
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants