add Ansible Flatcar and platform bootstrap
Kube-bench CIS scan / Scan ephemeral K3s cluster (push) Successful in 56s

This commit is contained in:
2026-08-15 16:40:37 -04:00
parent 478cc49e50
commit 664c3c8236
11 changed files with 379 additions and 6 deletions
@@ -0,0 +1,6 @@
---
argocd_enabled: true
argocd_namespace: argocd
argocd_install_manifest_url: https://raw.githubusercontent.com/argoproj/argo-cd/v3.1.8/manifests/install.yaml
argocd_root_application_manifest: "{{ k3d_workspace }}/deployments/argocd/app-of-apps.yaml"
argocd_rollout_timeout: 300s
@@ -0,0 +1,32 @@
---
- name: Create ArgoCD namespace
ansible.builtin.raw: >-
{{ k3d_tool_dir }}/kubectl create namespace {{ argocd_namespace }}
--dry-run=client -o yaml | {{ k3d_tool_dir }}/kubectl apply -f -
become_user: "{{ k3d_user }}"
changed_when: false
- name: Install pinned ArgoCD manifest
ansible.builtin.raw: >-
{{ k3d_tool_dir }}/kubectl apply --server-side --force-conflicts
-n {{ argocd_namespace }} -f {{ argocd_install_manifest_url }}
become_user: "{{ k3d_user }}"
- name: Wait for ArgoCD server
ansible.builtin.raw: >-
{{ k3d_tool_dir }}/kubectl -n {{ argocd_namespace }} rollout status
deployment/argocd-server --timeout={{ argocd_rollout_timeout }}
become_user: "{{ k3d_user }}"
- name: Apply the GitOps root Application
ansible.builtin.raw: "{{ k3d_tool_dir }}/kubectl apply -f {{ argocd_root_application_manifest }}"
become_user: "{{ k3d_user }}"
- name: Verify root Application source path
ansible.builtin.raw: >-
{{ k3d_tool_dir }}/kubectl get application security-baseline-root
-n {{ argocd_namespace }} -o jsonpath={.spec.source.path}
become_user: "{{ k3d_user }}"
register: argocd_root_path
changed_when: false
failed_when: argocd_root_path.stdout | trim != 'deployments/argocd/apps'
@@ -0,0 +1,7 @@
---
cilium_enabled: false
cilium_namespace: kube-system
cilium_chart_version: 1.20.0
cilium_values_file: "{{ k3d_workspace }}/deployments/cilium/cilium-values.yaml"
cilium_k8s_service_host: ""
cilium_k8s_service_port: 6443
@@ -0,0 +1,48 @@
---
- name: Require a reachable Kubernetes API endpoint
ansible.builtin.assert:
that:
- cilium_k8s_service_host | length > 0
- cilium_k8s_service_port | int > 0
fail_msg: Set cilium_k8s_service_host and cilium_k8s_service_port for kube-proxy replacement.
- name: Verify kube-proxy is disabled
ansible.builtin.raw: "{{ k3d_tool_dir }}/kubectl -n kube-system get daemonset kube-proxy"
become_user: "{{ k3d_user }}"
register: kube_proxy_check
changed_when: false
failed_when: false
- name: Refuse Cilium replacement when kube-proxy is present
ansible.builtin.assert:
that:
- kube_proxy_check.rc != 0
fail_msg: kube-proxy is present. Create the cluster with a kube-proxy-free profile first.
- name: Add the Cilium Helm repository
ansible.builtin.raw: "{{ k3d_tool_dir }}/helm repo add cilium https://helm.cilium.io/"
become_user: "{{ k3d_user }}"
changed_when: false
- name: Update Helm repositories
ansible.builtin.raw: "{{ k3d_tool_dir }}/helm repo update"
become_user: "{{ k3d_user }}"
changed_when: false
- name: Install Cilium with kube-proxy replacement
ansible.builtin.raw: >-
{{ k3d_tool_dir }}/helm upgrade --install cilium cilium/cilium
--namespace {{ cilium_namespace }}
--version {{ cilium_chart_version }}
--values {{ cilium_values_file }}
--set kubeProxyReplacement=true
--set k8sServiceHost={{ cilium_k8s_service_host }}
--set k8sServicePort={{ cilium_k8s_service_port }}
--wait --timeout 10m
become_user: "{{ k3d_user }}"
- name: Wait for Cilium agents
ansible.builtin.raw: >-
{{ k3d_tool_dir }}/kubectl -n {{ cilium_namespace }} rollout status
daemonset/cilium --timeout=300s
become_user: "{{ k3d_user }}"
@@ -0,0 +1,23 @@
---
flatcar_expected_distribution: Flatcar
k3d_cluster_name: security-baseline
k3d_config_source: "{{ playbook_dir }}/../local-quickstart/k3d-cluster-config.yaml"
k3d_workspace: /opt/k3d-test/workspace/kubernetes-security-baseline
k3d_tool_dir: /opt/k3d-test/bin
k3d_user: core
k3d_group: core
k3d_version: 5.9.0
kubectl_version: v1.35.5
helm_version: v3.19.0
tool_architecture: amd64
bootstrap_repo_url: ""
bootstrap_repo_ref: main
bootstrap_repo_ssh_private_key: ""
bootstrap_repo_ssh_private_key_path: /run/k3d-test-repo-key
bootstrap_repo_source: "{{ playbook_dir }}/.."
kubeconfig_fetch_enabled: true
kubeconfig_artifact_dir: "{{ playbook_dir }}/../artifacts"
@@ -0,0 +1,149 @@
---
- name: Require Flatcar Linux
ansible.builtin.assert:
that:
- flatcar_os_release.stdout is search('ID=flatcar')
fail_msg: This role is for Flatcar Linux. Use bootstrap-k3s.yml for K3s hosts.
- name: Read host architecture
ansible.builtin.raw: uname -m
register: host_architecture
changed_when: false
- name: Validate x86-64 host architecture
ansible.builtin.assert:
that:
- host_architecture.stdout | trim in ['x86_64', 'amd64']
- tool_architecture == 'amd64'
fail_msg: This profile currently pins x86-64 binaries.
- name: Ensure Docker is enabled and running
ansible.builtin.raw: systemctl enable --now docker
changed_when: false
- name: Create Flatcar k3d directories
ansible.builtin.raw: >-
install -d -m 0755 -o {{ k3d_user }} -g {{ k3d_group }}
{{ k3d_tool_dir }} {{ k3d_workspace }} /home/core/.kube
- name: Install pinned k3d
ansible.builtin.raw: >-
if [ ! -x {{ k3d_tool_dir }}/k3d ] || [ ! -f {{ k3d_tool_dir }}/.k3d-{{ k3d_version }} ]; then
curl --fail --location --silent --show-error https://github.com/k3d-io/k3d/releases/download/v{{ k3d_version }}/k3d-linux-{{ tool_architecture }} --output {{ k3d_tool_dir }}/k3d && chmod 0755 {{ k3d_tool_dir }}/k3d &&
touch {{ k3d_tool_dir }}/.k3d-{{ k3d_version }};
fi
- name: Install pinned kubectl
ansible.builtin.raw: >-
if [ ! -x {{ k3d_tool_dir }}/kubectl ] || [ ! -f {{ k3d_tool_dir }}/.kubectl-{{ kubectl_version }} ]; then
curl --fail --location --silent --show-error https://dl.k8s.io/release/{{ kubectl_version }}/bin/linux/{{ tool_architecture }}/kubectl --output {{ k3d_tool_dir }}/kubectl && chmod 0755 {{ k3d_tool_dir }}/kubectl &&
touch {{ k3d_tool_dir }}/.kubectl-{{ kubectl_version }};
fi
- name: Download and install pinned Helm
ansible.builtin.raw: >-
if [ ! -x {{ k3d_tool_dir }}/helm ] || [ ! -f {{ k3d_tool_dir }}/.helm-{{ helm_version }} ]; then
curl --fail --location --silent --show-error https://get.helm.sh/helm-{{ helm_version }}-linux-{{ tool_architecture }}.tar.gz --output /tmp/flatcar-k3d-helm.tar.gz &&
tar -xzf /tmp/flatcar-k3d-helm.tar.gz -C /tmp &&
install -m 0755 /tmp/linux-amd64/helm {{ k3d_tool_dir }}/helm &&
touch {{ k3d_tool_dir }}/.helm-{{ helm_version }};
fi
- name: Configure core shell PATH
ansible.builtin.raw: >-
grep -Fxq 'export PATH="{{ k3d_tool_dir }}:$HOME/bin:$PATH"' /home/core/.profile ||
printf '%s\n' 'export PATH="{{ k3d_tool_dir }}:$HOME/bin:$PATH"'
'export KUBECONFIG="$HOME/.kube/config"' >> /home/core/.profile
&& chown core:core /home/core/.profile && chmod 0644 /home/core/.profile
- name: Copy repository from the Ansible controller
ansible.posix.synchronize:
src: "{{ bootstrap_repo_source }}/"
dest: "{{ k3d_workspace }}/"
archive: true
delete: false
rsync_opts:
- "--exclude=.git"
- "--exclude=artifacts"
delegate_to: localhost
become: false
when: bootstrap_repo_url | length == 0
- name: Install temporary repository deploy key
ansible.builtin.raw: >-
printf '%s' '{{ bootstrap_repo_ssh_private_key | b64encode }}' | base64 -d
> {{ bootstrap_repo_ssh_private_key_path }} &&
chmod 0600 {{ bootstrap_repo_ssh_private_key_path }}
no_log: true
when:
- bootstrap_repo_url | length > 0
- bootstrap_repo_ssh_private_key | length > 0
- name: Clone or update the repository on the host
ansible.builtin.raw: >-
if [ -d {{ k3d_workspace }}/.git ]; then
git -C {{ k3d_workspace }} fetch --prune origin {{ bootstrap_repo_ref }} &&
git -C {{ k3d_workspace }} checkout {{ bootstrap_repo_ref }} &&
git -C {{ k3d_workspace }} reset --hard origin/{{ bootstrap_repo_ref }};
else
GIT_SSH_COMMAND="ssh -i {{ bootstrap_repo_ssh_private_key_path }} -o StrictHostKeyChecking=accept-new"
git clone --branch {{ bootstrap_repo_ref }} {{ bootstrap_repo_url }} {{ k3d_workspace }};
fi
no_log: "{{ bootstrap_repo_ssh_private_key | length > 0 }}"
when: bootstrap_repo_url | length > 0
- name: Remove temporary repository deploy key
ansible.builtin.raw: rm -f {{ bootstrap_repo_ssh_private_key_path }}
when:
- bootstrap_repo_url | length > 0
- bootstrap_repo_ssh_private_key | length > 0
- name: Check whether the k3d cluster already exists
ansible.builtin.raw: "{{ k3d_tool_dir }}/k3d cluster list"
register: k3d_cluster_list
changed_when: false
- name: Create the k3d cluster
ansible.builtin.raw: >-
{{ k3d_tool_dir }}/k3d cluster create
--config {{ k3d_workspace }}/local-quickstart/{{ k3d_config_source | basename }}
--wait --timeout 180s
become_user: "{{ k3d_user }}"
when: k3d_cluster_name not in k3d_cluster_list.stdout
- name: Write the cluster kubeconfig for the core user
ansible.builtin.raw: >-
{{ k3d_tool_dir }}/k3d kubeconfig get {{ k3d_cluster_name }}
> /home/core/.kube/config && chmod 0600 /home/core/.kube/config
become_user: "{{ k3d_user }}"
- name: Verify Kubernetes nodes are Ready
ansible.builtin.raw: "{{ k3d_tool_dir }}/kubectl get nodes --no-headers"
become_user: "{{ k3d_user }}"
register: k3d_nodes
changed_when: false
retries: 12
delay: 10
until:
- k3d_nodes.rc == 0
- k3d_nodes.stdout is search(' Ready ')
- name: Ensure local kubeconfig artifact directory exists
ansible.builtin.file:
path: "{{ kubeconfig_artifact_dir }}"
state: directory
mode: '0700'
delegate_to: localhost
become: false
run_once: true
when: kubeconfig_fetch_enabled | bool
- name: Fetch kubeconfig artifact to the Ansible controller
ansible.posix.synchronize:
src: /home/core/.kube/config
dest: "{{ kubeconfig_artifact_dir }}/{{ inventory_hostname }}-kubeconfig"
mode: pull
archive: true
delegate_to: localhost
become: false
when: kubeconfig_fetch_enabled | bool