Compare commits

..

No commits in common. "main" and "v1.0.0" have entirely different histories.
main ... v1.0.0

16 changed files with 70 additions and 405 deletions

View file

@ -5,6 +5,9 @@ on:
- cron: '0 3 * * 6'
push:
branches: ["main"]
paths:
- "Dockerfile"
- ".github/workflows/build-workflow.yaml"
tags: ["v*.*.*"]
pull_request:
branches: ["main"]

View file

@ -1,9 +1,8 @@
ARG NODE_IMAGE=node:22-trixie-slim
ARG NODE_IMAGE=node:22-bookworm-slim
FROM ${NODE_IMAGE} AS webssh2-builder
ENV DEBIAN_FRONTEND=noninteractive
# renovate: datasource=github-releases depName=billchurch/webssh2
ARG WEBSSH2_VERSION=5.0.1
RUN apt-get update \
@ -20,31 +19,19 @@ RUN apt-get update \
&& rm -f "/tmp/webssh2-${WEBSSH2_VERSION}.tar.gz" "/tmp/webssh2-${WEBSSH2_VERSION}.tar.gz.sha256" \
&& npm cache clean --force
FROM debian:trixie-slim
# renovate: datasource=github-releases depName=janosmiko/lfk
ARG LFK_VERSION=0.14.18
# renovate: datasource=github-releases depName=kubernetes/kubernetes
ARG KUBECTL_VERSION=1.36.2
# renovate: datasource=github-releases depName=helm/helm
ARG HELM_VERSION=3.21.2
# renovate: datasource=github-releases depName=derailed/k9s
ARG K9S_VERSION=0.51.0
# renovate: datasource=github-releases depName=int128/kubelogin
ARG OIDC_LOGIN_VERSION=1.36.2
# renovate: datasource=github-tags depName=ahmetb/kubectx
ARG KUBECTX_VERSION=0.9.5
FROM debian:bookworm-slim
ARG LFK_VERSION=0.14.9
ARG KUBECTL_VERSION=1.31.0
ARG HELM_VERSION=3.16.2
ARG K9S_VERSION=0.40.10
ARG WEBSSH2_VERSION=5.0.1
ENV DEBIAN_FRONTEND=noninteractive \
LANG=en_US.UTF-8 \
LANGUAGE=en_US:en \
LC_ALL=en_US.UTF-8 \
WEB_SSH_PORT=3000 \
WEBSSH2_LISTEN_PORT=3001 \
WEBSSH2_SSH_HOST=127.0.0.1 \
WEBSSH2_SSH_PORT=2222 \
SSH_PORT=2222 \
WEBSSH2_SSH_PORT=22 \
WEBSSH2_HEADER_TEXT=k8s-mgmt-pod \
WEBSSH2_SSH_HOSTKEY_ENABLED=false
@ -56,12 +43,7 @@ RUN apt-get update \
bash-completion \
ca-certificates \
curl \
jq \
locales \
unzip \
tar \
vim \
yq \
nginx-light \
netcat-openbsd \
openssh-client \
@ -93,23 +75,10 @@ RUN apt-get update \
&& curl -fsSLo "/tmp/k9s_Linux_amd64.tar.gz" "https://github.com/derailed/k9s/releases/download/v${K9S_VERSION}/k9s_Linux_amd64.tar.gz" \
&& tar -xzf "/tmp/k9s_Linux_amd64.tar.gz" -C /tmp \
&& install -m 0755 /tmp/k9s /usr/local/bin/k9s \
&& curl -fsSLo "/tmp/kubelogin_linux_amd64.zip" "https://github.com/int128/kubelogin/releases/download/v${OIDC_LOGIN_VERSION}/kubelogin_linux_amd64.zip" \
&& curl -fsSLo "/tmp/kubelogin_linux_amd64.zip.sha256" "https://github.com/int128/kubelogin/releases/download/v${OIDC_LOGIN_VERSION}/kubelogin_linux_amd64.zip.sha256" \
&& sed 's#\*kubelogin_linux_amd64.zip$#*/tmp/kubelogin_linux_amd64.zip#' /tmp/kubelogin_linux_amd64.zip.sha256 | sha256sum -c - \
&& unzip -p /tmp/kubelogin_linux_amd64.zip kubelogin > /usr/local/bin/kubectl-oidc_login \
&& chmod 0755 /usr/local/bin/kubectl-oidc_login \
&& curl -fsSLo /usr/local/bin/kubectx "https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_VERSION}/kubectx" \
&& curl -fsSLo /usr/local/bin/kubens "https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_VERSION}/kubens" \
&& chmod 0755 /usr/local/bin/kubectx /usr/local/bin/kubens \
&& mkdir -p /etc/bash_completion.d \
&& curl -fsSLo /etc/bash_completion.d/kubectx "https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_VERSION}/completion/kubectx.bash" \
&& curl -fsSLo /etc/bash_completion.d/kubens "https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_VERSION}/completion/kubens.bash" \
&& kubectl completion bash > /etc/bash_completion.d/kubectl \
&& helm completion bash > /etc/bash_completion.d/helm \
&& chmod 0644 /etc/bash_completion.d/kubectl /etc/bash_completion.d/helm /etc/bash_completion.d/kubectx /etc/bash_completion.d/kubens \
&& sed -i 's/^# *en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \
&& locale-gen en_US.UTF-8 \
&& update-locale LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \
&& chmod 0644 /etc/bash_completion.d/kubectl /etc/bash_completion.d/helm \
&& rm -f /tmp/kubectl.sha256 \
&& rm -rf /tmp/linux-amd64 \
&& rm -f \
@ -118,12 +87,8 @@ RUN apt-get update \
/tmp/k9s \
/tmp/README.md \
/tmp/LICENSE \
/tmp/kubelogin_linux_amd64.zip \
/tmp/kubelogin_linux_amd64.zip.sha256 \
/tmp/k9s_Linux_amd64.tar.gz \
&& rm -f /etc/ssh/ssh_host_* \
&& apt-get clean
&& rm -f /etc/ssh/ssh_host_*
COPY docker/sshd/10-lfk-base.conf /etc/ssh/sshd_config.d/10-lfk-base.conf
COPY docker/nginx/webssh.conf /etc/nginx/conf.d/webssh.conf
@ -134,9 +99,9 @@ COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod 0755 /usr/local/bin/entrypoint.sh \
&& chmod 0644 /etc/profile.d/20-k8s-tools-completion.sh
EXPOSE 2222 3000
EXPOSE 22 3000
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
CMD nc -z 127.0.0.1 "${SSH_PORT:-2222}" || exit 1
CMD nc -z 127.0.0.1 22 || exit 1
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/entrypoint.sh"]

View file

@ -6,10 +6,8 @@
- `kubectl` preinstalled from a pinned upstream binary release
- `helm` preinstalled from a pinned upstream binary release
- `k9s` preinstalled from a pinned GitHub release tarball
- `kubectx` and `kubens` preinstalled from a pinned upstream release
- `jq`, `yq`, and `vim` preinstalled from Debian packages
- `kubectl`, `helm`, `kubectx`, and `kubens` bash autocompletion enabled for both `admin` and `user`
- local `openssh-server` on port `2222`
- `kubectl` and `helm` bash autocompletion enabled for both `admin` and `user`
- local `openssh-server` on port `22`
- a browser-based SSH client on port `3000`
- a custom ASCII-art MOTD on login
- two provisioned users: `admin` and `user`
@ -22,7 +20,7 @@ One caveat is worth stating clearly: browser-based SSH tools do not keep the pri
## Ports
- `2222`: native SSH into the container's local `sshd`
- `22`: native SSH into the container's local `sshd`
- `3000`: browser UI entrypoint; `/` and `/ssh` are forced to a fixed local WebSSH2 session for `127.0.0.1` and rewritten back to that host if changed in the URL
## Runtime environment variables
@ -73,8 +71,6 @@ The included [docker-compose.yaml](docker-compose.yaml) enables kubeconfig boots
That bootstrap is explicitly opt-in and defaults to off in the container itself, so it does not run in Kubernetes unless you deliberately enable it.
When both are available, the bootstrap kubeconfig is applied after the service-account kubeconfig and therefore takes precedence.
Start it with:
```bash
@ -117,7 +113,7 @@ If `${HOME}/.kube/config` is missing on the host, the container logs that bootst
```bash
docker run --rm \
-p 2222:2222 \
-p 2222:22 \
-p 3000:3000 \
-e ADMIN_SSH_PUBKEY="$(cat ~/.ssh/id_ed25519.pub)" \
-e USER_SSH_PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexample user@example" \
@ -136,7 +132,7 @@ Or in a browser at `http://localhost:3000/`.
```bash
docker run --rm \
-p 2222:2222 \
-p 2222:22 \
-p 3000:3000 \
-e ADMIN_PASSWORD='change-this-admin-password' \
-e USER_PASSWORD='change-this-user-password' \
@ -147,7 +143,7 @@ If that fails with a message like `unable to upgrade to tcp, received 500`, the
```bash
docker run -d --name k8s-mgmt-pod \
-p 2222:2222 \
-p 2222:22 \
-p 3000:3000 \
-e ADMIN_PASSWORD='change-this-admin-password' \
-e USER_PASSWORD='change-this-user-password' \
@ -160,7 +156,7 @@ If Docker reports `bind: address already in use`, change the host-side ports or
```bash
docker run --rm \
-p 127.0.0.1::2222 \
-p 127.0.0.1::22 \
-p 127.0.0.1::3000 \
-e ADMIN_PASSWORD='change-this-admin-password' \
-e USER_PASSWORD='change-this-user-password' \
@ -171,7 +167,7 @@ docker run --rm \
```bash
docker run --rm \
-p 2222:2222 \
-p 2222:22 \
-p 3000:3000 \
-e ADMIN_SSH_PUBKEY="$(cat ~/.ssh/id_ed25519.pub)" \
-e ADMIN_PASSWORD='change-this-admin-password' \
@ -188,7 +184,7 @@ If you omit both the public-key and password variables for a user, the container
```bash
docker run --rm \
-p 2222:2222 \
-p 2222:22 \
-p 3000:3000 \
-e ADMIN_SSH_PUBKEY="$(cat ~/.ssh/id_ed25519.pub)" \
k8s-mgmt-pod:local

View file

@ -6,7 +6,7 @@ services:
dockerfile: Dockerfile
container_name: k8s-mgmt-pod
ports:
- "${HOST_SSH_PORT:-2222}:2222"
- "${HOST_SSH_PORT:-2222}:22"
- "${HOST_WEBSSH_PORT:-3000}:3000"
environment:
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-change-this-admin-password}

View file

@ -1,12 +1,12 @@
╔════════════════════════════════════════════════════════════════╗
║ ║
_ __ ___ ____ __ __ ____ __ __ _____
| |/ / / _ \ / ___| | \/ | / ___|| \/ ||_ _|
| ' / | (_) |\___ \ | |\/| || | _ | |\/| | | |
| . \ \__, | ___) | | | | || |_| || | | | | |
|_|\_\ /_/ |____/ |_| |_| \____||_| |_| |_|
██╗ ███████╗██╗ ██╗ ██╗ ██╗ █████╗ ███████╗
██║ ██╔════╝██║ ██╔╝ ██║ ██╔╝██╔══██╗██╔════╝
██║ █████╗ █████╔╝ █████╔╝ ╚█████╔╝███████╗
██║ ██╔══╝ ██╔═██╗ ██╔═██╗ ██╔══██╗╚════██║
███████╗██║ ██║ ██╗ ██║ ██╗╚█████╔╝███████║
╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚════╝ ╚══════╝
║ Kubernetes Management Pod - Jump Box ║
║ ║
╠════════════════════════════════════════════════════════════════╣
@ -15,7 +15,7 @@
║ - lfk : LFK kubernetes management ║
║ - k9s : interactive cluster navigation ║
║ - helm : chart install, upgrade, and rollback ║
║ - plus : kubectx, kubens, jq, yq, vim, and more ║
║ - plus : kubectx, kubens, jq, yq, and more
║ ║
╠════════════════════════════════════════════════════════════════╣
║ Quick start ║

View file

@ -13,14 +13,6 @@ if [ -n "${BASH_VERSION:-}" ]; then
if [ -r /etc/bash_completion.d/helm ]; then
. /etc/bash_completion.d/helm
fi
if [ -r /etc/bash_completion.d/kubectx ]; then
. /etc/bash_completion.d/kubectx
fi
if [ -r /etc/bash_completion.d/kubens ]; then
. /etc/bash_completion.d/kubens
fi
fi
alias k=kubectl

View file

@ -1,3 +1,4 @@
Port 22
Protocol 2
PermitRootLogin no
PubkeyAuthentication yes

View file

@ -4,20 +4,12 @@ set -Eeuo pipefail
STATE_DIR="/var/lib/k8s-mgmt-pod"
GENERATED_PASSWORDS_FILE="${STATE_DIR}/generated-passwords.env"
SSH_DYNAMIC_CONFIG="/etc/ssh/sshd_config.d/20-k8s-mgmt-pod-auth.conf"
K8S_RUNTIME_ENV_PROFILE="/etc/profile.d/30-kubernetes-runtime-env.sh"
PASSWORD_AUTH_REQUIRED=0
SSHD_PID=""
WEBSSH2_PID=""
NGINX_PID=""
BOOTSTRAP_KUBECONFIG="${BOOTSTRAP_KUBECONFIG:-/bootstrap/kubeconfig/config}"
ENABLE_BOOTSTRAP_KUBECONFIG="${ENABLE_BOOTSTRAP_KUBECONFIG:-false}"
KUBERNETES_SECRETS_DIR="${KUBERNETES_SECRETS_DIR:-/var/run/kubernetes.io}"
SSH_PORT="${SSH_PORT:-2222}"
if [[ -z "${WEBSSH2_SSH_PORT:-}" ]]; then
WEBSSH2_SSH_PORT="${SSH_PORT}"
fi
export WEBSSH2_SSH_PORT
ensure_host_keys() {
if [[ ! -f "${STATE_DIR}/ssh_host_rsa_key" ]]; then
@ -78,8 +70,7 @@ store_generated_password() {
read_generated_password() {
local username="$1"
# Return an empty string if no entry exists; never fail under `set -euo pipefail`.
awk -F '=' -v username="${username}" '$1 == username { value = substr($0, index($0, "=") + 1) } END { if (value != "") print value }' "${GENERATED_PASSWORDS_FILE}"
grep -E "^${username}=" "${GENERATED_PASSWORDS_FILE}" | tail -n 1 | cut -d '=' -f 2-
}
write_authorized_keys() {
@ -98,87 +89,12 @@ write_authorized_keys() {
install_kubeconfig_for_user() {
local username="$1"
local source_kubeconfig="$2"
local home_dir="/home/${username}"
local kube_dir="${home_dir}/.kube"
local kube_config="${kube_dir}/config"
mkdir -p "${kube_dir}"
mkdir -p "${kube_dir}/cache"
chown -R "${username}:${username}" "${kube_dir}"
chmod 0700 "${kube_dir}"
install -m 0600 -o "${username}" -g "${username}" "${source_kubeconfig}" "${kube_config}"
}
resolve_kubernetes_secrets_dir() {
local configured_dir="${KUBERNETES_SECRETS_DIR}"
local fallback_dir="/var/run/secrets/kubernetes.io/serviceaccount"
if [[ -f "${configured_dir}/token" && -f "${configured_dir}/ca.crt" && -f "${configured_dir}/namespace" ]]; then
printf '%s\n' "${configured_dir}"
return 0
fi
if [[ "${configured_dir}" != "${fallback_dir}" ]] \
&& [[ -f "${fallback_dir}/token" && -f "${fallback_dir}/ca.crt" && -f "${fallback_dir}/namespace" ]]; then
printf '%s\n' "${fallback_dir}"
return 0
fi
return 1
}
install_serviceaccount_kubeconfig() {
local sa_dir=""
local token_file=""
local ca_file=""
local namespace_file=""
local namespace=""
local kubernetes_host="${KUBERNETES_SERVICE_HOST:-kubernetes.default.svc}"
local kubernetes_port="${KUBERNETES_SERVICE_PORT_HTTPS:-443}"
local server=""
local generated_kubeconfig="${STATE_DIR}/incluster.kubeconfig"
if ! sa_dir="$(resolve_kubernetes_secrets_dir)"; then
log "Skipping in-cluster kubeconfig generation because no service-account mount was found in ${KUBERNETES_SECRETS_DIR} or /var/run/secrets/kubernetes.io/serviceaccount."
return
fi
token_file="${sa_dir}/token"
ca_file="${sa_dir}/ca.crt"
namespace_file="${sa_dir}/namespace"
namespace="$(tr -d '\n' < "${namespace_file}")"
if [[ -z "${namespace}" ]]; then
namespace="default"
fi
server="https://${kubernetes_host}:${kubernetes_port}"
cat > "${generated_kubeconfig}" <<EOF
apiVersion: v1
kind: Config
clusters:
- name: in-cluster
cluster:
certificate-authority: ${ca_file}
server: ${server}
contexts:
- name: in-cluster
context:
cluster: in-cluster
user: service-account
namespace: ${namespace}
current-context: in-cluster
users:
- name: service-account
user:
tokenFile: ${token_file}
EOF
chmod 0600 "${generated_kubeconfig}"
install_kubeconfig_for_user admin "${generated_kubeconfig}"
install_kubeconfig_for_user user "${generated_kubeconfig}"
log "Installed generated in-cluster kubeconfig for admin and user from ${sa_dir}."
install -m 0600 -o "${username}" -g "${username}" "${BOOTSTRAP_KUBECONFIG}" "${kube_config}"
}
install_bootstrap_kubeconfig() {
@ -191,8 +107,8 @@ install_bootstrap_kubeconfig() {
return
fi
install_kubeconfig_for_user admin "${BOOTSTRAP_KUBECONFIG}"
install_kubeconfig_for_user user "${BOOTSTRAP_KUBECONFIG}"
install_kubeconfig_for_user admin
install_kubeconfig_for_user user
log "Installed mounted kubeconfig for admin and user."
}
@ -270,38 +186,15 @@ render_sshd_auth_config() {
fi
cat > "${SSH_DYNAMIC_CONFIG}" <<EOF
Port ${SSH_PORT}
PasswordAuthentication ${password_value}
KbdInteractiveAuthentication ${keyboard_interactive_value}
EOF
}
persist_kubernetes_login_env() {
local kubernetes_host="${KUBERNETES_SERVICE_HOST:-kubernetes.default.svc}"
local kubernetes_https_port="${KUBERNETES_SERVICE_PORT_HTTPS:-443}"
local kubernetes_port="${KUBERNETES_SERVICE_PORT:-${kubernetes_https_port}}"
cat > "${K8S_RUNTIME_ENV_PROFILE}" <<EOF
# Generated at container start so SSH login shells see Kubernetes API environment values.
export KUBERNETES_SERVICE_HOST='${kubernetes_host}'
export KUBERNETES_SERVICE_PORT='${kubernetes_port}'
export KUBERNETES_SERVICE_PORT_HTTPS='${kubernetes_https_port}'
EOF
chmod 0644 "${K8S_RUNTIME_ENV_PROFILE}"
}
prepare_runtime() {
mkdir -p /var/run/sshd
ensure_host_keys
if [[ "${ENABLE_BOOTSTRAP_KUBECONFIG}" == "true" ]]; then
log "Kubeconfig mode: bootstrap-only (serviceaccount kubeconfig generation disabled)."
install_bootstrap_kubeconfig
else
log "Kubeconfig mode: in-cluster serviceaccount."
install_serviceaccount_kubeconfig
fi
persist_kubernetes_login_env
configure_user_auth admin ADMIN_SSH_PUBKEY ADMIN_PASSWORD
configure_user_auth user USER_SSH_PUBKEY USER_PASSWORD
render_sshd_auth_config
@ -318,7 +211,7 @@ start_services() {
nginx -g 'daemon off;' &
NGINX_PID=$!
log "sshd started on port ${SSH_PORT}."
log "sshd started on port 22."
log "WebSSH2 started on port ${WEBSSH2_LISTEN_PORT}."
log "nginx redirect/proxy started on port ${WEB_SSH_PORT}."

View file

@ -7,7 +7,6 @@ These manifests deploy `k8s-mgmt-pod` as a single-replica bastion deployment ins
1. Build and publish the image.
2. Replace the placeholder image in `deployment.yaml` with a pinned tag or digest.
3. Create the real `k8s-mgmt-pod-auth` Secret instead of applying `secret.yaml.example`.
4. The pod state directory is now backed by a PVC, so SSH host keys and generated fallback passwords survive pod recreation until you delete the claim.
## Create the Secret
@ -63,7 +62,7 @@ If you prefer individual files, apply `namespace.yaml`, `serviceaccount.yaml`, `
Port-forward the service instead of exposing it externally by default:
```bash
kubectl -n k8s-mgmt-pod port-forward svc/k8s-mgmt-pod 2222:2222 3000:3000
kubectl -n k8s-mgmt-pod port-forward svc/k8s-mgmt-pod 2222:22 3000:3000
```
Then connect with:

View file

@ -16,24 +16,20 @@ spec:
spec:
serviceAccountName: k8s-mgmt-pod
automountServiceAccountToken: true
securityContext:
seccompProfile:
type: RuntimeDefault
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
containers:
- name: k8s-mgmt-pod
image: git.alcatrash.net/michael/k8s-mgmt-pod/k8s-mgmt-pod:latest
imagePullPolicy: Always
image: git.alcatrash.net/michael/k8s-mgmt-pod/k8s-mgmt-pod:v1.0.0
imagePullPolicy: IfNotPresent
ports:
- name: ssh
containerPort: 2222
containerPort: 22
protocol: TCP
- name: webssh
containerPort: 3000
protocol: TCP
env:
- name: ADMIN_SSH_PUBKEY
valueFrom:
@ -59,7 +55,6 @@ spec:
name: k8s-mgmt-pod-auth
key: USER_PASSWORD
optional: true
resources:
requests:
cpu: 100m
@ -67,42 +62,30 @@ spec:
limits:
cpu: 500m
memory: 512Mi
readinessProbe:
tcpSocket:
port: 2222
port: 22
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 2222
port: 22
initialDelaySeconds: 15
periodSeconds: 20
volumeMounts:
- name: state
mountPath: /var/lib/k8s-mgmt-pod
securityContext:
# sshd still runs as root here because it needs to bind port 22 and switch to the authenticated user session.
# The tradeoff is deliberate: keep the container functional, then narrow capabilities instead of forcing a fragile rootless sshd setup.
runAsUser: 0
runAsGroup: 0
runAsNonRoot: false
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
capabilities:
drop:
- ALL
add:
- AUDIT_WRITE
- CHOWN
- DAC_OVERRIDE
- FOWNER
- SETGID
- SETUID
- SYS_CHROOT
drop: ["ALL"]
add: ["CHOWN", "DAC_OVERRIDE", "FOWNER", "NET_BIND_SERVICE", "SETGID", "SETUID"]
volumes:
- name: state
persistentVolumeClaim:
claimName: k8s-mgmt-pod-state
emptyDir: {}

View file

@ -5,7 +5,6 @@ resources:
- namespace.yaml
- serviceaccount.yaml
- rbac.yaml
- pvc.yaml
- deployment.yaml
- service.yaml
- networkpolicy.yaml

View file

@ -19,6 +19,6 @@ spec:
k8s-mgmt-pod-access: "true"
ports:
- protocol: TCP
port: 2222
port: 22
- protocol: TCP
port: 3000

View file

@ -1,10 +0,0 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: k8s-mgmt-pod-state
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi

View file

@ -1,189 +1,49 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
kind: Role
metadata:
name: k8s-mgmt-pod
rules:
# This is intentionally broader than the strict minimum so lfk and kubectl are usable.
# Scope it down to the smallest verb and resource set your operators actually need.
- apiGroups: [""]
resources:
- configmaps
- endpoints
- events
- limitranges
- namespaces
- nodes
- persistentvolumeclaims
- persistentvolumes
- pods
- pods/exec
- pods/log
- pods/portforward
- pods/proxy
- replicationcontrollers
- replicationcontrollers/scale
- resourcequotas
- secrets
- serviceaccounts
- services
- services/proxy
verbs: ["*"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["apps"]
resources:
- controllerrevisions
- daemonsets
- deployments
- deployments/scale
- replicasets
- replicasets/scale
- statefulsets
- statefulsets/scale
verbs: ["*"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["batch"]
resources:
- cronjobs
- jobs
verbs: ["*"]
- apiGroups: ["autoscaling"]
resources:
- horizontalpodautoscalers
verbs: ["*"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["networking.k8s.io"]
resources:
- ingressclasses
- ingresses
verbs: ["*"]
- apiGroups: ["extensions"]
resources:
- ingresses
verbs: ["*"]
- apiGroups: ["policy"]
resources:
- poddisruptionbudgets
verbs: ["*"]
- apiGroups: ["coordination.k8s.io"]
resources:
- leases
verbs: ["*"]
- apiGroups: ["storage.k8s.io"]
resources:
- csidrivers
- csinodes
- csistoragecapacities
- storageclasses
- volumeattachments
verbs: ["*"]
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
verbs: ["*"]
- apiGroups: ["admissionregistration.k8s.io"]
resources:
- mutatingadmissionpolicies
- mutatingwebhookconfigurations
- validatingadmissionpolicies
- validatingwebhookconfigurations
verbs: ["*"]
- apiGroups: ["metrics.k8s.io"]
resources:
- nodes
- pods
verbs: ["get", "list", "watch"]
- apiGroups: ["gateway.networking.k8s.io"]
resources:
- gatewayclasses
- gateways
- httproutes
- referencegrants
- tcproutes
- tlsroutes
- udproutes
verbs: ["*"]
- apiGroups: ["cert-manager.io"]
resources:
- certificates
- certificaterequests
- clusterissuers
- issuers
verbs: ["*"]
- apiGroups: ["monitoring.coreos.com"]
resources:
- alertmanagers
- podmonitors
- prometheuses
- prometheusrules
- servicemonitors
- thanosrulers
verbs: ["*"]
- apiGroups: ["argoproj.io"]
resources:
- applications
- appprojects
verbs: ["*"]
- apiGroups: ["traefik.containo.us", "traefik.io"]
resources:
- ingressroutes
- middlewares
- traefikservices
verbs: ["*"]
- apiGroups: ["k8s.cni.cncf.io"]
resources:
- network-attachment-definitions
verbs: ["*"]
- apiGroups: ["kubevirt.io"]
resources:
- virtualmachineinstances
- virtualmachines
verbs: ["*"]
- apiGroups: ["subresources.kubevirt.io"]
resources:
- "*"
verbs: ["*"]
- apiGroups: ["instancetype.kubevirt.io"]
resources:
- "*"
verbs: ["*"]
- apiGroups: ["cdi.kubevirt.io"]
resources:
- "*"
verbs: ["*"]
- apiGroups: ["pool.kubevirt.io"]
resources:
- "*"
verbs: ["*"]
- apiGroups: ["cluster.x-k8s.io"]
resources:
- clusters
- machinedeployments
- machinepools
- machines
- machinesets
verbs: ["*"]
- apiGroups: ["controlplane.cluster.x-k8s.io"]
resources:
- kubeadmcontrolplanes
verbs: ["*"]
- apiGroups: ["bootstrap.cluster.x-k8s.io"]
resources:
- kubeadmconfigs
- kubeadmconfigtemplates
verbs: ["*"]
- apiGroups: ["infrastructure.cluster.x-k8s.io"]
resources:
- kubevirtclusters
- kubevirtmachinetemplates
verbs: ["*"]
- apiGroups: ["addons.cluster.x-k8s.io"]
resources:
- clusterresourcesets
verbs: ["*"]
- networkpolicies
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
kind: RoleBinding
metadata:
name: k8s-mgmt-pod-access
name: k8s-mgmt-pod
subjects:
- kind: ServiceAccount
name: k8s-mgmt-pod
namespace: k8s-mgmt-pod
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
kind: Role
name: k8s-mgmt-pod

View file

@ -8,7 +8,7 @@ spec:
app.kubernetes.io/name: k8s-mgmt-pod
ports:
- name: ssh
port: 2222
port: 22
targetPort: ssh
protocol: TCP
- name: webssh
@ -27,7 +27,7 @@ spec:
# app.kubernetes.io/name: k8s-mgmt-pod
# ports:
# - name: ssh
# port: 2222
# port: 22
# targetPort: ssh
# - name: webssh
# port: 3000

View file

@ -1,16 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
],
"customManagers": [
{
"customType": "regex",
"managerFilePatterns": ["/^Dockerfile$/", "/Dockerfile.*/"],
"matchStrings": [
"# renovate: datasource=(?<datasource>.*?) depName=(?<depName>.*?)\\s+ARG .*?_VERSION=(?<currentValue>.*)\\s"
],
"datasourceTemplate": "{{{datasource}}}"
}
]
}