Creating the workload section of the contract
This step must be performed by the Solution Provider.
Prerequisites
- You have the encryption certificate files downloaded from the installation package.
- You have the sealed secret client binary files downloaded from the installation package.
Procedure
- Create a directory ContractDirectory by running the following
command:
mkdir ContractDirectory - Copy encryption certificate to the working directory by running the following command:
For Peerpod
cp ibm-confidential-computing-container-26.3.1-encrypt.crt ContractDirectoryFor Bare Metal
cp ibm-confidential-computing-container-2.0.6-encrypt.crt ContractDirectory - Change the directory to ContractDirectory by running the following
command:
cd ContractDirectory - If you are creating the contract with the cosign verified images, you must perform the Additional steps for the cosign
contract.
OR
If you are creating the contract with the workload sealed secret you must perform the Additional steps for the sealed secret contract.
- Create SamplePolicyPermissiveRules.rego according to the following
example:Note: For more information about Rego policies and the associated restrictive rules, see Rego policy rules and snippets.
package policy default AddARPNeighborsRequest := false default AddSwapRequest := false default CheckRequest := true default CloseStdinRequest := false default CopyFileRequest := false CopyFileRequest { allow_path(input.path) dir_mode := bits.lsh(1, 31) allowed_dir_permission := bits.or(dir_mode, 488) input.dir_mode == allowed_dir_permission } allow_path(path) { regex.match("/run/kata-containers/shared/containers/[[:xdigit:]]+", path) } default CreateContainerRequest := false CreateContainerRequest { allow_image(input.OCI.Annotations["io.kubernetes.cri-o.ImageName"]) } allow_image(image_name) { regex.match("quay\\.io/openshift-release-dev/ocp-v4\\.0-art-dev@sha256:[a-f0-9]{64}", image_name) } allow_image(image_name) { image_name == "<WorkloadImage>" } default CreateSandboxRequest := true default DestroySandboxRequest := true default GetMetricsRequest := false default GetOOMEventRequest := true default GuestDetailsRequest := false default ListInterfacesRequest := false default ListRoutesRequest := false default MemHotplugByProbeRequest := false default OnlineCPUMemRequest := true default PauseContainerRequest := false default PullImageRequest := false default ReadStreamRequest := false default RemoveContainerRequest := false RemoveContainerRequest { allow_startcontainer(input.container_id) } allow_startcontainer(container_id) { regex.match("^[a-f0-9]{64}$", container_id) } default RemoveStaleVirtiofsShareMountsRequest := false default ReseedRandomDevRequest := false default ResumeContainerRequest := false default SetGuestDateTimeRequest := false default SetPolicyRequest := false default SignalProcessRequest := true default StartContainerRequest := false StartContainerRequest { allow_startcontainer(input.container_id) } allow_startcontainer(container_id) { regex.match("^[a-f0-9]{64}$", container_id) } default StartTracingRequest := false default StatsContainerRequest := false default StopTracingRequest := false default TtyWinResizeRequest := false default UpdateContainerRequest := false default UpdateEphemeralMountsRequest := true default UpdateInterfaceRequest := true default UpdateRoutesRequest := true default WaitProcessRequest := false default WriteStreamRequest := false default WriteStdinRequest := false default ReadStdoutRequest := true default ReadStderrRequest := true default GetIPTablesRequest := false default SetIPTablesRequest := false default GetGuestDetailsRequest := false GetGuestDetailsRequest { input.mem_block_size == true input.mem_hotplug_probe == true } default GetVolumeStatsRequest := false default ResizeVolumeRequest := false default VersionRequest := false default ExecProcessRequest := falseImportant:In the Rego policy, for IBM CCCO Bare Metal deployments, make sure the following requests are always set to
true. If any of them are set tofalse, important guest-side functions do not work correctly:-
OnlineCPUMemRequest: If this isfalse, the CPUs and/or memory for the pod do not activate inside the guest. -
UpdateInterfaceRequest: If this isfalse, the guest does not create or attach pod network interfaces. -
UpdateRoutesRequest: If this isfalse, the guest has incomplete routing tables, which can break network connectivity. -
UpdateEphemeralMountsRequest: If this isfalse, the guest does not reconcile ephemeral and projected volumes. -
SignalProcessRequest: If this isfalse, containers do not receive process signals, including important ones likeSIGTERM. -
GetOOMEventRequest: If this isfalse, the kubelet cannot see Out-Of-Memory (OOM) events in the guest.
Note:Enabling exec capabilities for interactive shell access in CCCO Bare Metal deployments
Important: It is not recommended to enable exec processes on CCCO VMs. Enable only for debugging purposes.
The sample policy above has restrictive settings suitable for most workloads. However, if you require interactive shell access or exec operations for debugging purposes (for example, using
kubectl execoroc exec), you must enable additional policy rules.To enable exec support, set the following related rules to
truein your SamplePolicyPermissiveRules.rego file:ExecProcessRequest := true- Allows execution of processes inside the containerTtyWinResizeRequest := true- Enables terminal window resizing for interactive shellsWaitProcessRequest := true- Allows waiting for process completion to capture exit codesWriteStdinRequest := true- Enables writing to processstdinfor interactive inputReadStdoutRequest := true- Allows reading processstdoutto capture command output (already set totruein the sample policy)CloseStdinRequest := true- Enables properstdinclosure for process termination
These rules are interdependent and must be enabled together for exec operations to function properly. Enabling only
ExecProcessRequestwithout the supporting I/O and terminal management rules results in non-functional exec operations.Note: If you are using persistent block volumes, make sure thatRemoveContainerRequestis set totrue. -
- Replace the
<WorkloadImage>in SamplePolicyPermissiveRules.rego with your workload image according the format shown in the below example:image_name == "quay.io/prometheus/busybox:latest"Important: In the SamplePolicyPermissiveRules.rego, make sure to include the container image in the above mentioned format to enable image pulling and ensure proper functionality for all workloads. For more information, see CreateContainerRequest policy. - Set the encoded policy with the SamplePolicyPermissiveRules.rego by running the following commands:
- For
macOS:
export encoded_policy=$(cat SamplePolicyPermissiveRules.rego | gbase64 -w 0) - For
linux:
export encoded_policy=$(cat SamplePolicyPermissiveRules.rego | base64 -w 0)
- For
macOS:
- Create a workload.yaml according to the following example:
- For basic contract/contract with attestation encryption/contract with env sealed
secret:
cat << EOF > workload.yaml type: workload confidential-containers: regoValidator: policy: <BASE64-ENCODED-REGO-POLICY> EOFIf you want to use the workload image from the private registry, include the following
authssection in theworkload.yamlfile with the necessary information:auths: <PRIVATE_REGISTRY_URL>: username: <USER_NAME> password: <API_KEY_OR_PASSWORD>Note: If you want to add encrypted persistent volumes to your contract, see Configuring volumes in the workload section for detailed instructions on adding volume configurations. - For the contract with cosign verified container
images:
cat << EOF > workload.yaml workload: type: workload confidential-containers: regoValidator: policy: <BASE64-ENCODED-REGO-POLICY> config: cosign: quay.io/<username>/busybox: publicKey: ${cosign_pub_base64} EOF - For the contract with workload sealed
secret:
cat << EOF > workload.yaml type: workload confidential-containers: regoValidator: policy: ${encoded_policy} secret: verificationKey: "${SECRET_VERIFICATION_KEY}" decryptionKey: "${SECRET_DECRYPTION_KEY}" EOF
- For basic contract/contract with attestation encryption/contract with env sealed
secret:
- Create the encryption-workload.sh script with the following
content:
export CONTRACT_KEY="ibm-confidential-computing-container-encrypt.crt" export WORKLOAD="workload.yaml" export PASSWORD="$(openssl rand 32 | base64 -w0)" export ENCRYPTED_PASSWORD="$(echo -n "$PASSWORD" | base64 -d | openssl pkeyutl -encrypt -inkey $CONTRACT_KEY -certin | base64 -w0 )" export ENCRYPTED_WORKLOAD="$(echo -n "$PASSWORD" | base64 -d | openssl enc -aes-256-cbc -pbkdf2 -pass stdin -in "$WORKLOAD" | base64 -w0)" echo "workload: hyper-protect-basic.${ENCRYPTED_PASSWORD}.${ENCRYPTED_WORKLOAD}" > encrypted-workload.yaml - Make the encryption-workload.sh script executable by running the following
command:
chmod +x encryption-workload.sh - Run the following script to create
encrypted-workload.yaml:./encryption-workload.sh - Run the following command to view
encrypted-workload.yaml:cat encrypted-workload.yamlExample output:
workload: hyper-protect-basic.d458ARMC89mB0ymq3we6LDHFaF8oWVB6Nn5fvbFhJvMm2xFDnF MTHEL3KR/+KsazFxTRpBab/M+R8ocT9mfenYyRj6L6n8T/FWgjnaT.............. - Share the
encrypted-workload.yamlwith the Data Owner - Generate the contract signing key pair.