From 8f94946a26bce4da731e4d91af12e7c6eebf8c48 Mon Sep 17 00:00:00 2001 From: Costas K Date: Tue, 14 May 2024 09:08:00 +0100 Subject: [PATCH] Semi Rewrite/ Major Update (#4) * first pass of rewrite. Added multithreading and more services * tests, tox and accounts update * silly yaml * more services and moved to separate folder * added efs * bump version --- .github/workflows/test_and_publish.yaml | 6 +- README.md | 126 +- acknowledgements.md | 2 +- awsxenos/__init__.py | 4 +- awsxenos/accounts.json | 3678 +++++++++++++++++++---- awsxenos/config.yaml | 21 + awsxenos/finding.py | 111 +- awsxenos/report.py | 42 +- awsxenos/scan.py | 320 +- awsxenos/services/__init__.py | 0 awsxenos/services/efs.py | 25 + awsxenos/services/eventbridge.py | 22 + awsxenos/services/iam.py | 45 + awsxenos/services/kms.py | 28 + awsxenos/services/lambda.py | 40 + awsxenos/services/s3.py | 151 + awsxenos/services/secretsmanager.py | 32 + awsxenos/services/sqs.py | 33 + requirements.txt | 7 +- setup.py | 12 +- tests/fixtures.py | 11 +- tests/test_report.py | 29 +- tests/test_scan.py | 59 +- tox.ini | 7 +- 24 files changed, 3924 insertions(+), 887 deletions(-) create mode 100644 awsxenos/config.yaml create mode 100644 awsxenos/services/__init__.py create mode 100644 awsxenos/services/efs.py create mode 100644 awsxenos/services/eventbridge.py create mode 100644 awsxenos/services/iam.py create mode 100644 awsxenos/services/kms.py create mode 100644 awsxenos/services/lambda.py create mode 100644 awsxenos/services/s3.py create mode 100644 awsxenos/services/secretsmanager.py create mode 100644 awsxenos/services/sqs.py diff --git a/.github/workflows/test_and_publish.yaml b/.github/workflows/test_and_publish.yaml index bb7da90..389e3ce 100644 --- a/.github/workflows/test_and_publish.yaml +++ b/.github/workflows/test_and_publish.yaml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.7, 3.8, 3.9] + python-version: ["3.9", "3.10", "3.11"] steps: - uses: actions/checkout@v2 @@ -31,10 +31,10 @@ jobs: if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') steps: - uses: actions/checkout@master - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v1 with: - python-version: 3.9 + python-version: "3.10" - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/README.md b/README.md index b010e46..e1feb4e 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,18 @@ > Xenos, is Greek for stranger. -AWSXenos will list all the trust relationships in all the IAM roles, and S3 buckets, in an AWS account and give you a breakdown of all the accounts that have trust relationships to your account. It will also highlight whether the trusts have an [external ID](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html) or not. +AWSXenos will assess the trust relationships in all the IAM roles, and resource policies for [several AWS services](#aws-iam-access-analyzer-comparison) in an AWS account and give you a breakdown of all the accounts that have trust relationships to your account. It will also highlight whether the trusts have an [external ID](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html) or not. -This tool reports against the [Trusted Relationship Technique](https://attack.mitre.org/techniques/T1199/) of the ATT&CK Framework. +https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html -* For the "known" accounts list AWSXenos uses a modified version of [known AWS Account IDs](https://github.com/rupertbg/aws-public-account-ids). -* For the Org accounts list AWSXenos query AWS Organizations. +This tool reports against the [Trusted Relationship Technique](https://attack.mitre.org/techniques/T1199/) and parts of the [Valid Accounts: Cloud Accounts](https://attack.mitre.org/techniques/T1078/004/) of the ATT&CK Framework. + +* For the "known" accounts list AWSXenos uses a modified version of [known AWS Accounts](https://github.com/fwdcloudsec/known_aws_accounts). +* For the Org accounts list, AWSXenos will query AWS Organizations. * AWS Services are classified separately. * Everything else falls under unknown account +* For regional services, e.g. KMS, you'll need to run AWSXenos per region. +* You can configure which services you'd like to assess by providing a [config.yaml](awsxenos/config.yaml) file. ## Example ![HTML Report Screenshot](screenshots/report.png) @@ -26,6 +30,46 @@ Access Analyzer falls short because: 4. Does not identify AWS Service principals. This is mainly important because of [Wiz's AWSConfig, et al vulnverabilities](http://i.blackhat.com/USA21/Wednesday-Handouts/us-21-Breaking-The-Isolation-Cross-Account-AWS-Vulnerabilities.pdf) +## AWS IAM Access Analyzer comparison + +Comparison based on AWS Documentation [1](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html) and [2](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html#what-is-access-analyzer-resource-identification), including services or resources outside of docs, e.g. VPC endpoints. + + +| Service | AWSXenos | Access Analyzer | +| :--: | :--: | :--: | +| S3 Bucket| :white_check_mark: | :white_check_mark: | +| S3 Directory Buckets | :x: | :white_check_mark: | +| S3 Access Points | :x: | :white_check_mark: | +| S3 Bucket ACLs | :white_check_mark: | :white_check_mark: | +| S3 Glacier | :white_check_mark: | :x: | +| IAM | :white_check_mark: | :white_check_mark: | +| KMS | :white_check_mark: | :white_check_mark: | +| Secrets Manager | :white_check_mark: | :white_check_mark: | +| Lambda | :white_check_mark: | :white_check_mark: | +| SNS | :x: | :white_check_mark: | +| SQS | :white_check_mark: | :white_check_mark: | +| RDS Snapshots | :x: | :white_check_mark: | +| RDS Cluster Snapshots | :x: | :white_check_mark: | +| ECR | :x: | :white_check_mark: | +| EFS | :white_check_mark: | :white_check_mark: | +| DynamoDB streams | :x: | :white_check_mark: | +| DynamoDB tables | :x: | :white_check_mark: | +| EBS Snapshots | :x: | :white_check_mark: | +| EventBridge | :white_check_mark: | :x: | +| EventBridge Schema | :x: | :x: | +| Mediastore | :x: | :x: | +| Glue | :x: | :x: | +| Kinesis Data Streams | :x: | :x: | +| Lex v2 | :x: | :x: | +| Migration Hub Orchestrator | :x: | :x: | +| OpenSearch | :x: | :x: | +| AWS PCA | :x: | :x: | +| Redshift Serverless | :x: | :x: | +| Serverless Application Repository | :x: | :x: | +| SES v2 | :x: | :x: | +| Incident Manager | :x: | :x: | +| Incident Manager Contacts | :x: | :x: | +| VPC endpoints | :x: | :x: | ## How to run @@ -39,14 +83,27 @@ You will get an HTML and JSON report. See [example report](example/example.html) +You can configure the services you care about by using [your own config](awsxenos/config.yaml). + ### Library ```python -from awsxenos.scan import Scan +from awsxenos.scan import PreScan from awsxenos.report import Report +from awsxenos.s3 import S3 +#from awsxenos.iam import IAM + +# To run everything based on your config. -s = Scan() -r = Report(s.findings, s.known_accounts_data) +prescan = PreScan() +results = load_and_run(config_path, prescan.accounts) +r = Report(results, prescan.known_accounts) + +# Per service +prescan = PreScan() +aws_service = S3() +findings = aws_service.fetch(prescan.accounts) +r = Report(s.findings, s.known_accounts) json_summary = r.JSON_report() html_summary = r.HTML_report() ``` @@ -61,11 +118,24 @@ Permissions required. "Statement": [ { "Action": [ - "iam:ListRoles" + "elasticfilesystem:DescribeFileSystemPolicy", + "elasticfilesystem:DescribeFileSystems", + "events:ListEventBuses", + "glacier:GetVaultAccessPolicy", + "glacier:ListVaults", + "iam:ListRoles", "organizations:ListAccounts", - "s3:ListAllMyBuckets", + "kms:GetKeyPolicy", + "kms:ListKeys", + "lambda:GetPolicy", + "lambda:ListFunctions", + "s3:GetBucketAcl", "s3:GetBucketPolicy", - "s3:GetBucketAcl" + "s3:ListAllMyBuckets", + "secretsmanager:GetResourcePolicy", + "secretsmanager:ListSecrets", + "sqs:GetQueueAttributes", + "sqs:ListQueues" ], "Effect": "Allow", "Resource": "*" @@ -81,17 +151,35 @@ python3 -m env venv source /env/bin/activate pip install -r requirements.txt ``` + +1. Create a file with the name of the service. +2. Create a class with the name of the resource that you want from that service +3. Your class must inherit from `Service` and return `Findings` + +Example: + +```python +class S3(Service): + + def fetch(self, accounts: DefaultDict[str, Set] ) -> Findings: + self._buckets = self.list_account_buckets() + self.policies = self.get_bucket_policies() + return super().collate(accounts, self.policies) +``` +4. Add your filename and class to the config + +--- + +:warning: AWSXenos currently assesses access based on [https://github.com/Netflix-Skunkworks/policyuniverse](https://github.com/Netflix-Skunkworks/policyuniverse). +There are cases where IAM `conditions`, will _not_ be taken into account, therefore resulting in false positives. +This could be fairly common in KMS Customer Managed Keys created by AWS Services. +AWSXenos findings are per IAM statement on an IAM policy. + ## I want to add more known accounts Create a PR or raise an issue. Contributions are welcome. + + ## Features -- [x] IAM Roles -- [x] S3 Bucket Policies and ACLs - [x] Use as library -- [x] HTML and JSON output -- [x] Supports AWS Services - -## TODO -- [ ] Add support for more resource policies services, e.g. SecretsManager, KSM, SNS, SQS, Lambda -- [ ] Add support for Cognito, RAM -- [ ] Add support for VPCE +- [x] HTML and JSON output \ No newline at end of file diff --git a/acknowledgements.md b/acknowledgements.md index 527b786..4e1df11 100644 --- a/acknowledgements.md +++ b/acknowledgements.md @@ -3,7 +3,7 @@ The MIT License (MIT) Copyright (c) 2019 Rupert Bryant-Greene -Copyright (c) 2021 AirWalk Consulting Limited +Copyright (c) 2021 Airwalk Reply Consulting Limited Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/awsxenos/__init__.py b/awsxenos/__init__.py index 05775fa..8c824fa 100644 --- a/awsxenos/__init__.py +++ b/awsxenos/__init__.py @@ -1,5 +1,7 @@ """Find the Xenoi (external account trusts) in your AWS Account.""" + from pathlib import Path -from awsxenos.finding import AccountType, Finding + +from awsxenos.finding import Accounts, Finding, Findings, Resources, Service package_path = Path(__file__) diff --git a/awsxenos/accounts.json b/awsxenos/accounts.json index 0f78232..b3617b3 100644 --- a/awsxenos/accounts.json +++ b/awsxenos/accounts.json @@ -1,530 +1,3148 @@ -[{ - "owner": "Cloudhealth", - "source": "https://github.com/mozilla/security/blob/master/operations/cloudformation-templates/cloudhealth_iam_role.json", - "description": "Cloudhealth", - "id": "454464851268" - }, { - "owner": "SegmentIO", - "source": ["https://segment.com/docs/destinations/amazon-s3/", "https://segment.com/docs/destinations/amazon-kinesis/"], - "description": "SegmentIO", - "id": "107630771604" - }, { - "owner": "SegmentIO", - "source": ["https://segment.com/docs/destinations/amazon-s3/", "https://segment.com/docs/destinations/amazon-kinesis/"], - "description": "SegmentIO", - "id": "595280932656" - }, { - "owner": "StackDriver", - "source": "https://web.archive.org/web/20150423044518/https://support.stackdriver.com/customer/portal/articles/1491790-setting-up-stackdriver-for-your-aws-account", - "description": "StackDriver", - "id": "314658760392" - }, { - "owner": "Crowdstrike", - "source": "https://www.crowdstrike.com/falcon/2020/wp-content/uploads/2020/10/Crowdstrike-AWS-ControlTower-Implementation-Guide.pdf", - "description": "Crowdstrike Falcon", - "id": "292230061137" - }, { - "owner": "Zencoder", - "source": "https://support.brightcove.com/using-zencoder-s3", - "description": "The Performance Leader in File Cloud Encoding", - "id": "395540211253" - }, { - "owner": "Datadog", - "source": "https://docs.datadoghq.com/integrations/amazon_web_services/", - "description": "Datadog is a monitoring service for cloud-scale applications, providing monitoring of servers, databases, tools, and services, through a SaaS-based data analytics platform.", - "id": "464622532012" - }, { - "owner": "Cloudability", - "source": "https://github.com/edrans/tf-aws-iam-cloudability", - "description": "Cloudability is a cloud cost management platform that improves visibility, optimization, governance and more across cloud environments.", - "id": "165736516723" - }, { - "owner": "Rackspace", - "source": "https://manage.rackspace.com/aws/docs/product-guide/patching/ec2/meltdown.html", - "description": "Rackspace Inc. is an American managed cloud computing company based in Windcrest, Texas, a suburb of San Antonio.", - "id": "507897595701" - }, { - "owner": "New Relic", - "source": ["https://docs.newrelic.com/docs/integrations/amazon-integrations/get-started/connect-aws-services-infrastructure", "https://docs.newrelic.com/docs/infrastructure/new-relic-infrastructure/data-instrumentation/amazon-aws-ec2-integration-infrastructure"], - "description": "New Relic is an American software analytics company based in San Francisco, California.", - "id": "754728514883" - }, { - "owner": "New Relic", - "source": ["https://docs.newrelic.com/docs/integrations/amazon-integrations/get-started/connect-aws-services-infrastructure", "https://docs.newrelic.com/docs/infrastructure/new-relic-infrastructure/data-instrumentation/amazon-aws-ec2-integration-infrastructure"], - "description": "New Relic is an American software analytics company based in San Francisco, California.", - "id": "017663287629" - }, { - "owner": "Brightcove", - "source": "https://support.brightcove.com/using-dynamic-ingest-s3", - "description": "Brightcove, Inc. is a Boston, Massachusetts–based software company that produces an online video platform.", - "id": "749779118921" - }, { - "owner": "CloudCheckr", - "source": "https://support.cloudcheckr.com/cloudcheckr-api-userguide/cloudcheckr-admin-api-reference-guide/", - "description": "CloudCheckr's cloud management platform provides cost management, security, reporting and analytics to help users optimize their AWS and Azure environments.", - "id": "352813966189" - }, { - "owner": "SignifAI", - "source": "https://docs.signifai.io/docs/amazon-web-services", - "description": "Predict and prevent downtime with artificial intelligence and machine learning for Site Reliability Engineers.", - "id": "265975144233" - }, - { - "owner": "AlertLogic US", - "source":"https://docs.alertlogic.com/prepare/iam-role-creation.htm", - "description": "Alert Logic: Managed Detection and Response (MDR) Company", - "id": "733251395267" - }, - { - "owner": "AlertLogic EU", - "source":"https://docs.alertlogic.com/prepare/iam-role-creation.htm", - "description": "Alert Logic: Managed Detection and Response (MDR) Company", - "id": "857795874556" - }, - { - "owner": "ParkMyCloud", - "source": "https://parkmycloud.atlassian.net/wiki/spaces/PMCUG/pages/43876427/Create+an+IAM+Role+in+AWS+for+ParkMyCloud", - "description": "ParkMyCloud, a Turbonomic company, provides an easy-to-use platform that helps enterprises automatically identify and eliminate wasted cloud spend.", - "id": "753542375798" - }, { - "owner": "CenturyLinkCloud", - "source": "https://www.ctl.io/knowledge-base/cloud-application-manager/deploying-anywhere/using-your-aws-account/", - "description": "Centurylink Cloud offers secure enterprise cloud services ideal for business apps, IaaS, PaaS, SaaS, DBaaS and cloud management in a single platform.", - "id": "540339316802" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - US East (N. Virginia) - us-east-1", - "id": "127311923021" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - US East (Ohio) - us-east-2", - "id": "033677994240" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - US West (N. California) - us-west-1", - "id": "027434742980" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - US West (Oregon) - us-west-2", - "id": "797873946194" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - Canada (Central) - ca-central-1", - "id": "985666609251" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - EU (Frankfurt) - eu-central-1", - "id": "054676820928" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - EU (Ireland) - eu-west-1", - "id": "156460612806" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - EU (London) - eu-west-2", - "id": "652711504416" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - EU (Paris) - eu-west-3", - "id": "009996457667" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - Asia Pacific (Tokyo) - ap-northeast-1", - "id": "582318560864" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - Asia Pacific (Seoul) - ap-northeast-2", - "id": "600734575887" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - Asia Pacific (Osaka-Local) - ap-northeast-3", - "id": "383597477331" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - Asia Pacific (Singapore) - ap-southeast-1", - "id": "114774131450" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - Asia Pacific (Sydney) - ap-southeast-2", - "id": "783225319266" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - Asia Pacific (Mumbai) - ap-south-1", - "id": "718504428378" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - South America (São Paulo) - sa-east-1", - "id": "507241528517" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - AWS GovCloud (US-West) - us-gov-west-1", - "id": "048591011584" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - China (Beijing) - cn-north-1", - "id": "638102146993" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html", - "description": "Elastic Load Balancing (ELB) - China (Ningxia) - cn-northwest-1", - "id": "037604701340" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "193672423079" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "391106570357" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "262260360010" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "902366379725" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "865932855811" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "760740231472" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "361669875840" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "762762565011" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "404641285394" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "660998842044" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "907379612154" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "053454850223" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "210876761215" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "307160386991" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "915173422425" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html", - "description": "Redshift logs", - "id": "075028567923" - }, { - "owner": "Amazon Web Services", - "description": "Cloudfront logs", - "id": "cloudfront" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html", - "description": "Example Canonical User ID", - "id": "79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html", - "description": "Anonymous Canonical User ID", - "id": "65a011a29cdf8ec533ec3d1ccaae921c" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html", - "description": "AWS Log Delivery Canonical User ID", - "id": "c4c1ede66af53448b93c283ce9448c4ba468c9432aa01d700d3878632f77d2d0" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/billing-getting-started.html#step-2", - "description": "AWS ZA_Team Canonical User ID", - "id": "6aa5a366c34c1cbe25dc49211496e913e0351eb0e8c37aa3477e40942ec6b97c" - }, { - "owner": "Amazon Web Services", - "source": "https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/billing-getting-started.html#step-2", - "description": "Billing", - "id": "386209384616" - }, { - "owner": "Dome9", - "source": "http://support.dome9.com/knowledgebase/articles/796419-convert-dome9-aws-account-connection-from-iam-user", - "description": "Dome9 delivers full visibility, control and faster time to protection as organizations scale in AWS, Azure and Google Cloud environments.", - "id": "634729597623" - }, { - "owner": "Google", - "source": "https://support.stackdriver.com/customer/portal/articles/1491790-setting-up-stackdriver-for-your-aws-account", - "description": "Stackdriver aggregates metrics, logs, and events from infrastructure, giving developers and operators a rich set of observable signals that speed root-cause analysis and reduce mean time to resolution (MTTR).", - "id": "314658760392" - }, { - "owner": "Skeddly", - "source": "http://thecloudmarket.com/owner/478299826944", - "description": "Skeddly schedules and automates your cloud resources on Amazon Web Services, Microsoft Azure, and Google Cloud Platform.", - "id": "478299826944" - }, { - "owner": "Freshservice", - "source": "https://support.freshservice.com/support/solutions/articles/207515-creating-a-role-arn-for-integrating-amazon-web-services-aws-in-freshservice", - "description": "Cloud based ITSM software for your service desk", - "id": "618708667954" - }, { - "owner": "SignalFx", - "source": "https://signalfx-product-docs.readthedocs-hosted.com/en/latest/getting-started/send-data.html", - "description": "SignalFx is the only real-time cloud monitoring platform for infrastructure, microservices, and applications.", - "id": "134183635603" - }, { - "owner": "CloudSploit", - "source": "https://cloudsploit.freshdesk.com/support/solutions/articles/17000008755-connecting-an-aws-account-to-cloudsploit", - "description": "CloudSploit's open-source cloud security scans find misconfigurations and security risks, allowing for mitigation before a compromise.", - "id": "057012691312" - }, { - "owner": "Globus", - "source": "https://docs.globus.org/how-to/amazon-aws-s3-endpoints/", - "description": "Research data management simplified.", - "id": "328067584297" - }, { - "owner": "Dynatrace", - "source": "https://help.dynatrace.com/monitor-cloud-virtualization-and-hosts/cloud/how-do-i-start-amazon-web-services-monitoring/", - "description": "Dynatrace is a software intelligence company providing application performance management, artificial intelligence for operations, cloud infrastructure monitoring, and digital experience management, with products for the information technology departments and digital business owners of medium and large businesses.", - "id": "509560245411" - }, { - "owner": "Deep Security", - "source": "https://esupport.trendmicro.com/media/13166096/Generate-AWS-Role.pdf", - "description": "Trend Micro's Deep Security is an intelligent data protection solution that services all environments and was built purposefully to support VMware deployments.", - "id": "862820443276" - }, { - "owner": "Cloudbreak", - "source": "https://github.com/hortonworks/cloudbreak", - "description": "A tool for provisioning and managing Apache Hadoop clusters in the cloud.", - "id": "755047402263" - }, { - "owner": "Teraproc", - "source": "http://www.teraproc.com/awskey/", - "description": "Teraproc Cloud Manager is a complete solution of managing a heterogeneous cloud computing environment.", - "id": "122931797421" - }, { - "owner": "Orbitera", - "source": "https://support.orbitera.com/support/solutions/articles/147040-add-new-aws-accounts", - "description": "The Cloud Commerce Platform", - "id": "328676173091" - }, { - "owner": "RedLine13", - "source": "https://www.redline13.com/blog/aws-setup/", - "description": "Open Architecture for Building and Running Load Tests", - "id": "635144173025" - }, { - "owner": "Kochava", - "source": "https://support.kochava.com/reference-information/traffic-import-tool", - "description": "Kochava is the industry leader for mobile app attribution and mobile app analytics. ", - "id": "719465667078" - }, { - "owner": "Instaclustr", - "source": "https://support.instaclustr.com/hc/en-us/articles/226565607-Setting-Up-a-Datacenter-with-EBS-Encryption", - "description": "Managed and supported open source solutions for Apache Cassandra, Apache Kafka, Apache Spark, Elasticsearch, Apache Zeppelin, Kibana etc", - "id": "624537489435" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "475085895292" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "086441151436" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "388731089494" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "113285607260" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "819402241893" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "977081816279" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "765225791966" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "492519147666" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "903692715234" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "284668455005" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "216624486486" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "681348832753" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "035351147821" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "859597730677" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "282025262664" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "262312530599" - }, { - "owner": "CloudTrail", - "source": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html", - "description": "CloudTrail", - "id": "814480443879" - }, { - "owner": "Summit Route", - "source": "https://summitroute.com/aws_security_assessments/", - "description": "Summit Route", - "id": "393727464233" - }, { - "owner": "TrendMicro", - "source": "https://help.deepsecurity.trendmicro.com/Add-Computers/add-aws.html", - "description": "TrendMicro", - "id": "147995105371" - }, { - "owner": "Convox", - "source": "https://convox.com/docs/aws-integration", - "description": "Convox", - "id": "665986001363" - }, { - "owner": "Spotinst", - "source": "https://help.spotinst.com/hc/en-us/articles/360000343509-Functions-Permissions-Model-IAM-Role-", - "description": "Spotinst", - "id": "922761411349" - }, { - "owner": "Prisma", - "source": "https://docs.paloaltonetworks.com/prisma/prisma-cloud/prisma-cloud-admin/connect-your-cloud-platform-to-prisma-cloud/onboard-your-aws-account/set-up-your-prisma-cloud-role-for-aws-manual.html", - "description": "Prisma Cloud", - "id": "188619942792" - }, { - "owner": "Sumo Logic", - "source": "https://help.sumologic.com/03Send-Data/sources/02sources-for-Hosted-Collectors/Amazon-Web-Services/Grant-Access-to-an-AWS-Product#IAM_Role", - "description": "Account belonging to Sumo Logic used for ingestion of logs from customers' AWS accounts", - "id": "926226587429" - }, { - "owner": "Bridgecrew", - "description": "Bridgecrew", - "id": "890234264427" - }, { - "owner": "Lacework", - "description": "Lacework", - "id": "434813966438" - }, { - "owner": "Onelogin", - "description": "Onelogin", - "id": "842984801698" - }, { - "owner": "nOps", - "source": "https://help.nops.io/manual_setup", - "description": "nOps", - "id": "202279780353" - }, { - "owner": "Fivetran", - "source": "https://fivetran.com/docs/logs/cloudwatch/setup-guide", - "description": "Fivetran", - "id": "834469178297" - }, { - "owner": "Databricks", - "source": "https://docs.databricks.com/administration-guide/account-settings/aws-accounts.html", - "description": "Databricks", - "id": "414351767826" - }, { - "owner": "Threat Stack", - "source": "https://threatstack.zendesk.com/hc/en-us/articles/206006626-AWS-EC2-Integration", - "description": "Threat Stack", - "id": "896126563706" - }, { - "owner": "JupiterOne", - "source": "https://github.com/JupiterOne/jupiterone-aws-cloudformation/commit/0adf947dc98404cef1eee1f570f39c05c87d3f41", - "description": "JupiterOne", - "id": "612791702201" - }, { - "owner": "Rapid7", - "source": "https://insightvm.help.rapid7.com/docs/aws-connect-to-cloud-configuration-assessment", - "description": "Rapid7 InsightVM Cloud Configuration", - "id": "336818582268" - }] \ No newline at end of file +[ + { + "id": "454464851268", + "owner": "Cloudhealth", + "source": [ + "https://github.com/mozilla/security/blob/master/operations/cloudformation-templates/cloudhealth_iam_role.json" + ], + "description": "" + }, + { + "id": "107630771604", + "owner": "SegmentIO", + "source": [ + "https://segment.com/docs/destinations/amazon-s3/", + "https://segment.com/docs/destinations/amazon-kinesis/" + ], + "description": "" + }, + { + "id": "595280932656", + "owner": "SegmentIO", + "source": [ + "https://segment.com/docs/destinations/amazon-s3/", + "https://segment.com/docs/destinations/amazon-kinesis/" + ], + "description": "" + }, + { + "id": "314658760392", + "owner": "StackDriver", + "source": [ + "https://web.archive.org/web/20150423044518/https://support.stackdriver.com/customer/portal/articles/1491790-setting-up-stackdriver-for-your-aws-account", + "https://support.stackdriver.com/customer/portal/articles/1491790-setting-up-stackdriver-for-your-aws-account" + ], + "description": "" + }, + { + "id": "395540211253", + "owner": "Zencoder", + "source": [ + "https://support.brightcove.com/using-zencoder-s3" + ], + "description": "" + }, + { + "id": "464622532012", + "owner": "Datadog", + "source": [ + "https://docs.datadoghq.com/integrations/guide/aws-manual-setup/" + ], + "description": "" + }, + { + "id": "165736516723", + "owner": "Cloudability", + "source": [ + "https://github.com/edrans/tf-aws-iam-cloudability", + "https://developers.cloudability.com/docs/vendor-credentials-end-point" + ], + "description": "" + }, + { + "id": "507897595701", + "owner": "Rackspace", + "source": [ + "https://manage.rackspace.com/aws/docs/product-guide/patching/ec2/meltdown.html", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "530014582677", + "owner": "Rackspace", + "source": [ + "https://manage.rackspace.com/aws/docs/product-guide/patching/ec2/meltdown.html", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "754728514883", + "owner": "New Relic", + "source": [ + "https://docs.newrelic.com/docs/integrations/amazon-integrations/get-started/connect-aws-services-infrastructure", + "https://docs.newrelic.com/docs/infrastructure/new-relic-infrastructure/data-instrumentation/amazon-aws-ec2-integration-infrastructure" + ], + "description": "" + }, + { + "id": "017663287629", + "owner": "New Relic", + "source": [ + "https://docs.newrelic.com/docs/integrations/amazon-integrations/get-started/connect-aws-services-infrastructure", + "https://docs.newrelic.com/docs/infrastructure/new-relic-infrastructure/data-instrumentation/amazon-aws-ec2-integration-infrastructure" + ], + "description": "" + }, + { + "id": "749779118921", + "owner": "Brightcove", + "source": [ + "https://support.brightcove.com/using-dynamic-ingest-s3" + ], + "description": "" + }, + { + "id": "352813966189", + "owner": "CloudCheckr", + "source": [ + "https://support.cloudcheckr.com/cloudcheckr-api-userguide/cloudcheckr-admin-api-reference-guide/" + ], + "description": "" + }, + { + "id": "265975144233", + "owner": "SignifAI", + "source": [ + "https://docs.signifai.io/docs/amazon-web-services" + ], + "description": "" + }, + { + "id": "753542375798", + "owner": "ParkMyCloud", + "source": [ + "https://parkmycloud.atlassian.net/wiki/spaces/PMCUG/pages/43876427/Create+an+IAM+Role+in+AWS+for+ParkMyCloud" + ], + "description": "" + }, + { + "id": "540339316802", + "owner": "CenturyLinkCloud", + "source": [ + "https://www.ctl.io/knowledge-base/cloud-application-manager/deploying-anywhere/using-your-aws-account/" + ], + "description": "" + }, + { + "id": "127311923021", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "033677994240", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "027434742980", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "797873946194", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "985666609251", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "054676820928", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "156460612806", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "652711504416", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "009996457667", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "582318560864", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "600734575887", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "383597477331", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "114774131450", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "783225319266", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "718504428378", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "507241528517", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "048591011584", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "638102146993", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "037604701340", + "owner": "ELB logsaws", + "source": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html" + ], + "description": "" + }, + { + "id": "193672423079", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "391106570357", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "262260360010", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "902366379725", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "865932855811", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "760740231472", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "361669875840", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "762762565011", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "404641285394", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "660998842044", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "907379612154", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "053454850223", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "210876761215", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "307160386991", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "915173422425", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "075028567923", + "owner": "Redshift logsaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "description": "" + }, + { + "id": "386209384616", + "owner": "Billingaws", + "source": [ + "https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/billing-getting-started.html#step-2" + ], + "description": "" + }, + { + "id": "478299826944", + "owner": "skeddly", + "source": [ + "http://thecloudmarket.com/owner/478299826944" + ], + "description": "" + }, + { + "id": "618708667954", + "owner": "freshservice", + "source": [ + "https://support.freshservice.com/support/solutions/articles/207515-creating-a-role-arn-for-integrating-amazon-web-services-aws-in-freshservice" + ], + "description": "" + }, + { + "id": "134183635603", + "owner": "signalfx", + "source": [ + "https://signalfx-product-docs.readthedocs-hosted.com/en/latest/getting-started/send-data.html" + ], + "description": "" + }, + { + "id": "057012691312", + "owner": "cloudsploit", + "source": [ + "https://cloudsploit.freshdesk.com/support/solutions/articles/17000008755-connecting-an-aws-account-to-cloudsploit" + ], + "description": "" + }, + { + "id": "978540733285", + "owner": "Aqua", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "328067584297", + "owner": "globus", + "source": [ + "https://docs.globus.org/how-to/amazon-aws-s3-endpoints/" + ], + "description": "" + }, + { + "id": "509560245411", + "owner": "dynatrace", + "source": [ + "https://help.dynatrace.com/monitor-cloud-virtualization-and-hosts/cloud/how-do-i-start-amazon-web-services-monitoring/" + ], + "description": "" + }, + { + "id": "862820443276", + "owner": "Trend Micro deepsecurity", + "source": [ + "https://esupport.trendmicro.com/media/13166096/Generate-AWS-Role.pdf", + "https://help.deepsecurity.trendmicro.com/Add-Computers/add-aws.html" + ], + "description": "" + }, + { + "id": "147995105371", + "owner": "Trend Micro deepsecurity", + "source": [ + "https://esupport.trendmicro.com/media/13166096/Generate-AWS-Role.pdf", + "https://help.deepsecurity.trendmicro.com/Add-Computers/add-aws.html" + ], + "description": "" + }, + { + "id": "755047402263", + "owner": "cloudbreak", + "source": [ + "https://docs.hortonworks.com/HDPDocuments/HDP2/HDP-2.3.0/bk_cldbrk_install/bk_CLBK_IAG/content/clbk_iam_console.html" + ], + "description": "" + }, + { + "id": "122931797421", + "owner": "teraproc", + "source": [ + "http://www.teraproc.com/awskey/" + ], + "description": "" + }, + { + "id": "328676173091", + "owner": "orbitera", + "source": [ + "https://support.orbitera.com/support/solutions/articles/147040-add-new-aws-accounts" + ], + "description": "" + }, + { + "id": "635144173025", + "owner": "redline13", + "source": [ + "https://www.redline13.com/blog/aws-setup/" + ], + "description": "" + }, + { + "id": "719465667078", + "owner": "kochava", + "source": [ + "https://support.kochava.com/reference-information/traffic-import-tool" + ], + "description": "" + }, + { + "id": "624537489435", + "owner": "instaclustr", + "source": [ + "https://support.instaclustr.com/hc/en-us/articles/226565607-Setting-Up-a-Datacenter-with-EBS-Encryption" + ], + "description": "" + }, + { + "id": "475085895292", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "086441151436", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "388731089494", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "113285607260", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "819402241893", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "977081816279", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "765225791966", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "492519147666", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "903692715234", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "284668455005", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "216624486486", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "681348832753", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "035351147821", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "859597730677", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "282025262664", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "262312530599", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "814480443879", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "525921808201", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "119688915426", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "582488909970", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "069019280451", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "187074758985", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "193415116832", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "453052556044", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "829690693026", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "669305197877", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "757211635381", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "585772288577", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "034638983726", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "886388586500", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "608710470296", + "owner": "CloudTrailaws", + "source": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-supported-regions.html" + ], + "description": "" + }, + { + "id": "393727464233", + "owner": "Summit Route", + "source": [ + "https://summitroute.com/aws_security_assessments/" + ], + "description": "" + }, + { + "id": "124790101291", + "owner": "TrendMicro", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "607237235771", + "owner": "TrendMicro", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "675681123645", + "owner": "TrendMicro", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "811620960246", + "owner": "TrendMicro", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "868324285112", + "owner": "TrendMicro", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "665986001363", + "owner": "Convox", + "source": [ + "https://convox.com/docs/aws-integration" + ], + "description": "" + }, + { + "id": "922761411349", + "owner": "Spotinst", + "source": [ + "https://help.spotinst.com/hc/en-us/articles/360000343509-Functions-Permissions-Model-IAM-Role-" + ], + "description": "" + }, + { + "id": "188619942792", + "owner": "Redlock - PrismaCloud", + "source": [ + "https://docs.paloaltonetworks.com/prisma/prisma-cloud/prisma-cloud-admin/connect-your-cloud-platform-to-prisma-cloud/onboard-aws/manually-set-up-prisma-cloud-role-for-aws", + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html" + ], + "description": "" + }, + { + "id": "496947949261", + "owner": "Redlock - PrismaCloud", + "source": [ + "https://docs.paloaltonetworks.com/prisma/prisma-cloud/prisma-cloud-admin/connect-your-cloud-platform-to-prisma-cloud/onboard-aws/manually-set-up-prisma-cloud-role-for-aws", + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html" + ], + "description": "" + }, + { + "id": "926226587429", + "owner": "Sumo Logic", + "source": [ + "https://help.sumologic.com/03Send-Data/Sources/02Sources-for-Hosted-Collectors/Amazon-Web-Services/Grant-Access-to-an-AWS-Product" + ], + "description": "" + }, + { + "id": "890234264427", + "owner": "Bridgecrew", + "source": [ + "https://bridgecrew.cloud" + ], + "description": "" + }, + { + "id": "434813966438", + "owner": "Lacework", + "source": [ + "https://support.lacework.com/hc/en-us/articles/360017546933-Getting-Started" + ], + "description": "" + }, + { + "id": "842984801698", + "owner": "Onelogin", + "source": [ + "https://onelogin.service-now.com/kb_view_customer.do?sysparm_article=KB0010344" + ], + "description": "" + }, + { + "id": "202279780353", + "owner": "nOps", + "source": [ + "https://help.nops.io/manual_setup" + ], + "description": "" + }, + { + "id": "834469178297", + "owner": "Fivetran", + "source": [ + "https://fivetran.com/docs/logs/cloudwatch/setup-guide" + ], + "description": "" + }, + { + "id": "336818582268", + "owner": "Rapid7", + "source": [ + "https://insightvm.help.rapid7.com/docs/aws-connect-to-cloud-configuration-assessment" + ], + "description": "" + }, + { + "id": "414351767826", + "owner": "Databricks", + "source": [ + "https://docs.databricks.com/administration-guide/account-settings/aws-accounts.html", + "https://docs.databricks.com/sql/admin/data-access-configuration.html" + ], + "description": "" + }, + { + "id": "790110701330", + "owner": "Databricks", + "source": [ + "https://docs.databricks.com/administration-guide/account-settings/aws-accounts.html", + "https://docs.databricks.com/sql/admin/data-access-configuration.html" + ], + "description": "" + }, + { + "id": "896126563706", + "owner": "Threat Stack", + "source": [ + "https://threatstack.zendesk.com/hc/en-us/articles/206006626-AWS-EC2-Integration" + ], + "description": "" + }, + { + "id": "799803075172", + "owner": "Lucidchart", + "source": [ + "https://lucidchart.zendesk.com/hc/en-us/articles/208018563-Create-an-IAM-User-or-a-Cross-Account-Role-in-AWS-for-Lucidchart" + ], + "description": "" + }, + { + "id": "353360065216", + "owner": "Workato", + "source": [ + "https://docs.workato.com/connectors/s3.html" + ], + "description": "" + }, + { + "id": "122442690527", + "owner": "Palo Alto Networks", + "source": [ + "https://github.com/terraform-providers/terraform-provider-aws/issues/6674" + ], + "description": "" + }, + { + "id": "061190967865", + "owner": "CloudZero", + "source": [ + "https://www.cloudzero.com/hubfs/CloudZero%20Configuration%20Guide%20-%20Automated.pdf" + ], + "description": "" + }, + { + "id": "232482882421", + "owner": "Cloudinary", + "source": [ + "https://support.cloudinary.com/hc/en-us/articles/203276521-How-do-I-allow-Cloudinary-to-read-from-my-private-S3-bucket-" + ], + "description": "" + }, + { + "id": "012615275169", + "owner": "Tenable", + "source": [ + "https://docs.tenable.com/tenableio/vulnerabilitymanagement/Content/Settings/Connectors_ConfigureAWS_KeylessAutoDiscovery.htm", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "422820575223", + "owner": "Tenable", + "source": [ + "https://docs.tenable.com/tenableio/vulnerabilitymanagement/Content/Settings/Connectors_ConfigureAWS_KeylessAutoDiscovery.htm", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "218546966473", + "owner": "Stitch", + "source": [ + "https://www.stitchdata.com/docs/destinations/amazon-s3/connecting-an-amazon-s3-data-warehouse-to-stitch" + ], + "description": "" + }, + { + "id": "884047677700", + "owner": "Emnify", + "source": [ + "https://www.emnify.com/datastreamer-integration-into-aws" + ], + "description": "" + }, + { + "id": "080595016317", + "owner": "Qualys Cloud View", + "source": [ + "https://qualysguard.qualys.com/qwebhelp/fo_portal/scans/ec2_connector.htm" + ], + "description": "" + }, + { + "id": "205767712438", + "owner": "Qualys Cloud View", + "source": [ + "https://qualysguard.qualys.com/qwebhelp/fo_portal/scans/ec2_connector.htm" + ], + "description": "" + }, + { + "id": "951887872838", + "owner": "Auth0", + "source": [ + "https://auth0.com/docs/integrations/aws/sso" + ], + "description": "" + }, + { + "id": "062663104137", + "owner": "Altus", + "source": [ + "https://blog.cloudera.com/cloudera-altus-cloud-services-youre-in-control-part-2/" + ], + "description": "" + }, + { + "id": "239734009475", + "owner": "AlertLogic", + "source": [ + "https://docs.alertlogic.com/prepare/iam-role-creation.htm#top" + ], + "description": "" + }, + { + "id": "733251395267", + "owner": "AlertLogic", + "source": [ + "https://docs.alertlogic.com/prepare/iam-role-creation.htm#top" + ], + "description": "" + }, + { + "id": "857795874556", + "owner": "AlertLogic", + "source": [ + "https://docs.alertlogic.com/prepare/iam-role-creation.htm#top" + ], + "description": "" + }, + { + "id": "717210094962", + "owner": "CloudConformity", + "source": [ + "https://github.com/cloudconformity/documentation-api/blob/master/Accounts.md#update-account" + ], + "description": "" + }, + { + "id": "854209929931", + "owner": "Fortinet", + "source": [ + "https://fortinetweb.s3.amazonaws.com/docs.fortinet.com/v2/attachments/bf017449-572a-11e9-81a4-00505692583a/forticasb-4.1.0-admin-guide.pdf", + "https://docs.fortinet.com/document/forticwp/4.4.0/online-help/828941/amazon-web-services" + ], + "description": "" + }, + { + "id": "197857026523", + "owner": "Azure Sentinel", + "source": [], + "description": "" + }, + { + "id": "432263259397", + "owner": "Azure Billing Management", + "source": [ + "https://docs.microsoft.com/en-us/azure/cost-management/aws-integration-manage" + ], + "description": "" + }, + { + "id": "835822366011", + "owner": "ADC Application Deployment, ADM Delivery Management", + "source": [ + "https://docs.citrix.com/en-us/citrix-application-delivery-management-service/hybrid-multi-cloud-deployments/autoscale-for-aws/autoscale-for-aws-configuration.html" + ], + "description": "" + }, + { + "id": "695990169366", + "owner": "CloudManager for CloudVolumes", + "source": [ + "https://docs.netapp.com/us-en/cloud_volumes/aws/media/cvs_aws_account_setup.pdf" + ], + "description": "" + }, + { + "id": "802876684602", + "owner": "Axonius.com", + "source": [], + "description": "" + }, + { + "id": "817364327683", + "owner": "Axonius.com", + "source": [], + "description": "" + }, + { + "id": "405773942477", + "owner": "Axonius.com", + "source": [], + "description": "" + }, + { + "id": "370134896156", + "owner": "Fugue", + "source": [ + "https://docs.fugue.co/setup.html", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "944830124550", + "owner": "Fugue", + "source": [ + "https://docs.fugue.co/setup.html", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "057172825058", + "owner": "Fugue", + "source": [ + "https://docs.fugue.co/setup.html", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "810369035479", + "owner": "Fugue", + "source": [ + "https://docs.fugue.co/setup.html", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "863002038009", + "owner": "CloudPhysics", + "source": [ + "https://www.cloudphysics.com/connectaws/" + ], + "description": "" + }, + { + "id": "429269239926", + "owner": "QRadar", + "source": [], + "description": "" + }, + { + "id": "282028653949", + "owner": "LogicMonitor", + "source": [], + "description": "" + }, + { + "id": "307653271100", + "owner": "MVision ePO", + "source": [ + "https://docs.mcafee.com/bundle/prod-name-n.n.x-guide-type/page/GUID-9B6E696A-78DA-4F41-A0FC-39699DD39639.html" + ], + "description": "" + }, + { + "id": "754237914691", + "owner": "Symantec Cloud Workload Protection", + "source": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html" + ], + "description": "" + }, + { + "id": "033496790460", + "owner": "Symantec Cloud Workload Protection", + "source": [], + "description": "" + }, + { + "id": "406095609952", + "owner": "Logz.io", + "source": [], + "description": "" + }, + { + "id": "178591426237", + "owner": "Xi Frame", + "source": [], + "description": "" + }, + { + "id": "270852171095", + "owner": "CloudWisdom, metricly", + "source": [], + "description": "" + }, + { + "id": "216690786812", + "owner": "Rockset", + "source": [], + "description": "" + }, + { + "id": "545334166883", + "owner": "CloudHiro", + "source": [ + "https://cloudhiro.com/AWS/AWSRegistrationGuide.php" + ], + "description": "" + }, + { + "id": "036437403198", + "owner": "Densify", + "source": [ + "https://www.densify.com/docs/Content/Data_Collection_for_Public_Cloud_Systems/AWS_Data_Collection_Prerequisites_for_an_IAM_Role.htm" + ], + "description": "" + }, + { + "id": "679703615338", + "owner": "Armor Anywhere", + "source": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html", + "https://docs.armor.com/pages/viewpage.action?pageId=20709565" + ], + "description": "" + }, + { + "id": "345186984524", + "owner": "Armor Anywhere", + "source": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html", + "https://docs.armor.com/pages/viewpage.action?pageId=20709565" + ], + "description": "" + }, + { + "id": "765628985471", + "owner": "Genys", + "source": [ + "https://help.mypurecloud.com/articles/create-iam-resources-to-invoke-an-aws-lambda-function/" + ], + "description": "" + }, + { + "id": "949777495771", + "owner": "site24x7", + "source": [], + "description": "" + }, + { + "id": "710193521658", + "owner": "ylastic", + "source": [ + "https://blog.ylastic.com/post/153943542476/iam-role-with-external-id-for-cross-account-access" + ], + "description": "" + }, + { + "id": "805246085872", + "owner": "qubole", + "source": [ + "https://docs.qubole.com/en/latest/user-guide/managing-accounts/aws/iam-roles/override-iam-roles.html" + ], + "description": "" + }, + { + "id": "200235630647", + "owner": "VManage", + "source": [ + "https://www.cisco.com/c/en/us/td/docs/routers/sdwan/configuration/Network-Optimization-and-High-Availability/Network-Optimization-High-Availability-book/b_Network-Optimization-and-HA_chapter_00.html" + ], + "description": "" + }, + { + "id": "814021343637", + "owner": "Cloudaware", + "source": [], + "description": "" + }, + { + "id": "558211695259", + "owner": "Cloud Ranger", + "source": [], + "description": "" + }, + { + "id": "843529240033", + "owner": "FoxPass", + "source": [ + "https://docs.foxpass.com/docs/access-control-integration-with-amazon-ec2" + ], + "description": "" + }, + { + "id": "094919933512", + "owner": "Nirmata", + "source": [ + "https://nirmata-documentation.readthedocs.io/en/latest/CloudProviders.html" + ], + "description": "" + }, + { + "id": "855262394183", + "owner": "GitLab", + "source": [], + "description": "" + }, + { + "id": "956491294349", + "owner": "GitLab", + "source": [], + "description": "" + }, + { + "id": "198361731867", + "owner": "Snyk", + "source": [ + "https://support.snyk.io/hc/en-us/articles/360004002418-AWS-Lambda-integration", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "755778135062", + "owner": "Snyk", + "source": [ + "https://support.snyk.io/hc/en-us/articles/360004002418-AWS-Lambda-integration", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "968898580625", + "owner": "CloudCraft", + "source": [], + "description": "" + }, + { + "id": "612791702201", + "owner": "JupiterOne", + "source": [ + "https://github.com/JupiterOne/jupiterone-aws-cloudformation/commit/c9abbbcc3e29474c6605a6f8ace5ec0ff475d3f8" + ], + "description": "" + }, + { + "id": "414502572119", + "owner": "rev.com", + "source": [ + "https://www.rev.com/api/s3bucketpolicy" + ], + "description": "" + }, + { + "id": "071303700930", + "owner": "Funnel", + "source": [ + "https://help.funnel.io/en/articles/1494351-amazon-s3-bucket-configuration" + ], + "description": "" + }, + { + "id": "339405024189", + "owner": "Domo", + "source": [ + "https://knowledge.domo.com/Connect/Connecting_to_Data_with_Connectors/Configuring_Each_Connector/Connectors_for_File_Retrieval/Amazon_S3_AssumeRole_Connector" + ], + "description": "" + }, + { + "id": "010251424122", + "owner": "Domo", + "source": [ + "https://knowledge.domo.com/Connect/Connecting_to_Data_with_Connectors/Configuring_Each_Connector/Connectors_for_File_Retrieval/Amazon_S3_AssumeRole_Connector" + ], + "description": "" + }, + { + "id": "687132894031", + "owner": "Domo", + "source": [ + "https://knowledge.domo.com/Connect/Connecting_to_Data_with_Connectors/Configuring_Each_Connector/Connectors_for_File_Retrieval/Amazon_S3_AssumeRole_Connector" + ], + "description": "" + }, + { + "id": "622384692065", + "owner": "Domo", + "source": [ + "https://knowledge.domo.com/Connect/Connecting_to_Data_with_Connectors/Configuring_Each_Connector/Connectors_for_File_Retrieval/Amazon_S3_AssumeRole_Connector" + ], + "description": "" + }, + { + "id": "962727799805", + "owner": "Atlas DataLake", + "source": [], + "description": "" + }, + { + "id": "428641199958", + "owner": "Upsolver", + "source": [], + "description": "" + }, + { + "id": "376248598259", + "owner": "Weave Cloud", + "source": [ + "https://eksctl.io/" + ], + "description": "" + }, + { + "id": "515570774723", + "owner": "ChaosSearch", + "source": [ + "https://docs.chaossearch.io/docs/prerequisites" + ], + "description": "" + }, + { + "id": "305753120797", + "owner": "EDB Postgres", + "source": [ + "https://www.enterprisedb.com/edb-docs/d/edb-postgres-ark-platform/user-guides/administrative-users-guide/3.0/EDB_Ark_Administrative_User_Guide.1.20.html" + ], + "description": "" + }, + { + "id": "726941830086", + "owner": "TheGlobalSolutions.net", + "source": [ + "http://www.theglobalsolutions.net/awspatching/saas_help.php" + ], + "description": "" + }, + { + "id": "902500896138", + "owner": "wpengine", + "source": [ + "https://wpengine.com/support/configuring-largefs-store-transfer-unlimited-data/" + ], + "description": "" + }, + { + "id": "759994998399", + "owner": "cloudsqueeze", + "source": [ + "https://app.cloudsqueeze.ai/awsAddAccount" + ], + "description": "" + }, + { + "id": "675479154635", + "owner": "ThingSpace", + "source": [ + "https://thingspace.verizon.com/resources/documentation/cloudconnector/Getting_Started/Streaming_to_AWS/" + ], + "description": "" + }, + { + "id": "340481513670", + "owner": "Anodot", + "source": [ + "https://support.anodot.com/hc/en-us/articles/360034553113-Enable-Reading-from-the-Kinesis-Stream" + ], + "description": "" + }, + { + "id": "794878508631", + "owner": "MediaMath", + "source": [ + "https://apidocs.mediamath.com/reporting/log-level-data-service/overview#data-security-and-authorization" + ], + "description": "" + }, + { + "id": "118652503430", + "owner": "Presidio", + "source": [ + "customer IAM policy" + ], + "description": "" + }, + { + "id": "634729597623", + "owner": "Checkpoint Cloudguard", + "source": [ + "https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk159912&partition=Basic&product=CloudGuard" + ], + "description": "" + }, + { + "id": "568526795995", + "owner": "Cisco Umbrella", + "source": [ + "https://docs.umbrella.com/umbrella-user-guide/docs/enable-logging-to-your-own-s3-bucket" + ], + "description": "" + }, + { + "id": "391854517948", + "owner": "Cloudflare", + "source": [ + "https://developers.cloudflare.com/logs/logpush/aws-s3" + ], + "description": "" + }, + { + "id": "858827067514", + "owner": "[Deprecated] AWS Log delivery Service", + "source": [ + "https://forums.aws.amazon.com/thread.jspa?messageID=629256" + ], + "description": "" + }, + { + "id": "066549572091", + "owner": "Epsagon", + "source": [ + "https://docs.epsagon.com/docs/faq" + ], + "description": "" + }, + { + "id": "287590803701", + "owner": "Turbot", + "source": [ + "https://turbot.com/v5/docs/integrations/aws/import-aws-account" + ], + "description": "" + }, + { + "id": "255798382450", + "owner": "Turbot", + "source": [ + "https://turbot.com/v5/docs/integrations/aws/import-aws-account" + ], + "description": "" + }, + { + "id": "805950163170", + "owner": "Qualys AWS EC2 Connector", + "source": [ + "https://qualys-secure.force.com/discussions/s/question/0D52L00004TnxTqSAJ/aws-ec2-connector-creation-automation" + ], + "description": "" + }, + { + "id": "438908802199", + "owner": "Qualys", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "392220576650", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "718770453195", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "968246515281", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "109351309407", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "796887884028", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "631144002099", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "544388816663", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "061510835048", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "474240146802", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "166639821150", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "394634713161", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "753362059629", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "359345898052", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "969236854626", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "020402002396", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "195145609632", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "798376113853", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "652364314486", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "849137399833", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "507069717855", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "644042651268", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "174803364771", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "287228555773", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "855739686837", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "614065512851", + "owner": "API Gatewayaws", + "source": [ + "https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-accounts.html" + ], + "description": "" + }, + { + "id": "152659312504", + "owner": "Slack EKM", + "source": [ + "https://slackhq.com/dotcom/dotcom/wp-content/uploads/sites/6/2019/08/Slack-EKM-Implementation-Guide-1.pdf" + ], + "description": "" + }, + { + "id": "429538831549", + "owner": "Slack EKM", + "source": [ + "https://slackhq.com/dotcom/dotcom/wp-content/uploads/sites/6/2019/08/Slack-EKM-Implementation-Guide-1.pdf" + ], + "description": "" + }, + { + "id": "316881668097", + "owner": "Steampipe Cloud", + "source": [ + "https://cloud.steampipe.io/user//create/connection" + ], + "description": "" + }, + { + "id": "398997493752", + "owner": "unusd.cloud", + "source": [ + "https://unusd-cloud-saas-prod-artifacts-spoke.s3.eu-west-1.amazonaws.com/spoke-role.yml" + ], + "description": "" + }, + { + "id": "310957700191", + "owner": "CloudYali", + "source": [ + "https://docs.cloudyali.io/docs/connecting_aws" + ], + "description": "" + }, + { + "id": "423155938983", + "owner": "SSLMate", + "source": [ + "https://sslmate.com/help/reference/misc#aws_integration" + ], + "description": "" + }, + { + "id": "056196542512", + "owner": "SSLMate (Sandbox Site)", + "source": [ + "https://sslmate.com/help/reference/misc#aws_integration" + ], + "description": "" + }, + { + "id": "761931097553", + "owner": "Sysdig", + "source": [ + "https://docs.sysdig.com/en/docs/administration/saas-regions-and-ip-ranges/#aws-account-ids" + ], + "description": "" + }, + { + "id": "263844535661", + "owner": "Sysdig", + "source": [ + "https://docs.sysdig.com/en/docs/administration/saas-regions-and-ip-ranges/#aws-account-ids" + ], + "description": "" + }, + { + "id": "203796963081", + "owner": "MadKudu", + "source": [ + "https://support.madkudu.com/hc/en-us/articles/360036908291-Amazon-S3-Giving-MadKudu-access-to-an-S3-bucket" + ], + "description": "" + }, + { + "id": "913128560467", + "owner": "env0", + "source": [ + "https://docs.env0.com/docs/aws-costs" + ], + "description": "" + }, + { + "id": "032379705303", + "owner": "BuildKite (log output)", + "source": [ + "https://buildkite.com/docs/pipelines/managing-log-output" + ], + "description": "" + }, + { + "id": "324880187172", + "owner": "Spacelift", + "source": [ + "https://docs.spacelift.io/integrations/cloud-providers/aws" + ], + "description": "" + }, + { + "id": "826438284864", + "owner": "k9 security", + "source": [ + "https://www.k9security.io/docs/how-to-configure-k9-access/", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "139710491120", + "owner": "k9 security", + "source": [ + "https://www.k9security.io/docs/how-to-configure-k9-access/", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "720226181253", + "owner": "k9 security", + "source": [ + "https://www.k9security.io/docs/how-to-configure-k9-access/", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "457424274508", + "owner": "Codeshield", + "source": [ + "https://codeshield-public-templates-production.s3.eu-central-1.amazonaws.com/aws_connect_codeshield.yml" + ], + "description": "" + }, + { + "id": "746108190720", + "owner": "OpsLevel", + "source": [ + "https://docs.opslevel.com/docs/infrastructure" + ], + "description": "" + }, + { + "id": "368064434614", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "790247189693", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "703715109447", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "473191095985", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "420376844563", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "651179539253", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "297058826802", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "623197973179", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "945512339897", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "408097707231", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "398671365691", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "713597048934", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "960118270566", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "485979073181", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "615915377779", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "764870610256", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "434091160558", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "246478207311", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "885798887673", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "041313461515", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "694668203235", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "553461782468", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "668912161003", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "028811157404", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "051362938876", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "595013617770", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "392442076723", + "owner": "Redshift loggingaws", + "source": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/logging-with-cloudtrail.html" + ], + "description": "" + }, + { + "id": "024196225137", + "owner": "DuckbillGroup", + "source": [ + "https://www.lastweekinaws.com/blog/are-aws-account-ids-sensitive-information/" + ], + "description": "" + }, + { + "id": "008923505280", + "owner": "Grafana", + "source": [ + "https://grafana.com/docs/grafana-cloud/integrations/integrations/integration-cloudwatch/" + ], + "description": "" + }, + { + "id": "976280145156", + "owner": "Orca Security", + "source": [ + "https://orcasecurity.force.com/s/article/Orca-Scanner-Accounts-for-AWS-Trusted-Entities?topic=Onboarding&subtopic=AWS&article=Orca-Scanner-Accounts-for-AWS-Trusted-Entities" + ], + "description": "" + }, + { + "id": "727815099310", + "owner": "Orca Security", + "source": [ + "https://orcasecurity.force.com/s/article/Orca-Scanner-Accounts-for-AWS-Trusted-Entities?topic=Onboarding&subtopic=AWS&article=Orca-Scanner-Accounts-for-AWS-Trusted-Entities" + ], + "description": "" + }, + { + "id": "553950354547", + "owner": "Orca Security", + "source": [ + "https://orcasecurity.force.com/s/article/Orca-Scanner-Accounts-for-AWS-Trusted-Entities?topic=Onboarding&subtopic=AWS&article=Orca-Scanner-Accounts-for-AWS-Trusted-Entities" + ], + "description": "" + }, + { + "id": "135916806842", + "owner": "Orca Security", + "source": [ + "https://orcasecurity.force.com/s/article/Orca-Scanner-Accounts-for-AWS-Trusted-Entities?topic=Onboarding&subtopic=AWS&article=Orca-Scanner-Accounts-for-AWS-Trusted-Entities" + ], + "description": "" + }, + { + "id": "463932680998", + "owner": "Orca Security", + "source": [ + "https://orcasecurity.force.com/s/article/Orca-Scanner-Accounts-for-AWS-Trusted-Entities?topic=Onboarding&subtopic=AWS&article=Orca-Scanner-Accounts-for-AWS-Trusted-Entities" + ], + "description": "" + }, + { + "id": "784971140435", + "owner": "Orca Security", + "source": [ + "https://orcasecurity.force.com/s/article/Orca-Scanner-Accounts-for-AWS-Trusted-Entities?topic=Onboarding&subtopic=AWS&article=Orca-Scanner-Accounts-for-AWS-Trusted-Entities" + ], + "description": "" + }, + { + "id": "151784055945", + "owner": "Barracuda Networks", + "source": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html" + ], + "description": "" + }, + { + "id": "758245563457", + "owner": "Check Point", + "source": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html" + ], + "description": "" + }, + { + "id": "517716713836", + "owner": "CrowdStrike", + "source": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html" + ], + "description": "" + }, + { + "id": "292230061137", + "owner": "CrowdStrike", + "source": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html" + ], + "description": "" + }, + { + "id": "749430749651", + "owner": "CyberArk", + "source": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html" + ], + "description": "" + }, + { + "id": "365761988620", + "owner": "Forcepoint", + "source": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html" + ], + "description": "" + }, + { + "id": "062897671886", + "owner": "Sophos", + "source": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html" + ], + "description": "" + }, + { + "id": "978576646331", + "owner": "Vectra", + "source": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html" + ], + "description": "" + }, + { + "id": "453761072151", + "owner": "Turbot", + "source": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html" + ], + "description": "" + }, + { + "id": "956882708938", + "owner": "Sumo Logic", + "source": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-partner-providers.html", + "https://help.sumologic.com/docs/send-data/collect-from-other-data-sources/collect-aws-lambda-logs-extension/#aws-lambda-functions-created-using-zip-files-blueprint-serverless-applications" + ], + "description": "" + }, + { + "id": "081802104111", + "owner": "Ermetic", + "source": [ + "https://github.com/ermetic/utilities/blob/main/AWS/ControlTower/cloudformation/ermetic-controltower.yaml" + ], + "description": "" + }, + { + "id": "672188301118", + "owner": "Zesty", + "source": [ + "https://github.com/zesty-co/AWS-Integration/blob/main/Zesty-Minimal-ReadOnly-IAM-Role.json" + ], + "description": "" + }, + { + "id": "802587217904", + "owner": "Serverless", + "source": [ + "https://www.serverless.com/framework/docs/guides/monitoring/notifications" + ], + "description": "" + }, + { + "id": "983328018169", + "owner": "UiPath", + "source": [ + "https://forum.uipath.com/t/how-to-configure-aws-s3-storage-bucket-log-export-configuration-for-orchestrator-service-in-automation-cloud/506448" + ], + "description": "" + }, + { + "id": "242987662583", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "118283430703", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "144182107116", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "934957504740", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "107430051933", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "973841112453", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "965013871422", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "506403581195", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "436163563069", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "378365507264", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "383009515534", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "646602203151", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "741172661024", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "464168911255", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "476419727788", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "457615622431", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "926826061926", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "955633302743", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "430639793359", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "002991280229", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "003033775354", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "552740612889", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "030935290150", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "188461706213", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "445632894446", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "143972945659", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "129086577509", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "225965583551", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "595653072700", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "529900636122", + "owner": "GuardDuty Announcementsaws", + "source": [ + "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_sns.html" + ], + "description": "" + }, + { + "id": "013241004608", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "066635153087", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "151742754352", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "296578399912", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "455263428931", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "491585149902", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "558608220178", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "590381155156", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "602401143452", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "759879836304", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "800184023465", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "877085696533", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "900612956339", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "900889452093", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "918309763551", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "961992271922", + "owner": "EKS ECR Repositoriesaws", + "source": [ + "https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html" + ], + "description": "" + }, + { + "id": "956993596390", + "owner": "Vantaaws", + "source": [ + "https://help.vanta.com/hc/en-us/articles/8451925240980-Connecting-Vanta-AWS-Organization" + ], + "description": "" + }, + { + "id": "269135526815", + "owner": "Drataaws", + "source": [ + "https://github.com/drata/terraform-aws-drata-autopilot-role/blob/f774d423a62df3a3dd03008a68c3b3d70b95be33/variables.tf#L1-L5", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "085540434294", + "owner": "Drataaws", + "source": [ + "https://github.com/drata/terraform-aws-drata-autopilot-role/blob/f774d423a62df3a3dd03008a68c3b3d70b95be33/variables.tf#L1-L5", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "809336252980", + "owner": "Drataaws", + "source": [ + "https://github.com/drata/terraform-aws-drata-autopilot-role/blob/f774d423a62df3a3dd03008a68c3b3d70b95be33/variables.tf#L1-L5", + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "068664126052", + "owner": "DoItaws", + "source": [ + "https://help.doit.com/docs/flexsave/aws/standalone/required-policies" + ], + "description": "" + }, + { + "id": "205499583182", + "owner": "ProsperOpsaws", + "source": [ + "https://console.prosperops.com/onboarding" + ], + "description": "" + }, + { + "id": "727378841472", + "owner": "nOpsaws", + "source": [ + "https://help.nops.io/iam-yaml-sharesave.html#sharesave-yaml-file" + ], + "description": "" + }, + { + "id": "826182721854", + "owner": "Usage AIaws", + "source": [ + "https://cloudopt.usage.ai/onboard" + ], + "description": "" + }, + { + "id": "217452466226", + "owner": "Mackerelaws", + "source": [ + "https://mackerel.io/docs/entry/integrations/aws#:~:text=How%20to%20configure%20an%20IAM%20role" + ], + "description": "" + }, + { + "id": "099720109477", + "owner": "Canonicalaws", + "source": [ + "https://ubuntu.com/server/docs/cloud-images/amazon-ec2" + ], + "description": "" + }, + { + "id": "967800896805", + "owner": "Archeraaws", + "source": [ + "https://help.archera.ai/en/articles/5611146-what-is-the-archera-aws-account-id" + ], + "description": "" + }, + { + "id": "202754554539", + "owner": "Archeraaws", + "source": [ + "https://help.archera.ai/en/articles/5611146-what-is-the-archera-aws-account-id" + ], + "description": "" + }, + { + "id": "451234325714", + "owner": "Flexeraaws", + "source": [ + "https://github.com/flexera-public/aws-control-tower/blob/1da3eb7d96e6f31cf64fa317d77a3405ac61431f/template/flexeraOptimaAWSControlTower.yaml#L227" + ], + "description": "" + }, + { + "id": "902542641901", + "owner": "Temporal Technologies, Inc.aws", + "source": [ + "https://temporal-auditlogs-config.s3.us-west-2.amazonaws.com/cloudformation/iam-role-for-temporal-audit-logs.yaml" + ], + "description": "" + }, + { + "id": "160190466495", + "owner": "Temporal Technologies, Inc.aws", + "source": [ + "https://temporal-auditlogs-config.s3.us-west-2.amazonaws.com/cloudformation/iam-role-for-temporal-audit-logs.yaml" + ], + "description": "" + }, + { + "id": "819232936619", + "owner": "Temporal Technologies, Inc.aws", + "source": [ + "https://temporal-auditlogs-config.s3.us-west-2.amazonaws.com/cloudformation/iam-role-for-temporal-audit-logs.yaml" + ], + "description": "" + }, + { + "id": "829909441867", + "owner": "Temporal Technologies, Inc.aws", + "source": [ + "https://temporal-auditlogs-config.s3.us-west-2.amazonaws.com/cloudformation/iam-role-for-temporal-audit-logs.yaml" + ], + "description": "" + }, + { + "id": "354116250941", + "owner": "Temporal Technologies, Inc.aws", + "source": [ + "https://temporal-auditlogs-config.s3.us-west-2.amazonaws.com/cloudformation/iam-role-for-temporal-audit-logs.yaml" + ], + "description": "" + }, + { + "id": "253602268883", + "owner": "RunRevealaws", + "source": [ + "https://runreveal-public-assets.s3.us-east-2.amazonaws.com/runreveal-cloudformation.yml" + ], + "description": "" + }, + { + "id": "536727724300", + "owner": "MongoDB Atlasaws", + "source": [ + "https://github.com/mongodb/mongodbatlas-cloudformation-resources/blob/50e556bb4641ac6baed07a3b3b5bbf28c01d73bc/cfn-resources/datalakes/test/add-policy.json" + ], + "description": "" + }, + { + "id": "252516302205", + "owner": "AWS First-Party Security Hub Productsaws", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "368434119798", + "owner": "AWS First-Party Security Hub Productsaws", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "592144602629", + "owner": "AWS First-Party Security Hub Productsaws", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "615243839755", + "owner": "AWS First-Party Security Hub Productsaws", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "814336688286", + "owner": "AWS First-Party Security Hub Productsaws", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "916309344264", + "owner": "AWS First-Party Security Hub Productsaws", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "005076071273", + "owner": "AWS First-Party Security Hub Productsaws", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "005891025715", + "owner": "AWS First-Party Security Hub Productsaws", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "080354740365", + "owner": "AWS First-Party Security Hub Productsaws", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "758058086616", + "owner": "AWS First-Party Security Hub Productsaws", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "381031177744", + "owner": "AttackIQ", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "631402103377", + "owner": "Caveonix", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "015990171708", + "owner": "Claroty", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "820923007224", + "owner": "Claroty", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "883241448326", + "owner": "Claroty", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "490991382221", + "owner": "Contrast Security", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "763284681916", + "owner": "Contrast Security", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "013944500484", + "owner": "DisruptOps, Inc.", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "264756907367", + "owner": "FireEye", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "324264561773", + "owner": "Guardicore", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "949680696695", + "owner": "IBM", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "297986523463", + "owner": "McAfee", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "091741439927", + "owner": "NETSCOUT", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "585459848136", + "owner": "SecureCloudDB", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "842447150064", + "owner": "ServiceNow", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "112543817624", + "owner": "Splunk", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "044642040396", + "owner": "Plerion", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "173985203412", + "owner": "Plerion", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "588158338731", + "owner": "Plerion", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "736689547456", + "owner": "Plerion", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "213217834095", + "owner": "Sonrai Security", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "380873608913", + "owner": "Sonrai Security", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + }, + { + "id": "717025312494", + "owner": "Sonrai Security", + "source": [ + "https://blog.plerion.com/the-deputy-is-confused-about-aws-security-hub/" + ], + "description": "" + } +] \ No newline at end of file diff --git a/awsxenos/config.yaml b/awsxenos/config.yaml new file mode 100644 index 0000000..5bb79ed --- /dev/null +++ b/awsxenos/config.yaml @@ -0,0 +1,21 @@ +plugins: + - module: s3 + class: S3 + - module: s3 + class: S3ACL + - module: s3 + class: S3Glacier + - module: iam + class: IAM + - module: kms + class: KMS + - module: secretsmanager + class: SecretsManager + - module: eventbridge + class: EventBus + - module: lambda + class: LambdaResource + - module: sqs + class: SQS + - module: efs + class: EFSResource \ No newline at end of file diff --git a/awsxenos/finding.py b/awsxenos/finding.py index f6fbf22..5dae15d 100644 --- a/awsxenos/finding.py +++ b/awsxenos/finding.py @@ -1,5 +1,11 @@ +import abc +from collections import defaultdict, UserDict from dataclasses import dataclass, field -from typing import List +from typing import Any, DefaultDict, List, Set + +from policyuniverse.arn import ARN # type: ignore +from policyuniverse.policy import Policy # type: ignore +from policyuniverse.statement import ConditionTuple # type: ignore @dataclass @@ -15,8 +21,109 @@ def __str__(self) -> str: @dataclass -class AccountType: +class Accounts: org_accounts: List[Finding] = field(default_factory=list) known_accounts: List[Finding] = field(default_factory=list) unknown_accounts: List[Finding] = field(default_factory=list) aws_services: List[Finding] = field(default_factory=list) + + def __getitem__(self, key): + return super().__getattribute__(key) + + +class Findings(UserDict): + def __missing__(self, key): + self[key] = Accounts() + return self[key] + + +class Resources(UserDict): + def __missing__(self, key): + self[key] = defaultdict() + return self[key] + + +class Service(metaclass=abc.ABCMeta): + @abc.abstractmethod + def fetch(self, accounts: DefaultDict[str, Set], **kwargs) -> Findings: + raise NotImplementedError + + def collate(self, accounts: DefaultDict[str, Set], resources: Resources) -> Findings: + """Combine all accounts with all the resources to classify findings. Try custom_collate first and fallback to this. + + Args: + accounts (DefaultDict[str, Set]): Key of account type. Value account ids + resources (DefaultDict[str, Dict[Any, Any]]): Key ResourceIdentifier. Value Dict PolicyDocument + + Returns: + DefaultDict[str, AccountType]: Key of ARN, Value of AccountType + """ + + findings = Findings() + for resource, policy_document in resources.items(): + try: + policy = Policy(policy_document) + except: + continue + for unparsed_principal in policy.whos_allowed(): + try: + principal = ARN(unparsed_principal.value) # type: Any + except Exception as e: + print(e) + findings[resource].known_accounts.append(Finding(principal=unparsed_principal, external_id=True)) + continue + # Check if Principal is an AWS Service + if principal.service: + findings[resource].aws_services.append(Finding(principal=principal.arn, external_id=True)) + # Check against org_accounts + elif principal.account_number in accounts["org_accounts"]: + findings[resource].org_accounts.append(Finding(principal=principal.arn, external_id=True)) + # Check against known external accounts + elif ( + principal.account_number in accounts["known_accounts"] + or ConditionTuple(category="saml-endpoint", value="https://signin.aws.amazon.com/saml") + in policy.whos_allowed() + ): + sts_set = False + for pstate in policy.statements: + if "sts" in pstate.action_summary(): + try: + conditions = [ + k.lower() for k in list(pstate.statement["Condition"]["StringEquals"].keys()) + ] + if "sts:externalid" in conditions: + findings[resource].known_accounts.append( + Finding(principal=principal.arn, external_id=True) + ) + except: + findings[resource].known_accounts.append( + Finding(principal=principal.arn, external_id=False) + ) + finally: + sts_set = True + break + if not sts_set: + findings[resource].known_accounts.append(Finding(principal=principal.arn, external_id=False)) + + # Unknown Account + else: + sts_set = False + for pstate in policy.statements: + if "sts" in pstate.action_summary(): + try: + conditions = [ + k.lower() for k in list(pstate.statement["Condition"]["StringEquals"].keys()) + ] + if "sts:externalid" in conditions: + findings[resource].unknown_accounts.append( + Finding(principal=principal.arn, external_id=True) + ) + except: + findings[resource].unknown_accounts.append( + Finding(principal=principal.arn, external_id=False) + ) + finally: + break + if not sts_set: + findings[resource].unknown_accounts.append(Finding(principal=principal.arn, external_id=False)) + return findings diff --git a/awsxenos/report.py b/awsxenos/report.py index cf4c1a6..5823e5f 100644 --- a/awsxenos/report.py +++ b/awsxenos/report.py @@ -1,63 +1,61 @@ -from collections import defaultdict -from typing import List, Dict, DefaultDict import json +from collections import defaultdict +from typing import DefaultDict, Dict, List from jinja2 import Environment, FileSystemLoader # type: ignore from policyuniverse.arn import ARN # type: ignore -from awsxenos.finding import AccountType, Finding from awsxenos import package_path +from awsxenos.finding import Findings, Resources + class Report: - def __init__(self, findings: DefaultDict[str, AccountType], account_info: DefaultDict[str, Dict]) -> None: + def __init__(self, findings: Findings, account_info: Resources) -> None: self.summary = self._summarise(findings, account_info) - def _summarise( - self, findings: DefaultDict[str, AccountType], account_info: DefaultDict[str, Dict] - ) -> DefaultDict[str, List]: + def _summarise(self, findings: Findings, account_info: Resources) -> DefaultDict[str, List]: summary = defaultdict(list) - for resource, accounttype in findings.items(): - # Refactor - # for account_type, principal in finding - if accounttype.known_accounts: - for finding in accounttype.known_accounts: + + for resource, account_type in findings.items(): + if account_type.known_accounts: + for finding in account_type.known_accounts: role_arn = ARN(finding.principal) summary["known_accounts"].append( { "ARN": resource, - "principal": accounttype.known_accounts, + "principal": account_type.known_accounts, "external_info": account_info[role_arn.account_number], "external_id": finding.external_id, } ) - if accounttype.org_accounts: - for finding in accounttype.org_accounts: + if account_type.org_accounts: + for finding in account_type.org_accounts: role_arn = ARN(finding.principal) summary["org_accounts"].append( { "ARN": resource, - "principal": accounttype.org_accounts, + "principal": account_type.org_accounts, "external_info": account_info[role_arn.account_number], } ) - if accounttype.aws_services: - for finding in accounttype.aws_services: + if account_type.aws_services: + for finding in account_type.aws_services: role_arn = ARN(finding.principal) summary["aws_services"].append( { "ARN": resource, - "principal": accounttype.aws_services, + "principal": account_type.aws_services, "external_info": account_info[role_arn.tech], } ) - if accounttype.unknown_accounts: - for finding in accounttype.unknown_accounts: + if account_type.unknown_accounts: + for finding in account_type.unknown_accounts: role_arn = ARN(finding.principal) summary["unknown_accounts"].append( { "ARN": resource, - "principal": accounttype.unknown_accounts, + "principal": account_type.unknown_accounts, "external_info": account_info[role_arn.account_number], "external_id": finding.external_id, } diff --git a/awsxenos/scan.py b/awsxenos/scan.py index 0ea1074..3a49223 100755 --- a/awsxenos/scan.py +++ b/awsxenos/scan.py @@ -1,45 +1,43 @@ #!/usr/bin/env python3 - import argparse -from collections import defaultdict -from re import I -from typing import Any, Optional, Dict, List, DefaultDict, Set +import concurrent.futures +import importlib import json import sys +from typing import Any, Callable, Dict + import boto3 # type: ignore -from botocore.exceptions import ClientError # type: ignore -from policyuniverse.arn import ARN # type: ignore -from policyuniverse.policy import Policy # type: ignore -from policyuniverse.statement import Statement, ConditionTuple # type: ignore +import yaml # type: ignore -from awsxenos.finding import AccountType, Finding -from awsxenos.report import Report from awsxenos import package_path +from awsxenos.finding import Accounts, Findings, Resources +from awsxenos.report import Report + +""" +High level architecture -class Scan: - def __init__(self, exclude_service: Optional[bool] = True, exclude_aws: Optional[bool] = True) -> None: - self.known_accounts_data = defaultdict(dict) # type: DefaultDict[str, Dict[Any, Any]] - self.findings = defaultdict(AccountType) # type: DefaultDict[str, AccountType] +1. Run prescan to collect org_accounts and buckets. +2. Load config, instantiate classes, submit to ThreadPoolExecutor to run "fetch" +3. Each fetch will return `Findings` by running `collate` or `custom_collate` +4. Pass the findings to `Report` +""" + + +class PreScan: + def __init__(self): + self.known_accounts = Resources() self._buckets = self.list_account_buckets() - self.roles = self.get_roles(exclude_service, exclude_aws) self.accounts = self.get_all_accounts() - self.bucket_policies = self.get_bucket_policies() - self.bucket_acls = self.get_bucket_acls() - for resource in ["roles", "bucket_policies", "bucket_acls"]: - if resource != "bucket_acls": - self.findings.update(self.collate_findings(self.accounts, getattr(self, resource))) - else: - self.findings.update(self.collate_acl_findings(self.accounts, getattr(self, resource))) - - def get_org_accounts(self) -> DefaultDict[str, Dict]: + + def get_org_accounts(self) -> Resources: """Get Account Ids from the AWS Organization Returns: DefaultDict: Key of Account Ids. Value of other Information """ - accounts = defaultdict(dict) # type: DefaultDict[str, Dict] + accounts = Resources() orgs = boto3.client("organizations") paginator = orgs.get_paginator("list_accounts") try: @@ -53,231 +51,77 @@ def get_org_accounts(self) -> DefaultDict[str, Dict]: print(e) return accounts - def get_bucket_acls(self) -> DefaultDict[str, List[Dict[Any, Any]]]: - bucket_acls = defaultdict(str) - buckets = self._buckets - s3 = boto3.client("s3") - for bucket in buckets["Buckets"]: - bucket_arn = f'arn:aws:s3:::{bucket["Name"]}' - try: - bucket_acls[bucket_arn] = s3.get_bucket_acl(Bucket=bucket["Name"])["Grants"] - except ClientError as e: - if e.response["Error"]["Code"] == "AccessDenied": - bucket_acls[bucket_arn] = [ - { - "Grantee": {"DisplayName": "AccessDenied", "ID": "AccessDenied", "Type": "CanonicalUser"}, - "Permission": "FULL_CONTROL", - } - ] - else: - print(e) - continue - return bucket_acls - - def get_bucket_policies(self) -> DefaultDict[str, Dict[Any, Any]]: - """Get a dictionary of buckets and their policies from the AWS Account - - Returns: - DefaultDict[str, str]: Key of BucketARN, Value of PolicyDocument - """ - bucket_policies = defaultdict(str) - buckets = self._buckets - s3 = boto3.client("s3") - for bucket in buckets["Buckets"]: - bucket_arn = f'arn:aws:s3:::{bucket["Name"]}' - try: - bucket_policies[bucket_arn] = json.loads(s3.get_bucket_policy(Bucket=bucket["Name"])["Policy"]) - except ClientError as e: - if e.response["Error"]["Code"] == "AccessDenied": - bucket_policies[bucket_arn] = { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "AccessDeniedOnResource", - "Effect": "Allow", - "Principal": {"AWS": ["arn:aws:iam::111122223333:root"]}, - "Action": ["s3:*"], - "Resource": f"{bucket_arn}", - } - ], - } - continue - elif e.response["Error"]["Code"] == "NoSuchBucketPolicy": - continue - else: - print(e) - continue - return bucket_policies - - def get_roles( - self, exclude_service: Optional[bool] = True, exclude_aws: Optional[bool] = True - ) -> DefaultDict[str, Dict[Any, Any]]: - """Get a dictionary of roles and their policies from the AWS Account - - Args: - exclude_service (Optional[bool], optional): exclude roles starting with /service-role/. Defaults to True. - exclude_aws (Optional[bool], optional): exclude roles starting with /aws-service-role/. Defaults to True. - - Returns: - DefaultDict[str, str]: Key of RoleNames, Value of AssumeRolePolicyDocument - """ - roles = defaultdict(str) - iam = boto3.client("iam") - paginator = iam.get_paginator("list_roles") - role_iterator = paginator.paginate() - for role_resp in role_iterator: - for role in role_resp["Roles"]: - if role["Path"] == "/service-role/" and exclude_service: - continue - elif role["Path"].startswith("/aws-service-role/") and exclude_aws: - continue - else: - roles[role["Arn"]] = role["AssumeRolePolicyDocument"] - - return roles - def list_account_buckets(self) -> Dict[str, Dict[Any, Any]]: s3 = boto3.client("s3") return s3.list_buckets() - def get_all_accounts(self) -> DefaultDict[str, Set]: + def get_all_accounts(self) -> Accounts: """Get all known accounts and from the AWS Organization Returns: DefaultDict[str, Set]: Key of account type. Value account ids """ - accounts = defaultdict(set) # type: DefaultDict[str, Set] + accounts = Accounts() with open(f"{package_path.resolve().parent}/accounts.json", "r") as f: accounts_file = json.load(f) for account in accounts_file: - self.known_accounts_data[account["id"]] = account + self.known_accounts[account["id"]] = account - accounts["known_accounts"] = set(self.known_accounts_data.keys()) + accounts.known_accounts = set(self.known_accounts.keys()) # type: ignore # Populate Org accounts org_accounts = self.get_org_accounts() aws_canonical_user = self._buckets["Owner"] # Add to the set of org_accounts - accounts["org_accounts"] = set(org_accounts.keys()) - accounts["org_accounts"].add(aws_canonical_user["ID"]) + accounts.org_accounts = set(org_accounts.keys()) # type: ignore + accounts.org_accounts.add(aws_canonical_user["ID"]) # type: ignore # Combine the metadata - self.known_accounts_data[aws_canonical_user["ID"]] = {"owner": aws_canonical_user["DisplayName"]} - self.known_accounts_data = self.known_accounts_data | org_accounts # type: ignore + self.known_accounts[aws_canonical_user["ID"]] = {"owner": aws_canonical_user["DisplayName"]} + self.known_accounts = self.known_accounts | org_accounts # type: ignore return accounts - def collate_acl_findings( - self, accounts: DefaultDict[str, Set], resources: DefaultDict[str, List[Dict[Any, Any]]] - ) -> DefaultDict[str, AccountType]: - """Combine all accounts with all the acls to classify findings - - Args: - accounts (DefaultDict[str, Set]): [description] - resources (DefaultDict[str, List[Dict[Any, Any]]]): [description] - - Returns: - DefaultDict[str, AccountType]: [description] - """ - findings = defaultdict(AccountType) # type: DefaultDict[str, AccountType] - - for resource, grants in resources.items(): - for grant in grants: - if grant["Grantee"]["ID"] == self._buckets["Owner"]["ID"]: - continue # Don't add if the ACL is of the same account - elif grant["Grantee"]["ID"] in accounts["known_accounts"]: - findings[resource].known_accounts.append(Finding(principal=grant["Grantee"]["ID"], external_id=True)) - elif grant["Grantee"]["ID"] in accounts["org_accounts"]: - findings[resource].org_accounts.append(Finding(principal=grant["Grantee"]["ID"], external_id=True)) - else: - findings[resource].unknown_accounts.append( - Finding(principal=grant["Grantee"]["ID"], external_id=True) - ) - return findings - - def collate_findings( - self, accounts: DefaultDict[str, Set], resources: DefaultDict[str, Dict[Any, Any]] - ) -> DefaultDict[str, AccountType]: - """Combine all accounts with all the resources to classify findings - - Args: - accounts (DefaultDict[str, Set]): Key of account type. Value account ids - resources (DefaultDict[str, Dict[Any, Any]]): Key ResourceIdentifier. Value Dict PolicyDocument - Returns: - DefaultDict[str, AccountType]: Key of ARN, Value of AccountType - """ - findings = defaultdict(AccountType) # type: DefaultDict[str, AccountType] - for resource, policy_document in resources.items(): +def load_fetch(module_path: str, class_name: str) -> Callable: + """Dynamically load "fetch"" from a given file/module and class""" + path = f".services.{module_path}" + module = importlib.import_module(path, package="awsxenos") + cls = getattr(module, class_name) + instance = cls() + fn = getattr(instance, "fetch") + return fn + + +def load_and_run(config_file, accounts) -> Findings: + """Load classes from a YAML configuration file and run their 'fetch' method""" + results = Findings() + + with open(config_file, "r") as file: + config = yaml.safe_load(file) + plugins = config["plugins"] + + with concurrent.futures.ThreadPoolExecutor() as executor: + future_to_name = {} + for plugin in plugins: + fn = load_fetch(plugin["module"], plugin["class"]) + args = [accounts] + ext_args = plugin.get("args", []) + args = args + ext_args # type: ignore + future = executor.submit(fn, *args) + future_to_name[future] = plugin["module"] + "." + plugin["class"] + + for future in concurrent.futures.as_completed(future_to_name): + name = future_to_name[future] try: - policy = Policy(policy_document) - except: - print(policy_document) - continue - for unparsed_principal in policy.whos_allowed(): - try: - principal = ARN(unparsed_principal.value) # type: Any - except Exception as e: - print(e) - findings[resource].known_accounts.append(Finding(principal=unparsed_principal, external_id=True)) - continue - # Check if Principal is an AWS Service - if principal.service: - findings[resource].aws_services.append(Finding(principal=principal.arn, external_id=True)) - # Check against org_accounts - elif principal.account_number in accounts["org_accounts"]: - findings[resource].org_accounts.append(Finding(principal=principal.arn, external_id=True)) - # Check against known external accounts - elif ( - principal.account_number in accounts["known_accounts"] - or ConditionTuple(category="saml-endpoint", value="https://signin.aws.amazon.com/saml") - in policy.whos_allowed() - ): - sts_set = False - for pstate in policy.statements: - if "sts" in pstate.action_summary(): - try: - conditions = [ - k.lower() for k in list(pstate.statement["Condition"]["StringEquals"].keys()) - ] - if "sts:externalid" in conditions: - findings[resource].known_accounts.append( - Finding(principal=principal.arn, external_id=True) - ) - except: - findings[resource].known_accounts.append( - Finding(principal=principal.arn, external_id=False) - ) - finally: - sts_set = True - break - if not sts_set: - findings[resource].known_accounts.append(Finding(principal=principal.arn, external_id=False)) - - # Unknown Account - else: - sts_set = False - for pstate in policy.statements: - if "sts" in pstate.action_summary(): - try: - conditions = [ - k.lower() for k in list(pstate.statement["Condition"]["StringEquals"].keys()) - ] - if "sts:externalid" in conditions: - findings[resource].unknown_accounts.append( - Finding(principal=principal.arn, external_id=True) - ) - except: - findings[resource].unknown_accounts.append( - Finding(principal=principal.arn, external_id=False) - ) - finally: - break - if not sts_set: - findings[resource].unknown_accounts.append(Finding(principal=principal.arn, external_id=False)) - return findings + results.update(future.result()) + except Exception as e: + # TODO: Better handling, add logger + print(e) + results[name] = str(e) # Store the exception if the function call fails + return results def cli(): @@ -291,18 +135,11 @@ def cli(): help="Type of report to generate. JSON or HTML", ) parser.add_argument( - "--include_service_roles", - dest="service_roles", - action="store_false", - default=False, - help="Include service roles in the report", - ) - parser.add_argument( - "--include_aws_service_roles", - dest="aws_service_roles", - action="store_false", - default=False, - help="Include AWS roles in the report", + "-c", + "--config", + dest="config", + action="store", + help="Config location", ) parser.add_argument( "-w", @@ -314,12 +151,17 @@ def cli(): ) args = parser.parse_args() reporttype = args.reporttype - service_roles = args.service_roles - aws_service_roles = args.aws_service_roles write_output = args.write_output - s = Scan(service_roles, aws_service_roles) - r = Report(s.findings, s.known_accounts_data) + if not args.config: + config_path = f"{package_path.resolve().parent}/config.yaml" + else: + config_path = args.config + + prescan = PreScan() + results = load_and_run(config_path, prescan.accounts) + r = Report(results, prescan.known_accounts) + if reporttype.lower() == "json": summary = r.JSON_report() elif reporttype.lower() == "html": diff --git a/awsxenos/services/__init__.py b/awsxenos/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/awsxenos/services/efs.py b/awsxenos/services/efs.py new file mode 100644 index 0000000..801fd12 --- /dev/null +++ b/awsxenos/services/efs.py @@ -0,0 +1,25 @@ +import json +from typing import DefaultDict, Set + +import boto3 # type: ignore + +from awsxenos.finding import Findings, Resources, Service + +"""EFS Resource Policies""" + + +class EFSResource(Service): + + def fetch(self, accounts: DefaultDict[str, Set]) -> Findings: # type: ignore + return super().collate(accounts, self.get_efs_policies()) + + def get_efs_policies(self) -> Resources: + filesystems = Resources() + efs = boto3.client("efs") + paginator = efs.get_paginator("describe_file_systems") + for page in paginator.paginate(): + for fs in page["FileSystems"]: + filesystems[fs["FileSystemArn"]] = json.loads( + efs.describe_file_system_policy(FileSystemId=fs["FileSystemId"])["Policy"] + ) + return filesystems diff --git a/awsxenos/services/eventbridge.py b/awsxenos/services/eventbridge.py new file mode 100644 index 0000000..878bb72 --- /dev/null +++ b/awsxenos/services/eventbridge.py @@ -0,0 +1,22 @@ +import json +from typing import DefaultDict, Set + +import boto3 # type: ignore + +from awsxenos.finding import Findings, Resources, Service + +"""EventBridge Bus Resource Policies""" + + +class EventBus(Service): + + def fetch(self, accounts: DefaultDict[str, Set]) -> Findings: # type: ignore + return super().collate(accounts, self.get_eb_policies()) + + def get_eb_policies(self) -> Resources: + buses = Resources() + eb = boto3.client("events") + for bus in eb.list_event_buses(): + if "Policy" in bus: + buses[bus["Arn"]] = json.loads(bus["Policy"]) + return buses diff --git a/awsxenos/services/iam.py b/awsxenos/services/iam.py new file mode 100644 index 0000000..f2ccef7 --- /dev/null +++ b/awsxenos/services/iam.py @@ -0,0 +1,45 @@ +from typing import DefaultDict, Optional, Set + +import boto3 # type: ignore + +from awsxenos.finding import Findings, Resources, Service + +"""IAM Roles trust policies""" + + +class IAM(Service): + + def fetch( # type: ignore + self, + accounts: DefaultDict[str, Set], + exclude_service: Optional[bool] = True, + exclude_aws: Optional[bool] = True, + ) -> Findings: + return super().collate(accounts, self.get_role_policies(exclude_service, exclude_aws)) + + def get_role_policies( + self, exclude_service: Optional[bool] = True, exclude_aws: Optional[bool] = True + ) -> Resources: + """Get a dictionary of roles and their policies from the AWS Account + + Args: + exclude_service (Optional[bool], optional): exclude roles starting with /service-role/. Defaults to True. + exclude_aws (Optional[bool], optional): exclude roles starting with /aws-service-role/. Defaults to True. + + Returns: + DefaultDict[str, str]: Key of RoleNames, Value of AssumeRolePolicyDocument + """ + roles = Resources() + iam = boto3.client("iam") + paginator = iam.get_paginator("list_roles") + role_iterator = paginator.paginate() + for role_resp in role_iterator: + for role in role_resp["Roles"]: + if role["Path"] == "/service-role/" and exclude_service: + continue + elif role["Path"].startswith("/aws-service-role/") and exclude_aws: + continue + else: + roles[role["Arn"]] = role["AssumeRolePolicyDocument"] + + return roles diff --git a/awsxenos/services/kms.py b/awsxenos/services/kms.py new file mode 100644 index 0000000..3a73f44 --- /dev/null +++ b/awsxenos/services/kms.py @@ -0,0 +1,28 @@ +import json +from typing import DefaultDict, Set + +import boto3 # type: ignore + +from awsxenos.finding import Findings, Resources, Service + +"""KMS Customer Managed Keys resource policies""" + + +class KMS(Service): + + def fetch(self, accounts: DefaultDict[str, Set]) -> Findings: # type: ignore + return super().collate(accounts, self.get_kms_keys()) + + def get_kms_keys(self) -> Resources: + """ + Returns: + Resources: UserDict[arn] = KMSPolicy + """ + keys = Resources() + kms = boto3.client("kms") + paginator = kms.get_paginator("list_keys") + kms_paginator = paginator.paginate() + for kms_resp in kms_paginator: + for key in kms_resp["Keys"]: + keys[key["KeyArn"]] = json.loads(kms.get_key_policy(KeyId=key["KeyId"], PolicyName="default")["Policy"]) + return keys diff --git a/awsxenos/services/lambda.py b/awsxenos/services/lambda.py new file mode 100644 index 0000000..2bba269 --- /dev/null +++ b/awsxenos/services/lambda.py @@ -0,0 +1,40 @@ +import json +from typing import DefaultDict, Set + +import boto3 # type: ignore +from botocore.exceptions import ClientError # type: ignore + +from awsxenos.finding import Findings, Resources, Service + +"""Lambda Resource Policies""" + + +class LambdaResource(Service): + + def fetch(self, accounts: DefaultDict[str, Set]) -> Findings: # type: ignore + return super().collate(accounts, self.get_lambda_policies()) + + def get_lambda_policies(self) -> Resources: + lambdas = Resources() + lam = boto3.client("lambda") + paginator = lam.get_paginator("list_functions") + for lam_resp in paginator.paginate(): + for func in lam_resp["Functions"]: + try: + lambdas[func["FunctionArn"]] = json.loads( + lam.get_policy(FunctionName=func["FunctionName"])["Policy"] + ) + except ClientError as err: + lambdas[func["FunctionArn"]] = { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": f"{err}", + "Effect": "Allow", + "Principal": {"AWS": ["arn:aws:iam::111122223333:root"]}, + "Action": ["lambda:*"], + "Resource": f'{func["FunctionArn"]}', + } + ], + } + return lambdas diff --git a/awsxenos/services/s3.py b/awsxenos/services/s3.py new file mode 100644 index 0000000..fc1c350 --- /dev/null +++ b/awsxenos/services/s3.py @@ -0,0 +1,151 @@ +import json +from typing import Any, DefaultDict, Dict, Set + +import boto3 # type: ignore +from botocore.client import ClientError # type: ignore + +from awsxenos.finding import Finding, Findings, Resources, Service + +"""S3 Buckets Resource Policy """ + + +class S3(Service): + + def fetch(self, accounts: DefaultDict[str, Set]) -> Findings: # type: ignore + self._buckets = self.list_account_buckets() + self.policies = self.get_bucket_policies() + return super().collate(accounts, self.policies) + + def list_account_buckets(self) -> Dict[str, Dict[Any, Any]]: + s3 = boto3.client("s3") + return s3.list_buckets() + + def get_bucket_policies(self) -> Resources: + """Get a dictionary of buckets and their policies from the AWS Account + + Returns: + DefaultDict[str, str]: Key of BucketARN, Value of PolicyDocument + """ + bucket_policies = Resources() + buckets = self._buckets + s3 = boto3.client("s3") + for bucket in buckets["Buckets"]: + bucket_arn = f'arn:aws:s3:::{bucket["Name"]}' + try: + bucket_policies[bucket_arn] = json.loads(s3.get_bucket_policy(Bucket=bucket["Name"])["Policy"]) + except ClientError as e: + if e.response["Error"]["Code"] == "AccessDenied": + bucket_policies[bucket_arn] = { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "AccessDeniedOnResource", + "Effect": "Allow", + "Principal": {"AWS": ["arn:aws:iam::111122223333:root"]}, + "Action": ["s3:*"], + "Resource": f"{bucket_arn}", + } + ], + } + continue + elif e.response["Error"]["Code"] == "NoSuchBucketPolicy": + bucket_policies[bucket_arn] = { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "NoSuchBucketPolicy", + "Effect": "Allow", + "Principal": {}, + "Action": ["s3:*"], + "Resource": f"{bucket_arn}", + } + ], + } + else: + print(e) + continue + return bucket_policies + + +"""S3 Buckets ACLs""" + + +class S3ACL(Service): + + def fetch(self, accounts: DefaultDict[str, Set]) -> Findings: # type: ignore + self._buckets = self.list_account_buckets() + self.policies = self.get_acls() + return self.custom_collate(accounts, self.policies) + + def list_account_buckets(self) -> Dict[str, Dict[Any, Any]]: + s3 = boto3.client("s3") + return s3.list_buckets() + + def custom_collate(self, accounts: DefaultDict[str, Set], resources: Resources) -> Findings: + """Combine all accounts with all the acls to classify findings + + Args: + accounts (DefaultDict[str, Set]): [description] + resources (DefaultDict[str, List[Dict[Any, Any]]]): [description] + + Returns: + DefaultDict[str, Accounts]: [description] + """ + findings = Findings() + for resource, grants in resources.items(): + for grant in grants: + if grant["Grantee"]["ID"] == self._buckets["Owner"]["ID"]: + continue # Don't add if the ACL is of the same account + elif grant["Grantee"]["ID"] in accounts["known_accounts"]: + findings[resource].known_accounts.append( + Finding(principal=grant["Grantee"]["ID"], external_id=True) + ) + elif grant["Grantee"]["ID"] in accounts["org_accounts"]: + findings[resource].org_accounts.append(Finding(principal=grant["Grantee"]["ID"], external_id=True)) + else: + findings[resource].unknown_accounts.append( + Finding(principal=grant["Grantee"]["ID"], external_id=True) + ) + return findings + + def get_acls(self) -> Resources: + bucket_acls = Resources() + buckets = self._buckets + s3 = boto3.client("s3") + for bucket in buckets["Buckets"]: + bucket_arn = f'arn:aws:s3:::{bucket["Name"]}' + try: + bucket_acls[bucket_arn] = s3.get_bucket_acl(Bucket=bucket["Name"])["Grants"] + except ClientError as e: + if e.response["Error"]["Code"] == "AccessDenied": + bucket_acls[bucket_arn] = [ + { + "Grantee": {"DisplayName": "AccessDenied", "ID": "AccessDenied", "Type": "CanonicalUser"}, + "Permission": "FULL_CONTROL", + } + ] + else: + print(e) + continue + return bucket_acls + + +"""S3 Glacier Vault Policies""" + + +class S3Glacier(Service): + + def fetch(self, accounts: DefaultDict[str, Set]) -> Findings: # type: ignore + return super().collate(accounts, self.get_vault_policies()) + + def get_vault_policies(self) -> Resources: + vaults = Resources() + glacier = boto3.client("glacier") + paginator = glacier.get_paginator("list_vaults") + glacier_iterator = paginator.paginate() + for glacier_resp in glacier_iterator: + for vault in glacier_resp["VaultList"]: + vaults[vault["VaultARN"]] = json.loads( + glacier.get_vault_access_policy(vaultName=vault["VaultName"])["policy"]["Policy"] + ) + return vaults diff --git a/awsxenos/services/secretsmanager.py b/awsxenos/services/secretsmanager.py new file mode 100644 index 0000000..e70ef4d --- /dev/null +++ b/awsxenos/services/secretsmanager.py @@ -0,0 +1,32 @@ +import json +from typing import DefaultDict, Set + +import boto3 # type: ignore + +from awsxenos.finding import Findings, Resources, Service + +"""Secrets Manager Secrets Resource Policies""" + + +class SecretsManager(Service): + + def fetch(self, accounts: DefaultDict[str, Set]) -> Findings: # type: ignore + return super().collate(accounts, self.get_secret_policies()) + + def get_secret_policies(self) -> Resources: + """Get a dictionary of secrets and their policies from the AWS Account + + Args: + + Returns: + DefaultDict[str, str]: Key of ARN, Value of ResourcePolicy + """ + secrets = Resources() + sm = boto3.client("secretsmanager") + paginator = sm.get_paginator("list_secrets") + sm_iterator = paginator.paginate() + for sm_resp in sm_iterator: + for secret in sm_resp["SecretList"]: + secrets[secret["ARN"]] = json.loads(sm.get_resource_policy(SecretId=secret["ARN"])["ResourcePolicy"]) + + return secrets diff --git a/awsxenos/services/sqs.py b/awsxenos/services/sqs.py new file mode 100644 index 0000000..c1306ea --- /dev/null +++ b/awsxenos/services/sqs.py @@ -0,0 +1,33 @@ +import json +from typing import DefaultDict, Optional, Set + +import boto3 # type: ignore + +from awsxenos.finding import Findings, Resources, Service + +"""SQS Access/Resource Policy""" + + +class SQS(Service): + + def fetch( # type: ignore + self, + accounts: DefaultDict[str, Set], + exclude_service: Optional[bool] = True, + exclude_aws: Optional[bool] = True, + ) -> Findings: + return super().collate(accounts, self.get_sqs_policies(exclude_service, exclude_aws)) + + def get_sqs_policies(self, exclude_service: Optional[bool] = True, exclude_aws: Optional[bool] = True) -> Resources: + queues = Resources() + sqs = boto3.client("sqs") + paginator = sqs.get_paginator("list_queues") + for sqs_resp in paginator.paginate(): + for queue in sqs_resp["QueueUrls"]: + queues[queue["QueueUrl"]] = json.loads( + sqs.get_queue_attributes(QueueUrl=queue["QueueUrl"], AttributeNames=["Policy"])["Attributes"][ + "Policy" + ] + ) + + return queues diff --git a/requirements.txt b/requirements.txt index 3771c58..f73e569 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ -policyuniverse==1.4.0.20210730 -boto3==1.18.19 -jinja2==3.0.1 \ No newline at end of file +policyuniverse==1.5.1.20231109 +boto3==1.34.101 +jinja2==3.1.3 +pyyaml==6.0.1 diff --git a/setup.py b/setup.py index e1c365f..15e0989 100644 --- a/setup.py +++ b/setup.py @@ -6,21 +6,21 @@ requirements = fh.read() setup( name="AWSXenos", - version="0.0.2", - author="CostasK", + version="0.2.0", + author="Costas Kourmpoglou", author_email="costas.kourmpoglou@airwalkconsulting.com", license="MIT", - description="Scan and classify cross-account roles in your AWS Account", + description="Scan and classify cross-account roles and resources in your AWS Account", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/AirWalk-Digital/AWSXenos", py_modules=["awsxenos"], packages=find_packages(), install_requires=[requirements], - python_requires=">=3.7", - package_data={"": ["accounts.json", "template.html"]}, + python_requires=">=3.8", + package_data={"": ["config.yaml", "accounts.json", "template.html"]}, classifiers=[ - "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.10", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", ], diff --git a/tests/fixtures.py b/tests/fixtures.py index f2315b5..4aebc82 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -1,8 +1,17 @@ from collections import defaultdict import datetime - +from awsxenos.finding import Accounts, Findings, Finding class Fixtures: + @staticmethod + def mock_findings(): + findings = Findings() + findings["arn:aws:iam::000000000000:role/somerole"].known_accounts.append(Finding("arn:aws:iam::999999999991:role/known",False)) + findings["arn:aws:iam::000000000001:role/somerole"].unknown_accounts.append(Finding("arn:aws:iam::999999999992:role/unknown",False)) + findings["arn:aws:iam::000000000002:role/somerole"].org_accounts.append(Finding("arn:aws:iam::999999999993:role/org",False)) + findings["arn:aws:iam::000000000000:role/service-role/somerole"].aws_services.append(Finding("logging.s3.amazonaws.com",False)) + return findings + @staticmethod def mock_get_roles(): roles = defaultdict(str) diff --git a/tests/test_report.py b/tests/test_report.py index c409aa5..daaa361 100644 --- a/tests/test_report.py +++ b/tests/test_report.py @@ -4,33 +4,30 @@ from tests.fixtures import Fixtures -from awsxenos.scan import Scan +from awsxenos.scan import PreScan from awsxenos.report import Report class ReportTests(unittest.TestCase): - @mock.patch("awsxenos.scan.Scan.get_bucket_acls", return_value=Fixtures.mock_get_bucket_acl()) - @mock.patch("awsxenos.scan.Scan.get_bucket_policies", return_value=Fixtures.mock_get_bucket_policies()) - @mock.patch("awsxenos.scan.Scan.list_account_buckets", return_value=Fixtures.mock_list_s3_buckets()) - @mock.patch("awsxenos.scan.Scan.get_roles", return_value=Fixtures.mock_get_roles()) - @mock.patch("awsxenos.scan.Scan.get_all_accounts", return_value=Fixtures.mock_get_accounts()) + @mock.patch("awsxenos.scan.PreScan.list_account_buckets", return_value=Fixtures.mock_list_s3_buckets()) + @mock.patch("awsxenos.scan.PreScan.get_all_accounts", return_value=Fixtures.mock_get_accounts()) def test_report_summary(self, *args): - s = Scan() - r = Report(s.findings, s.known_accounts_data) + prescan = PreScan() + result = Fixtures.mock_findings() + r = Report(result, prescan.known_accounts) + self.assertIn("known_accounts", r.summary) self.assertIn("org_accounts", r.summary) self.assertIn("aws_services", r.summary) - # self.assertIn(r.summary, "unknown_accounts") + self.assertIn("unknown_accounts", r.summary) - @mock.patch("awsxenos.scan.Scan.get_bucket_acls", return_value=Fixtures.mock_get_bucket_acl()) - @mock.patch("awsxenos.scan.Scan.get_bucket_policies", return_value=Fixtures.mock_get_bucket_policies()) - @mock.patch("awsxenos.scan.Scan.list_account_buckets", return_value=Fixtures.mock_list_s3_buckets()) - @mock.patch("awsxenos.scan.Scan.get_roles", return_value=Fixtures.mock_get_roles()) - @mock.patch("awsxenos.scan.Scan.get_all_accounts", return_value=Fixtures.mock_get_accounts()) + @mock.patch("awsxenos.scan.PreScan.list_account_buckets", return_value=Fixtures.mock_list_s3_buckets()) + @mock.patch("awsxenos.scan.PreScan.get_all_accounts", return_value=Fixtures.mock_get_accounts()) def test_json_report(self, *args): - s = Scan() - r = Report(s.findings, s.known_accounts_data) + prescan = PreScan() + result = Fixtures.mock_findings() + r = Report(result, prescan.known_accounts) result = json.loads(r.JSON_report()) self.assertEqual(dict, type(result)) self.assertGreater(len(result), 1) diff --git a/tests/test_scan.py b/tests/test_scan.py index c2cd893..9af8858 100644 --- a/tests/test_scan.py +++ b/tests/test_scan.py @@ -5,49 +5,24 @@ from unittest import mock from tests.fixtures import Fixtures -from awsxenos.scan import Scan -from awsxenos.finding import Finding +from awsxenos.scan import PreScan +from awsxenos.finding import Finding, Findings, Service +class MockService(Service): + def fetch(self, accounts, **kwargs): + pass # Implementation not required for testing collate -class ScanTests(unittest.TestCase): - @mock.patch("awsxenos.scan.Scan.get_bucket_acls", return_value=Fixtures.mock_get_bucket_acl()) - @mock.patch("awsxenos.scan.Scan.get_bucket_policies", return_value=Fixtures.mock_get_bucket_policies()) - @mock.patch("awsxenos.scan.Scan.list_account_buckets", return_value=Fixtures.mock_list_s3_buckets()) - @mock.patch("awsxenos.scan.Scan.get_roles", return_value=Fixtures.mock_get_roles()) - @mock.patch("awsxenos.scan.Scan.get_all_accounts", return_value=Fixtures.mock_get_accounts()) - def test_collate_findings(self, *args): - s = Scan() - s.known_accounts_data = mock.MagicMock(return_value=Fixtures.mock_known_accounts()) - self.assertEqual(type(s.findings), collections.defaultdict) - for resource in s.findings.keys(): - self.assertIn("arn:aws:", resource) +class ServiceTests(unittest.TestCase): + def setUp(self): + self.service = MockService() + self.accounts = Fixtures.mock_get_accounts() + + self.resources = Fixtures.mock_get_roles() - self.assertGreaterEqual( - len(s.findings["arn:aws:iam::000000000000:role/service-role/AccessAnalyzerMonitor"].aws_services), - 1, - ) - # known_accounts - self.assertEqual( - s.findings["arn:aws:iam::000000000000:role/ExternalRoleNoExternalID"].known_accounts, - [Finding(principal="arn:aws:iam::000000000001:root", external_id=False)], - ) - self.assertEqual( - s.findings["arn:aws:iam::000000000000:role/ExternalRole"].known_accounts, - [Finding(principal="arn:aws:iam::000000000001:root", external_id=True)], - ) - # unknown_accounts - self.assertEqual( - s.findings["arn:aws:s3:::examplebucket"].unknown_accounts, - [Finding(principal="yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", external_id=True)], - ) - # bucket policy - self.assertEqual( - s.findings["arn:aws:s3:::examplebucketwithpolicy"].unknown_accounts, - [Finding(principal="*", external_id=False)], - ) + def test_collate(self): + + findings = self.service.collate(self.accounts, self.resources) # type: ignore - # org_accounts - self.assertEqual( - s.findings["arn:aws:iam::000000000000:role/ExternalRoleFromSaml"].org_accounts, - [Finding(principal="arn:aws:iam::000000000000:saml-provider/SAMLProvider", external_id=True)], - ) + self.assertTrue(findings["arn:aws:iam::000000000000:role/service-role/AccessAnalyzerMonitor"].aws_services) + self.assertTrue(findings["arn:aws:iam::000000000000:role/ExternalRoleNoExternalID"].known_accounts) + self.assertTrue(findings["arn:aws:iam::000000000000:user/ExternalUserWithinOrg"].org_accounts) diff --git a/tox.ini b/tox.ini index 4ccf525..f6eeba9 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py37,py38,py39 +envlist = py39,py310,py311 [testenv] deps = @@ -8,9 +8,12 @@ deps = mypy pylint coverage + ufmt + usort commands = + usort format awsxenos black --line-length 120 awsxenos pylint --max-line-length=120 --fail-under 7.5 awsxenos mypy awsxenos coverage run --omit '.tox/*' -m unittest discover - coverage report -m \ No newline at end of file + coverage report -m