IMDSv2 サポート

Discourse でインスタンスプロファイル経由の IMDSv2 をサポートしているかについてお問い合わせいたします。IMDSv1 は安全なオプションではないため、現在サービスを IMDSv2 を使用するように移行中です。

Discourse が現在インスタンスプロファイル経由で IMDSv2 をサポートしているか、サポートしていない場合は、近い将来サポートする計画があるかを知りたいです。さらに、Discourse で IMDSv2 を使用できるようにする回避策やパッチはありますか?

セキュリティ要件を満たすことが重要であり、IMDSv2 を介した一時的な認証情報を使用することがその重要な側面であると考えています。

インスタンスプロファイルから提供されるセキュリティ認証情報にアクセスするための希望される動作は次のとおりです。

  • インスタンス上のアプリケーションは、インスタンスメタデータ項目 iam/security-credentials/ role-name から、ロールによって提供されるセキュリティ認証情報を取得します。
  • アプリケーションは、ロールに関連付けられたセキュリティ認証情報を通じて、ロールに対して定義したアクションとリソースの権限を付与されます。これらのセキュリティ認証情報は一時的であり、自動的にローテーションされます。古い認証情報が期限切れになる少なくとも 5 分前に新しい認証情報が利用可能になります。

IMDSv1 と IMDSv2 の呼び出しには違いがあることに注意しました。

IMDSv1 呼び出し:

curl http://169.254.169.254/latest/meta-data/iam/security-credentials/s3access

IMDSv2 呼び出しでは メタデータトークン を使用する必要があり、次のコマンドで実行できます。

TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \\\\\\\\\\\\\\\\
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/iam/security-credentials/s3access

Discourse で IMDSv2 を使用する方法、または利用可能な回避策やパッチについて、情報を提供していただければ幸いです。

参照:

Discourse自体がIMDSを使用する方法は認識していません。AWSにDiscourseをインストールしましたか?すでにDiscourseでIMDSv1を使用していますか?

ユースケースは何ですか?

関連するコードを1つ見つけました。

これはテスト仕様にあります。

Discourse は、IMDSv2 をサポートするために必要な最小バージョン (3.130.2) より新しいバージョンの AWS SDK を使用しており、AWS デプロイメントの MetadataNoToken メトリックを確認した限りでは、IMDSv1 への呼び出しはありません。

私の知る限り、すでにどこでも IMDSv2 を使用しています。

「いいね!」 3

1年前にAWS EC2インスタンスでDiscourseの使用を開始しました。そして今週、インスタンスをIMDSv2のみを使用するように更新したところ、エラーメッセージ「unable to sign request without credentials set」が表示され、AWS S3のアップロードが失敗しました。また、「s3 use iam profile」設定も利用しています。

ローカルIMDSサービスは、Discourseが他のAWS関連サービスAPI呼び出しを行うための認証情報を取得するために使用されます。これはRuby aws-sdk-s3を使用して行われます。

セキュリティ上の理由からIMDSv1を無効にした後、このバックアップの問題も発生しています。

MetadataNoTokenメトリックを通じてIMDSv1の使用(3.3.0.beta1-devで)を確認できるため、Discourseのどのバージョンで全面的にv2の使用に切り替わったのか疑問に思っています。

本日、AWSインスタンスをIMDSv2のみを使用するように変更したところ、私たちもこれに影響を受けました。ユーザーがS3に画像をアップロードできなくなりました。

おそらく関連性があるのは、s3 use iam profile オプションも使用していることです。

今のところ、「Optional」に切り替えました。これは基本的にIMDSv1がまだ有効であることを意味し、セキュリティ的には最善ではありませんが、アップロードが再び機能するようになりました。

「いいね!」 1

Discourse を IMDSv2 で動作させるための解決策や回避策はありますか?

.aws/config ファイル経由でより多くの設定を可能にする/期待する変更を行っており、これが重複して可能になる場合があります。

@supermathie 私が理解できない最も奇妙な点は、2つのDiscourseインスタンス(開発/本番)を個人的にセットアップしたことです。これらは、S3でのファイルアップロードとIAMプロファイルを使用したバックアップに関して、同一の設定(9436f5e3d4)で同一のバージョンに更新されています。そして、IMDSv1を無効にしたところ…開発環境ではすべてが期待どおりに動作し続けましたが、本番環境では動作せず、「認証情報が設定されていないためリクエストに署名できません」のようなエラーが引き続き発生します…非常に不可解です。

テスト/チェックできるアイデアがあれば、お知らせください。

@ducks が、IMDS 認証情報を取得する SDK のタイムアウトが非常に短く(1 秒、リトライなし)なっていることを特定しました。そのため、そのタイムアウトにヒットしている可能性があります。

しかし、それはあくまで推測です。

本番環境にコンソールで接続できる場合、対話的に実行できますか?例えば:

discourse(prod)> c = Aws::S3::Client.new(region: ENV['DISCOURSE_S3_REGION'])
=> #<Aws::S3::Client>

discourse(prod)> c.list_objects_v2(bucket: ENV['DISCOURSE_S3_BUCKET']).contents.count
=> 1000
「いいね!」 1

問題の原因がわかり、それは私のせいだと責めるしかありませんが、問題はかなり微妙なものでした。
問題は「HttpPutResponseHopLimit」が1に設定されていたことで、コンテナ内からIMDSv2を呼び出すことができませんでした。

このコマンドを発行したところ、次の回答が得られました。

> aws ec2 describe-instances --instance-ids i-00000000000000000 --query “Reservations[0].Instances[0].MetadataOptions”`
{
“State”: “applied”,
“HttpTokens”: “optional”,
“HttpPutResponseHopLimit”: 1,
“HttpEndpoint”: “enabled”,
“HttpProtocolIpv6”: “disabled”,
“InstanceMetadataTags”: “disabled”
}

設定を調整すると、正しい出力は次のようになります。

> aws ec2 describe-instances --instance-ids i-00000000000000000 --query “Reservations[0].Instances[0].MetadataOptions”`
{
“State”: “applied”,
“HttpTokens”: “required”,
“HttpPutResponseHopLimit”: 2,
“HttpEndpoint”: “enabled”,
“HttpProtocolIpv6”: “disabled”,
“InstanceMetadataTags”: “disabled”
}

…そしてついに謎が解けました :sweat_smile:

皆さん、ご協力ありがとうございました。

「いいね!」 1

これは知っておくべき素晴らしい情報です!

そして、これが他の人にも当てはまることを願っています。

しかし、なぜこれが私たちにとっては問題にならないのか疑問に思います。私たちはこれを1に設定していますが、それでも動作しますか?

discourse(prod)> ENV['AWS_EC2_METADATA_V1_DISABLED'] = 'true'
=> "true"
discourse(prod)> c = Aws::S3::Client.new(region: ENV['DISCOURSE_S3_REGION'])
=> #<Aws::S3::Client: ...>
discourse(prod)> c.config.credentials.disable_imds_v1
=> true
discourse(prod)> c.list_objects_v2(bucket: ENV['DISCOURSE_S3_BUCKET']).contents.count
=> 1000

そして、そのインスタンスは同じクエリコマンドによると、このメタデータを持っています。

{
    "State": "applied",
    "HttpTokens": "optional",
    "HttpPutResponseHopLimit": 1,
    "HttpEndpoint": "enabled",
    "HttpProtocolIpv6": "disabled",
    "InstanceMetadataTags": "disabled"
}

私たちは他の人たちと同じように、EC2上のDockerコンテナでDiscourseを実行していますが…何が違うのでしょうか?

このトピックは21時間後に自動的にクローズされました。新しい返信は許可されていません。