{"id":15643041,"url":"https://github.com/jacobbednarz/cf-vault","last_synced_at":"2026-03-12T09:29:36.544Z","repository":{"id":37563077,"uuid":"294584742","full_name":"jacobbednarz/cf-vault","owner":"jacobbednarz","description":"Manage your Cloudflare credentials, securely","archived":false,"fork":false,"pushed_at":"2025-03-13T02:29:02.000Z","size":651,"stargazers_count":70,"open_issues_count":5,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-02T06:07:08.475Z","etag":null,"topics":["cloudflare","cloudflare-api","cloudflare-credentials"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jacobbednarz.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":"2020-09-11T03:30:03.000Z","updated_at":"2025-03-18T09:50:57.000Z","dependencies_parsed_at":"2023-11-07T03:15:10.396Z","dependency_job_id":"28daaac8-0b58-4442-a867-b363c7d29f09","html_url":"https://github.com/jacobbednarz/cf-vault","commit_stats":{"total_commits":251,"total_committers":9,"mean_commits":27.88888888888889,"dds":0.3187250996015937,"last_synced_commit":"d761c95cb4b8c935883a28a94fa2f5faf86df150"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacobbednarz%2Fcf-vault","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacobbednarz%2Fcf-vault/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacobbednarz%2Fcf-vault/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacobbednarz%2Fcf-vault/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jacobbednarz","download_url":"https://codeload.github.com/jacobbednarz/cf-vault/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247999861,"owners_count":21031046,"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":["cloudflare","cloudflare-api","cloudflare-credentials"],"created_at":"2024-10-03T11:58:42.586Z","updated_at":"2026-03-12T09:29:36.513Z","avatar_url":"https://github.com/jacobbednarz.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cf-vault\n\nManage your Cloudflare credentials, securely.\n\nThe goal of this project is to ensure that when you need to interact with Cloudflare:\n\n- You're not storing credentials unencrypted; and\n- You're not exposing your credentials to the entire environment or to all\n  processes; and\n- You're not using long lived credentials\n\nTo achieve this, `cf-vault` uses the concept of profiles with associated scopes\nto either generate short lived API tokens or retrieve the API key from secure\nstorage (such as Mac OS keychain).\n\n## Demo\n\n![demo](https://user-images.githubusercontent.com/283234/94203859-8c2d8680-ff03-11ea-8cd6-21161224c2ff.gif)\n\n\n## Install\n\n```\n$ brew tap jacobbednarz/tap\n$ brew install jacobbednarz/tap/cf-vault\n```\n\n## Getting started\n\n1. First step is to generate a new API key or API token. Either will work\n   however there are some subtle differences to take into consideration before\n   choosing your path.\n\n   - API tokens **are not** supported by all services yet. Regardless of whether\n     you are using the short lived credentials or long lived token, it may not\n     work for all services and you may need to have a backup profile defined\n     using an API key to cover all scenarios .\n   - API keys **are** supported everywhere however they cannot be scoped. API\n     keys have the permission and scopes that your user account has. This can be\n     dangerous so be sure to tread carefully as it may have unintended consequences.\n\n   While it is possible (and better practice of [principle of least privilege]),\n   to use an API token with only permissions to create a new API token, this\n   isn't really viable for all use cases yet. The recommended approach is to use\n   the API key for the profile and rely on a custom policy to scope the short\n   lived credential. This allows the best of both worlds where if you need to\n   use a service that doesn't support API tokens, you don't need to create a new\n   profile.\n\n   To create a new API token:\n\n   ```\n   \u003e https://dash.cloudflare.com/\n     \u003e My Profile\n       \u003e API Tokens\n         \u003e Create API token\n   ```\n\n   To retrieve your API key:\n\n    ```\n    \u003e https://dash.cloudflare.com/\n      \u003e My Profile\n        \u003e API Tokens\n          \u003e Global API Key\n    ```\n\n1. If you're using an API key, you can skip to the next step. Otherwise,\n   navigate through the UI and configure what permissions and resources you'd\n   like to assign to the token. If you're looking to use an API token to\n   generate short lived API tokens, you should only need the single predefined\n   \"Create API tokens\" permission. See the section below on generating the desired\n   TOML output for instructions on how to do automatically convert policies from\n   API responses.\n\n   Note: Be sure to note down the API token **before** closing/navigating away\n   from the UI as you won't be able to retrieve it again.\n\n1. Once you have your API key or API token value, you can start using `cf-vault`\n   by creating a profile. A profile is the collection of configuration that\n   tells `cf-vault` how you intend to interact with the Cloudflare credentials.\n   You need to start by calling `cf-vault add\n   [your-profile-name]` where `[your-profile-name]` is a label for what the\n   credential/use of the profile is. Some examples:\n\n   - `cf-vault add write-everything`\n   - `cf-vault add read-only`\n   - `cf-vault add super-scary-access-everything`\n   - `cf-vault add api-token-to-create-other-tokens`\n\n   There is no limit on how many profiles you have if you prefer to have\n   specific profiles for your use cases.\n\n1. Now that you have created a profile, you can use it with `cf-vault exec\n   [your-profile-name]`.\n\nIf you do not wish to use the short lived credentials functionality,\nthat's totally fine and you can do so by omitting the `session_duration` value\nand instead the long lived credentials you've setup will be used.\n\n## Usage\n\n`cf-vault` allows you to manage your Cloudflare credentials in a safe place and\nonly expose the credentials to the processes that require them and only for a\nlimited timespan.\n\n```shell\n$ env | grep -i cloudflare\n# =\u003e no results\n\n$ cf-vault exec work -- env | grep -i cloudflare\nCLOUDFLARE_VAULT_SESSION=work\nCLOUDFLARE_EMAIL=jacob@example.com\nCLOUDFLARE_API_KEY=s3cr3t\nCF_EMAIL=jacob@example.com\nCF_API_KEY=s3cr3t\n```\n\nIf you don't provide a command, you will be dropped into a new shell with the\ncredentials populated.\n\n```shell\n$ cf-vault exec work\n$ env | grep -i cloudflare\nCLOUDFLARE_VAULT_SESSION=work\nCLOUDFLARE_EMAIL=jacob@example.com\nCLOUDFLARE_API_KEY=s3cr3t\nCF_EMAIL=jacob@example.com\nCF_API_KEY=s3cr3t\n\n$ exit\n$ env | grep -i cloudflare\n# =\u003e no results\n```\n\n## Predefined short lived token policies\n\nIf you don't need to generate a custom token policy, you can instead use one of\nthe predefined templates which takes care of the heavy lifting for you. You can\nuse `read-only` (read all resources) or `write-everything` (write all resources)\nas the `--profile-template` flag and it will generate everything needed behind\nthe scenes on your behalf. Note: You **still** need to provide\n`--session-duration` as well otherwise the short lived tokens will not be\ngenerated.\n\nExamples:\n\n- `cf-vault add my-read-profile-name --profile-template \"read-only\" --session-duration \"15m\"`\n- `cf-vault add my-write-profile-name --profile-template \"write-everything\" --session-duration \"15m\"`\n\n## Generating token policies\n\nWhile TOML is more readable, its not always straight forward to generate the\ndesired output. Instead, you can use the Cloudflare dashboard to build the\npolicy you'd like and then covert that to TOML using some tooling to avoid\nmanually building your policy (though you can if you understand the syntax!).\n\n1. Using `cf-vault add` create your profile following the prompts.\n1. Create the token you'd like to use on the command line using the Cloudflare\n   dashboard.\n1. Make the API call to fetch the token you've just created. See\n   https://developers.cloudflare.com/api/operations/user-api-tokens-token-details or\n   https://developers.cloudflare.com/api/operations/user-api-tokens-list-tokens to fetch all tokens.\n1. Write the contents of the single `result` JSON payload to a local file. For\n   the example, I'll use `example_token.json` for the documentation.\n1. Run the following command using `docker` which will pull the `go-toml` tool\n   for coverting JSON -\u003e TOML. Remember to replace `example_token.json` with\n   your filename.\n\n   ```\n   docker run -v $PWD:/workdir pelletier/go-toml jsontoml /workdir/example_token.json\n   ```\n\n1. Paste the generated `policy` into your configuration file. You will need to\n   adjust the structure slightly to match the hierarchy. For instance, if I have\n  the following profile:\n\n  ```toml\n  [profiles]\n\n  [profiles.doco-example]\n    auth_type = \"api_token\"\n    email = \"me@example.com\"\n    session_duration = \"15m\"\n  ```\n\n  and my policy output:\n\n  ```toml\n  [[policies]]\n  effect = \"allow\"\n\n  [[policies.permission_groups]]\n    id = \"eb258a38ea634c86a0c89da6b27cb6b6\"\n    name = \"Access: Apps and Policies Read\"\n\n  [[policies.permission_groups]]\n    id = \"517b21aee92c4d89936c976ba6e4be55\"\n    name = \"Zone Settings Read\"\n\n  [[policies.permission_groups]]\n    id = \"c8fed203ed3043cba015a93ad1616f1f\"\n    name = \"Zone Read\"\n\n  # .. snip\n  ```\n\n  The policy needs to be updated to prepend `profiles.doco-example` to the\n  section keys.\n\n  ```toml\n  [[profiles.doco-example.policies]]\n  effect = \"allow\"\n\n  [[profiles.doco-example.policies.permission_groups]]\n    id = \"eb258a38ea634c86a0c89da6b27cb6b6\"\n    name = \"Access: Apps and Policies Read\"\n\n  [[profiles.doco-example.policies.permission_groups]]\n    id = \"517b21aee92c4d89936c976ba6e4be55\"\n    name = \"Zone Settings Read\"\n\n  [[profiles.doco-example.policies.permission_groups]]\n    id = \"c8fed203ed3043cba015a93ad1616f1f\"\n    name = \"Zone Read\"\n\n  # .. snip\n  ```\n\n  Making the complete configuration look like:\n\n```toml\n  [profiles]\n\n  [profiles.doco-example]\n    auth_type = \"api_token\"\n    email = \"me@example.com\"\n    session_duration = \"15m\"\n\n    [[policies]]\n    effect = \"allow\"\n\n    [[policies.permission_groups]]\n      id = \"eb258a38ea634c86a0c89da6b27cb6b6\"\n      name = \"Access: Apps and Policies Read\"\n\n    [[policies.permission_groups]]\n      id = \"517b21aee92c4d89936c976ba6e4be55\"\n      name = \"Zone Settings Read\"\n\n    [[policies.permission_groups]]\n      id = \"c8fed203ed3043cba015a93ad1616f1f\"\n      name = \"Zone Read\"\n\n    # .. snip\n  ```\n\n[principle of least privilege]: https://en.wikipedia.org/wiki/Principle_of_least_privilege\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjacobbednarz%2Fcf-vault","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjacobbednarz%2Fcf-vault","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjacobbednarz%2Fcf-vault/lists"}