spring-projects / spring-vault

Provides familiar Spring abstractions for HashiCorp Vault
https://spring.io/projects/spring-vault
Apache License 2.0
280 stars 184 forks source link

Dynamically Configure Cipher Suites for Vault Communication #859

Closed venkateshdomakonda closed 1 month ago

venkateshdomakonda commented 6 months ago

Hello,

I am using the CryptoConfiguration class, which extends AbstractVaultConfiguration, to provide a custom SslConfiguration for Vault communication. This configuration is currently set statically.

`

@Configuration
public class CryptoConfiguration extends AbstractVaultConfiguration {

  private static final String ROOT_CERT = "/tmp/cacertbundle.jks";

  @Override
  public ClientAuthentication clientAuthentication() {
    KubernetesAuthenticationOptions options = KubernetesAuthenticationOptions.builder().role("key-role")
        .build();
    return new KubernetesAuthentication(options, restOperations());
  }

  @Override
  public VaultEndpoint vaultEndpoint() {
    VaultEndpoint endpoint = VaultEndpoint.create(key-management, 8200);
    endpoint.setScheme("https");
    return endpoint;
  }

  @Override
  @Bean
  public ClientFactoryWrapper clientHttpRequestFactoryWrapper() {
    char[] password = {};
    SslConfiguration sslConfig = SslConfiguration.forTrustStore(new FileSystemResource(ROOT_CERT),
        password);
    return new ClientFactoryWrapper(ClientHttpRequestFactoryFactory.create(clientOptions(), sslConfig));
  }

}

`

`

public class CryptoAgent implements CryptoAgentInterface {
private static final String CRYPTO_KEY_NAME = "cm-key-v1";
private static final Retrier retrier = new Retrier();
private VaultTemplate vaultTemplate;
private VaultTransitOperations transitOps;
private AnnotationConfigApplicationContext ctx;

/**
 * CryptoConfiguration is used as configuration for vault agent.
 */
public CryptoAgent() {
    ctx = new AnnotationConfigApplicationContext();
    ctx.register(CryptoConfiguration.class);
    ctx.refresh();
    this.vaultTemplate = ctx.getBean(VaultTemplate.class);
    this.transitOps = vaultTemplate.opsForTransit();
}

@Override
public String encrypt(String input) {
    return retrier.runtimeRetry("encrypt", () -> {
        return transitOps.encrypt(CRYPTO_KEY_NAME, Plaintext.of(input)).getCiphertext();
    }, "Failed to encrypt");
}

@Override
public String decrypt(String input) {
    return retrier.runtimeRetry("decrypt", () -> {
        return transitOps.decrypt(CRYPTO_KEY_NAME, Ciphertext.of(input)).asString();
    }, "Failed to decrypt");
}

}

`

Could you please advise on the recommended approach to achieve dynamic cipher suite configuration(using SslConfiguration) for Vault communication within the current setup ?

mp911de commented 5 months ago

VaultTemplate is bound to RestOperations. You can implement your own ClientHttpRequestFactory that applies different client settings/clients per request/endpoint.

SSL settings are propagated into the HTTP client so there is no on-demand reconfiguration.

venkateshdomakonda commented 5 months ago

Hello @mp911de

I am considering to recreate the ClientFactoryWrapper by creating a new SslConfiguration with the desired cipher suites during runtime, particularly when there's a need to update cipher suites, which may occur infrequently, perhaps once or twice during the application's lifespan.

May I know your opinion on whether this approach seems viable and if there are any potential concerns or considerations I should be aware of ?

Regards, Venkat

mp911de commented 5 months ago

Occasional updates are fine. Either a proxied ClientHttpRequestFactory or a custom ClientHttpRequestFactory implementation that delegates to the currently active ClientHttpRequestFactory (holding the configured client) ist the best approach as VaultTemplate operates on top of RestTemplate. ClientFactoryWrapper is a Spring Vault-specific type that isn't wired directly into RestTemplate.