Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First version of trend-cloudone-onboard. #2

Merged
merged 29 commits into from
May 2, 2023
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
39352c3
First version of trend-cloudone-onboard.
raphabot Apr 6, 2023
9dae7b3
Updating to fix ash findings.
raphabot Apr 11, 2023
f7863e1
Merge branch 'main' into devel
raphabot Apr 11, 2023
b80c083
Adding the rule evaluation exceptions.
raphabot Apr 11, 2023
ff197ba
Adding the rule CKV_AWS_173 that I missed.
raphabot Apr 11, 2023
bf3b208
Moving Lambda Functions code to .py
raphabot Apr 12, 2023
17da702
Added all zips.
raphabot Apr 12, 2023
16d580c
Fixing Typos
raphabot Apr 12, 2023
8c6a8c8
Removing the zips.
raphabot Apr 12, 2023
4e2e2a2
Adding cfnresponse.py to the lambdas.
raphabot Apr 13, 2023
3920656
Improve the character limit issue.
raphabot Apr 13, 2023
4c6103c
Adding Custom Resource to grab the organizational trail.
raphabot Apr 14, 2023
4068a8f
Adding a ExistingBucketName parameter.
raphabot Apr 14, 2023
75e3a29
Adding ExistingCloudtrailBucketName to Parameters group.
raphabot Apr 14, 2023
8f10689
Reverting VERSION back to original value.
raphabot Apr 18, 2023
be7da11
Adding Vision One Enrollment Token
raphabot Apr 25, 2023
5748c17
Updating .taskcat.yaml
raphabot Apr 27, 2023
f2582ee
Merge branch 'main' into devel
kkvinjam Apr 27, 2023
22e0b61
Fixing typo
raphabot Apr 27, 2023
a56b15e
Moving to use CloudTrail ABI Submodule.
raphabot Apr 28, 2023
0c3ac1d
Removed submodule
raphabot Apr 28, 2023
b90828d
Removing CloudTrail ABI and making having a CloudTrail mandatory.
raphabot Apr 28, 2023
6fb8907
Adding the "!Ref" back.
raphabot Apr 28, 2023
128ca8e
Merge branch 'main' into devel
raphabot May 1, 2023
52846ac
Adding NoEcho to Vision One Auth token.
raphabot May 1, 2023
92baf35
Updating README.md
raphabot May 1, 2023
a086d28
Fixing taskcat.
raphabot May 2, 2023
243603c
Parameterizing Trend's AWS account id.
raphabot May 2, 2023
820bbd8
Merge branch 'main' into devel
raphabot May 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,16 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# taskcat
taskcat_outputs/
.taskcat/
.taskcat.secrets.yml
# since the zips are automatically generated, we don't want to check them in
lambda_functions/packages/

# General
.DS_Store

# Ash
aggregated_results.txt
Empty file added .gitmodules
Empty file.
27 changes: 10 additions & 17 deletions .taskcat.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
project:
name: update-me-to-project-repo-name
owner: [email protected]
package_lambda: false
name: cfn-abi-trend-cloudone
owner: [email protected] #We need a DL for this.
package_lambda: true
shorten_stack_name: true
regions:
- ap-northeast-1
- ap-northeast-2
Expand All @@ -14,20 +15,12 @@ project:
- us-west-1
- us-west-2
tests:
sample:
t1:
parameters:
Param1: 'Inputs to Stack'
# Examples: of other taskcat dynamic input parameters for more into see http://taskcat.io
#
# AvailabilityZones: $[taskcat_genaz_3]
# ByteValue: 1
# PasswordA: $[taskcat_genpass_8A]
# PasswordB: $[taskcat_genpass_32S]
# RandomNumber: $[taskcat_random-numbers]
# RandomString: $[taskcat_random-string]
# StackName: TestStack
# UUID: $[taskcat_genuuid]
#
CloudOneApiKey: $[taskcat_secrets_get_CloudOneApiKey]
raphabot marked this conversation as resolved.
Show resolved Hide resolved
VisionOneServiceToken: $[taskcat_secrets_get_VisionOneServiceToken]
QSS3BucketName: $[taskcat_autobucket]
QSS3KeyPrefix: $[taskcat_project_name]
regions:
- us-east-1
template: templates/sample-workload.template.yaml
template: templates/trend-cloudone-onboard/main.template.yaml
64 changes: 64 additions & 0 deletions lambda_functions/source/AWSConnectorCreateLambda/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""Custom Resource to add an AWS Account to Trend Cloud One Workload Security.

Version: 1.0

Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""
import json
import urllib3
import cfnresponse
import os

def lambda_handler(event, context):
print(event)
raphabot marked this conversation as resolved.
Show resolved Hide resolved

status = cfnresponse.SUCCESS
response_data = {}
physicalResourceId = None

accountId = os.environ['awsaccountid']
externalId = os.environ['externalid']
crossAccountRoleArn = os.environ['crossaccountrolearn']
cloudOneApiKey = event['ResourceProperties']['CloudOneApiKey']
cloudOneRegion = event['ResourceProperties']['CloudOneRegion']

headers = {
'api-version': 'v1',
'Authorization': 'ApiKey '+cloudOneApiKey+'',
'Content-Type': 'application/json'
}

http = urllib3.PoolManager()

try:
if event["RequestType"] == "Create" or event["RequestType"] == "Update":

url = 'https://workload.'+cloudOneRegion+'.cloudone.trendmicro.com/api/awsconnectors'

payload = json.dumps({
"displayName": accountId,
"accountId": accountId,
"crossAccountRoleArn": crossAccountRoleArn
})

encoded_payload = payload.encode("utf-8")
response = http.request("POST", url=url, headers=headers, body=encoded_payload)

response_json_data = json.loads(response.data.decode("utf-8"))
print(response_json_data)
physicalResourceId = str(response_json_data["ID"])
response_data = {"ID": str(response_json_data["ID"])}

else: # if event["RequestType"] == "Delete":
ID = event["PhysicalResourceId"]

url = 'https://workload.'+cloudOneRegion+'.cloudone.trendmicro.com/api/awsconnectors/'+ID
response = http.request("DELETE", url=url, headers=headers)
print(response.data.decode("utf-8"))

except Exception as exception:
print(exception)
status = cfnresponse.FAILED

cfnresponse.send(event, context, status, response_data, physicalResourceId)
47 changes: 47 additions & 0 deletions lambda_functions/source/AWSConnectorCreateLambda/cfnresponse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0

from __future__ import print_function
import urllib3
import json

SUCCESS = "SUCCESS"
FAILED = "FAILED"

http = urllib3.PoolManager()


def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False, reason=None):
responseUrl = event['ResponseURL']

print(responseUrl)

responseBody = {
'Status' : responseStatus,
'Reason' : reason or "See the details in CloudWatch Log Stream: {}".format(context.log_stream_name),
'PhysicalResourceId' : physicalResourceId or context.log_stream_name,
'StackId' : event['StackId'],
'RequestId' : event['RequestId'],
'LogicalResourceId' : event['LogicalResourceId'],
'NoEcho' : noEcho,
'Data' : responseData
}

json_responseBody = json.dumps(responseBody)

print("Response body:")
print(json_responseBody)

headers = {
'content-type' : '',
'content-length' : str(len(json_responseBody))
}

try:
response = http.request('PUT', responseUrl, headers=headers, body=json_responseBody)
print("Status code:", response.status)


except Exception as e:

print("send(..) failed executing http.request(..):", e)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# install the latest version
crhelper
raphabot marked this conversation as resolved.
Show resolved Hide resolved
61 changes: 61 additions & 0 deletions lambda_functions/source/AddAWSAccountToCloudOneFunction/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""Custom Resource to add an AWS Account to Trend Cloud One.

Version: 1.0

Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""
import json
import os
import urllib3
import cfnresponse

def lambda_handler(event, context):
status = cfnresponse.SUCCESS
response_data = {}
physicalResourceId = None
try:

cloudOneRoleArn = os.environ['CloudOneRoleArn']
cloudOneRegion = os.environ['CloudOneRegion']
cloudOneApiKey = os.environ['CloudOneApiKey']
raphabot marked this conversation as resolved.
Show resolved Hide resolved

headers = {
'api-version': 'v1',
'Authorization': 'ApiKey '+cloudOneApiKey+'',
'Content-Type': 'application/json'
}

http = urllib3.PoolManager()


if event["RequestType"] == "Create" or event["RequestType"] == "Update":

url = 'https://cloudaccounts.'+cloudOneRegion+'.cloudone.trendmicro.com/api/cloudaccounts/aws'

payload = json.dumps({
'roleARN': cloudOneRoleArn
})
encoded_payload = payload.encode("utf-8")
print(url)
response = http.request("POST", url=url, headers=headers, body=encoded_payload)
print(response)
response_json_data = json.loads(response.data.decode("utf-8"))
print(response_json_data)
physicalResourceId = response_json_data["id"]
response_data = {"ID": response_json_data["id"]}

else: # if event["RequestType"] == "Delete":
id = event["PhysicalResourceId"]

url = 'https://cloudaccounts.'+cloudOneRegion+'.cloudone.trendmicro.com/api/cloudaccounts/aws/' + id

print(url)
response = http.request("DELETE", url=url, headers=headers)
print(response)

except Exception as exception:
print(exception)
status = cfnresponse.FAILED

cfnresponse.send(event, context, status, response_data, physicalResourceId)
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0

from __future__ import print_function
import urllib3
import json

SUCCESS = "SUCCESS"
FAILED = "FAILED"

http = urllib3.PoolManager()


def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False, reason=None):
responseUrl = event['ResponseURL']

print(responseUrl)

responseBody = {
'Status' : responseStatus,
'Reason' : reason or "See the details in CloudWatch Log Stream: {}".format(context.log_stream_name),
'PhysicalResourceId' : physicalResourceId or context.log_stream_name,
'StackId' : event['StackId'],
'RequestId' : event['RequestId'],
'LogicalResourceId' : event['LogicalResourceId'],
'NoEcho' : noEcho,
'Data' : responseData
}

json_responseBody = json.dumps(responseBody)

print("Response body:")
print(json_responseBody)

headers = {
'content-type' : '',
'content-length' : str(len(json_responseBody))
}

try:
response = http.request('PUT', responseUrl, headers=headers, body=json_responseBody)
print("Status code:", response.status)


except Exception as e:

print("send(..) failed executing http.request(..):", e)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# install the latest version
crhelper
50 changes: 50 additions & 0 deletions lambda_functions/source/GetCloudOneRegionAndAccountFunction/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Custom Resource to get the Trend Cloud One region and account id.

Version: 1.0

Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""
import json
import os
import urllib3
import cfnresponse

def lambda_handler(event, context):
status = cfnresponse.SUCCESS
response_data = {}
physicalResourceId = None
try:

if event["RequestType"] == "Create" or event["RequestType"] == "Update":
cloudOneApiKey = os.environ['CloudOneApiKey']
raphabot marked this conversation as resolved.
Show resolved Hide resolved
apiKeyId = cloudOneApiKey.split(':')[0]

url = 'https://accounts.cloudone.trendmicro.com/api/apikeys/' + apiKeyId

headers = {
'api-version': 'v1',
'Authorization': 'ApiKey '+cloudOneApiKey+'',
'Content-Type': 'application/json'
}

http = urllib3.PoolManager()
print(url)
response = http.request("GET", url=url, headers=headers)
print(response)
response_json_data = json.loads(response.data.decode("utf-8"))
print(response_json_data)
urn = response_json_data["urn"]
region = urn.split(":")[3]
accountId = urn.split(":")[4]
physicalResourceId = response_json_data["urn"]
response_data = {"AccountId": accountId, "Region": region}

else: # if event["RequestType"] == "Delete":
physicalResourceId = event["PhysicalResourceId"]

except Exception as e:
print(e)
status = cfnresponse.FAILED

cfnresponse.send(event, context, status, response_data, physicalResourceId)
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0

from __future__ import print_function
import urllib3
import json

SUCCESS = "SUCCESS"
FAILED = "FAILED"

http = urllib3.PoolManager()


def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False, reason=None):
responseUrl = event['ResponseURL']

print(responseUrl)

responseBody = {
'Status' : responseStatus,
'Reason' : reason or "See the details in CloudWatch Log Stream: {}".format(context.log_stream_name),
'PhysicalResourceId' : physicalResourceId or context.log_stream_name,
'StackId' : event['StackId'],
'RequestId' : event['RequestId'],
'LogicalResourceId' : event['LogicalResourceId'],
'NoEcho' : noEcho,
'Data' : responseData
}

json_responseBody = json.dumps(responseBody)

print("Response body:")
print(json_responseBody)

headers = {
'content-type' : '',
'content-length' : str(len(json_responseBody))
}

try:
response = http.request('PUT', responseUrl, headers=headers, body=json_responseBody)
print("Status code:", response.status)


except Exception as e:

print("send(..) failed executing http.request(..):", e)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# install the latest version
crhelper
Loading