Remove deprecated code.
Removal of AppId, GcpIam authentication and deprecated methods. Closes #904
This commit is contained in:
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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
|
||||
*
|
||||
* https://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.HashMap;
|
||||
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.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
/**
|
||||
* AppId implementation of {@link ClientAuthentication}. {@link AppIdAuthentication} uses
|
||||
* a configured {@link AppIdUserIdMechanism} to obtain or calculate a UserId. AppId and
|
||||
* UserId are sent in the login request to Vault to obtain a {@link VaultToken}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdAuthenticationOptions
|
||||
* @see RestOperations
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/app-id.html">Auth Backend: App
|
||||
* ID</a>
|
||||
* @deprecated since 2.2. Use {@link AppRoleAuthentication}.
|
||||
*/
|
||||
@Deprecated(since = "2.2", forRemoval = true)
|
||||
public class AppIdAuthentication implements ClientAuthentication, AuthenticationStepsFactory {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AppIdAuthentication.class);
|
||||
|
||||
private final AppIdAuthenticationOptions options;
|
||||
|
||||
private final RestOperations restOperations;
|
||||
|
||||
/**
|
||||
* Create a {@link AppIdAuthentication} using {@link AppIdAuthenticationOptions} and
|
||||
* {@link RestOperations}.
|
||||
* @param options must not be {@literal null}.
|
||||
* @param restOperations must not be {@literal null}.
|
||||
*/
|
||||
public AppIdAuthentication(AppIdAuthenticationOptions options, RestOperations restOperations) {
|
||||
|
||||
Assert.notNull(options, "AppIdAuthenticationOptions must not be null");
|
||||
Assert.notNull(restOperations, "RestOperations must not be null");
|
||||
|
||||
this.options = options;
|
||||
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(AuthenticationUtil.getLoginPath(options.getPath()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultToken login() {
|
||||
return createTokenUsingAppId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticationSteps getAuthenticationSteps() {
|
||||
return createAuthenticationSteps(this.options);
|
||||
}
|
||||
|
||||
private VaultToken createTokenUsingAppId() {
|
||||
|
||||
Map<String, String> login = getAppIdLogin(this.options.getAppId(),
|
||||
this.options.getUserIdMechanism().createUserId());
|
||||
|
||||
try {
|
||||
VaultResponse response = this.restOperations
|
||||
.postForObject(AuthenticationUtil.getLoginPath(this.options.getPath()), login, VaultResponse.class);
|
||||
|
||||
Assert.state(response != null && response.getAuth() != null, "Auth field must not be null");
|
||||
|
||||
logger.debug("Login successful using AppId authentication");
|
||||
|
||||
return LoginTokenUtil.from(response.getAuth());
|
||||
}
|
||||
catch (RestClientException e) {
|
||||
throw VaultLoginException.create("app-id", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, String> getAppIdLogin(String appId, String userId) {
|
||||
|
||||
Map<String, String> login = new HashMap<>();
|
||||
|
||||
login.put("app_id", appId);
|
||||
login.put("user_id", userId);
|
||||
|
||||
return login;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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
|
||||
*
|
||||
* https://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 AppIdAuthentication}.
|
||||
* <p>
|
||||
* Authentication options provide the path, appId and a {@link AppIdUserIdMechanism}.
|
||||
* {@link AppIdAuthentication} can be constructed using {@link #builder()}. Instances of
|
||||
* this class are immutable once constructed.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdAuthentication
|
||||
* @see AppIdUserIdMechanism
|
||||
* @see #builder()
|
||||
* @deprecated since 2.2. Use {@link AppRoleAuthentication}.
|
||||
*/
|
||||
@Deprecated(since = "2.2", forRemoval = true)
|
||||
public class AppIdAuthenticationOptions {
|
||||
|
||||
public static final String DEFAULT_APPID_AUTHENTICATION_PATH = "app-id";
|
||||
|
||||
/**
|
||||
* Path of the appid authentication backend mount.
|
||||
*/
|
||||
private final String path;
|
||||
|
||||
/**
|
||||
* The AppId
|
||||
*/
|
||||
private final String appId;
|
||||
|
||||
/**
|
||||
* {@link AppIdUserIdMechanism} instance to obtain a userId.
|
||||
*/
|
||||
private final AppIdUserIdMechanism userIdMechanism;
|
||||
|
||||
private AppIdAuthenticationOptions(String path, String appId, AppIdUserIdMechanism userIdMechanism) {
|
||||
|
||||
this.path = path;
|
||||
this.appId = appId;
|
||||
this.userIdMechanism = userIdMechanism;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new {@link AppIdAuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public static AppIdAuthenticationOptionsBuilder builder() {
|
||||
return new AppIdAuthenticationOptionsBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mount path.
|
||||
*/
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the AppId.
|
||||
*/
|
||||
public String getAppId() {
|
||||
return this.appId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link AppIdUserIdMechanism}.
|
||||
*/
|
||||
public AppIdUserIdMechanism getUserIdMechanism() {
|
||||
return this.userIdMechanism;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for {@link AppIdAuthenticationOptions}.
|
||||
*/
|
||||
public static class AppIdAuthenticationOptionsBuilder {
|
||||
|
||||
private String path = DEFAULT_APPID_AUTHENTICATION_PATH;
|
||||
|
||||
private String appId;
|
||||
|
||||
private AppIdUserIdMechanism userIdMechanism;
|
||||
|
||||
AppIdAuthenticationOptionsBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the mount path.
|
||||
* @param path must not be empty or {@literal null}.
|
||||
* @return {@code this} {@link AppIdAuthenticationOptionsBuilder}.
|
||||
* @see #DEFAULT_APPID_AUTHENTICATION_PATH
|
||||
*/
|
||||
public AppIdAuthenticationOptionsBuilder path(String path) {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
|
||||
this.path = path;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the AppId.
|
||||
* @param appId must not be empty or {@literal null}.
|
||||
* @return {@code this} {@link AppIdAuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public AppIdAuthenticationOptionsBuilder appId(String appId) {
|
||||
|
||||
Assert.hasText(appId, "AppId must not be empty");
|
||||
|
||||
this.appId = appId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link AppIdUserIdMechanism}.
|
||||
* @param userIdMechanism must not be {@literal null}.
|
||||
* @return {@code this} {@link AppIdAuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public AppIdAuthenticationOptionsBuilder userIdMechanism(AppIdUserIdMechanism userIdMechanism) {
|
||||
|
||||
Assert.notNull(userIdMechanism, "AppIdUserIdMechanism must not be null");
|
||||
|
||||
this.userIdMechanism = userIdMechanism;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new {@link AppIdAuthenticationOptions} instance. Requires
|
||||
* {@link #userIdMechanism(AppIdUserIdMechanism)} to be configured.
|
||||
* @return a new {@link AppIdAuthenticationOptions}.
|
||||
*/
|
||||
public AppIdAuthenticationOptions build() {
|
||||
|
||||
Assert.hasText(this.appId, "AppId must not be empty");
|
||||
Assert.notNull(this.userIdMechanism, "AppIdUserIdMechanism must not be null");
|
||||
|
||||
return new AppIdAuthenticationOptions(this.path, this.appId, this.userIdMechanism);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
/**
|
||||
* Interface to obtain a UserId for AppId authentication. Implementations are used by
|
||||
* {@link AppIdAuthentication}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdAuthentication
|
||||
* @deprecated since 2.2. Use {@link AppRoleAuthentication}.
|
||||
*/
|
||||
@Deprecated(since = "2.2", forRemoval = true)
|
||||
@FunctionalInterface
|
||||
public interface AppIdUserIdMechanism {
|
||||
|
||||
/**
|
||||
* Create a UserId for AppId authentication.
|
||||
* @return the UserId.
|
||||
*/
|
||||
String createUserId();
|
||||
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-2025 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
|
||||
*
|
||||
* https://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.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.client.http.HttpTransport;
|
||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||
import com.google.api.services.iam.v1.Iam;
|
||||
import com.google.api.services.iam.v1.Iam.Builder;
|
||||
import com.google.api.services.iam.v1.Iam.Projects.ServiceAccounts.SignJwt;
|
||||
import com.google.api.services.iam.v1.model.SignJwtRequest;
|
||||
import com.google.api.services.iam.v1.model.SignJwtResponse;
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
/**
|
||||
* GCP IAM login implementation using GCP IAM service accounts to legitimate its
|
||||
* authenticity via JSON Web Token using the deprecated IAM
|
||||
* {@code projects.serviceAccounts.signJwt} method.
|
||||
* <p/>
|
||||
* This authentication method uses Googles IAM API to obtain a signed token for a specific
|
||||
* {@link com.google.api.client.auth.oauth2.Credential}. Project and service account
|
||||
* details are obtained from a {@link GoogleCredential} that can be retrieved either from
|
||||
* a JSON file or the runtime environment (GAE, GCE).
|
||||
* <p/>
|
||||
* {@link GcpIamAuthentication} uses Google Java API that uses synchronous API.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Magnus Jungsbluth
|
||||
* @author Bruno Rodrigues
|
||||
* @since 2.1
|
||||
* @see GcpIamAuthenticationOptions
|
||||
* @see HttpTransport
|
||||
* @see GoogleCredential
|
||||
* @see GoogleCredentials#getApplicationDefault()
|
||||
* @see RestOperations
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/gcp.html">Auth Backend: gcp
|
||||
* (IAM)</a>
|
||||
* @see <a href=
|
||||
* "https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts/signJwt">GCP:
|
||||
* projects.serviceAccounts.signJwt</a>
|
||||
* @deprecated since 2.3.2, use {@link GcpIamCredentialsAuthentication} instead.
|
||||
*/
|
||||
@Deprecated(since = "2.3.2", forRemoval = true)
|
||||
public class GcpIamAuthentication extends GcpJwtAuthenticationSupport implements ClientAuthentication {
|
||||
|
||||
private static final String SCOPE = "https://www.googleapis.com/auth/iam";
|
||||
|
||||
private final GcpIamAuthenticationOptions options;
|
||||
|
||||
private final HttpTransport httpTransport;
|
||||
|
||||
private final GoogleCredential credential;
|
||||
|
||||
/**
|
||||
* Create a new instance of {@link GcpIamAuthentication} given
|
||||
* {@link GcpIamAuthenticationOptions} and {@link RestOperations}. This constructor
|
||||
* initializes {@link NetHttpTransport} for Google API usage.
|
||||
* @param options must not be {@literal null}.
|
||||
* @param restOperations HTTP client for Vault login, must not be {@literal null}.
|
||||
*/
|
||||
public GcpIamAuthentication(GcpIamAuthenticationOptions options, RestOperations restOperations) {
|
||||
this(options, restOperations, new NetHttpTransport());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of {@link GcpIamAuthentication} given
|
||||
* {@link GcpIamAuthenticationOptions}, {@link RestOperations} and
|
||||
* {@link HttpTransport}.
|
||||
* @param options must not be {@literal null}.
|
||||
* @param restOperations HTTP client for Vault login, must not be {@literal null}.
|
||||
* @param httpTransport HTTP client for Google API use, must not be {@literal null}.
|
||||
*/
|
||||
public GcpIamAuthentication(GcpIamAuthenticationOptions options, RestOperations restOperations,
|
||||
HttpTransport httpTransport) {
|
||||
|
||||
super(restOperations);
|
||||
|
||||
Assert.notNull(options, "GcpIamAuthenticationOptions must not be null");
|
||||
Assert.notNull(restOperations, "RestOperations must not be null");
|
||||
Assert.notNull(httpTransport, "HttpTransport must not be null");
|
||||
|
||||
this.options = options;
|
||||
this.httpTransport = httpTransport;
|
||||
this.credential = options.getCredentialSupplier().get().createScoped(Collections.singletonList(SCOPE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultToken login() throws VaultException {
|
||||
|
||||
String signedJwt = signJwt();
|
||||
|
||||
return doLogin("GCP-IAM", signedJwt, this.options.getPath(), this.options.getRole());
|
||||
}
|
||||
|
||||
protected String signJwt() {
|
||||
|
||||
String projectId = getProjectId();
|
||||
String serviceAccount = getServiceAccountId();
|
||||
Map<String, Object> jwtPayload = getJwtPayload(this.options, serviceAccount);
|
||||
|
||||
Iam iam = new Builder(this.httpTransport, GoogleJsonUtil.JSON_FACTORY, this.credential)
|
||||
.setApplicationName("Spring Vault/" + getClass().getName())
|
||||
.build();
|
||||
|
||||
try {
|
||||
|
||||
String payload = GoogleJsonUtil.JSON_FACTORY.toString(jwtPayload);
|
||||
SignJwtRequest request = new SignJwtRequest();
|
||||
request.setPayload(payload);
|
||||
|
||||
SignJwt signJwt = iam.projects()
|
||||
.serviceAccounts()
|
||||
.signJwt("projects/%s/serviceAccounts/%s".formatted(projectId, serviceAccount), request);
|
||||
|
||||
SignJwtResponse response = signJwt.execute();
|
||||
|
||||
return response.getSignedJwt();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new VaultLoginException("Cannot sign JWT", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getServiceAccountId() {
|
||||
return this.options.getServiceAccountIdAccessor().getServiceAccountId(this.credential);
|
||||
}
|
||||
|
||||
private String getProjectId() {
|
||||
return this.options.getProjectIdAccessor().getProjectId(this.credential);
|
||||
}
|
||||
|
||||
private static Map<String, Object> getJwtPayload(GcpIamAuthenticationOptions options, String serviceAccount) {
|
||||
|
||||
Instant validUntil = options.getClock().instant().plus(options.getJwtValidity());
|
||||
|
||||
Map<String, Object> payload = new LinkedHashMap<>();
|
||||
|
||||
payload.put("sub", serviceAccount);
|
||||
payload.put("aud", "vault/" + options.getRole());
|
||||
payload.put("exp", validUntil.getEpochSecond());
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,287 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-2025 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
|
||||
*
|
||||
* https://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.time.Clock;
|
||||
import java.time.Duration;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Authentication options for {@link GcpIamAuthentication}.
|
||||
* <p/>
|
||||
* Authentication options provide the path, a {@link GcpCredentialSupplier}, role and JWT
|
||||
* expiry for GCP IAM authentication. Instances of this class are immutable once
|
||||
* constructed.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Magnus Jungsbluth
|
||||
* @see GcpIamAuthentication
|
||||
* @see #builder()
|
||||
* @since 2.1
|
||||
* @deprecated since 2.3.2
|
||||
*/
|
||||
@Deprecated(since = "2.3.2", forRemoval = true)
|
||||
public class GcpIamAuthenticationOptions extends GcpIamAuthenticationSupport {
|
||||
|
||||
public static final String DEFAULT_GCP_AUTHENTICATION_PATH = "gcp";
|
||||
|
||||
private final GcpCredentialSupplier credentialSupplier;
|
||||
|
||||
/**
|
||||
* Provide the service account id to use as sub/iss claims.
|
||||
*/
|
||||
private final GcpServiceAccountIdAccessor serviceAccountIdAccessor;
|
||||
|
||||
/**
|
||||
* The GCP project id to use in GCP IAM API calls.
|
||||
*/
|
||||
private final GcpProjectIdAccessor projectIdAccessor;
|
||||
|
||||
private GcpIamAuthenticationOptions(String path, GcpCredentialSupplier credentialSupplier, String role,
|
||||
Duration jwtValidity, Clock clock, GcpServiceAccountIdAccessor serviceAccountIdSupplier,
|
||||
GcpProjectIdAccessor projectIdAccessor) {
|
||||
|
||||
super(path, role, jwtValidity, clock);
|
||||
|
||||
this.credentialSupplier = credentialSupplier;
|
||||
this.serviceAccountIdAccessor = serviceAccountIdSupplier;
|
||||
this.projectIdAccessor = projectIdAccessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new {@link GcpIamAuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public static GcpIamAuthenticationOptionsBuilder builder() {
|
||||
return new GcpIamAuthenticationOptionsBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the gcp {@link Credential} supplier.
|
||||
*/
|
||||
public GcpCredentialSupplier getCredentialSupplier() {
|
||||
return this.credentialSupplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the service account id to use as sub/iss claims.
|
||||
* @since 2.1
|
||||
*/
|
||||
public GcpServiceAccountIdAccessor getServiceAccountIdAccessor() {
|
||||
return this.serviceAccountIdAccessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return GCP project id accessor to obtain the project id of GCP IAM API calls.
|
||||
* @since 2.1
|
||||
*/
|
||||
public GcpProjectIdAccessor getProjectIdAccessor() {
|
||||
return this.projectIdAccessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for {@link GcpIamAuthenticationOptions}.
|
||||
*/
|
||||
public static class GcpIamAuthenticationOptionsBuilder {
|
||||
|
||||
private String path = DEFAULT_GCP_AUTHENTICATION_PATH;
|
||||
|
||||
@Nullable
|
||||
private String role;
|
||||
|
||||
@Nullable
|
||||
private GcpCredentialSupplier credentialSupplier;
|
||||
|
||||
private Duration jwtValidity = Duration.ofMinutes(15);
|
||||
|
||||
private Clock clock = Clock.systemDefaultZone();
|
||||
|
||||
private GcpServiceAccountIdAccessor serviceAccountIdAccessor = DefaultGcpCredentialAccessors.INSTANCE;
|
||||
|
||||
private GcpProjectIdAccessor projectIdAccessor = DefaultGcpCredentialAccessors.INSTANCE;
|
||||
|
||||
GcpIamAuthenticationOptionsBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the mount path, defaults to {@literal aws}.
|
||||
* @param path must not be empty or {@literal null}.
|
||||
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public GcpIamAuthenticationOptionsBuilder path(String path) {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
|
||||
this.path = path;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure static Google credentials, required to create a signed JWT. Either
|
||||
* use static credentials or provide a
|
||||
* {@link #credentialSupplier(GcpCredentialSupplier) credentials provider}.
|
||||
* @param credential must not be {@literal null}.
|
||||
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
|
||||
* @see #credentialSupplier(GcpCredentialSupplier)
|
||||
*/
|
||||
public GcpIamAuthenticationOptionsBuilder credential(GoogleCredential credential) {
|
||||
|
||||
Assert.notNull(credential, "Credential must not be null");
|
||||
|
||||
return credentialSupplier(() -> credential);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a {@link GcpCredentialSupplier}, required to create a signed JWT.
|
||||
* Alternatively, configure static {@link #credential(GoogleCredential)
|
||||
* credentials}.
|
||||
* @param credentialSupplier must not be {@literal null}.
|
||||
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
|
||||
* @see #credential(GoogleCredential)
|
||||
*/
|
||||
public GcpIamAuthenticationOptionsBuilder credentialSupplier(GcpCredentialSupplier credentialSupplier) {
|
||||
|
||||
Assert.notNull(credentialSupplier, "GcpCredentialSupplier must not be null");
|
||||
|
||||
this.credentialSupplier = credentialSupplier;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure an explicit service account id to use in GCP IAM calls. If none is
|
||||
* configured, falls back to using {@link GoogleCredential#getServiceAccountId()}.
|
||||
* @param serviceAccountId the service account id (email) to use
|
||||
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
|
||||
* @since 2.1
|
||||
*/
|
||||
public GcpIamAuthenticationOptionsBuilder serviceAccountId(String serviceAccountId) {
|
||||
|
||||
Assert.notNull(serviceAccountId, "Service account id may not be null");
|
||||
|
||||
return serviceAccountIdAccessor((GoogleCredential credential) -> serviceAccountId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure an {@link GcpServiceAccountIdAccessor} to obtain the service account
|
||||
* id used in GCP IAM calls. If none is configured, falls back to using
|
||||
* {@link GoogleCredential#getServiceAccountId()}.
|
||||
* @param serviceAccountIdAccessor the service account id provider to use
|
||||
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
|
||||
* @see GcpServiceAccountIdAccessor
|
||||
* @since 2.1
|
||||
*/
|
||||
GcpIamAuthenticationOptionsBuilder serviceAccountIdAccessor(
|
||||
GcpServiceAccountIdAccessor serviceAccountIdAccessor) {
|
||||
|
||||
Assert.notNull(serviceAccountIdAccessor, "GcpServiceAccountIdAccessor must not be null");
|
||||
|
||||
this.serviceAccountIdAccessor = serviceAccountIdAccessor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure an explicit GCP project id to use in GCP IAM API calls. If none is
|
||||
* configured, falls back using
|
||||
* {@link GoogleCredential#getServiceAccountProjectId()}.
|
||||
* @param projectId the GCP project id to use in GCP IAM API calls
|
||||
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
|
||||
* @since 2.1
|
||||
*/
|
||||
public GcpIamAuthenticationOptionsBuilder projectId(String projectId) {
|
||||
|
||||
Assert.notNull(projectId, "GCP project id must not be null");
|
||||
|
||||
return projectIdAccessor((GoogleCredential credential) -> projectId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure an {@link GcpProjectIdAccessor} to use in GCP IAM API calls. If none
|
||||
* is configured, falls back using
|
||||
* {@link GoogleCredential#getServiceAccountProjectId()}.
|
||||
* @param projectIdAccessor the GCP project id supplier to use in GCP IAM API
|
||||
* calls
|
||||
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
|
||||
* @since 2.1
|
||||
*/
|
||||
GcpIamAuthenticationOptionsBuilder projectIdAccessor(GcpProjectIdAccessor projectIdAccessor) {
|
||||
|
||||
Assert.notNull(projectIdAccessor, "GcpProjectIdAccessor must not be null");
|
||||
|
||||
this.projectIdAccessor = projectIdAccessor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the name of the role against which the login is being attempted.
|
||||
* @param role must not be empty or {@literal null}.
|
||||
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public GcpIamAuthenticationOptionsBuilder role(String role) {
|
||||
|
||||
Assert.hasText(role, "Role must not be null or empty");
|
||||
|
||||
this.role = role;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link Duration} for the JWT expiration. This defaults to 15
|
||||
* minutes and cannot be more than a hour.
|
||||
* @param jwtValidity must not be {@literal null}.
|
||||
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public GcpIamAuthenticationOptionsBuilder jwtValidity(Duration jwtValidity) {
|
||||
|
||||
Assert.notNull(jwtValidity, "JWT validity duration must not be null");
|
||||
|
||||
this.jwtValidity = jwtValidity;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link Clock} used to calculate epoch seconds until the JWT
|
||||
* expiration.
|
||||
* @param clock must not be {@literal null}.
|
||||
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public GcpIamAuthenticationOptionsBuilder clock(Clock clock) {
|
||||
|
||||
Assert.notNull(clock, "Clock must not be null");
|
||||
|
||||
this.clock = clock;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new {@link GcpIamAuthenticationOptions} instance.
|
||||
* @return a new {@link GcpIamAuthenticationOptions}.
|
||||
*/
|
||||
public GcpIamAuthenticationOptions build() {
|
||||
|
||||
Assert.notNull(this.credentialSupplier, "GcpCredentialSupplier must not be null");
|
||||
Assert.notNull(this.role, "Role must not be null");
|
||||
|
||||
return new GcpIamAuthenticationOptions(this.path, this.credentialSupplier, this.role, this.jwtValidity,
|
||||
this.clock, this.serviceAccountIdAccessor, this.projectIdAccessor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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
|
||||
*
|
||||
* https://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.IOException;
|
||||
import java.net.InetAddress;
|
||||
|
||||
/**
|
||||
* Mechanism to generate a SHA-256 hashed and hex-encoded representation of the IP
|
||||
* address. Can be calculated with {@code echo -n 192.168.99.1 | sha256sum}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdUserIdMechanism
|
||||
*/
|
||||
public class IpAddressUserId implements AppIdUserIdMechanism {
|
||||
|
||||
@Override
|
||||
public String createUserId() {
|
||||
try {
|
||||
return Sha256.toSha256(InetAddress.getLocalHost().getHostAddress());
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -204,20 +204,6 @@ public abstract class LifecycleAwareSessionManagerSupport extends Authentication
|
||||
*/
|
||||
public interface RefreshTrigger {
|
||||
|
||||
/**
|
||||
* Determine the next execution time according to the given trigger context.
|
||||
* @param loginToken login token encapsulating renewability and lease duration.
|
||||
* @return the next execution time as defined by the trigger, or {@code null} if
|
||||
* the trigger won't fire anymore.
|
||||
* @deprecated since 3.1, use {@link #nextExecution(LoginToken) instead}.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated(since = "3.1")
|
||||
default Date nextExecutionTime(LoginToken loginToken) {
|
||||
Instant instant = nextExecution(loginToken);
|
||||
return instant != null ? Date.from(instant) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the next execution time according to the given trigger context.
|
||||
* @param loginToken login token encapsulating renewability and lease duration.
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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
|
||||
*
|
||||
* https://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.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Mechanism to generate a UserId based on the Mac address. {@link MacAddressUserId}
|
||||
* creates a hex-encoded representation of the Mac address without any separators
|
||||
* (0123456789AB). A network interface hint can be specified optionally to select a
|
||||
* network interface (index/name).
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdUserIdMechanism
|
||||
*/
|
||||
public class MacAddressUserId implements AppIdUserIdMechanism {
|
||||
|
||||
private final Log logger = LogFactory.getLog(MacAddressUserId.class);
|
||||
|
||||
private final String networkInterfaceHint;
|
||||
|
||||
/**
|
||||
* Create a new {@link MacAddressUserId} using the {@link NetworkInterface} from the
|
||||
* {@link InetAddress#getLocalHost()}.
|
||||
*/
|
||||
public MacAddressUserId() {
|
||||
this("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MacAddressUserId} using a {@code networkInterfaceIndex}. The
|
||||
* index is applied to {@link NetworkInterface#getNetworkInterfaces()} to obtain the
|
||||
* desired network interface.
|
||||
* @param networkInterfaceIndex must be greater or equal to zero.
|
||||
*/
|
||||
public MacAddressUserId(int networkInterfaceIndex) {
|
||||
|
||||
Assert.isTrue(networkInterfaceIndex >= 0, "NetworkInterfaceIndex must be greater or equal to 0");
|
||||
|
||||
this.networkInterfaceHint = "" + networkInterfaceIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MacAddressUserId} using a {@code networkInterfaceName}. This
|
||||
* name is compared with {@link NetworkInterface#getName()} and
|
||||
* {@link NetworkInterface#getDisplayName()} to obtain the desired network interface.
|
||||
* @param networkInterfaceName must not be {@literal null}.
|
||||
*/
|
||||
public MacAddressUserId(String networkInterfaceName) {
|
||||
|
||||
Assert.notNull(networkInterfaceName, "NetworkInterfaceName must not be null");
|
||||
|
||||
this.networkInterfaceHint = networkInterfaceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createUserId() {
|
||||
|
||||
try {
|
||||
|
||||
Optional<NetworkInterface> networkInterface = Optional.empty();
|
||||
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
|
||||
|
||||
if (StringUtils.hasText(this.networkInterfaceHint)) {
|
||||
|
||||
try {
|
||||
networkInterface = getNetworkInterface(Integer.parseInt(this.networkInterfaceHint), interfaces);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
networkInterface = getNetworkInterface((this.networkInterfaceHint), interfaces);
|
||||
}
|
||||
}
|
||||
|
||||
if (!networkInterface.isPresent()) {
|
||||
|
||||
if (StringUtils.hasText(this.networkInterfaceHint)) {
|
||||
this.logger
|
||||
.warn("Did not find a NetworkInterface applying hint %s".formatted(this.networkInterfaceHint));
|
||||
}
|
||||
|
||||
InetAddress localHost = InetAddress.getLocalHost();
|
||||
networkInterface = Optional.ofNullable(NetworkInterface.getByInetAddress(localHost));
|
||||
|
||||
if (!networkInterface.filter(MacAddressUserId::hasNetworkAddress).isPresent()) {
|
||||
networkInterface = getNetworkInterfaceWithHardwareAddress(interfaces);
|
||||
}
|
||||
}
|
||||
|
||||
return networkInterface.map(MacAddressUserId::getRequiredNetworkAddress) //
|
||||
.map(Sha256::toHexString) //
|
||||
.map(Sha256::toSha256) //
|
||||
.orElseThrow(() -> new IllegalStateException("Cannot determine NetworkInterface"));
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Optional<NetworkInterface> getNetworkInterface(Number hint, List<NetworkInterface> interfaces) {
|
||||
|
||||
if (interfaces.size() > hint.intValue() && hint.intValue() >= 0) {
|
||||
return Optional.of(interfaces.get(hint.intValue()));
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static Optional<NetworkInterface> getNetworkInterface(String hint, List<NetworkInterface> interfaces) {
|
||||
|
||||
return interfaces.stream() //
|
||||
.filter(anInterface -> matchesHint(hint, anInterface)) //
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
private static boolean matchesHint(String hint, NetworkInterface networkInterface) {
|
||||
|
||||
return hint.equals(networkInterface.getDisplayName()) || hint.equals(networkInterface.getName());
|
||||
}
|
||||
|
||||
private static Optional<NetworkInterface> getNetworkInterfaceWithHardwareAddress(
|
||||
List<NetworkInterface> interfaces) {
|
||||
|
||||
return interfaces.stream() //
|
||||
.filter(MacAddressUserId::hasNetworkAddress) //
|
||||
.sorted(Comparator.comparingInt(NetworkInterface::getIndex)) //
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
private static Optional<byte[]> getNetworkAddress(NetworkInterface it) {
|
||||
|
||||
try {
|
||||
return Optional.ofNullable(it.getHardwareAddress());
|
||||
}
|
||||
catch (SocketException e) {
|
||||
throw new IllegalStateException("Cannot determine hardware address for %s".formatted(it.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] getRequiredNetworkAddress(NetworkInterface it) {
|
||||
|
||||
return getNetworkAddress(it) //
|
||||
.orElseThrow(() -> new IllegalStateException(
|
||||
"Network interface %s has no hardware address".formatted(it.getName())));
|
||||
}
|
||||
|
||||
private static boolean hasNetworkAddress(NetworkInterface it) {
|
||||
return getNetworkAddress(it).isPresent();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
/**
|
||||
* A static UserId.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdUserIdMechanism
|
||||
*/
|
||||
public class StaticUserId implements AppIdUserIdMechanism {
|
||||
|
||||
private final String userId;
|
||||
|
||||
/**
|
||||
* Create a new {@link StaticUserId} for a given {@code userId}.
|
||||
* @param userId must not be empty or {@literal null}.
|
||||
*/
|
||||
public StaticUserId(String userId) {
|
||||
|
||||
Assert.hasText(userId, "UserId must not be empty");
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createUserId() {
|
||||
return this.userId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,7 +34,6 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.authentication.*;
|
||||
import org.springframework.vault.authentication.AppIdAuthenticationOptions.AppIdAuthenticationOptionsBuilder;
|
||||
import org.springframework.vault.authentication.AppRoleAuthenticationOptions.AppRoleAuthenticationOptionsBuilder;
|
||||
import org.springframework.vault.authentication.AppRoleAuthenticationOptions.RoleId;
|
||||
import org.springframework.vault.authentication.AppRoleAuthenticationOptions.SecretId;
|
||||
@@ -263,7 +262,6 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration im
|
||||
|
||||
return switch (authenticationMethod) {
|
||||
case TOKEN -> tokenAuthentication();
|
||||
case APPID -> appIdAuthentication();
|
||||
case APPROLE -> appRoleAuthentication();
|
||||
case AWS_EC2 -> awsEc2Authentication();
|
||||
case AWS_IAM -> awsIamAuthentication();
|
||||
@@ -288,24 +286,6 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration im
|
||||
return new TokenAuthentication(token);
|
||||
}
|
||||
|
||||
protected ClientAuthentication appIdAuthentication() {
|
||||
|
||||
String appId = getProperty("vault.app-id.app-id", getProperty("spring.application.name"));
|
||||
String userId = getProperty("vault.app-id.user-id");
|
||||
String path = getProperty("vault.app-id.app-id-path",
|
||||
AppIdAuthenticationOptions.DEFAULT_APPID_AUTHENTICATION_PATH);
|
||||
|
||||
Assert.hasText(appId, "Vault AppId authentication: AppId (vault.app-id.app-id) must not be empty");
|
||||
Assert.hasText(userId, "Vault AppId authentication: UserId (vault.app-id.user-id) must not be empty");
|
||||
|
||||
AppIdAuthenticationOptionsBuilder builder = AppIdAuthenticationOptions.builder()
|
||||
.appId(appId)
|
||||
.userIdMechanism(getAppIdUserIdMechanism(userId))
|
||||
.path(path);
|
||||
|
||||
return new AppIdAuthentication(builder.build(), restOperations());
|
||||
}
|
||||
|
||||
protected ClientAuthentication appRoleAuthentication() {
|
||||
|
||||
String roleId = getProperty("vault.app-role.role-id");
|
||||
@@ -326,19 +306,6 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration im
|
||||
return new AppRoleAuthentication(builder.build(), restOperations());
|
||||
}
|
||||
|
||||
protected AppIdUserIdMechanism getAppIdUserIdMechanism(String userId) {
|
||||
|
||||
if (userId.equalsIgnoreCase(AppIdUserId.IP_ADDRESS.name())) {
|
||||
return new IpAddressUserId();
|
||||
}
|
||||
|
||||
if (userId.equalsIgnoreCase(AppIdUserId.MAC_ADDRESS.name())) {
|
||||
return new MacAddressUserId();
|
||||
}
|
||||
|
||||
return new StaticUserId(userId);
|
||||
}
|
||||
|
||||
protected ClientAuthentication awsEc2Authentication() {
|
||||
|
||||
String role = getProperty("vault.aws-ec2.role");
|
||||
@@ -463,15 +430,9 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration im
|
||||
return value != null ? this.applicationContext.getResource(value) : null;
|
||||
}
|
||||
|
||||
enum AppIdUserId {
|
||||
|
||||
IP_ADDRESS, MAC_ADDRESS;
|
||||
|
||||
}
|
||||
|
||||
enum AuthenticationMethod {
|
||||
|
||||
TOKEN, APPID, APPROLE, AWS_EC2, AWS_IAM, AZURE, CERT, CUBBYHOLE, KUBERNETES;
|
||||
TOKEN, APPROLE, AWS_EC2, AWS_IAM, AZURE, CERT, CUBBYHOLE, KUBERNETES;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.springframework.vault.repository.mapping;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.data.keyvalue.core.mapping.KeySpaceResolver;
|
||||
import org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext;
|
||||
import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
@@ -31,17 +28,6 @@ import org.springframework.data.util.TypeInformation;
|
||||
*/
|
||||
public class VaultMappingContext extends KeyValueMappingContext<VaultPersistentEntity<?>, VaultPersistentProperty> {
|
||||
|
||||
/**
|
||||
* @return the {@link KeySpaceResolver} if configured.
|
||||
* @deprecated since 3.1, {@link KeySpaceResolver} has fully moved into
|
||||
* {@link KeyValueMappingContext}.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated(since = "3.1", forRemoval = true)
|
||||
public KeySpaceResolver getFallbackKeySpaceResolver() {
|
||||
return super.getKeySpaceResolver();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> VaultPersistentEntity<?> createPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
return new BasicVaultPersistentEntity<>(typeInformation, getKeySpaceResolver());
|
||||
|
||||
@@ -546,14 +546,6 @@ public class Policy {
|
||||
*/
|
||||
UPDATE,
|
||||
|
||||
/**
|
||||
* Deprecated: Previous capability literal before it was split into
|
||||
* {@link #CREATE} and {@link #UPDATE}.
|
||||
* @deprecated since 2.3 and Vault 0.5.
|
||||
*/
|
||||
@Deprecated(since = "2.3")
|
||||
WRITE,
|
||||
|
||||
/**
|
||||
* Allows deleting the data at the given path.
|
||||
*/
|
||||
|
||||
@@ -90,17 +90,6 @@ public class VaultSignRequest {
|
||||
return this.signatureAlgorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return algorithm used for creating the signature or {@literal null} to use the
|
||||
* default algorithm.
|
||||
* @deprecated since 2.4, use {@link #getSignatureAlgorithm()} instead.
|
||||
*/
|
||||
@Deprecated(since = "2.4")
|
||||
@Nullable
|
||||
public String getAlgorithm() {
|
||||
return getSignatureAlgorithm();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the input is already hashed.
|
||||
* @since 3.1
|
||||
@@ -180,19 +169,6 @@ public class VaultSignRequest {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the algorithm to be used for the operation.
|
||||
* @param algorithm Specify the algorithm to be used for the operation. Supported
|
||||
* algorithms are: {@literal sha2-224}, {@literal sha2-256}, {@literal sha2-384},
|
||||
* {@literal sha2-512}. Defaults to {@literal sha2-256} if not set.
|
||||
* @return {@code this} {@link VaultSignRequestBuilder}.
|
||||
* @deprecated since 2.4, use {@link #signatureAlgorithm(String)} instead.
|
||||
*/
|
||||
@Deprecated(since = "2.4")
|
||||
public VaultSignRequestBuilder algorithm(String algorithm) {
|
||||
return signatureAlgorithm(algorithm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new {@link VaultSignRequest} instance. Requires
|
||||
* {@link #plaintext(Plaintext)} to be configured.
|
||||
|
||||
@@ -130,17 +130,6 @@ public class VaultSignatureVerificationRequest {
|
||||
return this.signatureAlgorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return algorithm used for verifying the signature or {@literal null} to use the
|
||||
* default algorithm.
|
||||
* @deprecated since 2.4, use {@link #getSignatureAlgorithm()} instead.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated(since = "2.4")
|
||||
public String getAlgorithm() {
|
||||
return getSignatureAlgorithm();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the input is already hashed.
|
||||
* @since 3.1
|
||||
@@ -258,19 +247,6 @@ public class VaultSignatureVerificationRequest {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the algorithm to be used for the operation.
|
||||
* @param algorithm Specify the algorithm to be used for the operation. Supported
|
||||
* algorithms are: {@literal sha2-224}, {@literal sha2-256}, {@literal sha2-384},
|
||||
* {@literal sha2-512}. Defaults to {@literal sha2-256} if not set.
|
||||
* @return {@code this} {@link VaultSignatureVerificationRequestBuilder}.
|
||||
* @deprecated since 2.4, use {@link #signatureAlgorithm(String)} instead.
|
||||
*/
|
||||
@Deprecated(since = "2.4")
|
||||
public VaultSignatureVerificationRequestBuilder algorithm(String algorithm) {
|
||||
return signatureAlgorithm(algorithm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new {@link VaultSignatureVerificationRequest} instance. Requires
|
||||
* {@link #plaintext(Plaintext)} and one of {@link #hmac(Hmac)},
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-2025 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
|
||||
*
|
||||
* https://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.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
import org.springframework.vault.util.DisabledOnVaultVersion;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
|
||||
/**
|
||||
* Integration test base class for {@link AppIdAuthentication} tests.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@DisabledOnVaultVersion("1.12")
|
||||
public abstract class AppIdAuthenticationIntegrationTestBase extends IntegrationTestSupport {
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
|
||||
if (!prepare().hasAuth("app-id")) {
|
||||
prepare().mountAuth("app-id");
|
||||
}
|
||||
|
||||
prepare().getVaultOperations().doWithSession(restOperations -> {
|
||||
|
||||
Map<String, String> appIdData = new HashMap<String, String>();
|
||||
appIdData.put("value", "dummy"); // policy
|
||||
appIdData.put("display_name", "this is my test application");
|
||||
|
||||
restOperations.postForEntity("auth/app-id/map/app-id/myapp", appIdData, Map.class);
|
||||
|
||||
Map<String, String> userIdData = new HashMap<String, String>();
|
||||
userIdData.put("value", "myapp"); // name of the app-id
|
||||
userIdData.put("cidr_block", "0.0.0.0/0");
|
||||
|
||||
restOperations.postForEntity("auth/app-id/map/user-id/static-userid-value", userIdData, Map.class);
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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
|
||||
*
|
||||
* https://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.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.vault.VaultException;
|
||||
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.*;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link AppIdAuthentication}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class AppIdAuthenticationIntegrationTests extends AppIdAuthenticationIntegrationTestBase {
|
||||
|
||||
@Test
|
||||
void shouldLoginSuccessfully() {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()
|
||||
.appId("myapp") //
|
||||
.userIdMechanism(new StaticUserId("static-userid-value")) //
|
||||
.build();
|
||||
|
||||
RestTemplate restTemplate = TestRestTemplateFactory.create(Settings.createSslConfiguration());
|
||||
|
||||
AppIdAuthentication authentication = new AppIdAuthentication(options, restTemplate);
|
||||
VaultToken login = authentication.login();
|
||||
|
||||
assertThat(login.getToken()).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loginShouldFail() {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()
|
||||
.appId("wrong") //
|
||||
.userIdMechanism(new StaticUserId("wrong")) //
|
||||
.build();
|
||||
|
||||
RestTemplate restTemplate = TestRestTemplateFactory.create(Settings.createSslConfiguration());
|
||||
|
||||
assertThatExceptionOfType(VaultException.class)
|
||||
.isThrownBy(() -> new AppIdAuthentication(options, restTemplate).login());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-2025 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
|
||||
*
|
||||
* https://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.junit.jupiter.api.Test;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.vault.util.Settings;
|
||||
import org.springframework.vault.util.TestWebClientFactory;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link AppIdAuthentication} using
|
||||
* {@link AuthenticationStepsOperator}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class AppIdAuthenticationOperatorIntegrationTests extends AppIdAuthenticationIntegrationTestBase {
|
||||
|
||||
WebClient webClient = TestWebClientFactory.create(Settings.createSslConfiguration());
|
||||
|
||||
@Test
|
||||
void authenticationStepsShouldLoginSuccessfully() {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()
|
||||
.appId("myapp") //
|
||||
.userIdMechanism(new StaticUserId("static-userid-value")) //
|
||||
.build();
|
||||
|
||||
AuthenticationStepsOperator supplier = new AuthenticationStepsOperator(
|
||||
AppIdAuthentication.createAuthenticationSteps(options), this.webClient);
|
||||
|
||||
supplier.getVaultToken() //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(1) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void authenticationStepsLoginShouldFail() {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()
|
||||
.appId("wrong") //
|
||||
.userIdMechanism(new StaticUserId("wrong")) //
|
||||
.build();
|
||||
|
||||
AuthenticationStepsOperator supplier = new AuthenticationStepsOperator(
|
||||
AppIdAuthentication.createAuthenticationSteps(options), this.webClient);
|
||||
|
||||
supplier.getVaultToken() //
|
||||
.as(StepVerifier::create) //
|
||||
.expectError() //
|
||||
.verify();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-2025 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
|
||||
*
|
||||
* https://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.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.vault.VaultException;
|
||||
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.*;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link AppIdAuthentication} using
|
||||
* {@link AuthenticationStepsExecutor}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class AppIdAuthenticationStepsIntegrationTests extends AppIdAuthenticationIntegrationTestBase {
|
||||
|
||||
@Test
|
||||
void authenticationStepsShouldLoginSuccessfully() {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()
|
||||
.appId("myapp") //
|
||||
.userIdMechanism(new StaticUserId("static-userid-value")) //
|
||||
.build();
|
||||
|
||||
RestTemplate restTemplate = TestRestTemplateFactory.create(Settings.createSslConfiguration());
|
||||
|
||||
AuthenticationStepsExecutor executor = new AuthenticationStepsExecutor(
|
||||
AppIdAuthentication.createAuthenticationSteps(options), restTemplate);
|
||||
|
||||
VaultToken login = executor.login();
|
||||
|
||||
assertThat(login.getToken()).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void authenticationStepsLoginShouldFail() {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()
|
||||
.appId("wrong") //
|
||||
.userIdMechanism(new StaticUserId("wrong")) //
|
||||
.build();
|
||||
|
||||
RestTemplate restTemplate = TestRestTemplateFactory.create(Settings.createSslConfiguration());
|
||||
|
||||
AuthenticationStepsExecutor executor = new AuthenticationStepsExecutor(
|
||||
AppIdAuthentication.createAuthenticationSteps(options), restTemplate);
|
||||
|
||||
assertThatExceptionOfType(VaultException.class).isThrownBy(executor::login);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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
|
||||
*
|
||||
* https://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.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.client.VaultClients;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AppIdAuthentication}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class AppIdAuthenticationUnitTests {
|
||||
|
||||
RestTemplate restTemplate;
|
||||
|
||||
MockRestServiceServer mockRest;
|
||||
|
||||
@BeforeEach
|
||||
void before() {
|
||||
|
||||
RestTemplate restTemplate = VaultClients.createRestTemplate();
|
||||
restTemplate.setUriTemplateHandler(new VaultClients.PrefixAwareUriBuilderFactory());
|
||||
this.mockRest = MockRestServiceServer.createServer(restTemplate);
|
||||
this.restTemplate = restTemplate;
|
||||
}
|
||||
|
||||
@Test
|
||||
void loginShouldObtainTokenWithStaticUserId() {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()
|
||||
.appId("hello") //
|
||||
.userIdMechanism(new StaticUserId("world")) //
|
||||
.build();
|
||||
|
||||
this.mockRest.expect(requestTo("/auth/app-id/login"))
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
.andExpect(jsonPath("$.app_id").value("hello"))
|
||||
.andExpect(jsonPath("$.user_id").value("world"))
|
||||
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{" + "\"auth\":{\"client_token\":\"my-token\"}" + "}"));
|
||||
|
||||
AppIdAuthentication authentication = new AppIdAuthentication(options, this.restTemplate);
|
||||
|
||||
VaultToken login = authentication.login();
|
||||
assertThat(login).isInstanceOf(LoginToken.class);
|
||||
assertThat(login.getToken()).isEqualTo("my-token");
|
||||
}
|
||||
|
||||
@Test
|
||||
void loginShouldFail() {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()
|
||||
.appId("hello") //
|
||||
.userIdMechanism(new StaticUserId("world")) //
|
||||
.build();
|
||||
|
||||
this.mockRest.expect(requestTo("/auth/app-id/login")) //
|
||||
.andRespond(withServerError());
|
||||
|
||||
assertThatExceptionOfType(VaultException.class)
|
||||
.isThrownBy(() -> new AppIdAuthentication(options, this.restTemplate).login());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-2025 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
|
||||
*
|
||||
* https://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.security.PrivateKey;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GcpIamAuthenticationOptions}.
|
||||
*
|
||||
* @author Magnus Jungsbluth
|
||||
*/
|
||||
class GcpIamAuthenticationOptionsBuilderUnitTests {
|
||||
|
||||
@Test
|
||||
void shouldDefaultToCredentialServiceAccountId() {
|
||||
|
||||
GoogleCredential credential = createGoogleCredential();
|
||||
|
||||
GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder()
|
||||
.credential(credential)
|
||||
.role("foo")
|
||||
.build();
|
||||
|
||||
assertThat(options.getServiceAccountIdAccessor().getServiceAccountId(credential)).isEqualTo("hello@world");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAllowServiceAccountIdOverride() {
|
||||
|
||||
GoogleCredential credential = createGoogleCredential();
|
||||
|
||||
GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder()
|
||||
.credential(credential)
|
||||
.serviceAccountId("override@foo.com")
|
||||
.role("foo")
|
||||
.build();
|
||||
|
||||
assertThat(options.getServiceAccountIdAccessor().getServiceAccountId(credential)).isEqualTo("override@foo.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAllowServiceAccountIdProviderOverride() {
|
||||
|
||||
GoogleCredential credential = createGoogleCredential();
|
||||
|
||||
GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder()
|
||||
.credential(credential)
|
||||
.serviceAccountIdAccessor((GoogleCredential googleCredential) -> "override@foo.com")
|
||||
.role("foo")
|
||||
.build();
|
||||
|
||||
assertThat(options.getServiceAccountIdAccessor().getServiceAccountId(credential)).isEqualTo("override@foo.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDefaultToCredentialProjectId() {
|
||||
|
||||
GoogleCredential credential = createGoogleCredential();
|
||||
|
||||
GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder()
|
||||
.credential(credential)
|
||||
.role("foo")
|
||||
.build();
|
||||
|
||||
assertThat(options.getProjectIdAccessor().getProjectId(credential)).isEqualTo("project-id");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAllowProjectIdOverride() {
|
||||
|
||||
GoogleCredential credential = createGoogleCredential();
|
||||
|
||||
GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder()
|
||||
.credential(credential)
|
||||
.projectId("my-project")
|
||||
.role("foo")
|
||||
.build();
|
||||
|
||||
assertThat(options.getProjectIdAccessor().getProjectId(credential)).isEqualTo("my-project");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAllowProjectIdProviderOverride() {
|
||||
|
||||
GoogleCredential credential = createGoogleCredential();
|
||||
|
||||
GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder()
|
||||
.credential(credential)
|
||||
.projectIdAccessor((GoogleCredential googleCredential) -> "my-project")
|
||||
.role("foo")
|
||||
.build();
|
||||
|
||||
assertThat(options.getProjectIdAccessor().getProjectId(credential)).isEqualTo("my-project");
|
||||
}
|
||||
|
||||
private static GoogleCredential createGoogleCredential() {
|
||||
|
||||
GoogleCredential credential = new GoogleCredential.Builder().setServiceAccountId("hello@world")
|
||||
.setServiceAccountProjectId("project-id")
|
||||
.setServiceAccountPrivateKey(mock(PrivateKey.class))
|
||||
.setServiceAccountPrivateKeyId("key-id")
|
||||
.build();
|
||||
|
||||
credential.setAccessToken("foobar");
|
||||
|
||||
return credential;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-2025 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
|
||||
*
|
||||
* https://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.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.time.Duration;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential.Builder;
|
||||
import com.google.api.client.googleapis.testing.auth.oauth2.MockGoogleCredential;
|
||||
import com.google.api.client.json.gson.GsonFactory;
|
||||
import com.google.api.client.testing.http.MockHttpTransport;
|
||||
import com.google.api.client.testing.http.MockLowLevelHttpResponse;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
import org.springframework.vault.client.VaultClients;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GcpIamAuthentication}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class GcpIamAuthenticationUnitTests {
|
||||
|
||||
RestTemplate restTemplate;
|
||||
|
||||
MockRestServiceServer mockRest;
|
||||
|
||||
@BeforeEach
|
||||
void before() {
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
restTemplate.setUriTemplateHandler(new VaultClients.PrefixAwareUriBuilderFactory());
|
||||
|
||||
this.mockRest = MockRestServiceServer.createServer(restTemplate);
|
||||
this.restTemplate = restTemplate;
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldLogin() throws NoSuchAlgorithmException {
|
||||
|
||||
this.mockRest.expect(requestTo("/auth/gcp/login"))
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
.andExpect(jsonPath("$.role").value("dev-role"))
|
||||
.andExpect(jsonPath("$.jwt").value("my-jwt"))
|
||||
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{" + "\"auth\":{\"client_token\":\"my-token\", \"renewable\": true, \"lease_duration\": 10}"
|
||||
+ "}"));
|
||||
|
||||
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
|
||||
keyGen.initialize(1024);
|
||||
KeyPair key = keyGen.generateKeyPair();
|
||||
|
||||
GoogleCredential credential = new MockGoogleCredential.Builder().setServiceAccountId("hello@world")
|
||||
.setServiceAccountProjectId("foobar")
|
||||
.setServiceAccountPrivateKey(key.getPrivate())
|
||||
.setServiceAccountPrivateKeyId("key-id")
|
||||
.setJsonFactory(new GsonFactory())
|
||||
.setTransport(new MockHttpTransport.Builder().setLowLevelHttpResponse(createMockHttpResponse()).build())
|
||||
.build();
|
||||
credential.setAccessToken("foobar");
|
||||
|
||||
GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder()
|
||||
.role("dev-role")
|
||||
.credential(credential)
|
||||
.build();
|
||||
GcpIamAuthentication authentication = new GcpIamAuthentication(options, this.restTemplate,
|
||||
new MockHttpTransport.Builder().setLowLevelHttpResponse(createMockHttpResponse()).build());
|
||||
|
||||
VaultToken login = authentication.login();
|
||||
|
||||
assertThat(login).isInstanceOf(LoginToken.class);
|
||||
assertThat(login.getToken()).isEqualTo("my-token");
|
||||
|
||||
LoginToken loginToken = (LoginToken) login;
|
||||
assertThat(loginToken.isRenewable()).isTrue();
|
||||
assertThat(loginToken.getLeaseDuration()).isEqualTo(Duration.ofSeconds(10));
|
||||
}
|
||||
|
||||
private MockLowLevelHttpResponse createMockHttpResponse() {
|
||||
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse();
|
||||
response.setStatusCode(200);
|
||||
response.setContent("{\"keyId\":\"keyid\", \"signedJwt\":\"my-jwt\"}");
|
||||
return response;
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateNewGcpIamObjectInstance() throws GeneralSecurityException, IOException {
|
||||
|
||||
PrivateKey privateKeyMock = mock(PrivateKey.class);
|
||||
GoogleCredential credential = new Builder().setServiceAccountId("hello@world")
|
||||
.setServiceAccountProjectId("foobar")
|
||||
.setServiceAccountPrivateKey(privateKeyMock)
|
||||
.setServiceAccountPrivateKeyId("key-id")
|
||||
.build();
|
||||
credential.setAccessToken("foobar");
|
||||
|
||||
GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder()
|
||||
.role("dev-role")
|
||||
.credential(credential)
|
||||
.build();
|
||||
|
||||
new GcpIamAuthentication(options, this.restTemplate);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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
|
||||
*
|
||||
* https://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.regex.Pattern;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link IpAddressUserId}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class IpAddressUserIdTests {
|
||||
|
||||
@Test
|
||||
void shouldGenerateUppercaseSha256HexString() {
|
||||
|
||||
String userId = new IpAddressUserId().createUserId();
|
||||
|
||||
assertThat(userId).matches(Pattern.compile("[0-9A-F]+")).doesNotMatch(Pattern.compile("[a-f]"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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
|
||||
*
|
||||
* https://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.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assumptions.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MacAddressUserId}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class MacAddressUserIdUnitTests {
|
||||
|
||||
@Test
|
||||
void shouldGenerateUppercaseSha256HexString() {
|
||||
|
||||
String userId = new MacAddressUserId().createUserId();
|
||||
|
||||
assertThat(userId).matches(Pattern.compile("[0-9A-F]+")).doesNotMatch(Pattern.compile("[a-f]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldGenerateUserIdFromNetworkInterfaceIndex() throws Exception {
|
||||
|
||||
int index = getValidNetworkInterfaceIndex();
|
||||
assumeTrue(index != -1);
|
||||
|
||||
String userId = new MacAddressUserId(index).createUserId();
|
||||
|
||||
assertThat(userId).matches(Pattern.compile("[0-9A-F]+")).doesNotMatch(Pattern.compile("[a-f]"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain index for {@link NetworkInterface} with a HardwareAddress.
|
||||
* @return -1 if none, otherwise index.
|
||||
* @throws SocketException
|
||||
*/
|
||||
private int getValidNetworkInterfaceIndex() throws SocketException {
|
||||
|
||||
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
|
||||
|
||||
int index = -1;
|
||||
|
||||
for (int i = 0; i < interfaces.size(); i++) {
|
||||
if (interfaces.get(i).getHardwareAddress() != null) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-2025 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
|
||||
*
|
||||
* https://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.config;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
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.junit.jupiter.SpringExtension;
|
||||
import org.springframework.vault.authentication.AppIdAuthentication;
|
||||
import org.springframework.vault.authentication.ClientAuthentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link EnvironmentVaultConfiguration} with AppId authentication.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestPropertySource(properties = { "vault.uri=https://localhost:8123", "vault.authentication=appid",
|
||||
"vault.app-id.user-id=IP_ADDRESS", "vault.app-id.app-id=foo" })
|
||||
class EnvironmentVaultConfigurationAppIdAuthenticationUnitTests {
|
||||
|
||||
@Configuration
|
||||
@Import(EnvironmentVaultConfiguration.class)
|
||||
static class ApplicationConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Autowired
|
||||
EnvironmentVaultConfiguration configuration;
|
||||
|
||||
@Test
|
||||
void shouldConfigureAuthentication() {
|
||||
|
||||
ClientAuthentication clientAuthentication = this.configuration.clientAuthentication();
|
||||
|
||||
assertThat(clientAuthentication).isInstanceOf(AppIdAuthentication.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
* xref:introduction/introduction.adoc[]
|
||||
** xref:introduction/getting-started.adoc[]
|
||||
** xref:introduction/dependencies.adoc[]
|
||||
** xref:introduction/new-features.adoc[]
|
||||
* xref:vault/vault.adoc[]
|
||||
** xref:vault/imperative-template.adoc[]
|
||||
** xref:vault/vault-secret-engines.adoc[]
|
||||
@@ -13,5 +12,4 @@
|
||||
** xref:vault/authentication.adoc[]
|
||||
** xref:vault/spring-security.adoc[]
|
||||
|
||||
|
||||
* xref:attachment$api/java/index.html[Javadoc,role=link-external,window=_blank]
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
[[new-features]]
|
||||
= New & Noteworthy
|
||||
|
||||
[[new-features.3-0-0]]
|
||||
== What's new in Spring Vault 3.0
|
||||
|
||||
* Upgrade to Spring Framework 6 and Java 17 baseline
|
||||
* Upgrade to AWS SDK 2.
|
||||
|
||||
== What's new in Spring Vault 2.4
|
||||
|
||||
* Support for xref:vault/authentication.adoc#vault.authentication.userpass[Username/Password authentication] for Username/Password, LDAP, Okta, and RADIUS authentication.
|
||||
* Support of versioned Key/Value secrets engines for Vault repositories.
|
||||
* xref:vault/vault-repositories.adoc#repositories.optimistic-locking[Optimistic locking support through Vault repositories using versioned Key/Value secrets engines].
|
||||
|
||||
[[new-features.2-3-0]]
|
||||
== What's new in Spring Vault 2.3
|
||||
|
||||
* Support for PEM-encoded certificates for keystore and truststore usage.
|
||||
* `ReactiveVaultEndpointProvider` for non-blocking lookup of `VaultEndpoint`.
|
||||
* `VaultKeyValueMetadataOperations` for Key-Value metadata interaction.
|
||||
* Support for `transform` secrets engine (Enterprise Feature).
|
||||
* Documentation of xref:vault/vault-secret-engines.adoc[how to use Vault secret backends].
|
||||
* Login credentials for Kubernetes and PCF authentication are reloaded for each login attempt.
|
||||
* `SecretLeaseContainer` publishes `SecretLeaseRotatedEvent` instead of `SecretLeaseExpiredEvent` and `SecretLeaseCreatedEvent` on successful secret rotation.
|
||||
* `AbstractVaultConfiguration.threadPoolTaskScheduler()` bean type changed to `TaskSchedulerWrapper` instead of `ThreadPoolTaskScheduler`.
|
||||
* Since 2.3.2: `GcpIamCredentialsAuthentication`
|
||||
|
||||
[[new-features.2-2-0]]
|
||||
== What's new in Spring Vault 2.2
|
||||
|
||||
* Support for Key-Value v2 (versioned secrets engine) secrets through `@VaultPropertySource`.
|
||||
* SpEL support in `@Secret`.
|
||||
* Add support for Jetty as reactive HttpClient.
|
||||
* `LifecycleAwareSessionManager` and `ReactiveLifecycleAwareSessionManager` emit now ``AuthenticationEvent``s.
|
||||
* xref:vault/vault-secret-engines.adoc#vault.authentication.pcf[PCF Authentication].
|
||||
* Deprecation of `AppIdAuthentication`.
|
||||
Use `AppRoleAuthentication` instead as recommended by HashiCorp Vault.
|
||||
* `CubbyholeAuthentication` and wrapped `AppRoleAuthentication` now use `sys/wrapping/unwrap` endpoints by default.
|
||||
* Kotlin Coroutines support for `ReactiveVaultOperations`.
|
||||
|
||||
[[new-features.2-1-0]]
|
||||
== What's new in Spring Vault 2.1
|
||||
|
||||
* xref:vault/authentication.adoc#vault.authentication.gcpgce[GCP Compute], xref:vault/authentication.adoc#vault.authentication.gcpiam[GCP IAM], and xref:vault/authentication.adoc#vault.authentication.azuremsi[Azure] authentication.
|
||||
* Template API support for versioned and unversioned Key/Value secrets engines and for Vault wrapping operations.
|
||||
* Support full pull mode in reactive AppRole authentication.
|
||||
* Improved Exception hierarchy for Vault login failures.
|
||||
|
||||
[[new-features.2-0-0]]
|
||||
== What's new in Spring Vault 2.0
|
||||
|
||||
* Authentication steps DSL to xref:vault/authentication.adoc#vault.authentication.steps[compose authentication flows].
|
||||
* xref:vault/reactive-template.adoc[Reactive Vault client] via `ReactiveVaultOperations`.
|
||||
* xref:vault/vault-repositories.adoc[Vault repository support] based on Spring Data KeyValue.
|
||||
* Transit batch encrypt and decrypt support.
|
||||
* Policy management for policies stored as JSON.
|
||||
* Support CSR signing, certificate revocation and CRL retrieval.
|
||||
* xref:vault/authentication.adoc#vault.authentication.kubernetes[Kubernetes authentication].
|
||||
* RoleId/SecretId unwrapping for xref:vault/authentication.adoc#vault.authentication.approle[AppRole authentication].
|
||||
* Spring Security integration with transit secrets engine-based `BytesKeyGenerator` and `BytesEncryptor`.
|
||||
|
||||
[[new-features.1-1-0]]
|
||||
== What's new in Spring Vault 1.1.0
|
||||
|
||||
* AWS IAM authentication.
|
||||
* Configuration of encryption/decryption versions for transit keys.
|
||||
* Pull mode for AppRole authentication.
|
||||
* Transit batch encrypt and decrypt support.
|
||||
* TTL-based generic secret rotation.
|
||||
|
||||
[[new-features.1-0-0]]
|
||||
== What's new in Spring Vault 1.0
|
||||
|
||||
* Initial Vault support.
|
||||
|
||||
@@ -80,127 +80,12 @@ See also:
|
||||
* https://www.vaultproject.io/docs/concepts/tokens.html[Vault Documentation: Tokens]
|
||||
* https://www.vaultproject.io/docs/auth/token.html[Vault Documentation: Using the Token auth backend]
|
||||
|
||||
[[vault.authentication.appid]]
|
||||
== AppId authentication
|
||||
|
||||
NOTE: AppId authentication is deprecated by Vault. Use <<vault.authentication.approle>> instead.
|
||||
|
||||
Vault supports https://www.vaultproject.io/docs/auth/app-id.html[AppId]
|
||||
authentication that consists of two hard to guess tokens. The AppId
|
||||
defaults to `spring.application.name` that is statically configured.
|
||||
The second token is the UserId which is a part determined by the application,
|
||||
usually related to the runtime environment. IP address, Mac address or a
|
||||
Docker container name are good examples. Spring Vault supports
|
||||
IP address, Mac address and static UserId's (e.g. supplied via System properties).
|
||||
The IP and Mac address are represented as Hex-encoded SHA256 hash.
|
||||
|
||||
IP address-based UserId's use the local host's IP address.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
class AppConfig extends AbstractVaultConfiguration {
|
||||
|
||||
// …
|
||||
|
||||
@Override
|
||||
public ClientAuthentication clientAuthentication() {
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()
|
||||
.appId("myapp")
|
||||
.userIdMechanism(new IpAddressUserId())
|
||||
.build();
|
||||
|
||||
return new AppIdAuthentication(options, restOperations());
|
||||
}
|
||||
|
||||
// …
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The corresponding command to generate the IP address UserId from a command line is:
|
||||
|
||||
----
|
||||
$ echo -n 192.168.99.1 | sha256sum
|
||||
----
|
||||
|
||||
NOTE: Including the line break of `echo` leads to a different hash value
|
||||
so make sure to include the `-n` flag.
|
||||
|
||||
Mac address-based UserId's obtain their network device from the
|
||||
localhost-bound device. The configuration also allows specifying
|
||||
a `network-interface` hint to pick the right device. The value of
|
||||
`network-interface` is optional and can be either an interface
|
||||
name or interface index (0-based).
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
class AppConfig extends AbstractVaultConfiguration {
|
||||
|
||||
// …
|
||||
|
||||
@Override
|
||||
public ClientAuthentication clientAuthentication() {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()
|
||||
.appId("myapp")
|
||||
.userIdMechanism(new MacAddressUserId())
|
||||
.build();
|
||||
|
||||
return new AppIdAuthentication(options, restOperations());
|
||||
}
|
||||
|
||||
// …
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The corresponding command to generate the Mac address UserId from a command line is:
|
||||
|
||||
----
|
||||
$ echo -n 0AFEDE1234AC | sha256sum
|
||||
----
|
||||
|
||||
NOTE: The Mac address is specified uppercase and without colons.
|
||||
Including the line break of `echo` leads to a different hash value
|
||||
so make sure to include the `-n` flag.
|
||||
|
||||
=== Custom UserId
|
||||
|
||||
A more advanced approach lets you implementing your own `AppIdUserIdMechanism`.
|
||||
This class must be on your classpath and must implement
|
||||
the `org.springframework.vault.authentication.AppIdUserIdMechanism` interface
|
||||
and the `createUserId` method. Spring Vault will obtain the UserId
|
||||
by calling `createUserId` each time it authenticates using AppId to
|
||||
obtain a token.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
.MyUserIdMechanism.java
|
||||
----
|
||||
public class MyUserIdMechanism implements AppIdUserIdMechanism {
|
||||
|
||||
@Override
|
||||
public String createUserId() {
|
||||
|
||||
String userId = …
|
||||
return userId;
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
See also: https://www.vaultproject.io/docs/auth/app-id.html[Vault Documentation: Using the App ID auth backend]
|
||||
|
||||
[[vault.authentication.approle]]
|
||||
== AppRole authentication
|
||||
|
||||
https://www.vaultproject.io/docs/auth/app-id.html[AppRole] allows machine
|
||||
authentication, like the deprecated (since Vault 0.6.1) <<vault.authentication.appid>>.
|
||||
AppRole authentication consists of two hard to guess (secret) tokens: RoleId and SecretId.
|
||||
authentication. AppRole authentication consists of two hard to guess (secret)
|
||||
tokens: RoleId and SecretId.
|
||||
|
||||
Spring Vault supports AppRole authentication by providing either RoleId only
|
||||
or together with a provided SecretId and fetching RoleId/SecretId from Vault
|
||||
|
||||
@@ -182,7 +182,7 @@ vault.token=00000000-0000-0000-0000-000000000000
|
||||
** Truststore type: `vault.ssl.trust-store-type` (optional, typically `jks`, supports also `pem`)
|
||||
** Enabled SSL/TLS protocols: `vault.ssl.enabled-protocols` (since 2.3.2, optional, protocols separated with comma)
|
||||
** Enabled SSL/TLS cipher suites: `vault.ssl.enabled-cipher-suites` (since 2.3.2, optional, cipher suites separated with comma)
|
||||
* Authentication method: `vault.authentication` (defaults to `TOKEN`, supported authentication methods are: `TOKEN`, `APPID`, `APPROLE`, `AWS_EC2`, `AWS_IAM`, `AZURE`, `CERT`, `CUBBYHOLE`, `KUBERNETES`)
|
||||
* Authentication method: `vault.authentication` (defaults to `TOKEN`, supported authentication methods are: `TOKEN`, `APPROLE`, `AWS_EC2`, `AWS_IAM`, `AZURE`, `CERT`, `CUBBYHOLE`, `KUBERNETES`)
|
||||
|
||||
**Authentication-specific property keys**
|
||||
|
||||
@@ -190,13 +190,6 @@ vault.token=00000000-0000-0000-0000-000000000000
|
||||
|
||||
* Vault Token: `vault.token`
|
||||
|
||||
**<<vault.authentication.appid>>**
|
||||
|
||||
* AppId path: `vault.app-id.app-id-path` (defaults to `app-id`)
|
||||
* AppId: `vault.app-id.app-id`
|
||||
* UserId: `vault.app-id.user-id`. `MAC_ADDRESS` and `IP_ADDRESS` use `MacAddressUserId`, respective `IpAddressUserId` user id mechanisms.
|
||||
Any other value is used with `StaticUserId`.
|
||||
|
||||
**<<vault.authentication.approle>>**
|
||||
|
||||
* AppRole path: `vault.app-role.app-role-path` (defaults to `approle`)
|
||||
|
||||
Reference in New Issue
Block a user