K8S는 Secrets라는 리소스를 통해서 애플리케이션에 필요로하는 민감한 정보를 저장하고 관리할 수 있는 인터페이스를 제공하고 있습니다. 하지만 Kubernetes의 Secrets는 AWS Secrets Manager와 같은 외부 Secret 관리 system과 연동되지 않기 때문에 외부 Secret관리 System이 가지고 있는 기능들을 활용하지 못한다는 단점이 있습니다. K8s의 External Secrets는 이런 단점을 보완하기 위해 만들어진 System 입니다.
kubernetes-external-secrets
Example Architecture
- NodeJS 기반의 ExternalSecrets CRD를 통해 Backend의 Secret 저장소들과 연동
- AWS Secrets Manager, AWS Parameter Store, Hashicorp Vault, AKS, GKS, Alibaba 등의 Secret Manager와 연동
- 사용이 간편하며 기존 Secret Object를 사용하는 Pod들의 변경없이 사용 가능
- IAM Integration
- AWS 내부 EKS Slack Channel 및 Discussion 사이트 확인 결과 가장 많이 사용되고 있으며 가장 많이추천하고 있었음
External Secrets Controller가 External Secrets Resource에 해당되는 Key를 AWS Secrets Manager로 부터 가져와서 K8s Pod Secrets에 저장합니다.
AWS Secretes Manager
# Check Sample AWS SecretsManager $ aws secretsmanager list-secrets { "SecretList": [ { "ARN": "arn:aws:secretsmanager:ap-northeast-2:373394553405:secret:db-credential-SSstNC", "Name": "db-credential", "Description": "RDS Credential", "LastChangedDate": "2021-04-04T09:00:01.123000+09:00", "LastAccessedDate": "2021-04-04T09:00:00+09:00", "Tags": [], "SecretVersionsToStages": { "48ca88d2-badf-4a6a-bd2a-4ddaab0cc52a": [ "AWSCURRENT" ] } } ] } $ aws secretsmanager get-secret-value --secret-id db-credential { "ARN": "arn:aws:secretsmanager:ap-northeast-2:373394553405:secret:db-credential-SSstNC", "Name": "db-credential", "VersionId": "48ca88d2-badf-4a6a-bd2a-4ddaab0cc52a", "SecretString": "{\"username\":\"admin\",\"password\":\"woowaP@$$w0rd\",\"engine\":\"mysql\",\"host\":\"database-1.cducwci7wujy.ap-northeast-2.rds.amazonaws.com\",\"port\":3306,\"dbInstanceIdentifier\":\"database-1\"}", "VersionStages": [ "AWSCURRENT" ], "CreatedDate": "2021-03-24T15:54:49.662000+09:00" } |
External Secrets 권한 설정
External Secrets Controller가 Secrets를 가져오고 업데이트하는 등의 동작을 담당하고 있기 때문에 권한을 할당해야 하는 것도 External Secrets Controller의 임무입니다. 어떤 권한을 설정해야 하는지 알아보면, 먼저 접근 권한이 필요합니다. External Secrets에 말입니다. 접근을 해야 가져오고 업데이트를 할 수 있기 때문입니다.
IAM Policy for ServiceAccount
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "secretsmanager:GetResourcePolicy", "secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret", "secretsmanager:ListSecretVersionIds", "secretsmanager:GetRandomPassword", "secretsmanager:ListSecrets" ], "Resource": "*" }, { "Effect": "Allow", "Action": "ssm:GetParameter", "Resource": "*" } ] } |
External Secrets Custom Resource 생성
external-secrets-rds-sample.yaml
# Create ExternalSecret with Secrets Manager Backend apiVersion: "kubernetes-client.io/v1" kind: ExternalSecret metadata: name: db-credential spec: backendType: secretsManager # optional: specify role to assume when retrieving the data dataFrom: - db-credential # optional: specify a template with any additional markup you would like added to the downstream Secret resource. # This template will be deep merged without mutating any existing fields. For example: you cannot override metadata.name. template: metadata: annotations: type: rds labels: backend: secretsManager |
Check Secrets
# Check Kubernetes Secrets $ kubectl get secrets db-credential -o yaml apiVersion: v1 data: dbInstanceIdentifier: ZGF0YWJhc2UtMQ== engine: bXlzcWw= host: ZGF0YWJhc2UtMS5jZHVjd2ankuYXAtbm9ydGhlYXN0LTIucmRzLmFtYXpvb= password: d29vd2FQQCQkdzByZA== port: MzMwNg== username: YWRW4= kind: Secret metadata: annotations: type: rds creationTimestamp: "2021-04-03T00:24:42Z" labels: backend: secretsManager . . . name: db-credential namespace: default ownerReferences: - apiVersion: kubernetes-client.io/v1 controller: true kind: ExternalSecret name: db-credential type: Opaque |
External Secrets 사용하기
사용하지 않은 경우에는 일반적으로 Base64 Encoding 되어 있는 값을 코드 리포지토리에 커밋 → 보안적 측면에서 Plain Text를 그대로 커밋하는 것과 차이가 없으나 AWS SecretsManager에 값을 넣어놓고 해당 값을 통해 Kubernetes Secret을 자동 생성하도록 한다.
# Get Env Variables from Secretsmanager to volume envVariablesFromSecrets: - key: rds-credential name: DATA_ENDPOINT property: host - key: rds-credential name: DATA_USERNAME property: username - key: rds-credential name: DATA_PASSWORD property: password - key: rds-credential name: DATA_DATABASE property: dbname - key: shared-kafka-brokers name: shared-kafka-brokers property: host - key: dev-kafka-brokers name: dev-kafka-brokers property: host |
AWS Secrets Manager에 Secrets 생성
- App Chart에 ExternalSecrets Manifest만 정의하면 Secrets을 자동 생성해줌
배포 후 서비스에서 externalsecret 생성 확인가능함
apiVersion: "kubernetes-client.io/v1" kind: ExternalSecret metadata: name: {{ include "datasync.fullname" . }}-secrets spec: backendType: secretsManager # optional: specify role to assume when retrieving the data data: {{- toYaml .Values.envVariablesFromSecrets | nindent 4 }} # optional: specify a template with any additional markup you would like added to the downstream Secret resource. # This template will be deep merged without mutating any existing fields. For example: you cannot override metadata.name. template: metadata: annotations: type: StringList labels: backend: secretsManager |
'고기 대신 SW 한점 > Public Cloud' 카테고리의 다른 글
AWS CloudFront 뽀개기 (0) | 2023.06.27 |
---|---|
Kafka,카푸카 알아보기 (0) | 2023.04.26 |
Glue, Athena를 활용한 Data 정합성 구성 (0) | 2023.03.07 |
AWS Certified Cloud Practitioner 시험 범위 (0) | 2023.03.06 |
[AWS] External Secrets (0) | 2023.02.16 |