Fix Kerberos test flow and improve multi-namespace support in k3s

- Resolve namespace drift in Kerberos test flow and OpenBao deployment.
- Fix OpenAPI credential-validation failures in etc scripts by using --validate=false with kubectl.
- Introduce preferred_service_namespace() to accurately target namespaces for KDC policy/test paths.
- Default Kerberos test user to 'administrator' and prefill from Ansible vault secrets.
- Generalized OpenBao deployment logic to correctly handle multi-namespace environments.
- Added regression test 'tests/etc/test_init_kerberos_k3s_real_kdc.sh'.
- Synchronized SERVICE_NAMESPACE extraction in prole_cfg.sh.

Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
chrisfu 2026-03-01 00:57:10 -08:00
parent 28b3cd72df
commit 46f31843c2
13 changed files with 413 additions and 65 deletions

View File

@ -1,5 +1,5 @@
; Prole Master Configuration File
; Generated by install.py on 2026-02-28 23:26:36
; Generated by install.py on 2026-03-01 00:30:19
; This file is used as input for Ansible deployment and k8s cluster creation.
[User]
@ -27,40 +27,40 @@ dependencies.opentofu.install = true
dependencies.python.install = true
dependencies.verify_all = false
disk_selection.disk_type = local
disk_selection.local_path = /Users/chrisfu
disk_selection.local_path = ${PROLE_HOME}/prole-tools-app/dist
disk_selection.removable_mount =
env_setup.NAMESPACE = ${NAMESPACE}
env_setup.NAMESPACE = prole-hq0-db0
env_setup.PROLE_CONF = ${PROLE_CONF}
env_setup.PROLE_DATA = ${PROLE_DATA}
env_setup.PROLE_HOME = ${PROLE_HOME}
env_setup.PROLE_LOGS = ${PROLE_LOGS}
env_setup.PROLE_SERVICE = ${PROLE_SERVICE}
init_cluster.at_rest_encryption_enabled = true
init_cluster.cluster_env = dev
init_cluster.deployment_target = prole-dev-cluster
init_cluster.cluster_env = service
init_cluster.deployment_target = prole-service-cluster
init_cluster.gitops_enabled = false
init_cluster.k3s_server_url =
init_cluster.k3s_token =
init_cluster.kerberos_enabled = false
init_cluster.mode = k3d
init_cluster.k3s_server_url = https://myrddin.prole.org:6443
init_cluster.k3s_token = ${OPENBAO:REDACTED}
init_cluster.kerberos_enabled = true
init_cluster.mode = k3s
init_cluster.start_cluster = true
init_cluster.supabase_enabled = false
init_cnpg_deploy.force_rollout = false
init_cnpg_deploy.run_deploy = true
init_db_build.run_build = true
init_password.db_host_port = 5432
init_password.db_namespace = ${NAMESPACE}
init_password.db_password =
init_password.db_password_confirm =
init_password.db_username = root
init_password.db_namespace = prole-hq0-db0
init_password.db_password = ${OPENBAO:kv/prole/${NAMESPACE}/db#password}
init_password.db_password_confirm = ${OPENBAO:kv/prole/${NAMESPACE}/db#password}
init_password.db_username = chrisfu
init_password.generate_ssh_key = true
init_scripts.run_scripts = true
kerberos_config.enabled = false
kerberos_config.kdc =
kerberos_config.password =
kerberos_config.realm =
kerberos_config.test_connection = false
kerberos_config.user =
kerberos_config.enabled = true
kerberos_config.kdc = 10.0.0.3
kerberos_config.password = ${OPENBAO:kv/prole/${NAMESPACE}/kerberos#password}
kerberos_config.realm = PROLE.ORG
kerberos_config.test_connection = true
kerberos_config.user = chrisfu
network_scan.run = true
ollama_config.model =
ollama_config.server_host =
@ -68,16 +68,16 @@ ollama_config.server_port = 11434
[Global]
; Variables used by name in more than one place or assumed global scope
CLUSTER_ENV = dev
CLUSTER_ENV = service
DB_HOST_PORT = 5432
DB_PASSWORD =
DEPLOYMENT_MODE = k3d
DEPLOYMENT_TARGET = prole-dev-cluster
DB_PASSWORD = ${OPENBAO:kv/prole/${NAMESPACE}/db#password}
DEPLOYMENT_MODE = k3s
DEPLOYMENT_TARGET = prole-service-cluster
NAMESPACE = ${NAMESPACE}
PROLE_DB_USER = root
PROLE_DB_USER = chrisfu
PROLE_HOME = ${PROLE_HOME}
PROLE_K3S_SERVER =
PROLE_K3S_TOKEN =
PROLE_K3S_SERVER = https://myrddin.prole.org:6443
PROLE_K3S_TOKEN = ${OPENBAO:REDACTED}
PROLE_OPENTOFU_URL = http://127.0.0.1:8080
SERVICE_NAMESPACE = default
@ -96,6 +96,8 @@ ANSIBLE_INVENTORY = ${PROLE_HOME}/infrastructure/inventory
ANSIBLE_REALM = PROLE.ORG
ANSIBLE_TOPOLOGY = {"domain":"prole.org","realm":"PROLE.ORG","internal_records":{"aventage.prole.org":"10.0.0.206","fairyland.prole.org":"10.0.0.208","loghost.prole.org":"10.0.0.3","morana.prole.org":"10.0.0.66","morgoth.prole.org":"10.0.0.204","myrddin.prole.org":"10.0.0.3","pi.prole.org":"10.0.0.5","raspberry.prole.org":"10.0.0.4","retropie.prole.org":"10.0.0.207","synology.prole.org":"10.0.0.203","zinfandel.prole.org":"10.0.0.205"},"ad_dc":{"host":"myrddin.prole.org","ip":"10.0.0.3"},"k3s":{"server_url":"https://myrddin.prole.org:6443","server_host":"myrddin.prole.org","token_present":true},"groups":{"iscsi":["pi.prole.org","raspberry.prole.org","myrddin.prole.org","retropie.prole.org"],"pihole":["pi.prole.org","raspberry.prole.org"],"ad_dc":["myrddin.prole.org"],"k3s_hosts":["myrddin.prole.org","pi.prole.org","retropie.prole.org"],"linux_hosts":["pi.prole.org","raspberry.prole.org","myrddin.prole.org","retropie.prole.org"]},"hosts":{"myrddin.prole.org":"10.0.0.3","pi.prole.org":"10.0.0.5","raspberry.prole.org":"10.0.0.4","retropie.prole.org":"10.0.0.207"},"unmapped_hosts":[]}
KDC_ANSIBLE_DETECTED = 10.0.0.3
KDC_AUTO_DETECTED = 10.0.0.3
KERBEROS_AUTO_ENABLED = True
[Port Forwards]
; No configuration values captured yet for this section.
@ -111,13 +113,27 @@ PROLE_SERVICE = ${PROLE_SERVICE}
; No configuration values captured yet for this section.
[Kerberos Authentication]
; No configuration values captured yet for this section.
AD_PORT_FORWARD = 1
AD_PROXY_HOST_NETWORK = 1
AD_PROXY_IMAGE = alpine/socat
AD_PROXY_SERVICE = prole-kerberos-ad-dc
AD_TCP_PORTS = 88 389 445 464 636
AD_UDP_PORTS = 88 464
ENABLED = True
KDC = 10.0.0.3
PASSWORD = ${OPENBAO:kv/prole/${NAMESPACE}/kerberos#password}
REALM = PROLE.ORG
SERVER = 10.0.0.3
USER = chrisfu
[Ollama]
; No configuration values captured yet for this section.
[Optional Features]
AT_REST_ENCRYPTION_ENABLED = True
GITOPS_ENABLED = False
KERBEROS_ENABLED = True
SUPABASE_ENABLED = False
[GitOps]
; No configuration values captured yet for this section.
@ -126,38 +142,41 @@ GITOPS_ENABLED = False
NAMESPACE = ${NAMESPACE}
[Initialize Cluster]
; No configuration values captured yet for this section.
ENVIRONMENT = service
K3S_SERVER_URL = https://myrddin.prole.org:6443
K3S_TOKEN = ${OPENBAO:REDACTED}
[Dev Cluster (k3d)]
CLUSTER_ENV = dev
DISPLAY_NAME = prole-dev-cluster
KUBECTL_CONTEXT =
KUBECTL_CONTEXT = prole-k3s
MODE = k3d
[Service Cluster (k3s)]
CLUSTER_ENV = prole-service-cluster
DISPLAY_NAME = prole-service-cluster
K3S_SERVER_URL =
K3S_TOKEN =
K3S_SERVER_URL = https://myrddin.prole.org:6443
K3S_TOKEN = ${OPENBAO:REDACTED}
MODE = k3s
PIPELINE_URL = http://127.0.0.1:8080
[Prod Cluster (k8s)]
ARTIFACTS_DIR = /private/var/folders/rt/pywlnmxj3dn7t5552vwdcpp80000gn/T/pytest-of-chrisfu/pytest-67/test_encryption_toggle0/data/staging
ARTIFACTS_DIR = /Users/chrisfu/dev/prole/data/staging
CLUSTER_ENV = prole-prod-cluster
DISPLAY_NAME = prole-prod-cluster
MODE = k8s
PIPELINE_URL = http://127.0.0.1:8080
[Docker Build]
; No configuration values captured yet for this section.
LOCAL_REGISTRY = localhost:5000
LOCAL_REGISTRY_INTERNAL = k3d-prole-registry.localhost:5000
[Initialization Scripts]
; No configuration values captured yet for this section.
[Deployment]
MODE = k3d
TARGET = prole-dev-cluster
MODE = k3s
TARGET = prole-service-cluster
[Install]
; No configuration values captured yet for this section.

View File

@ -100,6 +100,23 @@ ensure_namespace_named() {
fi
}
preferred_service_namespace() {
local ns="${SERVICE_NAMESPACE:-}"
local primary="${NAMESPACE:-}"
if [[ -n "$primary" && "$primary" != "default" ]]; then
if [[ -z "$ns" || "$ns" == "default" ]]; then
ns="$primary"
fi
fi
if [[ -z "$ns" ]]; then
ns="${primary:-default}"
fi
printf '%s' "$ns"
}
is_ip_address() {
[[ "$1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]
}
@ -411,7 +428,7 @@ sync_prole_kdc_trust() {
return 0
fi
local svc_ns
svc_ns="${SERVICE_NAMESPACE:-${NAMESPACE:-default}}"
svc_ns=$(preferred_service_namespace)
SERVICE_NAMESPACE="$svc_ns" \
KRB5_REALM="$KRB5_REALM" \
KRB5_KDC="$KRB5_KDC" \
@ -460,7 +477,7 @@ ensure_krb5_conf_configmap() {
.$domain_val = $realm_val
$domain_val = $realm_val
EOF
kubectl -n "$NAMESPACE" create configmap prole-krb5-conf --from-file=krb5.conf="$TMP" --dry-run=client -o yaml | kubectl apply -f -
kubectl -n "$NAMESPACE" create configmap prole-krb5-conf --from-file=krb5.conf="$TMP" --dry-run=client -o yaml | kubectl apply --validate=false -f -
rm -f "$TMP"
}
@ -705,7 +722,7 @@ apply_ad_forwarder() {
local forward_cmd="${tcp_cmd}${udp_cmd}wait"
log "Applying AD DC forwarder '${KRB5_AD_PROXY_NAME}' in namespace '${KRB5_AD_NAMESPACE}' (target ${kdc_host}) ..."
cat <<EOF | kubectl apply -n "$KRB5_AD_NAMESPACE" -f -
cat <<EOF | kubectl apply --validate=false -n "$KRB5_AD_NAMESPACE" -f -
apiVersion: apps/v1
kind: Deployment
metadata:
@ -806,11 +823,11 @@ ensure_kdc_network_allow() {
fi
fi
cidr="${kdc_host}/32"
ns="${SERVICE_NAMESPACE:-${NAMESPACE:-default}}"
ns=$(preferred_service_namespace)
ensure_namespace_named "$ns"
log "Ensuring KDC egress policy in namespace '${ns}' ..."
cat <<EOF | kubectl apply -n "$ns" -f -
cat <<EOF | kubectl apply --validate=false -n "$ns" -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
@ -825,7 +842,7 @@ spec:
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
cidr: ${cidr}
ports:
$(for port in $KRB5_AD_TCP_PORTS; do printf " - protocol: TCP\n port: %s\n" "$port"; done)
$(for port in $KRB5_AD_UDP_PORTS; do printf " - protocol: UDP\n port: %s\n" "$port"; done)
@ -854,7 +871,7 @@ spec:
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
cidr: ${cidr}
EOF
}
@ -921,6 +938,8 @@ run_test() {
prefer_cfg_realm_for_test
resolve_krb5_password
KRB5_USER="${KERBEROS_TEST_ADMIN_USER:-administrator}"
if [[ -z "${KRB5_REALM}" || -z "${KRB5_KDC}" || -z "${KRB5_USER}" || -z "${KRB5_PASSWORD}" ]]; then
err "ERROR: Missing Kerberos configuration. Ensure KRB5_REALM, KRB5_KDC, KRB5_USER, KRB5_PASSWORD are set."
exit 1
@ -997,14 +1016,16 @@ run_test() {
if [[ "${KRB5_AD_PORT_FORWARD}" == "1" ]]; then
test_samba_dns="$effective_kdc"
fi
local kdc_ns="${SERVICE_NAMESPACE:-${NAMESPACE:-default}}"
local kdc_ns
kdc_ns=$(preferred_service_namespace)
run_kerberos_test_loop() {
local test_attempt=1
local test_max_attempts=2
while true; do
if PROLE_USE_CHILD_REALM="$test_use_child" \
KRB5_REALM="$KRB5_REALM" KRB5_KDC="$effective_kdc" KRB5_ADMIN="$KRB5_ADMIN" \
KRB5_USER="$KRB5_USER" KRB5_PASSWORD="$KRB5_PASSWORD" \
KRB5_USER="${KERBEROS_TEST_ADMIN_USER:-administrator}" KRB5_PASSWORD="$KRB5_PASSWORD" \
SAMBA_ADMIN_USER="${KERBEROS_TEST_ADMIN_USER:-administrator}" SAMBA_ADMIN_PASSWORD="$KRB5_PASSWORD" \
SAMBA_DNS_SERVER="$test_samba_dns" \
"$SCRIPT_DIR/init_kerberos_test.sh" test; then
return 0

View File

@ -244,10 +244,7 @@ _OPENBAO_PF_PID=""
_OPENBAO_PF_STARTED=0
should_skip_deployment() {
if [[ "${PROLE_MODE:-}" != "k3s" ]]; then
return 1
fi
# If we are in k3s and the current namespace is NOT the primary service namespace,
# If the current namespace is NOT the primary service namespace,
# we assume it's a sub-namespace (like prole-db) and we should use the common service.
if [[ "$NAMESPACE" != "$PRIMARY_SERVICE_NAMESPACE" ]]; then
return 0

View File

@ -247,7 +247,11 @@ if [[ -n "$_prole_cfg_file" ]]; then
if [[ -n "$_cfg_ns" ]]; then
export NAMESPACE="$_cfg_ns"
fi
unset _cfg_ns
_cfg_sns=$(_prole_cfg_extract_key "$_prole_cfg_file" "SERVICE_NAMESPACE")
if [[ -n "$_cfg_sns" ]]; then
export SERVICE_NAMESPACE="$_cfg_sns"
fi
unset _cfg_ns _cfg_sns
fi
if [[ -z "${PROLE_HOME:-}" && -d "$_prole_cfg_home_guess" ]]; then

View File

@ -1713,7 +1713,7 @@ class ProleSilentInstaller(ProleInstallerBase):
inputs["kerberos_config.enabled"] = _bool_str(False)
inputs["kerberos_config.realm"] = ""
inputs["kerberos_config.kdc"] = ""
inputs["kerberos_config.user"] = ""
inputs["kerberos_config.user"] = "administrator"
inputs["kerberos_config.password"] = ""
inputs["kerberos_config.test_connection"] = _bool_str(
DEFAULT_ACTION_FLAGS.get("kerberos_config.test_connection", False)

View File

@ -596,7 +596,7 @@ class ProleInstaller(
# Kerberos / optional features
self.kerberos_enabled = tk.BooleanVar(value=False)
self.kerberos_realm = tk.StringVar()
self.kerberos_user = tk.StringVar()
self.kerberos_user = tk.StringVar(value="administrator")
self.kerberos_password = tk.StringVar()
self.kerberos_kdc = tk.StringVar()
self.supabase_enabled = tk.BooleanVar(value=False)

View File

@ -4,6 +4,7 @@ import configparser
import os
import shutil
import subprocess
import tempfile
import threading
from pathlib import Path
import tkinter as tk
@ -15,7 +16,12 @@ from installer.core.env import (
_deployment_target_label,
_ensure_ansible_vault_credentials,
)
from installer.config import _decrypt_prole_secret, _is_openbao_ref, _is_prole_secret
from installer.config import (
SECRET_KEY_SPECS,
_decrypt_prole_secret,
_is_openbao_ref,
_is_prole_secret,
)
class SecurityScreenMixin:
@ -327,6 +333,86 @@ class SecurityScreenMixin:
ns = os.environ.get("NAMESPACE", "") or "default"
return ns
@staticmethod
def _yaml_scalar(content: str, key: str) -> str:
prefix = f"{key}:"
for line in content.splitlines():
stripped = line.strip()
if not stripped or stripped.startswith("#"):
continue
if not stripped.startswith(prefix):
continue
value = stripped[len(prefix) :].strip()
if len(value) >= 2 and value[0] == value[-1] and value[0] in ('"', "'"):
value = value[1:-1]
return value
return ""
@staticmethod
def _vault_password_files() -> list[Path]:
files: list[Path] = []
env_pw = os.environ.get("ANSIBLE_VAULT_PASSWORD_FILE", "").strip()
if env_pw:
files.append(Path(env_pw))
for base in (Path.cwd(), PROJECT_ROOT):
files.append(base / ".vault_pass")
seen: set[Path] = set()
unique: list[Path] = []
for item in files:
if item in seen:
continue
seen.add(item)
unique.append(item)
return unique
def _resolve_samba_admin_password_from_vault(self) -> str:
vault_path = (
PROJECT_ROOT
/ "infrastructure"
/ "inventory"
/ "group_vars"
/ "ad_dc"
/ "vault.yml"
)
if not vault_path.exists():
return ""
try:
raw = vault_path.read_text(encoding="utf-8")
except Exception:
raw = ""
if raw and "$ANSIBLE_VAULT;" not in raw:
return self._yaml_scalar(raw, "vault_samba_dns_admin_pass")
if shutil.which("ansible-vault") is None:
return ""
_ensure_ansible_vault_credentials(prompt_ui=False)
for password_file in self._vault_password_files():
if not password_file.is_file():
continue
try:
res = subprocess.run(
[
"ansible-vault",
"view",
str(vault_path),
"--vault-password-file",
str(password_file),
],
capture_output=True,
text=True,
check=False,
)
except Exception:
continue
if res.returncode != 0:
continue
value = self._yaml_scalar(res.stdout or "", "vault_samba_dns_admin_pass")
if value:
return value
return ""
def _load_secret_cache_from_cfg(self):
try:
if self._cfg_path_override is not None:
@ -389,6 +475,8 @@ class SecurityScreenMixin:
krb_plain = krb_val
else:
krb_plain = ""
if not krb_plain:
krb_plain = self._resolve_samba_admin_password_from_vault()
if krb_plain:
try:
self.kerberos_password.set(krb_plain)

View File

@ -2,7 +2,6 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: openbao
namespace: default
spec:
replicas: 1
selector:
@ -24,7 +23,6 @@ apiVersion: v1
kind: Service
metadata:
name: openbao
namespace: default
spec:
selector:
app: openbao

View File

@ -100,6 +100,23 @@ ensure_namespace_named() {
fi
}
preferred_service_namespace() {
local ns="${SERVICE_NAMESPACE:-}"
local primary="${NAMESPACE:-}"
if [[ -n "$primary" && "$primary" != "default" ]]; then
if [[ -z "$ns" || "$ns" == "default" ]]; then
ns="$primary"
fi
fi
if [[ -z "$ns" ]]; then
ns="${primary:-default}"
fi
printf '%s' "$ns"
}
is_ip_address() {
[[ "$1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]
}
@ -411,7 +428,7 @@ sync_prole_kdc_trust() {
return 0
fi
local svc_ns
svc_ns="${SERVICE_NAMESPACE:-${NAMESPACE:-default}}"
svc_ns=$(preferred_service_namespace)
SERVICE_NAMESPACE="$svc_ns" \
KRB5_REALM="$KRB5_REALM" \
KRB5_KDC="$KRB5_KDC" \
@ -460,7 +477,7 @@ ensure_krb5_conf_configmap() {
.$domain_val = $realm_val
$domain_val = $realm_val
EOF
kubectl -n "$NAMESPACE" create configmap prole-krb5-conf --from-file=krb5.conf="$TMP" --dry-run=client -o yaml | kubectl apply -f -
kubectl -n "$NAMESPACE" create configmap prole-krb5-conf --from-file=krb5.conf="$TMP" --dry-run=client -o yaml | kubectl apply --validate=false -f -
rm -f "$TMP"
}
@ -705,7 +722,7 @@ apply_ad_forwarder() {
local forward_cmd="${tcp_cmd}${udp_cmd}wait"
log "Applying AD DC forwarder '${KRB5_AD_PROXY_NAME}' in namespace '${KRB5_AD_NAMESPACE}' (target ${kdc_host}) ..."
cat <<EOF | kubectl apply -n "$KRB5_AD_NAMESPACE" -f -
cat <<EOF | kubectl apply --validate=false -n "$KRB5_AD_NAMESPACE" -f -
apiVersion: apps/v1
kind: Deployment
metadata:
@ -806,11 +823,11 @@ ensure_kdc_network_allow() {
fi
fi
cidr="${kdc_host}/32"
ns="${SERVICE_NAMESPACE:-${NAMESPACE:-default}}"
ns=$(preferred_service_namespace)
ensure_namespace_named "$ns"
log "Ensuring KDC egress policy in namespace '${ns}' ..."
cat <<EOF | kubectl apply -n "$ns" -f -
cat <<EOF | kubectl apply --validate=false -n "$ns" -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
@ -825,7 +842,7 @@ spec:
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
cidr: ${cidr}
ports:
$(for port in $KRB5_AD_TCP_PORTS; do printf " - protocol: TCP\n port: %s\n" "$port"; done)
$(for port in $KRB5_AD_UDP_PORTS; do printf " - protocol: UDP\n port: %s\n" "$port"; done)
@ -854,7 +871,7 @@ spec:
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
cidr: ${cidr}
EOF
}
@ -921,6 +938,8 @@ run_test() {
prefer_cfg_realm_for_test
resolve_krb5_password
KRB5_USER="${KERBEROS_TEST_ADMIN_USER:-administrator}"
if [[ -z "${KRB5_REALM}" || -z "${KRB5_KDC}" || -z "${KRB5_USER}" || -z "${KRB5_PASSWORD}" ]]; then
err "ERROR: Missing Kerberos configuration. Ensure KRB5_REALM, KRB5_KDC, KRB5_USER, KRB5_PASSWORD are set."
exit 1
@ -997,14 +1016,16 @@ run_test() {
if [[ "${KRB5_AD_PORT_FORWARD}" == "1" ]]; then
test_samba_dns="$effective_kdc"
fi
local kdc_ns="${SERVICE_NAMESPACE:-${NAMESPACE:-default}}"
local kdc_ns
kdc_ns=$(preferred_service_namespace)
run_kerberos_test_loop() {
local test_attempt=1
local test_max_attempts=2
while true; do
if PROLE_USE_CHILD_REALM="$test_use_child" \
KRB5_REALM="$KRB5_REALM" KRB5_KDC="$effective_kdc" KRB5_ADMIN="$KRB5_ADMIN" \
KRB5_USER="$KRB5_USER" KRB5_PASSWORD="$KRB5_PASSWORD" \
KRB5_USER="${KERBEROS_TEST_ADMIN_USER:-administrator}" KRB5_PASSWORD="$KRB5_PASSWORD" \
SAMBA_ADMIN_USER="${KERBEROS_TEST_ADMIN_USER:-administrator}" SAMBA_ADMIN_PASSWORD="$KRB5_PASSWORD" \
SAMBA_DNS_SERVER="$test_samba_dns" \
"$SCRIPT_DIR/init_kerberos_test.sh" test; then
return 0

View File

@ -247,7 +247,11 @@ if [[ -n "$_prole_cfg_file" ]]; then
if [[ -n "$_cfg_ns" ]]; then
export NAMESPACE="$_cfg_ns"
fi
unset _cfg_ns
_cfg_sns=$(_prole_cfg_extract_key "$_prole_cfg_file" "SERVICE_NAMESPACE")
if [[ -n "$_cfg_sns" ]]; then
export SERVICE_NAMESPACE="$_cfg_sns"
fi
unset _cfg_ns _cfg_sns
fi
if [[ -z "${PROLE_HOME:-}" && -d "$_prole_cfg_home_guess" ]]; then

View File

@ -1 +1 @@
78
81

View File

@ -0,0 +1,191 @@
#!/usr/bin/env bash
# Regression test for etc/init_kerberos.sh in k3s mode with real KDC endpoint.
set -euo pipefail
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
PROLE_HOME=$(cd "$SCRIPT_DIR/../.." && pwd)
SOURCE_ETC_DIR="$PROLE_HOME/etc"
TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR"' EXIT
WORK_DIR="$TMP_DIR/work"
BIN_DIR="$TMP_DIR/bin"
mkdir -p "$WORK_DIR/etc" "$WORK_DIR/conf" "$BIN_DIR"
cp "$SOURCE_ETC_DIR/init_kerberos.sh" "$WORK_DIR/etc/init_kerberos.sh"
cp "$SOURCE_ETC_DIR/prole_cfg.sh" "$WORK_DIR/etc/prole_cfg.sh"
chmod +x "$WORK_DIR/etc/init_kerberos.sh"
cat <<EOF > "$WORK_DIR/etc/init_kerberos_test.sh"
#!/usr/bin/env bash
exit 0
EOF
chmod +x "$WORK_DIR/etc/init_kerberos_test.sh"
cat <<EOF > "$WORK_DIR/env.sh"
#!/usr/bin/env bash
export PROLE_HOME="$WORK_DIR"
export PROLE_CONF="$WORK_DIR/conf"
EOF
cat <<EOF > "$WORK_DIR/conf/prole.cfg"
[globals]
prole.home = $WORK_DIR
prole.mode = k3s
EOF
export KUBECTL_LOG="$TMP_DIR/kubectl.log"
export KUBECTL_PAYLOAD_LOG="$TMP_DIR/kubectl-payload.log"
cat <<'EOF' > "$BIN_DIR/kubectl"
#!/usr/bin/env bash
set -euo pipefail
args=("$@")
printf '%s\n' "${args[*]}" >> "${KUBECTL_LOG}"
sub=""
sub_idx=-1
i=0
while [[ $i -lt ${#args[@]} ]]; do
case "${args[$i]}" in
-n|--namespace|--context|--kubeconfig)
i=$((i + 2))
;;
--namespace=*|--context=*|--kubeconfig=*)
i=$((i + 1))
;;
-*)
i=$((i + 1))
;;
*)
sub="${args[$i]}"
sub_idx=$i
break
;;
esac
done
case "$sub" in
get)
resource="${args[$((sub_idx + 1))]:-}"
if [[ "$resource" == "namespace" ]]; then
exit 1
fi
if [[ "$resource" == "pods" ]]; then
printf ''
exit 0
fi
exit 0
;;
create)
resource="${args[$((sub_idx + 1))]:-}"
if [[ "$resource" == "namespace" ]]; then
exit 0
fi
if [[ "$resource" == "configmap" ]]; then
cat <<YAML
apiVersion: v1
kind: ConfigMap
metadata:
name: prole-krb5-conf
YAML
exit 0
fi
exit 0
;;
apply)
payload="$(cat || true)"
printf '%s\n' "$payload" >> "${KUBECTL_PAYLOAD_LOG}"
case " ${args[*]} " in
*" --validate=false "*)
;;
*)
echo "error: error validating \"STDIN\": error validating data: failed to download openapi: the server has asked for the client to provide credentials" >&2
exit 1
;;
esac
if [[ "$payload" == *"name: prole-kdc-egress"* ]]; then
if [[ "$payload" != *"cidr: 10.0.0.3/32"* ]]; then
echo "missing expected kdc cidr in NetworkPolicy payload" >&2
exit 1
fi
if [[ "$payload" == *"cidr: 0.0.0.0/0"* ]]; then
echo "unexpected broad egress cidr in NetworkPolicy payload" >&2
exit 1
fi
fi
exit 0
;;
wait|exec|delete|rollout|patch|config)
exit 0
;;
*)
exit 0
;;
esac
EOF
chmod +x "$BIN_DIR/kubectl"
cat <<'EOF' > "$BIN_DIR/curl"
#!/usr/bin/env bash
exit 0
EOF
chmod +x "$BIN_DIR/curl"
cat <<'EOF' > "$BIN_DIR/jq"
#!/usr/bin/env bash
exit 0
EOF
chmod +x "$BIN_DIR/jq"
export PATH="$BIN_DIR:$PATH"
export PROLE_HOME="$WORK_DIR"
export PROLE_CONF="$WORK_DIR/conf"
export NAMESPACE="prole-db-a0001"
export SERVICE_NAMESPACE="default"
export PROLE_MODE="k3s"
export KRB5_REALM="PROLE.ORG"
export KRB5_KDC="10.0.0.3"
export KRB5_ADMIN="10.0.0.3"
export KRB5_PASSWORD="test-password"
if "$WORK_DIR/etc/init_kerberos.sh" test >"$TMP_DIR/stdout" 2>"$TMP_DIR/stderr"; then
:
else
echo "FAILURE: init_kerberos.sh test exited non-zero"
cat "$TMP_DIR/stderr"
exit 1
fi
if ! grep -q "Using KDC endpoint for test: 10.0.0.3" "$TMP_DIR/stdout"; then
echo "FAILURE: expected real KDC endpoint log line not found"
cat "$TMP_DIR/stdout"
exit 1
fi
if ! grep -q "apply --validate=false" "$KUBECTL_LOG"; then
echo "FAILURE: expected kubectl apply --validate=false invocation not found"
cat "$KUBECTL_LOG"
exit 1
fi
if ! grep -q "apply --validate=false -n prole-db-a0001 -f -" "$KUBECTL_LOG"; then
echo "FAILURE: expected KDC policy apply in resolved namespace not found"
cat "$KUBECTL_LOG"
exit 1
fi
if grep -q "apply --validate=false -n default -f -" "$KUBECTL_LOG"; then
echo "FAILURE: unexpected KDC policy apply against default namespace"
cat "$KUBECTL_LOG"
exit 1
fi
echo "SUCCESS"

View File

@ -12,6 +12,7 @@ from installer.state import InstallerState
from installer.milestone import Milestone, ProgressCallback
from installer.build import get_build_command, BuildMilestone
from installer.core.controller import ProleController
from installer.core.actions import ProleSilentInstaller
# ===== InstallerState =====
@ -270,6 +271,10 @@ class TestProleController:
assert c.project_root == tmp_path
assert c.verbose is False
assert c.state is not None
installer = ProleSilentInstaller(c)
defaults = installer._default_inputs()
assert defaults.get("kerberos_config.user") == "administrator"
assert defaults.get("kerberos_config.password") == ""
def test_init_verbose(self, tmp_path):
c = ProleController(tmp_path, verbose=True)