Installation Manual - 19 Greenfield HTPasswd Admin Identity
How the temporary greenfield HTPasswd cluster-admin identity is configured and validated on hub-dc-v7 and spoke-dc-v7.
This chapter configures a temporary HTPasswd identity provider for the greenfield OpenShift clusters after the hub and spoke clusters are installed and reachable.
Use this as the first human-login path before removing kubeadmin. Do not
remove kubeadmin until this login path is tested on each cluster and has
remained stable through OAuth rollout.
Target State
| Item | Value |
|---|---|
| Clusters | hub-dc-v7, spoke-dc-v7 |
| User | ze |
| OAuth provider | htpasswd-ze |
| Secret namespace | openshift-config |
| Secret name | htpasswd-ze |
| Role | cluster-admin |
| Password/hash storage | local-only operator custody, never Git |
Prerequisites
Run from gf-ocp-bootstrap-01 or from the operator workstation with SSH access
to it.
The cluster kubeconfigs must exist on gf-ocp-bootstrap-01:
/home/ze/ocp-greenfield-deployment/artifacts/openshift/hub-dc-v7/auth/kubeconfig
/home/ze/ocp-greenfield-deployment/artifacts/openshift/spoke-dc-v7/auth/kubeconfig
The operator must have the intended ze password from secure local custody.
Do not put the password in Git, issue comments, shell history, chat, or this
manual.
Create Local-Only HTPasswd Files
Create one htpasswd file per cluster under the local ignored secrets/
directory in the operator workspace.
Use a command pattern that avoids echoing the password. The example below expects the password to be supplied interactively or from a local-only secure source.
cd /home/ze/codex-opp-agent
umask 077
mkdir -p secrets
read -rsp "HTPasswd password for ze: " ZE_HTPASSWD_PASSWORD
printf '\n'
for cluster in hub-dc-v7 spoke-dc-v7; do
salt="$(openssl rand -base64 9 | tr -dc 'A-Za-z0-9' | head -c 8)"
hash="$(printf '%s' "$ZE_HTPASSWD_PASSWORD" \
| openssl passwd -apr1 -stdin -salt "$salt")"
printf 'ze:%s\n' "$hash" > "secrets/${cluster}-ze-htpasswd"
chmod 600 "secrets/${cluster}-ze-htpasswd"
done
unset ZE_HTPASSWD_PASSWORD hash salt
Do not print the generated htpasswd files. They contain password hashes and must remain local-only.
Create OpenShift Secrets
Copy each local htpasswd file to a temporary path on gf-ocp-bootstrap-01,
create the OpenShift Secret, and remove the temporary file immediately.
cd /home/ze/codex-opp-agent
for cluster in hub-dc-v7 spoke-dc-v7; do
remote="/tmp/${cluster}-ze-htpasswd.$$"
scp "secrets/${cluster}-ze-htpasswd" \
"ze@30.30.200.60:${remote}"
ssh ze@30.30.200.60 "
set -euo pipefail
export KUBECONFIG=/home/ze/ocp-greenfield-deployment/artifacts/openshift/${cluster}/auth/kubeconfig
oc -n openshift-config create secret generic htpasswd-ze \
--from-file=htpasswd=${remote} \
--dry-run=client -o yaml | oc apply -f -
rm -f ${remote}
"
done
Patch OAuth
Patch oauth/cluster on both clusters to use the htpasswd-ze provider.
for cluster in hub-dc-v7 spoke-dc-v7; do
ssh ze@30.30.200.60 "
set -euo pipefail
export KUBECONFIG=/home/ze/ocp-greenfield-deployment/artifacts/openshift/${cluster}/auth/kubeconfig
oc patch oauth cluster --type=merge -p '{
\"spec\": {
\"identityProviders\": [
{
\"name\": \"htpasswd-ze\",
\"mappingMethod\": \"claim\",
\"type\": \"HTPasswd\",
\"htpasswd\": {
\"fileData\": {
\"name\": \"htpasswd-ze\"
}
}
}
]
}
}'
"
done
This replaces the current identity provider list. If a future cluster already has production identity providers, merge the provider deliberately instead of blindly replacing the list.
Grant Cluster Admin
Grant cluster-admin to ze on both clusters.
for cluster in hub-dc-v7 spoke-dc-v7; do
ssh ze@30.30.200.60 "
set -euo pipefail
export KUBECONFIG=/home/ze/ocp-greenfield-deployment/artifacts/openshift/${cluster}/auth/kubeconfig
oc adm policy add-cluster-role-to-user cluster-admin ze
"
done
OpenShift may warn that user ze is not found before the first login. That is
expected. The RBAC binding is still created.
Wait For OAuth Rollout
Wait until authentication is healthy and OAuth pods are Running.
for cluster in hub-dc-v7 spoke-dc-v7; do
ssh ze@30.30.200.60 "
set -euo pipefail
export KUBECONFIG=/home/ze/ocp-greenfield-deployment/artifacts/openshift/${cluster}/auth/kubeconfig
oc get co authentication
oc -n openshift-authentication get pods
"
done
Expected state:
authenticationClusterOperator isAvailable=True,Progressing=False,Degraded=False;- OAuth pods in
openshift-authenticationare Running.
Validate Login And RBAC
Use a temporary kubeconfig for validation so the generated token is not stored in the repository.
read -rsp "HTPasswd password for ze: " ZE_HTPASSWD_PASSWORD
printf '\n'
for cluster in hub-dc-v7 spoke-dc-v7; do
server="$(ssh ze@30.30.200.60 "
export KUBECONFIG=/home/ze/ocp-greenfield-deployment/artifacts/openshift/${cluster}/auth/kubeconfig
oc whoami --show-server
")"
tmp="$(mktemp)"
KUBECONFIG="$tmp" oc login "$server" \
-u ze \
-p "$ZE_HTPASSWD_PASSWORD" \
--insecure-skip-tls-verify=true
KUBECONFIG="$tmp" oc whoami
KUBECONFIG="$tmp" oc auth can-i '*' '*' --all-namespaces
rm -f "$tmp"
done
unset ZE_HTPASSWD_PASSWORD
Expected output for each cluster:
ze
yes
Final Validation
Validate the provider, Secret, cluster-admin binding, and operator health without printing Secret data.
for cluster in hub-dc-v7 spoke-dc-v7; do
ssh ze@30.30.200.60 "
set -euo pipefail
export KUBECONFIG=/home/ze/ocp-greenfield-deployment/artifacts/openshift/${cluster}/auth/kubeconfig
echo \"== ${cluster} ==\"
oc get oauth cluster \
-o jsonpath='{range .spec.identityProviders[*]}{.name}{\"|\"}{.type}{\"\\n\"}{end}'
oc -n openshift-config get secret htpasswd-ze \
-o custom-columns=NAME:.metadata.name,TYPE:.type --no-headers
oc get clusterrolebinding -o json \
| jq -r '.items[]
| select(.roleRef.name==\"cluster-admin\")
| select(any(.subjects[]?; .kind==\"User\" and .name==\"ze\"))
| .metadata.name'
oc get co --no-headers \
| awk '\$3!=\"True\" || \$4!=\"False\" || \$5!=\"False\" {print}'
"
done
Expected state:
- OAuth provider
htpasswd-ze|HTPasswdexists on both clusters; - Secret
htpasswd-zeexists inopenshift-configon both clusters; - a
cluster-adminClusterRoleBinding forzeexists on both clusters; - the non-steady ClusterOperator command returns no output.
Kubeadmin Removal
Do not remove kubeadmin in this chapter.
Remove kubeadmin only in a later hardening gate after:
zelogin is validated again;zecan perform cluster-admin actions;- the operator has a second break-glass access plan or an explicit reinstall-only policy.
Completion State
For the recorded greenfield installation:
- issue:
OP-GF-IDP-1; - OAuth provider:
htpasswd-ze; - user:
ze; - role:
cluster-admin; - clusters:
hub-dc-v7;spoke-dc-v7;
- validation:
- real
zelogin succeeded on both clusters; oc auth can-i '*' '*' --all-namespacesreturnedyeson both clusters;- no non-steady ClusterOperators were reported after rollout.
- real