Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions _topic_maps/_topic_map.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,8 @@ Topics:
File: zero-trust-manager-install
- Name: Deploying Zero Trust Workload Identity Manager operands
File: zero-trust-manager-configuration
- Name: Configuring Zero Trust Workload Identity Manager SPIRE Federation
File: zero-trust-manager-spire-federation
- Name: Monitoring Zero Trust Workload Identity Manager
File: zero-trust-manager-monitoring
- Name: Uninstalling Zero Trust Workload Identity Manager
Expand Down
271 changes: 271 additions & 0 deletions modules/zero-trust-manager-automatic-management.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
// Module included in the following assemblies:
//
// * security/zero_trust_workload_identity_manager/zero-trust-manager-spire-federation.adoc

:_mod-docs-content-type: PROCEDURE
[id="zero-trust-manager-automatic-management_{context}"]
= Using SPIRE federation with Automatic Certificate Management Environment protocol

[role="_abstract"]
Using SPIRE federation with Automatic Certificate Management Environment (ACME) protocol provides automatic certificate provisioning from Let's Encrypt. ACME also enables automatic certificate renewal before expiration, eliminating manual certificate management overhead.

.Prerequisites

* You installed the {zero-trust-full} on all clusters that will participate in the federation.

* You installed the OpenShift CLI (`oc`).

* You have `cluster-admin` privileges on all participating clusters.

* Your federation endpoints must be publicly accessible for Let's Encrypt HTTP-01 challenge validation.

* You have network connectivity between all federated clusters.


.Procedure

. Configure the `SpireServer` custom resource on each cluster to enable federation with ACME certificate management.
+
Create or update your `SpireServer` resource with the federation configuration:
+
[source,yaml]
----
apiVersion: operator.openshift.io/v1alpha1
kind: SpireServer
metadata:
name: cluster
spec:
trustDomain: cluster1.example.com
federation:
bundleEndpoint:
profile: https_web
refreshHint: 300
httpsWeb:
acme:
directoryUrl: https://acme-v02.api.letsencrypt.org/directory
domainName: federation.apps.cluster1.example.com
email: admin@example.com
tosAccepted: "true"
managedRoute: "true"
----

* The `spec.trustDomain` field sets a unique trust domain for each cluster (for example, `cluster1.example.com`, `cluster2.example.com`).

* The `spec.federation.bundleEndpoint.profile` field uses the `https_web` profile for ACME-based certificate management.

* The `spec.federation.bundleEndpoint.httpsWeb.acme.directoryUrl` field contains the Let's Encrypt production directory URL. For testing, use: `https://acme-staging-v02.api.letsencrypt.org/directory`.

* The `spec.federation.bundleEndpoint.httpsWeb.acme.domainName` field is the domain name where your federation endpoint is accessible. This automatically sets to `federation.<cluster-apps-domain>` if `managedRoute` is set to "true".

* The `spec.federation.bundleEndpoint.httpsWeb.acme.email` field is your email address for ACME account registration and certificate expiration notifications.

* The `spec.federation.bundleEndpoint.httpsWeb.acme.tosAccepted` field accepts the Let's Encrypt Terms of Service.

* The `spec.federation.managedRoute` field enables an automatic route creation by the Operator for the federation bundle endpoint.

. Apply the configuration to each cluster by running the following command:
+
[source,terminal]
----
$ oc apply -f spireserver.yaml
----

. Check the status of the SPIRE Server by entering the following command. Wait for the `Ready` status to be returned before proceeding to the next step.
+
[source,terminal]
----
$ oc get spireserver cluster -w
----
+
.Example output
[source,terminal]
----
NAME STATUS AGE
cluster Ready 5m
----

. Verify that the federation route has been created by running the following command:
+
[source,terminal]
----
$ oc get route -n zero-trust-workload-identity-manager | grep federation
----
+
.Example output
[source,terminal]
----
NAME HOST/PORT PATH SERVICES PORT TERMINATION
spire-server-federation federation.apps.cluster1.example.com spire-server 8443 passthrough
----

. On each cluster, fetch the trust bundle from the federation endpoint by running the following command:
+
[source,terminal]
----
$ curl https://federation.apps.cluster1.example.com > cluster1-bundle.json
----
+
The response contains the trust bundle in JSON Web Key Set (JWKS) format:
+
.Example trust bundle
[source,json]
----
{
"keys": [
{
"use": "x509-svid",
"kty": "RSA",
"n": "...",
"e": "AQAB",
"x5c": ["..."]
}
],
"spiffe_sequence": 1,
"refresh_hint": 300
}
----

. Create `ClusterFederatedTrustDomain` resources to establish federation relationships.
+
.. On Cluster 1, create resources to federate with Cluster 2 and Cluster 3:
+
[source,yaml]
----
apiVersion: spire.spiffe.io/v1alpha1
kind: ClusterFederatedTrustDomain
metadata:
name: cluster2-federation
spec:
trustDomain: cluster2.example.com
bundleEndpointURL: https://federation.apps.cluster2.example.com
bundleEndpointProfile:
type: https_web
className: zero-trust-workload-identity-manager-spire
trustDomainBundle: |
{
"keys": [...],
"spiffe_sequence": 1
}
---
apiVersion: spire.spiffe.io/v1alpha1
kind: ClusterFederatedTrustDomain
metadata:
name: cluster3-federation
spec:
trustDomain: cluster3.example.com
bundleEndpointURL: https://federation.apps.cluster3.example.com
bundleEndpointProfile:
type: https_web
className: zero-trust-workload-identity-manager-spire
trustDomainBundle: |
{
"keys": [...],
"spiffe_sequence": 1
}
----

* The `spec.trustDomainBundle` field contains the complete trust bundle JSON that you fetched using `curl` in step 5.

* The `spec.className` field contains the name of a class to watch CRs for. Spire-controller-manager watches the resource only if `spec.className` is set to `zero-trust-workload-identity-manager-spire`.

. Apply the `ClusterFederatedTrustDomain` resources by running the following command:
+
[source,terminal]
----
$ oc apply -f cluster-federated-trust-domains.yaml
----

. Repeat steps 6 and 7 on each cluster to establish bidirectional federation. Each cluster needs `ClusterFederatedTrustDomain` resources for every other cluster it federates with.

. Update the `SpireServer` resource on each cluster to add the `federatesWith` configuration:
+
[source,yaml]
----
apiVersion: operator.openshift.io/v1alpha1
kind: SpireServer
metadata:
name: cluster
spec:
# ... existing configuration ...
federation:
bundleEndpoint:
# ... existing bundleEndpoint configuration ...
federatesWith:
- trustDomain: cluster2.example.com
bundleEndpointUrl: https://federation.apps.cluster2.example.com
bundleEndpointProfile: https_web
- trustDomain: cluster3.example.com
bundleEndpointUrl: https://federation.apps.cluster3.example.com
bundleEndpointProfile: https_web
managedRoute: "true"
----

* The `spec.federation.federatesWith` field lists all remote trust domains this cluster should federate with.

. Apply the updated configuration by running the following command:
+
[source,terminal]
----
$ oc apply -f spireserver.yaml
----

.Verification

. Verify that the `ClusterFederatedTrustDomain` resources have been created by running the following command:
+
[source,terminal]
----
$ oc get clusterfederatedtrustdomains
----
+
.Example output
[source,terminal]
----
NAME TRUST DOMAIN ENDPOINT URL AGE
cluster2-federation cluster2.example.com https://federation.apps.cluster2.example.com 5m
cluster3-federation cluster3.example.com https://federation.apps.cluster3.example.com 5m
----

. Check the status of a `ClusterFederatedTrustDomain` to ensure bundle synchronization is working by running the following command:
+
[source,terminal]
----
$ oc describe clusterfederatedtrustdomain cluster2-federation
----
+
Look for `Successful` status conditions indicating that the trust bundle has been synchronized.

. Verify that the federation endpoint is accessible and serving the trust bundle by running the following command:
+
[source,terminal]
----
$ curl https://federation.apps.cluster1.example.com
----
+
You should receive a JSON response containing the trust bundle.

. Check the SPIRE Server logs to confirm federation is active by running the following command:
+
[source,terminal]
----
$ oc logs -n zero-trust-workload-identity-manager deployment/spire-server -c spire-server --tail=50
----
+
Look for log messages indicating successful bundle synchronization with federated trust domains.

. Verify that all SPIRE components are running by running the following command:
+
[source,terminal]
----
$ oc get pods -n zero-trust-workload-identity-manager
----
+
.Example output
[source,terminal]
----
NAME READY STATUS RESTARTS AGE
spire-agent-abcde 1/1 Running 0 10m
spire-server-0 2/2 Running 0 10m
----

. Optional: Test cross-cluster workload authentication by deploying workloads with SPIFFE identities on different clusters and verifying they can authenticate to each other using the federated trust.
Loading