mirror of https://github.com/portainer/portainer
refactor(portainer): introduce internal package (#3924)
* refactor(auth): move auth helpers to internal package * refactor(edge-compute): move edge helpers to internal package * refactor(tags): move tags helper to internal package * style(portainer): sort importspull/3948/head
parent
5d7ba0baba
commit
7c3b83f6e5
|
@ -1,774 +0,0 @@
|
||||||
package portainer
|
|
||||||
|
|
||||||
// AuthorizationService represents a service used to
|
|
||||||
// update authorizations associated to a user or team.
|
|
||||||
type AuthorizationService struct {
|
|
||||||
dataStore DataStore
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAuthorizationService returns a point to a new AuthorizationService instance.
|
|
||||||
func NewAuthorizationService(dataStore DataStore) *AuthorizationService {
|
|
||||||
return &AuthorizationService{
|
|
||||||
dataStore: dataStore,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultEndpointAuthorizationsForEndpointAdministratorRole returns the default endpoint authorizations
|
|
||||||
// associated to the endpoint administrator role.
|
|
||||||
func DefaultEndpointAuthorizationsForEndpointAdministratorRole() Authorizations {
|
|
||||||
return map[Authorization]bool{
|
|
||||||
OperationDockerContainerArchiveInfo: true,
|
|
||||||
OperationDockerContainerList: true,
|
|
||||||
OperationDockerContainerExport: true,
|
|
||||||
OperationDockerContainerChanges: true,
|
|
||||||
OperationDockerContainerInspect: true,
|
|
||||||
OperationDockerContainerTop: true,
|
|
||||||
OperationDockerContainerLogs: true,
|
|
||||||
OperationDockerContainerStats: true,
|
|
||||||
OperationDockerContainerAttachWebsocket: true,
|
|
||||||
OperationDockerContainerArchive: true,
|
|
||||||
OperationDockerContainerCreate: true,
|
|
||||||
OperationDockerContainerPrune: true,
|
|
||||||
OperationDockerContainerKill: true,
|
|
||||||
OperationDockerContainerPause: true,
|
|
||||||
OperationDockerContainerUnpause: true,
|
|
||||||
OperationDockerContainerRestart: true,
|
|
||||||
OperationDockerContainerStart: true,
|
|
||||||
OperationDockerContainerStop: true,
|
|
||||||
OperationDockerContainerWait: true,
|
|
||||||
OperationDockerContainerResize: true,
|
|
||||||
OperationDockerContainerAttach: true,
|
|
||||||
OperationDockerContainerExec: true,
|
|
||||||
OperationDockerContainerRename: true,
|
|
||||||
OperationDockerContainerUpdate: true,
|
|
||||||
OperationDockerContainerPutContainerArchive: true,
|
|
||||||
OperationDockerContainerDelete: true,
|
|
||||||
OperationDockerImageList: true,
|
|
||||||
OperationDockerImageSearch: true,
|
|
||||||
OperationDockerImageGetAll: true,
|
|
||||||
OperationDockerImageGet: true,
|
|
||||||
OperationDockerImageHistory: true,
|
|
||||||
OperationDockerImageInspect: true,
|
|
||||||
OperationDockerImageLoad: true,
|
|
||||||
OperationDockerImageCreate: true,
|
|
||||||
OperationDockerImagePrune: true,
|
|
||||||
OperationDockerImagePush: true,
|
|
||||||
OperationDockerImageTag: true,
|
|
||||||
OperationDockerImageDelete: true,
|
|
||||||
OperationDockerImageCommit: true,
|
|
||||||
OperationDockerImageBuild: true,
|
|
||||||
OperationDockerNetworkList: true,
|
|
||||||
OperationDockerNetworkInspect: true,
|
|
||||||
OperationDockerNetworkCreate: true,
|
|
||||||
OperationDockerNetworkConnect: true,
|
|
||||||
OperationDockerNetworkDisconnect: true,
|
|
||||||
OperationDockerNetworkPrune: true,
|
|
||||||
OperationDockerNetworkDelete: true,
|
|
||||||
OperationDockerVolumeList: true,
|
|
||||||
OperationDockerVolumeInspect: true,
|
|
||||||
OperationDockerVolumeCreate: true,
|
|
||||||
OperationDockerVolumePrune: true,
|
|
||||||
OperationDockerVolumeDelete: true,
|
|
||||||
OperationDockerExecInspect: true,
|
|
||||||
OperationDockerExecStart: true,
|
|
||||||
OperationDockerExecResize: true,
|
|
||||||
OperationDockerSwarmInspect: true,
|
|
||||||
OperationDockerSwarmUnlockKey: true,
|
|
||||||
OperationDockerSwarmInit: true,
|
|
||||||
OperationDockerSwarmJoin: true,
|
|
||||||
OperationDockerSwarmLeave: true,
|
|
||||||
OperationDockerSwarmUpdate: true,
|
|
||||||
OperationDockerSwarmUnlock: true,
|
|
||||||
OperationDockerNodeList: true,
|
|
||||||
OperationDockerNodeInspect: true,
|
|
||||||
OperationDockerNodeUpdate: true,
|
|
||||||
OperationDockerNodeDelete: true,
|
|
||||||
OperationDockerServiceList: true,
|
|
||||||
OperationDockerServiceInspect: true,
|
|
||||||
OperationDockerServiceLogs: true,
|
|
||||||
OperationDockerServiceCreate: true,
|
|
||||||
OperationDockerServiceUpdate: true,
|
|
||||||
OperationDockerServiceDelete: true,
|
|
||||||
OperationDockerSecretList: true,
|
|
||||||
OperationDockerSecretInspect: true,
|
|
||||||
OperationDockerSecretCreate: true,
|
|
||||||
OperationDockerSecretUpdate: true,
|
|
||||||
OperationDockerSecretDelete: true,
|
|
||||||
OperationDockerConfigList: true,
|
|
||||||
OperationDockerConfigInspect: true,
|
|
||||||
OperationDockerConfigCreate: true,
|
|
||||||
OperationDockerConfigUpdate: true,
|
|
||||||
OperationDockerConfigDelete: true,
|
|
||||||
OperationDockerTaskList: true,
|
|
||||||
OperationDockerTaskInspect: true,
|
|
||||||
OperationDockerTaskLogs: true,
|
|
||||||
OperationDockerPluginList: true,
|
|
||||||
OperationDockerPluginPrivileges: true,
|
|
||||||
OperationDockerPluginInspect: true,
|
|
||||||
OperationDockerPluginPull: true,
|
|
||||||
OperationDockerPluginCreate: true,
|
|
||||||
OperationDockerPluginEnable: true,
|
|
||||||
OperationDockerPluginDisable: true,
|
|
||||||
OperationDockerPluginPush: true,
|
|
||||||
OperationDockerPluginUpgrade: true,
|
|
||||||
OperationDockerPluginSet: true,
|
|
||||||
OperationDockerPluginDelete: true,
|
|
||||||
OperationDockerSessionStart: true,
|
|
||||||
OperationDockerDistributionInspect: true,
|
|
||||||
OperationDockerBuildPrune: true,
|
|
||||||
OperationDockerBuildCancel: true,
|
|
||||||
OperationDockerPing: true,
|
|
||||||
OperationDockerInfo: true,
|
|
||||||
OperationDockerVersion: true,
|
|
||||||
OperationDockerEvents: true,
|
|
||||||
OperationDockerSystem: true,
|
|
||||||
OperationDockerUndefined: true,
|
|
||||||
OperationDockerAgentPing: true,
|
|
||||||
OperationDockerAgentList: true,
|
|
||||||
OperationDockerAgentHostInfo: true,
|
|
||||||
OperationDockerAgentBrowseDelete: true,
|
|
||||||
OperationDockerAgentBrowseGet: true,
|
|
||||||
OperationDockerAgentBrowseList: true,
|
|
||||||
OperationDockerAgentBrowsePut: true,
|
|
||||||
OperationDockerAgentBrowseRename: true,
|
|
||||||
OperationDockerAgentUndefined: true,
|
|
||||||
OperationPortainerResourceControlCreate: true,
|
|
||||||
OperationPortainerResourceControlUpdate: true,
|
|
||||||
OperationPortainerStackList: true,
|
|
||||||
OperationPortainerStackInspect: true,
|
|
||||||
OperationPortainerStackFile: true,
|
|
||||||
OperationPortainerStackCreate: true,
|
|
||||||
OperationPortainerStackMigrate: true,
|
|
||||||
OperationPortainerStackUpdate: true,
|
|
||||||
OperationPortainerStackDelete: true,
|
|
||||||
OperationPortainerWebsocketExec: true,
|
|
||||||
OperationPortainerWebhookList: true,
|
|
||||||
OperationPortainerWebhookCreate: true,
|
|
||||||
OperationPortainerWebhookDelete: true,
|
|
||||||
OperationIntegrationStoridgeAdmin: true,
|
|
||||||
EndpointResourcesAccess: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultEndpointAuthorizationsForHelpDeskRole returns the default endpoint authorizations
|
|
||||||
// associated to the helpdesk role.
|
|
||||||
func DefaultEndpointAuthorizationsForHelpDeskRole(volumeBrowsingAuthorizations bool) Authorizations {
|
|
||||||
authorizations := map[Authorization]bool{
|
|
||||||
OperationDockerContainerArchiveInfo: true,
|
|
||||||
OperationDockerContainerList: true,
|
|
||||||
OperationDockerContainerChanges: true,
|
|
||||||
OperationDockerContainerInspect: true,
|
|
||||||
OperationDockerContainerTop: true,
|
|
||||||
OperationDockerContainerLogs: true,
|
|
||||||
OperationDockerContainerStats: true,
|
|
||||||
OperationDockerImageList: true,
|
|
||||||
OperationDockerImageSearch: true,
|
|
||||||
OperationDockerImageGetAll: true,
|
|
||||||
OperationDockerImageGet: true,
|
|
||||||
OperationDockerImageHistory: true,
|
|
||||||
OperationDockerImageInspect: true,
|
|
||||||
OperationDockerNetworkList: true,
|
|
||||||
OperationDockerNetworkInspect: true,
|
|
||||||
OperationDockerVolumeList: true,
|
|
||||||
OperationDockerVolumeInspect: true,
|
|
||||||
OperationDockerSwarmInspect: true,
|
|
||||||
OperationDockerNodeList: true,
|
|
||||||
OperationDockerNodeInspect: true,
|
|
||||||
OperationDockerServiceList: true,
|
|
||||||
OperationDockerServiceInspect: true,
|
|
||||||
OperationDockerServiceLogs: true,
|
|
||||||
OperationDockerSecretList: true,
|
|
||||||
OperationDockerSecretInspect: true,
|
|
||||||
OperationDockerConfigList: true,
|
|
||||||
OperationDockerConfigInspect: true,
|
|
||||||
OperationDockerTaskList: true,
|
|
||||||
OperationDockerTaskInspect: true,
|
|
||||||
OperationDockerTaskLogs: true,
|
|
||||||
OperationDockerPluginList: true,
|
|
||||||
OperationDockerDistributionInspect: true,
|
|
||||||
OperationDockerPing: true,
|
|
||||||
OperationDockerInfo: true,
|
|
||||||
OperationDockerVersion: true,
|
|
||||||
OperationDockerEvents: true,
|
|
||||||
OperationDockerSystem: true,
|
|
||||||
OperationDockerAgentPing: true,
|
|
||||||
OperationDockerAgentList: true,
|
|
||||||
OperationDockerAgentHostInfo: true,
|
|
||||||
OperationPortainerStackList: true,
|
|
||||||
OperationPortainerStackInspect: true,
|
|
||||||
OperationPortainerStackFile: true,
|
|
||||||
OperationPortainerWebhookList: true,
|
|
||||||
EndpointResourcesAccess: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
if volumeBrowsingAuthorizations {
|
|
||||||
authorizations[OperationDockerAgentBrowseGet] = true
|
|
||||||
authorizations[OperationDockerAgentBrowseList] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return authorizations
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultEndpointAuthorizationsForStandardUserRole returns the default endpoint authorizations
|
|
||||||
// associated to the standard user role.
|
|
||||||
func DefaultEndpointAuthorizationsForStandardUserRole(volumeBrowsingAuthorizations bool) Authorizations {
|
|
||||||
authorizations := map[Authorization]bool{
|
|
||||||
OperationDockerContainerArchiveInfo: true,
|
|
||||||
OperationDockerContainerList: true,
|
|
||||||
OperationDockerContainerExport: true,
|
|
||||||
OperationDockerContainerChanges: true,
|
|
||||||
OperationDockerContainerInspect: true,
|
|
||||||
OperationDockerContainerTop: true,
|
|
||||||
OperationDockerContainerLogs: true,
|
|
||||||
OperationDockerContainerStats: true,
|
|
||||||
OperationDockerContainerAttachWebsocket: true,
|
|
||||||
OperationDockerContainerArchive: true,
|
|
||||||
OperationDockerContainerCreate: true,
|
|
||||||
OperationDockerContainerKill: true,
|
|
||||||
OperationDockerContainerPause: true,
|
|
||||||
OperationDockerContainerUnpause: true,
|
|
||||||
OperationDockerContainerRestart: true,
|
|
||||||
OperationDockerContainerStart: true,
|
|
||||||
OperationDockerContainerStop: true,
|
|
||||||
OperationDockerContainerWait: true,
|
|
||||||
OperationDockerContainerResize: true,
|
|
||||||
OperationDockerContainerAttach: true,
|
|
||||||
OperationDockerContainerExec: true,
|
|
||||||
OperationDockerContainerRename: true,
|
|
||||||
OperationDockerContainerUpdate: true,
|
|
||||||
OperationDockerContainerPutContainerArchive: true,
|
|
||||||
OperationDockerContainerDelete: true,
|
|
||||||
OperationDockerImageList: true,
|
|
||||||
OperationDockerImageSearch: true,
|
|
||||||
OperationDockerImageGetAll: true,
|
|
||||||
OperationDockerImageGet: true,
|
|
||||||
OperationDockerImageHistory: true,
|
|
||||||
OperationDockerImageInspect: true,
|
|
||||||
OperationDockerImageLoad: true,
|
|
||||||
OperationDockerImageCreate: true,
|
|
||||||
OperationDockerImagePush: true,
|
|
||||||
OperationDockerImageTag: true,
|
|
||||||
OperationDockerImageDelete: true,
|
|
||||||
OperationDockerImageCommit: true,
|
|
||||||
OperationDockerImageBuild: true,
|
|
||||||
OperationDockerNetworkList: true,
|
|
||||||
OperationDockerNetworkInspect: true,
|
|
||||||
OperationDockerNetworkCreate: true,
|
|
||||||
OperationDockerNetworkConnect: true,
|
|
||||||
OperationDockerNetworkDisconnect: true,
|
|
||||||
OperationDockerNetworkDelete: true,
|
|
||||||
OperationDockerVolumeList: true,
|
|
||||||
OperationDockerVolumeInspect: true,
|
|
||||||
OperationDockerVolumeCreate: true,
|
|
||||||
OperationDockerVolumeDelete: true,
|
|
||||||
OperationDockerExecInspect: true,
|
|
||||||
OperationDockerExecStart: true,
|
|
||||||
OperationDockerExecResize: true,
|
|
||||||
OperationDockerSwarmInspect: true,
|
|
||||||
OperationDockerSwarmUnlockKey: true,
|
|
||||||
OperationDockerSwarmInit: true,
|
|
||||||
OperationDockerSwarmJoin: true,
|
|
||||||
OperationDockerSwarmLeave: true,
|
|
||||||
OperationDockerSwarmUpdate: true,
|
|
||||||
OperationDockerSwarmUnlock: true,
|
|
||||||
OperationDockerNodeList: true,
|
|
||||||
OperationDockerNodeInspect: true,
|
|
||||||
OperationDockerNodeUpdate: true,
|
|
||||||
OperationDockerNodeDelete: true,
|
|
||||||
OperationDockerServiceList: true,
|
|
||||||
OperationDockerServiceInspect: true,
|
|
||||||
OperationDockerServiceLogs: true,
|
|
||||||
OperationDockerServiceCreate: true,
|
|
||||||
OperationDockerServiceUpdate: true,
|
|
||||||
OperationDockerServiceDelete: true,
|
|
||||||
OperationDockerSecretList: true,
|
|
||||||
OperationDockerSecretInspect: true,
|
|
||||||
OperationDockerSecretCreate: true,
|
|
||||||
OperationDockerSecretUpdate: true,
|
|
||||||
OperationDockerSecretDelete: true,
|
|
||||||
OperationDockerConfigList: true,
|
|
||||||
OperationDockerConfigInspect: true,
|
|
||||||
OperationDockerConfigCreate: true,
|
|
||||||
OperationDockerConfigUpdate: true,
|
|
||||||
OperationDockerConfigDelete: true,
|
|
||||||
OperationDockerTaskList: true,
|
|
||||||
OperationDockerTaskInspect: true,
|
|
||||||
OperationDockerTaskLogs: true,
|
|
||||||
OperationDockerPluginList: true,
|
|
||||||
OperationDockerPluginPrivileges: true,
|
|
||||||
OperationDockerPluginInspect: true,
|
|
||||||
OperationDockerPluginPull: true,
|
|
||||||
OperationDockerPluginCreate: true,
|
|
||||||
OperationDockerPluginEnable: true,
|
|
||||||
OperationDockerPluginDisable: true,
|
|
||||||
OperationDockerPluginPush: true,
|
|
||||||
OperationDockerPluginUpgrade: true,
|
|
||||||
OperationDockerPluginSet: true,
|
|
||||||
OperationDockerPluginDelete: true,
|
|
||||||
OperationDockerSessionStart: true,
|
|
||||||
OperationDockerDistributionInspect: true,
|
|
||||||
OperationDockerBuildPrune: true,
|
|
||||||
OperationDockerBuildCancel: true,
|
|
||||||
OperationDockerPing: true,
|
|
||||||
OperationDockerInfo: true,
|
|
||||||
OperationDockerVersion: true,
|
|
||||||
OperationDockerEvents: true,
|
|
||||||
OperationDockerSystem: true,
|
|
||||||
OperationDockerUndefined: true,
|
|
||||||
OperationDockerAgentPing: true,
|
|
||||||
OperationDockerAgentList: true,
|
|
||||||
OperationDockerAgentHostInfo: true,
|
|
||||||
OperationDockerAgentUndefined: true,
|
|
||||||
OperationPortainerResourceControlUpdate: true,
|
|
||||||
OperationPortainerStackList: true,
|
|
||||||
OperationPortainerStackInspect: true,
|
|
||||||
OperationPortainerStackFile: true,
|
|
||||||
OperationPortainerStackCreate: true,
|
|
||||||
OperationPortainerStackMigrate: true,
|
|
||||||
OperationPortainerStackUpdate: true,
|
|
||||||
OperationPortainerStackDelete: true,
|
|
||||||
OperationPortainerWebsocketExec: true,
|
|
||||||
OperationPortainerWebhookList: true,
|
|
||||||
OperationPortainerWebhookCreate: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
if volumeBrowsingAuthorizations {
|
|
||||||
authorizations[OperationDockerAgentBrowseGet] = true
|
|
||||||
authorizations[OperationDockerAgentBrowseList] = true
|
|
||||||
authorizations[OperationDockerAgentBrowseDelete] = true
|
|
||||||
authorizations[OperationDockerAgentBrowsePut] = true
|
|
||||||
authorizations[OperationDockerAgentBrowseRename] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return authorizations
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultEndpointAuthorizationsForReadOnlyUserRole returns the default endpoint authorizations
|
|
||||||
// associated to the readonly user role.
|
|
||||||
func DefaultEndpointAuthorizationsForReadOnlyUserRole(volumeBrowsingAuthorizations bool) Authorizations {
|
|
||||||
authorizations := map[Authorization]bool{
|
|
||||||
OperationDockerContainerArchiveInfo: true,
|
|
||||||
OperationDockerContainerList: true,
|
|
||||||
OperationDockerContainerChanges: true,
|
|
||||||
OperationDockerContainerInspect: true,
|
|
||||||
OperationDockerContainerTop: true,
|
|
||||||
OperationDockerContainerLogs: true,
|
|
||||||
OperationDockerContainerStats: true,
|
|
||||||
OperationDockerImageList: true,
|
|
||||||
OperationDockerImageSearch: true,
|
|
||||||
OperationDockerImageGetAll: true,
|
|
||||||
OperationDockerImageGet: true,
|
|
||||||
OperationDockerImageHistory: true,
|
|
||||||
OperationDockerImageInspect: true,
|
|
||||||
OperationDockerNetworkList: true,
|
|
||||||
OperationDockerNetworkInspect: true,
|
|
||||||
OperationDockerVolumeList: true,
|
|
||||||
OperationDockerVolumeInspect: true,
|
|
||||||
OperationDockerSwarmInspect: true,
|
|
||||||
OperationDockerNodeList: true,
|
|
||||||
OperationDockerNodeInspect: true,
|
|
||||||
OperationDockerServiceList: true,
|
|
||||||
OperationDockerServiceInspect: true,
|
|
||||||
OperationDockerServiceLogs: true,
|
|
||||||
OperationDockerSecretList: true,
|
|
||||||
OperationDockerSecretInspect: true,
|
|
||||||
OperationDockerConfigList: true,
|
|
||||||
OperationDockerConfigInspect: true,
|
|
||||||
OperationDockerTaskList: true,
|
|
||||||
OperationDockerTaskInspect: true,
|
|
||||||
OperationDockerTaskLogs: true,
|
|
||||||
OperationDockerPluginList: true,
|
|
||||||
OperationDockerDistributionInspect: true,
|
|
||||||
OperationDockerPing: true,
|
|
||||||
OperationDockerInfo: true,
|
|
||||||
OperationDockerVersion: true,
|
|
||||||
OperationDockerEvents: true,
|
|
||||||
OperationDockerSystem: true,
|
|
||||||
OperationDockerAgentPing: true,
|
|
||||||
OperationDockerAgentList: true,
|
|
||||||
OperationDockerAgentHostInfo: true,
|
|
||||||
OperationPortainerStackList: true,
|
|
||||||
OperationPortainerStackInspect: true,
|
|
||||||
OperationPortainerStackFile: true,
|
|
||||||
OperationPortainerWebhookList: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
if volumeBrowsingAuthorizations {
|
|
||||||
authorizations[OperationDockerAgentBrowseGet] = true
|
|
||||||
authorizations[OperationDockerAgentBrowseList] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return authorizations
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultPortainerAuthorizations returns the default Portainer authorizations used by non-admin users.
|
|
||||||
func DefaultPortainerAuthorizations() Authorizations {
|
|
||||||
return map[Authorization]bool{
|
|
||||||
OperationPortainerDockerHubInspect: true,
|
|
||||||
OperationPortainerEndpointGroupList: true,
|
|
||||||
OperationPortainerEndpointList: true,
|
|
||||||
OperationPortainerEndpointInspect: true,
|
|
||||||
OperationPortainerEndpointExtensionAdd: true,
|
|
||||||
OperationPortainerEndpointExtensionRemove: true,
|
|
||||||
OperationPortainerExtensionList: true,
|
|
||||||
OperationPortainerMOTD: true,
|
|
||||||
OperationPortainerRegistryList: true,
|
|
||||||
OperationPortainerRegistryInspect: true,
|
|
||||||
OperationPortainerTeamList: true,
|
|
||||||
OperationPortainerTemplateList: true,
|
|
||||||
OperationPortainerTemplateInspect: true,
|
|
||||||
OperationPortainerUserList: true,
|
|
||||||
OperationPortainerUserInspect: true,
|
|
||||||
OperationPortainerUserMemberships: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateVolumeBrowsingAuthorizations will update all the volume browsing authorizations for each role (except endpoint administrator)
|
|
||||||
// based on the specified removeAuthorizations parameter. If removeAuthorizations is set to true, all
|
|
||||||
// the authorizations will be dropped for the each role. If removeAuthorizations is set to false, the authorizations
|
|
||||||
// will be reset based for each role.
|
|
||||||
func (service AuthorizationService) UpdateVolumeBrowsingAuthorizations(remove bool) error {
|
|
||||||
roles, err := service.dataStore.Role().Roles()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, role := range roles {
|
|
||||||
// all roles except endpoint administrator
|
|
||||||
if role.ID != RoleID(1) {
|
|
||||||
updateRoleVolumeBrowsingAuthorizations(&role, remove)
|
|
||||||
|
|
||||||
err := service.dataStore.Role().UpdateRole(role.ID, &role)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateRoleVolumeBrowsingAuthorizations(role *Role, removeAuthorizations bool) {
|
|
||||||
if !removeAuthorizations {
|
|
||||||
delete(role.Authorizations, OperationDockerAgentBrowseDelete)
|
|
||||||
delete(role.Authorizations, OperationDockerAgentBrowseGet)
|
|
||||||
delete(role.Authorizations, OperationDockerAgentBrowseList)
|
|
||||||
delete(role.Authorizations, OperationDockerAgentBrowsePut)
|
|
||||||
delete(role.Authorizations, OperationDockerAgentBrowseRename)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
role.Authorizations[OperationDockerAgentBrowseGet] = true
|
|
||||||
role.Authorizations[OperationDockerAgentBrowseList] = true
|
|
||||||
|
|
||||||
// Standard-user
|
|
||||||
if role.ID == RoleID(3) {
|
|
||||||
role.Authorizations[OperationDockerAgentBrowseDelete] = true
|
|
||||||
role.Authorizations[OperationDockerAgentBrowsePut] = true
|
|
||||||
role.Authorizations[OperationDockerAgentBrowseRename] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveTeamAccessPolicies will remove all existing access policies associated to the specified team
|
|
||||||
func (service *AuthorizationService) RemoveTeamAccessPolicies(teamID TeamID) error {
|
|
||||||
endpoints, err := service.dataStore.Endpoint().Endpoints()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, endpoint := range endpoints {
|
|
||||||
for policyTeamID := range endpoint.TeamAccessPolicies {
|
|
||||||
if policyTeamID == teamID {
|
|
||||||
delete(endpoint.TeamAccessPolicies, policyTeamID)
|
|
||||||
|
|
||||||
err := service.dataStore.Endpoint().UpdateEndpoint(endpoint.ID, &endpoint)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
endpointGroups, err := service.dataStore.EndpointGroup().EndpointGroups()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, endpointGroup := range endpointGroups {
|
|
||||||
for policyTeamID := range endpointGroup.TeamAccessPolicies {
|
|
||||||
if policyTeamID == teamID {
|
|
||||||
delete(endpointGroup.TeamAccessPolicies, policyTeamID)
|
|
||||||
|
|
||||||
err := service.dataStore.EndpointGroup().UpdateEndpointGroup(endpointGroup.ID, &endpointGroup)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registries, err := service.dataStore.Registry().Registries()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, registry := range registries {
|
|
||||||
for policyTeamID := range registry.TeamAccessPolicies {
|
|
||||||
if policyTeamID == teamID {
|
|
||||||
delete(registry.TeamAccessPolicies, policyTeamID)
|
|
||||||
|
|
||||||
err := service.dataStore.Registry().UpdateRegistry(registry.ID, ®istry)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return service.UpdateUsersAuthorizations()
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveUserAccessPolicies will remove all existing access policies associated to the specified user
|
|
||||||
func (service *AuthorizationService) RemoveUserAccessPolicies(userID UserID) error {
|
|
||||||
endpoints, err := service.dataStore.Endpoint().Endpoints()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, endpoint := range endpoints {
|
|
||||||
for policyUserID := range endpoint.UserAccessPolicies {
|
|
||||||
if policyUserID == userID {
|
|
||||||
delete(endpoint.UserAccessPolicies, policyUserID)
|
|
||||||
|
|
||||||
err := service.dataStore.Endpoint().UpdateEndpoint(endpoint.ID, &endpoint)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
endpointGroups, err := service.dataStore.EndpointGroup().EndpointGroups()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, endpointGroup := range endpointGroups {
|
|
||||||
for policyUserID := range endpointGroup.UserAccessPolicies {
|
|
||||||
if policyUserID == userID {
|
|
||||||
delete(endpointGroup.UserAccessPolicies, policyUserID)
|
|
||||||
|
|
||||||
err := service.dataStore.EndpointGroup().UpdateEndpointGroup(endpointGroup.ID, &endpointGroup)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registries, err := service.dataStore.Registry().Registries()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, registry := range registries {
|
|
||||||
for policyUserID := range registry.UserAccessPolicies {
|
|
||||||
if policyUserID == userID {
|
|
||||||
delete(registry.UserAccessPolicies, policyUserID)
|
|
||||||
|
|
||||||
err := service.dataStore.Registry().UpdateRegistry(registry.ID, ®istry)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateUsersAuthorizations will trigger an update of the authorizations for all the users.
|
|
||||||
func (service *AuthorizationService) UpdateUsersAuthorizations() error {
|
|
||||||
users, err := service.dataStore.User().Users()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, user := range users {
|
|
||||||
err := service.updateUserAuthorizations(user.ID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (service *AuthorizationService) updateUserAuthorizations(userID UserID) error {
|
|
||||||
user, err := service.dataStore.User().User(userID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
endpointAuthorizations, err := service.getAuthorizations(user)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
user.EndpointAuthorizations = endpointAuthorizations
|
|
||||||
|
|
||||||
return service.dataStore.User().UpdateUser(userID, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (service *AuthorizationService) getAuthorizations(user *User) (EndpointAuthorizations, error) {
|
|
||||||
endpointAuthorizations := EndpointAuthorizations{}
|
|
||||||
if user.Role == AdministratorRole {
|
|
||||||
return endpointAuthorizations, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
userMemberships, err := service.dataStore.TeamMembership().TeamMembershipsByUserID(user.ID)
|
|
||||||
if err != nil {
|
|
||||||
return endpointAuthorizations, err
|
|
||||||
}
|
|
||||||
|
|
||||||
endpoints, err := service.dataStore.Endpoint().Endpoints()
|
|
||||||
if err != nil {
|
|
||||||
return endpointAuthorizations, err
|
|
||||||
}
|
|
||||||
|
|
||||||
endpointGroups, err := service.dataStore.EndpointGroup().EndpointGroups()
|
|
||||||
if err != nil {
|
|
||||||
return endpointAuthorizations, err
|
|
||||||
}
|
|
||||||
|
|
||||||
roles, err := service.dataStore.Role().Roles()
|
|
||||||
if err != nil {
|
|
||||||
return endpointAuthorizations, err
|
|
||||||
}
|
|
||||||
|
|
||||||
endpointAuthorizations = getUserEndpointAuthorizations(user, endpoints, endpointGroups, roles, userMemberships)
|
|
||||||
|
|
||||||
return endpointAuthorizations, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUserEndpointAuthorizations(user *User, endpoints []Endpoint, endpointGroups []EndpointGroup, roles []Role, userMemberships []TeamMembership) EndpointAuthorizations {
|
|
||||||
endpointAuthorizations := make(EndpointAuthorizations)
|
|
||||||
|
|
||||||
groupUserAccessPolicies := map[EndpointGroupID]UserAccessPolicies{}
|
|
||||||
groupTeamAccessPolicies := map[EndpointGroupID]TeamAccessPolicies{}
|
|
||||||
for _, endpointGroup := range endpointGroups {
|
|
||||||
groupUserAccessPolicies[endpointGroup.ID] = endpointGroup.UserAccessPolicies
|
|
||||||
groupTeamAccessPolicies[endpointGroup.ID] = endpointGroup.TeamAccessPolicies
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, endpoint := range endpoints {
|
|
||||||
authorizations := getAuthorizationsFromUserEndpointPolicy(user, &endpoint, roles)
|
|
||||||
if len(authorizations) > 0 {
|
|
||||||
endpointAuthorizations[endpoint.ID] = authorizations
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
authorizations = getAuthorizationsFromUserEndpointGroupPolicy(user, &endpoint, roles, groupUserAccessPolicies)
|
|
||||||
if len(authorizations) > 0 {
|
|
||||||
endpointAuthorizations[endpoint.ID] = authorizations
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
authorizations = getAuthorizationsFromTeamEndpointPolicies(userMemberships, &endpoint, roles)
|
|
||||||
if len(authorizations) > 0 {
|
|
||||||
endpointAuthorizations[endpoint.ID] = authorizations
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
authorizations = getAuthorizationsFromTeamEndpointGroupPolicies(userMemberships, &endpoint, roles, groupTeamAccessPolicies)
|
|
||||||
if len(authorizations) > 0 {
|
|
||||||
endpointAuthorizations[endpoint.ID] = authorizations
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return endpointAuthorizations
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAuthorizationsFromUserEndpointPolicy(user *User, endpoint *Endpoint, roles []Role) Authorizations {
|
|
||||||
policyRoles := make([]RoleID, 0)
|
|
||||||
|
|
||||||
policy, ok := endpoint.UserAccessPolicies[user.ID]
|
|
||||||
if ok {
|
|
||||||
policyRoles = append(policyRoles, policy.RoleID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return getAuthorizationsFromRoles(policyRoles, roles)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAuthorizationsFromUserEndpointGroupPolicy(user *User, endpoint *Endpoint, roles []Role, groupAccessPolicies map[EndpointGroupID]UserAccessPolicies) Authorizations {
|
|
||||||
policyRoles := make([]RoleID, 0)
|
|
||||||
|
|
||||||
policy, ok := groupAccessPolicies[endpoint.GroupID][user.ID]
|
|
||||||
if ok {
|
|
||||||
policyRoles = append(policyRoles, policy.RoleID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return getAuthorizationsFromRoles(policyRoles, roles)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAuthorizationsFromTeamEndpointPolicies(memberships []TeamMembership, endpoint *Endpoint, roles []Role) Authorizations {
|
|
||||||
policyRoles := make([]RoleID, 0)
|
|
||||||
|
|
||||||
for _, membership := range memberships {
|
|
||||||
policy, ok := endpoint.TeamAccessPolicies[membership.TeamID]
|
|
||||||
if ok {
|
|
||||||
policyRoles = append(policyRoles, policy.RoleID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return getAuthorizationsFromRoles(policyRoles, roles)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAuthorizationsFromTeamEndpointGroupPolicies(memberships []TeamMembership, endpoint *Endpoint, roles []Role, groupAccessPolicies map[EndpointGroupID]TeamAccessPolicies) Authorizations {
|
|
||||||
policyRoles := make([]RoleID, 0)
|
|
||||||
|
|
||||||
for _, membership := range memberships {
|
|
||||||
policy, ok := groupAccessPolicies[endpoint.GroupID][membership.TeamID]
|
|
||||||
if ok {
|
|
||||||
policyRoles = append(policyRoles, policy.RoleID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return getAuthorizationsFromRoles(policyRoles, roles)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAuthorizationsFromRoles(roleIdentifiers []RoleID, roles []Role) Authorizations {
|
|
||||||
var associatedRoles []Role
|
|
||||||
|
|
||||||
for _, id := range roleIdentifiers {
|
|
||||||
for _, role := range roles {
|
|
||||||
if role.ID == id {
|
|
||||||
associatedRoles = append(associatedRoles, role)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var authorizations Authorizations
|
|
||||||
highestPriority := 0
|
|
||||||
for _, role := range associatedRoles {
|
|
||||||
if role.Priority > highestPriority {
|
|
||||||
highestPriority = role.Priority
|
|
||||||
authorizations = role.Authorizations
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return authorizations
|
|
||||||
}
|
|
|
@ -28,6 +28,7 @@ import (
|
||||||
"github.com/portainer/portainer/api/bolt/user"
|
"github.com/portainer/portainer/api/bolt/user"
|
||||||
"github.com/portainer/portainer/api/bolt/version"
|
"github.com/portainer/portainer/api/bolt/version"
|
||||||
"github.com/portainer/portainer/api/bolt/webhook"
|
"github.com/portainer/portainer/api/bolt/webhook"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -143,7 +144,7 @@ func (store *Store) MigrateData() error {
|
||||||
UserService: store.UserService,
|
UserService: store.UserService,
|
||||||
VersionService: store.VersionService,
|
VersionService: store.VersionService,
|
||||||
FileService: store.fileService,
|
FileService: store.fileService,
|
||||||
AuthorizationService: portainer.NewAuthorizationService(store),
|
AuthorizationService: authorization.NewService(store),
|
||||||
}
|
}
|
||||||
migrator := migrator.NewMigrator(migratorParams)
|
migrator := migrator.NewMigrator(migratorParams)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package bolt
|
package bolt
|
||||||
|
|
||||||
import portainer "github.com/portainer/portainer/api"
|
import (
|
||||||
|
portainer "github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
|
)
|
||||||
|
|
||||||
// Init creates the default data set.
|
// Init creates the default data set.
|
||||||
func (store *Store) Init() error {
|
func (store *Store) Init() error {
|
||||||
|
@ -85,7 +88,7 @@ func (store *Store) Init() error {
|
||||||
Name: "Endpoint administrator",
|
Name: "Endpoint administrator",
|
||||||
Description: "Full control of all resources in an endpoint",
|
Description: "Full control of all resources in an endpoint",
|
||||||
Priority: 1,
|
Priority: 1,
|
||||||
Authorizations: portainer.DefaultEndpointAuthorizationsForEndpointAdministratorRole(),
|
Authorizations: authorization.DefaultEndpointAuthorizationsForEndpointAdministratorRole(),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = store.RoleService.CreateRole(environmentAdministratorRole)
|
err = store.RoleService.CreateRole(environmentAdministratorRole)
|
||||||
|
@ -97,7 +100,7 @@ func (store *Store) Init() error {
|
||||||
Name: "Helpdesk",
|
Name: "Helpdesk",
|
||||||
Description: "Read-only access of all resources in an endpoint",
|
Description: "Read-only access of all resources in an endpoint",
|
||||||
Priority: 2,
|
Priority: 2,
|
||||||
Authorizations: portainer.DefaultEndpointAuthorizationsForHelpDeskRole(false),
|
Authorizations: authorization.DefaultEndpointAuthorizationsForHelpDeskRole(false),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = store.RoleService.CreateRole(environmentReadOnlyUserRole)
|
err = store.RoleService.CreateRole(environmentReadOnlyUserRole)
|
||||||
|
@ -109,7 +112,7 @@ func (store *Store) Init() error {
|
||||||
Name: "Standard user",
|
Name: "Standard user",
|
||||||
Description: "Full control of assigned resources in an endpoint",
|
Description: "Full control of assigned resources in an endpoint",
|
||||||
Priority: 3,
|
Priority: 3,
|
||||||
Authorizations: portainer.DefaultEndpointAuthorizationsForStandardUserRole(false),
|
Authorizations: authorization.DefaultEndpointAuthorizationsForStandardUserRole(false),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = store.RoleService.CreateRole(standardUserRole)
|
err = store.RoleService.CreateRole(standardUserRole)
|
||||||
|
@ -121,7 +124,7 @@ func (store *Store) Init() error {
|
||||||
Name: "Read-only user",
|
Name: "Read-only user",
|
||||||
Description: "Read-only access of assigned resources in an endpoint",
|
Description: "Read-only access of assigned resources in an endpoint",
|
||||||
Priority: 4,
|
Priority: 4,
|
||||||
Authorizations: portainer.DefaultEndpointAuthorizationsForReadOnlyUserRole(false),
|
Authorizations: authorization.DefaultEndpointAuthorizationsForReadOnlyUserRole(false),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = store.RoleService.CreateRole(readOnlyUserRole)
|
err = store.RoleService.CreateRole(readOnlyUserRole)
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package migrator
|
package migrator
|
||||||
|
|
||||||
import portainer "github.com/portainer/portainer/api"
|
import (
|
||||||
|
portainer "github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
|
)
|
||||||
|
|
||||||
func (m *Migrator) updateResourceControlsToDBVersion22() error {
|
func (m *Migrator) updateResourceControlsToDBVersion22() error {
|
||||||
legacyResourceControls, err := m.resourceControlService.ResourceControls()
|
legacyResourceControls, err := m.resourceControlService.ResourceControls()
|
||||||
|
@ -32,7 +35,7 @@ func (m *Migrator) updateUsersAndRolesToDBVersion22() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, user := range legacyUsers {
|
for _, user := range legacyUsers {
|
||||||
user.PortainerAuthorizations = portainer.DefaultPortainerAuthorizations()
|
user.PortainerAuthorizations = authorization.DefaultPortainerAuthorizations()
|
||||||
err = m.userService.UpdateUser(user.ID, &user)
|
err = m.userService.UpdateUser(user.ID, &user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -44,7 +47,7 @@ func (m *Migrator) updateUsersAndRolesToDBVersion22() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
endpointAdministratorRole.Priority = 1
|
endpointAdministratorRole.Priority = 1
|
||||||
endpointAdministratorRole.Authorizations = portainer.DefaultEndpointAuthorizationsForEndpointAdministratorRole()
|
endpointAdministratorRole.Authorizations = authorization.DefaultEndpointAuthorizationsForEndpointAdministratorRole()
|
||||||
|
|
||||||
err = m.roleService.UpdateRole(endpointAdministratorRole.ID, endpointAdministratorRole)
|
err = m.roleService.UpdateRole(endpointAdministratorRole.ID, endpointAdministratorRole)
|
||||||
|
|
||||||
|
@ -53,7 +56,7 @@ func (m *Migrator) updateUsersAndRolesToDBVersion22() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
helpDeskRole.Priority = 2
|
helpDeskRole.Priority = 2
|
||||||
helpDeskRole.Authorizations = portainer.DefaultEndpointAuthorizationsForHelpDeskRole(settings.AllowVolumeBrowserForRegularUsers)
|
helpDeskRole.Authorizations = authorization.DefaultEndpointAuthorizationsForHelpDeskRole(settings.AllowVolumeBrowserForRegularUsers)
|
||||||
|
|
||||||
err = m.roleService.UpdateRole(helpDeskRole.ID, helpDeskRole)
|
err = m.roleService.UpdateRole(helpDeskRole.ID, helpDeskRole)
|
||||||
|
|
||||||
|
@ -62,7 +65,7 @@ func (m *Migrator) updateUsersAndRolesToDBVersion22() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
standardUserRole.Priority = 3
|
standardUserRole.Priority = 3
|
||||||
standardUserRole.Authorizations = portainer.DefaultEndpointAuthorizationsForStandardUserRole(settings.AllowVolumeBrowserForRegularUsers)
|
standardUserRole.Authorizations = authorization.DefaultEndpointAuthorizationsForStandardUserRole(settings.AllowVolumeBrowserForRegularUsers)
|
||||||
|
|
||||||
err = m.roleService.UpdateRole(standardUserRole.ID, standardUserRole)
|
err = m.roleService.UpdateRole(standardUserRole.ID, standardUserRole)
|
||||||
|
|
||||||
|
@ -71,7 +74,7 @@ func (m *Migrator) updateUsersAndRolesToDBVersion22() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
readOnlyUserRole.Priority = 4
|
readOnlyUserRole.Priority = 4
|
||||||
readOnlyUserRole.Authorizations = portainer.DefaultEndpointAuthorizationsForReadOnlyUserRole(settings.AllowVolumeBrowserForRegularUsers)
|
readOnlyUserRole.Authorizations = authorization.DefaultEndpointAuthorizationsForReadOnlyUserRole(settings.AllowVolumeBrowserForRegularUsers)
|
||||||
|
|
||||||
err = m.roleService.UpdateRole(readOnlyUserRole.ID, readOnlyUserRole)
|
err = m.roleService.UpdateRole(readOnlyUserRole.ID, readOnlyUserRole)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"github.com/portainer/portainer/api/bolt/teammembership"
|
"github.com/portainer/portainer/api/bolt/teammembership"
|
||||||
"github.com/portainer/portainer/api/bolt/user"
|
"github.com/portainer/portainer/api/bolt/user"
|
||||||
"github.com/portainer/portainer/api/bolt/version"
|
"github.com/portainer/portainer/api/bolt/version"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -39,7 +40,7 @@ type (
|
||||||
userService *user.Service
|
userService *user.Service
|
||||||
versionService *version.Service
|
versionService *version.Service
|
||||||
fileService portainer.FileService
|
fileService portainer.FileService
|
||||||
authorizationService *portainer.AuthorizationService
|
authorizationService *authorization.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parameters represents the required parameters to create a new Migrator instance.
|
// Parameters represents the required parameters to create a new Migrator instance.
|
||||||
|
@ -61,7 +62,7 @@ type (
|
||||||
UserService *user.Service
|
UserService *user.Service
|
||||||
VersionService *version.Service
|
VersionService *version.Service
|
||||||
FileService portainer.FileService
|
FileService portainer.FileService
|
||||||
AuthorizationService *portainer.AuthorizationService
|
AuthorizationService *authorization.Service
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/portainer/portainer/api/chisel"
|
"github.com/portainer/portainer/api/chisel"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
|
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/bolt"
|
"github.com/portainer/portainer/api/bolt"
|
||||||
|
@ -486,7 +487,7 @@ func main() {
|
||||||
Username: "admin",
|
Username: "admin",
|
||||||
Role: portainer.AdministratorRole,
|
Role: portainer.AdministratorRole,
|
||||||
Password: adminPasswordHash,
|
Password: adminPasswordHash,
|
||||||
PortainerAuthorizations: portainer.DefaultPortainerAuthorizations(),
|
PortainerAuthorizations: authorization.DefaultPortainerAuthorizations(),
|
||||||
}
|
}
|
||||||
err := dataStore.User().CreateUser(user)
|
err := dataStore.User().CreateUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
package portainer
|
|
||||||
|
|
||||||
// EdgeGroupRelatedEndpoints returns a list of endpoints related to this Edge group
|
|
||||||
func EdgeGroupRelatedEndpoints(edgeGroup *EdgeGroup, endpoints []Endpoint, endpointGroups []EndpointGroup) []EndpointID {
|
|
||||||
if !edgeGroup.Dynamic {
|
|
||||||
return edgeGroup.Endpoints
|
|
||||||
}
|
|
||||||
|
|
||||||
endpointIDs := []EndpointID{}
|
|
||||||
for _, endpoint := range endpoints {
|
|
||||||
if endpoint.Type != EdgeAgentEnvironment {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var endpointGroup EndpointGroup
|
|
||||||
for _, group := range endpointGroups {
|
|
||||||
if endpoint.GroupID == group.ID {
|
|
||||||
endpointGroup = group
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if edgeGroupRelatedToEndpoint(edgeGroup, &endpoint, &endpointGroup) {
|
|
||||||
endpointIDs = append(endpointIDs, endpoint.ID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return endpointIDs
|
|
||||||
}
|
|
||||||
|
|
||||||
// edgeGroupRelatedToEndpoint returns true is edgeGroup is associated with endpoint
|
|
||||||
func edgeGroupRelatedToEndpoint(edgeGroup *EdgeGroup, endpoint *Endpoint, endpointGroup *EndpointGroup) bool {
|
|
||||||
if !edgeGroup.Dynamic {
|
|
||||||
for _, endpointID := range edgeGroup.Endpoints {
|
|
||||||
if endpoint.ID == endpointID {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
endpointTags := TagSet(endpoint.TagIDs)
|
|
||||||
if endpointGroup.TagIDs != nil {
|
|
||||||
endpointTags = TagUnion(endpointTags, TagSet(endpointGroup.TagIDs))
|
|
||||||
}
|
|
||||||
edgeGroupTags := TagSet(edgeGroup.TagIDs)
|
|
||||||
|
|
||||||
if edgeGroup.PartialMatch {
|
|
||||||
intersection := TagIntersection(endpointTags, edgeGroupTags)
|
|
||||||
return len(intersection) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return TagContains(edgeGroupTags, endpointTags)
|
|
||||||
}
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
type authenticatePayload struct {
|
type authenticatePayload struct {
|
||||||
|
@ -101,7 +102,7 @@ func (handler *Handler) authenticateLDAPAndCreateUser(w http.ResponseWriter, use
|
||||||
user := &portainer.User{
|
user := &portainer.User{
|
||||||
Username: username,
|
Username: username,
|
||||||
Role: portainer.StandardUserRole,
|
Role: portainer.StandardUserRole,
|
||||||
PortainerAuthorizations: portainer.DefaultPortainerAuthorizations(),
|
PortainerAuthorizations: authorization.DefaultPortainerAuthorizations(),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.DataStore.User().CreateUser(user)
|
err = handler.DataStore.User().CreateUser(user)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -113,7 +114,7 @@ func (handler *Handler) validateOAuth(w http.ResponseWriter, r *http.Request) *h
|
||||||
user = &portainer.User{
|
user = &portainer.User{
|
||||||
Username: username,
|
Username: username,
|
||||||
Role: portainer.StandardUserRole,
|
Role: portainer.StandardUserRole,
|
||||||
PortainerAuthorizations: portainer.DefaultPortainerAuthorizations(),
|
PortainerAuthorizations: authorization.DefaultPortainerAuthorizations(),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.DataStore.User().CreateUser(user)
|
err = handler.DataStore.User().CreateUser(user)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/proxy"
|
"github.com/portainer/portainer/api/http/proxy"
|
||||||
"github.com/portainer/portainer/api/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler is the HTTP handler used to handle authentication operations.
|
// Handler is the HTTP handler used to handle authentication operations.
|
||||||
|
@ -18,7 +19,7 @@ type Handler struct {
|
||||||
JWTService portainer.JWTService
|
JWTService portainer.JWTService
|
||||||
LDAPService portainer.LDAPService
|
LDAPService portainer.LDAPService
|
||||||
ProxyManager *proxy.Manager
|
ProxyManager *proxy.Manager
|
||||||
AuthorizationService *portainer.AuthorizationService
|
AuthorizationService *authorization.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandler creates a handler to manage authentication operations.
|
// NewHandler creates a handler to manage authentication operations.
|
||||||
|
|
|
@ -7,7 +7,8 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
portainer "github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/internal/edge"
|
||||||
)
|
)
|
||||||
|
|
||||||
type edgeGroupUpdatePayload struct {
|
type edgeGroupUpdatePayload struct {
|
||||||
|
@ -73,7 +74,7 @@ func (handler *Handler) edgeGroupUpdate(w http.ResponseWriter, r *http.Request)
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve endpoint groups from database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve endpoint groups from database", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
oldRelatedEndpoints := portainer.EdgeGroupRelatedEndpoints(edgeGroup, endpoints, endpointGroups)
|
oldRelatedEndpoints := edge.EdgeGroupRelatedEndpoints(edgeGroup, endpoints, endpointGroups)
|
||||||
|
|
||||||
edgeGroup.Dynamic = payload.Dynamic
|
edgeGroup.Dynamic = payload.Dynamic
|
||||||
if edgeGroup.Dynamic {
|
if edgeGroup.Dynamic {
|
||||||
|
@ -102,7 +103,7 @@ func (handler *Handler) edgeGroupUpdate(w http.ResponseWriter, r *http.Request)
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist Edge group changes inside the database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist Edge group changes inside the database", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
newRelatedEndpoints := portainer.EdgeGroupRelatedEndpoints(edgeGroup, endpoints, endpointGroups)
|
newRelatedEndpoints := edge.EdgeGroupRelatedEndpoints(edgeGroup, endpoints, endpointGroups)
|
||||||
endpointsToUpdate := append(newRelatedEndpoints, oldRelatedEndpoints...)
|
endpointsToUpdate := append(newRelatedEndpoints, oldRelatedEndpoints...)
|
||||||
|
|
||||||
for _, endpointID := range endpointsToUpdate {
|
for _, endpointID := range endpointsToUpdate {
|
||||||
|
@ -143,7 +144,7 @@ func (handler *Handler) updateEndpoint(endpointID portainer.EndpointID) error {
|
||||||
|
|
||||||
edgeStackSet := map[portainer.EdgeStackID]bool{}
|
edgeStackSet := map[portainer.EdgeStackID]bool{}
|
||||||
|
|
||||||
endpointEdgeStacks := portainer.EndpointRelatedEdgeStacks(endpoint, endpointGroup, edgeGroups, edgeStacks)
|
endpointEdgeStacks := edge.EndpointRelatedEdgeStacks(endpoint, endpointGroup, edgeGroups, edgeStacks)
|
||||||
for _, edgeStackID := range endpointEdgeStacks {
|
for _, edgeStackID := range endpointEdgeStacks {
|
||||||
edgeStackSet[edgeStackID] = true
|
edgeStackSet[edgeStackID] = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/filesystem"
|
"github.com/portainer/portainer/api/filesystem"
|
||||||
|
"github.com/portainer/portainer/api/internal/edge"
|
||||||
)
|
)
|
||||||
|
|
||||||
// POST request on /api/endpoint_groups
|
// POST request on /api/endpoint_groups
|
||||||
|
@ -42,7 +43,7 @@ func (handler *Handler) edgeStackCreate(w http.ResponseWriter, r *http.Request)
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve edge groups from database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve edge groups from database", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
relatedEndpoints, err := portainer.EdgeStackRelatedEndpoints(edgeStack.EdgeGroups, endpoints, endpointGroups, edgeGroups)
|
relatedEndpoints, err := edge.EdgeStackRelatedEndpoints(edgeStack.EdgeGroups, endpoints, endpointGroups, edgeGroups)
|
||||||
|
|
||||||
for _, endpointID := range relatedEndpoints {
|
for _, endpointID := range relatedEndpoints {
|
||||||
relation, err := handler.DataStore.EndpointRelation().EndpointRelation(endpointID)
|
relation, err := handler.DataStore.EndpointRelation().EndpointRelation(endpointID)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/internal/edge"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (handler *Handler) edgeStackDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
func (handler *Handler) edgeStackDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||||
|
@ -42,7 +43,7 @@ func (handler *Handler) edgeStackDelete(w http.ResponseWriter, r *http.Request)
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve edge groups from database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve edge groups from database", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
relatedEndpoints, err := portainer.EdgeStackRelatedEndpoints(edgeStack.EdgeGroups, endpoints, endpointGroups, edgeGroups)
|
relatedEndpoints, err := edge.EdgeStackRelatedEndpoints(edgeStack.EdgeGroups, endpoints, endpointGroups, edgeGroups)
|
||||||
|
|
||||||
for _, endpointID := range relatedEndpoints {
|
for _, endpointID := range relatedEndpoints {
|
||||||
relation, err := handler.DataStore.EndpointRelation().EndpointRelation(endpointID)
|
relation, err := handler.DataStore.EndpointRelation().EndpointRelation(endpointID)
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/internal/edge"
|
||||||
)
|
)
|
||||||
|
|
||||||
type updateEdgeStackPayload struct {
|
type updateEdgeStackPayload struct {
|
||||||
|
@ -63,12 +64,12 @@ func (handler *Handler) edgeStackUpdate(w http.ResponseWriter, r *http.Request)
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve edge groups from database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve edge groups from database", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
oldRelated, err := portainer.EdgeStackRelatedEndpoints(stack.EdgeGroups, endpoints, endpointGroups, edgeGroups)
|
oldRelated, err := edge.EdgeStackRelatedEndpoints(stack.EdgeGroups, endpoints, endpointGroups, edgeGroups)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve edge stack related endpoints from database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve edge stack related endpoints from database", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
newRelated, err := portainer.EdgeStackRelatedEndpoints(payload.EdgeGroups, endpoints, endpointGroups, edgeGroups)
|
newRelated, err := edge.EdgeStackRelatedEndpoints(payload.EdgeGroups, endpoints, endpointGroups, edgeGroups)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve edge stack related endpoints from database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve edge stack related endpoints from database", err}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/internal/tag"
|
||||||
)
|
)
|
||||||
|
|
||||||
type endpointGroupUpdatePayload struct {
|
type endpointGroupUpdatePayload struct {
|
||||||
|
@ -52,14 +53,14 @@ func (handler *Handler) endpointGroupUpdate(w http.ResponseWriter, r *http.Reque
|
||||||
|
|
||||||
tagsChanged := false
|
tagsChanged := false
|
||||||
if payload.TagIDs != nil {
|
if payload.TagIDs != nil {
|
||||||
payloadTagSet := portainer.TagSet(payload.TagIDs)
|
payloadTagSet := tag.Set(payload.TagIDs)
|
||||||
endpointGroupTagSet := portainer.TagSet((endpointGroup.TagIDs))
|
endpointGroupTagSet := tag.Set((endpointGroup.TagIDs))
|
||||||
union := portainer.TagUnion(payloadTagSet, endpointGroupTagSet)
|
union := tag.Union(payloadTagSet, endpointGroupTagSet)
|
||||||
intersection := portainer.TagIntersection(payloadTagSet, endpointGroupTagSet)
|
intersection := tag.Intersection(payloadTagSet, endpointGroupTagSet)
|
||||||
tagsChanged = len(union) > len(intersection)
|
tagsChanged = len(union) > len(intersection)
|
||||||
|
|
||||||
if tagsChanged {
|
if tagsChanged {
|
||||||
removeTags := portainer.TagDifference(endpointGroupTagSet, payloadTagSet)
|
removeTags := tag.Difference(endpointGroupTagSet, payloadTagSet)
|
||||||
|
|
||||||
for tagID := range removeTags {
|
for tagID := range removeTags {
|
||||||
tag, err := handler.DataStore.Tag().Tag(tagID)
|
tag, err := handler.DataStore.Tag().Tag(tagID)
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package endpointgroups
|
package endpointgroups
|
||||||
|
|
||||||
import portainer "github.com/portainer/portainer/api"
|
import (
|
||||||
|
portainer "github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/internal/edge"
|
||||||
|
)
|
||||||
|
|
||||||
func (handler *Handler) updateEndpointRelations(endpoint *portainer.Endpoint, endpointGroup *portainer.EndpointGroup) error {
|
func (handler *Handler) updateEndpointRelations(endpoint *portainer.Endpoint, endpointGroup *portainer.EndpointGroup) error {
|
||||||
if endpoint.Type != portainer.EdgeAgentEnvironment {
|
if endpoint.Type != portainer.EdgeAgentEnvironment {
|
||||||
|
@ -31,7 +34,7 @@ func (handler *Handler) updateEndpointRelations(endpoint *portainer.Endpoint, en
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
endpointStacks := portainer.EndpointRelatedEdgeStacks(endpoint, endpointGroup, edgeGroups, edgeStacks)
|
endpointStacks := edge.EndpointRelatedEdgeStacks(endpoint, endpointGroup, edgeGroups, edgeStacks)
|
||||||
stacksSet := map[portainer.EdgeStackID]bool{}
|
stacksSet := map[portainer.EdgeStackID]bool{}
|
||||||
for _, edgeStackID := range endpointStacks {
|
for _, edgeStackID := range endpointStacks {
|
||||||
stacksSet[edgeStackID] = true
|
stacksSet[edgeStackID] = true
|
||||||
|
|
|
@ -7,13 +7,14 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler is the HTTP handler used to handle endpoint group operations.
|
// Handler is the HTTP handler used to handle endpoint group operations.
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
*mux.Router
|
*mux.Router
|
||||||
DataStore portainer.DataStore
|
DataStore portainer.DataStore
|
||||||
AuthorizationService *portainer.AuthorizationService
|
AuthorizationService *authorization.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandler creates a handler to manage endpoint group operations.
|
// NewHandler creates a handler to manage endpoint group operations.
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/crypto"
|
"github.com/portainer/portainer/api/crypto"
|
||||||
"github.com/portainer/portainer/api/http/client"
|
"github.com/portainer/portainer/api/http/client"
|
||||||
|
"github.com/portainer/portainer/api/internal/edge"
|
||||||
)
|
)
|
||||||
|
|
||||||
type endpointCreatePayload struct {
|
type endpointCreatePayload struct {
|
||||||
|
@ -167,7 +168,7 @@ func (handler *Handler) endpointCreate(w http.ResponseWriter, r *http.Request) *
|
||||||
}
|
}
|
||||||
|
|
||||||
if endpoint.Type == portainer.EdgeAgentEnvironment {
|
if endpoint.Type == portainer.EdgeAgentEnvironment {
|
||||||
relatedEdgeStacks := portainer.EndpointRelatedEdgeStacks(endpoint, endpointGroup, edgeGroups, edgeStacks)
|
relatedEdgeStacks := edge.EndpointRelatedEdgeStacks(endpoint, endpointGroup, edgeGroups, edgeStacks)
|
||||||
for _, stackID := range relatedEdgeStacks {
|
for _, stackID := range relatedEdgeStacks {
|
||||||
relationObject.EdgeStacks[stackID] = true
|
relationObject.EdgeStacks[stackID] = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ import (
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/client"
|
"github.com/portainer/portainer/api/http/client"
|
||||||
|
"github.com/portainer/portainer/api/internal/edge"
|
||||||
|
"github.com/portainer/portainer/api/internal/tag"
|
||||||
)
|
)
|
||||||
|
|
||||||
type endpointUpdatePayload struct {
|
type endpointUpdatePayload struct {
|
||||||
|
@ -79,14 +81,14 @@ func (handler *Handler) endpointUpdate(w http.ResponseWriter, r *http.Request) *
|
||||||
|
|
||||||
tagsChanged := false
|
tagsChanged := false
|
||||||
if payload.TagIDs != nil {
|
if payload.TagIDs != nil {
|
||||||
payloadTagSet := portainer.TagSet(payload.TagIDs)
|
payloadTagSet := tag.Set(payload.TagIDs)
|
||||||
endpointTagSet := portainer.TagSet((endpoint.TagIDs))
|
endpointTagSet := tag.Set((endpoint.TagIDs))
|
||||||
union := portainer.TagUnion(payloadTagSet, endpointTagSet)
|
union := tag.Union(payloadTagSet, endpointTagSet)
|
||||||
intersection := portainer.TagIntersection(payloadTagSet, endpointTagSet)
|
intersection := tag.Intersection(payloadTagSet, endpointTagSet)
|
||||||
tagsChanged = len(union) > len(intersection)
|
tagsChanged = len(union) > len(intersection)
|
||||||
|
|
||||||
if tagsChanged {
|
if tagsChanged {
|
||||||
removeTags := portainer.TagDifference(endpointTagSet, payloadTagSet)
|
removeTags := tag.Difference(endpointTagSet, payloadTagSet)
|
||||||
|
|
||||||
for tagID := range removeTags {
|
for tagID := range removeTags {
|
||||||
tag, err := handler.DataStore.Tag().Tag(tagID)
|
tag, err := handler.DataStore.Tag().Tag(tagID)
|
||||||
|
@ -248,7 +250,7 @@ func (handler *Handler) endpointUpdate(w http.ResponseWriter, r *http.Request) *
|
||||||
|
|
||||||
edgeStackSet := map[portainer.EdgeStackID]bool{}
|
edgeStackSet := map[portainer.EdgeStackID]bool{}
|
||||||
|
|
||||||
endpointEdgeStacks := portainer.EndpointRelatedEdgeStacks(endpoint, endpointGroup, edgeGroups, edgeStacks)
|
endpointEdgeStacks := edge.EndpointRelatedEdgeStacks(endpoint, endpointGroup, edgeGroups, edgeStacks)
|
||||||
for _, edgeStackID := range endpointEdgeStacks {
|
for _, edgeStackID := range endpointEdgeStacks {
|
||||||
edgeStackSet[edgeStackID] = true
|
edgeStackSet[edgeStackID] = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/proxy"
|
"github.com/portainer/portainer/api/http/proxy"
|
||||||
"github.com/portainer/portainer/api/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ type Handler struct {
|
||||||
*mux.Router
|
*mux.Router
|
||||||
requestBouncer *security.RequestBouncer
|
requestBouncer *security.RequestBouncer
|
||||||
DataStore portainer.DataStore
|
DataStore portainer.DataStore
|
||||||
AuthorizationService *portainer.AuthorizationService
|
AuthorizationService *authorization.Service
|
||||||
FileService portainer.FileService
|
FileService portainer.FileService
|
||||||
JobService portainer.JobService
|
JobService portainer.JobService
|
||||||
ProxyManager *proxy.Manager
|
ProxyManager *proxy.Manager
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler is the HTTP handler used to handle extension operations.
|
// Handler is the HTTP handler used to handle extension operations.
|
||||||
|
@ -16,7 +17,7 @@ type Handler struct {
|
||||||
*mux.Router
|
*mux.Router
|
||||||
DataStore portainer.DataStore
|
DataStore portainer.DataStore
|
||||||
ExtensionManager portainer.ExtensionManager
|
ExtensionManager portainer.ExtensionManager
|
||||||
AuthorizationService *portainer.AuthorizationService
|
AuthorizationService *authorization.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandler creates a handler to manage extension operations.
|
// NewHandler creates a handler to manage extension operations.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package settings
|
package settings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
@ -17,7 +18,7 @@ func hideFields(settings *portainer.Settings) {
|
||||||
// Handler is the HTTP handler used to handle settings operations.
|
// Handler is the HTTP handler used to handle settings operations.
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
*mux.Router
|
*mux.Router
|
||||||
AuthorizationService *portainer.AuthorizationService
|
AuthorizationService *authorization.Service
|
||||||
DataStore portainer.DataStore
|
DataStore portainer.DataStore
|
||||||
FileService portainer.FileService
|
FileService portainer.FileService
|
||||||
JobScheduler portainer.JobScheduler
|
JobScheduler portainer.JobScheduler
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler is the HTTP handler used to handle stack operations.
|
// Handler is the HTTP handler used to handle stack operations.
|
||||||
|
@ -58,7 +59,7 @@ func (handler *Handler) userCanAccessStack(securityContext *security.RestrictedR
|
||||||
userTeamIDs = append(userTeamIDs, membership.TeamID)
|
userTeamIDs = append(userTeamIDs, membership.TeamID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if resourceControl != nil && portainer.UserCanAccessResource(securityContext.UserID, userTeamIDs, resourceControl) {
|
if resourceControl != nil && authorization.UserCanAccessResource(securityContext.UserID, userTeamIDs, resourceControl) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (handler *Handler) cleanUp(stack *portainer.Stack, doCleanUp *bool) error {
|
func (handler *Handler) cleanUp(stack *portainer.Stack, doCleanUp *bool) error {
|
||||||
|
@ -133,7 +134,7 @@ func (handler *Handler) isValidStackFile(stackFileContent []byte) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *Handler) decorateStackResponse(w http.ResponseWriter, stack *portainer.Stack, userID portainer.UserID) *httperror.HandlerError {
|
func (handler *Handler) decorateStackResponse(w http.ResponseWriter, stack *portainer.Stack, userID portainer.UserID) *httperror.HandlerError {
|
||||||
resourceControl := portainer.NewPrivateResourceControl(stack.Name, portainer.StackResourceControl, userID)
|
resourceControl := authorization.NewPrivateResourceControl(stack.Name, portainer.StackResourceControl, userID)
|
||||||
|
|
||||||
err := handler.DataStore.ResourceControl().CreateResourceControl(resourceControl)
|
err := handler.DataStore.ResourceControl().CreateResourceControl(resourceControl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stackListOperationFilters struct {
|
type stackListOperationFilters struct {
|
||||||
|
@ -39,7 +40,7 @@ func (handler *Handler) stackList(w http.ResponseWriter, r *http.Request) *httpe
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve info from request context", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve info from request context", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
stacks = portainer.DecorateStacks(stacks, resourceControls)
|
stacks = authorization.DecorateStacks(stacks, resourceControls)
|
||||||
|
|
||||||
if !securityContext.IsAdmin {
|
if !securityContext.IsAdmin {
|
||||||
rbacExtensionEnabled := true
|
rbacExtensionEnabled := true
|
||||||
|
@ -60,7 +61,7 @@ func (handler *Handler) stackList(w http.ResponseWriter, r *http.Request) *httpe
|
||||||
userTeamIDs = append(userTeamIDs, membership.TeamID)
|
userTeamIDs = append(userTeamIDs, membership.TeamID)
|
||||||
}
|
}
|
||||||
|
|
||||||
stacks = portainer.FilterAuthorizedStacks(stacks, user, userTeamIDs, rbacExtensionEnabled)
|
stacks = authorization.FilterAuthorizedStacks(stacks, user, userTeamIDs, rbacExtensionEnabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.JSON(w, stacks)
|
return response.JSON(w, stacks)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/internal/edge"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DELETE request on /api/tags/:id
|
// DELETE request on /api/tags/:id
|
||||||
|
@ -111,7 +112,7 @@ func (handler *Handler) updateEndpointRelations(endpoint portainer.Endpoint, edg
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
endpointStacks := portainer.EndpointRelatedEdgeStacks(&endpoint, endpointGroup, edgeGroups, edgeStacks)
|
endpointStacks := edge.EndpointRelatedEdgeStacks(&endpoint, endpointGroup, edgeGroups, edgeStacks)
|
||||||
stacksSet := map[portainer.EdgeStackID]bool{}
|
stacksSet := map[portainer.EdgeStackID]bool{}
|
||||||
for _, edgeStackID := range endpointStacks {
|
for _, edgeStackID := range endpointStacks {
|
||||||
stacksSet[edgeStackID] = true
|
stacksSet[edgeStackID] = true
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -14,7 +15,7 @@ import (
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
*mux.Router
|
*mux.Router
|
||||||
DataStore portainer.DataStore
|
DataStore portainer.DataStore
|
||||||
AuthorizationService *portainer.AuthorizationService
|
AuthorizationService *authorization.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandler creates a handler to manage team membership operations.
|
// NewHandler creates a handler to manage team membership operations.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package teams
|
package teams
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
@ -13,7 +14,7 @@ import (
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
*mux.Router
|
*mux.Router
|
||||||
DataStore portainer.DataStore
|
DataStore portainer.DataStore
|
||||||
AuthorizationService *portainer.AuthorizationService
|
AuthorizationService *authorization.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandler creates a handler to manage team operations.
|
// NewHandler creates a handler to manage team operations.
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
type adminInitPayload struct {
|
type adminInitPayload struct {
|
||||||
|
@ -45,7 +46,7 @@ func (handler *Handler) adminInit(w http.ResponseWriter, r *http.Request) *httpe
|
||||||
user := &portainer.User{
|
user := &portainer.User{
|
||||||
Username: payload.Username,
|
Username: payload.Username,
|
||||||
Role: portainer.AdministratorRole,
|
Role: portainer.AdministratorRole,
|
||||||
PortainerAuthorizations: portainer.DefaultPortainerAuthorizations(),
|
PortainerAuthorizations: authorization.DefaultPortainerAuthorizations(),
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Password, err = handler.CryptoService.Hash(payload.Password)
|
user.Password, err = handler.CryptoService.Hash(payload.Password)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ type Handler struct {
|
||||||
*mux.Router
|
*mux.Router
|
||||||
DataStore portainer.DataStore
|
DataStore portainer.DataStore
|
||||||
CryptoService portainer.CryptoService
|
CryptoService portainer.CryptoService
|
||||||
AuthorizationService *portainer.AuthorizationService
|
AuthorizationService *authorization.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandler creates a handler to manage user operations.
|
// NewHandler creates a handler to manage user operations.
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
type userCreatePayload struct {
|
type userCreatePayload struct {
|
||||||
|
@ -60,7 +61,7 @@ func (handler *Handler) userCreate(w http.ResponseWriter, r *http.Request) *http
|
||||||
user = &portainer.User{
|
user = &portainer.User{
|
||||||
Username: payload.Username,
|
Username: payload.Username,
|
||||||
Role: portainer.UserRole(payload.Role),
|
Role: portainer.UserRole(payload.Role),
|
||||||
PortainerAuthorizations: portainer.DefaultPortainerAuthorizations(),
|
PortainerAuthorizations: authorization.DefaultPortainerAuthorizations(),
|
||||||
}
|
}
|
||||||
|
|
||||||
settings, err := handler.DataStore.Settings().Settings()
|
settings, err := handler.DataStore.Settings().Settings()
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
|
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
@ -30,7 +31,7 @@ type (
|
||||||
|
|
||||||
func (transport *Transport) newResourceControlFromPortainerLabels(labelsObject map[string]interface{}, resourceID string, resourceType portainer.ResourceControlType) (*portainer.ResourceControl, error) {
|
func (transport *Transport) newResourceControlFromPortainerLabels(labelsObject map[string]interface{}, resourceID string, resourceType portainer.ResourceControlType) (*portainer.ResourceControl, error) {
|
||||||
if labelsObject[resourceLabelForPortainerPublicResourceControl] != nil {
|
if labelsObject[resourceLabelForPortainerPublicResourceControl] != nil {
|
||||||
resourceControl := portainer.NewPublicResourceControl(resourceID, resourceType)
|
resourceControl := authorization.NewPublicResourceControl(resourceID, resourceType)
|
||||||
|
|
||||||
err := transport.dataStore.ResourceControl().CreateResourceControl(resourceControl)
|
err := transport.dataStore.ResourceControl().CreateResourceControl(resourceControl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -76,7 +77,7 @@ func (transport *Transport) newResourceControlFromPortainerLabels(labelsObject m
|
||||||
userIDs = append(userIDs, user.ID)
|
userIDs = append(userIDs, user.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
resourceControl := portainer.NewRestrictedResourceControl(resourceID, resourceType, userIDs, teamIDs)
|
resourceControl := authorization.NewRestrictedResourceControl(resourceID, resourceType, userIDs, teamIDs)
|
||||||
|
|
||||||
err := transport.dataStore.ResourceControl().CreateResourceControl(resourceControl)
|
err := transport.dataStore.ResourceControl().CreateResourceControl(resourceControl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -90,7 +91,7 @@ func (transport *Transport) newResourceControlFromPortainerLabels(labelsObject m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (transport *Transport) createPrivateResourceControl(resourceIdentifier string, resourceType portainer.ResourceControlType, userID portainer.UserID) (*portainer.ResourceControl, error) {
|
func (transport *Transport) createPrivateResourceControl(resourceIdentifier string, resourceType portainer.ResourceControlType, userID portainer.UserID) (*portainer.ResourceControl, error) {
|
||||||
resourceControl := portainer.NewPrivateResourceControl(resourceIdentifier, resourceType, userID)
|
resourceControl := authorization.NewPrivateResourceControl(resourceIdentifier, resourceType, userID)
|
||||||
|
|
||||||
err := transport.dataStore.ResourceControl().CreateResourceControl(resourceControl)
|
err := transport.dataStore.ResourceControl().CreateResourceControl(resourceControl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -158,7 +159,7 @@ func (transport *Transport) applyAccessControlOnResource(parameters *resourceOpe
|
||||||
return responseutils.RewriteResponse(response, responseObject, http.StatusOK)
|
return responseutils.RewriteResponse(response, responseObject, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
if executor.operationContext.isAdmin || executor.operationContext.endpointResourceAccess || (resourceControl != nil && portainer.UserCanAccessResource(executor.operationContext.userID, executor.operationContext.userTeamIDs, resourceControl)) {
|
if executor.operationContext.isAdmin || executor.operationContext.endpointResourceAccess || (resourceControl != nil && authorization.UserCanAccessResource(executor.operationContext.userID, executor.operationContext.userTeamIDs, resourceControl)) {
|
||||||
responseObject = decorateObject(responseObject, resourceControl)
|
responseObject = decorateObject(responseObject, resourceControl)
|
||||||
return responseutils.RewriteResponse(response, responseObject, http.StatusOK)
|
return responseutils.RewriteResponse(response, responseObject, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
@ -246,7 +247,7 @@ func (transport *Transport) filterResourceList(parameters *resourceOperationPara
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.isAdmin || context.endpointResourceAccess || portainer.UserCanAccessResource(context.userID, context.userTeamIDs, resourceControl) {
|
if context.isAdmin || context.endpointResourceAccess || authorization.UserCanAccessResource(context.userID, context.userTeamIDs, resourceControl) {
|
||||||
resourceObject = decorateObject(resourceObject, resourceControl)
|
resourceObject = decorateObject(resourceObject, resourceControl)
|
||||||
filteredResourceData = append(filteredResourceData, resourceObject)
|
filteredResourceData = append(filteredResourceData, resourceObject)
|
||||||
}
|
}
|
||||||
|
@ -256,7 +257,7 @@ func (transport *Transport) filterResourceList(parameters *resourceOperationPara
|
||||||
}
|
}
|
||||||
|
|
||||||
func (transport *Transport) findResourceControl(resourceIdentifier string, resourceType portainer.ResourceControlType, resourceLabelsObject map[string]interface{}, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
|
func (transport *Transport) findResourceControl(resourceIdentifier string, resourceType portainer.ResourceControlType, resourceLabelsObject map[string]interface{}, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
|
||||||
resourceControl := portainer.GetResourceControlByResourceIDAndType(resourceIdentifier, resourceType, resourceControls)
|
resourceControl := authorization.GetResourceControlByResourceIDAndType(resourceIdentifier, resourceType, resourceControls)
|
||||||
if resourceControl != nil {
|
if resourceControl != nil {
|
||||||
return resourceControl, nil
|
return resourceControl, nil
|
||||||
}
|
}
|
||||||
|
@ -264,7 +265,7 @@ func (transport *Transport) findResourceControl(resourceIdentifier string, resou
|
||||||
if resourceLabelsObject != nil {
|
if resourceLabelsObject != nil {
|
||||||
if resourceLabelsObject[resourceLabelForDockerServiceID] != nil {
|
if resourceLabelsObject[resourceLabelForDockerServiceID] != nil {
|
||||||
inheritedServiceIdentifier := resourceLabelsObject[resourceLabelForDockerServiceID].(string)
|
inheritedServiceIdentifier := resourceLabelsObject[resourceLabelForDockerServiceID].(string)
|
||||||
resourceControl = portainer.GetResourceControlByResourceIDAndType(inheritedServiceIdentifier, portainer.ServiceResourceControl, resourceControls)
|
resourceControl = authorization.GetResourceControlByResourceIDAndType(inheritedServiceIdentifier, portainer.ServiceResourceControl, resourceControls)
|
||||||
|
|
||||||
if resourceControl != nil {
|
if resourceControl != nil {
|
||||||
return resourceControl, nil
|
return resourceControl, nil
|
||||||
|
@ -273,7 +274,7 @@ func (transport *Transport) findResourceControl(resourceIdentifier string, resou
|
||||||
|
|
||||||
if resourceLabelsObject[resourceLabelForDockerSwarmStackName] != nil {
|
if resourceLabelsObject[resourceLabelForDockerSwarmStackName] != nil {
|
||||||
inheritedSwarmStackIdentifier := resourceLabelsObject[resourceLabelForDockerSwarmStackName].(string)
|
inheritedSwarmStackIdentifier := resourceLabelsObject[resourceLabelForDockerSwarmStackName].(string)
|
||||||
resourceControl = portainer.GetResourceControlByResourceIDAndType(inheritedSwarmStackIdentifier, portainer.StackResourceControl, resourceControls)
|
resourceControl = authorization.GetResourceControlByResourceIDAndType(inheritedSwarmStackIdentifier, portainer.StackResourceControl, resourceControls)
|
||||||
|
|
||||||
if resourceControl != nil {
|
if resourceControl != nil {
|
||||||
return resourceControl, nil
|
return resourceControl, nil
|
||||||
|
@ -282,7 +283,7 @@ func (transport *Transport) findResourceControl(resourceIdentifier string, resou
|
||||||
|
|
||||||
if resourceLabelsObject[resourceLabelForDockerComposeStackName] != nil {
|
if resourceLabelsObject[resourceLabelForDockerComposeStackName] != nil {
|
||||||
inheritedComposeStackIdentifier := resourceLabelsObject[resourceLabelForDockerComposeStackName].(string)
|
inheritedComposeStackIdentifier := resourceLabelsObject[resourceLabelForDockerComposeStackName].(string)
|
||||||
resourceControl = portainer.GetResourceControlByResourceIDAndType(inheritedComposeStackIdentifier, portainer.StackResourceControl, resourceControls)
|
resourceControl = authorization.GetResourceControlByResourceIDAndType(inheritedComposeStackIdentifier, portainer.StackResourceControl, resourceControls)
|
||||||
|
|
||||||
if resourceControl != nil {
|
if resourceControl != nil {
|
||||||
return resourceControl, nil
|
return resourceControl, nil
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
portainer "github.com/portainer/portainer/api"
|
portainer "github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -22,7 +23,7 @@ func getInheritedResourceControlFromConfigLabels(dockerClient *client.Client, co
|
||||||
|
|
||||||
swarmStackName := config.Spec.Labels[resourceLabelForDockerSwarmStackName]
|
swarmStackName := config.Spec.Labels[resourceLabelForDockerSwarmStackName]
|
||||||
if swarmStackName != "" {
|
if swarmStackName != "" {
|
||||||
return portainer.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
|
return authorization.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
portainer "github.com/portainer/portainer/api"
|
portainer "github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -21,7 +22,7 @@ func getInheritedResourceControlFromContainerLabels(dockerClient *client.Client,
|
||||||
|
|
||||||
serviceName := container.Config.Labels[resourceLabelForDockerServiceID]
|
serviceName := container.Config.Labels[resourceLabelForDockerServiceID]
|
||||||
if serviceName != "" {
|
if serviceName != "" {
|
||||||
serviceResourceControl := portainer.GetResourceControlByResourceIDAndType(serviceName, portainer.ServiceResourceControl, resourceControls)
|
serviceResourceControl := authorization.GetResourceControlByResourceIDAndType(serviceName, portainer.ServiceResourceControl, resourceControls)
|
||||||
if serviceResourceControl != nil {
|
if serviceResourceControl != nil {
|
||||||
return serviceResourceControl, nil
|
return serviceResourceControl, nil
|
||||||
}
|
}
|
||||||
|
@ -29,12 +30,12 @@ func getInheritedResourceControlFromContainerLabels(dockerClient *client.Client,
|
||||||
|
|
||||||
swarmStackName := container.Config.Labels[resourceLabelForDockerSwarmStackName]
|
swarmStackName := container.Config.Labels[resourceLabelForDockerSwarmStackName]
|
||||||
if swarmStackName != "" {
|
if swarmStackName != "" {
|
||||||
return portainer.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
|
return authorization.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
composeStackName := container.Config.Labels[resourceLabelForDockerComposeStackName]
|
composeStackName := container.Config.Labels[resourceLabelForDockerComposeStackName]
|
||||||
if composeStackName != "" {
|
if composeStackName != "" {
|
||||||
return portainer.GetResourceControlByResourceIDAndType(composeStackName, portainer.StackResourceControl, resourceControls), nil
|
return authorization.GetResourceControlByResourceIDAndType(composeStackName, portainer.StackResourceControl, resourceControls), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -25,7 +26,7 @@ func getInheritedResourceControlFromNetworkLabels(dockerClient *client.Client, n
|
||||||
|
|
||||||
swarmStackName := network.Labels[resourceLabelForDockerSwarmStackName]
|
swarmStackName := network.Labels[resourceLabelForDockerSwarmStackName]
|
||||||
if swarmStackName != "" {
|
if swarmStackName != "" {
|
||||||
return portainer.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
|
return authorization.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -85,7 +86,7 @@ func findSystemNetworkResourceControl(networkObject map[string]interface{}) *por
|
||||||
networkName := networkObject[networkObjectName].(string)
|
networkName := networkObject[networkObjectName].(string)
|
||||||
|
|
||||||
if networkName == "bridge" || networkName == "host" || networkName == "none" {
|
if networkName == "bridge" || networkName == "host" || networkName == "none" {
|
||||||
return portainer.NewSystemResourceControl(networkID, portainer.NetworkResourceControl)
|
return authorization.NewSystemResourceControl(networkID, portainer.NetworkResourceControl)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
portainer "github.com/portainer/portainer/api"
|
portainer "github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -22,7 +23,7 @@ func getInheritedResourceControlFromSecretLabels(dockerClient *client.Client, se
|
||||||
|
|
||||||
swarmStackName := secret.Spec.Labels[resourceLabelForDockerSwarmStackName]
|
swarmStackName := secret.Spec.Labels[resourceLabelForDockerSwarmStackName]
|
||||||
if swarmStackName != "" {
|
if swarmStackName != "" {
|
||||||
return portainer.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
|
return authorization.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -23,7 +24,7 @@ func getInheritedResourceControlFromServiceLabels(dockerClient *client.Client, s
|
||||||
|
|
||||||
swarmStackName := service.Spec.Labels[resourceLabelForDockerSwarmStackName]
|
swarmStackName := service.Spec.Labels[resourceLabelForDockerSwarmStackName]
|
||||||
if swarmStackName != "" {
|
if swarmStackName != "" {
|
||||||
return portainer.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
|
return authorization.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -10,12 +10,12 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/portainer/portainer/api/docker"
|
|
||||||
|
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
portainer "github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/docker"
|
||||||
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
||||||
"github.com/portainer/portainer/api/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
var apiVersionRe = regexp.MustCompile(`(/v[0-9]\.[0-9]*)?`)
|
var apiVersionRe = regexp.MustCompile(`(/v[0-9]\.[0-9]*)?`)
|
||||||
|
@ -462,7 +462,7 @@ func (transport *Transport) restrictedResourceOperation(request *http.Request, r
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resourceControl := portainer.GetResourceControlByResourceIDAndType(resourceID, resourceType, resourceControls)
|
resourceControl := authorization.GetResourceControlByResourceIDAndType(resourceID, resourceType, resourceControls)
|
||||||
if resourceControl == nil {
|
if resourceControl == nil {
|
||||||
agentTargetHeader := request.Header.Get(portainer.PortainerAgentTargetHeader)
|
agentTargetHeader := request.Header.Get(portainer.PortainerAgentTargetHeader)
|
||||||
|
|
||||||
|
@ -473,12 +473,12 @@ func (transport *Transport) restrictedResourceOperation(request *http.Request, r
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if inheritedResourceControl == nil || !portainer.UserCanAccessResource(tokenData.ID, userTeamIDs, inheritedResourceControl) {
|
if inheritedResourceControl == nil || !authorization.UserCanAccessResource(tokenData.ID, userTeamIDs, inheritedResourceControl) {
|
||||||
return responseutils.WriteAccessDeniedResponse()
|
return responseutils.WriteAccessDeniedResponse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if resourceControl != nil && !portainer.UserCanAccessResource(tokenData.ID, userTeamIDs, resourceControl) {
|
if resourceControl != nil && !authorization.UserCanAccessResource(tokenData.ID, userTeamIDs, resourceControl) {
|
||||||
return responseutils.WriteAccessDeniedResponse()
|
return responseutils.WriteAccessDeniedResponse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,10 @@ import (
|
||||||
|
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
|
||||||
portainer "github.com/portainer/portainer/api"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
||||||
"github.com/portainer/portainer/api/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -24,7 +25,7 @@ func getInheritedResourceControlFromVolumeLabels(dockerClient *client.Client, vo
|
||||||
|
|
||||||
swarmStackName := volume.Labels[resourceLabelForDockerSwarmStackName]
|
swarmStackName := volume.Labels[resourceLabelForDockerSwarmStackName]
|
||||||
if swarmStackName != "" {
|
if swarmStackName != "" {
|
||||||
return portainer.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
|
return authorization.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -38,6 +38,7 @@ import (
|
||||||
"github.com/portainer/portainer/api/http/handler/websocket"
|
"github.com/portainer/portainer/api/http/handler/websocket"
|
||||||
"github.com/portainer/portainer/api/http/proxy"
|
"github.com/portainer/portainer/api/http/proxy"
|
||||||
"github.com/portainer/portainer/api/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
"github.com/portainer/portainer/api/internal/authorization"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -73,7 +74,7 @@ type Server struct {
|
||||||
func (server *Server) Start() error {
|
func (server *Server) Start() error {
|
||||||
proxyManager := proxy.NewManager(server.DataStore, server.SignatureService, server.ReverseTunnelService, server.DockerClientFactory)
|
proxyManager := proxy.NewManager(server.DataStore, server.SignatureService, server.ReverseTunnelService, server.DockerClientFactory)
|
||||||
|
|
||||||
authorizationService := portainer.NewAuthorizationService(server.DataStore)
|
authorizationService := authorization.NewService(server.DataStore)
|
||||||
|
|
||||||
rbacExtensionURL := proxyManager.GetExtensionURL(portainer.RBACExtension)
|
rbacExtensionURL := proxyManager.GetExtensionURL(portainer.RBACExtension)
|
||||||
requestBouncer := security.NewRequestBouncer(server.DataStore, server.JWTService, rbacExtensionURL)
|
requestBouncer := security.NewRequestBouncer(server.DataStore, server.JWTService, rbacExtensionURL)
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
package portainer
|
package authorization
|
||||||
|
|
||||||
|
import "github.com/portainer/portainer/api"
|
||||||
|
|
||||||
// NewPrivateResourceControl will create a new private resource control associated to the resource specified by the
|
// NewPrivateResourceControl will create a new private resource control associated to the resource specified by the
|
||||||
// identifier and type parameters. It automatically assigns it to the user specified by the userID parameter.
|
// identifier and type parameters. It automatically assigns it to the user specified by the userID parameter.
|
||||||
func NewPrivateResourceControl(resourceIdentifier string, resourceType ResourceControlType, userID UserID) *ResourceControl {
|
func NewPrivateResourceControl(resourceIdentifier string, resourceType portainer.ResourceControlType, userID portainer.UserID) *portainer.ResourceControl {
|
||||||
return &ResourceControl{
|
return &portainer.ResourceControl{
|
||||||
Type: resourceType,
|
Type: resourceType,
|
||||||
ResourceID: resourceIdentifier,
|
ResourceID: resourceIdentifier,
|
||||||
SubResourceIDs: []string{},
|
SubResourceIDs: []string{},
|
||||||
UserAccesses: []UserResourceAccess{
|
UserAccesses: []portainer.UserResourceAccess{
|
||||||
{
|
{
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
AccessLevel: ReadWriteAccessLevel,
|
AccessLevel: portainer.ReadWriteAccessLevel,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
TeamAccesses: []TeamResourceAccess{},
|
TeamAccesses: []portainer.TeamResourceAccess{},
|
||||||
AdministratorsOnly: false,
|
AdministratorsOnly: false,
|
||||||
Public: false,
|
Public: false,
|
||||||
System: false,
|
System: false,
|
||||||
|
@ -22,13 +24,13 @@ func NewPrivateResourceControl(resourceIdentifier string, resourceType ResourceC
|
||||||
|
|
||||||
// NewSystemResourceControl will create a new public resource control with the System flag set to true.
|
// NewSystemResourceControl will create a new public resource control with the System flag set to true.
|
||||||
// These kind of resource control are not persisted and are created on the fly by the Portainer API.
|
// These kind of resource control are not persisted and are created on the fly by the Portainer API.
|
||||||
func NewSystemResourceControl(resourceIdentifier string, resourceType ResourceControlType) *ResourceControl {
|
func NewSystemResourceControl(resourceIdentifier string, resourceType portainer.ResourceControlType) *portainer.ResourceControl {
|
||||||
return &ResourceControl{
|
return &portainer.ResourceControl{
|
||||||
Type: resourceType,
|
Type: resourceType,
|
||||||
ResourceID: resourceIdentifier,
|
ResourceID: resourceIdentifier,
|
||||||
SubResourceIDs: []string{},
|
SubResourceIDs: []string{},
|
||||||
UserAccesses: []UserResourceAccess{},
|
UserAccesses: []portainer.UserResourceAccess{},
|
||||||
TeamAccesses: []TeamResourceAccess{},
|
TeamAccesses: []portainer.TeamResourceAccess{},
|
||||||
AdministratorsOnly: false,
|
AdministratorsOnly: false,
|
||||||
Public: true,
|
Public: true,
|
||||||
System: true,
|
System: true,
|
||||||
|
@ -36,13 +38,13 @@ func NewSystemResourceControl(resourceIdentifier string, resourceType ResourceCo
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPublicResourceControl will create a new public resource control.
|
// NewPublicResourceControl will create a new public resource control.
|
||||||
func NewPublicResourceControl(resourceIdentifier string, resourceType ResourceControlType) *ResourceControl {
|
func NewPublicResourceControl(resourceIdentifier string, resourceType portainer.ResourceControlType) *portainer.ResourceControl {
|
||||||
return &ResourceControl{
|
return &portainer.ResourceControl{
|
||||||
Type: resourceType,
|
Type: resourceType,
|
||||||
ResourceID: resourceIdentifier,
|
ResourceID: resourceIdentifier,
|
||||||
SubResourceIDs: []string{},
|
SubResourceIDs: []string{},
|
||||||
UserAccesses: []UserResourceAccess{},
|
UserAccesses: []portainer.UserResourceAccess{},
|
||||||
TeamAccesses: []TeamResourceAccess{},
|
TeamAccesses: []portainer.TeamResourceAccess{},
|
||||||
AdministratorsOnly: false,
|
AdministratorsOnly: false,
|
||||||
Public: true,
|
Public: true,
|
||||||
System: false,
|
System: false,
|
||||||
|
@ -50,29 +52,29 @@ func NewPublicResourceControl(resourceIdentifier string, resourceType ResourceCo
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRestrictedResourceControl will create a new resource control with user and team accesses restrictions.
|
// NewRestrictedResourceControl will create a new resource control with user and team accesses restrictions.
|
||||||
func NewRestrictedResourceControl(resourceIdentifier string, resourceType ResourceControlType, userIDs []UserID, teamIDs []TeamID) *ResourceControl {
|
func NewRestrictedResourceControl(resourceIdentifier string, resourceType portainer.ResourceControlType, userIDs []portainer.UserID, teamIDs []portainer.TeamID) *portainer.ResourceControl {
|
||||||
userAccesses := make([]UserResourceAccess, 0)
|
userAccesses := make([]portainer.UserResourceAccess, 0)
|
||||||
teamAccesses := make([]TeamResourceAccess, 0)
|
teamAccesses := make([]portainer.TeamResourceAccess, 0)
|
||||||
|
|
||||||
for _, id := range userIDs {
|
for _, id := range userIDs {
|
||||||
access := UserResourceAccess{
|
access := portainer.UserResourceAccess{
|
||||||
UserID: id,
|
UserID: id,
|
||||||
AccessLevel: ReadWriteAccessLevel,
|
AccessLevel: portainer.ReadWriteAccessLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
userAccesses = append(userAccesses, access)
|
userAccesses = append(userAccesses, access)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, id := range teamIDs {
|
for _, id := range teamIDs {
|
||||||
access := TeamResourceAccess{
|
access := portainer.TeamResourceAccess{
|
||||||
TeamID: id,
|
TeamID: id,
|
||||||
AccessLevel: ReadWriteAccessLevel,
|
AccessLevel: portainer.ReadWriteAccessLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
teamAccesses = append(teamAccesses, access)
|
teamAccesses = append(teamAccesses, access)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ResourceControl{
|
return &portainer.ResourceControl{
|
||||||
Type: resourceType,
|
Type: resourceType,
|
||||||
ResourceID: resourceIdentifier,
|
ResourceID: resourceIdentifier,
|
||||||
SubResourceIDs: []string{},
|
SubResourceIDs: []string{},
|
||||||
|
@ -86,10 +88,10 @@ func NewRestrictedResourceControl(resourceIdentifier string, resourceType Resour
|
||||||
|
|
||||||
// DecorateStacks will iterate through a list of stacks, check for an associated resource control for each
|
// DecorateStacks will iterate through a list of stacks, check for an associated resource control for each
|
||||||
// stack and decorate the stack element if a resource control is found.
|
// stack and decorate the stack element if a resource control is found.
|
||||||
func DecorateStacks(stacks []Stack, resourceControls []ResourceControl) []Stack {
|
func DecorateStacks(stacks []portainer.Stack, resourceControls []portainer.ResourceControl) []portainer.Stack {
|
||||||
for idx, stack := range stacks {
|
for idx, stack := range stacks {
|
||||||
|
|
||||||
resourceControl := GetResourceControlByResourceIDAndType(stack.Name, StackResourceControl, resourceControls)
|
resourceControl := GetResourceControlByResourceIDAndType(stack.Name, portainer.StackResourceControl, resourceControls)
|
||||||
if resourceControl != nil {
|
if resourceControl != nil {
|
||||||
stacks[idx].ResourceControl = resourceControl
|
stacks[idx].ResourceControl = resourceControl
|
||||||
}
|
}
|
||||||
|
@ -99,11 +101,11 @@ func DecorateStacks(stacks []Stack, resourceControls []ResourceControl) []Stack
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterAuthorizedStacks returns a list of decorated stacks filtered through resource control access checks.
|
// FilterAuthorizedStacks returns a list of decorated stacks filtered through resource control access checks.
|
||||||
func FilterAuthorizedStacks(stacks []Stack, user *User, userTeamIDs []TeamID, rbacEnabled bool) []Stack {
|
func FilterAuthorizedStacks(stacks []portainer.Stack, user *portainer.User, userTeamIDs []portainer.TeamID, rbacEnabled bool) []portainer.Stack {
|
||||||
authorizedStacks := make([]Stack, 0)
|
authorizedStacks := make([]portainer.Stack, 0)
|
||||||
|
|
||||||
for _, stack := range stacks {
|
for _, stack := range stacks {
|
||||||
_, ok := user.EndpointAuthorizations[stack.EndpointID][EndpointResourcesAccess]
|
_, ok := user.EndpointAuthorizations[stack.EndpointID][portainer.EndpointResourcesAccess]
|
||||||
if rbacEnabled && ok {
|
if rbacEnabled && ok {
|
||||||
authorizedStacks = append(authorizedStacks, stack)
|
authorizedStacks = append(authorizedStacks, stack)
|
||||||
continue
|
continue
|
||||||
|
@ -119,7 +121,7 @@ func FilterAuthorizedStacks(stacks []Stack, user *User, userTeamIDs []TeamID, rb
|
||||||
|
|
||||||
// UserCanAccessResource will valide that a user has permissions defined in the specified resource control
|
// UserCanAccessResource will valide that a user has permissions defined in the specified resource control
|
||||||
// based on its identifier and the team(s) he is part of.
|
// based on its identifier and the team(s) he is part of.
|
||||||
func UserCanAccessResource(userID UserID, userTeamIDs []TeamID, resourceControl *ResourceControl) bool {
|
func UserCanAccessResource(userID portainer.UserID, userTeamIDs []portainer.TeamID, resourceControl *portainer.ResourceControl) bool {
|
||||||
for _, authorizedUserAccess := range resourceControl.UserAccesses {
|
for _, authorizedUserAccess := range resourceControl.UserAccesses {
|
||||||
if userID == authorizedUserAccess.UserID {
|
if userID == authorizedUserAccess.UserID {
|
||||||
return true
|
return true
|
||||||
|
@ -139,7 +141,7 @@ func UserCanAccessResource(userID UserID, userTeamIDs []TeamID, resourceControl
|
||||||
|
|
||||||
// GetResourceControlByResourceIDAndType retrieves the first matching resource control in a set of resource controls
|
// GetResourceControlByResourceIDAndType retrieves the first matching resource control in a set of resource controls
|
||||||
// based on the specified id and resource type parameters.
|
// based on the specified id and resource type parameters.
|
||||||
func GetResourceControlByResourceIDAndType(resourceID string, resourceType ResourceControlType, resourceControls []ResourceControl) *ResourceControl {
|
func GetResourceControlByResourceIDAndType(resourceID string, resourceType portainer.ResourceControlType, resourceControls []portainer.ResourceControl) *portainer.ResourceControl {
|
||||||
for _, resourceControl := range resourceControls {
|
for _, resourceControl := range resourceControls {
|
||||||
if resourceID == resourceControl.ResourceID && resourceType == resourceControl.Type {
|
if resourceID == resourceControl.ResourceID && resourceType == resourceControl.Type {
|
||||||
return &resourceControl
|
return &resourceControl
|
|
@ -0,0 +1,776 @@
|
||||||
|
package authorization
|
||||||
|
|
||||||
|
import "github.com/portainer/portainer/api"
|
||||||
|
|
||||||
|
// Service represents a service used to
|
||||||
|
// update authorizations associated to a user or team.
|
||||||
|
type Service struct {
|
||||||
|
dataStore portainer.DataStore
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewService returns a point to a new Service instance.
|
||||||
|
func NewService(dataStore portainer.DataStore) *Service {
|
||||||
|
return &Service{
|
||||||
|
dataStore: dataStore,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultEndpointAuthorizationsForEndpointAdministratorRole returns the default endpoint authorizations
|
||||||
|
// associated to the endpoint administrator role.
|
||||||
|
func DefaultEndpointAuthorizationsForEndpointAdministratorRole() portainer.Authorizations {
|
||||||
|
return map[portainer.Authorization]bool{
|
||||||
|
portainer.OperationDockerContainerArchiveInfo: true,
|
||||||
|
portainer.OperationDockerContainerList: true,
|
||||||
|
portainer.OperationDockerContainerExport: true,
|
||||||
|
portainer.OperationDockerContainerChanges: true,
|
||||||
|
portainer.OperationDockerContainerInspect: true,
|
||||||
|
portainer.OperationDockerContainerTop: true,
|
||||||
|
portainer.OperationDockerContainerLogs: true,
|
||||||
|
portainer.OperationDockerContainerStats: true,
|
||||||
|
portainer.OperationDockerContainerAttachWebsocket: true,
|
||||||
|
portainer.OperationDockerContainerArchive: true,
|
||||||
|
portainer.OperationDockerContainerCreate: true,
|
||||||
|
portainer.OperationDockerContainerPrune: true,
|
||||||
|
portainer.OperationDockerContainerKill: true,
|
||||||
|
portainer.OperationDockerContainerPause: true,
|
||||||
|
portainer.OperationDockerContainerUnpause: true,
|
||||||
|
portainer.OperationDockerContainerRestart: true,
|
||||||
|
portainer.OperationDockerContainerStart: true,
|
||||||
|
portainer.OperationDockerContainerStop: true,
|
||||||
|
portainer.OperationDockerContainerWait: true,
|
||||||
|
portainer.OperationDockerContainerResize: true,
|
||||||
|
portainer.OperationDockerContainerAttach: true,
|
||||||
|
portainer.OperationDockerContainerExec: true,
|
||||||
|
portainer.OperationDockerContainerRename: true,
|
||||||
|
portainer.OperationDockerContainerUpdate: true,
|
||||||
|
portainer.OperationDockerContainerPutContainerArchive: true,
|
||||||
|
portainer.OperationDockerContainerDelete: true,
|
||||||
|
portainer.OperationDockerImageList: true,
|
||||||
|
portainer.OperationDockerImageSearch: true,
|
||||||
|
portainer.OperationDockerImageGetAll: true,
|
||||||
|
portainer.OperationDockerImageGet: true,
|
||||||
|
portainer.OperationDockerImageHistory: true,
|
||||||
|
portainer.OperationDockerImageInspect: true,
|
||||||
|
portainer.OperationDockerImageLoad: true,
|
||||||
|
portainer.OperationDockerImageCreate: true,
|
||||||
|
portainer.OperationDockerImagePrune: true,
|
||||||
|
portainer.OperationDockerImagePush: true,
|
||||||
|
portainer.OperationDockerImageTag: true,
|
||||||
|
portainer.OperationDockerImageDelete: true,
|
||||||
|
portainer.OperationDockerImageCommit: true,
|
||||||
|
portainer.OperationDockerImageBuild: true,
|
||||||
|
portainer.OperationDockerNetworkList: true,
|
||||||
|
portainer.OperationDockerNetworkInspect: true,
|
||||||
|
portainer.OperationDockerNetworkCreate: true,
|
||||||
|
portainer.OperationDockerNetworkConnect: true,
|
||||||
|
portainer.OperationDockerNetworkDisconnect: true,
|
||||||
|
portainer.OperationDockerNetworkPrune: true,
|
||||||
|
portainer.OperationDockerNetworkDelete: true,
|
||||||
|
portainer.OperationDockerVolumeList: true,
|
||||||
|
portainer.OperationDockerVolumeInspect: true,
|
||||||
|
portainer.OperationDockerVolumeCreate: true,
|
||||||
|
portainer.OperationDockerVolumePrune: true,
|
||||||
|
portainer.OperationDockerVolumeDelete: true,
|
||||||
|
portainer.OperationDockerExecInspect: true,
|
||||||
|
portainer.OperationDockerExecStart: true,
|
||||||
|
portainer.OperationDockerExecResize: true,
|
||||||
|
portainer.OperationDockerSwarmInspect: true,
|
||||||
|
portainer.OperationDockerSwarmUnlockKey: true,
|
||||||
|
portainer.OperationDockerSwarmInit: true,
|
||||||
|
portainer.OperationDockerSwarmJoin: true,
|
||||||
|
portainer.OperationDockerSwarmLeave: true,
|
||||||
|
portainer.OperationDockerSwarmUpdate: true,
|
||||||
|
portainer.OperationDockerSwarmUnlock: true,
|
||||||
|
portainer.OperationDockerNodeList: true,
|
||||||
|
portainer.OperationDockerNodeInspect: true,
|
||||||
|
portainer.OperationDockerNodeUpdate: true,
|
||||||
|
portainer.OperationDockerNodeDelete: true,
|
||||||
|
portainer.OperationDockerServiceList: true,
|
||||||
|
portainer.OperationDockerServiceInspect: true,
|
||||||
|
portainer.OperationDockerServiceLogs: true,
|
||||||
|
portainer.OperationDockerServiceCreate: true,
|
||||||
|
portainer.OperationDockerServiceUpdate: true,
|
||||||
|
portainer.OperationDockerServiceDelete: true,
|
||||||
|
portainer.OperationDockerSecretList: true,
|
||||||
|
portainer.OperationDockerSecretInspect: true,
|
||||||
|
portainer.OperationDockerSecretCreate: true,
|
||||||
|
portainer.OperationDockerSecretUpdate: true,
|
||||||
|
portainer.OperationDockerSecretDelete: true,
|
||||||
|
portainer.OperationDockerConfigList: true,
|
||||||
|
portainer.OperationDockerConfigInspect: true,
|
||||||
|
portainer.OperationDockerConfigCreate: true,
|
||||||
|
portainer.OperationDockerConfigUpdate: true,
|
||||||
|
portainer.OperationDockerConfigDelete: true,
|
||||||
|
portainer.OperationDockerTaskList: true,
|
||||||
|
portainer.OperationDockerTaskInspect: true,
|
||||||
|
portainer.OperationDockerTaskLogs: true,
|
||||||
|
portainer.OperationDockerPluginList: true,
|
||||||
|
portainer.OperationDockerPluginPrivileges: true,
|
||||||
|
portainer.OperationDockerPluginInspect: true,
|
||||||
|
portainer.OperationDockerPluginPull: true,
|
||||||
|
portainer.OperationDockerPluginCreate: true,
|
||||||
|
portainer.OperationDockerPluginEnable: true,
|
||||||
|
portainer.OperationDockerPluginDisable: true,
|
||||||
|
portainer.OperationDockerPluginPush: true,
|
||||||
|
portainer.OperationDockerPluginUpgrade: true,
|
||||||
|
portainer.OperationDockerPluginSet: true,
|
||||||
|
portainer.OperationDockerPluginDelete: true,
|
||||||
|
portainer.OperationDockerSessionStart: true,
|
||||||
|
portainer.OperationDockerDistributionInspect: true,
|
||||||
|
portainer.OperationDockerBuildPrune: true,
|
||||||
|
portainer.OperationDockerBuildCancel: true,
|
||||||
|
portainer.OperationDockerPing: true,
|
||||||
|
portainer.OperationDockerInfo: true,
|
||||||
|
portainer.OperationDockerVersion: true,
|
||||||
|
portainer.OperationDockerEvents: true,
|
||||||
|
portainer.OperationDockerSystem: true,
|
||||||
|
portainer.OperationDockerUndefined: true,
|
||||||
|
portainer.OperationDockerAgentPing: true,
|
||||||
|
portainer.OperationDockerAgentList: true,
|
||||||
|
portainer.OperationDockerAgentHostInfo: true,
|
||||||
|
portainer.OperationDockerAgentBrowseDelete: true,
|
||||||
|
portainer.OperationDockerAgentBrowseGet: true,
|
||||||
|
portainer.OperationDockerAgentBrowseList: true,
|
||||||
|
portainer.OperationDockerAgentBrowsePut: true,
|
||||||
|
portainer.OperationDockerAgentBrowseRename: true,
|
||||||
|
portainer.OperationDockerAgentUndefined: true,
|
||||||
|
portainer.OperationPortainerResourceControlCreate: true,
|
||||||
|
portainer.OperationPortainerResourceControlUpdate: true,
|
||||||
|
portainer.OperationPortainerStackList: true,
|
||||||
|
portainer.OperationPortainerStackInspect: true,
|
||||||
|
portainer.OperationPortainerStackFile: true,
|
||||||
|
portainer.OperationPortainerStackCreate: true,
|
||||||
|
portainer.OperationPortainerStackMigrate: true,
|
||||||
|
portainer.OperationPortainerStackUpdate: true,
|
||||||
|
portainer.OperationPortainerStackDelete: true,
|
||||||
|
portainer.OperationPortainerWebsocketExec: true,
|
||||||
|
portainer.OperationPortainerWebhookList: true,
|
||||||
|
portainer.OperationPortainerWebhookCreate: true,
|
||||||
|
portainer.OperationPortainerWebhookDelete: true,
|
||||||
|
portainer.OperationIntegrationStoridgeAdmin: true,
|
||||||
|
portainer.EndpointResourcesAccess: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultEndpointAuthorizationsForHelpDeskRole returns the default endpoint authorizations
|
||||||
|
// associated to the helpdesk role.
|
||||||
|
func DefaultEndpointAuthorizationsForHelpDeskRole(volumeBrowsingAuthorizations bool) portainer.Authorizations {
|
||||||
|
authorizations := map[portainer.Authorization]bool{
|
||||||
|
portainer.OperationDockerContainerArchiveInfo: true,
|
||||||
|
portainer.OperationDockerContainerList: true,
|
||||||
|
portainer.OperationDockerContainerChanges: true,
|
||||||
|
portainer.OperationDockerContainerInspect: true,
|
||||||
|
portainer.OperationDockerContainerTop: true,
|
||||||
|
portainer.OperationDockerContainerLogs: true,
|
||||||
|
portainer.OperationDockerContainerStats: true,
|
||||||
|
portainer.OperationDockerImageList: true,
|
||||||
|
portainer.OperationDockerImageSearch: true,
|
||||||
|
portainer.OperationDockerImageGetAll: true,
|
||||||
|
portainer.OperationDockerImageGet: true,
|
||||||
|
portainer.OperationDockerImageHistory: true,
|
||||||
|
portainer.OperationDockerImageInspect: true,
|
||||||
|
portainer.OperationDockerNetworkList: true,
|
||||||
|
portainer.OperationDockerNetworkInspect: true,
|
||||||
|
portainer.OperationDockerVolumeList: true,
|
||||||
|
portainer.OperationDockerVolumeInspect: true,
|
||||||
|
portainer.OperationDockerSwarmInspect: true,
|
||||||
|
portainer.OperationDockerNodeList: true,
|
||||||
|
portainer.OperationDockerNodeInspect: true,
|
||||||
|
portainer.OperationDockerServiceList: true,
|
||||||
|
portainer.OperationDockerServiceInspect: true,
|
||||||
|
portainer.OperationDockerServiceLogs: true,
|
||||||
|
portainer.OperationDockerSecretList: true,
|
||||||
|
portainer.OperationDockerSecretInspect: true,
|
||||||
|
portainer.OperationDockerConfigList: true,
|
||||||
|
portainer.OperationDockerConfigInspect: true,
|
||||||
|
portainer.OperationDockerTaskList: true,
|
||||||
|
portainer.OperationDockerTaskInspect: true,
|
||||||
|
portainer.OperationDockerTaskLogs: true,
|
||||||
|
portainer.OperationDockerPluginList: true,
|
||||||
|
portainer.OperationDockerDistributionInspect: true,
|
||||||
|
portainer.OperationDockerPing: true,
|
||||||
|
portainer.OperationDockerInfo: true,
|
||||||
|
portainer.OperationDockerVersion: true,
|
||||||
|
portainer.OperationDockerEvents: true,
|
||||||
|
portainer.OperationDockerSystem: true,
|
||||||
|
portainer.OperationDockerAgentPing: true,
|
||||||
|
portainer.OperationDockerAgentList: true,
|
||||||
|
portainer.OperationDockerAgentHostInfo: true,
|
||||||
|
portainer.OperationPortainerStackList: true,
|
||||||
|
portainer.OperationPortainerStackInspect: true,
|
||||||
|
portainer.OperationPortainerStackFile: true,
|
||||||
|
portainer.OperationPortainerWebhookList: true,
|
||||||
|
portainer.EndpointResourcesAccess: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
if volumeBrowsingAuthorizations {
|
||||||
|
authorizations[portainer.OperationDockerAgentBrowseGet] = true
|
||||||
|
authorizations[portainer.OperationDockerAgentBrowseList] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return authorizations
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultEndpointAuthorizationsForStandardUserRole returns the default endpoint authorizations
|
||||||
|
// associated to the standard user role.
|
||||||
|
func DefaultEndpointAuthorizationsForStandardUserRole(volumeBrowsingAuthorizations bool) portainer.Authorizations {
|
||||||
|
authorizations := map[portainer.Authorization]bool{
|
||||||
|
portainer.OperationDockerContainerArchiveInfo: true,
|
||||||
|
portainer.OperationDockerContainerList: true,
|
||||||
|
portainer.OperationDockerContainerExport: true,
|
||||||
|
portainer.OperationDockerContainerChanges: true,
|
||||||
|
portainer.OperationDockerContainerInspect: true,
|
||||||
|
portainer.OperationDockerContainerTop: true,
|
||||||
|
portainer.OperationDockerContainerLogs: true,
|
||||||
|
portainer.OperationDockerContainerStats: true,
|
||||||
|
portainer.OperationDockerContainerAttachWebsocket: true,
|
||||||
|
portainer.OperationDockerContainerArchive: true,
|
||||||
|
portainer.OperationDockerContainerCreate: true,
|
||||||
|
portainer.OperationDockerContainerKill: true,
|
||||||
|
portainer.OperationDockerContainerPause: true,
|
||||||
|
portainer.OperationDockerContainerUnpause: true,
|
||||||
|
portainer.OperationDockerContainerRestart: true,
|
||||||
|
portainer.OperationDockerContainerStart: true,
|
||||||
|
portainer.OperationDockerContainerStop: true,
|
||||||
|
portainer.OperationDockerContainerWait: true,
|
||||||
|
portainer.OperationDockerContainerResize: true,
|
||||||
|
portainer.OperationDockerContainerAttach: true,
|
||||||
|
portainer.OperationDockerContainerExec: true,
|
||||||
|
portainer.OperationDockerContainerRename: true,
|
||||||
|
portainer.OperationDockerContainerUpdate: true,
|
||||||
|
portainer.OperationDockerContainerPutContainerArchive: true,
|
||||||
|
portainer.OperationDockerContainerDelete: true,
|
||||||
|
portainer.OperationDockerImageList: true,
|
||||||
|
portainer.OperationDockerImageSearch: true,
|
||||||
|
portainer.OperationDockerImageGetAll: true,
|
||||||
|
portainer.OperationDockerImageGet: true,
|
||||||
|
portainer.OperationDockerImageHistory: true,
|
||||||
|
portainer.OperationDockerImageInspect: true,
|
||||||
|
portainer.OperationDockerImageLoad: true,
|
||||||
|
portainer.OperationDockerImageCreate: true,
|
||||||
|
portainer.OperationDockerImagePush: true,
|
||||||
|
portainer.OperationDockerImageTag: true,
|
||||||
|
portainer.OperationDockerImageDelete: true,
|
||||||
|
portainer.OperationDockerImageCommit: true,
|
||||||
|
portainer.OperationDockerImageBuild: true,
|
||||||
|
portainer.OperationDockerNetworkList: true,
|
||||||
|
portainer.OperationDockerNetworkInspect: true,
|
||||||
|
portainer.OperationDockerNetworkCreate: true,
|
||||||
|
portainer.OperationDockerNetworkConnect: true,
|
||||||
|
portainer.OperationDockerNetworkDisconnect: true,
|
||||||
|
portainer.OperationDockerNetworkDelete: true,
|
||||||
|
portainer.OperationDockerVolumeList: true,
|
||||||
|
portainer.OperationDockerVolumeInspect: true,
|
||||||
|
portainer.OperationDockerVolumeCreate: true,
|
||||||
|
portainer.OperationDockerVolumeDelete: true,
|
||||||
|
portainer.OperationDockerExecInspect: true,
|
||||||
|
portainer.OperationDockerExecStart: true,
|
||||||
|
portainer.OperationDockerExecResize: true,
|
||||||
|
portainer.OperationDockerSwarmInspect: true,
|
||||||
|
portainer.OperationDockerSwarmUnlockKey: true,
|
||||||
|
portainer.OperationDockerSwarmInit: true,
|
||||||
|
portainer.OperationDockerSwarmJoin: true,
|
||||||
|
portainer.OperationDockerSwarmLeave: true,
|
||||||
|
portainer.OperationDockerSwarmUpdate: true,
|
||||||
|
portainer.OperationDockerSwarmUnlock: true,
|
||||||
|
portainer.OperationDockerNodeList: true,
|
||||||
|
portainer.OperationDockerNodeInspect: true,
|
||||||
|
portainer.OperationDockerNodeUpdate: true,
|
||||||
|
portainer.OperationDockerNodeDelete: true,
|
||||||
|
portainer.OperationDockerServiceList: true,
|
||||||
|
portainer.OperationDockerServiceInspect: true,
|
||||||
|
portainer.OperationDockerServiceLogs: true,
|
||||||
|
portainer.OperationDockerServiceCreate: true,
|
||||||
|
portainer.OperationDockerServiceUpdate: true,
|
||||||
|
portainer.OperationDockerServiceDelete: true,
|
||||||
|
portainer.OperationDockerSecretList: true,
|
||||||
|
portainer.OperationDockerSecretInspect: true,
|
||||||
|
portainer.OperationDockerSecretCreate: true,
|
||||||
|
portainer.OperationDockerSecretUpdate: true,
|
||||||
|
portainer.OperationDockerSecretDelete: true,
|
||||||
|
portainer.OperationDockerConfigList: true,
|
||||||
|
portainer.OperationDockerConfigInspect: true,
|
||||||
|
portainer.OperationDockerConfigCreate: true,
|
||||||
|
portainer.OperationDockerConfigUpdate: true,
|
||||||
|
portainer.OperationDockerConfigDelete: true,
|
||||||
|
portainer.OperationDockerTaskList: true,
|
||||||
|
portainer.OperationDockerTaskInspect: true,
|
||||||
|
portainer.OperationDockerTaskLogs: true,
|
||||||
|
portainer.OperationDockerPluginList: true,
|
||||||
|
portainer.OperationDockerPluginPrivileges: true,
|
||||||
|
portainer.OperationDockerPluginInspect: true,
|
||||||
|
portainer.OperationDockerPluginPull: true,
|
||||||
|
portainer.OperationDockerPluginCreate: true,
|
||||||
|
portainer.OperationDockerPluginEnable: true,
|
||||||
|
portainer.OperationDockerPluginDisable: true,
|
||||||
|
portainer.OperationDockerPluginPush: true,
|
||||||
|
portainer.OperationDockerPluginUpgrade: true,
|
||||||
|
portainer.OperationDockerPluginSet: true,
|
||||||
|
portainer.OperationDockerPluginDelete: true,
|
||||||
|
portainer.OperationDockerSessionStart: true,
|
||||||
|
portainer.OperationDockerDistributionInspect: true,
|
||||||
|
portainer.OperationDockerBuildPrune: true,
|
||||||
|
portainer.OperationDockerBuildCancel: true,
|
||||||
|
portainer.OperationDockerPing: true,
|
||||||
|
portainer.OperationDockerInfo: true,
|
||||||
|
portainer.OperationDockerVersion: true,
|
||||||
|
portainer.OperationDockerEvents: true,
|
||||||
|
portainer.OperationDockerSystem: true,
|
||||||
|
portainer.OperationDockerUndefined: true,
|
||||||
|
portainer.OperationDockerAgentPing: true,
|
||||||
|
portainer.OperationDockerAgentList: true,
|
||||||
|
portainer.OperationDockerAgentHostInfo: true,
|
||||||
|
portainer.OperationDockerAgentUndefined: true,
|
||||||
|
portainer.OperationPortainerResourceControlUpdate: true,
|
||||||
|
portainer.OperationPortainerStackList: true,
|
||||||
|
portainer.OperationPortainerStackInspect: true,
|
||||||
|
portainer.OperationPortainerStackFile: true,
|
||||||
|
portainer.OperationPortainerStackCreate: true,
|
||||||
|
portainer.OperationPortainerStackMigrate: true,
|
||||||
|
portainer.OperationPortainerStackUpdate: true,
|
||||||
|
portainer.OperationPortainerStackDelete: true,
|
||||||
|
portainer.OperationPortainerWebsocketExec: true,
|
||||||
|
portainer.OperationPortainerWebhookList: true,
|
||||||
|
portainer.OperationPortainerWebhookCreate: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
if volumeBrowsingAuthorizations {
|
||||||
|
authorizations[portainer.OperationDockerAgentBrowseGet] = true
|
||||||
|
authorizations[portainer.OperationDockerAgentBrowseList] = true
|
||||||
|
authorizations[portainer.OperationDockerAgentBrowseDelete] = true
|
||||||
|
authorizations[portainer.OperationDockerAgentBrowsePut] = true
|
||||||
|
authorizations[portainer.OperationDockerAgentBrowseRename] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return authorizations
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultEndpointAuthorizationsForReadOnlyUserRole returns the default endpoint authorizations
|
||||||
|
// associated to the readonly user role.
|
||||||
|
func DefaultEndpointAuthorizationsForReadOnlyUserRole(volumeBrowsingAuthorizations bool) portainer.Authorizations {
|
||||||
|
authorizations := map[portainer.Authorization]bool{
|
||||||
|
portainer.OperationDockerContainerArchiveInfo: true,
|
||||||
|
portainer.OperationDockerContainerList: true,
|
||||||
|
portainer.OperationDockerContainerChanges: true,
|
||||||
|
portainer.OperationDockerContainerInspect: true,
|
||||||
|
portainer.OperationDockerContainerTop: true,
|
||||||
|
portainer.OperationDockerContainerLogs: true,
|
||||||
|
portainer.OperationDockerContainerStats: true,
|
||||||
|
portainer.OperationDockerImageList: true,
|
||||||
|
portainer.OperationDockerImageSearch: true,
|
||||||
|
portainer.OperationDockerImageGetAll: true,
|
||||||
|
portainer.OperationDockerImageGet: true,
|
||||||
|
portainer.OperationDockerImageHistory: true,
|
||||||
|
portainer.OperationDockerImageInspect: true,
|
||||||
|
portainer.OperationDockerNetworkList: true,
|
||||||
|
portainer.OperationDockerNetworkInspect: true,
|
||||||
|
portainer.OperationDockerVolumeList: true,
|
||||||
|
portainer.OperationDockerVolumeInspect: true,
|
||||||
|
portainer.OperationDockerSwarmInspect: true,
|
||||||
|
portainer.OperationDockerNodeList: true,
|
||||||
|
portainer.OperationDockerNodeInspect: true,
|
||||||
|
portainer.OperationDockerServiceList: true,
|
||||||
|
portainer.OperationDockerServiceInspect: true,
|
||||||
|
portainer.OperationDockerServiceLogs: true,
|
||||||
|
portainer.OperationDockerSecretList: true,
|
||||||
|
portainer.OperationDockerSecretInspect: true,
|
||||||
|
portainer.OperationDockerConfigList: true,
|
||||||
|
portainer.OperationDockerConfigInspect: true,
|
||||||
|
portainer.OperationDockerTaskList: true,
|
||||||
|
portainer.OperationDockerTaskInspect: true,
|
||||||
|
portainer.OperationDockerTaskLogs: true,
|
||||||
|
portainer.OperationDockerPluginList: true,
|
||||||
|
portainer.OperationDockerDistributionInspect: true,
|
||||||
|
portainer.OperationDockerPing: true,
|
||||||
|
portainer.OperationDockerInfo: true,
|
||||||
|
portainer.OperationDockerVersion: true,
|
||||||
|
portainer.OperationDockerEvents: true,
|
||||||
|
portainer.OperationDockerSystem: true,
|
||||||
|
portainer.OperationDockerAgentPing: true,
|
||||||
|
portainer.OperationDockerAgentList: true,
|
||||||
|
portainer.OperationDockerAgentHostInfo: true,
|
||||||
|
portainer.OperationPortainerStackList: true,
|
||||||
|
portainer.OperationPortainerStackInspect: true,
|
||||||
|
portainer.OperationPortainerStackFile: true,
|
||||||
|
portainer.OperationPortainerWebhookList: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
if volumeBrowsingAuthorizations {
|
||||||
|
authorizations[portainer.OperationDockerAgentBrowseGet] = true
|
||||||
|
authorizations[portainer.OperationDockerAgentBrowseList] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return authorizations
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultPortainerAuthorizations returns the default Portainer authorizations used by non-admin users.
|
||||||
|
func DefaultPortainerAuthorizations() portainer.Authorizations {
|
||||||
|
return map[portainer.Authorization]bool{
|
||||||
|
portainer.OperationPortainerDockerHubInspect: true,
|
||||||
|
portainer.OperationPortainerEndpointGroupList: true,
|
||||||
|
portainer.OperationPortainerEndpointList: true,
|
||||||
|
portainer.OperationPortainerEndpointInspect: true,
|
||||||
|
portainer.OperationPortainerEndpointExtensionAdd: true,
|
||||||
|
portainer.OperationPortainerEndpointExtensionRemove: true,
|
||||||
|
portainer.OperationPortainerExtensionList: true,
|
||||||
|
portainer.OperationPortainerMOTD: true,
|
||||||
|
portainer.OperationPortainerRegistryList: true,
|
||||||
|
portainer.OperationPortainerRegistryInspect: true,
|
||||||
|
portainer.OperationPortainerTeamList: true,
|
||||||
|
portainer.OperationPortainerTemplateList: true,
|
||||||
|
portainer.OperationPortainerTemplateInspect: true,
|
||||||
|
portainer.OperationPortainerUserList: true,
|
||||||
|
portainer.OperationPortainerUserInspect: true,
|
||||||
|
portainer.OperationPortainerUserMemberships: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateVolumeBrowsingAuthorizations will update all the volume browsing authorizations for each role (except endpoint administrator)
|
||||||
|
// based on the specified removeAuthorizations parameter. If removeAuthorizations is set to true, all
|
||||||
|
// the authorizations will be dropped for the each role. If removeAuthorizations is set to false, the authorizations
|
||||||
|
// will be reset based for each role.
|
||||||
|
func (service Service) UpdateVolumeBrowsingAuthorizations(remove bool) error {
|
||||||
|
roles, err := service.dataStore.Role().Roles()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, role := range roles {
|
||||||
|
// all roles except endpoint administrator
|
||||||
|
if role.ID != portainer.RoleID(1) {
|
||||||
|
updateRoleVolumeBrowsingAuthorizations(&role, remove)
|
||||||
|
|
||||||
|
err := service.dataStore.Role().UpdateRole(role.ID, &role)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateRoleVolumeBrowsingAuthorizations(role *portainer.Role, removeAuthorizations bool) {
|
||||||
|
if !removeAuthorizations {
|
||||||
|
delete(role.Authorizations, portainer.OperationDockerAgentBrowseDelete)
|
||||||
|
delete(role.Authorizations, portainer.OperationDockerAgentBrowseGet)
|
||||||
|
delete(role.Authorizations, portainer.OperationDockerAgentBrowseList)
|
||||||
|
delete(role.Authorizations, portainer.OperationDockerAgentBrowsePut)
|
||||||
|
delete(role.Authorizations, portainer.OperationDockerAgentBrowseRename)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
role.Authorizations[portainer.OperationDockerAgentBrowseGet] = true
|
||||||
|
role.Authorizations[portainer.OperationDockerAgentBrowseList] = true
|
||||||
|
|
||||||
|
// Standard-user
|
||||||
|
if role.ID == portainer.RoleID(3) {
|
||||||
|
role.Authorizations[portainer.OperationDockerAgentBrowseDelete] = true
|
||||||
|
role.Authorizations[portainer.OperationDockerAgentBrowsePut] = true
|
||||||
|
role.Authorizations[portainer.OperationDockerAgentBrowseRename] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveTeamAccessPolicies will remove all existing access policies associated to the specified team
|
||||||
|
func (service *Service) RemoveTeamAccessPolicies(teamID portainer.TeamID) error {
|
||||||
|
endpoints, err := service.dataStore.Endpoint().Endpoints()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, endpoint := range endpoints {
|
||||||
|
for policyTeamID := range endpoint.TeamAccessPolicies {
|
||||||
|
if policyTeamID == teamID {
|
||||||
|
delete(endpoint.TeamAccessPolicies, policyTeamID)
|
||||||
|
|
||||||
|
err := service.dataStore.Endpoint().UpdateEndpoint(endpoint.ID, &endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
endpointGroups, err := service.dataStore.EndpointGroup().EndpointGroups()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, endpointGroup := range endpointGroups {
|
||||||
|
for policyTeamID := range endpointGroup.TeamAccessPolicies {
|
||||||
|
if policyTeamID == teamID {
|
||||||
|
delete(endpointGroup.TeamAccessPolicies, policyTeamID)
|
||||||
|
|
||||||
|
err := service.dataStore.EndpointGroup().UpdateEndpointGroup(endpointGroup.ID, &endpointGroup)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
registries, err := service.dataStore.Registry().Registries()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, registry := range registries {
|
||||||
|
for policyTeamID := range registry.TeamAccessPolicies {
|
||||||
|
if policyTeamID == teamID {
|
||||||
|
delete(registry.TeamAccessPolicies, policyTeamID)
|
||||||
|
|
||||||
|
err := service.dataStore.Registry().UpdateRegistry(registry.ID, ®istry)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return service.UpdateUsersAuthorizations()
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveUserAccessPolicies will remove all existing access policies associated to the specified user
|
||||||
|
func (service *Service) RemoveUserAccessPolicies(userID portainer.UserID) error {
|
||||||
|
endpoints, err := service.dataStore.Endpoint().Endpoints()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, endpoint := range endpoints {
|
||||||
|
for policyUserID := range endpoint.UserAccessPolicies {
|
||||||
|
if policyUserID == userID {
|
||||||
|
delete(endpoint.UserAccessPolicies, policyUserID)
|
||||||
|
|
||||||
|
err := service.dataStore.Endpoint().UpdateEndpoint(endpoint.ID, &endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
endpointGroups, err := service.dataStore.EndpointGroup().EndpointGroups()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, endpointGroup := range endpointGroups {
|
||||||
|
for policyUserID := range endpointGroup.UserAccessPolicies {
|
||||||
|
if policyUserID == userID {
|
||||||
|
delete(endpointGroup.UserAccessPolicies, policyUserID)
|
||||||
|
|
||||||
|
err := service.dataStore.EndpointGroup().UpdateEndpointGroup(endpointGroup.ID, &endpointGroup)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
registries, err := service.dataStore.Registry().Registries()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, registry := range registries {
|
||||||
|
for policyUserID := range registry.UserAccessPolicies {
|
||||||
|
if policyUserID == userID {
|
||||||
|
delete(registry.UserAccessPolicies, policyUserID)
|
||||||
|
|
||||||
|
err := service.dataStore.Registry().UpdateRegistry(registry.ID, ®istry)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateUsersAuthorizations will trigger an update of the authorizations for all the users.
|
||||||
|
func (service *Service) UpdateUsersAuthorizations() error {
|
||||||
|
users, err := service.dataStore.User().Users()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, user := range users {
|
||||||
|
err := service.updateUserAuthorizations(user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (service *Service) updateUserAuthorizations(userID portainer.UserID) error {
|
||||||
|
user, err := service.dataStore.User().User(userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpointAuthorizations, err := service.getAuthorizations(user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
user.EndpointAuthorizations = endpointAuthorizations
|
||||||
|
|
||||||
|
return service.dataStore.User().UpdateUser(userID, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (service *Service) getAuthorizations(user *portainer.User) (portainer.EndpointAuthorizations, error) {
|
||||||
|
endpointAuthorizations := portainer.EndpointAuthorizations{}
|
||||||
|
if user.Role == portainer.AdministratorRole {
|
||||||
|
return endpointAuthorizations, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
userMemberships, err := service.dataStore.TeamMembership().TeamMembershipsByUserID(user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return endpointAuthorizations, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints, err := service.dataStore.Endpoint().Endpoints()
|
||||||
|
if err != nil {
|
||||||
|
return endpointAuthorizations, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpointGroups, err := service.dataStore.EndpointGroup().EndpointGroups()
|
||||||
|
if err != nil {
|
||||||
|
return endpointAuthorizations, err
|
||||||
|
}
|
||||||
|
|
||||||
|
roles, err := service.dataStore.Role().Roles()
|
||||||
|
if err != nil {
|
||||||
|
return endpointAuthorizations, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpointAuthorizations = getUserEndpointAuthorizations(user, endpoints, endpointGroups, roles, userMemberships)
|
||||||
|
|
||||||
|
return endpointAuthorizations, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUserEndpointAuthorizations(user *portainer.User, endpoints []portainer.Endpoint, endpointGroups []portainer.EndpointGroup, roles []portainer.Role, userMemberships []portainer.TeamMembership) portainer.EndpointAuthorizations {
|
||||||
|
endpointAuthorizations := make(portainer.EndpointAuthorizations)
|
||||||
|
|
||||||
|
groupUserAccessPolicies := map[portainer.EndpointGroupID]portainer.UserAccessPolicies{}
|
||||||
|
groupTeamAccessPolicies := map[portainer.EndpointGroupID]portainer.TeamAccessPolicies{}
|
||||||
|
for _, endpointGroup := range endpointGroups {
|
||||||
|
groupUserAccessPolicies[endpointGroup.ID] = endpointGroup.UserAccessPolicies
|
||||||
|
groupTeamAccessPolicies[endpointGroup.ID] = endpointGroup.TeamAccessPolicies
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, endpoint := range endpoints {
|
||||||
|
authorizations := getAuthorizationsFromUserEndpointPolicy(user, &endpoint, roles)
|
||||||
|
if len(authorizations) > 0 {
|
||||||
|
endpointAuthorizations[endpoint.ID] = authorizations
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
authorizations = getAuthorizationsFromUserEndpointGroupPolicy(user, &endpoint, roles, groupUserAccessPolicies)
|
||||||
|
if len(authorizations) > 0 {
|
||||||
|
endpointAuthorizations[endpoint.ID] = authorizations
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
authorizations = getAuthorizationsFromTeamEndpointPolicies(userMemberships, &endpoint, roles)
|
||||||
|
if len(authorizations) > 0 {
|
||||||
|
endpointAuthorizations[endpoint.ID] = authorizations
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
authorizations = getAuthorizationsFromTeamEndpointGroupPolicies(userMemberships, &endpoint, roles, groupTeamAccessPolicies)
|
||||||
|
if len(authorizations) > 0 {
|
||||||
|
endpointAuthorizations[endpoint.ID] = authorizations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpointAuthorizations
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuthorizationsFromUserEndpointPolicy(user *portainer.User, endpoint *portainer.Endpoint, roles []portainer.Role) portainer.Authorizations {
|
||||||
|
policyRoles := make([]portainer.RoleID, 0)
|
||||||
|
|
||||||
|
policy, ok := endpoint.UserAccessPolicies[user.ID]
|
||||||
|
if ok {
|
||||||
|
policyRoles = append(policyRoles, policy.RoleID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAuthorizationsFromRoles(policyRoles, roles)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuthorizationsFromUserEndpointGroupPolicy(user *portainer.User, endpoint *portainer.Endpoint, roles []portainer.Role, groupAccessPolicies map[portainer.EndpointGroupID]portainer.UserAccessPolicies) portainer.Authorizations {
|
||||||
|
policyRoles := make([]portainer.RoleID, 0)
|
||||||
|
|
||||||
|
policy, ok := groupAccessPolicies[endpoint.GroupID][user.ID]
|
||||||
|
if ok {
|
||||||
|
policyRoles = append(policyRoles, policy.RoleID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAuthorizationsFromRoles(policyRoles, roles)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuthorizationsFromTeamEndpointPolicies(memberships []portainer.TeamMembership, endpoint *portainer.Endpoint, roles []portainer.Role) portainer.Authorizations {
|
||||||
|
policyRoles := make([]portainer.RoleID, 0)
|
||||||
|
|
||||||
|
for _, membership := range memberships {
|
||||||
|
policy, ok := endpoint.TeamAccessPolicies[membership.TeamID]
|
||||||
|
if ok {
|
||||||
|
policyRoles = append(policyRoles, policy.RoleID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAuthorizationsFromRoles(policyRoles, roles)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuthorizationsFromTeamEndpointGroupPolicies(memberships []portainer.TeamMembership, endpoint *portainer.Endpoint, roles []portainer.Role, groupAccessPolicies map[portainer.EndpointGroupID]portainer.TeamAccessPolicies) portainer.Authorizations {
|
||||||
|
policyRoles := make([]portainer.RoleID, 0)
|
||||||
|
|
||||||
|
for _, membership := range memberships {
|
||||||
|
policy, ok := groupAccessPolicies[endpoint.GroupID][membership.TeamID]
|
||||||
|
if ok {
|
||||||
|
policyRoles = append(policyRoles, policy.RoleID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAuthorizationsFromRoles(policyRoles, roles)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuthorizationsFromRoles(roleIdentifiers []portainer.RoleID, roles []portainer.Role) portainer.Authorizations {
|
||||||
|
var associatedRoles []portainer.Role
|
||||||
|
|
||||||
|
for _, id := range roleIdentifiers {
|
||||||
|
for _, role := range roles {
|
||||||
|
if role.ID == id {
|
||||||
|
associatedRoles = append(associatedRoles, role)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var authorizations portainer.Authorizations
|
||||||
|
highestPriority := 0
|
||||||
|
for _, role := range associatedRoles {
|
||||||
|
if role.Priority > highestPriority {
|
||||||
|
highestPriority = role.Priority
|
||||||
|
authorizations = role.Authorizations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return authorizations
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package edge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/internal/tag"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EdgeGroupRelatedEndpoints returns a list of endpoints related to this Edge group
|
||||||
|
func EdgeGroupRelatedEndpoints(edgeGroup *portainer.EdgeGroup, endpoints []portainer.Endpoint, endpointGroups []portainer.EndpointGroup) []portainer.EndpointID {
|
||||||
|
if !edgeGroup.Dynamic {
|
||||||
|
return edgeGroup.Endpoints
|
||||||
|
}
|
||||||
|
|
||||||
|
endpointIDs := []portainer.EndpointID{}
|
||||||
|
for _, endpoint := range endpoints {
|
||||||
|
if endpoint.Type != portainer.EdgeAgentEnvironment {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var endpointGroup portainer.EndpointGroup
|
||||||
|
for _, group := range endpointGroups {
|
||||||
|
if endpoint.GroupID == group.ID {
|
||||||
|
endpointGroup = group
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if edgeGroupRelatedToEndpoint(edgeGroup, &endpoint, &endpointGroup) {
|
||||||
|
endpointIDs = append(endpointIDs, endpoint.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpointIDs
|
||||||
|
}
|
||||||
|
|
||||||
|
// edgeGroupRelatedToEndpoint returns true is edgeGroup is associated with endpoint
|
||||||
|
func edgeGroupRelatedToEndpoint(edgeGroup *portainer.EdgeGroup, endpoint *portainer.Endpoint, endpointGroup *portainer.EndpointGroup) bool {
|
||||||
|
if !edgeGroup.Dynamic {
|
||||||
|
for _, endpointID := range edgeGroup.Endpoints {
|
||||||
|
if endpoint.ID == endpointID {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
endpointTags := tag.Set(endpoint.TagIDs)
|
||||||
|
if endpointGroup.TagIDs != nil {
|
||||||
|
endpointTags = tag.Union(endpointTags, tag.Set(endpointGroup.TagIDs))
|
||||||
|
}
|
||||||
|
edgeGroupTags := tag.Set(edgeGroup.TagIDs)
|
||||||
|
|
||||||
|
if edgeGroup.PartialMatch {
|
||||||
|
intersection := tag.Intersection(endpointTags, edgeGroupTags)
|
||||||
|
return len(intersection) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return tag.Contains(edgeGroupTags, endpointTags)
|
||||||
|
}
|
|
@ -1,13 +1,16 @@
|
||||||
package portainer
|
package edge
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/portainer/portainer/api"
|
||||||
|
)
|
||||||
|
|
||||||
// EdgeStackRelatedEndpoints returns a list of endpoints related to this Edge stack
|
// EdgeStackRelatedEndpoints returns a list of endpoints related to this Edge stack
|
||||||
func EdgeStackRelatedEndpoints(edgeGroupIDs []EdgeGroupID, endpoints []Endpoint, endpointGroups []EndpointGroup, edgeGroups []EdgeGroup) ([]EndpointID, error) {
|
func EdgeStackRelatedEndpoints(edgeGroupIDs []portainer.EdgeGroupID, endpoints []portainer.Endpoint, endpointGroups []portainer.EndpointGroup, edgeGroups []portainer.EdgeGroup) ([]portainer.EndpointID, error) {
|
||||||
edgeStackEndpoints := []EndpointID{}
|
edgeStackEndpoints := []portainer.EndpointID{}
|
||||||
|
|
||||||
for _, edgeGroupID := range edgeGroupIDs {
|
for _, edgeGroupID := range edgeGroupIDs {
|
||||||
var edgeGroup *EdgeGroup
|
var edgeGroup *portainer.EdgeGroup
|
||||||
|
|
||||||
for _, group := range edgeGroups {
|
for _, group := range edgeGroups {
|
||||||
if group.ID == edgeGroupID {
|
if group.ID == edgeGroupID {
|
|
@ -1,8 +1,10 @@
|
||||||
package portainer
|
package edge
|
||||||
|
|
||||||
|
import "github.com/portainer/portainer/api"
|
||||||
|
|
||||||
// EndpointRelatedEdgeStacks returns a list of Edge stacks related to this Endpoint
|
// EndpointRelatedEdgeStacks returns a list of Edge stacks related to this Endpoint
|
||||||
func EndpointRelatedEdgeStacks(endpoint *Endpoint, endpointGroup *EndpointGroup, edgeGroups []EdgeGroup, edgeStacks []EdgeStack) []EdgeStackID {
|
func EndpointRelatedEdgeStacks(endpoint *portainer.Endpoint, endpointGroup *portainer.EndpointGroup, edgeGroups []portainer.EdgeGroup, edgeStacks []portainer.EdgeStack) []portainer.EdgeStackID {
|
||||||
relatedEdgeGroupsSet := map[EdgeGroupID]bool{}
|
relatedEdgeGroupsSet := map[portainer.EdgeGroupID]bool{}
|
||||||
|
|
||||||
for _, edgeGroup := range edgeGroups {
|
for _, edgeGroup := range edgeGroups {
|
||||||
if edgeGroupRelatedToEndpoint(&edgeGroup, endpoint, endpointGroup) {
|
if edgeGroupRelatedToEndpoint(&edgeGroup, endpoint, endpointGroup) {
|
||||||
|
@ -10,7 +12,7 @@ func EndpointRelatedEdgeStacks(endpoint *Endpoint, endpointGroup *EndpointGroup,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
relatedEdgeStacks := []EdgeStackID{}
|
relatedEdgeStacks := []portainer.EdgeStackID{}
|
||||||
for _, edgeStack := range edgeStacks {
|
for _, edgeStack := range edgeStacks {
|
||||||
for _, edgeGroupID := range edgeStack.EdgeGroups {
|
for _, edgeGroupID := range edgeStack.EdgeGroups {
|
||||||
if relatedEdgeGroupsSet[edgeGroupID] {
|
if relatedEdgeGroupsSet[edgeGroupID] {
|
|
@ -1,18 +1,20 @@
|
||||||
package portainer
|
package tag
|
||||||
|
|
||||||
type tagSet map[TagID]bool
|
import "github.com/portainer/portainer/api"
|
||||||
|
|
||||||
// TagSet converts an array of ids to a set
|
type tagSet map[portainer.TagID]bool
|
||||||
func TagSet(tagIDs []TagID) tagSet {
|
|
||||||
set := map[TagID]bool{}
|
// Set converts an array of ids to a set
|
||||||
|
func Set(tagIDs []portainer.TagID) tagSet {
|
||||||
|
set := map[portainer.TagID]bool{}
|
||||||
for _, tagID := range tagIDs {
|
for _, tagID := range tagIDs {
|
||||||
set[tagID] = true
|
set[tagID] = true
|
||||||
}
|
}
|
||||||
return set
|
return set
|
||||||
}
|
}
|
||||||
|
|
||||||
// TagIntersection returns a set intersection of the provided sets
|
// Intersection returns a set intersection of the provided sets
|
||||||
func TagIntersection(sets ...tagSet) tagSet {
|
func Intersection(sets ...tagSet) tagSet {
|
||||||
intersection := tagSet{}
|
intersection := tagSet{}
|
||||||
if len(sets) == 0 {
|
if len(sets) == 0 {
|
||||||
return intersection
|
return intersection
|
||||||
|
@ -35,8 +37,8 @@ func TagIntersection(sets ...tagSet) tagSet {
|
||||||
return intersection
|
return intersection
|
||||||
}
|
}
|
||||||
|
|
||||||
// TagUnion returns a set union of provided sets
|
// Union returns a set union of provided sets
|
||||||
func TagUnion(sets ...tagSet) tagSet {
|
func Union(sets ...tagSet) tagSet {
|
||||||
union := tagSet{}
|
union := tagSet{}
|
||||||
for _, set := range sets {
|
for _, set := range sets {
|
||||||
for tag := range set {
|
for tag := range set {
|
||||||
|
@ -46,8 +48,8 @@ func TagUnion(sets ...tagSet) tagSet {
|
||||||
return union
|
return union
|
||||||
}
|
}
|
||||||
|
|
||||||
// TagContains return true if setA contains setB
|
// Contains return true if setA contains setB
|
||||||
func TagContains(setA tagSet, setB tagSet) bool {
|
func Contains(setA tagSet, setB tagSet) bool {
|
||||||
containedTags := 0
|
containedTags := 0
|
||||||
for tag := range setB {
|
for tag := range setB {
|
||||||
if setA[tag] {
|
if setA[tag] {
|
||||||
|
@ -57,8 +59,8 @@ func TagContains(setA tagSet, setB tagSet) bool {
|
||||||
return containedTags == len(setA)
|
return containedTags == len(setA)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TagDifference returns the set difference tagsA - tagsB
|
// Difference returns the set difference tagsA - tagsB
|
||||||
func TagDifference(setA tagSet, setB tagSet) tagSet {
|
func Difference(setA tagSet, setB tagSet) tagSet {
|
||||||
set := tagSet{}
|
set := tagSet{}
|
||||||
|
|
||||||
for tag := range setA {
|
for tag := range setA {
|
Loading…
Reference in New Issue