Skip to content

Commit

Permalink
feat: support contributors
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanCaamano committed Oct 30, 2024
1 parent 4c54d84 commit 8659428
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 60 deletions.
10 changes: 7 additions & 3 deletions config/sso_extended.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type SSOExtendedLabel struct {
}

type ResourcesToFilter struct {
ArrayLabels []string
ArrayLabels map[string]string
Group string
LabelsFilter string
}
Expand All @@ -31,6 +31,7 @@ func CanDelegateByLabel() bool {

func RbacDelegateToLabel(ctx context.Context, mail string, apiUrl, apiEndpoint, apiPassword, label string, writeGroups []string) (*ResourcesToFilter, error) {
resourcesToFilterPopulated := &ResourcesToFilter{}
servicesToFilter := []string{}
devhubClient := devhub.NewClient()
mailParts := strings.Split(mail, "@")
servicesAndGroup, err := devhub.GetServicesAndGroup(devhubClient, apiUrl, apiEndpoint, apiPassword, mailParts[0], writeGroups)
Expand All @@ -39,8 +40,11 @@ func RbacDelegateToLabel(ctx context.Context, mail string, apiUrl, apiEndpoint,
}
resourcesToFilterPopulated.Group = servicesAndGroup.Group
if servicesAndGroup.Services != nil {
resourcesToFilterPopulated.ArrayLabels = append(resourcesToFilterPopulated.ArrayLabels, servicesAndGroup.Services...)
resourcesToFilterPopulated.LabelsFilter = fmt.Sprintf("%s in (%s)", label, strings.Join(resourcesToFilterPopulated.ArrayLabels[:], ","))
for service := range servicesAndGroup.Services {
servicesToFilter = append(servicesToFilter, service)
}
resourcesToFilterPopulated.ArrayLabels = servicesAndGroup.Services
resourcesToFilterPopulated.LabelsFilter = fmt.Sprintf("%s in (%s)", label, strings.Join(servicesToFilter[:], ","))
}
return resourcesToFilterPopulated, nil
}
18 changes: 7 additions & 11 deletions server/auth/devhub/aplication.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
)

type GroupAndServices struct {
Services []string
Services map[string]string
Group string
}
type ApiStruct struct {
Expand Down Expand Up @@ -45,7 +45,7 @@ type ApiStruct struct {

func GetServicesAndGroup(devhubclient *Client, apiUrl, apiEndpoint, apiPassword, userToIdentify string, writeGroups []string) (*GroupAndServices, error) {
var roles []string
var services []string
var services map[string]string
servicesAndGroup := &GroupAndServices{}
apiResponse := &ApiStruct{}
apiDevhub := fmt.Sprintf("%s/%s/%s", apiUrl, apiEndpoint, userToIdentify)
Expand All @@ -57,14 +57,14 @@ func GetServicesAndGroup(devhubclient *Client, apiUrl, apiEndpoint, apiPassword,
return nil, err
}

roles, services = GetRolesAndServices(apiResponse, services, roles)
services, roles = GetRolesAndServices(apiResponse, services, roles)

servicesAndGroup.Group = GetGroupByRole(writeGroups, roles)
servicesAndGroup.Services = services
return servicesAndGroup, nil
}

func GetRolesAndServices(result *ApiStruct, services, roles []string) ([]string, []string) {
func GetRolesAndServices(result *ApiStruct, services map[string]string, roles []string) (map[string]string, []string) {
if result.Teams == nil {
return services, roles
}
Expand All @@ -74,12 +74,8 @@ func GetRolesAndServices(result *ApiStruct, services, roles []string) ([]string,
continue
}
for _, project := range team.Applications {
if project.RelationshipType != "Owner" {
continue
}
if !slices.Contains(services, project.Key) {
services = append(services, project.Key)
}
services[project.Key] = project.RelationshipType

for _, profile := range team.Profiles {
if !slices.Contains(roles, profile.Name) {
roles = append(roles, profile.Name)
Expand All @@ -96,7 +92,7 @@ func GetRolesAndServices(result *ApiStruct, services, roles []string) ([]string,
}
}
}
return roles, services
return services, roles
}

func GetGroupByRole(writeGroups []string, roles []string) string {
Expand Down
10 changes: 5 additions & 5 deletions server/auth/types/claims.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ type HttpClient interface {
var httpClient HttpClient

type TeamFilterClaims struct {
Values []string `json:"values,omitempty"` // the values in array tu use to filter in get/update... in others actions different than list
Group string `json:"group,omitempty"` // Group to search ServiceAccount for (write, read... whatever)
FilterExpresion string `json:"filterexpresion,omitempty"` // This will be the filter used in list actions ex: "$Label in ($values)"
Label string `json:"label,omitempty"`
IsAdmin bool `json:"isAdmin,omitempty"`
Values map[string]string `json:"values,omitempty"` // the values in array tu use to filter in get/update... in others actions different than list
Group string `json:"group,omitempty"` // Group to search ServiceAccount for (write, read... whatever)
FilterExpresion string `json:"filterexpresion,omitempty"` // This will be the filter used in list actions ex: "$Label in ($values)"
Label string `json:"label,omitempty"`
IsAdmin bool `json:"isAdmin,omitempty"`
}

func init() {
Expand Down
4 changes: 2 additions & 2 deletions server/auth/types/claims_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func TestUnmarshalJSON(t *testing.T) {
},
},
TeamFilterClaims: TeamFilterClaims{
Values: []string{"testValue1", "testValue2"},
Values: map[string]string{"test": "testValue1", "test2": "testValue2"},
Group: "testGroup",
FilterExpresion: "testFilter",
Label: "testLabel",
Expand Down Expand Up @@ -154,7 +154,7 @@ func TestUnmarshalJSON(t *testing.T) {
},
},
TeamFilterClaims: TeamFilterClaims{
Values: []string{"testValue1", "testValue2"},
Values: map[string]string{"test": "testValue1", "test2": "testValue2"},
Group: "testGroup",
FilterExpresion: "testFilter",
Label: "testLabel",
Expand Down
19 changes: 16 additions & 3 deletions server/cronworkflow/cron_workflow_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func (c *cronWorkflowServiceServer) ListCronWorkflows(ctx context.Context, req *
}

func (c *cronWorkflowServiceServer) CreateCronWorkflow(ctx context.Context, req *cronworkflowpkg.CreateCronWorkflowRequest) (*v1alpha1.CronWorkflow, error) {
var hasPermission bool
wfClient := auth.GetWfClient(ctx)
if req.CronWorkflow == nil {
return nil, sutils.ToStatusError(fmt.Errorf("cron workflow was not found in the request body"), codes.NotFound)
Expand All @@ -66,6 +67,10 @@ func (c *cronWorkflowServiceServer) CreateCronWorkflow(ctx context.Context, req
if err != nil {
return nil, sutils.ToStatusError(err, codes.InvalidArgument)
}
hasPermission = filter.ForbidActionsIfNeeded(ctx, req.CronWorkflow.Labels)
if !hasPermission {
return nil, sutils.ToStatusError(fmt.Errorf("Permission Denied!"), codes.PermissionDenied)
}
crWf, err := wfClient.ArgoprojV1alpha1().CronWorkflows(req.Namespace).Create(ctx, req.CronWorkflow, metav1.CreateOptions{})
if err != nil {
return nil, sutils.ToStatusError(err, codes.Internal)
Expand Down Expand Up @@ -118,6 +123,10 @@ func (c *cronWorkflowServiceServer) DeleteCronWorkflow(ctx context.Context, req
}

func (c *cronWorkflowServiceServer) ResumeCronWorkflow(ctx context.Context, req *cronworkflowpkg.CronWorkflowResumeRequest) (*v1alpha1.CronWorkflow, error) {
_, err := c.getCronWorkflowAndValidate(ctx, req.Namespace, req.Name, metav1.GetOptions{})
if err != nil {
return nil, sutils.ToStatusError(fmt.Errorf("Permission Denied!"), codes.PermissionDenied)
}
crWf, err := setCronWorkflowSuspend(ctx, false, req.Namespace, req.Name)
if err != nil {
return nil, sutils.ToStatusError(err, codes.Internal)
Expand All @@ -126,6 +135,10 @@ func (c *cronWorkflowServiceServer) ResumeCronWorkflow(ctx context.Context, req
}

func (c *cronWorkflowServiceServer) SuspendCronWorkflow(ctx context.Context, req *cronworkflowpkg.CronWorkflowSuspendRequest) (*v1alpha1.CronWorkflow, error) {
_, err := c.getCronWorkflowAndValidate(ctx, req.Namespace, req.Name, metav1.GetOptions{})
if err != nil {
return nil, sutils.ToStatusError(fmt.Errorf("Permission Denied!"), codes.PermissionDenied)
}
crWf, err := setCronWorkflowSuspend(ctx, true, req.Namespace, req.Name)
if err != nil {
return nil, sutils.ToStatusError(err, codes.Internal)
Expand All @@ -148,16 +161,16 @@ func setCronWorkflowSuspend(ctx context.Context, setTo bool, namespace, name str
func (c *cronWorkflowServiceServer) getCronWorkflowAndValidate(ctx context.Context, namespace string, name string, options metav1.GetOptions) (*v1alpha1.CronWorkflow, error) {
wfClient := auth.GetWfClient(ctx)
cronWf, err := wfClient.ArgoprojV1alpha1().CronWorkflows(namespace).Get(ctx, name, options)
var hasService bool
var hasPermission bool
if err != nil {
return nil, sutils.ToStatusError(err, codes.Internal)
}
err = c.instanceIDService.Validate(cronWf)
if err != nil {
return nil, sutils.ToStatusError(err, codes.InvalidArgument)
}
hasService = filter.ForbidActionsIfNeeded(ctx, cronWf.Labels)
if !hasService {
hasPermission = filter.ForbidActionsIfNeeded(ctx, cronWf.Labels)
if !hasPermission {
return nil, sutils.ToStatusError(fmt.Errorf("Permission Denied!"), codes.PermissionDenied)
}

Expand Down
48 changes: 29 additions & 19 deletions server/workflow/workflow_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ func (s *workflowServer) Run(stopCh <-chan struct{}) {
}

func (s *workflowServer) CreateWorkflow(ctx context.Context, req *workflowpkg.WorkflowCreateRequest) (*wfv1.Workflow, error) {
var hasPermission bool
wfClient := auth.GetWfClient(ctx)

if req.Workflow == nil {
Expand Down Expand Up @@ -121,7 +122,10 @@ func (s *workflowServer) CreateWorkflow(ctx context.Context, req *workflowpkg.Wo
}
return workflow, nil
}

hasPermission = filter.ForbidActionsIfNeeded(ctx, req.Workflow.Labels)
if !hasPermission {
return nil, sutils.ToStatusError(fmt.Errorf("Permission Denied!"), codes.PermissionDenied)
}
wf, err := wfClient.ArgoprojV1alpha1().Workflows(req.Namespace).Create(ctx, req.Workflow, metav1.CreateOptions{})
if err != nil {
if apierr.IsServerTimeout(err) && req.Workflow.GenerateName != "" && req.Workflow.Name != "" {
Expand All @@ -138,12 +142,12 @@ func (s *workflowServer) CreateWorkflow(ctx context.Context, req *workflowpkg.Wo

func (s *workflowServer) GetWorkflow(ctx context.Context, req *workflowpkg.WorkflowGetRequest) (*wfv1.Workflow, error) {
wfGetOption := metav1.GetOptions{}
var hasService bool
var hasPermission bool
if req.GetOptions != nil {
wfGetOption = *req.GetOptions
}
wfClient := auth.GetWfClient(ctx)
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, wfGetOption)
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, wfGetOption, false)
if err != nil {
return nil, sutils.ToStatusError(err, codes.Internal)
}
Expand All @@ -162,8 +166,8 @@ func (s *workflowServer) GetWorkflow(ctx context.Context, req *workflowpkg.Workf
// should this be InvalidArgument?
return nil, sutils.ToStatusError(fmt.Errorf("unable to CleanFields in request: %w", err), codes.Internal)
} else if ok {
hasService = filter.ForbidActionsIfNeeded(ctx, newWf.Labels)
if !hasService {
hasPermission = filter.ForbidActionsIfNeeded(ctx, newWf.Labels)
if !hasPermission {
return nil, sutils.ToStatusError(fmt.Errorf("Permission Denied!"), codes.PermissionDenied)
}
return newWf, nil
Expand Down Expand Up @@ -281,7 +285,7 @@ func (s *workflowServer) WatchWorkflows(req *workflowpkg.WatchWorkflowsRequest,
if wfName != "" {
// If we are using an alias (such as `@latest`) we need to dereference it.
// s.getWorkflow does that for us
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, wfName, metav1.GetOptions{})
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, wfName, metav1.GetOptions{}, false)
if err != nil {
return sutils.ToStatusError(err, codes.Internal)
}
Expand Down Expand Up @@ -401,7 +405,7 @@ func (s *workflowServer) WatchEvents(req *workflowpkg.WatchEventsRequest, ws wor

func (s *workflowServer) DeleteWorkflow(ctx context.Context, req *workflowpkg.WorkflowDeleteRequest) (*workflowpkg.WorkflowDeleteResponse, error) {
wfClient := auth.GetWfClient(ctx)
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{})
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{}, false)
if err != nil {
return nil, sutils.ToStatusError(err, codes.Internal)
}
Expand All @@ -426,7 +430,7 @@ func (s *workflowServer) RetryWorkflow(ctx context.Context, req *workflowpkg.Wor
wfClient := auth.GetWfClient(ctx)
kubeClient := auth.GetKubeClient(ctx)

wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{})
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{}, false)
if err != nil {
return nil, sutils.ToStatusError(err, codes.Internal)
}
Expand Down Expand Up @@ -469,7 +473,7 @@ func (s *workflowServer) RetryWorkflow(ctx context.Context, req *workflowpkg.Wor

func (s *workflowServer) ResubmitWorkflow(ctx context.Context, req *workflowpkg.WorkflowResubmitRequest) (*wfv1.Workflow, error) {
wfClient := auth.GetWfClient(ctx)
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{})
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{}, false)
if err != nil {
return nil, sutils.ToStatusError(err, codes.Internal)
}
Expand All @@ -493,7 +497,7 @@ func (s *workflowServer) ResubmitWorkflow(ctx context.Context, req *workflowpkg.

func (s *workflowServer) ResumeWorkflow(ctx context.Context, req *workflowpkg.WorkflowResumeRequest) (*wfv1.Workflow, error) {
wfClient := auth.GetWfClient(ctx)
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{})
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{}, false)
if err != nil {
return nil, sutils.ToStatusError(err, codes.Internal)
}
Expand Down Expand Up @@ -521,7 +525,7 @@ func (s *workflowServer) ResumeWorkflow(ctx context.Context, req *workflowpkg.Wo
func (s *workflowServer) SuspendWorkflow(ctx context.Context, req *workflowpkg.WorkflowSuspendRequest) (*wfv1.Workflow, error) {
wfClient := auth.GetWfClient(ctx)

wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{})
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{}, false)
if err != nil {
return nil, sutils.ToStatusError(err, codes.Internal)
}
Expand All @@ -547,7 +551,7 @@ func (s *workflowServer) SuspendWorkflow(ctx context.Context, req *workflowpkg.W
func (s *workflowServer) TerminateWorkflow(ctx context.Context, req *workflowpkg.WorkflowTerminateRequest) (*wfv1.Workflow, error) {
wfClient := auth.GetWfClient(ctx)

wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{})
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{}, false)
if err != nil {
return nil, sutils.ToStatusError(err, codes.Internal)
}
Expand All @@ -571,7 +575,7 @@ func (s *workflowServer) TerminateWorkflow(ctx context.Context, req *workflowpkg

func (s *workflowServer) StopWorkflow(ctx context.Context, req *workflowpkg.WorkflowStopRequest) (*wfv1.Workflow, error) {
wfClient := auth.GetWfClient(ctx)
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{})
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{}, false)
if err != nil {
return nil, sutils.ToStatusError(err, codes.Internal)
}
Expand All @@ -593,7 +597,7 @@ func (s *workflowServer) StopWorkflow(ctx context.Context, req *workflowpkg.Work

func (s *workflowServer) SetWorkflow(ctx context.Context, req *workflowpkg.WorkflowSetRequest) (*wfv1.Workflow, error) {
wfClient := auth.GetWfClient(ctx)
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{})
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{}, false)
if err != nil {
return nil, sutils.ToStatusError(err, codes.Internal)
}
Expand Down Expand Up @@ -658,7 +662,7 @@ func (s *workflowServer) PodLogs(req *workflowpkg.WorkflowLogRequest, ws workflo
ctx := ws.Context()
wfClient := auth.GetWfClient(ctx)
kubeClient := auth.GetKubeClient(ctx)
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{})
wf, err := s.getWorkflow(ctx, wfClient, req.Namespace, req.Name, metav1.GetOptions{}, true)
if err != nil {
return sutils.ToStatusError(err, codes.Internal)
}
Expand All @@ -682,8 +686,8 @@ func (s *workflowServer) WorkflowLogs(req *workflowpkg.WorkflowLogRequest, ws wo
return sutils.ToStatusError(s.PodLogs(req, ws), codes.Internal)
}

func (s *workflowServer) getWorkflow(ctx context.Context, wfClient versioned.Interface, namespace string, name string, options metav1.GetOptions) (*wfv1.Workflow, error) {
var hasService bool
func (s *workflowServer) getWorkflow(ctx context.Context, wfClient versioned.Interface, namespace string, name string, options metav1.GetOptions, isPodLogs bool) (*wfv1.Workflow, error) {
var hasPermission bool
if name == latestAlias {
latest, err := getLatestWorkflow(ctx, wfClient, namespace)
if err != nil {
Expand All @@ -705,8 +709,8 @@ func (s *workflowServer) getWorkflow(ctx context.Context, wfClient versioned.Int
return nil, status.Error(codes.NotFound, "not found")
}
}
hasService = filter.ForbidActionsIfNeeded(ctx, wf.Labels)
if !hasService {
hasPermission = filter.ForbidActionsIfNeeded(ctx, wf.Labels)
if !hasPermission && !isPodLogs {
return nil, sutils.ToStatusError(fmt.Errorf("Permission Denied!"), codes.PermissionDenied)
}

Expand Down Expand Up @@ -735,6 +739,7 @@ func getLatestWorkflow(ctx context.Context, wfClient versioned.Interface, namesp
}

func (s *workflowServer) SubmitWorkflow(ctx context.Context, req *workflowpkg.WorkflowSubmitRequest) (*wfv1.Workflow, error) {
var hasPermission bool
wfClient := auth.GetWfClient(ctx)
var wf *wfv1.Workflow
switch req.ResourceKind {
Expand Down Expand Up @@ -768,6 +773,11 @@ func (s *workflowServer) SubmitWorkflow(ctx context.Context, req *workflowpkg.Wo
if err != nil {
return nil, sutils.ToStatusError(err, codes.InvalidArgument)
}
hasPermission = filter.ForbidActionsIfNeeded(ctx, wf.Labels)
if !hasPermission {
return nil, sutils.ToStatusError(fmt.Errorf("Permission Denied!"), codes.PermissionDenied)
}

wf, err = wfClient.ArgoprojV1alpha1().Workflows(req.Namespace).Create(ctx, wf, metav1.CreateOptions{})
if err != nil {
return nil, sutils.ToStatusError(err, codes.InvalidArgument)
Expand Down
6 changes: 3 additions & 3 deletions server/workflow/workflow_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -740,11 +740,11 @@ func TestGetWorkflow(t *testing.T) {
server, ctx := getWorkflowServer()
s := server.(*workflowServer)
wfClient := auth.GetWfClient(ctx)
wf, err := s.getWorkflow(ctx, wfClient, "test", "hello-world-9tql2-test", metav1.GetOptions{})
wf, err := s.getWorkflow(ctx, wfClient, "test", "hello-world-9tql2-test", metav1.GetOptions{}, false)
if assert.NoError(t, err) {
assert.NotNil(t, wf)
}
wf, err = s.getWorkflow(ctx, wfClient, "test", "hello-world-9tql2-test", metav1.GetOptions{})
wf, err = s.getWorkflow(ctx, wfClient, "test", "hello-world-9tql2-test", metav1.GetOptions{}, false)
if assert.NoError(t, err) {
assert.NotNil(t, wf)
}
Expand All @@ -754,7 +754,7 @@ func TestValidateWorkflow(t *testing.T) {
server, ctx := getWorkflowServer()
s := server.(*workflowServer)
wfClient := auth.GetWfClient(ctx)
wf, err := s.getWorkflow(ctx, wfClient, "test", "hello-world-9tql2-test", metav1.GetOptions{})
wf, err := s.getWorkflow(ctx, wfClient, "test", "hello-world-9tql2-test", metav1.GetOptions{}, false)
if assert.NoError(t, err) {
assert.NoError(t, s.validateWorkflow(wf))
}
Expand Down
Loading

0 comments on commit 8659428

Please sign in to comment.