{"id":13541737,"url":"https://github.com/Netflix-Skunkworks/aardvark","last_synced_at":"2025-04-02T09:32:19.554Z","repository":{"id":21624477,"uuid":"92543031","full_name":"Netflix-Skunkworks/aardvark","owner":"Netflix-Skunkworks","description":"Aardvark is a multi-account AWS IAM Access Advisor API","archived":false,"fork":false,"pushed_at":"2023-10-25T15:43:37.000Z","size":318,"stargazers_count":462,"open_issues_count":14,"forks_count":77,"subscribers_count":135,"default_branch":"master","last_synced_at":"2024-04-14T06:01:44.500Z","etag":null,"topics":["aws","security"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Netflix-Skunkworks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-26T19:39:23.000Z","updated_at":"2024-05-07T12:46:31.290Z","dependencies_parsed_at":"2023-01-13T21:35:50.426Z","dependency_job_id":"32b55dd9-0f45-406b-b5a5-249ff603a61e","html_url":"https://github.com/Netflix-Skunkworks/aardvark","commit_stats":{"total_commits":70,"total_committers":26,"mean_commits":"2.6923076923076925","dds":0.8428571428571429,"last_synced_commit":"c6f79b689d2715063b4cf7a803fb0e7f83b4c632"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Netflix-Skunkworks%2Faardvark","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Netflix-Skunkworks%2Faardvark/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Netflix-Skunkworks%2Faardvark/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Netflix-Skunkworks%2Faardvark/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Netflix-Skunkworks","download_url":"https://codeload.github.com/Netflix-Skunkworks/aardvark/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246651559,"owners_count":20811994,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","security"],"created_at":"2024-08-01T10:00:55.774Z","updated_at":"2025-04-02T09:32:19.349Z","avatar_url":"https://github.com/Netflix-Skunkworks.png","language":"Python","funding_links":[],"categories":["Projects","Python","Identity and access management"],"sub_categories":["Identity and Access Management","Hook management tools"],"readme":"Aardvark\n========\n[![NetflixOSS Lifecycle](https://img.shields.io/osslifecycle/Netflix/osstracker.svg)]()\n[![Discord chat](https://img.shields.io/discord/754080763070382130?logo=discord)](https://discord.gg/9kwMWa6)\n\n\u003cimg align=\"center\" alt=\"Aardvark Logo\" src=\"docs/images/aardvark_logo.jpg\" width=\"10%\" display=\"block\"\u003e\n\nAardvark is a multi-account AWS IAM Access Advisor API (and caching layer).\n\n## Install:\n\nEnsure that you have Python 3.6 or later. Python 2 is no longer supported.\n\n```bash\ngit clone https://github.com/Netflix-Skunkworks/aardvark.git\ncd aardvark\npython3 -m venv env\n. env/bin/activate\npython setup.py develop\n```\n\n### Known Dependencies\n - libpq-dev\n\n## Configure Aardvark\n\nThe Aardvark config wizard will guide you through the setup.\n```\n% aardvark config\n\nAardvark can use SWAG to look up accounts. https://github.com/Netflix-Skunkworks/swag-client\nDo you use SWAG to track accounts? [yN]: no\nROLENAME: Aardvark\nDATABASE [sqlite:////home/github/aardvark/aardvark.db]:\n# Threads [5]:\n\n\u003e\u003e Writing to config.py\n```\n- Whether to use [SWAG](https://github.com/Netflix-Skunkworks/swag-client) to enumerate your AWS accounts. (Optional, but useful when you have many accounts.)\n- The name of the IAM Role to assume into in each account.\n- The Database connection string. (Defaults to sqlite in the current working directory. Use RDS Postgres for production.)\n\n## Create the DB tables\n\n```\naardvark create_db\n```\n\n## IAM Permissions:\n\nAardvark needs an IAM Role in each account that will be queried.  Additionally, Aardvark needs to be launched with a role or user which can `sts:AssumeRole` into the different account roles.\n\nAardvarkInstanceProfile:\n- Only create one.\n- Needs the ability to call `sts:AssumeRole` into all of the AardvarkRole's\n\nAardvarkRole:\n- Must exist in every account to be monitored.\n- Must have a trust policy allowing `AardvarkInstanceProfile`.\n- Has these permissions:\n```\niam:GenerateServiceLastAccessedDetails\niam:GetServiceLastAccessedDetails\niam:listrolepolicies\niam:listroles\niam:ListUsers\niam:ListPolicies\niam:ListGroups\n```\n\nSo if you are monitoring `n` accounts, you will always need `n+1` roles. (`n` AardvarkRoles and `1` AardvarkInstanceProfile).\n\nNote: For locally running aardvark, you don't have to take care of the AardvarkInstanceProfile. Instead, just attach a policy which contains \"sts:AssumeRole\" to the user you are using on the AWS CLI to assume Aardvark Role. Also, the same user should be mentioned in the trust policy of Aardvark Role for proper assignment of the privileges.\n\n## Gather Access Advisor Data\n\nYou'll likely want to refresh the Access Advisor data regularly.  We recommend running the `update` command about once a day.  Cron works great for this.\n\n#### Without SWAG:\n\nIf you don't have SWAG you can pass comma separated account numbers:\n\n    aardvark update -a 123456789012,210987654321\n\n#### With SWAG:\n\nAardvark can use [SWAG](https://github.com/Netflix-Skunkworks/swag-client) to look up accounts, so you can run against all with:\n\n    aardvark update\n\nor by account name/tag with:\n\n    aardvark update -a dev,test,prod\n\n\n## API\n\n### Start the API\n\n    aardvark start_api -b 0.0.0.0:5000\n\nIn production, you'll likely want to have something like supervisor starting the API for you.\n\n### Use the API\n\nSwagger is available for the API at `\u003cAardvark_Host\u003e/apidocs/#!`.\n\nAardvark responds to get/post requests. All results are paginated and pagination can be controlled by passing `count` and/or `page` arguments. Here are a few example queries:\n```bash\ncurl localhost:5000/api/1/advisors\ncurl localhost:5000/api/1/advisors?phrase=SecurityMonkey\ncurl localhost:5000/api/1/advisors?arn=arn:aws:iam::000000000000:role/SecurityMonkey\u0026arn=arn:aws:iam::111111111111:role/SecurityMonkey\ncurl localhost:5000/api/1/advisors?regex=^.*Monkey$\n```\n\n## Docker\n\nAardvark can also be deployed with Docker and Docker Compose. The Aardvark services are built on a shared container. You will need Docker and Docker Compose installed for this to work.\n\nTo configure the containers for your set of accounts create a `.env` file in the root of this directory. Define the environment variables within this file. This example uses AWS Access Keys. We recommend using instance roles in production.\n\n```text\nAARDVARK_ROLE=Aardvark\nAARDVARK_ACCOUNTS=\u003caccount id\u003e\nAWS_DEFAULT_REGION=\u003caws region\u003e\nAWS_ACCESS_KEY_ID=\u003cyour access key\u003e\nAWS_SECRET_ACCESS_KEY=\u003cyou secret key\u003e\n```\n\n| Name | Service | Description |\n|---|---|---|\n| `AARDVARK_ROLE` | `collector` | The name of the role for Aardvark to assume so that it can collect the data. |\n| `AARDVARK_ACCOUNTS` | `collector` | Optional if using SWAG, otherwise required. Set this to a list of SWAG account name tags or a list of AWS account numbers from which to collect Access Advisor records. |\n| `AWS_ARN_PARTITION` | `collector` | Required if not using an AWS Commercial region. For example, `aws-us-gov`. By default, this is `aws`. |\n| `AWS_DEFAULT_REGION` | `collector` | Required if not running on an EC2 instance with an appropriate Instance Profile. Set these to the credentials of an AWS IAM user with permission to `sts:AssumeRole` to the Aardvark audit role. |\n| `AWS_ACCESS_KEY_ID` | `collector` | Required if not running on an EC2 instance with an appropriate Instance Profile. Set these to the credentials of an AWS IAM user with permission to `sts:AssumeRole` to the Aardvark audit role. |\n| `AWS_SECRET_ACCESS_KEY` | `collector` | Required if not running on an EC2 instance with an appropriate Instance Profile. Set these to the credentials of an AWS IAM user with permission to `sts:AssumeRole` to the Aardvark audit role. |\n| `AARDVARK_DATABASE_URI` | `collector` and `apiserver` | Specify a custom database URI supported by SQL Alchemy. By default, this will use the `AARDVARK_DATA_DIR` value to create a SQLLite Database. Example: `sqlite:///$AARDVARK_DATA_DIR/aardvark.db` |\n\nOnce this file is created, then build the containers and start the services. Aardvark consists of three services:\n\n- Init - The init container creates the database within the storage volume.\n- API Server - This is the HTTP webserver will serve the data. By default, this is listening on [http://localhost:5000/apidocs/#!](http://localhost:5000/apidocs/#!).\n- Collector - This is a daemon that will fetch and cache the data in the local SQL database. This should be run periodically.\n\n```bash\n# build the containers\ndocker-compose build\n\n# start up the containers\ndocker-compose up\n```\n\nFinally, to clean up the environment\n\n```bash\n# bring down the containers\ndocker-compose down\n\n# remove the containers\ndocker-compoes rm\n```\n\n## Notes\n\n### Threads\nAardvark will launch the number of threads specified in the configuration.  Each of these threads\nwill retrieve Access Advisor data for an account and then persist the\ndata.\n\n### Database\nThe `regex` query is only supported in Postgres (natively) and SQLite (via some magic courtesy of Xion\n  in the `sqla_regex` file).\n\n### TLS\nWe recommend enabling TLS for any service. Instructions for setting up TLS are out of scope for this document.\n\n## Signals\n\n\u003e New in v0.3.1\n\nAardvark uses [Blinker](https://pythonhosted.org/blinker/) for signals in its update process. These signals can be used\nfor things like emitting metrics, additional logging, or taking more actions on accounts. You can use them by writing a\nscript that defines your handlers and calls `aardvark.manage.main()`. For example, create a file called\n`signals_example.py` with the following contents:\n\n```python\nimport logging\n\nfrom aardvark.manage import main\nfrom aardvark.updater import AccountToUpdate\n\nlogger = logging.getLogger('aardvark_signals')\n\n\n@AccountToUpdate.on_ready.connect\ndef handle_on_ready(sender):\n    logger.info(f\"got on_ready from {sender}\")\n\n\n@AccountToUpdate.on_complete.connect\ndef handle_on_complete(sender):\n    logger.info(f\"got on_complete from {sender}\")\n\n\nif __name__ == \"__main__\":\n    main()\n```\n\nThis file can now be invoked in the same way as `manage.py`:\n\n```bash\npython signals_example.py update -a cool_account\n```\n\nThe log output will be similar to the following:\n\n```\nINFO: getting bucket swag-bucket\nINFO: Thread #1 updating account 123456789012 with all arns\nINFO: got on_ready from \u003caardvark.updater.AccountToUpdate object at 0x10c379b50\u003e\nINFO: got on_complete from \u003caardvark.updater.AccountToUpdate object at 0x10c379b50\u003e\nINFO: Thread #1 persisting data for account 123456789012\nINFO: Thread #1 FINISHED persisting data for account 123456789012\n```\n\n### Available signals\n\n| Class | Signals |\n|-------|---------|\n| `manage.UpdateAccountThread` | `on_ready`, `on_complete`, `on_failure` |\n| `updater.AccountToUpdate` | `on_ready`, `on_complete`, `on_error`, `on_failure` |\n\n## TODO:\n\nSee [TODO](TODO.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNetflix-Skunkworks%2Faardvark","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FNetflix-Skunkworks%2Faardvark","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNetflix-Skunkworks%2Faardvark/lists"}