Skip to content

Commit a62e7e0

Browse files
authored
docs: Add docs for cert-manager PKI (#620)
Signed-off-by: Gerald Nunn <[email protected]>
1 parent e14c865 commit a62e7e0

File tree

2 files changed

+257
-15
lines changed

2 files changed

+257
-15
lines changed

docs/configuration/agent/pki-certificates.md

Lines changed: 152 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,28 @@ The agent component uses certificates for two primary purposes:
2020
graph TB
2121
Principal[Principal<br/>argocd-agent-principal-tls]
2222
CA[Certificate Authority<br/>argocd-agent-ca]
23-
23+
2424
Agent1[Agent 1<br/>Workload Cluster 1]
2525
Agent2[Agent 2<br/>Workload Cluster 2]
26-
26+
2727
CA --> Agent1CA[CA Certificate<br/>argocd-agent-ca]
2828
CA --> Agent2CA[CA Certificate<br/>argocd-agent-ca]
29-
29+
3030
CA --> Agent1Cert[Client Certificate<br/>argocd-agent-client-tls]
3131
CA --> Agent2Cert[Client Certificate<br/>argocd-agent-client-tls]
32-
32+
3333
Agent1CA --> Agent1
3434
Agent1Cert --> Agent1
3535
Agent2CA --> Agent2
3636
Agent2Cert --> Agent2
37-
37+
3838
Agent1 -.->|TLS Connection| Principal
3939
Agent2 -.->|TLS Connection| Principal
40-
40+
4141
classDef agent fill:#e1f5fe
4242
classDef cert fill:#f3e5f5
4343
classDef ca fill:#e8f5e8
44-
44+
4545
class Agent1,Agent2 agent
4646
class Agent1Cert,Agent2Cert cert
4747
class CA,Agent1CA,Agent2CA ca
@@ -153,6 +153,148 @@ argocd-agent-ca Opaque 1 5m
153153
argocd-agent-client-tls kubernetes.io/tls 2 4m
154154
```
155155

156+
## Using cert-manager
157+
158+
The cert-manager operator can be used to manage PKI certificates, this section assumes the steps
159+
for the Principal PKI using cert-manager have been completed.
160+
161+
To register Agents, Agent specific certificates for both the Principal and Agent need to be minted for
162+
use with [Mutual TLS](https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/)
163+
164+
### Step 1: Register the Agent on the Principal
165+
166+
To register the Agent on the Principal a certificate must be minted for the Principal to provide
167+
to the Agent as part of mTLS. Note the `dnsNames` used is not important
168+
but a consistent method should be used, for example `<cluster-name>.<CA-ROOT-DOMAIN>`
169+
170+
Replace the `<cluster-name>` and `<Organizational Unit>` tokens to match your requirements:
171+
172+
```
173+
apiVersion: cert-manager.io/v1
174+
kind: Certificate
175+
metadata:
176+
name: <cluster-name>-principal
177+
namespace: argocd
178+
spec:
179+
secretName: <cluster-name>
180+
issuerRef:
181+
name: argocd-agent-ca
182+
kind: Issuer
183+
commonName: managed-cluster
184+
subject:
185+
organizationalUnits:
186+
- <Organizational Unit>
187+
dnsNames:
188+
- <cluster-name>.<CA-ROOT-DOMAIN>
189+
```
190+
191+
Create the cluster secret, note that you cannot directly use the previously created certificate
192+
but need to transpose it into the cluster secret.
193+
194+
Extract the fields we need into environment variables:
195+
196+
```
197+
export PRINCIPAL_AGENT_CA=$(kubectl get secret <cluster-name>-principal -o jsonpath='{.data.ca\.crt}')
198+
export PRINCIPAL_AGENT_TLS=$(kubectl get secret <cluster-name>-principal -o jsonpath='{.data.tls\.crt}')
199+
export PRINCIPAL_AGENT_KEY=$(kubectl get secret <cluster-name>-principal -o jsonpath='{.data.tls\.key}')
200+
```
201+
202+
To create the `<cluster-name>-cluster` secret that is needed we must first create the `config` block
203+
with the certs:
204+
205+
```
206+
cat << EOF > config
207+
{
208+
"username": "foo",
209+
"password": "bar",
210+
"tlsClientConfig": {
211+
"insecure": false,
212+
"certData": "${PRINCIPAL_AGENT_TLS}",
213+
"keyData": "${PRINCIPAL_AGENT_KEY}",
214+
"caData": "${PRINCIPAL_AGENT_CA}"
215+
}
216+
}
217+
EOF
218+
```
219+
220+
Now create the secret:
221+
222+
```
223+
kubectl create secret generic <cluster-name>-cluster -n argocd --from-literal=name=<cluster-name> --from-literal=server=argocd-agent-resource-proxy.argocd.svc.cluster.local --from-file=config=./config
224+
```
225+
226+
Then label the secret as a cluster secret:
227+
228+
```
229+
oc label secret <cluster-name>-cluster argocd.argoproj.io/secret-type=cluster
230+
```
231+
232+
### Step 2: Mint Certificate for Agent
233+
234+
The Agent requires it's own certificate which will be provided to the Principal for mTLS, this will
235+
be minted on the Principal where the Issuer is available and then moved to the Agent.
236+
237+
!!!note
238+
It is possible to mint this certificate on the Agent itself by simply using cert-manager
239+
with the identical CA secret on the Agent. However this has security implications since
240+
if any cluster is compromised the CA with its key could be retrieved and a hacker could mint their own certs. Generally
241+
the Agents will at times run in less secure locations/networks then the Principle so isolating
242+
the CA to one location, the principal, is beneficial.
243+
244+
```
245+
apiVersion: cert-manager.io/v1
246+
kind: Certificate
247+
metadata:
248+
name: <cluster-name>-agent
249+
namespace: argocd
250+
spec:
251+
secretName: <cluster-name>-agent
252+
issuerRef:
253+
name: argocd-agent-ca
254+
kind: Issuer
255+
commonName: managed-cluster
256+
subject:
257+
organizationalUnits:
258+
- <Organizational Unit>
259+
dnsNames:
260+
- <cluster-name>.<CA-ROOT-DOMAIN>
261+
```
262+
263+
Output the secret to a file as we need to install it on the cluster where the Agent resides:
264+
265+
```
266+
kubectl get secret managed-cluster-agent -o yaml -n argocd | oc neat > <cluster-name>-agent.yaml
267+
```
268+
269+
!!!note
270+
The [kubectl-neat](https://github.com/itaysk/kubectl-neat) plugin is used to clean the YAML, if you do not have access to this simply omit it
271+
and edit the secret after it is exported to remove the cruft:
272+
273+
The secret `argocd-agent-ca` is also required for the Agent however want it without the key for
274+
the security reasons discussed earlier.
275+
276+
!!!note
277+
The command `yq` is used to modify the secret, if `yq` is not available simply edit the secret as needed.
278+
279+
```
280+
kubectl get secret argocd-agent-ca -o yaml -n argocd | yq 'del(.data.["tls.key"])' -y | oc neat > argocd-agent-ca.yaml
281+
```
282+
283+
Change the secret type to `Opaque` since a Kubernetes TLS secret requires a key, additionally change the name of the exported secret from `<cluster-name>-agent` to
284+
to `argocd-agent-client-tls`.
285+
286+
```
287+
yq -i '.type = "Opaque"' ./argocd-agent-ca.yaml -y
288+
yq -i '.metadata.name = "argocd-agent-client-tls"' <path-to-secret>/managed-cluster-agent.yaml -y
289+
```
290+
291+
On the Agent cluster apply the two secrets:
292+
293+
```
294+
kubectl apply -f ./argocd-agent-ca.yaml
295+
kubectl apply -f <cluster-name>-agent.yaml
296+
```
297+
156298
## Manual Certificate Management
157299

158300
For production environments or when integrating with existing PKI infrastructure, you can manually create and manage the required certificates and secrets.
@@ -346,10 +488,10 @@ data:
346488
agent.tls.secret-name: "argocd-agent-client-tls"
347489
agent.tls.client.cert-path: ""
348490
agent.tls.client.key-path: ""
349-
491+
350492
# Authentication
351493
agent.creds: "userpass:/app/config/creds/userpass.creds"
352-
494+
353495
# Connection
354496
agent.server.address: "<principal-address>"
355497
agent.server.port: "8443"
@@ -672,4 +814,4 @@ spec:
672814
## Related Documentation
673815

674816
- [Principal PKI Configuration](../principal/pki-certificates.md) - PKI setup for the principal component
675-
- [Adding New Agents](../../user-guide/adding-agents.md) - Complete agent setup guide
817+
- [Adding New Agents](../../user-guide/adding-agents.md) - Complete agent setup guide

docs/configuration/principal/pki-certificates.md

Lines changed: 105 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ graph TB
2121
CA --> PrincipalCert[Principal gRPC Server<br/>argocd-agent-principal-tls]
2222
CA --> ProxyCert[Resource Proxy Server<br/>argocd-agent-resource-proxy-tls]
2323
CA --> AgentCert[Agent Client Certificates<br/>argocd-agent-client-tls]
24-
24+
2525
JWT[JWT Signing Key<br/>argocd-agent-jwt]
26-
26+
2727
PrincipalCert --> Agent1[Agent 1]
2828
PrincipalCert --> Agent2[Agent 2]
2929
ProxyCert --> ArgoCD[Argo CD Server]
30-
30+
3131
AgentCert --> Agent1
3232
JWT --> Agent1
3333
JWT --> Agent2
@@ -146,6 +146,106 @@ argocd-agent-resource-proxy-tls kubernetes.io/tls 2 3m
146146
argocd-agent-jwt Opaque 1 2m
147147
```
148148

149+
## Using cert-manager
150+
151+
The [cert-manager](https://cert-manager.io/docs/) operator can be used to manage the Argo CD Agent PKI requirements
152+
with a [Certificate Authority (CA) issuer](https://cert-manager.io/docs/configuration/ca/). This is where a custom CA is used to issue
153+
certificates on demand.
154+
155+
### Step 1: Initialize the PKI
156+
157+
Create private key with openssl
158+
159+
```
160+
openssl genrsa -out ca.key 4096
161+
```
162+
163+
Create root certificate using the generated key:
164+
165+
```
166+
openssl req -new -x509 -sha256 -days 3650 -key ca.key -out ca.crt
167+
```
168+
169+
Create a CA secret in Kubernetes:
170+
171+
```
172+
kubectl create secret tls argocd-agent-ca --cert=ca.crt --key=ca.key -n argocd
173+
```
174+
175+
Create cert-manager issuer for the CA we generated previously:
176+
177+
```
178+
apiVersion: cert-manager.io/v1
179+
kind: Issuer
180+
metadata:
181+
name: argocd-agent-ca
182+
namespace: argocd
183+
spec:
184+
ca:
185+
secretName: argocd-agent-ca
186+
```
187+
188+
### Step 2: Issue Principal gRPC Server Certificate
189+
190+
Generate the server certificate for the principal's gRPC service, `argocd-agent-principal-tls`, using cert-manager Certificate.
191+
Make sure you update the `organizationalUnits` and `dnsNames` to reflect the values for your installation:
192+
193+
```
194+
apiVersion: cert-manager.io/v1
195+
kind: Certificate
196+
metadata:
197+
name: argocd-agent-principal-tls
198+
namespace: argocd
199+
spec:
200+
secretName: argocd-agent-principal-tls
201+
issuerRef:
202+
name: argocd-agent-ca
203+
kind: Issuer
204+
commonName: principal
205+
subject:
206+
organizationalUnits:
207+
- <Organizational Unit>
208+
dnsNames:
209+
- <dns-name>
210+
```
211+
212+
### Step 3: Issue Resource Proxy Certificate
213+
214+
Next generate the certificate for the resource proxy, note the `dnsNames` may not
215+
need to be changed here since it is an internal service unless you are using a different
216+
namespace then `argocd`. However update your `organizationalUnits` as desired:
217+
218+
```
219+
apiVersion: cert-manager.io/v1
220+
kind: Certificate
221+
metadata:
222+
name: argocd-agent-resource-proxy-tls
223+
namespace: argocd
224+
spec:
225+
secretName: argocd-agent-resource-proxy-tls
226+
issuerRef:
227+
name: argocd-agent-ca
228+
kind: Issuer
229+
commonName: resource-proxy
230+
subject:
231+
organizationalUnits:
232+
- <Organizational Unit>
233+
dnsNames:
234+
- argocd-agent-resource-proxy.argocd.svc.cluster.local
235+
```
236+
237+
### Step 4: Validate the certificates
238+
239+
Confirm that the certificates have been deployed and are ready, `READY` should be `True` for both certs as
240+
per this example:
241+
242+
```
243+
$ kubectl get certificate -n argocd
244+
NAME READY SECRET AGE
245+
argocd-agent-principal-tls True argocd-agent-principal-tls 4m8s
246+
argocd-agent-resource-proxy-tls True argocd-agent-resource-proxy-tls 64s
247+
```
248+
149249
## Manual Certificate Management
150250

151251
For production environments or when integrating with existing PKI infrastructure, you can manually create and manage the required certificates and secrets.
@@ -473,7 +573,7 @@ Rotate certificates by re-issuing them with the `--upsert` flag:
473573
# Rotate principal certificate
474574
argocd-agentctl pki issue principal --upsert
475575
476-
# Rotate resource proxy certificate
576+
# Rotate resource proxy certificate
477577
argocd-agentctl pki issue resource-proxy --upsert
478578
479579
# Rotate JWT signing key
@@ -500,4 +600,4 @@ kubectl rollout restart deployment argocd-agent-principal -n argocd
500600

501601
## Related Documentation
502602

503-
- [Adding New Agents](../../user-guide/adding-agents.md) - How to create and configure agents
603+
- [Adding New Agents](../../user-guide/adding-agents.md) - How to create and configure agents

0 commit comments

Comments
 (0)