aws golang: Not able to getAccountID based on credentials file

128 Views Asked by At

My golang script is basically doing some AWS read/delete operation on aws lambda functions, and I have configured it in a way that if we pass --profile <profile_name> argument at run time, it would look into the respective AWS profile and perform the operation.

./golang-binary --profile stage -r us-east-1 It would perform the operation in stage profile. The same is working fine in local mac, but when I run the same code in Jenkins, it picks Jenkins default profile even specifying --profile stage

What I want??

We have role based access in jenkins(and we don't store AWS keys). For different accounts, it picks different profiles based on the credentials ec2instancemetadata file. I want that my code should pick the profile from the credentials.ini file which is there in the app directory itself, and based on that profile, it creates a session, rather than directly calling getCallerIdentity function.


package main

import (
    "fmt"
    "os"
    "regexp"
    "sort"
    "time"

    "github.com/alecthomas/kong"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/awserr"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/lambda"
    "github.com/aws/aws-sdk-go/service/s3"
    "github.com/aws/aws-sdk-go/service/sts"
    "k8s.io/klog/v2"
)

type CLI struct {
    Profile       string `short:"p" name:"profile"        default:""    help:"AWS Profile to use. Defaults to the env var AWS_PROFILE"`
    Region        string `short:"r" name:"region"         default:""    help:"Region to purge. Defaults to the env var AWS_DEFAULT_REGION"`
}

func parseCLI() CLI {
    var cli CLI
    kongCtx := kong.Parse(&cli)
    if kongCtx.Error != nil {
        klog.Fatalf("error parsing cli args: %s", kongCtx.Error)
    }
    return cli
}

func main() {
    cli := parseCLI()

    // Create Session
    var sess *session.Session
    var lambdaSvc *lambda.Lambda
    var s3Svc *s3.S3
    if cli.Profile == "" {
        sess = session.Must(session.NewSession())
    } else {
        sess = session.Must(session.NewSessionWithOptions(session.Options{
            Profile: cli.Profile,
        }))
    }
    if cli.Region == "" {
        klog.Errorf("please specify region")
        os.Exit(1)
    } else {
        lambdaSvc = lambda.New(sess, aws.NewConfig().WithRegion(cli.Region))
        s3Svc = s3.New(sess, aws.NewConfig().WithRegion(cli.Region))
    }



    functionName := cli.FunctionName
    if cli.FunctionName == "" {
        klog.Errorf("function name is not properly passed to the script.. exiting")
        os.Exit(1)
    }


    accountID, err := getAccountID(sess)
    if err != nil {
        klog.Errorf("Failed to getAccountID: %v", err)
        os.Exit(1)
    }
    klog.Infof("account id is %s", accountID)


func getAccountID(sess *session.Session) (string, error) {
    stsSvc := sts.New(sess)
    param := &sts.GetCallerIdentityInput{}
    result, err := stsSvc.GetCallerIdentity(param)
    if err != nil {
        klog.Errorf("Failed to sts.GetCallerIdentity: %v", err)
        return "", err
    }
    return aws.StringValue(result.Account), nil
}

func someOtherFunctionsThatDeletesInstances{}

I suspect jenkins is using its default configured profile because in getAccountID, we are using GetCallerIdentity API, which will give Jenkins callerIdentity instead. We need to modify the getAccountID function to take the creds from the credentials.ini file which has below format:

[profile-1]
region            = region-1
credential_source = Ec2InstanceMetadata
role_arn          = arn:aws:iam::<accountID-1>:role/jenkins_role

[profile-2]
region            = region-2
credential_source = Ec2InstanceMetadata
role_arn          = arn:aws:iam::<accountID-2>:role/jenkins_role

Currently, it is not reading this file and directly calling getcalleridentity due to which it works in local, but fails on Jenkins.

Update: I made bit of a progress by explicitly providing --role-arn-file as the argument to the aws_credentials file, so that it reads the profile from there, but ran into a different error:

E0623 14:38:02.301269    5498 main.go:335] Failed to assume role: InvalidParameter: 1 validation error(s) found.
- minimum field size of 20, AssumeRoleInput.RoleArn.
E0623 14:38:02.301298    5498 main.go:96] Failed to getAccountID: InvalidParameter: 1 validation error(s) found.
- minimum field size of 20, AssumeRoleInput.RoleArn.

It seems to be having some issue parsing it. not so sure what is happening. The aws credentials file sample is given above already.

0

There are 0 best solutions below