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

Add AWS secret data source. #20

Merged
merged 3 commits into from
Oct 12, 2017
Merged

Add AWS secret data source. #20

merged 3 commits into from
Oct 12, 2017

Conversation

paddycarver
Copy link
Contributor

This is a fully-functioning data source for retrieving AWS access tokens
and secret tokens from Vault. While the generic vault data source
could be used, this adds more affordances for users (named attributes,
required attributes, marking things as sensitive, generated paths
instead of forcing users to deal with API details, etc.) and allows us
to add some behaviour that helps mitigate AWS' eventual consistency,
which has caused problems for users in the past (credentials are
returned, but when users attempt to use them, they're "not valid"). The
approach to this is fairly naive at the moment (wait for the credentials
to make three successful API calls before returning them), but should
reduce the number of problems users see.

Also add the aws_secret_backend resource, which sets up an AWS secret
backend in Vault. We can't use vault_mount and vault_generic_secret to
set it up, because it needs special configuration (access key and secret
key) written that can't be deleted once written--the way to remove it is
to unmount. So the new resource mounts and writes to the location, and
when deleting, unmounts.

Also, add the aws_secret_role resource, which sets up an AWS secret
backend role. While vault_generic_secret could be used to manage
roles, we get a lot of affordances (named attributes instead of a lump
of JSON, required attributes, hiding API paths from users) by turning
them into a resource.

Finally, add some helpers for dealing with JSON.

Adding the resources all at once isn't ideal, obviously, and I wish I
had a smaller PR here. Unfortunately, I approached the problem from the
data source end, and had to build the stuff I needed to write the tests
and make them pass, and I underestimated how much stuff that would be.
:(

This is a fully-functioning data source for retrieving AWS access tokens
and secret tokens from Vault. While the generic vault data source
_could_ be used, this adds more affordances for users (named attributes,
required attributes, marking things as sensitive, generated paths
instead of forcing users to deal with API details, etc.) and allows us
to add some behaviour that helps mitigate AWS' eventual consistency,
which has caused problems for users in the past (credentials are
returned, but when users attempt to use them, they're "not valid"). The
approach to this is fairly naive at the moment (wait for the credentials
to make three successful API calls before returning them), but should
reduce the number of problems users see.

Also add the aws_secret_backend resource, which sets up an AWS secret
backend in Vault. We can't use vault_mount and vault_generic_secret to
set it up, because it needs special configuration (access key and secret
key) written that can't be deleted once written--the way to remove it is
to unmount. So the new resource mounts and writes to the location, and
when deleting, unmounts.

Also, add the aws_secret_role resource, which sets up an AWS secret
backend role. While vault_generic_secret *could* be used to manage
roles, we get a lot of affordances (named attributes instead of a lump
of JSON, required attributes, hiding API paths from users) by turning
them into a resource.

Finally, add some helpers for dealing with JSON.

Adding the resources all at once isn't ideal, obviously, and I wish I
had a smaller PR here. Unfortunately, I approached the problem from the
data source end, and had to build the stuff I needed to write the tests
and make them pass, and I underestimated how much stuff that would be.
:(
Plans aren't perpetually non-empty anymore on data source changes (or at
least are reporting they're not). Also, ensure network requests get
surrounded by log statements.
Copy link
Member

@apparentlymart apparentlymart left a comment

Choose a reason for hiding this comment

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

Implementation-wise this looks fine. Had a minor quibble with naming inline, but I'm happy to be overridden on that if you chose this name for some consistency with something in Vault I don't know about.

Whether you decide to change the name or not, should be fine to go ahead and merge this without another round of review from me. 👍

"vault_policy": policyResource(),
"vault_mount": mountResource(),
"vault_aws_secret_backend": awsSecretBackendResource(),
"vault_aws_secret_role": awsSecretRoleResource(),
Copy link
Member

Choose a reason for hiding this comment

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

If this is aligning with some terminology in Vault land then all of this comment is moot and ignorable, but...

"Secret Role" doesn't really speak to me as a what it seems to be here. I think this name would ideally have "credentials" in it to make it clear that what we're issuing here is credentials, rather than just generically a "secret" (which could, for example, be an AWS KMS thing, or an IAM server certificate key, etc).

I took a quick skim of the Vault docs related to this backend, and based on that (it looks like they use the terminology "access credentials" there) my suggestion would be vault_aws_access_credentials, to make it very explicit that it's access credentials that we're issuing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So for the line you specifically commented on, the relevant Vault docs say:

The next step is to configure a role. A role is a logical name that maps to a policy used to generated those credentials. You can either supply a user inline policy (via the policy argument), or provide a reference to an existing AWS policy by supplying the full ARN reference (via the arn argument).

For example, lets first create a "deploy" role using an user inline policy as an example:

So I think vault_aws_access_credentials doesn't quite capture the idea of it, if that's what you were suggesting get renamed. Though, looking at the pattern established in later resources, I renamed it vault_aws_secret_backend_role instead of vault_aws_secret_role, which feels a bit clearer.

Similarly, for vault_aws_secret_backend, the docs say:

The first step to using the aws backend is to mount it. Unlike the kv backend, the aws backend is not mounted by default.

{code_snippet}

Next, we must configure the credentials that Vault uses to manage the IAM credentials generated by this secret backend:

This is encapsulated in the vault_aws_secret_backend resource. I didn't call it vault_aws_secret_backend_credentials because it takes care of both the mounting and the credentials configuration, so it seemed clearer to have the name imply we were configuring the entire backend, not just the credentials. The reason the two API calls are combined like that is because removing the credentials once they're configured is impossible, and setting them to an invalid value breaks things, so I was struggling with the Delete function. The canonical way to remove configured credentials, as far as I can tell, is to unmount the backend. So I combined mounting/unmounting the backend and configuring the credentials so it all maps nicely to the CRUD format Terraform expects.

All that said, I can see an argument for renaming the vault_aws_secret data source to vault_aws_access_credentials, if that's what you're referencing. The _secret part largely just came from trying to match the pre-existing generic_secret, to make it obvious that that's generic and this is the aws-specific flavor. But on further consideration, I do like vault_aws_access_credentials better, so I've updated the name to reflect that. If any of this is unclear or does not make sense, or you disagree with it, do let me know.

EOT
}

data "vault_aws_secret" "creds" {
Copy link
Member

Choose a reason for hiding this comment

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

Maybe worth mentioning in a comment here that in practice the remainder of this would probably be in a separate config altogether, since it'd be weird to configure vault with credentials and then immediately read back again in the same config. 😀

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can see use cases (e.g., write one set of creds to vault, have it issue a more restricted set of creds, have Terraform use those to set up your provider) but I can also see it causing confusion, so I added a comment. :)

Also, update names on resources.
@lattwood
Copy link

@paddycarver looks like this isn't solving that issue in #9

@lattwood
Copy link

I still have to run

terraform state rm data.vault_aws_access_credentials.aws

before plan can run

@paddycarver
Copy link
Contributor Author

Hey @lattwood, sorry for the issues! To help me keep things straight, can you just either open a new issue, or we'll reopen #9?

I'd love to see a debug log and any error text you're seeing, as well.

@lattwood
Copy link

Let's re-open #9

@lattwood
Copy link

Hmm, looking like this may be related to stored state

@tyrannosaurus-becks tyrannosaurus-becks deleted the paddy_aws_data_source branch February 16, 2019 00:21
dandandy pushed a commit to dandandy/terraform-provider-vault that referenced this pull request Jun 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants