diff --git a/content/docs/latest/spire-helm-charts-hardened-about/exposing.md b/content/docs/latest/spire-helm-charts-hardened-about/exposing.md index f46f1c86..36bad43a 100644 --- a/content/docs/latest/spire-helm-charts-hardened-about/exposing.md +++ b/content/docs/latest/spire-helm-charts-hardened-about/exposing.md @@ -12,7 +12,6 @@ aliases: By default no SPIRE services are exposed outside the Kubernetes cluster. The below sections cover how to expose them. - # Exposable Services ## Production Services diff --git a/content/docs/latest/spire-helm-charts-hardened-about/namespaces.md b/content/docs/latest/spire-helm-charts-hardened-about/namespaces.md index c06753b3..4ee3594d 100644 --- a/content/docs/latest/spire-helm-charts-hardened-about/namespaces.md +++ b/content/docs/latest/spire-helm-charts-hardened-about/namespaces.md @@ -8,7 +8,6 @@ aliases: - /docs/latest/helm-charts-hardened/namespaces --- - ## Namespace Creation Options | Value | Default Value | Description | diff --git a/content/docs/latest/spire-helm-charts-hardened-advanced/nested-spire.md b/content/docs/latest/spire-helm-charts-hardened-advanced/nested-spire.md new file mode 100644 index 00000000..494ebaec --- /dev/null +++ b/content/docs/latest/spire-helm-charts-hardened-advanced/nested-spire.md @@ -0,0 +1,172 @@ +--- +title: Nested SPIRE +short: Nested SPIRE +description: Nested SPIRE Architectures +kind: spire-helm-charts-hardened-advanced +weight: 100 +aliases: + - /docs/latest/helm-charts-hardened-advanced/nested-spire +--- + +## Nested Considerations + +### Architectures + +The charts can be used to deploy many different styles of Nested SPIRE. A few possibilities are explained below. + +### SPIRE Controller Manager + +When multiple charts are installed at the same time with it enabled, they must use different classes. This is setup by default. Do not override without understanding the situation. + +### TTLs + + +*fixme* note here about tradeoffs between longer ca's more stable less risky for networking. longer ca time more risk of security issues. + + +The TTL of the workload certificates is limited by the root instances `spire-server.caTTL` and the TTL of the intermediate CA's it produces, default `spire-server.controllerManager.identity.default.ttl` + +The root CA will generate a new root at about 1/2 the `spire-server.caTTL`. + +# Kubernetes Integrated Root + +If your thinking about using nesting in the future, its easiest to start with a nested root deployment rather then a standalone instance. + +We start with deploying the SPIRE instance that includes a root server. + +## Setup Root Instance + +![Image](/img/spire-helm-charts-hardened/root-k8s.png) + + +### Install the CRDs. +```shell +helm upgrade --install --create-namespace -n spire-mgmt spire-crds spire-crds \ + --repo https://spiffe.github.io/helm-charts-hardened/ +``` + +Write out your-values.yaml as described in the [Install](../../spire-helm-charts-hardened-about/installation/#production-deployment) instructions steps 1 through 3. + +Create a file named root-values.yaml + +### No child clusters/VMs +If you do not have a need for any child clusters or VMs, you can turn off the external SPIRE server instance by adding the following to root-values.yaml: +``` +tags: + nestedRoot: true + +external-spire-server: + enabled: false +``` + +Install the root server: + +```shell +helm upgrade --install -n spire-mgmt spire spire-nested --repo https://spiffe.github.io/helm-charts-hardened/ \ + -f your-values.yaml -f root-values.yaml +``` + +### Child clusters/VMs +If you do want to have child clusters or VMs, it should be exposed outside the cluster. Ingress is the most common/easy way to do so. Add the following to root-values.yaml: +``` +tags: + nestedRoot: true + +spiffe-oidc-discovery-provider: + ingress: + enabled: true + +external-spire-server: + ingress: + enabled: true +``` + +Also, ensure spire-server.$trustdomain is setup in your dns environment to point at your ingress controller, or update the ingress related [settings](../../spire-helm-charts-hardened-about/exposing) + +For each child cluster, run the following on a control plane node and copy the generated content to a file named `.kubeconfig` where you are installing the root server: +``` +kubeadm kubeconfig user --client-name=spire-root | tr '\n' ' ' | sed 's/ //g'; echo +``` + +Install the root server: + +```shell +helm upgrade --install -n spire-mgmt spire spire-nested --repo https://spiffe.github.io/helm-charts-hardened/ \ + # Use as many of these lines as you have child clusters. Substitute for its short name: + --set "external-spire-server.kubeConfigs..kubeConfigBase64=$(cat .kubeconfig)" \ + -f your-values.yaml -f root-values.yaml +``` + +## Multi-Cluster + +![Image](/img/spire-helm-charts-hardened/multicluster-alternate3.png) + +Deploy the root server as described above. + +Write out a configuration file named child-values.yaml +``` +tags: + nestedChildFull: true + +global: + spire: + #Update these two values + clusterName: changeme + upstreamSpireAddress: spire-server.changeme +``` + +Make sure you update the two values mentioned in the file. Each cluster should have a unique clusterName, and the upstreamSpireAddress should match the dns entry you set up for the root server. + +Install the child server onto the child cluster: + +```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-nested --repo https://spiffe.github.io/helm-charts-hardened/ \ + -f your-values.yaml -f child-values.yaml +``` + +> **Note** +> The child cluster will fail to start some services at this point, as the root server doesn't have have a trust established yet. This is expected. + +Next, we will establish the trust between instances. + +Example: TODO + +## Security Cluster + +![Image](/img/spire-helm-charts-hardened/securitycluster.png) + +In some cases, you may have a separate Kubernetes Cluster just for security-related services that sits alongside one or more workload Kubernetes Clusters. The clusters share the same Data Center, Availability Zone, Region, or whatever other term is used to denote the same locality. + +Deploy the root server as described above + +Write out a configuration file named child-values.yaml + +``` +global: + spire: + # Update this value + clusterName: changeme + +tags: + nestedChildSecurity: true + +downstream-spire-agent-security: + serviceAccount: + server: + # Update this value + address: spire-server.changeme +``` + +Install the child server onto the child cluster: + +```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-nested --repo https://spiffe.github.io/helm-charts-hardened/ \ + -f your-values.yaml -f child-values.yaml +``` + +> **Note** +> The child cluster will fail to start some services at this point, as the root server doesn't have a trust established yet. This is expected. diff --git a/static/img/spire-helm-charts-hardened/Makefile b/static/img/spire-helm-charts-hardened/Makefile new file mode 100644 index 00000000..8c18d7dc --- /dev/null +++ b/static/img/spire-helm-charts-hardened/Makefile @@ -0,0 +1,23 @@ +all: multicluster-alternate.png multicluster-alternate2.png multicluster-alternate3.png multicluster.png securitycluster.png singlehardened.png root-k8s.png + +root-k8s.png: root-k8s.dot + dot -Tpng root-k8s.dot -o root-k8s.png + +multicluster-alternate.png: multicluster-alternate.dot + dot -Tpng multicluster-alternate.dot -o multicluster-alternate.png + +multicluster-alternate2.png: multicluster-alternate2.dot + dot -Tpng multicluster-alternate2.dot -o multicluster-alternate2.png + +multicluster-alternate3.png: multicluster-alternate3.dot + dot -Tpng multicluster-alternate3.dot -o multicluster-alternate3.png + +multicluster.png: multicluster.dot + dot -Tpng multicluster.dot -o multicluster.png + +securitycluster.png: securitycluster.dot + dot -Tpng securitycluster.dot -o securitycluster.png + +singlehardened.png: singlehardened.dot + dot -Tpng singlehardened.dot -o singlehardened.png + diff --git a/static/img/spire-helm-charts-hardened/multicluster-alternate.dot b/static/img/spire-helm-charts-hardened/multicluster-alternate.dot new file mode 100644 index 00000000..466f34e5 --- /dev/null +++ b/static/img/spire-helm-charts-hardened/multicluster-alternate.dot @@ -0,0 +1,128 @@ +digraph G { + compound=true; + subgraph cluster_root { + label="Cluster: Root K8S"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_root_release { + label="Helm Release: Namespace=spire-mgmt Name=spire" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_root_ns_server { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_root_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Root SPIRE Server" + spireRoot [label="K̶8̶s̶ ̶C̶o̶n̶t̶r̶o̶l̶l̶e̶r̶ ̶M̶a̶n̶a̶g̶e̶r̶",shape="record",style="rounded,solid,filled,bold",fontcolor="#b85450",color="#b85450",fillcolor="#f8cecc"]; + } + } + } + } + subgraph cluster_nested1 { + label="Cluster: K8S Workload 1"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_nested1_release { + label="Helm Release: Namespace=spire-mgmt Name=spire-root" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_nested1_ns1 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireUpstreamAgent1 [label="Upstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + subgraph cluster_nested1_ns2 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_nested1_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Nested SPIRE Server" + spireServerNested1 [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_nested1_ns3 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireDownstreamAgent1 [label="Downstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_nested1_user { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: user" + userWorkload1 [label="User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + } + subgraph cluster_nested2 { + label="Cluster: K8S Workload 2"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_nested2_release { + label="Helm Release: Namespace=spire-mgmt Name=spire" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_nested2_ns1 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireUpstreamAgent2 [label="Upstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + subgraph cluster_nested2_ns2 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_nested2_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Nested SPIRE Server" + spireServerNested2 [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_nested2_ns3 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireDownstreamAgent2 [label="Downstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_nested2_user { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: user" + userWorkload2 [label="Other User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + } + spireRoot -> spireUpstreamAgent1 [ltail=cluster_ns_root_server_obj]; + spireRoot -> spireUpstreamAgent2 [ltail=cluster_ns_root_server_obj]; + spireUpstreamAgent1 -> spireServerNested1 [lhead=cluster_ns_nested1_server_obj]; + spireServerNested1 -> spireDownstreamAgent1 [ltail=cluster_ns_nested1_server_obj]; + spireDownstreamAgent1 -> userWorkload1; + spireUpstreamAgent2 -> spireServerNested2 [lhead=cluster_ns_nested2_server_obj]; + spireServerNested2 -> spireDownstreamAgent2 [ltail=cluster_ns_nested2_server_obj]; + spireDownstreamAgent2 -> userWorkload2; +} diff --git a/static/img/spire-helm-charts-hardened/multicluster-alternate.png b/static/img/spire-helm-charts-hardened/multicluster-alternate.png new file mode 100644 index 00000000..7a631da6 Binary files /dev/null and b/static/img/spire-helm-charts-hardened/multicluster-alternate.png differ diff --git a/static/img/spire-helm-charts-hardened/multicluster-alternate2.dot b/static/img/spire-helm-charts-hardened/multicluster-alternate2.dot new file mode 100644 index 00000000..d483fb69 --- /dev/null +++ b/static/img/spire-helm-charts-hardened/multicluster-alternate2.dot @@ -0,0 +1,280 @@ +digraph G { + compound=true; + //splines = ortho; + subgraph cluster_baremetal { + label="(Bare Metal|Virtual) Node" + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + spireDownstreamAgentb [label="Downstream SPIRE Agent",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + userWorkloadb [label="External User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + subgraph cluster_baremetal2 { + label="(Bare Metal|Virtual) Node 2" + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + spireDownstreamAgentb2 [label="Downstream SPIRE Agent",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + userWorkloadb2 [label="External User Workload 2",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + subgraph cluster_k8s { + label="Cluster: Root K8s"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_root_release { + label="Helm Release: Namespace=spire-mgmt Name=spire-root"; + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_ns_root_server { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_root_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Root SPIRE Server" + spireRoot [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_ns_root1_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireRootUpstreamAgent1 [label="Upstream SPIRE Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_ns_root_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: kube-system" + kubeApiServerRoot [label="kube-apiserver",shape="record",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + } + subgraph cluster_nestedi_release { + label="Helm Release: Namespace=spire-mgmt Name=spire" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_ns_nested1iserver { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server"; + subgraph cluster_ns_internal_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Internal Nested SPIRE Server" + spireServerNestedi [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_ns_nestedi_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system"; + spireDownstreamAgenti [label="Downstream SPIRE Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + subgraph cluster_ns_nestedi_system2 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server"; + oidc [label="OIDC Discovery Provider",shape="box",style="rounded,solid,filled,bold",color="#d79b00",fillcolor="#ffe6cc"]; + } + } + subgraph cluster_ns_nestede_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: user"; + userWorkloadi1 [label="User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } +// subgraph cluster_ns_nestede_system2 { +// style="filled,dashed,bold"; +// color="#939393"; +// fillcolor="#d5d5d5"; +// label="Namespace: other-user"; +// userWorkloadi2 [label="Other User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; +// } + subgraph cluster_nestede_release { + label="Helm Release: Namespace=spire-mgmt Name=spire-external" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_ns_nestede_system3 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server"; + subgraph cluster_ns_external_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="External Nested SPIRE Server" + spireServerNestedExternal [label="K8s Controller Manager\n(static / trustdomains)",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + spireServerNestedExternal1 [label="K8s Controller Manager\n(spiffeids)",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + spireServerNestedExternal2 [label="K8s Controller Manager\n(spiffeids)",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + } + subgraph cluster_ns_nestede_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: ingress-nginx"; + ic [label="Ingress Controller(s)",shape="box",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + ie [label="Ingress Endpoint",shape="hexagon",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + } + } + subgraph cluster_nested1 { + label="Cluster: K8S Workload 1"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_nested1_release { + label="Helm Release: Namespace=spire-mgmt Name=spire-root" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_nested1_ns1 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireUpstreamAgent1 [label="Upstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + subgraph cluster_nested1_ns2 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_nested1_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Nested SPIRE Server" + spireServerNested1 [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_nested1_ns3 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireDownstreamAgent1 [label="Downstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_nested1_user { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: user" + userWorkload1 [label="User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + subgraph cluster_ns_nested1_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: kube-system" + kubeApiServerNested1 [label="kube-apiserver",shape="record",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + } + } + subgraph cluster_nested2 { + label="Cluster: K8S Workload 2"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_nested2_release { + label="Helm Release: Namespace=spire-mgmt Name=spire" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_nested2_ns1 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireUpstreamAgent2 [label="Upstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + subgraph cluster_nested2_ns2 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_nested2_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Nested SPIRE Server" + spireServerNested2 [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_nested2_ns3 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireDownstreamAgent2 [label="Downstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_nested2_user { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: user" + userWorkload2 [label="Other User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + subgraph cluster_ns_nested2_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: kube-system" + kubeApiServerNested2 [label="kube-apiserver",shape="record",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + } + } + //root + spireRoot:e -> kubeApiServerRoot:n; + spireRoot:s -> spireRootUpstreamAgent1:n [ltail=cluster_ns_root_server_obj]; + + //internal + spireRootUpstreamAgent1:w -> spireServerNestedi:n [lhead=cluster_ns_internal_server_obj]; + spireServerNestedi -> spireDownstreamAgenti [ltail=cluster_ns_internal_server_obj]; + spireServerNestedi:e -> kubeApiServerRoot:w[weight=0]; + spireDownstreamAgenti:s -> oidc:n; + spireDownstreamAgenti:e -> userWorkloadi1:n[weight=0]; + + ic:s -> ie:n; + + //external + spireRootUpstreamAgent1:e -> spireServerNestedExternal:nw [lhead=cluster_ns_external_server_obj]; + spireServerNestedExternal:n -> kubeApiServerRoot:s [weight=0]; + spireServerNestedExternal:s -> ic:n [ltail=cluster_ns_external_server_obj]; + + //externalNodes + ie:s -> spireDownstreamAgentb:n; + spireDownstreamAgentb:s -> userWorkloadb:n; + ie:s -> spireDownstreamAgentb2:n; + spireDownstreamAgentb2:s -> userWorkloadb2:n; + + //k8s workload 1 + spireServerNestedExternal1:s -> kubeApiServerNested1:n; + spireServerNested1:w -> kubeApiServerNested1:e; + ie:s -> spireUpstreamAgent1:n; + spireUpstreamAgent1:s -> spireServerNested1:n [lhead=cluster_ns_nested1_server_obj]; + spireServerNested1:s -> spireDownstreamAgent1:n [ltail=cluster_ns_nested1_server_obj]; + spireDownstreamAgent1:s -> userWorkload1:n; + + //k8s workload b + spireServerNestedExternal2:s -> kubeApiServerNested2:n; + spireServerNested2:e -> kubeApiServerNested2:w; + ie:s -> spireUpstreamAgent2:n; + spireUpstreamAgent2:s -> spireServerNested2:n [lhead=cluster_ns_nested2_server_obj]; + spireServerNested2:s -> spireDownstreamAgent2:n [ltail=cluster_ns_nested2_server_obj]; + spireDownstreamAgent2:s -> userWorkload2:n; +} diff --git a/static/img/spire-helm-charts-hardened/multicluster-alternate2.png b/static/img/spire-helm-charts-hardened/multicluster-alternate2.png new file mode 100644 index 00000000..ec5edb48 Binary files /dev/null and b/static/img/spire-helm-charts-hardened/multicluster-alternate2.png differ diff --git a/static/img/spire-helm-charts-hardened/multicluster-alternate3.dot b/static/img/spire-helm-charts-hardened/multicluster-alternate3.dot new file mode 100644 index 00000000..ca3c992d --- /dev/null +++ b/static/img/spire-helm-charts-hardened/multicluster-alternate3.dot @@ -0,0 +1,287 @@ +digraph G { + compound=true; + //splines = ortho; + subgraph cluster_k8s { + label="Cluster: Root K8s"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_ns_root_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: kube-system" + kubeApiServerRoot [label="kube-apiserver",shape="record",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + } + subgraph cluster_main_release { + label="Helm Release: Namespace=spire-mgmt Name=spire" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_g1 { + style="invis"; + subgraph cluster_ns_root_server { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_root_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Root SPIRE Server" + spireRoot [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_ns_root1_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireRootUpstreamAgent1 [label="Upstream SPIRE Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + subgraph cluster_ns_nested1iserver { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server"; + subgraph cluster_ns_internal_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Internal Nested SPIRE Server" + spireServerNestedi [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_ns_nestedi_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system"; + spireDownstreamAgenti [label="Downstream SPIRE Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_ns_nestedi_system2 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server"; + oidc [label="OIDC Discovery Provider",shape="box",style="rounded,solid,filled,bold",color="#d79b00",fillcolor="#ffe6cc"]; + } + subgraph cluster_ns_nestede_system3 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server"; + subgraph cluster_ns_external_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="External Nested SPIRE Server" + spireServerNestedExternal1 [label="K8s Controller Manager\n(spiffeids)",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + spireServerNestedExternal2 [label="K8s Controller Manager\n(spiffeids)",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + spireServerNestedExternal [label="K8s Controller Manager\n(static / trustdomains)",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + } + subgraph cluster_ns_nestede_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: ingress-nginx"; + ic [label="Ingress Controller(s)",shape="box",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + ie [label="Ingress Load Balancer",shape="hexagon",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + } + subgraph cluster_ns_nestede_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: user"; + userWorkloadi1 [label="User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + p3 [style=invis]; + } + subgraph cluster_all_nested_together { + style="invis"; + subgraph cluster_nestedtogether { + style="invis"; + subgraph cluster_nested2 { + label="Cluster: K8S Workload 2"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_nested2_release { + label="Helm Release: Namespace=spire-mgmt Name=spire" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_nested2_ns1 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireUpstreamAgent2 [label="Upstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + subgraph cluster_nested2_ns2 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_nested2_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Nested SPIRE Server" + spireServerNested2 [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_nested2_ns3 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireDownstreamAgent2 [label="Downstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_nested2_user { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: user" + userWorkload2 [label="Other User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + subgraph cluster_ns_nested2_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: kube-system" + kubeApiServerNested2 [label="kube-apiserver",shape="record",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + } + } + subgraph cluster_nested1 { + label="Cluster: K8S Workload 1"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_nested1_release { + label="Helm Release: Namespace=spire-mgmt Name=spire-root" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_nested1_ns1 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireUpstreamAgent1 [label="Upstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + subgraph cluster_nested1_ns2 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_nested1_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Nested SPIRE Server" + spireServerNested1 [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_nested1_ns3 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireDownstreamAgent1 [label="Downstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_nested1_user { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: user" + userWorkload1 [label="User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + subgraph cluster_ns_nested1_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: kube-system" + kubeApiServerNested1 [label="kube-apiserver",shape="record",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + } + } + } + subgraph cluster_vmtogether { + subgraph cluster_baremetal2 { + label="(Bare Metal|Virtual) Node 2" + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + spireDownstreamAgentb2 [label="Downstream SPIRE Agent",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + userWorkloadb2 [label="External User Workload 2",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + subgraph cluster_baremetal { + label="(Bare Metal|Virtual) Node" + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + spireDownstreamAgentb [label="Downstream SPIRE Agent",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + userWorkloadb [label="External User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + } + } + it [label="https://spire-server.$trustDomain",shape="box",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]// shape=point,weidth=0]; + + spireServerNestedExternal1:s -> kubeApiServerNested1:n [color="#093d54"]; + + oidc -> p3 [weight=20,style=invis]; + p3 -> ic [style=invis]; + p3 -> userWorkloadi1 [weight=20,style=invis]; + + oidc:s -> ic:n [style=bold]; + + //root + kubeApiServerRoot -> spireRoot [dir=back,color="#093d54"]; + kubeApiServerRoot -> spireServerNestedi [dir=back,constraint=false,color="#093d54"]; + kubeApiServerRoot -> spireServerNestedExternal [dir=back,constraint=false,color="#093d54"]; + spireRoot:s -> spireRootUpstreamAgent1:n [ltail=cluster_ns_root_server_obj,weight=20,style=bold]; + + //internal + spireRootUpstreamAgent1:s -> spireServerNestedi:n [lhead=cluster_ns_internal_server_obj,weight=20,style=bold]; + spireServerNestedi -> spireDownstreamAgenti [ltail=cluster_ns_internal_server_obj,weight=20,style=bold]; + spireDownstreamAgenti:s -> oidc:n [weight=20,style=bold]; + spireDownstreamAgenti:w -> userWorkloadi1:w [style=bold]; + + //formatting + oidc -> ic [style=invis]; + oidc -> userWorkloadi1 [style=invis]; + + //external + spireRootUpstreamAgent1:e -> spireServerNestedExternal:n [lhead=cluster_ns_external_server_obj,style=bold]; + spireServerNestedExternal:s -> ic:n [ltail=cluster_ns_external_server_obj,constraint=false,style=bold]; + + ic:s -> ie [weight=20,style=bold]; + ie -> it:n [weight=20,dir=none,style=bold]; + + //externalNodes + it:s -> spireDownstreamAgentb:n [style=bold]; + spireDownstreamAgentb:s -> userWorkloadb:n [style=bold]; + it:s -> spireDownstreamAgentb2:n [style=bold]; + spireDownstreamAgentb2:s -> userWorkloadb2:n [style=bold]; + + //k8s workload 1 + kubeApiServerNested1:s -> spireServerNested1:e [dir=back,color="#093d54"]; + it:s -> spireUpstreamAgent1:n [style=bold]; + spireUpstreamAgent1:s -> spireServerNested1:n [lhead=cluster_ns_nested1_server_obj,weight=30,style=bold]; + spireServerNested1:s -> spireDownstreamAgent1:n [ltail=cluster_ns_nested1_server_obj,weight=30,style=bold]; + spireDownstreamAgent1:s -> userWorkload1:n [style=bold]; + + //k8s workload b + spireServerNestedExternal2:s -> kubeApiServerNested2:n[weight=0,color="#093d54"]; + kubeApiServerNested2:s ->spireServerNested2:e [dir=back,color="#093d54"]; + it:s -> spireUpstreamAgent2:n [style=bold]; + spireUpstreamAgent2:s -> spireServerNested2:n [lhead=cluster_ns_nested2_server_obj,weight=30,style=bold]; + spireServerNested2:s -> spireDownstreamAgent2:n [ltail=cluster_ns_nested2_server_obj,weight=30,style=bold]; + spireDownstreamAgent2:s -> userWorkload2:n [style=bold]; +} diff --git a/static/img/spire-helm-charts-hardened/multicluster-alternate3.png b/static/img/spire-helm-charts-hardened/multicluster-alternate3.png new file mode 100644 index 00000000..30664e29 Binary files /dev/null and b/static/img/spire-helm-charts-hardened/multicluster-alternate3.png differ diff --git a/static/img/spire-helm-charts-hardened/multicluster.dot b/static/img/spire-helm-charts-hardened/multicluster.dot new file mode 100644 index 00000000..3cbc26da --- /dev/null +++ b/static/img/spire-helm-charts-hardened/multicluster.dot @@ -0,0 +1,202 @@ +digraph G { + compound=true; + subgraph cluster_k8s { + label="Cluster: K8s"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_root_release { + label="Helm Release: Namespace=spire-mgmt Name=spire-root"; + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_ns_root_server { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_root_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Root SPIRE Server" + spireRoot [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_ns_1_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireRootUpstreamAgent1 [label="Upstream SPIRE Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_ns_root_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: kube-system" + kubeApiServerRoot [label="kube-apiserver",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + subgraph cluster_root_nested1_release { + label="Helm Release: Namespace=spire-mgmt Name=spire-nested-a"; + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_ns_root_nested1_server { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_nested_server1_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Nested A SPIRE Server" + spireRootNested1 [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + } + subgraph cluster_root_nested2_release { + label="Helm Release: Namespace=spire-mgmt Name=spire-nested-b"; + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_ns_root_nested2_server { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_nested_server2_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Nested B SPIRE Server" + spireRootNested2 [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + } + } + subgraph cluster_nested1 { + label="Cluster: K8S Workload A"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_ns_nested1_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: kube-system" + kubeApiServerNested1 [label="kube-apiserver",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + subgraph cluster_nested1_release { + label="Helm Release: Namespace=spire-mgmt Name=spire-root" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_nested1_ns1 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireUpstreamAgent1 [label="Upstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + subgraph cluster_nested1_ns2 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_nested1_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Nested SPIRE Server" + spireServerNested1 [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_nested1_ns3 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireDownstreamAgent1 [label="Downstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_nested1_user { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: user" + userWorkload1 [label="User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + } + subgraph cluster_nested2 { + label="Cluster: K8S Workload B"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_nested2_release { + label="Helm Release: Namespace=spire-mgmt Name=spire" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_nested2_ns1 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireUpstreamAgent2 [label="Upstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + subgraph cluster_nested2_ns2 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_nested2_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Nested SPIRE Server" + spireServerNested2 [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_nested2_ns3 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireDownstreamAgent2 [label="Downstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_nested2_user { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: user" + userWorkload2 [label="Other User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + subgraph cluster_ns_nested2_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: kube-system" + kubeApiServerNested2 [label="kube-apiserver",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + spireRoot -> kubeApiServerRoot; + spireRootNested1 -> kubeApiServerNested1; + spireRootNested2 -> kubeApiServerNested2; + spireServerNested1 -> kubeApiServerNested1; + spireServerNested2 -> kubeApiServerNested2; + spireRoot -> spireRootUpstreamAgent1 [ltail=cluster_ns_root_server_obj]; + spireRootUpstreamAgent1 -> spireRootNested1 [lhead=cluster_ns_nested_server1_obj]; + spireRootUpstreamAgent1 -> spireRootNested2 [lhead=cluster_ns_nested_server2_obj]; + spireRootNested1 -> spireUpstreamAgent1 [ltail=cluster_ns_nested_server1_obj]; + spireRootNested2 -> spireUpstreamAgent2 [ltail=cluster_ns_nested_server2_obj]; + spireUpstreamAgent1 -> spireServerNested1 [lhead=cluster_ns_nested1_server_obj]; + spireServerNested1 -> spireDownstreamAgent1 [ltail=cluster_ns_nested1_server_obj]; + spireDownstreamAgent1 -> userWorkload1; + spireUpstreamAgent2 -> spireServerNested2 [lhead=cluster_ns_nested2_server_obj]; + spireServerNested2 -> spireDownstreamAgent2 [ltail=cluster_ns_nested2_server_obj]; + spireDownstreamAgent2 -> userWorkload2; +} diff --git a/static/img/spire-helm-charts-hardened/multicluster.png b/static/img/spire-helm-charts-hardened/multicluster.png new file mode 100644 index 00000000..ee05d457 Binary files /dev/null and b/static/img/spire-helm-charts-hardened/multicluster.png differ diff --git a/static/img/spire-helm-charts-hardened/root-k8s.dot b/static/img/spire-helm-charts-hardened/root-k8s.dot new file mode 100644 index 00000000..1d3db3b3 --- /dev/null +++ b/static/img/spire-helm-charts-hardened/root-k8s.dot @@ -0,0 +1,113 @@ +digraph G { + compound=true; + //splines = ortho; + //concentrate=true; + subgraph cluster_k8s { + label="Cluster: Root K8s"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_ns_root_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: kube-system" + kubeApiServerRoot [label="kube-apiserver",shape="record",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + } + subgraph cluster_main_release { + label="Helm Release: Namespace=spire-mgmt Name=spire" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_g1 { + style="invis"; + subgraph cluster_ns_root_server { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_root_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Root SPIRE Server" + spireRoot [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_ns_root1_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireRootUpstreamAgent1 [label="Upstream SPIRE Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + subgraph cluster_ns_nested1iserver { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server"; + subgraph cluster_ns_internal_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Internal Nested SPIRE Server" + spireServerNestedi [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_ns_nestedi_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system"; + spireDownstreamAgenti [label="Downstream SPIRE Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_ns_nestedi_system2 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server"; + oidc [label="OIDC Discovery Provider",shape="box",style="rounded,solid,filled,bold",color="#d79b00",fillcolor="#ffe6cc"]; + } + } + subgraph cluster_ns_nestede_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: ingress-nginx"; + ic [label="Ingress Controller(s)",shape="box",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + ie [label="Ingress Load Balancer",shape="hexagon",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + } + subgraph cluster_ns_nestede_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: user"; + userWorkloadi1 [label="User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + p3 [style=invis]; + } + + oidc -> p3 [weight=20,style=invis]; + p3 -> ic [style=invis]; + p3 -> userWorkloadi1 [weight=20,style=invis]; + + oidc:s -> ic:n [style=bold]; + + //root + kubeApiServerRoot -> spireRoot [dir=back,color="#093d54"]; + kubeApiServerRoot -> spireServerNestedi [dir=back,constraint=false,color="#093d54"]; + spireRoot:s -> spireRootUpstreamAgent1:n [ltail=cluster_ns_root_server_obj,weight=20,style=bold]; + + //internal + spireRootUpstreamAgent1:s -> spireServerNestedi:n [lhead=cluster_ns_internal_server_obj,weight=20,style=bold]; + spireServerNestedi -> spireDownstreamAgenti [ltail=cluster_ns_internal_server_obj,weight=20,style=bold]; + spireDownstreamAgenti:s -> oidc:n [weight=20,style=bold]; + spireDownstreamAgenti:e -> userWorkloadi1:e [style=bold]; + + //formatting + oidc -> ic [style=invis]; + oidc -> userWorkloadi1 [style=invis]; + + ic:s -> ie [weight=20,style=bold]; +} diff --git a/static/img/spire-helm-charts-hardened/root-k8s.png b/static/img/spire-helm-charts-hardened/root-k8s.png new file mode 100644 index 00000000..08b4b072 Binary files /dev/null and b/static/img/spire-helm-charts-hardened/root-k8s.png differ diff --git a/static/img/spire-helm-charts-hardened/securitycluster.dot b/static/img/spire-helm-charts-hardened/securitycluster.dot new file mode 100644 index 00000000..8ca11978 --- /dev/null +++ b/static/img/spire-helm-charts-hardened/securitycluster.dot @@ -0,0 +1,179 @@ +digraph G { + compound=true; + //splines = ortho; + //concentrate=true; + subgraph cluster_k8s { + label="Cluster: Root K8s"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_ns_root_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: kube-system" + kubeApiServerRoot [label="kube-apiserver",shape="record",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + } + subgraph cluster_main_release { + label="Helm Release: Namespace=spire-mgmt Name=spire" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_g1 { + style="invis"; + subgraph cluster_ns_root_server { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_root_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Root SPIRE Server" + spireRoot [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_ns_root1_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireRootUpstreamAgent1 [label="Upstream SPIRE Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + subgraph cluster_ns_nested1iserver { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server"; + subgraph cluster_ns_internal_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Internal Nested SPIRE Server" + spireServerNestedi [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_ns_nestedi_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system"; + spireDownstreamAgenti [label="Downstream SPIRE Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_ns_nestedi_system2 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server"; + oidc [label="OIDC Discovery Provider",shape="box",style="rounded,solid,filled,bold",color="#d79b00",fillcolor="#ffe6cc"]; + } + subgraph cluster_ns_nestede_system3 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server"; + subgraph cluster_ns_external_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="External Nested SPIRE Server" + spireServerNestedExternal1 [label="K8s Controller Manager\n(spiffeids)",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + spireServerNestedExternal [label="K8s Controller Manager\n(static / trustdomains)",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + } + subgraph cluster_ns_nestede_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: ingress-nginx"; + ic [label="Ingress Controller(s)",shape="box",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + ie [label="Ingress Load Balancer",shape="hexagon",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + } + subgraph cluster_ns_nestede_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: user"; + userWorkloadi1 [label="User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + p3 [style=invis]; + } + subgraph cluster_all_nested_together { + style="invis"; + subgraph cluster_nestedtogether { + style="invis"; + subgraph cluster_nested1 { + label="Cluster: K8S Workload 1"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_nested1_release { + label="Helm Release: Namespace=spire-mgmt Name=spire-root" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_nested1_ns3 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireDownstreamAgent1 [label="Downstream Spire Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_nested1_user { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: user" + userWorkload1 [label="User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + subgraph cluster_ns_nested1_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: kube-system" + kubeApiServerNested1 [label="kube-apiserver",shape="record",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]; + } + } + } + } + it [label="https://spire-server.$trustDomain",shape="box",style="rounded,solid,filled,bold",color="#847d96",fillcolor="#d0cee2"]// shape=point,weidth=0]; + + spireServerNestedExternal1:s -> kubeApiServerNested1:n [color="#093d54"]; + + oidc -> p3 [weight=20,style=invis]; + p3 -> ic [style=invis]; + p3 -> userWorkloadi1 [weight=20,style=invis]; + + oidc:s -> ic:n [style=bold]; + + //root + kubeApiServerRoot -> spireRoot [dir=back,color="#093d54"]; + kubeApiServerRoot -> spireServerNestedi [dir=back,constraint=false,color="#093d54"]; + kubeApiServerRoot -> spireServerNestedExternal [dir=back,constraint=false,color="#093d54"]; + spireRoot:s -> spireRootUpstreamAgent1:n [ltail=cluster_ns_root_server_obj,weight=20,style=bold]; + + //internal + spireRootUpstreamAgent1:s -> spireServerNestedi:n [lhead=cluster_ns_internal_server_obj,weight=20,style=bold]; + spireServerNestedi -> spireDownstreamAgenti [ltail=cluster_ns_internal_server_obj,weight=20,style=bold]; + spireDownstreamAgenti:s -> oidc:n [weight=20,style=bold]; + spireDownstreamAgenti:w -> userWorkloadi1:w [style=bold]; + + //formatting + oidc -> ic [style=invis]; + oidc -> userWorkloadi1 [style=invis]; + + //external + spireRootUpstreamAgent1:e -> spireServerNestedExternal:n [lhead=cluster_ns_external_server_obj,style=bold]; + spireServerNestedExternal:s -> ic:n [ltail=cluster_ns_external_server_obj,constraint=false,style=bold]; + + ic:s -> ie [weight=20,style=bold]; + ie -> it:n [weight=20,dir=none,style=bold]; + + //k8s workload 1 + it:s -> spireDownstreamAgent1:n [style=bold]; + spireDownstreamAgent1:s -> userWorkload1:n [style=bold]; +} diff --git a/static/img/spire-helm-charts-hardened/securitycluster.png b/static/img/spire-helm-charts-hardened/securitycluster.png new file mode 100644 index 00000000..15e4fd85 Binary files /dev/null and b/static/img/spire-helm-charts-hardened/securitycluster.png differ diff --git a/static/img/spire-helm-charts-hardened/singlehardened.dot b/static/img/spire-helm-charts-hardened/singlehardened.dot new file mode 100644 index 00000000..edd39765 --- /dev/null +++ b/static/img/spire-helm-charts-hardened/singlehardened.dot @@ -0,0 +1,127 @@ +digraph G { + compound=true; + subgraph cluster_baremetal { + label="(Bare Metal|Virtual) Node" + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + spireDownstreamAgent3 [label="Downstream SPIRE Agent",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + userWorkload3 [label="External User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + subgraph cluster_k8s { + label="Cluster: K8s"; + style="filled,solid,bold"; + color="#b3b3b3"; + fillcolor="#f5f5f5"; + subgraph cluster_root_release { + label="Helm Release: Namespace=spire-mgmt Name=spire-root"; + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_ns_root_server { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server" + subgraph cluster_ns_root_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Root SPIRE Server" + spireRoot [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_ns_1_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system" + spireUpstreamAgent1 [label="Upstream SPIRE Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + } + subgraph cluster_ns_root_kube_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: kube-system" + kubeApiServerRoot [label="kube-apiserver",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + subgraph cluster_nested1_release { + label="Helm Release: Namespace=spire-mgmt Name=spire" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_ns_nested1_server { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server"; + subgraph cluster_ns_internal_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="Internal Nested SPIRE Server" + spireServerNested1 [label="K8s Controller Manager",shape="record",style="rounded,solid,filled,bold",color="#10739e",fillcolor="#b1ddf0"]; + } + } + subgraph cluster_ns_nested1_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-system"; + spireDownstreamAgent1 [label="Downstream SPIRE Agent/CSI",shape="box",style="rounded,solid,filled,bold",color="#82b366",fillcolor="#d5e8d4"]; + } + subgraph cluster_ns_nested1_system2 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server"; + oidc [label="OIDC Discovery Provider",shape="box",style="rounded,solid,filled,bold",color="#d79b00",fillcolor="#ffe6cc"]; + } + } + subgraph cluster_ns_nested2_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: user"; + userWorkload1 [label="User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + subgraph cluster_ns_nested2_system2 { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: other-user"; + userWorkload2 [label="Other User Workload",shape="box",style="rounded,solid,filled,bold",color="#d6b656",fillcolor="#fff2cc"]; + } + subgraph cluster_nested3_release { + label="Helm Release: Namespace=spire-mgmt Name=spire-external" + style="filled,dashed,bold"; + color="#a3a3a3"; + fillcolor="#e5e5e5"; + subgraph cluster_ns_nested3_system { + style="filled,dashed,bold"; + color="#939393"; + fillcolor="#d5d5d5"; + label="Namespace: spire-server"; + subgraph cluster_ns_external_server_obj { + style="filled,rounded,bold"; + color="#6c8ebf"; + fillcolor="#dae8fc"; + label="External Nested SPIRE Server" + spireServerNested2 [label="K̶8̶s̶ ̶C̶o̶n̶t̶r̶o̶l̶l̶e̶r̶ ̶M̶a̶n̶a̶g̶e̶r̶",shape="record",style="rounded,solid,filled,bold",fontcolor="#b85450",color="#b85450",fillcolor="#f8cecc"]; + } + } + } + } + spireRoot -> kubeApiServerRoot; + spireServerNested1 -> kubeApiServerRoot [weight=0]; + spireRoot -> spireUpstreamAgent1 [ltail=cluster_ns_root_server_obj]; + spireUpstreamAgent1 -> spireServerNested1 [lhead=cluster_ns_internal_server_obj]; + spireServerNested1 -> spireDownstreamAgent1 [ltail=cluster_ns_internal_server_obj]; + spireDownstreamAgent1 -> userWorkload1; + spireDownstreamAgent1 -> userWorkload2; + spireUpstreamAgent1 -> spireServerNested2 [lhead=cluster_ns_external_server_obj]; + spireServerNested2 -> spireDownstreamAgent3 [ltail=cluster_ns_external_server_obj]; + spireDownstreamAgent3 -> userWorkload3; + spireDownstreamAgent1 -> oidc; +} diff --git a/static/img/spire-helm-charts-hardened/singlehardened.png b/static/img/spire-helm-charts-hardened/singlehardened.png new file mode 100644 index 00000000..2b235a2f Binary files /dev/null and b/static/img/spire-helm-charts-hardened/singlehardened.png differ