{"id":20951377,"url":"https://github.com/lgug2z/satounki","last_synced_at":"2026-03-08T00:32:35.206Z","repository":{"id":211020666,"uuid":"727336580","full_name":"LGUG2Z/satounki","owner":"LGUG2Z","description":"Temporary elevated access management as a self-hosted service","archived":false,"fork":false,"pushed_at":"2024-03-13T23:15:10.000Z","size":614,"stargazers_count":38,"open_issues_count":8,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-14T04:31:50.790Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LGUG2Z.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,"zenodo":null}},"created_at":"2023-12-04T16:57:48.000Z","updated_at":"2024-11-13T10:37:28.000Z","dependencies_parsed_at":"2025-05-14T04:31:42.670Z","dependency_job_id":"981e737f-4485-4731-9dff-fff78635577a","html_url":"https://github.com/LGUG2Z/satounki","commit_stats":null,"previous_names":["lgug2z/satounki"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/LGUG2Z/satounki","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LGUG2Z%2Fsatounki","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LGUG2Z%2Fsatounki/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LGUG2Z%2Fsatounki/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LGUG2Z%2Fsatounki/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LGUG2Z","download_url":"https://codeload.github.com/LGUG2Z/satounki/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LGUG2Z%2Fsatounki/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259320762,"owners_count":22840045,"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":[],"created_at":"2024-11-19T00:58:37.926Z","updated_at":"2026-03-08T00:32:35.156Z","avatar_url":"https://github.com/LGUG2Z.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 💻🔐☁️ S A T O U N K I\n\nTemporary elevated access management as a self-hosted service\n\n## Overview\n\nSatounki is a self-hosted service which brings visibility, order and auditability to temporary elevated access\nrequests, augmenting a traditional organizational least-privilege permissions approach with the ability to\nelevate permissions in a structured way in exceptional circumstances such as incident investigation and response.\n\nSatounki is composed of a self-hosted service to handle requests, a self-hosted client worker to action and revoke\nrequests, a CLI for handling access requests, a Slack bot for notifications, approving, or rejecting access requests,\nand a UI to explore policies and request history.\n\n### Configuration\n\nOnce deployed, Satounki can be configured via Terraform or API directly to configure cloud provider accounts and\npolicies across them:\n\n```terraform\nprovider \"satounki\" {\n  base_url  = \"https://satounki.yourcompany.com/v1\"\n  api_token = \"e-mo-tion\"\n}\n\nresource \"satounki_aws_account\" \"aws\" {\n  for_each                = toset([\"x-development\", \"x-production\"])\n  account                 = each.value\n  approvals_required      = 1\n  admin_approval_required = replace(each.value, \"production\", \"\") != each.value\n}\n\nresource \"satounki_gcp_project\" \"gcp\" {\n  for_each                = toset([\"x-development\", \"x-production\"])\n  project                 = each.value\n  approvals_required      = 1\n  admin_approval_required = replace(each.value, \"production\", \"\") != each.value\n}\n\nresource \"satounki_cloudflare_account\" \"cloudflare\" {\n  account                 = \"x\"\n  approvals_required      = 1\n  admin_approval_required = false\n}\n\nresource \"satounki_policy\" \"storage_analytics_ro\" {\n  name        = \"storage_compute_analytics_ro\"\n  description = \"Read only access to Storage on GCP and AWS, and Analytics on Cloudflare\"\n  gcp = [\n    \"roles/storage.objectViewer\",\n  ]\n  aws = [\n    \"arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess\"\n  ]\n  cloudflare = [\n    \"Analytics\"\n  ]\n}\n```\n\nThe roles of users, request approvers and administrators can similarly be configured via Terraform or API.\n\n### Usage\n\nSatounki has a CLI that is used to request access to any of the polices defined on the service.\n\n```shell\nexport SATOUNKI_USER_TOKEN=samirs-user-token\nsatounki request storage_analytics_ro --minutes 10 --aws-account x-production --gcp-project x-production --cloudflare-account x\n\n# $EDITOR opens here to the user write a justification for this request\n\n# view details       satounki describe-request \"samir-jan-grasshopper-grandson-joke\"\n# approve request    satounki approve-request \"samir-jan-grasshopper-grandson-joke\"\n# cancel request     satounki cancel-request \"samir-jan-grasshopper-grandson-joke\"\n# complete request   satounki complete-request \"samir-jan-grasshopper-grandson-joke\"\n```\n\nApprovers and admins can approve the request either by using the CLI, or interacting with the Satounki bot on Slack.\n\n![slackbot](assets/slackbot.png)\n\nThe requesting user can also opt to cancel the request before it is approved, or \"complete\" the request early after\naccess is granted if it is not needed for the remainder of the duration requested.\n\nThe Satounki UI can also be used to inspect requests.\n\n![ui](assets/ui.png)\n\n### Supported Services\n\nSatounki currently supports the following services:\n\n- Amazon Web Services\n- Google Cloud Platform\n- Cloudflare\n\n## Current State, Tentative Future Roadmap\n\nWhile Satounki is currently in a functional state, there are no documented steps for deployment and I don't recommend\nthat anyone use this software for anything mission-critical just yet.\n\nIf you would like to get involved in an open source Rust project, I would welcome your collaboration on Satounki!\n\nIf you are still exploring an interest in Rust and do not yet feel comfortable contributing, you can also help this\nproject with skills you may have in **Go** and **Typescript** by providing feedback on the Go and Typescript API client\nlibraries which are automatically generated from the Rust code.\n\nSome of the next areas that I would like see being worked on include:\n\n- [ ] Support for other login providers besides Google\n- [ ] Get the Satounki service published in Nixpkgs in 24.05 (hopefully)\n- [ ] Publishing Helm Charts and Kustomize templates for Kubernetes deployments\n- [ ] Support for Azure\n- [ ] Generate HTML reference documentation\n- [ ] Support for registering custom roles and policies to be used in Satounki policy definitions\n- [ ] Bots for Discord, Microsoft Teams and other team-chat services which can be used to approve or reject requests\n- [ ] Generation of Pulumi providers in Typescript and Go (maybe Python too?)\n- [ ] Improving the Terraform provider documentation and getting the provider published\n- [ ] Setting up a collaborative development/staging environment for contributors\n- [ ] Setting up issue and contribution templates/standards/checks on GitHub\n- [ ] Add conditions for automatic approvals on a Satounki policy\n\nI'm sure that there are as many ideas for a project like this as there are companies, teams and people; if you have an\nidea that you think would be a good fit for this project, I am always open to hearing it out.\n\n## Development\n\nThe dependencies required for developing on this project are handled by [Nix](https://nixos.org). The repository has\na [`shell.nix`](shell.nix) file integrated with `direnv` to make onboarding as painless as possible.\n\nBefore getting started you should create a `.env` file in the repository root following the format given below.\n\n```shell\nDATABASE_URL=\"dev.db\" # this defaults to dev.db anyway if not set\nGOOGLE_CLIENT_ID=xxx\nGOOGLE_CLIENT_SECRET=xxx\nSECRET_KEY=hey-i-just-met-you-and-this-is-crazy-but-heres-my-number-so-call-me-maybe\nSLACK_CLIENT_ID=xxx\nSLACK_CLIENT_SECRET=xxx\nSLACK_SIGNING_SECRET=xxx\nSATOUNKI_URL=http://localhost:8080 # this defaults to http://localhost:8080 anyway if not set\nSATOUNKIPLATFORM_API_TOKEN=e-mo-tion # if this value is set, it will be saved to the db instead of a generated value\nSATOUNKI_API_TOKEN=e-mo-tion # this is set when loading dev_data.sql\nSATOUNKI_USER_TOKEN=crj # this is set when loading dev_data.sql\nSATOUNKI_WORKER_KEY=swk-e0c43bd0-38a4-4e7b-9c0f-8bd5f47f20d2 # this is set when loading dev_data.sql\n```\n\n- The `GOOGLE_CLIENT_*` values are only required if you want to work on the login feature or work on the UI\n  - A free [Google Workspace Essentials Starter](https://workspace.google.com/essentials/) account can be used to\n    generate an oauth2 client id in the [Google API Console](https://console.cloud.google.com/apis/credentials) to\n    populate these fields; just make sure you set the redirect url to `http://localhost:8080/redirect/google` (or a\n    FQDN if you're using something like Cloudflare Tunnels)\n- The `SLACK_CLIENT_*` values are only required if you want to work on the Slack bot\n  - Make sure to set a redirect url using a FQDN eg. `https://dev.satounki.com/redirect/slack`\n  - You can create a new app on the [Slack API dashboard](https://api.slack.com/apps), making sure to enable the following bot token scopes:\n    - `chat:write`\n    - `incoming-webhook`\n    - `users:profile:read`\n    - `users:read`\n    - `users:read:email`\n- The `SATOUNKI*` values in the example are the ones set if you load `sqlite3 dev.db \u003c dev_data.sql`\n\n**Note: You do not need to create a Google oauth2 client or a Slack bot to start hacking on the API code!**\n\n### Quickstart\n\nWith the `.env` file in place, you have everything you need to get started\n\n- `direnv allow` to load the shell and generate a `process-compose.yaml` file\n- `cargo check` once just to make sure nothing is broken\n- `just start` to start the `api` backend and the `client` worker\n- `sqlite3 dev.db \u003c dev_data.sql` to load some predictable dev data as mentioned above\n- `just tf` to generate the Terraform provider code and initialize the projects in `./terraform`\n- `cd terraform/platform` and `terraform apply` to create a company (modify as you see fit)\n  - `terraform import satounkiplatform_company.satounki 1` if you're using `dev_data.sql`\n- `cd terraform/company` and `terraform apply` to create some accounts and policies in that company (modify as you see\n  fit)\n- `just satounki [user token (crj and smr are in dev_data.sql)] [command]` to start sending requests via the CLI\n- If you have set up the `GOOGLE_CLIENT_*` variables you can head to `http://localhost:8080/login/google` to sign in to\n  the UI\n- If you want the local worker to run against live cloud services, modify `client/src/configuration.yaml` accordingly\n\n### Code Standards\n\nThese will evolve as time goes on and suggestions are always welcome.\n\n- Commit messages should follow the [Commitizen](https://github.com/commitizen/cz-cli) format\n  e.g. `feat(cli): imperative description` to make for easier and more consistent changelog generation\n- Make sure to run `just fmt` before committing code\n- If you want to add an `#[allow(clippy::lint_name)]` annotation in the codebase please provide clear a justification\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flgug2z%2Fsatounki","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flgug2z%2Fsatounki","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flgug2z%2Fsatounki/lists"}