Bildiğimiz gibi, bir uygulamanın başka bir hesaptan bir hesaba erişmesi gerekiyorsa, rolü üstlenmesi ve geçici kimlik bilgileri alması gerekir (süresi 15 dakika içinde sona erer ancak otomatik olarak yenilenir). Buna hesaplar arası erişim denir. Kısacası, uygulama X uygulamasında çalışıyor ve Y hesabındaki kaynakları kullanmak istiyor.


Örnek olması açısından, uygulamanın aynı hesap içinden kaynakları (IAM) kullandığı bir örnek de ekleyeceğim. Hesaplar arası erişim için S3 kaynaklarına odaklanacağız.


Ön şartlar


Aşağıdaki paketleri yükleyin.


go get github.com/aws/aws-sdk-go-v2
go get github.com/aws/aws-sdk-go-v2/config
go get github.com/aws/aws-sdk-go-v2/service/iam
go get github.com/aws/aws-sdk-go-v2/service/s3
go get github.com/aws/aws-sdk-go-v2/service/sts

Dosyalar


aws/config.go


package aws

import (
"context"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"
"github.com/aws/aws-sdk-go-v2/service/sts"
)

// NewDefaultConfig current credentials for the current account and returns AWS
// config. Credentials do not expire.
func NewDefaultConfig(ctx context.Context) (aws.Config, error) {
return config.LoadDefaultConfig(ctx)
}

// NewCrossAccountConfigWithRole retrieves temporary credentials from the STS
// service for assumed role and returns AWS config for cross-account access. Credentials
// last 15 minutes but get automatically refreshed.
func NewCrossAccountConfigWithRole(ctx context.Context, roleARN string) (aws.Config, error) {
cfg, err := config.LoadDefaultConfig(ctx)
if err != nil {
return aws.Config{}, err
}

stsClient := sts.NewFromConfig(cfg)
stsCreds := stscreds.NewAssumeRoleProvider(stsClient, roleARN)

cfg.Credentials = aws.NewCredentialsCache(stsCreds)

return cfg, nil
}

aws/iam.go


package aws

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

func NewIAMClient(cfg aws.Config) *iam.Client {
return iam.NewFromConfig(cfg)
}

aws/s3.go


package aws

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

func NewS3Client(cfg aws.Config) *s3.Client {
return s3.NewFromConfig(cfg)
}

api/current_account.go


package api

import (
"context"
"log"
"net/http"

"github.com/aws/aws-sdk-go-v2/service/iam"
)

// CurrentAccount holds AWS current account dependencies.
type CurrentAccount struct {
IAMClient *iam.Client
}

// IAM fetches IAM groups from the current account.
func (c CurrentAccount) IAM(w http.ResponseWriter, r *http.Request) {
out, err := c.IAMClient.ListGroups(context.Background(), nil)
if err != nil {
log.Fatal(err)
}

for _, group := range out.Groups {
log.Println(*group.GroupName)
}
}

api/cross_account.go


package api

import (
"context"
"log"
"net/http"

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

// CrossAccount holds AWS cross-account dependencies.
type CrossAccount struct {
S3Client *s3.Client
}

// S3 fetches S3 bucktes from a cross account.
func (c CrossAccount) S3(w http.ResponseWriter, r *http.Request) {
out, err := c.S3Client.ListBuckets(context.Background(), nil)
if err != nil {
log.Fatal(err)
}

for _, bucket := range out.Buckets {
log.Println(*bucket.Name)
}
}

main.go


package main

import (
"aws/api"
"aws/aws"
"context"
"log"
"net/http"
)

func main() {
ctx := context.Background()

currentAccountConfig, err := aws.NewDefaultConfig(ctx)
if err != nil {
log.Fatal(err)
}

crossAccountConfig, err := aws.NewCrossAccountConfigWithRole(ctx, "arn:aws:iam::1234567890:role/services")
if err != nil {
log.Fatal(err)
}

currectAccountAPI := api.CurrentAccount{
IAMClient: aws.NewIAMClient(currentAccountConfig),
}

crossAccountAPI := api.CrossAccount{
S3Client: aws.NewS3Client(crossAccountConfig),
}

httpRouter := http.NewServeMux()
httpRouter.HandleFunc("/iam", currectAccountAPI.IAM)
httpRouter.HandleFunc("/s3", crossAccountAPI.S3)

log.Fatalln(http.ListenAndServe(":1234", httpRouter))
}

AWS yapılandırma


İsterseniz bunun yerine normal ortam değişkenlerini kullanabilirsiniz.


[default]
region = eu-west-1
output = json

[default]
aws_access_key_id = QWERTY09876541
aws_secret_access_key = QWERTY1234567890

Test


$ go run -race main.go

$ curl http://localhost:1234/iam
2023/06/03 14:53:39 admins
2023/06/03 14:53:39 devops
2023/06/03 14:53:39 developers

$ curl http://localhost:1234/s3
2023/06/03 14:53:45 inanzzz-development-cvs
2023/06/03 14:53:45 inanzzz-development-images