From 0aeae6416ebc2364a5a818f0e42c8da681b22ff2 Mon Sep 17 00:00:00 2001 From: Uchinda Padmaperuma <89894943+uchinda-sph@users.noreply.github.com> Date: Tue, 28 Feb 2023 11:13:44 +0800 Subject: [PATCH 1/3] removing local.external_id --- data.tf | 8 ++++---- lambda.tf | 2 +- locals.tf | 1 - src/lambda_function/index.py | 12 ++++++++---- src/lambda_function/lambda_function.zip | Bin 12060035 -> 12060068 bytes 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/data.tf b/data.tf index 30381b7..45b559e 100644 --- a/data.tf +++ b/data.tf @@ -235,7 +235,7 @@ data "aws_iam_policy_document" "aqua_cspm_custom_trust" { test = "StringEquals" variable = "sts:ExternalId" values = [ - local.external_id, + jsondecode(aws_lambda_invocation.external_id.result)["ExternalId"], ] } @@ -264,7 +264,7 @@ data "aws_iam_policy_document" "aqua_cspm_custom_trust" { test = "StringEquals" variable = "sts:ExternalId" values = [ - local.external_id, + jsondecode(aws_lambda_invocation.external_id.result)["ExternalId"], ] } @@ -293,7 +293,7 @@ data "aws_iam_policy_document" "aqua_cspm_custom_trust" { test = "StringEquals" variable = "sts:ExternalId" values = [ - local.external_id, + jsondecode(aws_lambda_invocation.external_id.result)["ExternalId"], ] } @@ -322,7 +322,7 @@ data "aws_iam_policy_document" "aqua_cspm_custom_trust" { test = "StringEquals" variable = "sts:ExternalId" values = [ - local.external_id, + jsondecode(aws_lambda_invocation.external_id.result)["ExternalId"], ] } diff --git a/lambda.tf b/lambda.tf index a7ee7ab..1a1217a 100644 --- a/lambda.tf +++ b/lambda.tf @@ -38,7 +38,7 @@ resource "aws_lambda_invocation" "onboarding" { input = jsonencode({ ResourceProperties = { Secret = local.secret_name, - ExtId = local.external_id, + ExtId = jsondecode(aws_lambda_invocation.external_id.result)["ExternalId"], Group = var.aqua_group_name, RoleArn = aws_iam_role.aqua_cspm.arn, AccId = data.aws_caller_identity.current.account_id diff --git a/locals.tf b/locals.tf index 740addd..e8d5a6b 100644 --- a/locals.tf +++ b/locals.tf @@ -3,7 +3,6 @@ locals { secret_name = "/aquacspm/secret-cspm" - external_id = jsondecode(aws_lambda_invocation.external_id.result)["ExternalId"] # public_ip = "13.215.18.141/32" aqua_cspm_role_policy_arns = [ diff --git a/src/lambda_function/index.py b/src/lambda_function/index.py index 5978c9a..cff5fdb 100644 --- a/src/lambda_function/index.py +++ b/src/lambda_function/index.py @@ -25,7 +25,8 @@ def lambda_handler(event, ctxt): aqua_secret = conf['aqua_secret'] except Exception as e: LOGGER.error('Error retrieving Keys: {e}') - return json.dumps({'status': 'FAILED', 'message': 'Error retrieving Keys'}) + failRetKey = {'status': 'FAILED', 'message': 'Error retrieving Keys'} + return failRetKey if event['LogicalResourceId'] == 'ExternalIDInvoke': LOGGER.info('ExtID creation started :{}'.format(event)) @@ -35,7 +36,8 @@ def lambda_handler(event, ctxt): return resData except Exception as e: LOGGER.error(e) - return json.dumps({'status': 'FAILED', 'message': str(e)}) + failExtID = {'status': 'FAILED', 'message': str(e)} + return failExtID elif event['LogicalResourceId'] == 'OnboardingInvoke': LOGGER.info('Onboarding started :{}'.format(event)) @@ -49,10 +51,12 @@ def lambda_handler(event, ctxt): register(aqua_url, aqua_api_key, aqua_secret, acc, role_arn, extid, g_id) LOGGER.info(f'Account registered {acc}') onbData = {'AccountId': acc, 'Registered': True} - return json.dumps({'status': 'SUCCESS', 'data': onbData}) + sucMsg = {'status': 'SUCCESS', 'data': onbData} + return sucMsg except Exception as e: LOGGER.error(e) - return json.dumps({'status': 'FAILED', 'message': str(e)}) + errMsg = {'status': 'FAILED', 'message': str(e)} + return errMsg def get_conf(secret): diff --git a/src/lambda_function/lambda_function.zip b/src/lambda_function/lambda_function.zip index f31cd90f8d25f0b7dba99ad54b09b44f941c82f6..4f37b23ee148216f72edc36d30e042b92d7980e4 100644 GIT binary patch delta 4684 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 LsC5Q;^fLZGRL-UJ From af3874867ee796979ca80b3e4acbb30b81514cdd Mon Sep 17 00:00:00 2001 From: Uchinda Padmaperuma <89894943+uchinda-sph@users.noreply.github.com> Date: Tue, 28 Feb 2023 11:54:16 +0800 Subject: [PATCH 2/3] add conditon for local external_id --- data.tf | 8 ++++---- lambda.tf | 2 +- locals.tf | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/data.tf b/data.tf index 45b559e..30381b7 100644 --- a/data.tf +++ b/data.tf @@ -235,7 +235,7 @@ data "aws_iam_policy_document" "aqua_cspm_custom_trust" { test = "StringEquals" variable = "sts:ExternalId" values = [ - jsondecode(aws_lambda_invocation.external_id.result)["ExternalId"], + local.external_id, ] } @@ -264,7 +264,7 @@ data "aws_iam_policy_document" "aqua_cspm_custom_trust" { test = "StringEquals" variable = "sts:ExternalId" values = [ - jsondecode(aws_lambda_invocation.external_id.result)["ExternalId"], + local.external_id, ] } @@ -293,7 +293,7 @@ data "aws_iam_policy_document" "aqua_cspm_custom_trust" { test = "StringEquals" variable = "sts:ExternalId" values = [ - jsondecode(aws_lambda_invocation.external_id.result)["ExternalId"], + local.external_id, ] } @@ -322,7 +322,7 @@ data "aws_iam_policy_document" "aqua_cspm_custom_trust" { test = "StringEquals" variable = "sts:ExternalId" values = [ - jsondecode(aws_lambda_invocation.external_id.result)["ExternalId"], + local.external_id, ] } diff --git a/lambda.tf b/lambda.tf index 1a1217a..a7ee7ab 100644 --- a/lambda.tf +++ b/lambda.tf @@ -38,7 +38,7 @@ resource "aws_lambda_invocation" "onboarding" { input = jsonencode({ ResourceProperties = { Secret = local.secret_name, - ExtId = jsondecode(aws_lambda_invocation.external_id.result)["ExternalId"], + ExtId = local.external_id, Group = var.aqua_group_name, RoleArn = aws_iam_role.aqua_cspm.arn, AccId = data.aws_caller_identity.current.account_id diff --git a/locals.tf b/locals.tf index e8d5a6b..1832661 100644 --- a/locals.tf +++ b/locals.tf @@ -3,6 +3,7 @@ locals { secret_name = "/aquacspm/secret-cspm" + external_id = jsondecode(aws_lambda_invocation.external_id.result)["status"] == "FAILED" ? jsondecode(aws_lambda_invocation.external_id.result)["message"] : jsondecode(aws_lambda_invocation.external_id.result)["ExternalId"] # public_ip = "13.215.18.141/32" aqua_cspm_role_policy_arns = [ From 313beed91dad83a7e6d1ca54db1f73aac8e70c33 Mon Sep 17 00:00:00 2001 From: Uchinda Padmaperuma <89894943+uchinda-sph@users.noreply.github.com> Date: Tue, 28 Feb 2023 12:30:08 +0800 Subject: [PATCH 3/3] update the code to retry --- src/lambda_function/index.py | 19 +++++++++++-------- src/lambda_function/lambda_function.zip | Bin 12060068 -> 12060115 bytes 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/lambda_function/index.py b/src/lambda_function/index.py index cff5fdb..70e06bc 100644 --- a/src/lambda_function/index.py +++ b/src/lambda_function/index.py @@ -30,14 +30,17 @@ def lambda_handler(event, ctxt): if event['LogicalResourceId'] == 'ExternalIDInvoke': LOGGER.info('ExtID creation started :{}'.format(event)) - try: - extid = get_ext_id(aqua_url, aqua_api_key, aqua_secret) - resData = {'ExternalId': extid} - return resData - except Exception as e: - LOGGER.error(e) - failExtID = {'status': 'FAILED', 'message': str(e)} - return failExtID + max_attempts = 3 + for i in range(max_attempts): + try: + extid = get_ext_id(aqua_url, aqua_api_key, aqua_secret) + resData = {'ExternalId': extid} + return resData + except Exception as e: + LOGGER.error(e) + if i == max_attempts - 1: + failExtID = {'status': 'FAILED', 'message': str(e)} + return failExtID elif event['LogicalResourceId'] == 'OnboardingInvoke': LOGGER.info('Onboarding started :{}'.format(event)) diff --git a/src/lambda_function/lambda_function.zip b/src/lambda_function/lambda_function.zip index 4f37b23ee148216f72edc36d30e042b92d7980e4..1ec40bcb636648c6d37ff408548f714d44b3d5ce 100644 GIT binary patch delta 4665 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 delta 4692 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