AB#2554 GCP CSI driver deployment (#532)

* Allow enabling/disabling of CSI driver through config

* Fix inconsistent namespace parsing

* Deploy GCP CSI driver on init

* Update invalid pod tolerations

* Add generate script for CSI charts

* Update generateCilium script

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
Daniel Weiße 2022-11-18 10:05:02 +01:00 committed by GitHub
parent 6b7e470983
commit b966f57a2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 1597 additions and 165 deletions

View File

@ -23,6 +23,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Environment variable `CONSTELL_AZURE_CLIENT_SECRET_VALUE` as an alternative way to provide the configuration value `provider.azure.clientSecretValue`. - Environment variable `CONSTELL_AZURE_CLIENT_SECRET_VALUE` as an alternative way to provide the configuration value `provider.azure.clientSecretValue`.
- GCP CSI driver deployment during Constellation init
### Changed ### Changed
<!-- For changes in existing functionality. --> <!-- For changes in existing functionality. -->

View File

@ -117,7 +117,7 @@ func initialize(cmd *cobra.Command, newDialer func(validator *cloudcmd.Validator
return fmt.Errorf("parsing or generating master secret from file %s: %w", flags.masterSecretPath, err) return fmt.Errorf("parsing or generating master secret from file %s: %w", flags.masterSecretPath, err)
} }
helmLoader := helm.New(provider, k8sVersion) helmLoader := helm.New(provider, k8sVersion)
helmDeployments, err := helmLoader.Load(provider, flags.conformance, masterSecret.Key, masterSecret.Salt, getEnforcedPCRs(provider, conf), getEnforceIDKeyDigest(provider, conf)) helmDeployments, err := helmLoader.Load(conf, flags.conformance, masterSecret.Key, masterSecret.Salt)
if err != nil { if err != nil {
return fmt.Errorf("loading Helm charts: %w", err) return fmt.Errorf("loading Helm charts: %w", err)
} }
@ -133,8 +133,8 @@ func initialize(cmd *cobra.Command, newDialer func(validator *cloudcmd.Validator
CloudServiceAccountUri: serviceAccURI, CloudServiceAccountUri: serviceAccURI,
KubernetesVersion: conf.KubernetesVersion, KubernetesVersion: conf.KubernetesVersion,
HelmDeployments: helmDeployments, HelmDeployments: helmDeployments,
EnforcedPcrs: getEnforcedPCRs(provider, conf), EnforcedPcrs: conf.GetEnforcedPCRs(),
EnforceIdkeydigest: getEnforceIDKeyDigest(provider, conf), EnforceIdkeydigest: conf.EnforcesIDKeyDigest(),
ConformanceMode: flags.conformance, ConformanceMode: flags.conformance,
} }
resp, err := initCall(cmd.Context(), newDialer(validator), idFile.IP, req) resp, err := initCall(cmd.Context(), newDialer(validator), idFile.IP, req)
@ -219,30 +219,6 @@ func writeRow(wr io.Writer, col1 string, col2 string) {
fmt.Fprint(wr, col1, "\t", col2, "\n") fmt.Fprint(wr, col1, "\t", col2, "\n")
} }
func getEnforcedPCRs(provider cloudprovider.Provider, config *config.Config) []uint32 {
switch provider {
case cloudprovider.AWS:
return config.Provider.AWS.EnforcedMeasurements
case cloudprovider.Azure:
return config.Provider.Azure.EnforcedMeasurements
case cloudprovider.GCP:
return config.Provider.GCP.EnforcedMeasurements
case cloudprovider.QEMU:
return config.Provider.QEMU.EnforcedMeasurements
default:
return nil
}
}
func getEnforceIDKeyDigest(provider cloudprovider.Provider, config *config.Config) bool {
switch provider {
case cloudprovider.Azure:
return *config.Provider.Azure.EnforceIDKeyDigest
default:
return false
}
}
// evalFlagArgs gets the flag values and does preprocessing of these values like // evalFlagArgs gets the flag values and does preprocessing of these values like
// reading the content from file path flags and deriving other values from flag combinations. // reading the content from file path flags and deriving other values from flag combinations.
func evalFlagArgs(cmd *cobra.Command) (initFlags, error) { func evalFlagArgs(cmd *cobra.Command) (initFlags, error) {

View File

@ -35,3 +35,13 @@ dependencies:
- Azure - Azure
- GCP - GCP
- AWS - AWS
- name: gcp-compute-persistent-disk-csi-driver
version: 1.0.1
condition: gcp.deployCSIDriver
tags:
- GCP
- name: csi-azuredisk
version: 1.0.1
condition: azure.deployCSIDriver
tags:
- Azure

View File

@ -14,4 +14,4 @@ roleRef:
subjects: subjects:
- kind: ServiceAccount - kind: ServiceAccount
name: constellation-cluster-autoscaler name: constellation-cluster-autoscaler
namespace: kube-system namespace: {{ .Release.Namespace }}

View File

@ -45,8 +45,7 @@ spec:
operator: Exists operator: Exists
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/master key: node-role.kubernetes.io/master
operator: Equal operator: Exists
value: "true"
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/control-plane key: node-role.kubernetes.io/control-plane
operator: Exists operator: Exists

View File

@ -0,0 +1,5 @@
apiVersion: v2
appVersion: "v1.0.1"
description: Azure disk Container Storage Interface (CSI) Storage Plugin with on-node encryption support
name: csi-azuredisk
version: v1.0.1

View File

@ -0,0 +1,5 @@
apiVersion: v2
version: 1.0.1
appVersion: "v1.0.1"
description: GCP Compute Persistent Disk Container Storage Interface (CSI) Storage Plugin with on-node encryption support
name: gcp-compute-persistent-disk-csi-driver

View File

@ -0,0 +1,308 @@
##### Node Service Account, Roles, RoleBindings
apiVersion: v1
kind: ServiceAccount
metadata:
name: csi-gce-pd-node-sa
namespace: {{ .Release.Namespace }}
---
##### Controller Service Account, Roles, Rolebindings
apiVersion: v1
kind: ServiceAccount
metadata:
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
---
# xref: https://github.com/kubernetes-csi/external-provisioner/blob/master/deploy/kubernetes/rbac.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-provisioner-role
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
- apiGroups: ["storage.k8s.io"]
resources: ["csinodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshots"]
verbs: ["get", "list"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents"]
verbs: ["get", "list"]
# Access to volumeattachments is only needed when the CSI driver
# has the PUBLISH_UNPUBLISH_VOLUME controller capability.
# In that case, external-provisioner will watch volumeattachments
# to determine when it is safe to delete a volume.
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments"]
verbs: ["get", "list", "watch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-provisioner-binding
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: csi-gce-pd-provisioner-role
apiGroup: rbac.authorization.k8s.io
---
# xref: https://github.com/kubernetes-csi/external-attacher/blob/master/deploy/kubernetes/rbac.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-attacher-role
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: ["storage.k8s.io"]
resources: ["csinodes"]
verbs: ["get", "list", "watch"]
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments/status"]
verbs: ["patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-attacher-binding
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: csi-gce-pd-attacher-role
apiGroup: rbac.authorization.k8s.io
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: csi-gce-pd-controller
value: 900000000
globalDefault: false
description: "This priority class should be used for the GCE PD CSI driver controller deployment only."
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: csi-gce-pd-node
value: 900001000
globalDefault: false
description: "This priority class should be used for the GCE PD CSI driver node deployment only."
---
# Resizer must be able to work with PVCs, PVs, SCs.
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-resizer-role
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["persistentvolumeclaims/status"]
verbs: ["update", "patch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
# If handle-volume-inuse-error=true, the pod specific rbac is needed
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-resizer-binding
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: csi-gce-pd-resizer-role
apiGroup: rbac.authorization.k8s.io
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-deploy
rules:
- apiGroups: ["policy"]
resources: ["podsecuritypolicies"]
verbs: ["use"]
resourceNames:
- csi-gce-pd-controller-psp
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: csi-gce-pd-controller-deploy
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: csi-gce-pd-controller-deploy
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-node-deploy
rules:
- apiGroups: ['policy']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames:
- csi-gce-pd-node-psp
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: csi-gce-pd-node
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: csi-gce-pd-node-deploy
subjects:
- kind: ServiceAccount
name: csi-gce-pd-node-sa
namespace: {{ .Release.Namespace }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: csi-gce-pd-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: csi-gce-pd-node-deploy
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csi-gce-pd-snapshotter-role
rules:
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
# Secrets resource omitted since GCE PD snapshots does not require them
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents"]
verbs: ["create", "get", "list", "watch", "update", "delete", "patch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents/status"]
verbs: ["update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-snapshotter-binding
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: csi-gce-pd-snapshotter-role
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-leaderelection-role
namespace: {{ .Release.Namespace }}
labels:
k8s-app: gcp-compute-persistent-disk-csi-driver
rules:
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["get", "watch", "list", "delete", "update", "create"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-leaderelection-binding
namespace: {{ .Release.Namespace }}
labels:
k8s-app: gcp-compute-persistent-disk-csi-driver
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
roleRef:
kind: Role
name: csi-gce-pd-leaderelection-role
apiGroup: rbac.authorization.k8s.io

View File

@ -0,0 +1,175 @@
kind: Deployment
apiVersion: apps/v1
metadata:
name: csi-gce-pd-controller
namespace: {{ .Release.Namespace }}
spec:
replicas: {{ .Values.csiController.replicas }}
selector:
matchLabels:
app: gcp-compute-persistent-disk-csi-driver
template:
metadata:
labels:
app: gcp-compute-persistent-disk-csi-driver
spec:
{{- if .Values.csiController.runOnControlPlane }}
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
operator: Exists
- effect: NoSchedule
key: node-role.kubernetes.io/master
operator: Exists
- effect: NoSchedule
key: node.cloudprovider.kubernetes.io/uninitialized
operator: Exists
- effect: NoSchedule
key: node.kubernetes.io/not-ready
operator: Exists
{{- end }}
nodeSelector:
kubernetes.io/os: linux
{{- if .Values.csiController.runOnControlPlane }}
node-role.kubernetes.io/control-plane: ""
{{- end }}
serviceAccountName: csi-gce-pd-controller-sa
priorityClassName: csi-gce-pd-controller
containers:
- name: csi-provisioner
image: {{ .Values.image.csiProvisioner.repo }}:{{ .Values.image.csiProvisioner.tag }}
imagePullPolicy: {{ .Values.image.csiProvisioner.pullPolicy }}
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--feature-gates=Topology=true"
- "--http-endpoint=:22011"
- "--leader-election-namespace=$(PDCSI_NAMESPACE)"
- "--timeout=450s"
- "--extra-create-metadata"
# - "--run-controller-service=false" # disable the controller service of the CSI driver
# - "--run-node-service=false" # disable the node service of the CSI driver
- "--leader-election"
- "--default-fstype=ext4"
- "--controller-publish-readonly=true"
env:
- name: PDCSI_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 22011
name: http-endpoint
protocol: TCP
livenessProbe:
failureThreshold: 1
httpGet:
path: /healthz/leader-election
port: http-endpoint
initialDelaySeconds: 10
timeoutSeconds: 10
periodSeconds: 20
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: csi-attacher
image: {{ .Values.image.csiAttacher.repo }}:{{ .Values.image.csiAttacher.tag }}
imagePullPolicy: {{ .Values.image.csiAttacher.pullPolicy }}
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--http-endpoint=:22012"
- "--leader-election"
- "--leader-election-namespace=$(PDCSI_NAMESPACE)"
- "--timeout=450s"
env:
- name: PDCSI_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 22012
name: http-endpoint
protocol: TCP
livenessProbe:
failureThreshold: 1
httpGet:
path: /healthz/leader-election
port: http-endpoint
initialDelaySeconds: 10
timeoutSeconds: 10
periodSeconds: 20
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: csi-resizer
image: {{ .Values.image.csiResizer.repo }}:{{ .Values.image.csiResizer.tag }}
imagePullPolicy: {{ .Values.image.csiResizer.pullPolicy }}
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--http-endpoint=:22013"
- "--leader-election"
- "--leader-election-namespace=$(PDCSI_NAMESPACE)"
- "--handle-volume-inuse-error=false"
env:
- name: PDCSI_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 22013
name: http-endpoint
protocol: TCP
livenessProbe:
failureThreshold: 1
httpGet:
path: /healthz/leader-election
port: http-endpoint
initialDelaySeconds: 10
timeoutSeconds: 10
periodSeconds: 20
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: csi-snapshotter
image: {{ .Values.image.csiSnapshotter.repo }}:{{ .Values.image.csiSnapshotter.tag }}
imagePullPolicy: {{ .Values.image.csiSnapshotter.pullPolicy }}
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--metrics-address=:22014"
- "--leader-election"
- "--leader-election-namespace=$(PDCSI_NAMESPACE)"
- "--timeout=450s"
env:
- name: PDCSI_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: gce-pd-driver
# Don't change base image without changing pdImagePlaceholder in
# test/k8s-integration/main.go
image: {{ .Values.image.gcepdDriver.repo }}:{{ .Values.image.gcepdDriver.tag }}
imagePullPolicy: {{ .Values.image.gcepdDriver.pullPolicy }}
args:
- "--v=5"
- "--endpoint=unix:/csi/csi.sock"
env:
- name: GOOGLE_APPLICATION_CREDENTIALS
value: "/etc/cloud-sa/key.json"
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: cloud-sa-volume
readOnly: true
mountPath: "/etc/cloud-sa"
volumes:
- name: socket-dir
emptyDir: {}
- name: cloud-sa-volume
secret:
secretName: gcekey

View File

@ -0,0 +1,117 @@
kind: DaemonSet
apiVersion: apps/v1
metadata:
name: csi-gce-pd-node
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: gcp-compute-persistent-disk-csi-driver
template:
metadata:
labels:
app: gcp-compute-persistent-disk-csi-driver
spec:
priorityClassName: csi-gce-pd-node
serviceAccountName: csi-gce-pd-node-sa
nodeSelector:
kubernetes.io/os: linux
containers:
- name: csi-driver-registrar
image: {{ .Values.image.csiNodeRegistrar.repo }}:{{ .Values.image.csiNodeRegistrar.tag }}
imagePullPolicy: {{ .Values.image.csiNodeRegistrar.pullPolicy }}
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--kubelet-registration-path=/var/lib/kubelet/plugins/gcp.csi.confidential.cloud/csi.sock"
env:
- name: KUBE_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
volumeMounts:
- name: plugin-dir
mountPath: /csi
- name: registration-dir
mountPath: /registration
livenessProbe:
initialDelaySeconds: 3
exec:
command:
- /csi-node-driver-registrar
- --kubelet-registration-path=/var/lib/kubelet/plugins/gcp.csi.confidential.cloud/csi.sock
- --mode=kubelet-registration-probe
- name: gce-pd-driver
image: {{ .Values.image.gcepdDriver.repo }}:{{ .Values.image.gcepdDriver.tag }}
imagePullPolicy: {{ .Values.image.gcepdDriver.pullPolicy }}
args:
- "--v=5"
- "--endpoint=unix:/csi/csi.sock"
- "--run-controller-service=false"
- "--kms-addr=kms.{{ .Values.csiNode.kmsNamespace | default .Release.Namespace }}:{{ .Values.csiNode.kmsPort }}"
securityContext:
privileged: true
volumeMounts:
- name: kubelet-dir
mountPath: /var/lib/kubelet
mountPropagation: "Bidirectional"
- name: plugin-dir
mountPath: /csi
- name: device-dir
mountPath: /dev
# The following mounts are required to trigger host udevadm from
# container
- name: udev-rules-etc
mountPath: /etc/udev
- name: udev-rules-lib
mountPath: /lib/udev
- name: udev-socket
mountPath: /run/udev
- name: sys
mountPath: /sys
- name: cryptsetup
mountPath: /run/cryptsetup
volumes:
- name: registration-dir
hostPath:
path: /var/lib/kubelet/plugins_registry/
type: Directory
- name: kubelet-dir
hostPath:
path: /var/lib/kubelet
type: Directory
- name: plugin-dir
hostPath:
path: /var/lib/kubelet/plugins/gcp.csi.confidential.cloud/
type: DirectoryOrCreate
- name: device-dir
hostPath:
path: /dev
type: Directory
# The following mounts are required to trigger host udevadm from
# container
- name: udev-rules-etc
hostPath:
path: /etc/udev
type: Directory
- name: udev-rules-lib
hostPath:
path: /lib/udev
type: Directory
- name: udev-socket
hostPath:
path: /run/udev
type: Directory
- name: sys
hostPath:
path: /sys
type: Directory
- name: cryptsetup
hostPath:
path: /run/cryptsetup
type: Directory
# https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
# See "special case". This will tolerate everything. Node component should
# be scheduled on all nodes.
tolerations:
- operator: Exists

View File

@ -0,0 +1,14 @@
{{- if .Values.createStorageClass }}
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
annotations:
storageclass.kubernetes.io/is-default-class: "true"
name: encrypted-rwo
parameters:
type: pd-standard
provisioner: gcp.csi.confidential.cloud
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: Immediate
{{- end }}

View File

@ -0,0 +1,14 @@
{{- if .Values.createStorageClass }}
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
annotations:
name: integrity-encrypted-rwo
parameters:
type: pd-ssd
csi.storage.k8s.io/fstype: ext4-integrity
provisioner: gcp.csi.confidential.cloud
allowVolumeExpansion: false
reclaimPolicy: Delete
volumeBindingMode: Immediate
{{- end }}

View File

@ -0,0 +1,7 @@
apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
name: gcp.csi.confidential.cloud
spec:
attachRequired: true
podInfoOnMount: false

View File

@ -0,0 +1,36 @@
image:
csiProvisioner:
repo: k8s.gcr.io/sig-storage/csi-provisioner
tag: "v3.1.0"
pullPolicy: IfNotPresent
csiAttacher:
repo: k8s.gcr.io/sig-storage/csi-attacher
tag: "v3.4.0"
pullPolicy: IfNotPresent
csiResizer:
repo: k8s.gcr.io/sig-storage/csi-resizer
tag: "v1.4.0"
pullPolicy: IfNotPresent
csiSnapshotter:
repo: k8s.gcr.io/sig-storage/csi-snapshotter
tag: "v4.0.1"
pullPolicy: IfNotPresent
csiNodeRegistrar:
repo: k8s.gcr.io/sig-storage/csi-node-driver-registrar
tag: "v2.5.0"
pullPolicy: IfNotPresent
gcepdDriver:
repo: ghcr.io/edgelesssys/constellation/gcp-csi-driver
# CSI driver version is independent of Constellation releases
tag: "v1.0.0"
pullPolicy: IfNotPresent
csiController:
replicas: 1
runOnControlPlane: true
csiNode:
kmsPort: "9000"
kmsNamespace: "kube-system"
createStorageClass: true

View File

@ -2,7 +2,7 @@ apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: join-config name: join-config
namespace: kube-system namespace: {{ .Release.Namespace }}
data: data:
# mustToJson is required so the json-strings passed from go are of type string in the rendered yaml. # mustToJson is required so the json-strings passed from go are of type string in the rendered yaml.
enforcedPCRs: {{ .Values.enforcedPCRs | mustToJson }} enforcedPCRs: {{ .Values.enforcedPCRs | mustToJson }}

View File

@ -23,8 +23,7 @@ spec:
operator: Exists operator: Exists
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/master key: node-role.kubernetes.io/master
operator: Equal operator: Exists
value: "true"
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/control-plane key: node-role.kubernetes.io/control-plane
operator: Exists operator: Exists
@ -39,7 +38,7 @@ spec:
image: {{ .Values.image }} image: {{ .Values.image }}
args: args:
- --cloud-provider={{ .Values.csp }} - --cloud-provider={{ .Values.csp }}
- --kms-endpoint=kms.kube-system:{{ .Values.global.kmsPort }} - --kms-endpoint=kms.{{ .Release.Namespace }}:{{ .Values.global.kmsPort }}
volumeMounts: volumeMounts:
- mountPath: {{ .Values.global.serviceBasePath }} - mountPath: {{ .Values.global.serviceBasePath }}
name: config name: config

View File

@ -1,5 +1,3 @@
# Namespace to which to deploy
namespace: "kube-system"
csp: "gcp" csp: "gcp"
joinServicePort: 9090 joinServicePort: 9090
joinServiceNodePort: 30090 joinServiceNodePort: 30090

View File

@ -35,8 +35,7 @@ spec:
operator: Exists operator: Exists
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/master key: node-role.kubernetes.io/master
operator: Equal operator: Exists
value: "true"
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/control-plane key: node-role.kubernetes.io/control-plane
operator: Exists operator: Exists

View File

@ -1,5 +1,3 @@
# Namespace to which KMS will be deployed.
namespace: "kube-system"
# Name of the key within the respective secret that holds the salt. # Name of the key within the respective secret that holds the salt.
saltKeyName: salt saltKeyName: salt
# Name of the secret that contains the master secret. # Name of the secret that contains the master secret.

View File

@ -10,6 +10,14 @@ global:
# Name of the ConfigMap that holds configs that should not be modified by the user. # Name of the ConfigMap that holds configs that should not be modified by the user.
internalCMName: internal-config internalCMName: internal-config
# GCP specific configuration
gcp:
deployCSIDriver: false
# Azure specific configuration
azure:
deployCSIDriver: false
# Set one of the tags to true to indicate which CSP you are deploying to. # Set one of the tags to true to indicate which CSP you are deploying to.
tags: tags:
Azure: false Azure: false

View File

@ -5,9 +5,16 @@ shopt -s inherit_errexit
calldir=$(pwd) calldir=$(pwd)
ciliumTmpDir=$(mktemp -d) ciliumTmpDir=$(mktemp -d)
cd "${ciliumTmpDir}" || exit 1 pushd "${ciliumTmpDir}"
git clone --depth 1 -b 1.12.1 https://github.com/cilium/cilium.git git clone --filter=blob:none --no-checkout --sparse --depth 1 -b 1.12.1 https://github.com/cilium/cilium.git
cd cilium || exit 1 pushd cilium
git sparse-checkout add install/kubernetes/cilium
git checkout
git apply "${calldir}"/cilium.patch git apply "${calldir}"/cilium.patch
cp -r install/kubernetes/cilium "${calldir}"/charts cp -r install/kubernetes/cilium "${calldir}"/charts
popd
popd
rm -r "${ciliumTmpDir}" rm -r "${ciliumTmpDir}"

View File

@ -18,6 +18,7 @@ import (
"strings" "strings"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/deploy/helm" "github.com/edgelesssys/constellation/v2/internal/deploy/helm"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions"
@ -30,6 +31,8 @@ import (
// Run `go generate` to deterministically create the patched Helm deployment for cilium // Run `go generate` to deterministically create the patched Helm deployment for cilium
//go:generate ./generateCilium.sh //go:generate ./generateCilium.sh
// Run `go generate` to load CSI driver charts from the CSI repositories
//go:generate ./update-csi-charts.sh
//go:embed all:charts/* //go:embed all:charts/*
var helmFS embed.FS var helmFS embed.FS
@ -66,13 +69,15 @@ func New(csp cloudprovider.Provider, k8sVersion versions.ValidK8sVersion) *Chart
} }
// Load the embedded helm charts. // Load the embedded helm charts.
func (i *ChartLoader) Load(csp cloudprovider.Provider, conformanceMode bool, masterSecret []byte, salt []byte, enforcedPCRs []uint32, enforceIDKeyDigest bool) ([]byte, error) { func (i *ChartLoader) Load(config *config.Config, conformanceMode bool, masterSecret, salt []byte) ([]byte, error) {
csp := config.GetProvider()
ciliumRelease, err := i.loadCilium(csp, conformanceMode) ciliumRelease, err := i.loadCilium(csp, conformanceMode)
if err != nil { if err != nil {
return nil, fmt.Errorf("loading cilium: %w", err) return nil, fmt.Errorf("loading cilium: %w", err)
} }
conServicesRelease, err := i.loadConstellationServices(csp, masterSecret, salt, enforcedPCRs, enforceIDKeyDigest) conServicesRelease, err := i.loadConstellationServices(config, masterSecret, salt)
if err != nil { if err != nil {
return nil, fmt.Errorf("loading constellation-services: %w", err) return nil, fmt.Errorf("loading constellation-services: %w", err)
} }
@ -122,11 +127,9 @@ func (i *ChartLoader) loadCilium(csp cloudprovider.Provider, conformanceMode boo
return helm.Release{Chart: chartRaw, Values: ciliumVals, ReleaseName: "cilium", Wait: true}, nil return helm.Release{Chart: chartRaw, Values: ciliumVals, ReleaseName: "cilium", Wait: true}, nil
} }
// loadConstellationServices loads the constellation-services chart from the embed.FS, marshals it into a helm-package .tgz and sets the values that can be set in the CLI. // loadConstellationServices loads the constellation-services chart from the embed.FS,
func (i *ChartLoader) loadConstellationServices(csp cloudprovider.Provider, // marshals it into a helm-package .tgz and sets the values that can be set in the CLI.
masterSecret []byte, salt []byte, enforcedPCRs []uint32, func (i *ChartLoader) loadConstellationServices(config *config.Config, masterSecret, salt []byte) (helm.Release, error) {
enforceIDKeyDigest bool,
) (helm.Release, error) {
chart, err := loadChartsDir(helmFS, "charts/edgeless/constellation-services") chart, err := loadChartsDir(helmFS, "charts/edgeless/constellation-services")
if err != nil { if err != nil {
return helm.Release{}, fmt.Errorf("loading constellation-services chart: %w", err) return helm.Release{}, fmt.Errorf("loading constellation-services chart: %w", err)
@ -137,11 +140,12 @@ func (i *ChartLoader) loadConstellationServices(csp cloudprovider.Provider,
return helm.Release{}, fmt.Errorf("packaging chart: %w", err) return helm.Release{}, fmt.Errorf("packaging chart: %w", err)
} }
enforcedPCRsJSON, err := json.Marshal(enforcedPCRs) enforcedPCRsJSON, err := json.Marshal(config.GetEnforcedPCRs())
if err != nil { if err != nil {
return helm.Release{}, fmt.Errorf("marshaling enforcedPCRs: %w", err) return helm.Release{}, fmt.Errorf("marshaling enforcedPCRs: %w", err)
} }
csp := config.GetProvider()
vals := map[string]any{ vals := map[string]any{
"global": map[string]any{ "global": map[string]any{
"kmsPort": constants.KMSPort, "kmsPort": constants.KMSPort,
@ -154,7 +158,6 @@ func (i *ChartLoader) loadConstellationServices(csp cloudprovider.Provider,
"image": i.kmsImage, "image": i.kmsImage,
"masterSecret": base64.StdEncoding.EncodeToString(masterSecret), "masterSecret": base64.StdEncoding.EncodeToString(masterSecret),
"salt": base64.StdEncoding.EncodeToString(salt), "salt": base64.StdEncoding.EncodeToString(salt),
"namespace": constants.ConstellationNamespace,
"saltKeyName": constants.ConstellationSaltKey, "saltKeyName": constants.ConstellationSaltKey,
"masterSecretKeyName": constants.ConstellationMasterSecretKey, "masterSecretKeyName": constants.ConstellationMasterSecretKey,
"masterSecretName": constants.ConstellationMasterSecretStoreName, "masterSecretName": constants.ConstellationMasterSecretStoreName,
@ -164,7 +167,6 @@ func (i *ChartLoader) loadConstellationServices(csp cloudprovider.Provider,
"csp": csp, "csp": csp,
"enforcedPCRs": string(enforcedPCRsJSON), "enforcedPCRs": string(enforcedPCRsJSON),
"image": i.joinServiceImage, "image": i.joinServiceImage,
"namespace": constants.ConstellationNamespace,
}, },
"ccm": map[string]any{ "ccm": map[string]any{
"csp": csp, "csp": csp,
@ -177,49 +179,61 @@ func (i *ChartLoader) loadConstellationServices(csp cloudprovider.Provider,
switch csp { switch csp {
case cloudprovider.Azure: case cloudprovider.Azure:
{ joinServiceVals, ok := vals["join-service"].(map[string]any)
joinServiceVals, ok := vals["join-service"].(map[string]any) if !ok {
if !ok { return helm.Release{}, errors.New("invalid join-service values")
return helm.Release{}, errors.New("invalid join-service values")
}
joinServiceVals["enforceIdKeyDigest"] = enforceIDKeyDigest
ccmVals, ok := vals["ccm"].(map[string]any)
if !ok {
return helm.Release{}, errors.New("invalid ccm values")
}
ccmVals["Azure"] = map[string]any{
"image": i.ccmImage,
}
vals["cnm"] = map[string]any{
"image": i.cnmImage,
}
vals["tags"] = map[string]any{
"Azure": true,
}
} }
joinServiceVals["enforceIdKeyDigest"] = config.EnforcesIDKeyDigest()
ccmVals, ok := vals["ccm"].(map[string]any)
if !ok {
return helm.Release{}, errors.New("invalid ccm values")
}
ccmVals["Azure"] = map[string]any{
"image": i.ccmImage,
}
vals["cnm"] = map[string]any{
"image": i.cnmImage,
}
vals["azure"] = map[string]any{
"deployCSIDriver": config.DeployCSIDriver(),
}
vals["tags"] = map[string]any{
"Azure": true,
}
case cloudprovider.GCP: case cloudprovider.GCP:
{ ccmVals, ok := vals["ccm"].(map[string]any)
ccmVals, ok := vals["ccm"].(map[string]any) if !ok {
if !ok { return helm.Release{}, errors.New("invalid ccm values")
return helm.Release{}, errors.New("invalid ccm values") }
} ccmVals["GCP"] = map[string]any{
ccmVals["GCP"] = map[string]any{ "image": i.ccmImage,
"image": i.ccmImage, }
}
vals["tags"] = map[string]any{ vals["gcp"] = map[string]any{
"GCP": true, "deployCSIDriver": config.DeployCSIDriver(),
}
} }
vals["gcp-compute-persistent-disk-csi-driver"] = map[string]any{
"csiNode": map[string]any{
"kmsPort": constants.KMSPort,
"kmsNamespace": "", // empty namespace means we use the release namespace
},
}
vals["tags"] = map[string]any{
"GCP": true,
}
case cloudprovider.QEMU: case cloudprovider.QEMU:
{ vals["tags"] = map[string]interface{}{
vals["tags"] = map[string]interface{}{ "QEMU": true,
"QEMU": true,
}
} }
case cloudprovider.AWS: case cloudprovider.AWS:
ccmVals, ok := vals["ccm"].(map[string]any) ccmVals, ok := vals["ccm"].(map[string]any)
if !ok { if !ok {

View File

@ -15,7 +15,7 @@ import (
"path" "path"
"testing" "testing"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/deploy/helm" "github.com/edgelesssys/constellation/v2/internal/deploy/helm"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -31,7 +31,8 @@ func TestLoad(t *testing.T) {
require := require.New(t) require := require.New(t)
chartLoader := ChartLoader{} chartLoader := ChartLoader{}
release, err := chartLoader.Load(cloudprovider.GCP, true, []byte("secret"), []byte("salt"), nil, false) config := &config.Config{Provider: config.ProviderConfig{GCP: &config.GCPConfig{}}}
release, err := chartLoader.Load(config, true, []byte("secret"), []byte("salt"))
require.NoError(err) require.NoError(err)
var helmReleases helm.Releases var helmReleases helm.Releases
@ -46,27 +47,35 @@ func TestLoad(t *testing.T) {
// TestTemplate checks if the rendered constellation-services chart produces the expected yaml files. // TestTemplate checks if the rendered constellation-services chart produces the expected yaml files.
func TestTemplate(t *testing.T) { func TestTemplate(t *testing.T) {
testCases := map[string]struct { testCases := map[string]struct {
csp cloudprovider.Provider config *config.Config
enforceIDKeyDigest bool enforceIDKeyDigest bool
valuesModifier func(map[string]any) error valuesModifier func(map[string]any) error
ccmImage string ccmImage string
cnmImage string cnmImage string
}{ }{
"GCP": { "GCP": {
csp: cloudprovider.GCP, config: &config.Config{Provider: config.ProviderConfig{GCP: &config.GCPConfig{
DeployCSIDriver: func() *bool { b := true; return &b }(),
EnforcedMeasurements: []uint32{1, 11},
}}},
enforceIDKeyDigest: false, enforceIDKeyDigest: false,
valuesModifier: prepareGCPValues, valuesModifier: prepareGCPValues,
ccmImage: "ccmImageForGCP", ccmImage: "ccmImageForGCP",
}, },
"Azure": { "Azure": {
csp: cloudprovider.Azure, config: &config.Config{Provider: config.ProviderConfig{Azure: &config.AzureConfig{
EnforcedMeasurements: []uint32{1, 11},
EnforceIDKeyDigest: func() *bool { b := true; return &b }(),
}}},
enforceIDKeyDigest: true, enforceIDKeyDigest: true,
valuesModifier: prepareAzureValues, valuesModifier: prepareAzureValues,
ccmImage: "ccmImageForAzure", ccmImage: "ccmImageForAzure",
cnmImage: "cnmImageForAzure", cnmImage: "cnmImageForAzure",
}, },
"QEMU": { "QEMU": {
csp: cloudprovider.QEMU, config: &config.Config{Provider: config.ProviderConfig{QEMU: &config.QEMUConfig{
EnforcedMeasurements: []uint32{1, 11},
}}},
enforceIDKeyDigest: false, enforceIDKeyDigest: false,
valuesModifier: prepareQEMUValues, valuesModifier: prepareQEMUValues,
}, },
@ -78,7 +87,7 @@ func TestTemplate(t *testing.T) {
require := require.New(t) require := require.New(t)
chartLoader := ChartLoader{joinServiceImage: "joinServiceImage", kmsImage: "kmsImage", ccmImage: tc.ccmImage, cnmImage: tc.cnmImage, autoscalerImage: "autoscalerImage"} chartLoader := ChartLoader{joinServiceImage: "joinServiceImage", kmsImage: "kmsImage", ccmImage: tc.ccmImage, cnmImage: tc.cnmImage, autoscalerImage: "autoscalerImage"}
release, err := chartLoader.Load(tc.csp, true, []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), []uint32{1, 11}, tc.enforceIDKeyDigest) release, err := chartLoader.Load(tc.config, true, []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
require.NoError(err) require.NoError(err)
var helmReleases helm.Releases var helmReleases helm.Releases
@ -110,7 +119,7 @@ func TestTemplate(t *testing.T) {
result, err := engine.Render(chart, valuesToRender) result, err := engine.Render(chart, valuesToRender)
require.NoError(err) require.NoError(err)
for k, v := range result { for k, v := range result {
currentFile := path.Join("testdata", tc.csp.String(), k) currentFile := path.Join("testdata", tc.config.GetProvider().String(), k)
content, err := os.ReadFile(currentFile) content, err := os.ReadFile(currentFile)
// If a file does not exist, we expect the render for that path to be empty. // If a file does not exist, we expect the render for that path to be empty.
@ -142,6 +151,45 @@ func prepareGCPValues(values map[string]any) error {
ccmVals["GCP"].(map[string]any)["uid"] = "242424242424" ccmVals["GCP"].(map[string]any)["uid"] = "242424242424"
ccmVals["GCP"].(map[string]any)["secretData"] = "baaaaaad" ccmVals["GCP"].(map[string]any)["secretData"] = "baaaaaad"
testTag := "v0.0.0"
pullPolicy := "IfNotPresent"
csiVals, ok := values["gcp-compute-persistent-disk-csi-driver"].(map[string]any)
if !ok {
return errors.New("missing 'gcp-compute-persistent-disk-csi-driver' key")
}
csiVals["image"] = map[string]any{
"csiProvisioner": map[string]any{
"repo": "csi-provisioner",
"tag": testTag,
"pullPolicy": pullPolicy,
},
"csiAttacher": map[string]any{
"repo": "csi-attacher",
"tag": testTag,
"pullPolicy": pullPolicy,
},
"csiResizer": map[string]any{
"repo": "csi-resizer",
"tag": testTag,
"pullPolicy": pullPolicy,
},
"csiSnapshotter": map[string]any{
"repo": "csi-snapshotter",
"tag": testTag,
"pullPolicy": pullPolicy,
},
"csiNodeRegistrar": map[string]any{
"repo": "csi-registrar",
"tag": testTag,
"pullPolicy": pullPolicy,
},
"gcepdDriver": map[string]any{
"repo": "csi-driver",
"tag": testTag,
"pullPolicy": pullPolicy,
},
}
return nil return nil
} }

View File

@ -14,4 +14,4 @@ roleRef:
subjects: subjects:
- kind: ServiceAccount - kind: ServiceAccount
name: constellation-cluster-autoscaler name: constellation-cluster-autoscaler
namespace: kube-system namespace: testNamespace

View File

@ -45,8 +45,7 @@ spec:
operator: Exists operator: Exists
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/master key: node-role.kubernetes.io/master
operator: Equal operator: Exists
value: "true"
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/control-plane key: node-role.kubernetes.io/control-plane
operator: Exists operator: Exists

View File

@ -2,7 +2,7 @@ apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: join-config name: join-config
namespace: kube-system namespace: testNamespace
data: data:
enforcedPCRs: "[1,11]" enforcedPCRs: "[1,11]"
measurements: "{'1':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA','15':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='}" measurements: "{'1':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA','15':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='}"

View File

@ -23,8 +23,7 @@ spec:
operator: Exists operator: Exists
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/master key: node-role.kubernetes.io/master
operator: Equal operator: Exists
value: "true"
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/control-plane key: node-role.kubernetes.io/control-plane
operator: Exists operator: Exists
@ -39,7 +38,7 @@ spec:
image: joinServiceImage image: joinServiceImage
args: args:
- --cloud-provider=Azure - --cloud-provider=Azure
- --kms-endpoint=kms.kube-system:9000 - --kms-endpoint=kms.testNamespace:9000
volumeMounts: volumeMounts:
- mountPath: /var/config - mountPath: /var/config
name: config name: config

View File

@ -35,8 +35,7 @@ spec:
operator: Exists operator: Exists
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/master key: node-role.kubernetes.io/master
operator: Equal operator: Exists
value: "true"
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/control-plane key: node-role.kubernetes.io/control-plane
operator: Exists operator: Exists

View File

@ -14,4 +14,4 @@ roleRef:
subjects: subjects:
- kind: ServiceAccount - kind: ServiceAccount
name: constellation-cluster-autoscaler name: constellation-cluster-autoscaler
namespace: kube-system namespace: testNamespace

View File

@ -0,0 +1,297 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: csi-gce-pd-node-sa
namespace: testNamespace
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: csi-gce-pd-controller-sa
namespace: testNamespace
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-provisioner-role
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
- apiGroups: ["storage.k8s.io"]
resources: ["csinodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshots"]
verbs: ["get", "list"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents"]
verbs: ["get", "list"]
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments"]
verbs: ["get", "list", "watch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-provisioner-binding
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: testNamespace
roleRef:
kind: ClusterRole
name: csi-gce-pd-provisioner-role
apiGroup: rbac.authorization.k8s.io
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-attacher-role
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: ["storage.k8s.io"]
resources: ["csinodes"]
verbs: ["get", "list", "watch"]
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments/status"]
verbs: ["patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-attacher-binding
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: testNamespace
roleRef:
kind: ClusterRole
name: csi-gce-pd-attacher-role
apiGroup: rbac.authorization.k8s.io
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: csi-gce-pd-controller
value: 900000000
globalDefault: false
description: "This priority class should be used for the GCE PD CSI driver controller deployment only."
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: csi-gce-pd-node
value: 900001000
globalDefault: false
description: "This priority class should be used for the GCE PD CSI driver node deployment only."
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-resizer-role
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["persistentvolumeclaims/status"]
verbs: ["update", "patch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-resizer-binding
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: testNamespace
roleRef:
kind: ClusterRole
name: csi-gce-pd-resizer-role
apiGroup: rbac.authorization.k8s.io
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-deploy
rules:
- apiGroups: ["policy"]
resources: ["podsecuritypolicies"]
verbs: ["use"]
resourceNames:
- csi-gce-pd-controller-psp
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: csi-gce-pd-controller-deploy
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: csi-gce-pd-controller-deploy
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: testNamespace
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-node-deploy
rules:
- apiGroups: ['policy']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames:
- csi-gce-pd-node-psp
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: csi-gce-pd-node
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: csi-gce-pd-node-deploy
subjects:
- kind: ServiceAccount
name: csi-gce-pd-node-sa
namespace: testNamespace
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: csi-gce-pd-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: csi-gce-pd-node-deploy
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: testNamespace
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csi-gce-pd-snapshotter-role
rules:
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents"]
verbs: ["create", "get", "list", "watch", "update", "delete", "patch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents/status"]
verbs: ["update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-snapshotter-binding
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: testNamespace
roleRef:
kind: ClusterRole
name: csi-gce-pd-snapshotter-role
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-leaderelection-role
namespace: testNamespace
labels:
k8s-app: gcp-compute-persistent-disk-csi-driver
rules:
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["get", "watch", "list", "delete", "update", "create"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-leaderelection-binding
namespace: testNamespace
labels:
k8s-app: gcp-compute-persistent-disk-csi-driver
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: testNamespace
roleRef:
kind: Role
name: csi-gce-pd-leaderelection-role
apiGroup: rbac.authorization.k8s.io

View File

@ -0,0 +1,167 @@
kind: Deployment
apiVersion: apps/v1
metadata:
name: csi-gce-pd-controller
namespace: testNamespace
spec:
replicas: 1
selector:
matchLabels:
app: gcp-compute-persistent-disk-csi-driver
template:
metadata:
labels:
app: gcp-compute-persistent-disk-csi-driver
spec:
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
operator: Exists
- effect: NoSchedule
key: node-role.kubernetes.io/master
operator: Exists
- effect: NoSchedule
key: node.cloudprovider.kubernetes.io/uninitialized
operator: Exists
- effect: NoSchedule
key: node.kubernetes.io/not-ready
operator: Exists
nodeSelector:
node-role.kubernetes.io/control-plane: ""
kubernetes.io/os: linux
serviceAccountName: csi-gce-pd-controller-sa
priorityClassName: csi-gce-pd-controller
containers:
- name: csi-provisioner
image: csi-provisioner:v0.0.0
imagePullPolicy: IfNotPresent
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--feature-gates=Topology=true"
- "--http-endpoint=:22011"
- "--leader-election-namespace=$(PDCSI_NAMESPACE)"
- "--timeout=450s"
- "--extra-create-metadata"
- "--leader-election"
- "--default-fstype=ext4"
- "--controller-publish-readonly=true"
env:
- name: PDCSI_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 22011
name: http-endpoint
protocol: TCP
livenessProbe:
failureThreshold: 1
httpGet:
path: /healthz/leader-election
port: http-endpoint
initialDelaySeconds: 10
timeoutSeconds: 10
periodSeconds: 20
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: csi-attacher
image: csi-attacher:v0.0.0
imagePullPolicy: IfNotPresent
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--http-endpoint=:22012"
- "--leader-election"
- "--leader-election-namespace=$(PDCSI_NAMESPACE)"
- "--timeout=450s"
env:
- name: PDCSI_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 22012
name: http-endpoint
protocol: TCP
livenessProbe:
failureThreshold: 1
httpGet:
path: /healthz/leader-election
port: http-endpoint
initialDelaySeconds: 10
timeoutSeconds: 10
periodSeconds: 20
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: csi-resizer
image: csi-resizer:v0.0.0
imagePullPolicy: IfNotPresent
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--http-endpoint=:22013"
- "--leader-election"
- "--leader-election-namespace=$(PDCSI_NAMESPACE)"
- "--handle-volume-inuse-error=false"
env:
- name: PDCSI_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 22013
name: http-endpoint
protocol: TCP
livenessProbe:
failureThreshold: 1
httpGet:
path: /healthz/leader-election
port: http-endpoint
initialDelaySeconds: 10
timeoutSeconds: 10
periodSeconds: 20
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: csi-snapshotter
image: csi-snapshotter:v0.0.0
imagePullPolicy: IfNotPresent
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--metrics-address=:22014"
- "--leader-election"
- "--leader-election-namespace=$(PDCSI_NAMESPACE)"
- "--timeout=450s"
env:
- name: PDCSI_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: gce-pd-driver
image: csi-driver:v0.0.0
imagePullPolicy: IfNotPresent
args:
- "--v=5"
- "--endpoint=unix:/csi/csi.sock"
env:
- name: GOOGLE_APPLICATION_CREDENTIALS
value: "/etc/cloud-sa/key.json"
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: cloud-sa-volume
readOnly: true
mountPath: "/etc/cloud-sa"
volumes:
- name: socket-dir
emptyDir: {}
- name: cloud-sa-volume
secret:
secretName: gcekey

View File

@ -0,0 +1,110 @@
kind: DaemonSet
apiVersion: apps/v1
metadata:
name: csi-gce-pd-node
namespace: testNamespace
spec:
selector:
matchLabels:
app: gcp-compute-persistent-disk-csi-driver
template:
metadata:
labels:
app: gcp-compute-persistent-disk-csi-driver
spec:
priorityClassName: csi-gce-pd-node
serviceAccountName: csi-gce-pd-node-sa
nodeSelector:
kubernetes.io/os: linux
containers:
- name: csi-driver-registrar
image: csi-registrar:v0.0.0
imagePullPolicy: IfNotPresent
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--kubelet-registration-path=/var/lib/kubelet/plugins/gcp.csi.confidential.cloud/csi.sock"
env:
- name: KUBE_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
volumeMounts:
- name: plugin-dir
mountPath: /csi
- name: registration-dir
mountPath: /registration
livenessProbe:
initialDelaySeconds: 3
exec:
command:
- /csi-node-driver-registrar
- --kubelet-registration-path=/var/lib/kubelet/plugins/gcp.csi.confidential.cloud/csi.sock
- --mode=kubelet-registration-probe
- name: gce-pd-driver
image: csi-driver:v0.0.0
imagePullPolicy: IfNotPresent
args:
- "--v=5"
- "--endpoint=unix:/csi/csi.sock"
- "--run-controller-service=false"
- "--kms-addr=kms.testNamespace:9000"
securityContext:
privileged: true
volumeMounts:
- name: kubelet-dir
mountPath: /var/lib/kubelet
mountPropagation: "Bidirectional"
- name: plugin-dir
mountPath: /csi
- name: device-dir
mountPath: /dev
- name: udev-rules-etc
mountPath: /etc/udev
- name: udev-rules-lib
mountPath: /lib/udev
- name: udev-socket
mountPath: /run/udev
- name: sys
mountPath: /sys
- name: cryptsetup
mountPath: /run/cryptsetup
volumes:
- name: registration-dir
hostPath:
path: /var/lib/kubelet/plugins_registry/
type: Directory
- name: kubelet-dir
hostPath:
path: /var/lib/kubelet
type: Directory
- name: plugin-dir
hostPath:
path: /var/lib/kubelet/plugins/gcp.csi.confidential.cloud/
type: DirectoryOrCreate
- name: device-dir
hostPath:
path: /dev
type: Directory
- name: udev-rules-etc
hostPath:
path: /etc/udev
type: Directory
- name: udev-rules-lib
hostPath:
path: /lib/udev
type: Directory
- name: udev-socket
hostPath:
path: /run/udev
type: Directory
- name: sys
hostPath:
path: /sys
type: Directory
- name: cryptsetup
hostPath:
path: /run/cryptsetup
type: Directory
tolerations:
- operator: Exists

View File

@ -0,0 +1,12 @@
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
annotations:
storageclass.kubernetes.io/is-default-class: "true"
name: encrypted-rwo
parameters:
type: pd-standard
provisioner: gcp.csi.confidential.cloud
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: Immediate

View File

@ -0,0 +1,12 @@
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
annotations:
name: integrity-encrypted-rwo
parameters:
type: pd-ssd
csi.storage.k8s.io/fstype: ext4-integrity
provisioner: gcp.csi.confidential.cloud
allowVolumeExpansion: false
reclaimPolicy: Delete
volumeBindingMode: Immediate

View File

@ -0,0 +1,7 @@
apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
name: gcp.csi.confidential.cloud
spec:
attachRequired: true
podInfoOnMount: false

View File

@ -2,7 +2,7 @@ apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: join-config name: join-config
namespace: kube-system namespace: testNamespace
data: data:
enforcedPCRs: "[1,11]" enforcedPCRs: "[1,11]"
measurements: "{'1':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA','15':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='}" measurements: "{'1':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA','15':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='}"

View File

@ -23,8 +23,7 @@ spec:
operator: Exists operator: Exists
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/master key: node-role.kubernetes.io/master
operator: Equal operator: Exists
value: "true"
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/control-plane key: node-role.kubernetes.io/control-plane
operator: Exists operator: Exists
@ -39,7 +38,7 @@ spec:
image: joinServiceImage image: joinServiceImage
args: args:
- --cloud-provider=GCP - --cloud-provider=GCP
- --kms-endpoint=kms.kube-system:9000 - --kms-endpoint=kms.testNamespace:9000
volumeMounts: volumeMounts:
- mountPath: /var/config - mountPath: /var/config
name: config name: config

View File

@ -35,8 +35,7 @@ spec:
operator: Exists operator: Exists
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/master key: node-role.kubernetes.io/master
operator: Equal operator: Exists
value: "true"
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/control-plane key: node-role.kubernetes.io/control-plane
operator: Exists operator: Exists

View File

@ -2,7 +2,7 @@ apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: join-config name: join-config
namespace: kube-system namespace: testNamespace
data: data:
enforcedPCRs: "[1,11]" enforcedPCRs: "[1,11]"
measurements: "{'1':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA','15':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='}" measurements: "{'1':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA','15':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='}"

View File

@ -23,8 +23,7 @@ spec:
operator: Exists operator: Exists
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/master key: node-role.kubernetes.io/master
operator: Equal operator: Exists
value: "true"
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/control-plane key: node-role.kubernetes.io/control-plane
operator: Exists operator: Exists
@ -39,7 +38,7 @@ spec:
image: joinServiceImage image: joinServiceImage
args: args:
- --cloud-provider=QEMU - --cloud-provider=QEMU
- --kms-endpoint=kms.kube-system:9000 - --kms-endpoint=kms.testNamespace:9000
volumeMounts: volumeMounts:
- mountPath: /var/config - mountPath: /var/config
name: config name: config

View File

@ -35,8 +35,7 @@ spec:
operator: Exists operator: Exists
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/master key: node-role.kubernetes.io/master
operator: Equal operator: Exists
value: "true"
- effect: NoSchedule - effect: NoSchedule
key: node-role.kubernetes.io/control-plane key: node-role.kubernetes.io/control-plane
operator: Exists operator: Exists

View File

@ -0,0 +1,54 @@
#!/usr/bin/env bash
# update-csi-charts updates the Helm charts for the CSI drivers in the CLI.
set -euo pipefail
shopt -s inherit_errexit
# Required tools
if ! command -v git &> /dev/null; then
echo "git could not be found"
exit 1
fi
# download_chart downloads the Helm chart for the given CSI driver and version.
#
# Arguments:
# $1: URL of the git repo containing the Helm chart
# $2: branch or tag of the git repo
# $3: path to the Helm chart in the git repo
# $4: name of the Helm chart
download_chart() {
chart_url=$1
branch=$2
chart_dir=$3
chart_name=$4
repo_tmp_dir=$(mktemp -d)
chart_base_path="charts/edgeless/constellation-services/charts/"
pushd "${repo_tmp_dir}"
git clone --filter=blob:none --no-checkout --sparse --depth 1 --branch="${branch}" "${chart_url}" "${repo_tmp_dir}"
git sparse-checkout add "${chart_dir}"
git checkout
popd
# remove old chart
rm -r "${chart_base_path}${chart_name}"
# move new chart
mkdir -p "${chart_base_path}/${chart_name}"
cp -r "${repo_tmp_dir}/${chart_dir}"/* "${chart_base_path}${chart_name}"
rm -r "${repo_tmp_dir}"
return
}
## GCP CSI Driver
# TODO: clone from main branch once we rebase on upstream
download_chart "https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver" "develop" "charts" "gcp-compute-persistent-disk-csi-driver"
## Azure CSI Driver
# TODO: https://github.com/edgelesssys/constellation/pull/548

View File

@ -182,11 +182,14 @@ type AzureConfig struct {
// Type of a node's state disk. The type influences boot time and I/O performance. See: https://docs.microsoft.com/en-us/azure/virtual-machines/disks-types#disk-type-comparison // Type of a node's state disk. The type influences boot time and I/O performance. See: https://docs.microsoft.com/en-us/azure/virtual-machines/disks-types#disk-type-comparison
StateDiskType string `yaml:"stateDiskType" validate:"oneof=Premium_LRS Premium_ZRS Standard_LRS StandardSSD_LRS StandardSSD_ZRS"` StateDiskType string `yaml:"stateDiskType" validate:"oneof=Premium_LRS Premium_ZRS Standard_LRS StandardSSD_LRS StandardSSD_ZRS"`
// description: | // description: |
// Expected confidential VM measurements. // Deploy Azure Disk CSI driver with on-node encryption. For details see: https://docs.edgeless.systems/constellation/architecture/encrypted-storage
Measurements Measurements `yaml:"measurements"` DeployCSIDriver *bool `yaml:"deployCSIDriver" validate:"required"`
// description: | // description: |
// List of values that should be enforced to be equal to the ones from the measurement list. Any non-equal values not in this list will only result in a warning. // Use Confidential VMs. If set to false, Trusted Launch VMs are used instead. See: https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview
EnforcedMeasurements []uint32 `yaml:"enforcedMeasurements"` ConfidentialVM *bool `yaml:"confidentialVM" validate:"required"`
// description: |
// Enable secure boot for VMs. If enabled, the OS image has to include a virtual machine guest state (VMGS) blob.
SecureBoot *bool `yaml:"secureBoot" validate:"required"`
// description: | // description: |
// Expected value for the field 'idkeydigest' in the AMD SEV-SNP attestation report. Only usable with ConfidentialVMs. See 4.6 and 7.3 in: https://www.amd.com/system/files/TechDocs/56860.pdf // Expected value for the field 'idkeydigest' in the AMD SEV-SNP attestation report. Only usable with ConfidentialVMs. See 4.6 and 7.3 in: https://www.amd.com/system/files/TechDocs/56860.pdf
IDKeyDigest string `yaml:"idKeyDigest" validate:"required_if=EnforceIdKeyDigest true,omitempty,hexadecimal,len=96"` IDKeyDigest string `yaml:"idKeyDigest" validate:"required_if=EnforceIdKeyDigest true,omitempty,hexadecimal,len=96"`
@ -194,11 +197,11 @@ type AzureConfig struct {
// Enforce the specified idKeyDigest value during remote attestation. // Enforce the specified idKeyDigest value during remote attestation.
EnforceIDKeyDigest *bool `yaml:"enforceIdKeyDigest" validate:"required"` EnforceIDKeyDigest *bool `yaml:"enforceIdKeyDigest" validate:"required"`
// description: | // description: |
// Use Confidential VMs. If set to false, Trusted Launch VMs are used instead. See: https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview // Expected confidential VM measurements.
ConfidentialVM *bool `yaml:"confidentialVM" validate:"required"` Measurements Measurements `yaml:"measurements"`
// description: | // description: |
// Enable secure boot for VMs. If enabled, the OS image has to include a virtual machine guest state (VMGS) blob. // List of values that should be enforced to be equal to the ones from the measurement list. Any non-equal values not in this list will only result in a warning.
SecureBoot *bool `yaml:"secureBoot" validate:"required"` EnforcedMeasurements []uint32 `yaml:"enforcedMeasurements"`
} }
// GCPConfig are GCP specific configuration values used by the CLI. // GCPConfig are GCP specific configuration values used by the CLI.
@ -225,6 +228,9 @@ type GCPConfig struct {
// Type of a node's state disk. The type influences boot time and I/O performance. See: https://cloud.google.com/compute/docs/disks#disk-types // Type of a node's state disk. The type influences boot time and I/O performance. See: https://cloud.google.com/compute/docs/disks#disk-types
StateDiskType string `yaml:"stateDiskType" validate:"oneof=pd-standard pd-balanced pd-ssd"` StateDiskType string `yaml:"stateDiskType" validate:"oneof=pd-standard pd-balanced pd-ssd"`
// description: | // description: |
// Deploy Persistent Disk CSI driver with on-node encryption. For details see: https://docs.edgeless.systems/constellation/architecture/encrypted-storage
DeployCSIDriver *bool `yaml:"deployCSIDriver" validate:"required"`
// description: |
// Expected confidential VM measurements. // Expected confidential VM measurements.
Measurements Measurements `yaml:"measurements"` Measurements Measurements `yaml:"measurements"`
// description: | // description: |
@ -295,21 +301,23 @@ func Default() *Config {
Image: DefaultImageAzure, Image: DefaultImageAzure,
InstanceType: "Standard_DC4as_v5", InstanceType: "Standard_DC4as_v5",
StateDiskType: "Premium_LRS", StateDiskType: "Premium_LRS",
Measurements: measurements.DefaultsFor(cloudprovider.Azure), DeployCSIDriver: func() *bool { b := true; return &b }(),
EnforcedMeasurements: []uint32{4, 8, 9, 11, 12, 13, 15},
IDKeyDigest: "57486a447ec0f1958002a22a06b7673b9fd27d11e1c6527498056054c5fa92d23c50f9de44072760fe2b6fb89740b696", IDKeyDigest: "57486a447ec0f1958002a22a06b7673b9fd27d11e1c6527498056054c5fa92d23c50f9de44072760fe2b6fb89740b696",
EnforceIDKeyDigest: func() *bool { b := true; return &b }(), EnforceIDKeyDigest: func() *bool { b := true; return &b }(),
ConfidentialVM: func() *bool { b := true; return &b }(), ConfidentialVM: func() *bool { b := true; return &b }(),
SecureBoot: func() *bool { b := false; return &b }(), SecureBoot: func() *bool { b := false; return &b }(),
Measurements: measurements.DefaultsFor(cloudprovider.Azure),
EnforcedMeasurements: []uint32{4, 8, 9, 11, 12, 13, 15},
}, },
GCP: &GCPConfig{ GCP: &GCPConfig{
Project: "", Project: "",
Region: "", Region: "",
Zone: "", Zone: "",
ServiceAccountKeyPath: "",
Image: DefaultImageGCP, Image: DefaultImageGCP,
InstanceType: "n2d-standard-4", InstanceType: "n2d-standard-4",
StateDiskType: "pd-ssd", StateDiskType: "pd-ssd",
ServiceAccountKeyPath: "", DeployCSIDriver: func() *bool { b := true; return &b }(),
Measurements: measurements.DefaultsFor(cloudprovider.GCP), Measurements: measurements.DefaultsFor(cloudprovider.GCP),
EnforcedMeasurements: []uint32{0, 4, 8, 9, 11, 12, 13, 15}, EnforcedMeasurements: []uint32{0, 4, 8, 9, 11, 12, 13, 15},
}, },
@ -320,9 +328,9 @@ func Default() *Config {
MetadataAPIImage: versions.QEMUMetadataImage, MetadataAPIImage: versions.QEMUMetadataImage,
LibvirtURI: "", LibvirtURI: "",
LibvirtContainerImage: versions.LibvirtImage, LibvirtContainerImage: versions.LibvirtImage,
NVRAM: "production",
Measurements: measurements.DefaultsFor(cloudprovider.QEMU), Measurements: measurements.DefaultsFor(cloudprovider.QEMU),
EnforcedMeasurements: []uint32{4, 8, 9, 11, 12, 13, 15}, EnforcedMeasurements: []uint32{4, 8, 9, 11, 12, 13, 15},
NVRAM: "production",
}, },
}, },
KubernetesVersion: string(versions.Default), KubernetesVersion: string(versions.Default),
@ -482,6 +490,29 @@ func (c *Config) EnforcesIDKeyDigest() bool {
return c.Provider.Azure != nil && c.Provider.Azure.EnforceIDKeyDigest != nil && *c.Provider.Azure.EnforceIDKeyDigest return c.Provider.Azure != nil && c.Provider.Azure.EnforceIDKeyDigest != nil && *c.Provider.Azure.EnforceIDKeyDigest
} }
// GetEnforcedPCRs returns the list of enforced PCRs for the configured cloud provider.
func (c *Config) GetEnforcedPCRs() []uint32 {
provider := c.GetProvider()
switch provider {
case cloudprovider.AWS:
return c.Provider.AWS.EnforcedMeasurements
case cloudprovider.Azure:
return c.Provider.Azure.EnforcedMeasurements
case cloudprovider.GCP:
return c.Provider.GCP.EnforcedMeasurements
case cloudprovider.QEMU:
return c.Provider.QEMU.EnforcedMeasurements
default:
return nil
}
}
// DeployCSIDriver returns whether the CSI driver should be deployed for a given cloud provider.
func (c *Config) DeployCSIDriver() bool {
return c.Provider.Azure != nil && c.Provider.Azure.DeployCSIDriver != nil && *c.Provider.Azure.DeployCSIDriver ||
c.Provider.GCP != nil && c.Provider.GCP.DeployCSIDriver != nil && *c.Provider.GCP.DeployCSIDriver
}
// Validate checks the config values and returns validation errors. // Validate checks the config values and returns validation errors.
func (c *Config) Validate() error { func (c *Config) Validate() error {
trans := ut.New(en.New()).GetFallback() trans := ut.New(en.New()).GetFallback()

View File

@ -208,7 +208,7 @@ func init() {
FieldName: "azure", FieldName: "azure",
}, },
} }
AzureConfigDoc.Fields = make([]encoder.Doc, 16) AzureConfigDoc.Fields = make([]encoder.Doc, 17)
AzureConfigDoc.Fields[0].Name = "subscription" AzureConfigDoc.Fields[0].Name = "subscription"
AzureConfigDoc.Fields[0].Type = "string" AzureConfigDoc.Fields[0].Type = "string"
AzureConfigDoc.Fields[0].Note = "" AzureConfigDoc.Fields[0].Note = ""
@ -259,36 +259,41 @@ func init() {
AzureConfigDoc.Fields[9].Note = "" AzureConfigDoc.Fields[9].Note = ""
AzureConfigDoc.Fields[9].Description = "Type of a node's state disk. The type influences boot time and I/O performance. See: https://docs.microsoft.com/en-us/azure/virtual-machines/disks-types#disk-type-comparison" AzureConfigDoc.Fields[9].Description = "Type of a node's state disk. The type influences boot time and I/O performance. See: https://docs.microsoft.com/en-us/azure/virtual-machines/disks-types#disk-type-comparison"
AzureConfigDoc.Fields[9].Comments[encoder.LineComment] = "Type of a node's state disk. The type influences boot time and I/O performance. See: https://docs.microsoft.com/en-us/azure/virtual-machines/disks-types#disk-type-comparison" AzureConfigDoc.Fields[9].Comments[encoder.LineComment] = "Type of a node's state disk. The type influences boot time and I/O performance. See: https://docs.microsoft.com/en-us/azure/virtual-machines/disks-types#disk-type-comparison"
AzureConfigDoc.Fields[10].Name = "measurements" AzureConfigDoc.Fields[10].Name = "deployCSIDriver"
AzureConfigDoc.Fields[10].Type = "Measurements" AzureConfigDoc.Fields[10].Type = "bool"
AzureConfigDoc.Fields[10].Note = "" AzureConfigDoc.Fields[10].Note = ""
AzureConfigDoc.Fields[10].Description = "Expected confidential VM measurements." AzureConfigDoc.Fields[10].Description = "Deploy Azure Disk CSI driver with on-node encryption. For details see: https://docs.edgeless.systems/constellation/architecture/encrypted-storage"
AzureConfigDoc.Fields[10].Comments[encoder.LineComment] = "Expected confidential VM measurements." AzureConfigDoc.Fields[10].Comments[encoder.LineComment] = "Deploy Azure Disk CSI driver with on-node encryption. For details see: https://docs.edgeless.systems/constellation/architecture/encrypted-storage"
AzureConfigDoc.Fields[11].Name = "enforcedMeasurements" AzureConfigDoc.Fields[11].Name = "confidentialVM"
AzureConfigDoc.Fields[11].Type = "[]uint32" AzureConfigDoc.Fields[11].Type = "bool"
AzureConfigDoc.Fields[11].Note = "" AzureConfigDoc.Fields[11].Note = ""
AzureConfigDoc.Fields[11].Description = "List of values that should be enforced to be equal to the ones from the measurement list. Any non-equal values not in this list will only result in a warning." AzureConfigDoc.Fields[11].Description = "Use Confidential VMs. If set to false, Trusted Launch VMs are used instead. See: https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview"
AzureConfigDoc.Fields[11].Comments[encoder.LineComment] = "List of values that should be enforced to be equal to the ones from the measurement list. Any non-equal values not in this list will only result in a warning." AzureConfigDoc.Fields[11].Comments[encoder.LineComment] = "Use Confidential VMs. If set to false, Trusted Launch VMs are used instead. See: https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview"
AzureConfigDoc.Fields[12].Name = "idKeyDigest" AzureConfigDoc.Fields[12].Name = "secureBoot"
AzureConfigDoc.Fields[12].Type = "string" AzureConfigDoc.Fields[12].Type = "bool"
AzureConfigDoc.Fields[12].Note = "" AzureConfigDoc.Fields[12].Note = ""
AzureConfigDoc.Fields[12].Description = "Expected value for the field 'idkeydigest' in the AMD SEV-SNP attestation report. Only usable with ConfidentialVMs. See 4.6 and 7.3 in: https://www.amd.com/system/files/TechDocs/56860.pdf" AzureConfigDoc.Fields[12].Description = "Enable secure boot for VMs. If enabled, the OS image has to include a virtual machine guest state (VMGS) blob."
AzureConfigDoc.Fields[12].Comments[encoder.LineComment] = "Expected value for the field 'idkeydigest' in the AMD SEV-SNP attestation report. Only usable with ConfidentialVMs. See 4.6 and 7.3 in: https://www.amd.com/system/files/TechDocs/56860.pdf" AzureConfigDoc.Fields[12].Comments[encoder.LineComment] = "Enable secure boot for VMs. If enabled, the OS image has to include a virtual machine guest state (VMGS) blob."
AzureConfigDoc.Fields[13].Name = "enforceIdKeyDigest" AzureConfigDoc.Fields[13].Name = "idKeyDigest"
AzureConfigDoc.Fields[13].Type = "bool" AzureConfigDoc.Fields[13].Type = "string"
AzureConfigDoc.Fields[13].Note = "" AzureConfigDoc.Fields[13].Note = ""
AzureConfigDoc.Fields[13].Description = "Enforce the specified idKeyDigest value during remote attestation." AzureConfigDoc.Fields[13].Description = "Expected value for the field 'idkeydigest' in the AMD SEV-SNP attestation report. Only usable with ConfidentialVMs. See 4.6 and 7.3 in: https://www.amd.com/system/files/TechDocs/56860.pdf"
AzureConfigDoc.Fields[13].Comments[encoder.LineComment] = "Enforce the specified idKeyDigest value during remote attestation." AzureConfigDoc.Fields[13].Comments[encoder.LineComment] = "Expected value for the field 'idkeydigest' in the AMD SEV-SNP attestation report. Only usable with ConfidentialVMs. See 4.6 and 7.3 in: https://www.amd.com/system/files/TechDocs/56860.pdf"
AzureConfigDoc.Fields[14].Name = "confidentialVM" AzureConfigDoc.Fields[14].Name = "enforceIdKeyDigest"
AzureConfigDoc.Fields[14].Type = "bool" AzureConfigDoc.Fields[14].Type = "bool"
AzureConfigDoc.Fields[14].Note = "" AzureConfigDoc.Fields[14].Note = ""
AzureConfigDoc.Fields[14].Description = "Use Confidential VMs. If set to false, Trusted Launch VMs are used instead. See: https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview" AzureConfigDoc.Fields[14].Description = "Enforce the specified idKeyDigest value during remote attestation."
AzureConfigDoc.Fields[14].Comments[encoder.LineComment] = "Use Confidential VMs. If set to false, Trusted Launch VMs are used instead. See: https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview" AzureConfigDoc.Fields[14].Comments[encoder.LineComment] = "Enforce the specified idKeyDigest value during remote attestation."
AzureConfigDoc.Fields[15].Name = "secureBoot" AzureConfigDoc.Fields[15].Name = "measurements"
AzureConfigDoc.Fields[15].Type = "bool" AzureConfigDoc.Fields[15].Type = "Measurements"
AzureConfigDoc.Fields[15].Note = "" AzureConfigDoc.Fields[15].Note = ""
AzureConfigDoc.Fields[15].Description = "Enable secure boot for VMs. If enabled, the OS image has to include a virtual machine guest state (VMGS) blob." AzureConfigDoc.Fields[15].Description = "Expected confidential VM measurements."
AzureConfigDoc.Fields[15].Comments[encoder.LineComment] = "Enable secure boot for VMs. If enabled, the OS image has to include a virtual machine guest state (VMGS) blob." AzureConfigDoc.Fields[15].Comments[encoder.LineComment] = "Expected confidential VM measurements."
AzureConfigDoc.Fields[16].Name = "enforcedMeasurements"
AzureConfigDoc.Fields[16].Type = "[]uint32"
AzureConfigDoc.Fields[16].Note = ""
AzureConfigDoc.Fields[16].Description = "List of values that should be enforced to be equal to the ones from the measurement list. Any non-equal values not in this list will only result in a warning."
AzureConfigDoc.Fields[16].Comments[encoder.LineComment] = "List of values that should be enforced to be equal to the ones from the measurement list. Any non-equal values not in this list will only result in a warning."
GCPConfigDoc.Type = "GCPConfig" GCPConfigDoc.Type = "GCPConfig"
GCPConfigDoc.Comments[encoder.LineComment] = "GCPConfig are GCP specific configuration values used by the CLI." GCPConfigDoc.Comments[encoder.LineComment] = "GCPConfig are GCP specific configuration values used by the CLI."
@ -299,7 +304,7 @@ func init() {
FieldName: "gcp", FieldName: "gcp",
}, },
} }
GCPConfigDoc.Fields = make([]encoder.Doc, 9) GCPConfigDoc.Fields = make([]encoder.Doc, 10)
GCPConfigDoc.Fields[0].Name = "project" GCPConfigDoc.Fields[0].Name = "project"
GCPConfigDoc.Fields[0].Type = "string" GCPConfigDoc.Fields[0].Type = "string"
GCPConfigDoc.Fields[0].Note = "" GCPConfigDoc.Fields[0].Note = ""
@ -335,16 +340,21 @@ func init() {
GCPConfigDoc.Fields[6].Note = "" GCPConfigDoc.Fields[6].Note = ""
GCPConfigDoc.Fields[6].Description = "Type of a node's state disk. The type influences boot time and I/O performance. See: https://cloud.google.com/compute/docs/disks#disk-types" GCPConfigDoc.Fields[6].Description = "Type of a node's state disk. The type influences boot time and I/O performance. See: https://cloud.google.com/compute/docs/disks#disk-types"
GCPConfigDoc.Fields[6].Comments[encoder.LineComment] = "Type of a node's state disk. The type influences boot time and I/O performance. See: https://cloud.google.com/compute/docs/disks#disk-types" GCPConfigDoc.Fields[6].Comments[encoder.LineComment] = "Type of a node's state disk. The type influences boot time and I/O performance. See: https://cloud.google.com/compute/docs/disks#disk-types"
GCPConfigDoc.Fields[7].Name = "measurements" GCPConfigDoc.Fields[7].Name = "deployCSIDriver"
GCPConfigDoc.Fields[7].Type = "Measurements" GCPConfigDoc.Fields[7].Type = "bool"
GCPConfigDoc.Fields[7].Note = "" GCPConfigDoc.Fields[7].Note = ""
GCPConfigDoc.Fields[7].Description = "Expected confidential VM measurements." GCPConfigDoc.Fields[7].Description = "Deploy Persistent Disk CSI driver with on-node encryption. For details see: https://docs.edgeless.systems/constellation/architecture/encrypted-storage"
GCPConfigDoc.Fields[7].Comments[encoder.LineComment] = "Expected confidential VM measurements." GCPConfigDoc.Fields[7].Comments[encoder.LineComment] = "Deploy Persistent Disk CSI driver with on-node encryption. For details see: https://docs.edgeless.systems/constellation/architecture/encrypted-storage"
GCPConfigDoc.Fields[8].Name = "enforcedMeasurements" GCPConfigDoc.Fields[8].Name = "measurements"
GCPConfigDoc.Fields[8].Type = "[]uint32" GCPConfigDoc.Fields[8].Type = "Measurements"
GCPConfigDoc.Fields[8].Note = "" GCPConfigDoc.Fields[8].Note = ""
GCPConfigDoc.Fields[8].Description = "List of values that should be enforced to be equal to the ones from the measurement list. Any non-equal values not in this list will only result in a warning." GCPConfigDoc.Fields[8].Description = "Expected confidential VM measurements."
GCPConfigDoc.Fields[8].Comments[encoder.LineComment] = "List of values that should be enforced to be equal to the ones from the measurement list. Any non-equal values not in this list will only result in a warning." GCPConfigDoc.Fields[8].Comments[encoder.LineComment] = "Expected confidential VM measurements."
GCPConfigDoc.Fields[9].Name = "enforcedMeasurements"
GCPConfigDoc.Fields[9].Type = "[]uint32"
GCPConfigDoc.Fields[9].Note = ""
GCPConfigDoc.Fields[9].Description = "List of values that should be enforced to be equal to the ones from the measurement list. Any non-equal values not in this list will only result in a warning."
GCPConfigDoc.Fields[9].Comments[encoder.LineComment] = "List of values that should be enforced to be equal to the ones from the measurement list. Any non-equal values not in this list will only result in a warning."
QEMUConfigDoc.Type = "QEMUConfig" QEMUConfigDoc.Type = "QEMUConfig"
QEMUConfigDoc.Comments[encoder.LineComment] = "QEMUConfig holds config information for QEMU based Constellation deployments." QEMUConfigDoc.Comments[encoder.LineComment] = "QEMUConfig holds config information for QEMU based Constellation deployments."