Skip to content

Commit 25e5f44

Browse files
authored
Merge pull request #7 from aquasecurity/update-credentials
feat: Trigger update credentials on API key change
2 parents d370749 + 80fdf95 commit 25e5f44

6 files changed

Lines changed: 245 additions & 82 deletions

File tree

modules/single/main.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ module "trigger" {
5454
aqua_api_key = var.aqua_api_key
5555
aqua_api_secret = var.aqua_api_secret
5656
aqua_autoconnect_url = var.aqua_autoconnect_url
57+
aqua_cspm_url = var.aqua_cspm_url
58+
aws_account_id = local.aws_account_id
5759
aqua_session_id = var.aqua_session_id
5860
cspm_role_arn = module.lambda.cspm_role_arn
5961
cspm_external_id = module.lambda.cspm_external_id
Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
import json
32
import urllib3
43
import hashlib
@@ -7,7 +6,6 @@
76

87
def handler(event, context):
98
cspm_url = event.get('ApiUrl')
10-
ac_url = event.get('AutoConnectApiUrl')
119
aqua_api_key = event.get('AquaApiKey')
1210
aqua_secret = event.get('AquaSecretKey')
1311
role_arn = event.get('RoleArn')
@@ -17,38 +15,59 @@ def handler(event, context):
1715
aws_account_id = context.invoked_function_arn.split(":")[4]
1816

1917
try:
20-
print('creating a new cspm key')
18+
cspm_key_id = get_cspm_key_id(aqua_api_key, aqua_secret, cspm_url, role_arn)
19+
is_already_cspm_client = True
20+
print(f'Existing CSPM key found: {cspm_key_id}')
21+
except Exception as key_not_found:
22+
print(f'No existing key found')
23+
print('Creating new CSPM key')
2124
is_already_cspm_client = create_cspm_key(
22-
cspm_url, ac_url, aqua_api_key, aqua_secret,
25+
cspm_url, aqua_api_key, aqua_secret,
2326
role_arn, external_id, group, account_id, aws_account_id
2427
)
25-
return {"IsAlreadyCSPMClient": is_already_cspm_client}
2628

27-
except Exception as e:
28-
print(f"error: {e}")
29-
return {"error": e}
29+
return {"IsAlreadyCSPMClient": is_already_cspm_client}
3030

3131

3232
def get_signature(aqua_secret, tstmp, path, method, body):
3333
enc = tstmp + method + path + body
34-
print(f'enc: {enc}')
3534
enc_b = bytes(enc, 'utf-8')
3635
secret = bytes(aqua_secret, 'utf-8')
3736
sig = hmac.new(secret, enc_b, hashlib.sha256).hexdigest()
3837
return sig
3938

39+
4040
def http_request(url, headers, method, body=None):
41-
http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED')
41+
if body is None:
42+
body = {}
43+
44+
http = urllib3.PoolManager(cert_reqs='CERT_NONE')
4245

4346
try:
4447
response = http.request(method, url, body=body, headers=headers)
45-
data = json.loads(response.data.decode('utf-8'))
48+
return response
4649
except Exception as e:
47-
print(f'could not parse event data; {e}')
48-
data = {}
49-
return data
50+
print('Failed to send http request; {}'.format(e))
51+
return None
52+
53+
54+
def get_cspm_key_id(aqua_api_key, aqua_secret, cspm_url, role_arn):
55+
tstmp = str(int(time.time() * 1000))
56+
sig = get_signature(aqua_secret, tstmp, "/v2/keys", "GET", '')
57+
headers = {"X-API-Key": aqua_api_key, "X-Signature": sig, "X-Timestamp": tstmp}
58+
59+
response = http_request(cspm_url + "/v2/keys", headers, "GET")
60+
json_object = json.loads(response.data)
61+
if response.status not in (200, 201):
62+
raise ValueError(f"Failed to get cspm key id for {role_arn}: {response.message}")
63+
64+
for key in json_object['data']:
65+
if key['role_arn'] == role_arn:
66+
return key['id']
67+
raise Exception("key not found")
68+
5069

51-
def create_cspm_key(cspm_url, ac_url, aqua_api_key, aqua_secret, role_arn, external_id, group, account_id, aws_account_id):
70+
def create_cspm_key(cspm_url, aqua_api_key, aqua_secret, role_arn, external_id, group, account_id, aws_account_id):
5271
body = {
5372
"name": account_id,
5473
"cloud": "aws",
@@ -58,7 +77,7 @@ def create_cspm_key(cspm_url, ac_url, aqua_api_key, aqua_secret, role_arn, exter
5877
"group_id": group
5978
}
6079

61-
print(f'body: {body}')
80+
print(f'CSPM body: {body}')
6281
tstmp = str(int(time.time() * 1000))
6382
jsonbody = json.dumps(body, separators=(',', ':'))
6483
sig = get_signature(aqua_secret, tstmp, "/v2/keys", "POST", jsonbody)
@@ -69,12 +88,12 @@ def create_cspm_key(cspm_url, ac_url, aqua_api_key, aqua_secret, role_arn, exter
6988
}
7089

7190
response = http_request(cspm_url + '/v2/keys', headers, "POST", jsonbody)
72-
print(f'response: {response}')
73-
if response.get('status', 0) != 200 and response.get('status', 0) != 201:
74-
raise Exception(response.get('message', "Internal server error"))
91+
if response.status not in (200, 201):
92+
raise Exception("Failed to create cspm key id", response.data.decode("utf-8"))
7593

94+
print(f'CSPM response: {response.data.decode("utf-8")}')
7695
is_already_cspm_client = False
77-
if response.get('status', 0) == 200:
96+
if response.status == 200:
7897
is_already_cspm_client = True
7998

8099
return is_already_cspm_client

modules/single/modules/lambda/main.tf

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ resource "aws_iam_role" "cspm_lambda_execution_role" {
3636
name = "aqua-autoconnect-cspm-lambda-execution-role-${var.random_id}"
3737
}
3838

39-
# Create generate CSPM external id lambda function
40-
resource "aws_lambda_function" "generate_cspm_external_id_function" {
39+
# Create generate Volume Scan external id lambda function
40+
resource "aws_lambda_function" "generate_volscan_external_id_function" {
4141
architectures = ["x86_64"]
42-
description = "Generate CSPM External ID"
43-
function_name = "aqua-autoconnect-generate-cspm-external-id-function-${var.random_id}"
42+
description = "Generate Volume Scanning External ID"
43+
function_name = "aqua-autoconnect-generate-volscan-external-id-function-${var.random_id}"
4444
handler = "generate_external_id.handler"
4545
role = aws_iam_role.cspm_lambda_execution_role.arn
4646
runtime = "python3.12"
@@ -52,22 +52,25 @@ resource "aws_lambda_function" "generate_cspm_external_id_function" {
5252
}
5353
}
5454

55-
# Invoking generate CSPM external id lambda function
56-
resource "aws_lambda_invocation" "generate_cspm_external_id_function" {
57-
function_name = aws_lambda_function.generate_cspm_external_id_function.function_name
55+
# Invoking generate Volume Scan external id lambda function
56+
resource "aws_lambda_invocation" "generate_volscan_external_id_function" {
57+
function_name = aws_lambda_function.generate_volscan_external_id_function.function_name
5858
input = jsonencode({
5959
ApiUrl = var.aqua_cspm_url
6060
AutoConnectApiUrl = var.aqua_autoconnect_url
6161
AquaApiKey = var.aqua_api_key
6262
AquaSecretKey = var.aqua_api_secret
6363
})
64+
triggers = {
65+
always_run = timestamp()
66+
}
6467
}
6568

66-
# Create generate Volume Scan external id lambda function
67-
resource "aws_lambda_function" "generate_volscan_external_id_function" {
69+
# Create generate CSPM external id lambda function
70+
resource "aws_lambda_function" "generate_cspm_external_id_function" {
6871
architectures = ["x86_64"]
69-
description = "Generate Volume Scanning External ID"
70-
function_name = "aqua-autoconnect-generate-volscan-external-id-function-${var.random_id}"
72+
description = "Generate CSPM External ID"
73+
function_name = "aqua-autoconnect-generate-cspm-external-id-function-${var.random_id}"
7174
handler = "generate_external_id.handler"
7275
role = aws_iam_role.cspm_lambda_execution_role.arn
7376
runtime = "python3.12"
@@ -79,15 +82,19 @@ resource "aws_lambda_function" "generate_volscan_external_id_function" {
7982
}
8083
}
8184

82-
# Invoking generate Volume Scan external id lambda function
83-
resource "aws_lambda_invocation" "generate_volscan_external_id_function" {
84-
function_name = aws_lambda_function.generate_volscan_external_id_function.function_name
85+
# Invoking generate CSPM external id lambda function
86+
resource "aws_lambda_invocation" "generate_cspm_external_id_function" {
87+
function_name = aws_lambda_function.generate_cspm_external_id_function.function_name
8588
input = jsonencode({
8689
ApiUrl = var.aqua_cspm_url
8790
AutoConnectApiUrl = var.aqua_autoconnect_url
8891
AquaApiKey = var.aqua_api_key
8992
AquaSecretKey = var.aqua_api_secret
9093
})
94+
triggers = {
95+
always_run = timestamp()
96+
}
97+
depends_on = [aws_lambda_invocation.generate_volscan_external_id_function]
9198
}
9299

93100
# Create Agentless role
@@ -429,7 +436,10 @@ resource "aws_iam_role" "cspm_role" {
429436
# Creating a sleep for 30s between CSPM role and CSPM key lambda function
430437
resource "time_sleep" "sleep" {
431438
create_duration = "30s"
432-
depends_on = [aws_iam_role.cspm_role]
439+
triggers = {
440+
cspm_assume_role_policy = aws_iam_role.cspm_role.assume_role_policy
441+
}
442+
depends_on = [aws_iam_role.cspm_role]
433443
}
434444

435445
# Create CSPM key lambda function
@@ -452,14 +462,16 @@ resource "aws_lambda_function" "create_cspm_key_function" {
452462
resource "aws_lambda_invocation" "create_cspm_key_function" {
453463
function_name = aws_lambda_function.create_cspm_key_function.function_name
454464
input = jsonencode({
455-
ApiUrl = var.aqua_cspm_url
456-
AutoConnectApiUrl = var.aqua_autoconnect_url
457-
AquaApiKey = var.aqua_api_key
458-
AquaSecretKey = var.aqua_api_secret
459-
RoleArn = aws_iam_role.cspm_role.arn
460-
ExternalId = local.cspm_external_id
461-
AccountId = tostring(var.aws_account_id)
462-
GroupId = var.aqua_cspm_group_id
465+
ApiUrl = var.aqua_cspm_url
466+
AquaApiKey = var.aqua_api_key
467+
AquaSecretKey = var.aqua_api_secret
468+
RoleArn = aws_iam_role.cspm_role.arn
469+
ExternalId = local.cspm_external_id
470+
AccountId = tostring(var.aws_account_id)
471+
GroupId = var.aqua_cspm_group_id
463472
})
473+
triggers = {
474+
always_run = timestamp()
475+
}
464476
depends_on = [time_sleep.sleep]
465-
}
477+
}

0 commit comments

Comments
 (0)