func main()

in Containment/forensics/source/main.go [22:130]


func main() {
	bucketArn := flag.String("bucketArn","", "Arn of the bucket, e.g. arn:aws:s3:::forensics/")
	namespace := flag.String("namespace", "forensics-system", "Service account namespace")
	serviceAccount := flag.String("serviceAccount", "forensics-worker", "Service account name")
	clusterName := flag.String("clusterName", "", "Name of cluster (required)")
	flag.Parse()
	flag.VisitAll(func (f *flag.Flag) {
		if f.Value.String()=="" {
			log.Fatalln(f.Name, "is not set")
		}
	})
	ctx := context.TODO()
	cfg, err := config.LoadDefaultConfig(context.TODO())
	if cfg.Region == "" {
		log.Fatalln("Could not find region in default profile")
	}
	if err != nil {
		log.Fatalf("unable to load SDK config, %v", err)
	}
	iamPolicy := "{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Sid\": \"VisualEditor0\",\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"s3:PutObject\",\n                \"s3:GetObject\"\n            ],\n            \"Resource\": \"" + *bucketArn + "*\"\n        }\n    ]\n}"

	k8s := eks.NewFromConfig(cfg)
	clusterOutput, err := k8s.DescribeCluster(ctx, &eks.DescribeClusterInput{
		Name: clusterName,
	})
	if err != nil {
		log.Fatalln(err)
	}
	oidcEndpointUrl := clusterOutput.Cluster.Identity.Oidc.Issuer
	u, _ := url.Parse(*oidcEndpointUrl)
	oidcEndpoint := u.Host + u.Path
	log.Println(oidcEndpoint)

	svc := iam.NewFromConfig(cfg)
	oidcProviders, err := svc.ListOpenIDConnectProviders(ctx, &iam.ListOpenIDConnectProvidersInput{})
	if err != nil {
		log.Println(err)
	}
	p := oidcProviders.OpenIDConnectProviderList
	oidcEndpointArn := p[0].Arn
	log.Println(*oidcEndpointArn)

	var policyArn string
	//create IAM policy
	cpo, err := svc.CreatePolicy(ctx, &iam.CreatePolicyInput{
		PolicyDocument: aws.String(iamPolicy),
		PolicyName:     aws.String(policyName),
		Description:    aws.String("allows writes to the specified s3 bucket"),
	})
	//if policy exists, get policy Arn
	if err != nil {
		var ne *types.EntityAlreadyExistsException
		if errors.As(err, &ne) {
			lpo, _ := svc.ListPolicies(ctx, &iam.ListPoliciesInput{Scope: "Local"})
			for _, v := range lpo.Policies {
				if aws.ToString(v.PolicyName) == "forensics-policy" {
					policyArn = aws.ToString(v.Arn)
				}
			}
		}
	} else {
		policyArn = aws.ToString(cpo.Policy.Arn)
	}

	trustPolicy := "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Principal\": {\n        \"Federated\": \"" + *oidcEndpointArn + "\"\n      },\n      \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n      \"Condition\": {\n        \"StringEquals\": {\n          \"" + oidcEndpoint + ":sub\": \"system:serviceaccount:" + *namespace + ":" + *serviceAccount + "\"\n        }\n      }\n    }\n  ]\n}"
	//create IAM role
	cro, err := svc.CreateRole(ctx, &iam.CreateRoleInput{
		AssumeRolePolicyDocument: aws.String(trustPolicy),
		RoleName:                 aws.String(roleName),
		Description:              aws.String("Role for writing forensic data to an s3 bucket"),
	})
	//if role already exists
	if err != nil {
		var ne *types.EntityAlreadyExistsException
		if errors.As(err, &ne) {
			log.Println("error:", ne)
			larp, err := svc.ListAttachedRolePolicies(ctx, &iam.ListAttachedRolePoliciesInput{RoleName: aws.String("forensics-role")})
			if err != nil {
				log.Println(err)
			}
			//if the role doesn't have a policy, attach policyArn
			if len(larp.AttachedPolicies) == 0 {
				log.Println("No policies attached to role")
				svc.AttachRolePolicy(ctx, &iam.AttachRolePolicyInput{
					RoleName: aws.String(roleName),
					PolicyArn: aws.String(policyArn),
				})
				gro, _ := svc.GetRole(ctx, &iam.GetRoleInput{RoleName: aws.String("forensics-role")})
				log.Println(aws.ToString(gro.Role.Arn))
				return
			//if the role has a policy, log the role Arn
			} else {
				gro, _ := svc.GetRole(ctx, &iam.GetRoleInput{RoleName: aws.String("forensics-role")})
				log.Println(aws.ToString(gro.Role.Arn))
				return
			}
		}
	// create role, and attach policy
	} else {
		_, err = svc.AttachRolePolicy(ctx, &iam.AttachRolePolicyInput{
			RoleName:  aws.String(roleName),
			PolicyArn: aws.String(policyArn),
		})
	}
	if err != nil {
		log.Println(err)
	}
	fmt.Println(aws.ToString(cro.Role.Arn))
}