init: 아르고cd, vault 기반 인프라 설계
This commit is contained in:
@@ -0,0 +1,97 @@
|
|||||||
|
# Agent Guide
|
||||||
|
|
||||||
|
이 파일은 이 저장소에서 작업을 시작하는 사람과 에이전트를 위한 첫 진입 문서입니다.
|
||||||
|
|
||||||
|
## Read First
|
||||||
|
|
||||||
|
작업을 시작하면 아래 순서로 문서를 읽습니다.
|
||||||
|
|
||||||
|
1. 이 파일 `AGENT.md`
|
||||||
|
2. 루트 [README.md](/home/donghyeon/dev/Project-Auth-GitOps/README.md)
|
||||||
|
3. 현재 작업과 직접 관련된 runbook
|
||||||
|
- Vault transit: [runbooks/vault-transit/dev/README.md](/home/donghyeon/dev/Project-Auth-GitOps/runbooks/vault-transit/dev/README.md)
|
||||||
|
- Workload Vault: [runbooks/vault/dev/README.md](/home/donghyeon/dev/Project-Auth-GitOps/runbooks/vault/dev/README.md)
|
||||||
|
- Argo CD 구조: [argocd/README.md](/home/donghyeon/dev/Project-Auth-GitOps/argocd/README.md)
|
||||||
|
|
||||||
|
## Working Rules
|
||||||
|
|
||||||
|
- README 최상단 `현재 최신 Dev 아키텍처` 는 최신 상태로 유지합니다.
|
||||||
|
- 기존 cycle은 지우지 말고 README 맨 아래에 새 cycle을 추가합니다.
|
||||||
|
- ops 변경이나 장애 대응을 했으면 명령, 관찰, 판단 근거, 수정, 검증을 함께 남깁니다.
|
||||||
|
- 워크플로 구조를 크게 바꿨으면 README에 새 cycle을 추가합니다.
|
||||||
|
- 민감한 값은 절대 문서에 기록하지 않습니다.
|
||||||
|
- token, password, kubeconfig 본문, secret payload 금지
|
||||||
|
- 대신 존재 여부, 길이, secret name, 리소스 상태만 기록
|
||||||
|
- repo 밖 임시 파일(`/tmp/...`)로 작업한 secret manifest는 Git에 넣지 않습니다.
|
||||||
|
- Vault 관련 자동화는 **bootstrap** 과 **reconcile** 을 분리합니다.
|
||||||
|
- bootstrap: privileged token 필요, 수동 runbook
|
||||||
|
- reconcile: workflow AppRole 기반 routine CI
|
||||||
|
- GitHub Actions YAML에는 긴 Bash를 직접 넣지 않고 `scripts/ci/*.sh` wrapper로 분리합니다.
|
||||||
|
- GitHub context(`inputs`, `client_payload`) 는 inline Bash에서 직접 쓰지 않고 step `env:` 로 매핑한 뒤 스크립트에서 읽습니다.
|
||||||
|
- `scripts/ci/reconcile-vault-dev.sh` 는 기본적으로 port-forward 모드지만, 장기적으로는 `RECONCILE_USE_PORT_FORWARD=false` + in-cluster service URL로 돌리는 방향이 목표입니다.
|
||||||
|
- `vault-dev-reconcile.yaml` 은 아래 GitHub Variables 로 runner/네트워크 전환을 제어합니다.
|
||||||
|
- `VAULT_DEV_RECONCILE_RUNS_ON`
|
||||||
|
- `RECONCILE_USE_PORT_FORWARD`
|
||||||
|
- `TRANSIT_VAULT_ADDR`
|
||||||
|
- `WORKLOAD_VAULT_ADDR`
|
||||||
|
|
||||||
|
## Troubleshooting Format
|
||||||
|
|
||||||
|
README cycle의 `### 6. 트러블슈팅 메모` 에 아래 형식으로 남깁니다.
|
||||||
|
|
||||||
|
- 재현/확인 명령: 실제로 사용한 명령
|
||||||
|
- 핵심 관찰값: 에러 문구, 상태 변화, 이벤트, 로그 핵심
|
||||||
|
- 판단 근거: 왜 그 관찰값을 보고 해당 원인이라고 판단했는지
|
||||||
|
- 수정 또는 조치: 어떤 파일/리소스를 바꿨는지
|
||||||
|
- 검증 명령: 해결 여부를 다시 확인한 명령
|
||||||
|
|
||||||
|
## Current Dev Pitfalls
|
||||||
|
|
||||||
|
- Argo CD `Application` 이 `Repository not found` 를 내면 로컬 git 인증이 아니라 `argocd` namespace의 repo credential secret부터 확인합니다.
|
||||||
|
- self-hosted runner 문제는 workflow YAML보다 먼저 runner 호스트의 실제 CLI 설치 여부를 확인합니다.
|
||||||
|
- `command -v kubectl vault jq base64 curl terraform`
|
||||||
|
- Vault raft 사용 시 `api_addr`, `cluster_addr`, listener `cluster_address`, service/deployment의 `8201` 포트 일관성을 먼저 확인합니다.
|
||||||
|
- `hashicorp/vault` 이미지를 ConfigMap mount와 함께 쓸 때는 read-only mount 충돌과 단일 PVC rollout 충돌을 같이 봅니다.
|
||||||
|
- 필요하면 `/tmp` 로 config 복사 후 실행, `strategy: Recreate` 적용
|
||||||
|
- Vault Agent template에 여러 `export` 줄을 렌더링할 때는 aggressive trim(`{{- ... -}}`) 때문에 줄바꿈이 붙지 않는지 실제 `/vault/secrets/*` 파일을 확인합니다.
|
||||||
|
- Postgres PVC를 유지하는 상태에서 Vault KV만 바꾸면 DB 내부 사용자 비밀번호와 주입값이 어긋날 수 있습니다. KV 값과 persisted DB state를 함께 확인합니다.
|
||||||
|
- Headless Service를 DB connection host로 쓸 때는 pod 안에서 실제로 어떤 이름이 해석되는지 먼저 확인합니다.
|
||||||
|
- `postgres.platform.svc.cluster.local` 이 안 되면 `postgres-0.postgres.platform.svc.cluster.local` 같이 pod FQDN 확인
|
||||||
|
- CI에서 Terraform local backend를 쓰면 self-hosted runner가 기존 `.terraform-state/*.tfstate` 를 실제로 보고 있는지 먼저 확인합니다. state가 완전히 없을 때뿐 아니라 일부 리소스만 남은 partial state도 위험합니다.
|
||||||
|
- `terraform state list`
|
||||||
|
- `terraform state show <resource>`
|
||||||
|
- workflow에서 빠진 리소스를 개별 import 하도록 유지
|
||||||
|
- 단, `vault_approle_auth_backend_role_secret_id` 처럼 provider가 import를 지원하지 않는 리소스는 예외로 두고 재생성으로 수렴시킵니다.
|
||||||
|
- Vault KV-v2 mount는 provider import 결과가 `type=kv` + `options.version=2` 로 보이므로, 선언도 그 형태로 맞추고 `prevent_destroy = true` 를 유지합니다.
|
||||||
|
- seal token을 state로 다시 맞출 때는 `auth/token/revoke-accessor` 권한이 필요합니다.
|
||||||
|
- `vault_mount`, `vault_auth_backend`, `vault_token.seal` 같이 bootstrap 성격이 강한 리소스는 routine CI에서 replacement가 나지 않게 drift를 최소화합니다.
|
||||||
|
- 필요하면 `ignore_changes`
|
||||||
|
- 더 좋게는 bootstrap 단계와 reconcile 단계를 분리
|
||||||
|
- `kubectl rollout status` 실패 시 `describe`, `logs`, `events` 를 세트로 봅니다.
|
||||||
|
|
||||||
|
## Default Command Order
|
||||||
|
|
||||||
|
Argo CD app 문제:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n argocd get applications
|
||||||
|
kubectl -n argocd describe application <name>
|
||||||
|
kubectl -n argocd get secrets
|
||||||
|
```
|
||||||
|
|
||||||
|
Runner 문제:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
command -v kubectl
|
||||||
|
command -v vault
|
||||||
|
command -v terraform
|
||||||
|
```
|
||||||
|
|
||||||
|
Vault pod 문제:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n <ns> get deploy,pods
|
||||||
|
kubectl -n <ns> describe deployment <name>
|
||||||
|
kubectl -n <ns> logs deploy/<name> --tail=200
|
||||||
|
kubectl -n <ns> get events --sort-by=.lastTimestamp | tail -n 30
|
||||||
|
```
|
||||||
+3044
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,69 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: api-server
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: api-server
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: api-server
|
||||||
|
spec:
|
||||||
|
serviceAccountName: api-server
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 10001
|
||||||
|
runAsGroup: 10001
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
containers:
|
||||||
|
- name: api-server
|
||||||
|
image: ghcr.io/donghyeonka/project-api-server
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- containerPort: 8082
|
||||||
|
name: http
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: api-server-config
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: false
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 250m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 512Mi
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /actuator/health/readiness
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 3
|
||||||
|
periodSeconds: 10
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /actuator/health/liveness
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 5
|
||||||
|
periodSeconds: 15
|
||||||
|
startupProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /actuator/health/liveness
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
timeoutSeconds: 3
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 12
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- serviceaccount.yaml
|
||||||
|
- service.yaml
|
||||||
|
- deployment.yaml
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: api-server
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: api-server
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: 8082
|
||||||
|
type: ClusterIP
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: api-server
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: ghcr-regcred
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: api-server-config
|
||||||
|
data:
|
||||||
|
APP_SERVER_PORT: "8082"
|
||||||
|
APP_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI: http://auth-public.auth-dev.svc.cluster.local
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
apiVersion: bitnami.com/v1alpha1
|
||||||
|
kind: SealedSecret
|
||||||
|
metadata:
|
||||||
|
name: ghcr-regcred
|
||||||
|
namespace: api-dev
|
||||||
|
spec:
|
||||||
|
encryptedData:
|
||||||
|
.dockerconfigjson: AgC7O6nq0aej7pxKXYyJy01HomK4s4jqkrwJ2iiVqjWrv4LjMqYY/8XiPnv7eyOAhBlpnSjULZ0pNPnQjUh6TUkcfbV0VOXjha6qkFIRZXLTlySvooS4FJH3lGjYBlli5bDfVw2KZTy9zR3qcpclOVJo5eEGJ+3rrl6NCUV7CzXfhpMsdATXtDRK1reSlpS2qWgLYJ8Dt0mdaz9yt1baGC3PwjeohnbmeCxRDi8HWOgWTXj0NqBtnpHnzQz5dox5NduQQCDh4ZrP7XK4CgeC3OIuTy1BokpTD5xfN3e0apiiZcUKQCN2I4NJ+B/JqgxceLxVXl3kYswlH+MjkzuejB3OPcGJsfQAs3gJUPB460mzT2S21xm4GloqL73utz+JuyE4pmCuPbFzgaJFNEamtAWtwZRiUwpjBG0HHLg2JPuLc07ljzfSiO9IqOA2zFmgYTX1dLdhrgSzIO6jaWFvctKTqavPxTRHNjBG9as+9gbQ7caH7vcV4k7q7XyEWpeEv9rCyVWcuRvZ7QNkHU1ss44uimr5I43JkEnsmacFRanxIlB80t357iGNiGNGCJFgfiVnh1PqmPlCvEtA42iTt+++2aU+x1SmiS4LYEs4YowVmanm0t1dBWSOMC7y6kM91W/fGPEo5i0lWbdvDKFuNS8RAWu4mXTgLjgbWz9a5PMcdioh0JMxV78FkDkU1jte/hFeIMOmA/xwrzIXVu7JTJK5a+6A9Dmhjpuiunv1nhDsxg1okPjiJ7W4T2pc0JpU+7XjhsXipE0FCwiNxwsh0GvI5MFGmipQwKbcSJuQJrXqAbTZZyDpa+0rUyc9YhYxAgxKf8AzxffMgDKm68MuS8KVdvIhC0dKUOccRnmrSYN8GMJSlZE065MOjY5FGsVfPRPHMYLhQnkNQPXSDB34UXl97mrUIz6mR3mnZar0PKqm9d5vZ19ujIwV7ZQEar8Sf6ZbT8n25hLUmq6JkGzsRiHo42S2JoVl1QlHgzQbv6i/JPsjzQcKfVhtAIXiyMIMvsbYLCjX9df6yVU3e0pCBVl3sGSMbOf4/QVrJtCqog==
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
name: ghcr-regcred
|
||||||
|
namespace: api-dev
|
||||||
|
type: kubernetes.io/dockerconfigjson
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: api-server
|
||||||
|
annotations:
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik
|
||||||
|
rules:
|
||||||
|
- host: api-public.api-dev.svc.cluster.local
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: api-server
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: api-dev
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- ../../base
|
||||||
|
- namespace.yaml
|
||||||
|
- configmap.yaml
|
||||||
|
- ingress.yaml
|
||||||
|
- public-access.yaml
|
||||||
|
- networkpolicy.yaml
|
||||||
|
- ghcr-regcred.sealedsecret.yaml
|
||||||
|
|
||||||
|
generatorOptions:
|
||||||
|
disableNameSuffixHash: true
|
||||||
|
|
||||||
|
images:
|
||||||
|
- name: ghcr.io/donghyeonka/project-api-server
|
||||||
|
newName: ghcr.io/donghyeonka/project-api-server
|
||||||
|
newTag: fd097c9
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: api-dev
|
||||||
|
labels:
|
||||||
|
pod-security.kubernetes.io/enforce: baseline
|
||||||
|
pod-security.kubernetes.io/enforce-version: latest
|
||||||
|
pod-security.kubernetes.io/warn: restricted
|
||||||
|
pod-security.kubernetes.io/warn-version: latest
|
||||||
|
pod-security.kubernetes.io/audit: restricted
|
||||||
|
pod-security.kubernetes.io/audit-version: latest
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: api-dev-default-deny
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: api-dev-allow-dns-egress
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
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
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: api-dev-allow-public-egress
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: api-server
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: kube-system
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: traefik
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8000
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: api-dev-allow-ingress-from-traefik
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: api-server
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: kube-system
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: traefik
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8082
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: api-public
|
||||||
|
spec:
|
||||||
|
type: ExternalName
|
||||||
|
externalName: traefik.kube-system.svc.cluster.local
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: api-prod
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- ../../base
|
||||||
|
- namespace.yaml
|
||||||
|
|
||||||
|
images:
|
||||||
|
- name: ghcr.io/donghyeonka/project-api-server
|
||||||
|
newName: ghcr.io/donghyeonka/project-api-server
|
||||||
|
newTag: fd097c9
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: api-prod
|
||||||
|
labels:
|
||||||
|
pod-security.kubernetes.io/enforce: baseline
|
||||||
|
pod-security.kubernetes.io/enforce-version: latest
|
||||||
|
pod-security.kubernetes.io/warn: restricted
|
||||||
|
pod-security.kubernetes.io/warn-version: latest
|
||||||
|
pod-security.kubernetes.io/audit: restricted
|
||||||
|
pod-security.kubernetes.io/audit-version: latest
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: auth-db-migration
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/hook: PreSync
|
||||||
|
argocd.argoproj.io/sync-wave: "-2"
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: ghcr-regcred
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: auth-db-migration
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/hook: PreSync
|
||||||
|
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation,HookSucceeded
|
||||||
|
argocd.argoproj.io/sync-wave: "-1"
|
||||||
|
spec:
|
||||||
|
backoffLimit: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: auth-db-migration
|
||||||
|
spec:
|
||||||
|
serviceAccountName: auth-db-migration
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
restartPolicy: Never
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 10001
|
||||||
|
runAsGroup: 10001
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
containers:
|
||||||
|
- name: auth-db-migration
|
||||||
|
image: ghcr.io/donghyeonka/project-auth-server
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command:
|
||||||
|
- java
|
||||||
|
- -jar
|
||||||
|
- /app/migration.jar
|
||||||
|
env:
|
||||||
|
- name: SPRING_MAIN_WEB_APPLICATION_TYPE
|
||||||
|
value: none
|
||||||
|
- name: APP_PERSISTENCE_MIGRATION_RUN_ON_STARTUP
|
||||||
|
value: "true"
|
||||||
|
- name: APP_PERSISTENCE_MIGRATION_LOCATION
|
||||||
|
value: classpath:db/migration
|
||||||
|
- name: APP_DATASOURCE_URL
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: auth-server-config
|
||||||
|
key: APP_DATASOURCE_URL
|
||||||
|
- name: APP_DATASOURCE_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: postgres-auth-server-credentials
|
||||||
|
key: APP_DATASOURCE_USERNAME
|
||||||
|
- name: APP_DATASOURCE_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: postgres-auth-server-credentials
|
||||||
|
key: APP_DATASOURCE_PASSWORD
|
||||||
|
- name: APP_DATASOURCE_DRIVER_CLASS_NAME
|
||||||
|
value: org.postgresql.Driver
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: false
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: auth-server
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "0"
|
||||||
|
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: auth-server
|
||||||
|
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: auth-server
|
||||||
|
|
||||||
|
spec:
|
||||||
|
serviceAccountName: auth-server
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 10001
|
||||||
|
runAsGroup: 10001
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
containers:
|
||||||
|
- name: auth-server
|
||||||
|
image: ghcr.io/donghyeonka/project-auth-server
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: http
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: auth-server-config
|
||||||
|
- secretRef:
|
||||||
|
name: postgres-auth-server-credentials
|
||||||
|
- secretRef:
|
||||||
|
name: keycloak-client-auth-server
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: false
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 250m
|
||||||
|
memory: 512Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 1024Mi
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /actuator/health/readiness
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 3
|
||||||
|
periodSeconds: 10
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /actuator/health/liveness
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 5
|
||||||
|
periodSeconds: 15
|
||||||
|
startupProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /actuator/health/liveness
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
timeoutSeconds: 3
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 12
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- serviceaccount.yaml
|
||||||
|
- auth-db-migration-serviceaccount.yaml
|
||||||
|
- service.yaml
|
||||||
|
- db-migration-job.yaml
|
||||||
|
- deployment.yaml
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: auth-server
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: auth-server
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
||||||
|
type: ClusterIP
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: auth-server
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: ghcr-regcred
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: auth-server-config
|
||||||
|
data:
|
||||||
|
SPRING_PROFILES_ACTIVE: dev
|
||||||
|
SERVER_FORWARD_HEADERS_STRATEGY: framework
|
||||||
|
APP_DOCS_TITLE: Project Auth Server API
|
||||||
|
APP_DOCS_DESCRIPTION: dev auth-server OpenAPI
|
||||||
|
APP_DOCS_VERSION: v1
|
||||||
|
APP_DATASOURCE_URL: jdbc:postgresql://postgres.platform.svc.cluster.local:5432/project_auth
|
||||||
|
APP_PERSISTENCE_MIGRATION_RUN_ON_STARTUP: "false"
|
||||||
|
APP_SECURITY_OAUTH2_KEYCLOAK_ISSUER_URI: http://keycloak-public.platform.svc.cluster.local/realms/project-auth
|
||||||
|
APP_SECURITY_OAUTH2_KEYCLOAK_CLIENT_ID: project-auth-server
|
||||||
|
APP_SECURITY_OAUTH2_GOOGLE_REGISTRATION_ID: keycloak-google
|
||||||
|
APP_SECURITY_OAUTH2_GOOGLE_IDP_HINT: google
|
||||||
|
APP_SECURITY_OAUTH2_GITHUB_REGISTRATION_ID: keycloak-github
|
||||||
|
APP_SECURITY_OAUTH2_GITHUB_IDP_HINT: github
|
||||||
|
APP_SECURITY_JWT_ISSUER: http://auth-public.auth-dev.svc.cluster.local
|
||||||
|
APP_SECURITY_JWT_ACTIVE_KEY_ID: dev-vault-rsa-1
|
||||||
|
APP_SECURITY_JWT_GENERATE_KEY_PAIR_ON_STARTUP: "false"
|
||||||
|
APP_SECURITY_JWT_ACCESS_TOKEN_EXPIRATION: PT30M
|
||||||
|
APP_SECURITY_JWT_VAULT_ENABLED: "true"
|
||||||
|
APP_SECURITY_JWT_VAULT_ADDRESS: http://vault.vault.svc.cluster.local:8200
|
||||||
|
APP_SECURITY_JWT_VAULT_MOUNT_PATH: transit
|
||||||
|
APP_SECURITY_JWT_VAULT_TRANSIT_KEY_NAME: project-auth-jwt
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: auth-db-migration
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
vault.hashicorp.com/agent-inject: "true"
|
||||||
|
vault.hashicorp.com/agent-inject-secret-migration-env: database/creds/auth-db-migration-dev
|
||||||
|
vault.hashicorp.com/agent-inject-template-migration-env: |
|
||||||
|
{{- with secret "database/creds/auth-db-migration-dev" -}}
|
||||||
|
export APP_DATASOURCE_USERNAME={{ printf "%q" .Data.username }}
|
||||||
|
export APP_DATASOURCE_PASSWORD={{ printf "%q" .Data.password }}
|
||||||
|
{{- end }}
|
||||||
|
vault.hashicorp.com/agent-pre-populate-only: "true"
|
||||||
|
vault.hashicorp.com/agent-run-as-group: "10001"
|
||||||
|
vault.hashicorp.com/agent-run-as-user: "10001"
|
||||||
|
vault.hashicorp.com/role: auth-db-migration-dev
|
||||||
|
spec:
|
||||||
|
automountServiceAccountToken: true
|
||||||
|
containers:
|
||||||
|
- name: auth-db-migration
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -ec
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
. /vault/secrets/migration-env
|
||||||
|
exec java -jar /app/migration.jar
|
||||||
|
env:
|
||||||
|
- $patch: replace
|
||||||
|
- name: SPRING_MAIN_WEB_APPLICATION_TYPE
|
||||||
|
value: none
|
||||||
|
- name: APP_PERSISTENCE_MIGRATION_RUN_ON_STARTUP
|
||||||
|
value: "true"
|
||||||
|
- name: APP_PERSISTENCE_MIGRATION_LOCATION
|
||||||
|
value: classpath:db/migration
|
||||||
|
- name: APP_DATASOURCE_URL
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: auth-server-config
|
||||||
|
key: APP_DATASOURCE_URL
|
||||||
|
- name: APP_DATASOURCE_DRIVER_CLASS_NAME
|
||||||
|
value: org.postgresql.Driver
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: auth-server
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
vault.hashicorp.com/agent-cache-enable: "true"
|
||||||
|
vault.hashicorp.com/agent-inject: "true"
|
||||||
|
vault.hashicorp.com/agent-inject-secret-runtime-env: kv/data/dev/platform/postgres/auth-server
|
||||||
|
vault.hashicorp.com/agent-inject-template-runtime-env: |
|
||||||
|
{{ with secret "kv/data/dev/platform/postgres/auth-server" }}
|
||||||
|
export APP_DATASOURCE_USERNAME={{ printf "%q" .Data.data.APP_DATASOURCE_USERNAME }}
|
||||||
|
export APP_DATASOURCE_PASSWORD={{ printf "%q" .Data.data.APP_DATASOURCE_PASSWORD }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ with secret "kv/data/dev/platform/keycloak/client-auth-server" }}
|
||||||
|
export APP_SECURITY_OAUTH2_KEYCLOAK_CLIENT_SECRET={{ printf "%q" .Data.data.APP_SECURITY_OAUTH2_KEYCLOAK_CLIENT_SECRET }}
|
||||||
|
{{ end }}
|
||||||
|
vault.hashicorp.com/agent-inject-token: "true"
|
||||||
|
vault.hashicorp.com/agent-run-as-group: "10001"
|
||||||
|
vault.hashicorp.com/agent-run-as-user: "10001"
|
||||||
|
vault.hashicorp.com/role: auth-server-dev
|
||||||
|
spec:
|
||||||
|
automountServiceAccountToken: true
|
||||||
|
containers:
|
||||||
|
- name: auth-server
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -ec
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
. /vault/secrets/runtime-env
|
||||||
|
export APP_SECURITY_JWT_VAULT_TOKEN="$(cat /vault/secrets/token)"
|
||||||
|
exec java -jar /app/application.jar
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: auth-server-config
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
apiVersion: bitnami.com/v1alpha1
|
||||||
|
kind: SealedSecret
|
||||||
|
metadata:
|
||||||
|
name: ghcr-regcred
|
||||||
|
namespace: auth-dev
|
||||||
|
spec:
|
||||||
|
encryptedData:
|
||||||
|
.dockerconfigjson: AgAIKHR/abtMIrkphJPG63jmOCXIMSBdDMdMUYjx37FRV9SpCA/j3UTHhhZlDSK5gXK/p9FGsR1mBjME+imHEa7/rqBMzfSoJjRQCln3TjD1GT+XJ9J8/qS9AQl+GG9kcJfVMTfGslFbQc1993uURdb/CDupe8XsJosMfzvV5h+SpSdytU2Y8CrhZSDNtz7/2Y+x0LQNfyafjXCxsc1kS5qt3WzPFD/zyk70+e2oq868ETBaij2dHEAQXH+XVz2ilqyzLE633X3/Wf/ADRMJ1i7XWaMir01mSXaB97U2+OPaSRJDf1TAfikn6D4BydNsTgI2UQ839edrgr9EXz1Sr4oYdpWjOpNmtH6OjfiiRj2r0LMvNKR/C1ruROfBcEV7y3kXpKRM5kwG+WM1/1B0ziodu0LZJl23QAgfNnTJrYlJJXJNSFNapPMWEcq91TMeauSIyRgbtLUZEemmlTVybt2SV86Yr+w9SlNAsBJGQaW34Ljfmu7X9H0JwTDkphWUotSPmmKj2GFdpVaNwL0Xvi6OoytiWu0rJWVkGar3mnyLPrkVLb5AlOZYPKxfPhZJfwZxPXBqgWj+6kHGs1SpH6v55wVIz1MdMoGcVqcjlOiMNFd2leOyejYQvRBXKRW3wgzgB6J0OdL1S8z1cOfblO4egx9C6RsaxDC//VDK36aAYvdc55Hsk2GC4iZKsug6EAdXWiiJjdM9yfAcGcv7LemQneA3OslJTdDTpWUdbREiIDXBX4PjEQz0G4oI5YDNYvS8NxUOWZ1ly0BH+uHbcm69tnD9ATSVvjvtKlLiP7/BCYZAguCzNEYkmf1neTtHYlVsoPmIuTkifaf9qRPU831MYj8wTfz56YVT1+aSbfQBK4XP49+bIf5AVo9K5JuEQETqMhZ0G05VjmlwUrgtQ60oZLu8dbvFyt/0VxfWBGcCi+AW+nmro3c14XmA4k1d09xtuoa+8QEObtOTEow3+tyqL46FlJgl7UjX8dd4p7gUAF/iADw8a0M32kIN0NHJ9o2EsFe85rn9qBoDLGrogDXRXJ4iCxE0Zgf7bw6tFA==
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
name: ghcr-regcred
|
||||||
|
namespace: auth-dev
|
||||||
|
type: kubernetes.io/dockerconfigjson
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: auth-server
|
||||||
|
annotations:
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik
|
||||||
|
rules:
|
||||||
|
- host: auth-public.auth-dev.svc.cluster.local
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: auth-server
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: auth-dev
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- ../../base
|
||||||
|
- namespace.yaml
|
||||||
|
- configmap.yaml
|
||||||
|
- ingress.yaml
|
||||||
|
- public-access.yaml
|
||||||
|
- networkpolicy.yaml
|
||||||
|
- ghcr-regcred.sealedsecret.yaml
|
||||||
|
|
||||||
|
patches:
|
||||||
|
- path: deployment.vault-patch.yaml
|
||||||
|
- path: db-migration-job.vault-patch.yaml
|
||||||
|
|
||||||
|
generatorOptions:
|
||||||
|
disableNameSuffixHash: true
|
||||||
|
|
||||||
|
images:
|
||||||
|
- name: ghcr.io/donghyeonka/project-auth-server
|
||||||
|
newName: ghcr.io/donghyeonka/project-auth-server
|
||||||
|
newTag: 1f47f2c
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: auth-dev
|
||||||
|
labels:
|
||||||
|
vault-injection: enabled
|
||||||
|
pod-security.kubernetes.io/enforce: baseline
|
||||||
|
pod-security.kubernetes.io/enforce-version: latest
|
||||||
|
pod-security.kubernetes.io/warn: restricted
|
||||||
|
pod-security.kubernetes.io/warn-version: latest
|
||||||
|
pod-security.kubernetes.io/audit: restricted
|
||||||
|
pod-security.kubernetes.io/audit-version: latest
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: auth-dev-default-deny
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: auth-dev-allow-dns-egress
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
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
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: auth-dev-allow-platform-and-vault-egress
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: platform
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: postgres
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 5432
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: vault
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: vault
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8200
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: auth-dev-allow-public-egress
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: auth-server
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: kube-system
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: traefik
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8000
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: auth-dev-allow-ingress-from-traefik
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: auth-server
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: kube-system
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: traefik
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8080
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: auth-public
|
||||||
|
spec:
|
||||||
|
type: ExternalName
|
||||||
|
externalName: traefik.kube-system.svc.cluster.local
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: auth-prod
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- ../../base
|
||||||
|
- namespace.yaml
|
||||||
|
|
||||||
|
images:
|
||||||
|
- name: ghcr.io/donghyeonka/project-auth-server
|
||||||
|
newName: ghcr.io/donghyeonka/project-auth-server
|
||||||
|
newTag: 5648fd2
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: auth-prod
|
||||||
|
labels:
|
||||||
|
pod-security.kubernetes.io/enforce: baseline
|
||||||
|
pod-security.kubernetes.io/enforce-version: latest
|
||||||
|
pod-security.kubernetes.io/warn: restricted
|
||||||
|
pod-security.kubernetes.io/warn-version: latest
|
||||||
|
pod-security.kubernetes.io/audit: restricted
|
||||||
|
pod-security.kubernetes.io/audit-version: latest
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
## Argo CD Structure
|
||||||
|
|
||||||
|
`argocd/` 디렉터리는 환경(`dev`, `prod`)과 성격(`apps`, `infra`) 기준으로 나눠 관리합니다.
|
||||||
|
|
||||||
|
- `applications/<env>/apps`: 서비스 애플리케이션 선언
|
||||||
|
- `applications/<env>/infra`: 공용 인프라/컨트롤러 선언
|
||||||
|
- `projects/<env>/apps-project.yaml`: 서비스 애플리케이션용 AppProject
|
||||||
|
- `projects/<env>/infra-project.yaml`: 공용 인프라용 AppProject
|
||||||
|
|
||||||
|
현재 `dev`에는 실제 선언을 두고, `prod`는 이후 운영 확장을 위한 구조와 프로젝트 골격을 먼저 유지합니다.
|
||||||
|
|
||||||
|
현재 dev `infra`에는 대표적으로 아래 Application이 포함됩니다.
|
||||||
|
|
||||||
|
- `vault-transit`: workload Vault transit auto-unseal provider
|
||||||
|
- `vault`: workload Vault
|
||||||
|
- `platform`: postgres, keycloak
|
||||||
|
- `vault-agent-injector`: workload secret injection
|
||||||
|
- `sealed-secrets`: image pull secret 같은 예외 secret 처리
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: api-server-dev
|
||||||
|
namespace: argocd
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "40"
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: apps-dev
|
||||||
|
source:
|
||||||
|
repoURL: https://github.com/DongHyeonka/Project-Auth-GitOps
|
||||||
|
targetRevision: main
|
||||||
|
path: apps/api-server/overlays/dev
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: api-dev
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
enabled: true
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
- PruneLast=true
|
||||||
|
- ApplyOutOfSyncOnly=true
|
||||||
|
retry:
|
||||||
|
limit: 5
|
||||||
|
backoff:
|
||||||
|
duration: 5s
|
||||||
|
factor: 2
|
||||||
|
maxDuration: 3m
|
||||||
|
revisionHistoryLimit: 5
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: auth-server-dev
|
||||||
|
namespace: argocd
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "30"
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: apps-dev
|
||||||
|
source:
|
||||||
|
repoURL: https://github.com/DongHyeonka/Project-Auth-GitOps
|
||||||
|
targetRevision: main
|
||||||
|
path: apps/auth-server/overlays/dev
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: auth-dev
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
enabled: true
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
- PruneLast=true
|
||||||
|
- ApplyOutOfSyncOnly=true
|
||||||
|
retry:
|
||||||
|
limit: 5
|
||||||
|
backoff:
|
||||||
|
duration: 5s
|
||||||
|
factor: 2
|
||||||
|
maxDuration: 3m
|
||||||
|
revisionHistoryLimit: 5
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: platform-dev
|
||||||
|
namespace: argocd
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "20"
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: infra-dev
|
||||||
|
source:
|
||||||
|
repoURL: https://github.com/DongHyeonka/Project-Auth-GitOps
|
||||||
|
targetRevision: main
|
||||||
|
path: infra/platform/overlays/dev
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: platform
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
enabled: true
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
- PruneLast=true
|
||||||
|
- ApplyOutOfSyncOnly=true
|
||||||
|
retry:
|
||||||
|
limit: 5
|
||||||
|
backoff:
|
||||||
|
duration: 5s
|
||||||
|
factor: 2
|
||||||
|
maxDuration: 3m
|
||||||
|
revisionHistoryLimit: 5
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: sealed-secrets-dev
|
||||||
|
namespace: argocd
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: infra-dev
|
||||||
|
source:
|
||||||
|
repoURL: https://bitnami-labs.github.io/sealed-secrets
|
||||||
|
chart: sealed-secrets
|
||||||
|
targetRevision: 2.17.9
|
||||||
|
helm:
|
||||||
|
values: |
|
||||||
|
fullnameOverride: sealed-secrets-controller
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: kube-system
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
enabled: true
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
- PruneLast=true
|
||||||
|
- ApplyOutOfSyncOnly=true
|
||||||
|
retry:
|
||||||
|
limit: 5
|
||||||
|
backoff:
|
||||||
|
duration: 5s
|
||||||
|
factor: 2
|
||||||
|
maxDuration: 3m
|
||||||
|
revisionHistoryLimit: 5
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: vault-agent-injector-dev
|
||||||
|
namespace: argocd
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "10"
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: infra-dev
|
||||||
|
source:
|
||||||
|
repoURL: https://helm.releases.hashicorp.com
|
||||||
|
chart: vault
|
||||||
|
targetRevision: 0.32.0
|
||||||
|
helm:
|
||||||
|
values: |
|
||||||
|
global:
|
||||||
|
externalVaultAddr: http://vault.vault.svc.cluster.local:8200
|
||||||
|
tlsDisable: true
|
||||||
|
server:
|
||||||
|
enabled: false
|
||||||
|
injector:
|
||||||
|
enabled: true
|
||||||
|
authPath: auth/kubernetes
|
||||||
|
webhook:
|
||||||
|
failurePolicy: Fail
|
||||||
|
namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
vault-injection: enabled
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 250m
|
||||||
|
memory: 256Mi
|
||||||
|
agentImage:
|
||||||
|
repository: hashicorp/vault
|
||||||
|
tag: "1.18"
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: vault
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
enabled: true
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
- PruneLast=true
|
||||||
|
- ApplyOutOfSyncOnly=true
|
||||||
|
retry:
|
||||||
|
limit: 5
|
||||||
|
backoff:
|
||||||
|
duration: 5s
|
||||||
|
factor: 2
|
||||||
|
maxDuration: 3m
|
||||||
|
revisionHistoryLimit: 5
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: vault-transit-dev
|
||||||
|
namespace: argocd
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "10"
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: infra-dev
|
||||||
|
source:
|
||||||
|
repoURL: https://github.com/DongHyeonka/Project-Auth-GitOps
|
||||||
|
targetRevision: main
|
||||||
|
path: infra/vault-transit/overlays/dev
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: vault-transit
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
enabled: true
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
- PruneLast=true
|
||||||
|
- ApplyOutOfSyncOnly=true
|
||||||
|
retry:
|
||||||
|
limit: 5
|
||||||
|
backoff:
|
||||||
|
duration: 5s
|
||||||
|
factor: 2
|
||||||
|
maxDuration: 3m
|
||||||
|
revisionHistoryLimit: 5
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: vault-dev
|
||||||
|
namespace: argocd
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "10"
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: infra-dev
|
||||||
|
source:
|
||||||
|
repoURL: https://github.com/DongHyeonka/Project-Auth-GitOps
|
||||||
|
targetRevision: main
|
||||||
|
path: infra/vault/overlays/dev
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: vault
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
enabled: true
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
- PruneLast=true
|
||||||
|
- ApplyOutOfSyncOnly=true
|
||||||
|
retry:
|
||||||
|
limit: 5
|
||||||
|
backoff:
|
||||||
|
duration: 5s
|
||||||
|
factor: 2
|
||||||
|
maxDuration: 3m
|
||||||
|
revisionHistoryLimit: 5
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: AppProject
|
||||||
|
metadata:
|
||||||
|
name: apps-dev
|
||||||
|
namespace: argocd
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
description: Dev application workloads managed by Argo CD
|
||||||
|
sourceRepos:
|
||||||
|
- https://github.com/DongHyeonka/Project-Auth-GitOps
|
||||||
|
destinations:
|
||||||
|
- namespace: auth-dev
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
- namespace: api-dev
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
clusterResourceWhitelist:
|
||||||
|
- group: ""
|
||||||
|
kind: Namespace
|
||||||
|
namespaceResourceWhitelist:
|
||||||
|
- group: ""
|
||||||
|
kind: ConfigMap
|
||||||
|
- group: ""
|
||||||
|
kind: Secret
|
||||||
|
- group: ""
|
||||||
|
kind: Service
|
||||||
|
- group: ""
|
||||||
|
kind: ServiceAccount
|
||||||
|
- group: ""
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
- group: "bitnami.com"
|
||||||
|
kind: SealedSecret
|
||||||
|
- group: "apps"
|
||||||
|
kind: Deployment
|
||||||
|
- group: "apps"
|
||||||
|
kind: StatefulSet
|
||||||
|
- group: "apps"
|
||||||
|
kind: ReplicaSet
|
||||||
|
- group: "autoscaling"
|
||||||
|
kind: HorizontalPodAutoscaler
|
||||||
|
- group: "batch"
|
||||||
|
kind: Job
|
||||||
|
- group: "networking.k8s.io"
|
||||||
|
kind: Ingress
|
||||||
|
- group: "networking.k8s.io"
|
||||||
|
kind: NetworkPolicy
|
||||||
|
- group: "policy"
|
||||||
|
kind: PodDisruptionBudget
|
||||||
|
orphanedResources:
|
||||||
|
warn: true
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: AppProject
|
||||||
|
metadata:
|
||||||
|
name: infra-dev
|
||||||
|
namespace: argocd
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
description: Dev shared infrastructure managed by Argo CD
|
||||||
|
sourceRepos:
|
||||||
|
- https://github.com/DongHyeonka/Project-Auth-GitOps
|
||||||
|
- https://bitnami-labs.github.io/sealed-secrets
|
||||||
|
- https://helm.releases.hashicorp.com
|
||||||
|
destinations:
|
||||||
|
- namespace: platform
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
- namespace: vault
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
- namespace: vault-transit
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
- namespace: kube-system
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
clusterResourceWhitelist:
|
||||||
|
- group: ""
|
||||||
|
kind: Namespace
|
||||||
|
- group: "apiextensions.k8s.io"
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
- group: "rbac.authorization.k8s.io"
|
||||||
|
kind: ClusterRole
|
||||||
|
- group: "rbac.authorization.k8s.io"
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
- group: "admissionregistration.k8s.io"
|
||||||
|
kind: MutatingWebhookConfiguration
|
||||||
|
namespaceResourceWhitelist:
|
||||||
|
- group: ""
|
||||||
|
kind: ConfigMap
|
||||||
|
- group: ""
|
||||||
|
kind: Secret
|
||||||
|
- group: ""
|
||||||
|
kind: Service
|
||||||
|
- group: ""
|
||||||
|
kind: ServiceAccount
|
||||||
|
- group: ""
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
- group: "bitnami.com"
|
||||||
|
kind: SealedSecret
|
||||||
|
- group: "rbac.authorization.k8s.io"
|
||||||
|
kind: Role
|
||||||
|
- group: "rbac.authorization.k8s.io"
|
||||||
|
kind: RoleBinding
|
||||||
|
- group: "apps"
|
||||||
|
kind: Deployment
|
||||||
|
- group: "apps"
|
||||||
|
kind: StatefulSet
|
||||||
|
- group: "apps"
|
||||||
|
kind: ReplicaSet
|
||||||
|
- group: "autoscaling"
|
||||||
|
kind: HorizontalPodAutoscaler
|
||||||
|
- group: "batch"
|
||||||
|
kind: Job
|
||||||
|
- group: "networking.k8s.io"
|
||||||
|
kind: Ingress
|
||||||
|
- group: "networking.k8s.io"
|
||||||
|
kind: NetworkPolicy
|
||||||
|
- group: "policy"
|
||||||
|
kind: PodDisruptionBudget
|
||||||
|
orphanedResources:
|
||||||
|
warn: true
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: AppProject
|
||||||
|
metadata:
|
||||||
|
name: apps-prod
|
||||||
|
namespace: argocd
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
description: Prod application workloads managed by Argo CD
|
||||||
|
sourceRepos:
|
||||||
|
- https://github.com/DongHyeonka/Project-Auth-GitOps
|
||||||
|
destinations:
|
||||||
|
- namespace: auth-prod
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
- namespace: api-prod
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
clusterResourceWhitelist:
|
||||||
|
- group: ""
|
||||||
|
kind: Namespace
|
||||||
|
namespaceResourceWhitelist:
|
||||||
|
- group: ""
|
||||||
|
kind: ConfigMap
|
||||||
|
- group: ""
|
||||||
|
kind: Secret
|
||||||
|
- group: ""
|
||||||
|
kind: Service
|
||||||
|
- group: ""
|
||||||
|
kind: ServiceAccount
|
||||||
|
- group: ""
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
- group: "bitnami.com"
|
||||||
|
kind: SealedSecret
|
||||||
|
- group: "apps"
|
||||||
|
kind: Deployment
|
||||||
|
- group: "apps"
|
||||||
|
kind: StatefulSet
|
||||||
|
- group: "apps"
|
||||||
|
kind: ReplicaSet
|
||||||
|
- group: "autoscaling"
|
||||||
|
kind: HorizontalPodAutoscaler
|
||||||
|
- group: "batch"
|
||||||
|
kind: Job
|
||||||
|
- group: "networking.k8s.io"
|
||||||
|
kind: Ingress
|
||||||
|
- group: "networking.k8s.io"
|
||||||
|
kind: NetworkPolicy
|
||||||
|
- group: "policy"
|
||||||
|
kind: PodDisruptionBudget
|
||||||
|
orphanedResources:
|
||||||
|
warn: true
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: AppProject
|
||||||
|
metadata:
|
||||||
|
name: infra-prod
|
||||||
|
namespace: argocd
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
description: Prod shared infrastructure managed by Argo CD
|
||||||
|
sourceRepos:
|
||||||
|
- https://github.com/DongHyeonka/Project-Auth-GitOps
|
||||||
|
- https://bitnami-labs.github.io/sealed-secrets
|
||||||
|
destinations:
|
||||||
|
- namespace: platform-prod
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
- namespace: kube-system
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
clusterResourceWhitelist:
|
||||||
|
- group: ""
|
||||||
|
kind: Namespace
|
||||||
|
- group: "apiextensions.k8s.io"
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
- group: "rbac.authorization.k8s.io"
|
||||||
|
kind: ClusterRole
|
||||||
|
- group: "rbac.authorization.k8s.io"
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
namespaceResourceWhitelist:
|
||||||
|
- group: ""
|
||||||
|
kind: ConfigMap
|
||||||
|
- group: ""
|
||||||
|
kind: Secret
|
||||||
|
- group: ""
|
||||||
|
kind: Service
|
||||||
|
- group: ""
|
||||||
|
kind: ServiceAccount
|
||||||
|
- group: ""
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
- group: "bitnami.com"
|
||||||
|
kind: SealedSecret
|
||||||
|
- group: "rbac.authorization.k8s.io"
|
||||||
|
kind: Role
|
||||||
|
- group: "rbac.authorization.k8s.io"
|
||||||
|
kind: RoleBinding
|
||||||
|
- group: "apps"
|
||||||
|
kind: Deployment
|
||||||
|
- group: "apps"
|
||||||
|
kind: StatefulSet
|
||||||
|
- group: "apps"
|
||||||
|
kind: ReplicaSet
|
||||||
|
- group: "autoscaling"
|
||||||
|
kind: HorizontalPodAutoscaler
|
||||||
|
- group: "batch"
|
||||||
|
kind: Job
|
||||||
|
- group: "networking.k8s.io"
|
||||||
|
kind: Ingress
|
||||||
|
- group: "networking.k8s.io"
|
||||||
|
kind: NetworkPolicy
|
||||||
|
- group: "policy"
|
||||||
|
kind: PodDisruptionBudget
|
||||||
|
orphanedResources:
|
||||||
|
warn: true
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"realm": "project-auth",
|
||||||
|
"enabled": true,
|
||||||
|
"displayName": "Project Auth",
|
||||||
|
"sslRequired": "NONE",
|
||||||
|
"registrationAllowed": false,
|
||||||
|
"loginWithEmailAllowed": true,
|
||||||
|
"duplicateEmailsAllowed": false,
|
||||||
|
"resetPasswordAllowed": true,
|
||||||
|
"clients": [
|
||||||
|
{
|
||||||
|
"clientId": "project-auth-server",
|
||||||
|
"name": "project-auth-server",
|
||||||
|
"enabled": true,
|
||||||
|
"protocol": "openid-connect",
|
||||||
|
"publicClient": false,
|
||||||
|
"standardFlowEnabled": true,
|
||||||
|
"directAccessGrantsEnabled": false,
|
||||||
|
"serviceAccountsEnabled": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
psql -v ON_ERROR_STOP=1 --username "${POSTGRES_USER}" --dbname "${POSTGRES_DB}" <<-EOSQL
|
||||||
|
CREATE USER ${AUTH_DB_USER} WITH PASSWORD '${AUTH_DB_PASSWORD}';
|
||||||
|
CREATE DATABASE ${AUTH_DB_NAME} OWNER ${AUTH_DB_USER};
|
||||||
|
|
||||||
|
CREATE USER ${KEYCLOAK_DB_USER} WITH PASSWORD '${KEYCLOAK_DB_PASSWORD}';
|
||||||
|
CREATE DATABASE ${KEYCLOAK_DB_NAME} OWNER ${KEYCLOAK_DB_USER};
|
||||||
|
EOSQL
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: keycloak-client-sync
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "4"
|
||||||
|
spec:
|
||||||
|
backoffLimit: 5
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: keycloak-client-sync
|
||||||
|
spec:
|
||||||
|
serviceAccountName: keycloak-client-sync
|
||||||
|
restartPolicy: OnFailure
|
||||||
|
containers:
|
||||||
|
- name: keycloak-client-sync
|
||||||
|
image: quay.io/keycloak/keycloak:26.5.5
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
until /opt/keycloak/bin/kcadm.sh config credentials \
|
||||||
|
--server http://keycloak.platform.svc.cluster.local \
|
||||||
|
--realm master \
|
||||||
|
--user "$KC_BOOTSTRAP_ADMIN_USERNAME" \
|
||||||
|
--password "$KC_BOOTSTRAP_ADMIN_PASSWORD" >/dev/null 2>&1; do
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
|
||||||
|
CLIENT_UUID=$(/opt/keycloak/bin/kcadm.sh get clients \
|
||||||
|
-r project-auth \
|
||||||
|
-q clientId="$KEYCLOAK_CLIENT_ID" | sed -n 's/.*"id" : "\([^"]*\)".*/\1/p' | head -n 1)
|
||||||
|
|
||||||
|
test -n "$CLIENT_UUID"
|
||||||
|
|
||||||
|
/opt/keycloak/bin/kcadm.sh update "clients/${CLIENT_UUID}" \
|
||||||
|
-r project-auth \
|
||||||
|
-s "secret=$KEYCLOAK_CLIENT_SECRET" \
|
||||||
|
-s "baseUrl=$AUTH_SERVER_BASE_URL" \
|
||||||
|
-s 'redirectUris=["'"$AUTH_SERVER_BASE_URL"'/login/oauth2/code/keycloak-google","'"$AUTH_SERVER_BASE_URL"'/login/oauth2/code/keycloak-github"]' \
|
||||||
|
-s 'webOrigins=["'"$AUTH_SERVER_BASE_URL"'"]'
|
||||||
|
env:
|
||||||
|
- name: KC_BOOTSTRAP_ADMIN_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: KEYCLOAK_BOOTSTRAP_ADMIN_USERNAME
|
||||||
|
- name: KC_BOOTSTRAP_ADMIN_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: keycloak-bootstrap-admin
|
||||||
|
key: KEYCLOAK_BOOTSTRAP_ADMIN_PASSWORD
|
||||||
|
- name: KEYCLOAK_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: KEYCLOAK_CLIENT_ID
|
||||||
|
- name: KEYCLOAK_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: keycloak-client-auth-server
|
||||||
|
key: KEYCLOAK_CLIENT_SECRET
|
||||||
|
- name: AUTH_SERVER_BASE_URL
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: AUTH_SERVER_BASE_URL
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: keycloak-client-sync
|
||||||
|
automountServiceAccountToken: false
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: keycloak
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "3"
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: keycloak
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: keycloak
|
||||||
|
spec:
|
||||||
|
serviceAccountName: keycloak
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
containers:
|
||||||
|
- name: keycloak
|
||||||
|
image: quay.io/keycloak/keycloak:26.5.5
|
||||||
|
args:
|
||||||
|
- start-dev
|
||||||
|
- --import-realm
|
||||||
|
- --http-port=8080
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: http
|
||||||
|
- containerPort: 9000
|
||||||
|
name: management
|
||||||
|
env:
|
||||||
|
- name: KC_DB
|
||||||
|
value: postgres
|
||||||
|
- name: KC_DB_URL
|
||||||
|
value: jdbc:postgresql://postgres.platform.svc.cluster.local:5432/keycloak
|
||||||
|
- name: KC_DB_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: KEYCLOAK_DB_USER
|
||||||
|
- name: KC_DB_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: postgres-keycloak-credentials
|
||||||
|
key: KEYCLOAK_DB_PASSWORD
|
||||||
|
- name: KC_HEALTH_ENABLED
|
||||||
|
value: "true"
|
||||||
|
- name: KC_BOOTSTRAP_ADMIN_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: KEYCLOAK_BOOTSTRAP_ADMIN_USERNAME
|
||||||
|
- name: KC_BOOTSTRAP_ADMIN_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: keycloak-bootstrap-admin
|
||||||
|
key: KEYCLOAK_BOOTSTRAP_ADMIN_PASSWORD
|
||||||
|
volumeMounts:
|
||||||
|
- name: keycloak-realm-import
|
||||||
|
mountPath: /opt/keycloak/data/import/project-auth-realm.json
|
||||||
|
subPath: project-auth-realm.json
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health/ready
|
||||||
|
port: management
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 6
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health/live
|
||||||
|
port: management
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
periodSeconds: 15
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 6
|
||||||
|
startupProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health/ready
|
||||||
|
port: management
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 30
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 250m
|
||||||
|
memory: 768Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 1536Mi
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
volumes:
|
||||||
|
- name: keycloak-realm-import
|
||||||
|
configMap:
|
||||||
|
name: keycloak-realm-import
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: keycloak
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: keycloak
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
||||||
|
type: ClusterIP
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: keycloak
|
||||||
|
automountServiceAccountToken: false
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- postgres-serviceaccount.yaml
|
||||||
|
- keycloak-serviceaccount.yaml
|
||||||
|
- keycloak-client-sync-serviceaccount.yaml
|
||||||
|
- postgres-service.yaml
|
||||||
|
- postgres-statefulset.yaml
|
||||||
|
- keycloak-service.yaml
|
||||||
|
- keycloak-deployment.yaml
|
||||||
|
- keycloak-client-sync-job.yaml
|
||||||
|
generatorOptions:
|
||||||
|
disableNameSuffixHash: true
|
||||||
|
|
||||||
|
configMapGenerator:
|
||||||
|
- name: postgres-init-script
|
||||||
|
files:
|
||||||
|
- files/postgres/01-init-project-auth-databases.sh
|
||||||
|
- name: keycloak-realm-import
|
||||||
|
files:
|
||||||
|
- files/keycloak/project-auth-realm.json
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: postgres
|
||||||
|
spec:
|
||||||
|
clusterIP: None
|
||||||
|
selector:
|
||||||
|
app: postgres
|
||||||
|
ports:
|
||||||
|
- name: postgres
|
||||||
|
port: 5432
|
||||||
|
targetPort: 5432
|
||||||
|
type: ClusterIP
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: postgres
|
||||||
|
automountServiceAccountToken: false
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: postgres
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "2"
|
||||||
|
spec:
|
||||||
|
serviceName: postgres
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: postgres
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: postgres
|
||||||
|
spec:
|
||||||
|
serviceAccountName: postgres
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 999
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
containers:
|
||||||
|
- name: postgres
|
||||||
|
image: postgres:16-alpine
|
||||||
|
ports:
|
||||||
|
- containerPort: 5432
|
||||||
|
name: postgres
|
||||||
|
env:
|
||||||
|
- name: PGDATA
|
||||||
|
value: /var/lib/postgresql/data/pgdata
|
||||||
|
- name: POSTGRES_USER
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: POSTGRES_SUPERUSER
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: postgres-superuser-credentials
|
||||||
|
key: POSTGRES_SUPERUSER_PASSWORD
|
||||||
|
- name: POSTGRES_DB
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: POSTGRES_DEFAULT_DB
|
||||||
|
- name: AUTH_DB_NAME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: AUTH_DB_NAME
|
||||||
|
- name: AUTH_DB_USER
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: AUTH_DB_USER
|
||||||
|
- name: AUTH_DB_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: postgres-auth-server-credentials
|
||||||
|
key: AUTH_DB_PASSWORD
|
||||||
|
- name: KEYCLOAK_DB_NAME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: KEYCLOAK_DB_NAME
|
||||||
|
- name: KEYCLOAK_DB_USER
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: KEYCLOAK_DB_USER
|
||||||
|
- name: KEYCLOAK_DB_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: postgres-keycloak-credentials
|
||||||
|
key: KEYCLOAK_DB_PASSWORD
|
||||||
|
securityContext:
|
||||||
|
volumeMounts:
|
||||||
|
- name: postgres-data
|
||||||
|
mountPath: /var/lib/postgresql/data
|
||||||
|
- name: postgres-init-script
|
||||||
|
mountPath: /docker-entrypoint-initdb.d/01-init-project-auth-databases.sh
|
||||||
|
subPath: 01-init-project-auth-databases.sh
|
||||||
|
- name: postgres-run
|
||||||
|
mountPath: /var/run/postgresql
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 3
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 15
|
||||||
|
timeoutSeconds: 3
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 250m
|
||||||
|
memory: 512Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 1024Mi
|
||||||
|
volumes:
|
||||||
|
- name: postgres-init-script
|
||||||
|
configMap:
|
||||||
|
name: postgres-init-script
|
||||||
|
defaultMode: 0555
|
||||||
|
- name: postgres-run
|
||||||
|
emptyDir: {}
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: postgres-data
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: platform-config
|
||||||
|
data:
|
||||||
|
POSTGRES_SUPERUSER: postgres
|
||||||
|
POSTGRES_DEFAULT_DB: postgres
|
||||||
|
AUTH_DB_NAME: project_auth
|
||||||
|
AUTH_DB_USER: project_auth
|
||||||
|
KEYCLOAK_DB_NAME: keycloak
|
||||||
|
KEYCLOAK_DB_USER: keycloak
|
||||||
|
KEYCLOAK_BOOTSTRAP_ADMIN_USERNAME: admin
|
||||||
|
KEYCLOAK_CLIENT_ID: project-auth-server
|
||||||
|
AUTH_SERVER_BASE_URL: http://auth-public.auth-dev.svc.cluster.local
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: keycloak-client-sync
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
vault.hashicorp.com/agent-inject: "true"
|
||||||
|
vault.hashicorp.com/agent-inject-perms-keycloak-sync-env: "0644"
|
||||||
|
vault.hashicorp.com/agent-inject-secret-keycloak-sync-env: kv/data/dev/platform/keycloak/bootstrap-admin
|
||||||
|
vault.hashicorp.com/agent-inject-template-keycloak-sync-env: |
|
||||||
|
{{ with secret "kv/data/dev/platform/keycloak/bootstrap-admin" }}
|
||||||
|
export KC_BOOTSTRAP_ADMIN_PASSWORD={{ printf "%q" .Data.data.KC_BOOTSTRAP_ADMIN_PASSWORD }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ with secret "kv/data/dev/platform/keycloak/client-auth-server" }}
|
||||||
|
export KEYCLOAK_CLIENT_SECRET={{ printf "%q" .Data.data.KEYCLOAK_CLIENT_SECRET }}
|
||||||
|
{{ end }}
|
||||||
|
vault.hashicorp.com/agent-pre-populate-only: "true"
|
||||||
|
vault.hashicorp.com/role: keycloak-client-sync-dev
|
||||||
|
spec:
|
||||||
|
automountServiceAccountToken: true
|
||||||
|
containers:
|
||||||
|
- name: keycloak-client-sync
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -ec
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
. /vault/secrets/keycloak-sync-env
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
until /opt/keycloak/bin/kcadm.sh config credentials \
|
||||||
|
--server http://keycloak.platform.svc.cluster.local \
|
||||||
|
--realm master \
|
||||||
|
--user "$KC_BOOTSTRAP_ADMIN_USERNAME" \
|
||||||
|
--password "$KC_BOOTSTRAP_ADMIN_PASSWORD" >/dev/null 2>&1; do
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
|
||||||
|
CLIENT_UUID=$(/opt/keycloak/bin/kcadm.sh get clients \
|
||||||
|
-r project-auth \
|
||||||
|
-q clientId="$KEYCLOAK_CLIENT_ID" | sed -n 's/.*"id" : "\([^"]*\)".*/\1/p' | head -n 1)
|
||||||
|
|
||||||
|
test -n "$CLIENT_UUID"
|
||||||
|
|
||||||
|
/opt/keycloak/bin/kcadm.sh update "clients/${CLIENT_UUID}" \
|
||||||
|
-r project-auth \
|
||||||
|
-s "secret=$KEYCLOAK_CLIENT_SECRET" \
|
||||||
|
-s "baseUrl=$AUTH_SERVER_BASE_URL" \
|
||||||
|
-s 'redirectUris=["'"$AUTH_SERVER_BASE_URL"'/login/oauth2/code/keycloak-google","'"$AUTH_SERVER_BASE_URL"'/login/oauth2/code/keycloak-github"]' \
|
||||||
|
-s 'webOrigins=["'"$AUTH_SERVER_BASE_URL"'"]'
|
||||||
|
env:
|
||||||
|
- $patch: replace
|
||||||
|
- name: KC_BOOTSTRAP_ADMIN_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: KEYCLOAK_BOOTSTRAP_ADMIN_USERNAME
|
||||||
|
- name: KEYCLOAK_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: KEYCLOAK_CLIENT_ID
|
||||||
|
- name: AUTH_SERVER_BASE_URL
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: AUTH_SERVER_BASE_URL
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: keycloak
|
||||||
|
annotations:
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik
|
||||||
|
rules:
|
||||||
|
- host: keycloak-public.platform.svc.cluster.local
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: keycloak
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: keycloak
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: keycloak
|
||||||
|
env:
|
||||||
|
- name: KC_HOSTNAME
|
||||||
|
value: keycloak-public.platform.svc.cluster.local
|
||||||
|
- name: KC_HOSTNAME_STRICT
|
||||||
|
value: "false"
|
||||||
|
- name: KC_PROXY_HEADERS
|
||||||
|
value: xforwarded
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: keycloak
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
vault.hashicorp.com/agent-inject: "true"
|
||||||
|
vault.hashicorp.com/agent-inject-perms-keycloak-env: "0644"
|
||||||
|
vault.hashicorp.com/agent-inject-secret-keycloak-env: kv/data/dev/platform/postgres/keycloak
|
||||||
|
vault.hashicorp.com/agent-inject-template-keycloak-env: |
|
||||||
|
{{ with secret "kv/data/dev/platform/postgres/keycloak" }}
|
||||||
|
export KC_DB_PASSWORD={{ printf "%q" .Data.data.KEYCLOAK_DB_PASSWORD }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ with secret "kv/data/dev/platform/keycloak/bootstrap-admin" }}
|
||||||
|
export KC_BOOTSTRAP_ADMIN_PASSWORD={{ printf "%q" .Data.data.KC_BOOTSTRAP_ADMIN_PASSWORD }}
|
||||||
|
{{ end }}
|
||||||
|
vault.hashicorp.com/role: keycloak-dev
|
||||||
|
spec:
|
||||||
|
automountServiceAccountToken: true
|
||||||
|
containers:
|
||||||
|
- name: keycloak
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -ec
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
. /vault/secrets/keycloak-env
|
||||||
|
exec /opt/keycloak/bin/kc.sh start-dev --import-realm --http-port=8080
|
||||||
|
env:
|
||||||
|
- $patch: replace
|
||||||
|
- name: KC_DB
|
||||||
|
value: postgres
|
||||||
|
- name: KC_DB_URL
|
||||||
|
value: jdbc:postgresql://postgres.platform.svc.cluster.local:5432/keycloak
|
||||||
|
- name: KC_DB_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: KEYCLOAK_DB_USER
|
||||||
|
- name: KC_HEALTH_ENABLED
|
||||||
|
value: "true"
|
||||||
|
- name: KC_BOOTSTRAP_ADMIN_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: KEYCLOAK_BOOTSTRAP_ADMIN_USERNAME
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: platform
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- ../../base
|
||||||
|
- namespace.yaml
|
||||||
|
- configmap.yaml
|
||||||
|
- keycloak-ingress.yaml
|
||||||
|
- public-access.yaml
|
||||||
|
- networkpolicy.yaml
|
||||||
|
|
||||||
|
patches:
|
||||||
|
- path: postgres.vault-patch.yaml
|
||||||
|
- path: keycloak.vault-patch.yaml
|
||||||
|
- path: keycloak-client-sync.vault-patch.yaml
|
||||||
|
- path: keycloak.public-url-patch.yaml
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: platform
|
||||||
|
labels:
|
||||||
|
vault-injection: enabled
|
||||||
|
pod-security.kubernetes.io/enforce: baseline
|
||||||
|
pod-security.kubernetes.io/enforce-version: latest
|
||||||
|
pod-security.kubernetes.io/warn: restricted
|
||||||
|
pod-security.kubernetes.io/warn-version: latest
|
||||||
|
pod-security.kubernetes.io/audit: restricted
|
||||||
|
pod-security.kubernetes.io/audit-version: latest
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: platform-default-deny
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: platform-allow-dns-egress
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
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
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: platform-allow-vault-egress
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: vault
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: vault
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8200
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: platform-allow-keycloak-egress-to-postgres
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: keycloak
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: postgres
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 5432
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: platform-allow-keycloak-client-sync-to-keycloak
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: keycloak-client-sync
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: keycloak
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8080
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: platform-allow-keycloak-ingress
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: keycloak
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: kube-system
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: traefik
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8080
|
||||||
|
- from:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: keycloak-client-sync
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8080
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: platform-allow-postgres-ingress
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: postgres
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: auth-dev
|
||||||
|
podSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- key: app
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- auth-server
|
||||||
|
- auth-db-migration
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 5432
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: vault
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: vault
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 5432
|
||||||
|
- from:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: keycloak
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 5432
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: postgres
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
vault.hashicorp.com/agent-inject: "true"
|
||||||
|
vault.hashicorp.com/agent-inject-perms-postgres-env: "0644"
|
||||||
|
vault.hashicorp.com/agent-inject-secret-postgres-env: kv/data/dev/platform/postgres/superuser
|
||||||
|
vault.hashicorp.com/agent-inject-template-postgres-env: |
|
||||||
|
{{ with secret "kv/data/dev/platform/postgres/superuser" }}
|
||||||
|
export POSTGRES_PASSWORD={{ printf "%q" .Data.data.POSTGRES_SUPERUSER_PASSWORD }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ with secret "kv/data/dev/platform/postgres/auth-server" }}
|
||||||
|
export AUTH_DB_PASSWORD={{ printf "%q" .Data.data.AUTH_DB_PASSWORD }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ with secret "kv/data/dev/platform/postgres/keycloak" }}
|
||||||
|
export KEYCLOAK_DB_PASSWORD={{ printf "%q" .Data.data.KEYCLOAK_DB_PASSWORD }}
|
||||||
|
{{ end }}
|
||||||
|
vault.hashicorp.com/role: postgres-dev
|
||||||
|
spec:
|
||||||
|
automountServiceAccountToken: true
|
||||||
|
containers:
|
||||||
|
- name: postgres
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -ec
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
. /vault/secrets/postgres-env
|
||||||
|
exec docker-entrypoint.sh postgres
|
||||||
|
env:
|
||||||
|
- $patch: replace
|
||||||
|
- name: PGDATA
|
||||||
|
value: /var/lib/postgresql/data/pgdata
|
||||||
|
- name: POSTGRES_USER
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: POSTGRES_SUPERUSER
|
||||||
|
- name: POSTGRES_DB
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: POSTGRES_DEFAULT_DB
|
||||||
|
- name: AUTH_DB_NAME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: AUTH_DB_NAME
|
||||||
|
- name: AUTH_DB_USER
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: AUTH_DB_USER
|
||||||
|
- name: KEYCLOAK_DB_NAME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: KEYCLOAK_DB_NAME
|
||||||
|
- name: KEYCLOAK_DB_USER
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: platform-config
|
||||||
|
key: KEYCLOAK_DB_USER
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: keycloak-public
|
||||||
|
spec:
|
||||||
|
type: ExternalName
|
||||||
|
externalName: traefik.kube-system.svc.cluster.local
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: platform-config
|
||||||
|
data:
|
||||||
|
POSTGRES_SUPERUSER: postgres
|
||||||
|
POSTGRES_DEFAULT_DB: postgres
|
||||||
|
AUTH_DB_NAME: project_auth
|
||||||
|
AUTH_DB_USER: project_auth
|
||||||
|
KEYCLOAK_DB_NAME: keycloak
|
||||||
|
KEYCLOAK_DB_USER: keycloak
|
||||||
|
KEYCLOAK_BOOTSTRAP_ADMIN_USERNAME: admin
|
||||||
|
KEYCLOAK_CLIENT_ID: project-auth-server
|
||||||
|
AUTH_SERVER_BASE_URL: http://auth-server.auth-prod.svc.cluster.local
|
||||||
|
VAULT_TRANSIT_KEY_NAME: project-auth-jwt
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: platform-prod
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- ../../base
|
||||||
|
- namespace.yaml
|
||||||
|
- configmap.yaml
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: platform-prod
|
||||||
|
labels:
|
||||||
|
pod-security.kubernetes.io/enforce: baseline
|
||||||
|
pod-security.kubernetes.io/enforce-version: latest
|
||||||
|
pod-security.kubernetes.io/warn: restricted
|
||||||
|
pod-security.kubernetes.io/warn-version: latest
|
||||||
|
pod-security.kubernetes.io/audit: restricted
|
||||||
|
pod-security.kubernetes.io/audit-version: latest
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: vault-transit
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: vault-transit
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: vault-transit
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: vault-transit
|
||||||
|
image: hashicorp/vault:1.18
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -ec
|
||||||
|
env:
|
||||||
|
- name: VAULT_ADDR
|
||||||
|
value: http://127.0.0.1:8200
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
cp /vault/config/vault.hcl /tmp/vault.hcl
|
||||||
|
exec vault server -config=/tmp/vault.hcl
|
||||||
|
ports:
|
||||||
|
- containerPort: 8200
|
||||||
|
name: http
|
||||||
|
- containerPort: 8201
|
||||||
|
name: cluster
|
||||||
|
volumeMounts:
|
||||||
|
- name: vault-transit-config
|
||||||
|
mountPath: /vault/config
|
||||||
|
readOnly: true
|
||||||
|
- name: vault-transit-data
|
||||||
|
mountPath: /vault/data
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- vault status -address=http://127.0.0.1:8200 >/dev/null 2>&1; code=$?; [ "$code" -eq 0 ] || [ "$code" -eq 2 ]
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- vault status -address=http://127.0.0.1:8200 >/dev/null 2>&1; code=$?; [ "$code" -eq 0 ] || [ "$code" -eq 2 ]
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 15
|
||||||
|
timeoutSeconds: 5
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
volumes:
|
||||||
|
- name: vault-transit-config
|
||||||
|
configMap:
|
||||||
|
name: vault-transit-config
|
||||||
|
defaultMode: 0555
|
||||||
|
- name: vault-transit-data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: vault-transit-data
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
ui = true
|
||||||
|
disable_mlock = true
|
||||||
|
api_addr = "http://vault-transit.vault-transit.svc.cluster.local:8200"
|
||||||
|
cluster_addr = "http://vault-transit.vault-transit.svc.cluster.local:8201"
|
||||||
|
|
||||||
|
listener "tcp" {
|
||||||
|
address = "0.0.0.0:8200"
|
||||||
|
cluster_address = "0.0.0.0:8201"
|
||||||
|
tls_disable = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
storage "raft" {
|
||||||
|
path = "/vault/data"
|
||||||
|
node_id = "vault-transit-dev-0"
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- service.yaml
|
||||||
|
- deployment.yaml
|
||||||
|
- pvc.yaml
|
||||||
|
|
||||||
|
generatorOptions:
|
||||||
|
disableNameSuffixHash: true
|
||||||
|
|
||||||
|
configMapGenerator:
|
||||||
|
- name: vault-transit-config
|
||||||
|
files:
|
||||||
|
- files/vault/vault.hcl
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: vault-transit-data
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: vault-transit
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: vault-transit
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 8200
|
||||||
|
targetPort: 8200
|
||||||
|
- name: cluster
|
||||||
|
port: 8201
|
||||||
|
targetPort: 8201
|
||||||
|
type: ClusterIP
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: vault-transit
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- ../../base
|
||||||
|
- namespace.yaml
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: vault-transit
|
||||||
|
labels:
|
||||||
|
pod-security.kubernetes.io/enforce: baseline
|
||||||
|
pod-security.kubernetes.io/enforce-version: latest
|
||||||
|
pod-security.kubernetes.io/warn: restricted
|
||||||
|
pod-security.kubernetes.io/warn-version: latest
|
||||||
|
pod-security.kubernetes.io/audit: restricted
|
||||||
|
pod-security.kubernetes.io/audit-version: latest
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
ui = true
|
||||||
|
disable_mlock = true
|
||||||
|
api_addr = "http://vault.vault.svc.cluster.local:8200"
|
||||||
|
cluster_addr = "http://vault.vault.svc.cluster.local:8201"
|
||||||
|
|
||||||
|
listener "tcp" {
|
||||||
|
address = "0.0.0.0:8200"
|
||||||
|
cluster_address = "0.0.0.0:8201"
|
||||||
|
tls_disable = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
seal "transit" {
|
||||||
|
address = "http://vault-transit.vault-transit.svc.cluster.local:8200"
|
||||||
|
disable_renewal = "false"
|
||||||
|
key_name = "workload-vault-dev-unseal"
|
||||||
|
mount_path = "transit/"
|
||||||
|
tls_skip_verify = "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
storage "raft" {
|
||||||
|
path = "/vault/data"
|
||||||
|
node_id = "vault-dev-0"
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- vault-serviceaccount.yaml
|
||||||
|
- vault-auth-delegator.clusterrolebinding.yaml
|
||||||
|
- vault-pvc.yaml
|
||||||
|
- vault-service.yaml
|
||||||
|
- vault-deployment.yaml
|
||||||
|
|
||||||
|
generatorOptions:
|
||||||
|
disableNameSuffixHash: true
|
||||||
|
|
||||||
|
configMapGenerator:
|
||||||
|
- name: vault-config
|
||||||
|
files:
|
||||||
|
- files/vault/vault.hcl
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: vault-server-auth-delegator
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: system:auth-delegator
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: vault-server
|
||||||
|
namespace: vault
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: vault
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: vault
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: vault
|
||||||
|
spec:
|
||||||
|
serviceAccountName: vault-server
|
||||||
|
containers:
|
||||||
|
- name: vault
|
||||||
|
image: hashicorp/vault:1.18
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -ec
|
||||||
|
env:
|
||||||
|
- name: VAULT_ADDR
|
||||||
|
value: http://127.0.0.1:8200
|
||||||
|
- name: VAULT_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: vault-transit-seal
|
||||||
|
key: VAULT_TRANSIT_SEAL_TOKEN
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
cp /vault/config/vault.hcl /tmp/vault.hcl
|
||||||
|
exec vault server -config=/tmp/vault.hcl
|
||||||
|
ports:
|
||||||
|
- containerPort: 8200
|
||||||
|
name: http
|
||||||
|
- containerPort: 8201
|
||||||
|
name: cluster
|
||||||
|
volumeMounts:
|
||||||
|
- name: vault-config
|
||||||
|
mountPath: /vault/config
|
||||||
|
readOnly: true
|
||||||
|
- name: vault-data
|
||||||
|
mountPath: /vault/data
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- vault status -address=http://127.0.0.1:8200 >/dev/null 2>&1; code=$?; [ "$code" -eq 0 ] || [ "$code" -eq 2 ]
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- vault status -address=http://127.0.0.1:8200 >/dev/null 2>&1; code=$?; [ "$code" -eq 0 ] || [ "$code" -eq 2 ]
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 15
|
||||||
|
timeoutSeconds: 5
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
volumes:
|
||||||
|
- name: vault-config
|
||||||
|
configMap:
|
||||||
|
name: vault-config
|
||||||
|
defaultMode: 0555
|
||||||
|
- name: vault-data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: vault-data
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: vault-data
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: vault
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: vault
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 8200
|
||||||
|
targetPort: 8200
|
||||||
|
- name: cluster
|
||||||
|
port: 8201
|
||||||
|
targetPort: 8201
|
||||||
|
type: ClusterIP
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: vault-server
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: vault
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- ../../base
|
||||||
|
- namespace.yaml
|
||||||
|
- networkpolicy.yaml
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: vault
|
||||||
|
labels:
|
||||||
|
pod-security.kubernetes.io/enforce: baseline
|
||||||
|
pod-security.kubernetes.io/enforce-version: latest
|
||||||
|
pod-security.kubernetes.io/warn: restricted
|
||||||
|
pod-security.kubernetes.io/warn-version: latest
|
||||||
|
pod-security.kubernetes.io/audit: restricted
|
||||||
|
pod-security.kubernetes.io/audit-version: latest
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: vault-server-default-deny
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: vault
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: vault-server-allow-dns-egress
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: vault
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
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
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: vault-server-allow-transit-egress
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: vault
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: vault-transit
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: vault-transit
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8200
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: vault-server-allow-postgres-egress
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: vault
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: platform
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: postgres
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 5432
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: vault-server-allow-kubernetes-api-egress
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: vault
|
||||||
|
policyTypes:
|
||||||
|
- Egress
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 10.43.0.1/32
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 443
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 10.208.141.98/32
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 6443
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: vault-server-allow-ingress-from-workloads
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: vault
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: auth-dev
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: platform
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8200
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: vault-agent-injector-webhook-ingress
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: vault-agent-injector
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
- ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8080
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: vault-prod
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- ../../base
|
||||||
|
- namespace.yaml
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: vault-prod
|
||||||
|
labels:
|
||||||
|
pod-security.kubernetes.io/enforce: baseline
|
||||||
|
pod-security.kubernetes.io/enforce-version: latest
|
||||||
|
pod-security.kubernetes.io/warn: restricted
|
||||||
|
pod-security.kubernetes.io/warn-version: latest
|
||||||
|
pod-security.kubernetes.io/audit: restricted
|
||||||
|
pod-security.kubernetes.io/audit-version: latest
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
## Vault Transit Dev Bootstrap
|
||||||
|
|
||||||
|
이 문서는 dev 환경의 **unseal provider Vault** 를 Terraform으로 선언적으로 bootstrap 하는 절차를 정리합니다.
|
||||||
|
|
||||||
|
이 Vault는 애플리케이션 secret을 직접 저장하지 않고, 업무용 Vault의 transit auto-unseal provider와 workload seed source 역할만 담당합니다.
|
||||||
|
|
||||||
|
### 준비물
|
||||||
|
|
||||||
|
- `kubectl`
|
||||||
|
- `vault`
|
||||||
|
- `jq`
|
||||||
|
- `terraform`
|
||||||
|
- dev 클러스터에 접근 가능한 kubeconfig
|
||||||
|
|
||||||
|
### 0. 기동 상태 확인
|
||||||
|
|
||||||
|
`init / unseal` 전에 먼저 `vault-transit` pod가 실제로 기동 가능한 상태인지 확인합니다.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n vault-transit get deploy,pods,svc,pvc
|
||||||
|
kubectl -n vault-transit rollout status deploy/vault-transit --timeout=180s
|
||||||
|
```
|
||||||
|
|
||||||
|
정상 기준:
|
||||||
|
|
||||||
|
- `deployment/vault-transit` 이 `1/1 Ready`
|
||||||
|
- pod가 `Running`
|
||||||
|
- `CrashLoopBackOff` 가 아님
|
||||||
|
|
||||||
|
기동이 안 되면 아래를 먼저 봅니다.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n vault-transit describe deployment vault-transit
|
||||||
|
kubectl -n vault-transit logs deploy/vault-transit --tail=200
|
||||||
|
kubectl -n vault-transit get events --sort-by=.lastTimestamp | tail -n 30
|
||||||
|
```
|
||||||
|
|
||||||
|
최근 dev 기준 대표 원인은 아래였습니다.
|
||||||
|
|
||||||
|
- `Cluster address must be set when using raft storage`
|
||||||
|
원인: raft storage 사용 시 `api_addr`, `cluster_addr`, listener `cluster_address` 가 빠져 있었음
|
||||||
|
- `Could not chown /vault/config`
|
||||||
|
원인: ConfigMap mount가 read-only 인데 이미지 entrypoint가 해당 경로를 `chown` 하려 함
|
||||||
|
|
||||||
|
현재 base manifest는 위 이슈를 피하기 위해:
|
||||||
|
|
||||||
|
- `api_addr`, `cluster_addr`, `cluster_address` 추가
|
||||||
|
- service/deployment `8201` cluster 포트 추가
|
||||||
|
- deployment `strategy: Recreate`
|
||||||
|
- `/vault/config/vault.hcl` 을 `/tmp/vault.hcl` 로 복사 후 `vault server` 실행
|
||||||
|
|
||||||
|
형태로 정리되어 있습니다.
|
||||||
|
|
||||||
|
### 1. 포트 포워딩
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl port-forward -n vault-transit svc/vault-transit 18200:8200
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. init / unseal
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export VAULT_ADDR=http://127.0.0.1:18200
|
||||||
|
vault operator init -format=json > .local/vault-transit-dev-init.json
|
||||||
|
vault operator unseal "$(jq -r '.unseal_keys_b64[0]' .local/vault-transit-dev-init.json)"
|
||||||
|
export TF_VAR_vault_token="$(jq -r '.root_token' .local/vault-transit-dev-init.json)"
|
||||||
|
export TF_VAR_vault_addr="$VAULT_ADDR"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Terraform bootstrap
|
||||||
|
|
||||||
|
```bash
|
||||||
|
terraform -chdir=terraform/vault-transit/dev init -input=false
|
||||||
|
terraform -chdir=terraform/vault-transit/dev apply -input=false -auto-approve
|
||||||
|
```
|
||||||
|
|
||||||
|
이 apply 는 아래를 선언적으로 맞춥니다.
|
||||||
|
|
||||||
|
- `kv` / `transit` secrets engine 활성화
|
||||||
|
- workload Vault auto-unseal key 생성
|
||||||
|
- `workload-vault-transit-dev`, `vault-transit-admin-dev`, `vault-transit-automation-dev` policy reconcile
|
||||||
|
- workflow용 `vault-transit-dev-workflow` AppRole reconcile
|
||||||
|
- `vault/vault-transit-seal` Kubernetes Secret 갱신
|
||||||
|
|
||||||
|
필요한 CI credential은 Terraform output 으로 확인합니다.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
terraform -chdir=terraform/vault-transit/dev output workflow_role_id
|
||||||
|
terraform -chdir=terraform/vault-transit/dev output -raw workflow_secret_id
|
||||||
|
```
|
||||||
|
|
||||||
|
이 두 값은 `VAULT_TRANSIT_DEV_ROLE_ID`, `VAULT_TRANSIT_DEV_SECRET_ID` 로 CI secret store 에 저장합니다.
|
||||||
|
|
||||||
|
### 4. 이후 역할
|
||||||
|
|
||||||
|
- 업무용 Vault([vault app](/home/donghyeon/dev/Project-Auth-GitOps/argocd/applications/dev/infra/vault.yaml)) 는 `vault-transit-seal` Secret 의 토큰으로 transit auto-unseal 을 수행합니다.
|
||||||
|
- `vault-transit` provider Vault 자체는 dev/on-prem 전제에서 여전히 **수동 unseal** 입니다.
|
||||||
|
- 수동 bootstrap 은 `terraform/vault-transit/dev`, `terraform/vault/dev` 를 사용합니다.
|
||||||
|
- self-hosted runner routine reconcile 은 provider AppRole 로 로그인한 뒤 `terraform/vault-transit/reconcile`, `terraform/vault/reconcile` 를 차례로 `apply` 합니다.
|
||||||
|
|
||||||
|
### 5. Workload seed 값 입력
|
||||||
|
|
||||||
|
provider Vault는 여전히 workload seed source of truth 이므로, app 비밀값은 한 번 입력해야 합니다.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export VAULT_ADDR=http://127.0.0.1:18200
|
||||||
|
export VAULT_TOKEN="$(vault write -field=token auth/approle/login \
|
||||||
|
role_id="<vault-transit-workflow-role-id>" \
|
||||||
|
secret_id="<vault-transit-workflow-secret-id>")"
|
||||||
|
|
||||||
|
./scripts/vault-transit/dev/populate-workload-seeds.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
이 스크립트는 값을 **프롬프트로 입력받기 때문에 shell history에 실제 secret이 남지 않습니다.**
|
||||||
|
|
||||||
|
주의:
|
||||||
|
|
||||||
|
- 이 스크립트는 `TF_VAR_transit_vault_token` 이 아니라 **`VAULT_TOKEN`** 을 사용합니다.
|
||||||
|
- `VAULT_ADDR` 는 provider Vault 포트포워드인 `http://127.0.0.1:18200` 이어야 합니다.
|
||||||
|
|
||||||
|
`populate-workload-seeds.example.sh` 는 필요한 key 구조를 보여주는 참고용 예시입니다.
|
||||||
|
|
||||||
|
입력 경로는 목적 기준으로 나뉩니다.
|
||||||
|
|
||||||
|
- `kv/dev/workload/platform/postgres/superuser`
|
||||||
|
- `kv/dev/workload/platform/postgres/auth-server`
|
||||||
|
- `kv/dev/workload/platform/postgres/keycloak`
|
||||||
|
- `kv/dev/workload/platform/keycloak/bootstrap-admin`
|
||||||
|
- `kv/dev/workload/platform/keycloak/client-auth-server`
|
||||||
|
|
||||||
|
`kv/dev/workload/bootstrap` 의 workload AppRole credential 은 manual bootstrap 단계의 `terraform/vault/dev` 가 자동으로 씁니다. 사람이 따로 넣지 않습니다.
|
||||||
|
|
||||||
|
### 6. 운영자 토큰이 필요한 경우
|
||||||
|
|
||||||
|
장기 토큰을 Terraform state 에 저장하지 않기 위해 `vault-transit-admin-dev` 토큰은 자동 발급하지 않습니다.
|
||||||
|
직접 점검이 필요하면 privileged token 으로 아래처럼 짧은 토큰을 발급합니다.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export VAULT_ADDR=http://127.0.0.1:18200
|
||||||
|
export VAULT_TOKEN="$TF_VAR_vault_token"
|
||||||
|
|
||||||
|
vault token create -orphan -policy=vault-transit-admin-dev -ttl=1h
|
||||||
|
```
|
||||||
|
|
||||||
|
### 주의
|
||||||
|
|
||||||
|
- manual bootstrap state 는 [`.terraform-state/vault-transit-dev.tfstate`](/home/donghyeon/dev/Project-Auth-GitOps/.terraform-state/vault-transit-dev.tfstate) 에 저장됩니다.
|
||||||
|
- routine reconcile state 는 [`.terraform-state/vault-transit-reconcile.tfstate`](/home/donghyeon/dev/Project-Auth-GitOps/.terraform-state/vault-transit-reconcile.tfstate) 에 저장됩니다.
|
||||||
|
- Vault provider state 에는 민감한 값이 들어가므로 self-hosted runner 와 로컬 작업 디렉터리를 동일하게 보호해야 합니다.
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
path "transit/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "kv/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "sys/internal/ui/mounts/*" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "sys/mounts/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "sys/auth/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "sys/policies/acl/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "auth/approle/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "auth/token/create-orphan" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "auth/token/revoke" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "auth/token/lookup" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
path "transit/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "kv/data/dev/workload/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "kv/metadata/dev/workload/*" {
|
||||||
|
capabilities = ["read", "delete", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "sys/internal/ui/mounts/*" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "sys/mounts/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "sys/auth/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "sys/policies/acl/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "auth/approle/*" {
|
||||||
|
capabilities = ["create", "read", "update", "delete", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "auth/token/create" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "auth/token/create-orphan" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "auth/token/revoke" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "auth/token/revoke-accessor" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "auth/token/lookup" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "auth/token/lookup-accessor" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "auth/token/lookup-self" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
path "transit/encrypt/workload-vault-dev-unseal" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "transit/decrypt/workload-vault-dev-unseal" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "transit/rewrap/workload-vault-dev-unseal" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "transit/keys/workload-vault-dev-unseal" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
vault kv put kv/dev/workload/platform/postgres/superuser \
|
||||||
|
POSTGRES_SUPERUSER_PASSWORD=change-me
|
||||||
|
|
||||||
|
vault kv put kv/dev/workload/platform/postgres/auth-server \
|
||||||
|
APP_DATASOURCE_USERNAME=project_auth \
|
||||||
|
APP_DATASOURCE_PASSWORD=change-me \
|
||||||
|
AUTH_DB_PASSWORD=change-me
|
||||||
|
|
||||||
|
vault kv put kv/dev/workload/platform/postgres/keycloak \
|
||||||
|
KEYCLOAK_DB_PASSWORD=change-me
|
||||||
|
|
||||||
|
vault kv put kv/dev/workload/platform/keycloak/bootstrap-admin \
|
||||||
|
KC_BOOTSTRAP_ADMIN_PASSWORD=change-me
|
||||||
|
|
||||||
|
vault kv put kv/dev/workload/platform/keycloak/client-auth-server \
|
||||||
|
APP_SECURITY_OAUTH2_KEYCLOAK_CLIENT_SECRET=change-me \
|
||||||
|
KEYCLOAK_CLIENT_SECRET=change-me
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
## Vault Dev Bootstrap
|
||||||
|
|
||||||
|
이 문서는 dev 환경의 **workload Vault** 를 Terraform으로 선언적으로 bootstrap / reconcile 하는 절차를 정리합니다.
|
||||||
|
|
||||||
|
이제 책임은 두 단계로 분리합니다.
|
||||||
|
|
||||||
|
- bootstrap
|
||||||
|
- privileged workload token 필요
|
||||||
|
- 수동 runbook 사용
|
||||||
|
- reconcile
|
||||||
|
- bootstrap 완료 후 `vault-dev-reconcile` workflow 가 routine apply 수행
|
||||||
|
|
||||||
|
사전 조건:
|
||||||
|
|
||||||
|
- [vault-transit bootstrap runbook](/home/donghyeon/dev/Project-Auth-GitOps/runbooks/vault-transit/dev/README.md) 을 먼저 완료해야 합니다.
|
||||||
|
- `vault` namespace에 `vault-transit-seal` Secret 이 준비되어 있어야 workload Vault 가 auto-unseal 됩니다.
|
||||||
|
|
||||||
|
현재 저장소의 source of truth 는 아래 두 Terraform 루트로 분리합니다.
|
||||||
|
|
||||||
|
- bootstrap/manual: `terraform/vault/dev`
|
||||||
|
- reconcile/CI: `terraform/vault/reconcile`
|
||||||
|
|
||||||
|
`bootstrap-runbook.sh` 는 bootstrap 루트를, routine workflow 는 reconcile 루트를 호출합니다.
|
||||||
|
|
||||||
|
### 준비물
|
||||||
|
|
||||||
|
- `kubectl`
|
||||||
|
- `vault`
|
||||||
|
- `jq`
|
||||||
|
- `terraform`
|
||||||
|
- dev 클러스터에 접근 가능한 kubeconfig
|
||||||
|
|
||||||
|
### 1. Vault 포트 포워딩
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl port-forward -n vault svc/vault 8200:8200
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Vault init / bootstrap token 준비
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export VAULT_ADDR=http://127.0.0.1:8200
|
||||||
|
vault operator init -format=json > .local/vault-dev-init.json
|
||||||
|
export TF_VAR_workload_vault_addr="$VAULT_ADDR"
|
||||||
|
export TF_VAR_workload_vault_token="$(jq -r '.root_token' .local/vault-dev-init.json)"
|
||||||
|
```
|
||||||
|
|
||||||
|
Transit auto-unseal 구조이므로 정상 상태에서는 `vault operator unseal` 을 반복하지 않습니다.
|
||||||
|
|
||||||
|
### 3. Provider seed credential 연결
|
||||||
|
|
||||||
|
workload Terraform 은 provider Vault 에서 seed 값을 읽고, 생성한 workload workflow AppRole credential 을 다시 provider Vault bootstrap path 로 써넣습니다.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export TF_VAR_transit_vault_addr=http://127.0.0.1:18200
|
||||||
|
export TF_VAR_transit_vault_token="$(VAULT_ADDR="$TF_VAR_transit_vault_addr" vault write -field=token auth/approle/login \
|
||||||
|
role_id="<vault-transit-workflow-role-id>" \
|
||||||
|
secret_id="<vault-transit-workflow-secret-id>")"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Terraform bootstrap
|
||||||
|
|
||||||
|
```bash
|
||||||
|
terraform -chdir=terraform/vault/dev init -input=false
|
||||||
|
terraform -chdir=terraform/vault/dev apply -input=false -auto-approve
|
||||||
|
```
|
||||||
|
|
||||||
|
이 apply 는 아래를 선언적으로 맞춥니다.
|
||||||
|
|
||||||
|
- `kv`, `database`, `transit` mount 활성화
|
||||||
|
- Kubernetes auth backend / role reconcile
|
||||||
|
- AppRole backend / workflow AppRole reconcile
|
||||||
|
- dev runtime KV 를 provider Vault seed 에 맞춰 동기화
|
||||||
|
- JWT transit key 생성
|
||||||
|
- Postgres database backend / dynamic role 정의
|
||||||
|
- `kv/dev/workload/bootstrap` 에 workload workflow AppRole credential publish
|
||||||
|
|
||||||
|
필요하면 output 으로 workload workflow AppRole 값을 직접 확인할 수 있습니다.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
terraform -chdir=terraform/vault/dev output workflow_role_id
|
||||||
|
terraform -chdir=terraform/vault/dev output -raw workflow_secret_id
|
||||||
|
```
|
||||||
|
|
||||||
|
### 정책 분리
|
||||||
|
|
||||||
|
현재 dev 정책은 아래처럼 역할별로 나눕니다.
|
||||||
|
|
||||||
|
- `auth-server-dev`
|
||||||
|
이유: 앱 런타임은 `platform/postgres/auth-server`, `platform/keycloak/client-auth-server`, JWT transit signing만 접근하면 충분합니다.
|
||||||
|
- `auth-db-migration-dev`
|
||||||
|
이유: migration job 은 `database/creds/auth-db-migration-dev` 로 짧은 DB credential 을 받아 실행합니다.
|
||||||
|
- `postgres-dev`
|
||||||
|
이유: DB pod 는 `platform/postgres/superuser`, `platform/postgres/auth-server`, `platform/postgres/keycloak` 만 읽으면 됩니다.
|
||||||
|
- `keycloak-dev`
|
||||||
|
이유: Keycloak pod 는 `platform/postgres/keycloak`, `platform/keycloak/bootstrap-admin` 만 읽으면 됩니다.
|
||||||
|
- `keycloak-client-sync-dev`
|
||||||
|
이유: client sync job 은 `platform/keycloak/bootstrap-admin`, `platform/keycloak/client-auth-server` 만 읽으면 됩니다.
|
||||||
|
- `workload-automation-dev`
|
||||||
|
이유: Terraform apply 가 policy, role, auth, transit, KV, AppRole, database 설정을 모두 reconcile 합니다.
|
||||||
|
- `platform-admin-dev`
|
||||||
|
이유: 사람이 비상 복구나 수동 운영 작업을 할 때 쓰는 운영자 정책입니다.
|
||||||
|
- `postgres-operator-dev`
|
||||||
|
이유: 사람이 dev DB 에 직접 접속할 때는 `database/creds/postgres-operator-dev` 만 읽는 짧은 토큰으로 제한합니다.
|
||||||
|
- `keycloak-operator-dev`
|
||||||
|
이유: 사람이 Keycloak 에 직접 로그인할 때는 bootstrap admin credential 만 읽는 짧은 토큰으로 제한합니다.
|
||||||
|
|
||||||
|
### 자동화용 CI Secret
|
||||||
|
|
||||||
|
`vault-dev-reconcile` workflow 를 사용하려면 최소 아래 secret 이 필요합니다.
|
||||||
|
|
||||||
|
- `KUBECONFIG_DEV_B64`
|
||||||
|
- `VAULT_TRANSIT_DEV_ROLE_ID`
|
||||||
|
- `VAULT_TRANSIT_DEV_SECRET_ID`
|
||||||
|
|
||||||
|
권장 흐름은 아래와 같습니다.
|
||||||
|
|
||||||
|
1. `vault-transit` runbook 으로 provider Vault 를 1회 init / unseal / bootstrap 합니다.
|
||||||
|
2. provider Vault 에 app seed 값을 입력합니다.
|
||||||
|
3. workload Vault 를 1회 init 합니다.
|
||||||
|
4. `terraform/vault/dev` 를 root token 으로 1회 apply 합니다.
|
||||||
|
5. 이 apply 가 workload workflow AppRole credential 을 `kv/dev/workload/bootstrap` 에 써넣습니다.
|
||||||
|
6. 이후부터는 workflow 가 provider bootstrap 확인, `terraform/vault/reconcile` apply, Argo CD app apply 를 자동 수행합니다.
|
||||||
|
|
||||||
|
bootstrap용 privileged token은 GitHub secret에 올리지 않고 운영자 로컬에서만 사용하는 것을 권장합니다.
|
||||||
|
|
||||||
|
### 정적 seed 로 최초 1회 넣어야 하는 값
|
||||||
|
|
||||||
|
아래 값들은 최초 1회 사람이 입력하거나 상위 secret source 에서 sync 해야 합니다.
|
||||||
|
|
||||||
|
- `kv/dev/workload/platform/postgres/superuser`
|
||||||
|
값: `POSTGRES_SUPERUSER_PASSWORD`
|
||||||
|
- `kv/dev/workload/platform/postgres/auth-server`
|
||||||
|
값: `APP_DATASOURCE_USERNAME`, `APP_DATASOURCE_PASSWORD`, `AUTH_DB_PASSWORD`
|
||||||
|
- `kv/dev/workload/platform/postgres/keycloak`
|
||||||
|
값: `KEYCLOAK_DB_PASSWORD`
|
||||||
|
- `kv/dev/workload/platform/keycloak/bootstrap-admin`
|
||||||
|
값: `KC_BOOTSTRAP_ADMIN_PASSWORD`
|
||||||
|
- `kv/dev/workload/platform/keycloak/client-auth-server`
|
||||||
|
값: `APP_SECURITY_OAUTH2_KEYCLOAK_CLIENT_SECRET`, `KEYCLOAK_CLIENT_SECRET`
|
||||||
|
|
||||||
|
이 값들은 provider Vault seed path 가 source of truth 이고, workload Terraform apply 가 이를 workload Vault KV 로 동기화합니다.
|
||||||
|
|
||||||
|
### 사람 직접 접근용 토큰 발급
|
||||||
|
|
||||||
|
장기 운영자 토큰은 Terraform state 에 저장하지 않습니다.
|
||||||
|
필요할 때 privileged token 으로 `platform-admin-dev` 토큰을 짧게 발급한 뒤 아래 스크립트를 사용합니다.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export VAULT_ADDR=http://127.0.0.1:8200
|
||||||
|
export VAULT_TOKEN=<privileged-token>
|
||||||
|
|
||||||
|
vault token create -orphan -policy=platform-admin-dev -ttl=1h
|
||||||
|
```
|
||||||
|
|
||||||
|
발급된 `platform-admin-dev` 토큰으로:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export VAULT_TOKEN=<platform-admin-dev-token>
|
||||||
|
./scripts/vault/dev/issue-operator-tokens.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
이후:
|
||||||
|
|
||||||
|
- `postgres-operator-dev`: `vault read database/creds/postgres-operator-dev`
|
||||||
|
- `keycloak-operator-dev`: `vault kv get kv/dev/platform/keycloak/bootstrap-admin`
|
||||||
|
|
||||||
|
를 수행해 dev 접속 정보를 확인할 수 있습니다.
|
||||||
|
|
||||||
|
### 주의
|
||||||
|
|
||||||
|
- manual bootstrap state 는 [`.terraform-state/vault-dev.tfstate`](/home/donghyeon/dev/Project-Auth-GitOps/.terraform-state/vault-dev.tfstate) 에 저장됩니다.
|
||||||
|
- routine reconcile state 는 [`.terraform-state/vault-reconcile.tfstate`](/home/donghyeon/dev/Project-Auth-GitOps/.terraform-state/vault-reconcile.tfstate) 에 저장됩니다.
|
||||||
|
- Vault provider state 에는 민감한 값이 들어가므로 self-hosted runner 와 로컬 작업 디렉터리를 동일하게 보호해야 합니다.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
path "database/creds/auth-db-migration-dev" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
path "kv/data/dev/platform/postgres/auth-server" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "kv/data/dev/platform/keycloak/client-auth-server" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "transit/keys/project-auth-jwt" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "transit/sign/project-auth-jwt" {
|
||||||
|
capabilities = ["update"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
path "kv/data/dev/platform/keycloak/bootstrap-admin" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "kv/data/dev/platform/keycloak/client-auth-server" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
path "kv/data/dev/platform/postgres/keycloak" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "kv/data/dev/platform/keycloak/bootstrap-admin" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user