.. awsfindingsmanagerlib documentation master file, created by sphinx-quickstart on 2023-11-21. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. =================== awsfindingsmanagerlib =================== Quickstart ========== Installation ------------ Install with your favorite Python package manager like:: pip install awsfindingsmanagerlib Define Your Rules ----------------- You can define rules in multiple ways, the most common are: 1. **Using a YAML File** Create a YAML file, such as ``rules.yaml``, defining the findings you want to suppress. For example: .. code-block:: yaml Rules: - note: Suppress DynamoDB Autoscaling findings action: SUPPRESSED match_on: security_control_id: DynamoDB.1 - note: Suppress findings for development resources action: SUPPRESSED match_on: tags: - key: env value: dev Host the file on an HTTP server (e.g., using ``python3 -m http.server``) or use it directly in your project. .. code-block:: python from awsfindingsmanagerlib import FindingsManager, Http http_backend = Http('http://localhost:8000/rules.yaml') findings_manager = FindingsManager('eu-west-1') findings_manager.register_rules(http_backend.get_rules()) findings_manager.suppress_matching_findings() And zip 🤐 all noise is silenced. 2. **Programmatically with `register_rule`** If you prefer a more dynamic approach, you can define rules programmatically using the ``register_rule`` method: .. code-block:: python from awsfindingsmanagerlib import FindingsManager findings_manager = FindingsManager('eu-west-1') findings_manager.register_rule( note="Suppress DynamoDB Autoscaling findings", action="SUPPRESSED", match_on={"security_control_id": "DynamoDB.1"} ) findings_manager.suppress_matching_findings() And zip 🤐 all noise is silenced. Rule Syntax =========== Rules in your YAML file follow this general syntax: .. code-block:: yaml Rules: - note: 'str' # A descriptive note for the rule action: 'SUPPRESSED' match_on: security_control_id: 'str' rule_or_control_id: 'str' product_name: 'str' title: 'str' tags: - key: 'str' value: 'str' resource_id_regexps: - 'regex' regions: - 'str' **When Suppressing Native Security Hub Findings**: Specify either ``security_control_id`` or ``rule_or_control_id`` — but not both!. *If ``rule_or_control_id`` is used, ensure that "consolidated control findings" is disabled in AWS Security Hub.* **When Suppressing Findings from AWS Security Hub Service Integrations**: Specify both ``product_name`` and ``title``. The ``product_name`` field must match the name of the product that created the finding (e.g., Inspector). The ``title`` field must match the title of the finding. Read the `AWS service integrations `_ page for all the supported integrations. **Additional Filters**: Either ``regions``, ``tags``, or ``resource_id_regexps`` (or all) can be provided to ensure precise matching. When no ``regions`` are set, the rule will match findings from all regions. Note Configuration ================== The library supports two modes for handling finding notes: **text mode** (default) and **JSON mode**. Text Mode (Default) ------------------- By default, suppression notes are stored as plain text. .. code-block:: python from awsfindingsmanagerlib import FindingsManager findings_manager = FindingsManager('eu-west-1') findings_manager.register_rule( note="Suppress SSM.7 findings", action="SUPPRESSED", match_on={"security_control_id": "SSM.7"} ) findings_manager.suppress_matching_findings() Finding notes will be stored as: ``"Suppress SSM.7 findings"`` JSON Mode ------------------------------ JSON mode enables a more structured way of storing notes and allows for note preservation by merging existing JSON formatted metadata. This is particularly useful when integrating with ticketing systems or when multiple teams manage suppressions. To enable this feature, configure the ``FindingsManager`` with a ``NoteTextConfig`` object: .. code-block:: python from awsfindingsmanagerlib import FindingsManager, NoteTextConfig # Enable JSON mode with default key "Note" findings_manager = FindingsManager( region='eu-west-1', note_text=NoteTextConfig(format="json") ) When JSON mode is enabled: 1. **No existing note or empty note**: Creates a new JSON note with the suppression reason .. code-block:: json {"Note": "Suppress SSM.7 findings"} 2. **Existing plain text note**: Replaces the plain text with a JSON note containing the suppression reason .. code-block:: json {"Note": "Suppress SSM.7 findings"} 3. **Existing JSON note**: Merges the suppression reason with existing metadata .. code-block:: json # Before: {"jiraIssue": "PROJ-123"} # After: {"jiraIssue": "PROJ-123", "Note": "Suppress SSM.7 findings"} Custom JSON Key ^^^^^^^^^^^^^^^ You can customize the JSON key used for suppression notes: .. code-block:: python from awsfindingsmanagerlib import FindingsManager, NoteTextConfig findings_manager = FindingsManager( region='eu-west-1', note_text=NoteTextConfig(format="json", key="suppressionReason") ) This will store suppression notes using your custom key: .. code-block:: json {"jiraIssue": "PROJ-123", "suppressionReason": "Suppress SSM.7 findings"} Valid Credentials ============================== To ensure successful operation, your AWS credentials must include the following permissions: - ``ec2:DescribeRegions`` - ``securityhub:GetFindings`` - ``securityhub:BatchUpdateFindings`` Why use awsfindingsmanagerlib? ============================== You may wonder what justifies using a dedicated lib to suppress findings. You could have just as easily, maybe even more easily clicked suppress in the console, right? Yes, BUT, actually, multiple buts. Let's sum up the advantages of using awsfindingsmanagerlib from the skeptic's perspective. "I can just do this in the AWS console" --------------------------------------- Well, that will be a tedious amount of clicking for a lot false positives, while you could have just written: .. code-block:: yaml Rules: - note: My dev instance action: SUPPRESSED match_on: resource_ids: - arn:aws:ec2:eu-central-1:1234567890:instance/i-1234567890 Maybe, better yet: .. code-block:: yaml Rules: - note: dev resources by tag action: SUPPRESSED match_on: tags: - key: env value: dev - note: dev resources by name action: SUPPRESSED match_on: resource_ids: - '*-dev$' # yes, we support regex Add this point you might almost get scared of being too suppressive. Don't panic: .. code-block:: yaml Rules: - note: We'll make this one exception, especially for you two then action: SUPPRESSED match_on: security_control_id: 'IAM.3' resource_ids: - '^arn:aws:iam::1234567890:user/lazyperson1$' - '^arn:aws:iam::1234567890:user/lazyperson2$' As you can see, suppressions can now be expressed in a more general, meaningful, dare-we-say-Pythonic way. Moreover, you can apply your suppressions over all your AWS accounts with this tool with little effort. Control ids are the same in every AWS account and you can express you resources with tags and regex. This way, your suppressions become portable through your whole environment. The generality makes it possible to apply the suppressions even in your audit account, despite differing AWS account ids. This way you can get a truly good overview without clutter from false positives. "I don't have that many findings to suppress" --------------------------------------------- Even if you don't have many false positives in your environment, findings are only saved for 90 days. After that time your suppressions are gone with them. Most checks immediately generate a new finding then. Re-suppressing these findings each time manually is error-prone and can eventually amount to a lot of work. To reduce errors further, we recommend storing your suppressions file in a VCS and suppressing in full automation. (See below for our :ref:`reference implementation `.) Third-Party Tools ----------------- While tools like Splunk, Datadog, and OpenSearch excel at aggregation and analysis, managing findings **at the source** in AWS Security Hub offers significant advantages. Suppressing irrelevant findings within AWS Security Hub ensures: - Only relevant data is forwarded to third-party tools, reducing noise and enhancing visibility. - Lower costs due to reduced storage requirements and improved query performance. AWS Security Hub Automations ---------------------------- AWS Security Hub Automations is AWS's native solution for managing findings. However, it has several limitations that can hinder its effectiveness in large or complex environments: Rule Count ---------- Automations are limited to **100 rules**, which can quickly become insufficient in large environments. Each unique suppression scenario often requires its own rule, leading to a rapid depletion of the rule quota. Flexibility ----------- Automations lack support for **regex** or **multi-property rules**, making them less flexible for complex suppression needs. For example, suppressing a specific check across multiple resources in Automations requires creating multiple rules. With regex, you can achieve the same result with a single, concise rule. For instance, to suppress findings for Lambda functions in specific dev/test accounts, you could use: `arn:aws:lambda:eu-central-1:(1234567890|2345678901):function:(client-a|client-b|client-c)` In Automations, this scenario would require separate rules for each permutation, increasing rule count and reducing manageability. Retroactive Suppression ----------------------- Unlike Automations, this library supports **retroactive suppression**, allowing you to address findings from the past. This eliminates the need to wait for the 90-day retention period to expire before irrelevant findings stop cluttering your dashboard. Readability ----------- While regex has some inherent readability challenges, it offers more flexibility than Automations' filter: prefix/suffix. This flexibility reduces the number of rules required, simplifying suppression management. Additionally, suppressions should be regularly reviewed, often by someone other than the original author. A well-structured regex rule can still be easier to manage than dozens of fragmented rules in Automations. .. _reference-implementation: "Alright, I want this, why is there still more text on this page?" ------------------------------------------------------------------ Well, this is 'just' a lib. While it provides all the magic you want, why do the standard infra work yourself? We have a standard implementation of suppressing with this lib available in Terraform `here `_. On top of that, it provides some integrations for automatic alerting and ticketing. Contents ======== .. toctree:: :maxdepth: 2 readme installation usage contributing modules authors history Indices and Tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search`