Overview
This feature allows platform administrators to:
- Rotate Cassandra credentials in Hashicorp Vault.
- Roll back to the previous Cassandra credentials in Vault in case of any issues during password rotation.
- Rotate the Cassandra password for one region at a time, so that you can ensure minimal impact on service availability and maintain control over the rotation process.
- Track the start, progress, and completion of the rotation for a single region.
This feature is available in Apigee Hybrid 1.13.1 and later.
Before you begin
Before setting up credential rotation:
- Backup your Cassandra database. This backup is to ensure recovery is possible to pre-rotated credentials.
- Ensure the cluster is in a healthy state (i.e. all Apigee resources are running, no state changes are pending).
Single region setup
-
Create a new
SecretProviderClassKubernetes resource in your Apigee namespace for the new Cassandra credentials. See Storing Cassandra secrets in Hashicorp Vault for a template to use. This allows a Vault role to access secrets within the Kubernetes namespaces. -
Create a new
SecretRotationcustom resource using the following template:# rotation.yaml apiVersion: apigee.cloud.google.com/v1alpha1 kind: SecretRotation metadata: name: ROTATION_PROCESS_NAME namespace: APIGEE_NAMESPACE spec: organizationId: ORG_NAME rotationId: ROTATION_ID timeoutMinutes: 480 # optional. overrides the default (480m == 8hr). # less than or equal to 0 means infinite timeout. precheck: true cassandra: oldSecretProviderClass: OLD_SPC_NAME newSecretProviderClass: NEW_SPC_NAME jobType: ROTATE- ROTATION_PROCESS_NAME: A unique name for the rotation job. You will need to set
metadata.nameto a unique value for the rotation precheck job and again for the rotation job. For examplesr-1-precheckfollowed bysr-1. - ROTATION_ID: Set
spec.rotationIdto a custom identifier, for examplerotation-1-precheck. - NEW_SPC_NAME: Set
spec.cassandra.newSecretProviderClassto the new secret provider class name you created in the previous step. - OLD_SPC_NAME: Set
spec.cassandra.oldSecretProviderClassto the SPC name currently being used by theApigeeDatastore.
- ROTATION_PROCESS_NAME: A unique name for the rotation job. You will need to set
-
Trigger the rotation precheck job by applying the
rotation.yamlfile.kubectl -n APIGEE_NAMESPACE apply -f rotation.yaml
-
Check the job status to verify when the precheck job is complete.
kubectl -n APIGEE_NAMESPACE get job sr-(rotationId)-(rotate|rollback|cleanup)-job
-
Once the rotation precheck job completes, change the value of
metadata.nameand setspec.prechecktofalse. Apply the file again to perform the rotation.kubectl -n APIGEE_NAMESPACE apply -f rotation.yaml
-
After the rotation job completes and you have validated traffic is still flowing correctly, clean up the process with the following two steps:
-
Update the value of
metadata.nameand setspec.cassandra.jobTypetoCLEANUP. -
Trigger the cleanup job by applying the file.
kubectl -n APIGEE_NAMESPACE apply -f rotation.yaml
When the cleanup job is completed, the rotation process is complete.
-
Update the value of
- Backup your Cassandra database. This backup is to ensure recovery is possible to post-rotated credentials.
- Delete the old Cassandra credentials, role, and policy from Vault.
Multi-region setup
The multi-region setup procedures are divided into two sections: setup for the first region and setup for the remaining regions.
- Complete the following steps in the first region before starting the subsequent regions.
-
Create a new
SecretProviderClassKubernetes resource in theAPIGEE_NAMESPACEnamespace for the new Cassandra credentials. See Storing Cassandra secrets in Hashicorp Vault for a template to use. This allows a Vault role to access secrets within the Kubernetes namespaces. -
Create a new
SecretRotationcustom resource using the following template:# rotation.yaml apiVersion: apigee.cloud.google.com/v1alpha1 kind: SecretRotation metadata: name: ROTATION_PROCESS_NAME namespace: APIGEE_NAMESPACE spec: organizationId: ORG_NAME rotationId: ROTATION_ID timeoutMinutes: -1 # this value is required and should not be changed. precheck: true cassandra: oldSecretProviderClass: OLD_SPC_NAME newSecretProviderClass: NEW_SPC_NAME jobType: ROTATE- ROTATION_PROCESS_NAME: A unique name for the rotation job. You will need to set
metadata.nameto a unique value for the rotation precheck job and again for the rotation job. For examplesr-1-precheckfollowed bysr-1. - ROTATION_ID: Set
spec.rotationIdto a custom identifier, for examplerotation-1-precheck. - NEW_SPC_NAME: Set
spec.cassandra.newSecretProviderClassto the new secret provider class name you created in the previous step. - OLD_SPC_NAME: Set
spec.cassandra.oldSecretProviderClassto the SPC name currently being used by theApigeeDatastore.
- ROTATION_PROCESS_NAME: A unique name for the rotation job. You will need to set
-
Trigger the rotation precheck job by applying the
rotation.yamlfile.kubectl -n APIGEE_NAMESPACE apply -f rotation.yaml
-
Check the job status to verify when the precheck job is complete.
kubectl -n APIGEE_NAMESPACE get job sr-(rotationId)-(rotate|rollback|cleanup)-job
-
Once the rotation precheck job completes:
- Change the value of
metadata.name, for example fromsr-1-prechecktosr-1. - Set
spec.prechecktofalseto turn off the precheck and perform the rotation. - Set
spec.rotationIdto a new identifier, for examplerotation-1.
- Change the value of
-
Apply the file again to perform the rotation.
kubectl -n APIGEE_NAMESPACE apply -f rotation.yaml
-
Check the state of the
SecretRotationand wait until it iscomplete.kubectl -n APIGEE_NAMESPACE get sr SR_NAME
-
Create a new
-
In each subsequent region, complete the following steps:
- Create a new
SecretProviderClassKubernetes resource in your Apigee namespace for the new Cassandra credentials. See Storing Cassandra secrets in Hashicorp Vault for a template to use. This should be the same definition as step 1a. - Update your
overrides.yamland setcassandra.auth.secretProviderClassto the match the value ofspec.cassandra.newSecretProviderClassin therotation.yamlfile.cassandra: auth: secretProviderClass: NEW_SPC_NAME - Apply the operator chart:
helm upgrade operator apigee-operator/ \ --namespace APIGEE_NAMESPACE \ --atomic \ -f OVERRIDES_FILE
-
A new
ReplicaSetwill be created. Check that the new controller-manager pods are using the new SPC:export POD=NEW_CONTROLLER_MANAGER_POD_NAME
kubectl -n APIGEE_NAMESPACE get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'The result should match the value you set for
spec.cassandra.newSecretProviderClassinrotation.yaml, for example:kubectl -n apigee get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'my-new-spc - Apply the datastore chart:
helm upgrade datastore apigee-datastore/ \ --namespace APIGEE_NAMESPACE \ --atomic \ -f OVERRIDES_FILE
- The datastore will go into a releasing state. Wait until the datastore has finished releasing and is in the running state.
kubectl -n APIGEE_NAMESPACE get apigeedatastore DATASTORE_NAME
DATASTORE_NAME is
defaultin most installations. - Check that the new datastore pods are using the new SPC:
export POD=NEW_DATASTORE_POD_NAME
kubectl -n APIGEE_NAMESPACE get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'The result should match the value you set for
spec.cassandra.newSecretProviderClassinrotation.yaml, for example:kubectl -n apigee get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'my-new-spc - Wait until the organization and environments are done releasing and have returned to the running state.
kubectl -n APIGEE_NAMESPACE get apigeeorg ORG_NAME
kubectl -n APIGEE_NAMESPACE get apigeeenv ENV_NAME - Check that the new MART, runtime, and synchronizer pods are using the new SPC:
export POD=NEW_MART_POD_NAME
kubectl -n APIGEE_NAMESPACE get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'export POD=NEW_RUNTIME_POD_NAMEkubectl -n APIGEE_NAMESPACE get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'export POD=NEW_SYNCHRONIZER_POD_NAMEkubectl -n APIGEE_NAMESPACE get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'The result should match the value you set for
spec.cassandra.newSecretProviderClassinrotation.yaml, for example:kubectl -n apigee get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'my-new-spc
- Create a new
-
After completing the steps in every region and validate traffic is still flowing correctly, clean up the process in the first region with the following two steps:
-
In the first region, update the value of
metadata.nameand setspec.cassandra.jobTypetoCLEANUP. -
Trigger the cleanup job by applying the file.
kubectl -n APIGEE_NAMESPACE apply -f rotation.yaml
- Check the job status and watch the job logs to verify when the cleanup job is complete.
When the cleanup job is completed, the rotation process is complete.
-
In the first region, update the value of
- Backup your Cassandra database. This backup is to ensure recovery is possible to post-rotated credentials.
- Delete the old Cassandra credentials, role, and policy from Vault.