Skip to content
KentrowPublic

About

Local web interface to inventory, audit, revoke and create OVHcloud API keys. Unofficial, zero persistence, Docker only.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

1 watching

Forks

Latest commit

 

History

67 Commits

Folders and files

Keymaker

CI Latest release License: Apache-2.0 Scorecard OpenSSF Best Practices

A local web interface to inventory, audit, revoke and create OVHcloud API keys.

English · Français

Important

Keymaker is an independent project. It is not affiliated with, endorsed by or sponsored by OVHcloud. OVHcloud is a trademark of its owner, used here only to identify the API this tool works with.

The inventory: the account split by band, the quick filters, the first keys.

The inventory, taken with make demo: every key, name and address in it is invented.

Features

Keymaker works with classic OVHcloud API keys: an application key, an application secret and a consumer key.

  • Inventory of every key on the account, with its access rules, allowed addresses, creation, expiry and last use, and the application it belongs to, including applications the account does not own, such as the OVHcloud API console. The key Keymaker itself uses is marked, and any rule it holds beyond what Keymaker needs is named. A key whose application was deleted, which OVHcloud keeps listing as active, is shown as opening nothing. The whole inventory, with its findings, downloads as a JSON or CSV report that holds no key value.
  • Audit that flags keys reaching the whole account, able to change who can access it or reaching billing and payments, working from any address, never expiring or expiring within a week, never used, dormant for six months, created by OVHcloud support rather than by you, never validated, indistinguishable from another key of the same application, or without a description, and sorts them into "at risk", "to watch" and "nothing flagged".
  • Route explorer over the whole published API, searchable by route or by purpose, to build a set of access rules, with a warning when a rule reaches the whole account, can change who can access it, or reaches billing and payments.
  • Key creation through the OVHcloud createToken page, opened with the chosen rules already filled in. The values of the new key never pass through Keymaker.
  • Replacement of a key whose rules no longer fit, since the API cannot change the rules of an existing key. The rules of the old key are the starting point, its allowed addresses are listed to be entered again, and revoking it is the last step.
  • Allowed addresses of an existing key changed in place, the one thing about a key the API lets anyone change. The list is shown as OVHcloud will store it before it is saved, and the key Keymaker uses is only ever restricted to a list covering the address it is seen from: a key restricted away from its own address cannot even undo it.
  • Revocation behind typing the key's identifier, and in one pass for every expired or refused key. The key Keymaker uses is never revoked by mistake: it has its own way out, revoke and leave, for when you are done with the tool.
  • Applications left without a key, which no inventory of keys can show. Revoking a key leaves its application behind, and an application is a key and a secret a new credential can still be requested under. They can be deleted from here, one at a time or all at once, and an application still holding a key never is, because OVHcloud would revoke that key along with it.
  • An Understand screen that lays out what an application, a key and an access rule each are, on a made-up example, and what follows from it: why a revocation leaves an application behind, why rules cannot be edited, and why some applications cannot be deleted from here.
  • Nothing written to disk: no database, no cache, and a configuration file mounted read-only.
  • English and French interface, light and dark themes, list and card layouts.

Security model

In short, with the details in docs/ARCHITECTURE.md and the reporting policy in SECURITY.md:

  • Keymaker is a local, single-user tool. Anyone who can reach the interface can act with its management key, so it listens on 127.0.0.1 and the container port must be published on 127.0.0.1 only.
  • A random access token is generated at every start and printed once in the address to open. Every route but GET /healthz requires it.
  • Every change also requires a second token that other origins cannot read.
  • The content security policy allows nothing the binary does not serve.
  • The application secret and the consumer key are redacted from every log line.
  • Nothing is persisted, and created keys never reach the process.
  • The only hosts contacted are the OVHcloud API and, when you ask for your public address or restrict the key Keymaker uses, api.ipify.org. KEYMAKER_IP_LOOKUP=off removes the latter.

Quick start

1. Create the management key

Keymaker authenticates with a key of its own, which needs read access to your credentials and applications:

GET    /me/api/credential
GET    /me/api/credential/*
GET    /me/api/application
GET    /me/api/application/*
DELETE /me/api/credential/*
DELETE /me/api/application/*

Three rules are optional, and Keymaker says which one is missing instead of failing: DELETE /me/api/credential/* for revoking keys, GET /me/api/application for listing the applications holding no key, and DELETE /me/api/application/* for deleting those. Never grant this key /me/* or /*.

A seventh rule, PUT /me/api/credential/*, lets Keymaker change the allowed addresses of your keys. The links below leave it out on purpose: the same rule can widen the reach of any key, so Keymaker's audit flags a key holding it, this one included, as able to change access to the account. Add it on the OVHcloud page if you want that trade, or follow the link Keymaker shows when you ask to edit addresses without it.

Each link below opens the OVHcloud page of one endpoint with those rules filled in. Take the one matching the region of your account, as the official SDKs name it.

ovh-eu

https://eu.api.ovh.com/createToken/?GET=/me/api/credential&GET=/me/api/credential/*&GET=/me/api/application&GET=/me/api/application/*&DELETE=/me/api/credential/*&DELETE=/me/api/application/*

ovh-ca

https://ca.api.ovh.com/createToken/?GET=/me/api/credential&GET=/me/api/credential/*&GET=/me/api/application&GET=/me/api/application/*&DELETE=/me/api/credential/*&DELETE=/me/api/application/*

ovh-us

https://api.us.ovhcloud.com/createToken/?GET=/me/api/credential&GET=/me/api/credential/*&GET=/me/api/application&GET=/me/api/application/*&DELETE=/me/api/credential/*&DELETE=/me/api/application/*

The page also asks for a validity. A key that never expires is one Keymaker's own audit flags, so give this one an expiry you are willing to renew. Keymaker offers the right link for its own endpoint whenever the API refuses its key.

2. Write ovh.conf

[default]
endpoint=ovh-eu

[ovh-eu]
application_key=<application key>
application_secret=<application secret>
consumer_key=<consumer key>

ovh.conf.example is this file with every value explained. Keep the file out of version control and readable by you alone:

cp ovh.conf.example ovh.conf
chmod 600 ovh.conf

3. Run the container

docker run --rm \
  -p 127.0.0.1:8080:8080 \
  --user "$(id -u):$(id -g)" \
  -v ./ovh.conf:/config/ovh.conf:ro \
  --read-only \
  --cap-drop=ALL \
  --security-opt no-new-privileges \
  ghcr.io/kentrow/keymaker:1

The process prints one address, token included. Open it: the token moves into a session cookie and disappears from the address bar. Stopping the process ends the session.

--user runs the container as you, so it can read an ovh.conf that only you can read. The image otherwise runs as its own unprivileged user.

The tag 1 follows every 1.x release, which the compatibility promise keeps safe to take. To stay on one release, name it instead, for example ghcr.io/kentrow/keymaker:1.0.0.

Or with Docker Compose

# compose.yaml
services:
  keymaker:
    image: ghcr.io/kentrow/keymaker:1
    user: "${KEYMAKER_UID:?run export KEYMAKER_UID=$(id -u)}:${KEYMAKER_GID:?run export KEYMAKER_GID=$(id -g)}"
    ports:
      - "127.0.0.1:8080:8080"
    volumes:
      - ./ovh.conf:/config/ovh.conf:ro
    read_only: true
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
export KEYMAKER_UID=$(id -u) KEYMAKER_GID=$(id -g)
docker compose up

Check where the image comes from

Every release image carries a build provenance and an SBOM, signed and attested by GitHub. With the GitHub CLI:

gh attestation verify oci://ghcr.io/kentrow/keymaker:1 --repo kentrow/keymaker

A successful check proves that the image was built by the release workflow of this repository, from the tagged commit it names, and has not been changed since. It does not prove that the code is free of bugs: it tells you what you run, not that it is right. Each release on GitHub also carries the same signed provenance as a file, keymaker-X.Y.Z.intoto.jsonl.

Configuration

ovh.conf

The file follows the format the official OVHcloud SDKs read. endpoint in [default] names the section to use, and must be ovh-eu, ovh-ca or ovh-us. Keymaker reads only the file it is given: it ignores ~/.ovh.conf, /etc/ovh.conf and the OVH_* environment variables.

Environment variables

Variable Default Purpose
KEYMAKER_CONFIG /config/ovh.conf Path to the configuration file, opened read-only.
KEYMAKER_ADDR 127.0.0.1:8080 for the binary, 0.0.0.0:8080 in the image Listen address. Any address other than loopback logs a warning.
KEYMAKER_PUBLIC_URL derived from the listen address Address the interface is reached on, used to print the startup link. Set it when the published port differs from 8080, for example http://127.0.0.1:9000. An https address, behind a reverse proxy, also marks the session cookie Secure.
KEYMAKER_IP_LOOKUP enabled off removes the public address lookup, so the OVHcloud API is the only host contacted.
KEYMAKER_LOG_LEVEL info debug, info, warn or error. debug adds one line per request, without its query string.

Command line

Command Purpose
keymaker Start the server.
keymaker --version Print the version, commit and build date, then exit.
keymaker healthcheck Ask GET /healthz of the running server on the loopback, and exit 0 when it answers.

Health check

GET /healthz answers ok without the access token, for orchestrators and probes. The image declares a HEALTHCHECK that runs keymaker healthcheck: the binary asks that route on the loopback and exits 0 or 1, since the image has no shell and no HTTP client. docker ps and Compose show the container as healthy without any further setting.

Compatibility

From 1.0, Keymaker follows semantic versioning, and every 1.x release keeps the following as they are:

  • the ovh.conf format and the keys it reads: endpoint, application_key, application_secret and consumer_key;
  • the KEYMAKER_* environment variables, their defaults and the values they accept;
  • the command line: keymaker, --version and healthcheck;
  • GET /healthz, its path and its ok answer;
  • the image: its name, its tags (X.Y.Z, X.Y, X and latest), its platforms (linux/amd64 and linux/arm64), port 8080, and running as an unprivileged user on a read-only root filesystem, as the commands above start it;
  • the access rules a management key needs: a 1.x release may only make use of a new rule as an optional one, without which everything that worked keeps working;
  • the downloadable report: fields may be added, and existing ones keep their name and meaning.

Everything else may change in a minor release: the interface and its layout, the /api/* routes it talks to, the wording and shape of log lines, and the audit, which may raise new findings. Something on the list above that has to go is first deprecated, in a release whose notes say so and which logs a warning when it is used, and removed in 2.0 at the earliest.

Keymaker is tried on ovh-eu. ovh-ca and ovh-us go through the same code and are supported on a best-effort basis; a report on either is welcome in #50. The interface needs a current browser: the latest two major versions of Chrome, Edge, Firefox or Safari.

Building from source

Requirements: Go (the version in go.mod), Docker, and golangci-lint for make lint.

make help     # list the targets
make build    # build ./bin/keymaker
make test     # run the tests with the race detector
make lint     # gofmt, go mod tidy and golangci-lint
make vuln     # govulncheck
make docker   # build the image for the local platform
make demo     # run the interface on invented data, no account needed

Run the binary against your configuration:

KEYMAKER_CONFIG=./ovh.conf ./bin/keymaker

Documentation

License

Keymaker is licensed under the Apache License 2.0. Third-party components and attributions are listed in NOTICE.

The Keymaker mascot is licensed under the Creative Commons Attribution 4.0 license. It was inspired by the Go gopher, designed by Renee French, whose artwork is licensed under the Creative Commons Attribution 4.0 license. The icons come from Lucide, under the ISC license.

About

Local web interface to inventory, audit, revoke and create OVHcloud API keys. Unofficial, zero persistence, Docker only.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages