178 lines
7.9 KiB
YAML
178 lines
7.9 KiB
YAML
- name: Deploy+Verify 04-12 nodejs TLS Ingress
|
|
hosts: k3s_server
|
|
become: true
|
|
run_once: true
|
|
vars:
|
|
k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
|
verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}"
|
|
nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-12/04-12-nodejs-demo.yaml"
|
|
nodejs_manifest_dest: /tmp/nodejs-demo-04-12.yaml
|
|
# extra var 或环境变量(与 04-07 一致)
|
|
_nodejs_tls_entry_base: "{{ NODEJS_TLS_ENTRY_BASE | default(lookup('env', 'NODEJS_TLS_ENTRY_BASE') | default('', true), true) | trim }}"
|
|
_nodejs_tls_host: "{{ NODEJS_TLS_HOST | default(lookup('env', 'NODEJS_TLS_HOST') | default('', true), true) | trim }}"
|
|
create_nodejs_demo_tls_secret: "{{ (lookup('env', 'CREATE_NODEJS_DEMO_TLS_SECRET') | default('0', true) | trim) == '1' }}"
|
|
# 与清单 Ingress 默认 host 对齐;未 export NODEJS_TLS_* 时仍可用自签 + 默认 host
|
|
nodejs_verify_entry_base: "{{ (_nodejs_tls_entry_base | length > 0) | ternary(_nodejs_tls_entry_base, 'https://app.example.local') }}"
|
|
nodejs_verify_path: "/api/"
|
|
nodejs_verify_host: "{{ (_nodejs_tls_host | length > 0) | ternary(_nodejs_tls_host, 'app.example.local') }}"
|
|
# 自签实验室路径或显式 NODEJS_TLS_* 时跑 openssl/curl
|
|
nodejs_http_check_enabled: "{{ (create_nodejs_demo_tls_secret | bool) or ((_nodejs_tls_entry_base | length > 0) and (_nodejs_tls_host | length > 0)) }}"
|
|
_nodejs_tls_authority: "{{ nodejs_verify_entry_base | trim | regex_replace('^https?://', '') | regex_replace('/.*$', '') }}"
|
|
nodejs_tls_connect_host: "{{ _nodejs_tls_authority | regex_replace(':([0-9]+)$', '') }}"
|
|
nodejs_tls_connect_port: "{{ (_nodejs_tls_authority | regex_replace('^[^:]*:', '') | int) if (':' in _nodejs_tls_authority) else 443 }}"
|
|
tasks:
|
|
- name: Check TLS secret exists (nodejs-demo-tls)
|
|
ansible.builtin.shell: |
|
|
set -e
|
|
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n default get secret nodejs-demo-tls
|
|
args:
|
|
executable: /bin/bash
|
|
changed_when: false
|
|
failed_when: false
|
|
register: nodejs_tls_secret_check
|
|
|
|
- name: Create self-signed nodejs-demo-tls (lab opt-in, matches Ingress host in manifest)
|
|
when:
|
|
- nodejs_tls_secret_check.rc != 0
|
|
- create_nodejs_demo_tls_secret | bool
|
|
ansible.builtin.shell: |
|
|
set -euo pipefail
|
|
export KUBECONFIG={{ k3s_kubeconfig }}
|
|
HOST={{ nodejs_verify_host | quote }}
|
|
TMP=$(mktemp -d)
|
|
trap 'rm -rf "$TMP"' EXIT
|
|
echo "[OC-ASSERT] assertion=nodejs_tls_selfsigned phase=cluster probe=openssl_san host=${HOST}"
|
|
if openssl req -help 2>&1 | grep -q -- -addext; then
|
|
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
|
-keyout "$TMP/tls.key" -out "$TMP/tls.crt" \
|
|
-subj "/CN=${HOST}" \
|
|
-addext "subjectAltName=DNS:${HOST}"
|
|
else
|
|
: >"$TMP/cnf"
|
|
printf '%s\n' '[req]' 'distinguished_name = req_distinguished_name' 'x509_extensions = v3_ca' 'prompt = no' >>"$TMP/cnf"
|
|
printf '%s\n' '[req_distinguished_name]' "CN = ${HOST}" >>"$TMP/cnf"
|
|
printf '%s\n' '[v3_ca]' 'subjectAltName = @alt_names' '[alt_names]' "DNS.1 = ${HOST}" >>"$TMP/cnf"
|
|
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
|
-keyout "$TMP/tls.key" -out "$TMP/tls.crt" \
|
|
-config "$TMP/cnf" -extensions v3_ca
|
|
fi
|
|
kubectl create secret tls nodejs-demo-tls \
|
|
--cert="$TMP/tls.crt" --key="$TMP/tls.key" -n default \
|
|
--dry-run=client -o yaml | kubectl apply -f -
|
|
args:
|
|
executable: /bin/bash
|
|
register: nodejs_tls_autocreate
|
|
changed_when: true
|
|
|
|
- name: Remember autocreated TLS secret for teardown
|
|
ansible.builtin.set_fact:
|
|
nodejs_tls_secret_autocreated: true
|
|
when:
|
|
- create_nodejs_demo_tls_secret | bool
|
|
- nodejs_tls_autocreate is defined
|
|
- not (nodejs_tls_autocreate.skipped | default(false))
|
|
- (nodejs_tls_autocreate.rc | default(1)) == 0
|
|
|
|
- name: Re-read TLS secret (after optional create)
|
|
ansible.builtin.shell: |
|
|
set -e
|
|
KUBECONFIG={{ k3s_kubeconfig }} kubectl -n default get secret nodejs-demo-tls
|
|
args:
|
|
executable: /bin/bash
|
|
changed_when: false
|
|
failed_when: false
|
|
register: nodejs_tls_secret_check
|
|
|
|
- name: Gate when TLS secret missing
|
|
when: nodejs_tls_secret_check.rc != 0
|
|
ansible.builtin.include_role:
|
|
name: verify_common
|
|
tasks_from: gate-debug-end-play.yml
|
|
vars:
|
|
verify_gate_message: "[GATE] skipped doc_id=04-12 reason=missing_tls_secret secret=nodejs-demo-tls namespace=default hint=export CREATE_NODEJS_DEMO_TLS_SECRET=1 or kubectl create secret tls"
|
|
|
|
- name: Copy nodejs demo manifest
|
|
ansible.builtin.copy:
|
|
src: "{{ nodejs_manifest_src }}"
|
|
dest: "{{ nodejs_manifest_dest }}"
|
|
mode: "0644"
|
|
|
|
- name: Apply nodejs demo manifest
|
|
ansible.builtin.shell: |
|
|
set -e
|
|
KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ nodejs_manifest_dest }}
|
|
args:
|
|
executable: /bin/bash
|
|
changed_when: true
|
|
|
|
- name: Rollout status nodejs-demo
|
|
ansible.builtin.include_role:
|
|
name: verify_common
|
|
tasks_from: kubectl-rollout-status.yml
|
|
vars:
|
|
verify_rollout_ref: deployment/nodejs-demo
|
|
|
|
- name: Assert Service targetPort matches expected (optional)
|
|
when: nodejs_expected_target_port is defined and (nodejs_expected_target_port | int) > 0
|
|
ansible.builtin.shell: |
|
|
set -euo pipefail
|
|
exp="{{ nodejs_expected_target_port | int }}"
|
|
got=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get svc nodejs-demo -n default -o jsonpath='{.spec.ports[0].targetPort}')
|
|
echo "svc/nodejs-demo targetPort=$got expected=$exp"
|
|
test "$got" = "$exp"
|
|
args:
|
|
executable: /bin/bash
|
|
changed_when: false
|
|
|
|
- name: Assert Endpoints exist
|
|
ansible.builtin.include_role:
|
|
name: verify_common
|
|
tasks_from: kubectl-endpoints-ready.yml
|
|
vars:
|
|
verify_endpoints_service: nodejs-demo
|
|
verify_endpoints_assertion_label: nodejs_demo_endpoints
|
|
|
|
- name: TLS SNI + certificate subject (openssl)
|
|
when: nodejs_http_check_enabled | default(false)
|
|
ansible.builtin.include_role:
|
|
name: verify_common
|
|
tasks_from: tls-openssl-sni.yml
|
|
vars:
|
|
verify_tls_connect_host: "{{ nodejs_tls_connect_host }}"
|
|
verify_tls_port: "{{ nodejs_tls_connect_port }}"
|
|
verify_tls_servername: "{{ nodejs_verify_host }}"
|
|
verify_tls_expect_subject_substring: "{{ nodejs_verify_host }}"
|
|
verify_tls_assertion_label: nodejs_demo_tls_sni_handshake
|
|
|
|
- name: HTTPS check nodejs demo (path/host)
|
|
when: nodejs_http_check_enabled | default(false)
|
|
ansible.builtin.include_role:
|
|
name: verify_common
|
|
tasks_from: http-curl-expect.yml
|
|
vars:
|
|
verify_http_entry_base: "{{ nodejs_verify_entry_base }}"
|
|
verify_http_path: "{{ nodejs_verify_path | default('/api/') }}"
|
|
verify_http_host_header: "{{ nodejs_verify_host }}"
|
|
verify_http_assertion_label: nodejs_tls_ingress_entry_http
|
|
verify_http_tls_insecure: "{{ (create_nodejs_demo_tls_secret | bool) or ((lookup('env', 'NODEJS_TLS_CURL_INSECURE') | default('0', true) | trim) == '1') }}"
|
|
|
|
- name: Teardown when VERIFY_TEARDOWN=1
|
|
when: verify_teardown == "1"
|
|
ansible.builtin.shell: |
|
|
set -e
|
|
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ nodejs_manifest_dest }} --ignore-not-found=true
|
|
args:
|
|
executable: /bin/bash
|
|
changed_when: true
|
|
|
|
- name: Delete autocreated TLS secret on teardown
|
|
when:
|
|
- verify_teardown == "1"
|
|
- nodejs_tls_secret_autocreated | default(false) | bool
|
|
ansible.builtin.shell: |
|
|
set -e
|
|
KUBECONFIG={{ k3s_kubeconfig }} kubectl delete secret nodejs-demo-tls -n default --ignore-not-found=true
|
|
args:
|
|
executable: /bin/bash
|
|
changed_when: true
|