11package io .scalecube .config .vault ;
22
3- import static java .util .Objects .requireNonNull ;
4-
53import com .bettercloud .vault .EnvironmentLoader ;
6- import com .bettercloud .vault .SslConfig ;
74import com .bettercloud .vault .Vault ;
85import com .bettercloud .vault .VaultConfig ;
96import com .bettercloud .vault .VaultException ;
1512import io .scalecube .config .utils .ThrowableUtil ;
1613import java .time .Duration ;
1714import java .util .Map ;
15+ import java .util .Objects ;
1816import java .util .concurrent .Executors ;
1917import java .util .concurrent .ThreadFactory ;
2018import java .util .concurrent .TimeUnit ;
2119import java .util .function .Function ;
20+ import java .util .function .UnaryOperator ;
2221import java .util .stream .Collectors ;
2322import org .slf4j .Logger ;
2423import 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}
0 commit comments