Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7088f9c
chore: improve wrapper scripts for flexibility
butler54 Dec 10, 2025
4b64072
feat: trustee GA
butler54 Dec 10, 2025
9f0074b
fix: test uplifting posture
butler54 Dec 17, 2025
04c9e3c
fix: add url path for a repo
butler54 Dec 17, 2025
af41851
fix: remove dead chart
butler54 Dec 17, 2025
71dcba5
fix: relative urls
butler54 Dec 17, 2025
a3a23c8
fix: update with security policies
butler54 Dec 17, 2025
7051aa9
fix: clean up secrets and gen secrets script
butler54 Dec 17, 2025
87a1dfb
fix: correct charts
butler54 Dec 22, 2025
7c90be7
chore: add flag
butler54 Jan 5, 2026
73d8cac
feat: add components required for pcr securing
butler54 Jan 5, 2026
c51b7ac
fix: Add corrected health check
butler54 Jan 6, 2026
0a7ecd9
fix: correctly override values
butler54 Jan 6, 2026
0f11573
fix: temporarily change for single source charts
butler54 Jan 6, 2026
fd031b3
fix: clean up measurements
butler54 Jan 12, 2026
fda5a3e
fix: deal with existing file
butler54 Jan 12, 2026
30121e3
fix: remove uneeded resource constrains
butler54 Jan 13, 2026
049fc9a
fix: add policy keywords
butler54 Feb 5, 2026
1a04d3d
fix: allow policy changes
butler54 Feb 5, 2026
1e48e90
fix: correct pcr8 rendering
butler54 Feb 5, 2026
61da62a
fix: stuff
butler54 Feb 5, 2026
27fa8e4
fix: make sure xxd is in the imperative container
butler54 Feb 6, 2026
db10ade
fix: decrease encoding variations
butler54 Feb 6, 2026
0123233
fix: use consistent gzip | base64 approach for initdata encoding
butler54 Feb 6, 2026
239b48e
fix: correct initial_pcr to have 64 zeros (32 bytes)
butler54 Feb 6, 2026
ea1257f
fix: hard return at EoL
butler54 Feb 6, 2026
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
33 changes: 23 additions & 10 deletions ansible/init-data-gzipper.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- name: Gzip initdata
- name: Gzip initdata and register init data
become: false
connection: local
hosts: localhost
Expand All @@ -7,6 +7,7 @@
kubeconfig: "{{ lookup('env', 'KUBECONFIG') }}"
cluster_platform: "{{ global.clusterPlatform | default('none') | lower }}"
hub_domain: "{{ global.hubClusterDomain | default('none') | lower}}"
security_policy_flavour: "{{ global.coco.securityPolicyFlavour | default('insecure') }}"
template_src: "initdata-default.toml.tpl"
tasks:
- name: Create temporary working directory
Expand Down Expand Up @@ -36,7 +37,6 @@
- name: Define temp file paths
ansible.builtin.set_fact:
rendered_path: "{{ tmpdir.path }}/rendered.toml"
gz_path: "{{ tmpdir.path }}/rendered.toml.gz"

- name: Render template to temp file
ansible.builtin.template:
Expand All @@ -45,15 +45,27 @@
mode: "0600"


- name: Gzip the rendered content
- name: Gzip and base64 encode the rendered content

Check failure on line 48 in ansible/init-data-gzipper.yaml

View workflow job for this annotation

GitHub Actions / build

risky-shell-pipe

Shells that use pipes should set the pipefail option.
ansible.builtin.shell: |
gzip -c "{{ rendered_path }}" > "{{ gz_path }}"
changed_when: true
cat "{{ rendered_path }}" | gzip | base64 -w0
register: initdata_encoded
changed_when: false

# This block runs a shell script that calculates a hash value (PCR8_HASH) derived from the contents of 'initdata.toml'.
# The script performs the following steps:
# 1. hash=$(sha256sum initdata.toml | cut -d' ' -f1): Computes the sha256 hash of 'initdata.toml' and assigns it to $hash.
# 2. initial_pcr=0000000000000000000000000000000000000000000000000000000000000000: Initializes a string of zeros as the initial PCR value.
# 3. PCR8_HASH=$(echo -n "$initial_pcr$hash" | xxd -r -p | sha256sum | cut -d' ' -f1): Concatenates initial_pcr and $hash, converts from hex to binary, computes its sha256 hash, and stores the result as PCR8_HASH.

Check failure on line 58 in ansible/init-data-gzipper.yaml

View workflow job for this annotation

GitHub Actions / build

yaml[line-length]

Line too long (217 > 160 characters)
# 4. echo $PCR8_HASH: Outputs the PCR hash value.
# The important part: The 'register: pcr8_hash' registers the **stdout of the command**, which is the value output by 'echo $PCR8_HASH', as 'pcr8_hash.stdout' in Ansible.

Check failure on line 60 in ansible/init-data-gzipper.yaml

View workflow job for this annotation

GitHub Actions / build

yaml[line-length]

Line too long (174 > 160 characters)
# It does NOT register an environment variable, but rather the value actually printed by 'echo'.
- name: Register init data pcr into a var

Check failure on line 62 in ansible/init-data-gzipper.yaml

View workflow job for this annotation

GitHub Actions / build

risky-shell-pipe

Shells that use pipes should set the pipefail option.

Check failure on line 62 in ansible/init-data-gzipper.yaml

View workflow job for this annotation

GitHub Actions / build

no-changed-when

Commands should not change things if nothing needs doing.
ansible.builtin.shell: |
hash=$(sha256sum "{{ rendered_path }}" | cut -d' ' -f1)
initial_pcr=0000000000000000000000000000000000000000000000000000000000000000
PCR8_HASH=$(echo -n "$initial_pcr$hash" | xxd -r -p | sha256sum | cut -d' ' -f1) && echo $PCR8_HASH
register: pcr8_hash

- name: Read gzip as base64
ansible.builtin.slurp:
path: "{{ gz_path }}"
register: gz_slurped

- name: Create/update ConfigMap with gzipped+base64 content
kubernetes.core.k8s:
Expand All @@ -66,4 +78,5 @@
name: "initdata"
namespace: "imperative"
data:
INITDATA: "{{ gz_slurped.content }}"
INITDATA: "{{ initdata_encoded.stdout }}"
PCR8_HASH: "{{ pcr8_hash.stdout }}"
37 changes: 27 additions & 10 deletions ansible/initdata-default.toml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ url = "https://kbs.{{ hub_domain }}"

[token_configs.kbs]
url = "https://kbs.{{ hub_domain }}"
cert = """
{{ trustee_cert }}
"""
cert = """{{ trustee_cert }}"""
'''

"cdh.toml" = '''
Expand All @@ -21,22 +19,27 @@ credentials = []
[kbc]
name = "cc_kbc"
url = "https://kbs.{{ hub_domain }}"
kbs_cert = """
{{ trustee_cert }}
"""
kbs_cert = """{{ trustee_cert }}"""


[image]
image_security_policy_uri = 'kbs:///default/security-policy/{{ security_policy_flavour }}'
'''

"policy.rego" = '''
package agent_policy

import future.keywords.in
import future.keywords.if
import future.keywords.every

default AddARPNeighborsRequest := true
default AddSwapRequest := true
default CloseStdinRequest := true
default CopyFileRequest := true
default CreateContainerRequest := true
default CreateSandboxRequest := true
default DestroySandboxRequest := true
default ExecProcessRequest := false
default GetMetricsRequest := true
default GetOOMEventRequest := true
default GuestDetailsRequest := true
Expand All @@ -52,7 +55,6 @@ default RemoveStaleVirtiofsShareMountsRequest := true
default ReseedRandomDevRequest := true
default ResumeContainerRequest := true
default SetGuestDateTimeRequest := true
default SetPolicyRequest := true
default SignalProcessRequest := true
default StartContainerRequest := true
default StartTracingRequest := true
Expand All @@ -64,5 +66,20 @@ default UpdateEphemeralMountsRequest := true
default UpdateInterfaceRequest := true
default UpdateRoutesRequest := true
default WaitProcessRequest := true
default WriteStreamRequest := true
'''
default ExecProcessRequest := false
default SetPolicyRequest := true
default WriteStreamRequest := false

ExecProcessRequest if {
input_command = concat(" ", input.process.Args)
some allowed_command in policy_data.allowed_commands
input_command == allowed_command
}

policy_data := {
"allowed_commands": [
"curl http://127.0.0.1:8006/cdh/resource/default/attestation-status/status",
"curl http://127.0.0.1:8006/cdh/resource/default/attestation-status/random"
]
}
'''
7 changes: 6 additions & 1 deletion overrides/values-trustee.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@ kbs:
- name: "kbsres1" # name is the name of the k8s secret that will be presented to trustee and accessible via the CDH
key: "secret/data/hub/kbsres1" # this is the path to the secret in vault.
- name: "passphrase"
key: "secret/data/hub/passphrase"
key: "secret/data/hub/passphrase"
# Override the default values for the coco pattern this is because when testing against a branch strange stuff happens
# FIXME: Don't commit this to main
global:
coco:
secured: true # true or false. If true, the cluster will be secured. If false, the cluster will be insecure.
34 changes: 30 additions & 4 deletions rhdp/rhdp-cluster-define.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,22 @@
from typing_extensions import Annotated


def get_default_cluster_configs() -> List[Dict]:
"""Get default cluster configurations"""
def get_default_cluster_configs(prefix: str = "") -> List[Dict]:
"""Get default cluster configurations

Args:
prefix: Optional prefix to add to cluster name and directory
"""
if prefix:
return [
{
"name": f"coco-{prefix}",
"directory": f"openshift-install-{prefix}",
"cluster_network_cidr": "10.128.0.0/14",
"machine_network_cidr": "10.0.0.0/16",
"service_network_cidr": "172.30.0.0/16",
}
]
return [
{
"name": "coco",
Expand Down Expand Up @@ -135,23 +149,35 @@ def run(
multicluster: Annotated[
bool, typer.Option("--multicluster", help="Deploy hub and spoke clusters")
] = False,
prefix: Annotated[
str, typer.Option("--prefix", help="Prefix for cluster name and directory")
] = "",
):
"""
Region flag requires an azure region key which can be (authoritatively)
requested with: "az account list-locations -o table".

Use --multicluster flag to deploy both hub (coco-hub) and spoke (coco-spoke)
clusters.

Use --prefix to add a prefix to cluster name and install directory, enabling
multiple cluster deployments (e.g., --prefix cluster1 creates coco-cluster1
in openshift-install-cluster1).
"""
validate_dir()

# Choose cluster configurations based on multicluster flag
if multicluster:
if prefix:
rprint("WARNING: --prefix is ignored when using --multicluster")
cluster_configs = get_multicluster_configs()
rprint("Setting up multicluster deployment (hub and spoke)")
else:
cluster_configs = get_default_cluster_configs()
rprint("Setting up single cluster deployment")
cluster_configs = get_default_cluster_configs(prefix)
if prefix:
rprint(f"Setting up single cluster deployment with prefix: {prefix}")
else:
rprint("Setting up single cluster deployment")

cleanup(pathlib.Path.cwd(), cluster_configs)
setup_install(
Expand Down
61 changes: 54 additions & 7 deletions rhdp/wrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,56 @@ get_python_cmd() {
fi
}

if [ "$#" -ne 1 ]; then
echo "Error: Exactly one argument is required."
echo "Usage: $0 {azure-region-code}"
# Parse arguments
AZUREREGION=""
PREFIX=""

while [[ $# -gt 0 ]]; do
case $1 in
--prefix)
PREFIX="$2"
shift 2
;;
--prefix=*)
PREFIX="${1#*=}"
shift
;;
-*)
echo "Error: Unknown option $1"
echo "Usage: $0 [--prefix <prefix>] {azure-region-code}"
echo "Example: $0 eastasia"
echo "Example: $0 --prefix cluster1 eastasia"
exit 1
;;
*)
if [ -z "$AZUREREGION" ]; then
AZUREREGION="$1"
else
echo "Error: Too many positional arguments."
echo "Usage: $0 [--prefix <prefix>] {azure-region-code}"
exit 1
fi
shift
;;
esac
done

if [ -z "$AZUREREGION" ]; then
echo "Error: Azure region is required."
echo "Usage: $0 [--prefix <prefix>] {azure-region-code}"
echo "Example: $0 eastasia"
echo "Example: $0 --prefix cluster1 eastasia"
exit 1
fi
AZUREREGION=$1

# Set install directory based on prefix
if [ -n "$PREFIX" ]; then
INSTALL_DIR="openshift-install-${PREFIX}"
echo "Using prefix: $PREFIX"
echo "Install directory: $INSTALL_DIR"
else
INSTALL_DIR="openshift-install"
fi

echo "---------------------"
echo "Validating configuration"
Expand Down Expand Up @@ -113,15 +156,19 @@ echo "---------------------"
echo "defining cluster"
echo "---------------------"
PYTHON_CMD=$(get_python_cmd)
$PYTHON_CMD rhdp/rhdp-cluster-define.py ${AZUREREGION}
if [ -n "$PREFIX" ]; then
$PYTHON_CMD rhdp/rhdp-cluster-define.py --prefix "${PREFIX}" ${AZUREREGION}
else
$PYTHON_CMD rhdp/rhdp-cluster-define.py ${AZUREREGION}
fi
echo "---------------------"
echo "cluster defined"
echo "---------------------"
sleep 10
echo "---------------------"
echo "openshift-install"
echo "---------------------"
openshift-install create cluster --dir=./openshift-install
openshift-install create cluster --dir=./${INSTALL_DIR}
echo "openshift-install done"
echo "---------------------"
echo "setting up secrets"
Expand All @@ -133,7 +180,7 @@ sleep 60
echo "---------------------"
echo "pattern install"
echo "---------------------"
export KUBECONFIG="$(pwd)/openshift-install/auth/kubeconfig"
export KUBECONFIG="$(pwd)/${INSTALL_DIR}/auth/kubeconfig"


./pattern.sh make install
Expand Down
22 changes: 0 additions & 22 deletions scripts/gen-secrets.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,13 @@ echo "Creating secrets as required"
echo

COCO_SECRETS_DIR="${HOME}/.coco-pattern"
SECURITY_POLICY_FILE="${COCO_SECRETS_DIR}/security-policy-config.json"
SSH_KEY_FILE="${COCO_SECRETS_DIR}/id_rsa"
KBS_PRIVATE_KEY="${COCO_SECRETS_DIR}/kbsPrivateKey"
KBS_PUBLIC_KEY="${COCO_SECRETS_DIR}/kbsPublicKey"
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
VALUES_FILE="${HOME}/values-secret-coco-pattern.yaml"

mkdir -p ${COCO_SECRETS_DIR}

if [ ! -f "${SECURITY_POLICY_FILE}" ]; then
echo "Creating security policy"
cat > ${SECURITY_POLICY_FILE} <<EOF
{
"default": [
{
"type": "insecureAcceptAnything"
}],
"transports": {}
}
EOF

fi

if [ ! -f "${KBS_PRIVATE_KEY}" ]; then
echo "Creating kbs keys"
Expand All @@ -34,13 +19,6 @@ if [ ! -f "${KBS_PRIVATE_KEY}" ]; then
openssl pkey -in "${KBS_PRIVATE_KEY}" -pubout -out "${KBS_PUBLIC_KEY}"
fi

if [ ! -f "${SSH_KEY_FILE}" ]; then
echo "Creating ssh keys"
rm -f "${SSH_KEY_FILE}.pub"
ssh-keygen -f "${SSH_KEY_FILE}" -N ""
fi


## Copy a sample values file if this stuff doesn't exist

if [ ! -f "${VALUES_FILE}" ]; then
Expand Down
Loading
Loading