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.