Skip to content
Draft
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
30 changes: 30 additions & 0 deletions .goreleaser-docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ before:
- apt update
- apt install -y pkg-config libudev-dev:amd64 libudev-dev:arm64
builds:
- id: attestation-sidecar-linux-amd64
binary: attestation-sidecar
main: ./sidecar/attestation
goarch:
- amd64
goos:
- linux
env:
- CGO_ENABLED=0
flags:
- -trimpath
ldflags:
- -s -w
- id: provider-services-linux-arm64
binary: provider-services
main: ./cmd/provider-services
Expand Down Expand Up @@ -160,3 +173,20 @@ dockers:
- --label=org.opencontainers.image.revision={{ .FullCommit }}
image_templates:
- "{{ .Env.DOCKER_IMAGE }}:latest-arm64-debug"
- dockerfile: sidecar/attestation/Dockerfile
ids:
- attestation-sidecar-linux-amd64
use: buildx
goos: linux
goarch: amd64
build_flag_templates:
- --platform=linux/amd64
- --label=org.opencontainers.image.title=attestation-sidecar
- --label=org.opencontainers.image.description=Akash attestation sidecar for confidential compute
- --label=org.opencontainers.image.url={{.GitURL}}
- --label=org.opencontainers.image.source={{.GitURL}}
- --label=org.opencontainers.image.version={{ .Version }}
- --label=org.opencontainers.image.created={{ time "2006-01-02T15:04:05Z07:00" }}
- --label=org.opencontainers.image.revision={{ .FullCommit }}
image_templates:
- "{{ .Env.DOCKER_IMAGE }}-attestation-sidecar:latest-amd64"
13 changes: 13 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,19 @@ builds:
- -extldflags "-L./.cache/lib -lwasmvm_muslc.x86_64 -Wl,-z,muldefs -lm -lrt -lc"
gcflags:
- "all=-N -l"
- id: attestation-sidecar-linux-amd64
binary: attestation-sidecar
main: ./sidecar/attestation
goarch:
- amd64
goos:
- linux
env:
- CGO_ENABLED=0
flags:
- -trimpath
ldflags:
- -s -w
universal_binaries:
- id: darwin-universal
ids:
Expand Down
7 changes: 6 additions & 1 deletion _run/common-commands.mk
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ PRICE ?= 10uakt
CERT_HOSTNAME ?= localhost
LEASE_SERVICES ?= web

RESOURCE_SERVER_HOST ?= localhost:8445
RESOURCE_SERVER_HOST ?= localhost:8445
GATEWAY_GRPC_ENDPOINT ?= localhost:8444

GW_AUTH_TYPE ?= jwt

Expand Down Expand Up @@ -293,6 +294,10 @@ provider-lease-events:
--provider "$(PROVIDER_ADDRESS)" \
--auth-type "$(GW_AUTH_TYPE)"

.PHONY: provider-lease-attestation
provider-lease-attestation:
$(PROVIDER_SERVICES) lease-attestation --dseq "$(DSEQ)" --gseq "$(GSEQ)" --oseq "$(OSEQ)" --from "$(KEY_NAME)" --provider "$(PROVIDER_ADDRESS)" --auth-type "$(GW_AUTH_TYPE)"

.PHONY: provider-lease-status
provider-lease-status:
$(PROVIDER_SERVICES) lease-status \
Expand Down
67 changes: 64 additions & 3 deletions _run/kube/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
GATEWAY_API ?= false
GATEWAY_API ?= false
CONFIDENTIAL_COMPUTE ?= false

KUBE_SETUP_PREREQUISITES ?= \

Expand All @@ -23,7 +24,22 @@ kube-setup-ingress-default: kube-setup-ingress-gateway
@echo "Gateway API ingress setup complete"
endif

SDL_PATH ?= grafana.yaml
# CC mode: use Kind config with containerd runtime patches (no restart needed)
ifeq ($(CONFIDENTIAL_COMPUTE),true)
KIND_CONFIG_FILE := $(CURDIR)/kind-config-cc.yaml
endif

# Confidential compute mode overrides
DEV_REGISTRY ?= ghcr.io/cloud-j-luna
DEV_COMMIT := $(shell git rev-parse --short HEAD)

ifeq ($(CONFIDENTIAL_COMPUTE),true)
SDL_PATH := deployment-cc.yaml
PROVIDER_CONFIG_PATH := provider-cc.yaml
ATTESTATION_SIDECAR_IMAGE ?= $(DEV_REGISTRY)/attestation-sidecar:$(DEV_COMMIT)
else
SDL_PATH ?= grafana.yaml
endif

GATEWAY_HOSTNAME ?= localhost
GATEWAY_HOST ?= $(GATEWAY_HOSTNAME):8443
Expand All @@ -42,7 +58,12 @@ provider-run:
--bid-price-strategy "randomRange" \
--deployment-runtime-class "none" \
--ip-operator=true \
$(if $(filter true,$(GATEWAY_API)),--ingress-mode=gateway-api)
$(if $(filter true,$(GATEWAY_API)),--ingress-mode=gateway-api) \
$(if $(filter true,$(CONFIDENTIAL_COMPUTE)),\
--attestation-webhook-enabled=true \
--attestation-sidecar-image="$(ATTESTATION_SIDECAR_IMAGE)" \
--attestation-mock=true \
)

.PHONY: provider-lease-ping
provider-lease-ping:
Expand All @@ -52,6 +73,44 @@ provider-lease-ping:
hostname-operator:
$(PROVIDER_SERVICES) hostname-operator

# Confidential compute cluster setup: creates RuntimeClass objects and labels
# the Kind node with TEE capability labels so the provider can schedule CC
# workloads. The pods won't actually run with Kata (Kind doesn't have it),
# but the webhook, annotations, and sidecar injection can be verified.
.PHONY: kube-setup-cc
kube-setup-cc:
kubectl apply -f cc-setup.yaml
@echo "Labeling kind node for CC..."
@for node in $$(kubectl get nodes -o name); do \
kubectl label $$node \
katacontainers.io/kata-runtime=true \
amd.feature.node.kubernetes.io/snp=true \
intel.feature.node.kubernetes.io/tdx=true \
nvidia.com/cc.ready.state=true \
--overwrite; \
done
@echo "Building and loading attestation sidecar image into Kind..."
@mkdir -p /tmp/akash-sidecar-build
GOWORK=off CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -mod=vendor -ldflags="-s -w" -o /tmp/akash-sidecar-build/attestation-sidecar $(AP_ROOT)/sidecar/attestation
cp $(AP_ROOT)/sidecar/attestation/Dockerfile /tmp/akash-sidecar-build/Dockerfile
docker build -q -t "$(ATTESTATION_SIDECAR_IMAGE)" /tmp/akash-sidecar-build/
$(KIND) load docker-image "$(ATTESTATION_SIDECAR_IMAGE)" --name "$(KIND_NAME)"
@echo "CC setup complete. RuntimeClasses, node labels, and sidecar image loaded."

.PHONY: kube-teardown-cc
kube-teardown-cc:
-kubectl delete -f cc-setup.yaml 2>/dev/null
@for node in $$(kubectl get nodes -o name); do \
kubectl label $$node \
katacontainers.io/kata-runtime- \
amd.feature.node.kubernetes.io/snp- \
intel.feature.node.kubernetes.io/tdx- \
nvidia.com/cc.ready.state- \
2>/dev/null; \
done
@echo "CC teardown complete."

.PHONY: clean-kube
clean-kube:

Expand All @@ -61,6 +120,8 @@ kube-deployments-rollout: #$(patsubst %, kube-deployment-rollout-%,$(KUSTOMIZE_I
.PHONY: kube-setup-kube
ifeq ($(GATEWAY_API),true)
kube-setup-kube: kube-setup-hostname-operator-gateway
else ifeq ($(CONFIDENTIAL_COMPUTE),true)
kube-setup-kube: kube-setup-cc
else
kube-setup-kube:
endif
Expand Down
22 changes: 22 additions & 0 deletions _run/kube/cc-containerd-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash
# Registers mock CC runtime handlers in containerd, aliased to runc.
# Run inside the Kind node via: docker exec <node> bash /path/to/this/script
set -e

if grep -q kata-qemu-snp /etc/containerd/config.toml; then
echo "CC runtime handlers already registered"
exit 0
fi

for rt in kata-qemu-snp kata-qemu-nvidia-gpu-snp kata-qemu-tdx kata-qemu-nvidia-gpu-tdx; do
cat >> /etc/containerd/config.toml <<EOF

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.${rt}]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.${rt}.options]
SystemdCgroup = true
EOF
done

systemctl restart containerd
echo "containerd restarted with CC runtime aliases"
29 changes: 29 additions & 0 deletions _run/kube/cc-setup.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
# RuntimeClass objects for confidential compute.
# These reference Kata runtime handlers that don't exist on a Kind cluster,
# but the webhook fires on the pod spec before scheduling — so the sidecar
# injection can be verified even without real Kata.

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: kata-qemu-snp
handler: kata-qemu-snp
---
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: kata-qemu-nvidia-gpu-snp
handler: kata-qemu-nvidia-gpu-snp
---
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: kata-qemu-tdx
handler: kata-qemu-tdx
---
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: kata-qemu-nvidia-gpu-tdx
handler: kata-qemu-nvidia-gpu-tdx
41 changes: 41 additions & 0 deletions _run/kube/deployment-cc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
version: "2.1"

services:
web:
image: nginx
expose:
- port: 80
as: 80
accept:
- hello.localhost
to:
- global: true
params:
tee:
type: sev-snp

profiles:
compute:
web:
resources:
cpu:
units: 0.5
memory:
size: 256Mi
storage:
size: 128Mi
placement:
westcoast:
attributes:
region: us-west
pricing:
web:
denom: uact
amount: 1000

deployment:
web:
westcoast:
profile: web
count: 1
32 changes: 32 additions & 0 deletions _run/kube/kind-config-cc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
protocol: TCP
containerdConfigPatches:
- |-
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-qemu-snp]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-qemu-snp.options]
SystemdCgroup = true
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-qemu-nvidia-gpu-snp]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-qemu-nvidia-gpu-snp.options]
SystemdCgroup = true
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-qemu-tdx]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-qemu-tdx.options]
SystemdCgroup = true
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-qemu-nvidia-gpu-tdx]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-qemu-nvidia-gpu-tdx.options]
SystemdCgroup = true
11 changes: 11 additions & 0 deletions _run/kube/provider-cc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
host: https://localhost:8443
jwt-host: https://localhost:8444
attributes:
- key: region
value: us-west
- key: tee/type
value: sev-snp
- key: capabilities/storage/1/persistent
value: true
- key: capabilities/storage/1/class
value: default
7 changes: 4 additions & 3 deletions bidengine/pricing.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,8 @@ type dataForScriptElement struct {
}

type dataForScript struct {
Resources []dataForScriptElement `json:"resources"`
Price sdk.DecCoin `json:"price"`
PricePrecision *int `json:"price_precision,omitempty"`
Resources []dataForScriptElement `json:"resources"`
Price sdk.DecCoin `json:"price"`
PricePrecision *int `json:"price_precision,omitempty"`
ConfidentialComputeSidecar bool `json:"confidential_compute_sidecar"`
}
7 changes: 7 additions & 0 deletions bidengine/shellscript.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,13 @@ func newDataForScript(r Request) dataForScript {
d.PricePrecision = &r.PricePrecision
}

for _, attr := range r.GSpec.Requirements.Attributes {
if attr.Key == "confidential-compute" && attr.Value == "true" {
d.ConfidentialComputeSidecar = true
break
}
}

resources := r.GSpec.Resources
if len(r.AllocatedResources) > 0 {
resources = r.AllocatedResources
Expand Down
11 changes: 11 additions & 0 deletions cluster/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ type Client interface {
DeclareIP(ctx context.Context, lID mtypes.LeaseID, serviceName string, port uint32, externalPort uint32, proto mani.ServiceProtocol, sharingKey string, overwrite bool) error
PurgeDeclaredIP(ctx context.Context, lID mtypes.LeaseID, serviceName string, externalPort uint32, proto mani.ServiceProtocol) error
PurgeDeclaredIPs(ctx context.Context, lID mtypes.LeaseID) error

// AttestationQuote forwards an attestation quote request to the sidecar
// running inside a confidential compute pod. The requestBody (containing the
// tenant's nonce) is sent verbatim to the sidecar; the response (hardware-signed
// evidence) is returned verbatim. The provider never inspects or modifies
// either payload (invariants #1 and #5).
AttestationQuote(ctx context.Context, lID mtypes.LeaseID, requestBody []byte) ([]byte, int, error)
}

func ErrorIsOkToSendToClient(err error) bool {
Expand Down Expand Up @@ -310,6 +317,10 @@ func (c *nullClient) PurgeDeclaredIPs(_ context.Context, _ mtypes.LeaseID) error
return errNotImplemented
}

func (c *nullClient) AttestationQuote(_ context.Context, _ mtypes.LeaseID, _ []byte) ([]byte, int, error) {
return nil, 0, errNotImplemented
}

func (c *nullClient) ObserveIPState(_ context.Context) (<-chan cip.ResourceEvent, error) {
return nil, errNotImplemented
}
Expand Down
1 change: 1 addition & 0 deletions cluster/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -859,3 +859,4 @@ func reservationCountEndpoints(reservation *reservation) uint {

return externalPortCount
}

Loading