Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ linters:
- importas
- ineffassign
- misspell
- nolintlint
# Disabled because of https://github.com/argoproj/argo-cd/issues/21705
# - nolintlint
- perfsprint
- revive
- staticcheck
Expand All @@ -29,12 +30,12 @@ linters:
- unparam
- unused
- usestdlibvars
- whitespace
- whitespace
linters-settings:
gocritic:
disabled-checks:
- appendAssign
- assignOp # Keep it disabled for readability
- assignOp # Keep it disabled for readability
- exitAfterDefer
- mapKey
- typeSwitchVar
Expand All @@ -49,23 +50,23 @@ linters-settings:
- github.com/imdario/mergo:
recommendations:
- dario.cat/mergo
reason: "`github.com/imdario/mergo` has been renamed."
reason: '`github.com/imdario/mergo` has been renamed.'
- github.com/pkg/errors:
recommendations:
- errors
importas:
alias:
- alias: jwtgo
- alias: jwtgo
pkg: github.com/golang-jwt/jwt/v5
- alias: appsv1
pkg: k8s.io/api/apps/v1
- alias: corev1
pkg: k8s.io/api/core/v1
- alias: rbacv1
pkg: k8s.io/api/rbac/v1
- alias: apierrors
- alias: apierrors
pkg: k8s.io/apimachinery/pkg/api/errors
- alias: metav1
- alias: metav1
pkg: k8s.io/apimachinery/pkg/apis/meta/v1
- alias: informersv1
pkg: k8s.io/client-go/informers/core/v1
Expand All @@ -92,15 +93,15 @@ linters-settings:
disabled: true
- name: context-as-argument
arguments:
- allowTypesBefore: "*testing.T,testing.TB"
- allowTypesBefore: '*testing.T,testing.TB'
- name: context-keys-type
disabled: true
- name: dot-imports
disabled: true
- name: duplicated-imports
- name: early-return
arguments:
- "preserveScope"
- 'preserveScope'
- name: empty-block
disabled: true
- name: error-naming
Expand All @@ -114,7 +115,7 @@ linters-settings:
- name: increment-decrement
- name: indent-error-flow
arguments:
- "preserveScope"
- 'preserveScope'
- name: modifies-parameter
- name: optimize-operands-order
- name: range
Expand All @@ -124,7 +125,7 @@ linters-settings:
- name: redundant-import-alias
- name: superfluous-else
arguments:
- "preserveScope"
- 'preserveScope'
- name: time-equal
- name: time-naming
disabled: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func NewCommand() *cobra.Command {
metricsCacheExpiration time.Duration
metricsAplicationLabels []string
metricsAplicationConditions []string
metricsClusterLabels []string
kubectlParallelismLimit int64
cacheSource func() (*appstatecache.Cache, error)
redisClient *redis.Client
Expand Down Expand Up @@ -202,6 +203,7 @@ func NewCommand() *cobra.Command {
metricsCacheExpiration,
metricsAplicationLabels,
metricsAplicationConditions,
metricsClusterLabels,
kubectlParallelismLimit,
persistResourceHealth,
clusterSharding,
Expand Down Expand Up @@ -272,6 +274,7 @@ func NewCommand() *cobra.Command {
command.Flags().BoolVar(&repoServerStrictTLS, "repo-server-strict-tls", env.ParseBoolFromEnv("ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_STRICT_TLS", false), "Whether to use strict validation of the TLS cert presented by the repo server")
command.Flags().StringSliceVar(&metricsAplicationLabels, "metrics-application-labels", []string{}, "List of Application labels that will be added to the argocd_application_labels metric")
command.Flags().StringSliceVar(&metricsAplicationConditions, "metrics-application-conditions", []string{}, "List of Application conditions that will be added to the argocd_application_conditions metric")
command.Flags().StringSliceVar(&metricsClusterLabels, "metrics-cluster-labels", []string{}, "List of Cluster labels that will be added to the argocd_cluster_labels metric")
command.Flags().StringVar(&otlpAddress, "otlp-address", env.StringFromEnv("ARGOCD_APPLICATION_CONTROLLER_OTLP_ADDRESS", ""), "OpenTelemetry collector address to send traces to")
command.Flags().BoolVar(&otlpInsecure, "otlp-insecure", env.ParseBoolFromEnv("ARGOCD_APPLICATION_CONTROLLER_OTLP_INSECURE", true), "OpenTelemetry collector insecure mode")
command.Flags().StringToStringVar(&otlpHeaders, "otlp-headers", env.ParseStringToStringFromEnv("ARGOCD_APPLICATION_CONTROLLER_OTLP_HEADERS", map[string]string{}, ","), "List of OpenTelemetry collector extra headers sent with traces, headers are comma-separated key-value pairs(e.g. key1=value1,key2=value2)")
Expand Down
21 changes: 13 additions & 8 deletions cmd/argocd/commands/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ import (
argocdclient "github.com/argoproj/argo-cd/v3/pkg/apiclient"
sessionpkg "github.com/argoproj/argo-cd/v3/pkg/apiclient/session"
settingspkg "github.com/argoproj/argo-cd/v3/pkg/apiclient/settings"
claimsutil "github.com/argoproj/argo-cd/v3/util/claims"
"github.com/argoproj/argo-cd/v3/util/cli"
"github.com/argoproj/argo-cd/v3/util/errors"
grpc_util "github.com/argoproj/argo-cd/v3/util/grpc"
"github.com/argoproj/argo-cd/v3/util/io"
jwtutil "github.com/argoproj/argo-cd/v3/util/jwt"
"github.com/argoproj/argo-cd/v3/util/localconfig"
oidcutil "github.com/argoproj/argo-cd/v3/util/oidc"
"github.com/argoproj/argo-cd/v3/util/rand"
Expand Down Expand Up @@ -143,7 +143,9 @@ argocd login cd.argoproj.io --core`,
claims := jwt.MapClaims{}
_, _, err := parser.ParseUnverified(tokenString, &claims)
errors.CheckError(err)
fmt.Printf("'%s' logged in successfully\n", userDisplayName(claims))
argoClaims, err := claimsutil.MapClaimsToArgoClaims(claims)
errors.CheckError(err)
fmt.Printf("'%s' logged in successfully\n", userDisplayName(argoClaims))
}

// login successful. Persist the config
Expand Down Expand Up @@ -190,14 +192,17 @@ argocd login cd.argoproj.io --core`,
return command
}

func userDisplayName(claims jwt.MapClaims) string {
if email := jwtutil.StringField(claims, "email"); email != "" {
return email
func userDisplayName(claims *claimsutil.ArgoClaims) string {
if claims == nil {
return ""
}
if claims.Email != "" {
return claims.Email
}
if name := jwtutil.StringField(claims, "name"); name != "" {
return name
if claims.Name != "" {
return claims.Name
}
return jwtutil.StringField(claims, "sub")
return claims.GetUserIdentifier()
}

// oauth2Login opens a browser, runs a temporary HTTP server to delegate OAuth2 login flow and
Expand Down
27 changes: 24 additions & 3 deletions cmd/argocd/commands/login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import (
"os"
"testing"

claimsutil "github.com/argoproj/argo-cd/v3/util/claims"
utils "github.com/argoproj/argo-cd/v3/util/io"

"github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func captureStdout(callback func()) (string, error) {
Expand All @@ -35,26 +37,45 @@ func captureStdout(callback func()) (string, error) {
}

func Test_userDisplayName_email(t *testing.T) {
claims := jwt.MapClaims{"iss": "qux", "sub": "foo", "email": "firstname.lastname@example.com", "groups": []string{"baz"}}
claims, err := claimsutil.MapClaimsToArgoClaims(jwt.MapClaims{"iss": "qux", "sub": "foo", "email": "firstname.lastname@example.com", "groups": []string{"baz"}})
require.NoError(t, err)
actualName := userDisplayName(claims)
expectedName := "firstname.lastname@example.com"
assert.Equal(t, expectedName, actualName)
}

func Test_userDisplayName_name(t *testing.T) {
claims := jwt.MapClaims{"iss": "qux", "sub": "foo", "name": "Firstname Lastname", "groups": []string{"baz"}}
claims, err := claimsutil.MapClaimsToArgoClaims(jwt.MapClaims{"iss": "qux", "sub": "foo", "name": "Firstname Lastname", "groups": []string{"baz"}})
require.NoError(t, err)
actualName := userDisplayName(claims)
expectedName := "Firstname Lastname"
assert.Equal(t, expectedName, actualName)
}

func Test_userDisplayName_sub(t *testing.T) {
claims := jwt.MapClaims{"iss": "qux", "sub": "foo", "groups": []string{"baz"}}
claims, err := claimsutil.MapClaimsToArgoClaims(jwt.MapClaims{"iss": "qux", "sub": "foo", "groups": []string{"baz"}})
require.NoError(t, err)
actualName := userDisplayName(claims)
expectedName := "foo"
assert.Equal(t, expectedName, actualName)
}

func Test_userDisplayName_federatedClaims(t *testing.T) {
claims, err := claimsutil.MapClaimsToArgoClaims(jwt.MapClaims{
"iss": "qux",
"sub": "foo",
"groups": []string{"baz"},
"federated_claims": map[string]any{
"connector_id": "dex",
"user_id": "ldap-123",
},
})
require.NoError(t, err)
actualName := userDisplayName(claims)
expectedName := "ldap-123"
assert.Equal(t, expectedName, actualName)
}

func Test_ssoAuthFlow_ssoLaunchBrowser_false(t *testing.T) {
out, _ := captureStdout(func() {
ssoAuthFlow("http://test-sso-browser-flow.com", false)
Expand Down
21 changes: 14 additions & 7 deletions cmd/argocd/commands/project_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
argocdclient "github.com/argoproj/argo-cd/v3/pkg/apiclient"
projectpkg "github.com/argoproj/argo-cd/v3/pkg/apiclient/project"
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
claimsutil "github.com/argoproj/argo-cd/v3/util/claims"
"github.com/argoproj/argo-cd/v3/util/errors"
"github.com/argoproj/argo-cd/v3/util/io"
"github.com/argoproj/argo-cd/v3/util/jwt"
Expand Down Expand Up @@ -191,7 +192,7 @@ func NewProjectRoleCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra.
command := &cobra.Command{
Use: "create PROJECT ROLE-NAME",
Short: "Create a project role",
Example: templates.Examples(`
Example: templates.Examples(`
# Create a project role in the "my-project" project with the name "my-role".
argocd proj role create my-project my-role --description "My project role description"
`),
Expand Down Expand Up @@ -321,18 +322,24 @@ Create token succeeded for proj:test-project:test-role.
})
errors.CheckError(err)

token, err := jwtgo.Parse(tokenResponse.Token, nil)
if token == nil {
var claims jwtgo.MapClaims
_, _, err = jwtgo.NewParser().ParseUnverified(tokenResponse.Token, &claims)
if err != nil {
err = fmt.Errorf("received malformed token %w", err)
errors.CheckError(err)
return
}

claims := token.Claims.(jwtgo.MapClaims)
argoClaims, err := claimsutil.MapClaimsToArgoClaims(claims)
if err != nil {
errors.CheckError(fmt.Errorf("invalid argo claims: %w", err))
return
}

issuedAt, _ := jwt.IssuedAt(claims)
expiresAt := int64(jwt.Float64Field(claims, "exp"))
id := jwt.StringField(claims, "jti")
subject := jwt.StringField(claims, "sub")
id := argoClaims.ID
subject := argoClaims.GetUserIdentifier()

if !outputTokenOnly {
fmt.Printf("Create token succeeded for %s.\n", subject)
Expand Down Expand Up @@ -496,7 +503,7 @@ func NewProjectRoleListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
command := &cobra.Command{
Use: "list PROJECT",
Short: "List all the roles in a project",
Example: templates.Examples(`
Example: templates.Examples(`
# This command will list all the roles in argocd-project in a default table format.
argocd proj role list PROJECT

Expand Down
5 changes: 4 additions & 1 deletion controller/appcontroller.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ type ApplicationController struct {
refreshRequestedApps map[string]CompareWith
refreshRequestedAppsMutex *sync.Mutex
metricsServer *metrics.MetricsServer
metricsClusterLabels []string
kubectlSemaphore *semaphore.Weighted
clusterSharding sharding.ClusterShardingCache
projByNameCache sync.Map
Expand Down Expand Up @@ -173,6 +174,7 @@ func NewApplicationController(
metricsCacheExpiration time.Duration,
metricsApplicationLabels []string,
metricsApplicationConditions []string,
metricsClusterLabels []string,
kubectlParallelismLimit int64,
persistResourceHealth bool,
clusterSharding sharding.ClusterShardingCache,
Expand Down Expand Up @@ -218,6 +220,7 @@ func NewApplicationController(
applicationNamespaces: applicationNamespaces,
dynamicClusterDistributionEnabled: dynamicClusterDistributionEnabled,
ignoreNormalizerOpts: ignoreNormalizerOpts,
metricsClusterLabels: metricsClusterLabels,
}
if hydratorEnabled {
ctrl.hydrator = hydrator.NewHydrator(&ctrl, appResyncPeriod, commitClientset)
Expand Down Expand Up @@ -857,8 +860,8 @@ func (ctrl *ApplicationController) Run(ctx context.Context, statusProcessors int
defer ctrl.appHydrateQueue.ShutDown()
defer ctrl.hydrationQueue.ShutDown()

ctrl.metricsServer.RegisterClustersInfoSource(ctx, ctrl.stateCache)
ctrl.RegisterClusterSecretUpdater(ctx)
ctrl.metricsServer.RegisterClustersInfoSource(ctx, ctrl.stateCache, ctrl.db, ctrl.metricsClusterLabels)

go ctrl.appInformer.Run(ctx.Done())
go ctrl.projInformer.Run(ctx.Done())
Expand Down
1 change: 1 addition & 0 deletions controller/appcontroller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ func newFakeControllerWithResync(data *fakeData, appResyncPeriod time.Duration,
data.metricsCacheExpiration,
[]string{},
[]string{},
[]string{},
0,
true,
nil,
Expand Down
Loading