diff --git a/content/docs/latest/spire-helm-charts-hardened-about/_index.md b/content/docs/latest/spire-helm-charts-hardened-about/_index.md new file mode 100644 index 00000000..0430b09b --- /dev/null +++ b/content/docs/latest/spire-helm-charts-hardened-about/_index.md @@ -0,0 +1,14 @@ +--- +title: About SPIRE Helm Charts Hardened +short: About +kind: spire-helm-charts-hardened-about +aliases: + - /spire-helm-charts-hardened +--- + +The [SPIRE Helm chart](https://artifacthub.io/packages/helm/spiffe/spire) provided by the [helm-charts-hardened](https://github.com/spiffe/helm-charts-hardened) project is an easy and supported way to deploy a complete SPIRE stack in Kubernetes. + +Out of the box, it deploys the SPIRE Server, SPIRE Agent, SPIRE Controller Manager, SPIFFE CSI Driver, and SPIFFE OIDC Discovery Provider along with configuring them all to integrate with the Kubernetes +cluster it is running on. + +{{< sectiontoc "spire-helm-charts-hardened-about" >}} diff --git a/content/docs/latest/spire-helm-charts-hardened-about/exposing.md b/content/docs/latest/spire-helm-charts-hardened-about/exposing.md new file mode 100644 index 00000000..f46f1c86 --- /dev/null +++ b/content/docs/latest/spire-helm-charts-hardened-about/exposing.md @@ -0,0 +1,107 @@ +--- +title: Exposing Services +short: Exposing Services +description: How to expose SPIFFE/SPIRE services outside of Kubernetes +kind: spire-helm-charts-hardened-about +weight: 150 +aliases: + - /docs/latest/helm-charts-hardened/exposing +--- + +# Default + +By default no SPIRE services are exposed outside the Kubernetes cluster. The below sections cover how to expose them. + + +# Exposable Services + +## Production Services + +| Service Name | Section Value | Default DNS Name | +| -------------------------------- | -------------------------------------- | ------------------------------------ | +| SPIRE Server | spire-server.ingress | spire-server.$trustDomain | +| SPIRE Federation Bundle Endpoint | spire-server.federation.ingress | spire-server-federation.$trustDomain | +| SPIFFE OIDC Discovery Provider | spiffe-oidc-discovery-provider.ingress | oidc-discovery.$trustDomain | + +## Experimental Services + +| Service Name | Value | Default DNS Name | +| -------------------------------- | -------------------------------------- | ------------------------------------ | +| Tornjak Frontend | tornjak-frontend.ingress | tornjak-backend.$trustDomain | +| Tornjak Backend | spire-server.tornjak.ingress | tornjak-frontend.$trustDomain | + +# Ingress Controller Support + +We have tests for ingress-nginx based Ingress Controllers and the Ingress Controller built into OpenShift. + +For ingress-nginx, set `global.spire.ingressControllerType=ingress-nginx` + +For OpenShift, set `global.openshift=true` + +Other Ingress Controllers may work but are untested and unsupported. Set the +`ingress.annotations` values as appropriate for your Ingress Controller. Please consider [submitting a PR](https://github.com/spiffe/helm-charts-hardened/pulls) if you're able to get another Ingress to work. + +# Generic Ingress Config + +Each Ingress that is enabled by setting `ingress.enabled=true` will by default create a virtual host with a DNS name like +`$serviceName.$trustDomain`. You can override the host under the services ingress section with key host. If the host +value doesn't have a `.` in it, $trustDomain will automatically be added. + +Example: Overriding the spire-server-federation host to be `example-fed.$trustDomain` + +your-values.yaml snippet: +```yaml +spire-server: + federation: + ingress: + enabled: true + host: example-fed +``` + +Example: Overriding the spire-server-federation host to be `example-fed.my-domain.com` + +your-values.yaml snippet: +```yaml +spire-server: + federation: + ingress: + enabled: true + host: example-fed.my-domain.com +``` + +# SPIFFE OIDC Discovery Provider + +The most likely service you will want to expose outside the Kubernetes Cluster is the the SPIFFE OIDC Discovery Provider. + +In order to check the integrity of a JWT, an external service needs information about the server used to sign the +JWT. This info can be retrieved from the SPIFFE OIDC Discovery Provider. It will need to be exposed to any other +service needing to validate JWT's. + +# SPIRE Server + +When setting up a Nested SPIRE installation and you have child SPIRE instances in other clusters, you will need to +expose the Root SPIRE instance outside the Kubernetes cluster. You can do this like: + +your-values.yaml snippet: +```yaml +spire-server: + ingress: + enabled: true +``` + +# SPIRE Federation Bundle Endpoint + +When setting up Federation, you need to expose the bundle endpoint outside the Kubernetes cluster so other SPIRE +instances can contact it. It will not work without enabling Federation as well. Please see the +[Federation documentation](/docs/latest/spire-helm-charts-hardened-advanced/federation/) of the Helm Chart for +all the related options to successfully deploy a Federation. + +your-values.yaml snippet: +```yaml +spire-server: + federation: + enabled: true + ingress: + enabled: true +``` + diff --git a/content/docs/latest/spire-helm-charts-hardened-about/identifiers.md b/content/docs/latest/spire-helm-charts-hardened-about/identifiers.md new file mode 100644 index 00000000..dff8ae02 --- /dev/null +++ b/content/docs/latest/spire-helm-charts-hardened-about/identifiers.md @@ -0,0 +1,155 @@ +--- +title: Identifiers +short: Identifiers +description: How to configure SPIFFE IDs +kind: spire-helm-charts-hardened-about +weight: 200 +aliases: + - /docs/latest/helm-charts-hardened/identifiers +--- + +## Defaults + +- The chart deploys [SPIRE Controller Manager](https://github.com/spiffe/spire-controller-manager) to manage SPIFFE Identifiers by Kubernetes Custom Resources. +- The chart deploys a ClusterSPIFFEID Custom Resource that gives an identifier to all pods of the form `spiffe://{{ .TrustDomain }}/ns/{{ .PodMeta.Namespace }}/sa/{{ .PodSpec.ServiceAccountName }}`. +- For a lot of use cases you don't need to add additional identifiers. + +## Custom / Additional Identifiers + +In some cases you may want to customize your identifiers or add additional ones. + +The chart supports managing the Custom Resources from the charts values file for even easier management. We recommend using values for customization. + +While you can manage identities using the [Kubernetes Custom Resources](https://github.com/spiffe/spire-controller-manager?tab=readme-ov-file#custom-resources) directly, +we do not recommend doing that as it takes care to not misconfigure. + +## Restricting the default SVIDs + +Some workloads only reliably support one SVID at a time. To support customization you can do either two things: + +1. You can disable the default ClusterSPIFFEID entirely and load in individual ClusterSPIFFEIDs for each workload/namespace. +2. Restrict the namespaces the default ClusterSPIFFEID applies to, so new ClusterSPIFFEIDs can uniquely match the workload in the excluded namespaces. + +### Disabling the default ClusterSPIFFEIDs + +your-values.yaml snippet: +```yaml +spire-server: + controllerManager: + identities: + clusterSPIFFEIDs: + default: + enabled: false +``` + +### Restricting the default ClusterSPIFFEIDs + +Example: Exclude the default ClusterSPIFFEID from getting applied to the `dev` and `test` namespaces + +your-values.yaml snippet: +```yaml +spire-server: + controllerManager: + identities: + clusterSPIFFEIDs: + default: + namespaceSelector: + matchExpressions: + - key: "kubernetes.io/metadata.name" + operator: NotIn + values: [dev, test] +``` + +# Dynamic SVIDs + +Additional ClusterSPIFFEIDs can be added to the cluster by adding additional keys / values under the `spire-server.controllerManager.identities.clusterSPIFFEIDs` dictionary. + +Example: Add a SVID that matches the workload labeled `app: frontend` in namespace `test` and add a DNS entry to it named `frontend.example.com`: + +your-values.yaml snippet: +```yaml +spire-server: + controllerManager: + identities: + clusterSPIFFEIDs: + test-frontend: + namespaceSelector: + matchExpressions: + - key: "kubernetes.io/metadata.name" + operator: In + values: [test] + podSelector: + matchLabels: + app: frontend + dnsNameTemplates: + - frontend.example.com +``` + +# Static SVIDs + +## Regular SVIDs + +Generally, loading Static SVIDS is only useful when using a workload attestor that is not the Kubernetes attestor. (non default settings) + +Example: Add a SVID that matches processes running under gid `1000` on node `x` and give it a spiffeID of `spiffe://example.com/frontend` with dns name `frontend.example.com` + +your-values.yaml snippet: +```yaml +spire-server: + controllerManager: + identities: + clusterStaticEntries: + frontend: + parentID: spiffe://example.com/node/x + spiffeID: spiffe://example.com/frontend + selectors: + - unix:gid:1000 + dnsNameTemplates: + - frontend.example.com +``` + +## Node SVIDs + +When using a node attestor other then k8sPsat, you may need to add some node entries to the database. You can make static entries for them by using the SPIRE Server's identity +as the parent. To link up to the k8sPsat + +Example: + +your-values.yaml snippet: +```yaml +spire-server: + controllerManager: + identities: + clusterStaticEntries: + node1: + parentID: spiffe://example.org/spire/server + spiffeID: spiffe://example.org/spire/agent/k8s_psat/example-cluster/e860cb09-8533-4f2e-80dc-8286d768c992 + selectors: + - tpm:pub_hash:646789aab7a9028713b8fa5197cf6be0e935d7da048866f86224ec64c50d590c + node2: + parentID: spiffe://example.org/spire/server + spiffeID: spiffe://example.org/spire/agent/k8s_psat/example-cluster/8494d54e-6ad5-4c8e-87d1-2e6b7c2315cc + selectors: + - tpm:pub_hash:d2f0ac3a4ad72e0f14f3cd7d6b5cab16c06dc05a6b847a03c8771d640709eadd + node3: + parentID: spiffe://example.org/spire/server + spiffeID: spiffe://example.org/spire/agent/k8s_psat/example-cluster/5afebd69-7c67-4998-a953-f491c156ee35 + selectors: + - tpm:pub_hash:ac951f972127d8176c367bba4684e57da3589d1f0e072a608d53977255503c7f +``` + +## Join Tokens + +When using the spire-controller-manager, do not use the `-spiffeID` flag to `spire-server token generate`. It will get undone by the controller manager. To use, generate the token +then add to your-values.yaml +```yaml +spire-server: + controllerManager: + identities: + clusterStaticEntries: + node123: + spiffeID: spiffe://example.org/your-identifier-here + parentID: spiffe://example.org/spire/agent/join_token/3b6c7dcf-10de-406c-9733-f22846f3addb + selectors: + - spiffe_id:spiffe://example.org/spire/agent/join_token/3b6c7dcf-10de-406c-9733-f22846f3addb +``` diff --git a/content/docs/latest/spire-helm-charts-hardened-about/installation.md b/content/docs/latest/spire-helm-charts-hardened-about/installation.md new file mode 100644 index 00000000..e8e7c732 --- /dev/null +++ b/content/docs/latest/spire-helm-charts-hardened-about/installation.md @@ -0,0 +1,69 @@ +--- +title: Installation +short: Installation +description: How to install the SPIRE stack using the SPIRE Helm charts +kind: spire-helm-charts-hardened-about +weight: 100 +aliases: + - /docs/latest/helm-charts-hardened/installation +--- + +## Quick start + +To do a quick install suitable for non production environments such as [minikube](https://minikube.sigs.k8s.io/docs/): + +``` +helm upgrade --install --create-namespace -n spire spire-crds spire-crds \ + --repo https://spiffe.github.io/helm-charts-hardened/ + +helm upgrade --install -n spire spire spire \ + --repo https://spiffe.github.io/helm-charts-hardened/ +``` + +## Production Deployment + +Preparing a production deployment requires a few extra steps. + +1. Save the following to your-values.yaml, ideally in your git repo. +```yaml +global: + openshift: false # If running on openshift, set to true + spire: + recommendations: + enabled: true + namespaces: + create: true + ingressControllerType: "" # If not openshift, and want to expose services, set to a supported option [ingress-nginx] + # Update these + clusterName: example-cluster + trustDomain: example.org + caSubject: + country: ARPA + organization: Example + commonName: example.org +``` + +2. If you need a non default storageClass, append the following to the spire-server section and update: +``` + persistence: + storageClass: your-storage-class +``` + +3. If your Kubernetes cluster is OpenShift based, use the output of the following command to update the trustDomain setting: +```shell +oc get cm -n openshift-config-managed console-public -o go-template="{{ .data.consoleURL }}" | \ + sed 's@https://@@; s/^[^.]*\.//' +``` + +4. Find any additional values you might want to set based on the documentation on this site or the [examples](https://github.com/spiffe/helm-charts-hardened/tree/main/examples). In particular, consider using an external database. + +5. Deploy + +```shell +helm upgrade --install --create-namespace -n spire-mgmt spire-crds spire-crds \ + --repo https://spiffe.github.io/helm-charts-hardened/ + +helm upgrade --install -n spire-mgmt spire spire \ + --repo https://spiffe.github.io/helm-charts-hardened/ \ + -f your-values.yaml +``` diff --git a/content/docs/latest/spire-helm-charts-hardened-about/namespaces.md b/content/docs/latest/spire-helm-charts-hardened-about/namespaces.md new file mode 100644 index 00000000..c06753b3 --- /dev/null +++ b/content/docs/latest/spire-helm-charts-hardened-about/namespaces.md @@ -0,0 +1,80 @@ +--- +title: Namespaces +short: Namespaces +description: Which namespaces to install the SPIRE Helm charts to +kind: spire-helm-charts-hardened-about +weight: 210 +aliases: + - /docs/latest/helm-charts-hardened/namespaces +--- + + +## Namespace Creation Options + +| Value | Default Value | Description | +| ------------------------------------- | ------------- | -------------------------------------------------------------------------------------------- | +| global.spire.namespaces.create | false | Create both recommeded namespaces | +| global.spire.namespaces.server.create | false | Create the namespace specified by global.spire.namespaces.server.name (default spire-server) | +| global.spire.namespaces.system.create | false | Create the namespace specified by global.spire.namespaces.spire.name (default spire-server) | + +## Three Namespace Configuration + +This is the recommended configuration, it automatically creates and deploys SPIRE across 3 namespaces. + +your-values.yaml snippet: +```yaml +global: + spire: + recommendations: + enabled: true + namespaces: + create: true +``` + +This will create `spire-server` and `spire-system` namespaces, label them +for proper Kubernetes Pod Security Standards operations, and deploy the various +services appropriately. + +A third namespace is needed to house the Kubernetes Custom Resource Definitions +as provided by the [spire-crds](https://artifacthub.io/packages/helm/spiffe/spire-crds) chart, as well as any Release information helm +needs to store to manage the installation. This management namespace is specified +directly to helm when installing/upgrading the release. We used `spire-mgmt` as the namespace in the installation section. + +## Two Namespace Configuration + +In some cases, it's necessary to create the `spire-server` and/or `spire-system` namespaces outside the chart. For example if a different team is responsible for creating one of the namespaces. This section will cover deployments where some or all of the namespaces can't be managed by the SPIRE helm chart. + +### Manual spire-server, Automatic spire-system + +This is the next most recommended configuration. + +Create the spire-server namespace as needed on your cluster. For example: +```shell +kubectl create namespace spire-server +kubectl label namespace spire-server pod-security.kubernetes.io/enforce=restricted +``` + +your-values.yaml snippet: +```yaml +global: + spire: + recommendations: + enabled: true + namespaces: + system: + create: true +``` + +Then run: +```shell +helm upgrade --install -n spire-server spire-crds spire-crds \ + --repo https://spiffe.github.io/helm-charts-hardened/ + +helm upgrade --install -n spire-server spire spire \ + --repo https://spiffe.github.io/helm-charts-hardened/ \ + -f your-values.yaml +``` + +## Single Namespace Configuration + +This is only recommended for non production deployments as described in the [quick start.](/docs/latest/spire-helm-charts-hardened-about/installation/#quick-start) diff --git a/content/docs/latest/spire-helm-charts-hardened-about/recommendations.md b/content/docs/latest/spire-helm-charts-hardened-about/recommendations.md new file mode 100644 index 00000000..57ace0ca --- /dev/null +++ b/content/docs/latest/spire-helm-charts-hardened-about/recommendations.md @@ -0,0 +1,90 @@ +--- +title: Recommendations +short: Recommendations +description: Recommended Configuration +kind: spire-helm-charts-hardened-about +weight: 120 +aliases: + - /docs/latest/helm-charts-hardened/recommendations +--- + +# Enable Recommendations + +In a production deployment there are a series of recommendations we +have. By enabling the recommendations, you can easily get all of +them applied to your deployment. If there are particular recommmendations +you do not wish to use, you can still set those recommendations to `false` +to disable them. + +your-values.yaml snippet: +```yaml +global: + spire: + recommendations: + enabled: true +``` + +# Individual Recommentations + +| Name | Value | +| ----------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | +| [Namespace Layout](/docs/latest/spire-helm-charts-hardened-about/recommendations/#namespace-layout) | global.spire.recommendations.namespaceLayout | +| [Namespace Pod Security Standards](/docs/latest/spire-helm-charts-hardened-about/recommendations/#namespace-pod-security-standards) | global.spire.recommendations.namespacePSS | +| [PriorityClassName](/docs/latest/spire-helm-charts-hardened-about/recommendations/#priority-class-name) | global.spire.recommendations.priorityClassName | +| [Prometheus](/docs/latest/spire-helm-charts-hardened-about/recommendations/#prometheus) | global.spire.recommendations.prometheus | +| [Strict Mode](/docs/latest/spire-helm-charts-hardened-about/recommendations/#namespace-layout) | global.spire.recommendations.strictMode | +| [Security Contexts](/docs/latest/spire-helm-charts-hardened-about/recommendations/#security-contexts) | global.spire.recommendations.securityContexts | + +## Namespace Layout + +Option `global.spire.recommendations.namespaceLayout` causes the services to be deployed +across the two recommended namespaces for the services: + +| Namespace Type | Namespace Value | Default Value | Purpose | +| -------------- | ----------------------------------- | ------------- | ---------------------------------------------------------- | +| Server | global.spire.namespaces.server.name | spire-server | Services that should have restricted Kubernetes privileges | +| System | global.spire.namespaces.system.name | spire-system | Services needing Kubernetes privileges | + +| Service Name | Namespace Type | +| ------------------------------ | -------------- | +| SPIRE Server | Server | +| SPIFFE OIDC Discovery Provider | Server | +| SPIFFE CSI Driver | System | +| SPIRE Agent | System | + +## Namespace Pod Security Standards + +Option `global.spire.recommendations.namespacePSS` sets the chart to set the recommended +[Kubernetes Pod Security Standard](https://kubernetes.io/docs/concepts/security/pod-security-standards/) labels when namespaces +are created with the chart via any of the namespace flags as described in the [namespace documentation](../namespaces/#namespace-creation-options.) + + +On creation, the following Namespaces are assigned their Pod Security Standard: + +| Namespace Type | Pod Security Standard | +| -------------- | --------------------- | +| Server | Restricted | +| System | Privileged | + + +## Priority Class Name + +Option `global.spire.recommendations.priorityClassName` sets the Kubernetes Priority Class Names so that if there is resource contention on the cluster +the SPIRE Services will have a very high priority. SPIRE malfunctioning can cuase other important workloads to malfunction too so we prevent that from +happening. + +## Prometheus + +Option `global.spire.recommendations.prometheus` enables prometheus style exporters to be exposed out of the relevant pods. This enables Prometheus or +other compatable services to gather metrics from the various services. + +## Strict Mode + +Option `global.spire.recommendations.strictMode` adds additional checks on the configuration to help ensure your configuration is production ready. These are +settings that are recommended as part of the [install instructions.](..//installation/#production-deployment) + +## Security Contexts + +Option `global.spire.recommendations.securityContexts` sets the Kubernetes pod securityContext and container securityContext to settings that +meet the required [Kubernetes Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/) as well as addition +settings that tighten security as much as the maintainers know how. diff --git a/content/docs/latest/spire-helm-charts-hardened-about/service-selection.md b/content/docs/latest/spire-helm-charts-hardened-about/service-selection.md new file mode 100644 index 00000000..9c7c22a1 --- /dev/null +++ b/content/docs/latest/spire-helm-charts-hardened-about/service-selection.md @@ -0,0 +1,46 @@ +--- +title: Service Selection +short: Service Selection +description: How to enable/disable individual services +kind: spire-helm-charts-hardened-about +weight: 110 +aliases: + - /docs/latest/helm-charts-hardened/service-selection +--- + +# Services provided by the chart + +There are multiple services provided by the chart. They can be enabled/disabled as needed using helm +values. + +## Production Services + +| Service Name | Value | Enabled by Default | +| ------------------------------ | ------------------------------------------- | ------------------ | +| SPIRE Server | spire-server.enabled | true | +| SPIRE Agent | spire-agent.enabled | true | +| SPIRE Controller Manager | spire-server.spireControllerManager.enabled | true | +| SPIFFE OIDC Discovery Provider | spiffe-oidc-discovery-provider.enabled | true | +| SPIFFE CSI Driver | spiffe-csi-driver.enabled | true | + +## Experimental Services + +| Service Name | Value | Enabled by Default | +| ------------------------------ | ------------------------------------------- | ------------------ | +| Tornjak Frontend | tornjak-frontend.enabled | false | +| Tornjak Backend | spire-server.tornjak.enabled | false | + +## Customization Examples + +Example: Running the SPIRE Server Standalone: + +your-values.yaml snippet: +```yaml +spire-agent: + enabled: false +spiffe-oidc-discovery-provider: + enabled: false +spiffe-csi-driver: + enabled: false +``` + diff --git a/content/docs/latest/spire-helm-charts-hardened-about/upgrading.md b/content/docs/latest/spire-helm-charts-hardened-about/upgrading.md new file mode 100644 index 00000000..a3e771a2 --- /dev/null +++ b/content/docs/latest/spire-helm-charts-hardened-about/upgrading.md @@ -0,0 +1,46 @@ + +--- +title: Upgrading +short: Upgrading +description: How to upgrade the SPIRE stack using the Helm charts +kind: spire-helm-charts-hardened-about +weight: 100 +aliases: + - /docs/latest/helm-charts-hardened/upgrading +--- + +# Chart version number meaning + +The chart has its own version number following the semver scheme of: + +`Major`.`Minor`.`Patch` versioning. + +# Prerequisites + +## Version upgrades +We only support upgrading one Major/Minor version at a time. Version skipping isn't supported except for patch versions. + +Examples: + * It's supported to upgrade from 0.11.1 directly to 0.11.7 + * It's supported to upgrade from 0.11.2 to 0.12.1 + * It's not supported to upgrade from 0.11.0 to 0.13.0 + +## Additional Upgrade Steps + +From time to time you may need to do some upgrade steps before upgrading. We'll only do this +during Major or Minor version changes of the chart, never a patch release. + +Look at the [upgrade notes](https://artifacthub.io/packages/helm/spiffe/spire#upgrade-notes) from the chart before performing the upgrade. + +# Upgrading + +Once all prerequisite steps have been performed, upgrade the instance by running the following. Make sure to use the namespace you installed the chart to: + +```shell +helm upgrade --install --create-namespace -n spire-mgmt spire-crds spire-crds \ + --repo https://spiffe.github.io/helm-charts-hardened/ + +helm upgrade --install -n spire-mgmt spire spire \ + --repo https://spiffe.github.io/helm-charts-hardened/ \ + -f your-values.yaml +``` diff --git a/content/docs/latest/spire-helm-charts-hardened-advanced/_index.md b/content/docs/latest/spire-helm-charts-hardened-advanced/_index.md new file mode 100644 index 00000000..fa5fb791 --- /dev/null +++ b/content/docs/latest/spire-helm-charts-hardened-advanced/_index.md @@ -0,0 +1,11 @@ +--- +title: SPIRE Helm Charts Hardened Advanced Configuration +short: Advanced +kind: spire-helm-charts-hardened-advanced +aliases: + - /spire-helm-charts-hardened-advanced +--- + +The SPIRE Helm chart provided by the helm-charts-hardened project can be configured into many different architectures and configurations. + +{{< sectiontoc "spire-helm-charts-hardened-advanced" >}} diff --git a/content/docs/latest/spire-helm-charts-hardened-advanced/federation.md b/content/docs/latest/spire-helm-charts-hardened-advanced/federation.md new file mode 100644 index 00000000..02607fa5 --- /dev/null +++ b/content/docs/latest/spire-helm-charts-hardened-advanced/federation.md @@ -0,0 +1,216 @@ +--- +title: Federation +short: Federation +description: How to setup a SPIRE Federation using the SPIRE Helm charts +kind: spire-helm-charts-hardened-advanced +weight: 200 +aliases: + - /docs/latest/helm-charts-hardened-architecture/federation +--- + +The typical architecture for Federated SPIRE using the Helm charts uses a 1:1 relationship between SPIRE instances and Kubernetes Clusters, as well as multiple Kubernetes clusters. + +# Federation Configuration + +There are 4 pieces of configuration related to Federation. + +## Enabling Federation + +Set `spire-server.federation.enabled=true`. + +your-values.yaml snippet: +```yaml +spire-server: + federation: + enabled: true +``` + +## Exposing Federation Bundle Endpoint outside the Kubernetes Cluster + +Set `spire-server.federation.ingress.enabled=true`. Futher customization can be made as described in +[Exposing Services](/docs/latest/spire-helm-charts-hardened-about/exposing/#generic-ingress-config) + +your-values.yaml snippet: +```yaml +spire-server: + federation: + ingress: + enabled: true +``` + +## Configure local SPIRE to talk to and trust other SPIRE Instances + +your-values.yaml snippet: +```yaml +spire-server: + controllerManager: + identities: + clusterFederatedTrustDomains: + b: + bundleEndpointProfile: + endpointSPIFFEID: spiffe://b-org.local/spire/server + type: https_spiffe + bundleEndpointURL: https://spire-server-federation.b-org.local + trustDomain: b-org.local +``` + +## Configure local workloads to trust the other SPIRE + +your-values.yaml snippet: +```yaml +spire-server: + controllerManager: + identities: + clusterSPIFFEIDs: + default: + federatesWith: + - b-org.local +``` + +# Example Federated Installation + +## Kubernetes Cluster A + +your-values.yaml +```yaml +global: + openshift: false + spire: + recommendations: + enabled: true + namespaces: + create: true + ingressControllerType: ingress-nginx + clusterName: a + trustDomain: a-org.local + +spire-server: + ca_subject: + country: US + organization: A + common_name: a.local + federation: + enabled: true + ingress: + enabled: true + controllerManager: + identities: + clusterSPIFFEIDs: + default: + federatesWith: + - b-org.local + clusterFederatedTrustDomains: + b: + bundleEndpointProfile: + endpointSPIFFEID: spiffe://b-org.local/spire/server + type: https_spiffe + bundleEndpointURL: https://spire-server-federation.b-org.local + trustDomain: b-org.local + +spiffe-oidc-discovery-provider: + ingress: + enabled: true +``` + +Install on Cluster A + +```shell +helm upgrade --install --create-namespace -n spire-server spire-crds spire-crds \ + --repo https://spiffe.github.io/helm-charts-hardened/ + +helm upgrade --install -n spire-server spire spire \ + --repo https://spiffe.github.io/helm-charts-hardened/ +``` + +## Kubernetes Cluster B + +your-values.yaml +```yaml +global: + openshift: false + spire: + recommendations: + enabled: true + namespaces: + create: true + ingressControllerType: ingress-nginx + clusterName: b + trustDomain: b-org.local + +spire-server: + ca_subject: + country: US + organization: B + common_name: b.local + federation: + enabled: true + ingress: + enabled: true + controllerManager: + identities: + clusterSPIFFEIDs: + default: + federatesWith: + - a-org.local + clusterFederatedTrustDomains: + a: + bundleEndpointProfile: + endpointSPIFFEID: spiffe://a-org.local/spire/server + type: https_spiffe + bundleEndpointURL: https://spire-server-federation.a-org.local + trustDomain: a-org.local + +spiffe-oidc-discovery-provider: + ingress: + enabled: true +``` + +Install on Cluster B + +```shell +helm upgrade --install --create-namespace -n spire-server spire-crds spire-crds \ + --repo https://spiffe.github.io/helm-charts-hardened/ + +helm upgrade --install -n spire-server spire spire \ + --repo https://spiffe.github.io/helm-charts-hardened/ +``` + +## DNS +Ensure that the bundleEndpointURL's specified are valid and in DNS. Use the External IP Address of the Ingress Controller service. + +The hostnames can be adjusted if desired, as described in +[Exposing Services](/docs/latest/spire-helm-charts-hardened-about/exposing/#generic-ingress-config) + +## Bootstrapping the Federation + +When using bundleEndpointProfile's of type `https_spiffe`, both instances will need to have trust bundles from the other instance loaded in manually. +Once they are loaded. The instances can automatically renew them once trust is established. + +### On Cluster A, retrieve the trust bundle + +```shell +kubectl exec -it -n spire-server spire-server-0 -c spire-server -- spire-server bundle show -format spiffe > cluster-a.bundle +``` + +Then send cluster-a.bundle to the admin of Cluster B via a secure means. (Signed email, scp, etc) + +### On Cluster B, retrieve the trust bundle + +```shell +kubectl exec -it -n spire-server spire-server-0 -c spire-server -- spire-server bundle show -format spiffe > cluster-b.bundle +``` + +Then, send cluster-b.bundle to the admin of Cluster A via a secure means. (Signed email, scp, etc) + +### On Cluster A, load in Cluster Bs trust bundle + +```shell +cat cluster-b.bundle | kubectl exec -i -n spire-server spire-server-0 -c spire-server -- spire-server bundle set -format spiffe -id spiffe://b-org.local +``` + +### On Cluster B, load in Cluster As trust bundle + +```shell +cat cluster-a.bundle | kubectl exec -i -n spire-server spire-server-0 -c spire-server -- spire-server bundle set -format spiffe -id spiffe://a-org.local +``` + diff --git a/content/docs/latest/spire-helm-charts-hardened-advanced/mirror.md b/content/docs/latest/spire-helm-charts-hardened-advanced/mirror.md new file mode 100644 index 00000000..a3187fd6 --- /dev/null +++ b/content/docs/latest/spire-helm-charts-hardened-advanced/mirror.md @@ -0,0 +1,74 @@ +--- +title: Local Mirrors +short: Local Mirrors +description: How to setup a local mirror for SPIRE images +kind: spire-helm-charts-hardened-advanced +weight: 200 +aliases: + - /docs/latest/helm-charts-hardened-architecture/mirror +--- + +## Identify Containers needing mirroring + +Run: +```bash +helm template spire --repo https://spiffe.github.io/helm-charts-hardened/ -f your-values.yaml | yq e -rN \ + '[.spec, .spec.template.spec] | flatten(1) | .[]| [.containers, .initContainers] | flatten(1) | .[].image' - \ + | sort -u +``` + +Example output: +``` +cgr.dev/chainguard/bash:latest +cgr.dev/chainguard/kubectl:latest +cgr.dev/chainguard/wait-for-it:latest-20230113 +ghcr.io/spiffe/spiffe-csi-driver:0.2.3 +ghcr.io/spiffe/spire-agent:1.6.3 +ghcr.io/spiffe/spire-controller-manager:0.2.2 +ghcr.io/spiffe/spire-server:1.6.3 +registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.6.2 +``` + +## Mirror Containers + +Copy each container to your local repository, replacing the server name but keeping the paths. + +This is easiest to do with [skopeo](https://github.com/containers/skopeo) or [crane](https://michaelsauter.github.io/crane/index.html), but can be done with docker as well. + +## Mirror the Charts to the Registry + +Pull down SPIRE charts +```shell +helm pull spire-crds --repo https://spiffe.github.io/helm-charts-hardened/ +helm pull spire --repo https://spiffe.github.io/helm-charts-hardened/ +``` + +Push up charts to registry +```shell +helm push spire-crds*.tgz oci:///helm-charts-hardened/spire-crds +helm push spire-0*.tgz oci:///helm-charts-hardened/spire +``` + +## Configuration + +Update the repo values to point at your local mirror: + +your-values.yaml snippet: +```yaml +global: + spire: + image: + registry: "" +``` + +## Installation + +Install using the mirrored charts: +``` +helm upgrade --install --create-namespace -n spire-mgmt spire-crds \ + oci:///helm-charts/spire-crds + +helm upgrade --install -n spire-mgmt spire spire \ + --repo https://spiffe.github.io/helm-charts-hardened/ \ + -f your-values.yaml +``` diff --git a/layouts/partials/docs/sidenav.html b/layouts/partials/docs/sidenav.html index e9358b33..5ebc2af4 100644 --- a/layouts/partials/docs/sidenav.html +++ b/layouts/partials/docs/sidenav.html @@ -5,6 +5,9 @@ {{ $spireAbout := where $allDocs ".Params.kind" "eq" "spire-about" }} +{{ $spireHelmChartsHardenedAbout := where $allDocs ".Params.kind" "eq" "spire-helm-charts-hardened-about" }} +{{ $spireHelmChartsHardenedAdvanced := where $allDocs ".Params.kind" "eq" "spire-helm-charts-hardened-advanced" }} + {{ $spirePlanning := where $allDocs ".Params.kind" "eq" "planning" }} {{ $spireTry := where $allDocs ".Params.kind" "eq" "try" }} {{ $spireDeploying := where $allDocs ".Params.kind" "eq" "deploying" }} @@ -54,6 +57,12 @@ {{ partial "docs/sidenav-section.html" ( dict "ctx" . "section" $spireDeploying "pageUrl" $pageUrl "version" $version ) }} {{ partial "docs/sidenav-section.html" ( dict "ctx" . "section" $spireMaintenance "pageUrl" $pageUrl "version" $version ) }} + + Helm Charts Hardened + +{{ partial "docs/sidenav-section.html" ( dict "ctx" . "section" $spireHelmChartsHardenedAbout "pageUrl" $pageUrl "version" $version ) }} +{{ partial "docs/sidenav-section.html" ( dict "ctx" . "section" $spireHelmChartsHardenedAdvanced "pageUrl" $pageUrl "version" $version ) }} + Integrate SPIRE diff --git a/layouts/partials/navbar.html b/layouts/partials/navbar.html index 6ea60236..a93a3216 100644 --- a/layouts/partials/navbar.html +++ b/layouts/partials/navbar.html @@ -19,6 +19,9 @@ {{ $spireAbout := where site.Pages ".Params.kind" "eq" "spire-about" }} +{{ $spireHelmChartsHardenedAbout := where site.Pages ".Params.kind" "eq" "spire-helm-charts-hardened-about" }} +{{ $spireHelmChartsHardenedAdvanced := where site.Pages ".Params.kind" "eq" "spire-helm-charts-hardened-advanced" }} + {{ $spirePlanning := where site.Pages ".Params.kind" "eq" "planning" }} {{ $spireTry := where site.Pages ".Params.kind" "eq" "try" }} {{ $spireDeploying := where site.Pages ".Params.kind" "eq" "deploying" }} @@ -117,6 +120,13 @@ {{ partial "docs/navbar-section.html" ( dict "ctx" . "sectionTitle" "Plan" "section" $spirePlanning "pageUrl" $pageUrl "version" $version ) }} {{ partial "docs/navbar-section.html" ( dict "ctx" . "sectionTitle" "Deploy" "section" $spireDeploying "pageUrl" $pageUrl "version" $version ) }} {{ partial "docs/navbar-section.html" ( dict "ctx" . "sectionTitle" "Maintain" "section" $spireMaintenance "pageUrl" $pageUrl "version" $version ) }} + + + Helm Chart Hardened + + + {{ partial "docs/navbar-section.html" ( dict "ctx" . "sectionTitle" "About" "section" $spireHelmChartsHardenedAbout "pageUrl" $pageUrl "version" $version ) }} + {{ partial "docs/navbar-section.html" ( dict "ctx" . "sectionTitle" "About" "section" $spireHelmChartsHardenedAdvanced "pageUrl" $pageUrl "version" $version ) }} Integrate SPIRE