Skip to content

feat: block auth/config when external credential provider is active#627

Open
MaxHuang22 wants to merge 6 commits intomainfrom
feat/auth-login-block
Open

feat: block auth/config when external credential provider is active#627
MaxHuang22 wants to merge 6 commits intomainfrom
feat/auth-login-block

Conversation

@MaxHuang22
Copy link
Copy Markdown
Collaborator

@MaxHuang22 MaxHuang22 commented Apr 23, 2026

Summary

When an external credential provider (env vars or sidecar) is active, the built-in auth and config command families are meaningless and potentially misleading — credentials are injected externally and the interactive management flow cannot function. This PR adds a guard that fails all subcommands under both families immediately with a structured error (exit 2, type external_provider), directing the user or calling agent toward the appropriate authorization channel instead.

Changes

  • internal/credential/credential_provider.go: add ActiveExtensionProviderName to probe extension providers directly (independent of the sync.Once cache)
  • internal/cmdutil/factory.go: add RequireBuiltinCredentialProvider guard helper returning a structured ErrWithHint error
  • cmd/auth/auth.go: wire PersistentPreRunE on the auth parent command; add cmd.SilenceUsage = true to replicate root-level behaviour
  • cmd/config/config.go: same guard wired on the config parent command
  • Tests: 5 unit tests in credential_provider_test.go, 3 in factory_test.go, 6-subtest TestAuthBlockedByExternalProvider in auth_test.go, 5-subtest TestConfigBlockedByExternalProvider in config_test.go, 15 E2E scenarios in tests_e2e/auth/

Test Plan

  • make unit-test passed
  • make validate passed
  • local-eval passed (E2E 15/15, skillave N/A — no shortcut/skill changes)
  • acceptance-reviewer passed (4/4 cases)
  • manual verification: LARKSUITE_CLI_APP_ID=fake lark-cli auth login → exit 2, {"ok":false,"error":{"type":"external_provider",...}}

Related Issues

N/A

Summary by CodeRabbit

  • Bug Fixes

    • auth and config commands now suppress usage output during pre-run and consistently block interactive credential operations when an external credential provider is active, returning a clear validation error (detail type "external_provider").
  • Tests

    • Added tests covering external-provider blocking and the new pre-run behavior to ensure consistent failures and error details across affected commands.

…providers

Change-Id: Ie17a4b714e5eca17ae574ac188d570721790107d
…l credential providers

Change-Id: I8f2ea0af6fe6506b29beb69264b04c21c0f75da1
…rovider is active

Change-Id: If215cb8f0a53cc92d623dd3d842e4465124af2be
…der is active

Change-Id: Ia61184fb2daeb6a7a38d122c647b7cb67eaf8b1f
…mmand behaviour

Change-Id: I6d4b3c7d9d9c7b10fc2482fdc80252bf051771ee
@github-actions github-actions Bot added the size/L Large or sensitive change across domains or core paths label Apr 23, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 23, 2026

Codecov Report

❌ Patch coverage is 87.50000% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.17%. Comparing base (3f4352d) to head (61facfc).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
internal/credential/credential_provider.go 72.22% 3 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #627      +/-   ##
==========================================
+ Coverage   59.94%   62.17%   +2.22%     
==========================================
  Files         405      407       +2     
  Lines       42673    35839    -6834     
==========================================
- Hits        25580    22282    -3298     
+ Misses      15084    11526    -3558     
- Partials     2009     2031      +22     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

📝 Walkthrough

Walkthrough

Adds runtime checks that block interactive auth and config command execution when an external credential provider is active. Introduces Factory.RequireBuiltinCredentialProvider and CredentialProvider.ActiveExtensionProviderName plus tests and command PersistentPreRunE hooks to enforce the guard.

Changes

Cohort / File(s) Summary
Auth command & tests
cmd/auth/auth.go, cmd/auth/auth_test.go
Adds PersistentPreRunE to silence usage and call RequireBuiltinCredentialProvider("auth"); test harness injects stub external provider and asserts subcommands fail with external_provider validation error and that SilenceUsage is set on matched subcommand.
Config command & tests
cmd/config/config.go, cmd/config/config_test.go
Adds PersistentPreRunE to silence usage and call RequireBuiltinCredentialProvider("config"); tests inject stub provider and assert config subcommands are blocked with external_provider validation error and SilenceUsage is set on matched subcommand.
Factory utility & tests
internal/cmdutil/factory.go, internal/cmdutil/factory_test.go
New RequireBuiltinCredentialProvider(ctx, command) added; returns a structured ExitValidation (Detail.Type=="external_provider") when an active extension provider exists; tests cover blocking, pass-through, nil-credential, and provider-error propagation cases.
Credential provider & tests
internal/credential/credential_provider.go, internal/credential/credential_provider_test.go
Adds ActiveExtensionProviderName(ctx) to probe extension providers for engagement (account or extcred.BlockError), returning provider name, empty string, or error as appropriate; tests cover success, block, absence, propagation of unexpected errors, and ignored providers.

Sequence Diagram

sequenceDiagram
    participant User
    participant Cmd as Auth/Config<br/>Command
    participant PreRun as PersistentPreRunE<br/>Hook
    participant Factory as cmdutil.Factory
    participant Cred as CredentialProvider
    participant Ext as ExternalProvider

    User->>Cmd: run subcommand
    Cmd->>PreRun: invoke PersistentPreRunE
    PreRun->>Factory: RequireBuiltinCredentialProvider(ctx, "auth"/"config")
    Factory->>Cred: ActiveExtensionProviderName(ctx)
    Cred->>Ext: ResolveAccount(ctx)
    alt external provider engaged (account or BlockError)
        Ext-->>Cred: account or BlockError
        Cred-->>Factory: provider name (non-empty)
        Factory-->>PreRun: ExitValidation error (Detail.Type="external_provider")
        PreRun-->>Cmd: return error (SilenceUsage set on matched subcommand)
        Cmd-->>User: execution blocked with validation error
    else no external provider engaged
        Ext-->>Cred: nil (no account) or no engagement
        Cred-->>Factory: "" (no provider)
        Factory-->>PreRun: nil
        PreRun-->>Cmd: continue
        Cmd-->>User: command proceeds
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I sniffed for external keys in the night,

If someone else tends them, I step light.
With a hop and a guard, I gently say “nay,”
Auth and config now politely stay.
🌿🔐

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and accurately summarizes the main change: blocking auth/config commands when external credential providers are active.
Description check ✅ Passed The PR description is comprehensive, following the template structure with Summary, Changes, Test Plan, and Related Issues sections. All required sections are present and well-detailed.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/auth-login-block

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 23, 2026

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@61facfc531f55de70aa9b806c3051e23c6153336

🧩 Skill update

npx skills add larksuite/cli#feat/auth-login-block -y -g

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/auth/auth_test.go`:
- Around line 351-354: The test currently pre-sets cmd.SilenceUsage = true which
masks the new PersistentPreRunE behavior in NewCmdAuth; remove or stop setting
cmd.SilenceUsage (leave it false) in the test, optionally discard command stderr
using io.Discard (add io to imports) so test output stays clean, run the command
with cmd.SetArgs(tt.args) and then assert that cmd.SilenceUsage (or the side
effect set by PersistentPreRunE) is true after execution to verify the new
behavior; keep cmd.SilenceErrors handling as needed but do not preconfigure
SilenceUsage before exercising PersistentPreRunE.

In `@cmd/config/config_test.go`:
- Around line 383-386: The test currently pre-sets cmd.SilenceUsage masking the
PersistentPreRunE guard; remove the line that sets SilenceUsage before running
NewCmdConfig/Execute, add io to imports and call cmd.SetErr(io.Discard) to keep
stderr quiet, then call cmd.Execute() and assert that cmd.SilenceUsage is true
(and keep SilenceErrors and cmd.SetArgs as-is); this verifies the new
PersistentPreRunE behavior rather than hiding it.

In `@internal/cmdutil/factory.go`:
- Around line 214-217: Add a unit test that verifies
RequireBuiltinCredentialProvider propagates provider errors: create a sentinel
error and a stub provider (e.g., stubExtProvider with name "env" that returns
the sentinel), build a credential provider set
(credential.NewCredentialProvider) and assign it to f.Credential from
TestFactory, then call f.RequireBuiltinCredentialProvider(ctx, "auth") and
assert the returned error is the sentinel using errors.Is; this ensures the
error produced by f.Credential.ActiveExtensionProviderName (and the
unexpected-error path) is not swallowed.

In `@internal/credential/credential_provider.go`:
- Around line 348-355: When returning the active provider string from the
credential check, ensure it is never empty: inside the errors.As branch for
extcred.BlockError (and in the acct != nil branch returning prov.Name()), if
blockErr.Provider or prov.Name() is empty, fall back first to prov.Name() (when
available) and then to a stable sentinel constant (e.g., "external-provider" or
"unknown-external-provider") so RequireBuiltinCredentialProvider cannot mistake
an engaged external provider for none; update the BlockError.Provider return
path and the prov.Name() return path to apply this fallback.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b66655f-9821-4aed-8f8d-bdb054b53e56

📥 Commits

Reviewing files that changed from the base of the PR and between 81d22c6 and 87b9c5b.

📒 Files selected for processing (8)
  • cmd/auth/auth.go
  • cmd/auth/auth_test.go
  • cmd/config/config.go
  • cmd/config/config_test.go
  • internal/cmdutil/factory.go
  • internal/cmdutil/factory_test.go
  • internal/credential/credential_provider.go
  • internal/credential/credential_provider_test.go

Comment thread cmd/auth/auth_test.go
Comment thread cmd/config/config_test.go
Comment thread internal/cmdutil/factory.go
Comment thread internal/credential/credential_provider.go Outdated
- Use cmd.Find() to assert SilenceUsage on matched subcommand (not parent)
- Add TestRequireBuiltinCredentialProvider_PropagatesProviderError for error path
- Add 'external' fallback sentinel in ActiveExtensionProviderName

Change-Id: Iba35779ad2ed9807556264ba23db7096541e2bf3
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
internal/cmdutil/factory_test.go (1)

407-414: Optional: make the "allows built-in" assertion explicit.

TestRequireBuiltinCredentialProvider_AllowsBuiltinProvider depends on whatever TestFactory wires up for f.Credential. If TestFactory ever returns a Credential with extension providers configured by default, this test silently becomes a no-op vs. the separate NilCredential case. Consider explicitly constructing a credential.NewCredentialProvider(nil, ...) with no extension providers to make the "built-in path" intent unambiguous.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmdutil/factory_test.go` around lines 407 - 414,
TestRequireBuiltinCredentialProvider_AllowsBuiltinProvider currently relies on
TestFactory to supply f.Credential which could include extension providers;
explicitly construct a credential provider with no extension providers (e.g.,
call credential.NewCredentialProvider(nil, <other-args>) or use the
NilCredential variant) and pass it into TestFactory or assign it to f.Credential
before calling f.RequireBuiltinCredentialProvider to ensure the test exercises
the built-in path unambiguously; update the test so it references
TestRequireBuiltinCredentialProvider_AllowsBuiltinProvider, TestFactory,
RequireBuiltinCredentialProvider, and credential.NewCredentialProvider (or
NilCredential) when making this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@internal/cmdutil/factory_test.go`:
- Around line 407-414:
TestRequireBuiltinCredentialProvider_AllowsBuiltinProvider currently relies on
TestFactory to supply f.Credential which could include extension providers;
explicitly construct a credential provider with no extension providers (e.g.,
call credential.NewCredentialProvider(nil, <other-args>) or use the
NilCredential variant) and pass it into TestFactory or assign it to f.Credential
before calling f.RequireBuiltinCredentialProvider to ensure the test exercises
the built-in path unambiguously; update the test so it references
TestRequireBuiltinCredentialProvider_AllowsBuiltinProvider, TestFactory,
RequireBuiltinCredentialProvider, and credential.NewCredentialProvider (or
NilCredential) when making this change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5d707ecb-365c-4ab8-aaf7-c2b5f7b2603f

📥 Commits

Reviewing files that changed from the base of the PR and between 87b9c5b and 61facfc.

📒 Files selected for processing (4)
  • cmd/auth/auth_test.go
  • cmd/config/config_test.go
  • internal/cmdutil/factory_test.go
  • internal/credential/credential_provider.go

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

Labels

feature size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant