Vault Secret Operator로 Gitops 보안 강화하기

Glen·2025년 1월 14일
0
post-thumbnail

회사에서 EKS에 CWPP를 배포할수있는 소중한 기회를 얻었다.
( 도입해준 회사에 무한한 감사를 )

github에 helm chart 올리고 argocd로 배포할 생각인데...


key값들을 그냥 vaule에 박아서 사용하라네..?

회사에선 vault를 사용중이었기 때문에 혹시 몰라 업체에 연락해서 지원되는지 물어봤는데 지원은 안해준다고 답변을 받았다.

기존 helm chart를 손보고 vault injector로 secret, configmap을 안쓰도록 해봤는데 잘안되더라.

그래서 생각한게 처음에는 sealed secret 이었다.

  • 커피고래님 블로그

설치는 꽤나 간편했고 사용하는 것도 딱히 어렵진 않았다.

  • sealed secret이 kubernetes secret을 생성

하지만 결국에 secret을 쓰는건 똑같았다.

마치 뫼비우스 띠에 갇힌 느낌이랄까?

sops 쓰는것 마냥 로컬에서 sealed secret controller로 암호화 해줘야하는것도 생각보다 번거로운 일이었고

인프라팀에게 내용 공유해드렸더니, 이미 사용중인 vault가 있는데 또 관리해야할 리소스를 만드는게 맞는가 싶다고 하셨다.

내용을 듣다보니 맞는말이네? ㅋㅋㅋㅋㅋㅋ

그러면서 vault secret operator를 공유해주셨다.

내용을 훑어보니 sealed secret이랑 크게 다르진 않아 보였다.

차이점은 인증 방식 정도?

오히려 세팅만 잘하면 관리자 입장에선 sealed secret처럼 번거롭게 암호화 과정을 거치치 않아도 되는게 좋아 보였다.

그럼 뭐다?

바로 테스트 해봤다.

설정

VSO

  • helm 으로 설치 진행한다.
    • 로컬에는 accesskey가 없고 aws-vault를 사용
    • vault와 배포할 앱이 같은 클러스터에 있기 때문에 address를 core-dns를 사용했다.
aws-vault exec dev -- helm install --namespace <namespace> <resource-name> hashicorp/vault-secrets-operator \
--set "defaultVaultConnection.enabled=true" \
--set "defaultVaultConnection.address=http://vault-internal.vault.svc.cluster.local:8200"
  • crd 확인

  • controller 확인

  • connection 확인
    • 설치시 set 옵션으로 설정. 이게 없으면 secret 생성 안됨.

Role

  • kubernetes role을 사용한다.

    • vault와 배포할 앱이 같은 클러스터이기 때문에 coredns로 지정.
  • role을 사용할 sa, sa ns도 지정.

    • audience도 추가함.

yaml

vaultauth

apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
  name: test-vault-auth
  namespace: {{ .Release.Namespace }}
spec:
  method: kubernetes   
  mount: kubernetes 
  kubernetes:
    role: test-role   # vault role name
    serviceAccount: security-sa # secret을 사용할 앱에서 만들어질 SA Name(vault role에 입력했던 것과 동일해야함)
    audiences:        # role을 생성할 때 넣었던 audience 값 입력
      - security

VaultStaticSecret

  • destination type 확인할것.
    • default는 opaque
apiVersion: secrets.hashicorp.com/v1beta1 
kind: VaultStaticSecret 
metadata:
  name: {{ include "EDR.fullname" . }}-vault-static-secret
  namespace: {{ .Release.Namespace }}
spec:
  type: kv-v2                  # type

  # mount path
  mount: security              # Secret Engine name

  # path of the secret
  path: dockerconfigjson          

  # dest k8s secret
  destination:
    name: {{ include "EDR.fullname" . }}-pull-secret    # kubernetes secret으로 생성할 kubernetes secret name 입력
    create: true                                        # kubernetes secret으로 생성여부
    type: kubernetes.io/dockerconfigjson                # imagepullsecret 일때는 명시필요함. 

  # static secret refresh interval
  refreshAfter: 60s         

  # Name of the CRD to authenticate to Vault
  vaultAuthRef: {{ include "EDR.fullname" . }}-vault-auth 

deployment

# 기존에 envfrom > confimapRef로 설정되어있던걸 secretRef로 변경
# env: 환경 변수를 세밀하게 설정하거나 개별적으로 관리하고 싶을 때 사용.
# envFrom: ConfigMap 또는 Secret의 모든 키-값 쌍을 환경 변수로 가져올 때 사용.
      - envFrom:
        - secretRef:
            name: {{ include "EDR.fullname" . }}-config

테스트 결과

  • vaultauth로 인증하여 staticsecret이 kubernetes secret을 생성하는것을 확인 할 수 있다.



문제점 발견


역시나 테스트환경과 운영환경의 일치가 중요하다는것을 한번더 깨닫는다.


앞서 진행한 테스트는 vault와 앱을 배포할 클러스터가 같았다.

근데 실제 운영환경은 서로 다른 클러스터에 있었다.

PUT https://vault.com/v1/auth/kubernetes/login
Code: 403. Errors: * permission denied"

배포해보려고 하니 위와 같이 permission denied가 발생했다.

kubernetes role에 도메인도 바꿔보고, ca, token 값도 변경해봤으나 동일했다.

Kubernetes auth method Doc를 차근차근 읽어보고 답을 찾을수 있었다

https://developer.hashicorp.com/vault/docs/auth/kubernetes#use-the-vault-client-s-jwt-as-the-reviewer-jwt


kubernetes api 서버가 인증요청을 처리할때 특정 주체에게 권한을 위임할수 있도록 서비스 어카운트에 system:auth-delegator 권한을 바인딩 해줘야 했다.

  • 아래는 예시
kubectl create clusterrolebinding vault-client-auth-delegator \
    --clusterrole=system:auth-delegator \
    --group=group1 \
    --serviceaccount=default:svcaccount1 \
    ...

그래서 VaultAuth에서 사용하는 SA에 ClusterRoleBinding을 구성하도록 HelmChart에 template을 추가했다.


ClusterRoleBinding 해주고 StaticSecret을 확인해보면 아까전에는 Permission Denied가 뜨던게 synced 됐다고 보인다.

이로써 gitops 환경에 key값을 하드코딩 하지 않고 secret으로 사용할 수 있게 되었다.

알게된점

  • vault도 secret operator를 제공해준다.
  • deployment의 env, envfrom의 차이점
  • dockerconfigjson은 type이 맞지 않으면 인식하지 못한다.
  • system:auth-delegator와 SA의 ClusterRoleBinding 필요
profile
어제보다 나은 엔지니어가 되기 위해서 공부중

0개의 댓글