From dc3e3f36e6ba3df69bc7ed3db9dadb2262391299 Mon Sep 17 00:00:00 2001 From: Lucas Ritzdorf <42657792+LRitzdorf@users.noreply.github.com> Date: Tue, 18 Jun 2024 15:10:05 -0600 Subject: [PATCH 1/7] quickstart: include TPM-manager container Note that we do not perform SSH host key checking. Host keys are treated as secrets, and will be applied via cloud-init *after* all TPM operations have completed (since this needs the key that we store into the TPM). --- quickstart/tpm-manager.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 quickstart/tpm-manager.yml diff --git a/quickstart/tpm-manager.yml b/quickstart/tpm-manager.yml new file mode 100644 index 0000000..6275d37 --- /dev/null +++ b/quickstart/tpm-manager.yml @@ -0,0 +1,20 @@ +services: + ### + # TPM-manager container, pushes cloud-init tokens into nodes' TPM storage + ### + tpm-manager: + image: ghcr.io/openchami/tpm-manager:v0.1.3 + container_name: tpm-manager + hostname: tpm-manager + command: ["-port", "27780", "-batch-size", "100", "-interval", "30s"] + environment: + - OPAAL_URL=http://opaal:3333 + - HSM_URL=http://smd:27779 + - ANSIBLE_HOST_KEY_CHECKING=False + depends_on: + opaal: + condition: service_healthy + smd: + condition: service_healthy + networks: + - internal From f876286d7d593e5c9cb9a9af6051214031cb54fa Mon Sep 17 00:00:00 2001 From: Lucas Ritzdorf <42657792+LRitzdorf@users.noreply.github.com> Date: Fri, 28 Jun 2024 12:32:29 -0600 Subject: [PATCH 2/7] quickstart(bss,tpm-manager): update to new BSS notifier system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a node requests its bootscript, BSS can now initiate a POST request to and endpoint of the user's choice — in this case, to the TPM manager daemon. This notification includes the booting node's IP address, which is passed to Ansible as inventory to be configured with a TPM key. --- quickstart/openchami-svcs.yml | 1 + quickstart/tpm-manager.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/quickstart/openchami-svcs.yml b/quickstart/openchami-svcs.yml index 3c6842b..87e7ad8 100644 --- a/quickstart/openchami-svcs.yml +++ b/quickstart/openchami-svcs.yml @@ -93,6 +93,7 @@ services: - BSS_OAUTH2_PUBLIC_BASE_URL=http://opaal:3333 - BSS_IPXE_SERVER=${SYSTEM_NAME}.${SYSTEM_DOMAIN} - BSS_CHAIN_PROTO=https + - BSS_BOOTSCRIPT_NOTIFY_URL=http://tpm-manager:27780/Node #ports: # - '27778:27778' depends_on: diff --git a/quickstart/tpm-manager.yml b/quickstart/tpm-manager.yml index 6275d37..94b0760 100644 --- a/quickstart/tpm-manager.yml +++ b/quickstart/tpm-manager.yml @@ -3,7 +3,7 @@ services: # TPM-manager container, pushes cloud-init tokens into nodes' TPM storage ### tpm-manager: - image: ghcr.io/openchami/tpm-manager:v0.1.3 + image: ghcr.io/openchami/tpm-manager:v0.2.2 container_name: tpm-manager hostname: tpm-manager command: ["-port", "27780", "-batch-size", "100", "-interval", "30s"] From 7f1e34a361e6a8c7d27930be0757eb06f9c4a85c Mon Sep 17 00:00:00 2001 From: Lucas Ritzdorf <42657792+LRitzdorf@users.noreply.github.com> Date: Mon, 8 Jul 2024 16:23:09 -0600 Subject: [PATCH 3/7] quickstart(openchami-svcs,tpm-manager): add cloud-init server The tpm-manager compose file, in particular, includes an override clause which enables the cloud-init server's "secure route" (i.e. JWT-authenticated config data). --- quickstart/openchami-svcs.yml | 23 +++++++++++++++++++++-- quickstart/tpm-manager.yml | 8 ++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/quickstart/openchami-svcs.yml b/quickstart/openchami-svcs.yml index 87e7ad8..4539ea2 100644 --- a/quickstart/openchami-svcs.yml +++ b/quickstart/openchami-svcs.yml @@ -112,5 +112,24 @@ services: interval: 5s timeout: 10s retries: 60 - - +### +# cloud-init Server Container +### + # cloud-init server, with the secure route disabled for now + cloud-init: + image: ghcr.io/openchami/cloud-init:v0.1.0 + container_name: cloud-init + hostname: cloud-init + environment: + - LISTEN_ADDR=:27777 + - SMD_URL=http://smd:27779 + - OPAAL_URL=http://opaal:3333 + ports: + - '27777:27777' + depends_on: + smd: + condition: service_healthy + opaal: + condition: service_healthy + networks: + - internal diff --git a/quickstart/tpm-manager.yml b/quickstart/tpm-manager.yml index 94b0760..0666f60 100644 --- a/quickstart/tpm-manager.yml +++ b/quickstart/tpm-manager.yml @@ -18,3 +18,11 @@ services: condition: service_healthy networks: - internal + ### + # cloud-init server container, provides secured config access via JWT authorization + # NOTE: This merges with the default cloud-init config specified in openchami-svcs.yml + ### + cloud-init: + environment: + # This enables the server's secure route + - JWKS_URL=http://opaal:3333/keys From ace6d8659c227eeb3004b587e7054d075186cd07 Mon Sep 17 00:00:00 2001 From: Lucas Ritzdorf <42657792+LRitzdorf@users.noreply.github.com> Date: Wed, 17 Jul 2024 15:37:23 -0600 Subject: [PATCH 4/7] quickstart(tpm-manager): bind-mount host's `.ssh` into container This is, usually, required so that Ansible in the container can SSH to nodes. --- quickstart/tpm-manager.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/quickstart/tpm-manager.yml b/quickstart/tpm-manager.yml index 0666f60..7688987 100644 --- a/quickstart/tpm-manager.yml +++ b/quickstart/tpm-manager.yml @@ -11,6 +11,10 @@ services: - OPAAL_URL=http://opaal:3333 - HSM_URL=http://smd:27779 - ANSIBLE_HOST_KEY_CHECKING=False + volumes: + - type: bind + source: /root/.ssh + target: /root/.ssh depends_on: opaal: condition: service_healthy From ea94be2b2c6589f7c506a9e8ebee1d12dafbbe5e Mon Sep 17 00:00:00 2001 From: Lucas Ritzdorf <42657792+LRitzdorf@users.noreply.github.com> Date: Fri, 19 Jul 2024 14:56:06 -0600 Subject: [PATCH 5/7] quickstart(openchami-svcs): update cloud-init server --- quickstart/openchami-svcs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart/openchami-svcs.yml b/quickstart/openchami-svcs.yml index 4539ea2..5339073 100644 --- a/quickstart/openchami-svcs.yml +++ b/quickstart/openchami-svcs.yml @@ -117,7 +117,7 @@ services: ### # cloud-init server, with the secure route disabled for now cloud-init: - image: ghcr.io/openchami/cloud-init:v0.1.0 + image: ghcr.io/openchami/cloud-init:v0.1.1 container_name: cloud-init hostname: cloud-init environment: From cae9ac8f56e15385b44fce0ac54c2009fe11fdce Mon Sep 17 00:00:00 2001 From: Lucas Ritzdorf <42657792+LRitzdorf@users.noreply.github.com> Date: Wed, 7 Aug 2024 13:58:06 -0600 Subject: [PATCH 6/7] quickstart(haproxy): add cloud-init backend, secured route --- quickstart/configs/haproxy.cfg | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/quickstart/configs/haproxy.cfg b/quickstart/configs/haproxy.cfg index a97f5fd..29dcb6f 100644 --- a/quickstart/configs/haproxy.cfg +++ b/quickstart/configs/haproxy.cfg @@ -40,12 +40,14 @@ frontend openchami acl PATH_opaal-idp path_beg -i /oauth2/token acl PATH_cloud-init path_beg -i /cloud-init + acl PATH_cloud-init path_beg -i /cloud-init-secure use_backend opaal if PATH_opaal use_backend opaal-idp if PATH_opaal-idp use_backend smd if PATH_smd use_backend bss if PATH_bss + use_backend cloud-init if PATH_cloud-init backend opaal server opaal opaal:3333 @@ -60,6 +62,5 @@ backend bss server bss bss:27778 http-request replace-path ^/apis/bss/(.*) /\1 - - - +backend cloud-init + server cloud-init cloud-init:27777 From 4afa858b8a575ceabd547e902712550432c371d4 Mon Sep 17 00:00:00 2001 From: Lucas Ritzdorf <42657792+LRitzdorf@users.noreply.github.com> Date: Thu, 8 Aug 2024 14:22:54 -0600 Subject: [PATCH 7/7] quickstart(readme): document cloud-init server setup --- quickstart/README.md | 63 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/quickstart/README.md b/quickstart/README.md index 30295e9..3fca5d1 100644 --- a/quickstart/README.md +++ b/quickstart/README.md @@ -64,6 +64,69 @@ This quickstart makes a few assumptions about the target operating system and is ``` +## cloud-init Server Setup + +OpenCHAMI utilizes the cloud-init platform for post-boot configuration. +A custom cloud-init server container is included with this quickstart Docker Compose setup, but must be populated prior to use. + +The cloud-init server provides two API endpoints, described in the sections below. +Choose the appropriate option for your needs. + +### Unprotected Data + +#### Setup +The first endpoint, located at `/cloud-init/`, permits access to all stored data (and should therefore not contain configuration secrets). +Storing data into this endpoint is accomplished via HTTP POST requests containing JSON-formatted cloud-init configuration details. +For example: +```bash +curl 'https://foobar.openchami.cluster/cloud-init/' \ + -X POST \ + -d '{"name": "IDENTIFIER", "cloud-init": { + "userdata": { + "write_files": [{"content": "hello world", "path": "/etc/hello"}] + }, + "metadata": {...}, + "vendordata": {...} + }}' +``` +`IDENTIFIER` can be: +- A node MAC address +- A node xname +- An SMD group name +It may be easiest to add nodes to a group for testing, and upload a cloud-init configuration for that group to this server. + +#### Usage +Data is retrieved via HTTP GET requests to the `meta-data`, `user-data`, and `vendor-data` endpoints. +For example, one could download all cloud-init data for a node/group via `curl 'https://foobar.openchami.cluster/cloud-init//{meta-data,user-data,vendor-data}'`. + +When retrieving data, `IDENTIFIER` can also be omitted entirely (e.g. `https://foobar.openchami.cluster/cloud-init/user-data`). +In this case, the cloud-init server will attempt to look up the relevant xname based on the request's source IP address. + +Thus, the intended use case is to set nodes' cloud-init datasource URLs to `https://foobar.openchami.cluster/cloud-init/`, from which the cloud-init client will load its configuration data. +Note that in this case, no `IDENTIFIER` is provided, so IP-based autodetection will be performed. + +### JWT-Protected Data + +#### Setup +The second endpoint, located at `/cloud-init-secure/`, restricts access to its cloud-init data behind a valid bearer token (i.e. a JWT). +Storing data into this endpoint requires a valid access token, which we assume is stored in `$ACCESS_TOKEN`. +The workflow described for unprotected data can be used, with the addition of the required authorization header, via e.g. `curl`'s `-H "Authorization: Bearer $ACCESS_TOKEN"`. + +#### Usage +In order to access this protected data, nodes must also supply valid JWTs. +These may be distributed to nodes at boot time by including [`tpm-manager.yml`](tpm-manager.yml) in the `docker compose` command provided above. +(It should be provided last, since it supplements service definitions from other files.) + +For nodes without hardware TPMs, the TPM manager will drop a JWT into `/var/run/cloud-init-jwt`. +The token can be retrieved and included with a request to the cloud-init server, using an invocation such as: +```bash +curl 'https://foobar.openchami.cluster/cloud-init-secure//{meta-data,user-data,vendor-data}' \ + --create-dirs --output '/PATH/TO/DATA-DIR/#1' \ + --header "Authorization: Bearer $(