mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-06-23 04:10:25 +00:00
d5badba547
CI / lint (push) Has been cancelled
CI / test (agent) (push) Has been cancelled
CI / test (cli) (push) Has been cancelled
CI / test (cmd) (push) Has been cancelled
CI / test (internal) (push) Has been cancelled
CI / test (manager, true) (push) Has been cancelled
CI / test (pkg) (push) Has been cancelled
CI / upload-coverage (push) Has been cancelled
* feat: Implement per-resource KBS configuration, allowing algorithms and datasets to specify individual KBS URLs. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * refactor: Encapsulate CLI error handling and CVM certificate paths within the CLI struct, and add algorithm type to agent's algorithm structure. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * style: Remove blank lines and fix indentation in CLI commands. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * refactor: Update downloadAndDecryptGenericResource to accept KBS URL as a parameter and adjust related tests Signed-off-by: Sammy Oina <sammyoina@gmail.com> * refactor: group CLI configuration into structured types and simplify skopeo decryption key handling Signed-off-by: Sammy Oina <sammyoina@gmail.com> --------- Signed-off-by: Sammy Oina <sammyoina@gmail.com>
469 lines
13 KiB
Markdown
469 lines
13 KiB
Markdown
# Testing Remote Resources with CoCo Key Provider
|
|
|
|
This guide explains how to test Cocos with encrypted remote resources using the Confidential Containers Key Provider ecosystem.
|
|
|
|
## Architecture Overview
|
|
|
|
```
|
|
┌────────────────────────────────────────────────────────────┐
|
|
│ CVM (Agent) │
|
|
│ │
|
|
│ ┌──────────┐ ┌────────────────┐ ┌─────────────────┐ │
|
|
│ │ Agent │──▶│ Skopeo │──▶│ CoCo Keyprovider│ │
|
|
│ │ │ │ (ocicrypt) │ │ (gRPC:50011) │ │
|
|
│ │ │ └───────┬────────┘ └────────┬────────┘ │
|
|
│ │ │ │ │ │
|
|
│ │ │ ┌───────▼────────┐ ┌────────▼────────┐ │
|
|
│ │ │──▶│ S3/HTTP │ │ Attestation │ │
|
|
│ │ │ │ Downloader │ │ Agent (50002) │ │
|
|
│ └────┬─────┘ └───────┬────────┘ └────────┬────────┘ │
|
|
│ │ │ │ │
|
|
│ └──────────────────┼──────────────────────┘ │
|
|
└────────┬─────────────────┼──────────────────────┬──────────┘
|
|
│ (Resource) │ (Resource) │ (Attest)
|
|
▼ ▼ ▼
|
|
OCI Registry S3 / HTTP / GCS KBS
|
|
(Key Broker)
|
|
```
|
|
|
|
## Prerequisites
|
|
|
|
### 1. Install Skopeo (Host Machine)
|
|
|
|
```bash
|
|
# Ubuntu/Debian
|
|
sudo apt-get install skopeo
|
|
|
|
# macOS
|
|
brew install skopeo
|
|
|
|
# Or build from source
|
|
git clone https://github.com/containers/skopeo
|
|
cd skopeo
|
|
make bin/skopeo
|
|
sudo make install
|
|
```
|
|
|
|
### 2. Start KBS Server (Host Machine)
|
|
|
|
```bash
|
|
# Clone and build KBS
|
|
git clone https://github.com/confidential-containers/trustee
|
|
cd trustee/kbs
|
|
# Patch Cargo.toml to disable SGX requirement (for testing only)
|
|
sed -i 's/"all-verifier",//g' Cargo.toml
|
|
|
|
make
|
|
make cli
|
|
|
|
# Generate admin keys
|
|
openssl genpkey -algorithm ed25519 -out kbs-admin.key
|
|
openssl pkey -in kbs-admin.key -pubout -out kbs-admin.pub
|
|
|
|
# Create KBS configuration file
|
|
cat > kbs-config.toml << 'EOF'
|
|
[http_server]
|
|
sockets = ["0.0.0.0:8080"]
|
|
insecure_http = true
|
|
|
|
[admin]
|
|
type = "Simple"
|
|
[[admin.personas]]
|
|
id = "admin"
|
|
public_key_path = "kbs-admin.pub"
|
|
|
|
[attestation_service]
|
|
type = "coco_as_builtin"
|
|
work_dir = "kbs-data/as"
|
|
|
|
[attestation_service.rvps_config]
|
|
type = "BuiltIn"
|
|
|
|
[attestation_service.rvps_config.storage]
|
|
type = "LocalFs"
|
|
file_path = "kbs-data/rvps-values"
|
|
|
|
[[plugins]]
|
|
name = "resource"
|
|
type = "LocalFs"
|
|
dir_path = "kbs-data/repository"
|
|
EOF
|
|
|
|
# Create configuration directories
|
|
mkdir -p kbs-data/as kbs-data/rvps kbs-data/repository
|
|
|
|
# Start KBS
|
|
sudo ../target/release/kbs --config-file kbs-config.toml
|
|
```
|
|
|
|
KBS will listen on `http://localhost:8080`
|
|
|
|
### 3. Setup Local OCI Registry (Optional)
|
|
|
|
For testing, you can use a local registry:
|
|
|
|
```bash
|
|
docker run -d -p 5000:5000 --name registry registry:2
|
|
```
|
|
|
|
## Creating Encrypted Resources
|
|
|
|
### Encrypt an Algorithm (Python Script)
|
|
|
|
```bash
|
|
# 1. Create a simple algorithm
|
|
cat > lin_reg.py << 'EOF'
|
|
import pandas as pd
|
|
from sklearn.linear_model import LinearRegression
|
|
import sys
|
|
import os
|
|
|
|
# Load dataset
|
|
data = pd.read_csv(sys.argv[1])
|
|
X = data[['feature1', 'feature2']]
|
|
y = data['target']
|
|
|
|
# Train model
|
|
model = LinearRegression()
|
|
model.fit(X, y)
|
|
|
|
# Save results
|
|
os.makedirs("results", exist_ok=True)
|
|
with open("results/output.txt", "w") as f:
|
|
f.write(f"Coefficients: {model.coef_}\n")
|
|
f.write(f"Intercept: {model.intercept_}\n")
|
|
|
|
print(f"Coefficients: {model.coef_}")
|
|
print(f"Intercept: {model.intercept_}")
|
|
EOF
|
|
|
|
# 2. Create requirements.txt
|
|
cat > requirements.txt << 'EOF'
|
|
pandas
|
|
scikit-learn
|
|
EOF
|
|
|
|
# 3. Create a Dockerfile
|
|
cat > Dockerfile << 'EOF'
|
|
FROM python:3.9-slim
|
|
RUN pip install pandas scikit-learn
|
|
COPY lin_reg.py /app/algorithm.py
|
|
COPY requirements.txt /app/requirements.txt
|
|
WORKDIR /app
|
|
ENTRYPOINT ["python", "algorithm.py"]
|
|
EOF
|
|
|
|
# 4. Build the image
|
|
docker build -t localhost:5000/lin-reg-algo:v1.0 .
|
|
docker push localhost:5000/lin-reg-algo:v1.0
|
|
|
|
# 5. Generate and store key
|
|
openssl rand -out algo.key 32
|
|
|
|
# 6. Store key in KBS using kbs-client
|
|
../target/release/kbs-client --url http://localhost:8080 config \
|
|
--auth-private-key kbs-admin.key \
|
|
set-resource \
|
|
--path default/key/algo-key \
|
|
--resource-file algo.key
|
|
|
|
# 7. Encrypt the image using Host Skopeo + Docker Keyprovider
|
|
# Start Keyprovider in background
|
|
docker run -d --rm --name keyprovider --network host \
|
|
-v "$PWD:/work" -w /work \
|
|
ghcr.io/confidential-containers/staged-images/coco-keyprovider:latest \
|
|
coco_keyprovider --socket 127.0.0.1:50000
|
|
|
|
# Configure Ocicrypt to use local Keyprovider
|
|
cat <<EOF > ocicrypt.conf
|
|
{
|
|
"key-providers": {
|
|
"attestation-agent": {
|
|
"grpc": "127.0.0.1:50000"
|
|
}
|
|
}
|
|
}
|
|
EOF
|
|
export OCICRYPT_KEYPROVIDER_CONFIG=$(pwd)/ocicrypt.conf
|
|
|
|
# Encrypt Algo
|
|
skopeo copy \
|
|
--src-tls-verify=false \
|
|
--dest-tls-verify=false \
|
|
--encryption-key "provider:attestation-agent:keypath=/work/algo.key::keyid=kbs:///default/key/algo-key::algorithm=A256GCM" \
|
|
docker://localhost:5000/lin-reg-algo:v1.0 \
|
|
docker://localhost:5000/encrypted-lin-reg:v1.0
|
|
|
|
# Stop Keyprovider
|
|
docker stop keyprovider
|
|
```
|
|
|
|
### Encrypt a Dataset (CSV in OCI Image)
|
|
|
|
```bash
|
|
# 1. Create dataset
|
|
cat > iris.csv << 'EOF'
|
|
feature1,feature2,target
|
|
5.1,3.5,0
|
|
4.9,3.0,0
|
|
6.2,3.4,1
|
|
5.9,3.0,1
|
|
EOF
|
|
|
|
# 2. Create Dockerfile for dataset
|
|
cat > Dockerfile.dataset << 'EOF'
|
|
FROM scratch
|
|
COPY iris.csv /data/iris.csv
|
|
EOF
|
|
|
|
# 3. Build and push
|
|
docker build -f Dockerfile.dataset -t localhost:5000/iris-dataset:v1.0 .
|
|
docker push localhost:5000/iris-dataset:v1.0
|
|
|
|
# 4. Generate and store key
|
|
# 4. Generate and store key
|
|
openssl rand -out dataset.key 32
|
|
../target/release/kbs-client --url http://localhost:8080 config \
|
|
--auth-private-key kbs-admin.key \
|
|
set-resource \
|
|
--path default/key/dataset-key \
|
|
--resource-file dataset.key
|
|
|
|
# 5. Encrypt dataset image using Host Skopeo + Docker Keyprovider
|
|
# Start Keyprovider in background
|
|
docker run -d --rm --name keyprovider --network host \
|
|
-v "$PWD:/work" -w /work \
|
|
ghcr.io/confidential-containers/staged-images/coco-keyprovider:latest \
|
|
coco_keyprovider --socket 127.0.0.1:50000
|
|
|
|
# Configure Ocicrypt (if not already done)
|
|
export OCICRYPT_KEYPROVIDER_CONFIG=$(pwd)/ocicrypt.conf
|
|
|
|
# Encrypt Dataset
|
|
skopeo copy \
|
|
--src-tls-verify=false \
|
|
--dest-tls-verify=false \
|
|
--encryption-key "provider:attestation-agent:keypath=/work/dataset.key::keyid=kbs:///default/key/dataset-key::algorithm=A256GCM" \
|
|
docker://localhost:5000/iris-dataset:v1.0 \
|
|
docker://localhost:5000/encrypted-iris:v1.0
|
|
|
|
# Stop Keyprovider
|
|
docker stop keyprovider
|
|
```
|
|
|
|
## Running a Computation
|
|
|
|
### 1. Start Manager (Host)
|
|
|
|
```bash
|
|
cd /path/to/cocos-ai
|
|
./build/cocos-manager
|
|
```
|
|
|
|
### 2. Start CVMS Test Server (Host)
|
|
|
|
Get your host IP:
|
|
```bash
|
|
HOST_IP=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v 127.0.0.1 | head -n1)
|
|
```
|
|
|
|
Start CVMS server:
|
|
```bash
|
|
# Calculate SHA3-256 of decrypted files using cocos-cli or cvms-test
|
|
# NOTE: We use the hash of the original plaintext files, as the Agent validates the decrypted content.
|
|
# For single files, use the file hash. For directories, use the hash of the directory (which the tools zip deterministically).
|
|
|
|
ALGO_HASH=$(./build/cocos-cli checksum lin_reg.py 2>&1 | awk '{print $NF}')
|
|
|
|
DATASET_HASH=$(./build/cocos-cli checksum iris.csv 2>&1 | awk '{print $NF}')
|
|
|
|
go build -o build/cvms-test ./test/cvms/main.go
|
|
HOST=$HOST_IP PORT=7001 ./build/cvms-test \
|
|
-public-key-path ./public.pem \
|
|
-attested-tls-bool false \
|
|
-algo-type python \
|
|
-algo-source-url docker://$HOST_IP:5000/encrypted-lin-reg:v1.0 \
|
|
-algo-kbs-path default/key/algo-key \
|
|
-algo-kbs-url http://$HOST_IP:8080 \
|
|
-algo-hash $ALGO_HASH \
|
|
-algo-args datasets/dataset_0.csv \
|
|
-dataset-source-urls docker://$HOST_IP:5000/encrypted-iris:v1.0 \
|
|
-dataset-kbs-paths default/key/dataset-key \
|
|
-dataset-kbs-urls http://$HOST_IP:8080 \
|
|
-dataset-hash $DATASET_HASH
|
|
```
|
|
|
|
> [!NOTE]
|
|
> You must specify the KBS URL for each encrypted resource using `-algo-kbs-url` and `-dataset-kbs-urls`. A global KBS is no longer supported.
|
|
|
|
|
|
### 3. Create VM via CLI (Host)
|
|
|
|
```bash
|
|
export MANAGER_GRPC_URL=localhost:7002
|
|
./build/cocos-cli create-vm \
|
|
--server-url $HOST_IP:7001 \
|
|
--log-level debug
|
|
```
|
|
|
|
The agent will:
|
|
1. Receive computation manifest from CVMS
|
|
2. Use Skopeo to download encrypted OCI images
|
|
3. Skopeo invokes CoCo Keyprovider via ocicrypt
|
|
4. CoCo Keyprovider requests decryption key from KBS
|
|
5. Attestation Agent generates TEE evidence for KBS
|
|
6. KBS validates evidence and returns decryption key
|
|
7. Image layers are decrypted and extracted
|
|
8. Computation executes with decrypted algorithm and dataset
|
|
|
|
## Verifying the Setup
|
|
|
|
### Check CoCo Keyprovider Status (Inside CVM)
|
|
|
|
```bash
|
|
# SSH into CVM or use console
|
|
systemctl status coco-keyprovider
|
|
journalctl -u coco-keyprovider -f
|
|
```
|
|
|
|
### Check Attestation Agent Status
|
|
|
|
```bash
|
|
systemctl status attestation-agent
|
|
journalctl -u attestation-agent -f
|
|
```
|
|
|
|
### Test Skopeo Decryption Manually
|
|
|
|
```bash
|
|
# Inside CVM
|
|
export OCICRYPT_KEYPROVIDER_CONFIG=/etc/ocicrypt_keyprovider.conf
|
|
|
|
skopeo copy \
|
|
--src-tls-verify=false \
|
|
--dest-tls-verify=false \
|
|
--decryption-key provider:attestation-agent:cc_kbc::null \
|
|
docker://localhost:5000/encrypted-lin-reg:v1.0 \
|
|
oci:/tmp/decrypted-algo
|
|
|
|
# Verify decryption
|
|
skopeo inspect oci:/tmp/decrypted-algo | jq -r '.LayersData[].MIMEType'
|
|
# Should show: application/vnd.oci.image.layer.v1.tar+gzip
|
|
```
|
|
|
|
## Computation Manifest Format
|
|
|
|
The CVMS server sends this manifest to the agent:
|
|
|
|
```json
|
|
{
|
|
"computation_id": "1",
|
|
"algorithm": {
|
|
"type": "oci-image",
|
|
"uri": "docker://localhost:5000/encrypted-lin-reg:v1.0",
|
|
"encrypted": true,
|
|
"kbs_resource_path": "default/key/algo-key",
|
|
"kbs": {
|
|
"url": "http://192.168.100.15:8080",
|
|
"enabled": true
|
|
}
|
|
},
|
|
"datasets": [
|
|
{
|
|
"filename": "iris.csv",
|
|
"source": {
|
|
"type": "oci-image",
|
|
"url": "docker://localhost:5000/encrypted-iris:v1.0",
|
|
"encrypted": true,
|
|
"kbs_resource_path": "default/key/dataset-key"
|
|
},
|
|
"kbs": {
|
|
"url": "http://192.168.100.20:8080",
|
|
"enabled": true
|
|
}
|
|
}
|
|
],
|
|
"kbs": {
|
|
"url": "http://192.168.100.15:8080",
|
|
"enabled": true
|
|
}
|
|
}
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### CoCo Keyprovider Not Starting
|
|
|
|
```bash
|
|
# Check logs
|
|
journalctl -u coco-keyprovider -n 50
|
|
|
|
# Verify socket is listening
|
|
ss -tlnp | grep 50011
|
|
|
|
# Check environment
|
|
cat /etc/default/coco-keyprovider
|
|
```
|
|
|
|
### Skopeo Decryption Fails
|
|
|
|
```bash
|
|
# Verify ocicrypt config
|
|
cat /etc/ocicrypt_keyprovider.conf
|
|
|
|
# Test keyprovider connection
|
|
grpcurl -plaintext 127.0.0.1:50011 list
|
|
|
|
# Check KBS connectivity from CVM
|
|
curl http://HOST_IP:8080/kbs/v0/auth
|
|
```
|
|
|
|
### KBS Returns 401
|
|
|
|
```bash
|
|
# Check KBS logs on host
|
|
# Verify attestation evidence format
|
|
# Ensure KBS is configured for sample attestation
|
|
```
|
|
|
|
## 4. Testing with Non-OCI Sources (S3, HTTP, GCS)
|
|
|
|
The `cvms` test utility also supports testing remote encrypted resources hosted in more traditional environments like S3-compatible storage or simple web servers, bypassing the need for container registries and OCI images.
|
|
|
|
### Supported Flags
|
|
|
|
The following flags define how resources should be fetched:
|
|
|
|
- `--algo-source-url`: The URL of the algorithm (e.g. `s3://bucket/algo.bin`, `https://server/algo.bin`)
|
|
- `--algo-source-type`: The type of remote endpoint (`s3`, `gcs`, `https`, `http`). If omitted, it will automatically be inferred from the URL scheme.
|
|
- `--algo-kbs-path`: The KBS path to retrieve the AES-256-GCM key from. If present, the agent will attempt decryption.
|
|
- `--dataset-source-urls` and `--dataset-source-type`: Defines the locations and protocols for datasets.
|
|
|
|
### Encryption Format for Non-OCI Sources
|
|
|
|
Unlike OCI images where `ocicrypt` wraps the dataset, resources hosted on HTTP/S3 must be straightforwardly encrypted using **AES-256-GCM**.
|
|
|
|
The expected format is exactly as produced by standard Go AES-GCM:
|
|
`nonce (12 bytes) || ciphertext || tag`
|
|
|
|
### Test Example
|
|
|
|
If you had a Python script encrypted using a key hosted at KBS path `default/my-keys/python-script` and uploaded to `s3://my-secure-bucket/script.enc`, you could run:
|
|
|
|
```bash
|
|
cd test
|
|
go run cvms/main.go --algo-source-url="s3://my-secure-bucket/script.enc" \
|
|
--algo-source-type="s3" \
|
|
--algo-kbs-path="default/my-keys/python-script" \
|
|
--algo-type="python" \
|
|
--public-key-path=./test-data/public-key.pem
|
|
```
|
|
|
|
The system will:
|
|
1. Connect via `attestation-agent` to the KBS to retrieve the symmetric key
|
|
2. Use Google Cloud Storage client library methods (support for generic S3 via environment variables is standard) to fetch the resource
|
|
3. Decrypt using AES-256-GCM
|
|
4. Run the code normally
|
|
|
|
---
|