Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for IBM SE #39

Merged
merged 1 commit into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ type KbsConfigSpec struct {
// tdxConfigSpec is the struct that hosts the TDX specific configuration
// +optional
TdxConfigSpec TdxConfigSpec `json:"tdxConfigSpec,omitempty"`

// ibmSEConfigSpec is the struct that hosts the IBMSE specific configuration
// +optional
IbmSEConfigSpec IbmSEConfigSpec `json:"ibmSEConfigSpec,omitempty"`
}

// IbmSEConfigSpec defines the desired state for IBMSE configuration
type IbmSEConfigSpec struct {
// certStorePvc is the name of the PeristentVolumeClaim where certificates/keys are mounted
// +optional
CertStorePvc string `json:"certStorePvc,omitempty"`
}

// TdxConfigSpec defines the desired state for TDX configuration
Expand Down Expand Up @@ -156,8 +167,12 @@ spec:
kbsSecretResources: ["kbsres1"]
# Resource policy
kbsResourcePolicyConfigMapName: resource-policy
# TDX configuration file
kbsTdxConfigMapName: tdx-config
# TDX settings
tdxConfigSpec:
kbsTdxConfigMapName: tdx-config-sample
# IBMSE settings
ibmSEConfigSpec:
certStorePvc: ibmse-pvc
```

## Getting Started
Expand Down Expand Up @@ -241,6 +256,10 @@ You’ll need a Kubernetes cluster to run against. You can use [KIND](https://si
```

It is also possible to create the K8s secrets (a commented out example is provided in the [kustomization.yaml](config/samples/microservices/kustomization.yaml)). To enable the secrets you'd need to uncomment the relevant secret generator entry and patch.

### IBM Secure Execution

For IBM SE specific configuration, please refer to [ibmse.md](docs/ibmse.md).

### Uninstall CRDs

Expand Down
11 changes: 11 additions & 0 deletions api/v1alpha1/kbsconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ type TdxConfigSpec struct {
KbsTdxConfigMapName string `json:"kbsTdxConfigMapName,omitempty"`
}

// IbmSEConfigSpec defines the desired state for IBMSE configuration
type IbmSEConfigSpec struct {
// certStorePvc is the name of the PeristentVolumeClaim where certificates/keys are mounted
// +optional
CertStorePvc string `json:"certStorePvc,omitempty"`
}

// KbsConfigSpec defines the desired state of KbsConfig
type KbsConfigSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
Expand Down Expand Up @@ -98,6 +105,10 @@ type KbsConfigSpec struct {
// tdxConfigSpec is the struct that hosts the TDX specific configuration
// +optional
TdxConfigSpec TdxConfigSpec `json:"tdxConfigSpec,omitempty"`

// ibmSEConfigSpec is the struct that hosts the IBMSE specific configuration
// +optional
IbmSEConfigSpec IbmSEConfigSpec `json:"ibmSEConfigSpec,omitempty"`
}

// KbsConfigStatus defines the observed state of KbsConfig
Expand Down
16 changes: 16 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions bundle/manifests/confidentialcontainers.org_kbsconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ spec:
spec:
description: KbsConfigSpec defines the desired state of KbsConfig
properties:
ibmSEConfigSpec:
description: ibmSEConfigSpec is the struct that hosts the IBMSE specific
configuration
properties:
certStorePvc:
description: certStorePvc is the name of the PeristentVolumeClaim
where certificates/keys are mounted
type: string
type: object
kbsAsConfigMapName:
description: |-
KbsAsConfigMapName is the name of the configmap that contains the KBS AS configuration
Expand Down
9 changes: 9 additions & 0 deletions config/crd/bases/confidentialcontainers.org_kbsconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ spec:
spec:
description: KbsConfigSpec defines the desired state of KbsConfig
properties:
ibmSEConfigSpec:
description: ibmSEConfigSpec is the struct that hosts the IBMSE specific
configuration
properties:
certStorePvc:
description: certStorePvc is the name of the PeristentVolumeClaim
where certificates/keys are mounted
type: string
type: object
kbsAsConfigMapName:
description: |-
KbsAsConfigMapName is the name of the configmap that contains the KBS AS configuration
Expand Down
19 changes: 19 additions & 0 deletions config/samples/all-in-one/ibmse-pv.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: ibmse-pv
namespace: kbs-operator-system
spec:
capacity:
storage: 100Mi
accessModes:
- ReadOnlyMany
storageClassName: ""
local:
path: /opt/confidential-containers/ibmse
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/worker
operator: Exists
12 changes: 12 additions & 0 deletions config/samples/all-in-one/ibmse-pvc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ibmse-pvc
namespace: kbs-operator-system
spec:
accessModes:
- ReadOnlyMany
storageClassName: ""
resources:
requests:
storage: 100Mi
2 changes: 2 additions & 0 deletions config/samples/all-in-one/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ resources:
- rvps-reference-values.yaml
- resource-policy.yaml
- tdx-config.yaml
- ibmse-pv.yaml
- ibmse-pvc.yaml
#+kubebuilder:scaffold:manifestskustomizesamples
19 changes: 19 additions & 0 deletions config/samples/microservices/ibmse-pv.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: ibmse-pv
namespace: kbs-operator-system
spec:
capacity:
storage: 100Mi
accessModes:
- ReadOnlyMany
storageClassName: ""
local:
Copy link
Member

@bpradipt bpradipt Jul 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder how ReadOnlyMany will be populated. It assumes the storage is pre-populated and then shared afaik. An admin can create a dynamic PVC as well if default storage class exists. In such a case it's unclear how the certs will be populated.

@huoqifeng can you please help with instructions on populating the required certs for SE on a non local storage based PV, ie not using a directory on the worker node.

Also have you considered alternative approaches. For example can we use a side car (or initContainer) to populate the required certs in a persistent volume.
Also, let's say for test env if PV is not used, then can we use the sidecar (or initContainer) approach to simply download the certs and place it in a well-defined path? (eg /opt/confidential-containers/ibmse)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bpradipt I did not try PV approach. The code does hint the materials need be populated beforehand.
I think initContainer/sidecar approach should be OK. the initContainer/sidecar can retrieve all the materials and put it on a shared folder with KBS container following https://github.com/confidential-containers/trustee/blob/main/deps/verifier/src/se/README.md#deployment-of-kbs-with-ibm-se-verifier, like /opt/confidential-containers/ibmse, and then start the KBS/AS.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK downloading all the materials is not easy, each IBM node would require its specific keys to run (the certificates should be ok). This is why I was suggesting to decouple the process of keys/certs preparation from the actual trustee deployment.
What is the advantage of using a sidecar approach? Would you need to create a PV anyway and then copy contents to the containers, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK downloading all the materials is not easy, each IBM node would require its specific keys to run (the certificates should be ok).

I didn't get this. How is key materials on IBM nodes (I think you meant worker nodes here) be relevant to key materials on KBS side? I understand they need to be same, but the setup is entirely different. KBS just needs to have the key materials for all the worker nodes that it needs to validate. Am I missing something ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is why I was suggesting to decouple the process of keys/certs preparation from the actual trustee deployment.

It needs to be de-coupled for sure. However trustee operator needs to have an opinionated way to use the certificates along with admin instructions on how to make those keys available to Trustee. Currently this not clear.
The PV example using the worker node path is making it strongly coupled to IBM nodes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't get this. How is key materials on IBM nodes (I think you meant worker nodes here) be relevant to key materials on KBS side? I understand they need to be same, but the setup is entirely different. KBS just needs to have the key materials for all the worker nodes that it needs to validate. Am I missing something ?

I was mentioning the worker node as a convenient way to prepare a local directory for the required certs/keys to be mounted as a PV/PVC in kbs, just for test purposes. In a production environment, as you said, we could have a non-local storage PV instead. Yes, I think the kbs should have access to all certs/keys for all the worker nodes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It needs to be de-coupled for sure. However trustee operator needs to have an opinionated way to use the certificates along with admin instructions on how to make those keys available to Trustee. Currently this not clear.
The PV example using the worker node path is making it strongly coupled to IBM nodes.

In the current implementation, the trustee container just needs to mount a PVC (by name), no other dependencies on local dirs or the way the PV is created, the storage, etc.
What matters is that a PV is created by admin in advance with all the data trustee is expecting.
Would it be worth to mention the directory structure in the documentation?
For example:

├── certs
│   ├── ibm-z-host-key-signing-gen2.crt
|   └── DigiCertCA.crt
├── crls
│   └── ibm-z-host-key-gen2.crl
│   └── DigiCertTrustedRootG4.crl
│   └── DigiCertTrustedG4CodeSigningRSA4096SHA3842021CA1.crl
├── hdr
│   └── hdr.bin
├── hkds
│   └── HKD-3931-0275D38.crt
└── rsa
    ├── encrypt_key.pem
    └── encrypt_key.pub

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, let's add these details in the readme. Even add the pv yaml example using local storage in the readme for IBM SE. The operator will simply expect a PVC name which is pre-populated with the required data.

path: /opt/confidential-containers/ibmse
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/worker
operator: Exists
12 changes: 12 additions & 0 deletions config/samples/microservices/ibmse-pvc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ibmse-pvc
namespace: kbs-operator-system
spec:
accessModes:
- ReadOnlyMany
storageClassName: ""
resources:
requests:
storage: 100Mi
2 changes: 2 additions & 0 deletions config/samples/microservices/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,6 @@ resources:
- rvps-reference-values.yaml
- resource-policy.yaml
- tdx-config.yaml
- ibmse-pv.yaml
- ibmse-pvc.yaml
#+kubebuilder:scaffold:manifestskustomizesamples
95 changes: 95 additions & 0 deletions docs/ibmse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# IBM Secure Execution (SE)

## Download certificate and keys

In order to Trustee to work properly with IBM SE, a directory containing certificates and keys needs to be mounted in the trustee pod file system.
More information about the IBM download process can be found [here](https://github.com/confidential-containers/trustee/blob/main/deps/verifier/src/se/README.md#download-certs-crls).

By the end of the aforementioned procedure, you should end up having a directory like the following:

```
├── certs
│ ├── ibm-z-host-key-signing-gen2.crt
| └── DigiCertCA.crt
├── crls
│ └── ibm-z-host-key-gen2.crl
│ └── DigiCertTrustedRootG4.crl
│ └── DigiCertTrustedG4CodeSigningRSA4096SHA3842021CA1.crl
├── hdr
│ └── hdr.bin
├── hkds
│ └── HKD-3931-0275D38.crt
└── rsa
├── encrypt_key.pem
└── encrypt_key.pub
```

## Persistent Volume creation

For mounting the above directory to the trustee pod filesystem, we'd need to create a Persistent Volume (PV) and a Persistent Volume Claim (PVC).
The configuration of PV/PVC is deployment specific (e.g. dependent on cloud provider), so it is not reported here in this guide.

In a development environment, you may want to create a PV/PVC that makes use of a local directory. This approach is not recommended for production environments:

PersistentVolume:

```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: ibmse-pv
namespace: kbs-operator-system
spec:
capacity:
storage: 100Mi
accessModes:
- ReadOnlyMany
storageClassName: ""
local:
path: /opt/confidential-containers/ibmse
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/worker
operator: Exists
```
Note: the `path` has to match a local directory on the worker node.

PersistentVolumeClaim:

```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ibmse-pvc
namespace: kbs-operator-system
spec:
accessModes:
- ReadOnlyMany
storageClassName: ""
resources:
requests:
storage: 100Mi
```

## KBS config CRD

For enabling IBM specific configuration in trustee pod, the `KbsConfig` custom resource should have the `ibmSEConfigSpec` section populated as in the following example:

```yaml
apiVersion: confidentialcontainers.org/v1alpha1
kind: KbsConfig
metadata:
name: kbsconfig-sample
namespace: kbs-operator-system
spec:
# omitted all the rest of config
# ...

# IBMSE settings
ibmSEConfigSpec:
certStorePvc: ibmse-pvc
```

The `certStorePvc` has to match the aforementioned PVC name.
3 changes: 3 additions & 0 deletions internal/controller/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ const (

// TDX config file
tdxConfigFile = "sgx_default_qcnl.conf"

// IBM SE path
ibmSePath = "/run/confidential-containers/ibmse/"
)

func contains(list []string, s string) bool {
Expand Down
11 changes: 11 additions & 0 deletions internal/controller/kbsconfig_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,17 @@ func (r *KbsConfigReconciler) newKbsDeployment(ctx context.Context) (*appsv1.Dep
kbsVM = append(kbsVM, volumeMount)
}

// IBMSE specific configuration
if r.kbsConfig.Spec.IbmSEConfigSpec.CertStorePvc != "" {
volume, err := r.createPVCVolume(ctx, r.kbsConfig.Spec.IbmSEConfigSpec.CertStorePvc)
if err != nil {
return nil, err
}
volumeMount = createVolumeMount(volume.Name, ibmSePath)
volumes = append(volumes, *volume)
kbsVM = append(kbsVM, volumeMount)
}

// auth-secret
volume, err = r.createSecretVolume(ctx, "auth-secret", r.kbsConfig.Spec.KbsAuthSecretName)
if err != nil {
Expand Down
13 changes: 13 additions & 0 deletions internal/controller/volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,16 @@ func createVolumeMountWithSubpath(volumeName string, mountPath string, subPath s
SubPath: subPath,
}
}

func (r *KbsConfigReconciler) createPVCVolume(ctx context.Context, volumeName string) (*corev1.Volume, error) {
volume := corev1.Volume{
Name: volumeName,
VolumeSource: corev1.VolumeSource{
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
ClaimName: volumeName,
ReadOnly: true,
},
},
}
return &volume, nil
}
Loading