본문 바로가기
CI&CD

[CI/CD] OpenLDAP + KeyCloak + Argo CD + Jenkins 구축 과정

by interlude-3 2025. 11. 23.

1. [wsl2 + kind] myk8s 클러스터 및 ingress 배포

  • SSL Passthrough flag 활성화

# kubectl describe -n ingress-nginx deployments/ingress-nginx-controller

...

Args:
      /nginx-ingress-controller
      --election-id=ingress-nginx-leader
      --controller-class=k8s.io/ingress-nginx
      --ingress-class=nginx
      --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
      --validating-webhook=:8443
      --validating-webhook-certificate=/usr/local/certificates/cert
      --validating-webhook-key=/usr/local/certificates/key
      --watch-ingress-without-class=true
      --publish-status-address=localhost
      --enable-ssl-passthrough

...

 

2. Jenkins 배포

  • C:\Windows\System32\drivers\etc\hosts 관리자모드 메모장에 "127.0.0.1 jenkins.example.com" 추가
  • https://jenkins.example.com 접속 확인

 

3. ArgoCD 배포

[Argo CD TLS 동작]

  • OpenSSL로 self-signed 인증서 생성 및 Secrets 생성
  • Argo CD 서버는 TLS 인증서를 "argocd-server-tls" Secret 에서 직접 로드
    • server.ingress.tls=true
  • Ingress는 TLS를 종료하지 않고 그대로 Pod에게 전달
    • nginx.ingress.kubernetes.io/ssl-passthrough=true
    • 브라우저 → Ingress → Argo CD Server 까지 end-to-end HTTPS가 유지됨

 

# kubectl get ingress -n argocd argocd-server -o yaml |yq

...

"annotations": {
      "meta.helm.sh/release-name": "argocd",
      "meta.helm.sh/release-namespace": "argocd",
      "nginx.ingress.kubernetes.io/force-ssl-redirect": "true",
      "nginx.ingress.kubernetes.io/ssl-passthrough": "true"
    },

...

"spec": {
    "ingressClassName": "nginx",
    "rules": [
      {
        "host": "argocd.example.com",
        "http": {
          "paths": [
            {
              "backend": {
                "service": {
                  "name": "argocd-server",
                  "port": {
                    "number": 443
                  }
                }
              },
              "path": "/",
              "pathType": "Prefix"
            }
          ]
        }
      }
    ],
    "tls": [
      {
        "hosts": [
          "argocd.example.com"
        ],
        "secretName": "argocd-server-tls"
      }
    ]
  },

  • C:\Windows\System32\drivers\etc\hosts 관리자모드 메모장에 "127.0.0.1 argocd.example.com" 추가

 

4. KeyCloak 배포

  • C:\Windows\System32\drivers\etc\hosts 관리자모드 메모장에 "127.0.0.1 keycloak.example.com" 추가

  • realm 생성

  • password 설정

  • CoreDNS 컨피그맵에 jenkins, argocd, keyclock 도메인 지정

# kubectl edit cm -n kube-system coredns

...

hosts {
          10.96.16.142 jenkins.example.com
          10.96.231.225 argocd.example.com
          10.96.115.111 keycloak.example.com
          fallthrough
        }

...

 

5. SSO (OIDC) 설정

5-1. jenkins client

  • [keycloak] 클라이언트 등록

  • [jenkins] openid 플러그인 설치

  • [jenkins] Security Realm 설정

  • keycloak기반 jenkins 로그인

 

 

5-2. argocd client

  • [keycloak] 클라이언트 등록

  • [argocd] client 시크릿 설정

# kubectl get secret -n argocd argocd-secret -o jsonpath='{.data}' | jq

{
  "admin.password": "JDJhJDEwJElqZWQyLkU1bEhvT2wyNUFNdDJDVHU1ZlA3czZpV0xjUkZScGxDamFNSm96czl6cS9ESzB5",
  "admin.passwordMtime": "MjAyNS0xMS0yMlQxNzowNDoyNlo=",
  "oidc.keycloak.clientSecret": "bUQzWTl3N0NpQmpnUDhPbUl3MDRpcm9FdzhISDA5dWM=",
  "server.secretkey": "b3AzcDBiOHY0bGY2d3VQK2t2VlZSOHh3OWtTeklhY0dsSStDOFpjY010Zz0="
}

 

# kubectl get cm -n argocd argocd-cm -o yaml | grep oidc.config: -A5

oidc.config: |
    name: Keycloak
    issuer: http://keycloak.example.com/realms/myrealm
    clientID: argocd
    clientSecret: mD3Y9w7CiBjgP8OmIw04iroEw8HH09uc
    requestedScopes: ["openid", "profile", "email"]

 

  • keycloak기반 argocd 로그인

 

6. OpenLDAP 배포

  • http://127.0.0.1:30000 접속

  • 조직도 구성
dc=example,dc=org
├── ou=people
│   ├── uid=alice
│   │   ├── cn: Alice
│   │   ├── sn: Kim
│   │   ├── uid: alice
│   │   └── mail: alice@example.org
│   └── uid=bob
│       ├── cn: Bob
│       ├── sn: Lee
│       ├── uid: bob
│       └── mail: bob@example.org
└── ou=groups
    ├── cn=devs
    │   └── member: uid=bob,ou=people,dc=example,dc=org
    └── cn=admins
        └── member: uid=alice,ou=people,dc=example,dc=org
  • ldapadd로 ou, users, groups 추가
root@openldap-54857b746c-jx76l:/# ldapsearch -x -D "cn=admin,dc=example,dc=org" -w admin \
>   -b "dc=example,dc=org" "(objectClass=organizationalUnit)" ou
# extended LDIF
#
# LDAPv3
# base <dc=example,dc=org> with scope subtree
# filter: (objectClass=organizationalUnit)
# requesting: ou
#

# people, example.org
dn: ou=people,dc=example,dc=org
ou: people

# groups, example.org
dn: ou=groups,dc=example,dc=org
ou: groups

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2

root@openldap-54857b746c-jx76l:/# ldapsearch -x -D "cn=admin,dc=example,dc=org" -w admin \
>   -b "ou=people,dc=example,dc=org" "(uid=*)" uid cn mail
# extended LDIF
#
# LDAPv3
# base <ou=people,dc=example,dc=org> with scope subtree
# filter: (uid=*)
# requesting: uid cn mail
#

# bob, people, example.org
dn: uid=bob,ou=people,dc=example,dc=org
cn: Bob
uid: bob
mail: bob@example.org

# alice, people, example.org
dn: uid=alice,ou=people,dc=example,dc=org
cn: Alice
uid: alice
mail: alice@example.org

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2

root@openldap-54857b746c-jx76l:/# ldapsearch -x -D "cn=admin,dc=example,dc=org" -w admin \
 "ou=gr>   -b "ou=groups,dc=example,dc=org" "(objectClass=groupOfNames)" cn member
# extended LDIF
#
# LDAPv3
# base <ou=groups,dc=example,dc=org> with scope subtree
# filter: (objectClass=groupOfNames)
# requesting: cn member
#

# devs, groups, example.org
dn: cn=devs,ou=groups,dc=example,dc=org
cn: devs
member: uid=bob,ou=people,dc=example,dc=org

# admins, groups, example.org
dn: cn=admins,ou=groups,dc=example,dc=org
cn: admins
member: uid=alice,ou=people,dc=example,dc=org

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2

root@openldap-54857b746c-jx76l:/# ldapwhoami -x -D "uid=alice,ou=people,dc=example,dc=org" -w alice123
dn:uid=alice,ou=people,dc=example,dc=org

  • keycloak 연동
    => "User Federation” 으로 LDAP과 연동하여 사용자 정보 동기화

  • bob 사용자로 로그인 확인