From 5ae83d34e6b534e35194070faccdb76c8e30ad7c Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 6 Jul 2017 20:26:27 +0200 Subject: [PATCH] Provide static AuthenticationSteps factory methods in authentication implementations. See gh-107. --- .../authentication/AppIdAuthentication.java | 36 ++++++-- .../authentication/AppRoleAuthentication.java | 35 +++++-- .../AuthenticationStepsFactory.java | 1 + .../authentication/AwsEc2Authentication.java | 91 +++++++++++++------ .../ClientCertificateAuthentication.java | 20 +++- .../CubbyholeAuthentication.java | 37 ++++++-- .../authentication/TokenAuthentication.java | 19 +++- 7 files changed, 174 insertions(+), 65 deletions(-) diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/AppIdAuthentication.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/AppIdAuthentication.java index d1e4227c..6c36c6b7 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/AppIdAuthentication.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/AppIdAuthentication.java @@ -66,11 +66,35 @@ public class AppIdAuthentication implements ClientAuthentication, this.restOperations = restOperations; } + /** + * Creates a {@link AuthenticationSteps} for AppId authentication given + * {@link AppIdAuthenticationOptions}. + * + * @param options must not be {@literal null}. + * @return {@link AuthenticationSteps} for AppId authentication. + * @since 2.0 + */ + public static AuthenticationSteps createAuthenticationSteps( + AppIdAuthenticationOptions options) { + + Assert.notNull(options, "AppIdAuthenticationOptions must not be null"); + + return AuthenticationSteps.fromSupplier( + () -> getAppIdLogin(options.getAppId(), options.getUserIdMechanism() + .createUserId())) // + .login("auth/{mount}/login", options.getPath()); + } + @Override public VaultToken login() { return createTokenUsingAppId(); } + @Override + public AuthenticationSteps getAuthenticationSteps() { + return createAuthenticationSteps(options); + } + private VaultToken createTokenUsingAppId() { Map login = getAppIdLogin(options.getAppId(), options @@ -90,19 +114,13 @@ public class AppIdAuthentication implements ClientAuthentication, } } - public AuthenticationSteps getAuthenticationSteps() { - - return AuthenticationSteps.fromSupplier( - () -> getAppIdLogin(options.getAppId(), options.getUserIdMechanism() - .createUserId())) // - .login("auth/{mount}/login", options.getPath()); - } - - private Map getAppIdLogin(String appId, String userId) { + private static Map getAppIdLogin(String appId, String userId) { Map login = new HashMap<>(); + login.put("app_id", appId); login.put("user_id", userId); + return login; } } diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/AppRoleAuthentication.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/AppRoleAuthentication.java index ebeb398a..8e35b64a 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/AppRoleAuthentication.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/AppRoleAuthentication.java @@ -68,11 +68,34 @@ public class AppRoleAuthentication implements ClientAuthentication, this.restOperations = restOperations; } + /** + * Creates a {@link AuthenticationSteps} for AppRole authentication given + * {@link AppRoleAuthenticationOptions}. + * + * @param options must not be {@literal null}. + * @return {@link AuthenticationSteps} for AppRole authentication. + * @since 2.0 + */ + public static AuthenticationSteps createAuthenticationSteps( + AppRoleAuthenticationOptions options) { + + Assert.notNull(options, "AppRoleAuthenticationOptions must not be null"); + + return AuthenticationSteps.fromSupplier( + () -> getAppRoleLogin(options.getRoleId(), options.getSecretId())) // + .login("auth/{mount}/login", options.getPath()); + } + @Override public VaultToken login() { return createTokenUsingAppRole(); } + @Override + public AuthenticationSteps getAuthenticationSteps() { + return createAuthenticationSteps(options); + } + private VaultToken createTokenUsingAppRole() { Map login = getAppRoleLogin(options.getRoleId(), @@ -92,21 +115,15 @@ public class AppRoleAuthentication implements ClientAuthentication, } } - @Override - public AuthenticationSteps getAuthenticationSteps() { - - return AuthenticationSteps.fromSupplier( - () -> getAppRoleLogin(options.getRoleId(), options.getSecretId())) // - .login("auth/{mount}/login", options.getPath()); - } - - private Map getAppRoleLogin(String roleId, String secretId) { + private static Map getAppRoleLogin(String roleId, String secretId) { Map login = new HashMap<>(); + login.put("role_id", roleId); if (secretId != null) { login.put("secret_id", secretId); } + return login; } } diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/AuthenticationStepsFactory.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/AuthenticationStepsFactory.java index 17d84842..35b801ba 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/AuthenticationStepsFactory.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/AuthenticationStepsFactory.java @@ -25,6 +25,7 @@ package org.springframework.vault.authentication; * @since 2.0 * @see AuthenticationSteps */ +@FunctionalInterface public interface AuthenticationStepsFactory { /** diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/AwsEc2Authentication.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/AwsEc2Authentication.java index edb2cc57..15f9b66c 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/AwsEc2Authentication.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/AwsEc2Authentication.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -94,11 +95,64 @@ public class AwsEc2Authentication implements ClientAuthentication, this.awsMetadataRestOperations = awsMetadataRestOperations; } + /** + * Creates a {@link AuthenticationSteps} for AWS-EC2 authentication given + * {@link AwsEc2AuthenticationOptions}. + * + * @param options must not be {@literal null}. + * @return {@link AuthenticationSteps} for AWS-EC2 authentication. + * @since 2.0 + */ + public static AuthenticationSteps createAuthenticationSteps( + AwsEc2AuthenticationOptions options) { + + Assert.notNull(options, "AwsEc2AuthenticationOptions must not be null"); + + AtomicReference nonce = new AtomicReference<>(EMPTY); + + return createAuthenticationSteps(options, nonce, () -> doCreateNonce(options)); + } + + protected static AuthenticationSteps createAuthenticationSteps( + AwsEc2AuthenticationOptions options, AtomicReference nonce, + Supplier nonceSupplier) { + + return AuthenticationSteps + .fromHttpRequest( + HttpRequestBuilder.get( + options.getIdentityDocumentUri().toString()).as( + String.class)) // + .map(pkcs7 -> pkcs7.replaceAll("\\r", "")) // + .map(pkcs7 -> pkcs7.replace("\\n", "")) // + .map(pkcs7 -> { + + Map login = new HashMap<>(); + + if (StringUtils.hasText(options.getRole())) { + login.put("role", options.getRole()); + } + + if (Objects.equals(nonce.get(), EMPTY)) { + nonce.compareAndSet(EMPTY, nonceSupplier.get()); + } + + login.put("nonce", new String(nonce.get())); + login.put("pkcs7", pkcs7); + + return login; + }).login("auth/{mount}/login", options.getPath()); + } + @Override public VaultToken login() throws VaultException { return createTokenUsingAwsEc2(); } + @Override + public AuthenticationSteps getAuthenticationSteps() { + return createAuthenticationSteps(this.options, this.nonce, this::createNonce); + } + @SuppressWarnings("unchecked") private VaultToken createTokenUsingAwsEc2() { @@ -132,33 +186,6 @@ public class AwsEc2Authentication implements ClientAuthentication, } } - public AuthenticationSteps getAuthenticationSteps() { - - return AuthenticationSteps - .fromHttpRequest( - HttpRequestBuilder.get( - options.getIdentityDocumentUri().toString()).as( - String.class)) - .map(pkcs7 -> pkcs7.replaceAll("\\r", "").replace("\\n", "")) - .map(pkcs7 -> { - - Map login = new HashMap<>(); - - if (StringUtils.hasText(options.getRole())) { - login.put("role", options.getRole()); - } - - if (Objects.equals(this.nonce.get(), EMPTY)) { - this.nonce.compareAndSet(EMPTY, createNonce()); - } - - login.put("nonce", new String(this.nonce.get())); - login.put("pkcs7", pkcs7); - - return login; - }).login("auth/{mount}/login", options.getPath()); - } - protected Map getEc2Login() { Map login = new HashMap<>(); @@ -167,15 +194,15 @@ public class AwsEc2Authentication implements ClientAuthentication, login.put("role", options.getRole()); } - if (this.nonce.get() == EMPTY) { + if (Objects.equals(this.nonce.get(), EMPTY)) { this.nonce.compareAndSet(EMPTY, createNonce()); } login.put("nonce", new String(this.nonce.get())); try { - String pkcs7 = awsMetadataRestOperations.getForObject( - options.getIdentityDocumentUri(), String.class); + String pkcs7 = this.awsMetadataRestOperations.getForObject( + this.options.getIdentityDocumentUri(), String.class); if (StringUtils.hasText(pkcs7)) { login.put("pkcs7", pkcs7.replaceAll("\\r", "").replace("\\n", "")); } @@ -190,6 +217,10 @@ public class AwsEc2Authentication implements ClientAuthentication, } protected char[] createNonce() { + return doCreateNonce(this.options); + } + + private static char[] doCreateNonce(AwsEc2AuthenticationOptions options) { return options.getNonce().getValue(); } } diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/ClientCertificateAuthentication.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/ClientCertificateAuthentication.java index 7f4e874c..f3cd7861 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/ClientCertificateAuthentication.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/ClientCertificateAuthentication.java @@ -55,11 +55,26 @@ public class ClientCertificateAuthentication implements ClientAuthentication, this.restOperations = restOperations; } + /** + * Creates a {@link AuthenticationSteps} for client certificate authentication. + * + * @return {@link AuthenticationSteps} for client certificate authentication. + * @since 2.0 + */ + public static AuthenticationSteps createAuthenticationSteps() { + return AuthenticationSteps.just(post("auth/cert/login").as(VaultResponse.class)); + } + @Override public VaultToken login() { return createTokenUsingTlsCertAuthentication("cert"); } + @Override + public AuthenticationSteps getAuthenticationSteps() { + return createAuthenticationSteps(); + } + private VaultToken createTokenUsingTlsCertAuthentication(String path) { try { @@ -76,9 +91,4 @@ public class ClientCertificateAuthentication implements ClientAuthentication, VaultResponses.getError(e.getResponseBodyAsString()))); } } - - @Override - public AuthenticationSteps getAuthenticationSteps() { - return AuthenticationSteps.just(post("auth/cert/login").as(VaultResponse.class)); - } } diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/CubbyholeAuthentication.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/CubbyholeAuthentication.java index deb28011..a651d5d1 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/CubbyholeAuthentication.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/CubbyholeAuthentication.java @@ -162,12 +162,34 @@ public class CubbyholeAuthentication implements ClientAuthentication, this.restOperations = restOperations; } + /** + * Creates a {@link AuthenticationSteps} for cubbyhole authentication given + * {@link CubbyholeAuthenticationOptions}. + * + * @param options must not be {@literal null}. + * @return {@link AuthenticationSteps} for cubbyhole authentication. + * @since 2.0 + */ + public static AuthenticationSteps createAuthenticationSteps( + CubbyholeAuthenticationOptions options) { + + Assert.notNull(options, "CubbyholeAuthenticationOptions must not be null"); + + HttpRequest initialRequest = get(options.getPath()) // + .with(VaultHttpHeaders.from(options.getInitialToken())) // + .as(VaultResponse.class); + + return AuthenticationSteps.fromHttpRequest(initialRequest) // + .map(VaultResponseSupport::getData) // + .login(map -> getToken(options, map)); + } + @Override public VaultToken login() throws VaultException { Map data = lookupToken(); - VaultToken tokenToUse = getToken(data); + VaultToken tokenToUse = getToken(this.options, data); if (shouldEnhanceTokenWithSelfLookup(tokenToUse)) { @@ -180,15 +202,9 @@ public class CubbyholeAuthentication implements ClientAuthentication, return tokenToUse; } + @Override public AuthenticationSteps getAuthenticationSteps() { - - HttpRequest initialRequest = get(options.getPath()) // - .with(VaultHttpHeaders.from(options.getInitialToken())) // - .as(VaultResponse.class); - - return AuthenticationSteps.fromHttpRequest(initialRequest) // - .map(VaultResponseSupport::getData) // - .login(this::getToken); + return createAuthenticationSteps(options); } private Map lookupToken() { @@ -227,7 +243,8 @@ public class CubbyholeAuthentication implements ClientAuthentication, return true; } - private VaultToken getToken(Map data) { + private static VaultToken getToken(CubbyholeAuthenticationOptions options, + Map data) { if (options.isWrappedToken()) { diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/TokenAuthentication.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/TokenAuthentication.java index f1f3e632..5ff1a32e 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/TokenAuthentication.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/TokenAuthentication.java @@ -54,13 +54,28 @@ public class TokenAuthentication implements ClientAuthentication, this.token = token; } + /** + * Creates a {@link AuthenticationSteps} for token authentication given + * {@link VaultToken}. + * + * @param token must not be {@literal null}. + * @return {@link AuthenticationSteps} for token authentication. + * @since 2.0 + */ + public static AuthenticationSteps createAuthenticationSteps(VaultToken token) { + + Assert.notNull(token, "VaultToken must not be null"); + + return AuthenticationSteps.just(token); + } + @Override public VaultToken login() { - return token; + return this.token; } @Override public AuthenticationSteps getAuthenticationSteps() { - return AuthenticationSteps.just(token); + return createAuthenticationSteps(this.token); } }