[アップデート]AWS SAM CLIのローカル実行時に環境上のhostsファイルに設定を追加できるようになりました

2024.01.24

初めに

本日AWS SAM CLIのv1.108.0がリリースされました。

今回のアップデートでlocal invoke--add-hostオプションが追加されました。
こちらのオプションは値としてホスト名:IPを指定することでコンテナ内のhostsファイルに対してその値を引き渡すことができます。

説明や実装を見る限りstart-lambdastart-apiにも実装されていそうですが(オプションを受け付ける)、実際に実行して見る限りinvokeではhostsファイルに書き込まれるもののそれ以外のサブコマンドでは確認できていません(バグかも?)。

これまでAWS SAM CLIでローカル実行する際に特定のホスト名への通信を一時的に別の通信先に向けたい場合や、ネームサーバを利用しない場合で実行環境内へのhostsファイルの書き直しが必要な場合、引き渡すための手段がないためそれだけのためにコンテナイメージを別途ビルドするなりアプリ側に差し替えるような処理を差し込むような必要がありました。

また開発環境のみでそれを適用したい場合当然フロー次第では誤ったデプロイをさせないように注意する必要があります。

今後はそういった必要はなく一時的であれば実行時のオプション、継続的であればsamconfigに書き込むことで実行環境や処理とは独立して設定をすることができます。

機能としてはdocker runの同名のオプション相当の機能ですので普段かからこちらをご利用いただいている方には説明不要かもしれません。

確認

実際にプログラム側に特定のホスト名にHTTPリクエストをかけてもいいのですが、直接環境に入ったほうがhostsファイルも見れてわかりやすいと思いますのでそちらで確認します。

未指定時

まずは比較として通常時(未指定時)の確認を行います。

sam initでPython3.12のHelloWorldをlocal start-apiで起動します。

% sam local start-api
Initializing the lambda functions containers.                                                                                                                                          
Local image is out of date and will be updated to the latest runtime. To skip this, pass in the parameter --skip-pull-image                                                            
Building image..........................................................................................................................................................................
Using local image: public.ecr.aws/lambda/python:3.12-rapid-x86_64.                                                                                                            
...
 * Running on http://127.0.0.1:3000
2024-01-24 12:26:57 Press CTRL+C to quit

SAMの実際の実行環境はコンテナ上で動いているためdocker psで実行中のコンテナを確認すると対象のコンテナが確認できます。

% docker ps
CONTAINER ID   IMAGE                                            COMMAND                   CREATED         STATUS         PORTS                      NAMES
769b3f8e0f99   public.ecr.aws/lambda/python:3.12-rapid-x86_64   "/var/rapid/aws-lamb…"   3 seconds ago   Up 2 seconds   127.0.0.1:5513->8080/tcp   eager_blackburn

なお今回確認して初めて知ったのですがSAM側としては常に指定ポート(デフォルト3000)で受け付けるようですが立ち上がるコンテナ自体は別のランダムなポートで受け付けているようです。
あまりそこまで詳しく処理を見たことはないのですがSAM側のflaskが3000番台で受け付けて、オーソライザの処理等はSAM側で行い実際のLambdaコード処理のフェーズになったら別途処理コンテナに投げるような処理をしているのかもしれません(想像のため実態は不明)。

該当コンテナのhostsをdocker exec経由で確認します。

% docker exec 769b3f8e0f99 cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.3	769b3f8e0f99

add-host指定時

--add-hostの指定はdocker run同様にホスト名:IPの組で引き渡します。複数指定が必要な場合はその分だけ--add-hostオプションを列挙します。

前述の通りlocal invoke以外では動作を確認できなかったためtime.sleep()でコンテナをできる限り起動状態で保持するようにした上でlocal invokeを実行し先ほど同様に立ち上がってるコンテナで/etc/hostsdocker exec経由で表示します。

$ sam local invoke --add-host foo:127.0.0.1 --add-host bar:127.0.0.1
...
% docker exec 06787ba36889 cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
127.0.0.1	bar
127.0.0.1	foo
172.17.0.2	06787ba36889

samconfigで指定し引き渡す場合は配列で定義を行います。

samconfig.toml

[default.local_invoke.parameters]
add_host = ["foo:127.0.0.1", "bar:127.0.0.1"]

一応start-apiでもdebugのログを見る限り値自体は引渡されていそうではあるのですが現バージョンではhostsファイルに乗っていることを確認できませんでした。

 % sam local start-api --add-host foo:127.0.0.1 --add-host bar:127.0.0.1 --debug
...                                                                                                                      
2024-01-24 19:43:34,299 | --template_file=/Users/xxx/git/sam-app/.aws-sam/build/template.yaml --add_host={'foo': '127.0.0.1', 'bar': '127.0.0.1'} --host=127.0.0.1 --port=3000
...
% docker exec f0364ca01517 cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.2	f0364ca01517

終わりに

ハードコードされたURLがありアプリを書き換えたくない場合、公開したくないホスト名ではあるがプライベートのDNSサーバを作る感じでもなくhostsファイルを利用している場合、といった形でローカル環境だと結構利用するケースはあるかと思いますのでこれがぱっとできるのは嬉しいのではないでしょうか。

SAM環境からSAM環境にはなりますが直近SAMでHTTPS通信が利用できるアップデートがありましたので信頼される正規の認証機関から発行された証明書をローカルに持ち込み、そのSAM環境にアクセスする際にhostsファイルでそのドメインを割り当てると証明書の検証を正規に通しつつ確認ということもできそうです。

今回動作を確認する限りはまだlocal invoke以外では利用できなさそうなのでこの辺りが対応(もしくは修正?)されてくれれば一気に利用ケースが膨らみそうです。