2019-11-12 23:41:42 +00:00
|
|
|
package docker
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"net/http"
|
|
|
|
|
2021-02-23 20:18:05 +00:00
|
|
|
portainer "github.com/portainer/portainer/api"
|
|
|
|
|
2019-11-12 23:41:42 +00:00
|
|
|
"github.com/docker/docker/api/types"
|
|
|
|
|
|
|
|
"github.com/docker/docker/client"
|
|
|
|
|
2021-07-14 09:15:21 +00:00
|
|
|
"github.com/portainer/portainer/api/http/proxy/factory/utils"
|
2020-06-16 07:58:16 +00:00
|
|
|
"github.com/portainer/portainer/api/internal/authorization"
|
2019-11-12 23:41:42 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
networkObjectIdentifier = "Id"
|
|
|
|
networkObjectName = "Name"
|
|
|
|
)
|
|
|
|
|
2021-02-23 20:18:05 +00:00
|
|
|
func getInheritedResourceControlFromNetworkLabels(dockerClient *client.Client, endpointID portainer.EndpointID, networkID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
|
2019-11-12 23:41:42 +00:00
|
|
|
network, err := dockerClient.NetworkInspect(context.Background(), networkID, types.NetworkInspectOptions{})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-02-23 20:18:05 +00:00
|
|
|
stackResourceID := getStackResourceIDFromLabels(network.Labels, endpointID)
|
|
|
|
if stackResourceID != "" {
|
|
|
|
return authorization.GetResourceControlByResourceIDAndType(stackResourceID, portainer.StackResourceControl, resourceControls), nil
|
2019-11-12 23:41:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// networkListOperation extracts the response as a JSON object, loop through the networks array
|
|
|
|
// decorate and/or filter the networks based on resource controls before rewriting the response.
|
|
|
|
func (transport *Transport) networkListOperation(response *http.Response, executor *operationExecutor) error {
|
|
|
|
// NetworkList response is a JSON array
|
|
|
|
// https://docs.docker.com/engine/api/v1.28/#operation/NetworkList
|
2021-07-14 09:15:21 +00:00
|
|
|
responseArray, err := utils.GetResponseAsJSONArray(response)
|
2019-11-12 23:41:42 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
resourceOperationParameters := &resourceOperationParameters{
|
|
|
|
resourceIdentifierAttribute: networkObjectIdentifier,
|
|
|
|
resourceType: portainer.NetworkResourceControl,
|
|
|
|
labelsObjectSelector: selectorNetworkLabels,
|
|
|
|
}
|
|
|
|
|
|
|
|
responseArray, err = transport.applyAccessControlOnResourceList(resourceOperationParameters, responseArray, executor)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-07-14 09:15:21 +00:00
|
|
|
return utils.RewriteResponse(response, responseArray, http.StatusOK)
|
2019-11-12 23:41:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// networkInspectOperation extracts the response as a JSON object, verify that the user
|
|
|
|
// has access to the network based on resource control and either rewrite an access denied response or a decorated network.
|
|
|
|
func (transport *Transport) networkInspectOperation(response *http.Response, executor *operationExecutor) error {
|
|
|
|
// NetworkInspect response is a JSON object
|
|
|
|
// https://docs.docker.com/engine/api/v1.28/#operation/NetworkInspect
|
2021-07-14 09:15:21 +00:00
|
|
|
responseObject, err := utils.GetResponseAsJSONObject(response)
|
2019-11-12 23:41:42 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
resourceOperationParameters := &resourceOperationParameters{
|
|
|
|
resourceIdentifierAttribute: networkObjectIdentifier,
|
|
|
|
resourceType: portainer.NetworkResourceControl,
|
|
|
|
labelsObjectSelector: selectorNetworkLabels,
|
|
|
|
}
|
|
|
|
|
|
|
|
return transport.applyAccessControlOnResource(resourceOperationParameters, responseObject, response, executor)
|
|
|
|
}
|
|
|
|
|
|
|
|
// findSystemNetworkResourceControl will check if the network object is a system network
|
|
|
|
// and will return a system resource control if that's the case.
|
|
|
|
func findSystemNetworkResourceControl(networkObject map[string]interface{}) *portainer.ResourceControl {
|
|
|
|
if networkObject[networkObjectName] == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
networkID := networkObject[networkObjectIdentifier].(string)
|
|
|
|
networkName := networkObject[networkObjectName].(string)
|
|
|
|
|
2022-05-17 02:45:30 +00:00
|
|
|
if networkName == "bridge" || networkName == "host" || networkName == "ingress" || networkName == "nat" || networkName == "none" {
|
2020-06-16 07:58:16 +00:00
|
|
|
return authorization.NewSystemResourceControl(networkID, portainer.NetworkResourceControl)
|
2019-11-12 23:41:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// selectorNetworkLabels retrieve the labels object associated to the network object.
|
|
|
|
// Labels are available under the "Labels" property.
|
|
|
|
// API schema references:
|
|
|
|
// https://docs.docker.com/engine/api/v1.28/#operation/NetworkInspect
|
|
|
|
// https://docs.docker.com/engine/api/v1.28/#operation/NetworkList
|
|
|
|
func selectorNetworkLabels(responseObject map[string]interface{}) map[string]interface{} {
|
2021-07-14 09:15:21 +00:00
|
|
|
return utils.GetJSONObject(responseObject, "Labels")
|
2019-11-12 23:41:42 +00:00
|
|
|
}
|