From 3848f01447a81917c56fadf695bc741dc174dddb Mon Sep 17 00:00:00 2001 From: Itxaka Date: Thu, 24 Oct 2024 17:59:38 +0200 Subject: [PATCH 1/6] WIP keylime example Signed-off-by: Itxaka --- examples/keylime/Dockerfile | 9 ++++++ examples/keylime/keylime.yaml | 51 ++++++++++++++++++++++++++++++++ examples/keylime/luet-amd64.yaml | 16 ++++++++++ examples/keylime/luet-arm64.yaml | 16 ++++++++++ 4 files changed, 92 insertions(+) create mode 100644 examples/keylime/Dockerfile create mode 100644 examples/keylime/keylime.yaml create mode 100644 examples/keylime/luet-amd64.yaml create mode 100644 examples/keylime/luet-arm64.yaml diff --git a/examples/keylime/Dockerfile b/examples/keylime/Dockerfile new file mode 100644 index 000000000..d877b44f7 --- /dev/null +++ b/examples/keylime/Dockerfile @@ -0,0 +1,9 @@ +FROM quay.io/kairos/ubuntu:24.04-core-amd64-generic-v3.2.1 AS base +ARG TARGETARCH +# copy both arches +COPY luet-arm64.yaml /tmp/luet-arm64.yaml +COPY luet-amd64.yaml /tmp/luet-amd64.yaml +# Set the default luet config to the current build arch +RUN mkdir -p /etc/luet/ +RUN cp /tmp/luet-${TARGETARCH}.yaml /etc/luet/luet.yaml +RUN luet install -y --relax utils/keylime-agent \ No newline at end of file diff --git a/examples/keylime/keylime.yaml b/examples/keylime/keylime.yaml new file mode 100644 index 000000000..46d17e1c5 --- /dev/null +++ b/examples/keylime/keylime.yaml @@ -0,0 +1,51 @@ +#cloud-config + +install: + auto: true + reboot: true + device: /dev/vda + bind_mounts: + - /var/lib/keylime + grub_options: + extra_cmdline: "rd.immucore.debug" + +# Keylime needs several things to work +# User keylime which is part of the tss group. Does not need to be able to login or have password, +# its mainly used for the agent to drop pivs to when runs as a service +# the /var/lib/keylime dir writable and owned by the keylime user +# the keylime registrar generated public CAs if any +# Any config dropped at /etc/keylime/agent.conf.d/ +# So registrar IP for example or verifier, etc... +# any extra config needs to be dropped there +stages: + initramfs: + - name: "Set user and password" + users: + kairos: + passwd: "kairos" + groups: + - "admin" + keylime: + groups: + - "tss" + hostname: kairos-{{ trunc 4 .Random }} + boot: # Do it on boot, at this point the bind mount for /var/lib/keylime is done and the user created + - name: "Set keylime owner to /var/lib/keylime" + commands: + - chown keyline /var/lib/keylime + - name: "Keylime config" + files: + - path: /path/to/server_key # Add whatever public keys you need from the registrar/verifier + content: KEY + owner_string: "keylime" + - path: /etc/keylime/agent.conf.d/10-config.conf + content: | + [agent] + ip = '0.0.0.0' + registrar_ip = '' + uuid = '' + server_key = '' + server_key_password = '' + server_cert = '' + trusted_client_ca = '[, ]' + owner_string: "keylime" \ No newline at end of file diff --git a/examples/keylime/luet-amd64.yaml b/examples/keylime/luet-amd64.yaml new file mode 100644 index 000000000..41941d429 --- /dev/null +++ b/examples/keylime/luet-amd64.yaml @@ -0,0 +1,16 @@ +general: + debug: false + spinner_charset: 9 +logging: + enable_emoji: false +repositories: + - name: "kairos" + description: "kairos repository" + type: "docker" + cached: true + enable: true + priority: 2 + urls: + - "quay.io/kairos/packages" + # renovate: datasource=docker depName=quay.io/kairos/packages + reference: 202410241450-git608b1d23-repository.yaml diff --git a/examples/keylime/luet-arm64.yaml b/examples/keylime/luet-arm64.yaml new file mode 100644 index 000000000..e6a897802 --- /dev/null +++ b/examples/keylime/luet-arm64.yaml @@ -0,0 +1,16 @@ +general: + debug: false + spinner_charset: 9 +logging: + enable_emoji: false +repositories: + - name: "kairos-arm64" + description: "kairos repository arm64" + type: "docker" + cached: true + enable: true + priority: 2 + urls: + - "quay.io/kairos/packages-arm64" + # renovate: datasource=docker depName=quay.io/kairos/packages-arm64 + reference: 202410241504-git608b1d23-repository.yaml From e4990ecf513a066cb26fadc058cc6432958ae734 Mon Sep 17 00:00:00 2001 From: Itxaka Date: Thu, 24 Oct 2024 17:59:38 +0200 Subject: [PATCH 2/6] WIP keylime example Signed-off-by: Itxaka --- examples/keylime/Dockerfile | 7 +-- examples/keylime/keylime.yaml | 101 ++++++++++++++++++++++++++----- examples/keylime/luet-amd64.yaml | 16 ----- examples/keylime/luet-arm64.yaml | 16 ----- examples/keylime/luet.yaml | 21 +++++++ 5 files changed, 109 insertions(+), 52 deletions(-) delete mode 100644 examples/keylime/luet-amd64.yaml delete mode 100644 examples/keylime/luet-arm64.yaml create mode 100644 examples/keylime/luet.yaml diff --git a/examples/keylime/Dockerfile b/examples/keylime/Dockerfile index d877b44f7..9ee3cadc4 100644 --- a/examples/keylime/Dockerfile +++ b/examples/keylime/Dockerfile @@ -1,9 +1,4 @@ FROM quay.io/kairos/ubuntu:24.04-core-amd64-generic-v3.2.1 AS base ARG TARGETARCH -# copy both arches -COPY luet-arm64.yaml /tmp/luet-arm64.yaml -COPY luet-amd64.yaml /tmp/luet-amd64.yaml -# Set the default luet config to the current build arch -RUN mkdir -p /etc/luet/ -RUN cp /tmp/luet-${TARGETARCH}.yaml /etc/luet/luet.yaml +COPY luet.yaml /etc/luet/luet.yaml RUN luet install -y --relax utils/keylime-agent \ No newline at end of file diff --git a/examples/keylime/keylime.yaml b/examples/keylime/keylime.yaml index 46d17e1c5..297bcb748 100644 --- a/examples/keylime/keylime.yaml +++ b/examples/keylime/keylime.yaml @@ -7,7 +7,8 @@ install: bind_mounts: - /var/lib/keylime grub_options: - extra_cmdline: "rd.immucore.debug" + # This is needed for IMA to work and measure stuff + extra_cmdline: "ima_appraise=fix ima_template=ima-sig ima_policy=tcb" # Keylime needs several things to work # User keylime which is part of the tss group. Does not need to be able to login or have password, @@ -30,22 +31,94 @@ stages: - "tss" hostname: kairos-{{ trunc 4 .Random }} boot: # Do it on boot, at this point the bind mount for /var/lib/keylime is done and the user created - - name: "Set keylime owner to /var/lib/keylime" - commands: - - chown keyline /var/lib/keylime - - name: "Keylime config" + - name: "Set Keylime config" files: - - path: /path/to/server_key # Add whatever public keys you need from the registrar/verifier - content: KEY + - path: /var/lib/keylime/cv_ca/cacert.crt + # This is the ROOT CA the agent needs otherwise the tenant and verifier cannot connect to the agent! + # This is provided by the registrar and it gets generated on the registrar side ont he first boot + # or you can provide your own Root CA. In any case, the agent needs to have it otherwise no connection will be possible to it + content: | + -----BEGIN CERTIFICATE----- + MIID8zCCAtugAwIBAgIBATANBgkqhkiG9w0BAQsFADBzMQswCQYDVQQGEwJVUzEm + MCQGA1UEAwwdS2V5bGltZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxCzAJBgNVBAgM + Ak1BMRIwEAYDVQQHDAlMZXhpbmd0b24xDjAMBgNVBAoMBU1JVExMMQswCQYDVQQL + DAI1MzAeFw0yNDEwMzAxMTQyNDNaFw0zNDEwMjgxMTQyNDNaMHMxCzAJBgNVBAYT + AlVTMSYwJAYDVQQDDB1LZXlsaW1lIENlcnRpZmljYXRlIEF1dGhvcml0eTELMAkG + A1UECAwCTUExEjAQBgNVBAcMCUxleGluZ3RvbjEOMAwGA1UECgwFTUlUTEwxCzAJ + BgNVBAsMAjUzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjiRxfpyt + ro1FSEprtrDOUo66AmobNO4j2oNeFBbwG31a4bZqHcD7Tjke9V9cwFRM8TtBrg0r + L5dlZZyM5betmGbgZTwGtPFZthbPvusEOHUrNrwR0imTJtYbqUk5nsRtyyxDJdec + kh4ibfugyYJu1gEKkZe4BiUisAp5tNifaEdfs9uTz4Ijr4jSniveL1Kio6ngARvM + xpQgYj4M7fn5q1rIVeZyTFNWFBUY13rViQkvK69b2oz+RwARPgDYkl6kRW/7Z07f + T7CrEzhbxfbAlPKpfAhcgusHUcajQXfh8T8OtlTNNbTedlFS4dHWkEUKRfoUA09h + p2ZNCIaGPqQ34QIDAQABo4GRMIGOMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE + FHxXU4zLckC2WtgM6kxL4c1nxmB1MCsGA1UdHwQkMCIwIKAeoByGGmh0dHA6Ly9s + b2NhbGhvc3Q6MzgwODAvY3JsMA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBR8 + V1OMy3JAtlrYDOpMS+HNZ8ZgdTANBgkqhkiG9w0BAQsFAAOCAQEAb9ZyuWPLQDd+ + H2MHr4VEADuXY/EXlBKf+YH9tfWfiWkUkOVPFanX9+dO/EDcOMKItTd6u8FI05SL + UCjLsjLSwufxC8SpCo3XgkL/1q2wRlZ0IZcHPZV+7qATkqBl54k/ImZwENs0oXuT + uDcfdJ4FgP/M47HnJaP9/8IRxOgLn370zhxrjx56+A1BPiRAYfWyqCYOEHbFd+Cf + q9pFQQOHdmarzF/EScq6UvndtXRAthu1I1ArqzSisLV55O5eu6L+5h2ZAoBHlCD6 + Imgvg/m5BbmUo3G5QlfGpU1H7edNsn+OPfC9SDI9jYSKJ8lbyb/fn1QRnjEEnzqs + AV0t3VsfgQ== + -----END CERTIFICATE----- owner_string: "keylime" + permissions: 0640 - path: /etc/keylime/agent.conf.d/10-config.conf + # This is the agent config, it needs to know the registrar IP + # If the ip is not set, the agent will listen on localhost only + # The UUID is the agent UUID, it needs to be unique per agent. You can leave it empty and the agent will generate one on boot content: | [agent] ip = '0.0.0.0' - registrar_ip = '' - uuid = '' - server_key = '' - server_key_password = '' - server_cert = '' - trusted_client_ca = '[, ]' - owner_string: "keylime" \ No newline at end of file + registrar_ip = '192.168.100.184' + uuid = '61388a67-baa4-4f2b-8221-d539b7b4d98b' + owner_string: "keylime" + permissions: 0640 + - name: "Set keylime owner to /var/lib/keylime" + commands: + - chown -R keylime:keylime /var/lib/keylime + - name: "Set default IMA policy" + path: /etc/ima/ima-policy + permissions: 0644 + content: | + # PROC_SUPER_MAGIC + dont_measure fsmagic=0x9fa0 + # SYSFS_MAGIC + dont_measure fsmagic=0x62656572 + # DEBUGFS_MAGIC + dont_measure fsmagic=0x64626720 + # TMPFS_MAGIC + dont_measure fsmagic=0x01021994 + # RAMFS_MAGIC + dont_measure fsmagic=0x858458f6 + # SECURITYFS_MAGIC + dont_measure fsmagic=0x73636673 + # SELINUX_MAGIC + dont_measure fsmagic=0xf97cff8c + # CGROUP_SUPER_MAGIC + dont_measure fsmagic=0x27e0eb + # OVERLAYFS_MAGIC + # when containers are used we almost always want to ignore them + dont_measure fsmagic=0x794c7630 + # Don't measure log, audit or tmp files + dont_measure obj_type=var_log_t + dont_measure obj_type=auditd_log_t + dont_measure obj_type=tmp_t + # MEASUREMENTS + measure func=BPRM_CHECK + measure func=FILE_MMAP mask=MAY_EXEC + measure func=MODULE_CHECK uid=0 + + +# Then you can run on your tenant something like this to add that agent with a tpm policy +# Note that you can add more than one tpm to the policy, this uses 15 as an example +# keylime_tenant -c update --uuid UID_OF_AGENT -t IP_OF_AGENT --tpm_policy '{"15":["0000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000","000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"]}' +# +# Then to test, you can manually extend the PCR for example to trigger a failure un attestation +# tpm2_pcrextend 15:sha256=f1d2d2f924e986ac86fdf7b36c94bcdf32beec15324234324234234333333333 +# When it fails you will see something like this on the verifier: +# {"61388a67-baa4-4f2b-8221-d539b7b4d98b": {"operational_state": "Invalid Quote", "v": null, "ip": "192.168.100.164", "port": 9002, "tpm_policy": "{\"22\": [\"0000000000000000000000000000000000000001\", \"0000000000000000000000000000000000000000000000000000000000000001\", \"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\", \"ffffffffffffffffffffffffffffffffffffffff\", \"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\", \"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"], \"15\": [\"0000000000000000000000000000000000000000\", \"0000000000000000000000000000000000000000000000000000000000000000\", \"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"], \"mask\": \"0x408000\"}", "meta_data": "{}", "has_mb_refstate": 0, "has_runtime_policy": 0, "accept_tpm_hash_algs": ["sha512", "sha384", "sha256"], "accept_tpm_encryption_algs": ["ecc", "rsa"], "accept_tpm_signing_algs": ["ecschnorr", "rsassa"], "hash_alg": "sha256", "enc_alg": "rsa", "sign_alg": "rsassa", "verifier_id": "default", "verifier_ip": "127.0.0.1", "verifier_port": 8881, "severity_level": 6, "last_event_id": "pcr_validation.invalid_pcr_15", "attestation_count": 158, "last_received_quote": 1730388195, "last_successful_attestation": 1730388193}} +# And supposedly the agent runs a revocation script. You can see the logs on the agent side +# INFO keylime_agent::notifications_handler > Received revocation +# WARN keylime_agent::revocation > Revocation certificate not yet available diff --git a/examples/keylime/luet-amd64.yaml b/examples/keylime/luet-amd64.yaml deleted file mode 100644 index 41941d429..000000000 --- a/examples/keylime/luet-amd64.yaml +++ /dev/null @@ -1,16 +0,0 @@ -general: - debug: false - spinner_charset: 9 -logging: - enable_emoji: false -repositories: - - name: "kairos" - description: "kairos repository" - type: "docker" - cached: true - enable: true - priority: 2 - urls: - - "quay.io/kairos/packages" - # renovate: datasource=docker depName=quay.io/kairos/packages - reference: 202410241450-git608b1d23-repository.yaml diff --git a/examples/keylime/luet-arm64.yaml b/examples/keylime/luet-arm64.yaml deleted file mode 100644 index e6a897802..000000000 --- a/examples/keylime/luet-arm64.yaml +++ /dev/null @@ -1,16 +0,0 @@ -general: - debug: false - spinner_charset: 9 -logging: - enable_emoji: false -repositories: - - name: "kairos-arm64" - description: "kairos repository arm64" - type: "docker" - cached: true - enable: true - priority: 2 - urls: - - "quay.io/kairos/packages-arm64" - # renovate: datasource=docker depName=quay.io/kairos/packages-arm64 - reference: 202410241504-git608b1d23-repository.yaml diff --git a/examples/keylime/luet.yaml b/examples/keylime/luet.yaml new file mode 100644 index 000000000..fdb9a8119 --- /dev/null +++ b/examples/keylime/luet.yaml @@ -0,0 +1,21 @@ +repositories: + - name: "kairos" + description: "kairos repository" + type: "docker" + arch: amd64 + cached: true + priority: 1 + urls: + - "quay.io/kairos/packages" + # renovate: datasource=docker depName=quay.io/kairos/packages + reference: 202410241450-git608b1d23-repository.yaml + - name: "kairos" + description: "kairos repository" + type: "docker" + cached: true + arch: arm64 + priority: 2 + urls: + - "quay.io/kairos/packages-arm64" + # renovate: datasource=docker depName=quay.io/kairos/packages-arm64 + reference: 202410241504-git608b1d23-repository.yaml From 8e6b04d251a7493f61dd00bf78c0c11bffa1389c Mon Sep 17 00:00:00 2001 From: Itxaka Date: Mon, 11 Nov 2024 09:33:22 +0100 Subject: [PATCH 3/6] Update examples/keylime/keylime.yaml Co-authored-by: Ettore Di Giacinto Signed-off-by: Itxaka --- examples/keylime/keylime.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/keylime/keylime.yaml b/examples/keylime/keylime.yaml index 297bcb748..535264762 100644 --- a/examples/keylime/keylime.yaml +++ b/examples/keylime/keylime.yaml @@ -71,7 +71,7 @@ stages: content: | [agent] ip = '0.0.0.0' - registrar_ip = '192.168.100.184' + registrar_ip = '192.168.100.184' # change to the keylime remote attestation server IP uuid = '61388a67-baa4-4f2b-8221-d539b7b4d98b' owner_string: "keylime" permissions: 0640 From e4e57d06aa78bfea50044e84835426e3a41e619e Mon Sep 17 00:00:00 2001 From: Itxaka Date: Mon, 11 Nov 2024 11:34:43 +0100 Subject: [PATCH 4/6] Move explanation into readme Signed-off-by: Itxaka --- examples/keylime/README.md | 178 ++++++++++++++++++++++++++++++++++ examples/keylime/keylime.yaml | 31 +----- 2 files changed, 180 insertions(+), 29 deletions(-) create mode 100644 examples/keylime/README.md diff --git a/examples/keylime/README.md b/examples/keylime/README.md new file mode 100644 index 000000000..ac25b6054 --- /dev/null +++ b/examples/keylime/README.md @@ -0,0 +1,178 @@ +# Setting up the keylime agent in Kairos + +Most of the steps are already covered in the [Keylime documentation](https://keylime-docs.readthedocs.io/en/latest/). Here we will cover the steps that are specific to Kairos. + + +We provide thee keylime agent as a luet package for ease of installation. +For it to be installeed you need to create your own derivative of the Kairos image and add the keylime-agent package to it. + + +```Dockerfile +FROM quay.io/kairos/ubuntu:24.04-core-amd64-generic-v3.2.1 AS base +COPY luet.yaml /etc/luet/luet.yaml +RUN luet install -y --relax utils/keylime-agent +``` + +Then you can build your image with the agent on it: + +```bash +docker build -t kairos-keylime . +``` + + +That will generate an artifact based on the Kairos image with the keylime-agent installed. + +Then you need at a minimum the follow configuration in your cloud config: + +```yaml +install: + bind_mounts: + - /var/lib/keylime + grub_options: + extra_cmdline: "ima_appraise=fix ima_template=ima-sig ima_policy=tcb" + +stages: + initramfs: + - name: "Set keylime user and password" + users: + kairos: + passwd: "kairos" + groups: + - "admin" + keylime: + groups: + - "tss" + boot: + - name: "Set Keylime config" + files: + - path: /var/lib/keylime/cv_ca/cacert.crt + content: | + -----BEGIN CERTIFICATE----- + MIID8zCCAtugAwIBAgIBATANBgkqhkiG9w0BAQsFADBzMQswCQYDVQQGEwJVUzEm + MCQGA1UEAwwdS2V5bGltZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxCzAJBgNVBAgM + Ak1BMRIwEAYDVQQHDAlMZXhpbmd0b24xDjAMBgNVBAoMBU1JVExMMQswCQYDVQQL + DAI1MzAeFw0yNDEwMzAxMTQyNDNaFw0zNDEwMjgxMTQyNDNaMHMxCzAJBgNVBAYT + AlVTMSYwJAYDVQQDDB1LZXlsaW1lIENlcnRpZmljYXRlIEF1dGhvcml0eTELMAkG + A1UECAwCTUExEjAQBgNVBAcMCUxleGluZ3RvbjEOMAwGA1UECgwFTUlUTEwxCzAJ + BgNVBAsMAjUzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjiRxfpyt + ro1FSEprtrDOUo66AmobNO4j2oNeFBbwG31a4bZqHcD7Tjke9V9cwFRM8TtBrg0r + L5dlZZyM5betmGbgZTwGtPFZthbPvusEOHUrNrwR0imTJtYbqUk5nsRtyyxDJdec + kh4ibfugyYJu1gEKkZe4BiUisAp5tNifaEdfs9uTz4Ijr4jSniveL1Kio6ngARvM + xpQgYj4M7fn5q1rIVeZyTFNWFBUY13rViQkvK69b2oz+RwARPgDYkl6kRW/7Z07f + T7CrEzhbxfbAlPKpfAhcgusHUcajQXfh8T8OtlTNNbTedlFS4dHWkEUKRfoUA09h + p2ZNCIaGPqQ34QIDAQABo4GRMIGOMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE + FHxXU4zLckC2WtgM6kxL4c1nxmB1MCsGA1UdHwQkMCIwIKAeoByGGmh0dHA6Ly9s + b2NhbGhvc3Q6MzgwODAvY3JsMA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBR8 + V1OMy3JAtlrYDOpMS+HNZ8ZgdTANBgkqhkiG9w0BAQsFAAOCAQEAb9ZyuWPLQDd+ + H2MHr4VEADuXY/EXlBKf+YH9tfWfiWkUkOVPFanX9+dO/EDcOMKItTd6u8FI05SL + UCjLsjLSwufxC8SpCo3XgkL/1q2wRlZ0IZcHPZV+7qATkqBl54k/ImZwENs0oXuT + uDcfdJ4FgP/M47HnJaP9/8IRxOgLn370zhxrjx56+A1BPiRAYfWyqCYOEHbFd+Cf + q9pFQQOHdmarzF/EScq6UvndtXRAthu1I1ArqzSisLV55O5eu6L+5h2ZAoBHlCD6 + Imgvg/m5BbmUo3G5QlfGpU1H7edNsn+OPfC9SDI9jYSKJ8lbyb/fn1QRnjEEnzqs + AV0t3VsfgQ== + -----END CERTIFICATE----- + owner_string: "keylime" + permissions: 0640 + - path: /etc/keylime/agent.conf.d/10-config.conf + content: | + [agent] + ip = '0.0.0.0' + registrar_ip = '192.168.100.184' + uuid = '61388a67-baa4-4f2b-8221-d539b7b4d98b' + owner_string: "keylime" + permissions: 0640 + - name: "Set keylime owner to /var/lib/keylime" + commands: + - chown -R keylime:keylime /var/lib/keylime + - name: "Set default IMA policy" + path: /etc/ima/ima-policy + permissions: 0644 + content: | + # PROC_SUPER_MAGIC + dont_measure fsmagic=0x9fa0 + # SYSFS_MAGIC + dont_measure fsmagic=0x62656572 + # DEBUGFS_MAGIC + dont_measure fsmagic=0x64626720 + # TMPFS_MAGIC + dont_measure fsmagic=0x01021994 + # RAMFS_MAGIC + dont_measure fsmagic=0x858458f6 + # SECURITYFS_MAGIC + dont_measure fsmagic=0x73636673 + # SELINUX_MAGIC + dont_measure fsmagic=0xf97cff8c + # CGROUP_SUPER_MAGIC + dont_measure fsmagic=0x27e0eb + # OVERLAYFS_MAGIC + # when containers are used we almost always want to ignore them + dont_measure fsmagic=0x794c7630 + # Don't measure log, audit or tmp files + dont_measure obj_type=var_log_t + dont_measure obj_type=auditd_log_t + dont_measure obj_type=tmp_t + # MEASUREMENTS + measure func=BPRM_CHECK + measure func=FILE_MMAP mask=MAY_EXEC + measure func=MODULE_CHECK uid=0 + - name: "Enable keylime-agent service" + systemctl: + enable: + - keylime-agent + start: + - keylime-agent +``` + + +Lets go a bit into detail of some of the options. + + - `bind_mounts`: This is required for the keylime-agent to store the keys and certificates. It needs to be persisted across reboots. + - `extra_cmdline`: This is required to enable the IMA appraisal in the kernel. This is required for keylime to work if you expect to use runtime attestation. + - `users`: We add the keylime user as the default keylime agent service will drop privileges to this user. Has to have the `tss` group as well. + - `/etc/ima/ima-policy`: This is the default IMA policy that the kernel will use. The one provided is just a generic example. + - `/var/lib/keylime/cv_ca/cacert.crt`: This is the CA certificate that the verifier, tenant, and registrar will use to communicate with the agent. This comes from the registrar server and its either self-signed or signed by a CA that the verifier trusts. You have to make sure that this is deployed properly, otherwise the agent will not be able to communicate with the verifier/tenant/registrar correcttly. + - Ownership of /var/lib/keylime: The keylime agent will need to write to this directory. It is important to set the correct ownership. We do it at the end so all the writen files are owned by the keylime user. + - `systemctl`: We want to enable and start the keylime-agent service so it starts on boot and is running. + - `/etc/keylime/agent.conf.d/10-config.conf`: This is the keylime agent configuration. Keylime agent provides a default config and we use this to override those default values. Minimal values that need configuring here are as follows: + - `ip`: The IP address the agent will listen on. This should be set to `0.0.0.0` to listen on all interfaces or to the specific interface IP address if you know it on advance. Otherwise it will only listen on the loopback interface and wont be reachable from the outside. + - `registrar_ip`: The IP address of the keylime registrar server. Otherwise the agent will not be able to communicate with the registrar. + - `uuid`: The UUID of the agent. This is used to identify the agent in the registrar. This can be any UUID as long as it is unique in the registrar server. If you set it to 'generate' it will generate a random UUID for you. + + +With this values, building a derivative image and installing it should be enough to have the keylime agent running in Kairos. +You can verify it under the registrar as it should auto register itself. + + +Now from the tenant you can apply any policy you want to the agent. + +As an example, we add a policy that will only allow the agent to boot if the PCR 15 is equal to a specific value (in this case empty value as we havent measured anything into PCR15): + +```bash +$ keylime_tenant -c update --uuid UID_OF_AGENT -t IP_OF_AGENT --tpm_policy '{"15":["0000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000","000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"]}' +``` + +Then the agent will start the attestation process, which you can see both in the agent logs and in the verifier logs. As well as checking with the tenant that the agent is in the correct state. + +Then to test the revocation you can extend the PCR15 manually: + +```bash +$ tpm2_pcrextend 15:sha256=f1d2d2f924e986ac86fdf7b36c94bcdf32beec15324234324234234333333333 +``` + +Then the verifier will see that the agent is not in the correct state and will revoke it. You can see this in the verifier logs: + +```bash +# {"61388a67-baa4-4f2b-8221-d539b7b4d98b": {"operational_state": "Invalid Quote", "v": null, "ip": "192.168.100.164", "port": 9002, "tpm_policy": "{ \"15\": [\"0000000000000000000000000000000000000000\", \"0000000000000000000000000000000000000000000000000000000000000000\", \"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"], \"mask\": \"0x408000\"}", "meta_data": "{}", "has_mb_refstate": 0, "has_runtime_policy": 0, "accept_tpm_hash_algs": ["sha512", "sha384", "sha256"], "accept_tpm_encryption_algs": ["ecc", "rsa"], "accept_tpm_signing_algs": ["ecschnorr", "rsassa"], "hash_alg": "sha256", "enc_alg": "rsa", "sign_alg": "rsassa", "verifier_id": "default", "verifier_ip": "127.0.0.1", "verifier_port": 8881, "severity_level": 6, "last_event_id": "pcr_validation.invalid_pcr_15", "attestation_count": 158, "last_received_quote": 1730388195, "last_successful_attestation": 1730388193}} +``` + +You will also see on the agent logs that it has been revoked: + +```bash +# INFO keylime_agent::notifications_handler > Received revocation +``` + +This is a very basic example of how to use keylime in Kairos. You can extend this to use more complex policies and more complex attestation mechanisms. +As Keylime is a very flexible tool, you can use it in many different ways to secure your infrastructure. Here are some more links to the Keylime documentation to get you started: + - [Keylime documentation](https://keylime-docs.readthedocs.io/en/latest/) + - [Red Hat Keylime documentation](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/security_hardening/assembly_ensuring-system-integrity-with-keylime_security-hardening) + - [Suse Keylime documentation](https://documentation.suse.com/sle-micro/6.0/html/Micro-keylime/index.html) \ No newline at end of file diff --git a/examples/keylime/keylime.yaml b/examples/keylime/keylime.yaml index 535264762..f29431d70 100644 --- a/examples/keylime/keylime.yaml +++ b/examples/keylime/keylime.yaml @@ -7,17 +7,9 @@ install: bind_mounts: - /var/lib/keylime grub_options: - # This is needed for IMA to work and measure stuff extra_cmdline: "ima_appraise=fix ima_template=ima-sig ima_policy=tcb" -# Keylime needs several things to work -# User keylime which is part of the tss group. Does not need to be able to login or have password, -# its mainly used for the agent to drop pivs to when runs as a service -# the /var/lib/keylime dir writable and owned by the keylime user -# the keylime registrar generated public CAs if any -# Any config dropped at /etc/keylime/agent.conf.d/ -# So registrar IP for example or verifier, etc... -# any extra config needs to be dropped there + stages: initramfs: - name: "Set user and password" @@ -29,14 +21,10 @@ stages: keylime: groups: - "tss" - hostname: kairos-{{ trunc 4 .Random }} - boot: # Do it on boot, at this point the bind mount for /var/lib/keylime is done and the user created + boot: - name: "Set Keylime config" files: - path: /var/lib/keylime/cv_ca/cacert.crt - # This is the ROOT CA the agent needs otherwise the tenant and verifier cannot connect to the agent! - # This is provided by the registrar and it gets generated on the registrar side ont he first boot - # or you can provide your own Root CA. In any case, the agent needs to have it otherwise no connection will be possible to it content: | -----BEGIN CERTIFICATE----- MIID8zCCAtugAwIBAgIBATANBgkqhkiG9w0BAQsFADBzMQswCQYDVQQGEwJVUzEm @@ -65,9 +53,6 @@ stages: owner_string: "keylime" permissions: 0640 - path: /etc/keylime/agent.conf.d/10-config.conf - # This is the agent config, it needs to know the registrar IP - # If the ip is not set, the agent will listen on localhost only - # The UUID is the agent UUID, it needs to be unique per agent. You can leave it empty and the agent will generate one on boot content: | [agent] ip = '0.0.0.0' @@ -110,15 +95,3 @@ stages: measure func=FILE_MMAP mask=MAY_EXEC measure func=MODULE_CHECK uid=0 - -# Then you can run on your tenant something like this to add that agent with a tpm policy -# Note that you can add more than one tpm to the policy, this uses 15 as an example -# keylime_tenant -c update --uuid UID_OF_AGENT -t IP_OF_AGENT --tpm_policy '{"15":["0000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000","000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"]}' -# -# Then to test, you can manually extend the PCR for example to trigger a failure un attestation -# tpm2_pcrextend 15:sha256=f1d2d2f924e986ac86fdf7b36c94bcdf32beec15324234324234234333333333 -# When it fails you will see something like this on the verifier: -# {"61388a67-baa4-4f2b-8221-d539b7b4d98b": {"operational_state": "Invalid Quote", "v": null, "ip": "192.168.100.164", "port": 9002, "tpm_policy": "{\"22\": [\"0000000000000000000000000000000000000001\", \"0000000000000000000000000000000000000000000000000000000000000001\", \"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\", \"ffffffffffffffffffffffffffffffffffffffff\", \"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\", \"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"], \"15\": [\"0000000000000000000000000000000000000000\", \"0000000000000000000000000000000000000000000000000000000000000000\", \"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"], \"mask\": \"0x408000\"}", "meta_data": "{}", "has_mb_refstate": 0, "has_runtime_policy": 0, "accept_tpm_hash_algs": ["sha512", "sha384", "sha256"], "accept_tpm_encryption_algs": ["ecc", "rsa"], "accept_tpm_signing_algs": ["ecschnorr", "rsassa"], "hash_alg": "sha256", "enc_alg": "rsa", "sign_alg": "rsassa", "verifier_id": "default", "verifier_ip": "127.0.0.1", "verifier_port": 8881, "severity_level": 6, "last_event_id": "pcr_validation.invalid_pcr_15", "attestation_count": 158, "last_received_quote": 1730388195, "last_successful_attestation": 1730388193}} -# And supposedly the agent runs a revocation script. You can see the logs on the agent side -# INFO keylime_agent::notifications_handler > Received revocation -# WARN keylime_agent::revocation > Revocation certificate not yet available From f98cc0fbbd992e517d5b05e5685cb41e476f18e5 Mon Sep 17 00:00:00 2001 From: Itxaka Date: Tue, 12 Nov 2024 09:30:18 +0100 Subject: [PATCH 5/6] Update examples/keylime/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Itxaka --- examples/keylime/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/keylime/README.md b/examples/keylime/README.md index ac25b6054..d583ea3ea 100644 --- a/examples/keylime/README.md +++ b/examples/keylime/README.md @@ -130,7 +130,7 @@ Lets go a bit into detail of some of the options. - `extra_cmdline`: This is required to enable the IMA appraisal in the kernel. This is required for keylime to work if you expect to use runtime attestation. - `users`: We add the keylime user as the default keylime agent service will drop privileges to this user. Has to have the `tss` group as well. - `/etc/ima/ima-policy`: This is the default IMA policy that the kernel will use. The one provided is just a generic example. - - `/var/lib/keylime/cv_ca/cacert.crt`: This is the CA certificate that the verifier, tenant, and registrar will use to communicate with the agent. This comes from the registrar server and its either self-signed or signed by a CA that the verifier trusts. You have to make sure that this is deployed properly, otherwise the agent will not be able to communicate with the verifier/tenant/registrar correcttly. + You have to make sure that this is deployed properly, otherwise the agent will not be able to communicate with the verifier/tenant/registrar correctly. - Ownership of /var/lib/keylime: The keylime agent will need to write to this directory. It is important to set the correct ownership. We do it at the end so all the writen files are owned by the keylime user. - `systemctl`: We want to enable and start the keylime-agent service so it starts on boot and is running. - `/etc/keylime/agent.conf.d/10-config.conf`: This is the keylime agent configuration. Keylime agent provides a default config and we use this to override those default values. Minimal values that need configuring here are as follows: From ab1b0b0470699681c95cc279508920166ca784d7 Mon Sep 17 00:00:00 2001 From: Itxaka Date: Wed, 13 Nov 2024 11:19:19 +0100 Subject: [PATCH 6/6] Update examples/keylime/README.md Co-authored-by: Ettore Di Giacinto Signed-off-by: Itxaka --- examples/keylime/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/keylime/README.md b/examples/keylime/README.md index d583ea3ea..930d8a999 100644 --- a/examples/keylime/README.md +++ b/examples/keylime/README.md @@ -3,7 +3,7 @@ Most of the steps are already covered in the [Keylime documentation](https://keylime-docs.readthedocs.io/en/latest/). Here we will cover the steps that are specific to Kairos. -We provide thee keylime agent as a luet package for ease of installation. +We provide the keylime agent as a luet package for ease of installation. For it to be installeed you need to create your own derivative of the Kairos image and add the keylime-agent package to it.