> For the complete documentation index, see [llms.txt](https://docs.strongdm.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.strongdm.com/users/connect/aws-cli-and-sdk-tools.md).

# AWS CLI and SDK Tools

This guide for developers who access AWS accounts through StrongDM cloud datasources (AWS instance-profile/assumed-role resources).

## Overview

StrongDM is credential-less by design. When you access an AWS datasource:

* StrongDM's proxy performs the `AssumeRole` and holds the real temporary credentials.
* Your local traffic is routed to a StrongDM proxy listener, which re-signs each request with the real credentials before forwarding it to AWS.
* Your client never receives the real temporary credentials. This is intentional and cannot be changed. There is no way to have StrongDM hand back usable `aws_access_key_id` or `aws_secret_access_key` or session token values.

{% hint style="info" %}
**Key mental model:** `sdm connect` creates the per-datasource proxy listener, whereas `HTTPS_PROXY` selects which listener (account) your traffic goes to. The credentials and any AWS profile are passive. They never route and never determine your identity.
{% endhint %}

The command that wires this up is `sdm aws env`, which prints the environment variables your tools need. It does not execute anything or change your environment on its own (that is, you load its output into your shell).

## Prerequisites

Before you begin, ensure you have the following:

* StrongDM Desktop application installed and running
* StrongDM CLI installed
* Network access to Global Protect (Prisma Access) or your organization's VPN
* Target AWS resource connected in StrongDM via the CLI or StrongDM Desktop

## Steps

### Step 1: Connect to StrongDM

In the terminal, run:

{% code overflow="wrap" %}

```bash
sdm connect <resource>
```

{% endcode %}

Use the exact name of your AWS resource as it appears in StrongDM. You can keep multiple resources connected simultaneously if needed.

### Step 2: Inject AWS Environment Variables

Use the following command to inject the StrongDM-provided environment variables into your current shell session.

{% code overflow="wrap" %}

```bash
set -aeval "$(sdm aws env)"set +a
```

{% endcode %}

The `set -a` / `set +a` wrapper is required so the variables export to child processes (your scripts, IDEs, and tools).

Without `set -a` / `set +a`, `eval` sets the variables only in your interactive shell and they will not reach the programs you launch, and your tools will then fail with `Unable to locate credentials`.

#### What `sdm aws env` provides

When you run `sdm aws env`, it prints output such as the following:

```bash
AWS_SESSION_TOKEN=
HTTPS_PROXY=http://127.0.0.1:<port>
AWS_CA_BUNDLE=/Users/you/.sdm/org.crt
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
```

| Variable                                      | Role                                                                                                                                                                                                                                          |
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `HTTPS_PROXY`                                 | Routes AWS traffic to StrongDM and selects which datasource/account you hit; this is the essential one                                                                                                                                        |
| `AWS_CA_BUNDLE`                               | Tells the AWS CLI to trust the StrongDM proxy's TLS certificate                                                                                                                                                                               |
| `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` | Placeholders (AWS's own documentation example keys) that exist only so the AWS CLI/SDK won't refuse to run with "no credentials"; their values are irrelevant, as StrongDM re-signs with the real role; seeing this is expected, not an error |
| `AWS_SESSION_TOKEN=`                          | Empty, to clear any stale token inherited from the parent shell                                                                                                                                                                               |

### Step 3: Set the Proxy

The proxy value is already included in the output from step 2, but ensure it's explicitly available:

{% code overflow="wrap" %}

```bash
export HTTPS_PROXY=http://127.0.0.1:<port>
```

{% endcode %}

Obtain the exact `HTTPS_PROXY` value from:

* The output of `sdm aws env` (already loaded in step 2)
* `sdm status` output for the resource
* StrongDM Desktop application resource details

This routes all AWS traffic through the StrongDM local proxy.

{% hint style="info" %}
Setting `HTTPS_PROXY` globally can interfere with StrongDM CLI commands (such as `sdm status`, `sdm connect`, and so forth). See [Troubleshooting](#troubleshooting) for solutions.
{% endhint %}

### Step 4: Export CA Bundle If Required

{% code overflow="wrap" %}

```sh
export AWS_CA_BUNDLE="$HOME/.sdm/org.crt"
```

{% endcode %}

Only run this step if you encounter certificate validation errors. If step 2 worked without errors, you can skip this.

### Step 5: Launch VS Code

Launch VS Code from the **same terminal** where you ran the above steps. This ensures that VS Code and its integrated terminal inherit the environment variables and proxy settings.

{% code overflow="wrap" %}

```bash
code --user-data-dir "$HOME/.sdm-vscode"
```

{% endcode %}

Why `--user-data-dir`? This runs VS Code as a separate instance with its own settings profile, so it coexists with a normal VS Code window (VS Code is otherwise single-instance and a second launch would open a window in an existing, un-wired process). VS Code extensions are still shared across instances.

If `code` is not in your PATH (common on macOS):

{% code overflow="wrap" %}

```bash
/Applications/Visual\ Studio\ Code.app/Contents/Resources/app/bin/code --user-data-dir "$HOME/.sdm-vscode"
```

{% endcode %}

Find the exact path with `find /Applications -name "Visual Studio Code.app"` and quote it properly.

In VS Code:

* **Integrated terminal:** Run `aws ...`, scripts, and Terraform with no prefix.
* **AWS Toolkit:** Select your profile in the connection picker; it authenticates and browses resources through StrongDM.
* The echo should show non-empty values for both `HTTPS_PROXY` and `AWS_CA_BUNDLE`.
* `aws sts get-caller-identity` should return the AWS identity/role you expect from StrongDM.

Both commands should succeed:

{% code overflow="wrap" %}

```bash
echo "proxy=$HTTPS_PROXY  ca=$AWS_CA_BUNDLE"   # both must be non-emptyaws sts get-caller-identity
```

{% endcode %}

In the terminal (or VS Code's integrated terminal), confirm the setup is working:

### Step 6: Verify

In the terminal (or VS Code's integrated terminal), confirm that the setup is working:

{% code overflow="wrap" %}

```bash
echo "proxy=$HTTPS_PROXY  ca=$AWS_CA_BUNDLE"   # both must be non-emptyaws sts get-caller-identity
```

{% endcode %}

Both commands should succeed:

* The echo should show non-empty values for both `HTTPS_PROXY` and `AWS_CA_BUNDLE`.
* `aws sts get-caller-identity` should return the AWS identity/role you expect from StrongDM.

### Step 7: Switch to Another AWS Resource

If you need to work with a different AWS account or datasource, follow these steps:

1\. Connect to the new resource:

{% code overflow="wrap" %}

```bash
sdm connect "<new-resource>"
```

{% endcode %}

2\. Refresh the environment variables:

{% code overflow="wrap" %}

```bash
set -aeval "$(sdm aws env)"set +a
```

{% endcode %}

3\. Update the HTTPS\_PROXY value for the newly connected resource (repeat step 3).

4\. Continue working, or relaunch VS Code from the updated terminal if needed.

You can keep multiple resources connected and switch as required, but always ensure that the proxy and environment variables match the active resource you're targeting.

## Troubleshooting

| Symptom                                                                                 | Cause                                                                                                         | Fix                                                                                                                                                     |
| --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SSL validation failed … CERTIFICATE_VERIFY_FAILED (self-signed certificate…)`          | Traffic is reaching the StrongDM proxy but the CLI doesn't trust its cert — `AWS_CA_BUNDLE` not set/exported. | Run `export AWS_CA_BUNDLE="$HOME/.sdm/org.crt"`. For the AWS Toolkit, also `export NODE_EXTRA_CA_CERTS="$AWS_CA_BUNDLE"`.                               |
| `Unable to locate credentials` / `NoCredentials`                                        | `eval` was run without `set -a`, so vars didn't export to child processes.                                    | Use `set -a; eval "$(sdm aws env)"; set +a`. Verify with `env \| grep HTTPS_PROXY`.                                                                     |
| `SSL validation failed … unable to get local issuer certificate` on a real AWS endpoint | Request went **direct** to AWS — `HTTPS_PROXY` not set, so StrongDM was never used.                           | Set `HTTPS_PROXY` (via Step 3 or `sdm aws env`).                                                                                                        |
| `sdm connect` → `error loading datasources`; other `sdm` commands fail                  | `HTTPS_PROXY` is set shell-wide, so `sdm`'s own control-plane calls are misrouted through the AWS proxy.      | Set `NO_PROXY` (see below) or use per-command `HTTPS_PROXY`.                                                                                            |
| VS Code cannot authenticate or run AWS commands                                         | VS Code was not launched from the wired terminal, so it didn't inherit the environment variables.             | Launch VS Code from the same terminal where you ran Steps 1–4. Verify the terminal itself can run `aws sts get-caller-identity` before opening VS Code. |

### Keep StrongDM CLI commands working

If you export `HTTPS_PROXY` shell-wide, the `sdm` CLI's own control-plane calls will also try to use that proxy and fail. Consider the following two solutions:

* Preferred: Don't set `HTTPS_PROXY` shell-wide. Instead, use the per-command form (below), so your interactive shell never has it set.
* Alternatively, carve StrongDM's hosts and loopback out of the proxy:

{% code overflow="wrap" %}

```bash
export NO_PROXY="strongdm.com,.strongdm.com,sdm.network,.sdm.network,localhost,127.0.0.1"
```

{% endcode %}

Add your organization's custom SDM domain if it isn't under `strongdm.com`.

### Advanced: Terminal-only workflow (no VS Code)

If you prefer the command line and don't use VS Code, the setup is simpler:

{% code overflow="wrap" %}

```bash
# 1. Connect the datasourcesdm
connect my-aws-account

# 2. Load the StrongDM environment into your shell
set -aeval "$(sdm aws env)"set +a

# 3. Use AWS normally with no sdm prefix
aws sts get-caller-identityaws s3 ls./deploy.shterraform apply
```

{% endcode %}

This works for the AWS CLI, boto3/SDKs, Terraform, and any script.

### Advanced: Per-command proxy (multiple accounts, no shell-wide state)

Set the proxy inline for a single command. You can hit any connected account per command without changing your shell's proxy:

{% code overflow="wrap" %}

```bash
HTTPS_PROXY=http://127.0.0.1:<portA> AWS_CA_BUNDLE=~/.sdm/org.crt \  AWS_ACCESS_KEY_ID=x AWS_SECRET_ACCESS_KEY=x aws s3 ls        # account A
HTTPS_PROXY=http://127.0.0.1:<portB> AWS_CA_BUNDLE=~/.sdm/org.crt \  AWS_ACCESS_KEY_ID=x AWS_SECRET_ACCESS_KEY=x aws s3 ls        # account B
```

{% endcode %}

Helper function for your `~/.zshrc`:

{% code overflow="wrap" %}

```bash
awsq() {  local r="$1"; shift  sdm connect "$r" >/dev/null  local addr=$(sdm status | awk -v n="$r" '$1==n{print $3}')  HTTPS_PROXY="http://$addr" AWS_CA_BUNDLE="$HOME/.sdm/org.crt" \    AWS_ACCESS_KEY_ID=x AWS_SECRET_ACCESS_KEY=x "$@"}# Usage: awsq prod-acct-01 aws s3 ls# Or loop: for a in acct-01 acct-02 acct-03; do awsq "$a" aws sts get-caller-identity; done
```

{% endcode %}

{% hint style="info" %}
Set a fixed port override on each datasource in StrongDM so every account has a stable, predictable listener `host:port`.
{% endhint %}

### Advanced: AWS named profiles

AWS named profiles are optional and only play a supporting role:

* Can hold `ca_bundle`, `region`, and the placeholder credentials.
* Cannot hold the proxy. There is no proxy field in `~/.aws/config`. `HTTPS_PROXY` always must be set in the environment (or as VS Code's `http.proxy` setting).
* Does not select the account or determine your identity. That's the proxy and the StrongDM datasource, respectively.

If you prefer a named profile to carry the static pieces:

`~/.aws/config`

{% code overflow="wrap" %}

```
[profile aws_account_sdm]
ca_bundle = /Users/you/.sdm/org.crt
region    = us-west-2
```

{% endcode %}

`~/.aws/credentials`

{% code overflow="wrap" %}

```
[aws_account_sdm]
aws_access_key_id     = AKIAIOSF••••••••••••
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
```

{% endcode %}

Then:

{% code overflow="wrap" %}

```bash
export HTTPS_PROXY=http://127.0.0.1:<port>   # still required
aws s3 ls --profile aws_account_sdm
```

{% endcode %}

## Limitations

* **No real temporary credentials are exposed.** By design; there is no workaround.
* **`HTTPS_PROXY` is the only routing mechanism.** It can't live in an AWS profile, and only the standard variable name works (an `SDM_`-prefixed name does nothing).
* **One account per shell / window.** Switching accounts means changing the proxy value.
* **Session-wide `HTTPS_PROXY` affects non-AWS traffic too.** Any HTTPS call in that shell/window (including `sdm` commands and things like a plugin fetching from GitHub) routes through the proxy. Use `NO_PROXY` or per-command scoping to contain it.
* **GUI profile switching is not account switching.** Selecting a different profile in the AWS Toolkit does **not** switch which StrongDM account you reach. The account is determined by the proxy, which is a single value per window. To switch accounts in the GUI, repoint the proxy (edit the `http.proxy` VS Code setting and reload, or relaunch wired to the other datasource). For genuine multi-account work, use the terminal.

## Quick Reference

```bash
# One datasource, whole shell:
sdm connect <resource>
set -a; eval "$(sdm aws env)"; set +a
aws sts get-caller-identity

# Keep sdm commands working in the same shell:
export NO_PROXY="strongdm.com,.strongdm.com,sdm.network,.sdm.network,localhost,127.0.0.1"

# One command against a specific datasource (no shell-wide state):
HTTPS_PROXY=http://127.0.0.1:<port> AWS_CA_BUNDLE=~/.sdm/org.crt \
  AWS_ACCESS_KEY_ID=x AWS_SECRET_ACCESS_KEY=x aws s3 ls

# VS Code, wired:
sdm connect <resource>
set -a; eval "$(sdm aws env)"; set +a
export NODE_EXTRA_CA_CERTS="$AWS_CA_BUNDLE"
code --user-data-dir "$HOME/.sdm-vscode"
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.strongdm.com/users/connect/aws-cli-and-sdk-tools.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
