> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensor9.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart: AWS to Azure

> Send AWS S3 requests through Cloud Adapter to Azure Blob Storage.

This quickstart keeps the AWS S3 API at the application boundary while Cloud Adapter stores object data in Azure Blob Storage.

<Frame>
  <img className="block dark:hidden" src="https://mintcdn.com/tensor9/3qwgIru3kCfHriJC/images/diagrams/cloud-adapter-quickstart-aws-to-azure-dark.svg?fit=max&auto=format&n=3qwgIru3kCfHriJC&q=85&s=18573a1bcac04ceb9b2eff7233212958" alt="AWS API requests pass through Tensor9 Cloud Adapter to Azure services." width="1100" height="360" data-path="images/diagrams/cloud-adapter-quickstart-aws-to-azure-dark.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/tensor9/3qwgIru3kCfHriJC/images/diagrams/cloud-adapter-quickstart-aws-to-azure-light.svg?fit=max&auto=format&n=3qwgIru3kCfHriJC&q=85&s=9946dba903f83fe2bc7833a6ddd66c4e" alt="AWS API requests pass through Tensor9 Cloud Adapter to Azure services." width="1100" height="360" data-path="images/diagrams/cloud-adapter-quickstart-aws-to-azure-light.svg" />
</Frame>

## Outcome

You will upload one S3 object through Cloud Adapter, read it back through S3, verify the corresponding Azure blob, test a missing-object response, and delete the object.

Review [S3 on Azure](/cloud-adapter/service-catalog/aws/databases-storage/s3#on-azure) first. Common object CRUD is supported. Azure's flat listing does not reproduce every S3 delimiter and `CommonPrefixes` behavior. Copy downloads and re-uploads the object, multi-delete becomes multiple backend calls, and one `PutObject` is limited to 5,000 MiB in this profile. Bucket policy, ACL, retention, and legal-hold behavior remain outside the object endpoint.

## Prerequisites

* an installed AWS-origin Cloud Adapter endpoint;
* an S3 to Blob Storage service adapter;
* an origin-side AWS test identity;
* an Azure runtime identity for the adapter and a separate read-only verification identity;
* an existing test storage account and container;
* AWS CLI v2 and Azure CLI.

## Set test values

```bash theme={null}
export T9_CLOUD_ADAPTER_ENDPOINT="https://adapter.example.test"
export AWS_PROFILE="adapter-test"
export AWS_REGION="us-east-1"
export AWS_REQUEST_CHECKSUM_CALCULATION="WHEN_REQUIRED"
export ORIGIN_BUCKET="adapter-smoke-test"
export AZURE_STORAGE_ACCOUNT="adaptedsmoke"
export AZURE_CONTAINER="adapter-smoke-test"
export TEST_KEY="quickstart/aws-azure-$(date +%s).txt"
printf 'hello from S3 to Blob Storage\n' > /tmp/cloud-adapter-smoke.txt
```

`AWS_REQUEST_CHECKSUM_CALCULATION=WHEN_REQUIRED` keeps this smoke test on the required S3 checksum path. Validate optional flexible-checksum behavior separately if your application enables it.

The commands below use an explicit `--endpoint-url`. To route every S3 client in the process instead, set `AWS_ENDPOINT_URL_S3="$T9_CLOUD_ADAPTER_ENDPOINT"` and omit the command-level override.

## Verify the native target

```bash theme={null}
az storage container show \
  --account-name "$AZURE_STORAGE_ACCOUNT" \
  --name "$AZURE_CONTAINER" \
  --auth-mode login
```

If this fails, repair the verification identity or target selection before testing adaptation.

## Write through S3

```bash theme={null}
aws s3api put-object \
  --bucket "$ORIGIN_BUCKET" \
  --key "$TEST_KEY" \
  --body /tmp/cloud-adapter-smoke.txt \
  --content-type text/plain \
  --metadata quickstart=aws-to-azure \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" \
  --profile "$AWS_PROFILE" \
  --region "$AWS_REGION"
```

Read it back through the origin API:

```bash theme={null}
aws s3api head-object \
  --bucket "$ORIGIN_BUCKET" --key "$TEST_KEY" \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" --profile "$AWS_PROFILE" --region "$AWS_REGION"

aws s3api get-object \
  --bucket "$ORIGIN_BUCKET" --key "$TEST_KEY" \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" --profile "$AWS_PROFILE" --region "$AWS_REGION" \
  /tmp/cloud-adapter-origin.txt
```

## Verify the Azure blob

```bash theme={null}
az storage blob show \
  --account-name "$AZURE_STORAGE_ACCOUNT" \
  --container-name "$AZURE_CONTAINER" \
  --name "$TEST_KEY" \
  --auth-mode login

az storage blob download \
  --account-name "$AZURE_STORAGE_ACCOUNT" \
  --container-name "$AZURE_CONTAINER" \
  --name "$TEST_KEY" \
  --file /tmp/cloud-adapter-target.txt \
  --auth-mode login \
  --overwrite

cmp /tmp/cloud-adapter-smoke.txt /tmp/cloud-adapter-origin.txt
cmp /tmp/cloud-adapter-smoke.txt /tmp/cloud-adapter-target.txt
```

Check the content type and metadata in both views. Do not assume S3 version IDs, delete markers, ETags, or account-level settings have identical Azure representations.

## Verify the error path

Request a missing key through S3 and retain the command timestamp, AWS error code, and message. The normal AWS CLI output does not expose arbitrary response headers; use an SDK with structured, redacted response metadata when a support workflow requires them. A target-side authorization failure should not be mistaken for not found.

```bash theme={null}
aws s3api get-object \
  --bucket "$ORIGIN_BUCKET" --key "quickstart/missing-object" \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" --profile "$AWS_PROFILE" --region "$AWS_REGION" \
  /tmp/cloud-adapter-missing.txt
```

S3 can return permission denied instead of not found when the caller lacks permission to establish that the object is missing.

## Clean up

```bash theme={null}
aws s3api delete-object \
  --bucket "$ORIGIN_BUCKET" --key "$TEST_KEY" \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" --profile "$AWS_PROFILE" --region "$AWS_REGION"

az storage blob show \
  --account-name "$AZURE_STORAGE_ACCOUNT" \
  --container-name "$AZURE_CONTAINER" \
  --name "$TEST_KEY" \
  --auth-mode login
```

The native check should show that the current blob is no longer readable. Versioned or soft-delete-enabled targets can retain prior versions or recovery state; use an unversioned disposable target for this quickstart or remove the created version explicitly. Keep container deletion separate from object cleanup.

## Production readiness

Test listing prefixes and pagination, copy sizes, batch-delete failure handling, metadata, conditional requests, retries, and any versioning behavior the application depends on. Plan existing-object migration separately. Record which Azure account settings are shared across adapted buckets, and establish an uncertain-write check before enabling automatic retries.

Use [Debugging Your Adapters](/cloud-adapter/debugging/overview) when the S3 response and Azure state disagree.
