Skip to content

Commit 741ab0e

Browse files
JoibelAnton Gilgur
and
Anton Gilgur
authored
Merge commit from fork
* fix(api): properly authorize GET workflow fallback to archive - the authorization was accidentally removed in f1ab5aa - also if no archived workflow is found, properly return the original error as per ac9e2de Signed-off-by: Anton Gilgur <[email protected]> * test: add permission assertions for GET WF archived fallback - the permission suite seemed to not have previously tested this - add good, bad, and fake token checks - where "bad" is valid, but unauthorized, while "fake" is valid in format, but not corresponding to a real token Signed-off-by: Anton Gilgur <[email protected]> * fix(test): assign `goodToken` initially - these tests were relying on ordering of assignments before, i.e. 1. good 2. bad 3. bad - should just assign before each test instead for simplicity / less complexity / less mistakes Signed-off-by: Anton Gilgur <[email protected]> --------- Signed-off-by: Anton Gilgur <[email protected]> Co-authored-by: Anton Gilgur <[email protected]>
1 parent f55af8f commit 741ab0e

File tree

2 files changed

+51
-11
lines changed

2 files changed

+51
-11
lines changed

server/workflow/workflow_server.go

+20-9
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,10 @@ func (s *workflowServer) ListWorkflows(ctx context.Context, req *workflowpkg.Wor
174174
s.instanceIDService.With(&listOption)
175175

176176
options, err := sutils.BuildListOptions(listOption, req.Namespace, "", req.NameFilter)
177-
178177
if err != nil {
179178
return nil, err
180179
}
180+
181181
// verify if we have permission to list Workflows
182182
allowed, err := auth.CanI(ctx, "list", workflow.WorkflowPlural, options.Namespace, "")
183183
if err != nil {
@@ -688,7 +688,6 @@ func (s *workflowServer) PodLogs(req *workflowpkg.WorkflowLogRequest, ws workflo
688688
req.Name = wf.Name
689689

690690
err = ws.SendHeader(metadata.MD{})
691-
692691
if err != nil {
693692
return sutils.ToStatusError(err, codes.Internal)
694693
}
@@ -710,22 +709,34 @@ func (s *workflowServer) getWorkflow(ctx context.Context, wfClient versioned.Int
710709
log.Debugf("Resolved alias %s to workflow %s.\n", latestAlias, latest.Name)
711710
return latest, nil
712711
}
713-
var err error
712+
714713
wf, origErr := wfClient.ArgoprojV1alpha1().Workflows(namespace).Get(ctx, name, options)
714+
// fallback to retrieve from archived workflows
715715
if wf == nil || origErr != nil {
716-
wf, err = s.wfArchive.GetWorkflow("", namespace, name)
716+
allowed, err := auth.CanI(ctx, "get", workflow.WorkflowPlural, namespace, name)
717717
if err != nil {
718-
log.Errorf("failed to get live workflow: %v; failed to get archived workflow: %v", origErr, err)
719-
// We only return the original error to preserve the original status code.
720-
return nil, sutils.ToStatusError(origErr, codes.Internal)
718+
return nil, getWorkflowOrigErr(origErr, err)
721719
}
722-
if wf == nil {
723-
return nil, status.Error(codes.NotFound, "not found")
720+
if !allowed {
721+
err = status.Error(codes.PermissionDenied, "permission denied")
722+
return nil, getWorkflowOrigErr(origErr, err)
723+
}
724+
725+
wf, err = s.wfArchive.GetWorkflow("", namespace, name)
726+
if wf == nil || err != nil {
727+
return nil, getWorkflowOrigErr(origErr, err)
724728
}
725729
}
726730
return wf, nil
727731
}
728732

733+
// getWorkflowOrigErr only returns the original error to preserve the original status code
734+
// it logs out the new error
735+
func getWorkflowOrigErr(origErr error, err error) error {
736+
log.Errorf("failed to get live workflow: %v; failed to get archived workflow: %v", origErr, err)
737+
return sutils.ToStatusError(origErr, codes.Internal)
738+
}
739+
729740
func (s *workflowServer) validateWorkflow(wf *wfv1.Workflow) error {
730741
return sutils.ToStatusError(s.instanceIDService.Validate(wf), codes.InvalidArgument)
731742
}

test/e2e/argo_server_test.go

+31-2
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,9 @@ func (s *ArgoServerSuite) TestPermission() {
461461
badToken = string(secret.Data["token"])
462462
})
463463

464+
// fake / spoofed token
465+
fakeToken := "faketoken"
466+
464467
token := s.bearerToken
465468
defer func() { s.bearerToken = token }()
466469

@@ -564,8 +567,8 @@ func (s *ArgoServerSuite) TestPermission() {
564567
Status(200)
565568
})
566569

567-
// we've now deleted the workflow, but it is still in the archive, testing the archive
568-
// after deleting the workflow makes sure that we are no dependant of the workflow for authorization
570+
// we've now deleted the workflow, but it is still in the archive
571+
// testing the archive after deleting it makes sure that we are not dependent on a live workflow resource for authorization
569572

570573
// Test list archived WFs with good token
571574
s.Run("ListArchivedWFsGoodToken", func() {
@@ -605,7 +608,33 @@ func (s *ArgoServerSuite) TestPermission() {
605608
Status(403)
606609
})
607610

611+
// Test get wf w/ archive fallback with good token
612+
s.bearerToken = goodToken
613+
s.Run("GetWFsFallbackArchivedGoodToken", func() {
614+
s.e().GET("/api/v1/workflows/"+uid).
615+
WithQuery("listOptions.labelSelector", "workflows.argoproj.io/test").
616+
Expect().
617+
Status(200)
618+
})
619+
620+
// Test get wf w/ archive fallback with bad token
621+
s.bearerToken = badToken
622+
s.Run("GetWFsFallbackArchivedBadToken", func() {
623+
s.e().GET("/api/v1/workflows/" + uid).
624+
Expect().
625+
Status(403)
626+
})
627+
628+
// Test get wf w/ archive fallback with fake token
629+
s.bearerToken = fakeToken
630+
s.Run("GetWFsFallbackArchivedFakeToken", func() {
631+
s.e().GET("/api/v1/workflows/" + uid).
632+
Expect().
633+
Status(403)
634+
})
635+
608636
// Test deleting archived wf with bad token
637+
s.bearerToken = badToken
609638
s.Run("DeleteArchivedWFsBadToken", func() {
610639
s.e().DELETE("/api/v1/archived-workflows/" + uid).
611640
Expect().

0 commit comments

Comments
 (0)