Fix invoker/runner mixup & move exec access-control check higher

This commit is contained in:
Denis Arh
2022-01-25 15:34:50 +01:00
parent e203300736
commit a4e5d2691a
9 changed files with 101 additions and 22 deletions
+8 -2
View File
@@ -269,7 +269,7 @@ func (svc *session) Resume(sessionID, stateID uint64, i auth.Identifiable, input
//
// We need initial context for the session because we want to catch all cancellations or timeouts from there
// and not from any potential HTTP requests or similar temporary context that can prematurely destroy a workflow session
func (svc *session) spawn(g *wfexec.Graph, workflowID uint64, trace bool, callStack []uint64, invoker, runner auth.Identifiable) (ses *types.Session) {
func (svc *session) spawn(g *wfexec.Graph, workflowID uint64, trace bool, callStack []uint64, runner, invoker auth.Identifiable) (ses *types.Session) {
s := &spawn{
workflowID: workflowID,
session: make(chan *wfexec.Session, 1),
@@ -316,9 +316,15 @@ func (svc *session) Watch(ctx context.Context) {
}
if svc.opt.ExecDebug {
log := svc.log.
Named("exec").
With(zap.Uint64("workflowID", s.workflowID)).
With(zap.Uint64("runnerID", s.runner.Identity())).
With(zap.Uint64s("runnerRoles", s.runner.Roles()))
opts = append(
opts,
wfexec.SetLogger(svc.log.Named("exec").With(zap.Uint64("workflowID", s.workflowID))),
wfexec.SetLogger(log),
wfexec.SetDumpStacktraceOnPanic(true),
)
}
-5
View File
@@ -560,11 +560,6 @@ func (svc *trigger) registerTriggers(wf *types.Workflow, runAs auth.Identifiable
continue
}
if t.EventType == "onManual" {
// skip onManual trigger registration,
// we'll handle them directly
}
var (
cnstr eventbus.ConstraintMatcher
ops = make([]eventbus.HandlerRegOp, 0, len(t.Constraints)+2)
+4 -7
View File
@@ -559,6 +559,10 @@ func (svc *workflow) Exec(ctx context.Context, workflowID uint64, p types.Workfl
wap.setWorkflow(wf)
if !svc.ac.CanExecuteWorkflow(ctx, wf) {
return WorkflowErrNotAllowedToExecute()
}
if !wf.Enabled && !p.Trace {
return WorkflowErrDisabled()
}
@@ -612,7 +616,6 @@ func (svc *workflow) Exec(ctx context.Context, workflowID uint64, p types.Workfl
p.EventType = "onTrace"
}
//wait, err = svc.session.Start(g, ssp)
wait, err = svc.exec(ctx, wf, p)
if err != nil {
@@ -700,12 +703,6 @@ func (svc *workflow) exec(ctx context.Context, wf *types.Workflow, p types.Workf
// merge workflow scope with the input
scope = wf.Scope.MustMerge(p.Input)
// User (either invoker or one set in the security descriptor) MUST have
// permissions to execute this workflow
if !svc.ac.CanExecuteWorkflow(ctx, wf) {
return nil, WorkflowErrNotAllowedToExecute()
}
return svc.session.Start(ctx, g, types.SessionStartParams{
Invoker: intAuth.GetIdentityFromContext(ctx),
Runner: runAs,
+2 -1
View File
@@ -3,11 +3,12 @@ package types
import (
"context"
"fmt"
"time"
"github.com/cortezaproject/corteza-server/pkg/expr"
"github.com/cortezaproject/corteza-server/pkg/logger"
"github.com/cortezaproject/corteza-server/pkg/wfexec"
"go.uber.org/zap"
"time"
)
type (
+1 -6
View File
@@ -626,12 +626,7 @@ func (s *Session) exec(ctx context.Context, log *zap.Logger, st *State) (nxt []*
// push logger to context but raise the stacktrace level to panic
// to prevent overly verbose traces
ctx = logger.ContextWithValue(ctx, log)
// Context received in exec() wil not have the identity we're expecting
// so we need to pull it from state owner and add it to new context
// that is set to step exec function
stepCtx := auth.SetIdentityToContext(ctx, st.owner)
stepCtx = SetContextCallStack(stepCtx, s.callStack)
stepCtx := SetContextCallStack(ctx, s.callStack)
result, st.err = st.step.Exec(stepCtx, st.MakeRequest())
+62
View File
@@ -0,0 +1,62 @@
package workflows
import (
"context"
"testing"
"github.com/cortezaproject/corteza-server/automation/service"
"github.com/cortezaproject/corteza-server/automation/types"
"github.com/cortezaproject/corteza-server/pkg/auth"
"github.com/cortezaproject/corteza-server/pkg/rbac"
"github.com/cortezaproject/corteza-server/tests/helpers"
"github.com/stretchr/testify/require"
)
func Test_exec_permissions(t *testing.T) {
var (
ctx = bypassRBAC(context.Background())
req = require.New(t)
)
req.NoError(defStore.TruncateUsers(ctx))
req.NoError(defStore.TruncateRoles(ctx))
req.NoError(defStore.TruncateRoleMembers(ctx))
req.NoError(defStore.TruncateRbacRules(ctx))
loadNewScenario(ctx, t)
// user that the workflow is configured to use for run-as
execAllowed, err := defStore.LookupUserByHandle(ctx, "exec-allowed")
req.NoError(err)
// user that the workflow is configured to use for run-as
execDenied, err := defStore.LookupUserByHandle(ctx, "exec-denied")
req.NoError(err)
// invokers group with permissions to execute workflow
executors, err := defStore.LookupRoleByHandle(ctx, "executors")
req.NoError(err)
//err = defStore.CreateRoleMember(ctx, &sysTypes.RoleMember{UserID: wfInvoker.ID, RoleID: wfInvokers.ID})
//req.NoError(err)
execAllowed.SetRoles(executors.ID)
helpers.UpdateRBAC(
executors.ID,
)
rbac.Global().Reload(ctx)
t.Run("exec allowed", func(t *testing.T) {
ctx = auth.SetIdentityToContext(ctx, execAllowed)
_, _ = mustExecWorkflow(ctx, t, "wf", types.WorkflowExecParams{})
})
t.Run("exec denied", func(t *testing.T) {
req = require.New(t)
ctx = auth.SetIdentityToContext(ctx, execDenied)
_, _, err = execWorkflow(ctx, "wf", types.WorkflowExecParams{})
req.ErrorIs(err, service.WorkflowErrNotAllowedToExecute())
})
}
@@ -85,5 +85,4 @@ func Test_invoker_and_runner_in_scope(t *testing.T) {
req.Equal(aux.Runner.Handle, wfRunner.Handle)
req.Equal(aux.Invoker.Handle, wfInvoker.Handle)
})
}
+8
View File
@@ -0,0 +1,8 @@
users:
exec-allowed: exec-allowed@cortezaproject.org
exec-denied: exec-denied@cortezaproject.org
roles:
executors:
members:
- exec-allowed
+16
View File
@@ -0,0 +1,16 @@
workflows:
wf:
enabled: true
trace: true
triggers:
- enabled: true
stepID: 1
steps:
- stepID: 1
kind: termination
paths: []
allow:
executors:
- execute