-
Notifications
You must be signed in to change notification settings - Fork 27
feat(agent): select Conjur JWT or legacy username/password authenticator #822
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
mladen-rusev-cyberark
merged 5 commits into
jetstack:master
from
roeezis:split/05-auth-wiring
Aug 27, 2026
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
ffa53d1
CP-21164: add jwtsource package for reading projected SA tokens
33e6b50
CP-21164: split legacy username/password login into its own file
ee1907b
CP-21164: resolve secrets_manager alongside identity_administration
987bd4b
CP-21164: add Conjur JWT authentication client
7e4e017
CP-21164: select Conjur JWT or legacy username/password authenticator
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| package cyberark_test | ||
|
|
||
| import ( | ||
| "net/http" | ||
| "os" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/require" | ||
| "k8s.io/klog/v2" | ||
| "k8s.io/klog/v2/ktesting" | ||
|
|
||
| "github.com/jetstack/preflight/internal/cyberark" | ||
| "github.com/jetstack/preflight/internal/cyberark/conjur" | ||
| "github.com/jetstack/preflight/internal/cyberark/dataupload" | ||
| "github.com/jetstack/preflight/internal/cyberark/identity" | ||
| "github.com/jetstack/preflight/internal/cyberark/servicediscovery" | ||
|
|
||
| _ "k8s.io/klog/v2/ktesting/init" | ||
| ) | ||
|
|
||
| // The agent supports two coexisting auth methods (the product is GA). These | ||
| // tests pin the selection rule in NewDatauploadClient / selectAuthenticator: | ||
| // - ServiceID set → Conjur JWT exchange | ||
| // - else Username+Secret present → legacy username/password | ||
| // - both set → Conjur wins | ||
| // - neither → ErrNoAuthMethod | ||
| func TestNewDatauploadClient_AuthMethodSelection(t *testing.T) { | ||
| logger := ktesting.NewLogger(t, ktesting.DefaultConfig) | ||
| ctx := klog.NewContext(t.Context(), logger) | ||
|
|
||
| const conjurToken = "success-token" // matches dataupload mock's expected bearer token | ||
|
|
||
| writeJWT := func(t *testing.T) string { | ||
| t.Helper() | ||
| f, err := os.CreateTemp(t.TempDir(), "jwt-*") | ||
| require.NoError(t, err) | ||
| _, err = f.WriteString("fake-service-account-jwt") | ||
| require.NoError(t, err) | ||
| require.NoError(t, f.Close()) | ||
| return f.Name() | ||
| } | ||
|
|
||
| // stack builds a service map whose DiscoveryContext points at a dataupload | ||
| // mock (which requires Authorization: Bearer success-token). The Identity | ||
| // and SecretsManager endpoints are supplied separately and deliberately | ||
| // differ: the username/password path must use Identity and the Conjur | ||
| // authn-jwt exchange must use SecretsManager, so pointing a mock at only | ||
| // one of them proves which endpoint the code actually called. | ||
| stack := func(t *testing.T, identityAPI, smsAPI string) *servicediscovery.Services { | ||
| t.Helper() | ||
| discoveryContextAPI, _ := dataupload.MockDataUploadServer(t) | ||
| return &servicediscovery.Services{ | ||
| Identity: servicediscovery.ServiceEndpoint{API: identityAPI}, | ||
| DiscoveryContext: servicediscovery.ServiceEndpoint{API: discoveryContextAPI}, | ||
| SecretsManager: servicediscovery.ServiceEndpoint{API: smsAPI}, | ||
| } | ||
| } | ||
|
|
||
| // Endpoints that must never be dialled by the path under test. | ||
| const unusedIdentity = "https://identity.example.invalid" | ||
| const unusedSMS = "https://secretsmgr.example.invalid" | ||
|
|
||
| t.Run("serviceID set -> conjur path", func(t *testing.T) { | ||
| conjurSrv, _ := conjur.MockConjurExchangeServer(t, conjurToken) | ||
| t.Cleanup(conjurSrv.Close) | ||
|
|
||
| cfg := cyberark.ClientConfig{ | ||
| ServiceID: "dev-cluster", | ||
| JWTFilePath: writeJWT(t), | ||
| } | ||
| _, err := cyberark.NewDatauploadClient(ctx, conjurSrv.Client(), stack(t, unusedIdentity, conjurSrv.URL), "tenant", cfg) | ||
| require.NoError(t, err) | ||
| }) | ||
|
|
||
| t.Run("username/password only -> identity path", func(t *testing.T) { | ||
| identityURL, httpClient := identity.MockIdentityServer(t) | ||
|
|
||
| cfg := cyberark.ClientConfig{ | ||
| Subdomain: "tenant-sub", | ||
| Username: identity.MockSuccessUser, | ||
| Secret: []byte(identity.MockSuccessPassword), | ||
| } | ||
| // Login happens during construction; success proves the UP path ran. | ||
| _, err := cyberark.NewDatauploadClient(ctx, httpClient, stack(t, identityURL, unusedSMS), "tenant", cfg) | ||
| require.NoError(t, err) | ||
| }) | ||
|
|
||
| t.Run("both set -> conjur wins", func(t *testing.T) { | ||
| conjurSrv, _ := conjur.MockConjurExchangeServer(t, conjurToken) | ||
| t.Cleanup(conjurSrv.Close) | ||
|
|
||
| cfg := cyberark.ClientConfig{ | ||
| ServiceID: "dev-cluster", | ||
| JWTFilePath: writeJWT(t), | ||
| // UP creds present too — must be ignored. Deliberately bogus so that | ||
| // if the identity path were taken, login would fail. | ||
| Username: "should-not-be-used@example.com", | ||
| Secret: []byte("wrong-password"), | ||
| } | ||
| _, err := cyberark.NewDatauploadClient(ctx, conjurSrv.Client(), stack(t, unusedIdentity, conjurSrv.URL), "tenant", cfg) | ||
| require.NoError(t, err) // conjur path used; bogus UP creds never exercised | ||
| }) | ||
|
|
||
| t.Run("neither set -> ErrNoAuthMethod", func(t *testing.T) { | ||
| cfg := cyberark.ClientConfig{Subdomain: "tenant-sub"} | ||
| _, err := cyberark.NewDatauploadClient(ctx, &http.Client{}, stack(t, unusedIdentity, unusedSMS), "tenant", cfg) | ||
| require.ErrorIs(t, err, cyberark.ErrNoAuthMethod) | ||
| }) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.