BLOG
AWS CodeArtifact를 사용하면 개발자가 내부 코드 리포지토리를 Pypi, Maven 또는 NPM과 같은 업스트림 코드 리포지토리에 연결할 수 있습니다. AWS CodeArtifact는 AWS의 CI/CD 워크플로에 대한 강력한 추가 기능이지만 Jupyter 노트북에서 호스팅되는 코드 기반에도 효과적입니다. 이는 ML 모델을 정기적으로 빌드하고 훈련하는 기계 학습 개발자를 위한 일반적인 개발 패러다임입니다.
오늘 포스팅에서는 인터넷이 비활성화된 SageMaker 노트북 인스턴스에서 AWS CodeArtifact에 안전하게 연결하는 방법을 보여드리려고 하는데요, AWS에서 분산형 데이터 과학 팀을 지원하는 네트워크 및 보안 설계자 분들께 유용할 것 같습니다.
다른 게시물에서 AWS Private Link 엔드포인트를 통해 AWS 서비스에 대한 연결을 유지하면서 Amazon VPC의 프라이빗 서브넷에서 인터넷 비활성화 노트북을 생성하는 방법에 대해 논의했습니다. 오늘 예제는 인터넷이 비활성화된 노트북 인스턴스를 AWS CodeArtifact에 연결하고 공용 인터넷을 통과할 필요 없이 오픈 소스 코드 패키지를 다운로드할 예정입니다.
솔루션 개요
아래 다이어그램은 저희가 구현할 솔루션을 설명하고 있는데요, 먼저 VPC의 프라이빗 서브넷에 SageMaker 노트북 인스턴스를 생성합니다. AWS CodeArtifact 도메인과 리포지토리도 생성합니다. 리포지토리에 대한 액세스는 CodeArtifact 리포지토리 정책 및 PrivateLink 액세스 정책에 의해 제어됩니다.
이 아키텍처를 통해 인터넷이 비활성화된 SageMaker 노트북 인스턴스는 공용 인터넷을 통과하지 않고도 CodeArtifact 리포지토리에 액세스할 수 있습니다. 네트워크 트래픽이 공용 인터넷을 통과하지 않기 때문에 예상되는 네트워크 액세스 권한이 있는 사용자만 노트북 인스턴스에 액세스할 수 있도록 하여 노트북 인스턴스의 보안 태세를 개선합니다. 또한 이 패러다임을 통해 보안 관리자는 라이브러리 사용을 코드 패키지의 “승인된” 배포로만 제한할 수 있습니다. 네트워크 보안과 보안 패키지 관리를 결합하여 보안 엔지니어는 작업 능력을 방해하지 않으면서 데이터 과학자를 위한 오픈 소스 라이브러리를 투명하게 관리할 수 있습니다.
전제 조건
오늘 예제를 위해서는 인터넷이 비활성화된 SageMaker 노트북 인스턴스와 프라이빗 서브넷이 있는 VPC가 필요합니다. 이 링크를 방문하여 VPC에 프라이빗 서브넷을 생성하고 이 시리즈의 이전 게시물을 방문하여 전제 조건을 준비하세요.
또한 인터넷이 비활성화된 SageMaker 노트북 인스턴스를 생성한 AWS 리전에 CodeArtifact 도메인이 필요한데요, 도메인은 CodeArtifact 서비스에서 리포지토리를 논리적으로 구성하는 방법입니다. 도메인 이름을 지정하고 암호화를 위한 AWS 관리형 키를 선택한 다음 도메인을 생성합니다. 이 링크 에서는 AWS CodeArtifact 도메인을 생성하는 방법을 설명합니다.
AWS CodeArtifact 구성
AWS CodeArtifact를 구성하기 위해 도메인에 리포지토리를 생성합니다. 계속하기 전에 노트북 인스턴스가 배포된 동일한 지역을 선택해야 합니다. AWS CodeArtifact를 구성하려면 다음 단계를 수행해야 합니다.
- AWS CodeArtifact 콘솔에서 Create repository을 선택합니다.
- 저장소에 이름과 설명을 지정합니다. 사용하려는 공개 업스트림 리포지토리를 선택합니다. 이 포스트에서는 pypi-store를 사용합니다.
- Next를 선택합니다.
- 작업 중인 AWS 계정과 이 계정에 사용할 AWS CodeArtifact 도메인을 선택합니다.
- Next를 선택합니다.
- 리포지토리 정보 요약을 검토하고 Create repository를 선택합니다.
- 참고: “Package flow” 로 표시된 검토 화면 섹션에는 외부 연결에서 AWS CodeArtifact에서 관리하는 도메인으로의 종속성 흐름을 설명하는 흐름도가 있습니다.
- 이 순서도는 리포지토리를 생성할 때 발생하는 일을 설명합니다. 우리는 실제로 두 개의 저장소를 만들고 있습니다. 첫 번째는 외부 호스팅 pypi 리포지토리에 연결하는 “pypi-store” 리포지토리입니다. 이 리포지토리는 AWS CodeArtifact에 의해 생성되었으며 업스트림 리포지토리에 대한 연결을 준비하는 데 사용됩니다. 두 번째 저장소인 “isolatedsm”은 “pypi-store” 저장소에 연결됩니다. 이 전이적 리포지토리를 사용하면 외부 연결을 결합하고 타사 라이브러리를 사용하기 전에 스테이징할 수 있습니다.
- 이 형태의 전이적 리포지토리 관리를 통해 데이터 과학 워크로드에 사용하는 라이브러리에 대해 최소 권한 액세스를 적용할 수 있습니다.
또는 다음 명령을 사용하여 AWS CLI에서 이러한 단계를 수행할 수 있습니다.
aws codeartifact create-repository –domain <domain_name> –domain-owner <account_number> –repository <repo_name> –description <repo_description> –region <region_name>
이 프로세스가 끝나면 우리 도메인에 두 개의 리포지토리가 생성됩니다.
CodeArtifact 리포지토리 정책
간결함을 위해 개발자라면 누구나 CodeArtifact 리포지토리에 액세스할 수 있도록 하는 IsolatedSM 리포지토리에 대해 상대적으로 개방된 정책을 부여합니다. 프로덕션 사용 사례에 대해 이 정책을 수정해야 합니다. 게시물 뒷부분에서 노트북 인스턴스 역할에 연결된 IAM 정책을 사용하여 역할 수준에서 최소 권한 액세스를 구현하는 방법에 대해 설명합니다. 지금은 AWS Management 콘솔에서 리포지토리로 이동하여 리포지토리 구성 페이지의 세부 정보 섹션을 확장합니다. Repository policy에서 Apply a repository policy를 선택합니다.
다음 화면에서 Edit repository policy로 표시된 텍스트 필드에 다음 정책 문서를 붙여 넣고 저장을 선택합니다.
{ “Version”: “2012-10-17”, “Statement”: [ { “Action”: [ “codeartifact:AssociateExternalConnection”, “codeartifact:CopyPackageVersions”, “codeartifact:DeletePackageVersions”, “codeartifact:DeleteRepository”, “codeartifact:DeleteRepositoryPermissionsPolicy”, “codeartifact:DescribePackageVersion”, “codeartifact:DescribeRepository”, “codeartifact:DisassociateExternalConnection”, “codeartifact:DisposePackageVersions”, “codeartifact:GetPackageVersionReadme”, “codeartifact:GetRepositoryEndpoint”, “codeartifact:ListPackageVersionAssets”, “codeartifact:ListPackageVersionDependencies”, “codeartifact:ListPackageVersions”, “codeartifact:ListPackages”, “codeartifact:PublishPackageVersion”, “codeartifact:PutPackageMetadata”, “codeartifact:PutRepositoryPermissionsPolicy”, “codeartifact:ReadFromRepository”, “codeartifact:UpdatePackageVersionsStatus”, “codeartifact:UpdateRepository” ], “Effect”: “Allow”, “Resource”: “*”, “Principal”: { “AWS”: “arn:aws:iam::329542461890:role/GeneralIsolatedNotebook” } } ]
}
이 정책은 격리된 노트북 인스턴스에 연결된 역할의 저장소에 대한 전체 액세스를 제공합니다. 이 정책은 개발자가 CodeArtifact에 액세스할 수 있도록 하는 샘플 정책입니다. CodeArtifact 리포지토리에 대한 정책 정의에 대한 자세한 내용(특히 보다 제한적인 역할 기반 액세스가 필요한 경우)은 CodeArtifact 사용 설명서 를 참조하십시오. AWS CLI를 사용하여 동일한 리포지토리 정책을 구성하려면 앞의 정책 문서를 policy.json로 저장하고 다음 명령을 실행합니다.
aws codeartifact put-repository-permissions-policy –domain <domain_name> –domain-owner <account_number> –repository <repo_name> –policy-document file:///PATH/TO/policy.json –region <region_name>
AWS CodeArtifact에 대한 액세스 구성
CodeArtifact 리포지토리에 연결하려면 리포지토리에 사용자로 로그인해야 합니다. 리포지토리로 이동하고 View connection instructions를 선택하여 선택한 패키지 관리자에 대한 적절한 연결 지침을 선택할 수 있습니다. 우리는 이 포스트에서 pip를 사용할 것입니다. 드롭다운에서 pip 를 선택하고 연결 지침을 복사합니다.
사용할 AWS CLI 명령은 다음과 유사해야 합니다.
aws codeartifact login –tool pip –repository <repo_name> –domain <domain_name> –domain-owner <account_number> –region <region_name>
이 명령은 이 리포지토리에 대한 액세스를 요청한 역할에 대한 인증 쿠키를 반환하는 CodeArtifact API 호출입니다. 이 명령은 Jupyter 노트북에서 실행하여 CodeArtifact 리포지토리에 대한 액세스를 인증하고 해당 업스트림 리포지토리에서 라이브러리를 설치하도록 패키지 관리자를 구성합니다. 인터넷이 비활성화된 SageMaker 노트북 인스턴스에서 이를 테스트할 수 있습니다.
격리된 노트북 인스턴스에서 로그인 명령을 실행하면 한동안 아무 일도 일어나지 않습니다. 잠시 후(약 300초) Jupyter는 연결 시간 초과 오류를 출력합니다. 노트북 인스턴스가 격리된 네트워크 서브넷에 있기 때문입니다. 이는 예상된 동작이며, 노트북 인스턴스가 인터넷을 사용할 수 없음을 확인합니다. 이 서브넷과 CodeArtifact 리포지토리 간에 네트워크 액세스를 프로비저닝해야 합니다.
노트북과 CodeArtifact 간에 PrivateLink 연결 만들기
AWS PrivateLink 는 Amazon Elastic Compute Cloud (Amazon EC2), Amazon S3 및 Amazon Simple Notification Service (Amazon SNS)와 같은 다른 AWS 서비스를 위해 VPC에 VPC 엔드포인트를 생성하는 네트워킹 서비스입니다. 프라이빗 엔드포인트는 퍼블릭 인터넷 대신 VPC를 통해 다른 AWS 서비스에 대한 API 요청을 용이하게 합니다. 이것은 우리 솔루션이 우리가 만든 CodeArtifact 리포지토리에 비공개로 안전하게 액세스할 수 있도록 하는 중요한 구성 요소입니다.
PrivateLink 끝점을 만들기 전에 끝점과 연결할 보안 그룹을 만들어야 합니다. 계속하기 전에 인터넷이 비활성화된 SageMaker 노트북 인스턴스와 동일한 지역에 있는지 확인이 필요합니다.
- Amazon VPC 콘솔에서 Security Groups을 선택합니다.
- Create security group을 선택합니다.
- 그룹에 적절한 이름과 설명을 제공합니다.
- PrivateLink 엔드포인트를 배포할 VPC를 선택합니다. 이것은 격리된 SageMaker 노트북을 호스팅하는 동일한 VPC여야 합니다.
- Inbound Rules (인바운드 규칙)에서 Add Rule (규칙 추가)을 선택한 다음 격리된 SageMaker 노트북을 호스팅하는 보안 그룹의 모든 트래픽을 허용합니다.
- 아웃바운드 규칙은 기본값으로 유지되어야 하며, 보안 그룹을 생성합니다.
다음을 사용하여 CLI에서 이러한 단계를 복제할 수 있습니다.
> aws ec2 create-security-group –group-name endpoint-sec-group –description “group for endpoint security” –vpc-id vpc_id –region region> { “GroupId”: endpoint-sec-group-id}
aws ec2 authorize-security-group-ingress –group-id endpoint-sec-group-id –protocol all –port -1 –source-group isolated-SM-sec-group-id –region region
이 다음 단계에서는 단순성을 위해 고객이 AWS CLI를 사용하는 것이 좋습니다. 먼저 로컬 파일 시스템에서와 policy.json같이 다음 정책 문서를 저장합니다.
{ “Statement”: [ { “Action”: “codeartifact:*”, “Effect”: “Allow”, “Resource”: “*”, “Principal”: “*” }, { “Effect”: “Allow”, “Action”: “sts:GetServiceBearerToken”, “Resource”: “*”, “Principal”: “*” }, { “Action”: [ “codeartifact:CreateDomain”, “codeartifact:CreateRepository”, “codeartifact:DeleteDomain”, “codeartifact:DeleteDomainPermissionsPolicy”, “codeartifact:DeletePackageVersions”, “codeartifact:DeleteRepository”, “codeartifact:DeleteRepositoryPermissionsPolicy”, “codeartifact:PutDomainPermissionsPolicy”, “codeartifact:PutRepositoryPermissionsPolicy”, “codeartifact:UpdateRepository” ], “Effect”: “Deny”, “Resource”: “*”, “Principal”: “*” } ]
}
그런 다음 AWS CLI를 사용하여 다음 명령을 실행하여 CodeArtifact에 대한 PrivateLink 엔드포인트를 생성합니다. 이 첫 번째 명령은 CodeArtifact 리포지토리 API 명령에 대한 VPC 엔드포인트를 생성합니다.
> aws ec2 create-vpc-endpoint \–vpc-endpoint-type Interface \–vpc-id vpc-id \–service-name com.amazonaws.region.codeartifact.repositories \–subnet-ids [list-of-subnet-ids] \-–security-group-ids endpoint-sec-group-id \–-private-dns-enabled \–policy-document file:///PATH/TO/policy.json \
–region region
이 두 번째 명령은 CodeArtifact 비저장소 API 명령에 대한 VPC 엔드포인트를 생성합니다. 이 명령에서는 엔드포인트에 대해 프라이빗 DNS를 활성화하지 않습니다. 후속 CLI 명령에서 프라이빗 DNS를 활성화하는 데 사용할 것이기 때문에 이 명령의 출력을 기록해 두십시오.
> aws ec2 create-vpc-endpoint \–vpc-endpoint-type Interface \–vpc-id vpc-id \–service-name com.amazonaws.region.codeartifact.api \–subnet-ids [list-of-subnet-ids] \-–security-group-ids endpoint-sec-group-id \–-no-private-dns-enabled \–policy-document file:///PATH/TO/policy.json \–region region{ “VpcEndpoint”: { “VpcEndpointId”: “vpc-endpoint-id”, … }
}
이 VPC 엔드포인트가 생성되면 다음 최종 명령을 실행하여 엔드포인트에 대한 프라이빗 DNS를 활성화합니다.
> aws ec2 modify-vpc-endpoint \–vpc-endpoint-id vpc-endpoint-id \–private-dns-enabled \
–region region
이 정책 문서는 개발자가 수행하는 일반적인 CodeArtifact 작업이 이 PrivateLink 끝점을 통해 허용되도록 허용합니다. CodeArtifact를 사용하면 리포지토리 자체에 대한 액세스 정책을 정의할 수 있기 때문에 이는 사용 사례에 적합합니다. 이 끝점을 통해 전송되는 CodeArtifact 관리 명령만 차단하고 있습니다. 개발자가 저장소에서 관리 명령을 수행하는 것을 원하지 않기 때문에 관리 명령을 차단합니다.
다음 스크린샷은 API 엔드포인트와 엔드포인트가 속한 보안 그룹을 보여줍니다.
이 보안 그룹의 인바운드 규칙은 격리된 SageMaker 노트북의 보안 그룹에서 오는 모든 트래픽을 허용하는 하나의 인바운드 규칙을 나열해야 합니다.
네트워크 테스트
보안 그룹이 구성되고 PrivateLink 엔드포인트가 생성되면 격리된 SageMaker 노트북 인스턴스에서 Jupyter 노트북을 엽니다. 셀에서 앞에서 만든 CodeArtifact 리포지토리에 대한 연결 지침을 실행합니다. 결국 시간 초과 오류가 발생하는 긴 일시 중지 대신 이제 AccessDenied 예외가 발생합니다.
CodeArtifact 연결 지침은 AWS Management Console에서 CodeArtifact 리포지토리로 이동하여 연결 지침 보기를 선택하여 찾을 수 있음을 기억하십시오. 이 게시물의 경우 pip에 대한 연결 지침을 선택합니다.
이 시점에서 격리된 SageMaker 노트북 인스턴스는 PrivateLink를 통해 CodeArtifact 서비스에 연결할 수 있습니다. 이제 노트북 인스턴스의 역할에 Jupyter 노트북의 서비스와 상호 작용하는 데 필요한 관련 권한을 부여해야 합니다.
노트북 권한 수정
CodeArtifact 리포지토리가 구성되면 노트북이 아티팩트 리포지토리에서 읽을 수 있도록 격리된 노트북 인스턴스 역할에 대한 권한을 수정해야 합니다. AWS Management 콘솔에서 IAM 서비스로 이동하고 정책 아래에서 정책 생성을 선택합니다. JSON 탭을 선택하고 텍스트 창에 다음 JSON 문서를 붙여넣습니다.
{ “Version”: “2012-10-17”, “Statement”: [ { “Effect”: “Allow”, “Action”: “codeartifact:GetAuthorizationToken”, “Resource”: “arn:aws:codeartifact:<region>:<account_no>:domain/<domain_name>” }, { “Effect”: “Allow”, “Action”: “sts:GetServiceBearerToken”, “Resource”: “*” } ]
}
CLI에서 이 정책 문서를 생성하려면 이 JSON을 다른 이름으로 저장 policy.json하고 다음 명령을 실행합니다.
aws iam create-policy –policy-name <policy_name> –policy-document file:///PATH/TO/policy.json
역할에 연결되면 이 정책 문서는 CodeArtifact 서비스에서 인증 토큰 검색을 허용합니다. AWS Management 콘솔에서 IAM 서비스로 이동하여 이 정책을 노트북 인스턴스 역할에 연결합니다. 사용 중인 노트북 인스턴스 역할을 선택하고 이 정책을 인스턴스 역할에 직접 연결합니다. 이는 다음 명령을 실행하여 AWS CLI로 수행할 수 있습니다.
aws iam attach-role-policy –role-name <role_name> –policy-arn <policy_arn>
CodeArtifact에 대한 인증을 허용하는 역할을 갖추었으므로 이제 테스트를 계속할 수 있습니다.
권한 테스트
AWS Management Console에서 SageMaker 서비스로 이동하여 인터넷 비활성화 노트북 인스턴스에서 Jupyter 노트북을 엽니다. 노트북 셀에서 네트워크 테스트(네트워크 테스트 섹션에 있음)의 동일한 명령을 사용하여 CodeArtifact 리포지토리에 로그인을 시도합니다.
액세스 거부 예외 대신 출력에 토큰이 만료된 저장소에 대한 성공적인 인증이 표시되어야 합니다. pip를 사용하여 패키지를 다운로드, 설치 및 제거하여 테스트를 계속하십시오. 이러한 명령은 CodeArtifact 리포지토리에 연결된 정책에 따라 권한이 부여됩니다. 사용자를 기반으로 리포지토리에 대한 액세스를 제한하려는 경우(예: 패키지 제거 기능 제한) CodeArtifact 리포지토리 정책을 수정합니다.
AWS Management 콘솔에서 리포지토리로 이동하고 설치된 패키지를 검색하여 패키지가 설치되었는지 확인할 수 있습니다.
정리
VPC 엔드포인트를 제거하면 노트북 인스턴스가 CodeArtifact 리포지토리에 액세스할 수 없게 되며, 앞부분에서의 시간 초과 오류를 다시 도입합니다. 이는 예상된 동작이며, 매월 저장된 데이터의 GB 수를 기준으로 고객에게 요금을 부과하는 CodeArtifact 리포지토리를 삭제할 수도 있습니다.
결론
VPC 엔드포인트를 SageMaker 노트북과 결합하여 다른 AWS 서비스의 가용성을 인터넷이 비활성화된 프라이빗 노트북 인스턴스로 확장할 수 있습니다. 이를 통해 개발자 생산성을 희생하지 않고 개발 환경의 보안 태세를 개선할 수 있습니다.
메가존클라우드 TechBlog는 AWS BLOG 영문 게재 글이나 관련 기사 중에서 한국 사용자들에게 유용한 정보 및 콘텐츠를 우선적으로 번역하여 내부 엔지니어 검수를 받아 정기적으로 게재하고 있습니다. 추가로 번역 및 게재를 희망하는 글에 대해서 관리자에게 메일 또는 SNS 페이지에 댓글을 남겨주시면, 우선적으로 번역해서 전달해드리도록 하겠습니다.