From 96ac3ba712abf7a6c71e2d619aa2a0782d250f49 Mon Sep 17 00:00:00 2001 From: Kevin Holditch Date: Wed, 25 Oct 2017 12:48:15 +0100 Subject: [PATCH] Add support for AWS IAM authentication. We now support configuration of AWS IAM using AWS' default credential provider chain to obtain credentials from the environment/system properties/credentials profile/ECS/EC2 metadata service. spring.cloud.vault: authentication: AWS_IAM Original pull request: gh-175. Closes gh-134. --- docs/src/main/asciidoc/README.adoc | 6 ++- .../src/main/asciidoc/spring-cloud-vault.adoc | 48 +++++++++++++++++++ spring-cloud-vault-config/pom.xml | 17 +++++++ .../config/ClientAuthenticationFactory.java | 25 ++++++++-- .../cloud/vault/config/VaultProperties.java | 12 ++++- 5 files changed, 102 insertions(+), 6 deletions(-) diff --git a/docs/src/main/asciidoc/README.adoc b/docs/src/main/asciidoc/README.adoc index a66023a5..ad34d4fc 100644 --- a/docs/src/main/asciidoc/README.adoc +++ b/docs/src/main/asciidoc/README.adoc @@ -21,8 +21,10 @@ Specifically for Spring applications: {docs}#vault.config.authentication.appid[AppId], {docs}#vault.config.authentication.approle[AppRole], {docs}#vault.config.authentication.clientcert[Client Certificate], -{docs}#vault.config.authentication.cubbyhole[Cubbyhole], and -{docs}#vault.config.authentication.awsec2[AWS-EC2] authentication +{docs}#vault.config.authentication.cubbyhole[Cubbyhole], +{docs}#vault.config.authentication.awsec2[AWS-EC2] authentication, and +{docs}#vault.config.authentication.awsiam[AWS-IAM] authentication + * Bootstrap application context: a parent context for the main application that can be trained to do anything diff --git a/docs/src/main/asciidoc/spring-cloud-vault.adoc b/docs/src/main/asciidoc/spring-cloud-vault.adoc index d57e17f0..27063ad6 100644 --- a/docs/src/main/asciidoc/spring-cloud-vault.adoc +++ b/docs/src/main/asciidoc/spring-cloud-vault.adoc @@ -280,6 +280,53 @@ authentication method See also: https://www.vaultproject.io/docs/auth/aws-ec2.html[Vault Documentation: Using the aws-ec2 auth backend] +[[vault.config.authentication.awsiam]] +=== AWS-IAM authentication + +The https://www.vaultproject.io/docs/auth/aws-ec2.html[aws] backend provides a secure +authentication mechanism for AWS IAM roles, allowing the automatic authentication with +vault based on the current IAM role of the running application. + Unlike most Vault authentication backends, this backend +does not require first-deploying, or provisioning security-sensitive +credentials (tokens, username/password, client certificates, etc.). +Instead, it treats AWS as a Trusted Third Party and uses the +4 pieces of information signed by the caller with their IAM credentials + to verify that the caller is indeed using that IAM role. + +The current IAM role the application is running in is automatically calculated. If you are +running your application on AWS ECS then the application will use the IAM role assigned +to the ECS task of the running container. If you are running your application naked on top of +an EC2 instance then the IAM role used will be the one assigned to the EC2 instance. + +When using the AWS-IAM authentication you must create a role in vault and assign it to your IAM + role. If no vault-role value is supplied in the configuration (as below) then the friendly name + of the current IAM role will be used as the vault role. + +.bootstrap.yml with required AWS-IAM Authentication properties +==== +[source,yaml] +---- +spring.cloud.vault: + authentication: AWS_IAM +---- +==== + + +.bootstrap.yml with all AWS-IAM Authentication properties +==== +[source,yaml] +---- +spring.cloud.vault: + authentication: AWS_IAM + vault-role: my-dev-role +---- +==== + +* `vault-role` sets the vault-role that is to be logged in to, this should be bound to your IAM role. If one is not + supplied then the friendly name of the current IAM user will be used as the vault role. + +See also: https://www.vaultproject.io/docs/auth/aws.html[Vault documentation on configuring iam auth] + [[vault.config.authentication.clientcert]] === TLS certificate authentication @@ -352,6 +399,7 @@ See also: * https://www.vaultproject.io/docs/secrets/cubbyhole/index.html[Vault Documentation: Cubbyhole Secret Backend] * https://www.vaultproject.io/docs/concepts/response-wrapping.html[Vault Documentation: Response Wrapping] + [[vault.config.backends]] == Secret Backends diff --git a/spring-cloud-vault-config/pom.xml b/spring-cloud-vault-config/pom.xml index e4a571bb..02f61786 100644 --- a/spring-cloud-vault-config/pom.xml +++ b/spring-cloud-vault-config/pom.xml @@ -76,6 +76,23 @@ true + + com.amazonaws + aws-java-sdk-core + true + 1.11.208 + + + software.amazon.ion + ion-java + + + com.fasterxml.jackson.dataformat + jackson-dataformat-cbor + + + + org.apache.httpcomponents httpcore diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/ClientAuthenticationFactory.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/ClientAuthenticationFactory.java index c9fcd105..20eeb40c 100644 --- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/ClientAuthenticationFactory.java +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/ClientAuthenticationFactory.java @@ -15,10 +15,9 @@ */ package org.springframework.cloud.vault.config; -import java.net.URI; - +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; import lombok.RequiredArgsConstructor; - import org.springframework.beans.BeanUtils; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -28,6 +27,8 @@ import org.springframework.vault.authentication.AwsEc2AuthenticationOptions.Nonc import org.springframework.vault.support.VaultToken; import org.springframework.web.client.RestOperations; +import java.net.URI; + /** * Factory for {@link ClientAuthentication}. * @@ -65,6 +66,9 @@ class ClientAuthenticationFactory { case AWS_EC2: return awsEc2Authentication(vaultProperties); + case AWS_IAM: + return awsIamAuthentication(vaultProperties); + case CUBBYHOLE: return cubbyholeAuthentication(); } @@ -155,6 +159,21 @@ class ClientAuthenticationFactory { restOperations); } + private ClientAuthentication awsIamAuthentication(VaultProperties vaultProperties) { + + AwsIamAuthenticationOptions.AwsIamAuthenticationOptionsBuilder awsIamAuthenticationOptionsBuilder = AwsIamAuthenticationOptions.builder(); + + if (vaultProperties.getAwsIam() != null && vaultProperties.getAwsIam().getVaultRole() != null) + awsIamAuthenticationOptionsBuilder.role(vaultProperties.getAwsIam().getVaultRole()); + + AwsIamAuthenticationOptions options = awsIamAuthenticationOptionsBuilder + .credentialsProvider(new DefaultAWSCredentialsProviderChain()) + .build(); + + return new AwsIamAuthentication(options, restOperations); + + } + private ClientAuthentication cubbyholeAuthentication() { Assert.hasText(vaultProperties.getToken(), diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultProperties.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultProperties.java index d28f13b3..03872f54 100644 --- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultProperties.java +++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultProperties.java @@ -94,6 +94,8 @@ public class VaultProperties implements EnvironmentAware { private AwsEc2Properties awsEc2 = new AwsEc2Properties(); + private AwsIamProperties awsIam = new AwsIamProperties(); + private Ssl ssl = new Ssl(); private Config config = new Config(); @@ -216,6 +218,14 @@ public class VaultProperties implements EnvironmentAware { private String nonce; } + @Data + public static class AwsIamProperties { + /** + * Name of the vault role, optional if not specified then the friendly IAM name will be used. + */ + private String vaultRole; + } + @Data @Validated public static class Ssl { @@ -275,6 +285,6 @@ public class VaultProperties implements EnvironmentAware { } public enum AuthenticationMethod { - TOKEN, APPID, APPROLE, AWS_EC2, CERT, CUBBYHOLE; + TOKEN, APPID, APPROLE, AWS_EC2, AWS_IAM, CERT, CUBBYHOLE; } }