-
Notifications
You must be signed in to change notification settings - Fork 50
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
replace TokenFile with direct Token in provider configuration #1053
Conversation
Optional: true, | ||
Description: "The path to a file containing a JWT token retrieved from an OpenID Connect (OIDC) or OAuth2 provider. Exactly one of `token_file` or `token` must be set.", | ||
Validators: []validator.String{ | ||
stringvalidator.LengthAtLeast(1), |
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.
Could we use stringvalidator.ConflictsWith
or something similar to have TF validate only one 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.
Nice, didn't know they had such specific validators. I did end up using ExactlyOneOf
instead of just ConflictsWith
- I think that has the same effect but with an additional validation that one must be set.
I've tested this locally, and all is working 🎉 |
docs/index.md
Outdated
|
||
Optional: | ||
|
||
- `token` (String) The JWT token retrieved from an OpenID Connect (OIDC) or OAuth2 provider. Exactly one of `token_file` or `token` must be 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.
What is the motivation of doing an exactly one?
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.
This is two different ways of specifying the same information. Either the token has been written to disk, in which case you should specify the token_file
variable, or the token has been loaded dynamically and Terraform just has it, in which case you should specify it directly via token
.
It doesn't make sense to specify both of these together. Similarly, you must specify the token somehow if you are authenticating via the block, so you must specify at least one.
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.
Letting the user specifying both with a priority would simplify the conditional. I understand the need for at least once. As an example, firebase/firebase-tool: https://github.com/firebase/firebase-tools?tab=readme-ov-file#general
Ultimately, I don't mind having a exactly once, I would like to know the why behind 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.
I've changed this to AtLeastOneOf
, and the token
field takes precedence over the token_file
field.
internal/clients/client.go
Outdated
@@ -122,18 +127,35 @@ func NewClient(config ClientConfig) (*Client, error) { | |||
opts = append(opts, hcpConfig.WithClientCredentials(config.ClientID, config.ClientSecret)) | |||
} else if config.CredentialFile != "" { | |||
opts = append(opts, hcpConfig.WithCredentialFilePath(config.CredentialFile)) | |||
} else if config.WorloadIdentityTokenFile != "" && config.WorkloadIdentityResourceName != "" { | |||
} else if (config.WorkloadIdentityToken != "" || config.WorkloadIdentityTokenFile != "") && config.WorkloadIdentityResourceName != "" { |
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.
This is hard to parse for my out-of-context brain. Is it possible to do it better?
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.
I've pulled out the combined or logic into a standalone variable, and added some additional comments explaining the flow. Hopefully, that is better?
@@ -101,15 +101,15 @@ func GetRotatingSecretState(ctx context.Context, client *Client, loc *sharedmode | |||
|
|||
// CreateMongoDBAtlasRotationIntegration NOTE: currently just needed for tests | |||
func CreateMongoDBAtlasRotationIntegration(ctx context.Context, client *Client, loc *sharedmodels.HashicorpCloudLocationLocation, integrationName, mongodbAtlasPublicKey, mongodbAtlasPrivateKey string) (*secretmodels.Secrets20231128MongoDBAtlasIntegration, error) { | |||
body := secret_service.CreateMongoDBAtlasIntegrationBody{ | |||
body := secretmodels.SecretServiceCreateMongoDBAtlasIntegrationBody{ |
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.
Can you give some context for those changes?
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.
These are changes forced by the hcp-sdk-go upgrade that also added in the new token
input when authenticating. The old approach (via the secret_service
package) has gone and so wasn't compiling after the upgrade.
There's no functional changes here, the location and names of the various structs have simply been moved around in the referenced library, so the code needs to be updated to point to the new locations.
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.
I don't see any added or updated test
docs/index.md
Outdated
|
||
Optional: | ||
|
||
- `token` (String) The JWT token retrieved from an OpenID Connect (OIDC) or OAuth2 provider. Exactly one of `token_file` or `token` must be 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.
Letting the user specifying both with a priority would simplify the conditional. I understand the need for at least once. As an example, firebase/firebase-tool: https://github.com/firebase/firebase-tools?tab=readme-ov-file#general
Ultimately, I don't mind having a exactly once, I would like to know the why behind it.
internal/clients/client.go
Outdated
@@ -116,24 +121,47 @@ type ClientConfig struct { | |||
|
|||
// NewClient creates a new Client that is capable of making HCP requests | |||
func NewClient(config ClientConfig) (*Client, error) { | |||
hasWorkloadIdentityToken := config.WorkloadIdentityToken != "" || config.WorkloadIdentityTokenFile != "" |
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.
I like that approach of add boolean, i think it would be beneficial to add even more which will make your intention more clear and the make the code a little bit more self documenting.
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.
I've added more in 👍
This is very difficult to test with an automated process. It's why there weren't any automatic tests for the previous implementation which just supported the We'd need to:
I've tested this manually by modifying TFC / Atlas / tfc-agent so that I can get a JWT from there which usually isn't possible, and definitely not something we should allow in normal operation. I then built the provider locally, and tested Terraform operations using the JWT I hacked out of TFC with my HCP account set up to trust TFC. I could add some unit tests for this, but the client actually initiates the token exchange as part of it's initialisation, so we'd need to create some kind of mock or move the token exchange out of initialisation and refactor everything to call the token exchange after. |
I would be minimally happy with only unit test that validate that the expected output are created from the given input. |
Added unit tests! |
🛠️ Description
For Stacks, we want to support the ability to process the JWT directly instead of loading it via a file. This PR updates the provider configuration so that users can choose to specify the token directly instead of writing it into a file first. The old approach of writing into a file is still available.