From 97acbf9c537df2974474e599e35618b07609c588 Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Wed, 11 Apr 2018 17:11:40 -0700 Subject: [PATCH 1/4] Rebase all changes on to master --- cmd/argocd/commands/app.go | 13 ++++++------- cmd/argocd/commands/cluster.go | 10 +++++----- cmd/argocd/commands/repo.go | 7 +++---- cmd/argocd/commands/root.go | 22 +++++++++++++++++++++- pkg/apiclient/apiclient.go | 4 ++++ server/server.go | 22 ++++++++++++++++++++++ server/session/session.go | 5 +++++ util/session/sessionmanager.go | 6 ++++-- 8 files changed, 70 insertions(+), 19 deletions(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index a588bf86a885f..d4718629c0f1f 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "log" "net/url" @@ -99,7 +98,7 @@ func NewApplicationAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com } conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) - _, err := appIf.Create(context.Background(), &app) + _, err := appIf.Create(DefaultClientContext(clientOpts), &app) errors.CheckError(err) }, } @@ -126,7 +125,7 @@ func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) appName := args[0] - app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: appName}) + app, err := appIf.Get(DefaultClientContext(clientOpts), &application.ApplicationQuery{Name: appName}) errors.CheckError(err) format := "%-15s%s\n" fmt.Printf(format, "Name:", app.Name) @@ -176,7 +175,7 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) appName := args[0] - app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: appName}) + app, err := appIf.Get(DefaultClientContext(clientOpts), &application.ApplicationQuery{Name: appName}) errors.CheckError(err) targetObjs, err := app.Status.ComparisonResult.TargetObjects() errors.CheckError(err) @@ -215,7 +214,7 @@ func NewApplicationRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra. conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) for _, appName := range args { - _, err := appIf.Delete(context.Background(), &application.DeleteApplicationRequest{Name: appName}) + _, err := appIf.Delete(DefaultClientContext(clientOpts), &application.DeleteApplicationRequest{Name: appName}) errors.CheckError(err) } }, @@ -231,7 +230,7 @@ func NewApplicationListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co Run: func(c *cobra.Command, args []string) { conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) - apps, err := appIf.List(context.Background(), &application.ApplicationQuery{}) + apps, err := appIf.List(DefaultClientContext(clientOpts), &application.ApplicationQuery{}) errors.CheckError(err) w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) fmt.Fprintf(w, "NAME\tENVIRONMENT\tTARGET\tCLUSTER\tNAMESPACE\tSTATUS\n") @@ -275,7 +274,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co Name: appName, DryRun: dryRun, } - syncRes, err := appIf.Sync(context.Background(), &syncReq) + syncRes, err := appIf.Sync(DefaultClientContext(clientOpts), &syncReq) errors.CheckError(err) fmt.Printf("%s %s\n", appName, syncRes.Message) w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) diff --git a/cmd/argocd/commands/cluster.go b/cmd/argocd/commands/cluster.go index 862aa91945131..8928cdc2641bc 100644 --- a/cmd/argocd/commands/cluster.go +++ b/cmd/argocd/commands/cluster.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "io/ioutil" "os" @@ -73,7 +72,7 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie conn, clusterIf := argocdclient.NewClientOrDie(clientOpts).NewClusterClientOrDie() defer util.Close(conn) clst := NewCluster(args[0], conf) - clst, err = clusterIf.Create(context.Background(), clst) + clst, err = clusterIf.Create(DefaultClientContext(clientOpts), clst) errors.CheckError(err) fmt.Printf("Cluster '%s' added\n", clst.Name) }, @@ -159,7 +158,7 @@ func NewClusterGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command conn, clusterIf := argocdclient.NewClientOrDie(clientOpts).NewClusterClientOrDie() defer util.Close(conn) for _, clusterName := range args { - clst, err := clusterIf.Get(context.Background(), &cluster.ClusterQuery{Server: clusterName}) + clst, err := clusterIf.Get(DefaultClientContext(clientOpts), &cluster.ClusterQuery{Server: clusterName}) errors.CheckError(err) yamlBytes, err := yaml.Marshal(clst) errors.CheckError(err) @@ -185,7 +184,7 @@ func NewClusterRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comm for _, clusterName := range args { // TODO(jessesuen): find the right context and remove manager RBAC artifacts // common.UninstallClusterManagerRBAC(conf) - _, err := clusterIf.Delete(context.Background(), &cluster.ClusterQuery{Server: clusterName}) + _, err := clusterIf.Delete(DefaultClientContext(clientOpts), &cluster.ClusterQuery{Server: clusterName}) errors.CheckError(err) } }, @@ -201,7 +200,8 @@ func NewClusterListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman Run: func(c *cobra.Command, args []string) { conn, clusterIf := argocdclient.NewClientOrDie(clientOpts).NewClusterClientOrDie() defer util.Close(conn) - clusters, err := clusterIf.List(context.Background(), &cluster.ClusterQuery{}) + + clusters, err := clusterIf.List(DefaultClientContext(clientOpts), &cluster.ClusterQuery{}) errors.CheckError(err) w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) fmt.Fprintf(w, "SERVER\tNAME\n") diff --git a/cmd/argocd/commands/repo.go b/cmd/argocd/commands/repo.go index c2653927a8aa6..9d4c26d3db108 100644 --- a/cmd/argocd/commands/repo.go +++ b/cmd/argocd/commands/repo.go @@ -2,7 +2,6 @@ package commands import ( "bufio" - "context" "fmt" "io/ioutil" "os" @@ -72,7 +71,7 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { errors.CheckError(err) conn, repoIf := argocdclient.NewClientOrDie(clientOpts).NewRepoClientOrDie() defer util.Close(conn) - createdRepo, err := repoIf.Create(context.Background(), &repo) + createdRepo, err := repoIf.Create(DefaultClientContext(clientOpts), &repo) errors.CheckError(err) fmt.Printf("repository '%s' added\n", createdRepo.Repo) }, @@ -110,7 +109,7 @@ func NewRepoRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command conn, repoIf := argocdclient.NewClientOrDie(clientOpts).NewRepoClientOrDie() defer util.Close(conn) for _, repoURL := range args { - _, err := repoIf.Delete(context.Background(), &repository.RepoQuery{Repo: repoURL}) + _, err := repoIf.Delete(DefaultClientContext(clientOpts), &repository.RepoQuery{Repo: repoURL}) errors.CheckError(err) } }, @@ -126,7 +125,7 @@ func NewRepoListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { Run: func(c *cobra.Command, args []string) { conn, repoIf := argocdclient.NewClientOrDie(clientOpts).NewRepoClientOrDie() defer util.Close(conn) - repos, err := repoIf.List(context.Background(), &repository.RepoQuery{}) + repos, err := repoIf.List(DefaultClientContext(clientOpts), &repository.RepoQuery{}) errors.CheckError(err) w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) fmt.Fprintf(w, "REPO\tUSER\n") diff --git a/cmd/argocd/commands/root.go b/cmd/argocd/commands/root.go index c73b695eb7e5d..6f9e9942b5bce 100644 --- a/cmd/argocd/commands/root.go +++ b/cmd/argocd/commands/root.go @@ -1,12 +1,33 @@ package commands import ( + "context" + argocdclient "github.com/argoproj/argo-cd/pkg/apiclient" "github.com/argoproj/argo-cd/util/cli" + util_config "github.com/argoproj/argo-cd/util/config" + log "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "google.golang.org/grpc/metadata" "k8s.io/client-go/tools/clientcmd" ) +// DefaultClientContext assembles a context with proper auth tokens, etc. +func DefaultClientContext(clientOpts *argocdclient.ClientOptions) context.Context { + ctx := context.Background() + + localConfig, err := util_config.ReadLocalConfig() + if err != nil { + log.Fatal(err) + } + + token, ok := localConfig.Sessions[clientOpts.ServerAddr] + if ok { + ctx = metadata.AppendToOutgoingContext(ctx, "tokens", token) + } + return ctx +} + // NewCommand returns a new instance of an argocd command func NewCommand() *cobra.Command { var ( @@ -33,6 +54,5 @@ func NewCommand() *cobra.Command { command.PersistentFlags().StringVar(&clientOpts.ServerAddr, "server", "", "ArgoCD server address") command.PersistentFlags().BoolVar(&clientOpts.Insecure, "insecure", false, "Disable transport security for the client connection, including host verification") command.PersistentFlags().StringVar(&clientOpts.CertFile, "server-crt", "", "Server certificate file") - return command } diff --git a/pkg/apiclient/apiclient.go b/pkg/apiclient/apiclient.go index 694c1bce5d82e..8eebcbd7534e5 100644 --- a/pkg/apiclient/apiclient.go +++ b/pkg/apiclient/apiclient.go @@ -24,6 +24,7 @@ const ( EnvArgoCDServer = "ARGOCD_SERVER" ) +// ServerClient defines an interface for interaction with an Argo CD server. type ServerClient interface { NewConn() (*grpc.ClientConn, error) NewRepoClient() (*grpc.ClientConn, repository.RepositoryServiceClient, error) @@ -36,6 +37,7 @@ type ServerClient interface { NewSessionClientOrDie() (*grpc.ClientConn, session.SessionServiceClient) } +// ClientOptions hold address, security, and other settings for the API client. type ClientOptions struct { ServerAddr string Insecure bool @@ -46,6 +48,7 @@ type client struct { ClientOptions } +// NewClient creates a new API client from a set of config options. func NewClient(opts *ClientOptions) (ServerClient, error) { clientOpts := *opts if clientOpts.ServerAddr == "" { @@ -59,6 +62,7 @@ func NewClient(opts *ClientOptions) (ServerClient, error) { }, nil } +// NewClientOrDie creates a new API client from a set of config options, or fails fatally if the new client creation fails. func NewClientOrDie(opts *ClientOptions) ServerClient { client, err := NewClient(opts) if err != nil { diff --git a/server/server.go b/server/server.go index ee7f90b92c676..99703e2b9c579 100644 --- a/server/server.go +++ b/server/server.go @@ -21,14 +21,17 @@ import ( "github.com/argoproj/argo-cd/util/config" grpc_util "github.com/argoproj/argo-cd/util/grpc" jsonutil "github.com/argoproj/argo-cd/util/json" + util_session "github.com/argoproj/argo-cd/util/session" tlsutil "github.com/argoproj/argo-cd/util/tls" grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" + grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth" grpc_logrus "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus" "github.com/grpc-ecosystem/grpc-gateway/runtime" log "github.com/sirupsen/logrus" "github.com/soheilhy/cmux" "google.golang.org/grpc" "google.golang.org/grpc/credentials" + "google.golang.org/grpc/metadata" "k8s.io/client-go/kubernetes" ) @@ -144,10 +147,12 @@ func (a *ArgoCDServer) newGRPCServer() *grpc.Server { // This is because TLS handshaking occurs in cmux handling sOpts = append(sOpts, grpc.StreamInterceptor(grpc_middleware.ChainStreamServer( grpc_logrus.StreamServerInterceptor(a.log), + grpc_auth.StreamServerInterceptor(a.authenticate), grpc_util.PanicLoggerStreamServerInterceptor(a.log), ))) sOpts = append(sOpts, grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer( grpc_logrus.UnaryServerInterceptor(a.log), + grpc_auth.UnaryServerInterceptor(a.authenticate), grpc_util.PanicLoggerUnaryServerInterceptor(a.log), ))) @@ -254,3 +259,20 @@ func mustRegisterGWHandler(register registerFunc, ctx context.Context, mux *runt panic(err) } } + +// Authenticate checks for the presence of a token when accessing server-side resources. +func (a *ArgoCDServer) authenticate(ctx context.Context) (context.Context, error) { + if md, ok := metadata.FromIncomingContext(ctx); ok { + mgr := util_session.MakeSessionManager(a.settings.ServerSignature) + tokens := md["tokens"] + for _, token := range tokens { + _, err := mgr.Parse(token) + if err == nil { + return ctx, nil + } + } + return ctx, fmt.Errorf("user is not allowed access") + } + + return ctx, fmt.Errorf("empty metadata") +} diff --git a/server/session/session.go b/server/session/session.go index 37b55414da6e4..8b57c987f6dc1 100644 --- a/server/session/session.go +++ b/server/session/session.go @@ -64,3 +64,8 @@ func (s *Server) Create(ctx context.Context, q *SessionRequest) (*SessionRespons } return &SessionResponse{token}, err } + +// AuthFuncOverride overrides the authentication function and let us not require auth to receive auth. +func (s *Server) AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error) { + return ctx, nil +} diff --git a/util/session/sessionmanager.go b/util/session/sessionmanager.go index e5a6b0c5d7ba8..8865bddba42f0 100644 --- a/util/session/sessionmanager.go +++ b/util/session/sessionmanager.go @@ -72,8 +72,10 @@ func (mgr SessionManager) Parse(tokenString string) (*SessionManagerTokenClaims, return mgr.serverSecretKey, nil }) - if claims, ok := token.Claims.(*SessionManagerTokenClaims); ok && token.Valid { - return claims, nil + if token != nil { + if claims, ok := token.Claims.(*SessionManagerTokenClaims); ok && token.Valid { + return claims, nil + } } return nil, err } From cee45d3a73104ed2223dfc9eb74d2f34aaa6f543 Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Thu, 12 Apr 2018 08:51:26 -0700 Subject: [PATCH 2/4] Add additional comments, fix errors, thanks @jessesuen --- server/server.go | 5 +++-- server/session/session.go | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/server/server.go b/server/server.go index 99703e2b9c579..fb9f04fd8b87e 100644 --- a/server/server.go +++ b/server/server.go @@ -30,6 +30,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/soheilhy/cmux" "google.golang.org/grpc" + "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" "google.golang.org/grpc/metadata" "k8s.io/client-go/kubernetes" @@ -271,8 +272,8 @@ func (a *ArgoCDServer) authenticate(ctx context.Context) (context.Context, error return ctx, nil } } - return ctx, fmt.Errorf("user is not allowed access") + return ctx, grpc.Errorf(codes.Unauthenticated, "user is not allowed access") } - return ctx, fmt.Errorf("empty metadata") + return ctx, grpc.Errorf(codes.Unauthenticated, "empty metadata") } diff --git a/server/session/session.go b/server/session/session.go index 8b57c987f6dc1..8a6a0ca5c2cb0 100644 --- a/server/session/session.go +++ b/server/session/session.go @@ -66,6 +66,9 @@ func (s *Server) Create(ctx context.Context, q *SessionRequest) (*SessionRespons } // AuthFuncOverride overrides the authentication function and let us not require auth to receive auth. +// Without this function here, ArgoCDServer.authenticate would be invoked and credentials checked. +// Since this service is generally invoked when the user has _no_ credentials, that would create a +// chicken-and-egg situation if we didn't place this here to allow traffic to pass through. func (s *Server) AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error) { return ctx, nil } From b26e156cf5926f9991e370781fed9c6794649f0d Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Thu, 12 Apr 2018 10:26:47 -0700 Subject: [PATCH 3/4] Centralize token injection, thanks @jessesuen --- cmd/argocd/commands/app.go | 13 ++++++------ cmd/argocd/commands/cluster.go | 10 ++++----- cmd/argocd/commands/repo.go | 7 +++--- cmd/argocd/commands/root.go | 22 +------------------ pkg/apiclient/apiclient.go | 39 +++++++++++++++++++++++++++++++++- 5 files changed, 55 insertions(+), 36 deletions(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index d4718629c0f1f..a588bf86a885f 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -1,6 +1,7 @@ package commands import ( + "context" "fmt" "log" "net/url" @@ -98,7 +99,7 @@ func NewApplicationAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com } conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) - _, err := appIf.Create(DefaultClientContext(clientOpts), &app) + _, err := appIf.Create(context.Background(), &app) errors.CheckError(err) }, } @@ -125,7 +126,7 @@ func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) appName := args[0] - app, err := appIf.Get(DefaultClientContext(clientOpts), &application.ApplicationQuery{Name: appName}) + app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: appName}) errors.CheckError(err) format := "%-15s%s\n" fmt.Printf(format, "Name:", app.Name) @@ -175,7 +176,7 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) appName := args[0] - app, err := appIf.Get(DefaultClientContext(clientOpts), &application.ApplicationQuery{Name: appName}) + app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: appName}) errors.CheckError(err) targetObjs, err := app.Status.ComparisonResult.TargetObjects() errors.CheckError(err) @@ -214,7 +215,7 @@ func NewApplicationRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra. conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) for _, appName := range args { - _, err := appIf.Delete(DefaultClientContext(clientOpts), &application.DeleteApplicationRequest{Name: appName}) + _, err := appIf.Delete(context.Background(), &application.DeleteApplicationRequest{Name: appName}) errors.CheckError(err) } }, @@ -230,7 +231,7 @@ func NewApplicationListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co Run: func(c *cobra.Command, args []string) { conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) - apps, err := appIf.List(DefaultClientContext(clientOpts), &application.ApplicationQuery{}) + apps, err := appIf.List(context.Background(), &application.ApplicationQuery{}) errors.CheckError(err) w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) fmt.Fprintf(w, "NAME\tENVIRONMENT\tTARGET\tCLUSTER\tNAMESPACE\tSTATUS\n") @@ -274,7 +275,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co Name: appName, DryRun: dryRun, } - syncRes, err := appIf.Sync(DefaultClientContext(clientOpts), &syncReq) + syncRes, err := appIf.Sync(context.Background(), &syncReq) errors.CheckError(err) fmt.Printf("%s %s\n", appName, syncRes.Message) w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) diff --git a/cmd/argocd/commands/cluster.go b/cmd/argocd/commands/cluster.go index 8928cdc2641bc..862aa91945131 100644 --- a/cmd/argocd/commands/cluster.go +++ b/cmd/argocd/commands/cluster.go @@ -1,6 +1,7 @@ package commands import ( + "context" "fmt" "io/ioutil" "os" @@ -72,7 +73,7 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie conn, clusterIf := argocdclient.NewClientOrDie(clientOpts).NewClusterClientOrDie() defer util.Close(conn) clst := NewCluster(args[0], conf) - clst, err = clusterIf.Create(DefaultClientContext(clientOpts), clst) + clst, err = clusterIf.Create(context.Background(), clst) errors.CheckError(err) fmt.Printf("Cluster '%s' added\n", clst.Name) }, @@ -158,7 +159,7 @@ func NewClusterGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command conn, clusterIf := argocdclient.NewClientOrDie(clientOpts).NewClusterClientOrDie() defer util.Close(conn) for _, clusterName := range args { - clst, err := clusterIf.Get(DefaultClientContext(clientOpts), &cluster.ClusterQuery{Server: clusterName}) + clst, err := clusterIf.Get(context.Background(), &cluster.ClusterQuery{Server: clusterName}) errors.CheckError(err) yamlBytes, err := yaml.Marshal(clst) errors.CheckError(err) @@ -184,7 +185,7 @@ func NewClusterRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comm for _, clusterName := range args { // TODO(jessesuen): find the right context and remove manager RBAC artifacts // common.UninstallClusterManagerRBAC(conf) - _, err := clusterIf.Delete(DefaultClientContext(clientOpts), &cluster.ClusterQuery{Server: clusterName}) + _, err := clusterIf.Delete(context.Background(), &cluster.ClusterQuery{Server: clusterName}) errors.CheckError(err) } }, @@ -200,8 +201,7 @@ func NewClusterListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman Run: func(c *cobra.Command, args []string) { conn, clusterIf := argocdclient.NewClientOrDie(clientOpts).NewClusterClientOrDie() defer util.Close(conn) - - clusters, err := clusterIf.List(DefaultClientContext(clientOpts), &cluster.ClusterQuery{}) + clusters, err := clusterIf.List(context.Background(), &cluster.ClusterQuery{}) errors.CheckError(err) w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) fmt.Fprintf(w, "SERVER\tNAME\n") diff --git a/cmd/argocd/commands/repo.go b/cmd/argocd/commands/repo.go index 9d4c26d3db108..c2653927a8aa6 100644 --- a/cmd/argocd/commands/repo.go +++ b/cmd/argocd/commands/repo.go @@ -2,6 +2,7 @@ package commands import ( "bufio" + "context" "fmt" "io/ioutil" "os" @@ -71,7 +72,7 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { errors.CheckError(err) conn, repoIf := argocdclient.NewClientOrDie(clientOpts).NewRepoClientOrDie() defer util.Close(conn) - createdRepo, err := repoIf.Create(DefaultClientContext(clientOpts), &repo) + createdRepo, err := repoIf.Create(context.Background(), &repo) errors.CheckError(err) fmt.Printf("repository '%s' added\n", createdRepo.Repo) }, @@ -109,7 +110,7 @@ func NewRepoRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command conn, repoIf := argocdclient.NewClientOrDie(clientOpts).NewRepoClientOrDie() defer util.Close(conn) for _, repoURL := range args { - _, err := repoIf.Delete(DefaultClientContext(clientOpts), &repository.RepoQuery{Repo: repoURL}) + _, err := repoIf.Delete(context.Background(), &repository.RepoQuery{Repo: repoURL}) errors.CheckError(err) } }, @@ -125,7 +126,7 @@ func NewRepoListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { Run: func(c *cobra.Command, args []string) { conn, repoIf := argocdclient.NewClientOrDie(clientOpts).NewRepoClientOrDie() defer util.Close(conn) - repos, err := repoIf.List(DefaultClientContext(clientOpts), &repository.RepoQuery{}) + repos, err := repoIf.List(context.Background(), &repository.RepoQuery{}) errors.CheckError(err) w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) fmt.Fprintf(w, "REPO\tUSER\n") diff --git a/cmd/argocd/commands/root.go b/cmd/argocd/commands/root.go index 6f9e9942b5bce..c73b695eb7e5d 100644 --- a/cmd/argocd/commands/root.go +++ b/cmd/argocd/commands/root.go @@ -1,33 +1,12 @@ package commands import ( - "context" - argocdclient "github.com/argoproj/argo-cd/pkg/apiclient" "github.com/argoproj/argo-cd/util/cli" - util_config "github.com/argoproj/argo-cd/util/config" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "google.golang.org/grpc/metadata" "k8s.io/client-go/tools/clientcmd" ) -// DefaultClientContext assembles a context with proper auth tokens, etc. -func DefaultClientContext(clientOpts *argocdclient.ClientOptions) context.Context { - ctx := context.Background() - - localConfig, err := util_config.ReadLocalConfig() - if err != nil { - log.Fatal(err) - } - - token, ok := localConfig.Sessions[clientOpts.ServerAddr] - if ok { - ctx = metadata.AppendToOutgoingContext(ctx, "tokens", token) - } - return ctx -} - // NewCommand returns a new instance of an argocd command func NewCommand() *cobra.Command { var ( @@ -54,5 +33,6 @@ func NewCommand() *cobra.Command { command.PersistentFlags().StringVar(&clientOpts.ServerAddr, "server", "", "ArgoCD server address") command.PersistentFlags().BoolVar(&clientOpts.Insecure, "insecure", false, "Disable transport security for the client connection, including host verification") command.PersistentFlags().StringVar(&clientOpts.CertFile, "server-crt", "", "Server certificate file") + return command } diff --git a/pkg/apiclient/apiclient.go b/pkg/apiclient/apiclient.go index 8eebcbd7534e5..1f0972490e11e 100644 --- a/pkg/apiclient/apiclient.go +++ b/pkg/apiclient/apiclient.go @@ -13,6 +13,7 @@ import ( "github.com/argoproj/argo-cd/server/cluster" "github.com/argoproj/argo-cd/server/repository" "github.com/argoproj/argo-cd/server/session" + config_util "github.com/argoproj/argo-cd/util/config" grpc_util "github.com/argoproj/argo-cd/util/grpc" log "github.com/sirupsen/logrus" "google.golang.org/grpc" @@ -71,6 +72,42 @@ func NewClientOrDie(opts *ClientOptions) ServerClient { return client } +// JwtCredentials holds a token for authentication. +type jwtCredentials struct { + Token string +} + +func (c jwtCredentials) RequireTransportSecurity() bool { + return false +} + +func (c jwtCredentials) GetRequestMetadata(context.Context, ...string) (map[string]string, error) { + return map[string]string{ + "tokens": c.Token, + }, nil +} + +// endpointCredentials retrieves from configuration the login token for a given endpoint. +func endpointCredentials(endpoint string) jwtCredentials { + credentials := jwtCredentials{} + + localConfig, err := config_util.ReadLocalConfig() + if err != nil { + return credentials + } + + token, ok := localConfig.Sessions[endpoint] + if !ok { + // Use blank-key token, if it exists, as a fallback + token, ok = localConfig.Sessions[""] + } + + if ok { + credentials.Token = token + } + return credentials +} + func (c *client) NewConn() (*grpc.ClientConn, error) { var creds credentials.TransportCredentials if c.CertFile != "" { @@ -97,7 +134,7 @@ func (c *client) NewConn() (*grpc.ClientConn, error) { creds = credentials.NewTLS(&tlsConfig) } } - return grpc_util.BlockingDial(context.Background(), "tcp", c.ServerAddr, creds) + return grpc_util.BlockingDial(context.Background(), "tcp", c.ServerAddr, creds, grpc.WithPerRPCCredentials(endpointCredentials(c.ServerAddr))) } func (c *client) NewRepoClient() (*grpc.ClientConn, repository.RepositoryServiceClient, error) { From 1783f3142a2aa1559991873c4564c5f52854d5f0 Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Fri, 13 Apr 2018 10:00:00 -0700 Subject: [PATCH 4/4] Add REQUIREAUTH=1 env flag to enable authentication --- server/server.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/server.go b/server/server.go index fb9f04fd8b87e..a8236675012e0 100644 --- a/server/server.go +++ b/server/server.go @@ -7,6 +7,7 @@ import ( "fmt" "net" "net/http" + "os" "strings" argocd "github.com/argoproj/argo-cd" @@ -263,6 +264,10 @@ func mustRegisterGWHandler(register registerFunc, ctx context.Context, mux *runt // Authenticate checks for the presence of a token when accessing server-side resources. func (a *ArgoCDServer) authenticate(ctx context.Context) (context.Context, error) { + if os.Getenv("REQUIREAUTH") != "1" { + return ctx, nil + } + if md, ok := metadata.FromIncomingContext(ctx); ok { mgr := util_session.MakeSessionManager(a.settings.ServerSignature) tokens := md["tokens"]