Add spire-lib chart (#289)

* Add spire-lib chart

Make spire-lib bits into its own library chart.

Signed-off-by: Kevin Fox <[email protected]>

* Apply suggestions from code review

Co-authored-by: Marco Franssen <[email protected]>
Signed-off-by: kfox1111 <[email protected]>

* Move notes back

Signed-off-by: Kevin Fox <[email protected]>

* Fix NOTES

Signed-off-by: Kevin Fox <[email protected]>

---------

Signed-off-by: Kevin Fox <[email protected]>
Signed-off-by: kfox1111 <[email protected]>
Co-authored-by: Marco Franssen <[email protected]>
This commit is contained in:
kfox1111
2024-04-18 08:21:31 -07:00
committed by GitHub
co-authored by Marco Franssen
parent 260b02f973
commit 08f699bdb0
10 changed files with 86 additions and 4 deletions
+23
View File
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
+24
View File
@@ -0,0 +1,24 @@
apiVersion: v2
name: spire-lib
description: A Helm chart for Kubernetes
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: library
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: ""
+14
View File
@@ -0,0 +1,14 @@
# SPIRE Common Library Chart
A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between SPIRE charts.
## TL;DR
```yaml
dependencies:
- name: spire-lib
version: 0.1.0
repository: https://spiffe.github.io/helm-charts-hardened/
```
## Parameters
@@ -0,0 +1,338 @@
{{- define "spire-lib.cluster-name" }}
{{- if ne (len (dig "spire" "clusterName" "" .Values.global)) 0 }}
{{- .Values.global.spire.clusterName }}
{{- else }}
{{- .Values.clusterName }}
{{- end }}
{{- end }}
{{- define "spire-lib.trust-domain" }}
{{- if ne (len (dig "spire" "trustDomain" "" .Values.global)) 0 }}
{{- .Values.global.spire.trustDomain }}
{{- else }}
{{- .Values.trustDomain }}
{{- end }}
{{- end }}
{{- define "spire-lib.jwt-issuer" }}
{{- if ne (len (dig "spire" "jwtIssuer" "" .Values.global)) 0 }}
{{- .Values.global.spire.jwtIssuer }}
{{- else if ne (len .Values.jwtIssuer) 0 }}
{{- .Values.jwtIssuer }}
{{- else }}
{{- printf "https://oidc-discovery.%s" (include "spire-lib.trust-domain" .) }}
{{- end }}
{{- end }}
{{- define "spire-lib.bundle-configmap" }}
{{- if ne (len (dig "spire" "bundleConfigMap" "" .Values.global)) 0 }}
{{- .Values.global.spire.bundleConfigMap }}
{{- else }}
{{- .Values.bundleConfigMap }}
{{- end }}
{{- end }}
{{- define "spire-lib.cluster-domain" -}}
{{- if ne (len (dig "k8s" "clusterDomain" "" .Values.global)) 0 }}
{{- .Values.global.k8s.clusterDomain }}
{{- else }}
{{- .Values.clusterDomain }}
{{- end }}
{{- end }}
{{- define "spire-lib.registry" }}
{{- if ne (len (dig "spire" "image" "registry" "" .global)) 0 }}
{{- print .global.spire.image.registry "/"}}
{{- else if ne (len (.image.registry)) 0 }}
{{- print .image.registry "/"}}
{{- end }}
{{- end }}
{{- define "spire-lib.image" -}}
{{- $registry := include "spire-lib.registry" . }}
{{- $repo := .image.repository }}
{{- $tag := .image.tag | toString }}
{{- if eq (substr 0 7 $tag) "sha256:" }}
{{- printf "%s/%s@%s" $registry $repo $tag }}
{{- else if .appVersion }}
{{- $appVersion := .appVersion }}
{{- if and (hasKey . "ubi") (dig "openshift" false .global) }}
{{- $appVersion = printf "ubi-%s" $appVersion }}
{{- end }}
{{- printf "%s%s:%s" $registry $repo (default $appVersion $tag) }}
{{- else if $tag }}
{{- printf "%s%s:%s" $registry $repo $tag }}
{{- else }}
{{- printf "%s%s" $registry $repo }}
{{- end }}
{{- end }}
{{/* Takes in a dictionary with keys:
* global - the standard global object
* ingress - a standard format ingress config object
*/}}
{{- define "spire-lib.ingress-controller-type" }}
{{- $type := "" }}
{{- if ne (len (dig "spire" "ingressControllerType" "" .global)) 0 }}
{{- $type = .global.spire.ingressControllerType }}
{{- else if ne .ingress.controllerType "" }}
{{- $type = .ingress.controllerType }}
{{- else if (dig "openshift" false .global) }}
{{- $type = "openshift" }}
{{- else }}
{{- $type = "other" }}
{{- end }}
{{- if not (has $type (list "ingress-nginx" "openshift" "other")) }}
{{- fail "Unsupported ingress controller type specified. Must be one of [ingress-nginx, openshift, other]" }}
{{- end }}
{{- $type }}
{{- end }}
{{/* Takes in a dictionary with keys:
* ingress - the standardized ingress object
* Values - Chart values
*/}}
{{ define "spire-lib.ingress-calculated-name" }}
{{- $host := .ingress.host }}
{{- if not (contains "." $host) }}
{{- $host = printf "%s.%s" $host (include "spire-lib.trust-domain" .) }}
{{- end }}
{{- $host }}
{{- end }}
{{/* Takes in a dictionary with keys:
* ingress - the standardized ingress object
* svcName - The service to route to
* port - which port on the service to use
* path - optional path to set on the rules
* pathType - typical ingress path type
* tlsSection - bool specifying to add by default the tls section to the ingress. Ingress-nginx needs true, openshift needs false.
* Values - Chart values
*/}}
{{ define "spire-lib.ingress-spec" }}
{{- $host := include "spire-lib.ingress-calculated-name" . }}
{{- $svcName := .svcName }}
{{- $port := .port }}
{{- with .ingress.className }}
ingressClassName: {{ . | quote }}
{{- end }}
{{- if eq (add (len .ingress.tls) (len .ingress.hosts)) 0 }}
{{ if or .tlsSection .ingress.tlsSecret }}
tls:
- hosts:
- {{ $host | quote }}
{{- with .ingress.tlsSecret }}
secretName: {{ . | quote }}
{{- end }}
{{- end }}
rules:
- host: {{ $host | quote }}
http:
paths:
- pathType: {{ .pathType }}
{{- with .path }}
path: {{ . }}
{{- end }}
backend:
service:
name: {{ $svcName | quote }}
port:
number: {{ $port }}
{{- else }}
{{- if .ingress.tls }}
tls:
{{- range .ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName | quote }}
{{- end }}
{{- end }}
rules:
{{- range .ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ $svcName | quote }}
port:
number: {{ $port }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- define "spire-lib.kubectl-image" }}
{{- $root := deepCopy . }}
{{- $tag := $root.image.tag | toString }}
{{- if eq (len $tag) 0 }}
{{- if dig "spire" "tools" "kubectl" "tag" "" $root.global }}
{{- $_ := set $root.image "tag" $root.global.spire.tools.kubectl.tag }}
{{- else }}
{{- $_ := set $root.image "tag" (regexReplaceAll "^(v?\\d+\\.\\d+\\.\\d+).*" $root.KubeVersion "${1}") }}
{{- end }}
{{- end }}
{{- include "spire-lib.image" $root }}
{{- end }}
{{/*
Take in an array of, '.', a failure string to display, and boolean to to display it,
if strictMode is enabled and the boolean is true
*/}}
{{- define "spire-lib.check-strict-mode" }}
{{ $root := index . 0 }}
{{ $message := index . 1 }}
{{ $condition := index . 2 }}
{{- if or (dig "spire" "strictMode" false $root.Values.global) (and (dig "spire" "recommendations" "enabled" false $root.Values.global) (dig "spire" "recommendations" "strictMode" true $root.Values.global)) }}
{{- if $condition }}
{{- fail $message }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Take a copy of the config and merge in .Values.customPlugins and .Values.unsupportedBuiltInPlugins passed through as root.
*/}}
{{- define "spire-lib.config_merge" }}
{{- $pluginsToMerge := dict "plugins" dict }}
{{- range $type, $val := .root.Values.customPlugins }}
{{- if . }}
{{- if eq $type "svidstore" }}
{{- $_ := set $pluginsToMerge.plugins "SVIDStore" (deepCopy $val) }}
{{- else }}
{{- $nt := printf "%s%s" (substr 0 1 $type | upper) (substr 1 -1 $type) }}
{{- $_ := set $pluginsToMerge.plugins $nt (deepCopy $val) }}
{{- end }}
{{- end }}
{{- end }}
{{- range $type, $val := .root.Values.unsupportedBuiltInPlugins }}
{{- if . }}
{{- if eq $type "svidstore" }}
{{- $_ := set $pluginsToMerge.plugins "SVIDStore" (deepCopy $val) }}
{{- else }}
{{- $nt := printf "%s%s" (substr 0 1 $type | upper) (substr 1 -1 $type) }}
{{- $_ := set $pluginsToMerge.plugins $nt (deepCopy $val) }}
{{- end }}
{{- end }}
{{- end }}
{{- $newConfig := .config | fromYaml | mustMerge $pluginsToMerge }}
{{- $newConfig | toYaml }}
{{- end }}
{{/*
Take a copy of the plugin section and return a yaml string based version
reformatted from a dict of dicts to a dict of lists of dicts
*/}}
{{- define "spire-lib.plugins_reformat" }}
{{- range $type, $v := . }}
{{ $type }}:
{{- range $name, $v2 := $v }}
- {{ $name }}: {{ $v2 | toYaml | nindent 8 }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Take a copy of the config as a yaml config and root var.
Merge in .root.Values.customPlugins and .Values.unsupportedBuiltInPlugins into config,
Reformat the plugin section from a dict of dicts to a dict of lists of dicts,
and export it back as as json string.
This makes it much easier for users to merge in plugin configs, as dicts are easier
to merge in values, but spire needs arrays.
*/}}
{{- define "spire-lib.reformat-and-yaml2json" -}}
{{- $config := include "spire-lib.config_merge" . | fromYaml }}
{{- $plugins := include "spire-lib.plugins_reformat" $config.plugins | fromYaml }}
{{- $_ := set $config "plugins" $plugins }}
{{- $config | toPrettyJson }}
{{- end }}
{{- define "spire-lib.default_securitycontext_values" }}
allowPrivilegeEscalation: false
runAsNonRoot: true
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]
seccompProfile:
type: RuntimeDefault
{{- end }}
{{- define "spire-lib.default_k8s_podsecuritycontext_values" }}
fsGroupChangePolicy: OnRootMismatch
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
{{- end }}
{{/*
Note: runAsUser, runAsGroup, fsGroup, are not needed due to it autoassigning restricted users feature of openshift
*/}}
{{- define "spire-lib.default_openshift_podsecuritycontext_values" }}
fsGroupChangePolicy: OnRootMismatch
{{- end }}
{{- define "spire-lib.securitycontext" }}
{{- include "spire-lib.securitycontext-extended" (dict "root" . "securityContext" .Values.securityContext) }}
{{- end }}
{{/* Same as securitycontext but takes in:
root - global . context for the chart
securityContext - the subbranch of values that contains the securityContext to merge
*/}}
{{- define "spire-lib.securitycontext-extended" }}
{{- if and (dig "spire" "recommendations" "enabled" false .root.Values.global) (dig "spire" "recommendations" "securityContexts" true .root.Values.global) }}
{{- $vals := deepCopy (include "spire-lib.default_securitycontext_values" .root | fromYaml) }}
{{- $vals = mergeOverwrite $vals .securityContext }}
{{- toYaml $vals }}
{{- else }}
{{- toYaml .securityContext }}
{{- end }}
{{- end }}
{{- define "spire-lib.podsecuritycontext" }}
{{- $vals := dict }}
{{- if and (dig "spire" "recommendations" "enabled" false .Values.global) (dig "spire" "recommendations" "securityContexts" true .Values.global) }}
{{- if (dig "openshift" false .Values.global) }}
{{- $vals = mergeOverwrite $vals (include "spire-lib.default_openshift_podsecuritycontext_values" . | fromYaml) }}
{{- else }}
{{- $vals = mergeOverwrite $vals (include "spire-lib.default_k8s_podsecuritycontext_values" . | fromYaml) }}
{{- end }}
{{- end }}
{{- $vals = mergeOverwrite $vals .Values.podSecurityContext }}
{{- toYaml $vals }}
{{- end }}
{{- define "spire-lib.default_node_priority_class_name" }}
{{- if .Values.priorityClassName }}
priorityClassName: {{ .Values.priorityClassName }}
{{- else if and (dig "spire" "recommendations" "enabled" false .Values.global) (dig "spire" "recommendations" "priorityClassName" true .Values.global) }}
priorityClassName: system-node-critical
{{- end }}
{{- end }}
{{- define "spire-lib.default_cluster_priority_class_name" }}
{{- if .Values.priorityClassName }}
priorityClassName: {{ .Values.priorityClassName }}
{{- else if and (dig "spire" "recommendations" "enabled" false .Values.global) (dig "spire" "recommendations" "priorityClassName" true .Values.global) }}
priorityClassName: system-cluster-critical
{{- end }}
{{- end }}
{{/*
Use autoscaling/v2 (Kubernetes 1.23 and newer) or autoscaling/v2beta2 (Kubernetes 1.12-1.25) based on cluster capabilities.
Anything lower has an incompatible API.
*/}}
{{- define "spire-lib.autoscalingVersion" -}}
{{- if (.Capabilities.APIVersions.Has "autoscaling/v2") }}
{{- print "autoscaling/v2" }}
{{- else if (.Capabilities.APIVersions.Has "autoscaling/v2beta2") }}
{{- print "autoscaling/v2beta2" }}
{{- else }}
{{- fail "Unsupported autoscaling API version" }}
{{- end }}
{{- end }}
@@ -0,0 +1,5 @@
{{- define "spire-lib.namespaces" }}
{{- include "spire-lib.namespace.system" . }}
---
{{- include "spire-lib.namespace.server" . }}
{{- end }}
@@ -0,0 +1,32 @@
{{- define "spire-lib.namespace.default_server_labels" }}
"pod-security.kubernetes.io/warn": restricted
"pod-security.kubernetes.io/audit": restricted
"pod-security.kubernetes.io/enforce": restricted
{{- end }}
{{- define "spire-lib.namespace.server" }}
{{- if or .Values.global.spire.namespaces.create .Values.global.spire.namespaces.server.create }}
{{- $labels := dict }}
{{- if and (dig "spire" "recommendations" "enabled" false .Values.global) (dig "spire" "recommendations" "namespacePSS" true .Values.global) }}
{{- $labels = mergeOverwrite $labels (include "spire-lib.namespace.default_server_labels" . | fromYaml) }}
{{- if (dig "openshift" false .Values.global) }}
{{- $_ := set $labels "security.openshift.io/scc.podSecurityLabelSync" "false" }}
{{- if (index .Values "spiffe-oidc-discovery-provider").enabled }}
{{- $_ := set $labels "pod-security.kubernetes.io/enforce" "privileged" }}
{{- end }}
{{- end }}
{{- end }}
{{- $labels = mergeOverwrite $labels .Values.global.spire.namespaces.server.labels }}
apiVersion: v1
kind: Namespace
metadata:
name: {{ .Values.global.spire.namespaces.server.name }}
{{- with $labels }}
labels:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.global.spire.namespaces.server.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{- end }}
@@ -0,0 +1,29 @@
{{- define "spire-lib.namespace.default_system_labels" }}
"pod-security.kubernetes.io/warn": privileged
"pod-security.kubernetes.io/audit": privileged
"pod-security.kubernetes.io/enforce": privileged
{{- end }}
{{- define "spire-lib.namespace.system" }}
{{- if or .Values.global.spire.namespaces.create .Values.global.spire.namespaces.system.create }}
{{- $labels := dict }}
{{- if and (dig "spire" "recommendations" "enabled" false .Values.global) (dig "spire" "recommendations" "namespacePSS" true .Values.global) }}
{{- $labels = mergeOverwrite $labels (include "spire-lib.namespace.default_system_labels" . | fromYaml) }}
{{- if (dig "openshift" false .Values.global) }}
{{- $_ := set $labels "security.openshift.io/scc.podSecurityLabelSync" "false" }}
{{- end }}
{{- end }}
{{- $labels = mergeOverwrite $labels .Values.global.spire.namespaces.server.labels }}
apiVersion: v1
kind: Namespace
metadata:
name: {{ .Values.global.spire.namespaces.system.name }}
{{- with $labels }}
labels:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.global.spire.namespaces.system.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{- end }}
@@ -0,0 +1,8 @@
# Default values for spire-lib.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
## It is required by CI/CD tools and processes.
## @skip exampleValue
##
exampleValue: spire-lib