{"id":19347199,"url":"https://github.com/dcos/bouncer","last_synced_at":"2026-03-06T15:03:24.559Z","repository":{"id":39845590,"uuid":"150589318","full_name":"dcos/bouncer","owner":"dcos","description":"The DC/OS identity and access management service (IAM)","archived":false,"fork":false,"pushed_at":"2022-05-25T01:32:17.000Z","size":208,"stargazers_count":7,"open_issues_count":4,"forks_count":7,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-04-23T05:41:39.930Z","etag":null,"topics":["dcos","dcos-networking-guild"],"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/dcos.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}},"created_at":"2018-09-27T13:14:12.000Z","updated_at":"2024-04-30T13:15:20.000Z","dependencies_parsed_at":"2022-08-29T20:01:25.684Z","dependency_job_id":null,"html_url":"https://github.com/dcos/bouncer","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dcos/bouncer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dcos%2Fbouncer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dcos%2Fbouncer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dcos%2Fbouncer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dcos%2Fbouncer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dcos","download_url":"https://codeload.github.com/dcos/bouncer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dcos%2Fbouncer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30182686,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T14:42:24.748Z","status":"ssl_error","status_checked_at":"2026-03-06T14:42:14.925Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["dcos","dcos-networking-guild"],"created_at":"2024-11-10T04:14:56.026Z","updated_at":"2026-03-06T15:03:24.543Z","avatar_url":"https://github.com/dcos.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bouncer (DC/OS IAM Service)\n\nBouncer provides an HTTP API for managing users as well as for login. \"Login\" in\nthis context is the process of exchanging primary credentials (such as service\naccount credentials) into a DC/OS authentication token which can subsequently\npresented to DC/OS components.\n\n## Architectural overview\n\n### WSGI application\n\nBouncer's HTTP API is provided by a\n[WSGI](https://www.python.org/dev/peps/pep-0333/) web application which is built\nusing the [Falcon](http://falcon.readthedocs.io/) framework. Bouncer is\ncurrently intended to be run within [gunicorn](http://gunicorn.org/) using\nthe `gthread` worker type (with a fixed-size CPython threadpool for processing\nHTTP requests).\n\n### Persistence\n\nBouncer uses [SQLAlchemy](https://www.sqlalchemy.org/) for persisting data in\nand reading data from a relational database.\n\nIn a production DC/OS environment Bouncer communicates with\na fault-tolerant and highly available CockroachDB cluster comprised of three or\nfive machines.\n\nWhen testing Bouncer via `make test` a single containerized CockroachDB instance\nis tested against.\n\nWhen using `make run` or when using `tools/run-gunicorn-testconfig.sh` for a\nlocal playground environment Bouncer operates against an in-memory SQLite\ninstance.\n\n\n### A DC/OS authentication token primer\n\nDC/OS has a decentralized authentication architecture using a concept that is\nsometimes called client-side sessions.\n\nIn DC/OS, Bouncer is the only entity which signs and emits DC/OS authentication\ntokens. A DC/OS authentication token is a JSON Web Token (JWT) of type RS256\nsigned with the private key of an RSA key pair. Bouncer keeps the private key to\nitself and exposes the corresponding public key via its JSON Web Key Set (JWKS)\nendpoint. A so-called DC/OS authenticator can consume this endpoint and perform\nauthentication token validation.\n\n\n## Local development\n\n### The canonical way to run tests\n\nThe following command runs the complete test suite just like the Jenkins CI\ndoes and therefore is the canonical way to run tests locally:\n\n    make test\n\nThis executes the test runner in a container, and spawns periphery containers\nsuch as for CockroachDB. Upon the first invocation this takes a while for\ndownloading resources and for building the required container images.\n\n\n### A more custom way to invoke tests\n\nThis is the recommended way for custom invocation of the pytest test runner:\n\n    make shell\n    pytest \u003coptions\u003e\n\nThis is for example useful for executing just a subset of the tests and allows\nfor quicker iteration than using the `make test` approach.\n\n\n### Containerized local playground deployment\n\nFor a local playground deployment of Bouncer one can launch `make run`. This\nstarts just a single container in which Bouncer runs against an in-memory SQLite\ninstance. That is, this deployment model differs significantly from the\nproduction environment in which Bouncer uses CockroachDB.\n\nAfter the container has come up, test Bouncer's reachability with\n`$ curl 127.0.0.1:8101/acs/api/v1/users`\n\nThe expected HTTP response status code is 200 with a JSON document in the\nresponse body (the users collection is initially empty, so the JSON document\nlooks like `{\"array\": []})`.\n\nNote: For macOS users we recommend running in a Linux virtual machine. We\nprovide a simple Vagrantfile to use:\n\n```\n# Install vagrant:\n#   https://www.vagrantup.com/downloads.html\n\n# cd to the Bouncer repository\nvagrant up\nvagrant ssh\ncd /vagrant\nmake run\n```\n\n### Non-containerized local deployment\n\nIf you are brave and up for installing various dependencies into your local\ndevelopment environment then what follows is the way to run Bouncer natively on\nyour machine:\n\nInstall library and header file dependencies:\n\n    # Debian-based systems\n    sudo apt-get install nmap \\\n        libxml2 libxml2-dev \\\n        libxmlsec1 libxmlsec1-dev \\\n        libxmlsec1-openssl libxmlsec1-openssl-dev\n\n    # RHEL/Fedora:\n    sudo dnf install nmap-ncat \\\n      libxml2 libxml2-devel \\\n      xmlsec1 xmlsec1-devel \\\n      xmlsec1-openssl xmlsec1-openssl-devel \\\n      libtool-ltdl-devel\n\nBouncer is currently tested to run with CPython 3.6.x. For setting up a distinct\nPython build and for creating a virtual environment form it, we recommend a\nyyuu/pyenv-based workflow:\n\n    # Install pyenv:\n    #   https://github.com/yyuu/pyenv#basic-github-checkout\n    # Install pyenv-virtualenv:\n    #   https://github.com/yyuu/pyenv-virtualenv#installing-as-a-pyenv-plugin\n\n    # Create custom local Python build and create a virtualenv from it.\n    pyenv install 3.6.13\n    pyenv virtualenv 3.6.13 venv36-bouncer\n    pyenv activate venv36-bouncer\n\n    # cd to the Bouncer repository and install dependencies from PyPI.\n    pip install -r requirements.txt --upgrade\n    pip install -r requirements-tests.txt --upgrade\n\n\n### Debugging in the context of a test run\n\nLogs from the WSGI server are written to the files\n`gunicorn_*.outerr`.\n\nAfter running tests a coverage report can be found in the directory\n`coverage-report-html`.\n\n\n### Profiling the test runner:\n\nIf performance bottlenecks need to be understood in the test runner itself\nthe following recipe can be helpful:\n\n```\n# Write profiling data to file `pytest.profile`:\n$ python -m cProfile -o pytest.profile $(which pytest) -m app\n[...]\n\n# Analyze profile data in the stats browser\n$ python -m pstats pytest.profile\nWelcome to the profile statistics browser.\npytest.profile% sort time\npytest.profile% stats 10\n[...]\n```\n\n\n## Commit messages\n\nPlease make sure that\n\n* commits are squashed into logical units.\n* commit messages have the format `component: summary`, if possible.\n* summary uses the imperative, present tense: \"change\", not \"changed\" or \"changes\"\n  ([ref](http://git.kernel.org/cgit/git/git.git/tree/Documentation/SubmittingPatches?id=HEAD)).\n\n\n## Bouncer configuration overview\n\nA template for setting deployment options is provided by the file\n`./tools/run-gunicorn-testconfig.sh`. Generally, the configuration is\ncomprised of two parts:\n\n1. WSGI server configuration (see [gunicorn](http://gunicorn.org/)\n2. Bouncer configuration\n\nBouncer is configured via the environment variable `BOUNCER_CONFIG_CLASS`\nin combination with predefined configuration classes in `bouncer/config.py`.\n\nIf the environment variable `BOUNCER_CONFIG_FILE_PATH` is set, Bouncer reads\nthe file (expects flat JSON) and updates the configuration. That is, keys\nspecified in that JSON file take precedence over defaults defined in\n`bouncer/config.py`.\n\n\n## Debugging in production via SIGUSR2\n\nUpon receiving a SIGUSR2 signal, a Bouncer worker process dumps a stack trace\nfor each thread (in the worker process) to stderr. The operation is intended to\nnot affect the health of the application. First, find out the process ID of a\nworker process via e.g. `ps ax | grep 'gunicorn: worker'` and then send the\nsignal via e.g. `kill -SIGUSR2 27784`\n\n\n## HTTP API specification\n\nThe file `docs/openapi-spec.yaml` specifies the behavior bouncer's HTTP API,\nusing [OpenAPI/Swagger 2.0 notation](https://github.com/swagger-api/swagger-spec).\n\nFor ease of viewing, the contents of `docs/openapi-spec.yaml` can be pasted\ninto the [Swagger editor](http://editor.swagger.io) — resulting in a useful\nand beautiful HTML live-rendering of the API specification. Note that the\nHTML output does not necessarily contain all detail specified in the YAML\nfile.\n\nThis spec also contains [JSON schema](http://json-schema.org/) definitions for\nobjects transferred in the body of requests/responses. For working with those,\nit might be useful to work with `docs/openapi-spec.yaml`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdcos%2Fbouncer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdcos%2Fbouncer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdcos%2Fbouncer/lists"}