Saturday, July 31, 2021

Getting DB Passwords from Vault Secrets for OKE Deployments

OCI allows storing of DB passwords as secrets in the vault. These secrets could be retreived using various SDKs, CLI and etc. This post shows how DB password could be retreived from a vault for JDBC Connection pools when a java application is deployed in OKE.
1. In order to retreivew the secrets from vault the user making the request must be authenticated. Instance principal is used to avoid using a password based authentication for this. OCI allows dynamic group be created based compartment, instance id, tag and tag value. As a first step create a dynamic group specifying the compartment where OKE worker node resides and some qualifying tags. The dynamic group is called "test dynamic group".

Compartment is used instead of instance ID in the dynamic group creation. This is due the fact that new worker nodes could be created and old ones destroyed as part of the life cycle of the OKE cluster. Tag values have been used to further reduce the number of instances that qualify for the dynamic group. All worker nodes would have "oke" as the created-by tag value. So this tag could be used to distinguish between OKE cluster service created instances vs other compute instnaces. Further reduction could be made based on project, enviornment and etc.
2. Create the secrets in the vault. Secrets could be created with a prefix which would allow writing of policy capturing only the secrets with the specified prefix text. Below two secrets have been created both with prefix "acme_test_prod".

3. Write a policy allowing dynamic group to access the secret bundles. Use the vault id and prefix of the secret to restrict the dynamic group to specific set of secrets and vaults. Below policy would allow test_dynamic_group to get all the secret bundles with names begining with "acme_test_prod" in the specified vault id.

Policy is written for secret bundles as that's what the java API expect. If this is done for OCI CLI then policy could be written for secrets instead of secret bundles. Java API access fails when policy only allow access to secrets instead of secret bundles.



4. Final step set is to write the java code that would be deployed as part of the application into OKE cluster. Download the java SDK from the link here. Below is an example java code that uses instance principal provider to create a secrets client that could be used to retreive the secrets from the vault.
final InstancePrincipalsAuthenticationDetailsProvider provider;
        try {
            provider = InstancePrincipalsAuthenticationDetailsProvider.builder().build();
        } catch (Exception e) {
            
            throw e;
        }
    
        SecretsClient secretsDpClient  = new SecretsClient(provider);
                
        GetSecretBundleByNameResponse getSecretBundleByNameResponse = secretsDpClient.getSecretBundleByName(GetSecretBundleByNameRequest.builder()
        .secretName("acme_test_prod_schema1").vaultId("ocid1.vault.oc1.vault id here...").build());
        
        Base64SecretBundleContentDetails details = (Base64SecretBundleContentDetails) getSecretBundleByNameResponse.getSecretBundle().getSecretBundleContent();
        byte[] content = Base64.getDecoder().decode(details.getContent());
        //System.out.println("Password : "new String(content));
        
        PoolDataSource ds = PoolDataSourceFactory.getPoolDataSource();
        ds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
        ds.setURL("jdbc:oracle:thin:@test");
        ds.setUser("asanga");
        ds.setPassword(new String(content));