README
¶
ArgoCD plugin - Key Protect secrets
ArgoCD plugin to generate secrets from values stored in Key Protect.
Why?
A common issue when doing GitOps is how to handle sensitive information that should not be stored in the Git repository (e.g. passwords, keys, etc). There are two different approaches to how to handle this issue:
- Inject the values from another source into kubernetes Secret(s) at deployment time
- Inject the values from another source in the pod at startup time via an InitContainer
The "other source" in this case would be a key management system that centralizes the storage and management of sensitive information.
This repository addresses the first approach listed above by providing a plugin to ArgoCD to pull the sensitive values from Key Protect at deployment time and generate the appropriate kubernetes Secret(s).
How it works
The plugin takes a directory containing template secret CR(s) as input, looks up the values of any sensitive information for the provided keyIds from Key Protect, and generates a kubernetes Secret for each input template.
Secret template
The input to the plugin is a directory that contains one or more "secret templates". In this case the "secret template" provides the structure of the desired template with placeholders for the values that will be pulled from the key management system. The following provides the structure of the template:
apiVersion: keymanagement.ibm/v1
kind: SecretTemplate
metadata:
name: mysecret
annotations:
key-manager: key-protect
key-protect/instanceId: instance-id
key-protect/region: us-east
spec:
labels: {}
annotations: {}
values:
- name: url
value: https://ibm.com
- name: username
b64value: dGVhbS1jYXA=
- name: password
keyId: 36397b07-d98d-4c0b-bd7a-d6c290163684
-
The
metadata.annotations
value is optional.key-manager
- the only value supported currently iskey-protect
key-protect/instanceId
- the instance id of the key protect instance. If not provided then theinstance-id
value from thekey-protect-access
secret will be used.key-protect/region
- the region where the key protect instance has been provisioned. If not provided then theregion
value from thekey-protect-access
secret will be used.
-
The
metadata.name
value given will be used as the name for the Secret that will be generated. -
The information in
spec.labels
andspec.annotations
will be copied over as thelabels
andannotations
in the Secret that is generated -
The
spec.values
section contains the information that should be provided in thedata
section of the generated Secret. There are three prossible ways the values can be provided:value
- the actual value can be provided directly as clear text. This would be appropriate for information that is not sensitive but is required in the secretb64value
- a base64 encoded value can be provided to the secret. This can be used for large values that might present formatting issues or for information that is not sensitive but that might be obfuscated a bit (like a username)keyId
- the id (not the name) of the Standard Key that has been stored in Key Protect. The value stored in Key Protect can be anything
Managing keys in Key Protect
Key Protect manages two different types of keys: root keys
and standard keys
. Standard keys
are used to store any
kind of protected information. The Key Protect plugin reads the contents of a standard key, identified by a given key id, and
stores the key value into a secret in the cluster.
The following steps describe how to create a standard key:
-
Open the IBM Cloud console and navigate to the Key Protect service
-
Within Key Protect, select the Manage Keys tab
-
Press the
Add key
button to open the "Add a new key" dialog -
Select the
Import your own key
radio button andStandard key
from the drop down -
Provide a descriptive name for the key and paste the base-64 encoded value of the key into the
Key material
fieldNote: A value can be encoded as base-64 from the terminal with the following command:
echo -n "{VALUE}" | base64
If you need to encode a larger value, create the value in a file and encode the entire contents of the file with:
cat {file} | base64
-
Click Import key to create the key
-
Copy the value of the ID. This will be used later by the plugin
Configuring an ArgoCD application
Assuming the ArgoCD setup has been completed for the plugin, the flow for ArgoCD would be as follows:
-
Create a directory in your GitOps repository for the secrets
-
Create a SecretTemplate yaml file in the directory for each Secret with the appropriate values
-
In ArgoCD, configure an Application for each secret directory created:
- Provide the standard values for the General, Source, and Destination sections. The
path
in the Source section should refer to the directory containing the SecretTemplates - Select
Plugin
from the dropdown in the section at the bottom - Select
key-protect-secret
for the plugin name
- Provide the standard values for the General, Source, and Destination sections. The
Multiple directories can be defined within the GitOps repository to support whatever level of granularity is desired for managing the secrets. Currently only one Key Protect instance is supported for a single ArgoCD instance.
Setting up ArgoCD
Key Protect credentials
In order to connect with Key Protect you will need three pieces of information:
IBM Cloud API Key
- an API Key that hasReader
andReaderPlus
access to the Key Protect instanceKey Protect region
- the region where the Key Protect instance has been deployedKey Protect instance id
- the GUID of the Key Protect instance where the secrets are stored
The three values can be provided in a secret named key-protect-access
in the same namespace where ArgoCD has been deployed. As shown above,
the region and instance id values can be provided in the SecretTemplate configuration. Additionally, the default API Key will be used
from the cloud-access
secret if the value is not available from the key-protect-access
secret.
Get the instance id for Key Protect
-
Set the target resource group and region for the Key Protect instance.
ibmcloud target -g {RESOURCE_GROUP} -r {REGION}
-
List the available resources and find the name of the Key Protect instance.
ibmcloud resource service-instances
-
List the details for the Key Protect instance. The
Key Protect instance id
is listed asGUID
.ibmcloud resource service-instance {INSTANCE_NAME}
Create the secret with the information needed to access Key Protect
Armed with the information from the previous step, run the following to create a secret:
NAMESPACE="tools"
kubectl create secret generic -n ${NAMESPACE} key-protect-access \
--from-literal=api-key=${API_KEY} \
--from-literal=region=${REGION} \
--from-literal=instance-id=${KP_INSTANCE_ID}
where:
NAMESPACE
should be the namespace where ArgoCD has been deployed
Install the plugin dependencies
In order for the plugin to work, the argocd-repo-server
deployment needs to have access to the command and
the credentials. To do this, the deployment needs to be patched with an InitContainer to install the command and
the environment variables from the secret generated in the previous step.
A script has been provided to simplify this step. To install the dependencies do the following:
-
Log into the cluster from the terminal
-
Clone the repository (if you haven't already)
-
Run the
install-plugin-dependencies.sh
script in thehack
directory. (hack
is a convention of Golang/operator repos. Don't blame us for the name of the folder...)NAMESPACE="tools" ./hack/install-plugin-dependencies.sh ${NAMESPACE} [${NAME}]
where:
NAMESPACE
is the namespace where ArgoCD has been deployedNAME
is the name of the ArgoCD instance. If not provided defaults toargocd
When this script has completed, you should notice several new elements in the ${NAME}-repo-server
deployment:
- A new volume named
key-protect-install
defined in thevolumes
section - A new initContainer named
key-protect-install
- A new volume mount in the main conatiner named
key-protect-install
- Three new environment variables in the
env
section referring to thekey-protect-access
secret
If you'd like to review further, the definition of the patch that has been applied can be found in hack/install-plugin-dependencies-patch.json
Configure the plugin
The last step is to register the plugin with ArgoCD. To do this the argocd-cm
ConfigMap must be updated.
However, if you are using the ArgoCD operator then the argocd-cm
ConfigMap cannot be updated directly. Instead
the ArgoCD CR must be updated with the configuration values.
A script has been provided to patch the ArgoCD CR with the plugin configuration. To configure the plugin, do the following:
-
Log into the cluster from the terminal
-
Clone the repository (if you haven't already)
-
Run the
install-plugin.sh
script in thehack
directory.NAMESPACE="tools" ./hack/install-plugin.sh ${NAMESPACE} [${ARGOCD_CR}]
where:
NAMESPACE
is the namespace where ArgoCD has been deployedARGOCD_CR
is an optional value containing the name of the ArgoCD CR instance that will be patched. If not provided it defaults toargocd
When the script has completed, the ArgoCD CR should have a configManagementPlugins
entry with the following
content, at a minimum:
configManagementPlugins: |
- name: key-protect-secret
generate:
command: ["/key-protect/generate-secrets"]
args: []
Development
Install dependencies
make install
go mod vendor
Test
make test
Build
make compile
Run
With the required information, the following will run the command:
export API_KEY={IBM Cloud API Key}
export REGION={Key Protect region}
export KP_INSTANCE_ID={Key Protect instance id}
./bin/generate-secrets
Publishing
The repository has been configured to use GitHub Actions to automate the build and release cycle. To release a new version of the plugin, do the following:
- Make your changes in a branch
- Create a Pull Request with your changes. Be sure to add a change type label (
feature
,bug
, orchore
) to the PR as well as a version label (major
,minor
, orpatch
) - If the build runs successfully and the changes look good, merge the PR. Pushing to master kicks off a chain of two other Actions:
- The changes in master will be verified and, if passing, a release will be created
- When the release is published, the changes will be built and published as assets on the release
Documentation
¶
There is no documentation for this package.