AWS基礎 #4 AWS CLI と SDK のセットアップ

読了 8分

#2 IAM で作った IAM ユーザーのアクセスキー、そして #3 で ON にした請求アラームまで揃いました。これでコンソールの外で AWS と作業する番です。

コンソールは学習 / 1 回限りの作業には良いですが 繰り返し / 自動化 / 精密な作業 では限界が来ます。そこで次の 2 つが登場します。

  • AWS CLI — ターミナルから aws s3 cp ... のようなコマンドで AWS を操るツール
  • SDK — コードの中から AWS を呼ぶライブラリ (boto3 for Python、aws-sdk for JS、…)

この記事ではその 2 つのセットアップと、その裏で認証情報が流れる順序 (credential chain) を整理します。

AWS CLI v2 のインストール #

CLI は v1 と v2 があります。v2 が標準 — v1 はもう使わないでください。v2 の違い:

  • 単一の実行ファイル (Python 環境への依存なし)
  • IAM Identity Center (SSO) ネイティブサポート (#5)
  • 出力が高速 / より豊富な自動補完
  • aws configure import のような新コマンド

macOS #

インストール (Homebrew)
brew install awscli

または公式 pkg インストール:

インストール (公式 pkg)
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /

Linux #

インストール (x86_64)
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

Windows #

winget または MSI インストーラ:

winget
winget install -e --id Amazon.AWSCLI

インストール確認 #

バージョン確認
aws --version
# aws-cli/2.x.x Python/3.x.x ...

2.x.x が見えなければ which aws で v1 の残骸を確認して削除してください。

aws configure — 認証情報を登録 #

CLI が入ったら #2 の IAM ユーザーのアクセスキーを登録。

デフォルトプロファイル設定
aws configure
# AWS Access Key ID [None]: AKIA...
# AWS Secret Access Key [None]: wJal...
# Default region name [None]: ap-northeast-1
# Default output format [None]: json

この 4 つの値が 2 つのファイルに分かれて保存されます。

保存場所
~/.aws/credentials   # キー (機密)
~/.aws/config        # region / output / role など

~/.aws/credentials の形 #

~/.aws/credentials
[default]
aws_access_key_id = AKIA...
aws_secret_access_key = wJal...

~/.aws/config の形 #

~/.aws/config
[default]
region = ap-northeast-1
output = json

プロファイル — 複数の認証情報を同時に #

複数のアカウント / 環境 / ロールを扱う場合、default 1 つでは足りません。プロファイル で複数の認証情報を分けます。

プロファイルを追加 #

dev / prod の 2 プロファイル
aws configure --profile dev
aws configure --profile prod
結果 — ~/.aws/credentials
[default]
aws_access_key_id = AKIA...

[dev]
aws_access_key_id = AKIA-DEV-...
aws_secret_access_key = ...

[prod]
aws_access_key_id = AKIA-PROD-...
aws_secret_access_key = ...

プロファイルの使い方 #

3 つの方法。

1) --profile フラグ
aws s3 ls --profile prod
2) 環境変数
export AWS_PROFILE=prod
aws s3 ls
3) シェル関数 (.zshrc / .bashrc)
function awsenv() {
  export AWS_PROFILE=$1
  echo "AWS_PROFILE=$AWS_PROFILE"
}
# 使い方: awsenv prod

運用では環境変数 + シェルプロンプトに現在のプロファイルを表示するパターンがよくあります。

シェルプロンプトに現在のプロファイル表示 #

AWS_PROFILE をプロンプトに出すと事故が減ります。

zsh の例 (~/.zshrc)
PROMPT='%n@%m %1~ ${AWS_PROFILE:+[aws:$AWS_PROFILE]} %# '

本番用ターミナルの色を変えるパターンもよくあります — prod プロファイルのときは赤、dev のときは緑など。

Role を使う — assume-role の流れ #

#2 で扱ったロール (Role) を CLI から借りる方法です。マルチアカウントセットアップの定番パターンです。

~/.aws/config — role プロファイル
[profile prod]
role_arn = arn:aws:iam::222222222222:role/AdminRole
source_profile = default
mfa_serial = arn:aws:iam::111111111111:mfa/curtis
region = ap-northeast-1

このプロファイルを使うと:

  1. default プロファイルの認証情報で STS AssumeRole を呼び出す
  2. MFA コードを聞かれる (mfa_serial があれば)
  3. 一時認証情報を受け取ってコマンドに使う
  4. 1 時間キャッシュ → 再利用
使い方
aws s3 ls --profile prod
# Enter MFA code for arn:aws:iam::111111111111:mfa/curtis: 123456
# (この後 1 時間キャッシュ)

CI 環境では #5 の IAM Identity Center (SSO) の方がスムーズです。

環境変数 — CI とコンテナでの利用 #

~/.aws/credentials がない環境 (CI、コンテナ、一時シェル) では環境変数。

変数何か
AWS_ACCESS_KEY_IDアクセスキー
AWS_SECRET_ACCESS_KEYシークレットキー
AWS_SESSION_TOKEN一時認証時に併せて (STS / SSO)
AWS_REGION または AWS_DEFAULT_REGIONリージョン
AWS_PROFILEプロファイル名
環境変数で一時シェル
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=ap-northeast-1
aws s3 ls

認証情報チェーン — どこから認証情報を探すか #

CLI / SDK が認証情報を探す 順序 が決まっています。これを知らないと「なぜこのキーで動いているんだ?」のデバッグに時間を浪費します。

認証情報チェーン (上から下へ)
1. コマンドラインオプション (--profile、--region など)
2. 環境変数              (AWS_ACCESS_KEY_ID など)
3. アシスタントファイル  (CLI Web Identity Token、Container Credentials)
4. ~/.aws/credentials の default または指定プロファイル
5. ~/.aws/config のプロファイル (role_arn、sso_session など)
6. EC2 / ECS / Lambda のインスタンス / コンテナ認証情報

EC2 内で aws s3 ls が認証情報なしで動く理由 — 6 段階目のインスタンスメタデータが拾ってくれます (#2 のインスタンスプロファイル)。

どの認証情報が使われているか確認 #

現在の認証情報を確認
aws sts get-caller-identity
# {
#   "UserId": "AIDA...",
#   "Account": "111111111111",
#   "Arn": "arn:aws:iam::111111111111:user/curtis"
# }

この 1 行がデバッグの最初のステップです。どのユーザー / どのアカウントで動いているか が出ます。

よく使う CLI コマンド #

出力フォーマット #

--output オプション
aws ec2 describe-instances --output json   # デフォルト
aws ec2 describe-instances --output table  # 人間用
aws ec2 describe-instances --output text   # grep / awk 用
aws ec2 describe-instances --output yaml   # YAML

–query — JMESPath で絞り込み #

JSON 出力が長くて grep では限界が来ます。--query で必要な値だけを絞り込みます:

実行中のインスタンス ID とタイプだけ
aws ec2 describe-instances \
  --query 'Reservations[].Instances[?State.Name==`running`].[InstanceId,InstanceType]' \
  --output table

JMESPath の文法は最初は難しいですが、よく使うパターンを 5~10 個覚えれば日常作業が速くなります。

パターン意味
[]配列のフラット化
[?key==\value`]`フィルタ
[].fieldフィールド取り出し
[].[a,b,c]複数フィールドを新しい配列へ
length(@)長さ
sort_by(@, &date)ソート

よく使うコマンドたち #

アイデンティティ / 環境
aws sts get-caller-identity
aws configure list
aws configure list-profiles
S3
aws s3 ls                              # すべてのバケット
aws s3 ls s3://my-bucket/              # バケット内
aws s3 cp file.txt s3://my-bucket/     # アップロード
aws s3 sync ./local s3://my-bucket/    # フォルダ同期
aws s3 rm s3://my-bucket/file.txt      # 削除
aws s3 presign s3://my-bucket/file.pdf --expires-in 3600
EC2
aws ec2 describe-instances
aws ec2 start-instances --instance-ids i-...
aws ec2 stop-instances --instance-ids i-...
aws ec2 describe-regions --query 'Regions[].RegionName'
IAM
aws iam list-users
aws iam get-user --user-name curtis
aws iam list-attached-user-policies --user-name curtis
aws iam create-access-key --user-name curtis

SDK — コードの中の AWS #

CLI がターミナルで使うツールなら、SDK はコードの中で使うツールです。同じ認証情報チェーンを共有します。

Python — boto3 #

インストール
pip install boto3
基本的な使い方
import boto3

s3 = boto3.client("s3")
res = s3.list_buckets()
for b in res["Buckets"]:
    print(b["Name"])

認証情報は自動で認証情報チェーンから探します。~/.aws/credentials、環境変数、EC2 インスタンスプロファイルなどから探します。

明示的なプロファイル / リージョン #

明示指定
session = boto3.Session(profile_name="prod", region_name="ap-northeast-1")
s3 = session.client("s3")

リソース vs クライアント #

boto3 には 2 つのインターフェースがあります。

client — 低レベル、AWS API そのまま
s3 = boto3.client("s3")
res = s3.list_objects_v2(Bucket="my-bucket")
for obj in res.get("Contents", []):
    print(obj["Key"])
resource — オブジェクト指向、より短い (徐々に deprecated 傾向)
s3 = boto3.resource("s3")
for obj in s3.Bucket("my-bucket").objects.all():
    print(obj.key)

現代の boto3 は client 推奨です。 resource は一部のサービスしかサポートせず、新しいサービスには追加されません。

Pagination — よく出会う落とし穴 #

list_objects_v2 は 1 回で最大 1000 個。それ以上は paginator で。

paginator ですべてのオブジェクト
s3 = boto3.client("s3")
paginator = s3.get_paginator("list_objects_v2")
for page in paginator.paginate(Bucket="my-bucket"):
    for obj in page.get("Contents", []):
        print(obj["Key"])

JavaScript / TypeScript — aws-sdk v3 #

v2 は deprecated です。v3 に行きましょう。

インストール
npm install @aws-sdk/client-s3
基本的な使い方
import { S3Client, ListBucketsCommand } from "@aws-sdk/client-s3";

const client = new S3Client({ region: "ap-northeast-1" });
const res = await client.send(new ListBucketsCommand({}));
for (const b of res.Buckets ?? []) {
  console.log(b.Name);
}

v3 の特徴:

  • モジュラー — 必要なサービスだけ import (バンドルサイズ ↓)
  • ツリーシェイキング フレンドリー
  • すべての呼び出しが client.send(new XxxCommand(...)) パターン

Go — aws-sdk-go-v2 #

インストール
go get github.com/aws/aws-sdk-go-v2/aws
go get github.com/aws/aws-sdk-go-v2/config
go get github.com/aws/aws-sdk-go-v2/service/s3
基本的な使い方
package main

import (
    "context"
    "fmt"

    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/s3"
)

func main() {
    ctx := context.Background()
    cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("ap-northeast-1"))
    if err != nil {
        panic(err)
    }
    client := s3.NewFromConfig(cfg)
    res, err := client.ListBuckets(ctx, &s3.ListBucketsInput{})
    if err != nil {
        panic(err)
    }
    for _, b := range res.Buckets {
        fmt.Println(*b.Name)
    }
}

Go トラック のコンベンション — context 優先 + 明示的なエラー。

自動補完を有効化 #

タブ自動補完を有効にすれば CLI がぐっと滑らかになります。

zsh
autoload bashcompinit && bashcompinit
autoload -Uz compinit && compinit
complete -C "$(which aws_completer)" aws
bash
complete -C "$(which aws_completer)" aws

.zshrc / .bashrc に入れて新しいシェル。これで aws s3 <TAB> でコマンド / オプションが見えます。

よく出会う落とし穴 #

1) ~/.aws/credentials を git にコミット #

もっとも危険な事故です。.aws/必ず .gitignore かグローバル gitignore に入れます。そしてアクセスキーは可能なら環境変数 / SSO で扱い、ファイルに置かないのが標準になりつつあります。

2) 違うプロファイルから本番コマンド #

AWS_PROFILE=dev で作業していて aws s3 rb s3://...-prod — 待って、環境変数が dev なのになぜ prod のバケットが見える? 実は --profile prod が別途書かれていたのです。出所の明示性 + aws sts get-caller-identity の最初の点検 が答えです。

3) 認証情報チェーンのデバッグ #

「環境変数にキーを入れたのに古いキーで動いている」 — 認証情報チェーンの 1 段階目 (コマンドラインの --profile) が優先だからです。またはシェルが export を受け取っていない可能性もあります。aws sts get-caller-identity で最初に診断します。

4) v1 の残骸 #

aws --version が 1.x なら (特に macOS / Linux で pip install awscli の痕跡) v1 の残骸。v1 / v2 が同時に PATH に存在すると意図しない v1 実行 — which aws で確認して削除。

5) Pagination の漏れ #

list_* API はほぼすべてページネーションがあります。最初のページだけ処理して終えると本番データの 1000 番目以降が漏れます。paginator または NextToken ループを使います。

6) SDK の認証情報をコードに埋め込む #

ダメ
boto3.client("s3", aws_access_key_id="AKIA...", aws_secret_access_key="...")

認証情報は環境変数 / プロファイル / インスタンスプロファイルから取得します。コードに埋め込んだ瞬間 git に上がり、漏洩し、事故につながります。

まとめ #

今回つかんだもの:

  • AWS CLI v2 のインストール — Homebrew / curl / winget。v1 はもう使いません
  • aws configure で認証情報を登録 → ~/.aws/credentials + ~/.aws/config の 2 ファイルに保存
  • プロファイル で複数アカウント / 環境を分離。--profileAWS_PROFILE、シェル関数
  • Role プロファイル で AssumeRole の流れ。role_arn + source_profile + mfa_serial
  • 環境変数 — CI / コンテナ / 一時シェル。AWS_ACCESS_KEY_ID 以外に AWS_SESSION_TOKENAWS_REGION
  • 認証情報チェーン — コマンドライン → 環境 → ファイル → インスタンスプロファイル。aws sts get-caller-identity がデバッグの最初のステップ
  • CLI オプション--output table/json/text--query (JMESPath)
  • SDK — boto3 / aws-sdk v3 / aws-sdk-go-v2。認証情報チェーンを共有、client / resource、paginator
  • 落とし穴 — credentials の git コミット、プロファイル混乱、v1 残骸、pagination 漏れ、コードへのキー埋め込み

次回 — CloudShell と SSO #

ローカルセットアップが終わりました。ところで 他人のノート PC / 会社の一時的な環境でも同じ CLI が必要になるときがあります。さらにマルチアカウントが始まると ログインそのもの がより精緻にならないといけません。

#5 CloudShell と IAM Identity Center (SSO) ではコンソール内のブラウザターミナル (CloudShell) と、マルチアカウントの標準ログインになった IAM Identity Center (SSO) のセットアップを整理します。

X