Authorization
How Lunar Hub identifies callers and decides which operations each credential may perform.
Most Lunar Hub calls require authentication. Installations use a shared service token, CI jobs use short-lived OIDC tokens from their Git platform, and people sign in through Git platform OAuth. A small set of sign-in setup calls requires no credential.
Installation
Hub service token in LUNAR_HUB_TOKEN
Every permission
CI job
OIDC token from its Git platform in LUNAR_HUB_TOKEN
Its repository and commit
Person
Git platform OAuth through lunar login
Their role on the target repository
Every installation has a service token. Depending on its configuration, CI jobs and people can also authenticate with their own identities.
Permissions
Every Hub operation is assigned a permission, such as components.read or secrets.write. The table shows the built-in defaults; run lunar hub permissions to inspect the effective rules.
components.read
COMPONENT
READ
read
reporter
own repo; fleet-wide: cataloged repo or config repo
components.collect
COMPONENT
WRITE
write
developer
own commit
components.run
COMPONENT
WRITE
write
developer
own commit; fleet-wide: config repo, protected branch
bypasses.manage
COMPONENT
WRITE
maintain
maintainer
own commit
hub.read
LUNAR_CONFIG_REPO
READ
read
reporter
cataloged repo or config repo
hub.operate
LUNAR_CONFIG_REPO
WRITE
maintain
maintainer
no
hub.pull
LUNAR_CONFIG_REPO
WRITE
maintain
maintainer
config repo, protected branch
secrets.read
LUNAR_CONFIG_REPO
READ
maintain
maintainer
no
secrets.write
LUNAR_CONFIG_REPO
WRITE
maintain
maintainer
no
admin.read
LUNAR_CONFIG_REPO
READ
maintain
maintainer
no
sql.connect
LUNAR_CONFIG_REPO
READ
maintain
maintainer
no
The Hub evaluates each permission according to the caller:
Service token: always allowed.
CI job identity: Git platform roles do not apply. The
CI jobcolumn restricts the call to the job's repository, commit, or configuration repository. ForWRITEoperations scoped toLUNAR_CONFIG_REPO, the job must run on the branch the configuration was pulled from, and that branch must be marked protected. It does not need to be the repository's default branch, or be namedmain.Personal sign-in: the Hub checks the person's role on the repository selected by
Scope.COMPONENTuses the target component's repository;LUNAR_CONFIG_REPOuses the configuration repository. Only a granted role counts: the read anyone has on a public repository does not, so a public configuration repository opens nothing to people outside it. Role requirements can be overridden underauthorization, but cannot go below theREADorWRITEaccess floor.
Configuration repository administrators
Whoever can change lunar-config.yml already decides what the Hub enforces and knows, so the table's target checks do not bind them:
A person with
maintain(GitHub) orMaintainer(GitLab) or above on the configuration repository holds every permission in the table, on every component, unlessauthorizationraised that permission abovemaintain/Maintainer. A raise still binds on the configuration repository:secrets.read: { github_role: admin }requiresadminthere, which a Maintainer cannot merge past branch protection to undo. A bypass they create on a component they hold no role on recordsverified_roleas their role on the configuration repository, suffixed with it —github:maintain@github.com/acme/lunar-config— so an audit can tell it apart from a role verified on the component.The configuration repository's own CI job, running on the protected branch the configuration was pulled from, may make any call the
CI jobcolumn opens to CI jobs, on any component or commit. A role raise does not apply: CI jobs have no git platform role. Calls markednostay refused: a workflow on that branch is not the administrator, and any step in it holds the job's token.
The Hub checks this only after the ordinary rule refuses, so nothing that passes today changes, and a refusal reads exactly as before. internal calls and lunar hub pull are excluded: pulling the configuration from a different repository still requires hub.pull on both the current and the new repository. lunar hub permissions prints a note under its table when the connected Hub applies this.
Protect the branch the configuration is pulled from so that only reviewed changes reach it. On a Hub pulling github://acme/lunar-config@release, that is release, not the repository's default branch. Without that, anyone who can push to the branch administers Lunar.
components.read
Reads about a component: its status, Component JSON, catalog entry, and bypasses.
components.collect
Records collection data against a commit.
components.run
Runs collectors or catalogers.
bypasses.manage
Creates and revokes bypasses, from the CLI and from a /lunar bypass comment alike. The comment path checks the commenter's role on the pull or merge request's own repository against this permission's role, so an authorization override moves both surfaces at once; the configuration repository administrator rule below applies to the CLI only.
A CI job may create one only for a component in its own repository and only for its own commit, which it must name, so the next push retires it. Revoking is scoped to the job's repository, since it carries no commit and only removes authority. The configuration repository's own job is not held to either bound, though it must still name the commit. Fork pull-request jobs and GitHub pull_request_target jobs are refused, as for any other WRITE.
hub.read
Reads Hub-wide runtime data. It is also what admits a person to the dashboards when they sign in through the Hub: whoever holds it gets in, as a Grafana Viewer, and whoever loses it is signed out within 15 minutes. Raising its role under authorization raises both the dashboards and the read-only CLI calls together.
hub.operate
Changes Hub-wide runtime state.
hub.pull
Installs Lunar configuration.
secrets.read
Reads secret names and values.
secrets.write
Sets and deletes secrets.
admin.read
Reads operator-only Hub data.
sql.connect
Obtains a SQL API credential.
The three fixed permissions
These are not configurable:
public— no credential requiredauthenticated— any recognized credentialinternal— service token only
When a call is refused
Unauthenticated
Missing or invalid credential
PermissionDenied
Recognized caller without the required permission
Unavailable
Git platform verification failed temporarily
ResourceExhausted
Too many failed authentication attempts
FailedPrecondition
The operation needs Hub state or configuration that is unavailable; token exchange uses this when the session signing key is missing
Last updated
