├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── bandit.yml │ └── validate-reporter.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CreateService.py ├── DEVELOPER.md ├── DISCLAIMER.md ├── DocLinkValidity.py ├── LICENSE ├── NOTICE ├── README.md ├── RuleCount.py ├── Screener.py ├── adminlte └── aws │ └── res │ ├── .gitignore │ ├── LICENCE.md │ ├── dist │ ├── css │ │ └── adminlte.min.css │ ├── img │ │ ├── AdminLTELogo.png │ │ ├── aws.png │ │ ├── boxed-bg.jpg │ │ ├── boxed-bg.png │ │ ├── default-150x150.png │ │ └── icons.png │ └── js │ │ ├── .eslintrc.json │ │ ├── adminlte.js │ │ ├── adminlte.js.map │ │ ├── adminlte.min.js │ │ ├── adminlte.min.js.map │ │ └── demo.js │ └── plugins │ ├── bootstrap │ └── js │ │ └── bootstrap.bundle.min.js │ ├── chart.js │ └── Chart.min.js │ ├── datatables-bs4 │ ├── css │ │ ├── dataTables.bootstrap4.css │ │ └── dataTables.bootstrap4.min.css │ └── js │ │ ├── dataTables.bootstrap4.js │ │ └── dataTables.bootstrap4.min.js │ ├── datatables-buttons │ ├── css │ │ ├── buttons.bootstrap4.css │ │ └── buttons.bootstrap4.min.css │ └── js │ │ ├── buttons.bootstrap4.js │ │ ├── buttons.bootstrap4.min.js │ │ ├── buttons.colVis.js │ │ ├── buttons.colVis.min.js │ │ ├── buttons.html5.js │ │ ├── buttons.html5.min.js │ │ ├── buttons.print.js │ │ ├── buttons.print.min.js │ │ ├── dataTables.buttons.js │ │ └── dataTables.buttons.min.js │ ├── datatables-responsive │ ├── css │ │ ├── responsive.bootstrap4.css │ │ └── responsive.bootstrap4.min.css │ └── js │ │ ├── dataTables.responsive.js │ │ ├── dataTables.responsive.min.js │ │ ├── responsive.bootstrap4.js │ │ └── responsive.bootstrap4.min.js │ ├── datatables │ ├── jquery.dataTables.js │ └── jquery.dataTables.min.js │ ├── fontawesome-free │ ├── css │ │ ├── all.css │ │ ├── all.min.css │ │ ├── brands.css │ │ ├── brands.min.css │ │ ├── fontawesome.css │ │ ├── fontawesome.min.css │ │ ├── regular.css │ │ ├── regular.min.css │ │ ├── solid.css │ │ ├── solid.min.css │ │ ├── svg-with-js.css │ │ ├── svg-with-js.min.css │ │ ├── v4-shims.css │ │ └── v4-shims.min.css │ └── webfonts │ │ ├── fa-brands-400.eot │ │ ├── fa-brands-400.svg │ │ ├── fa-brands-400.ttf │ │ ├── fa-brands-400.woff │ │ ├── fa-brands-400.woff2 │ │ ├── fa-regular-400.eot │ │ ├── fa-regular-400.svg │ │ ├── fa-regular-400.ttf │ │ ├── fa-regular-400.woff │ │ ├── fa-regular-400.woff2 │ │ ├── fa-solid-900.eot │ │ ├── fa-solid-900.svg │ │ ├── fa-solid-900.ttf │ │ ├── fa-solid-900.woff │ │ └── fa-solid-900.woff2 │ ├── icheck-bootstrap │ └── icheck-bootstrap.min.css │ ├── jquery │ └── jquery.js │ ├── overlayScrollbars │ ├── css │ │ └── OverlayScrollbars.min.css │ └── js │ │ └── jquery.overlayScrollbars.min.js │ └── select2 │ ├── css │ ├── select2.css │ └── select2.min.css │ └── js │ ├── i18n │ ├── af.js │ ├── ar.js │ ├── az.js │ ├── bg.js │ ├── bn.js │ ├── bs.js │ ├── build.txt │ ├── ca.js │ ├── cs.js │ ├── da.js │ ├── de.js │ ├── dsb.js │ ├── el.js │ ├── en.js │ ├── es.js │ ├── et.js │ ├── eu.js │ ├── fa.js │ ├── fi.js │ ├── fr.js │ ├── gl.js │ ├── he.js │ ├── hi.js │ ├── hr.js │ ├── hsb.js │ ├── hu.js │ ├── hy.js │ ├── id.js │ ├── is.js │ ├── it.js │ ├── ja.js │ ├── ka.js │ ├── km.js │ ├── ko.js │ ├── lt.js │ ├── lv.js │ ├── mk.js │ ├── ms.js │ ├── nb.js │ ├── ne.js │ ├── nl.js │ ├── pl.js │ ├── ps.js │ ├── pt-BR.js │ ├── pt.js │ ├── ro.js │ ├── ru.js │ ├── sk.js │ ├── sl.js │ ├── sq.js │ ├── sr-Cyrl.js │ ├── sr.js │ ├── sv.js │ ├── th.js │ ├── tk.js │ ├── tr.js │ ├── uk.js │ ├── vi.js │ ├── zh-CN.js │ └── zh-TW.js │ ├── select2.full.js │ ├── select2.full.min.js │ ├── select2.js │ └── select2.min.js ├── constants.py ├── crossAccounts.sample.json ├── frameworks ├── CIS │ ├── CIS.py │ ├── CISPageBuilder.py │ └── map.json ├── FTR │ ├── FTR.py │ ├── FTRPageBuilder.py │ └── map.json ├── Framework.py ├── FrameworkPageBuilder.py ├── MSR │ ├── .~c9_invoke_T7uTi.py │ ├── MSR.py │ ├── MSRPageBuilder.py │ ├── README.md │ └── map.json ├── NIST │ ├── NIST.py │ ├── NISTPageBuilder.py │ ├── map.json │ └── readme.md ├── RMiT │ ├── RMiT.py │ ├── RMiTPageBuilder.py │ └── map.json ├── SPIP │ ├── SPIP.py │ ├── SPIPPageBuilder.py │ └── map.json ├── SSB │ ├── SSB.py │ ├── SSBPageBuilder.py │ └── map.json ├── WAFS │ ├── WAFS.py │ ├── WAFSPageBuilder.py │ └── map.json ├── api.json └── helper │ └── WATools.py ├── info.json ├── licenses.txt ├── main.py ├── organizationAccountsInit.py ├── readme.txt ├── reporter.md ├── requirements.txt ├── scripts └── validate_reporter.py ├── services ├── Cloudwatch.py ├── Evaluator.py ├── PageBuilder.py ├── Reporter.py ├── Service.py ├── apigateway │ ├── Apigateway.py │ ├── apigateway.reporter.json │ └── drivers │ │ ├── ApiGatewayCommon.py │ │ └── ApiGatewayRest.py ├── cloudfront │ ├── Cloudfront.py │ ├── cloudfront.reporter.json │ └── drivers │ │ └── cloudfrontDist.py ├── cloudtrail │ ├── Cloudtrail.py │ ├── README.md │ ├── cloudtrail.reporter.json │ └── drivers │ │ ├── CloudtrailAccount.py │ │ └── CloudtrailCommon.py ├── cloudwatch │ ├── Cloudwatch.py │ ├── cloudwatch.reporter.json │ └── drivers │ │ ├── CloudwatchCommon.py │ │ └── CloudwatchTrails.py ├── dashboard │ └── DashboardPageBuilder.py ├── dynamodb │ ├── Dynamodb.py │ ├── drivers │ │ ├── DateTimeEncoder.py │ │ ├── DynamoDbCommon.py │ │ └── DynamoDbGeneric.py │ └── dynamodb.reporter.json ├── ec2 │ ├── Ec2.py │ ├── drivers │ │ ├── Ec2AutoScaling.py │ │ ├── Ec2CompOpt.py │ │ ├── Ec2CostExplorerRecs.py │ │ ├── Ec2EIP.py │ │ ├── Ec2EbsSnapshot.py │ │ ├── Ec2EbsVolume.py │ │ ├── Ec2ElbClassic.py │ │ ├── Ec2ElbCommon.py │ │ ├── Ec2Instance.py │ │ ├── Ec2NACL.py │ │ ├── Ec2SecGroup.py │ │ └── Ec2Vpc.py │ └── ec2.reporter.json ├── efs │ ├── Efs.py │ ├── README.md │ ├── drivers │ │ └── EfsDriver.py │ └── efs.reporter.json ├── eks │ ├── Eks.py │ ├── README.md │ ├── drivers │ │ └── EksCommon.py │ └── eks.reporter.json ├── elasticache │ ├── Elasticache.py │ ├── drivers │ │ ├── ElasticacheCommon.py │ │ ├── ElasticacheMemcached.py │ │ ├── ElasticacheRedis.py │ │ └── ElasticacheReplicationGroup.py │ └── elasticache.reporter.json ├── general.reporter.json ├── guardduty │ ├── Guardduty.py │ ├── GuarddutypageBuilder.py │ ├── README.md │ ├── drivers │ │ └── GuarddutyDriver.py │ └── guardduty.reporter.json ├── iam │ ├── Iam.py │ ├── README.md │ ├── drivers │ │ ├── IamAccount.py │ │ ├── IamCommon.py │ │ ├── IamGroup.py │ │ ├── IamRole.py │ │ └── IamUser.py │ └── iam.reporter.json ├── kms │ ├── Kms.py │ ├── drivers │ │ └── KmsCommon.py │ └── kms.reporter.json ├── lambda_ │ ├── Lambda.py │ ├── README.md │ ├── drivers │ │ └── LambdaCommon.py │ └── lambda.reporter.json ├── opensearch │ ├── Opensearch.py │ ├── README.md │ ├── drivers │ │ └── OpensearchCommon.py │ └── opensearch.reporter.json ├── rds │ ├── README.md │ ├── Rds.py │ ├── drivers │ │ ├── RdsCommon.py │ │ ├── RdsMariadb.py │ │ ├── RdsMssql.py │ │ ├── RdsMysql.py │ │ ├── RdsMysqlAurora.py │ │ ├── RdsPostgres.py │ │ ├── RdsPostgresAurora.py │ │ ├── RdsSecretsManager.py │ │ ├── RdsSecretsVsDB.py │ │ └── RdsSecurityGroup.py │ └── rds.reporter.json ├── redshift │ ├── Redshift.py │ ├── drivers │ │ └── RedshiftCluster.py │ └── redshift.reporter.json └── s3 │ ├── S3.py │ ├── drivers │ ├── S3Bucket.py │ ├── S3Control.py │ └── S3Macie.py │ └── s3.reporter.json ├── setup.py ├── templates ├── breadcrumb.template.html ├── footer.postjs.template.html ├── footer.prejs.template.html ├── header.postcss.template.html ├── header.precss.template.html ├── sidebar.postcustom.template.html └── sidebar.precustom.template.html ├── unzip_botocore_lambda_runtime.py ├── usecases ├── accountsWithinOrganization │ └── README.md ├── crossAccounts │ ├── README.md │ ├── crossAccountRoleCF.yml │ └── static │ │ └── images │ │ ├── p1-architecture-diagram.png │ │ ├── p2-cloudshell.png │ │ └── p3-report.png └── scheduler │ ├── README.md │ ├── docker │ ├── Dockerfile │ ├── README.md │ ├── docker-base-image │ │ └── Dockerfile │ └── docker-entrypoint.sh │ ├── screener-architecture.png │ └── src │ ├── infra │ ├── .gitignore │ ├── README.md │ ├── app.py │ ├── cdk.json │ ├── deploy.sh │ ├── requirements-dev.txt │ ├── requirements.txt │ ├── service_screener_automation │ │ ├── __init__.py │ │ └── service_screener_automation_stack.py │ └── source.bat │ └── lambda │ ├── ssv2_configUpdater │ ├── configUpdater.py │ ├── sampleDDBDelete.json │ └── sampleDDBStream.json │ ├── ssv2_envInserter │ └── envInsert.py │ └── ssv2_resultProcesser │ ├── requirements.txt │ ├── resultProcesser.py │ └── sampleS3Event.json └── utils ├── ArguParser.py ├── AwsRegionSelector.py ├── CfnTrail.py ├── Config.py ├── CrossAccountsValidator.py ├── CustomPage ├── CustomObject.py ├── CustomPage.py ├── CustomPageBuilder.py └── Pages │ ├── Findings │ ├── Findings.py │ └── FindingsPageBuilder.py │ ├── Modernize │ ├── Modernize.py │ └── ModernizePageBuilder.py │ └── TA │ ├── TA.py │ └── TAPageBuilder.py ├── ExcelBuilder.py ├── Policy.py ├── RuleReader.py ├── Tools.py └── services-template ├── Service.py ├── drivers └── ServiceDriver.py └── service.reporter.json /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Clone Repo 16 | 2. Setup Alias 17 | 3. Run command 18 | 19 | **Full commands used to reproduce this bug** 20 | e.g: screener --regions ALL --services rds,iam,ec2 21 | 22 | **Expected behavior** 23 | A clear and concise description of what you expected to happen. 24 | 25 | **Screenshots** 26 | If applicable, add screenshots to help explain your problem. 27 | 28 | **AWS CloudShell (please complete the following information):** 29 | - Region: [e.g. us-east-1] 30 | - Python version [e.g. 7.2] 31 | - AWS SDK version (boto3) [e.g. 3.0] 32 | - Browser (to display output) [e.g. chrome, safari] 33 | 34 | **Execution Environment (PLEASE FILL THIS UP IF YOU ARE NOT RUNNING THIS IN AWS CLOUDSHELL):** 35 | - Instance type: [e.g. t2.small] 36 | - OS: [e.g. Linux] 37 | - EBS volume size [e.g. 20GiB] 38 | - Region: [e.g. us-east-1] 39 | - Python version [e.g. 3.8] 40 | - AWS SDK version (boto3) [e.g. 1.29.3] 41 | - Browser (to display output) [e.g. chrome, safari] 42 | 43 | **Additional context** 44 | Add any other context about the problem here. 45 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | **Pick a category** 10 | - [] New Checks/Rules 11 | - [] New Services coverage 12 | - [] UI improvement 13 | - [] New Features (e.g: new parameter, new filter, new page) 14 | - [] Others... 15 | 16 | **Is your feature request related to a problem? Please describe.** 17 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 18 | 19 | **Describe the solution you'd like** 20 | A clear and concise description of what you want to happen. 21 | 22 | **Describe alternatives you've considered** 23 | A clear and concise description of any alternative solutions or features you've considered. 24 | 25 | **Additional context** 26 | Add any other context or screenshots about the feature request here. 27 | 28 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. 4 | 5 | Fixes # (issue) 6 | 7 | ## Type of change 8 | 9 | Please delete options that are not relevant, and add any that may be relevant. 10 | 11 | - [ ] Bug fix (non-breaking change which fixes an issue) 12 | - [ ] New feature (non-breaking change which adds functionality) 13 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 14 | - [ ] This change requires a documentation update 15 | 16 | # How Has This Been Tested? 17 | 18 | Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration 19 | 20 | - [ ] Single Account, Single Service and Single Region 21 | - [ ] Single Account, Single Service and Multiple Regions 22 | - [ ] Single Account, Multiple Services and Single Region 23 | - [ ] Single Account, Multiple Services and Multiple Regions 24 | - [ ] CrossAccounts, Multiple Services and Multiple Regions 25 | 26 | # Checklist: 27 | 28 | - [ ] My code follows the style guidelines of this project 29 | - [ ] I have performed a self-review of my own code 30 | - [ ] I have commented my code, particularly in hard-to-understand areas 31 | - [ ] I have made corresponding changes to the documentation 32 | - [ ] My changes generate no new warnings 33 | - [ ] I have added tests that prove my fix is effective or that my feature works 34 | - [ ] New and existing unit tests pass locally with my changes 35 | - [ ] I have tested this change with all regions and services 36 | - [ ] Any dependent changes have been merged and published in downstream modules 37 | -------------------------------------------------------------------------------- /.github/workflows/bandit.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | # Bandit is a security linter designed to find common security issues in Python code. 7 | # This action will run Bandit on your codebase. 8 | # The results of the scan will be found under the Security tab of your repository. 9 | 10 | # https://github.com/marketplace/actions/bandit-scan is ISC licensed, by abirismyname 11 | # https://pypi.org/project/bandit/ is Apache v2.0 licensed, by PyCQA 12 | 13 | name: Bandit 14 | on: 15 | push: 16 | branches: [ "main" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "main" ] 20 | schedule: 21 | - cron: '30 11 * * 6' 22 | 23 | jobs: 24 | bandit: 25 | permissions: 26 | contents: read # for actions/checkout to fetch code 27 | security-events: write # for github/codeql-action/upload-sarif to upload SARIF results 28 | actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status 29 | 30 | runs-on: ubuntu-latest 31 | steps: 32 | - uses: actions/checkout@v2 33 | - name: Bandit Scan 34 | uses: shundor/python-bandit-scan@9cc5aa4a006482b8a7f91134412df6772dbda22c 35 | with: # optional arguments 36 | # exit with 0, even with results found 37 | exit_zero: true # optional, default is DEFAULT 38 | # Github token of the repository (automatically created by Github) 39 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information. 40 | # File or directory to run bandit on 41 | # path: # optional, default is . 42 | # Report only issues of a given severity level or higher. Can be LOW, MEDIUM or HIGH. Default is UNDEFINED (everything) 43 | # level: # optional, default is UNDEFINED 44 | # Report only issues of a given confidence level or higher. Can be LOW, MEDIUM or HIGH. Default is UNDEFINED (everything) 45 | # confidence: # optional, default is UNDEFINED 46 | # comma-separated list of paths (glob patterns supported) to exclude from scan (note that these are in addition to the excluded paths provided in the config file) (default: .svn,CVS,.bzr,.hg,.git,__pycache__,.tox,.eggs,*.egg) 47 | # excluded_paths: # optional, default is DEFAULT 48 | # comma-separated list of test IDs to skip 49 | skips: B310 50 | # path to a .bandit file that supplies command line arguments 51 | # ini_path: # optional, default is DEFAULT 52 | 53 | -------------------------------------------------------------------------------- /.github/workflows/validate-reporter.yml: -------------------------------------------------------------------------------- 1 | name: Validate Reporter Files 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'services/**/*.reporter.json' 7 | push: 8 | paths: 9 | - 'services/**/*.reporter.json' 10 | 11 | jobs: 12 | validate: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v3 17 | with: 18 | fetch-depth: 2 # Required to get file changes 19 | 20 | - name: Set up Python 21 | uses: actions/setup-python@v4 22 | with: 23 | python-version: '3.x' 24 | 25 | - name: Install dependencies 26 | run: | 27 | python -m pip install --upgrade pip 28 | pip install -r requirements.txt 29 | 30 | - name: Get changed files 31 | id: changed-files 32 | run: | 33 | if [ "${{ github.event_name }}" == "pull_request" ]; then 34 | # For pull requests 35 | changed_files=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} | grep "\.reporter\.json$" || true) 36 | else 37 | # For pushes 38 | changed_files=$(git diff --name-only HEAD^ HEAD | grep "\.reporter\.json$" || true) 39 | fi 40 | echo "Changed reporter files:" 41 | echo "$changed_files" 42 | echo "files=${changed_files}" >> $GITHUB_OUTPUT 43 | 44 | - name: Run validation 45 | if: steps.changed-files.outputs.files != '' 46 | run: | 47 | python scripts/validate_reporter.py ${{ steps.changed-files.outputs.files }} 48 | 49 | - name: Comment on PR 50 | if: failure() && github.event_name == 'pull_request' 51 | uses: actions/github-script@v6 52 | with: 53 | script: | 54 | github.rest.issues.createComment({ 55 | issue_number: context.issue.number, 56 | owner: context.repo.owner, 57 | repo: context.repo.repo, 58 | body: '❌ Reporter file validation failed. Please check the workflow logs for details.' 59 | }); 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Custom 2 | .DS_Store 3 | test* 4 | crossAccounts.json 5 | output.zip 6 | __fork 7 | adminlte/aws/**/ 8 | adminlte/aws/**/*.html 9 | adminlte/aws/**/*.xlsx 10 | adminlte/aws/**/error.txt 11 | .~c9_invoke* 12 | pyvenv.cfg 13 | 14 | # Byte-compiled / optimized / DLL files 15 | __pycache__/ 16 | *.py[cod] 17 | *$py.class 18 | .DS_Store 19 | *.xlsx 20 | 21 | # Distribution / packaging 22 | .Python 23 | build/ 24 | build.log 25 | develop-eggs/ 26 | # dist/ 27 | downloads/ 28 | eggs/ 29 | .eggs/ 30 | lib/ 31 | lib64/ 32 | parts/ 33 | sdist/ 34 | var/ 35 | wheels/ 36 | share/python-wheels/ 37 | *.egg-info/ 38 | .installed.cfg 39 | *.egg 40 | MANIFEST 41 | AWSCLIV2.pkg 42 | 43 | # Unit test / coverage reports 44 | htmlcov/ 45 | .tox/ 46 | .nox/ 47 | .coverage 48 | .coverage.* 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | *.cover 53 | *.py,cover 54 | .hypothesis/ 55 | .pytest_cache/ 56 | cover/ 57 | 58 | # pipenv 59 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 60 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 61 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 62 | # install all needed dependencies. 63 | #Pipfile.lock 64 | 65 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 66 | __pypackages__/ 67 | 68 | 69 | # Environments 70 | .env 71 | .venv 72 | env/ 73 | venv/ 74 | bin/ 75 | ENV/ 76 | env.bak/ 77 | venv.bak/ 78 | >>>>>>> 533bf7053abb2c4935e28536b76d2a14435ef1fd 79 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CreateService.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import boto3 4 | import argparse 5 | import constants as _C 6 | 7 | 8 | session = boto3.Session() 9 | services = session.get_available_services() 10 | 11 | parser = argparse.ArgumentParser(prog='Create New Checks', description='Clone folders and files for new checks') 12 | parser.add_argument('-s', '--service', required=True, choices=services) 13 | args = parser.parse_args() 14 | 15 | serviceName = args.service 16 | serviceName = serviceName.replace("-","") 17 | 18 | servicePath = _C.SERVICE_DIR + '/' + serviceName + '/' 19 | 20 | if os.path.isdir(servicePath): 21 | print(servicePath + ' is existing. Please make sure the service name is correct') 22 | else: 23 | os.mkdir(servicePath) 24 | os.mkdir(servicePath + 'drivers/') 25 | 26 | serviceTemplatePath = os.getcwd() + '/utils/services-template/' 27 | 28 | if not os.path.isdir(serviceTemplatePath): 29 | print("Service template is missing. Please reach out to service screener team for further support") 30 | else: 31 | shutil.copyfile(serviceTemplatePath + 'Service.py', servicePath + serviceName.capitalize() + '.py') 32 | shutil.copyfile(serviceTemplatePath + 'service.reporter.json', servicePath + serviceName + '.reporter.json') 33 | shutil.copyfile(serviceTemplatePath + 'drivers/ServiceDriver.py', servicePath + 'drivers/' + serviceName.capitalize() + 'Common.py') -------------------------------------------------------------------------------- /DEVELOPER.md: -------------------------------------------------------------------------------- 1 | # Service Screener Developer Guide 2 | 3 | ## Preparation on Mac environment 4 | ```bash 5 | 6 | ## Install homebrew 7 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 8 | # PLEASE READ 9 | # FOLLOW THE 'NEXT STEP' shows after installation 10 | # THERE ARE 2 COMMANDS TO COPY/PASTE to set the environment variables correctly 11 | 12 | ## Install Python, and set the alias in ~/.zprofile or ~/.bash_profile 13 | brew install python@3.12 14 | which python3.12 15 | alias python3=... , #also setup this in ~/.zprofile? 16 | 17 | ## Install AWS CLI 18 | curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg" 19 | sudo installer -pkg AWSCLIV2.pkg -target / 20 | 21 | # Setup AWS Profile 22 | aws configure --profile ss 23 | 24 | # Setup before running screener command 25 | python3 -m venv . 26 | source bin/activate 27 | python3 -m pip install --upgrade pip 28 | pip install -r requirements.txt 29 | alias screener="python3 $(pwd)/main.py" 30 | 31 | ## When executing SS locally 32 | screener --regions ap-southeast-1 --profile ss 33 | 34 | ## TROUBLESHOOTING 35 | # 1/ For some odd cases, where modules install but venv shows 'module not found', has to force refresh python module by 36 | # executing help("modules") command 37 | % python 38 | >>> help("modules") 39 | >>> import boto3 40 | ``` 41 | 42 | ## Pre-requisite 43 | 1. Login to your Git account 44 | 1. Fork the master repository from aws-samples 45 | 1. git clone 46 | 1. setup aws-cli follows aws official documentation: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html 47 | 1. Setup necessary IAM Users with readOnly permission. 48 | 1. Generate Accesskey & Secret combination to be used by local machine 49 | 1. Run ```aws configure --profile ``` and follow through the setup wizard 50 | -------------------------------------------------------------------------------- /DISCLAIMER.md: -------------------------------------------------------------------------------- 1 | While the original authentic version of this tool will not use your AWS credentials for malicious purposes, it is your responsibility to ensure that the computer or server you install it on is secured. 2 | 3 | Use of this tool should be limited only to data that is considered non-sensitive. Users must not use this tool to share, or store any kind of sensitive data under ANY circumstance. Service Screener does not provide any guarantees in terms of security with respect to using this tool. As this tool is licensed under Apache 2.0 License, each user will use it at their own risk. The report generated by this tool shows the vulnerabilities and gaps within the users' AWS environments. Therefore, it is highly recommended to follow security best practices in terms of securing access to the report as well as your AWS environment. 4 | 5 | The material embodied in this tool is provided to you "as-is" and without warranty of any kind, express, implied or otherwise, including without limitation, any warranty of security and or fitness for a particular purpose. This tool is hosted and run by users, and is under Apache 2.0 licence. [Security](https://aws.amazon.com/compliance/shared-responsibility-model/) is the responsibility of each individual user and in no event shall the owners, publishers or contributors be liable to you or anyone else for any direct, special, incidental, indirect or consequential damages of any kind, or any damages whatsoever, including without limitation, security incidents, loss of profit, loss of use, savings or revenue, or the claims of third parties, however caused and on any theory of liability, arising out of or in connection with the possession, use or performance of this tool. Users must not supply any IAM credentials including Access Keys and Secret Access Keys directly while using this tool. 6 | 7 | Administrators for this service reserve the right to moderate all information used, shared, or stored with this tool at any time. Any user that cannot abide by this disclaimer and Code of Conduct should not use this tool. 8 | The use of this tool implies that the user has consented to their personal data being collected. This data consists of IP Address (e.g. for CloudShell users, this would be the CloudShell IP address), services scanned (name of service only) and regions scanned. This data will not be collected by default, and will only be collected if the user adds a `--feedback 1` attribute when running the tool. 9 | 10 | AWS CloudTrail logs Service Screener activities based on each API request. Each time you run this tool, CloudTrail records the API activity and you can view details about the event in your logs. 11 | 12 | Note: The solution is NOT hosted locally. Only the report is downloaded onto the user machine. 13 | -------------------------------------------------------------------------------- /DocLinkValidity.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import json 4 | import re 5 | from urllib.request import Request, urlopen 6 | import urllib.error 7 | 8 | from utils.RuleReader import RuleReader 9 | 10 | SERVICE_FOLDER_PATH = os.getcwd() + '/services' 11 | 12 | if __name__ == "__main__": 13 | attrName = 'ref' 14 | rr = RuleReader(SERVICE_FOLDER_PATH) 15 | 16 | 17 | ruleList = rr.getRulesAttr(attrName) 18 | invalidRefDict = { 19 | 'NoRef': [], 20 | 'InvalidSyntax': [] 21 | } 22 | 23 | for rule in ruleList: 24 | for ref in ruleList[rule][attrName]: 25 | if ref.strip() == '': 26 | invalidRefDict['NoRef'].append(rule) 27 | continue 28 | output = re.search(r'<(.*)>', ref) 29 | if output is None: 30 | invalidRefDict['InvalidSyntax'].append(rule) 31 | continue 32 | try: 33 | url = output.group(1) 34 | if url.strip() == '': 35 | invalidRefDict['NoRef'].append(rule) 36 | continue 37 | 38 | print('.', end="", flush=True) 39 | conn = Request(url) 40 | conn.add_header('User-Agent', 'aws-cli') 41 | resp = urlopen(conn, timeout=10) 42 | 43 | if resp.getcode() != 200: 44 | if e.code not in invalidRefDict: 45 | invalidRefDict[resp.getcode()] = [] 46 | invalidRefDict[resp.getcode()].append({rule: url}) 47 | except urllib.error.HTTPError as e: 48 | if e.code not in invalidRefDict: 49 | invalidRefDict[e.code] = [] 50 | invalidRefDict[e.code].append({rule: url}) 51 | except Exception as e: 52 | print(e) 53 | if 'UnknownError' not in invalidRefDict: 54 | invalidRefDict['UnknownError'] = [] 55 | invalidRefDict['UnknownError'].append({rule: e}) 56 | 57 | 58 | print('') 59 | print(invalidRefDict) -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Service Screener 2 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | 4 | This tool contains third-party software (https://github.com/ColorlibHQ/AdminLTE) developed by ColorlibHQ, licensed under: 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2014-2021 ColorlibHQ 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of 11 | this software and associated documentation files (the "Software"), to deal in 12 | the Software without restriction, including without limitation the rights to 13 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 14 | the Software, and to permit persons to whom the Software is furnished to do so, 15 | subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 22 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 23 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 24 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /adminlte/aws/res/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /adminlte/aws/res/LICENCE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2021 ColorlibHQ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /adminlte/aws/res/dist/img/AdminLTELogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/service-screener-v2/41e9512e8544bff9ba6bcd6249ace88fb619c194/adminlte/aws/res/dist/img/AdminLTELogo.png -------------------------------------------------------------------------------- /adminlte/aws/res/dist/img/aws.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/service-screener-v2/41e9512e8544bff9ba6bcd6249ace88fb619c194/adminlte/aws/res/dist/img/aws.png -------------------------------------------------------------------------------- /adminlte/aws/res/dist/img/boxed-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/service-screener-v2/41e9512e8544bff9ba6bcd6249ace88fb619c194/adminlte/aws/res/dist/img/boxed-bg.jpg -------------------------------------------------------------------------------- /adminlte/aws/res/dist/img/boxed-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/service-screener-v2/41e9512e8544bff9ba6bcd6249ace88fb619c194/adminlte/aws/res/dist/img/boxed-bg.png -------------------------------------------------------------------------------- /adminlte/aws/res/dist/img/default-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/service-screener-v2/41e9512e8544bff9ba6bcd6249ace88fb619c194/adminlte/aws/res/dist/img/default-150x150.png -------------------------------------------------------------------------------- /adminlte/aws/res/dist/img/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/service-screener-v2/41e9512e8544bff9ba6bcd6249ace88fb619c194/adminlte/aws/res/dist/img/icons.png -------------------------------------------------------------------------------- /adminlte/aws/res/dist/js/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parserOptions": { 4 | "ecmaVersion": 5, 5 | "sourceType": "script" 6 | }, 7 | "env": { 8 | "jquery": true 9 | }, 10 | "extends": [ 11 | "plugin:unicorn/recommended", 12 | "xo", 13 | "xo/browser" 14 | ], 15 | "rules": { 16 | "capitalized-comments": "off", 17 | "indent": [ 18 | "error", 19 | 2, 20 | { 21 | "MemberExpression": "off", 22 | "SwitchCase": 1 23 | } 24 | ], 25 | "multiline-ternary": [ 26 | "error", 27 | "always-multiline" 28 | ], 29 | "object-curly-spacing": [ 30 | "error", 31 | "always" 32 | ], 33 | "semi": [ 34 | "error", 35 | "never" 36 | ], 37 | "strict": "error", 38 | "unicorn/no-array-for-each": "off", 39 | "unicorn/no-for-loop": "off", 40 | "unicorn/no-null": "off", 41 | "unicorn/prefer-dataset": "off", 42 | "unicorn/prefer-includes": "off", 43 | "unicorn/prefer-node-append": "off", 44 | "unicorn/prefer-query-selector": "off", 45 | "unicorn/prefer-spread": "off", 46 | "unicorn/prevent-abbreviations": "off" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /adminlte/aws/res/plugins/datatables-buttons/js/buttons.bootstrap4.js: -------------------------------------------------------------------------------- 1 | /*! Bootstrap integration for DataTables' Buttons 2 | * ©2016 SpryMedia Ltd - datatables.net/license 3 | */ 4 | 5 | (function( factory ){ 6 | if ( typeof define === 'function' && define.amd ) { 7 | // AMD 8 | define( ['jquery', 'datatables.net-bs4', 'datatables.net-buttons'], function ( $ ) { 9 | return factory( $, window, document ); 10 | } ); 11 | } 12 | else if ( typeof exports === 'object' ) { 13 | // CommonJS 14 | module.exports = function (root, $) { 15 | if ( ! root ) { 16 | root = window; 17 | } 18 | 19 | if ( ! $ || ! $.fn.dataTable ) { 20 | $ = require('datatables.net-bs4')(root, $).$; 21 | } 22 | 23 | if ( ! $.fn.dataTable.Buttons ) { 24 | require('datatables.net-buttons')(root, $); 25 | } 26 | 27 | return factory( $, root, root.document ); 28 | }; 29 | } 30 | else { 31 | // Browser 32 | factory( jQuery, window, document ); 33 | } 34 | }(function( $, window, document, undefined ) { 35 | 'use strict'; 36 | var DataTable = $.fn.dataTable; 37 | 38 | $.extend( true, DataTable.Buttons.defaults, { 39 | dom: { 40 | container: { 41 | className: 'dt-buttons btn-group flex-wrap' 42 | }, 43 | button: { 44 | className: 'btn btn-secondary' 45 | }, 46 | collection: { 47 | tag: 'div', 48 | className: 'dropdown-menu', 49 | closeButton: false, 50 | button: { 51 | tag: 'a', 52 | className: 'dt-button dropdown-item', 53 | active: 'active', 54 | disabled: 'disabled' 55 | } 56 | }, 57 | splitWrapper: { 58 | tag: 'div', 59 | className: 'dt-btn-split-wrapper btn-group', 60 | closeButton: false, 61 | }, 62 | splitDropdown: { 63 | tag: 'button', 64 | text: '', 65 | className: 'btn btn-secondary dt-btn-split-drop dropdown-toggle dropdown-toggle-split', 66 | closeButton: false, 67 | align: 'split-left', 68 | splitAlignClass: 'dt-button-split-left' 69 | }, 70 | splitDropdownButton: { 71 | tag: 'button', 72 | className: 'dt-btn-split-drop-button btn btn-secondary', 73 | closeButton: false 74 | } 75 | }, 76 | buttonCreated: function ( config, button ) { 77 | return config.buttons ? 78 | $('
').append(button) : 79 | button; 80 | } 81 | } ); 82 | 83 | DataTable.ext.buttons.collection.className += ' dropdown-toggle'; 84 | DataTable.ext.buttons.collection.rightAlignClassName = 'dropdown-menu-right'; 85 | 86 | return DataTable.Buttons; 87 | })); 88 | -------------------------------------------------------------------------------- /adminlte/aws/res/plugins/datatables-buttons/js/buttons.bootstrap4.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | Bootstrap integration for DataTables' Buttons 3 | ©2016 SpryMedia Ltd - datatables.net/license 4 | */ 5 | (function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net-bs4","datatables.net-buttons"],function(a){return c(a,window,document)}):"object"===typeof exports?module.exports=function(a,b){a||(a=window);b&&b.fn.dataTable||(b=require("datatables.net-bs4")(a,b).$);b.fn.dataTable.Buttons||require("datatables.net-buttons")(a,b);return c(b,a,a.document)}:c(jQuery,window,document)})(function(c,a,b,f){a=c.fn.dataTable;c.extend(!0,a.Buttons.defaults,{dom:{container:{className:"dt-buttons btn-group flex-wrap"}, 6 | button:{className:"btn btn-secondary"},collection:{tag:"div",className:"dropdown-menu",closeButton:!1,button:{tag:"a",className:"dt-button dropdown-item",active:"active",disabled:"disabled"}},splitWrapper:{tag:"div",className:"dt-btn-split-wrapper btn-group",closeButton:!1},splitDropdown:{tag:"button",text:"",className:"btn btn-secondary dt-btn-split-drop dropdown-toggle dropdown-toggle-split",closeButton:!1,align:"split-left",splitAlignClass:"dt-button-split-left"},splitDropdownButton:{tag:"button", 7 | className:"dt-btn-split-drop-button btn btn-secondary",closeButton:!1}},buttonCreated:function(e,d){return e.buttons?c('
').append(d):d}});a.ext.buttons.collection.className+=" dropdown-toggle";a.ext.buttons.collection.rightAlignClassName="dropdown-menu-right";return a.Buttons}); 8 | -------------------------------------------------------------------------------- /adminlte/aws/res/plugins/datatables-buttons/js/buttons.print.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | Print button for Buttons and DataTables. 3 | 2016 SpryMedia Ltd - datatables.net/license 4 | */ 5 | (function(b){"function"===typeof define&&define.amd?define(["jquery","datatables.net","datatables.net-buttons"],function(d){return b(d,window,document)}):"object"===typeof exports?module.exports=function(d,h){d||(d=window);h&&h.fn.dataTable||(h=require("datatables.net")(d,h).$);h.fn.dataTable.Buttons||require("datatables.net-buttons")(d,h);return b(h,d,d.document)}:b(jQuery,window,document)})(function(b,d,h,y){var u=b.fn.dataTable,n=h.createElement("a"),v=function(a){n.href=a;a=n.host;-1===a.indexOf("/")&& 6 | 0!==n.pathname.indexOf("/")&&(a+="/");return n.protocol+"//"+a+n.pathname+n.search};u.ext.buttons.print={className:"buttons-print",text:function(a){return a.i18n("buttons.print","Print")},action:function(a,e,p,k){a=e.buttons.exportData(b.extend({decodeEntities:!1},k.exportOptions));p=e.buttons.exportInfo(k);var w=e.columns(k.exportOptions.columns).flatten().map(function(f){return e.settings()[0].aoColumns[e.column(f).index()].sClass}).toArray(),r=function(f,g){for(var x="",l=0,z=f.length;l"+(null===f[l]||f[l]===y?"":f[l])+"";return x+""},m='';k.header&&(m+=""+r(a.header,"th")+"");m+="";for(var t=0,A=a.body.length;t";k.footer&&a.footer&&(m+=""+r(a.footer,"th")+"");m+="
";var c=d.open("","");if(c){c.document.close();var q=""+p.title+"";b("style, link").each(function(){var f=q,g=b(this).clone()[0]; 8 | "link"===g.nodeName.toLowerCase()&&(g.href=v(g.href));q=f+g.outerHTML});try{c.document.head.innerHTML=q}catch(f){b(c.document.head).html(q)}c.document.body.innerHTML="

"+p.title+"

"+(p.messageTop||"")+"
"+m+"
"+(p.messageBottom||"")+"
";b(c.document.body).addClass("dt-print-view");b("img",c.document.body).each(function(f,g){g.setAttribute("src",v(g.getAttribute("src")))});k.customize&&k.customize(c,k,e);a=function(){k.autoPrint&&(c.print(),c.close())};navigator.userAgent.match(/Trident\/\d.\d/)? 9 | a():c.setTimeout(a,1E3)}else e.buttons.info(e.i18n("buttons.printErrorTitle","Unable to open print view"),e.i18n("buttons.printErrorMsg","Please allow popups in your browser for this site to be able to view the print view."),5E3)},title:"*",messageTop:"*",messageBottom:"*",exportOptions:{},header:!0,footer:!1,autoPrint:!0,customize:null};return u.Buttons}); 10 | -------------------------------------------------------------------------------- /adminlte/aws/res/plugins/datatables-responsive/js/responsive.bootstrap4.js: -------------------------------------------------------------------------------- 1 | /*! Bootstrap 4 integration for DataTables' Responsive 2 | * ©2016 SpryMedia Ltd - datatables.net/license 3 | */ 4 | 5 | (function( factory ){ 6 | if ( typeof define === 'function' && define.amd ) { 7 | // AMD 8 | define( ['jquery', 'datatables.net-bs4', 'datatables.net-responsive'], function ( $ ) { 9 | return factory( $, window, document ); 10 | } ); 11 | } 12 | else if ( typeof exports === 'object' ) { 13 | // CommonJS 14 | module.exports = function (root, $) { 15 | if ( ! root ) { 16 | root = window; 17 | } 18 | 19 | if ( ! $ || ! $.fn.dataTable ) { 20 | $ = require('datatables.net-bs4')(root, $).$; 21 | } 22 | 23 | if ( ! $.fn.dataTable.Responsive ) { 24 | require('datatables.net-responsive')(root, $); 25 | } 26 | 27 | return factory( $, root, root.document ); 28 | }; 29 | } 30 | else { 31 | // Browser 32 | factory( jQuery, window, document ); 33 | } 34 | }(function( $, window, document, undefined ) { 35 | 'use strict'; 36 | var DataTable = $.fn.dataTable; 37 | 38 | 39 | var _display = DataTable.Responsive.display; 40 | var _original = _display.modal; 41 | var _modal = $( 42 | '