github.com/argoproj/argo-cd/v3@v3.2.1/server/session/session.go (about) 1 package session 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/argoproj/argo-cd/v3/util/settings" 8 9 "github.com/google/uuid" 10 "google.golang.org/grpc/codes" 11 "google.golang.org/grpc/status" 12 13 "github.com/argoproj/argo-cd/v3/pkg/apiclient/session" 14 "github.com/argoproj/argo-cd/v3/server/rbacpolicy" 15 utilio "github.com/argoproj/argo-cd/v3/util/io" 16 sessionmgr "github.com/argoproj/argo-cd/v3/util/session" 17 ) 18 19 // Server provides a Session service 20 type Server struct { 21 mgr *sessionmgr.SessionManager 22 settingsMgr *settings.SettingsManager 23 authenticator Authenticator 24 policyEnf *rbacpolicy.RBACPolicyEnforcer 25 limitLoginAttempts func() (utilio.Closer, error) 26 } 27 28 type Authenticator interface { 29 Authenticate(ctx context.Context) (context.Context, error) 30 } 31 32 const ( 33 success = "success" 34 failure = "failure" 35 ) 36 37 // NewServer returns a new instance of the Session service 38 func NewServer(mgr *sessionmgr.SessionManager, settingsMgr *settings.SettingsManager, authenticator Authenticator, policyEnf *rbacpolicy.RBACPolicyEnforcer, rateLimiter func() (utilio.Closer, error)) *Server { 39 return &Server{mgr, settingsMgr, authenticator, policyEnf, rateLimiter} 40 } 41 42 // Create generates a JWT token signed by Argo CD intended for web/CLI logins of the admin user 43 // using username/password 44 func (s *Server) Create(_ context.Context, q *session.SessionCreateRequest) (*session.SessionResponse, error) { 45 if s.limitLoginAttempts != nil { 46 closer, err := s.limitLoginAttempts() 47 if err != nil { 48 s.mgr.IncLoginRequestCounter(failure) 49 return nil, err 50 } 51 defer utilio.Close(closer) 52 } 53 54 if q.Token != "" { 55 s.mgr.IncLoginRequestCounter(failure) 56 return nil, status.Errorf(codes.Unauthenticated, "token-based session creation no longer supported. please upgrade argocd cli to v0.7+") 57 } 58 if q.Username == "" || q.Password == "" { 59 s.mgr.IncLoginRequestCounter(failure) 60 return nil, status.Errorf(codes.Unauthenticated, "no credentials supplied") 61 } 62 err := s.mgr.VerifyUsernamePassword(q.Username, q.Password) 63 if err != nil { 64 s.mgr.IncLoginRequestCounter(failure) 65 return nil, err 66 } 67 uniqueId, err := uuid.NewRandom() 68 if err != nil { 69 s.mgr.IncLoginRequestCounter(failure) 70 return nil, err 71 } 72 argoCDSettings, err := s.settingsMgr.GetSettings() 73 if err != nil { 74 s.mgr.IncLoginRequestCounter(failure) 75 return nil, err 76 } 77 jwtToken, err := s.mgr.Create( 78 fmt.Sprintf("%s:%s", q.Username, settings.AccountCapabilityLogin), 79 int64(argoCDSettings.UserSessionDuration.Seconds()), 80 uniqueId.String()) 81 if err != nil { 82 s.mgr.IncLoginRequestCounter(failure) 83 return nil, err 84 } 85 s.mgr.IncLoginRequestCounter(success) 86 return &session.SessionResponse{Token: jwtToken}, nil 87 } 88 89 // Delete an authentication cookie from the client. This makes sense only for the Web client. 90 func (s *Server) Delete(_ context.Context, _ *session.SessionDeleteRequest) (*session.SessionResponse, error) { 91 return &session.SessionResponse{Token: ""}, nil 92 } 93 94 // AuthFuncOverride overrides the authentication function and let us not require auth to receive auth. 95 // Without this function here, ArgoCDServer.authenticate would be invoked and credentials checked. 96 // Since this service is generally invoked when the user has _no_ credentials, that would create a 97 // chicken-and-egg situation if we didn't place this here to allow traffic to pass through. 98 func (s *Server) AuthFuncOverride(ctx context.Context, _ string) (context.Context, error) { 99 // this authenticates the user, but ignores any error, so that we have claims populated 100 ctx, _ = s.authenticator.Authenticate(ctx) 101 return ctx, nil 102 } 103 104 func (s *Server) GetUserInfo(ctx context.Context, _ *session.GetUserInfoRequest) (*session.GetUserInfoResponse, error) { 105 return &session.GetUserInfoResponse{ 106 LoggedIn: sessionmgr.LoggedIn(ctx), 107 Username: sessionmgr.Username(ctx), 108 Iss: sessionmgr.Iss(ctx), 109 Groups: sessionmgr.Groups(ctx, s.policyEnf.GetScopes()), 110 }, nil 111 }