Skip to content

Commit 837328c

Browse files
committed
chore(docs): add updated documentation for configmaps in trust-manager docs and root
Signed-off-by: Matthew H. Irby <matt.irby@keyfactor.com>
1 parent 088cc34 commit 837328c

File tree

3 files changed

+155
-24
lines changed

3 files changed

+155
-24
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ test: manifests generate fmt vet envtest ## Run tests.
6767
# Utilize Kind or modify the e2e tests to load the image locally, enabling compatibility with other vendors.
6868
.PHONY: test-e2e # Run the e2e tests against a Kind k8s instance that is spun up.
6969
test-e2e:
70-
source e2e/.env && ./e2e/run_tests.sh
70+
cd e2e && source .env && ./run_tests.sh
7171

7272
.PHONY: lint
7373
lint: golangci-lint ## Run golangci-lint linter & yamllint

docs/ca-bundle/README.md

Lines changed: 146 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ The command-cert-manager-issuer integration requires a secure, trusted connectio
44

55
## Using Self-Signed Certificates
66

7-
If the targeted Keyfactor Command API is configured to use a self-signed certificate or with a certificate whose issuer isn't widely trusted, the CA certificate **must be provided** as a Kubernetes secret. The secret must belong to the same namespace that command-cert-manager-issuer is deployed to (i.e. `command-issuer-system`).
7+
If the targeted Keyfactor Command API is configured to use a self-signed certificate or with a certificate whose issuer isn't widely trusted, the CA certificate **must be provided** via a Kubernetes Secret of ConfigMap. The secret must belong to the same namespace that command-cert-manager-issuer is deployed to (i.e. `command-issuer-system`).
88

99
```shell
1010
kubectl -n command-issuer-system create secret generic command-ca-secret --from-file=ca.crt
11+
12+
kubectl -n command-issuer-system create configmap command-ca --from-file=ca.crt
1113
```
1214

13-
In the issuer specification, reference the created secret with the `caSecretName` field. The issuer resource does not need to belong to the same namespace as the secret.
15+
In the Issuer / ClusterIssuer specification, reference the created resource.
1416

1517
```yaml
1618
apiVersion: command-issuer.keyfactor.com/v1alpha1
@@ -20,22 +22,28 @@ In the issuer specification, reference the created secret with the `caSecretName
2022
namespace: default
2123
spec:
2224
...
23-
caSecretName: "command-ca-secret"
25+
caSecretName: "command-ca-secret" # if using Kubernetes Secret
26+
caBundleConfigMapName: "command-ca" # if using Kubernetes ConfigMap
27+
caBundleKey: "ca.crt" # optional key name, pulls the last key in resource if not specified
2428
```
2529
2630
## Using Publicly Trusted Certificates
2731
28-
If the targeted Keyfactor Command API is configured with a publicly trusted certificate authority (Sectigo / LetsEncrypt / etc.), the command-cert-manager-issuer image is built with a pre-bundled trust store of publicly trusted certificates but with a ***very important caveat***. The trust store may become out-of-sync over time, especially if the certificate authority issuing the Keyfactor Command certificate is updated.
32+
If the targeted Keyfactor Command API is configured with a publicly trusted certificate authority (Sectigo / LetsEncrypt / etc.), the command-cert-manager-issuer container image is built with a pre-bundled trust store of publicly trusted certificates but with a ***very important caveat***. The trust store may become out-of-sync over time, especially if the certificate authority issuing the Keyfactor Command certificate is updated.
2933
30-
It is not required to use the `caSecretName` specification, but it is **recommended** to maintain a list of trusted certificates instead of relying on the pre-bundled certificate store when the command-cert-manager-issuer image is created. This will reduce the likelihood of connectivity issues if the Keyfactor Command instance is updated to use a new CA or if the command-cert-manager-issuer image is updated and it does not include the Command CA in its trust store.
34+
It is **not required** to use the `caSecretName` / `caBundleConfigMapName` specification if Keyfactor Command's TLS certificate is built using a publicly trusted root, but it is **recommended for production workloads to maintain a list of trusted certificates** instead of relying on the pre-bundled certificate store when the command-cert-manager-issuer image is created. This will reduce the likelihood of connectivity issues if the Keyfactor Command instance is updated to use a new CA or if the command-cert-manager-issuer image is updated and it does not include the Keyfactor Command TLS certificate's root CA in its trust store.
3135

3236
This document covers available tools to help manage CA trust bundles.
3337

3438
### trust-manager
3539

36-
[trust-manager](https://cert-manager.io/docs/trust/trust-manager/) can be used to sync CA trust bundles in a Kubernetes cluster. trust-manager can synchronize a list of publicly trusted CAs as well as any custom CAs to be included in the trust chain.
40+
[trust-manager](https://cert-manager.io/docs/trust/trust-manager/) can be used to sync CA trust bundles in a Kubernetes cluster. trust-manager can synchronize a list of publicly trusted CAs as well as any custom CAs to be included in the trust chain. It is recommended to add your Keyfactor Command's intermediate and root CAs to a Kubernetes Secret / ConfigMap and synchronize this with the trust-manager bundle.
41+
42+
The publicly trusted certificates are tied to the trust-manager image. To pull up-to-date publicly trusted CAs, update the trust-manager deployment to the latest version.
43+
44+
trust-manager can synchronize the CA trust bundle to either a Kubernetes Secret or ConfigMap, this documentation will cover both methods.
3745

38-
TODO: trust-manager also supports configMap targets, which are more secure to write to with better RBAC policy.
46+
> NOTE: For the latest documentation and installation instructions, please refer to the [cert-manager trust-manager documentation](https://cert-manager.io/docs/trust/trust-manager/installation/). The instructions below may become outdated over time.
3947

4048
#### Pre-requisites
4149

@@ -44,26 +52,132 @@ TODO: trust-manager also supports configMap targets, which are more secure to wr
4452

4553
#### Security Considerations
4654

47-
> ⚠️ Important: Required Permissions
55+
> ⚠️ Important: Required Permissions. Please Read!
56+
57+
trust-manager requires different permission scopes depending on your synchronization target:
58+
59+
**Synchronizing to ConfigMaps (Recommended):**
60+
- ✅ Only requires cluster-wide **read** access to ConfigMaps
61+
- ✅ Lower security risk
62+
- ✅ Suitable for most environments
4863

49-
trust-manager requires **cluster-wide read access** to secrets. This is a hard technical requirement of trust-manager's architecture.
64+
**Synchronizing to Secrets:**
65+
- ⚠️ Requires cluster-wide **read** access to **all Secrets**
66+
- ⚠️ Higher security risk - trust-manager can read any secret in the cluster
67+
- ⚠️ Requires explicit RBAC configuration (shown below)
68+
- ⚠️ Only use if you have specific requirements for Secret storage
5069

51-
| Permission Type | Scope | Resources | Verbs | Purpose |
52-
| --------------- | ------------------ | ------------------- | ----------------------------- | --------------------------------- |
53-
| **Read** | Cluster-wide | secrets, configmaps | get, list, watch | Discover sources, monitor targets |
54-
| **Write** | Namespace-specific | secrets | create, update, patch, delete | Deploy CA bundles |
70+
**Permission Summary:**
5571

56-
#### Setting up trust-manager
72+
| Target Type | Read Scope | Write Scope | Security Impact |
73+
|-------------|----------------|--------------------|-----------------|
74+
| ConfigMap | ConfigMaps | Namespace-specific | Low |
75+
| Secret | **All Secrets**| Namespace-specific | High |
5776

58-
> NOTE: The below instructions are subject to become outdated over time. Please always refer to the [cert-manager](https://cert-manager.io/docs/trust/trust-manager/installation/) documentation for updated installation instructions.
77+
For most deployments, **Option 1 (ConfigMap)** is recommended unless you have compliance requirements mandating Secret storage.
78+
79+
#### Option 1: Synchronizing to a ConfigMap
80+
81+
##### Setting up trust-manager
5982

6083
1. Install trust-manager
6184

6285
```bash
6386
# Install trust-manager in the cert-manager namespace
6487
helm install trust-manager oci://quay.io/jetstack/charts/trust-manager \
6588
--namespace cert-manager \
66-
--set secretTargets.enabled=true \ # required trust-manager to write to Kubernetes secrets
89+
--create-namespace \
90+
--wait
91+
```
92+
2. Create a ConfigMap from a PEM file
93+
94+
Create a ConfigMap containing the PEM of the CA certificates you want to trust. Create the ConfigMap in the same namespace trust-manager is deployed to.
95+
96+
```bash
97+
kubectl create configmap enterprise-root-ca \
98+
--from-file=ca.crt=/path/to/root-ca.pem \
99+
--namespace=cert-manager \
100+
--dry-run=client -o yaml | kubectl apply -f -
101+
```
102+
103+
3. Label target namespaces
104+
105+
Label the namespace command-cert-manager-issuer is deployed to annotate trust-manager should write ConfigMaps to it
106+
107+
```bash
108+
kubectl label namespace command-issuer-system command-issuer-ca-bundle=enabled # change to your namespace
109+
```
110+
111+
4. Create a Bundle
112+
113+
Create a bundle resource to tell trust-manager what ConfigMaps to synchronize and whether to include publicly trusted CAs as part of the sync.
114+
115+
```yaml
116+
kubectl apply -f - <<EOF
117+
apiVersion: trust.cert-manager.io/v1alpha1
118+
kind: Bundle
119+
metadata:
120+
name: command-issuer-ca-bundle
121+
spec:
122+
sources:
123+
- useDefaultCAs: true # determines whether to bundle publicly trusted certificates used to validate most TLS certificates on the internet (Let's Encrypt, Google, Amazon, etc.)
124+
125+
- configMap:
126+
name: "enterprise-root-ca"
127+
key: "ca.crt"
128+
129+
# Additional intermediate or partner CAs (can also target Secrets in the same namespace)
130+
#- secret:
131+
# name: "enterprise-ca-bundle"
132+
# key: "ca.crt"
133+
134+
target:
135+
configMap:
136+
key: "ca.crt"
137+
138+
# Distribute to all namespaces with this label
139+
namespaceSelector:
140+
matchLabels:
141+
command-issuer-ca-bundle: "enabled"
142+
EOF
143+
```
144+
145+
##### Using the trust bundle
146+
147+
Once the setup is complete, trust-manager will create a resource in the target namespace:
148+
- **Resource name:** Matches the Bundle metadata name (`command-issuer-ca-bundle` in this example)
149+
- **Namespace:** Any namespace matching the `namespaceSelector` label
150+
- **Key:** As specified in `target.configMap.key`
151+
152+
You can verify the resource was created:
153+
````bash
154+
kubectl get configmap -n command-issuer-system command-issuer-ca-bundle
155+
````
156+
157+
In your issuer specification (Issuer/ClusterIssuer), reference the ConfigMap in the `caBundleConfigMapName` specification field:
158+
159+
```yaml
160+
apiVersion: command-issuer.keyfactor.com/v1alpha1
161+
kind: Issuer # or ClusterIssuer
162+
metadata:
163+
...
164+
spec:
165+
...
166+
caBundleConfigMapName: "command-issuer-ca-bundle"
167+
caBundleKey: "ca.crt" # optional key name, pulls the last key in resource if not specified
168+
```
169+
170+
#### Option 2: Synchronizing to a Secret
171+
172+
##### Setting up trust-manager
173+
174+
1. Install trust-manager
175+
176+
```bash
177+
# Install trust-manager in the cert-manager namespace
178+
helm install trust-manager oci://quay.io/jetstack/charts/trust-manager \
179+
--namespace cert-manager \
180+
--set secretTargets.enabled=true \
67181
--create-namespace \
68182
--wait
69183
```
@@ -139,7 +253,7 @@ Due to Kubernetes constraints, writing to secrets outside of trust-manager's nam
139253
rules:
140254
- apiGroups: [""]
141255
resources: ["secrets"]
142-
verbs: ["create", "update", "patch", "delete"]
256+
verbs: ["create", "update", "patch", "delete", "read"]
143257
---
144258
apiVersion: rbac.authorization.k8s.io/v1
145259
kind: RoleBinding
@@ -161,6 +275,7 @@ Due to Kubernetes constraints, writing to secrets outside of trust-manager's nam
161275
Create a bundle resource to tell trust-manager what secrets to synchronize and whether to include publicly trusted CAs as part of the sync.
162276

163277
```yaml
278+
kubectl apply -f - <<EOF
164279
apiVersion: trust.cert-manager.io/v1alpha1
165280
kind: Bundle
166281
metadata:
@@ -173,8 +288,8 @@ Due to Kubernetes constraints, writing to secrets outside of trust-manager's nam
173288
name: "enterprise-root-ca"
174289
key: "ca.crt"
175290
176-
# Additional intermediate or partner CAs
177-
#- secret:
291+
# Additional intermediate or partner CAs (can also target ConfigMaps in the same namespace)
292+
#- configMap:
178293
# name: "enterprise-ca-bundle"
179294
# key: "ca.crt"
180295
@@ -186,11 +301,20 @@ Due to Kubernetes constraints, writing to secrets outside of trust-manager's nam
186301
namespaceSelector:
187302
matchLabels:
188303
command-issuer-ca-bundle: "enabled"
304+
EOF
189305
```
190306

191-
#### Using the trust bundle
307+
##### Using the trust bundle
308+
309+
Once the setup is complete, trust-manager will create a resource in the target namespace:
310+
- **Resource name:** Matches the Bundle metadata name (`command-issuer-ca-bundle` in this example)
311+
- **Namespace:** Any namespace matching the `namespaceSelector` label
312+
- **Key:** As specified in `target.secret.key`
192313

193-
Once the setup is complete, a Kubernetes secret called `command-issuer-ca-bundle` will appear in the desired namespace (i.e. `command-issuer-system`) and the trusted CA bundle will appear in the `ca.crt` key.
314+
You can verify the resource was created:
315+
````bash
316+
kubectl get secret -n command-issuer-system command-issuer-ca-bundle
317+
````
194318

195319
In your issuer specification (Issuer/ClusterIssuer), reference the secret in the `caSecretName` specification field:
196320

@@ -202,4 +326,5 @@ In your issuer specification (Issuer/ClusterIssuer), reference the secret in the
202326
spec:
203327
...
204328
caSecretName: "command-issuer-ca-bundle"
329+
caBundleKey: "ca.crt" # optional key name, pulls the last key in resource if not specified
205330
```

docsource/content.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ For example, ClusterIssuer resources can be used to issue certificates for resou
222222
| apiPath | (optional) The base path of the Command REST API. Defaults to `KeyfactorAPI`. |
223223
| commandSecretName | (optional) The name of the Kubernetes secret containing basic auth credentials or OAuth 2.0 credentials. Omit if using ambient credentials. |
224224
| caSecretName | (optional) The name of the Kubernetes secret containing the CA certificate trust chain. See the [CA Bundle docs](./docs/ca-bundle/README.md) for more information. |
225+
| caBundleConfigMapName | (optional) The name of the Kubernetes ConfigMap containing the CA certificate trust chain. See the [CA Bundle docs](./docs/ca-bundle/README.md) for more information. |
226+
| caBundleKey | (optional) The name of the key in the ConfigMap or Secret specified by `caSecretName` or `caBundleConfigMapName` that contains the CA bundle. If omitted, the last key of the ConfigMap / Secret resource will be used. |
225227
| certificateAuthorityLogicalName | The logical name of the Certificate Authority to use in Command. For example, `Sub-CA` |
226228
| certificateAuthorityHostname | (optional) The hostname of the Certificate Authority specified by `certificateAuthorityLogicalName`. This field is usually only required if the CA in Command is a DCOM (MSCA-like) CA. |
227229
| enrollmentPatternId | The ID of the [Enrollment Pattern](https://software.keyfactor.com/Core-OnPrem/Current/Content/ReferenceGuide/Enrollment-Patterns.htm) to use when this Issuer/ClusterIssuer enrolls CSRs. **Supported by Keyfactor Command 25.1 and above**. If `certificateTemplate` and `enrollmentPatternId` are both specified, the enrollment pattern parameter will take precedence. If `enrollmentPatternId` and `enrollmentPatternName` are both specified, `enrollmentPatternId` will take precedence. Enrollment will fail if the specified certificate template is not compatible with the enrollment pattern. |
@@ -251,7 +253,9 @@ For example, ClusterIssuer resources can be used to issue certificates for resou
251253
hostname: "$HOSTNAME"
252254
apiPath: "/KeyfactorAPI" # Preceding & trailing slashes are handled automatically
253255
commandSecretName: "command-secret" # references the secret created above. Omit if using ambient credentials.
254-
caSecretName: "command-ca-secret" # references a secret containing the CA trust chain (see CA Bundle docs for more info)
256+
# caSecretName: "command-ca-secret" # references a secret containing the CA trust chain (see CA Bundle docs for more info)
257+
# caBundleConfigMapName: "command-ca-configmap" # references a configmap containing the CA trust chain (see CA Bundle docs for more info)
258+
# caBundleKey: "ca.crt" # references the key in the secret/configmap containing the CA trust chain (see CA Bundle docs for more info)
255259
256260
# certificateAuthorityHostname: "$COMMAND_CA_HOSTNAME" # Uncomment if required
257261
certificateAuthorityLogicalName: "$COMMAND_CA_LOGICAL_NAME"
@@ -281,7 +285,9 @@ For example, ClusterIssuer resources can be used to issue certificates for resou
281285
hostname: "$HOSTNAME"
282286
apiPath: "/KeyfactorAPI" # Preceding & trailing slashes are handled automatically
283287
commandSecretName: "command-secret" # references the secret created above. Omit if using ambient credentials.
284-
caSecretName: "command-ca-secret" # references a secret containing the CA trust chain (see CA Bundle docs for more info)
288+
# caSecretName: "command-ca-secret" # references a secret containing the CA trust chain (see CA Bundle docs for more info)
289+
# caBundleConfigMapName: "command-ca-configmap" # references a configmap containing the CA trust chain (see CA Bundle docs for more info)
290+
# caBundleKey: "ca.crt" # references the key in the secret/configmap containing the CA trust chain (see CA Bundle docs for more info)
285291
286292
# certificateAuthorityHostname: "$COMMAND_CA_HOSTNAME" # Uncomment if required
287293
certificateAuthorityLogicalName: "$COMMAND_CA_LOGICAL_NAME"

0 commit comments

Comments
 (0)