mirror of
https://github.com/dredx/prole.git
synced 2026-09-23 10:13:58 +00:00
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:
parent
28b3cd72df
commit
46f31843c2
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -1 +1 @@
|
||||
78
|
||||
81
|
||||
191
tests/etc/test_init_kerberos_k3s_real_kdc.sh
Normal file
191
tests/etc/test_init_kerberos_k3s_real_kdc.sh
Normal 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"
|
||||
@ -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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user