Remove deprecated code.

Removal of AppId, GcpIam authentication and deprecated methods.

Closes #904
This commit is contained in:
Mark Paluch
2025-02-18 15:33:27 +01:00
parent e4b2fd1eb4
commit 5d138a105e
28 changed files with 4 additions and 2152 deletions

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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.

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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());

View File

@@ -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.
*/

View File

@@ -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.

View File

@@ -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)},

View File

@@ -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;
});
}
}

View File

@@ -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());
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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());
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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]"));
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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]

View File

@@ -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.

View File

@@ -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

View File

@@ -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`)