lambda-uploader利用時にAssumeRole operationでAccess deniedとなった状態を解消までもっていった記録

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Lambdaに直書きしていた関数をバージョン管理すべくと移植作業をしていましたが、 Lambdaに上げる際にAssumeRole周りでハマってしまいました。

単純にポリシーの追加で賄えればよかったのですが、実験ということもあって最初からAdministratorAccessでした。何が問題なのか延々と検証した結果、辛うじて解決に至ったので記録として残してみます。

事のはじめ

最初遭遇したのは以下の1文でした。

botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the AssumeRole operation: Access denied

AdministratorAccessの状態でどうしたらこうなるのかと悩ましい状態です。

とりあえず、ポリシーの設定が問題になることはない、とだけ認識しました。

Lambda-Uploaderのログ調査

-VVをつけて確認してみました。

% lambda-uploader ....  -VV
....
DEBUG:botocore.hooks:Event request-created.sts.AssumeRole: calling handler <bound method RequestSigner.handler of <botocore.signers.RequestSigner object at 0x1063787f0>&gt;
DEBUG:botocore.hooks:Event choose-signer.sts.AssumeRole: calling handler <function set_operation_specific_signer at 0x104b4cbf8>
DEBUG:botocore.auth:Calculating signature using v4 auth.
DEBUG:botocore.auth:CanonicalRequest:
POST
/
content-type:application/x-www-form-urlencoded; charset=utf-8
host:sts.amazonaws.com
x-amz-date:20190219T095800Z</p>
content-type;host;x-amz-date
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
DEBUG:botocore.auth:StringToSign:
AWS4-HMAC-SHA256
20190219T095800Z
20190219/us-east-1/sts/aws4_request
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
DEBUG:botocore.auth:Signature:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
DEBUG:botocore.endpoint:Sending http request: <AWSPreparedRequest stream_output=False, method=POST, url=https://sts.amazonaws.com/, headers={'Content-Type': b'application/x-www-form-urlencoded; charset=utf-8', 'User-Agent': b'Boto3/1.9.97 Python/3.6.6 Darwin/18.2.0 Botocore/1.12.97', 'X-Amz-Date': b'20190219T095800Z', 'Authorization': b'AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXXXXXXXXXXX/20190219/us-east-1/sts/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', 'Content-Length': '147'}>
DEBUG:urllib3.util.retry:Converted retries value: False -&gt; Retry(total=False, connect=None, read=None, redirect=0, status=None)
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): sts.amazonaws.com:443
DEBUG:urllib3.connectionpool:https://sts.amazonaws.com:443 "POST / HTTP/1.1" 403 257
DEBUG:botocore.parsers:Response headers: {'x-amzn-RequestId': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', 'Content-Type': 'text/xml', 'Content-Length': '257', 'Date': 'Tue, 19 Feb 2019 09:58:00 GMT'}
DEBUG:botocore.parsers:Response body:
b'<ErrorResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">\n  <Error>\n    <Type>Sender</Type>\n    <Code>AccessDenied</Code>\n    <Message>Access denied</Message>\n  </Error>\n  <RequestId>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</RequestId>\n</ErrorResponse>\n'
DEBUG:botocore.hooks:Event needs-retry.sts.AssumeRole: calling handler <botocore.retryhandler.RetryHandler object at 0x106378f60>

ぱっとみた限り、余り直接的な原因がわかる感じでもありません。強いて言えば、

DEBUG:urllib3.connectionpool:https://sts.amazonaws.com:443 "POST / HTTP/1.1" 403 257

ここが気になります。Google検索するとstackoverflowで該当しそうな結果も出てきたのですが、AdministratorAccessが前提なので論証としては弱めです。

Roleの利用過程の検証

次に、Lambda-uploaderがそもそも何故AssumeRoleを求めているのかという点で調査してみました。SwitchRoleも絡むのかと思いましたが、実行時のProfileはスイッチ後のアカウントRoleとKeyを指定しているため必要がないと思われます。

ただ、検索のキーワードが思い浮かびませんでした。スイッチしないけどスイッチする前提とか何を言ってるのかわからない状態です。止む無くDevIOで「AssumeRole」絡みで何か出てこないかと調べていると以下の記事が出てきました。

MFA関連のオプション--serial-numberと--token-codeを適切に設定する

「これかもしれない」と思いましたがLambda-uploader相手にどうすればいいんだろう、と。そこで次に「MFA」絡みで何か出てこないかと調べてみました。

ここで試しにaws/configにmfa_serialを指定してみました。

% vim ~/.aws/config
[profile ...]
..
mfa_serial = arn:aws:iam::XXXXXXXXXXXX:mfa/XXXXXXXXXXXXXXX
% lambda-uploader --profile=XXXXX
λ Building Package
INFO:lambda_uploader.package:Building new virtualenv and installing requirements
INFO:lambda_uploader.package:Copying site packages
INFO:lambda_uploader.utils:Copying source files
INFO:lambda_uploader.utils:Copying source files
INFO:lambda_uploader.package:Creating zipfile
λ Uploading Package
Enter MFA code for arn:aws:iam::XXXXXXXXXXXX:mfa/XXXXXXXXXXXXXXX:
λ Fin

Enter MFA...で入力待ちになるため、ワンタイムパスワードを入力します。そして無事完了となりました。

まとめ

MFAでの認証設定が必要ではあるものの、ログには一切でてこないところがポイントでした。尚、lambda-uploaderだけでなく、Pyathenaなどのboto3でSTSを使っているパッケージでも恐らく同じ状態に陥る可能性があります。

今回はいくら検索してもStackoverflowですら求めていた答えが引っかからなかったため、中々難儀しました。MFAはセキュリティ対策を行う上で必須ですが、今回のようにそこへの対応も必要だと気が付かないケースも多々あります。行き詰まった時の解消のキッカケになれれば幸いです。