diff --git a/bin/asff-builder b/bin/asff-builder new file mode 100755 index 0000000..5609569 --- /dev/null +++ b/bin/asff-builder @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +import argparse +import inspect +import sys + +from asff import AmazonSecurityFinding, ValidationError + + +def convert_function_signature_to_args(function_name=AmazonSecurityFinding.from_kwargs): + """ + Function to generate argparse-compatible arguments from function parameters & docstrings. + """ + sig = inspect.signature(function_name) + doc = inspect.getdoc(function_name) + + params = sig.parameters + doc_lines = doc.splitlines() + + args = {} + + for name, param in params.items(): + if name in ["kwargs"]: + continue + + help_text = None + for line in doc_lines: + if f"{name}:" in line: + help_text = line.split(" ", 2)[-1] + + required = False + if param.default is param.empty: + required = True + default = None + else: + default = param.default + + nargs = None + if "list" in str(param.annotation).lower(): + nargs = "+" + + args[name] = { + "help": help_text, + "default": default, + "nargs": nargs, + "required": required, + } + + return args + + +def parse_arguments(): + + func_args = convert_function_signature_to_args() + + parser = argparse.ArgumentParser( + description="Simple tool to build ASFF findings from command line" + ) + for name, func_arg in func_args.items(): + arg_name = f"--{name}" + parser.add_argument(arg_name, **func_arg) + + return parser.parse_args() + + +def main(): + args = parse_arguments() + + try: + f = AmazonSecurityFinding.from_kwargs(**vars(args)) + except ValidationError as e: + print(e, file=sys.stderr) + exit(1) + + print(f.to_json()) + + +if __name__ == "__main__": + main() diff --git a/bin/asff-send b/bin/asff-send new file mode 100755 index 0000000..b701304 --- /dev/null +++ b/bin/asff-send @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +import argparse +import os +import sys +import boto3 + +from asff.constants import DEFAULT_REGION +from asff import AmazonSecurityFinding + +DEFAULT_PROFILE = os.environ.get("AWS_PROFILE", "default") + + +def send_finding_to_securityhub(finding, session): + client = session.client("securityhub") + + client.batch_import_findings(Findings=[finding]) + + +def parse_aguments(): + parser = argparse.ArgumentParser( + description="Utility to send ASFF findings to Security Hub easily from command line" + ) + + parser.add_argument("--region", default=DEFAULT_REGION, help="AWS region to use") + parser.add_argument("--profile", default=DEFAULT_PROFILE, help="AWS profile to use") + parser.add_argument( + "file", + type=argparse.FileType("r"), + default=sys.stdin, + ) + + return parser.parse_args() + + +def main(): + + args = parse_aguments() + + finding_data = args.file.read() + finding = AmazonSecurityFinding.from_json(data=finding_data) + + session = boto3.session.Session(profile_name=args.profile, region_name=args.region) + + try: + send_finding_to_securityhub(finding=finding.to_dict(), session=session) + except Exception as e: + print(e.args[0]) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/docs/user-guide/cli.md b/docs/user-guide/cli.md new file mode 100644 index 0000000..199561f --- /dev/null +++ b/docs/user-guide/cli.md @@ -0,0 +1,156 @@ +# CLI utilities + +python-asff comes with command line tools that make working with ASFF findings easier. + +## asff-builder + +_asff-builder_ allows the user to build ASFF finding from executing it from the command line. It is meant to be used mostly by the user or from the scripts. +Example use cases include running it from scripts and outputt ing the finding in ASFF. + +### Available options + +```shell +usage: asff-builder [-h] --aws_account_id AWS_ACCOUNT_ID --types TYPES + [TYPES ...] --title TITLE --description DESCRIPTION + [--resources RESOURCES [RESOURCES ...]] [--id ID] + [--schema_version SCHEMA_VERSION] [--severity SEVERITY] + [--product_name PRODUCT_NAME] + [--product_version PRODUCT_VERSION] [--region REGION] + [--record_state RECORD_STATE] + [--workflow_status WORKFLOW_STATUS] + [--generator_id GENERATOR_ID] [--created_at CREATED_AT] + [--updated_at UPDATED_AT] + +Simple tool to build ASFF findings from command line + +optional arguments: + -h, --help show this help message and exit + --aws_account_id AWS_ACCOUNT_ID + The AWS account ID that the finding applies to. + --types TYPES [TYPES ...] + Finding type that classifies the finding + --title TITLE A finding's title. + --description DESCRIPTION + A finding's description. + --resources RESOURCES [RESOURCES ...] + A set of resource data types that describe the + resources that the finding refers to. + --id ID The identifier for the solution-specific component + that generated a finding. + --schema_version SCHEMA_VERSION + The schema version that a finding is formatted for + --severity SEVERITY A finding's severity. + --product_name PRODUCT_NAME + Product name that generated the finding + --product_version PRODUCT_VERSION + Product version that generated the finding + --region REGION AWS region where the finding was found + --record_state RECORD_STATE + The record state of a finding. + --workflow_status WORKFLOW_STATUS + Provides information about the status of the + investigation into a finding. + --generator_id GENERATOR_ID + The identifier for the solution-specific component + that generated a finding. + --created_at CREATED_AT + Indicates when the potential security issue captured + by a finding was created. + --updated_at UPDATED_AT + Indicates when the finding provider last updated the + finding record. + +``` + +### Examples + +#### Building ASFF JSON from the command line + +```shell +% asff-builder --aws_account_id 1242334534 \ + --types 'TTPs/Defense Evasion' \ + --title 'Defense Evasion detected' \ + --description 'Defense Evastion detected on AWS account 1242334534' \ + --severity HIGH \ + --generator_id defense-evasion-detector +{ + "AwsAccountId": "1242334534", + "CreatedAt": "2021-04-09T20:30:29+00:00", + "Description": "Defense Evastion detected on AWS account 1242334534", + "GeneratorId": "defense-evasion-detector", + "Id": "c096c7ed402f02a78ee3dbecee25711595fd0bfbc2c77449d25fc173bf66f06d", + "ProductArn": "arn:aws:securityhub:eu-west-1:1242334534:product/1242334534/default", + "ProductFields": { + "ProviderName": "default", + "ProviderVersion": "1.0.0" + }, + "RecordState": "ACTIVE", + "Resources": [ + { + "Id": "AWS::::Account:1242334534", + "Partition": "aws", + "Region": "eu-west-1", + "Type": "AwsAccount" + } + ], + "SchemaVersion": "2018-10-08", + "Severity": { + "Label": "HIGH" + }, + "Title": "Defense Evasion detected", + "Types": [ + "TTPs/Defense Evasion" + ], + "UpdatedAt": "2021-04-09T20:30:29+00:00", + "Workflow": { + "Status": "NEW" + } +} +``` + +## asff-send + +_asff-send_ is a utility to send ASFF findings directly to the Security Hub from the command line. It supports reading findings from a file or standard input, which is suitable for usage in shell pipelines. + +### Available options + +```shell +usage: asff-send [-h] [--region REGION] [--profile PROFILE] file + +Utility to send ASFF findings to Security Hub easily from command line + +positional arguments: + file + +optional arguments: + -h, --help show this help message and exit + --region REGION AWS region to use + --profile PROFILE AWS profile to use + +``` + +### Examples + +#### Sending finding to Security Hub from a file + +```shell +% asff-builder --aws_account_id 1242334534 \ + --types 'TTPs/Defense Evasion' \ + --title 'Defense Evasion detected' \ + --description 'Defense Evastion detected on AWS account 1242334534' \ + --severity HIGH \ + --generator_id defense-evasion-detector > finding.json +% asff-send finding.json +``` + +#### Sending finding to Security Hub from standard input + +```shell +% asff-builder --aws_account_id 1242334534 \ + --types 'TTPs/Defense Evasion' \ + --title 'Defense Evasion detected' \ + --description 'Defense Evastion detected on AWS account 1242334534' \ + --severity HIGH \ + --generator_id defense-evasion-detector | \ + asff-send --region eu-west-2 - +``` \ No newline at end of file diff --git a/docs/user-guide/index.rst b/docs/user-guide/index.rst index e5058b6..00fc71f 100644 --- a/docs/user-guide/index.rst +++ b/docs/user-guide/index.rst @@ -4,4 +4,5 @@ User guide .. toctree:: :maxdepth: 1 - installation \ No newline at end of file + installation + cli \ No newline at end of file