-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Add private_key auth method to snowflake query runner #7371
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
Conversation
Thanks!! Just updated our instance to this branch and it's working perfectly |
@adrianoesch |
hi @sh47267
it doesn't yet, because i don't understand the motivation behind storing an encrypted string with the password in the same place. but it could easily be added to load_pem_private_key (see here) |
You're right — I realize now that without separating the passphrase from the key file, it doesn't really provide any additional security. There might still be demand for it, but thanks for the clarification for now. |
Any updates here? We're using redash in my org and trying to get ahead of the snowflake requirements/mandates. We're on an older version of redash anyway and we're holding until a version of redash has this fix on it. |
hi @uofifox , we need the attention of one of the maintainers to merge this into the main branch. as this is an open-source project, one can expect this to take some time. in the meantime, @nijave seems to have had success deploying this branch in his org. also, snowflake allows you to continue working with passwords for user with type |
Thanks for the update, and while the delay in enforcement is not until November, these kinds of things have a way of slipping your mind until its too late. Also note, I noticed you don't have the ability to support encrypted private keys. Most of the other platforms I used actually won't accept the private keys unless it is encrypted. Agree its a bit overkill, but to keep it standard for our group we've just by default encrypted the private key. |
any chance you can unblock us here @arikfr ? |
Thank you very much for your contribution!
Thank you! |
redash/query_runner/snowflake.py
Outdated
if self.configuration.__contains__("password"): | ||
connection = snowflake.connector.connect( | ||
user=self.configuration["user"], | ||
password=self.configuration["password"], | ||
account=account, | ||
region=region, | ||
host=host, | ||
application="Redash/{} (Snowflake)".format(__version__.split("-")[0]), | ||
) | ||
else: | ||
connection = snowflake.connector.connect( | ||
user=self.configuration["user"], | ||
private_key=self._get_private_key(), | ||
account=account, | ||
region=region, | ||
host=host, | ||
application="Redash/{} (Snowflake)".format(__version__.split("-")[0]), | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's what @yoshiokatsuneo meant in terms of reducing duplication:
if self.configuration.__contains__("password"): | |
connection = snowflake.connector.connect( | |
user=self.configuration["user"], | |
password=self.configuration["password"], | |
account=account, | |
region=region, | |
host=host, | |
application="Redash/{} (Snowflake)".format(__version__.split("-")[0]), | |
) | |
else: | |
connection = snowflake.connector.connect( | |
user=self.configuration["user"], | |
private_key=self._get_private_key(), | |
account=account, | |
region=region, | |
host=host, | |
application="Redash/{} (Snowflake)".format(__version__.split("-")[0]), | |
) | |
params = { | |
'user': self.configuration["user"], | |
'account': account, | |
'region': region, | |
'host': host, | |
'application': "Redash/{} (Snowflake)".format(__version__.split("-")[0]), | |
} | |
if 'password' in self.configuration: | |
params['password'] = self.configuration['password'] | |
elif 'private_key' in self.configuration: | |
params['private_key'] = self._get_private_key() | |
else: | |
raise Exception("Password or private key not set.") | |
connection = snowflake.connector.connect(**params) |
(I typed this in the GitHub UI, so you would want to double check it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also added handling of the case when no password or private key is set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much for much clear comment !
@yoshiokatsuneo I think they add the headers in case they are missing .. as you can't be sure what type of private key the user will upload. |
Thank you ! |
hi @yoshiokatsuneo & @arikfr, and thanks for taking this up!
|
Thank you ! I noticed that the code assume private key header is "-----BEGIN PRIVATE KEY-----", but it is not always true.
Also, private key generated by some old tool looks have header "-----BEGIN RSA PRIVATE KEY-----". And future version or other variants may have different header. Again, I just feel that handling those all cases make code base complex compare to the benefit, as the setting private key in only once. Thank you ! |
Just for your information but I think here is a sample implementation that load private key from AWS secret manager. ( I'm not saying that this PR should handle the case. Just as a information.) https://zenn.dev/dataheroes/articles/20250411-redash-snowflake-keypair-authn Thank you ! |
i wasnt aware of the different rsa key headers, that does indeed complicate things.
you mean as base64 encoded string like here? but then i'd suggest renaming the property to thanks for the hint towards the integration with the aws secret manager. this is neat for secret rotation i guess, but then you one would also have to take care of authentication towards aws. even though in an aws deployment that's rather easy, but let's leave this out of scope for now. |
i would think that the secret array in the configuration (see here) would take care of that. is that not the case? |
I think we also need to set type to "password" instead of "string" to set input field type to password like below.
|
i've added base64 encoded private key handling to simplify code. unfortunately this is the error on create datasource with type password:
adding the attribute to the secret array in the runner config will replace the string with dashs on subsequent config loads which seems good enough to me: |
Ah, you are right ! I just noticed that the properties in which key have suffix "password" or "passwd" are handled as password type, and properties in which key have suffix "File" is handled as file type.
So, how about changing property key name following the convention like below ?
|
we don't store private keys on disk and other services like dbt also use base64 encoded keys for snowflake auth (see here). if you want, i can add the file option additionally, but i don't think it's necessary.
this would not change the field type in
|
Ah I see, you are right again ! |
I think this code asks users to input base64-encode PEM while dbt asks users to input PEM(or base64-DER). ( It looks following dbt-snowflake code implementing authentication may be one reference.) Thank you. |
@yoshiokatsuneo added the file option |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank your for the update !
Thank you ! And, when I tried to connect Snowflake using private key with password, I got error below.
|
@yoshiokatsuneo |
Thank you ! |
The PR looks good, I tested and and it looks working well. Just to make sure, do you have any thought or comment ? There is some discussion how to load the PEM file whether string or file. Current code(loading from file) looks good, but do you have any idea ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adrianoesch
I think this feature improve Redash, the code is good and works well.
I believes we can merge the PR.
Thank you very much for your contribution !
What type of PR is this?
Description
Snowflake will soon require private key authentication for service users without multi factor authentication (see announcement). This PR makes snowflake configurable with a private_key.
How is this tested?
I would need guidance on how you want this tested.
Related Tickets & Documents
I could only find this discussion.