Skip to content

Commit 540b31a

Browse files
committed
baremetal-coco: Add DCAP deployment for TDX
Let's set up a per-cluster PCCS, meaning: * a single service that chaces all the DCAP collateral requests * "indirect" DCAP registration, which stores the encrypted platform keys on PCCS * PCCS database on a dedicated node, where the admin knows what to back up (if needed) This is required in order to have attestation working for TDX, be it using DCAP directly or ITA. Signed-off-by: Fabiano Fidêncio <[email protected]> Signed-off-by: Mikko Ylinen <[email protected]>
1 parent 3259a59 commit 540b31a

File tree

5 files changed

+377
-0
lines changed

5 files changed

+377
-0
lines changed

scripts/install-helpers/baremetal-coco/install.sh

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ SKIP_NFD="${SKIP_NFD:-false}"
99
TRUSTEE_URL="${TRUSTEE_URL:-"http://kbs-service:8080"}"
1010
CMD_TIMEOUT="${CMD_TIMEOUT:-900}"
1111

12+
export PCCS_API_KEY="${PCCS_API_KEY:-}"
13+
export PCCS_DB_NAME="${PCCS_DB_NAME:-database}"
14+
export PCCS_DB_USERNAME="${PCCS_DB_USERNAME:-username}"
15+
export PCCS_DB_PASSWORD="${PCCS_DB_PASSWORD:-password}"
16+
export PCCS_USER_TOKEN="${PCCS_USER_TOKEN:-}"
17+
PCCS_ADMIN_TOKEN="${PCCS_ADMIN_TOKEN:-}"
18+
PCCS_PEM_CERT_PATH="${PCCS_PEM_CERT_PATH:-}"
19+
1220
# Function to check if a command is available
1321
function check_command() {
1422
local cmd="$1"
@@ -40,6 +48,29 @@ function wait_for_deployment() {
4048
return 1
4149
}
4250

51+
# Function to wait for a daemonset deployment to be ready
52+
function wait_for_daemonset() {
53+
local daemonset=$1
54+
local namespace=$2
55+
local timeout=$CMD_TIMEOUT
56+
local interval=5
57+
local elapsed=0
58+
local ready=0
59+
60+
local total_pods=$(oc get daemonset -n "$namespace" "$daemonset" -o=jsonpath='{.status.desiredNumberScheduled}' 2>/dev/null)
61+
while [ $elapsed -lt "$timeout" ]; do
62+
pods_ready=$(oc get daemonset -n "$namespace" "$daemonset" -o=jsonpath='{.status.numberReady}' 2>/dev/null)
63+
if [ "$total_pods" -eq "$pods_ready" ]; then
64+
echo "Daemonset $daemonset is ready"
65+
return 0
66+
fi
67+
sleep $interval
68+
elapsed=$((elapsed + interval))
69+
done
70+
echo "Daemonset $deployment is not ready after $timeout seconds"
71+
return 1
72+
}
73+
4374
# Function to wait for service endpoints IP to be available
4475
# Example json for service endpoints. IP is available in the "addresses" field
4576
# "subsets": [
@@ -247,6 +278,41 @@ function deploy_intel_device_plugins() {
247278
echo "Intel Device Plugins operator | deployment finished successfully"
248279
}
249280

281+
function deploy_intel_dcap() {
282+
echo "Intel DCAP | starting the deployment"
283+
284+
pushd intel-dcap || return 1
285+
oc apply -f ns.yaml || return 1
286+
287+
oc project intel-dcap
288+
oc adm policy add-scc-to-user privileged -z default
289+
oc project default
290+
291+
local PCCS_NODE=$(oc get nodes -l 'node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=' -o jsonpath='{.items[0].metadata.name}')
292+
export PCCS_NODE
293+
envsubst < pccs.yaml.in > pccs.yaml
294+
oc apply -f pccs.yaml || return 1
295+
wait_for_deployment pccs intel-dcap || return 1
296+
297+
local PCCS_URL=$(echo -n "https://pccs-service:8042" | base64 -w 0)
298+
local SECURE_CERT=$(echo -n "false" | base64 -w 0)
299+
local USER_TOKEN=$(echo -n $PCCS_USER_TOKEN | base64 -w 0)
300+
local REGISTRATION_HTTP_PROXY=$(echo -n $HTTP_PROXY | base64 -w 0)
301+
export PCCS_URL
302+
export SECURE_CERT
303+
export USER_TOKEN
304+
export REGISTRATION_HTTP_PROXY
305+
envsubst < registration-ds.yaml.in > registration-ds.yaml
306+
oc apply -f registration-ds.yaml || return 1
307+
wait_for_daemonset intel-dcap-registration-flow intel-dcap || return 1
308+
309+
oc apply -f qgs.yaml || return 1
310+
wait_for_daemonset tdx-qgs intel-dcap || return 1
311+
popd || return 1
312+
313+
echo "Intel DCAP | deployment finished successfully"
314+
}
315+
250316
function create_amd_node_feature_rules() {
251317
echo "Node Feature Discovery operator | creating amd node feature rules"
252318

@@ -415,6 +481,15 @@ function display_help() {
415481
echo "SKIP_NFD: Skip NFD operator installation and CR creation (default: false)"
416482
echo "TRUSTEE_URL: Trustee URL to be used in the kernel config (default: http://kbs-service:8080)"
417483
echo "CMD_TIMEOUT: Timeout for the commands (default: 900)"
484+
echo " "
485+
echo "Some environment variables required for TDX deployment:"
486+
echo "PCCS_API_KEY: The API key from https://api.portal.trustedservices.intel.com/ (THIS MUST BE PROVIDED)"
487+
echo "PCCS_DB_NAME: The name of the pccs database (if none is set, \"database\" will be used)"
488+
echo "PCCS_DB_USERNAME: The name of the pccs database user (if none is set, \"username\" will be used)"
489+
echo "PCCS_DB_PASSWORD: The password of the pccs database user (if none is set, \"password\" will be used)"
490+
echo "PCCS_USER_TOKEN: the user token for the PCCS client user to register a platform (if none is set, \"mytoken\" will be used)"
491+
echo "PCCS_ADMIN_TOKEN: the admin token for the PCCS client user to register a platform (if none is set, \"mytoken\" will be used)"
492+
echo "PCCS_PEM_CERT_PATH: The path where PCK (private.pem) and PCK Cert (certificate.pem) can be found (if none is passed, a pccs_tls folder will be created in your \$HOME directory, where PKC and PKC Cert will be created and used)"
418493
# Add some example usage options
419494
echo " "
420495
echo "Example usage:"
@@ -465,6 +540,47 @@ function verify_params() {
465540
return 1
466541
fi
467542

543+
if [ "$TEE_TYPE" = "tdx" ]; then
544+
if [ -z "$PCCS_API_KEY" ]; then
545+
echo "PCCS_API_KEY is a required environment variable for TDX deployment"
546+
display_help
547+
return 1
548+
fi
549+
550+
if [ -z "$PCCS_USER_TOKEN" ]; then
551+
PCCS_USER_TOKEN="mytoken"
552+
fi
553+
export PCCS_USER_TOKEN_HASH=$(echo -n "$PCCS_USER_TOKEN" | sha512sum | tr -d '[:space:]-')
554+
555+
if [ -z "$PCCS_ADMIN_TOKEN" ]; then
556+
PCCS_ADMIN_TOKEN="mytoken"
557+
fi
558+
export PCCS_ADMIN_TOKEN_HASH=$(echo -n "$PCCS_ADMIN_TOKEN" | sha512sum | tr -d '[:space:]-')
559+
560+
if [ -z "$PCCS_PEM_CERT_PATH" ]; then
561+
PCCS_PEM_CERT_PATH="$HOME/pccs-tls"
562+
mkdir -p "$PCCS_PEM_CERT_PATH"
563+
pushd "$PCCS_PEM_CERT_PATH"
564+
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout private.pem -out certificate.pem -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com"
565+
popd
566+
fi
567+
568+
if [ ! -f $PCCS_PEM_CERT_PATH/private.pem ]; then
569+
echo "PCCS_PEM_CERT_PATH does NOT contain a private.pem file, required for TDX deployment"
570+
display_help
571+
return 1
572+
fi
573+
574+
if [ ! -f $PCCS_PEM_CERT_PATH/certificate.pem ]; then
575+
echo "PCCS_PEM_CERT_PATH does NOT contain a certificate.pem file, required for TDX deployment"
576+
display_help
577+
return 1
578+
fi
579+
580+
export PCCS_PEM=$(cat $PCCS_PEM_CERT_PATH/private.pem | base64 | tr -d '\n')
581+
export PCCS_CERT=$(cat $PCCS_PEM_CERT_PATH/certificate.pem | base64 | tr -d '\n')
582+
fi
583+
468584
# If ADD_IMAGE_PULL_SECRET is true, then check if PULL_SECRET_JSON is set
469585
if [ "$ADD_IMAGE_PULL_SECRET" = true ] && [ -z "$PULL_SECRET_JSON" ]; then
470586
echo "ADD_IMAGE_PULL_SECRET is set but required environment variable: PULL_SECRET_JSON is not set"
@@ -473,6 +589,19 @@ function verify_params() {
473589

474590
}
475591

592+
function uninstall_intel_dcap() {
593+
echo "Intel DCAP | starting the uninstall"
594+
595+
pushd intel-dcap || return 1
596+
oc delete -f qgs.yaml || return 1
597+
oc delete -f registration-ds.yaml || return 1
598+
oc delete -f pccs.yaml || return 1
599+
oc delete -f ns.yaml || return 1
600+
popd || return 1
601+
602+
echo "Intel DCAP | deployment uninstalled successfully"
603+
}
604+
476605
function uninstall_intel_device_plugins() {
477606
echo "Intel Device Plugins operator | starting the uninstall"
478607

@@ -514,6 +643,7 @@ function uninstall() {
514643
echo "Uninstalling all the artifacts"
515644

516645
if [ "$TEE_TYPE" = "tdx" ]; then
646+
uninstall_intel_dcap || exit 1
517647
uninstall_intel_device_plugins || exit 1
518648
fi
519649

@@ -689,6 +819,7 @@ if [ "$SKIP_NFD" = false ]; then
689819
tdx)
690820
create_intel_node_feature_rules || exit 1
691821
deploy_intel_device_plugins || exit 1
822+
deploy_intel_dcap || exit 1
692823
;;
693824
snp)
694825
create_amd_node_feature_rules || exit 1
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
apiVersion: v1
2+
kind: Namespace
3+
metadata:
4+
name: intel-dcap
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
apiVersion: v1
2+
kind: ConfigMap
3+
metadata:
4+
name: pccs-config
5+
namespace: intel-dcap
6+
data:
7+
default.json: |
8+
{
9+
"HTTPS_PORT" : 8042,
10+
"hosts" : "0.0.0.0",
11+
"uri": "https://api.trustedservices.intel.com/sgx/certification/v4/",
12+
"ApiKey" : "${PCCS_API_KEY}",
13+
"proxy" : "${HTTP_PROXY}",
14+
"RefreshSchedule": "0 0 1 * * *",
15+
"UserTokenHash" : "${PCCS_USER_TOKEN_HASH}",
16+
"AdminTokenHash" : "${PCCS_ADMIN_TOKEN_HASH}",
17+
"CachingFillMode" : "LAZY",
18+
"OPENSSL_FIPS_MODE" : false,
19+
"LogLevel" : "info",
20+
"DB_CONFIG" : "sqlite",
21+
"sqlite" : {
22+
"database" : "${PCCS_DB_NAME}",
23+
"username" : "${PCCS_DB_USERNAME}",
24+
"password" : "${PCCS_DB_PASSWORD}",
25+
"options" : {
26+
"host": "localhost",
27+
"dialect": "sqlite",
28+
"pool": {
29+
"max": 5,
30+
"min": 0,
31+
"acquire": 30000,
32+
"idle": 10000
33+
},
34+
"define": {
35+
"freezeTableName": true
36+
},
37+
"logging" : true,
38+
"storage": "/var/cache/pccs/pckcache.db"
39+
}
40+
}
41+
}
42+
---
43+
apiVersion: v1
44+
kind: Secret
45+
metadata:
46+
name: pccs-tls
47+
namespace: intel-dcap
48+
type: Opaque
49+
data:
50+
private.pem: ${PCCS_PEM}
51+
file.crt: ${PCCS_CERT}
52+
---
53+
apiVersion: v1
54+
kind: Service
55+
metadata:
56+
name: pccs-service
57+
namespace: intel-dcap
58+
spec:
59+
selector:
60+
trustedservices.intel.com/cache: pccs
61+
ports:
62+
- name: pccs
63+
protocol: TCP
64+
port: 8042
65+
targetPort: pccs-port
66+
---
67+
apiVersion: apps/v1
68+
kind: Deployment
69+
metadata:
70+
name: pccs
71+
namespace: intel-dcap
72+
spec:
73+
replicas: 1
74+
selector:
75+
matchLabels:
76+
app: pccs
77+
template:
78+
metadata:
79+
labels:
80+
app: pccs
81+
trustedservices.intel.com/cache: pccs
82+
spec:
83+
nodeSelector:
84+
kubernetes.io/hostname: ${PCCS_NODE}
85+
initContainers:
86+
- name: init-seclabel
87+
image: quay.io/fidencio/init-seclabel:latest
88+
command: ["sh", "-c", "chcon -Rt container_file_t /var/cache/pccs"]
89+
volumeMounts:
90+
- name: host-database
91+
mountPath: /var/cache/pccs
92+
securityContext:
93+
runAsUser: 0
94+
runAsGroup: 0
95+
privileged: true # Required for chcon to work on host files
96+
containers:
97+
- name: pccs
98+
image: quay.io/fidencio/dcap/pccs:1.21
99+
ports:
100+
- containerPort: 8042
101+
name: pccs-port
102+
volumeMounts:
103+
- name: pccs-tls
104+
mountPath: /opt/intel/pccs/ssl_key
105+
readOnly: true
106+
- name: pccs-config
107+
mountPath: /opt/intel/pccs/config
108+
readOnly: true
109+
- name: host-database
110+
mountPath: /var/cache/pccs/
111+
securityContext:
112+
runAsUser: 0
113+
volumes:
114+
- name: pccs-tls
115+
secret:
116+
secretName: pccs-tls
117+
- name: pccs-config
118+
configMap:
119+
name: pccs-config
120+
- name: host-database
121+
hostPath:
122+
path: /var/cache/pccs/
123+
type: DirectoryOrCreate
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
apiVersion: v1
2+
kind: ConfigMap
3+
metadata:
4+
name: qgs-config
5+
namespace: intel-dcap
6+
data:
7+
qgs.conf: |
8+
port = 4050
9+
number_threads = 4
10+
---
11+
apiVersion: v1
12+
kind: ConfigMap
13+
metadata:
14+
name: sgx-default-qcnl-conf
15+
namespace: intel-dcap
16+
data:
17+
sgx_default_qcnl.conf: |
18+
{
19+
"pccs_url": "https://pccs-service:8042/sgx/certification/v4",
20+
"use_secure_cert": false,
21+
"retry_times": 6,
22+
"retry_delay": 10,
23+
"pck_cache_expire_hours": 168,
24+
"verify_collateral_cache_expire_hours": 168,
25+
"local_cache_only": false
26+
}
27+
---
28+
apiVersion: apps/v1
29+
kind: DaemonSet
30+
metadata:
31+
name: tdx-qgs
32+
namespace: intel-dcap
33+
spec:
34+
nodeSelector:
35+
intel.feature.node.kubernetes.io/tdx: true
36+
selector:
37+
matchLabels:
38+
app: tdx-qgs
39+
template:
40+
metadata:
41+
labels:
42+
app: tdx-qgs
43+
annotations:
44+
sgx.intel.com/quote-provider: tdx-qgs
45+
spec:
46+
hostNetwork: true
47+
containers:
48+
- name: tdx-qgs
49+
image: quay.io/fidencio/dcap/tdx-qgs:1.21
50+
workingDir: /opt/intel/tdx-qgs
51+
securityContext:
52+
readOnlyRootFilesystem: true
53+
allowPrivilegeEscalation: false
54+
resources:
55+
limits:
56+
sgx.intel.com/epc: "512Ki"
57+
sgx.intel.com/enclave: 1
58+
volumeMounts:
59+
- name: qgs-config
60+
mountPath: /etc/qgs.conf
61+
subPath: qgs.conf
62+
- name: sgx-default-qcnl-conf
63+
mountPath: /etc/sgx_default_qcnl.conf
64+
subPath: sgx_default_qcnl.conf
65+
volumes:
66+
- name: qgs-config
67+
configMap:
68+
name: qgs-config
69+
- name: sgx-default-qcnl-conf
70+
configMap:
71+
name: sgx-default-qcnl-conf

0 commit comments

Comments
 (0)