github.com/argoproj/argo-cd/v3@v3.2.1/server/repocreds/repocreds.go (about)

     1  package repocreds
     2  
     3  import (
     4  	"context"
     5  	"reflect"
     6  
     7  	"github.com/argoproj/argo-cd/v3/util/argo"
     8  
     9  	"google.golang.org/grpc/codes"
    10  	"google.golang.org/grpc/status"
    11  
    12  	repocredspkg "github.com/argoproj/argo-cd/v3/pkg/apiclient/repocreds"
    13  	appsv1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
    14  	"github.com/argoproj/argo-cd/v3/util/db"
    15  	"github.com/argoproj/argo-cd/v3/util/rbac"
    16  )
    17  
    18  // Server provides a Repository service
    19  type Server struct {
    20  	db  db.ArgoDB
    21  	enf *rbac.Enforcer
    22  }
    23  
    24  // NewServer returns a new instance of the Repository service
    25  func NewServer(
    26  	db db.ArgoDB,
    27  	enf *rbac.Enforcer,
    28  ) *Server {
    29  	return &Server{
    30  		db:  db,
    31  		enf: enf,
    32  	}
    33  }
    34  
    35  // ListRepositoryCredentials returns a list of all configured repository credential sets
    36  func (s *Server) ListRepositoryCredentials(ctx context.Context, _ *repocredspkg.RepoCredsQuery) (*appsv1.RepoCredsList, error) {
    37  	urls, err := s.db.ListRepositoryCredentials(ctx)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	items := make([]appsv1.RepoCreds, 0)
    42  	for _, url := range urls {
    43  		if s.enf.Enforce(ctx.Value("claims"), rbac.ResourceRepositories, rbac.ActionGet, url) {
    44  			repo, err := s.db.GetRepositoryCredentials(ctx, url)
    45  			if err != nil {
    46  				return nil, err
    47  			}
    48  			if repo != nil {
    49  				items = append(items, appsv1.RepoCreds{
    50  					URL:      url,
    51  					Username: repo.Username,
    52  				})
    53  			}
    54  		}
    55  	}
    56  	return &appsv1.RepoCredsList{Items: items}, nil
    57  }
    58  
    59  // ListWriteRepositoryCredentials returns a list of all configured repository credential sets
    60  func (s *Server) ListWriteRepositoryCredentials(ctx context.Context, _ *repocredspkg.RepoCredsQuery) (*appsv1.RepoCredsList, error) {
    61  	urls, err := s.db.ListRepositoryCredentials(ctx)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  	items := make([]appsv1.RepoCreds, 0)
    66  	for _, url := range urls {
    67  		if s.enf.Enforce(ctx.Value("claims"), rbac.ResourceWriteRepositories, rbac.ActionGet, url) {
    68  			repo, err := s.db.GetWriteRepositoryCredentials(ctx, url)
    69  			if err != nil {
    70  				return nil, err
    71  			}
    72  			if repo != nil && repo.Password != "" {
    73  				items = append(items, appsv1.RepoCreds{
    74  					URL:      url,
    75  					Username: repo.Username,
    76  				})
    77  			}
    78  		}
    79  	}
    80  	return &appsv1.RepoCredsList{Items: items}, nil
    81  }
    82  
    83  // CreateRepositoryCredentials creates a new credential set in the configuration
    84  func (s *Server) CreateRepositoryCredentials(ctx context.Context, q *repocredspkg.RepoCredsCreateRequest) (*appsv1.RepoCreds, error) {
    85  	if q.Creds == nil {
    86  		return nil, status.Errorf(codes.InvalidArgument, "missing payload in request")
    87  	}
    88  	if err := s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceRepositories, rbac.ActionCreate, q.Creds.URL); err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	r := q.Creds
    93  
    94  	if r.URL == "" {
    95  		return nil, status.Errorf(codes.InvalidArgument, "must specify URL")
    96  	}
    97  
    98  	_, err := s.db.CreateRepositoryCredentials(ctx, r)
    99  	if status.Convert(err).Code() == codes.AlreadyExists {
   100  		// act idempotent if existing spec matches new spec
   101  		existing, getErr := s.db.GetRepositoryCredentials(ctx, r.URL)
   102  		if getErr != nil {
   103  			return nil, status.Errorf(codes.Internal, "unable to check existing repository credentials details: %v", getErr)
   104  		}
   105  
   106  		switch {
   107  		case reflect.DeepEqual(existing, r):
   108  			err = nil
   109  		case q.Upsert:
   110  			return s.UpdateRepositoryCredentials(ctx, &repocredspkg.RepoCredsUpdateRequest{Creds: r})
   111  		default:
   112  			return nil, status.Error(codes.InvalidArgument, argo.GenerateSpecIsDifferentErrorMessage("repository credentials", existing, r))
   113  		}
   114  	}
   115  	return &appsv1.RepoCreds{URL: r.URL}, err
   116  }
   117  
   118  // CreateWriteRepositoryCredentials creates a new credential set in the configuration
   119  func (s *Server) CreateWriteRepositoryCredentials(ctx context.Context, q *repocredspkg.RepoCredsCreateRequest) (*appsv1.RepoCreds, error) {
   120  	if q.Creds == nil {
   121  		return nil, status.Errorf(codes.InvalidArgument, "missing payload in request")
   122  	}
   123  	if err := s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceWriteRepositories, rbac.ActionCreate, q.Creds.URL); err != nil {
   124  		return nil, err
   125  	}
   126  
   127  	r := q.Creds
   128  
   129  	if r.URL == "" {
   130  		return nil, status.Errorf(codes.InvalidArgument, "must specify URL")
   131  	}
   132  
   133  	_, err := s.db.CreateWriteRepositoryCredentials(ctx, r)
   134  	if status.Convert(err).Code() == codes.AlreadyExists {
   135  		// act idempotent if existing spec matches new spec
   136  		existing, getErr := s.db.GetWriteRepositoryCredentials(ctx, r.URL)
   137  		if getErr != nil {
   138  			return nil, status.Errorf(codes.Internal, "unable to check existing repository credentials details: %v", getErr)
   139  		}
   140  
   141  		switch {
   142  		case reflect.DeepEqual(existing, r):
   143  			err = nil
   144  		case q.Upsert:
   145  			return s.UpdateWriteRepositoryCredentials(ctx, &repocredspkg.RepoCredsUpdateRequest{Creds: r})
   146  		default:
   147  			return nil, status.Error(codes.InvalidArgument, argo.GenerateSpecIsDifferentErrorMessage("repository credentials", existing, r))
   148  		}
   149  	}
   150  	return &appsv1.RepoCreds{URL: r.URL}, err
   151  }
   152  
   153  // UpdateRepositoryCredentials updates a repository credential set
   154  func (s *Server) UpdateRepositoryCredentials(ctx context.Context, q *repocredspkg.RepoCredsUpdateRequest) (*appsv1.RepoCreds, error) {
   155  	if q.Creds == nil {
   156  		return nil, status.Errorf(codes.InvalidArgument, "missing payload in request")
   157  	}
   158  	if err := s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceRepositories, rbac.ActionUpdate, q.Creds.URL); err != nil {
   159  		return nil, err
   160  	}
   161  	_, err := s.db.UpdateRepositoryCredentials(ctx, q.Creds)
   162  	return &appsv1.RepoCreds{URL: q.Creds.URL}, err
   163  }
   164  
   165  // UpdateWriteRepositoryCredentials updates a repository credential set
   166  func (s *Server) UpdateWriteRepositoryCredentials(ctx context.Context, q *repocredspkg.RepoCredsUpdateRequest) (*appsv1.RepoCreds, error) {
   167  	if q.Creds == nil {
   168  		return nil, status.Errorf(codes.InvalidArgument, "missing payload in request")
   169  	}
   170  	if err := s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceWriteRepositories, rbac.ActionUpdate, q.Creds.URL); err != nil {
   171  		return nil, err
   172  	}
   173  	_, err := s.db.UpdateWriteRepositoryCredentials(ctx, q.Creds)
   174  	return &appsv1.RepoCreds{URL: q.Creds.URL}, err
   175  }
   176  
   177  // DeleteRepositoryCredentials removes a credential set from the configuration
   178  func (s *Server) DeleteRepositoryCredentials(ctx context.Context, q *repocredspkg.RepoCredsDeleteRequest) (*repocredspkg.RepoCredsResponse, error) {
   179  	if err := s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceRepositories, rbac.ActionDelete, q.Url); err != nil {
   180  		return nil, err
   181  	}
   182  
   183  	err := s.db.DeleteRepositoryCredentials(ctx, q.Url)
   184  	return &repocredspkg.RepoCredsResponse{}, err
   185  }
   186  
   187  // DeleteWriteRepositoryCredentials removes a credential set from the configuration
   188  func (s *Server) DeleteWriteRepositoryCredentials(ctx context.Context, q *repocredspkg.RepoCredsDeleteRequest) (*repocredspkg.RepoCredsResponse, error) {
   189  	if err := s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceWriteRepositories, rbac.ActionDelete, q.Url); err != nil {
   190  		return nil, err
   191  	}
   192  
   193  	err := s.db.DeleteWriteRepositoryCredentials(ctx, q.Url)
   194  	return &repocredspkg.RepoCredsResponse{}, err
   195  }