AWS CLI Setup

What is the AWS CLI?

The AWS CLI is a command-line client for the AWS API. Each command corresponds to one API operation:

aws s3 ls                          # ListBuckets
aws ec2 describe-instances         # DescribeInstances
aws sts get-caller-identity        # GetCallerIdentity

boto3 calls the same API and reads the same credential files. One configuration serves both.

Installation

Version 2 is current. Version 1 is still distributed and differs in output and options.

macOS

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 "/tmp/awscliv2.zip"
unzip -q /tmp/awscliv2.zip -d /tmp
sudo /tmp/aws/install
rm -rf /tmp/aws /tmp/awscliv2.zip

For ARM Linux, replace x86_64 with aarch64.

Windows

msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi

Verify:

aws --version
# aws-cli/2.36.49 Python/3.14.7 Darwin/27.0.0 source/arm64

Package managers (brew, apt, pip) also distribute the CLI. Some carry version 1 or lag releases.

Credentials

Requests are signed with an access key. Access keys belong to IAM users.

Root User and IAM Users

The root user is the email and password the account was created with. It has unrestricted access and cannot be limited by policy. CLI and SDK access uses an IAM user with attached policies. The root user is used once, to create that user.

Role-Management Policy

IAM users in this course create roles for EC2 and Lambda. No AWS managed policy grants role management without also granting user management, so a custom policy supplies it.

IAM → Policies → Create policy → JSON:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iam:CreateRole",
        "iam:DeleteRole",
        "iam:UpdateAssumeRolePolicy",
        "iam:TagRole",
        "iam:AttachRolePolicy",
        "iam:DetachRolePolicy",
        "iam:PutRolePolicy",
        "iam:DeleteRolePolicy",
        "iam:PassRole",
        "iam:CreatePolicy",
        "iam:DeletePolicy",
        "iam:CreatePolicyVersion",
        "iam:DeletePolicyVersion",
        "iam:CreateInstanceProfile",
        "iam:DeleteInstanceProfile",
        "iam:AddRoleToInstanceProfile",
        "iam:RemoveRoleFromInstanceProfile"
      ],
      "Resource": "*"
    }
  ]
}

Policy name: ee547-role-management

IAM User

IAM → Users → Create user

  1. User name: ee547-cli. Console access: off.
  2. Permissions options: Attach policies directly:
    • PowerUserAccess (AWS managed)
    • IAMReadOnlyAccess (AWS managed)
    • ee547-role-management (created above)
  3. Create user.

Combined effect: every service operation used in the course, read access to IAM, and role management. Not granted: creating or modifying users and access keys. Policies needed by a later assignment or a project are attached to the same user.

Access Key

User → Security credentials → Access keys → Create access key

  1. Use case: Command Line Interface (CLI)
  2. Description: the machine the key is for
  3. Create access key. The secret is shown once. Download the CSV. A lost secret requires a new key.

One key per machine. Keys no longer in use are deleted.

Configuration

aws configure
AWS Access Key ID [None]: AKIA................
AWS Secret Access Key [None]: ........................................
Default region name [None]: us-west-2
Default output format [None]: json

The course region is us-west-2.

Configuration Files

aws configure writes two files:

# ~/.aws/credentials
[default]
aws_access_key_id = AKIA................
aws_secret_access_key = ........................................
# ~/.aws/config
[default]
region = us-west-2
output = json

Keys are in credentials; region, output format, and other settings are in config. Both are plain text. Neither belongs in a repository.

Profiles

A second set of credentials, for another account or another key, is a named profile:

aws configure --profile project

This writes a [project] section to credentials and a [profile project] section to config. Selection is per command or per shell:

aws s3 ls --profile project
export AWS_PROFILE=project

Precedence

The CLI and boto3 resolve each setting from the first source that provides it:

  1. Command-line options (--region, --profile)
  2. Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION, AWS_PROFILE)
  3. ~/.aws/credentials and ~/.aws/config
  4. An IAM role attached to the EC2 instance or container running the code

Environment variables override the files. aws configure list shows the source of each value:

aws configure list
NAME       : VALUE                : TYPE                    : LOCATION
profile    : <not set>            : None                    : None
access_key : ****************ABCD : shared-credentials-file :
secret_key : ****************WXYZ : shared-credentials-file :
region     : us-west-2            : config-file             : ~/.aws/config

Identity Check

aws sts get-caller-identity
{
    "UserId": "AIDAEXAMPLEUSERID",
    "Account": "123456789012",
    "Arn": "arn:aws:iam::123456789012:user/ee547-cli"
}

Account is the account the credentials belong to. Arn is the identity: user/ee547-cli for the IAM user, root if a root access key is in use.

Unable to locate credentials. You can configure credentials by running "aws configure".

No source in the precedence list provided a key.

Command Structure

aws <service> <operation> [options]

Names follow the API. The EC2 operation DescribeInstances is aws ec2 describe-instances; its InstanceIds parameter is --instance-ids.

aws ec2 describe-instances --instance-ids i-0123456789abcdef0
aws s3api list-objects-v2 --bucket my-bucket --max-keys 10
aws lambda invoke --function-name my-function --payload '{}' out.json

Structured parameters accept JSON inline or from a file:

aws lambda invoke --function-name f --payload '{"key": "value"}' out.json
aws lambda invoke --function-name f --payload file://request.json out.json

Help

aws help                          # services
aws s3api help                    # operations in a service
aws s3api list-objects-v2 help    # parameters, output structure, examples

s3 and s3api

s3api maps one-to-one to the S3 API. s3 provides file-transfer commands with Unix names:

aws s3 ls s3://my-bucket/models/
aws s3 cp model.pkl s3://my-bucket/models/model.pkl
aws s3 sync ./output s3://my-bucket/output/

Output

Format

--output overrides the configured default:

aws ec2 describe-regions --output json     # scripts; shows the response structure
aws ec2 describe-regions --output table    # terminal
aws ec2 describe-regions --output text     # shell pipelines

Query

--query takes a JMESPath expression and returns the selected part of the response:

# One field from each instance
aws ec2 describe-instances \
    --query 'Reservations[].Instances[].InstanceId'

# Several fields, as rows
aws ec2 describe-instances \
    --query 'Reservations[].Instances[].[InstanceId,State.Name,PublicIpAddress]' \
    --output table

# Filter on a field value
aws ec2 describe-instances \
    --query 'Reservations[].Instances[?State.Name==`running`].InstanceId'

[] flattens a list, [?expr] filters, [a,b] selects fields into a row. Path names follow the JSON output of the same command without --query.

Region

--region overrides the configured default:

aws ec2 describe-instances --region us-east-1

Most resources are regional. An instance in us-west-2 does not appear in a us-east-1 listing.

Pager

Version 2 pages output longer than one screen through less, which blocks in scripts and pipelines. Disable per command, per shell, or in the config file:

aws ec2 describe-instances --no-cli-pager
export AWS_PAGER=""
aws configure set cli_pager ""

Quick Reference

# Setup
aws --version
aws configure                          # default profile
aws configure --profile NAME
aws configure list                     # source of each setting
aws sts get-caller-identity            # active identity

# Command shape
aws <service> <operation> --param value
aws <service> <operation> help

# Output control
--output json|table|text
--query '<JMESPath>'
--region REGION
--profile NAME
--no-cli-pager

# Files
~/.aws/credentials                     # keys
~/.aws/config                          # region, output, pager, profiles

# Environment overrides
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION, AWS_PROFILE, AWS_PAGER