Skip to content

Validate GitRepo defaults from GitRepoRestriction and Policy against allow-lists#5285

Open
p-se wants to merge 3 commits into
rancher:mainfrom
p-se:policy-inconsistency
Open

Validate GitRepo defaults from GitRepoRestriction and Policy against allow-lists#5285
p-se wants to merge 3 commits into
rancher:mainfrom
p-se:policy-inconsistency

Conversation

@p-se

@p-se p-se commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

When a GitRepoRestriction (or Policy) defines a defaultServiceAccount that is not contained in a non-empty allowedServiceAccounts (and likewise defaultClientSecretName vs allowedClientSecretNames), the GitRepo reconciler applies the default to gitrepo.spec and persists it before that value is validated against the allow-list. The disallowed value is validated only on the following reconcile, once it is an explicit spec field, and the GitRepo is rejected then.

This is inconsistent with the HelmOp and Bundle paths, which validate defaults before applying them.

Steps to reproduce

# GitRepoRestriction in fleet-local
apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepoRestriction
metadata: { name: repro, namespace: fleet-local }
defaultServiceAccount: some-default-sa
allowedServiceAccounts: [some-other-sa]   # non-empty, does NOT contain the default
# GitRepo in fleet-local with no serviceAccount set
apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepo
metadata: { name: repro, namespace: fleet-local }
spec:
  repo: https://github.com/rancher/fleet-examples

Apply the restriction, then the GitRepo, and inspect it.

Expected

The GitRepo is rejected without spec.serviceAccount being modified; metadata.generation stays 1.

Actual

spec.serviceAccount is set to some-default-sa, metadata.generation becomes 2, and only then is the GitRepo rejected (Accepted=False, PolicyViolation event).

Refers to #5422

Additional Information

Checklist

  • I have updated the documentation via a pull request in the fleet-product-docs repository.

p-se added 2 commits June 15, 2026 08:49
Defaults like defaultServiceAccount and defaultClientSecretName were
applied via isAllowed's fallback before being checked against the
allow-list, silently accepting disallowed values. Resolve defaults
first, then validate — consistent with HelmOp and Bundle paths.
Defaults are now resolved by the caller before validation, so the
defaultValue parameter and string return are dead code.
Copilot AI review requested due to automatic review settings June 15, 2026 13:52
@p-se p-se requested a review from a team as a code owner June 15, 2026 13:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR tightens restriction enforcement for GitRepo by ensuring defaults coming from GitRepoRestriction and Policy are validated against allow-lists (matching existing HelmOp/Bundle behavior), instead of being silently accepted.

Changes:

  • Resolve serviceAccount / clientSecretName defaults before allow-list validation so disallowed defaults are rejected.
  • Simplify isAllowed to a validation-only helper (no defaulting), and adjust call sites accordingly.
  • Update/add unit tests to cover the “default not in allow-list is denied” behavior for GitRepoRestriction.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
internal/cmd/controller/gitops/reconciler/restrictions.go Apply defaults before allow-list checks; refactor allow-list helper to validate-only.
internal/cmd/controller/gitops/reconciler/restrictions_test.go Update defaulting test data and add coverage for rejecting disallowed defaults (GitRepoRestriction path).

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

},
expectedErr: "disallowed clientSecretName.*",
},
{

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.

Those test are exercising the same path as GRR is to be removed eventually, it does make sense to have tests that cover Policy to make sure those aren't lost when GRR is removed.

p-se added a commit to p-se/fleet-product-docs that referenced this pull request Jun 15, 2026
p-se added a commit to p-se/fleet-product-docs that referenced this pull request Jun 15, 2026
p-se added a commit to p-se/fleet-product-docs that referenced this pull request Jun 15, 2026

repo, err := isAllowedByRepo(gitrepo.Spec.Repo, grr.AllowedRepoPatterns, pol.GitAllowedRepoPatterns)
if err != nil {
if _, err := isAllowedByRepo(gitrepo.Spec.Repo, grr.AllowedRepoPatterns, pol.GitAllowedRepoPatterns); err != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: isAllowedByRepo seems to only be used here, so we could refactor it to return a single value.

// Apply defaults before validation, so a default that is not in the allow-list
// is rejected rather than silently accepted. This keeps the GitRepo path
// consistent with the HelmOp and Bundle paths.
serviceAccount := firstNonEmpty(gitrepo.Spec.ServiceAccount, defaultSA)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: if the target namespace validation fails, we don't even need to compute these.

- isAllowedByRepo returns only an error; the repo string it returned was
  always the input and discarded at the sole call site.
- Add standalone Policy cases covering defaultServiceAccount and
  defaultClientSecretName rejected against non-empty allow-lists, so the
  Policy path stays covered once GitRepoRestriction is removed.
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.

3 participants