この記事は Codex と一緒に書きました。
会社のPCで aws login が通らない!
AWS は少し触れる。CLI だって怖くない!
そんな希望に満ちた新入社員が、会社支給の PC を使った途端、なんと AWS CLI のコマンドがことごとくエラーになってしまった! 一体どうなっているんだ!?
ナイスな導入
会社のローカル PC のコマンドプロンプトで aws login コマンド1を叩いたところ、首尾よくブラウザが起動して認証は成功したはずなのに、最後の最後で以下のようなエラーになった(SSL validation failed とかcertificate verify failed と言われた)。
AWS 側の設定が悪いのか、自分の権限が足りないのか、CLI の使い方が間違っているのか、最初は切り分けがつきにくいと思います。
実際には、この種のトラブルの原因は AWS そのものではなく、社内ネットワーク上の HTTPS 中継機器にあることが少なくありません。
その代表例が Zscaler です。
急いでいる人向け(その場しのぎソリューション)
まずは一刻も早く問題を切り分けるため、さっそく以下のコマンドを試してみましょう。
aws login --profile sandbox --no-verify-ssl
もしこれでエラーが出なければ、ぜひこの先を読み進めてください。
それ以外の症状についてはこの記事では救わないので2、ここでブラウザバックしましょう。
なお、この --no-verify-ssl オプションはあくまでその場しのぎの弥縫策なので、常用は NG です。
注意: --no-verify-ssl は、AWS CLI の SSL 証明書検証を一時的に無効化するオプションです。
証明書設定が原因かどうかを切り分ける用途には使えますが、接続先の正当性を確認できなくなるため、常用してはいけません。
この記事でやること
この記事では、次のことを行います。
準備編:
-
aws loginが Zscaler 環境で失敗する理由を理解する
対策編:
-
certifiの標準 CA バンドルに Zscaler の CA 証明書を追加したバンドルを作成する - AWS CLI がそのバンドルを参照するように設定する
-
aws loginが成功することを確認する
なぜ aws login が失敗するのか
aws login は、AWS の認証用サーバーに HTTPS で接続してログインを行います。
このとき AWS CLI は、接続先が本当に AWS なのか、通信が安全に行われているのかを、接続先が提示したサーバー証明書を使って確認しています3。
通常であれば、AWS CLI は AWS が提示する証明書を受け取り、それが信頼できるものであれば処理を続行します。
このとき AWS CLI は、手元にある CA 証明書の一覧(CA バンドル)を使って、そのサーバー証明書が信頼できる認証局につながっているかを検証します。
しかし、社内ネットワークで Zscaler などのセキュリティ製品を利用している場合、HTTPS 通信はそのまま外部に出ていくのではなく、途中で社内のセキュリティ機器を経由することがあります。
HTTPS は、そのままでは通信内容を途中で確認できません。
そのため、この種のセキュリティ機器は、通信をいったん中継し、外部サイトとの通信とは別に、PC との間で新たに HTTPS 通信を張り直します。
その際、PC に対しては AWS 本来の証明書ではなく、社内で信頼させた別の証明書を提示します。
すると AWS CLI が検証する相手も、AWS が直接提示する証明書ではなく、社内のセキュリティ機器が提示する証明書になります。
この社内証明書が CA バンドルに含まれていなければ、接続先を安全だと判断できず、次のようなエラーになります。
SSL validation failed
certificate verify failed
この状態では、ブラウザで認証画面が開いたとしても、最後まで正常にログインを完了できません。
ここまでの内容を踏まえると、問題は「AWS CLI が接続時に受け取った証明書を検証したいのに、その検証に必要な社内 CA 証明書を知らないこと」にあります。
そのため今回の対処では、AWS CLI が HTTPS 通信の際に参照する CA 証明書の一覧(CA バンドル)に、Zscaler の CA 証明書も含めるようにします。
前提条件
以下を前提にします。
- Windows 環境で
cmd.exeまたは PowerShell が使える - AWS CLI v2 がインストール済みである
- Python がインストール済みである
- Python から
certifiが利用できる -
Zscaler の CA 証明書ファイルが適当なフォルダに配置されている
- 例:
D:\ZscalerRootCertificate.crt4
- 例:
- AWS にログインするための対象プロファイル名を決めている
- 例:
sandbox
- 例:
これらの条件を満たすかどうかを確認するため、次のコマンドを実行します。
aws --version
py --version
py -c "import certifi; print(certifi.where())"
確認ポイントは次の通りです。
-
aws --versionで AWS CLI の版が表示される -
py --versionで Python の版が表示される -
py -c ...でcertifiの CA バンドルのパスが表示される
手順 1: certifi の CA バンドルの場所を確認する
まず、Python の certifi が持っている標準 CA バンドルの場所を確認します。
py -c "import certifi; print(certifi.where())"
なぜこの手順が必要か
このあと行いたいのは、AWS CLI が社内ネットワーク経由でも証明書エラーを出さずに HTTPS 通信できるようにすることです。
そのためには、AWS CLI が通信先の証明書を確認するときに使う「信頼する証明書の一覧」を、社内環境に合わせて用意する必要があります。
ここで使うのが AWS_CA_BUNDLE です。
AWS_CA_BUNDLE は、AWS CLI が HTTPS 通信のときに参照する「信頼する証明書一覧ファイル」を指定するための設定です。
ここにファイルを指定すると、AWS CLI はそのファイルに入っている証明書を使って、接続先の証明書を検証します。
注意したいのは、AWS_CA_BUNDLE に指定したファイルの内容が、もともとの標準設定に自動で追加されるわけではないことです。
つまり、Zscaler の証明書だけを入れたファイルを指定すると、AWS CLI はそのファイルだけを参照することになり、通常であれば信頼している公開 CA の一覧が使われなくなることがあります。
その結果、社内の Zscaler 証明書は検証できても、今度は AWS 側が提示する証明書の検証に必要な公開 CA 情報が不足し、別の証明書エラーが起きる可能性があります。
そのため、まず既存の標準 CA バンドルの場所を確認し、それをベースにして Zscaler の証明書を追加した統合バンドルを作る必要があります。
実行後の確認方法
たとえば次のようなパスが表示されれば OK です。
C:\Users\<your-windows-user>\AppData\Local\Programs\Python\Python313\Lib\site-packages\certifi\cacert.pem
必要であれば、そのファイルが実在することも確認します。
dir C:\Users\<your-windows-user>\AppData\Local\Programs\Python\Python313\Lib\site-packages\certifi\cacert.pem
手順 2: certifi の CA バンドルと Zscaler 証明書を結合する
確認した cacert.pem と Zscaler 証明書を結合して、新しい CA バンドルを作成します。
コマンドは、以下の形式で記述しましょう。
$\texttt{copy}\ \texttt{/b}\ \fbox{手順1で確認したCAバンドルのフルパス}\texttt{+}\fbox{ZscalerのCA証明書ファイルのフルパス}\ \ \fbox{結合したCAバンドルの出力先フルパス}$
たとえば、
- CAバンドルのフルパスが
C:\Users\<your-windows-user>\AppData\Local\Programs\Python\Python313\Lib\site-packages\certifi\cacert.pem - ZscalerのCA証明書が
D:\ZscalerRootCertificate.crt、 - 出力先が
D:\aws-ca-bundle.pem
の場合、コマンドの例は以下のとおりとなります(適宜読み替えてください)。
例:
copy /b C:\Users\<your-windows-user>\AppData\Local\Programs\Python\Python313\Lib\site-packages\certifi\cacert.pem+D:\ZscalerRootCertificate.crt D:\aws-ca-bundle.pem
実行後の確認方法
作成されたファイルが存在することを確認します。
dir D:\aws-ca-bundle.pem
必要なら中身も確認できます。
type D:\aws-ca-bundle.pem
-----BEGIN CERTIFICATE----- が複数含まれていれば、バンドルとして妥当です。
手順 3: 作成した CA バンドルを一時的に使って aws login を実行する
まずは環境変数で一時的に CA バンドルを指定し、その状態でログインできるか確認します。
コマンドプロンプトの場合
set AWS_CA_BUNDLE=D:\aws-ca-bundle.pem
aws login --profile sandbox
PowerShellの場合
$env:AWS_CA_BUNDLE = "D:\aws-ca-bundle.pem"
aws login --profile sandbox
実行後の確認方法
成功すると、次のようなメッセージが表示されます。
Updated profile sandbox to use arn:aws:iam::xxxxxxxxxxxx:user/xxxxx credentials.
Use "--profile sandbox" to use the new credentials
これが出れば、sandbox プロファイルに一時クレデンシャルが設定されています。
手順 4: sts get-caller-identity で認証確認をする
aws login が成功したら、実際に AWS API を呼び出せるかを確認します。
aws sts get-caller-identity --profile sandbox
実行後の確認方法
次のような JSON が返れば成功です。
{
"UserId": "...",
"Account": "...",
"Arn": "..."
}
少なくとも Account と Arn が返ってくれば、AWS CLI からそのプロファイルで認証できています。
手順 5: 問題なければ CA バンドル設定をプロファイルに恒久化する
一時設定で問題がなければ、毎回 set AWS_CA_BUNDLE=... を実行しなくてよいように、プロファイルへ保存します。
aws configure set ca_bundle D:\aws-ca-bundle.pem --profile sandbox
実行後の確認方法
aws configure get ca_bundle --profile sandbox
次のように表示されれば OK です。
D:\aws-ca-bundle.pem
手順 6: 以後の AWS CLI 利用は --profile sandbox を付けて実行する
ログイン後は、対象のプロファイルを指定して AWS CLI を使います。
aws s3 ls --profile sandbox
aws ec2 describe-regions --profile sandbox
実行後の確認方法
各コマンドが正常に結果を返せば OK です。
もし AccessDenied が返る場合は権限不足の可能性がありますが、その場合でも認証そのものは通っています。
まとめ
今回のポイントは次の3つです。
- Zscaler 環境では AWS CLI の証明書検証が失敗することがある
-
certifiの標準 CA と Zscaler の CA を結合したバンドルを使うと解決できる - ログイン後は
--profile sandboxを付けて操作する
それでは新入社員のみなさん、楽しいエンジニアライフを。
-
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-sign-in.html ↩
-
なお、会社のネットワーク構成によっては、証明書設定とは別に
HTTP_PROXY/HTTPS_PROXYの設定が必要な場合があります(この場合はネットワークタイムアウトなどのエラーが出ます)。なおプロキシ設定は本記事の対象外です。 ↩ -
ここで使用する証明書は ZscalerRootCertificate.crt とは限りません。組織によっては独自のルート CA 証明書を配布しているため、自社で案内されている TLS/SSL Inspection 用の CA 証明書を使用してください。 ↩



