1
votes

I have 2 Aws accounts(Account A and Account B). My goal is create Custom AWS Config rule in Account B by using lambda function in Account A. I had created lambda function in account A as

import boto3
import json
import logging

log = logging.getLogger()
log.setLevel(logging.DEBUG)
APPLICABLE_RESOURCES = ["AWS::S3::Bucket"]


def evaluate_compliance(configuration_item):
    if configuration_item["resourceType"] not in APPLICABLE_RESOURCES:
        return {
            "compliance_type": "NOT_APPLICABLE",
            "annotation": "The rule doesn't apply to resources of type " +
            configuration_item["resourceType"] + "."
        }

    if configuration_item['configurationItemStatus'] == "ResourceDeleted":
        return {
            "compliance_type": "NOT_APPLICABLE",
            "annotation": "The configurationItem was deleted " +
                          "and therefore cannot be validated"
        }

    bucket_policy = configuration_item["supplementaryConfiguration"].get("BucketPolicy")
    if bucket_policy['policyText'] is None:
        return {
            "compliance_type": "COMPLIANT",
            "annotation": 'Bucket Policy does not exists'
        }

    else:
        return {
            "compliance_type": "NON_COMPLIANT",
            "annotation": 'Bucket Policy exists'
        }


def lambda_handler(event, context):
    log.debug('Event %s', event)
    invoking_event      = json.loads(event['invokingEvent'])
    configuration_item  = invoking_event["configurationItem"]
    evaluation          = evaluate_compliance(configuration_item)
    config              = boto3.client('config')

    config.put_evaluations(
       Evaluations=[
           {
               'ComplianceResourceType':    invoking_event['configurationItem']['resourceType'],
               'ComplianceResourceId':      invoking_event['configurationItem']['resourceId'],
               'ComplianceType':            evaluation["compliance_type"],
               "Annotation":                evaluation["annotation"],
               'OrderingTimestamp':         invoking_event['configurationItem']['configurationItemCaptureTime']
           },
       ],
       ResultToken=event['resultToken'])

I have one lambda execution role(Which is auto created when i created lambda function) in account A and I added one assumeRole for role created in account B as

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:us-east-2:Account A:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:us-east-2:Account A:log-group:/aws/lambda/LambdaFunctionName:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::Account B:role/AccountBRole"
        }
    ]
}

I am using user in account A for credentials access required for sts Client for asssume role

Added assume in policy in user as well as :-

 {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "*"
        }
    ]
}

Created Role in Account B with AWSConfigRulesExecutionRole Aws Managed Permission

and trust relationship is as : -

 {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": [
              "arn:aws:iam::Account A:root",
              "arn:aws:iam::Account A:user/userName"
            ]
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }

Here is my java code to create custom AWS Config Rule in Account B using Lambda function of account A as

AWSCredentials ourAwsCredentials = new BasicAWSCredentials("AWSSecretKeyAccountA",
                "AWSAccessKeyAccountA");   

        AWSSecurityTokenServiceClient stsClient = (AWSSecurityTokenServiceClient) AWSSecurityTokenServiceClientBuilder
                .standard()
                .withRegion(Regions.US_EAST_2)
                .withCredentials(new AWSStaticCredentialsProvider(ourAwsCredentials))
                .build();


            AssumeRoleRequest assumeRequest = new AssumeRoleRequest()
                   .withRoleArn("arn:aws:iam::Account B:role/AccountBRole")
                    .withDurationSeconds(3600)
                .withRoleSessionName("demo-1235");

            AssumeRoleResult assumeResult =
            stsClient.assumeRole(assumeRequest);

            BasicSessionCredentials temporaryCredentials =
            new BasicSessionCredentials(
                        assumeResult.getCredentials().getAccessKeyId(),
                        assumeResult.getCredentials().getSecretAccessKey(),
                        assumeResult.getCredentials().getSessionToken());

            AWSCredentialsProvider rolecredentials = new
                    AWSStaticCredentialsProvider(temporaryCredentials);
            AmazonConfigClient roleamazonConfigClient = (AmazonConfigClient) AmazonConfigClientBuilder.standard().withCredentials(rolecredentials)
                    .withRegion(Regions.US_EAST_2).build();


        PutConfigRuleRequest putConfigRuleRequest = new PutConfigRuleRequest();
        ConfigRule configRule = new ConfigRule();
        Source source = new Source();
        source.setOwner("CUSTOM_LAMBDA");
        source.setSourceIdentifier("arn:aws:lambda:us-east-2:Account A:function:TestLmabda");
        SourceDetail sourceDetail = new SourceDetail();     
        sourceDetail.setEventSource(EventSource.AwsConfig);
        sourceDetail.setMaximumExecutionFrequency(MaximumExecutionFrequency.TwentyFour_Hours);
        sourceDetail.setMessageType(MessageType.ScheduledNotification);
        source.setSourceDetails(Arrays.asList(sourceDetail));
        configRule.setSource(source);
        configRule.setConfigRuleName("TestCrossAcRule");
        putConfigRuleRequest.setConfigRule(configRule);
        PutConfigRuleResult putConfigRuleResult=amazonConfigRoleClient.putConfigRule(putConfigRuleRequest);
        logger.info("Put ConfigRuleResult is "+putConfigRuleResult);

It giving me error as

Exception in thread "main" com.amazonaws.services.config.model.InsufficientPermissionsException: The AWS Lambda function arn:aws:lambda:us-east-2:Account A:function:TestLmabda cannot be invoked. Check the specified function ARN, and check the function's permissions. (Service: AmazonConfig; Status Code: 400; Error Code: InsufficientPermissionsException; Request ID: 10d99a37-ba7b-4bdd-a7cd-941aa3287895)

Edit : -

Is this really correct way? Any other ways are also welcome... First thing is it really possible to use lambda function from one account to another account?

1
do you have vpc peering set up between these two accounts?Ashish Modi
No..but why do we need ?Dhanraj
because you are trying to acces or modify things from one account to another account. as far as I know apart from s3 no other service works if they are not in same vpc.Ashish Modi
Oh.. need to check.ThanksDhanraj
VPC peering is not needed, or even relevant. This is an API permissions issue.jarmod

1 Answers

0
votes

InsufficientPermissionsException Indicates one of the following errors:

For PutConfigRule, the rule cannot be created because the IAM role assigned to AWS Config lacks permissions to perform the config:Put* action.

For PutConfigRule, the AWS Lambda function cannot be invoked. Check the function ARN, and check the function's permissions.

For PutOrganizationConfigRule, organization config rule cannot be created because you do not have permissions to call IAM GetRole action or create a service linked role.

For PutConformancePack and PutOrganizationConformancePack, a conformance pack cannot be created because you do not have permissions:

To call IAM GetRole action or create a service linked role.

To read Amazon S3 bucket.

HTTP Status Code: 400

You are calling:

amazonConfigRoleClient.putConfigRule(putConfigRuleRequest);

But your IAM policy lacks

"config:Put*",

or you can use the AWS managed policy AWSConfigRole and attach it to the IAM role that you assign to AWS Config.

Moreover, Did you check the lambda ARN to find out if it is correct? I am seeing in the error log that you pasted this: arn:aws:lambda:us-east-2:Account A:function:TestLmabda . TestLmabda typo maybe is the issue?

Reference:

  1. https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/config/AmazonConfig.html#tagResource-com.amazonaws.services.config.model.TagResourceRequest-

  2. https://docs.aws.amazon.com/config/latest/APIReference/API_PutConfigRule.html

  3. https://docs.aws.amazon.com/config/latest/developerguide/iamrole-permissions.html