From 8d5d3915edb679b8199ce1ad2f14c3091f0dcafc Mon Sep 17 00:00:00 2001 From: Thomas Tendyck Date: Sat, 7 Nov 2020 18:28:21 +0100 Subject: [PATCH] aks sample Signed-off-by: Thomas Tendyck --- docs/ERTAzureAKSDeployment.md | 4 +- samples_edgeless/aks/Dockerfile | 12 +++++ samples_edgeless/aks/README.md | 66 ++++++++++++++++++++++++++++ samples_edgeless/aks/aks.yml | 25 +++++++++++ samples_edgeless/aks/public.pem | 11 +++++ samples_edgeless/go_ra/app/server.go | 5 ++- samples_edgeless/go_ra/client.go | 14 +++--- 7 files changed, 128 insertions(+), 9 deletions(-) create mode 100644 samples_edgeless/aks/Dockerfile create mode 100644 samples_edgeless/aks/README.md create mode 100644 samples_edgeless/aks/aks.yml create mode 100644 samples_edgeless/aks/public.pem diff --git a/docs/ERTAzureAKSDeployment.md b/docs/ERTAzureAKSDeployment.md index 2fe3da83d..b93726592 100644 --- a/docs/ERTAzureAKSDeployment.md +++ b/docs/ERTAzureAKSDeployment.md @@ -1,2 +1,2 @@ -# Deploy an Edgeless RT App on Azure Kubernetes Service (AKS) -coming soon +# Edgeless RT Apps on Azure Kubernetes Service (AKS) +Edgeless RT apps can be deployed on AKS. Please see [the example](../samples_edgeless/aks) in `samples_edgeless/aks`. diff --git a/samples_edgeless/aks/Dockerfile b/samples_edgeless/aks/Dockerfile new file mode 100644 index 000000000..a5188b5b5 --- /dev/null +++ b/samples_edgeless/aks/Dockerfile @@ -0,0 +1,12 @@ +# syntax=docker/dockerfile:experimental + +FROM ghcr.io/edgelesssys/edgelessrt-dev AS build +RUN git clone https://github.com/edgelesssys/edgelessrt /edgelessrt +WORKDIR /edgelessrt/samples_edgeless/go_ra/build +RUN cmake .. +RUN --mount=type=secret,id=signingkey,dst=/edgelessrt/samples_edgeless/go_ra/build/private.pem,required=true make + +FROM ghcr.io/edgelesssys/edgelessrt-deploy +LABEL description="ERT sample image" +COPY --from=build /edgelessrt/samples_edgeless/go_ra/build/enclave.signed /go_ra/ +ENTRYPOINT ["erthost", "/go_ra/enclave.signed"] diff --git a/samples_edgeless/aks/README.md b/samples_edgeless/aks/README.md new file mode 100644 index 000000000..5c6fac0db --- /dev/null +++ b/samples_edgeless/aks/README.md @@ -0,0 +1,66 @@ +# Deploy an Edgeless RT App on Azure Kubernetes Service (AKS) + +This sample shows how to deploy an ERT App on AKS. + +## 0. Build the Docker image +We provide a sample image that is used in the following steps. If you want to build it yourself (or your own app), you need to generate a signing key and then build and push the image: +``` +openssl genrsa -out private.pem -3 3072 +openssl rsa -in private.pem -pubout -out public.pem +DOCKER_BUILDKIT=1 docker build --secret id=signingkey,src=private.pem --tag ghcr.io/OWNER/ert-sample . +docker push ghcr.io/OWNER/ert-sample +``` + +## 1. Deploy on AKS + +### Prerequisites: Setting up an [AKS cluster](https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-nodes-aks-get-started) +* Note: see available [VM sizes](https://docs.microsoft.com/en-us/azure/virtual-machines/dcv2-series) and supported [regions](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines®ions=all#select-product) for confidential nodes + +### Push configuration to cluster +* switch to AKS context: + ``` + kubectl config use-context myAKSCluster + ``` +* apply [deployment](aks.yml) to cluster: + ``` + kubectl apply -f aks.yml + ``` + +### Verify that the pod is running +``` +$ kubectl get pods + +NAME READY STATUS RESTARTS AGE +ert-sample-pod 1/1 Running 0 20s + +$ kubectl logs ert-sample-pod + +[erthost] loading enclave ... +[erthost] entering enclave ... +[deventry] running in development mode +[deventry] invoking main +listening ... +``` + +## 2. Use the service +* obtain IP from service: + ``` + $ kubectl get service + + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + ert-sample-svc LoadBalancer 10.0.216.92 8080:32177/TCP 20s + ``` +* use the client: + ``` + $ cd ../go_ra + $ go run client.go -s `oesign signerid -k ../aks/public.pem` -a :8080 + + Sent secret over attested TLS channel. + ``` +## Managing the cluster +* start cluster: ```az aks start --name myAKSCluster --resource-group myResourceGroup``` +* stop cluster: ```az aks stop --name myAKSCluster --resource-group myResourceGroup``` + +## References +* [az aks documentation](https://docs.microsoft.com/en-us/cli/azure/aks?view=azure-cli-latest) +* [kubectl cheat sheet](https://kubernetes.io/de/docs/reference/kubectl/cheatsheet/) diff --git a/samples_edgeless/aks/aks.yml b/samples_edgeless/aks/aks.yml new file mode 100644 index 000000000..e2dd0ced2 --- /dev/null +++ b/samples_edgeless/aks/aks.yml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: Service +metadata: + name: ert-sample-svc +spec: + ports: + - port: 8080 + targetPort: 8080 + type: LoadBalancer + selector: + app: ert-sample-app +--- +apiVersion: v1 +kind: Pod +metadata: + name: ert-sample-pod + labels: + app: ert-sample-app +spec: + containers: + - name: ert-sample-image + image: ghcr.io/edgelesssys/ert-sample + resources: + limits: + kubernetes.azure.com/sgx_epc_mem_in_MiB: 10 diff --git a/samples_edgeless/aks/public.pem b/samples_edgeless/aks/public.pem new file mode 100644 index 000000000..27152d7d1 --- /dev/null +++ b/samples_edgeless/aks/public.pem @@ -0,0 +1,11 @@ +-----BEGIN PUBLIC KEY----- +MIIBoDANBgkqhkiG9w0BAQEFAAOCAY0AMIIBiAKCAYEAsqi2kC6Rfb3ev0dbr3iF +wSKQjWjqJn8KvC1TiOiYUZAca0ee0OxI1PUBMrjnEDRTgpjpe5EOqLQRXQx1WL6x +QCbFZcyvpqU0TS9YMyg4XWqTKq7Sof/4u+awbGy3D8o7TPryBUEPPxwLN3EAFU22 +S87sjpePieVINH0k9sjQW5bRkCW425pzTAX/TdPtQYqXip7i1/a74ka1bPIn54BS +GJiNzLrwhGSuPw9pvJMbqe3iMWXcl5XqumuQxsaZ/JVTTWe9ttexOpOY7IPITnwg +X10dqWCPJ2V/qOEMsCK8EQian4g1jA0XmLcjJGKMT06Zf9TlVa87tkHHLEKODMWd +4viB21Wya/bj1NcklyJd4hlkxuFlOTWZ0oBmb8fXYr98YAQh55lDkd32eUJA59HS ++fQRJInEtiZTw804sNv2AoskNS7b8TLG7ilkmgJzu/BiOjm0KvyN8LM6p6E9UoLq +x3fALuNQ4dyViQbv+gNClFDsW9JUTe8Agg3sC5Iozlx9AgED +-----END PUBLIC KEY----- diff --git a/samples_edgeless/go_ra/app/server.go b/samples_edgeless/go_ra/app/server.go index c41f864b5..77ec754c7 100644 --- a/samples_edgeless/go_ra/app/server.go +++ b/samples_edgeless/go_ra/app/server.go @@ -25,7 +25,7 @@ func main() { hash := sha256.Sum256(cert) report, err := ertenclave.GetRemoteReport(hash[:]) if err != nil { - panic(err) + fmt.Println(err) } // Create HTTPS server. @@ -45,7 +45,7 @@ func main() { }, } - server := http.Server{Addr: "localhost:8080", TLSConfig: &tlsCfg} + server := http.Server{Addr: "0.0.0.0:8080", TLSConfig: &tlsCfg} fmt.Println("listening ...") err = server.ListenAndServeTLS("", "") @@ -57,6 +57,7 @@ func createCertificate() ([]byte, crypto.PrivateKey) { SerialNumber: &big.Int{}, Subject: pkix.Name{CommonName: "localhost"}, NotAfter: time.Now().Add(time.Hour), + DNSNames: []string{"localhost"}, } priv, _ := rsa.GenerateKey(rand.Reader, 2048) cert, _ := x509.CreateCertificate(rand.Reader, template, template, &priv.PublicKey, priv) diff --git a/samples_edgeless/go_ra/client.go b/samples_edgeless/go_ra/client.go index c067c6880..cb2be699e 100644 --- a/samples_edgeless/go_ra/client.go +++ b/samples_edgeless/go_ra/client.go @@ -20,9 +20,11 @@ import ( ) func main() { - // get signer command line argument signerArg := flag.String("s", "", "signer ID") + serverAddr := flag.String("a", "localhost:8080", "server address") flag.Parse() + + // get signer command line argument signer, err := hex.DecodeString(*signerArg) if err != nil { panic(err) @@ -32,11 +34,13 @@ func main() { return } + url := "https://" + *serverAddr + // Get server certificate and its report. Skip TLS certificate verification because // the certificate is self-signed and we will verify it using the report instead. tlsConfig := &tls.Config{InsecureSkipVerify: true} - certBytes := httpGet(tlsConfig, "https://localhost:8080/cert") - reportBytes := httpGet(tlsConfig, "https://localhost:8080/report") + certBytes := httpGet(tlsConfig, url+"/cert") + reportBytes := httpGet(tlsConfig, url+"/report") if err := verifyReport(reportBytes, certBytes, signer); err != nil { panic(err) @@ -45,10 +49,10 @@ func main() { // Create a TLS config that uses the server certificate as root // CA so that future connections to the server can be verified. cert, _ := x509.ParseCertificate(certBytes) - tlsConfig = &tls.Config{RootCAs: x509.NewCertPool()} + tlsConfig = &tls.Config{RootCAs: x509.NewCertPool(), ServerName: "localhost"} tlsConfig.RootCAs.AddCert(cert) - httpGet(tlsConfig, "https://localhost:8080/secret?s=mySecret") + httpGet(tlsConfig, url+"/secret?s=mySecret") fmt.Println("Sent secret over attested TLS channel.") }