AWS

S3にaptリポジトリを作成してプライベートサブネットから参照する

スポンサーリンク
S3にaptリポジトリを作成してプライベートサブネットから参照する AWS
スポンサーリンク
スポンサーリンク

プライベートサブネット内のUbuntuから、S3上の自作aptリポジトリにアクセスする

以下のページで、S3上にyumリポジトリを作成する方法をご紹介しました。

今回はS3上でaptリポジトリを構築し、プライベートサブネット上に配置されたUbuntuからアクセスします。

構築する環境

AWS認定資格試験テキスト AWS認定ソリューションアーキテクト - アソシエイト 改訂第2版 | 佐々木 拓郎, 林 晋一郎, 金澤 圭 | 産業研究 | Kindleストア | Amazon
Amazonで佐々木 拓郎, 林 晋一郎, 金澤 圭のAWS認定資格試験テキスト AWS認定ソリューションアーキテクト - アソシエイト 改訂第2版。アマゾンならポイント還元本が多数。一度購入いただいた電子書籍は、KindleおよびFire端末、スマートフォンやタブレットなど、様々な端末でもお楽しみいただけます。
Diagram of create apt Repository in S3 and Access from Private Subnet.

2つのVPCを作成します。

一方のVPCはaptリポジトリ作成用です。
最新のUbuntuインスタンスを配置し、aptlyを使用してリポジトリを作成します。

aptly - Debian repository management tool

今回はプライベートサブネットからApacheをインストールするためのリポジトリを作成します。

もう一方のVPCに、自作リポジトリの検証インスタンスを配置します。
こちらのVPCにはインターネットゲートウェイやNATゲートウェイを配置せず、S3用VPCエンドポイントを経由して、S3バケットにアクセスします。

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置してます。

awstut-fa/032 at main · awstut-an-r/awstut-fa
Contribute to awstut-an-r/awstut-fa development by creating an account on GitHub.

テンプレートファイルのポイント解説

静的Webサイトホスティング機能を有効化する

S3バケットを確認します。
ポイントは静的Webサイトホスティングに関する設定です。

Resources: Bucket: Type: AWS::S3::Bucket Properties: BucketName: !Ref Prefix AccessControl: Private WebsiteConfiguration: IndexDocument: index.html
Code language: YAML (yaml)

WebsiteConfigurationプロパティで静的Webサイトホスティング機能を設定します。
本機能を有効化することで、aptクライアントからのHTTP通信を受け付けることができます。

注意点はIndexDocumentプロパティです。
本プロパティに「index.html」を設定します。
これは本プロパティを設定しなければ、ホスティング機能が有効化できないためです。
そのため実際にインデックスファイルを設置するわけではありませんが、形式的に設定します。

バケットポリシーでアクセス制限する

作成したバケットへのアクセスを、バケットポリシーを使って制限します。
ポイントはアクセスを許可する条件です。
今回は以下の方針でアクセス制限します。

  • 送信元のIPアドレスが、NATゲートウェイに付与したElastic IPアドレスの場合は、アクセスを許可する ※ VPC1内のインスタンス用
  • 送信元のVPCがVPC2の場合は、アクセスを許可する ※ VPC2内のインスタンス用
Resources: BucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref Bucket PolicyDocument: Version: 2012-10-17 Statement: - Action: - s3:* Effect: Allow Resource: - !Sub "arn:aws:s3:::${Bucket}" - !Sub "arn:aws:s3:::${Bucket}/*" Condition: IpAddress: "aws:SourceIp": - !Ref EIP Principal: "*" - Action: - s3:* Effect: Allow Resource: - !Sub "arn:aws:s3:::${Bucket}" - !Sub "arn:aws:s3:::${Bucket}/*" Condition: StringEquals: "aws:SourceVpc": - !Ref VPC Principal: "*"
Code language: YAML (yaml)

2つのポリシーを定義します。

1つ目のポリシーは、インスタンス1からのアクセスを許可するためのものです。
Conditionプロパティがポイントです。
IpAddressプロパティに「aws:SourceIp」およびNATゲートウェイに付与したElastic IPアドレスを設定することで、同アドレスからの通信を許可するポリシーとなります。
インスタンス1がS3バケットにアクセスする際は、NATゲートウェイを経由し、送信元アドレスがElastic IPアドレスに付け替わるためです。

2つ目のポリシーは、インスタンス2からのアクセスを許可するためのものです。
こちらもConditionプロパティで条件を設定します。
StringEqualsプロパティに「aws:SourceVpc」およびVPC2のIDを設定することで、同VPC内からの通信を許可するポリシーとなります。

S3用VPCエンドポイント

VPC2はインターネットとの接点を作成せず、VPCエンドポイントを通じて、S3バケットへアクセスします。

Resources: S3Endpoint: Type: AWS::EC2::VPCEndpoint Properties: RouteTableIds: - !Ref PrivateRouteTable ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3" VpcId: !Ref VPC
Code language: YAML (yaml)

特別な設定は不要です。
ServiceNameプロパティにS3を設定します。
S3用のVPCエンドポイントはゲートウェイタイプですから、VPC2のIDおよび同VPC内のサブネットに関連づいたルートテーブルを設定します。

aptlyでリポジトリを作成する

aptリポジトリを作成するために、インスタンス1で実行する内容を確認します。

Resources: RunShellScriptAssociation1: Type: AWS::SSM::Association Properties: AssociationName: !Sub "${Prefix}-runshellscript-association1" Name: AWS-RunShellScript Parameters: commands: - "sudo apt update" - "sudo apt install -y aptly" - "sudo apt install -y unzip" - "curl 'https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip' -o 'awscliv2.zip'" - "unzip awscliv2.zip" - "sudo ./aws/install" - !Sub | sudo cat << EOF > ./gpg.txt Key-Type: RSA Subkey-Type: RSA Key-Length: 2048 Subkey-Length: 2048 Expire-Date: 0 Name-Real: ${GPGName} Name-Email: ${GPGEmail} Passphrase: ${GPGPassphrase} EOF - "sudo gpg1 --gen-key --batch ./gpg.txt" - "sudo gpg1 --no-default-keyring --keyring trustedkeys.gpg --keyserver keyserver.ubuntu.com --recv-keys 40976EAF437D05B5 3B4FE6ACC0B21F32" - !Sub "sudo aptly mirror create -architectures=${Arch} -filter='apache2' -filter-with-deps myrepo http://ap-northeast-1a.clouds.ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe multiverse" - !Sub "sudo aptly mirror update ${Repository}" - !Sub "sudo aptly snapshot create ${Repository}-${SnapshotSuffix} from mirror ${Repository}" - !Sub | sudo cat << EOF > /root/.aptly.conf { "rootDir": "/root/.aptly", "downloadConcurrency": 4, "downloadSpeedLimit": 0, "architectures": [], "dependencyFollowSuggests": false, "dependencyFollowRecommends": false, "dependencyFollowAllVariants": false, "dependencyFollowSource": false, "dependencyVerboseResolve": false, "gpgDisableSign": false, "gpgDisableVerify": false, "gpgProvider": "gpg", "downloadSourcePackages": false, "skipLegacyPool": true, "ppaDistributorID": "ubuntu", "ppaCodename": "", "skipContentsPublishing": false, "FileSystemPublishEndpoints": {}, "S3PublishEndpoints": { "fa-032": { "region": "${AWS::Region}", "bucket": "${Bucket}" } }, "SwiftPublishEndpoints": {} } EOF - !Sub "sudo aptly publish snapshot -batch -passphrase='${GPGPassphrase}' ${Repository}-${SnapshotSuffix} s3:${Bucket}:" - "sudo gpg1 --export --armor > ./gpg.pub" - !Sub "aws s3 cp ./gpg.pub s3://${Bucket}/" Targets: - Key: InstanceIds Values: - !Ref Instance1 WaitForSuccessTimeoutSeconds: !Ref WaitForSuccessTimeoutSeconds
Code language: YAML (yaml)

今回はインスタンス初期化処理の一環として、SSMドキュメントAWS-RunShellScriptを実行し、リポジトリ作成を行います。
同ドキュメントを使用した初期化処理に関しては、以下のページをご確認ください。

冒頭でも述べた通り、aptlyを使用してリポジトリを作成し、S3バケットに公開します。

commandsプロパティで、実際に実行するコマンドを定義します。
コマンドの内容は以下の通りです。

  • 事前準備(パッケージ更新、aptlyインストール、AWS CLIインストール)
  • バッチモードのGnuPGで公開鍵を作成する
  • 元リポジトリ(http://ap-northeast-1a.clouds.ports.ubuntu.com/ubuntu-ports/)用の公開鍵を取得して、ミラーリポジトリを作成し、スナップショットを作成する
  • aptlyのコンフィグファイルにS3バケットの情報を記載し、バッチモードでS3バケットにスナップショットを公開する。
  • リポジトリ署名時に使用した鍵の公開鍵をエクスポートし、AWS CLIを使用してS3バケットにアップロードする。

注意点はaptlyが対応しているGnuPGのバージョンです。

Aptly at this time only supports GNUPG 1.x for server-side use. On newer Debian systems you’ll want to make sure that the gnupg1 and gpgv1 packages are installed.

PGP PROVIDERS

上記の通り、1系にのみ対応しているとされていますので、2系を使用しないように注意してください。
ですから今回は「gpg」コマンドではなく、「gpg1」コマンドを使用することで、明示的に1系を使用しています。

もう1つの注意点は、aptlyからS3バケットにアクセスするための権限についてです。
公式サイトでは、必要な権限を持つIAMユーザーのアクセスキーを使用する方法が紹介されています。

awsAccessKeyID, awsSecretAccessKey: (optional) Amazon credentials to access S3 bucket. If not supplied, environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are used.

PUBLISHING TO AMAZON S3

ただし今回は上記で記されているようなパラメータ設定や、環境変数の指定は不要です。
これは先述のS3バケットポリシー側で、両インスタンスからのアクセスを許可しているためです。

なおaptlyの使用方法については、以下のサイトを参照しました。

第485回 aptlyで本格的なパッケージリポジトリを作る
Ubuntuのパッケージリポジトリのスナップショットを作成したり,独自パッケージリポジトリを作成したいならaptlyが便利です。今回はこのaptlyの使い方について紹介します。
aptlyを用いたDebianローカルリポジトリ構築 - Qiita
背景 Ubuntuの環境構築を行う際、パッケージの更新やインストールを行いますが、環境によってはインターネット接続が制限されるケースもあると思います。そのような場合、Debianパッケージのローカルリポジトリを構築して、そこから...

aptに自作リポジトリを登録する

インスタンス2で実行する内容を確認します。
ポイントは自作したaptリポジトリを参照する方法です。

Resources: RunShellScriptAssociation2: Type: AWS::SSM::Association DependsOn: - RunShellScriptAssociation1 Properties: AssociationName: !Sub "${Prefix}-runshellscript-association2" Name: AWS-RunShellScript Parameters: commands: - !Sub "curl ${BucketWebsiteURL}/gpg.pub | sudo apt-key add -" - !Sub | sudo cat << EOF > /etc/apt/sources.list deb ${BucketWebsiteURL}/ xenial main EOF Targets: - Key: InstanceIds Values: - !Ref Instance2 WaitForSuccessTimeoutSeconds: !Ref WaitForSuccessTimeoutSeconds
Code language: YAML (yaml)

こちらもSSMドキュメントAWS-RunShellScriptを実行して、自作リポジトリ参照に必要な処理を行います。
コマンドの内容は以下の通りです。

  • S3バケットに配置した公開鍵をインポートする
  • 自作リポジトリを記載した/etc/apt/sources.listを配置する

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • S3バケット:fa-032
  • S3バケットのWebサイトエンドポイント:http://fa-032.s3-website-ap-northeast-1.amazonaws.com
  • インスタンス1:i-09467a9a4e6bb9bc4
  • インスタンス2:i-063843a7185abe446

AWS Management Consoleからも、リソースの作成状況を確認します。
まずインスタンスの作成状況です。

Two Ubuntu instances are created.

確かに2つのインスタンスが作成されています。

次に両インスタンスにおけるSSMドキュメントの実行結果を確認します。

SSM Document Execution Result 1.
SSM Document Execution Result 2.

Outputから実行結果を確認することができます。

S3バケットを確認します。

Snapshots are published in S3 aptly.

aptlyでアップロードされたリポジトリファイルと、このリポジトリの公開鍵が配置されていることがわかります。

S3 website hosting is enabled.

静的Webサイトホスティング機能が有効化され、HTTPリクエストを受け付ける準備が整っていることも確認できます。

S3 bucket policy allows access from both instances.

バケットポリシーによってNATゲートウェイのアドレスと、VPC2からのアクセスが許可されています。
これで両インスタンスがS3バケットにアクセス可能ということです。

動作確認

準備が整いましたので、インスタンス2にアクセスします。
インスタンスへのアクセスは、SSM Session Managerを使用します。

% aws ssm start-session --target i-063843a7185abe446 Starting session with SessionId: root-05d2fb1be2c79590b $
Code language: Bash (bash)

詳細は以下のページをご確認ください。

公開鍵の登録状況を確認します。

$ sudo apt-key list /etc/apt/trusted.gpg -------------------- pub rsa2048 2022-06-19 [SCEA] 1133 C594 73B1 E2D9 5E32 09A2 BD71 F30D 3250 8A8D uid [ unknown] fa-032 <fa-032@example.com> sub rsa2048 2022-06-19 [SEA] ...
Code language: Bash (bash)

自作リポジトリの検証用鍵が登録されています。

自作リポジトリの登録用ファイルを確認します。

$ sudo cat /etc/apt/sources.list deb http://fa-032.s3-website-ap-northeast-1.amazonaws.com/ xenial main
Code language: Bash (bash)

確かに自作リポジトリが登録されています。

パッケージ一覧を更新します。

$ sudo apt update Get:1 http://fa-032.s3-website-ap-northeast-1.amazonaws.com xenial InRelease [3170 B] Get:2 http://fa-032.s3-website-ap-northeast-1.amazonaws.com xenial/main arm64 Packages [31.8 kB] Fetched 34.9 kB in 0s (151 kB/s) Reading package lists... Done Building dependency tree Reading state information... Done All packages are up to date.
Code language: Bash (bash)

自作リポジトリにアクセスし、正常に更新されました。
先述の鍵を使って検証が行われたということです。

Apacheをインストールします。

$ sudo apt install -y apache2 Reading package lists... Done Building dependency tree Reading state information... Done The following additional packages will be installed: apache2-bin apache2-data apache2-utils libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.1-0 libssl1.0.0 Suggested packages: www-browser apache2-doc apache2-suexec-pristine | apache2-suexec-custom Recommended packages: ssl-cert The following NEW packages will be installed: apache2 apache2-bin apache2-data apache2-utils libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.1-0 libssl1.0.0 0 upgraded, 10 newly installed, 0 to remove and 0 not upgraded. Need to get 2061 kB of archives. After this operation, 8762 kB of additional disk space will be used. Get:1 http://fa-032.s3-website-ap-northeast-1.amazonaws.com xenial/main arm64 libapr1 arm64 1.5.2-3 [71.1 kB] Get:2 http://fa-032.s3-website-ap-northeast-1.amazonaws.com xenial/main arm64 libssl1.0.0 arm64 1.0.2g-1ubuntu4 [726 kB] Get:3 http://fa-032.s3-website-ap-northeast-1.amazonaws.com xenial/main arm64 libaprutil1 arm64 1.5.4-1build1 [67.4 kB] Get:4 http://fa-032.s3-website-ap-northeast-1.amazonaws.com xenial/main arm64 libaprutil1-dbd-sqlite3 arm64 1.5.4-1build1 [9656 B] Get:5 http://fa-032.s3-website-ap-northeast-1.amazonaws.com xenial/main arm64 libaprutil1-ldap arm64 1.5.4-1build1 [8358 B] Get:6 http://fa-032.s3-website-ap-northeast-1.amazonaws.com xenial/main arm64 liblua5.1-0 arm64 5.1.5-8ubuntu1 [88.7 kB] Get:7 http://fa-032.s3-website-ap-northeast-1.amazonaws.com xenial/main arm64 apache2-bin arm64 2.4.18-2ubuntu3 [764 kB] Get:8 http://fa-032.s3-website-ap-northeast-1.amazonaws.com xenial/main arm64 apache2-utils arm64 2.4.18-2ubuntu3 [77.5 kB] Get:9 http://fa-032.s3-website-ap-northeast-1.amazonaws.com xenial/main arm64 apache2-data all 2.4.18-2ubuntu3 [162 kB] Get:10 http://fa-032.s3-website-ap-northeast-1.amazonaws.com xenial/main arm64 apache2 arm64 2.4.18-2ubuntu3 [86.7 kB] ...
Code language: Bash (bash)

正常に自作リポジトリからインストールが完了しました。

最後にApacheの動作状況を確認します。

$ sudo systemctl status apache2 ● apache2.service - LSB: Apache2 web server Loaded: loaded (/etc/init.d/apache2; generated) Drop-In: /usr/lib/systemd/system/apache2.service.d └─apache2-systemd.conf Active: active (running) since Sun 2022-06-19 03:58:31 UTC; 1min 54s ago Docs: man:systemd-sysv-generator(8) Tasks: 55 (limit: 1061) Memory: 4.6M CGroup: /system.slice/apache2.service ├─2221 /usr/sbin/apache2 -k start ├─2224 /usr/sbin/apache2 -k start └─2225 /usr/sbin/apache2 -k start Jun 19 03:58:30 ip-10-0-1-205 systemd[1]: Starting LSB: Apache2 web server... Jun 19 03:58:30 ip-10-0-1-205 apache2[2199]: * Starting Apache httpd web server apache2 Jun 19 03:58:31 ip-10-0-1-205 apache2[2199]: * Jun 19 03:58:31 ip-10-0-1-205 systemd[1]: Started LSB: Apache2 web server.
Code language: Bash (bash)

正常に動作しています。

まとめ

S3上に、自作のaptリポジトリを構築する方法を確認しました。
自作リポジトリを作成し、参照することで、プライベートサブネットに配置されたUbuntuインスタンスでも、インターネットにアクセスせずとも、任意のパッケージをインストールできることできました。

タイトルとURLをコピーしました