こんにちは。アクセンチュアの奥友です。

皆さんAWSのアクセスキーは適切に管理されているでしょうか?

AWSのアクセスキーとは、AWS APIにプログラムでアクセスするためのIAMユーザーまたはAWSアカウントルートユーザーの長期的な認証情報を指します。
残念ながら、少し検索するだけでAWSのアクセスキーが外部に漏洩し、「不正アクセスによるデータ流出」「大量のEC2インスタンスが不正に起動されることによる、多額の利用費請求」など 様々な事例を見つけることができます。

AWSのプラットフォームは堅牢ですが、責任共有モデルに従いユーザーの責任範囲は使い方次第です。
AWSのアクセスキーを管理するためのベストプラクティスでは、そもそもアクセスキーは極力作成せず、IAMロールを使用することが推奨されています。
とはいえ、IAMロールはAWS環境内のリソースからは容易に使用できますが、例えばオンプレミスのサーバからAWSにデータを送付するような際には通常利用できません。

本日は、オンプレミスのサーバでAWSのアクセスキーを作成せず、IAMロールを使用してAWSにアクセスする方法を記載してみようと思います。
なお、大前提として、IAMロールには必要最小限のIAMポリシーを付与する、ということを忘れないようにしましょう!

AWS Systems Manager ハイブリッド環境

AWS Systems Manager Agent(SSM Agent)をオンプレミスのサーバにインストールし、ハイブリッド環境を設定することでオンプレミスからIAMロールを使用することができます。

設定概要

  1. オンプレミスのサーバで使用するIAMロール及びIAMポリシーを作成する
  2. ハイブリッドアクティベーションコードを発行する
  3. オンプレミスのサーバにSSM Agentをインストールする
  4. SSM Agentを登録する

詳しくは、ハイブリッド環境で AWS Systems Manager を設定するを参照ください。

SSM Agentが取得したIAMロール認証情報を取得

SSM Agentを起動すると、デフォルトでは下記に[credentials]ファイルを保存し、定期的に認証情報(aws_access_key_id/aws_secret_access_key/aws_session_token)を自動更新してくれるようになります。

  • Linux: "/root/.aws/credentials"
  • Windows: "%USERPROFILE%\.aws\credentials" ※SYSTEMアカウントの場合 "C:\Windows\System32\config\systemprofile"

認証情報ファイルは、SSM Agent によって新しい一時的な認証情報で 30 分ごとに更新されます。

引用元: https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudwatch-on-premises-temp-credentials/

実際に手元の環境で動作させてみると、30分ごとに認証情報が自動更新されていることを確認できました。

プログラムを実行するOSのユーザーアカウントがSSM Agentと異なる場合は、[credentials]ファイルへの読み込みアクセス権限を付与した上で
環境変数を設定することにより、異なるユーザーアカウントのAWS CLIやSDKから[credentials]ファイルを使用することが可能となります。

AWS_SHARED_CREDENTIALS_FILE=/root/.aws/credentials

留意点としては、[credentials]ファイルから取得する認証情報の有効期限は、紐付けたIAMロールのセッション有効期限に依存するため、[credentials]ファイルが自動更新されても更新前の認証情報は無効になりません。
また、IAMロールの信頼関係は認証情報を発行できる対象を制限しますが、例えば取得後の[credentials]ファイルを持ち出して他のサーバ等で利用することは可能です。
これはSSM Agent特有の事象ではなく、例えばLambdaに付与したIAMロールの認証情報を環境変数から取得し、ローカル端末から実行することもセッション有効期限内ならば可能です。
SSM Agentにより認証情報は30分毎に自動更新されるためIAMロールのセッション時間は充分短く設定するよう留意してください。
(AWSマネージメンドコンソールからハイブリットアクティベーションを有効化した際に、自動で作成できるIAMロールのセッション時間はデフォルト1時間で作成されます)

SSM AgentはどのようにIAMロールの認証情報を取得しているのか

SSM Agentは認証情報をどのように取得しているのでしょうか?
少し長くなりますが、AWS Systems Managerの公式ドキュメントから引用します。

ハイブリッド環境でオンプレミスサーバーと仮想マシン (VM) を実行する場合、SSM Mエージェントは多数のシステム属性 (ハードウェアハッシュと呼ばれます) を収集し、これらの属性を使用してフィンガープリントを計算します。フィンガープリントは、エージェントが特定の Systems Manager API に渡す不透明な文字列です。
この一意のフィンガープリントは、発信者を特定のマネージドインスタンスに関連付けます。エージェントは、フィンガープリントとハードウェアハッシュをローカルディスク上の Vault と呼ばれる場所に保存します。エージェントは、オンプレミスサーバーまたは VM が Systems Manager で使用するために登録されると、ハードウェアハッシュとフィンガープリントを計算します。
エージェントが RegisterManagedInstance コマンドを送信すると、フィンガープリントが Systems Manager サービスに戻されます。その後、RequestManagedInstanceRoleToken コマンドを送信するときに、エージェントは Vault 内のフィンガープリントとハードウェアハッシュをチェックして、現在のマシン属性が保存されているハードウェアハッシュと一致することを確認します。
現在のマシン属性が Vault に保存されているハードウェアハッシュと一致する場合、エージェントはフィンガープリントを Vault から RegisterManagedInstance に渡し、呼び出しが成功します。
現在のマシン属性が保存されているハードウェアハッシュと一致しない場合、SSM Agent は新しいフィンガープリントをコンピューティングし、新しいハードウェアハッシュとフィンガープリントを Vault に保存し、新しいフィンガープリントを RequestManagedInstanceRoleToken に渡します。
これにより RequestManagedInstanceRoleToken が失敗し、エージェントは Systems Manager サービスに接続するためのロールトークンを取得できません。この障害は設計上のものであり、複数のオンプレミスサーバーおよび VM が同じマネージドインスタンスとして Systems Manager サービスと通信するのを防ぐための検証手順として使用されます。

引用元: https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/ssm-agent-technical-details.html#fingerprint-validation

ドキュメントの通りですが、手元の環境でも動作を確認してみます。
オンプレミスのサーバにインストールしたSSM Agentをアクティベーションすると、[InstanceFingerprint]ファイルへ、uuid-v4のフィンガープリントとマシンIDやIP/MACアドレスなどをセットしたハードウェアハッシュが保存されました。また、[RegistrationKey]ファイルへ、RSA-2048のプライベートキーが保存されました。

/var/lib/amazon/ssm/Vault/Store/InstanceFingerprint

{"fingerprint":"xxx-xxxx-xxxx-xxxx-xxxx","hardwareHash":{"bios-hash":"xxx","disk-info":"xxx","hostname-info":"xxx","ipaddress-info":"172.xx.xx.xx","macaddr-info":"02:xx:xx:xx:xx:02","machine-id":"xxxx","memory-hash":"xxx","processor-hash":"xxx","system-hash":"xxx"},"similarityThreshold":40}

/var/lib/amazon/ssm/Vault/Store/RegistrationKey

{"instanceID":"mi-xxxx","region":"ap-northeast-1","instanceType":"","availabilityZone":"","privateKey":"xxxx","privateKeyType":"Rsa","privateKeyCreatedDate":"2021-08-xx xx:xx:xx.xxxx +0900 JST"}

SSM Agent起動時には再度ハードウェアハッシュを作成し、保存されているハードウェアハッシュと同様かを検査し、その後Credentialを取得しています。

DEBUG [OnPremCreds] Calculated hardware hash is same as saved one, returning fingerprint DEBUG [ssm-agent-worker] [HealthCheck] UpdateInstanceInformation Response{} DEBUG [ssm-agent-worker] Health process has already been initialized. DEBUG [ssm-agent-worker] Getting credentials for v4 signatures.

IPアドレスやMACアドレスは変更が許容されますが、マシンIDなどが異なる場合は、下記のようにエラーとなりました。
(変更を許容する範囲は、SSM Agentの登録後にコマンドを使用して類似のしきい値を変更することで調整できます)

ERROR [OnPremCreds] Cannot connect to AWS Systems Manager. The hardware ID () has changed from the registered value (111). DEBUG [OnPremCreds] Calculated hardware hash is different with saved one, retry to ensure the difference is not cause by the dependency has not been ready

またフィンガープリントがSSMに登録している値と異なる場合は、休止モードに自動的に移行しました。

DEBUG [OnPremCreds] Calculated hardware hash is same as saved one, returning fingerprint INFO [ssm-agent-worker] Entering SSM Agent hibernate - error occurred in RequestManagedInstanceRoleToken: MachineFingerprintDoesNotMatch: Fingerprint does not match xxx-xxx-xxx-xxx-xxx

ドキュメントの通り、フィンガープリントやハードウェアハッシュを使用して、SSM AgentがIAMロールの認証情報を取得していることを確認できました。

終わりに

今回は、クライアント端末上でユーザーがAWS CLIをインタラクティブに利用するようなケースではなく、稼働中のシステム、かつオンプレミスのサーバ上でAWSアクセスキーを利用しない方法のひとつとして、SSM Agentを利用する方法をご紹介しました。
皆様のAWSアクセスキー管理の参考となれば幸いです。

奥友 雄太

テクノロジー コンサルティング本部 インテリジェントクラウドアンドインフラストラクチャーグループ マネジャー

ニュースレター
Subscribe to アクセンチュア・ クラウド・ ダイアリーズ Blog Subscribe to アクセンチュア・ クラウド・ ダイアリーズ Blog