Terraform은 최근 IBM에 인수된 Hashicorp사의 대표적인 서비스 중 하나이다. 최근 라이센스 변경으로 인해 오픈소스로서의 사용성이 떨어졌다고 평가받고 있지만, 그래도 많은 곳에서 사용을 지속해오고 있는 제품 중 하나이다.
Terraform을 활용해서 인프라 리소스를 문서화할 때, 해당 문서에 민감정보가 들어가는 것은 불가피한 일이다.
작게는 개인의 이름이나 생년월일부터, 크게는 기업 단위의 정보(AWS 계정 관련 Secret Key 라던가,,,)까지 민감정보의 범위는 넓다.
AWS 가 제시한 Zero-Trust 아키텍쳐 가이드를 보면(아무래도 KMS에 대한 글이다 보니,,,), 권장 사항에 KMS를 이용한 민감정보 암호화를 강조하고 있다.
How to think about zero trust architectures on aws
결국 이것도 따지고 보면 AWS만큼은 신뢰할 수 밖에 없다는,,,의문점이 조금 남기는 하지만, 개인 컴퓨터에 영원히 민감정보를 저장하고 있는 것이 아니라면 협업에서는 어쩔 수 없는 부분인 것 같다.
어쨌든, 우리는 Terraform을 사용할 때 필요한 무수한 민감정보들을 관리해야만 한다.
1차원적으로, Terraform을 사용할 때 .tfvars
를 생성하고 해당 파일에 필요한 민감정보들을 담아두는 방식을 사용한다.
이렇게 저장한 .tfvars
파일은 .gitignore
에 추가하여 github에 올라가지 않도록 방지하고, 환경변수 취급하여 필요한 사람들끼리 로컬에서 공유하여 사용한다.
그렇다면, 이러한 파일도 필요하지 않게 하고 싶어!
이를 위해 사용되는 것이 AWS KMS 서비스이다. 이외에도 많은 암호화 서비스가 존재하지만, 여기서는 KMS를 알아본다.
AWS KMS는 데이터를 암호화하거나 디지털 서명할 때 사용하는 키를 생성 및 제어
하는 서비스라고 명시되어 있다.
다시 말해서, 특정 데이터를 암호화 및 복호화할 때 사용하는 key 서비스이다. 실제 AWS 서비스를 비롯한 다양한 곳에서 폭넓게 사용되는 매우 보편적인 서비스 중 하나이다.
AWS KMS를 활용하면 로컬에 key를 저장하지 않고도 안전하게 데이터를 보관할 수 있다. 특히, IAM을 통한 접근제어를 이용하여 원격으로 해당 데이터의 접근을 제어할 수 있다는 점이 강점이다.
이제, 해당 변수를 암호화할 툴로 우리가 사용할 것은 sops이다. 기존에는 SSM(Secret Manager Pararmeter Store) 를 사용했지만, 최근에는 sops를 많이 사용하고 있다고 한다. 물론 SSM의 SecureString을 사용하는 것도 매우 올바른 사례이다.
sops는 암호화 도구 중 하나로, 가볍고, 사용이 용이하며, 높은 보안성을 가지고 있다.
https://github.com/getsops/sops
또한 sops는 aws kms를 이용한 암호화 및 terraform provider를 제공하기 때문에, 더욱 사용이 용이하다.
실제로 사용해본 결과 매우 쉽게 암호화를 진행할 수 있었다.
예를 들어서, 내가 Terraform에서 다음과 같은 key를 사용한다고 가정하자.
{
"secret": "hello world"
}
Terraform sops provider에서 공식적으로 지원하는 파일 확장자가 json과 yaml이기 때문에, tfvars 대신 json의 형태로 변수를 저장했다. 실제로 tfvars를 사용하려고 하면 plan 과정에서 에러가 발생한다.
이 친구를 암호화 할건데, kms를 이용해서 암호화한다.
sops는 macos기준 homebrew로 간편하게 설치할 수 있고, 이외에는 공식문서를 살펴보자,,,설치가 어려워 보이지는 않았다.
이제 암호화에 사용할 kms의 arn을 가져오고, 해당 arn을 이용해서 encrypt를 진행한다. 당연하겠지만, 이 과정에서 AWS PROFILE 에 kms:Encrypt
권한이 있어야만 동작함을 명심하자.
sops --encrypt --kms=arn:aws:kms:<AWS_REGION>:<AWS_ACCOUNT_ID>:key/<AWS_KMS_KEY_ID> terraform.dec.json
위와 같이 특정 kms key를 가지고 파일을 암호화할 수 있다.
혹은 미리 디렉토리 내에 sops관련 설정 파일인 .sops.yaml
을 작성해주어 해당 파일에 arn을 미리 명시해줄 수도 있다.
그러면 아래와 같이 kms arn을 지정하지 않아도 encryption이 가능하다.
sops --encrypt terraform.dec.json > terraform.enc.json
.sops.yaml
을 활용하면, 개발 환경 별로 다른 key를 적용한다거나, gcp kms, terraform vault 등 다른 key management service들도 쉽게 이용할 수 있다.
이외에도 프로필 지정 등이 가능하니, 자세한 활용법은 공식문서를 확인하자.
위와 같이 암호화한 내용을 저장할 파일 명을 명시하면 해당 파일에 저장이 되고, 아니라면 단순히 암호화된 메타데이터 값이 출력된다.
이때, 출력되는 메타데이터는 다음과 같은 형태를 띈다.
// terrafrom.enc.json
{
"secret-value": "ENC[AES256_GCM,data:Kko0A4uRuvjB9daW,iv:Co1NGfx4I6DitshLJ0BYDBBSrP+zLPkiQe+H9/7uwDs=,tag:iNyOWzKKcNqbznOvbS4ysw==,type:str]",
"sops": {
"kms": [
{
"arn": "arn:aws:kms:<AWS_REGION>:<AWS_ACCOUNT_ID>:key/<AWS_KMS_KEY_ID>",
"created_at": "2024-05-07T07:31:53Z",
"enc": "AQICAHj1y+P0JmoeOyDOyEGgBIFMhJj9v+yGfV/MMM5oBXJz8gEbiNoL/FeedA4UoWS2/41DAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMqwm1JHKfJqrTOTtUAgEQgDt4l0qF/UqtJdxaeAySIx/0AeOGRBKvpvIiRZA7juBbbWlXXJ7EZX5qU++32/U5/XXzrDj7fh1iQunmxw==",
"aws_profile": ""
}
],
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": null,
"lastmodified": "2024-05-07T07:31:54Z",
"mac": "ENC[AES256_GCM,data:jfUA0gJVA6GdYkWNQfioukczKJ62qSn9M9y7OR+u3Ma0berpdmHBpJN5Crq0up2KnaBFRoCe+iyMfHNfnZ55+uBV2EstXkiHkMetx54BSWTGQxYgeKG6BwkNDwgmFBi73hxcZgSQ1J6bCzgN81qESnWUsO+VatfP6C4OE0KKVHI=,iv:GTcj02u48YplSx2WfdAQb9rJ1aKD+s3f1sR6pIPeHsc=,tag:sbpVOyTT+Ug64JxrXHau/w==,type:str]",
"pgp": null,
"unencrypted_suffix": "_unencrypted",
"version": "3.8.1"
}
}
이렇게 암호화된 파일을 버전 관리 툴에 저장해두고, 이후에는 해당 파일을 kms와 해당 iam을 활용해 해당 kms key에 대한 접근 권한을 관리하는 것으로 민감정보에 대한 접근을 제어하게 된다.
여기서 중요한 점은, 로컬에는 아무것도 존재하지 않더라도 KMS에 대한 접근 제어 만으로 민감정보에 대한 접근을 관리할 수 있다는 점이다.
예를 들어, 내가 특정 개발자에게 해당 민감정보를 열람할 권한을 주고 싶다면, 기존처럼 로컬 환경변수를 제공할 것이 아니라, 해당 KMS에 대한 IAM Role만 열어주면 되는것이다!!!
매니징을 하는 입장에서는 각 개발자 별 AWS PROFILE만 잘 관리하면 된다는 이점이 있다.
이미 앞에서 암호화된 파일을 보면 알 수 있겠지만, kms의 arn이 그대로 드러난다는게 조금 마음에 걸린다.
사실 민감정보 관리에 있어서 어떠한 정보라도 최소한의 접근을 제공하는 것이 맞다고 생각하는데, 혹여나 public repo에 해당 정보가 올라가게 되면, 어쨌든 arn을 공개하게 되는 것이기 때문이다.
물론 kms의 권한 관리만 잘 제어하면 되겠지만, 그래도 마음이 쓰이는 것은 사실인 것 같다.
그래서 내가 AWS 한국사용자모임 내 general 채널의 AI에게 물어본 결과, 해당 암호화 파일은 arn이 보여지는 것은 맞지만 버전 관리 툴에 올린다고 한다.
또한 질문에 스레드로 답변을 주신 AWS Community Builder님의 의견도 동일했다.
gcp kms와 같은 툴의 경우 alias를 arn대신 사용할 수 있도록 기능을 제공하는 것 같던데, 아직 aws kms에 대해서는 해당 옵션을 제공하지 않는다.
관련해서 아직 논의중인 issue 또한 찾을 수 있었다.
https://github.com/getsops/sops/issues/381
여기 사람들도 보면 나와 같이 arn에 포함된 계정 ID나 Key ID 등이 노출되는 것을 꺼려한다.
언젠가는,,,aws kms에도 해당 기능이 추가되었으면 좋겠다. 적어도 내가 실무하기 전까지는...? ㅜ
오늘은 가볍고 보안성이 높아 최근 많이 사용되고 있는 sops 와 aws kms의 조합을 이용하여 민감정보를 관리하는 방법을 알아보았다.
확실히 모든 로컬에 특정 파일을 굳이 저장하지 않아도 접근 제어만으로 민감정보에 대한 컨트롤을 할 수 있다는 점이 큰 장점으로 다가오는 것 같다.
이전에는 ksm 에 ssm(secret manager parameter store)를 엮은 조합을 많이 사용했다고 하는데, sops의 이점들이 많아 sops와의 조합을 많이 채택한다고 한다.
ssm 대신 sops를 선택하면 뭐가 좋을까?
보안 강화
편의성
운영 효율성
비용 절감
AI의 답변을 토대로 장점들을 작성해보았는데, 정말 많은 부분에서 공감할 수 있었다.
이후에는 sops와 다른 key management service를 이용한 예시들도 연습해보고싶다.
AWS 한국사용자모임 슬랙
송주영님의 DevOps 강의
난 형근 trust