How to make SSO auth work for Golang AWS SDK




Recently, we open sourced cloudlens, a k9s style CLI for AWS. We’ve used Go to build cloudlens.

Within the first week of its release, a user raised an issue that he wasn’t able to use cloudlens with SSO credentials. It turns out that AWS’s v1 Go SDK doesn’t support SSO credentials.

This blog describes how we solved this problem.

In cloudlens v0.1.1, we read the AWS credentials and configurations from ~/.aws/credentials and ~/.aws/config files respectively. But it did not have the support for reading SSO credentials. In the later version of cloudlens though (v0.1.2 and above), we added the support for AWS SSO credentials. So how did we do it?

For accessing AWS services via the Go SDK, you need to authenticate yourself when using the SDK.

There are 3 ways of authenticating with AWS. Those are:

  1. Environment Variables
  2. Credentials and Config files (~/.aws/credentials and ~/.aws/config)
  3. SSO

The AWS SDK for Go has two versions v1 and v2. It turns out, v1 version of the SDK doesn’t support SSO credentials. And that’s the version we were using. So we decided to upgrade the SDK’s version from v1 to v2.

A side note about AWS Go SDK v1 and SSO credentials

As a side note, the v1 version of SDK does have partial support for SSO. In the sense that, you need to have your ~/.aws/config file in the following format:

[profile xxx]
sso_start_url = [<https://d-xxxxxxxxxx.awsapps.com/start>](<https://d-xxxxxxxxxx.awsapps.com/start>)
sso_session = xxx
sso_account_id = xxxxxxxxxx
sso_role_name = xxxxxxxxxx
region = ap-northeast-1
sso_region = ap-northeast-1
output = json

Notice that all the SSO key values must be in the profile section itself. AWS also has a way to describe the same config in a different format where you specify some SSO key values in a separate section, like below.

[profile xxx]
sso_session = xxx
sso_account_id = xxxxxxxxxx
sso_role_name = xxxxxxxxxx
region = ap-northeast-1
sso_region = ap-northeast-1
output = json

[sso-session xxx]
sso_start_url = https://d-xxxxxxxxxx.awsapps.com/start
sso_region = ap-northeast-1
sso_registration_scopes = sso:account:access

If you have your ~/.aws/config file like above, it will NOT work with v1 version of AWS SDK. For it to work with SDK’s v1 version, we need to copy the sso_start_url and sso_region from sso-session block, and paste it into the profile block itself. Have a look at this GitHub Issue Comment for more details.

So what are our options?

We have two options:

  1. Upgrade SDK version to v2 or
  2. Ask users to update their ~/.aws/config file

Naturally, we decided to go ahead with option 1.

How we migrated from AWS SDK from v1 to v2?

Before we proceeded with the upgradation, we had some questions:

  • What all has really changed in v2 version?
  • Is v2 backward compatible with v1?
  • How much code change is needed to migrate from v1 to v2?
  • How will we ensure that nothing breaks?

The major change in v2 is that it uses Go’s module feature and separates all SDK code into separate modules. Also, v2 uses config instead of session for authentication. We need to create a client by passing the config for every service separately. i.e. ec2 client will be different from s3 client. Thus, each service needs its own client.

Also, v2 and v1 are backward compatible. Just that, instead of session, we need context and config. Technically, we can replace v1 import in go.mod with v2 import and things will just work. However, we wanted to change the SSO auth code. So we had to perform code changes to update how auth is handled using config instead of session.

The code change to use the v2 SDK is as follows:

After we get the config, a client of any AWS service needs to be created. That client can then be used to call any of the methods of that service.

Similar change needed to be done for other services like EC2, IAM, etc that cloudlens supports. Here’s the final PR for this change – https://github.com/one2nc/cloudlens/pull/14.

With this change, the user can pass the SSO credentials via ~/.aws/config in any format (no need to fiddle with the config file). The final ~/.aws/config file can be something like this:

[profile xxx]
sso_session = xxx
sso_account_id = xxxxxxxxxx
sso_role_name = xxxxxxxxxx
region = ap-northeast-1
sso_region = ap-northeast-1
output = json

[sso-session xxx]
sso_start_url = https://d-xxxxxxxxxx.awsapps.com/start
sso_region = ap-northeast-1
sso_registration_scopes = sso:account:access 

And cloudlens will be able to parse and use this config.

If your application wants to make SSO authentication work with AWS’s Go SDK, you will have to either modify your ~/.aws/config file, or upgrade to v2 version of SDK.

Chinmay Somani
Chinmay Somani