How to list resources of linked AWS accounts using AWS Go sdk

404 Views Asked by At

This is what I have tried. The code below fetches a list of linked accounts, but fetches the list of domains of only one AWS account. I want to list domains or any other resources of each particular linked account.

The problem seems to be around svc := route53.New(sess) or the sess itself as an account Id is not pass to svc or sess. So the question is how to pass the account Id?

package main

import (
    "context"
    "crypto/tls"
    "fmt"
    "log"

    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/organizations"
    "github.com/aws/aws-sdk-go-v2/service/route53domains"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/route53"
)

func main() {

    // Load the Shared AWS Configuration (~/.aws/config)
    cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithDefaultRegion("us-east-1"))
    if err != nil {
        log.Fatal(err)
    }

    // Create an Amazon service clients
    awsOrgClient := organizations.NewFromConfig(cfg)
    awsRoute53DomainsClient := route53domains.NewFromConfig(cfg)

    // Build the request with its input parameters
    resp, err := awsOrgClient.ListAccounts(context.TODO(), &organizations.ListAccountsInput{})
    if err != nil {
        log.Fatalf("failed to list tables, %v", err)
    }

    fmt.Println("Accounts:")
    for _, account := range resp.Accounts {
        fmt.Println(*account.Name)

        // Build the request with its input parameters
        resp, err := awsRoute53DomainsClient.ListDomains(context.TODO(), &route53domains.ListDomainsInput{}, func(o *route53domains.Options) {})

        if err != nil {
            log.Fatalf("failed to list tables, %v", err)
        }

        fmt.Println("Accounts:")
        for _, route53 := range resp.Domains {
            fmt.Println(*&route53.DomainName)
        }

        // fetch list of domains from AWS Route53
        sess := session.Must(session.NewSessionWithOptions(session.Options{
            SharedConfigState: session.SharedConfigEnable,
        }))

        svc := route53.New(sess)

        // call svc.ListHostedZones() for an account

        result, err := svc.ListHostedZones(&route53.ListHostedZonesInput{})
        if err != nil {
            fmt.Println(err.Error())
            return
        }

        for _, hostedzone := range result.HostedZones {
            fmt.Println(*hostedzone.Name)
        }
    }
}
1

There are 1 best solutions below

0
On

It appears that you are running the AWS Organizations ListAccounts() command to obtain a list of accounts.

If you then want to make API calls to each 'member' account, your code will need to assume an IAM Role in the member account. This is because your existing credentials are associated with the Organizations account, which does not have permission to access the member accounts.

From Accessing and administering the member accounts in your organization - AWS Organizations:

If you create an account by using the tools provided as part of AWS Organizations, you can access the account by using the preconfigured role named OrganizationAccountAccessRole that exists in all new accounts that you create this way.

Thus, you could call AssumeRole() on OrganizationAccountAccessRole in the member account, which will then return a set of temporary credentials. You can use those credentials to make API calls to the member account.

Basically, a set of credentials will only work with one account.