AWS 기술 블로그
AWS 개발자 도구를 활용한 사전 코드 보안 점검 파이프라인으로 Shift-Left 구현
이 게시글은 AWS Security Blog에 게시된 “Implement an early feedback loop with AWS developer tools to shift security left by by Barry Conway, Deenadayaalan Thirugnanasambandam, Balamurugan Kumaran, and Nitin Kumar”를 한국어로 번역 및 편집하였습니다.
소프트웨어 개발 사이클(SDLC, Software Development Life Cycle) 내에서, 보안 점검은 일반적으로 코드 개발 및 빌드 이후에 이루어지게 됩니다. 하지만, 이러한 구성은 보안 점검이 완료되지 않은 코드에 대해서 빌드가 이루어지게 되고, 빌드 후의 보안 및 규정 준수에 대한 점검으로 인하여 개발 프로세스를 지연시킵니다. 이를 해결하는 방법 중 하나는, 조기 피드백 루프로 자동화된 점검을 통해 보다 빠르게 개발자에게 지속적인 피드백을 제공하는 것 입니다. 이를 통해 개발자는 조기에 수정 조치를 취하고, 코드 검토 프로세스의 효율성을 높여서, 결과적으로 생산성을 높일 수 있습니다.
또한 리뷰어가 검토하기 전에 기본적인 보안 및 규정 준수 요건이 검증되었다는 확신을 가지게 됩니다. 동일한 수준의 코드 표준과 품질에 대한 기준을 유지하면서, 거버넌스 메커니즘을 좀 더 왼쪽으로 앞당길 수 있습니다. (Shift-Left, 소프트웨어 개발 라이프 사이클(SDLC)에서 좀 더 앞 단계에서 테스트 및 보안 검증을 도입하는 것을 의미)
이 블로그에서는 AWS 개발자 도구를 사용하여, 개발자의 개발 프로세스 내에서 조기 피드백 루프를 통해 개발자의 역량을 강화하는, 보안에 대한 왼쪽 이동 접근 방식(Shift-Left)을 구현하는 방법을 소개하여 드리겠습니다. Git 리포지토리를 안전하게 호스팅하는 AWS CodeCommit, 지속적 배포 파이프라인을 자동화하는 AWS CodePipeline, 코드를 빌드하고 테스트하는 AWS CodeBuild, 잠재적인 코드 결함을 감지하는 Amazon CodeGuru Reviewer를 사용합니다.
Shift Left 접근법이 중요한 이유
개발자들은 조직에서 가장 중요한 고객 대상 애플리케이션을 구축하고 유지 관리하는 핵심적인 역할을 담당하고 있습니다. 개발자는 제품을 프로덕션 환경에 출시하기 전에 잠재적인 보안 문제를 식별하고 도움이 되는 지식, 도구 및 프로세스를 갖추고 있어야 합니다.
이것이 바로 왼쪽 이동 접근 방식(Shift-Left)이 중요한 이유입니다. 왼쪽으로 이동은 소프트웨어 개발의 초기 단계에서 취약점과 문제를 확인하는 프로세스입니다. 소프트웨어 팀은 왼쪽으로 이동하는 프로세스를 따름으로써(넓은 범위의 애플리케이션 보안 검토 및 위협 모델링 프로세스의 일부가 되어야 함), 애플리케이션을 구축할 때 탐지되지 않은 보안 문제를 방지할 수 있습니다. 최신 DevSecOps 워크플로는 다음과 같은 목표를 달성하기 위해 개발자와 개발자의 관행으로 계속 왼쪽으로 이동하고 있습니다:
- 코드 보안에 대한 개발자의 책임 의식 고취
- 개발팀 스스로 속도에 맞춰 문제를 미리 해결할 수 있는 역량 강화
- 조기 피드백 루프를 통해 잠재적인 보안 문제를 보다 빠르게 파악하여 위험 관리 개선
AWS 개발자 도구를 사용하면 코드가 커밋될 때마다 개발자에게 지속적으로 빠른 피드백을 제공할 수 있습니다.
솔루션 사전 요구사항
해당 솔루션을 따라하기 위해서는 아래와 같은 사전 요구사항이 필요합니다.
- AWS 계정
- 아래 서비스들의 AWS 서비스 접근 권한:
위의 나열된 서비스 및 DevOps 사례에 대한 일반적인 실무 지식이 필요합니다.
솔루션 개요
다음 다이어그램은 솔루션의 아키텍처입니다.
그림 1: 솔루션 개요
코드 보안 취약점을 탐지하기 위해, 리포지토리와 통합할 AWS 개발자 도구인 AWS CodeCommit, AWS CodePipeline, AWS CodeBuild 및 Amazon CodeGuru를 사용하여, 지속적 통합 및 지속적 배포(CI/CD) 파이프라인을 설정하는 방법을 보여드리겠습니다. 그림 1에서 볼 수 있듯이 솔루션은 다음과 같은 단계로 구성되어 있습니다:
- 개발자가 새 브랜치를 코드 리포지토리에 커밋합니다.
- 개발자가 메인 브랜치에 풀 요청을 생성합니다.
- 풀 요청은 두 가지 작업, Amazon CodeGuru Reviewer 코드 스캔과 AWS CodeBuild 작업을 트리거합니다.
- CodeGuru Reviewer는 프로그램 분석과 머신 러닝을 사용하여 Java 및 Python 코드의 잠재적 결함을 탐지하고, 개선을 위한 권장 사항을 제공합니다. 이 뿐만 아니라 CodeGuru Reviewer를 통해 보안 취약성, 암호화키, 리소스 누출, 동시성 문제, 잘못된 입력 유효성 검사, AWS API 및 SDK 등 모범 사례와의 차이를 감지하는데 도움을 줍니다.
- Python 코드의 보안 문제를 감지하는데 도움이 되도록 Python용 Bandit과 같은 써드파티 도구를 사용하여 AWS CodeBuild 배포를 구성할 수도 있습니다.
- CodeGuru Reviewer 또는 CodeBuild는 코드 스캔 결과를 풀 요청에 다시 기록하여, 개발자가 특정 코드 업데이트와 관련된 결과를 검토할 수 있는 하나의 공통된 장소를 제공합니다.
다음 표에는 평가하려는 코드 또는 아티팩트 유형에 따라, 조기 피드백 도구 체인에 통합할 수 있는 몇 가지 다른 도구가 나와 있습니다:
조기 피드백 – 보안 도구 | 사용 사례 | 라이선스 |
cfn-guard , cfn-nag , cfn-lint | 인프라스트럭처 코드 린팅 및 유효성 검사 | cfn-guard license, cfn-nag license, cfn-lint license |
CodeGuru, Bandit | Python | Bandit license |
CodeGuru | Java | |
npm-audit, Dependabot | npm libraries | Dependabot license |
AWS 계정에서 솔루션을 배포할 때, 그림 2와 같이 구성된 빌드 스펙 파일과 함께 AWS CodeBuild를 사용하여, 배포 파이프라인에 Python용 Bandit이 어떻게 빌드되었는지 검토할 수 있습니다. 동일한 방식으로 다른 도구를 사용할 수도 있습니다.
그림 2: CodeBuild에서 Bandit 설정
솔루션 배포 순서
솔루션을 배포하는 순서는 다음과 같습니다.
- CloudFormation 템플릿을 사용하여 솔루션을 배포
- CodeGuru를 코드 리포지토리와 연결
- 코드 리포지토리에 풀 요청을 생성
- 풀 요청의 코드 스캔 결과를 검토하고 결과를 해결
솔루션 배포
먼저 CloudFormation을 사용하여 필요한 리소스를 AWS 환경에 배포합니다.
CloudFormation 템플릿 배포
- 다음의 스택 시작 버튼을 선택하여 솔루션의 CloudFormation 템플릿을 배포합니다.
솔루션 사전 요구사항에 나열된 AWS 서비스들을 사용하기 위해서 솔루션은 기본값으로 AWS 미국 동부(버지니아 북부) 리전(us-east-1)에 배포됩니다. 다른 리전에 솔루션을 배포하려면 콘솔 탐색창에서 다른 리전 선택 후 배포 절차에 필요한 서비스가 선택한 지역에서 지원되는지 확인하세요. 리전별 서비스 가용성은 리전별 AWS 서비스를 참조하세요.
(역자 주: 원본 영문 블로그의 CloudFormation 템플릿은 배포 오류가 발생하여, 한국 기술 블로그 저장소의 오류를 수정한 템플릿으로 링크가 변경이 되어 있습니다.)
- 빠른 스택 생성 화면에서 다음을 수행합니다:
- 제공된 매개변수 기본값을 사용합니다.
- 아래로 스크롤하여 기능 섹션에서 “AWS CloudFormation에서 사용자 지정 이름으로 IAM 리소스를 생성할 수 있음을 승인합니다.”를 선택합니다.
- “스택 생성”을 선택합니다.
- CloudFormation 템플릿이 완료되면 AWS Cloud9 콘솔을 엽니다.
- 그림 3과 같이 환경 테이블에서, shift-left-blog-cloud9-ide 환경에서 열림을 선택합니다.
그림 3: Cloud9 환경
- 프로비저닝된 Cloud9 환경이 새 탭에서 열립니다. 그림 4와 같이 Cloud9이 두 개의 샘플 코드 리포지토리인 shift-left-sample-app-java 및 shift-left-sample-app-python을 초기화할 때까지 기다립니다. 이 게시물에서는 Python 샘플 리포지토리 shift-left-sample-app-python으로만 작업하지만, Java 리포지토리에서도 동일하게 동작합니다.
그림 4: Cloud9 IDE
CodeGuru Reviewer와 리포지토리 연결하기
다음 단계는 Python 리포지토리를 CodeGuru Reviewer와 연결하는 것입니다. 리포지토리가 연결 된 후, CodeGuru Reviewer는 풀 요청을 만들 때 발견한 이슈를 분석하고 댓글을 답니다.
CodeGuru Reviewer와 리포지토리 연결하는 방법
- CodeGuru 콘솔을 열고 왼쪽 탭의 Reviewer 아래에서 리포지토리를 선택합니다.
- 리포지토리 섹션에서 리포지토리 연결 및 분석 실행을 선택합니다.
- 리포지토리 연결 섹션에서 다음을 수행합니다:
- 소스 공급자 선택에서 AWS CodeCommit을 선택합니다.
- 리포지토리 위치에서 shift-left-sample-app-python을 선택합니다.
- 리포지토리 분석 실행 섹션에서 그림 5와 같이 다음을 수행합니다:
- 소스 분기에서 main을 선택합니다.
- 코드 검토 이름 – 선택 사항 이름을 입력합니다.
- 태그 –선택 사항 기본 설정을 그대로 둡니다.
- 리포지토리 연결 및 분석 실행을 선택합니다.
그림 5: CodeGuru 리포지토리 구성
- CodeGuru가 전체 리포지토리 분석을 시작하고 그림 6과 같이 상태는 보류 중입니다. 전체 분석을 완료하는데 약 5분이 걸립니다. 상태가 대기 중(Pending)에서 완료(Completed)될 때까지 기다립니다.
그림 6: CodeGuru코드 리뷰 콘솔
풀 요청(Pull Request) 생성하기
다음 단계는 새 브랜치를 만들고 풀 요청(Pull Request)을 만들어, 샘플 코드를 리포지토리에 푸시하고 CodeGuru Reviewer와 CodeBuild 작업에서 코드 스캔을 트리거합니다.
신규 브랜치 생성 순서
- Cloud9 IDE에서 터미널을 찾아 다음 명령을 실행하여 새 브랜치를 생성합니다.
cd ~/environment/shift-left-sample-app-python
git checkout -b python-test
- 그림 7과 같이 새 브랜치에서 작업 중인지 확인할 수 있습니다.
현재 브랜치(python-test)는 Cloud9 IDE 터미널에 강조 표시됩니다.
git branch -v
그림 7: Cloud9 IDE terminal
신규 파일 생성 후 리포지토리에 푸시하기
- 아래의 명령어로 sample.py 파일을 생성합니다.
touch sample.py
- 그림 8과 같이 아래의 샘플 코드를 복사하여 sample.py 파일에 붙여넣고 변경 사항을 저장합니다.
import requests
data = requests.get("https://www.example.org/", verify = False)
print(data.status_code)
그림 8: Cloud9 IDE 규정 비준수 코드
- 아래의 명령어로 Git의 변경사항을 커밋합니다.
git status
git add -A
git commit -m "shift left blog python sample app update"
Note: 이름과 이메일 주소를 설정하라는 메시지가 표시되더라도 Git에서 자동으로 설정하고 Git 커밋이 성공적으로 완료되므로 무시해도 됩니다.
- 그림 9와 같이 변경 사항을 리포지토리에 푸시합니다.
git push origin python-test
그림 9: Git push
신규 풀 요청 생성하기
- CodeCommit 콘솔을 열고, shift-left-sample-app-python 리포지토리를 선택합니다.
- 그림 10과 같이 브랜치 드롭다운에서 새로 생성하여 푸시한 브랜치(python-test)를 선택합니다.
그림 10: CodeCommit 브랜치 선택
- 새 브랜치에서 sample.py 파일을 선택하고 파일에 변경한 내용이 있는지 확인한 다음 그림 11과 같이 풀 요청 생성을 선택합니다.
그림 11: CodeCommit 풀 요청 확인
새 코드 업데이트를 병합 가능(Mergeable)는 알림이 표시됩니다.
- 소스 드롭다운에서 새 브랜치 python-test를 선택합니다. 드롭다운에서 풀 요청이 종료될 때 코드 변경 사항 병합 대상으로 main 브랜치를 선택합니다.
- CodeCommit에서 비교를 선택하여 메인 브랜치와 새 브랜치 python-test와 비교합니다. 두 브랜치 간의 차이점을 확인하려면 페이지 하단의 변경사항 탭을 선택합니다. 또한 풀요청이 닫힐 때 두 브랜치를 자동으로 병합할 수 있는지 여부도 평가합니다.
- 풀 요청의 비교 결과가 문제 없다면 제목과 설명(선택 사항)을 입력한 다음 풀 요청 생성을 선택합니다. 그림 12와 같이 CodeCommit 리포지토리의 풀 요청 목록에 나타납니다.
그림 12: 풀 요청 확인
위의 절차대로 풀 요청을 생성하면 두 개의 개별 코드 스캔이 자동으로 트리거됩니다. 첫번째는 CodeGuru 증분 코드 검토이고, 두번째는 Bandit을 사용하여 Python 코드의 보안 코드 스캔을 수행하는 CodeBuild입니다.
코드 스캔 결과 검토 및 발견된 취약점 해결
다음 단계는 코드 스캔 결과를 리뷰하여 발견된 보안 취약점과 이를 해결하는 방법에 대한 권장 사항을 식별하는 것입니다.
코드 스캔 결과 리뷰하기
- CodeGuru 콘솔을 열고 왼쪽 탐색 창의 리뷰어 하단에서 코드 검토를 선택합니다.
- 증분 코드 리뷰 탭에서 이전 풀 요청에 대해 생성된 새 코드 리뷰 항목이 표시되는지 확인합니다.
그림 13: CodeGuru 코드 리뷰
- 몇 분 후 CodeGuru가 증분 분석을 완료하면 코드 검토를 선택하여 풀 요청에 대한 CodeGuru 권장 사항을 검토합니다. 그림 14는 예제에 대한 CodeGuru 권장 사항을 보여줍니다.
그림 14: CodeGuru 권장 사항
- CodeBuild 콘솔을 열고 shift-left-blog-pr-Python이라는 코드 빌드 작업을 선택합니다. 이 예제에서는 이 작업이 실패 상태여야 합니다.
- 코드 빌드 실행을 열고 빌드 기록 탭에서 실패 상태인 코드 빌드 작업을 선택합니다. 빌드 로그 탭에서 로그에 다음 오류가 표시될 때까지 아래로 스크롤합니다. 발견된 심각도는 높음이며, 이는 CodeBuild 작업이 실패한 이유입니다. Bandit 문서에서 Bandit 스캔 옵션을 검토할 수 있습니다.
Test results:
>> Issue: [B501:request_with_no_cert_validation] Call to requests with verify=False disabling SSL certificate checks, security issue.
Severity: High Confidence: High
CWE: CWE-295 (https://cwe.mitre.org/data/definitions/295.html)
More Info: https://bandit.readthedocs.io/en/1.7.5/plugins/b501_request_with_no_cert_validation.html
Location: sample.py:3:7
data = requests.get("https://www.example.org/", verify = False)
print(data.status_code)
- CodeCommit 콘솔로 이동하여 풀 요청의 활동 탭에서 CodeGuru 권장 사항을 검토합니다. 그림 15에 표시된 것처럼 Bandit이 수행한 CodeBuild 작업의 결과도 검토할 수 있습니다.
그림 15: CodeGuru 권장사항과 로그
이를 통해 개발자가 보안 코드 스캔과 관련된 정보를, 코드 개발 단계에서 풀 요청 생성시 개발자에게 필요한 보안 점검을 조기에 진행하여, 시큐어 코딩에 대한 이해도를 높일 수 있습니다.
탐지된 취약점 해결하기
- 그림 16과 같이 Cloud9 IDE에서 Python 샘플 리포지토리에 있는 sample.py 파일로 이동합니다.
그림 16: Cloud9 IDE sample.py
- 다음 코드를 복사하여 sample.py 파일에 붙여넣고 기존 코드를 덮어쓴 후, 업데이트를 저장합니다.
import requests
data = requests.get("https://www.example.org", timeout=5)
print(data.status_code)
- 다음 명령을 실행하여 변경 사항을 커밋합니다.
git status
git add -A
git commit -m "shift left python sample.py resolve security errors"
git push origin python-test
- CodeCommit 콘솔을 열고 이전에 만든 풀 요청에서 활동 탭을 선택합니다. 풀 요청이 업데이트되었음을 나타내는 배너가 표시됩니다. 그리고 새 풀 요청 업데이트에 대해 CodeGuru 및 CodeBuild를 사용한 새 코드 스캔이 시작되었음을 나타내는 새 댓글도 표시됩니다.
- CodeGuru 콘솔의 증분 코드 검토 페이지에서 새 코드 스캔이 시작되었는지 확인합니다. 스캔이 완료되면 앞서 설명한 대로 CodeGuru 콘솔과 CodeBuild 빌드 로그에서 결과를 검토합니다. 이전에 발견된 보안 취약점이 해결되었음을 확인할 수 있습니다.
- CodeCommit 콘솔의 활동 탭에 있는 활동 기록 아래에서 설명을 검토하여 그림 17과 같이 각 코드 스캔의 상태가 통과인지 확인합니다.
그림 17: CodeCommit 활동 기록
- 이제 보안 문제가 해결되었으므로 풀 요청을 리포지토리의 메인 브랜치에 병합합니다. 병합을 선택하고, 병합 전략에서 빠른 전달 병합을 선택합니다.
AWS 계정 리소스 정리
이 솔루션으로 생성된 리소스를 정리하여 향후 요금이 발생하지 않도록 합니다.
계정 정리
- 배포한 Java 및 Python 샘플 애플리케이션에 대한 CloudFormation 스택을 삭제하는 것으로 시작합니다. CloudFormation 콘솔의 스택 섹션에서 이러한 스택 중 하나를 선택하고 삭제를 선택한 다음, 다른 스택을 선택하고 삭제를 선택합니다.
그림 18: repository 스택 삭제
- Cloud9 CloudFormation스택을 선택하고 삭제를 선택합니다.
- Amazon S3 콘솔을 열고 검색 창에서 shift-left로 시작하는 CodePipeline에서 사용한 S3 버킷을 검색합니다.
그림 19: CodePipeline S3 버킷 선택
- S3 버킷을 선택하고, 버킷에 있는 모든 개체 폴더를 선택한 다음 삭제를 선택합니다.
그림 20: CodePipeline S3 객체 선택 후 삭제
- 객체 삭제를 확인하려면 “객체를 영구 삭제하시겠습니까?” 섹션에서 “영구 삭제”를 입력한 다음 객체 삭제를 선택합니다. 삭제 완료시 상단에 “개체가 성공적으로 삭제되었습니다”라는 배너 메시지가 표시됩니다.
- CloudFormation 콘솔로 돌아가서 shift-left-blog 스택을 선택한 다음 삭제를 선택합니다.
결론
이 블로그 게시물에서는 코드 리포지토리의 풀 요청 생성 시에, 자동화된 코드 보안 검사를 수행하기 위해 Amazon CodeGuru Reviewer와 CodeBuild를 사용하여, CodeCommit 풀 요청 활동 탭의 상태 댓글을 통해, 코드 개발에 대한 조기 피드백을 제공하는 솔루션의 구현 방법을 보여드렸습니다.
해당 솔루션을 통해 얻을 수 있는 장점은 크게 3가지입니다.
- 타사 또는 오픈 소스 도구를 개발 주기에 통합하는 방법을 보여드리기 위해 Python용 Bandit으로 CodeBuild를 구성했습니다. 이 접근 방식을 사용하여 다른 도구를 워크플로에 통합할 수 있습니다.
- 개발 주기 초기에 보안을 왼쪽으로 전환(Shift-left)하면 잠재적인 보안 문제를 조기에 식별하고, 팀이 문제를 조기에 해결할 수 있도록 지원하여, 빌드 후반에 코드를 리팩토링할 필요성을 줄일 수 있습니다.
- 신규 개발한 코드의 잠재적인 보안 문제를 확인하고 이해하는 데 사용할 수 있는, 간단한 방법을 제공함으로써 조직 내 보안 요구사항에 대한 인식을 향상시킬 수 있습니다.
배포 가이드에 따라서 손쉽게 시작할 수 있습니다. AWS 계정에 가입하고, 스택 시작 버튼을 통해 제공된 CloudFormation 템플릿을 배포하고, 코드를 커밋하고, 취약점 스캔을 시작할 수 있습니다.
해당 블로그에 대한 피드백이 있으면 아래의 댓글 부탁드립니다. 추가적인 문의사항이 있는 경우, AWS re:Post에서 새 스레드를 시작하거나 AWS Support팀에 문의하시기 바랍니다.