diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubeAuthenticationOptions.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubeAuthenticationOptions.java deleted file mode 100644 index 03954e0f..00000000 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubeAuthenticationOptions.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2016-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.vault.authentication; - -import org.springframework.util.Assert; - -/** - * Authentication options for {@link KubeAuthentication}. - *

- * Authentication options provide the path, role and jwt supplier. - * {@link KubeAuthentication} can be constructed using {@link #builder()}. Instances of - * this class are immutable once constructed. - * - * @author Michal Budzyn - * @see KubeAuthentication - * @see #builder() - */ -public class KubeAuthenticationOptions { - - public static final String DEFAULT_KUBERNETES_AUTHENTICATION_PATH = "kubernetes"; - - /** - * Path of the kubernetes authentication backend mount. - */ - private final String path; - - /** - * The Role. - */ - private final String role; - - /** - * {@link KubeJwtSupplier} instance to obtain a service account JSON Web Tokens. - */ - private final KubeJwtSupplier jwtSupplier; - - private KubeAuthenticationOptions(String path, String role, - KubeJwtSupplier jwtSupplier) { - - this.path = path; - this.role = role; - this.jwtSupplier = jwtSupplier; - } - - public static KubernetesAuthenticationOptionsBuilder builder() { - return new KubernetesAuthenticationOptionsBuilder(); - } - - public String getPath() { - return path; - } - - public String getRole() { - return role; - } - - public KubeJwtSupplier getJwtSupplier() { - return jwtSupplier; - } - - /** - * Builder for {@link KubeAuthenticationOptions}. - */ - public static class KubernetesAuthenticationOptionsBuilder { - private String path = DEFAULT_KUBERNETES_AUTHENTICATION_PATH; - - private String role; - - private KubeJwtSupplier jwtSupplier; - - public KubernetesAuthenticationOptionsBuilder path(String path) { - - Assert.hasText(path, "Path must not be empty"); - - this.path = path; - return this; - } - - public KubernetesAuthenticationOptionsBuilder role(String role) { - - Assert.hasText(role, "Role must not be empty"); - - this.role = role; - return this; - } - - public KubernetesAuthenticationOptionsBuilder jwtSupplier( - KubeJwtSupplier jwtSupplier) { - - Assert.notNull(jwtSupplier, "JwtSupplier must not be null"); - - this.jwtSupplier = jwtSupplier; - return this; - } - - public KubeAuthenticationOptions build() { - - Assert.notNull(role, "Role must not be null"); - Assert.notNull(path, "Path must not be null"); - Assert.notNull(jwtSupplier, "JwtSupplier must not be null"); - - return new KubeAuthenticationOptions(path, role, jwtSupplier); - } - } -} \ No newline at end of file diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubeServiceAccountTokenFile.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubeServiceAccountTokenFile.java deleted file mode 100644 index 00359feb..00000000 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubeServiceAccountTokenFile.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2016-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.vault.authentication; - -import static java.nio.charset.StandardCharsets.US_ASCII; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - -import org.springframework.core.io.FileSystemResource; -import org.springframework.core.io.Resource; -import org.springframework.util.StreamUtils; -import org.springframework.vault.VaultException; - -/** - * Mechanism to retrieve a Kubernetes service account token. - *

- * A file containing a token for a pod’s service account is automatically mounted at - * /var/run/secrets/kubernetes.io/serviceaccount/token - * - * @author Michal Budzyn - * @see KubeJwtSupplier - */ -public class KubeServiceAccountTokenFile implements KubeJwtSupplier { - - public static final String DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_FILE = "/var/run/secrets/kubernetes.io/serviceaccount/token"; - - private final Resource resource; - - public KubeServiceAccountTokenFile() { - this(DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_FILE); - } - - public KubeServiceAccountTokenFile(String fileName) { - this(new FileSystemResource(fileName)); - } - - public KubeServiceAccountTokenFile(File file) { - this(new FileSystemResource(file)); - } - - public KubeServiceAccountTokenFile(Resource resource) { - this.resource = resource; - } - - @Override - public String getKubeJwt() { - try (InputStream is = resource.getInputStream()) { - return StreamUtils.copyToString(is, US_ASCII); - } - catch (IOException e) { - throw new VaultException( - String.format("Kube JWT token retrieval from %s failed", resource), - e); - } - } -} diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubeAuthentication.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesAuthentication.java similarity index 56% rename from spring-vault-core/src/main/java/org/springframework/vault/authentication/KubeAuthentication.java rename to spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesAuthentication.java index b21859e1..42beb8ce 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubeAuthentication.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesAuthentication.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017 the original author or authors. + * Copyright 2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.util.Assert; import org.springframework.vault.VaultException; import org.springframework.vault.client.VaultResponses; @@ -29,32 +30,36 @@ import org.springframework.web.client.HttpStatusCodeException; import org.springframework.web.client.RestOperations; /** - * Kubernetes implementation of {@link ClientAuthentication}. {@link KubeAuthentication} - * uses a Kubernetes Service Account JSON Web Token to login into Vault. JWT and Role are - * sent in the login request to Vault to obtain a {@link VaultToken}. + * Kubernetes implementation of {@link ClientAuthentication}. + * {@link KubernetesAuthentication} uses a Kubernetes Service Account JSON Web Token to + * login into Vault. JWT and Role are sent in the login request to Vault to obtain a + * {@link VaultToken}. * * @author Michal Budzyn - * @see KubeAuthenticationOptions + * @author Mark Paluch + * @since 2.0 + * @see KubernetesAuthenticationOptions * @see RestOperations * @see Auth Backend: * Kubernetes */ -public class KubeAuthentication implements ClientAuthentication { +public class KubernetesAuthentication implements ClientAuthentication, + AuthenticationStepsFactory { - private static final Log logger = LogFactory.getLog(KubeAuthentication.class); + private static final Log logger = LogFactory.getLog(KubernetesAuthentication.class); - private final KubeAuthenticationOptions options; + private final KubernetesAuthenticationOptions options; private final RestOperations restOperations; /** - * Create a {@link KubeAuthentication} using {@link KubeAuthenticationOptions} and - * {@link RestOperations}. + * Create a {@link KubernetesAuthentication} using + * {@link KubernetesAuthenticationOptions} and {@link RestOperations}. * * @param options must not be {@literal null}. * @param restOperations must not be {@literal null}. */ - public KubeAuthentication(KubeAuthenticationOptions options, + public KubernetesAuthentication(KubernetesAuthenticationOptions options, RestOperations restOperations) { Assert.notNull(options, "KubeAuthenticationOptions must not be null"); @@ -64,28 +69,29 @@ public class KubeAuthentication implements ClientAuthentication { this.restOperations = restOperations; } - private static Map getKubeLogin(String role, String jwt) { + /** + * Creates a {@link AuthenticationSteps} for kubernetes authentication given + * {@link KubernetesAuthenticationOptions}. + * + * @param options must not be {@literal null}. + * @return {@link AuthenticationSteps} for kubernetes authentication. + */ + public static AuthenticationSteps createAuthenticationSteps( + KubernetesAuthenticationOptions options) { - Assert.hasText(role, "role must not be empty"); - Assert.hasText(role, "jwt must not be empty"); + Assert.notNull(options, "CubbyholeAuthenticationOptions must not be null"); - Map login = new HashMap<>(); - - login.put("jwt", jwt); - login.put("role", role); - - return login; + String token = options.getJwtSupplier().get(); + return AuthenticationSteps.fromSupplier( + () -> getKubernetesLogin(options.getRole(), token)) // + .login("auth/{mount}/login", options.getPath()); } @Override public VaultToken login() throws VaultException { - return createTokenUsingKubernetes(); - } - private VaultToken createTokenUsingKubernetes() { - - Map login = getKubeLogin(options.getRole(), - options.getJwtSupplier().getKubeJwt()); + Map login = getKubernetesLogin(options.getRole(), options + .getJwtSupplier().get()); try { VaultResponse response = restOperations.postForObject("auth/{mount}/login", @@ -103,4 +109,22 @@ public class KubeAuthentication implements ClientAuthentication { VaultResponses.getError(e.getResponseBodyAsString()))); } } + + @Override + public AuthenticationSteps getAuthenticationSteps() { + return createAuthenticationSteps(this.options); + } + + private static Map getKubernetesLogin(String role, String jwt) { + + Assert.hasText(role, "Role must not be empty"); + Assert.hasText(role, "JWT must not be empty"); + + Map login = new HashMap<>(); + + login.put("jwt", jwt); + login.put("role", role); + + return login; + } } diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesAuthenticationOptions.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesAuthenticationOptions.java new file mode 100644 index 00000000..e506d43b --- /dev/null +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesAuthenticationOptions.java @@ -0,0 +1,162 @@ +/* + * Copyright 2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.vault.authentication; + +import java.util.function.Supplier; + +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * Authentication options for {@link KubernetesAuthentication}. + *

+ * Authentication options provide the path, role and jwt supplier. + * {@link KubernetesAuthentication} can be constructed using {@link #builder()}. Instances + * of this class are immutable once constructed. + * + * @author Michal Budzyn + * @author Mark Paluch + * @since 2.0 + * @see KubernetesAuthentication + * @see #builder() + */ +public class KubernetesAuthenticationOptions { + + public static final String DEFAULT_KUBERNETES_AUTHENTICATION_PATH = "kubernetes"; + + /** + * Path of the kubernetes authentication backend mount. + */ + private final String path; + + /** + * Name of the role against which the login is being attempted. + */ + private final String role; + + /** + * Supplier instance to obtain a service account JSON Web Tokens. + */ + private final Supplier jwtSupplier; + + private KubernetesAuthenticationOptions(String path, String role, + Supplier jwtSupplier) { + + this.path = path; + this.role = role; + this.jwtSupplier = jwtSupplier; + } + + /** + * @return a new {@link KubernetesAuthenticationOptionsBuilder}. + */ + public static KubernetesAuthenticationOptionsBuilder builder() { + return new KubernetesAuthenticationOptionsBuilder(); + } + + /** + * @return the path of the aws authentication backend mount. + */ + public String getPath() { + return path; + } + + /** + * @return name of the role against which the login is being attempted. + */ + public String getRole() { + return role; + } + + /** + * @return JSON Web Token supplier. + */ + public Supplier getJwtSupplier() { + return jwtSupplier; + } + + /** + * Builder for {@link KubernetesAuthenticationOptions}. + */ + public static class KubernetesAuthenticationOptionsBuilder { + + private String path = DEFAULT_KUBERNETES_AUTHENTICATION_PATH; + + @Nullable + private String role; + + @Nullable + private Supplier jwtSupplier; + + /** + * Configure the mount path. + * + * @param path must not be {@literal null} or empty. + * @return {@code this} {@link KubernetesAuthenticationOptionsBuilder}. + */ + public KubernetesAuthenticationOptionsBuilder path(String path) { + + Assert.hasText(path, "Path must not be empty"); + + this.path = path; + return this; + } + + /** + * Configure the role. + * + * @param role name of the role against which the login is being attempted, must + * not be {@literal null} or empty. + * @return {@code this} {@link KubernetesAuthenticationOptionsBuilder}. + */ + public KubernetesAuthenticationOptionsBuilder role(String role) { + + Assert.hasText(role, "Role must not be empty"); + + this.role = role; + return this; + } + + /** + * Configure the {@link Supplier} to obtain a Kubernetes authentication token. + * + * @param jwtSupplier the supplier, must not be {@literal null}. + * @return {@code this} {@link KubernetesAuthenticationOptionsBuilder}. + */ + public KubernetesAuthenticationOptionsBuilder jwtSupplier( + Supplier jwtSupplier) { + + Assert.notNull(jwtSupplier, "JwtSupplier must not be null"); + + this.jwtSupplier = jwtSupplier; + return this; + } + + /** + * Build a new {@link KubernetesAuthenticationOptions} instance. + * + * @return a new {@link KubernetesAuthenticationOptions}. + */ + public KubernetesAuthenticationOptions build() { + + Assert.notNull(role, "Role must not be null"); + + return new KubernetesAuthenticationOptions(path, role, + jwtSupplier == null ? new KubernetesServiceAccountTokenFile() + : jwtSupplier); + } + } +} diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubeJwtSupplier.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesJwtSupplier.java similarity index 76% rename from spring-vault-core/src/main/java/org/springframework/vault/authentication/KubeJwtSupplier.java rename to spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesJwtSupplier.java index 10fe8376..44033c26 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubeJwtSupplier.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesJwtSupplier.java @@ -15,19 +15,25 @@ */ package org.springframework.vault.authentication; +import java.util.function.Supplier; + /** * Interface to obtain a Kubernetes Service Account Token for Kubernetes authentication. - * Implementations are used by {@link KubeAuthentication}. + * Implementations are used by {@link KubernetesAuthentication}. * * @author Michal Budzyn - * @see KubeAuthentication + * @author Mark Paluch + * @since 2.0 + * @see KubernetesAuthentication */ -public interface KubeJwtSupplier { +@FunctionalInterface +public interface KubernetesJwtSupplier extends Supplier { /** * Get a JWT for Kubernetes authentication. * * @return the Kubernetes Service Account JWT. */ - String getKubeJwt(); + @Override + String get(); } diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesServiceAccountTokenFile.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesServiceAccountTokenFile.java new file mode 100644 index 00000000..f1cbef4f --- /dev/null +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesServiceAccountTokenFile.java @@ -0,0 +1,124 @@ +/* + * Copyright 2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.vault.authentication; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.util.Assert; +import org.springframework.util.StreamUtils; +import org.springframework.vault.VaultException; + +/** + * Mechanism to retrieve a Kubernetes service account token. + *

+ * A file containing a token for a pod's service account is automatically mounted at + * {@code /var/run/secrets/kubernetes.io/serviceaccount/token}. + * + * @author Michal Budzyn + * @author Mark Paluch + * @since 2.0 + * @see KubernetesJwtSupplier + */ +public class KubernetesServiceAccountTokenFile implements KubernetesJwtSupplier { + + /** + * Default path to the service account token file. + */ + public static final String DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_FILE = "/var/run/secrets/kubernetes.io/serviceaccount/token"; + + private byte[] token; + + /** + * Create a new {@link KubernetesServiceAccountTokenFile} pointing to the + * {@link #DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_FILE}. Construction fails with an + * exception if the file does not exist. + * + * @throws IllegalArgumentException if the + * {@link #DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_FILE} does not exist. + */ + public KubernetesServiceAccountTokenFile() { + this(DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_FILE); + } + + /** + * Create a new {@link KubernetesServiceAccountTokenFile} + * {@link KubernetesServiceAccountTokenFile} from a {@code path}. + * + * @param path path to the service account token file. + * @throws IllegalArgumentException if the{@code path} does not exist. + */ + public KubernetesServiceAccountTokenFile(String path) { + this(new FileSystemResource(path)); + } + + /** + * Create a new {@link KubernetesServiceAccountTokenFile} + * {@link KubernetesServiceAccountTokenFile} from a {@link File} handle. + * + * @param file path to the service account token file. + * @throws IllegalArgumentException if the{@code path} does not exist. + */ + public KubernetesServiceAccountTokenFile(File file) { + this(new FileSystemResource(file)); + } + + /** + * Create a new {@link KubernetesServiceAccountTokenFile} + * {@link KubernetesServiceAccountTokenFile} from a {@link Resource} handle. + * + * @param resource resource pointing to the service account token file. + * @throws IllegalArgumentException if the{@code path} does not exist. + */ + public KubernetesServiceAccountTokenFile(Resource resource) { + + Assert.isTrue(resource.exists(), + () -> String.format("Resource %s does not exist", resource)); + + try { + this.token = readToken(resource); + } + catch (IOException e) { + throw new VaultException(String.format( + "Kube JWT token retrieval from %s failed", resource), e); + } + } + + @Override + public String get() { + return new String(token, StandardCharsets.US_ASCII); + } + + /** + * Read the token from {@link Resource}. + * + * @param resource the resource to read from, must not be {@literal null}. + * @return the new byte array that has been copied to (possibly empty). + * @throws IOException in case of I/O errors. + */ + protected static byte[] readToken(Resource resource) throws IOException { + + Assert.notNull(resource, "Resource must not be null"); + + try (InputStream is = resource.getInputStream()) { + return StreamUtils.copyToByteArray(is); + } + } +} diff --git a/spring-vault-core/src/main/java/org/springframework/vault/config/EnvironmentVaultConfiguration.java b/spring-vault-core/src/main/java/org/springframework/vault/config/EnvironmentVaultConfiguration.java index 6f49d65a..f58ae504 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/config/EnvironmentVaultConfiguration.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/config/EnvironmentVaultConfiguration.java @@ -32,23 +32,23 @@ import org.springframework.vault.authentication.AppRoleAuthentication; import org.springframework.vault.authentication.AppRoleAuthenticationOptions; import org.springframework.vault.authentication.AwsEc2Authentication; import org.springframework.vault.authentication.AwsEc2AuthenticationOptions; -import org.springframework.vault.authentication.AwsEc2AuthenticationOptions.AwsEc2AuthenticationOptionsBuilder; import org.springframework.vault.authentication.ClientAuthentication; import org.springframework.vault.authentication.ClientCertificateAuthentication; import org.springframework.vault.authentication.CubbyholeAuthentication; import org.springframework.vault.authentication.CubbyholeAuthenticationOptions; import org.springframework.vault.authentication.IpAddressUserId; -import org.springframework.vault.authentication.KubeAuthentication; -import org.springframework.vault.authentication.KubeAuthenticationOptions; -import org.springframework.vault.authentication.KubeJwtSupplier; -import org.springframework.vault.authentication.KubeServiceAccountTokenFile; +import org.springframework.vault.authentication.KubernetesAuthentication; +import org.springframework.vault.authentication.KubernetesAuthenticationOptions; +import org.springframework.vault.authentication.KubernetesJwtSupplier; +import org.springframework.vault.authentication.KubernetesServiceAccountTokenFile; import org.springframework.vault.authentication.MacAddressUserId; import org.springframework.vault.authentication.StaticUserId; import org.springframework.vault.authentication.TokenAuthentication; +import org.springframework.vault.authentication.AwsEc2AuthenticationOptions.AwsEc2AuthenticationOptionsBuilder; import org.springframework.vault.client.VaultEndpoint; import org.springframework.vault.support.SslConfiguration; -import org.springframework.vault.support.SslConfiguration.KeyStoreConfiguration; import org.springframework.vault.support.VaultToken; +import org.springframework.vault.support.SslConfiguration.KeyStoreConfiguration; import org.springframework.web.client.RestOperations; /** @@ -138,7 +138,7 @@ import org.springframework.web.client.RestOperations; * @see AwsEc2Authentication * @see ClientCertificateAuthentication * @see CubbyholeAuthentication - * @see KubeAuthentication + * @see KubernetesAuthentication */ @Configuration public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration implements @@ -339,14 +339,18 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration im String tokenFile = getProperty("vault.kubernetes.service-account-token-file"); if (!StringUtils.hasText(tokenFile)) { - tokenFile = KubeServiceAccountTokenFile.DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_FILE; + tokenFile = KubernetesServiceAccountTokenFile.DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_FILE; } - KubeJwtSupplier jwtSupplier = new KubeServiceAccountTokenFile(tokenFile); + KubernetesJwtSupplier jwtSupplier = new KubernetesServiceAccountTokenFile( + tokenFile); - KubeAuthenticationOptions authenticationOptions = KubeAuthenticationOptions - .builder().role(role).jwtSupplier(jwtSupplier).build(); + KubernetesAuthenticationOptions authenticationOptions = KubernetesAuthenticationOptions + .builder() // + .role(role) // + .jwtSupplier(jwtSupplier) // + .build(); - return new KubeAuthentication(authenticationOptions, restOperations()); + return new KubernetesAuthentication(authenticationOptions, restOperations()); } @Nullable diff --git a/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubeServiceAccountTokenFileUnitTests.java b/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubeServiceAccountTokenFileUnitTests.java index c2d93c47..f8fd23a1 100644 --- a/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubeServiceAccountTokenFileUnitTests.java +++ b/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubeServiceAccountTokenFileUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017 the original author or authors. + * Copyright 2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,34 +15,51 @@ */ package org.springframework.vault.authentication; -import static org.assertj.core.api.Assertions.assertThat; - import org.junit.Test; + import org.springframework.core.io.ClassPathResource; +import static org.assertj.core.api.Assertions.assertThat; + /** - * Unit tests for {@link KubeServiceAccountTokenFile}. + * Unit tests for {@link KubernetesServiceAccountTokenFile}. * * @author Michal Budzyn + * @author Mark Paluch */ - public class KubeServiceAccountTokenFileUnitTests { - private final static String TEST_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tNHcydmciLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjllMjQzNWY0LTgxNDctMTFlNy05MGFiLTA4MDAyN2NlZTQwNyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.asFRZRZ1gRj9sF0lQqbbxrNhW_lOdj9WjqUpH_4TstxqZZ7B36a0xKKXg6XaFWJY1eMsytpwa7uMzvsvf2pYCcklinaSE_F-wc42IOWcpwSLl4PND92Tp7n_JYEAbbSQVfZPzQ2Y7b6cWu6NRzDs638LwVTqYeWMWbcWlOMaTxjMzGTcgDe5RWslkKUPkYsvPOAFtt5ZErwtVcvTUmplJfHzdWwatlpZRQhYkxGgRIJ6LabXfZOd2N_TchJ3tHjAVBzUDTQq3APQssGb9df2RxVTUiyzbhdRGt7129-LCZ8rZYE7E-Mr3SSpExGYcDk-v0It8hky0CKtCLs2UHiABA"; + private final static String TEST_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9." + + "eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy" + + "5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJu" + + "ZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG" + + "9rZW4tNHcydmciLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZp" + + "Y2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2Vydm" + + "ljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjllMjQzNWY0LTgxNDctMT" + + "FlNy05MGFiLTA4MDAyN2NlZTQwNyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3" + + "VudDpkZWZhdWx0OmRlZmF1bHQifQ." + + "asFRZRZ1gRj9sF0lQqbbxrNhW_lOdj9WjqUpH_4TstxqZZ7B36a0xKKXg6XaFW" + + "JY1eMsytpwa7uMzvsvf2pYCcklinaSE_F-wc42IOWcpwSLl4PND92Tp7n_JYEAbb" + + "SQVfZPzQ2Y7b6cWu6NRzDs638LwVTqYeWMWbcWlOMaTxjMzGTcgDe5RWslkKUPkY" + + "svPOAFtt5ZErwtVcvTUmplJfHzdWwatlpZRQhYkxGgRIJ6LabXfZOd2N_TchJ3tH" + + "jAVBzUDTQq3APQssGb9df2RxVTUiyzbhdRGt7129-LCZ8rZYE7E-Mr3SSpExGYcD" + + "k-v0It8hky0CKtCLs2UHiABA"; @Test - public void shouldGetJwtTokenFromResource() throws Exception { - final String jwt = new KubeServiceAccountTokenFile( - new ClassPathResource("kube-jwt-token")).getKubeJwt(); + public void shouldGetJwtTokenFromResource() { + + String jwt = new KubernetesServiceAccountTokenFile(new ClassPathResource( + "kube-jwt-token")).get(); assertThat(jwt).isEqualTo(TEST_TOKEN); } @Test public void shouldGetJwtTokenFromFile() throws Exception { - final String fileName = new ClassPathResource("kube-jwt-token").getFile() + + String fileName = new ClassPathResource("kube-jwt-token").getFile() .getAbsolutePath(); - final String jwt = new KubeServiceAccountTokenFile(fileName).getKubeJwt(); + String jwt = new KubernetesServiceAccountTokenFile(fileName).get(); assertThat(jwt).isEqualTo(TEST_TOKEN); } -} \ No newline at end of file +} diff --git a/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubeAuthenticationIntegrationTestBase.java b/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubernetesAuthenticationIntegrationTestBase.java similarity index 84% rename from spring-vault-core/src/test/java/org/springframework/vault/authentication/KubeAuthenticationIntegrationTestBase.java rename to spring-vault-core/src/test/java/org/springframework/vault/authentication/KubernetesAuthenticationIntegrationTestBase.java index 042695db..718e2085 100644 --- a/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubeAuthenticationIntegrationTestBase.java +++ b/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubernetesAuthenticationIntegrationTestBase.java @@ -15,9 +15,6 @@ */ package org.springframework.vault.authentication; -import static org.junit.Assume.assumeTrue; -import static org.springframework.vault.util.Settings.findWorkDir; - import java.io.File; import java.nio.charset.StandardCharsets; import java.util.HashMap; @@ -25,18 +22,22 @@ import java.util.Map; import org.assertj.core.util.Files; import org.junit.Before; + import org.springframework.util.StringUtils; import org.springframework.vault.core.RestOperationsCallback; import org.springframework.vault.util.IntegrationTestSupport; import org.springframework.vault.util.Version; +import static org.junit.Assume.assumeTrue; +import static org.springframework.vault.util.Settings.findWorkDir; + /** - * Integration test base class for {@link KubeAuthentication} tests. + * Integration test base class for {@link KubernetesAuthentication} tests. * * @author Michal Budzyn */ -public abstract class KubeAuthenticationIntegrationTestBase - extends IntegrationTestSupport { +public abstract class KubernetesAuthenticationIntegrationTestBase extends + IntegrationTestSupport { @Before public void before() { @@ -49,13 +50,12 @@ public abstract class KubeAuthenticationIntegrationTestBase prepare().mountAuth("kubernetes"); } - prepare().getVaultOperations() - .doWithSession((RestOperationsCallback) restOperations -> { + prepare().getVaultOperations().doWithSession( + (RestOperationsCallback) restOperations -> { File workDir = findWorkDir(); - String certificate = Files.contentOf( - new File(workDir, "minikube/ca.crt"), - StandardCharsets.US_ASCII); + String certificate = Files.contentOf(new File(workDir, + "minikube/ca.crt"), StandardCharsets.US_ASCII); String host = String.format("https://%s:8443", minikubeIp); @@ -73,7 +73,6 @@ public abstract class KubeAuthenticationIntegrationTestBase return restOperations.postForEntity("auth/kubernetes/role/my-role", roleData, Map.class); - }); } } diff --git a/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubeAuthenticationIntegrationTests.java b/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubernetesAuthenticationIntegrationTests.java similarity index 68% rename from spring-vault-core/src/test/java/org/springframework/vault/authentication/KubeAuthenticationIntegrationTests.java rename to spring-vault-core/src/test/java/org/springframework/vault/authentication/KubernetesAuthenticationIntegrationTests.java index d4de8d82..e110594c 100644 --- a/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubeAuthenticationIntegrationTests.java +++ b/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubernetesAuthenticationIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017 the original author or authors. + * Copyright 2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,12 +15,10 @@ */ package org.springframework.vault.authentication; -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.vault.util.Settings.findWorkDir; - import java.io.File; import org.junit.Test; + import org.springframework.core.io.ClassPathResource; import org.springframework.vault.VaultException; import org.springframework.vault.support.VaultToken; @@ -28,27 +26,32 @@ import org.springframework.vault.util.Settings; import org.springframework.vault.util.TestRestTemplateFactory; import org.springframework.web.client.RestTemplate; +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.vault.util.Settings.findWorkDir; + /** - * Integration tests for {@link KubeAuthentication}. + * Integration tests for {@link KubernetesAuthentication}. * * @author Michal Budzyn */ -public class KubeAuthenticationIntegrationTests - extends KubeAuthenticationIntegrationTestBase { +public class KubernetesAuthenticationIntegrationTests extends + KubernetesAuthenticationIntegrationTestBase { @Test public void shouldLoginSuccessfully() { File tokenFile = new File(findWorkDir(), "minikube/hello-minikube-token"); - KubeAuthenticationOptions options = KubeAuthenticationOptions.builder() - .role("my-role").jwtSupplier(new KubeServiceAccountTokenFile(tokenFile)) + KubernetesAuthenticationOptions options = KubernetesAuthenticationOptions + .builder().role("my-role") + .jwtSupplier(new KubernetesServiceAccountTokenFile(tokenFile)) .build(); RestTemplate restTemplate = TestRestTemplateFactory .create(Settings.createSslConfiguration()); - KubeAuthentication authentication = new KubeAuthentication(options, restTemplate); + KubernetesAuthentication authentication = new KubernetesAuthentication(options, + restTemplate); VaultToken login = authentication.login(); assertThat(login.getToken()).isNotEmpty(); @@ -59,14 +62,15 @@ public class KubeAuthenticationIntegrationTests File tokenFile = new File(findWorkDir(), "minikube/hello-minikube-token"); - KubeAuthenticationOptions options = KubeAuthenticationOptions.builder() - .role("wrong").jwtSupplier(new KubeServiceAccountTokenFile(tokenFile)) + KubernetesAuthenticationOptions options = KubernetesAuthenticationOptions + .builder().role("wrong") + .jwtSupplier(new KubernetesServiceAccountTokenFile(tokenFile)) .build(); RestTemplate restTemplate = TestRestTemplateFactory .create(Settings.createSslConfiguration()); - new KubeAuthentication(options, restTemplate).login(); + new KubernetesAuthentication(options, restTemplate).login(); } @@ -75,14 +79,15 @@ public class KubeAuthenticationIntegrationTests ClassPathResource tokenResource = new ClassPathResource("kube-jwt-token"); - KubeAuthenticationOptions options = KubeAuthenticationOptions.builder() + KubernetesAuthenticationOptions options = KubernetesAuthenticationOptions + .builder() .role("my-role") - .jwtSupplier(new KubeServiceAccountTokenFile(tokenResource)).build(); + .jwtSupplier(new KubernetesServiceAccountTokenFile(tokenResource)) + .build(); RestTemplate restTemplate = TestRestTemplateFactory .create(Settings.createSslConfiguration()); - new KubeAuthentication(options, restTemplate).login(); - + new KubernetesAuthentication(options, restTemplate).login(); } } diff --git a/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubernetesAuthenticationStepsIntegrationTests.java b/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubernetesAuthenticationStepsIntegrationTests.java new file mode 100644 index 00000000..5127072c --- /dev/null +++ b/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubernetesAuthenticationStepsIntegrationTests.java @@ -0,0 +1,57 @@ +/* + * Copyright 2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.vault.authentication; + +import java.io.File; + +import org.junit.Test; + +import org.springframework.vault.support.VaultToken; +import org.springframework.vault.util.Settings; +import org.springframework.vault.util.TestRestTemplateFactory; +import org.springframework.web.client.RestTemplate; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.vault.util.Settings.findWorkDir; + +/** + * Integration tests for {@link KubernetesAuthentication} using + * {@link AuthenticationStepsExecutor}. + * + * @author Mark Paluch + */ +public class KubernetesAuthenticationStepsIntegrationTests extends + KubernetesAuthenticationIntegrationTestBase { + + @Test + public void shouldLoginSuccessfully() { + + File tokenFile = new File(findWorkDir(), "minikube/hello-minikube-token"); + + KubernetesAuthenticationOptions options = KubernetesAuthenticationOptions + .builder().role("my-role") + .jwtSupplier(new KubernetesServiceAccountTokenFile(tokenFile)).build(); + + RestTemplate restTemplate = TestRestTemplateFactory.create(Settings + .createSslConfiguration()); + + AuthenticationStepsExecutor executor = new AuthenticationStepsExecutor( + KubernetesAuthentication.createAuthenticationSteps(options), restTemplate); + + VaultToken login = executor.login(); + assertThat(login.getToken()).doesNotContain(Settings.token().getToken()); + } +} diff --git a/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubeAuthenticationUnitTests.java b/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubernetesAuthenticationUnitTests.java similarity index 76% rename from spring-vault-core/src/test/java/org/springframework/vault/authentication/KubeAuthenticationUnitTests.java rename to spring-vault-core/src/test/java/org/springframework/vault/authentication/KubernetesAuthenticationUnitTests.java index 206ef33b..4a315a9c 100644 --- a/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubeAuthenticationUnitTests.java +++ b/spring-vault-core/src/test/java/org/springframework/vault/authentication/KubernetesAuthenticationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017 the original author or authors. + * Copyright 2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,15 +15,9 @@ */ package org.springframework.vault.authentication; -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.jsonPath; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withServerError; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; - import org.junit.Before; import org.junit.Test; + import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.test.web.client.MockRestServiceServer; @@ -33,40 +27,50 @@ import org.springframework.vault.client.VaultClients.PrefixAwareUriTemplateHandl import org.springframework.vault.support.VaultToken; import org.springframework.web.client.RestTemplate; +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.jsonPath; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withServerError; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; + /** - * Unit tests for {@link KubeAuthentication}. + * Unit tests for {@link KubernetesAuthentication}. * * @author Michal Budzyn */ -public class KubeAuthenticationUnitTests { +public class KubernetesAuthenticationUnitTests { private RestTemplate restTemplate; private MockRestServiceServer mockRest; @Before - public void before() throws Exception { + public void before() { RestTemplate restTemplate = VaultClients.createRestTemplate(); restTemplate.setUriTemplateHandler(new PrefixAwareUriTemplateHandler()); + this.mockRest = MockRestServiceServer.createServer(restTemplate); this.restTemplate = restTemplate; } @Test - public void loginShouldObtainTokenWithStaticJwtSupplier() throws Exception { + public void loginShouldObtainTokenWithStaticJwtSupplier() { - KubeAuthenticationOptions options = KubeAuthenticationOptions.builder() - .role("hello") // + KubernetesAuthenticationOptions options = KubernetesAuthenticationOptions + .builder().role("hello") // .jwtSupplier(() -> "my-jwt-token").build(); mockRest.expect(requestTo("/auth/kubernetes/login")) .andExpect(method(HttpMethod.POST)) .andExpect(jsonPath("$.role").value("hello")) .andExpect(jsonPath("$.jwt").value("my-jwt-token")) - .andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON) - .body("{" + "\"auth\":{\"client_token\":\"my-token\"}" + "}")); + .andRespond( + withSuccess().contentType(MediaType.APPLICATION_JSON).body( + "{" + "\"auth\":{\"client_token\":\"my-token\"}" + "}")); - KubeAuthentication authentication = new KubeAuthentication(options, restTemplate); + KubernetesAuthentication authentication = new KubernetesAuthentication(options, + restTemplate); VaultToken login = authentication.login(); assertThat(login).isInstanceOf(LoginToken.class); @@ -74,14 +78,14 @@ public class KubeAuthenticationUnitTests { } @Test(expected = VaultException.class) - public void loginShouldFail() throws Exception { + public void loginShouldFail() { - KubeAuthenticationOptions options = KubeAuthenticationOptions.builder() - .role("hello").jwtSupplier(() -> "my-jwt-token").build(); + KubernetesAuthenticationOptions options = KubernetesAuthenticationOptions + .builder().role("hello").jwtSupplier(() -> "my-jwt-token").build(); mockRest.expect(requestTo("/auth/kubernetes/login")) // .andRespond(withServerError()); - new KubeAuthentication(options, restTemplate).login(); + new KubernetesAuthentication(options, restTemplate).login(); } } diff --git a/spring-vault-core/src/test/java/org/springframework/vault/config/EnvironmentVaultConfigurationKubeAuthenticationUnitTests.java b/spring-vault-core/src/test/java/org/springframework/vault/config/EnvironmentVaultConfigurationKubernetesAuthenticationUnitTests.java similarity index 76% rename from spring-vault-core/src/test/java/org/springframework/vault/config/EnvironmentVaultConfigurationKubeAuthenticationUnitTests.java rename to spring-vault-core/src/test/java/org/springframework/vault/config/EnvironmentVaultConfigurationKubernetesAuthenticationUnitTests.java index 30e48c0d..42b6e372 100644 --- a/spring-vault-core/src/test/java/org/springframework/vault/config/EnvironmentVaultConfigurationKubeAuthenticationUnitTests.java +++ b/spring-vault-core/src/test/java/org/springframework/vault/config/EnvironmentVaultConfigurationKubernetesAuthenticationUnitTests.java @@ -15,33 +15,46 @@ */ package org.springframework.vault.config; -import static org.assertj.core.api.Assertions.assertThat; +import java.nio.file.Files; +import java.nio.file.Paths; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.vault.authentication.ClientAuthentication; -import org.springframework.vault.authentication.KubeAuthentication; +import org.springframework.vault.authentication.KubernetesAuthentication; + +import static org.assertj.core.api.Assertions.assertThat; /** * Unit tests for {@link EnvironmentVaultConfiguration} with Kube authentication. * * @author Michal Budzyn + * @author Mark Paluch */ @RunWith(SpringRunner.class) @TestPropertySource(properties = { "vault.uri=https://localhost:8123", - "vault.authentication=kubernetes", "vault.kubernetes.role=my-role"}) -public class EnvironmentVaultConfigurationKubeAuthenticationUnitTests { + "vault.authentication=kubernetes", "vault.kubernetes.role=my-role", + "vault.kubernetes.service-account-token-file=target/token" }) +public class EnvironmentVaultConfigurationKubernetesAuthenticationUnitTests { @Configuration @Import(EnvironmentVaultConfiguration.class) static class ApplicationConfiguration { } + @BeforeClass + public static void beforeClass() throws Exception { + + Files.write(Paths.get("target", "token"), "token".getBytes()); + } + @Autowired private EnvironmentVaultConfiguration configuration; @@ -50,6 +63,6 @@ public class EnvironmentVaultConfigurationKubeAuthenticationUnitTests { ClientAuthentication clientAuthentication = configuration.clientAuthentication(); - assertThat(clientAuthentication).isInstanceOf(KubeAuthentication.class); + assertThat(clientAuthentication).isInstanceOf(KubernetesAuthentication.class); } } diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index b5a0fef8..d077dfa3 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -10,6 +10,7 @@ * Transit batch encrypt and decrypt support. * Policy management for policies stored as JSON. * Support CSR signing, certificate revocation and CRL retrieval. +* <>. * RoleId/SecretId unwrapping for <>. [[new-features.1-1-0]] diff --git a/src/main/asciidoc/reference/authentication.adoc b/src/main/asciidoc/reference/authentication.adoc index e5897389..67cb5b75 100644 --- a/src/main/asciidoc/reference/authentication.adoc +++ b/src/main/asciidoc/reference/authentication.adoc @@ -534,6 +534,47 @@ 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.authentication.kubernetes]] +== Kubernetes authentication + +Vault supports since 0.8.3 https://www.vaultproject.io/docs/auth/kubernetes.html[kubernetes] +-based authentication using Kubernetes tokens. + +Using Kubernetes authentication requires a Kubernetes Service Account Token, +usually mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`. The file contains +the token which is read and sent to Vault. Vault verifies its validity using Kubernets' API +during login. + +Configuring Kubernetes authentication requires at least the role name to be provided: + +==== +[source,java] +---- +@Configuration +class AppConfig extends AbstractVaultConfiguration { + + // … + + @Override + public ClientAuthentication clientAuthentication() { + + KubernetesAuthenticationOptions options = KubernetesAuthenticationOptions.builder() + .role(…).build(); + + return new KubernetesAuthentication(options, restOperations()); + } + + // … +} +---- +==== + +You can configure the authentication via `KubernetesAuthenticationOptions`. + +See also: + +* https://www.vaultproject.io/docs/auth/kubernetes.html[Vault Documentation: Using the Kubernetes auth backend] +* https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/[Kubernetes Documentation: Configure Service Accounts for Pods] [[vault.authentication.steps]] == Authentication Steps diff --git a/src/test/bash/local_run_k8s.sh b/src/test/bash/local_run_k8s.sh index 68e5d8a8..6d913a8b 100755 --- a/src/test/bash/local_run_k8s.sh +++ b/src/test/bash/local_run_k8s.sh @@ -12,6 +12,7 @@ fi mkdir -p work/minikube SERVICE_ACCOUNT_TOKEN_FILE=work/minikube/hello-minikube-token +SERVICE_ACCOUNT_CA_CRT=work/minikube/ca.crt function is_cluster_running() { local _running=$(${CMD_MINIKUBE} status | grep "cluster: Running" || true) @@ -40,8 +41,9 @@ while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' ${HELLO_MINIKUBE_URL})" != sleep 3 done -# Copy service account token POD_NAME=$(${CMD_KUBECTL} get pod --selector=run=hello-minikube -o jsonpath='{.items..metadata.name}') + +# Copy service account token ${CMD_KUBECTL} exec ${POD_NAME} -- cat /var/run/secrets/kubernetes.io/serviceaccount/token > ${SERVICE_ACCOUNT_TOKEN_FILE} if [ $? != 0 ] ; then echo "Error while retrieving service account token file" @@ -50,12 +52,8 @@ fi # Copy ca cert cp $HOME/.minikube/ca.crt work/minikube - -#BASEDIR=`dirname $0`/../../.. -#sh <( -#cat <<-EOF -#cd ${BASEDIR} && ${BASEDIR}/src/test/bash/env.sh -#vault auth-enable kubernetes -#vault write auth/kubernetes/config kubernetes_host=https://$(minikube ip):8443 kubernetes_ca_cert=@$HOME/.minikube/ca.crt -#EOF -#) +${CMD_KUBECTL} exec ${POD_NAME} -- cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt > ${SERVICE_ACCOUNT_CA_CRT} +if [ $? != 0 ] ; then + echo "Error while retrieving service account ca.crt" + exit 1 +fi diff --git a/src/test/bash/minikube_ci_initialize.sh b/src/test/bash/minikube_ci_initialize.sh index 68cb75f6..0d9a7ea0 100755 --- a/src/test/bash/minikube_ci_initialize.sh +++ b/src/test/bash/minikube_ci_initialize.sh @@ -1,6 +1,5 @@ #!/usr/bin/env bash - # Taken from https://github.com/aaron-prindle/minikube-travis-example/blob/master/minikube-ci-initialize.sh # Thanks to https://github.com/aaron-prindle #