Skip to content

feat: command caller specification#106

Open
Yash Shrivastava (alephys26) wants to merge 2 commits into
mainfrom
alephys26/allowed-callers
Open

feat: command caller specification#106
Yash Shrivastava (alephys26) wants to merge 2 commits into
mainfrom
alephys26/allowed-callers

Conversation

@alephys26
Copy link
Copy Markdown
Contributor

Description

This pull request introduces support for per-command caller allowlists, enabling commands to restrict which users can invoke them based on anchored regex patterns. The implementation includes changes to both the command object and the job submission logic, along with an update to the documentation.

Changes

Command allowlist enforcement:

  • Added a new AllowedCallers field to the Command struct, allowing configuration of permitted callers as anchored regex patterns. Patterns are compiled and cached for efficient matching. (pkg/object/command/command.go, [1] [2]
  • Implemented the IsCallerAllowed method on the Command struct to check if a user matches any of the allowed caller patterns. (pkg/object/command/command.go, pkg/object/command/command.goR68-R102)
  • During job submission, Heimdall now enforces the allowlist by rejecting jobs from disallowed callers with a specific error. (internal/pkg/heimdall/job.go, [1] [2]

Documentation:

  • Updated the README.md to describe the new allowed_callers feature and its effect on command invocation.

Tests

Tested locally on docker compose and with unit tests. All passed.

Copilot AI review requested due to automatic review settings May 28, 2026 11:45
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds per-command caller allowlists so commands can restrict who may submit jobs, based on regex matching against the authenticated user (e.g., X-Heimdall-User via auth header plugin).

Changes:

  • Added allowed_callers to Command, compiling/caching regex patterns and exposing IsCallerAllowed.
  • Enforced the allowlist during job submission, rejecting disallowed callers with a dedicated error.
  • Documented the new allowed_callers configuration in the README.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
README.md Documents allowed_callers and how it affects job submission.
pkg/object/command/command.go Adds allowlist config field, regex compilation/cache, and caller check method.
internal/pkg/heimdall/job.go Enforces allowlist in submitJob and introduces ErrCallerNotAllowed.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/object/command/command.go
Comment thread pkg/object/command/command.go
Comment thread internal/pkg/heimdall/job.go
var (
ErrCommandClusterPairNotFound = fmt.Errorf(`command-cluster pair is not found`)
ErrJobCancelFailed = fmt.Errorf(`async job unrecognized or already in final state`)
ErrCallerNotAllowed = fmt.Errorf(`caller is not allowed to run this command`)
Copy link
Copy Markdown
Collaborator

@prasadlohakpure prasadlohakpure May 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like its an authorization piece. Do you thin it can go in auth plugin? Maybe we can expose a new method, like AuthorizeCommandRequest() in auth plugin here which will do the job?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a simple static ACL co-located with the command config. Moving it to the auth plugin would mean the auth plugin has to know about commands, every deployment would need an auth plugin just to express "user X can run command Y", even for the simplest cases.

Copy link
Copy Markdown
Contributor

@wlggraham Will Graham (wlggraham) left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Yash, nice work, very clean. Just one optional optimization. I think you can evaluate all the patterns in one go by joining them into a single regex before compiling:

parts = append(parts, `(?:` + raw + `)`)
// ...
regexp.Compile(`^(?:` + strings.Join(parts, `|`) + `)$`)

this would get rid of the loop but its more cosmetic than anything since the actual optimization isn't huge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants