in source/Orchestrator/exec_ssm_doc.py [0:0]
def lambda_handler(event, context):
# Expected:
# {
# Finding: {
# AwsAccountId: <aws account>,
# ControlId: string
# },
# RemediationRole: string,
# AutomationDocId: string.
# SSMExecution: json data
# }
# Returns:
# {
# status: { 'UNKNOWN'| string },
# message: { '' | string },
# executionid: { '' | string }
# }
answer = utils.StepFunctionLambdaAnswer()
LOGGER.info(event)
if "Finding" not in event or \
"EventType" not in event:
answer.update({
'status':'ERROR',
'message':'Missing required data in request'
})
LOGGER.error(answer.message)
return answer.json()
finding = Finding(event['Finding'])
automation_doc = event['AutomationDocument']
alt_workflow_doc = event.get('Workflow',{}).get('WorkflowDocument', None)
alt_workflow_account = event.get('Workflow',{}).get('WorkflowAccount', None)
alt_workflow_role = event.get('Workflow',{}).get('WorkflowRole', None)
alt_workflow_config = event.get('Workflow',{}).get('WorkflowConfig', None)
remote_workflow_doc = alt_workflow_doc if alt_workflow_doc else event['AutomationDocument']['AutomationDocId']
execution_account = alt_workflow_account if alt_workflow_account else automation_doc['AccountId']
execution_region = AWS_REGION if alt_workflow_account else automation_doc.get('ResourceRegion', '')
if "SecurityStandard" not in automation_doc or \
"ControlId" not in automation_doc or \
"AccountId" not in automation_doc:
answer.update({
'status':'ERROR',
'message':'Missing AutomationDocument data in request: ' + json.dumps(automation_doc)
})
LOGGER.error(answer.message)
return answer.json()
# Execution role will be, in order of precedence
# 1) remote_workflow_role
# 2) Derived from standard and control if it exists
# 3) Orchestrator Member role
#
# In most cases the Orchestrator Member role is used, and it passes
# the value in RemediationRole as the AutomationExectutionRole
remediation_role = SOLUTION_ID + '-SHARR-Orchestrator-Member' # default
if alt_workflow_doc and alt_workflow_role:
remediation_role = alt_workflow_role
elif lambda_role_exists(execution_account, automation_doc['RemediationRole']):
remediation_role = automation_doc['RemediationRole']
print(f'Using role {remediation_role} to execute {remote_workflow_doc} in {execution_account} {execution_region}')
remediation_role_arn = f'arn:{AWS_PARTITION}:iam::{execution_account}:role/{remediation_role}'
print(f'ARN: {remediation_role_arn}')
ssm = _get_ssm_client(execution_account, remediation_role, execution_region)
ssm_parameters = {
"Finding": [
json.dumps(event['Finding'])
],
"AutomationAssumeRole": [
remediation_role_arn
]
}
if remote_workflow_doc != automation_doc['AutomationDocId']:
ssm_parameters["RemediationDoc"] = [automation_doc['AutomationDocId']]
ssm_parameters["Workflow"] = [json.dumps(event.get('Workflow', {}))]
exec_id = ssm.start_automation_execution(
# Launch SSM Doc via Automation
DocumentName=remote_workflow_doc,
Parameters=ssm_parameters
)['AutomationExecutionId']
answer.update({
'status':'QUEUED',
'message': f'{exec_id}: {automation_doc["ControlId"]} remediation was successfully invoked via AWS Systems Manager in account {automation_doc["AccountId"]} {execution_region}',
'executionid': exec_id,
'executionregion': execution_region,
'executionaccount': execution_account
})
LOGGER.info(answer.message)
return answer.json()