func (infra *Infrastructure) createIAMLambdaRolePolicy(roleName string) error { svc := iam.New(session.New(), infra.config) _, err := svc.PutRolePolicy(&iam.PutRolePolicyInput{ PolicyDocument: aws.String(`{ "Version": "2012-10-17", "Statement": [ { "Action": [ "sqs:SendMessage" ], "Effect": "Allow", "Resource": "arn:aws:sqs:*:*:goad-*" }, { "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Effect": "Allow", "Resource": "arn:aws:logs:*:*:*" } ] }`), PolicyName: aws.String("goad-lambda-role-policy"), RoleName: aws.String(roleName), }) return err }
// Retrieve generates a new set of temporary credentials using STS. func (p *AssumeRoleProvider) Retrieve() (credentials.Value, error) { // Apply defaults where parameters are not set. if p.RoleSessionName == "" { // Try to work out a role name that will hopefully end up unique. p.RoleSessionName = fmt.Sprintf("%d", time.Now().UTC().UnixNano()) } if p.Duration == 0 { // Expire as often as AWS permits. p.Duration = DefaultDuration } roleOutput, err := p.Client.AssumeRole(&sts.AssumeRoleInput{ DurationSeconds: aws.Int64(int64(p.Duration / time.Second)), RoleArn: aws.String(p.RoleARN), RoleSessionName: aws.String(p.RoleSessionName), ExternalId: p.ExternalID, }) if err != nil { return credentials.Value{}, err } // We will proactively generate new credentials before they expire. p.SetExpiration(*roleOutput.Credentials.Expiration, p.ExpiryWindow) return credentials.Value{ AccessKeyID: *roleOutput.Credentials.AccessKeyId, SecretAccessKey: *roleOutput.Credentials.SecretAccessKey, SessionToken: *roleOutput.Credentials.SessionToken, }, nil }
func (infra *Infrastructure) removeSQSQueue() { svc := sqs.New(session.New(), infra.config) svc.DeleteQueue(&sqs.DeleteQueueInput{ QueueUrl: aws.String(infra.queueURL), }) }
// SendResult adds a result to the queue func (adaptor SQSAdaptor) SendResult(result AggData) { str, jsonerr := jsonFromResult(result) if jsonerr != nil { fmt.Println(jsonerr) return } params := &sqs.SendMessageInput{ MessageBody: aws.String(str), QueueUrl: aws.String(adaptor.QueueURL), } _, err := adaptor.Client.SendMessage(params) if err != nil { fmt.Println(err.Error()) return } }
func (t *Test) invokeLambda(awsConfig *aws.Config, cmd string) { svc := lambda.New(session.New(), awsConfig) svc.InvokeAsync(&lambda.InvokeAsyncInput{ FunctionName: aws.String("goad"), InvokeArgs: strings.NewReader(`{"cmd":"` + cmd + `"}`), }) }
// Receive a result, or timeout in 1 second func (adaptor SQSAdaptor) Receive() *AggData { params := &sqs.ReceiveMessageInput{ QueueUrl: aws.String(adaptor.QueueURL), MaxNumberOfMessages: aws.Int64(1), VisibilityTimeout: aws.Int64(1), WaitTimeSeconds: aws.Int64(1), } resp, err := adaptor.Client.ReceiveMessage(params) if err != nil { fmt.Println(err.Error()) return nil } if len(resp.Messages) == 0 { return nil } item := resp.Messages[0] deleteParams := &sqs.DeleteMessageInput{ QueueUrl: aws.String(adaptor.QueueURL), ReceiptHandle: aws.String(*item.ReceiptHandle), } _, delerr := adaptor.Client.DeleteMessage(deleteParams) if delerr != nil { fmt.Println(err.Error()) return nil } result, jsonerr := resultFromJSON(*item.Body) if jsonerr != nil { fmt.Println(err.Error()) return nil } return &result }
func (infra *Infrastructure) createSQSQueue() (url string, err error) { svc := sqs.New(session.New(), infra.config) resp, err := svc.CreateQueue(&sqs.CreateQueueInput{ QueueName: aws.String("goad-" + uuid.NewV4().String()), }) if err != nil { return "", err } return *resp.QueueUrl, nil }
func (infra *Infrastructure) createIAMLambdaRole(roleName string) (arn string, err error) { svc := iam.New(session.New(), infra.config) resp, err := svc.GetRole(&iam.GetRoleInput{ RoleName: aws.String(roleName), }) if err != nil { if awsErr, ok := err.(awserr.Error); ok { if awsErr.Code() == "NoSuchEntity" { resp, err := svc.CreateRole(&iam.CreateRoleInput{ AssumeRolePolicyDocument: aws.String(`{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Principal": {"Service": "lambda.amazonaws.com"}, "Action": "sts:AssumeRole" } }`), RoleName: aws.String(roleName), Path: aws.String("/"), }) if err != nil { return "", err } if err := infra.createIAMLambdaRolePolicy(*resp.Role.RoleName); err != nil { return "", err } return *resp.Role.Arn, nil } } else { return "", err } } return *resp.Role.Arn, nil }
func (infra *Infrastructure) createLambdaFunction(roleArn string, payload []byte) error { svc := lambda.New(session.New(), infra.config) _, err := svc.GetFunction(&lambda.GetFunctionInput{ FunctionName: aws.String("goad"), }) if err != nil { if awsErr, ok := err.(awserr.Error); ok { if awsErr.Code() == "ResourceNotFoundException" { _, err := svc.CreateFunction(&lambda.CreateFunctionInput{ Code: &lambda.FunctionCode{ ZipFile: payload, }, FunctionName: aws.String("goad"), Handler: aws.String("index.handler"), Role: aws.String(roleArn), Runtime: aws.String("nodejs"), Description: aws.String("Description"), MemorySize: aws.Int64(128), Publish: aws.Bool(true), Timeout: aws.Int64(300), }) if err != nil { if awsErr, ok := err.(awserr.Error); ok { // Calling this function too soon after creating the role might // fail, so we should retry after a little while. // TODO: limit the number of retries. if awsErr.Code() == "InvalidParameterValueException" { time.Sleep(time.Second) return infra.createLambdaFunction(roleArn, payload) } } return err } } } } return nil }