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

`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を使ってみる。

```console
$ 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を追加する。

```go
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`がそのままだと設定されていない。

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