Open NLPatras opened 4 days ago
Hi @NLPatras 👋 Could you first confirm that you follow the docs? To read the key from file, you can use file
function like this: private_key = file("<filepath>")
. Also, you can read troubleshooting if you encounter any errors returned from snowflake.
Related issues: #2646, #1515, #2432.
Hi @NLPatras 👋 Could you first confirm that you follow the docs? To read the key from file, you can use
file
function like this:private_key = file("<filepath>")
. Also, you can read troubleshooting if you encounter any errors returned from snowflake.Related issues: #2646, #1515, #2432.
I am not using the pem file since I can not input the file within the Terraform Cloud UI variables, instead i am using the value of the pem file. When using the value hardcoded as shown below it works.
provider "snowflake" { account = "account_id" user = "technical_user" authenticator = "JWT" private_key = "-----BEGIN ENCRYPTED PRIVATE KEY-----.....\n-----END ENCRYPTED PRIVATE KEY-----\n" private_key_passphrase = "password" }
However, when using the same exact value in Terraform Cloud UI variable TF_VAR_snowflake_private_key, it fails with the error "Error: could not retrieve private key: could not parse private key, key is not in PEM format".
@NLPatras did you check the related issues in detail? The last one describes almost the same case with the solution (https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2432#issuecomment-2185508243).
@NLPatras did you check the related issues in detail? The last one describes almost the same case with the solution (#2432 (comment)).
Yes, I did, the pem key that I have used hard coded and it worked was already of the below format having a \n for every new line. "-----BEGIN ENCRYPTED PRIVATE KEY-----\n.....\n-----END ENCRYPTED PRIVATE KEY-----\n"
Did you try the solution from https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2432#issuecomment-2186547837 ?
It does not seem like a problem with the provider but with how it is passed to it (as you said, the key directly in the provider config works).
Did you try the solution from #2432 (comment) ?
It does not seem like a problem with the provider but with how it is passed to it (as you said, the key directly in the provider config works).
The solution provided above, seems to not be suitable for my case. My private key is already in the format that he was trying to achieved with the following commands: ` locals { processed-secret-string = jsondecode(data.aws_secretsmanager_secret_version.snowflake-secret-version.secret_string)
pre-processed-private-key-body = regex("-----BEGIN PRIVATE KEY----- (.*)-----END PRIVATE KEY-----", local.processed-secret-string["PrivateKey"])[0]
processed-private-key-body = replace(local.pre-processed-private-key-body, " ", "\n")
processed-private-key = join("\n", ["-----BEGIN PRIVATE KEY-----", local.processed-private-key-body, "-----END PRIVATE KEY-----"]) }`
What I can recommend to check is to set SNOWFLAKE_PRIVATE_KEY
env instead of TF_VAR_snowflake_private_key
(the same with the SNOWFLAKE_PRIVATE_KEY_PASSPHRASE
) and leave them unset in the provider config:
provider "snowflake" {
account = "account_id"
user = "technical_user"
authenticator = "JWT"
}
(they will be taken from the above envs). It should not change anything but it's worth try. Otherwise, I would still claim that the format must be incorrect in some way (because we do not process it anyhow, and as you claim, setting it directly works).
What I can recommend to check is to set
SNOWFLAKE_PRIVATE_KEY
env instead ofTF_VAR_snowflake_private_key
(the same with theSNOWFLAKE_PRIVATE_KEY_PASSPHRASE
) and leave them unset in the provider config:provider "snowflake" { account = "account_id" user = "technical_user" authenticator = "JWT" }
(they will be taken from the above envs). It should not change anything but it's worth try. Otherwise, I would still claim that the format must be incorrect in some way (because we do not process it anyhow, and as you claim, setting it directly works).
Getting same exact error!
I currently see no other option than the key being formatted badly (assuming no hidden configs like envs are set additionally). For the current implementation, there is no difference between passing the key directly through the config and setting it as an environment variable.
If you have already tried out the solution referenced above (this one: https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2899#issuecomment-2200439319), then there is not much I can offer more.
You can spin out a short test in Golang that checks the output of pem.Decode
(the "encoding/pem"
package). If the first returned value is nil, then the key is bad essentially, something like:
import (
"encoding/pem"
"os"
"testing"
"github.com/stretchr/testify/require"
)
func Test_properlyFormattedKey(t *testing.T) {
t.Run("verify key", func(t *testing.T) {
// you can uncomment it to experiment with the key formats
// leaving it commented out should test against your env value
//t.Setenv("SNOWFLAKE_PRIVATE_KEY", "<your key>")
value := os.Getenv("SNOWFLAKE_PRIVATE_KEY")
require.NotEmpty(t, value)
p, _ := pem.Decode([]byte(value))
require.NotNil(t, p)
})
}
I currently see no other option than the key being formatted badly (assuming no hidden configs like envs are set additionally). For the current implementation, there is no difference between passing the key directly through the config and setting it as an environment variable.
If you have already tried out the solution referenced above (this one: #2899 (comment)), then there is not much I can offer more.
You can spin out a short test in Golang that checks the output of
pem.Decode
(the"encoding/pem"
package). If the first returned value is nil, then the key is bad essentially, something like:import ( "encoding/pem" "os" "testing" "github.com/stretchr/testify/require" ) func Test_properlyFormattedKey(t *testing.T) { t.Run("verify key", func(t *testing.T) { // you can uncomment it to experiment with the key formats // leaving it commented out should test against your env value //t.Setenv("SNOWFLAKE_PRIVATE_KEY", "<your key>") value := os.Getenv("SNOWFLAKE_PRIVATE_KEY") require.NotEmpty(t, value) p, _ := pem.Decode([]byte(value)) require.NotNil(t, p) }) }
I have tried asserting the private key using python script, and it passed the test. Would it make a difference asserting it with golang or python?
Yes. The suggested pem.Decode
is the same one that is used in the provider's implementation.
Yes. The suggested
pem.Decode
is the same one that is used in the provider's implementation.
The assertion of private key with the above script running in golang is a PASS. It is the same exact private key that was hard coded. To recall the private key has the below format. Just a remainder \n has a single backslash.
-----BEGIN ENCRYPTED PRIVATE KEY-----\n...\n...\n...\n-----END ENCRYPTED PRIVATE KEY-----\n
Yes. The suggested
pem.Decode
is the same one that is used in the provider's implementation.
The actual issue is that the Terraform Cloud UI adds to the variables an extra back slash thus if my input has "\n" or "\t" , Terraform Cloud UI returns it as double backslash "\\n" or "\\t" . Therefore the solution is as follow:
provider "snowflake" {
account = var.snowflake_account
user = var.snowflake_user
authenticator = var.snowflake_authenticator
private_key = replace(var.snowflake_private_key, "\\n", "\n")
private_key_passphrase = replace(var.snowflake_private_key_passphrase, "\\t", "\t")
With Terraform Cloud UI env variables named in this way:
TF_VAR_snowflake_account TF_VAR_snowflake_user TF_VAR_snowflake_authenticator TF_VAR_snowflake_private_key - sensitive TF_VAR_snowflake_private_key_passphrase - sensitive
Terraform CLI Version
1.8.5
Terraform Provider Version
0.92.0
Terraform Configuration
Category
category:provider_config
Object type(s)
resource:account_parameter
Expected Behavior
Successful run of terraform apply/plan
Actual Behavior
Error: could not retrieve private key: could not parse private key, key is not in PEM format
Steps to Reproduce
1. Terraform Cloud UI env variables : TF_VAR_snowflake_account TF_VAR_snowflake_user TF_VAR_snowflake_authenticator TF_VAR_snowflake_private_key - sensitive TF_VAR_snowflake_private_key_passphrase - sensitive
2. provider "snowflake" { account = var.snowflake_account user = var.snowflake_user authenticator = var.snowflake_authenticator private_key = var.snowflake_private_key private_key_passphrase = var.snowflake_private_key_passphrase }
How much impact is this issue causing?
Medium
Logs
No response
Additional Information
No response
Would you like to implement a fix?