7
4

More than 3 years have passed since last update.

ECS内(特にsshシェル)からのAWSへアクセスする時のcredential

Posted at

AWS_CONTAINER_CREDENTIALS_RELATIVE_URIとか知らないよって話

ドキュメントから

https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials
デフォルトでは以下の順でcredentialを探すようになっている。(これはSDKだが恐らくawscliも同じだろう)

  1. 環境変数
  2. .aws/credentials
  3. EC2のIAMロール(169.254.169.254
  4. ECSのタスクロール(169.254.170.2

3,4のIPアドレスはメタデータエンドポイントで、ECSの場合、ここからタスク定義においてtaskRoleArnに指定した値を取得するといった感じだろう。

ssh越しの場合

それではコンテナ内からは常にタスクロール相当のアクセス権を行使できるか? 例えばsshdをentrypointとして、ssh接続したシェルからawscliを使ってみる。

$ aws ssm describe-parameters
Unable to locate credentials. You can configure credentials by running "aws configure".

上手くいかない。--debugオプションを付けると

2019-12-12 12:32:30,906 - MainThread - urllib3.connectionpool - DEBUG - Starting new HTTP connection (1): 169.254.169.254:80
2019-12-12 12:32:30,907 - MainThread - botocore.utils - DEBUG - Caught retryable HTTP exception while making metadata service request to http://169.254.169.254/latest/api/token: Could not connect to the endpoint URL: "http://169.254.169.254/latest/api/token"
Traceback (most recent call last):
  File "/home/username/.local/lib/python3.5/site-packages/urllib3/connection.py", line 157, in _new_conn
    (self._dns_host, self.port), self.timeout, **extra_kw
  File "/home/username/.local/lib/python3.5/site-packages/urllib3/util/connection.py", line 84, in create_connection
    raise err
  File "/home/username/.local/lib/python3.5/site-packages/urllib3/util/connection.py", line 74, in create_connection
    sock.connect(sa)
OSError: [Errno 22] Invalid argument

こうしたエラーが見えるが169.254.170.2は見つからない。3の時点で諦めてしまっているのか?

SDKでも試してみる。普通にやると

NoCredentialProviders: no valid providers in chain. Deprecated. 
    For verbose messaging see aws.Config.CredentialsChainVerboseErrors

こうしたメッセージが出るのでConfigを追加する。

package main

import (
    "fmt"

    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/ssm"
)

func main() {
    sess := session.Must(session.NewSessionWithOptions(session.Options{
        Config: aws.Config{
            CredentialsChainVerboseErrors: aws.Bool(true),
        },
    }))
    client := ssm.New(sess)

    input := &ssm.DescribeParametersInput{
    }
    output, err := client.DescribeParameters(input)
    if err != nil {
        fmt.Printf("err: %s", err)
        return
    }

    fmt.Printf("%s", output)
}

以下のようにcredentialを順に試しているのが分かる。

err: NoCredentialProviders: no valid providers in chain
caused by: EnvAccessKeyNotFound: failed to find credentials in the environment.
SharedCredsLoad: failed to load profile, .
EC2RoleRequestError: no EC2 instance role found
caused by: RequestError: send request failed
caused by: Get http://169.254.169.254/latest/meta-data/iam/security-credentials/: dial tcp 169.254.169.254:80: connect: invalid argument

やはり169.254.169.254のエラーで止まっている。awscliもSDKもECSを知らない筈はないのだが、どういうことだろうか?

原因

https://forums.aws.amazon.com/thread.jspa?threadID=273767#898645
原因はこの$AWS_CONTAINER_CREDENTIALS_RELATIVE_URIにあった。

ECSでは169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URIにアクセスすることでロール情報を取得しており、この環境変数はinitプロセス(PID=1)にしか与えられない。sshログインした時のシェルはsshdが生成する子プロセスで、AWS_CONTAINER_CREDENTIALS_RELATIVE_URIがそのままだと設定されていない。

実はこの環境変数の引継ぎは参考にしたコードには書いてあったので、軽率に削除するのは愚かだったと言う他ない。ただログが参考にならなかった点は不満を言いたいが。

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4