-
Notifications
You must be signed in to change notification settings - Fork 2
Auth and flow fixes #279
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
Auth and flow fixes #279
Conversation
…uth and devbox sessions
internal/locald/run.go
Outdated
| // initViperFromCIConfig initializes viper with the config file path from ciConfig | ||
| func initViperFromCIConfig(ciConfig *config.ConnectInvocationConfig) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a lot of duplication in this func vs:
Lines 34 to 56 in 1547b73
| if c.ConfigFile != "" { | |
| viper.SetConfigFile(c.ConfigFile) | |
| } else { | |
| signadotDir, err := system.GetSignadotDir() | |
| if err != nil { | |
| return err | |
| } | |
| viper.AddConfigPath(signadotDir) | |
| viper.SetConfigName("config") // Doesn't include extension. | |
| viper.SetConfigType("yaml") // File name will be "config.yaml". | |
| } | |
| viper.SetEnvPrefix("signadot") | |
| viper.AutomaticEnv() | |
| if err := viper.ReadInConfig(); err != nil { | |
| // The config file is optional (required params (org, apikey) can | |
| // be set by env var instead). | |
| if _, ok := err.(viper.ConfigFileNotFoundError); !ok { | |
| return fmt.Errorf("error reading config file: %w", err) | |
| } | |
| } |
Why don't we centralize this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't build:
$ go build ./cmd/signadot
# github.com/signadot/cli/internal/locald/sandboxmanager/apiclient
internal/locald/sandboxmanager/apiclient/apiclient.go:109:6: authType redeclared in this block
internal/locald/sandboxmanager/apiclient/apiclient.go:47:2: other declaration of authTypeThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry I thought the agent checked for that after nudging it to clean up...
| } | ||
|
|
||
| // CreateAPIClientWithLogger creates a unified API client with logging support | ||
| func CreateAPIClientWithLogger(ciConfig *config.ConnectInvocationConfig, authInfo *auth.ResolvedAuth, log *slog.Logger) (*client.SignadotAPI, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, this func deserves some normalization (repeated if statements, repeted logic, etc), e.g.:
cli/internal/locald/sandboxmanager/apiclient/apiclient.go
Lines 83 to 105 in 1547b73
| // Get API URL - prefer ciConfig (passed from connect command), then viper, then default | |
| // Note: In daemon context, viper may not be initialized, so ciConfig.APIURL is preferred | |
| apiURL := "https://api.signadot.com" | |
| apiURLSource := "default" | |
| if ciConfig != nil && ciConfig.APIURL != "" { | |
| apiURL = ciConfig.APIURL | |
| apiURLSource = "ciConfig" | |
| } else if apiURLFromViper := viper.GetString("api_url"); apiURLFromViper != "" { | |
| apiURL = apiURLFromViper | |
| apiURLSource = "viper" | |
| } | |
| log.Debug("CreateAPIClient: API URL resolved", | |
| "apiURL", apiURL, | |
| "source", apiURLSource, | |
| "ciConfigHasAPIURL", ciConfig != nil && ciConfig.APIURL != "", | |
| "viperHasAPIURL", viper.GetString("api_url") != "") | |
| // Create transport config | |
| cfg := &transport.APIConfig{ | |
| APIURL: apiURL, | |
| UserAgent: fmt.Sprintf("signadot-cli:%s", buildinfo.Version), | |
| Debug: false, | |
| } |
vs
cli/internal/locald/sandboxmanager/apiclient/apiclient.go
Lines 146 to 163 in 1547b73
| // Create an unauthenticated API client for the refresh call | |
| apiURL := "https://api.signadot.com" | |
| apiURLSource := "default" | |
| if apiURLFromViper := viper.GetString("api_url"); apiURLFromViper != "" { | |
| apiURL = apiURLFromViper | |
| apiURLSource = "viper" | |
| } | |
| log.Debug("refreshBearerToken: using API URL for refresh", | |
| "apiURL", apiURL, | |
| "source", apiURLSource, | |
| "hasRefreshToken", authInfo.RefreshToken != "") | |
| cfg := &transport.APIConfig{ | |
| APIURL: apiURL, | |
| UserAgent: fmt.Sprintf("signadot-cli:%s", buildinfo.Version), | |
| Debug: false, | |
| } |
These are pretty much the same, and in the first case we use ciConfig while in the second we don't.
| } | ||
|
|
||
| // refreshBearerToken refreshes an expired bearer token using the refresh token | ||
| func refreshBearerToken(authInfo *auth.ResolvedAuth, log *slog.Logger) (*auth.ResolvedAuth, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@scott-cotton, did you test the refresh token works fine?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
|
@daniel-de-vera comments addressed |
daniel-de-vera
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
* remove the rpc for register sandbox, it is now unused * Auth and flow fixes (#279) * refactor auth and fix a default flow issue that crept in * add viper init with config file info in sbmgr and debug logging for auth and devbox sessions * CR followup
Summary
Stacked on #278
Refactors authentication logic into a unified shared package, fixes a bug where devbox sessions were being double-claimed when a devbox ID was explicitly provided, fixes daemon viper initialization causing incorrect auth resolution, and adds comprehensive debug logging for auth diagnostics.
Key Changes
Auth Refactoring
createAPIClientfunction frominternal/devbox/session_manager.gointo a new shared packageinternal/locald/sandboxmanager/apiclient/apiclient.goapiclient.CreateAPIClient()which handles:apiclient.GetAuthHeaders()function for consistent auth header resolution across componentsBug Fix: Double Devbox Claim Prevention
--devboxflag, the code would attempt to claim the devbox session even thoughdevbox.GetID()already handles claiming when no devbox ID is providedclaimedboolean flag to track whether the devbox was already claimed during ID retrieval, preventing duplicate claim attemptsBug Fix: Daemon Viper Initialization
locald) was not initializing viper with the config file specified via--configflag. This causedauth.ResolveAuth()to read from the wrong config file (default~/.signadot/config.yamlinstead of the specified config), leading to incorrect auth resolution (e.g., trying to use API keys from wrong config when bearer token auth should be used)ConfigFilefield toConnectInvocationConfigto pass the config file path from CLI to daemoninitViperFromCIConfig()helper function that initializes viper with the correct config file before auth resolutionRunSandboxManager()before creating components that use authDebug Logging Enhancements
slog.Default()when no logger provided, eliminating nil checks throughout the codebaseTechnical Details
session_manager.goto sharedapiclientpackageciConfigbefore any auth resolutionslog, with automatic fallback toslog.Default()when no logger providedTesting Notes
--devboxflag without double-claiming--devboxflag (auto-registration/retrieval)--configflag