The AWS CLI & APIs
The AWS CLI & APIs
Every action you take in the AWS Console — launching an EC2 instance, creating an S3 bucket, attaching an IAM policy — is nothing more than an authenticated HTTPS call to an AWS API endpoint. The AWS CLI is a thin wrapper around those same APIs. Understanding this equivalence is the mental shift that turns you from a console operator into an automation engineer who can script, test, reproduce, and version-control every infrastructure change.
At big-tech scale, the CLI is not a convenience shortcut — it is the foundation of every deployment pipeline, runbook, and incident-response script. This lesson covers everything you need to use it professionally: how credentials are resolved, how to configure named profiles for multiple accounts and roles, the key CLI patterns every SRE uses daily, and how to compose powerful jq pipelines to extract exactly the signal you need from JSON API responses.
How the CLI Resolves Credentials — The Credential Chain
The single most important concept to understand about the AWS CLI is its credential provider chain. When you run any aws command, the SDK works through a fixed priority list and uses the first credential source it finds:
- CLI flags:
--profile,--region, environment-variable overrides passed inline. - Environment variables:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_SESSION_TOKEN,AWS_PROFILE. These override every file-based source — useful in CI but dangerous if you forget them set in a terminal session. ~/.aws/credentialsand~/.aws/config: Named profiles. The[default]profile is used when no profile is specified.- AWS SSO / Identity Center: Short-lived token obtained via
aws sso login. - ECS task role / EC2 instance profile: On AWS-managed compute, credentials are injected automatically via the Instance Metadata Service or the ECS credential provider endpoint. This is how production workloads should authenticate — never bake long-lived keys into EC2 or containers.
- AWS config file role assumption: A profile with
role_arn+source_profilecauses the CLI to callsts:AssumeRoleautomatically and cache the resulting session credentials.
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY in a Docker image, a CI log, or a shipped binary is one of the most common root causes of cloud account takeovers. In production, always use instance profiles, task roles, or short-lived SSO sessions. Rotate any long-lived key that exists — treat them like passwords.Configuring Named Profiles
Professional AWS users manage multiple accounts — development, staging, production, plus separate accounts per service team in large organisations. Named profiles in ~/.aws/config let you switch contexts cleanly without re-exporting environment variables.
Once profiles are defined, specify them per-command with --profile or set AWS_PROFILE for the lifetime of a shell session:
aws sts get-caller-identity before any destructive operation — terminate-instances, delete-stack, delete-bucket. It takes 200ms and confirms you are authenticated as the role you intended, in the account you intended. Teams that skip this step accidentally delete production resources from a wrong profile.Common CLI Patterns Every SRE Uses
The --query flag (JMESPath expression) and --output flag (json, text, table, yaml) are your primary tools for shaping API responses without external tools. Combine them with --filters to push filtering server-side and avoid transferring large response payloads.
jq Pipelines for Production Queries
jq is a command-line JSON processor that every SRE should be fluent in. While the CLI's built-in --query (JMESPath) handles simple projections, jq gives you Turing-complete transformations: conditionals, arithmetic, grouping, custom keys, and cross-resource joins. Pipe any aws ... --output json call into jq and you have a full query engine over your infrastructure state.
--dry-run before destructive operations. Many EC2 and IAM write API calls accept a --dry-run flag. It sends the full authenticated request to AWS, performs all IAM authorization checks, but does not execute the mutation. You get an DryRunOperation error (which means "you have permission and this would have worked") or a real auth error (which means "fix your IAM before running for real"). Make dry-run part of your runbook standard for any operation touching production.AWS APIs Beyond the CLI — SDKs and Direct HTTP
The CLI is built on the boto3 Python SDK (or the Go SDK for newer CLI v2 internals). Every SDK call maps 1:1 to a CLI command: aws ec2 describe-instances is exactly boto3.client('ec2').describe_instances(). Understanding this lets you prototype in the CLI and then promote to SDK code in your Lambda functions, Terraform providers, and internal tooling without re-learning the API shape.
Every AWS API request is authenticated using Signature Version 4 (SigV4) — an HMAC-SHA256 signing algorithm that covers the request method, URI, headers, and body, preventing tampering in transit. You will never implement SigV4 manually (every SDK does it), but knowing it exists explains why rotating a compromised key immediately invalidates all in-flight requests signed with the old key.
NextToken for subsequent pages. The CLI --no-paginate flag fetches all pages automatically (at the cost of memory), while the AWS SDK has dedicated paginator objects. A script that only reads the first page of describe-instances or list-buckets silently misses resources in large accounts — a subtle bug that has caused genuine production incidents when compliance scripts miss untagged or misconfigured resources.Key Takeaways
- The credential provider chain resolves credentials in strict priority order: flags, environment variables, config files, SSO, instance profile. In production, always use instance profiles or task roles — never long-lived keys.
- Named profiles in
~/.aws/configwithrole_arn+source_profileenable automatic role assumption — essential for multi-account environments. - Run
aws sts get-caller-identitybefore any destructive operation to confirm the active identity and account. - Use
--filtersfor server-side filtering (reduces API response size) and--query(JMESPath) for client-side projection. jqunlocks cross-resource queries, conditional logic, grouping, and audit pipelines that JMESPath cannot express.- All CLI calls are authenticated HTTP requests signed with SigV4. The CLI is thin sugar over the same public APIs used by the Console, SDKs, and Terraform.
- Always paginate in scripts — missing the second page of results is a real, silent failure mode in large-scale accounts.