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

feature: OpenSearch SIEM for ASEA #853

Merged
merged 44 commits into from
Jan 7, 2022

Conversation

rjjaegeraws
Copy link
Contributor

@rjjaegeraws rjjaegeraws commented Nov 10, 2021

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

OpenSearch SIEM for ASEA

This pull request adds a new deployment feature that deploys an implementation of https://github.com/aws-samples/siem-on-amazon-opensearch-service.

That project is composed for three main pieces:

  1. CDK to deploy needed AWS Infrastructure
  2. Lambda ('deploy_es') that deploys OpenSearch and then configures it based on values from an INI file.
  3. Lambda ('es_loader') that that handles S3 Event Notifications, parses the log files, and writes to OpenSearch

This implementation:

  • Introduces a new feature that can be added to the config.json file as a new 'deployment' type. It looks like the following:
"siem": {
    "deploy": true,
    "vpc-name": "Central",
    "region": "ca-central-1",
    "security-groups": [
        {
        "name": "OpenSearch-SIEM-SG",
        "inbound-rules": [
            {
            "description": "Allow Traffic Inbound",
            "tcp-ports": [
                443
            ],
            "source": [
                "10.0.0.0/8",
                "100.96.252.0/23",
                "100.96.250.0/23"
            ]
            }
        ],
        "outbound-rules": [
            {
            "description": "All Outbound",
            "type": [
                "ALL"
            ],
            "source": [
                "0.0.0.0/0"
            ]
            }
        ]
        }
    ],
    "app-subnets": [
        {
        "name": "App",
        "az": "a"
        },
        {
        "name": "App",
        "az": "b"
        }
    ],
    "lambda-log-processing-role": "ASEA-OpenSearch-ProcessingRole",
    "cognito-domain-prefix": "asea-siem-1234",
    "opensearch-instance-type-main-nodes": "c6g.xlarge.search",
    "opensearch-instance-type-data-nodes": "r6g.xlarge.search",
    "opensearch-capacity-main-nodes": 3,
    "opensearch-capacity-data-nodes": 4,
    "opensearch-volume-size": 100,
    "opensearch-configuration": "siem/opensearch-config.json",    
    "event-processor-lambda-package": "siem/os-loader.zip",
    "maxmind-license": "siem/license.txt"
}

it does the following:

  • Creates roles for OpenSearch

    • Master admin role, KMS key policy updates for EBS
  • Registers the Service-Linked Role for OpenSearch

  • Creates a role that will be use by the 'loader' Lambda

    • Permissions added to the resource policies of the central log buckets (and updated KMS key policies)
  • Creats an OpenSearch 1.0 cluster with values specified in the above 'siem' config section.

    • Enables Fine Grained permissions on the cluster
  • Deploys a Cognito User Pool and Identity Pool

    • Identity Pool roles created
  • Lambda 'loader' is created

    • A zip file containing the packaged 'es_loader' python code and dependency libraries should be zipped and uploaded to the central config bucket.
    • No code changed here; it uses the above repo and loader INI file as-is (but bundled with dependencies)
  • Lambda 'configuration' is created and re-written as a custom cdk-resource

    • The config file from the above project has been rewritten into a JSON format
    • The configuration code is re-written following the same logic
    • It configures OpenSearch with:
      • OpenSearch cluster settings
      • Role Mapping (ex: Cognito to OpenSearch roles, Lambda processing roles)
      • Uploads OpenSearch Component Templates, Index Templates, and Rollover configuration (all based on the above project)
  • Lambda 'S3Notifications' is created to configure the log-archive buckets (two of them)

    • Custom cdk-resource configures the S3 Notifications for PUT to target the Lambda 'loader'
  • Upgraded to a later CDK library that uses the OpenSearch references. The upgrade conversion from Elasticsearch CDK should be avoided

  • Deploys a Lambda function if the maxmind license is provide. This lambda will download the latest database from maxmind to populate IP/world visualizations in OpenSearch.

    • The Lambda function is configured for VPC connectivity; egress internet must exist for the downloads to succeed.
  • The OpenSearch dashboard can be configured by manually uploading the Dashboard zip file from the above project

Configuration Steps

  1. Apply the above sample configuration to the 'Operations' account section in the config.json
    • Ensure that the value "cognito-domain-prefix": "asea-siem-1234" is regionally unique. The value, ex: asea-siem-1234 needs to be updated.
  2. If you want to overide any of the provided siem configuration defaults: In the central configuration S3 bucket, create a folder called 'siem'. Upload both the opensearch-config.json and os-loader.zip found in the reference-artifacts/siem folder. This folder and filename should align to the S3 key values referenced in the SIEM configuration section. For example:
"opensearch-configuration": "siem/opensearch-config.json",    
"event-processor-lambda-package": "siem/os-loader.zip"
  1. Run the State Machine (SM)
  2. Go to Cognito and locate the new User Pool
  3. Create a new User and validate/update credentials as part of the new user flow.
  4. Go to OpenSearch and get the Dashboard URL
  5. This will be a Service Endpoint link; it's not configured for public access. Several access mechanisms exist:
    a) configure Client VPN in the Operations account VPC. Create the ClientVPN using the ASEA-Pipeline roll (SCPs block it) with the following configuration parameters
    • Select User authentication and select the Managed Active Directory (MAD) instance.
    • Select the App subnets
    • Select the OpenSearch Security Groups that are newly deployed
    • Select SplitTunnel
    • Create an authorize rule for the VPC ip space
    • Download the ClientVPN OS app.
    • Download the ClientVPN configuration file
    • Login with 'Admin' domain credentials. (Admin password is found in the root AWS Account Secrets Manager)
    • Connect to the VPN
    • Open the OpenSearch Dashboard, the page should load and present you with the Cognito authentication screen. After authenticating, you'll be redirected to the Dashboard UI.
    • Follow the instructions in the above repo project to upload the Dashboard saved objects.
      b) Access the RDGW bastion host in the ops account using SSM and RDSH per FAQ1.1.13

Additional Tweaks

  • CfnHostedZones updated to optionally store DNS entries. Example, the output for Endpoints now include the Endpoint DNS values. (see following note on STS as to why)
  • In an SEA environment where there is no outbound internet connectivity (example: perimeter firewalls off), HostedZones + Endpoints should handle connectivity to required AWS services. However, in development, it was noticed that sts.amazonaws.com would NOT resolve to an endpoint IP; always a public ip. This can be replicated by creating a VPC lambda function and running a DNS resolver command for sts.amazonaws.com. Even with the sts Hosted Zone and properly configured endpoint. The configuration lambda assume the OpenSearch admin role, but this fails in an environment with no egress internet. As a work around, the lambda will iterate over possible sts options: sts.amazonaws.com, sts.{region}.amazonaws.com, and finally the sts vpc endpoint value from the 'output'. The latter requires the above CfnHostedZone update such that it can be fetched from Outputs. This works and lambda is able to assume role in a private network. This Lambda that configures OpenSearch no longer assumes role, which exposed this issue. The Lambda runs with the 'Admin' OpenSearch role.
  • IAM Asset role creation was updated with improved logic for 'sourceAccount' when specifying an IAM role in the config file. This change was reverted

Jest Snapshot Update:

There are several TransitGateway properties that have switched from Immutable to now support 'No-interruption' (Mutable). See the following github documentation change and public docs reference. The snap shot update removes the previous immutable fields.
awsdocs/aws-cloudformation-user-guide@dafa014
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-transitgateway.html
New:

  Array [
    Object {
      "LogicalId": "TgwMain627BB489",
      "Properties": Object {
        "AmazonSideAsn": 65521,
        "MulticastSupport": undefined,
      },
    },
  ]

Previous:

  Array [
    Object {
      "LogicalId": "TgwMain627BB489",
      "Properties": Object {
        "AmazonSideAsn": 65521,
        "AutoAcceptSharedAttachments": "enable",
        "DefaultRouteTableAssociation": "disable",
        "DefaultRouteTablePropagation": "disable",
        "Description": undefined,
        "DnsSupport": "enable",
        "MulticastSupport": undefined,
        "Tags": Array [
          Object {
            "Key": "Accelerator",
            "Value": "PBMM",
          },
          Object {
            "Key": "Name",
            "Value": "Main_tgw",
          },
        ],
        "VpnEcmpSupport": "enable",
      },
    },

Considerations

  • CloudTrail and VPC flow logs have been seen to load into OpenSearch. Not all types have been tested.
  • The log-archive files from Firehose are skipped by the loader function; its logic doesn't understand it.
  • Development and testing has been done on the standalone ASEA install. Needs to be tried out on a Control Tower install.
  • OpenSearch takes ~20 minutes to provision

@rjjaegeraws rjjaegeraws requested a review from Brian969 November 10, 2021 14:16
@rjjaegeraws rjjaegeraws marked this pull request as ready for review November 22, 2021 20:48
@Brian969
Copy link
Contributor

Question - Can you confirm you append the 'es_loader' S3 Event Notifications on the bucket and do not overwrite any existing notifications?

@rjjaegeraws
Copy link
Contributor Author

Question - Can you confirm you append the 'es_loader' S3 Event Notifications on the bucket and do not overwrite any existing notifications?

Yes. Here's what it looks like:

let lambdaConfigurations = existingNotifcationConfiguration.LambdaFunctionConfigurations ?? [];
  const foundIndex = lambdaConfigurations.findIndex(x => x.Id === s3EventName);

  if (foundIndex > -1) {
    lambdaConfigurations = foundIndex === 0 ? [] : lambdaConfigurations.splice(foundIndex, 1);
  }
  lambdaConfigurations.push({
    Id: s3EventName,
    LambdaFunctionArn: lambdaArn,
    Events: s3Events,
  });
  existingNotifcationConfiguration.LambdaFunctionConfigurations = lambdaConfigurations;

Note how there's a fetch to get existing notifications and then 'push' a new one into the array.

@hickeydh-aws hickeydh-aws merged commit 5f88292 into aws-samples:main Jan 7, 2022
@Brian969
Copy link
Contributor

Brian969 commented Feb 4, 2022

UPDATE: THIS PR TO BE REVERTED

  • We will be exploring an alternate mechanism to deliver this functionality

Brian969 added a commit that referenced this pull request Feb 9, 2022
* initial opensearch cdk work

* working os configure

* working dashboard

* Remove debug statement

* removal updates

* update for linting

* eslint fixes

* update sample config

* Add artifacts

* prettier

* eslint

* initial opensearch cdk work

* working os configure

* working dashboard

* Remove debug statement

* removal updates

* update for linting

* eslint fixes

* update sample config

* Add artifacts

* prettier

* eslint

* more eslint

* update jest snapshot with latest TransitGateway cloudformation immutable property changes

* updated snapshot with log-archive phase 4 (this is the phase that adds s3 notifications)

* Update test sample

* update verify files with siem config

* remove unused folder

* opensearch logs

* add geoip

* remove admin role. use lambda role to bootstrap OpenSearch

* configure siem geoip custom resource to bootstrap download

* update cdk version number in script file

* merge

* prettier

* update sample config

* update sample config

* remove unused unauthenticated cognito roles, enable MFA for cognito, enable AdvancedSecurty for cognito

* update README

Co-authored-by: Brian969 <[email protected]>
@Brian969
Copy link
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FEATURE] Enhance structure of log archive bucket to support analytics
3 participants