mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-21 09:58:46 +08:00
feat(ql3): add opt-in security administration job
This commit is contained in:
@@ -76,6 +76,18 @@ command schemas and operator procedure are documented in
|
||||
response-loss behavior and remaining gates are frozen in
|
||||
[`ADR-0500`](../../../docs/adr/ADR-0500-short-lived-cluster-security-administration-command.md).
|
||||
|
||||
An opt-in one-shot Job is available under
|
||||
[`operations/security-administration`](./operations/security-administration).
|
||||
It is deliberately absent from the shared operations Kustomization. Select
|
||||
`base` or `cloudnative-pg`; select a credential-delivery variant only for
|
||||
issue/rotate after provisioning a private encrypted RWO PVC. A non-root init
|
||||
container copies the kubelet symlink projection into a `0700` memory-backed
|
||||
directory with `0600` files before the administrator starts. The Job has no
|
||||
Kubernetes API token or RBAC, does not retry, and retains the one-connection
|
||||
database ceiling. The exact serial dispatch and cleanup procedure is in the
|
||||
operator guide above; production remains gated on the ADR-0501 live K3s,
|
||||
PostgreSQL and PVC ceremony.
|
||||
|
||||
Workstation operators may pass an explicit owner-private context to reuse only
|
||||
stable client paths:
|
||||
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: ql3-security-administration
|
||||
namespace: qinglong3-system
|
||||
labels:
|
||||
app.kubernetes.io/name: ql3-security-administration
|
||||
app.kubernetes.io/component: security-administration
|
||||
app.kubernetes.io/part-of: qinglong3
|
||||
qinglong.io/execution-model: caller-driven
|
||||
spec:
|
||||
backoffLimit: 0
|
||||
activeDeadlineSeconds: 300
|
||||
ttlSecondsAfterFinished: 600
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: ql3-security-administration
|
||||
app.kubernetes.io/component: security-administration
|
||||
app.kubernetes.io/part-of: qinglong3
|
||||
qinglong.io/execution-model: caller-driven
|
||||
spec:
|
||||
serviceAccountName: ql3-security-administration
|
||||
automountServiceAccountToken: false
|
||||
enableServiceLinks: false
|
||||
restartPolicy: Never
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 10001
|
||||
runAsGroup: 10001
|
||||
fsGroup: 10001
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
initContainers:
|
||||
- name: stage-private-input
|
||||
image: qinglong3-cluster-admin:3.0.0-alpha.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- node
|
||||
- /opt/qinglong/node_modules/@qinglong/cluster-admin/dist/security-administration/clusterAdministrationKubernetesInputStageCli.js
|
||||
args:
|
||||
- --source=/var/run/secrets/qinglong3/security-administration-projected
|
||||
- --target=/var/run/qinglong3/security-administration-private/input
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
resources:
|
||||
requests:
|
||||
cpu: 25m
|
||||
memory: 48Mi
|
||||
limits:
|
||||
cpu: 250m
|
||||
memory: 128Mi
|
||||
volumeMounts:
|
||||
- name: projected-input
|
||||
mountPath: /var/run/secrets/qinglong3/security-administration-projected
|
||||
readOnly: true
|
||||
- name: private-input
|
||||
mountPath: /var/run/qinglong3/security-administration-private
|
||||
containers:
|
||||
- name: administrator
|
||||
image: qinglong3-cluster-admin:3.0.0-alpha.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- node
|
||||
- /opt/qinglong/node_modules/@qinglong/cluster-admin/dist/security-administration/clusterAdministrationCli.js
|
||||
args:
|
||||
- --command=/var/run/qinglong3/security-administration-private/input/command.json
|
||||
- --assertion=/var/run/qinglong3/security-administration-private/input/assertion.jwt
|
||||
- --keyset=/var/run/qinglong3/security-administration-private/input/keyset.json
|
||||
- --pepper=/var/run/qinglong3/security-administration-private/input/pepper
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
env:
|
||||
- name: QL3_POSTGRES_ADMIN_TLS_MODE
|
||||
value: verify-full
|
||||
- name: QL3_POSTGRES_ADMIN_TLS_CA_FILE
|
||||
value: /var/run/secrets/qinglong3/postgres-security-administration/ca.crt
|
||||
- name: QL3_POSTGRES_ADMIN_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: ql3-security-administration-database
|
||||
key: postgres-admin-url
|
||||
- name: QL3_POSTGRES_ADMIN_TLS_SERVERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: ql3-security-administration-database
|
||||
key: postgres-tls-servername
|
||||
resources:
|
||||
requests:
|
||||
cpu: 25m
|
||||
memory: 48Mi
|
||||
limits:
|
||||
cpu: 250m
|
||||
memory: 128Mi
|
||||
volumeMounts:
|
||||
- name: private-input
|
||||
mountPath: /var/run/qinglong3/security-administration-private
|
||||
readOnly: true
|
||||
- name: postgres-ca
|
||||
mountPath: /var/run/secrets/qinglong3/postgres-security-administration
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: projected-input
|
||||
secret:
|
||||
secretName: ql3-security-administration-input
|
||||
defaultMode: 288
|
||||
items:
|
||||
- key: command.json
|
||||
path: command.json
|
||||
- key: assertion.jwt
|
||||
path: assertion.jwt
|
||||
- key: keyset.json
|
||||
path: keyset.json
|
||||
- key: pepper
|
||||
path: pepper
|
||||
- name: private-input
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
sizeLimit: 1Mi
|
||||
- name: postgres-ca
|
||||
secret:
|
||||
secretName: ql3-security-administration-database
|
||||
defaultMode: 292
|
||||
items:
|
||||
- key: postgres-ca.crt
|
||||
path: ca.crt
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- service-account.yaml
|
||||
- job.yaml
|
||||
- network-policy.yaml
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: ql3-security-administration
|
||||
namespace: qinglong3-system
|
||||
labels:
|
||||
app.kubernetes.io/name: ql3-security-administration
|
||||
app.kubernetes.io/component: security-administration
|
||||
app.kubernetes.io/part-of: qinglong3
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: ql3-security-administration
|
||||
app.kubernetes.io/component: security-administration
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress: []
|
||||
egress:
|
||||
- to:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: kube-system
|
||||
podSelector:
|
||||
matchLabels:
|
||||
k8s-app: kube-dns
|
||||
ports:
|
||||
- protocol: UDP
|
||||
port: 53
|
||||
- protocol: TCP
|
||||
port: 53
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: ql3-security-administration
|
||||
namespace: qinglong3-system
|
||||
labels:
|
||||
app.kubernetes.io/name: ql3-security-administration
|
||||
app.kubernetes.io/component: security-administration
|
||||
app.kubernetes.io/part-of: qinglong3
|
||||
automountServiceAccountToken: false
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../cloudnative-pg
|
||||
|
||||
components:
|
||||
- ../credential-delivery/component
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/env
|
||||
value:
|
||||
- name: QL3_POSTGRES_ADMIN_TLS_MODE
|
||||
value: verify-full
|
||||
- name: QL3_POSTGRES_ADMIN_TLS_CA_FILE
|
||||
value: /var/run/secrets/qinglong3/postgres-security-administration/ca.crt
|
||||
- name: QL3_POSTGRES_ADMIN_HOST
|
||||
value: ql3-postgres-rw.qinglong3-system.svc
|
||||
- name: QL3_POSTGRES_ADMIN_PORT
|
||||
value: '5432'
|
||||
- name: QL3_POSTGRES_ADMIN_DATABASE
|
||||
value: qinglong
|
||||
- name: QL3_POSTGRES_ADMIN_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: ql3-postgres-admin-auth
|
||||
key: username
|
||||
- name: QL3_POSTGRES_ADMIN_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: ql3-postgres-admin-auth
|
||||
key: password
|
||||
- name: QL3_POSTGRES_ADMIN_TLS_SERVERNAME
|
||||
value: ql3-postgres-rw.qinglong3-system.svc
|
||||
- op: replace
|
||||
path: /spec/template/spec/volumes/2/secret/secretName
|
||||
value: ql3-postgres-ca
|
||||
- op: replace
|
||||
path: /spec/template/spec/volumes/2/secret/items/0/key
|
||||
value: ca.crt
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../base
|
||||
|
||||
patches:
|
||||
- path: job-patch.yaml
|
||||
target:
|
||||
group: batch
|
||||
version: v1
|
||||
kind: Job
|
||||
name: ql3-security-administration
|
||||
- path: network-policy-patch.yaml
|
||||
target:
|
||||
group: networking.k8s.io
|
||||
version: v1
|
||||
kind: NetworkPolicy
|
||||
name: ql3-security-administration
|
||||
|
||||
images:
|
||||
- name: qinglong3-cluster-admin
|
||||
newName: registry.example.com/qinglong/qinglong3-cluster-admin
|
||||
digest: sha256:0000000000000000000000000000000000000000000000000000000000000000
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: ql3-security-administration
|
||||
namespace: qinglong3-system
|
||||
spec:
|
||||
egress:
|
||||
- to:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: kube-system
|
||||
podSelector:
|
||||
matchLabels:
|
||||
k8s-app: kube-dns
|
||||
ports:
|
||||
- protocol: UDP
|
||||
port: 53
|
||||
- protocol: TCP
|
||||
port: 53
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
cnpg.io/cluster: ql3-postgres
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 5432
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
- op: add
|
||||
path: /spec/template/spec/initContainers/0/args/-
|
||||
value: --delivery-directory=/var/lib/qinglong3/security-administration-delivery/private
|
||||
- op: add
|
||||
path: /spec/template/spec/initContainers/0/volumeMounts/-
|
||||
value:
|
||||
name: credential-delivery
|
||||
mountPath: /var/lib/qinglong3/security-administration-delivery
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/args/-
|
||||
value: --delivery=/var/lib/qinglong3/security-administration-delivery/private/replace-with-unique-delivery.json
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts/-
|
||||
value:
|
||||
name: credential-delivery
|
||||
mountPath: /var/lib/qinglong3/security-administration-delivery
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes/-
|
||||
value:
|
||||
name: credential-delivery
|
||||
persistentVolumeClaim:
|
||||
claimName: ql3-security-administration-delivery
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||
kind: Component
|
||||
|
||||
patches:
|
||||
- path: job-patch.yaml
|
||||
target:
|
||||
group: batch
|
||||
version: v1
|
||||
kind: Job
|
||||
name: ql3-security-administration
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../base
|
||||
|
||||
components:
|
||||
- component
|
||||
|
||||
images:
|
||||
- name: qinglong3-cluster-admin
|
||||
newName: registry.example.com/qinglong/qinglong3-cluster-admin
|
||||
digest: sha256:0000000000000000000000000000000000000000000000000000000000000000
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
# Generic PostgreSQL example only. CloudNativePG users do not need this Secret.
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: ql3-security-administration-database
|
||||
namespace: qinglong3-system
|
||||
type: Opaque
|
||||
immutable: true
|
||||
stringData:
|
||||
postgres-admin-url: postgresql://ql3_admin:REPLACE@postgres.example.test:5432/qinglong
|
||||
postgres-tls-servername: postgres.example.test
|
||||
postgres-ca.crt: REPLACE_WITH_POSTGRES_CA_CERTIFICATE
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
# Example only. Use an encrypted, access-controlled StorageClass and a fresh PVC.
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: ql3-security-administration-delivery
|
||||
namespace: qinglong3-system
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 16Mi
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
# Example only. Create a private per-dispatch Secret; never commit real values.
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: ql3-security-administration-input
|
||||
namespace: qinglong3-system
|
||||
type: Opaque
|
||||
immutable: true
|
||||
stringData:
|
||||
command.json: |
|
||||
{"schemaVersion":1,"operation":"audit.list","request":{"limit":25,"filter":{"outcome":"allowed"}}}
|
||||
assertion.jwt: REPLACE_WITH_SHORT_LIVED_MULTI_FACTOR_ASSERTION
|
||||
keyset.json: REPLACE_WITH_PINNED_SECURITY_ADMINISTRATION_KEYSET
|
||||
pepper: REPLACE_WITH_CANONICAL_32_BYTE_BASE64URL_API_CREDENTIAL_PEPPER
|
||||
Reference in New Issue
Block a user