Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions spring-cloud-vault-config/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,44 @@
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.unboundid</groupId>
<artifactId>unboundid-ldapsdk</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp-tls</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.20.4</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>vault</artifactId>
<version>1.20.4</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicReference;

import org.springframework.vault.authentication.UsernamePasswordAuthentication;
import org.springframework.vault.authentication.UsernamePasswordAuthenticationOptions;
import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
Expand Down Expand Up @@ -114,7 +116,11 @@ ClientAuthentication createClientAuthentication() {
case GCP_IAM -> gcpIamAuthentication(this.vaultProperties);
case GITHUB -> gitHubAuthentication(this.vaultProperties);
case KUBERNETES -> kubernetesAuthentication(this.vaultProperties);
case LDAP -> ldapAuthentication(this.vaultProperties);
case OKTA -> oktaAuthentication(this.vaultProperties);
case PCF -> pcfAuthentication(this.vaultProperties);
case RADIUS -> radiusAuthentication(this.vaultProperties);
case USERPASS -> userpassAuthentication(this.vaultProperties);
case TOKEN -> tokenAuthentication(this.vaultProperties);
default -> throw new UnsupportedOperationException(
String.format("Client authentication %s not supported", this.vaultProperties.getAuthentication()));
Expand Down Expand Up @@ -354,6 +360,39 @@ private ClientAuthentication kubernetesAuthentication(VaultProperties vaultPrope
return new KubernetesAuthentication(options, this.restOperations);
}

private ClientAuthentication ldapAuthentication(VaultProperties vaultProperties) {

VaultProperties.UsernamePasswordProperties ldap = vaultProperties.getLdap();

Assert.hasText(ldap.getUsername(), "Username (spring.cloud.vault.ldap.username) must not be empty");
Assert.hasText(ldap.getPassword().toString(), "Password (spring.cloud.vault.ldap.password) must not be empty");

UsernamePasswordAuthenticationOptions options = UsernamePasswordAuthenticationOptions.builder()
.path(ldap.getPath())
.username(ldap.getUsername())
.password(ldap.getPassword())
.build();

return new UsernamePasswordAuthentication(options, this.restOperations);
}

private ClientAuthentication oktaAuthentication(VaultProperties vaultProperties) {

VaultProperties.UsernamePasswordProperties okta = vaultProperties.getOkta();

Assert.hasText(okta.getUsername(), "Username (spring.cloud.vault.okta.username) must not be empty");
Assert.hasText(okta.getPassword().toString(), "Password (spring.cloud.vault.okta.password) must not be empty");

UsernamePasswordAuthenticationOptions options = UsernamePasswordAuthenticationOptions.builder()
.path(okta.getPath())
.username(okta.getUsername())
.password(okta.getPassword())
.totp(okta.getTotp())
.build();

return new UsernamePasswordAuthentication(options, this.restOperations);
}

private ClientAuthentication pcfAuthentication(VaultProperties vaultProperties) {

VaultProperties.PcfProperties pcfProperties = vaultProperties.getPcf();
Expand All @@ -377,6 +416,40 @@ private ClientAuthentication pcfAuthentication(VaultProperties vaultProperties)
return new PcfAuthentication(builder.build(), this.restOperations);
}

private ClientAuthentication radiusAuthentication(VaultProperties vaultProperties) {

VaultProperties.UsernamePasswordProperties radius = vaultProperties.getRadius();

Assert.hasText(radius.getUsername(), "Username (spring.cloud.vault.radius.username) must not be empty");
Assert.hasText(radius.getPassword().toString(),
"Password (spring.cloud.vault.radius.password) must not be empty");

UsernamePasswordAuthenticationOptions options = UsernamePasswordAuthenticationOptions.builder()
.path(radius.getPath())
.username(radius.getUsername())
.password(radius.getPassword())
.build();

return new UsernamePasswordAuthentication(options, this.restOperations);
}

private ClientAuthentication userpassAuthentication(VaultProperties vaultProperties) {

VaultProperties.UsernamePasswordProperties userpass = vaultProperties.getUserpass();

Assert.hasText(userpass.getUsername(), "Username (spring.cloud.vault.userpass.username) must not be empty");
Assert.hasText(userpass.getPassword().toString(),
"Password (spring.cloud.vault.userpass.password) must not be empty");

UsernamePasswordAuthenticationOptions options = UsernamePasswordAuthenticationOptions.builder()
.path(userpass.getPath())
.username(userpass.getUsername())
.password(userpass.getPassword())
.build();

return new UsernamePasswordAuthentication(options, this.restOperations);
}

private ClientAuthentication certificateAuthentication(VaultProperties vaultProperties) {

ClientCertificateAuthenticationOptionsBuilder builder = ClientCertificateAuthenticationOptions.builder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,16 @@ public class VaultProperties implements EnvironmentAware {

private KubernetesProperties kubernetes = new KubernetesProperties();

private UsernamePasswordProperties ldap = new UsernamePasswordProperties("ldap");

private UsernamePasswordProperties okta = new UsernamePasswordProperties("okta");

private PcfProperties pcf = new PcfProperties();

private UsernamePasswordProperties radius = new UsernamePasswordProperties("radius");

private UsernamePasswordProperties userpass = new UsernamePasswordProperties("userpass");

private Ssl ssl = new Ssl();

private Config config = new Config();
Expand Down Expand Up @@ -329,6 +337,22 @@ public void setKubernetes(KubernetesProperties kubernetes) {
this.kubernetes = kubernetes;
}

public UsernamePasswordProperties getLdap() {
return ldap;
}

public void setLdap(UsernamePasswordProperties ldap) {
this.ldap = ldap;
}

public UsernamePasswordProperties getOkta() {
return okta;
}

public void setOkta(UsernamePasswordProperties okta) {
this.okta = okta;
}

public PcfProperties getPcf() {
return this.pcf;
}
Expand All @@ -337,6 +361,22 @@ public void setPcf(PcfProperties pcf) {
this.pcf = pcf;
}

public UsernamePasswordProperties getRadius() {
return radius;
}

public void setRadius(UsernamePasswordProperties radius) {
this.radius = radius;
}

public UsernamePasswordProperties getUserpass() {
return userpass;
}

public void setUserpass(UsernamePasswordProperties userpass) {
this.userpass = userpass;
}

public Ssl getSsl() {
return this.ssl;
}
Expand Down Expand Up @@ -382,7 +422,8 @@ public void setAuthentication(AuthenticationMethod authentication) {
*/
public enum AuthenticationMethod {

APPROLE, AWS_EC2, AWS_IAM, AZURE_MSI, CERT, CUBBYHOLE, GCP_GCE, GCP_IAM, GITHUB, KUBERNETES, NONE, PCF, TOKEN;
APPROLE, AWS_EC2, AWS_IAM, AZURE_MSI, CERT, CUBBYHOLE, GCP_GCE, GCP_IAM, GITHUB, KUBERNETES, LDAP, NONE, OKTA,
PCF, RADIUS, USERPASS, TOKEN;

}

Expand Down Expand Up @@ -1260,6 +1301,72 @@ public void setEnabledCipherSuites(List<String> enabledCipherSuites) {

}

/**
* Common properties for userpass, LDAP, Okta, and RADIUS authentications.
*/
static class UsernamePasswordProperties {

/**
* Mount path of the username/password authentication backend.
*/
private String path;

/**
* Username for the user
*/
private String username;

/**
* Password for the user
*/
private CharSequence password;

/**
* TOTP for OKTA multifactor authentication
*/
private CharSequence totp;

/**
* @param defaultPath the default path
*/
protected UsernamePasswordProperties(String defaultPath) {
this.path = defaultPath;
}

public String getPath() {
return path;
}

public void setPath(String path) {
this.path = path;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public CharSequence getPassword() {
return password;
}

public void setPassword(CharSequence password) {
this.password = password;
}

public CharSequence getTotp() {
return totp;
}

public void setTotp(CharSequence totp) {
this.totp = totp;
}

}

/**
* Property source properties.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.nio.file.StandardOpenOption;

import org.junit.jupiter.api.Test;
import org.springframework.vault.authentication.UsernamePasswordAuthentication;
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.regions.Region;

Expand Down Expand Up @@ -206,6 +207,43 @@ public void shouldSupportGitHubAuthentication() {
assertThat(clientAuthentication).isInstanceOf(GitHubAuthentication.class);
}

@Test
public void shouldSupportLdapAuthentication() {

VaultProperties properties = new VaultProperties();
properties.setAuthentication(VaultProperties.AuthenticationMethod.LDAP);
VaultProperties.UsernamePasswordProperties usernamePasswordProperties = new VaultProperties.UsernamePasswordProperties(
"ldap");
usernamePasswordProperties.setUsername("username");
usernamePasswordProperties.setPassword("password");
properties.setLdap(usernamePasswordProperties);

ClientAuthentication clientAuthentication = new ClientAuthenticationFactory(properties, new RestTemplate(),
new RestTemplate())
.createClientAuthentication();

assertThat(clientAuthentication).isInstanceOf(UsernamePasswordAuthentication.class);
}

@Test
public void shouldSupportOktaAuthentication() {

VaultProperties properties = new VaultProperties();
properties.setAuthentication(VaultProperties.AuthenticationMethod.OKTA);
VaultProperties.UsernamePasswordProperties usernamePasswordProperties = new VaultProperties.UsernamePasswordProperties(
"okta");
usernamePasswordProperties.setUsername("username");
usernamePasswordProperties.setPassword("password");
usernamePasswordProperties.setTotp("totp");
properties.setOkta(usernamePasswordProperties);

ClientAuthentication clientAuthentication = new ClientAuthenticationFactory(properties, new RestTemplate(),
new RestTemplate())
.createClientAuthentication();

assertThat(clientAuthentication).isInstanceOf(UsernamePasswordAuthentication.class);
}

@Test
public void shouldSupportPcfAuthentication() {

Expand All @@ -222,6 +260,42 @@ public void shouldSupportPcfAuthentication() {
assertThat(clientAuthentication).isInstanceOf(PcfAuthentication.class);
}

@Test
public void shouldSupportRadiusAuthentication() {

VaultProperties properties = new VaultProperties();
properties.setAuthentication(VaultProperties.AuthenticationMethod.RADIUS);
VaultProperties.UsernamePasswordProperties usernamePasswordProperties = new VaultProperties.UsernamePasswordProperties(
"radius");
usernamePasswordProperties.setUsername("username");
usernamePasswordProperties.setPassword("password");
properties.setRadius(usernamePasswordProperties);

ClientAuthentication clientAuthentication = new ClientAuthenticationFactory(properties, new RestTemplate(),
new RestTemplate())
.createClientAuthentication();

assertThat(clientAuthentication).isInstanceOf(UsernamePasswordAuthentication.class);
}

@Test
public void shouldSupportUserpassAuthentication() {

VaultProperties properties = new VaultProperties();
properties.setAuthentication(VaultProperties.AuthenticationMethod.USERPASS);
VaultProperties.UsernamePasswordProperties usernamePasswordProperties = new VaultProperties.UsernamePasswordProperties(
"userpass");
usernamePasswordProperties.setUsername("username");
usernamePasswordProperties.setPassword("password");
properties.setUserpass(usernamePasswordProperties);

ClientAuthentication clientAuthentication = new ClientAuthenticationFactory(properties, new RestTemplate(),
new RestTemplate())
.createClientAuthentication();

assertThat(clientAuthentication).isInstanceOf(UsernamePasswordAuthentication.class);
}

@Test
public void shouldSupportSslCertificateAuthentication() {

Expand Down
Loading
Loading