Go monk

AWS configuration sources

When talking to AWS from a Go program the easiest way is to use the AWS SDK. Say you want to list the S3 buckets. The program would look something like:

package main

import (
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/s3"
)

func main() {
	// ...
	cfg, err := config.LoadDefaultConfig(ctx)
	// ...
	client := s3.NewFromConfig(cfg)
	out, err := client.ListBuckets(ctx, &s3.ListBucketsInput{})
	// ...
}

You can find the full program here.

Now, let’s build and run the program inside a container that has never been configured to connect to AWS:

$ cd ~/github.com/go-monk/aws-config/list-s3-buckets
$ GOOS=linux CGO_ENABLED=0 go build
$ docker run --rm -it --mount type=bind,source=".",target=/tmp,readonly busybox sh
# /tmp/list-s3-buckets 
list-s3-buckets: operation error S3: ListBuckets, resolve auth scheme: resolve endpoint: endpoint rule error, Invalid region: region was not a valid DNS name.

You get this error because region is a required configuration value and it’s not set since there’s no configuration in the container. The default configuration sources that the SDK’s config.LoadDefaultConfig function searches are:

  • environment variables, like AWS_REGION
  • shared1 configuration and credentials files in ~/.aws/

You can also optionally pass additional configuration to the function as you can see below where the config.WithRegion function is used.

Let’s look in more detail at all three configuration sources:

	// ...
	cfg, err := config.LoadDefaultConfig(
		context.Background(), config.WithRegion("us-east-1"))
	// ...
	for i, source := range cfg.ConfigSources {
		var region string
		switch source := source.(type) {
		case config.LoadOptions:
			region = source.Region
		case config.EnvConfig:
			region = source.Region
		case config.SharedConfig:
			region = source.Region
		}
		fmt.Fprintf(writer, "%d\t%T\t%s\n", i+1, source, region)
	}
	// ...

You can find the full program here. Let’s run it:

# AWS_REGION=eu-central-1 /tmp/list-config-sources 
SOURCE  TYPE                 REGION
1       config.LoadOptions   us-east-1
2       config.EnvConfig     eu-central-1
3       config.SharedConfig  us-east-2

In the table above you can see the three types of configuration sources and the region configuration value. The us-east-1 region is hardcoded inside the program by virtue of the config.WithRegion option, eu-central-1 comes from the AWS_REGION environment variable and us-east-2 from the default profile in the ~/.aws/config file:

# cat ~/.aws/config 
[default]
region=us-east-2

Play around with the programs, change them and change the config file and environment variables. It will help you to understand what’s going on.


  1. They are called shared because they are used by all local AWS CLIs (like aws s3 ls) and SDKs (like the programs above). ↩︎