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

[Docs]: Misleading example of SNOWFLAKE_PRIVATE_KEY #3332

Closed
1 task
martinw-intersport opened this issue Jan 8, 2025 · 11 comments · Fixed by #3348
Closed
1 task

[Docs]: Misleading example of SNOWFLAKE_PRIVATE_KEY #3332

martinw-intersport opened this issue Jan 8, 2025 · 11 comments · Fixed by #3348
Assignees
Labels
category:migration Issues connected with migration to v1.0.0. category:provider_config docs Used to mark issues with documentation remark/questions

Comments

@martinw-intersport
Copy link

Company Name

No response

Object type(s)

No response

Documentation Link

https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/index.md

Description

In section #keypair-authentication-passphrase and #order-precedence mentioned example to assign SNOWFLAKE_PRIVATE_KEY with private key path, like

export SNOWFLAKE_USER="..."
export SNOWFLAKE_PRIVATE_KEY="~/.ssh/snowflake_key.p8"
export SNOWFLAKE_PRIVATE_KEY_PASSPHRASE="..."

Instead the SNOWFLAKE_PRIVATE_KEY accepts file content, and there's no way to pass in file path directly to snowflake provider.

References

No response

Would you like to implement a fix?

  • Yeah, I'll take it 😎
@martinw-intersport martinw-intersport added the docs Used to mark issues with documentation remark/questions label Jan 8, 2025
@sfc-gh-jmichalak
Copy link
Collaborator

Hi @martinw-intersport 👋

You're right - the example is misleading. We will adjust this soon. You should be able to load the contents of your key file like this:

export SNOWFLAKE_PRIVATE_KEY=$(cat ~/.ssh/snowflake_key.p8)

@sfc-gh-jmichalak sfc-gh-jmichalak self-assigned this Jan 9, 2025
@sfc-gh-jmichalak sfc-gh-jmichalak added the category:migration Issues connected with migration to v1.0.0. label Jan 9, 2025
@martinw-intersport
Copy link
Author

Hi @sfc-gh-jmichalak,

thanks for your reply! I still get following error when i set through env var SNOWFLAKE_PRIVATE_KEY

  │ Error: could not retrieve private key: could not parse private key, key is not in PEM format
  │ 
  │   with provider["registry.terraform.io/snowflake-labs/snowflake"].accountadmin,
  │   on main.tf line 1, in provider "snowflake":
  │    1: provider "snowflake" {
  │ 

and when I run echo "$SNOWFLAKE_PRIVATE_KEY", it outputs correct file content. Is that because provider cannot load multiline file?

@sfc-gh-jmichalak
Copy link
Collaborator

Probably the key is not formatted correctly. Please take a look at similar issues: #2899 and #2432. We don't do any processing on the file, we just pass it straight to the gosnowflake driver - see #2899 (comment).

@martinw-intersport
Copy link
Author

@sfc-gh-jmichalak The file is correctly formatted, at least when i use file("~/.ssh/snowflake_key.p8") it works.

But this command does not work as i said before (does this work on your side?)

export SNOWFLAKE_PRIVATE_KEY=$(cat ~/.ssh/snowflake_key.p8)

Regarding this #2899 (comment), it can be passed through on my side when env set using above command. So not due to pem.Decode

I have tried many ways, including:

  • Set ssh key content as one line local variable like
    locals ssh_content = "-----BEGIN PRIVATE KEY-----\nxxx\n-----END PRIVATE KEY-----\n to pass into schema private_key, it can be recongized by provider.
  • But if set ssh key content like this oneline string and then export SNOWFLAKE_PRIVATE_KEY=$(cat ~/.ssh/snowflake_key.p8) it doesn't work
  • Directly export SNOWFLAKE_PRIVATE_KEY="ssh oneline string" it works
  • Wrap ssh key content with <<EOT and EOT then export SNOWFLAKE_PRIVATE_KEY=$(cat ~/.ssh/snowflake_key.p8) it works

It seems there was an issue transferring the content from the SSH file to the environment variables. So your commit c7e463d about SNOWFLAKE_PRIVATE_KEY might still not work for others.

It will be good like snowflake cli to set private_key_file as file path, then we don't have to struggle with multiline string parameter. I know in gosnowflake haven't implement it, but snowflake provider can accept file path and load content by itself to pass to Config.PrivateKey

@sfc-gh-jmichalak
Copy link
Collaborator

I checked again, and it is working on my side. I checked multiple ways:

  • key embedded in main.tf
  • key sourced from a file with file() function
  • key set like
export SNOWFLAKE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDAr1xap9HA6Anx
...
qXcroyYiKfMLzlt+WYqk4qs5
-----END PRIVATE KEY-----"
  • key set like
export SNOWFLAKE_PRIVATE_KEY=$(cat ~/.ssh/key.p8)"

Note that I did not process the key/file in any way. It is a multiline key. To convert a singleline key to a multiline key, you can change encoded new lines \n to line breaks like sed 's/\\n/\'$'\n/g'.

Regarding a separate field - actually, we had private_key_path before, but it was deprecated in favor of using private_key with TF or shell capabilities, and it was removed in v1.

@martinw-intersport
Copy link
Author

martinw-intersport commented Jan 16, 2025

Hi @sfc-gh-jmichalak,

i found the reason behind, I use the command openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out rsa_key.p8 -nocrypt from snowflake to generate the private key. And the private key has the empty line at the end, after I remove that line, then export SNOWFLAKE_PRIVATE_KEY=$(cat ~/.ssh/key.p8" works. (I'm not expert in bash, don't know how to solve with sed)

Just to clarify the background we have, so in our team we want to find the one stop solution (like all set in .env or tfvar or toml file) that each member can set up their own different snowflake connection in provider. So hard coding like following does not work and not safe.

  • key embedded in main.tf
  • key sourced from a file with file() function

And we want the private_key_passphrase to be asked and input from terminal instead of saving in file (just leave the variable unset).

Also this statement in README file

Not all fields must be configured in one source; users can choose which fields are configured in which source.
is not correct, when i set private_key content in toml and passphrase as terraform variable, these two fields needs to set in one place.

So as I said before, there's no solution in our mind to set all snowflake connection in one-stop without having private_key_path now.

sfc-gh-jcieslak pushed a commit that referenced this issue Jan 20, 2025
<!-- Feel free to delete comments as you fill this in -->
- Fix handling optional account fields in the state upgrader. This error happened after importing accounts where the optional fields were not set—they are not populated in Import/Read. This resulted in empty values and panics.
- The change has been verified manually. The acceptance test can be added in a follow-up (linked ticket) because of the potential limitations of the plugin SDK.
- Fix failing tests.
- Fix a few issues in docs.

## Test Plan
<!-- detail ways in which this PR has been tested or needs to be tested -->
* [ ] acceptance tests
<!-- add more below if you think they are relevant -->
* [ ] …

## References
<!-- issues documentation links, etc  -->

#3328 #3332
sfc-gh-jcieslak pushed a commit that referenced this issue Jan 20, 2025
…3330)

<!-- Feel free to delete comments as you fill this in -->
- Fix handling optional account fields in the state upgrader. This error happened after importing accounts where the optional fields were not set—they are not populated in Import/Read. This resulted in empty values and panics.
- The change has been verified manually. The acceptance test can be added in a follow-up (linked ticket) because of the potential limitations of the plugin SDK.
- Fix failing tests.
- Fix a few issues in docs.

## Test Plan
<!-- detail ways in which this PR has been tested or needs to be tested -->
* [ ] acceptance tests
<!-- add more below if you think they are relevant -->
* [ ] …

## References
<!-- issues documentation links, etc  -->

#3328 #3332
sfc-gh-jcieslak pushed a commit that referenced this issue Jan 20, 2025
…3330)

<!-- Feel free to delete comments as you fill this in -->
- Fix handling optional account fields in the state upgrader. This error happened after importing accounts where the optional fields were not set—they are not populated in Import/Read. This resulted in empty values and panics.
- The change has been verified manually. The acceptance test can be added in a follow-up (linked ticket) because of the potential limitations of the plugin SDK.
- Fix failing tests.
- Fix a few issues in docs.

## Test Plan
<!-- detail ways in which this PR has been tested or needs to be tested -->
* [ ] acceptance tests
<!-- add more below if you think they are relevant -->
* [ ] …

## References
<!-- issues documentation links, etc  -->

#3328 #3332
sfc-gh-jcieslak pushed a commit that referenced this issue Jan 21, 2025
🤖 I have created a release *beep* *boop*
---


##
[1.0.2](v1.0.1...v1.0.2)
(2025-01-20)


### 🔧 **Misc**

* Generate ID and ObjectType Show Object Methods
([#3292](#3292))
([f7ff70a](f7ff70a))
* Generate multiline by default
([#3315](#3315))
([520bb4c](520bb4c))
* Overview of the grant ownership resource
([#3342](#3342))
([9f891d6](9f891d6))
* Update docs and migration guide
([#3313](#3313))
([59e333a](59e333a))


### 🐛 **Bug fixes:**

* Fixes in account parameters
([#3310](#3310))
([96a1f17](96a1f17))
* Handle optional account fields in the state upgrader correctly
([#3330](#3330))
([4eae4c8](4eae4c8)),
closes
[#3332](#3332)
* Small fixes
([#3337](#3337))
([8807839](8807839))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: snowflake-release-please[bot] <105954990+snowflake-release-please[bot]@users.noreply.github.com>
@martinw-intersport
Copy link
Author

Hi @sfc-gh-jmichalak,

why this issue has been closed? Could you explain here how we should proceed?

@sfc-gh-jmichalak
Copy link
Collaborator

Hi @martinw-intersport, I'm sorry, it has been closed by some Github automation :(

It's true that private_key and private_key_passphrase can't be read from 2 different sources - this is a mistake on our end. However, I think you should be able to set them both in main.tf, with usage of TF variables. These variables can be overridden during terraform apply, so the passphrase would be passed during command execution instead of being stored in a file. I will get back to you with a more concrete example.

@Bryan-Meier
Copy link

Hopefully this helps others. I found that an easy way to get around some of the issues if you have the key as a string and are following best practices to not store the key in your code, you can create a Terraform Variable for the key contents and another for the passphrase. Then, pass the key variable in as a base64 encoded value. At this point the key is in fact a single line. Then in your provider config when you go to set the private_key attribute, you will base64decode the key.

This is particularly useful for those of us leveraging cloud Terraform platforms like Env0 and Spacelift.

Again, I hope it helps for now until a better solution can be developed.

@sfc-gh-jmichalak
Copy link
Collaborator

The most generic configuration can look like this:

variable "private_key" {
  type      = string
  sensitive = true
}
variable "private_key_passphrase" {
  type      = string
  sensitive = true
}
provider "snowflake" {
  ...
  authenticator = "SNOWFLAKE_JWT"
  private_key            = var.private_key
  private_key_passphrase = var.private_key_passphrase
}

You can now provide these values in multiple ways:

  • If these variables don't have any value set, you will be prompted by Terraform to provide these.
  • If you want to provide them before, you can do it like:
    • Use Terraform VAR environment variables: TF_VAR_private_key="<key>" terraform plan
    • Use Terraform flags: terraform plan -var="private_key=<key>"
    • Use Snowflake Terraform Provider flags: SNOWFLAKE_PRIVATE_KEY="<key>" terraform plan
    • You can also load the variables from the tfvars file like terraform apply -var-file="config.tfvars", but this does not support the file function.
    • Use the default field of the variables - for the key, you can additionally use the file function, as described in the comments above.

These approaches can be mixed for different variables here. We don't need to hardcode any value here.

sfc-gh-jmichalak added a commit that referenced this issue Jan 29, 2025
<!-- Feel free to delete comments as you fill this in -->
- Upgrade github.com/hashicorp/terraform-plugin-docs to v0.19.4. The
newer versions (up to v0.20.1) require bumping Go to v1.22.
- Simplify the templates.
- Add a note about coupling provider fields (#3332)
- Fix a few typos.
<!-- summary of changes -->

## Test Plan
<!-- detail ways in which this PR has been tested or needs to be tested
-->
* [ ] acceptance tests
<!-- add more below if you think they are relevant -->
* [ ] …

## References
<!-- issues documentation links, etc  -->
sfc-gh-jmichalak added a commit that referenced this issue Jan 29, 2025
<!-- Feel free to delete comments as you fill this in -->
- Upgrade github.com/hashicorp/terraform-plugin-docs to v0.19.4. The
newer versions (up to v0.20.1) require bumping Go to v1.22.
- Simplify the templates.
- Add a note about coupling provider fields (#3332)
- Fix a few typos.
<!-- summary of changes -->

<!-- detail ways in which this PR has been tested or needs to be tested
-->
* [ ] acceptance tests
<!-- add more below if you think they are relevant -->
* [ ] …

<!-- issues documentation links, etc  -->
@martinw-intersport
Copy link
Author

@sfc-gh-jmichalak Thanks for your answer that shows comprehensive ways to handle this.

We end up using file function to dynamically load private key from different colleagues. And leave var private_key_passphrase value empty to let terraform prompt it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
category:migration Issues connected with migration to v1.0.0. category:provider_config docs Used to mark issues with documentation remark/questions
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants