spring-vault icon indicating copy to clipboard operation
spring-vault copied to clipboard

Dynamically Configure Cipher Suites for Vault Communication

Open venkateshdomakonda opened this issue 1 year ago • 3 comments

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 ?

venkateshdomakonda avatar Mar 12 '24 14:03 venkateshdomakonda

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.

mp911de avatar Mar 12 '24 14:03 mp911de

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

venkateshdomakonda avatar Mar 18 '24 08:03 venkateshdomakonda

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.

mp911de avatar Mar 18 '24 08:03 mp911de