본문 바로가기
CICD/Jenkins

Kubernetes Secret으로 Jenkins Credentials 안전하게 관리하기 (with External Secrets Operator)

by wlsdn3004 2025. 3. 27.
728x90
반응형

 

개요

Jenkins를 운영하다 보면 빌드 및 배포 과정에서 다양한 Credentials을 사용하게 되는데, Credentials이 많아지면 수동으로 관리하기엔 번거롭고 보안상의 위험이 높아져 관리의 리스크가 커진다.

 
이러한 문제를 해결하기 위해 Jenkins의 Kubernetes Credentials Provider 플러그인과 External Secrets Operator(ESO)를 활용할 수 있는데, ESO를 통해 AWS Secrets Manager, HashiCorp Vault, Google Secret Manager와 같은 외부 비밀 저장소와 Kubernetes Secret을 자동으로 동기화하여 Credentials를 보다 안전하고 효율적으로 관리할 수 있다.

 

아래 그림은 External Secrets Operator(ESO)가 IRSA(IAM Roles for Service Accounts)를 활용하여 AWS Secrets Manager에 접근할 수 있는 권한을 얻고, 저장된 Secret 값을 가져와 Kubernetes Secret을 생성한 후, 이를 기반으로 Jenkins에서 Kubernetes Credentials Provider 플러그인을 사용하여 Jenkins Credentials를 자동으로 동기화하는 과정을 보여준다.

본 글에서는 실습을 통해 위 그림과 같이 구성하는 과정을 다룬다.

 

구성 환경

  • Amazon EKS: 1.30
  • Helm CLI: 3.17.2
  • Jenkins: 2.480
  • ESO Helm Chart APP : 0.15.0

설치 버전

  • Jenkins Plugin
    • Kubernetes Credentials Provider : 1.276.v99a_de03cb_076

전제 조건

 

 

1. Kubernetes Credentials Provider 플러그인 설치


먼저, Kubernetes 클러스터에 저장된 Secret을 Jenkins에서 사용할 수 있도록 "Kubernetes Credentials Provider" 플러그인을 설치한다.

  • Jenkins Dashboard > Jenkins 관리 > Plugins 

 

플러그인 설치가 완료되면 Jenkins 재시작을 위해 다음과 같이 체크박스를 체크한다.

 

다음 경로로 이동하면 Kubernetes Store가 생성된 것을 확인할 수 있다.

  • Jenkins Dashboard > Jenkins 관리 > Credentials

 

이제부터 Kubernetes Secrets에 추가 설정을 하면, 해당 설정이 Kubernetes Store Credentials에 자동으로 등록된다.

 

 

2. ESO(External Secrets Operator) 설정 & Kubernetes Secrets 생성


AWS Secrets Manager를 통해 Kubernetes Secrets이 생성될 수 있도록 ESO 관련 구성을 해야 한다.

 

AWS Secrets Manager와 연결하기 위해 다음과 같이 ClusterSecretStore 리소스를 배포한다.

apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: secretstore-sample-test
spec:
  provider:
    aws:
      service: SecretsManager
      region: ap-northeast-2
      auth:
        jwt:
          serviceAccountRef:
            name: external-secrets
            namespace: external-secrets

 

ClusterSecretStore 리소스가 정상적으로 생성되었는지 확인한다.

$ kubectl get clustersecretstores.external-secrets.io
NAME                      AGE   STATUS   CAPABILITIES   READY
secretstore-sample-test   9s    Valid    ReadWrite      True

 

AWS Secrets Manager의 Secret이 생성될 수 있도록 ExternalSecret 리소스를 배포한다.

아래 YAML에서 각 환경에 맞는 AWS Secrets Manager 이름과 Key Name을 입력해야 한다.

target의 template 하위 내용은 앞서 설치한 Jenkins의 "Kubernetes Credentials Provider 플러그인"을 사용하여 Jenkins Credentials를 생성하는 방법이다.

  • labels: Jenkins Credentials 타입을 입력한다. usernamePassword, secretText 등을 설정할 수 있다.
  • annotations: Jenkins Credentials의 description 내용을 입력한다.

방법 1

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: example
  namespace: jenkins
spec:
  refreshInterval: 1m
  secretStoreRef:
    name: secretstore-sample-test
    kind: ClusterSecretStore
  target:
    name: secrets-manager-key1
    template:
      metadata:
        labels:
          "jenkins.io/credentials-type": "secretText"
        annotations:
          "jenkins.io/credentials-description": "Secrets Manager Key"
      data:
        text: "{{ .key }}"
  data:
  - secretKey: key
    remoteRef:
      key: {AWS Secret Manager name}
      property: {AWS Secret Manager key name}

 

방법 2

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: example
  namespace: jenkins
spec:
  refreshInterval: 1m
  secretStoreRef:
    name: secretstore-sample-test
    kind: ClusterSecretStore
  target:
    name: secrets-manager-key1
    template:
      metadata:
        labels:
          "jenkins.io/credentials-type": "secretText"
        annotations:
          "jenkins.io/credentials-description": "Secrets Manager Key"
      data:
        text: "{{ .AWS_Secret_Manager_key_name }}"
  dataFrom:
    - extract:
        key: {AWS Secret Manager name}

참고

Kubernetes Secrets에서 labels과 annotations 설정을 통해 Credentials을 사용하는 방법에 대한 다양한 예제는 여기를 참고한다.

 

ExternalSecret 리소스 생성 후 target의 name에 지정한 이름으로 Kubernetes Secret이 생성되었는지 확인한다.

$ kubectl get secrets -n jenkins secrets-manager-key1
NAME                   TYPE     DATA   AGE
secrets-manager-key1   Opaque   1      11m

 

Kubernetes Secret의 내용을 확인하고, 실제 AWS Secrets Manager의 정보와 동일한지 비교한다.

$ kubectl get secrets -n jenkins secrets-manager-key1 -ojsonpath="{.data.text}" | base64 -d

 

 

3. Jenkins Credentials 확인 및 검증


ExternalSecret 리소스에서 설정한 내용에 맞게 Jenkins Credentials가 생성되었는지 확인해 보자.

다음 경로로 이동하여 확인한다.

  • Jenkins Dashboard > Jenkins 관리 > Credentials

설정에 맞게 Kubernetes Store에 Credentials이 생성된 것을 확인할 수 있다.

생성된 Jenkins Credentials이 실제 AWS Secrets Manager의 정보와 동일한지 확인해 보자.

 

Credentials 값은 기본적으로 파이프라인에서 마스킹(***) 되어 표시되기 때문에 직접 확인할 수 없다.

하지만 Jenkins에서 제공하는 "Script Console"을 사용하면 이를 확인할 수 있다.

Script Console

Script Console은 Jenkins 서버에서 Groovy 스크립트를 실행할 수 있는 도구이다. 관리자 권한을 가진 사용자만 접근할 수 있으며, Jenkins 인스턴스의 상태를 확인하고 설정 변경 및 문제를 디버깅하는 데 사용될 수 있다.

 

Groovy 스크립트를 다음과 같이 입력 후 실행하면, Credentials에 설정된 값을 확인할 수 있다. 각 환경에 맞는 Credentials ID를 입력 후 실행하면 된다.

  • Jenkins Dashboard > Jenkins 관리 > Script Console
import com.cloudbees.plugins.credentials.CredentialsProvider
import jenkins.model.Jenkins
import org.jenkinsci.plugins.plaincredentials.StringCredentials
import hudson.util.Secret

def allCredentials = CredentialsProvider.lookupCredentials(
    com.cloudbees.plugins.credentials.Credentials.class,
    Jenkins.instance,
    null,
    []
)

allCredentials.each { cred ->
    if (cred instanceof StringCredentials && cred.id == '{Credentials ID 입력}') {
        println "ID: ${cred.id}"
        println "Type: ${cred.getClass().simpleName}"
        println "Value: ${cred.secret.plainText}"
        println "-------------------"
    }
}

 

결과는 Value 항목에서 확인할 수 있다.

 

값이 일치한 지 확인한 후 AWS Secrets Manager에서 값을 변경하고 앞서 실행한 Groovy 스크립트를 다시 실행하면 변경된 값이 출력되는 것을 확인할 수 있을 것이다.

반응형

댓글