Implement invoker and runner wf scope vars
This commit is contained in:
@@ -12,7 +12,7 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/pkg/objstore"
|
||||
"github.com/cortezaproject/corteza-server/pkg/options"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
sysTypes "github.com/cortezaproject/corteza-server/system/types"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
@@ -28,7 +28,7 @@ type (
|
||||
}
|
||||
|
||||
userService interface {
|
||||
FindByAny(ctx context.Context, identifier interface{}) (*types.User, error)
|
||||
FindByAny(ctx context.Context, identifier interface{}) (*sysTypes.User, error)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/pkg/rbac"
|
||||
"github.com/cortezaproject/corteza-server/pkg/wfexec"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
sysAutoTypes "github.com/cortezaproject/corteza-server/system/automation"
|
||||
sysTypes "github.com/cortezaproject/corteza-server/system/types"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
@@ -489,6 +491,8 @@ func (svc *workflow) Exec(ctx context.Context, workflowID uint64, p types.Workfl
|
||||
wait WaitFn
|
||||
|
||||
stacktrace types.Stacktrace
|
||||
|
||||
runner, invoker *sysTypes.User
|
||||
)
|
||||
|
||||
err := func() (err error) {
|
||||
@@ -579,11 +583,19 @@ func (svc *workflow) Exec(ctx context.Context, workflowID uint64, p types.Workfl
|
||||
ssp.ResourceType = ""
|
||||
}
|
||||
|
||||
// Finally, assign input values
|
||||
ssp.Input = scope.MustMerge(p.Input)
|
||||
if invokerId := intAuth.GetIdentityFromContext(ctx).Identity(); invokerId > 0 {
|
||||
var is bool
|
||||
if invoker, is = intAuth.GetIdentityFromContext(ctx).(*sysTypes.User); !is {
|
||||
if invoker, err = DefaultUser.FindByAny(ctx, invokerId); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
runner = invoker
|
||||
}
|
||||
|
||||
if wf.RunAs > 0 {
|
||||
if runAs, err = DefaultUser.FindByAny(ctx, wf.RunAs); err != nil {
|
||||
if runner, err = DefaultUser.FindByAny(ctx, wf.RunAs); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -593,6 +605,14 @@ func (svc *workflow) Exec(ctx context.Context, workflowID uint64, p types.Workfl
|
||||
runAs = intAuth.GetIdentityFromContext(ctx)
|
||||
}
|
||||
|
||||
// @todo find a better way to typify expression values
|
||||
// so that we do not have to import automation types from the system component
|
||||
_ = scope.AssignFieldValue("invoker", expr.Must(sysAutoTypes.NewUser(invoker)))
|
||||
_ = scope.AssignFieldValue("runner", expr.Must(sysAutoTypes.NewUser(runner)))
|
||||
|
||||
// Finally, assign input values
|
||||
ssp.Input = scope.MustMerge(p.Input)
|
||||
|
||||
wait, err = svc.session.Start(g, runAs, ssp)
|
||||
|
||||
if err != nil {
|
||||
|
||||
85
tests/workflows/invoker_and_runner_in_scope_test.go
Normal file
85
tests/workflows/invoker_and_runner_in_scope_test.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package workflows
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/automation/types"
|
||||
"github.com/cortezaproject/corteza-server/pkg/auth"
|
||||
"github.com/cortezaproject/corteza-server/pkg/rbac"
|
||||
sysTypes "github.com/cortezaproject/corteza-server/system/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_invoker_and_runner_in_scope(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
|
||||
wfRunner, err := defStore.LookupUserByHandle(ctx, "wf-runner")
|
||||
req.NoError(err)
|
||||
|
||||
// user invoking the workflow
|
||||
wfInvoker, err := defStore.LookupUserByHandle(ctx, "wf-invoker")
|
||||
req.NoError(err)
|
||||
|
||||
// invokers group with permissions to execute workflow
|
||||
wfInvokers, err := defStore.LookupRoleByHandle(ctx, "wf-invokers")
|
||||
req.NoError(err)
|
||||
err = defStore.CreateRoleMember(ctx, &sysTypes.RoleMember{UserID: wfInvoker.ID, RoleID: wfInvokers.ID})
|
||||
req.NoError(err)
|
||||
|
||||
wfInvoker.SetRoles(wfInvokers.ID)
|
||||
ctx = auth.SetIdentityToContext(ctx, wfInvoker)
|
||||
|
||||
rbac.Global().UpdateRoles(rbac.CommonRole.Make(wfInvokers.ID, wfInvokers.Handle))
|
||||
rbac.Global().Reload(ctx)
|
||||
|
||||
t.Run("invoker set in scope", func(t *testing.T) {
|
||||
var (
|
||||
req = require.New(t)
|
||||
aux = struct {
|
||||
Invoker *sysTypes.User
|
||||
Runner *sysTypes.User
|
||||
}{}
|
||||
)
|
||||
|
||||
vars, _ := mustExecWorkflow(ctx, t, "invoker", types.WorkflowExecParams{})
|
||||
req.NoError(vars.Decode(&aux))
|
||||
|
||||
// Expecting both, invoker & runner to be same as invoker
|
||||
req.NotNil(aux.Runner)
|
||||
req.NotNil(aux.Invoker)
|
||||
req.Equal(aux.Runner.Handle, wfInvoker.Handle)
|
||||
req.Equal(aux.Invoker.Handle, wfInvoker.Handle)
|
||||
})
|
||||
|
||||
t.Run("runner set in scope", func(t *testing.T) {
|
||||
var (
|
||||
req = require.New(t)
|
||||
aux = struct {
|
||||
Invoker *sysTypes.User
|
||||
Runner *sysTypes.User
|
||||
}{}
|
||||
)
|
||||
|
||||
vars, _ := mustExecWorkflow(ctx, t, "runner", types.WorkflowExecParams{})
|
||||
req.NoError(vars.Decode(&aux))
|
||||
|
||||
// Expecting runner and invoker to be different.
|
||||
req.NotNil(aux.Runner)
|
||||
req.NotNil(aux.Invoker)
|
||||
req.Equal(aux.Runner.Handle, wfRunner.Handle)
|
||||
req.Equal(aux.Invoker.Handle, wfInvoker.Handle)
|
||||
})
|
||||
|
||||
}
|
||||
@@ -69,6 +69,13 @@ func loadScenario(ctx context.Context, t *testing.T) {
|
||||
loadScenarioWithName(ctx, t, "S"+t.Name()[4:])
|
||||
}
|
||||
|
||||
// 1st step in migration to workflow testdata w/o number prefix
|
||||
//
|
||||
// When all old scenarios are renamed, replace it with loadScenario.
|
||||
func loadNewScenario(ctx context.Context, t *testing.T) {
|
||||
loadScenarioWithName(ctx, t, t.Name()[5:])
|
||||
}
|
||||
|
||||
func loadScenarioWithName(ctx context.Context, t *testing.T, scenario string) {
|
||||
var (
|
||||
err error
|
||||
@@ -110,6 +117,10 @@ func bypassRBAC(ctx context.Context) context.Context {
|
||||
ID: id.Next(),
|
||||
}
|
||||
|
||||
if err := defStore.CreateUser(ctx, u); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
u.SetRoles(auth.BypassRoles().IDs()...)
|
||||
|
||||
return auth.SetIdentityToContext(ctx, u)
|
||||
@@ -135,7 +146,11 @@ func mustExecWorkflow(ctx context.Context, t *testing.T, name string, p autTypes
|
||||
}
|
||||
}
|
||||
|
||||
t.Fatalf("could not exec %q: %v", name, errors.Unwrap(err))
|
||||
if unw := errors.Unwrap(err); unw != nil {
|
||||
err = unw
|
||||
}
|
||||
|
||||
t.Fatalf("could not exec %q: %v", name, err)
|
||||
|
||||
}
|
||||
|
||||
|
||||
8
tests/workflows/testdata/invoker_and_runner_in_scope/users.yaml
vendored
Normal file
8
tests/workflows/testdata/invoker_and_runner_in_scope/users.yaml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
users:
|
||||
wf-runner: workflow-runner@cortezaproject.org
|
||||
wf-invoker: workflow-invoker@cortezaproject.org
|
||||
|
||||
roles:
|
||||
wf-invokers:
|
||||
members:
|
||||
- wf-invoker
|
||||
33
tests/workflows/testdata/invoker_and_runner_in_scope/workflow.yaml
vendored
Normal file
33
tests/workflows/testdata/invoker_and_runner_in_scope/workflow.yaml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
workflows:
|
||||
invoker:
|
||||
enabled: true
|
||||
trace: true
|
||||
triggers:
|
||||
- enabled: true
|
||||
stepID: 1
|
||||
|
||||
steps:
|
||||
- stepID: 1
|
||||
kind: termination
|
||||
|
||||
paths: []
|
||||
allow:
|
||||
wf-invokers:
|
||||
- execute
|
||||
|
||||
runner:
|
||||
enabled: true
|
||||
trace: true
|
||||
runAs: wf-runner
|
||||
triggers:
|
||||
- enabled: true
|
||||
stepID: 1
|
||||
|
||||
steps:
|
||||
- stepID: 1
|
||||
kind: termination
|
||||
|
||||
paths: []
|
||||
allow:
|
||||
wf-invokers:
|
||||
- execute
|
||||
Reference in New Issue
Block a user