Commit 80e7356f authored by Denis Arh's avatar Denis Arh
Browse files

Implement invoker and runner wf scope vars

parent b89f9b37
......@@ -13,7 +13,7 @@ import (
"github.com/cortezaproject/corteza-server/pkg/options"
"github.com/cortezaproject/corteza-server/pkg/rbac"
"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"
)
......@@ -30,7 +30,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"
)
......@@ -493,6 +495,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) {
......@@ -590,11 +594,16 @@ func (svc *workflow) Exec(ctx context.Context, workflowID uint64, p types.Workfl
ssp.ResourceType = ""
}
// Finally, assign input values
ssp.Input = scope.Merge(p.Input)
if invokerId := intAuth.GetIdentityFromContext(ctx).Identity(); invokerId > 0 {
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
}
}
......@@ -604,6 +613,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.Merge(p.Input)
wait, err = svc.session.Start(g, runAs, ssp)
if err != nil {
......
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 = superUser(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([]uint64{wfInvokers.ID})
ctx = auth.SetIdentityToContext(ctx, wfInvoker)
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)
})
}
......@@ -66,6 +66,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
......@@ -130,7 +137,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)
}
......
users:
wf-runner: workflow-runner@cortezaproject.org
wf-invoker: workflow-invoker@cortezaproject.org
roles:
wf-invokers:
members:
- wf-invoker
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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment