Skip to content

Commit afb1ab2

Browse files
authored
Merge pull request #135 from scalecube/develop
New release
2 parents 48a660f + 5a03d0e commit afb1ab2

File tree

13 files changed

+611
-345
lines changed

13 files changed

+611
-345
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@
1515

1616
# IntelliJ IDEA project files and directories
1717
*.iml
18+
19+
**/pom.xml.releaseBackup
20+
/release.properties

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,8 @@ deploy:
2121
- "./src/main/scripts/cd/release.sh"
2222
on:
2323
branch: master
24+
- provider: script
25+
script:
26+
- "./src/main/scripts/cd/release.sh"
27+
on:
28+
tags: true

config-vault/pom.xml

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010

1111
<artifactId>config-vault</artifactId>
1212

13+
<properties>
14+
<log4j.version>2.5</log4j.version>
15+
<vault-java-driver.version>5.0.0</vault-java-driver.version>
16+
<org.testcontainers.vault.version>1.12.1</org.testcontainers.vault.version>
17+
</properties>
18+
1319
<dependencies>
1420
<dependency>
1521
<groupId>io.scalecube</groupId>
@@ -19,12 +25,24 @@
1925
<dependency>
2026
<groupId>com.bettercloud</groupId>
2127
<artifactId>vault-java-driver</artifactId>
22-
<version>3.1.0</version>
28+
<version>${vault-java-driver.version}</version>
2329
</dependency>
2430
<dependency>
2531
<groupId>org.testcontainers</groupId>
2632
<artifactId>vault</artifactId>
27-
<version>1.6.0</version>
33+
<version>${org.testcontainers.vault.version}</version>
34+
<scope>test</scope>
35+
</dependency>
36+
<dependency>
37+
<groupId>org.apache.logging.log4j</groupId>
38+
<artifactId>log4j-slf4j-impl</artifactId>
39+
<version>${log4j.version}</version>
40+
<scope>test</scope>
41+
</dependency>
42+
<dependency>
43+
<groupId>org.apache.logging.log4j</groupId>
44+
<artifactId>log4j-core</artifactId>
45+
<version>${log4j.version}</version>
2846
<scope>test</scope>
2947
</dependency>
3048
</dependencies>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package io.scalecube.config.vault;
2+
3+
import com.bettercloud.vault.EnvironmentLoader;
4+
import com.bettercloud.vault.Vault;
5+
import com.bettercloud.vault.VaultConfig;
6+
import io.scalecube.config.utils.ThrowableUtil;
7+
import java.nio.file.Files;
8+
import java.nio.file.Paths;
9+
import java.util.Objects;
10+
import java.util.stream.Collectors;
11+
12+
public class KubernetesVaultTokenSupplier implements VaultTokenSupplier {
13+
14+
private static final String VAULT_ROLE = "VAULT_ROLE";
15+
private static final String SERVICE_ACCOUNT_TOKEN_PATH =
16+
"/var/run/secrets/kubernetes.io/serviceaccount/token";
17+
18+
@Override
19+
public String getToken(EnvironmentLoader environmentLoader, VaultConfig config) {
20+
String role = Objects.requireNonNull(environmentLoader.loadVariable(VAULT_ROLE), "vault role");
21+
try {
22+
String jwt = Files.lines(Paths.get(SERVICE_ACCOUNT_TOKEN_PATH)).collect(Collectors.joining());
23+
return Objects.requireNonNull(
24+
new Vault(config).auth().loginByKubernetes(role, jwt).getAuthClientToken(),
25+
"vault token");
26+
} catch (Exception e) {
27+
throw ThrowableUtil.propagate(e);
28+
}
29+
}
30+
}
Lines changed: 78 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package io.scalecube.config.vault;
22

3-
import static java.util.Objects.requireNonNull;
4-
53
import com.bettercloud.vault.EnvironmentLoader;
6-
import com.bettercloud.vault.SslConfig;
74
import com.bettercloud.vault.Vault;
85
import com.bettercloud.vault.VaultConfig;
96
import com.bettercloud.vault.VaultException;
@@ -15,10 +12,12 @@
1512
import io.scalecube.config.utils.ThrowableUtil;
1613
import java.time.Duration;
1714
import java.util.Map;
15+
import java.util.Objects;
1816
import java.util.concurrent.Executors;
1917
import java.util.concurrent.ThreadFactory;
2018
import java.util.concurrent.TimeUnit;
2119
import java.util.function.Function;
20+
import java.util.function.UnaryOperator;
2221
import java.util.stream.Collectors;
2322
import org.slf4j.Logger;
2423
import org.slf4j.LoggerFactory;
@@ -32,47 +31,69 @@ public class VaultConfigSource implements ConfigSource {
3231

3332
private static final Logger LOGGER = LoggerFactory.getLogger(VaultConfigSource.class);
3433

34+
private static final ThreadFactory THREAD_FACTORY =
35+
r -> {
36+
Thread thread = new Thread(r);
37+
thread.setDaemon(true);
38+
thread.setName(VaultConfigSource.class.getSimpleName().toLowerCase() + "-token-renewer");
39+
return thread;
40+
};
41+
42+
private static final String VAULT_SECRETS_PATH = "VAULT_SECRETS_PATH";
43+
private static final String VAULT_RENEW_PERIOD = "VAULT_RENEW_PERIOD";
44+
3545
private final Vault vault;
3646
private final String secretsPath;
37-
private final Duration renewEvery;
3847

3948
/**
4049
* Create a new {@link VaultConfigSource} with the given {@link Builder}.
4150
*
4251
* @param builder configuration to create vault access with.
4352
*/
44-
private VaultConfigSource(Builder builder) {
45-
this.secretsPath = builder.secretsPath();
46-
this.renewEvery = builder.renewEvery;
47-
vault = new Vault(builder.config);
53+
private VaultConfigSource(Builder builder) throws VaultException {
54+
EnvironmentLoader environmentLoader =
55+
builder.environmentLoader != null ? builder.environmentLoader : new EnvironmentLoader();
56+
57+
secretsPath =
58+
Objects.requireNonNull(
59+
builder.secretsPath != null
60+
? builder.secretsPath
61+
: environmentLoader.loadVariable(VAULT_SECRETS_PATH),
62+
"Missing secretsPath");
63+
64+
VaultConfig vaultConfig =
65+
builder.config.apply(new VaultConfig()).environmentLoader(environmentLoader).build();
66+
String token = builder.tokenSupplier.getToken(environmentLoader, vaultConfig);
67+
vault = new Vault(vaultConfig.token(token));
68+
69+
Duration renewEvery =
70+
builder.renewEvery != null
71+
? builder.renewEvery
72+
: duration(environmentLoader.loadVariable(VAULT_RENEW_PERIOD));
4873

4974
if (renewEvery != null) {
50-
long initialDelay = renewEvery.toMillis();
51-
long period = renewEvery.toMillis();
52-
TimeUnit unit = TimeUnit.MILLISECONDS;
53-
ThreadFactory factory =
54-
r -> {
55-
Thread thread = new Thread(r);
56-
thread.setDaemon(true);
57-
thread.setName(VaultConfigSource.class.getSimpleName() + " token renewer");
58-
return thread;
59-
};
60-
Executors.newScheduledThreadPool(1, factory)
61-
.scheduleAtFixedRate(
62-
() -> {
63-
try {
64-
vault.auth().renewSelf();
65-
LOGGER.info("renew token success");
66-
} catch (VaultException vaultException) {
67-
LOGGER.error("failed to renew token", vaultException);
68-
}
69-
},
70-
initialDelay,
71-
period,
72-
unit);
75+
scheduleVaultTokenRenew(renewEvery);
7376
}
7477
}
7578

79+
private void scheduleVaultTokenRenew(Duration renewEvery) {
80+
long initialDelay = renewEvery.toMillis();
81+
long period = renewEvery.toMillis();
82+
Executors.newSingleThreadScheduledExecutor(THREAD_FACTORY)
83+
.scheduleAtFixedRate(
84+
() -> {
85+
try {
86+
this.vault.auth().renewSelf();
87+
LOGGER.info("renew token success");
88+
} catch (VaultException vaultException) {
89+
LOGGER.error("failed to renew token", vaultException);
90+
}
91+
},
92+
initialDelay,
93+
period,
94+
TimeUnit.MILLISECONDS);
95+
}
96+
7697
private void checkVaultStatus() throws VaultException {
7798
if (vault.seal().sealStatus().getSealed()) {
7899
throw new VaultException("Vault is sealed");
@@ -83,6 +104,10 @@ private void checkVaultStatus() throws VaultException {
83104
}
84105
}
85106

107+
private Duration duration(String duration) {
108+
return duration != null ? Duration.parse(duration) : null;
109+
}
110+
86111
@Override
87112
public Map<String, ConfigProperty> loadConfig() {
88113
try {
@@ -119,42 +144,38 @@ public static Builder builder() {
119144
* @param environmentLoader an {@link EnvironmentLoader}
120145
*/
121146
static Builder builder(EnvironmentLoader environmentLoader) {
122-
return builder(
123-
environmentLoader.loadVariable("VAULT_ADDR"),
124-
environmentLoader.loadVariable("VAULT_TOKEN"),
125-
environmentLoader.loadVariable("VAULT_SECRETS_PATH"));
126-
}
127-
128-
public static Builder builder(String address, String token, String secretsPath) {
129-
return new Builder(address, token, secretsPath);
147+
return new Builder(environmentLoader);
130148
}
131149

132150
public static final class Builder {
133151

134-
final VaultConfig config = new VaultConfig();
135-
private final String secretsPath;
136-
private Duration renewEvery = null;
152+
private Function<VaultConfig, VaultConfig> config = Function.identity();
153+
private VaultTokenSupplier tokenSupplier = new VaultTokenSupplier() {};
154+
private EnvironmentLoader environmentLoader;
155+
private String secretsPath;
156+
private Duration renewEvery;
137157

138-
Builder(String address, String token, String secretsPath) {
139-
config
140-
.address(requireNonNull(address, "Missing address"))
141-
.token(requireNonNull(token, "Missing token"))
142-
.sslConfig(new SslConfig());
143-
this.secretsPath = requireNonNull(secretsPath, "Missing secretsPath");
158+
private Builder(EnvironmentLoader environmentLoader) {
159+
this.environmentLoader = environmentLoader;
144160
}
145161

146-
public Builder connectTimeout(int connectTimeout) {
147-
config.openTimeout(connectTimeout);
162+
public Builder renewEvery(Duration duration) {
163+
renewEvery = duration;
148164
return this;
149165
}
150166

151-
public Builder readTimeout(int readTimeout) {
152-
config.readTimeout(readTimeout);
167+
public Builder secretsPath(String secretsPath) {
168+
this.secretsPath = secretsPath;
153169
return this;
154170
}
155171

156-
public Builder renewEvery(Duration duration) {
157-
renewEvery = duration;
172+
public Builder config(UnaryOperator<VaultConfig> config) {
173+
this.config = this.config.andThen(config);
174+
return this;
175+
}
176+
177+
public Builder tokenSupplier(VaultTokenSupplier supplier) {
178+
this.tokenSupplier = supplier;
158179
return this;
159180
}
160181

@@ -165,17 +186,11 @@ public Builder renewEvery(Duration duration) {
165186
*/
166187
public VaultConfigSource build() {
167188
try {
168-
this.config.build();
169189
return new VaultConfigSource(this);
170-
} catch (VaultException propogateException) {
171-
LOGGER.error(
172-
"Unable to build " + VaultConfigSource.class.getSimpleName(), propogateException);
173-
throw ThrowableUtil.propagate(propogateException);
190+
} catch (VaultException e) {
191+
LOGGER.error("Unable to build " + VaultConfigSource.class.getSimpleName(), e);
192+
throw ThrowableUtil.propagate(e);
174193
}
175194
}
176-
177-
public String secretsPath() {
178-
return secretsPath;
179-
}
180195
}
181196
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.scalecube.config.vault;
2+
3+
import com.bettercloud.vault.EnvironmentLoader;
4+
import com.bettercloud.vault.VaultConfig;
5+
import java.util.Objects;
6+
7+
public interface VaultTokenSupplier {
8+
9+
default String getToken(EnvironmentLoader environmentLoader, VaultConfig config) {
10+
return Objects.requireNonNull(config.getToken(), "vault token");
11+
}
12+
}

0 commit comments

Comments
 (0)