【AWS】AWS Transfer FamilyでEFSにパスワード認証で接続する

AWS Transfer Familyのパスワード認証の設定で、S3への接続設定の記事は結構あったが、EFSの方があまりなく若干追加で設定しないといけないことがあったので共有します。

1. リソースの作成

まずはパスワード認証に必要なリソース(AWS Transfer Family, API Gateway, Lambda)をAWS公式のCloudFormationのテンプレートから作成します。こちらのリンクからダウンロードしてください。

https://s3.amazonaws.com/aws-transfer-resources/custom-idp-templates/aws-transfer-custom-idp-secrets-manager-apig.template.yml

このまま作成するとS3用のAWS Transfer Family(SFTPサーバー)が作成されてしまうので、EFS用に設定するため66行目に1行追記します。

さらにEFS接続の場合はPosixProfileが必要になるため、Lambda関数でPosixProfileをレスポンスに含める記述を315~319行目あたりに以下を追記します。

if 'PosixUserId' in resp_dict and 'PosixGroupId' in resp_dict:
        print("PosixUserId and PosixGroupId found - Applying setting for PosixProfile")
        resp_data['PosixProfile'] = {"Uid": resp_dict['PosixUserId'], "Gid": resp_dict['PosixGroupId']}
else:
        print("PosixUserId or PosixGroupId not found - PosixProfile not set in response")

※PosixProfile(PosixUser, PosixGroup)が何なのかに興味がある方はこちら→https://dev.classmethod.jp/articles/efs-accesspoint-option-settings/


あとは更新したテンプレートでCloudFormationを実行し、リソースを作成するだけです。CloudFormationの具体的な操作方法が必要な方は以下の記事の「1.2. CloudFormationテンプレートの実行編」を参照ください。

https://dev.classmethod.jp/articles/aws-transfer-family-sftp-with-password-method/

2. AWS Transfer Family(SFTPサーバー)の接続ユーザーにEFSへの接続権限を付与

AWS Transfer Familyのマネジメントコンソールへログインし、「1」で作成されたサーバーの画面を開き、「IDプロバイダー」のセクションにある「呼び出しロール」のリンクを押下。 許可ポリシーの「許可を追加」で「AmazonElasticFileSystemFullAccess」権限を追加します(ここではいったんフル権限で設定しますが、必要に応じて最小権限のカスタマー管理ポリシーを作成・設定ください)。

3. 認証用のID/パスワードを作成

あとはAWS Transfer Family(SFTPサーバー)に接続するユーザー情報を、Secrets Managerに登録するだけです。Secrets Managerのコンソール画面から「新しいシークレットを保存する」ボタンを押下し、シークレットのタイプで「そのほかのシークレットタイプ」を選択、「キー/値のペア」のセクションで以下のペアを登録します。

  • Password:SFTPサーバーログイン時のパスワードを入力します
  • Role:「2」のロールのARNを指定します
  • HomeDirectory:EFSへログインした時の初期ディレクトリを指定します
  • PosixUserId:任意のPosix User IDを指定します
  • PosixGroupId:任意のPosix Group IDを指定します

次のページでSFTPログイン時のユーザー名となる「シークレットの名前」を登録しますが、必ず「SFTP/」を最初に記述してから任意のユーザー名を記載してください(Lambda側で「SFTP/」で認識する仕様になっているため)。SFTPサーバーへログインする時はこの「SFTP/」以後のユーザー名で実行することになります。

4. SFTPサーバーに接続

これで準備は整ったので、SFTPサーバー経由でEFSに接続します。コマンドラインでも可能ですが、今回はWinSCPでログインしてみます。

  • ホスト名:AWS Transfer Familyの対象のサーバーの「エンドポイント」を入力
  • ユーザー名:「3」で登録した「シークレットの名前」の「SFTP/」以後のユーザー名を入力
  • パスワード:「3」で登録した「キー/値のペア」の「Password」で登録した値を入力

無事ログインできたでしょうか?うまくいかない場合はAWS Transfer Familyのサーバーの画面で以下「テスト」の機能があり、そこでエラーメッセージが確認できるため見てみてください。

以上、どなたかのお役に立てられれば幸いです。Good Luck!

【AWS】AWS Transfer Family でEFSにWinSCPでSFTP接続する

EFSへは踏み台サーバーのEC2経由でログインして利用していたが、作業効率が悪いのでWinSCPとかで繋げたいなということで、AWS Transfer Familyを利用することにした。手順は以下の通り(※EFSは作成済のものとする)

1) SFTPサーバーの作成

  1. AWS Transfer Familyのマネジメントコンソールから「サーバーを作成」ボタンを押下
  2. プロトコルを選択します。今回はWinSCPからSFTP接続したかったのでSFTPを選択
  3. IDプロバイダーも今回は鍵認証でそのまま「サービスマネージド」で次へ
  4. エンドポイントの選択も外部からWinSCPで接続するため「パブリックアクセス可能」のまま次へ
  5. ドメインの選択。ここで今回は「Amazon EFS」の方を選択
  6. 「追加の詳細を設定」のページは特に何もないのでそのまま次へ
  7. 「確認と作成」のページもそのままで「サーバーを作成」ボタン押下

2) (ユーザー用の) ロールの作成

作成したSFTPサーバーを経由してEFSにアクセスするユーザーは、対象のEFSへの操作権限を持つロールが設定されている必要があるため、ユーザー作成前にそのロール及びポリシーを作成しておく

  1. まずはEFSへの操作を許可するIAMポリシーを作成する。IAM→ポリシー→ポリシーの作成でJSON形式で以下のように設定する EFSってなぜかコンソール画面でARNが載っておらず、自分でリージョン情報やらアカウント情報やらをくっつけて作らないといけなくて、自分は東京リージョンにEFS作ってたんですが、リージョン名を「ap-norheast-1」としないといけないところを「ap-norheast-1a」とAZ名にしてしまっていてハマりました。
  2. 次にロールを作成します。任意の名前で作成し、許可ポリシーのセクションで「許可を追加」ボタンを押下し、「1」で作成したポリシーをアタッチします。 ちなみにここで「AmazonElasticFileSystemFullAccess」ポリシーを付与すると、WinSCPで接続した際にアカウント内の全てのEFSにアクセスすることができた。※AWSのBestPracticeの「最小権限」に基づいて、ポリシーは必要最小限の設定推奨
  3. こちらは確認だけになりますが、「信頼ポリシー」が以下のような設定になっているかもチェック

3) ユーザーの作成

  1. 1)で作成したSFTPサーバーのリンクを押下しサーバーのページを開く
  2. 「ユーザー」セクションにて「ユーザーを追加」ボタンを押下
  3. ユーザー名などを入力。 POSIXユーザーID/POSIXグループIDというのはアクセスポイントに割り当てられたユーザー情報のことで、今回作成したユーザーでSFTPサーバー経由でEFSにアクセスした際に適用される。例えばLinux上で「ls -la」コマンドでファイルの一覧を表示したときに記載がある「所有ユーザー:所有グループ」を「chown」コマンドなどでここで指定したユーザーIDやグループIDに変更することで、SFTPから指定の権限にてそのファイルを操作できるようになる。セカンダリグループIDでもう一つ別のグループも割り当てることができる。
  4. ロールは2)で作成したロールを指定、ホームディレクトリは対象のEFSを指定する。「オプションのフォルダを入力」のテキストボックスにはログイン時のデフォルトパスを入力。「/」などのルートディレクトリは非推奨となっている。
  5. SSHパブリックキー」のセクションには公開鍵を入力するが、今回はWinSCPで接続するためputtyの鍵が必要。ローカルのWinSCPのツールから「PuTTYgenを実行」を選択
  6. 「Generate」ボタンを押下
  7. 以下赤枠の部分にてマウスを細かく動かすと鍵の生成が進行する
  8. 赤枠の公開鍵はコピーして5の「SSHパブリックキー」に貼り付け・保存する。緑枠部分にパスフレーズを入力し「Save private key」ボタン押下でローカルの任意の場所に秘密鍵を保存

4) WinSCPにてEFSにアクセスする

  1. WinSCPの「新しいサイト」にホスト名にAWS Transfer Familyで作成したSFTPサーバーのエンドポイントを入力。SFTP接続のためポート番号は22、ユーザー名は3)で作成したユーザー名、パスワードは今回は鍵認証なので入力しない。
  2. 「設定」ボタンを押下し、認証→秘密鍵で3)で作成した秘密鍵ファイル(ppkファイル)を選択し「OK」ボタン
  3. 元の画面に戻って「ログイン」ボタン押下。パスフレーズを聞かれるので3)-8で指定したパスフレーズを入力
  4. 無事ログインできました!

ちなみにここで「Unable to load key file "new.ppk" (PuTTY key format too new)」などのエラーメッセージが出た場合(私は出ました)、鍵とWinSCPのバージョンが合っていないのが原因のため、以下記事を参考にしてもらえると解決すると思います。 ccportal.ims.ac.jp

以上、長々とお付き合い頂きありがとうございました!この記事がどなたかのお役に立てれば幸いです。

【AWS】EventBridgeでFargateECSを自動停止/起動する

開発環境のECSコンテナを、コスト削減のため夜間は自動で止めておく設定をEventBridgeのルールを使用して実装する。今回作成するルールは二つ。

・コンテナを停止させるルール
・コンテナを起動させるルール

作成の仕方は同じなので停止させるルールで以下手順を記述。

  1. EventBridge -> ルール -> ルールを作成
  2. ルール名を指定。今回はCron式で日時を指定して実行させるため「スケジュール」を選択
  3. Cron式で日時指定。今回は月曜~金曜まで夜の22時に停止を実行させるよう記述
  4. ターゲット1を以下のような形で指定
  5. タグは任意で追加
  6. レビュー画面で問題がなければ「ルールの作成」ボタンを押下し完了

起動させるルール作成時はターゲット指定時に以下のタスク数を「1」で指定すればOK

※以下はターゲットがEC2のケースになりますが、IAMロールの作成方法などより詳細が書かれていたのでリンク貼っておきます

bftnagoya.hateblo.jp

【AWS / CodeBuild / Docker】You have reached your pull rate limit. You may increase the limit by authenticating and upgrading

◆問題

CodePipelineでECSのFargateにDeploy時、DockerHubのRateLimitに引っかかった。何度かやると成功する時もあるけど、正直何度も実行するのが面倒なので渋々対策することに。

◆解決方法

基本的には以下のページにあった内容の通りで行けた。

fu3ak1.hatenablog.com

1点付け加えるとすれば、CodeBuildの実行ロールでSSMの読み込み権限をPolicyアタッチしないと権限エラーとなる。アタッチするPolicyは以下の通り。

f:id:daylambsbecomelions:20220410111521p:plain

【AWS / Laravel】The stream or file "/var/www/html/storage/logs/laravel.log" could not be opened in append mode: failed to open stream: Permission denied

◆問題

ECSのFargateでLaravelのプロジェクトを立ち上げた時に掲題のエラーが発生。storageのフォルダはDockerfileで以下の通り権限変更しており、同じDockerイメージでローカルで立ち上げた時は何事もなく動くのになぜ??

RUN chmod -R 775 storage

◆原因

色々試してみて分かったのだが、どうやらルートからの絶対パスで書かないとダメだったのと、AWS環境の場合はフォルダの所有者も「www-data」に変更する必要がある模様。

◆解決方法

自分のケースの場合は「/var/www/html」配下にLaravelのプロジェクトソースを展開しているので、以下のような形でDockerfile内の権限部分を変更するとうまくいった。

RUN chmod -R 775 /var/www/html/storage && \
         chown -R www-data:www-data /var/www/html/storage

【AWS】CodePipelineでFargateのコンテナをDeploy時、ALBのTargetGroupが切り替わらない

◆問題

掲題の通りなのだが、自分でECSのFargateを立てて、CodePipelineでDeploy自動化を実装した際、ECS側のTargetGroupは切り替わるけど、ALBのTargetGroupが2つのうち1つ(Green側だけ)が固定となり切り替わらず、CodePipelineでGreen側にDeployした時だけ(2回に1回)しかリクエストが通らない問題が発生した。

◆原因

結局ALBへのTargetGroupの設定方法に問題があった。ALBとTargetGroupの紐付ける際、他にも色んなエラーが出ていたので、TargetGroupを個別で作成して、それをALBやECSのサービスに紐付けたりしていたけど、そのやり方が不味かった。

◆解決方法

正解のやり方として、ALBにTargetGroupが何も紐づいていない状態で、ECSのサービスを作成する際にALBを指定し、TargetGroupを新規作成して紐付ける必要があった。こういう方法でTargetGroupを紐づけることで、CodePipelineでDeployしてうまく切り替えられるようになり、想定通りの挙動になった。

f:id:daylambsbecomelions:20220409160724p:plain

【AWS】standard_init_linux.go:228: exec user process caused: exec format error 解決方法

MacでローカルでDockerイメージをビルドしてAWSのECRにpush。ECR上のイメージでECSのFargateを作って起動させた時に以下エラーが発生してコンテナが起動してはすぐに落ちるのループ状態に。

standard_init_linux.go:228: exec user process caused: exec format error

同じイメージでローカルでコンテナを起動したらうまく行くのになんでやねん!と思ってハマってたところ、以下のような記事を見つけた。

hikari-blog.com

はい、ここにある通り、M1チップ搭載のMacでDockerイメージをビルドしたのが原因でした。ビルドするマシンと実行するマシンのCPUアーキテクチャが異なると起動に失敗する、とのことです。Cloud9とかEC2, CodeBuildなど、AWSのサービス上でビルドすれば問題なかったようですが、まさかM1チップが原因だとは思いつきませんでした。

イメージビルド時にplatformを指定やれば、Macローカルビルドしたイメージでも問題なくコンテナ起動しました。

docker build --platform amd64 ./