閉域環境でのPythonパッケージ管理:インターネット接続なしのVPCでCodeArtifactを利用する
はじめに
阿河です。
閉域環境ではインターネットに直接アクセスできないため、Pythonパッケージの管理には特別な工夫が求められます。本記事では、AWS CodeArtifactを活用し、閉域環境でも安全かつ効率的にPythonパッケージを利用する方法をご紹介します。
特に、怪しいファイルや意図しないパッケージが閉域環境に持ち込まれるリスクを最小限にするため、安全なリポジトリ(以下では「Safeリポジトリ」と呼びます)を活用し、信頼されたパッケージのみを利用する運用フローの構築を目指します。
このアプローチにより、CodeArtifactの柔軟性を最大限に活用しながら、安全性と運用効率を両立する方法を提案します。
目次
- CodeArtifactリポジトリのセットアップ
- ネットワーク環境構築
- テスト用にSageMakerノートブックインスタンスの作成
- パッケージのインストール
1. CodeArtifactリポジトリのセットアップ
ドメインの作成
- AWSマネジメントコンソールで、ドメインを作成。
- リポジトリは、ドメインと呼ばれる上位レベルのエンティティに集約されます。すべてのパッケージ アセットとメタデータはドメインに保存されますが、リポジトリを通じて使用されます。
- CodeArtifactのConceptはリンク先を御確認ください。
リポジトリの作成
- リポジトリ名を指定。
- リポジトリには、一連のパッケージ バージョンが含まれており、各バージョンは一連のアセットまたはファイルにマップされます。
- パブリックアップストリームリポジトリとして、pypi-storeを指定しています。
- CodeArtifactパブリックアップストリームリポジトリは、NPMなどの公式パッケージオーソリティにリポジトリを接続する中間リポジトリです。
- 外部接続からtest-artifact-domainを経由して、test-artifact-repositoryにパッケージがどのように流れるかを確認できます。
- アップストリームリポジトリを持つ場合の挙動は上記リンクを参照ください。
- 結果として2つのリポジトリが作成されます。
リポジトリエンドポイントの確認
aws codeartifact get-repository-endpoint \
--domain test-artifact-domain \
--repository test-artifact-repository \
--format pypi \
--region ap-northeast-1
- 特定のパッケージ形式のリポジトリのエンドポイントを返します。
- 閉域環境で利用するためのリポジトリエンドポイントを確認します。
2. ネットワーク環境構築
テスト環境をCloudFormationで構築します。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
EnableDnsHostnames: true
Subnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: false
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow access to VPC Endpoints
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
SubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref Subnet
RouteTableId: !Ref RouteTable
S3GatewayEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref VPC
ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3"
VpcEndpointType: Gateway
RouteTableIds:
- !Ref RouteTable
CodeArtifactAPIVPCEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref VPC
ServiceName: !Sub "com.amazonaws.ap-northeast-1.codeartifact.api"
VpcEndpointType: Interface
SubnetIds:
- !Ref Subnet
SecurityGroupIds:
- !Ref SecurityGroup
PrivateDnsEnabled: true
CodeArtifactRepoVPCEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref VPC
ServiceName: !Sub "com.amazonaws.ap-northeast-1.codeartifact.repositories"
VpcEndpointType: Interface
SubnetIds:
- !Ref Subnet
SecurityGroupIds:
- !Ref SecurityGroup
PrivateDnsEnabled: true
SageMakerNotebookVPCEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref VPC
ServiceName: !Sub "aws.sagemaker.ap-northeast-1.notebook"
VpcEndpointType: Interface
SubnetIds:
- !Ref Subnet
SecurityGroupIds:
- !Ref SecurityGroup
PrivateDnsEnabled: true
SageMakerAPIVPCEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref VPC
ServiceName: !Sub "com.amazonaws.ap-northeast-1.sagemaker.api"
VpcEndpointType: Interface
SubnetIds:
- !Ref Subnet
SecurityGroupIds:
- !Ref SecurityGroup
PrivateDnsEnabled: true
STSVPCEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref VPC
ServiceName: !Sub "com.amazonaws.ap-northeast-1.sts"
VpcEndpointType: Interface
SubnetIds:
- !Ref Subnet
SecurityGroupIds:
- !Ref SecurityGroup
PrivateDnsEnabled: true
LogsVPCEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref VPC
ServiceName: !Sub "com.amazonaws.ap-northeast-1.logs"
VpcEndpointType: Interface
SubnetIds:
- !Ref Subnet
SecurityGroupIds:
- !Ref SecurityGroup
PrivateDnsEnabled: true
Outputs:
VPCId:
Description: "VPC ID"
Value: !Ref VPC
Export:
Name: App-VPC
SubnetId:
Description: "Subnet ID"
Value: !Ref Subnet
Export:
Name: App-Subnet
SecurityGroupId:
Description: "Security Group ID"
Value: !Ref SecurityGroup
Export:
Name: App-SecurityGroup
- 設定は環境に合わせて変更してください。
3. テスト用にSageMakerノートブックインスタンスの作成
AWSTemplateFormatVersion: '2010-09-09'
Resources:
SageMakerNotebookRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: "sagemaker.amazonaws.com"
Action: "sts:AssumeRole"
Policies:
- PolicyName: SageMakerAccessPolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "codeartifact:GetRepositoryEndpoint"
- "codeartifact:ReadFromRepository"
- "codeartifact:GetAuthorizationToken"
- "codeartifact:ListPackages"
- "codeartifact:ListDomains"
Resource: "*"
- Effect: Allow
Action:
- "s3:GetObject"
- "s3:PutObject"
Resource: "arn:aws:s3:::xxxxxx/*"
- Effect: Allow
Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
Resource: "arn:aws:logs:*:*:*"
- Effect: Allow
Action:
- "sts:AssumeRole"
- "sts:GetCallerIdentity"
- "sts:GetServiceBearerToken"
Resource: "*"
SageMakerNotebookInstance:
Type: AWS::SageMaker::NotebookInstance
Properties:
InstanceType: ml.t3.medium
RoleArn: !GetAtt SageMakerNotebookRole.Arn
SubnetId: !ImportValue App-Subnet
SecurityGroupIds:
- !ImportValue App-SecurityGroup
NotebookInstanceName: Test-Notebook-Instance
DirectInternetAccess: "Disabled"
- SageMakerノートブックインスタンスは、インターネットアクセスをOFFにしています。
- 「xxxxxx」は環境に合わせてS3バケットを指定してください。
4. パッケージのインストール
デフォルトでインストールされているパッケージの確認
import pkg_resources
installed_packages = sorted([(d.project_name, d.version) for d in pkg_resources.working_set])
for package in installed_packages:
print(f"{package[0]}=={package[1]}")
- SageMakerノートブックインスタンスにログインし、上記コードを実行します。
- SageMaker ノートブックインスタンスにデフォルトでインストールされている Pythonパッケージを確認します。
- 私の環境ではstreamlitが入っていないようなので、次の検証でインストールしてみます。
CodeArtifactからいくつかパッケージをインストール
!aws codeartifact login --tool pip \
--domain test-artifact-domain \
--domain-owner xxxxxxxxx \
--repository test-artifact-repository \
--region ap-northeast-1
- domain-ownerにはAWSアカウント番号を入力
!pip install streamlit
- Streamlitをインストール
- 少し時間はかかるが、インストール成功。
streamlit 1.40.2
- インストールされたことが確認できます。
!pip install pandas --upgrade --force-reinstall
- 既にノートブックにインストールされていたPandasは再インストールを行っても、パッケージを取りに行く挙動を行いませんでした。
- こちらでPandsの再インストールおよびリポジトリへのパッケージ反映がされました。
おわりに
今回の解説を通じて、AWS CodeArtifactを活用した閉域環境でのPythonパッケージ管理の基盤が構築できました。現時点ではPyPIのコピーリポジトリを用いていますが、追加でSafeリポジトリを用意することで、信頼されたパッケージのみを利用できる仕組みを導入し、怪しいファイルや意図しないパッケージが閉域環境に持ち込まれるリスクをさらに低減する運用フローに繋げることができます。
完全にリスクを排除するには、CodeArtifactのリポジトリポリシーやIAMポリシーを適切に設定し、さらに運用面での管理を強化する必要があります。これらを補完するための「Safeリポジトリ」の活用が、安全な運用を支える重要な鍵と考えます。
閉域環境でのパッケージ管理には特有の課題がありますが、AWSのサービスを組み合わせることで、安全性と効率性を両立した運用を実現できる可能性があります。今後も最新のAWSサービスやセキュリティに関する情報を活用し、より堅牢な運用方法を模索していきたいと考えています。
Discussion