AWS Java SDK: Creating a role and Lambda, Lambda cannot assume role

110 views Asked by At

I am trying to get used to the Java SDK for AWS but I am failing to get some basic stuff done. The code is supposed to do the following:

  • Upload a zip file to s3 bucket
  • create execution role for lambda
  • create lambda with code from uploaded zip and created role
  • assign policies to lambda execution role

The code fails to properly deploy the desired resources because the Lambda cannot assume the role.

Please find below the code I am using. The various clients are properly initialized. Moreover:

  • bucketName is a valid name of an existing S3 bucket
  • objectKey is a valid name for an S3 key, no existing key matching this name in bucketName bucket
  • zipFile is a File pointing to a valid and existing zip file containing code for an AWS Lambda function handler
  • lambdaAssume is a String containing an assume role policy for lambda as described in the AWS documentation, it's content is shown after the code
  • policyArn is a valid ARN of an existing policy
s3Client.putObject(PutObjectRequest.builder()
    .bucket(bucketName)
    .key(objectKey)
    .build(),
  RequestBody.fromFile(zipFile));

Role execRole = iamClient.createRole(CreateRoleRequest.builder()
    .roleName("my-new-lambda-exec-role")
    .assumeRolePolicyDocument(lambdaAssume)
    .build
  ).role();

lambdaClient.createFunction(CreateFunctionRequest.builder()
    .functionName("my-new-lambda")
    .packageType(PackageType.ZIP)
    .code(FunctionCode.builder()
      .s3Bucket(bucketName)
      .s3Key(objectKey)
      .build())
    .role(execRole.arn())
    .handler("org.acme.App::handleRequest")
    .runtime(Runtime.JAVA11)
    .architectures(Architecture.X86_64)
    .build());

iamClient.attachRolePolicy(AttachRolePolicyRequest.builder()
    .roleName(execRole.roleName())
    .policyArn(policyArn)
    .build());

where lambdaAssume is as follows:

"""
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
"""

The code execution fails with the following error: Exception in thread "main" software.amazon.awssdk.services.lambda.model.InvalidParameterValueException: The role defined for the function cannot be assumed by Lambda. (Service: Lambda, Status Code: 400, Request ID: ...)

Could anyone have a look at the code and tell me if I'm getting anything from? I also tried putting a waiter on the creation of the role but nothing changed. I've read on the aws console that when creating a lambda it might take up to 5 mins to get a newly created execution role to work and that it would be better not to modify it during that period. Would this apply also in the case of the SDK? (if so, wouldn't it be very bothersome? and how would I detect when the role is ready for modification?)

Please mind that the goal is to avoid creating resources by hand through the console, this means ideally everything is done through the sdk, with the possibility of using the cli but I would prefer to avoid that.

Thank you very much for anything you can help me with!

1

There are 1 answers

1
rlhagerm On BEST ANSWER

Looks like you may need to adjust your order. There is an example in the AWS Code example library in Java for IAM that does the creation of a role and adding a policy, and it has 30 sec waits after creating the resource. Maybe you would also want to catch a "role not found" exception (if there is one) and wait again and retry. But even with a wait, you would need one of the following orders:

  1. Create the role with the policy in one step.
  2. Wait for the role to be ready.
  3. Create your function.

OR

  1. Create the role.
  2. Wait for the role to be ready.
  3. Attach the policy.
  4. Create your function.

There is also a Lambda example in the library, but it uses a pre-existing role, so it doesn't exactly match your scenario.