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?