Routing AWS CLI Requests to Wasabi by Region

Prev Next

The AWS CLI is certified for use with Wasabi. Normally, that means adding --endpoint-url to every command, or creating a separate CLI profile for every Wasabi region you use. This article provides a shell function that removes both steps. It reads the --region you already pass and automatically sends that one command to the matching Wasabi endpoint.

This article assumes the AWS CLI is already installed and that you have a Wasabi access key and secret key configured under a named profile. For installation help, refer to AWS CLI With Wasabi.

macOS / Linux (zsh)

  1. Open ~/.zshrc in a text editor.

  2. Add the following to the end of the file:

    # "named" (default): only profiles containing "wasabi" use Wasabi endpoints.
    # "all": every call, including the default profile, uses Wasabi endpoints.
    export AWS_ROUTING_MODE="named"
     
    wasabi-mode() {
      case "$1" in
        all|named) export AWS_ROUTING_MODE="$1"; echo "aws routing mode: $1" ;;
        *) echo "usage: wasabi-mode [all|named]  (current: $AWS_ROUTING_MODE)" ;;
      esac
    }
     
    aws() {
      local region="" profile=""
      local args=("$@")
      local n=$#args
      local i val
     
      for (( i=1; i<=n; i++ )); do
        val="$args[i]"
        case "$val" in
          --region) region="$args[i+1]" ;;
          --region=*) region="${val#--region=}" ;;
          --profile) profile="$args[i+1]" ;;
          --profile=*) profile="${val#--profile=}" ;;
        esac
      done
     
      local use_wasabi=0
      if [[ "$AWS_ROUTING_MODE" == "all" ]]; then
        use_wasabi=1
      elif [[ "$AWS_ROUTING_MODE" == "named" && "$profile" == *wasabi* ]]; then
        use_wasabi=1
      fi
     
      # Default region for wasabi profiles when --region wasn't passed
      if [[ "$use_wasabi" == 1 && -z "$region" ]]; then
        region="us-east-1"
      fi
     
      if [[ -n "$region" && "$use_wasabi" == 1 ]]; then
        AWS_ENDPOINT_URL_S3="https://s3.${region}.wasabisys.com" \
        AWS_ENDPOINT_URL_IAM="https://iam.wasabisys.com" \
        AWS_ENDPOINT_URL_STS="https://sts.wasabisys.com" \
        command aws "${args[@]}"
      else
        command aws "${args[@]}"
      fi
    }

    Commands such as aws s3 ls --profile cloudnas-wasabi do not take a --region flag at all. Without the default-region fallback above, the function would have no region from which to build an endpoint and would silently fall through to real AWS, which is why a command that omits --region can fail with InvalidAccessKeyId instead of routing to Wasabi. The fallback here defaults to us-east-1. Change it if your buckets reside in a different Wasabi region.

  3. Save the file.

  4. Reload your shell:

    $ source ~/.zshrc
  5. Run AWS CLI commands as usual. Any command using a profile name containing wasabi is sent to the matching Wasabi region automatically:

    $ aws --region us-east-1 --profile prod-wasabi s3 ls
  6. To route every command to Wasabi, including the default profile, switch modes:

    $ wasabi-mode all
    $ aws --region us-east-1 s3 ls
    $ wasabi-mode named   # back to the default behavior

Windows (PowerShell)

  1. Check your profile path and whether it already exists:

    PS> $PROFILE
    PS> Test-Path $PROFILE
  2. Write the script directly to the file with the command below. This is safer than opening the file in Notepad and pasting. The Notepad Save dialog can silently save a decoy Microsoft.PowerShell_profile.ps1.txt file instead of overwriting the real PS1 file, leaving the real profile empty.

    New-Item -ItemType Directory -Force -Path (Split-Path $PROFILE) | Out-Null
     
    @'
    $env:AWS_ROUTING_MODE = "named"   # "named" = only *wasabi* profiles use Wasabi
                                       # "all"   = every call uses Wasabi
     
    function wasabi-mode {
        param([string]$Mode)
        if ($Mode -eq "all" -or $Mode -eq "named") {
            $env:AWS_ROUTING_MODE = $Mode
            Write-Host "aws routing mode: $Mode"
        } else {
            Write-Host "usage: wasabi-mode [all|named]  (current: $env:AWS_ROUTING_MODE)"
        }
    }
     
    function aws {
        $region = $null
        $profileName = $null
     
        for ($i = 0; $i -lt $args.Count; $i++) {
            if ($args[$i] -eq '--region')          { $region = $args[$i + 1] }
            elseif ($args[$i] -like '--region=*')  { $region = $args[$i].Substring(9) }
            elseif ($args[$i] -eq '--profile')     { $profileName = $args[$i + 1] }
            elseif ($args[$i] -like '--profile=*') { $profileName = $args[$i].Substring(10) }
        }
     
        $realAws = (Get-Command -CommandType Application aws | Select-Object -First 1).Source
     
        $useWasabi = $false
        if ($env:AWS_ROUTING_MODE -eq "all") {
            $useWasabi = $true
        } elseif ($env:AWS_ROUTING_MODE -eq "named" -and $profileName -like '*wasabi*') {
            $useWasabi = $true
        }
     
        # Default region for wasabi profiles when --region wasn't passed
        if ($useWasabi -and -not $region) {
            $region = "us-east-1"
        }
     
        if ($region -and $useWasabi) {
            $env:AWS_ENDPOINT_URL_S3  = "https://s3.$region.wasabisys.com"
            $env:AWS_ENDPOINT_URL_IAM = "https://iam.wasabisys.com"
            $env:AWS_ENDPOINT_URL_STS = "https://sts.wasabisys.com"
            try {
                & $realAws @args
            } finally {
                Remove-Item Env:AWS_ENDPOINT_URL_S3, Env:AWS_ENDPOINT_URL_IAM, Env:AWS_ENDPOINT_URL_STS -ErrorAction SilentlyContinue
            }
        } else {
            & $realAws @args
        }
    }
    '@ | Set-Content -Path $PROFILE -Encoding UTF8

    Commands such as aws s3 ls --profile cloudnas-wasabi do not take a --region flag at all. Without the default-region fallback above, the function would have no region from which to build an endpoint and would silently fall through to real AWS, which is why a command that omits --region can fail with InvalidAccessKeyId instead of routing to Wasabi. The fallback here defaults to us-east-1. Change it if your buckets reside in a different Wasabi region.

    If you prefer a text editor, run notepad $PROFILE, paste the script, and save. Be sure the “Save as type” drop-down is set to All Files (not Text Documents) before saving.

    No matter your approach, verify the file with the next step before reloading.

  3. Verify the script actually saved before reloading:

    PS> Get-Content $PROFILE | Select-String "wasabi-mode"

    This should print two matching lines. If it prints nothing, the file is empty, or the write failed. If there is a failure, repeat Step 2 before continuing.

  4. Load the profile in to your current session. (Note the space between the dot and the path. Without it, PowerShell tries to run the path as a command instead of loading it.)

    PS> . $PROFILE

    If this fails with “running scripts is disabled on this system,” your execution policy is blocking it. Run Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned (no administrator rights required for -Scope CurrentUser).

  5. Confirm the function loaded:

    PS> Get-Command wasabi-mode -CommandType Function
    PS> Get-Command aws -CommandType Function
  6. Run AWS CLI commands as usual. Any command using a profile name containing wasabi is sent to the matching Wasabi region automatically.

    PS> aws --region us-east-1 --profile prod-wasabi s3 ls
  7. To route every command to Wasabi, including the default profile, switch modes:

    PS> wasabi-mode all
    PS> aws --region us-east-1 s3 ls
    PS> wasabi-mode named   # back to the default behavior

Notes

This function only reads the --region and --profile flags typed on the command line. It does not read the AWS_PROFILE environment variable.

Neither script edits ~/.aws/config, ~/.aws/credentials, or any existing profile. They only change where one command is sent, for the duration of that command.

Non-interactive environments (cron, CI pipelines) generally do not load ~/.zshrc or a PowerShell profile automatically. So this has no effect there unless the script explicitly sources it first.

Replace wasabi in the profile-name check with whatever naming convention your Wasabi profiles use, if different.

Additional Information

Refer to: