Skip to content

Commit

Permalink
🧹 Retry login command when concurrent IAM updates are detected (#3151)
Browse files Browse the repository at this point in the history
* 🧹 Retry login command when concurrent IAM updates are detected

If the server returns aborted for RegisterAgent, that means it aborted
the change because of concurrent writes to the IAM policy, likely
meaning concurrent registrations. Clients are safe to backoff and
retry in this case.

* 🧹 improve logout error message on cli

---------

Co-authored-by: Christoph Hartmann <[email protected]>
  • Loading branch information
jaym and chris-rock authored Jan 29, 2024
1 parent 99ef99a commit f493c37
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
33 changes: 31 additions & 2 deletions apps/cnquery/cmd/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package cmd

import (
"context"
"math/rand"
"strings"
"time"

Expand All @@ -19,7 +20,9 @@ import (
"go.mondoo.com/cnquery/v10/providers-sdk/v1/sysinfo"
"go.mondoo.com/cnquery/v10/providers-sdk/v1/upstream"
"go.mondoo.com/ranger-rpc"
"go.mondoo.com/ranger-rpc/codes"
"go.mondoo.com/ranger-rpc/plugins/authentication/statictoken"
"go.mondoo.com/ranger-rpc/status"
)

func init() {
Expand Down Expand Up @@ -116,7 +119,7 @@ func register(token string, annotations map[string]string) error {
name = sysInfo.Hostname
}

confirmation, err := client.RegisterAgent(context.Background(), &upstream.AgentRegistrationRequest{
confirmation, err := registerAgent(context.Background(), client, &upstream.AgentRegistrationRequest{
Token: token,
Name: name,
AgentInfo: &upstream.AgentInfo{
Expand Down Expand Up @@ -193,7 +196,7 @@ func register(token string, annotations map[string]string) error {
name = sysInfo.Hostname
}

confirmation, err := client.RegisterAgent(context.Background(), &upstream.AgentRegistrationRequest{
confirmation, err := registerAgent(context.Background(), client, &upstream.AgentRegistrationRequest{
Name: name,
AgentInfo: &upstream.AgentInfo{
Mrn: opts.AgentMrn,
Expand Down Expand Up @@ -247,3 +250,29 @@ func register(token string, annotations map[string]string) error {
log.Info().Msgf("client %s has logged in successfully", viper.Get("agent_mrn"))
return nil
}

func registerAgent(ctx context.Context, client *upstream.AgentManagerClient, req *upstream.AgentRegistrationRequest) (*upstream.AgentRegistrationConfirmation, error) {
const maxRetries = 3
try := 0
for {
confirmation, err := client.RegisterAgent(ctx, req)
if err != nil {
if status.Code(err) == codes.Aborted {
jitter := time.Duration(rand.Intn(5000)) * time.Millisecond
sleepTime := 5*(1<<try)*time.Second + jitter

try++
if try > maxRetries {
return nil, errors.Wrap(err, "failed to log in client due to concurrent IAM changes")
}

log.Warn().Err(err).Msgf("failed to log in client due to concurrent IAM changes, retrying (%d/%d) in %dms", try, maxRetries, sleepTime.Milliseconds())
time.Sleep(sleepTime)
} else {
return nil, errors.Wrap(err, "failed to log in client")
}
} else {
return confirmation, nil
}
}
}
2 changes: 1 addition & 1 deletion apps/cnquery/cmd/logout.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ ensure the credentials cannot be used in the future.

if !viper.GetBool("force") {
log.Info().Msg("are you sure you want to revoke client access to Mondoo Platform? Use --force if you are sure")
return cli_errors.ExitCode1WithoutError
return cli_errors.NewCommandError(errors.New("--force is required to logout"), ConfigurationErrorCode)
}

// try to load config into credentials struct
Expand Down

0 comments on commit f493c37

Please sign in to comment.