github.com/argoproj/argo-cd/v2@v2.10.9/server/session/session.go (about)

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