Configure the Trustee operator
Now that the Trustee operator is installed, we need to set it up.
Reminder: You can assume that everything running in the trustee-operator-sysem namespace should run in a trusted, separate environment. Because of the limitations of this ARO workshop, it is not possible to set up two clusters.
Create the required keys
In order to simplify the flow, we will create here all the keys necessary to securely run Trustee.
More specifically, these keys are:
-
admin authentication keys
-
https keys
-
attestation token key
Of course the user can also bring his own existing keys. The exact purpose of these keys will be explained as they are used in the following sections.
mkdir -p trustee
cd trustee
# Admin authentication keys
openssl genpkey -algorithm ed25519 > privateKey
openssl pkey -in privateKey -pubout -out publicKey
# HTTPS keys
DOMAIN=$(oc get ingress.config/cluster -o jsonpath='{.spec.domain}')
NS=trustee-operator-system
ROUTE_NAME=kbs-service
CN_NAME=kbs-trustee-operator-system
ORG_NAME=my_org
ROUTE="${ROUTE_NAME}-${NS}.${DOMAIN}"
echo "ROUTE: $ROUTE"
echo ""
openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout tls.key \
-out tls.crt \
-subj "/CN=${CN_NAME}/O=${ORG_NAME}$" \
-addext "subjectAltName=DNS:${ROUTE}"
# Attestation token
openssl ecparam -name prime256v1 -genkey -noout -out token.key
openssl req -new -x509 -key token.key -out token.crt -days 365 \
-subj "/CN=${CN_NAME}/O=${ORG_NAME}"
Create a route for Trustee
Create a secure route with passthrough
TLS termination for Trustee. External ingress traffic does not get decrypted by the router but forwarded directly to Trustee pod.
It is also possible to create an edge
route, but then the connection between Trustee and OCP router will be in plain text (http). In this workshop, we will use passthrough
.
Upload the previously self-signed certificates in the Trustee namespace:
oc create secret generic kbs-https-certificate --from-file=tls.crt -n trustee-operator-system
oc create secret generic kbs-https-key --from-file=tls.key -n trustee-operator-system
TRUSTEE_CERT=$(cat tls.crt)
clear
echo "$TRUSTEE_CERT"
echo ""
echo "ROUTE: $ROUTE"
echo ""
oc get secrets -n trustee-operator-system | grep kbs-https
Create the route and set TRUSTEE_HOST
, which together with TRUSTEE_CERT
will be used later when configuring the initdata.
HTTP="https://"
oc create route passthrough kbs-service \
--service=kbs-service \
--port=kbs-port \
-n trustee-operator-system
TRUSTEE_ROUTE="$(oc get route -n trustee-operator-system kbs-service \
-o jsonpath={.spec.host})"
TRUSTEE_HOST=${HTTP}${TRUSTEE_ROUTE}
echo $TRUSTEE_HOST
Example output:
https://kbs-service-trustee-operator-system.apps.rs01nyk5.eastus.aroapp.io
Create the Trustee authentication secret
Such key is not really used when the Trustee is run as Openshift operator, but it is needed in order to start the trustee application.
Create a secret with the public key:
oc create secret generic kbs-auth-public-key --from-file=./publicKey -n trustee-operator-system
Create the attestation token key
Secret retrieval works in a two-step authentication:
-
First, a confidential container sends the reference values to the Trustee
-
The Trustee checks the reference values and if they match, generates and signs an attestation token
-
The attestation token is then sent to the CoCo pod
-
The CoCo pod can now use this token without doing the attestation again to request a secret, and the same token can be reused multiple times until it expires.
The attestation token has to therefore be signed by the Trustee, otherwise a malicious CoCo pod can sign its own fake attestation token and request secrets from the Trustee bypassing the whole reference values check.
Upload the attestation token key and certificate as secret:
oc create secret generic attestation-token --from-file=token.crt --from-file=token.key -n trustee-operator-system
Create Trustee ConfigMap
Create the and apply the Trustee kbs-configmap.yaml
ConfigMap.
Among the others, in this ConfigMap we will enable HTTPS, authenticated admin API and signed attestation token verification.
cat > kbs-configmap.yaml <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: kbs-config-cm
namespace: trustee-operator-system
data:
kbs-config.toml: |
[http_server]
sockets = ["0.0.0.0:8080"]
insecure_http = false
private_key = "/etc/https-key/tls.key"
certificate = "/etc/https-cert/tls.crt"
[admin]
insecure_api = false
auth_public_key = "/etc/auth-secret/publicKey"
[attestation_token]
insecure_key = false
trusted_certs_paths = ["/opt/confidential-containers/kbs/repository/default/attestation-token/token.crt"]
attestation_token_type = "CoCo"
[attestation_service.attestation_token_broker.signer]
key_path = "/opt/confidential-containers/kbs/repository/default/attestation-token/token.key"
cert_path = "/opt/confidential-containers/kbs/repository/default/attestation-token/token.crt"
[attestation_service]
type = "coco_as_builtin"
work_dir = "/opt/confidential-containers/attestation-service"
policy_engine = "opa"
[attestation_service.attestation_token_broker]
type = "Ear"
policy_dir = "/opt/confidential-containers/attestation-service/policies"
[attestation_service.attestation_token_config]
duration_min = 5
[attestation_service.rvps_config]
type = "BuiltIn"
[attestation_service.rvps_config.storage]
type = "LocalJson"
file_path = "/opt/confidential-containers/rvps/reference-values/reference-values.json"
[[plugins]]
name = "resource"
type = "LocalFs"
dir_path = "/opt/confidential-containers/kbs/repository"
[policy_engine]
policy_path = "/opt/confidential-containers/opa/policy.rego"
EOF
clear
cat kbs-configmap.yaml
oc apply -f kbs-configmap.yaml
The initdata policy
About initdata
This step will be also useful in the OSC operator setup. However, since this policy is part of the attestation and we need the expected PCR to be added in the Trustee reference values, we will create the file now.
The initdata specification provides a flexible way to initialize a CoCo peer pod with sensitive or workload-specific data at runtime, avoiding the need to embed such data in the virtual machine (VM) image. This enhances security by reducing exposure of confidential information and improves flexibility by eliminating custom image builds. For example, initdata can include three configuration settings:
-
An X.509 certificate for secure communication.
-
A cryptographic key for authentication.
-
An optional Kata Agent policy.rego file to enforce runtime behavior when overriding the default Kata Agent policy.
We can apply an initdata configuration by using one of the following methods:
-
Globally by including it in the peer pods config map, setting a cluster-wide default for all pods.
-
For a specific pod when configuring a pod workload object, allowing customization for individual workloads.
The
io.katacontainers.config.runtime.cc_init_data
annotation undermetadata:annotations:
in the pod yaml spec overrides the globalINITDATA
setting in the peer pods config map for that specific pod. The Kata runtime handles this precedence automatically at pod creation time.
The initdata content configures the following components:
-
Attestation Agent (AA), which verifies the trustworthiness of the peer pod by sending evidence to the Trustee for attestation.
-
Confidential Data Hub (CDH), which manages secrets and secure data access within the peer pod VM.
-
Kata Agent, which enforces runtime policies and manages the lifecycle of the containers inside the pod VM.
Create the initdata policy
In this section, we will create the initdata that will be later set up as global in the OSC operator configmap.
In this policy, we will set the Trustee address in the internal CVM components. We will use TRUSTEE_HOST
defined previously when configuring the Trustee.
Why do we add this to the Trustee reference values? Remember that this policy is actually added into the OSC operator Configmap, or injected as pod annotation at deployment time. Both scenarios are happening outside the trusted zone, meaning a rogue admin can simply change these values and connect the CoCo pod to a different Trustee, use insecure http and so on.
|
cat > initdata.toml <<EOF
algorithm = "sha256"
version = "0.1.0"
[data]
"aa.toml" = '''
[token_configs]
[token_configs.coco_as]
url = "${TRUSTEE_HOST}"
[token_configs.kbs]
url = "${TRUSTEE_HOST}"
cert = """
${TRUSTEE_CERT}
"""
'''
"cdh.toml" = '''
socket = 'unix:///run/confidential-containers/cdh.sock'
credentials = []
[kbc]
name = "cc_kbc"
url = "${TRUSTEE_HOST}"
kbs_cert = """
${TRUSTEE_CERT}
"""
'''
"policy.rego" = '''
package agent_policy
import future.keywords.in
import future.keywords.if
default AddARPNeighborsRequest := true
default AddSwapRequest := true
default CloseStdinRequest := true
default CopyFileRequest := true
default CreateContainerRequest := true
default CreateSandboxRequest := true
default DestroySandboxRequest := true
default GetMetricsRequest := true
default GetOOMEventRequest := true
default GuestDetailsRequest := true
default ListInterfacesRequest := true
default ListRoutesRequest := true
default MemHotplugByProbeRequest := true
default OnlineCPUMemRequest := true
default PauseContainerRequest := true
default PullImageRequest := true
default RemoveContainerRequest := true
default RemoveStaleVirtiofsShareMountsRequest := true
default ReseedRandomDevRequest := true
default ResumeContainerRequest := true
default SetGuestDateTimeRequest := true
default SetPolicyRequest := true
default SignalProcessRequest := true
default StartContainerRequest := true
default StartTracingRequest := true
default StatsContainerRequest := true
default StopTracingRequest := true
default TtyWinResizeRequest := true
default UpdateContainerRequest := true
default UpdateEphemeralMountsRequest := true
default UpdateInterfaceRequest := true
default UpdateRoutesRequest := true
default WaitProcessRequest := true
default WriteStreamRequest := true
# Enable logs, to see the output of curl
default ReadStreamRequest := true
# Restrict exec
default ExecProcessRequest := false
ExecProcessRequest if {
input_command = concat(" ", input.process.Args)
some allowed_command in policy_data.allowed_commands
input_command == allowed_command
}
# Add allowed commands for exec
policy_data := {
"allowed_commands": [
"curl -s http://127.0.0.1:8006/cdh/resource/default/kbsres1/key1",
"cat /sealed/secret-value/key2"
]
}
'''
EOF
clear
cat initdata.toml
A note on policy.rego
Under policy.rego
, you can specify a custom Kata Agent policy. The default policy allows all API calls. For production environments, set ReadStreamRequest
and ExecProcessRequest
to false
to disable the oc exec
and oc log
APIs, preventing unencrypted data transmission via the control plane. Adjust other true
or false
values to customize the policy further based on your needs. Note that if ExecProcessRequest
is enabled, but ReadStreamRequest
is not, the user can still inject commands, but won’t be able to see the output. This does not mean the command won’t be executed.
In this demo, we try something a bit more advanced: in order to securely allow the user to manually perform attestation, we restrict the exec
commands to only allow the secret fetching, and nothing else. allowed_commands
defines the only commands allowed to be exec’ed into the CoCo pod.
What the above means is that the defined command to curl key1
and cat /sealed/secret-value/key2
will work, but any other command will fail. Even oc exec -it pods/your_pod — curl http://127.0.0.1:8006/cdh/resource/default/kbsres1/key2
will not work.
This is extremely useful if the pod has to provide restricted access to an untrusted actor (admin, developer) to for example debug the application logic inside the Confidential Container.
For more information about these policy please check alternative Kata policy.
Measure the policy
Let’s convert the policy in base64 and store it in the INITDATA
variable.
INITDATA=$(cat initdata.toml | gzip | base64 -w0)
echo ""
echo $INITDATA
Now, let’s calculate the expected value of PCR8, which will be given in the reference values to make sure that every CoCo pod actually uses this initdata config.
initial_pcr=0000000000000000000000000000000000000000000000000000000000000000
hash=$(sha256sum initdata.toml | cut -d' ' -f1)
PCR8_HASH=$(echo -n "$initial_pcr$hash" | xxd -r -p | sha256sum | cut -d' ' -f1)
echo ""
echo "PCR 8:" $PCR8_HASH
Configure Trustee
You can configure the following values, policies, and secrets for Trustee:
-
TDX ConfigMap (used in this workshop but optional for non-TDX instances).
In the sections below, we will elencate how to set up all these options, but for the purpose of the workshop, we will not enforce the image signature verification.
Reference values for the Reference Value Provider Service
Purpose of this resource: In an attestation scenario, the client (CoCo) collects measurements from the running software, the Trusted Execution Environment (TEE) hardware and firmware and it submits a quote with the claims to the Attestation Server (Trustee, what we are setting right now). These measurements must match the trusted digests registered to the Trustee. This process ensures that the confidential VM (CVM) is running the expected software stack and has not been tampered with. By setting reference values, the user effectively defines the trusted digest (expected values) that Trustee expects from a valid client.
You can configure reference values for the Reference Value Provider Service (RVPS) by specifying the trusted digests of your hardware platform.
Red Hat currently ships an official CoCo podVM image together with its measurements. Therefore we simply need to insert the values into rvps-configmap.yaml
. Such values ensure that CoCo is running that specific image, with a RH kernel and specific features like initdata policy enabled.
Let’s download the measurements from Redhat and then convert them into a reference value configmap:
# 1. Prepare required files
IMAGE=$(oc get csv -n openshift-sandboxed-containers-operator -o yaml \
| grep RELATED_IMAGE_PODVM_OCI -A1 \
| awk '/value:/ {print $2}')
oc get -n openshift-config secret/pull-secret -o json \
| jq -r '.data.".dockerconfigjson"' \
| base64 -d \
| jq '.' > cluster-pull-secret.json
# On the ARO workshop, we don't have enough space for podman.
# Use a different folder.
sudo mkdir -p /podvm
sudo chown azure:azure /podvm
# 2. Download the measurements
podman pull --root /podvm --authfile cluster-pull-secret.json $IMAGE
cid=$(podman create --root /podvm --entrypoint /bin/true $IMAGE)
echo "CID ${cid}"
podman unshare --root /podvm sh -c '
mnt=$(podman mount --root /podvm '"$cid"')
echo "MNT ${mnt}"
cp $mnt/image/measurements.json /podvm
podman umount --root /podvm '"$cid"'
'
podman rm --root /podvm $cid
JSON_DATA=$(cat /podvm/measurements.json)
# 3. Prepare reference-values.json
REFERENCE_VALUES_JSON=$(echo "$JSON_DATA" | jq \
--arg pcr8_val "$PCR8_HASH" '
.measurements.sha256 | to_entries | map({
"name": .key,
"expiration": "2026-12-12T00:00:00Z",
"hash-value": [
{
"alg": "sha256",
"value": (.value | ltrimstr("0x"))
}
]
})
+
[
{
"name": "pcr08",
"expiration": "2026-12-12T00:00:00Z",
"hash-value": [
{
"alg": "sha256",
"value": $pcr8_val
}
]
}
]
| sort_by(.name | ltrimstr("pcr") | tonumber)
' | sed 's/^/ /')
# 4. Build the final ConfigMap
cat > rvps-configmap.yaml <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: rvps-reference-values
namespace: trustee-operator-system
data:
reference-values.json: |
$REFERENCE_VALUES_JSON
EOF
clear
cat rvps-configmap.yaml
Once the reference values have been added, apply the ConfigMap.
oc apply -f rvps-configmap.yaml
Attestation policy
Purpose of this resource: An attestation policy defines which part of the attestation report sent by the client (CoCo) is important for the Attester (Trustee), and how to compare the report with the reference values.
By default, Trustee has already an attestation policy. You can overwrite the default one by creating your own attestation policy.
The attestation policy follows the Open Policy Agent specification.
The policy below checks the Platform Configuration Register (PCR) values 03
, 08
, 09
, 11
, and 12
against the reference values to ensure that the Confidential Containers pod uses the specified restrictive Kata agent policy and that the Red Hat pod VM image has not been altered. The attestation process is successful only if all the values match. For details, see Linux TPM PCR Registry in the UAPI Group Specifications documentation.
cat > attestation-policy.yaml <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: attestation-policy
namespace: trustee-operator-system
data:
default.rego: |
package policy
import rego.v1
default executables := 33
default hardware := 97
default configuration := 36
##### Azure vTPM SNP
executables := 3 if {
input.azsnpvtpm.tpm.pcr03 in data.reference.pcr03
input.azsnpvtpm.tpm.pcr08 in data.reference.pcr08
input.azsnpvtpm.tpm.pcr09 in data.reference.pcr09
input.azsnpvtpm.tpm.pcr11 in data.reference.pcr11
input.azsnpvtpm.tpm.pcr12 in data.reference.pcr12
}
hardware := 0 if {
input.azsnpvtpm
}
configuration := 0 if {
input.azsnpvtpm
}
##### Azure vTPM TDX
executables := 3 if {
input.aztdxvtpm.tpm.pcr03 in data.reference.pcr03
input.aztdxvtpm.tpm.pcr08 in data.reference.pcr08
input.aztdxvtpm.tpm.pcr09 in data.reference.pcr09
input.aztdxvtpm.tpm.pcr11 in data.reference.pcr11
input.aztdxvtpm.tpm.pcr12 in data.reference.pcr12
}
hardware := 0 if {
input.aztdxvtpm
}
configuration := 0 if {
input.aztdxvtpm
}
EOF
clear
cat attestation-policy.yaml
Once you defined your own policy, apply it.
oc apply -f attestation-policy.yaml
TDX ConfigMap
Purpose of this resource: If your TEE is Intel Trust Domain Extensions (TDX), meaning the instance size you use or plan to use is Standard_DCe*, you must create the following ConfigMap.
Enabling such configmap does not prevent CoCo to use other TEEs.
cat > tdx-config.yaml <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: tdx-config
namespace: trustee-operator-system
data:
sgx_default_qcnl.conf: |
{
"collateral_service": "https://api.trustedservices.intel.com/sgx/certification/v4/"
}
EOF
clear
cat tdx-config.yaml
Once tdx-config.yaml
is ready, apply the ConfigMap.
oc apply -f tdx-config.yaml
Container image signature verification policy
Purpose of this resource: Sets wether to enforce or not the container image signature verification feature. If enabled, all containers images not signed by the trusted certificate provided in the container image verification secret will not be run.
The Trustee Operator returns this secret to the CoCo CVM components (which will run the CoCo pod) after attestation, to make sure they will perform the intended check. The CVM components will then compare the secret with the actual pod signature to determine whether to run it or not, ensuring that only trusted and authenticated container images are deployed in your environment.
You must in any case create the container image signature verification policy because signature verification is always enabled. If this policy is missing, the pods will not start.
-
Create a
security-policy-config.json
that enables or disables signature verification.In this example, we are going to create a policy that:
-
Ensures that the container
quay.io/confidential-devhub/signed-hello-openshift
(regardless of the tag) is signed, otherwise it will not be run. -
As a global policy, reject any other registry and non-signed image. This means only the above image is allowed to run, and only if it’s signed. Such policy can be also relaxed, for example allowing any container under the
confidential-devhub
org (by usingquay.io/confidential-devhub/*
), or to restrict the image signature to only such org/container pair while allowing all the others to be unsigned (changereject
toinsecureAcceptAnything
).Let’s create a secret containing the public key used to signed the above container image: because the image was built by the CoCo team, we need to download it first.
# Download the key curl -L https://raw.githubusercontent.com/confidential-devhub/workshop-on-ARO-showroom/refs/heads/showroom/helpers/cosign.pub -o cosign.pub SIGNATURE_SECRET_NAME=cosign-key SIGNATURE_SECRET_FILE=hello-pub-key oc create secret generic $SIGNATURE_SECRET_NAME \ --from-file=$SIGNATURE_SECRET_FILE=./cosign.pub \ -n trustee-operator-system
If you want to sign your own container, refer to the Red Hat Trusted Artifact Signer or other tools to sign container images. A simple guide on how to use upstream
cosign
is here.Note that
$SIGNATURE_SECRET_NAME
will be later used in the KbsConfigThen, create
security-policy-config.json
.Specify the image repository for
$SECURITY_POLICY_TRANSPORT
, in this casedocker
:. For more information, see containers-transports 5.Create
security-policy-config.json
. Specify the containerregistry/image
in$SECURITY_POLICY_IMAGE
.SECURITY_POLICY_TRANSPORT=docker SECURITY_POLICY_IMAGE=quay.io/confidential-devhub/signed-hello-openshift # TODO: this doesn't work for now! cat > security-policy-config-restrictive.json <<EOF { "default": [ { "type": "reject" } ], "transports": { "$SECURITY_POLICY_TRANSPORT": { "$SECURITY_POLICY_IMAGE": [ { "type": "sigstoreSigned", "keyPath": "kbs:///default/$SIGNATURE_SECRET_NAME/$SIGNATURE_SECRET_FILE" } ] } } } EOF cat > security-policy-config.json <<EOF { "default": [ { "type": "insecureAcceptAnything" } ], "transports": {} } EOF clear cat security-policy-config.json
Note how we set reject
as adefault
global policy. As explained above, this forbids any other non-specified image from being run. Change it ininsecureAcceptAnything
if you want to allow also unsigned images. If you don’t care at all about container policy, leaveinsecureAcceptAnything
and ensure"transports": {}"
.For more information on security policy, see containers-policy.json.5 and in particular this example.
-
-
After
security-policy-config.json
is created, upload it as a secret with the following command:oc create secret generic security-policy \ --from-file=osc=./security-policy-config.json \ -n trustee-operator-system
Do not alter the secret type, security-policy
, or the key,osc
.Note that
security-policy
will be later used in the KbsConfig
Resource access policy
Purpose of this resource: Resource policies control which secrets are released and are generally scoped to the workload. They allow the user define which attested workload has access to which resource, to avoid that the wrong client accesses data that it is not supposed to.
In this example below we are creating a simple policy that accepts any request that comes from an attester (client) that does use a TEE. For more information about resource access policies, and how to create stronger ones, look here
cat > resourcepolicy-configmap.yaml <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: resource-policy
namespace: trustee-operator-system
data:
policy.rego: |
package policy
import rego.v1
default allow = false
allow if {
input["submods"]["cpu"]["ear.status"] == "affirming"
}
EOF
clear
cat resourcepolicy-configmap.yaml
Once the policy has been implemented, apply the ConfigMap.
oc apply -f resourcepolicy-configmap.yaml
Add a secret to Trustee
Populate Trustee with secret(s) that are then managed by the above policies and if attestation is successful, are sent to the client(s) (CoCo). For example, a Confidential Container image/workload could be encrypted, and the key to decrypt it is stored inside the Trustee and provided only if attestation is successful. In this section, we will show how to add the key into Trustee.
Prerequisites: You have created one or more custom keys. In this workshop, we will also create 2 keys.
Define secret name and values. In this example, the kbsres1
secret has two entries (key1
, key2
), which the clients retrieve. You can add additional secrets according to your requirements by using the same format.
For the purpose of this workshop, we will show how to retrieve the key in two ways:
-
key1
will be retrieved via lazy attestation, meaning the application has to retrieve it itself by connecting with the internal guest components (the container does not need to know the Trustee address!) -
key2
will be retireved via a sealed secret, meaning which allows to load confidential information in the untrusted OCP environment. What this means is that the OCP sealed secret will simply be a pointer to the desiredkey2
stored in Trustee, and once the container starts, the CoCo guest components will automatically perform attestation with the Trustee, retrieve the key and load it into a specified volume.
More info on this in the example section.
Create what will be uploaded as key2
:
echo "This is my super secret key!" > key.bin
# Alternatively:
# openssl rand 128 > key.bin
We will add key1
as a simple string containing the text Confidential_Secret!
, and key2
as key.bin
.
SECRET_NAME=kbsres1
oc create secret generic $SECRET_NAME \
--from-literal key1=Confidential_Secret! \
--from-file key2=key.bin \
-n trustee-operator-system
Note that kbsres1
will be later used in the KbsConfig
Now, prepare the key2
sealed secret. Note that this secret is uploaded in the namespace where the CoCo pod will run (default
), not in the Trustee/OSC namespace, as it will be used directly by the CoCo pod:
SECRET=$(podman run -it quay.io/confidential-devhub/coco-tools:0.3.0 /tools/secret seal vault --resource-uri kbs:///default/${SECRET_NAME}/key2 --provider kbs | grep -v "Warning")
oc create secret generic sealed-secret --from-literal=key2=$SECRET -n default
Create the KbsConfig custom resource
To complete Trustee setup, you must create a KbsConfig
.
cat > kbsconfig-cr.yaml <<EOF
apiVersion: confidentialcontainers.org/v1alpha1
kind: KbsConfig
metadata:
labels:
app.kubernetes.io/name: kbsconfig
app.kubernetes.io/instance: kbsconfig
app.kubernetes.io/part-of: trustee-operator
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/created-by: trustee-operator
name: kbsconfig
namespace: trustee-operator-system
spec:
kbsConfigMapName: kbs-config-cm
kbsAuthSecretName: kbs-auth-public-key
kbsDeploymentType: AllInOneDeployment
kbsRvpsRefValuesConfigMapName: rvps-reference-values
kbsSecretResources: ["$SECRET_NAME", "security-policy", "attestation-token", "$SIGNATURE_SECRET_NAME"]
kbsResourcePolicyConfigMapName: resource-policy
kbsAttestationPolicyConfigMapName: attestation-policy
kbsHttpsKeySecretName: kbs-https-key
kbsHttpsCertSecretName: kbs-https-certificate
tdxConfigSpec:
kbsTdxConfigMapName: tdx-config
EOF
clear
cat kbsconfig-cr.yaml
Once the KbsConfig has been configured, apply it.
oc apply -f kbsconfig-cr.yaml
Verification
Verify the Trustee configuration by checking the Trustee pods and logs.
-
Check that both pods are up and running:
oc get pods -n trustee-operator-system
Expected output:
NAME READY STATUS RESTARTS AGE trustee-deployment-8585f98449-9bbgl 1/1 Running 0 22m trustee-operator-controller-manager-5fbd44cd97-55dlh 2/2 Running 0 59m
-
Check the KBS pod logs
POD_NAME=$(oc get pods -l app=kbs -o jsonpath='{.items[0].metadata.name}' -n trustee-operator-system) clear oc logs -n trustee-operator-system $POD_NAME
Expected output:
[2025-08-25T12:56:21Z INFO kbs] Using config file /etc/kbs-config/kbs-config.toml [2025-08-25T12:56:21Z WARN kbs::admin] insecure admin APIs are enabled [2025-08-25T12:56:21Z INFO attestation_service::rvps] launch a built-in RVPS. [2025-08-25T12:56:21Z WARN attestation_service::policy_engine::opa] Default policy file is already populated. Existing policy file will be used. [2025-08-25T12:56:21Z INFO attestation_service::token::ear_broker] Loading default AS policy "ear_default_policy.rego" [2025-08-25T12:56:21Z INFO attestation_service::token::ear_broker] No Token Signer key in config file, create an ephemeral key and without CA pubkey cert [2025-08-25T12:56:21Z INFO kbs::api_server] Starting HTTPS server at [0.0.0.0:8080] [2025-08-25T12:56:21Z INFO actix_server::builder] starting 64 workers [2025-08-25T12:56:21Z INFO actix_server::server] Actix runtime found; starting in Actix runtime [2025-08-25T12:56:21Z INFO actix_server::server] starting service: "actix-web-service-0.0.0.0:8080", workers: 64, listening on: 0.0.0.0:8080