CyberArk Conjur
CyberArk Secrets Manager Provider
This section describes how to set up the CyberArk Secrets Manager provider for External Secrets Operator (ESO). For a working example, see the Accelerator-K8s-External-Secrets repo.
Prerequisites
Before installing the Secrets Manager provider, you need:
- A running instance of Conjur OSS or CyberArk Secrets Manager, with:
- An accessible Secrets Manager endpoint (for example:
https://myapi.example.com
). - Your configured Secrets Manager authentication info (such as
hostid
,apikey
, or JWT service ID). For more information on configuring Secrets Manager, see Policy statement reference. - Support for your authentication method (
apikey
is supported by default,jwt
requires additional configuration). - Optional: Secrets Manager server certificate (see below).
- A Kubernetes cluster with ESO installed.
Secrets Manager server certificate
If you set up your Secrets Manager server with a self-signed certificate, we recommend that you populate the caBundle
field with the Secrets Manager self-signed certificate in the secret-store definition. The certificate CA must be referenced in the secret-store definition using either caBundle
or caProvider
:
....
spec:
provider:
conjur:
# Service URL
url: https://myapi.conjur.org
# [OPTIONAL] base64 encoded string of certificate
caBundle: "<base64 encoded cabundle>"
# [OPTIONAL] caProvider:
# Instead of caBundle you can also specify a caProvider,
# which retrieves the cert from a Secret or ConfigMap
caProvider:
type: "Secret" # Can be Secret or ConfigMap
name: "<name of secret or configmap>"
key: "<key inside secret or configmap>"
# namespace is required for ClusterSecretStore
# but not relevant for SecretStore
namespace: "my-cert-secret-namespace"
....
External secret store
The Secrets Manager provider is configured as an external secret store in ESO. The Secrets Manager provider supports these two methods to authenticate to Secrets Manager:
apikey
: uses a Secrets Managerhostid
andapikey
to authenticate with Secrets Managerjwt
: uses a JWT to authenticate with Secrets Manager
Option 1: External secret store with apiKey authentication
This method uses a Secrets Manager hostid
and apikey
to authenticate with Secrets Manager. It is the simplest method to set up and use because your Secrets Manager instance requires no additional configuration.
Step 1: Define an external secret store
Tip
Save as the file as: conjur-secret-store.yaml
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
name: conjur
spec:
provider:
conjur:
# Service URL
url: https://myapi.conjur.org
# [OPTIONAL] base64 encoded string of certificate
caBundle: OPTIONALxFIELDxxxBase64xCertxString==
auth:
apikey:
# conjur account
account: conjur
userRef: # Get this from K8S secret
name: conjur-creds
key: hostid
apiKeyRef: # Get this from K8S secret
name: conjur-creds
key: apikey
Step 2: Create Kubernetes secrets for Secrets Manager credentials
To connect to the Secrets Manager server, the ESO Secrets Manager provider needs to retrieve the apikey
credentials from K8s secrets.
Note
For more information about how to create K8s secrets, see Creating a secret.
Here is an example of how to create K8s secrets using the kubectl
command:
# This is all one line
kubectl -n external-secrets create secret generic conjur-creds --from-literal=hostid=MYCONJURHOSTID --from-literal=apikey=MYAPIKEY
# Example:
# kubectl -n external-secrets create secret generic conjur-creds --from-literal=hostid=host/data/app1/host001 --from-literal=apikey=321blahblah
Note
conjur-creds
is the name
defined in the userRef
and apikeyRef
fields of the conjur-secret-store.yml
file.
Step 3: Create the external secrets store
Important
Unless you are using a ClusterSecretStore, credentials must reside in the same namespace as the SecretStore.
# WARNING: creates the store in the "external-secrets" namespace, update the value as needed
#
kubectl apply -n external-secrets -f conjur-secret-store.yaml
# WARNING: running the delete command will delete the secret store configuration
#
# If there is a need to delete the external secretstore
# kubectl delete secretstore -n external-secrets conjur
Option 2: External secret store with JWT authentication
This method uses JWT tokens to authenticate with Secrets Manager. You can use the following methods to retrieve a JWT token for authentication:
- JWT token from a referenced Kubernetes service account
- JWT token stored in a Kubernetes secret
Step 1: Define an external secret store
When you use JWT authentication, the following must be specified in the SecretStore
:
account
- The name of the Secrets Manager accountserviceId
- The ID of the JWT AuthenticatorWebService
configured in Secrets Manager that is used to authenticate the JWT token
You can retrieve the JWT token from either a referenced service account or a Kubernetes secret.
For example, to retrieve a JWT token from a referenced Kubernetes service account, the following secret store definition can be used:
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
name: conjur
spec:
provider:
conjur:
# Service URL
url: https://myapi.conjur.org
# [OPTIONAL] base64 encoded string of certificate
caBundle: OPTIONALxFIELDxxxBase64xCertxString==
auth:
jwt:
# conjur account
account: conjur
# The authn-jwt service ID
serviceID: my-jwt-auth-service
# Service account to retrieve JWT token for
serviceAccountRef:
name: my-service-account
# [OPTIONAL] audiences to include in JWT token
audiences:
- https://conjur.company.com
Important
This method is only supported in Kubernetes 1.22 and above as it uses the TokenRequest API to get the JWT token from the referenced service account. Audiences can be defined in the Secrets Manager JWT authenticator.
Alternatively, here is an example where a secret containing a valid JWT token is referenced:
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
name: conjur
spec:
provider:
conjur:
# Service URL
url: https://myapi.conjur.org
# [OPTIONAL] base64 encoded string of certificate
caBundle: OPTIONALxFIELDxxxBase64xCertxString==
auth:
jwt:
# conjur account
account: conjur
# The authn-jwt service ID
serviceID: my-jwt-auth-service
# Secret containing a valid JWT token
secretRef:
name: my-jwt-secret
key: token
The JWT token must identify your Secrets Manager host, be compatible with your configured Secrets Manager JWT authenticator, and meet all the Secrets Manager JWT guidelines.
You can use an external JWT issuer or the Kubernetes API server to create the token. For example, a Kubernetes service account token can be created with this command:
kubectl create token my-service-account --audience='https://conjur.company.com' --duration=3600s
Save the secret store file as conjur-secret-store.yaml
.
Step 2: Create the external secrets store
# WARNING: creates the store in the "external-secrets" namespace, update the value as needed
#
kubectl apply -n external-secrets -f conjur-secret-store.yaml
# WARNING: running the delete command will delete the secret store configuration
#
# If there is a need to delete the external secretstore
# kubectl delete secretstore -n external-secrets conjur
Define an external secret
After you have configured the Secrets Manager provider secret store, you can fetch secrets from Secrets Manager.
Here is an example of how to fetch a single secret from Secrets Manager:
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: conjur
spec:
refreshInterval: 1h
secretStoreRef:
# This name must match the metadata.name in the `SecretStore`
name: conjur
kind: SecretStore
data:
- secretKey: secret00
remoteRef:
key: data/app1/secret00
Save the external secret file as conjur-external-secret.yaml
.
Find by Name and Find by Tag
The Secrets Manager provider also supports the Find by Name and Find by Tag ESO features. This means that you can use a regular expression or tags to dynamically fetch multiple secrets from Secrets Manager.
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: conjur-find-by-name
spec:
refreshInterval: 1h
secretStoreRef:
# This name must match the metadata.name in the `SecretStore`
name: conjur
kind: SecretStore
target:
name: k8s-secret-to-be-created
dataFrom:
- find:
# You can use *either* `name` or `tags` to filter the secrets. Here are basic examples of both:
name:
# Match all secrets in the app1 namespace (e.g., `app1/secret00`, `app1/secret01`, etc.)
regexp: "^app1\/.+$"
tags:
# Only fetch Conjur secrets with the following annotations
environment: "prod"
application: "app1"
If you use these features, we strongly recommend that you limit the permissions of the Secrets Manager host to only the secrets that it needs to access. This is more secure and it reduces the load on both the Secrets Manager server and ESO.
Create the external secret
# WARNING: creates the external-secret in the "external-secrets" namespace, update the value as needed
#
kubectl apply -n external-secrets -f conjur-external-secret.yaml
# WARNING: running the delete command will delete the external-secrets configuration
#
# If there is a need to delete the external secret
# kubectl delete externalsecret -n external-secrets conjur
Get the K8s secret
- Log in to your Secrets Manager server and verify that your secret exists
- Review the value of your Kubernetes secret to verify that it contains the same value as the Secrets Manager server
# WARNING: this command will reveal the stored secret in plain text
#
# Assuming the secret name is "secret00", this will show the value
kubectl get secret -n external-secrets conjur -o jsonpath="{.data.secret00}" | base64 --decode && echo
See also
License
Copyright (c) 2023-2024 CyberArk Software Ltd. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.