Files
portainer/api/uac/generic_rc_getter_test.go

173 lines
6.0 KiB
Go

package uac
import (
"testing"
"github.com/docker/docker/api/types/container"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/datastore"
"github.com/portainer/portainer/api/docker/consts"
"github.com/portainer/portainer/api/internal/authorization"
"github.com/stretchr/testify/require"
)
func TestGenericResourcControlGetter(t *testing.T) {
t.Parallel()
is := require.New(t)
ok, store := datastore.MustNewTestStore(t, true, false)
is.True(ok)
is.NotNil(store)
endpointID := portainer.EndpointID(1)
composeStackName := "compose-stack"
composeStackRCID := StackResourceControlID(endpointID, composeStackName)
swarmStackName := "swarm-stack"
swarmStackRCID := StackResourceControlID(endpointID, swarmStackName)
serviceID := "service"
err := store.UpdateTx(func(tx dataservices.DataStoreTx) error {
// created on container create
is.NoError(tx.ResourceControl().Create(authorization.NewPublicResourceControl("container", portainer.ContainerResourceControl)))
// created on compose stack create
is.NoError(tx.ResourceControl().Create(authorization.NewPublicResourceControl(composeStackRCID, portainer.StackResourceControl)))
// created on swarm stack create
is.NoError(tx.ResourceControl().Create(authorization.NewPublicResourceControl(swarmStackRCID, portainer.StackResourceControl)))
// created a swarm service create
is.NoError(tx.ResourceControl().Create(authorization.NewPublicResourceControl(serviceID, portainer.ServiceResourceControl)))
return nil
})
is.NoError(err)
err = store.ViewTx(func(tx dataservices.DataStoreTx) error {
context := ResourceContext[container.Summary]{RCType: portainer.ContainerResourceControl, IDGetter: ContainerResourceControlID, LabelsGetter: ContainerLabels}
// trying to get UAC for a container created through Portainer
rc, err := genericResourcControlGetter(tx, 1, context)(container.Summary{ID: "container"})
is.NoError(err)
is.NotNil(rc)
// trying to get UAC for an external container
rc, err = genericResourcControlGetter(tx, 1, context)(container.Summary{ID: "unknown"})
is.NoError(err)
is.NotNil(rc)
is.Empty(rc.UserAccesses)
is.Empty(rc.TeamAccesses)
// trying to get UAC for a container from a compose stack
rc, err = genericResourcControlGetter(tx, 1, context)(container.Summary{ID: "by-compose-stack-name-label", Labels: map[string]string{consts.ComposeStackNameLabel: composeStackName}})
is.NoError(err)
is.NotNil(rc)
is.Equal(composeStackRCID, rc.ResourceID)
// trying to get UAC for a container from a swarm stack
rc, err = genericResourcControlGetter(tx, 1, context)(container.Summary{ID: "by-swarm-stack-name-label", Labels: map[string]string{consts.SwarmStackNameLabel: swarmStackName}})
is.NoError(err)
is.NotNil(rc)
is.Equal(swarmStackRCID, rc.ResourceID)
// trying to get UAC for a container from a swarm service
rc, err = genericResourcControlGetter(tx, 1, context)(container.Summary{ID: "by-swarm-service-id-label", Labels: map[string]string{consts.SwarmServiceIDLabel: serviceID}})
is.NoError(err)
is.NotNil(rc)
is.Equal(serviceID, rc.ResourceID)
return nil
})
is.NoError(err)
}
func TestGenericResourcControlGetterWithPortainerLabels(t *testing.T) {
t.Parallel()
is := require.New(t)
ok, store := datastore.MustNewTestStore(t, true, false)
is.True(ok)
is.NotNil(store)
is.NoError(store.UpdateTx(func(tx dataservices.DataStoreTx) error {
is.NoError(tx.User().Create(&portainer.User{Role: portainer.AdministratorRole, Username: "admin"}))
is.NoError(tx.User().Create(&portainer.User{Role: portainer.AdministratorRole, Username: "user"}))
is.NoError(tx.Team().Create(&portainer.Team{Name: "team"}))
is.NoError(tx.TeamMembership().Create(&portainer.TeamMembership{UserID: 2, TeamID: 1}))
return nil
}))
is.NoError(store.ViewTx(func(tx dataservices.DataStoreTx) error {
context := ResourceContext[container.Summary]{RCType: portainer.ContainerResourceControl, IDGetter: ContainerResourceControlID, LabelsGetter: ContainerLabels}
rc, err := genericResourcControlGetter(tx, 1, context)(container.Summary{
ID: "public",
Labels: map[string]string{publicRCLabel: "true"},
})
is.NoError(err)
is.NotNil(rc)
is.True(rc.Public)
rc, err = genericResourcControlGetter(tx, 1, context)(container.Summary{
ID: "team",
Labels: map[string]string{teamRCLabel: "team"},
})
is.NoError(err)
is.NotNil(rc)
is.Contains(rc.TeamAccesses, portainer.TeamResourceAccess{TeamID: 1, AccessLevel: portainer.ReadWriteAccessLevel})
rc, err = genericResourcControlGetter(tx, 1, context)(container.Summary{
ID: "no-team",
Labels: map[string]string{teamRCLabel: "team2"},
})
is.NoError(err)
is.NotNil(rc)
is.Empty(rc.UserAccesses)
is.Empty(rc.TeamAccesses)
rc, err = genericResourcControlGetter(tx, 1, context)(container.Summary{
ID: "user",
Labels: map[string]string{userRCLabel: "user"},
})
is.NoError(err)
is.NotNil(rc)
is.Contains(rc.UserAccesses, portainer.UserResourceAccess{UserID: 2, AccessLevel: portainer.ReadWriteAccessLevel})
rc, err = genericResourcControlGetter(tx, 1, context)(container.Summary{
ID: "no-user",
Labels: map[string]string{userRCLabel: "user2"},
})
is.NoError(err)
is.NotNil(rc)
is.Empty(rc.UserAccesses)
is.Empty(rc.TeamAccesses)
rc, err = genericResourcControlGetter(tx, 1, context)(container.Summary{
ID: "warn-on-unknown",
Labels: map[string]string{userRCLabel: "user2,user3", teamRCLabel: "team2,team3"},
})
is.NoError(err)
is.NotNil(rc)
is.Empty(rc.UserAccesses)
is.Empty(rc.TeamAccesses)
rc, err = genericResourcControlGetter(tx, 1, context)(container.Summary{
ID: "empty-when-no-label",
})
is.NoError(err)
is.NotNil(rc)
is.Empty(rc.UserAccesses)
is.Empty(rc.TeamAccesses)
rc, err = genericResourcControlGetter(tx, 1, context)(container.Summary{
ID: "empty-when-empty-labels",
Labels: map[string]string{},
})
is.NoError(err)
is.NotNil(rc)
is.Empty(rc.UserAccesses)
is.Empty(rc.TeamAccesses)
return nil
}))
}