Skip to content
Open
2 changes: 2 additions & 0 deletions cmd/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

"github.com/formancehq/go-libs/v5/pkg/cloud/aws/iam"
"github.com/formancehq/go-libs/v5/pkg/fx/storagefx"
"github.com/formancehq/go-libs/v5/pkg/observe/metrics"
"github.com/formancehq/go-libs/v5/pkg/observe/traces"
Expand Down Expand Up @@ -132,6 +133,7 @@ func NewWorkerCommand() *cobra.Command {
connect.AddFlags(cmd.Flags())
metrics.AddFlags(cmd.Flags())
traces.AddFlags(cmd.Flags())
iam.AddFlags(cmd.Flags())
Comment thread
NumaryBot marked this conversation as resolved.
Comment thread
NumaryBot marked this conversation as resolved.

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.

🟠 [major] --aws-role-arn flag is registered but silently ignored in the Postgres IAM connection path
reported by codex, gfyrag, NumaryBot

The worker command registers --aws-role-arn (alongside --postgres-aws-enable-iam), but connect.ConnectionOptionsFromFlags loads AWS config via iam.LoadOptionFromFlags, which reads region/static keys/session/profile but not role ARN. A worker started with --postgres-aws-enable-iam --aws-role-arn will not assume the requested role; it silently falls back to the default/static credential chain. MarkHidden (if used) only hides the flag from help output — Cobra still parses and accepts it — so the no-op behaviour is invisible to operators.

Suggestion: Either (a) make the connection path consume AWSRoleArnFlag by wrapping the loaded credentials with stscreds.NewAssumeRoleProvider + aws.NewCredentialsCache when the flag is non-empty, (b) do not register --aws-role-arn on the worker command at all until the underlying library supports it and document the limitation clearly, or (c) add an explicit pre-run validation that returns a clear error when --aws-role-arn is set alongside --postgres-aws-enable-iam so operators are not silently misled.


return cmd
}
Expand Down
90 changes: 90 additions & 0 deletions cmd/worker_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package cmd

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/formancehq/go-libs/v5/pkg/cloud/aws/iam"
"github.com/formancehq/go-libs/v5/pkg/storage/bun/connect"
)

// TestWorkerCommandHasAWSIAMFlags verifies that the worker command registers
// all required AWS IAM flags, so that users running the standalone worker binary
// (e.g. on AWS ECS Fargate) can configure RDS IAM auth for the primary store
// via CLI flags, not just via environment variables.
//
func TestWorkerCommandHasAWSIAMFlags(t *testing.T) {
t.Parallel()

cmd := NewWorkerCommand()
flags := cmd.Flags()

// These flags come from connect.AddFlags and enable IAM on the primary store
t.Run("postgres-aws-enable-iam flag is registered", func(t *testing.T) {
t.Parallel()
f := flags.Lookup(connect.PostgresAWSEnableIAMFlag)
require.NotNil(t, f, "--postgres-aws-enable-iam flag must be registered on the worker command")
assert.Equal(t, "false", f.DefValue)
})

// These flags come from iam.AddFlags (added to fix issue #1556)
t.Run("aws-region flag is registered", func(t *testing.T) {
t.Parallel()
f := flags.Lookup(iam.AWSRegionFlag)
require.NotNil(t, f, "--aws-region flag must be registered on the worker command")
})

t.Run("aws-access-key-id flag is registered", func(t *testing.T) {
t.Parallel()
f := flags.Lookup(iam.AWSAccessKeyIDFlag)
require.NotNil(t, f, "--aws-access-key-id flag must be registered on the worker command")
})

t.Run("aws-secret-access-key flag is registered", func(t *testing.T) {
t.Parallel()
f := flags.Lookup(iam.AWSSecretAccessKeyFlag)
require.NotNil(t, f, "--aws-secret-access-key flag must be registered on the worker command")
})

t.Run("aws-session-token flag is registered", func(t *testing.T) {
t.Parallel()
f := flags.Lookup(iam.AWSSessionTokenFlag)
require.NotNil(t, f, "--aws-session-token flag must be registered on the worker command")
})

t.Run("aws-role-arn flag is registered", func(t *testing.T) {
t.Parallel()
f := flags.Lookup(iam.AWSRoleArnFlag)
require.NotNil(t, f, "--aws-role-arn flag must be registered on the worker command")
})
}

// TestServeCommandHasAWSIAMFlags verifies the serve command also exposes
// the same AWS IAM flags for parity (regression guard).
func TestServeCommandHasAWSIAMFlags(t *testing.T) {
t.Parallel()

cmd := NewServeCommand()
flags := cmd.Flags()

iamFlags := []string{
connect.PostgresAWSEnableIAMFlag,
iam.AWSRegionFlag,
iam.AWSAccessKeyIDFlag,
iam.AWSSecretAccessKeyFlag,
iam.AWSSessionTokenFlag,
iam.AWSRoleArnFlag,
}

for _, flagName := range iamFlags {
flagName := flagName
t.Run(flagName+" is registered on serve", func(t *testing.T) {
t.Parallel()
f := flags.Lookup(flagName)
require.NotNil(t, f, "--%s flag must be registered on the serve command", flagName)
})
}
}