AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
とか知らないよって話
ドキュメントから
https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials
デフォルトでは以下の順でcredentialを探すようになっている。(これはSDKだが恐らくawscliも同じだろう)
- 環境変数
.aws/credentials
- EC2のIAMロール(
169.254.169.254
) - 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
がそのままだと設定されていない。
実はこの環境変数の引継ぎは参考にしたコードには書いてあったので、軽率に削除するのは愚かだったと言う他ない。ただログが参考にならなかった点は不満を言いたいが。