{"action":"created","issue":{"url":"https://api.github.com/repos/docker/docker/issues/18647","labels_url":"https://api.github.com/repos/docker/docker/issues/18647/labels{/name}","comments_url":"https://api.github.com/repos/docker/docker/issues/18647/comments","events_url":"https://api.github.com/repos/docker/docker/issues/18647/events","html_url":"https://github.com/docker/docker/issues/18647","id":122128025,"number":18647,"title":"Proposal: Policy Extension Point","user":{"login":"dave-tucker","id":3781777,"avatar_url":"https://avatars.githubusercontent.com/u/3781777?v=3","gravatar_id":"","url":"https://api.github.com/users/dave-tucker","html_url":"https://github.com/dave-tucker","followers_url":"https://api.github.com/users/dave-tucker/followers","following_url":"https://api.github.com/users/dave-tucker/following{/other_user}","gists_url":"https://api.github.com/users/dave-tucker/gists{/gist_id}","starred_url":"https://api.github.com/users/dave-tucker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dave-tucker/subscriptions","organizations_url":"https://api.github.com/users/dave-tucker/orgs","repos_url":"https://api.github.com/users/dave-tucker/repos","events_url":"https://api.github.com/users/dave-tucker/events{/privacy}","received_events_url":"https://api.github.com/users/dave-tucker/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/docker/docker/labels/kind/feature","name":"kind/feature","color":"AAB3AB"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":7,"created_at":"2015-12-14T20:48:31Z","updated_at":"2016-01-05T21:08:24Z","closed_at":null,"body":"I've been working with @jainvipin on the following proposal for the last week or so...\r\n\r\n## Introduction\r\n\r\nIn an enterprise environment, strict control over how the infrastructure is running is required is required to ensure compliance with either business policies or with regulations such as those imposed by HIPAA, SOX or PCI etc…\r\n\r\nWhile the work on AuthN #13697 and AuthZ #14674 will allow us to provide Role-Based Access Control (RBAC) this deals with **who** can execute commands and **what** can they execute. Policy is complementary to this as it is focussed on **how** the container is being run.\r\n\r\n- A policy consists of a selector and a one or more constraints\r\n- A selector is a means of identifying containers that are to be targeted by this policy \r\n- Constraints are a set of conditions that are to be enforced by the policy \r\n\r\nNeither of these concepts are native to the Docker Engine and it is expected that a Policy Engine is responsible for implementing them.\r\n\r\nThe following would be examples of policy:\r\n\r\n- “Containers that have the label ‘environment=production’ may only be deployed on networks named ‘prod-*’”\r\n\r\n- “Containers that have the label ‘environment=production’ are to receive preferred access to memory, cpu and network”\r\n\r\n- “Containers that are using the ‘postgres’ image are to be started with at least 2GB RAM\r\n\r\nA Policy Engine is responsible for determining:\r\n- What policies are defined\r\n- Which policies should be applied to a given container\r\n- In cases where more than one policy applies, it should resolve any conflicts It should determine:\r\n  - If a container can be run as intended\r\n  - If a container will not be permitted to be run\r\n  - If a policy changes, which containers are affected\r\n\r\nIn order for these decisions to be made, I'm proposing that we add a Policy Extension Point to the Docker Engine.\r\n\r\n## Requirements\r\n\r\nIn order for this decision to be made, the policy engine *should* be passed the `ContainerConfig` and `HostConfig`. It may use any of the passed parameters like 'labels', 'network', 'exposed ports', 'domain name', 'ENV' to specify a language to implement a selector. \r\nIn Future, we may also pass information about the Authenticated User and Roles applied once AuthN and AuthZ work has concluded\r\n\r\nThe policy engine should also have the opportunity to make changes to the configuration.\r\nAs there are cases where the Docker Engine is not responsible for enforcing the result of policy, for example, when the implementation is handled by a Docker Plugin, it is recommended that the result of the policy engine’s computations should be written to the `HostConfig` in such a way that it can be interpreted by the necessary drivers.\r\n\r\nThe fundamental reason for being to override behaviour is that constraints are specified by someone who has override authority above whoever is doing 'docker run'.\r\n\r\nIn general, there are multiple roles in the infra:\r\n- Developer\r\n- SRE or Ops person in a DevOps team\r\n- Infra Owner (this person is responsible for infra to be up and running either bare-metal servers or VMs, physical/virtual network, physical/virtual storage)\r\n\r\nThe override rules are specified by the SRE/Ops person who is responsible for security, and well maintained application infrastructure. The infrastructure operator who wants to offer a set of profiles may also create policies to be consumed by the application SRE/Ops person to use to run those applications.\r\n\r\nIt’s the responsibility of the user to choose a compatible Policy Engine, Network Driver, IP Addressing Driver, Volume Driver combination. The communication between these components is expected to take place out-of-band and is outside the scope of this proposal.\r\n\r\n\r\n## Proposed Implementation\r\n\r\n### Changes to HostConfig\r\n\r\nA new field should be added to HostConfig in support of this change\r\n\r\n``` go \r\ntype HostConfig struct\r\n    Policy map[string]string\r\n```\r\n\r\n### Changes to existing plugin protocols\r\n\r\nThe Policy field from HostConfig should also be passed as part of the Plugin protocol for Networks, IPAM and Volumes.\r\n\r\n### Policy Extension Point\r\n\r\nThe implementation centers around a new Policy Engine extension point.\r\nThe suggested protocol is as follows:\r\n\r\n#### PolicyEngine.CreateContainer\r\n\r\nThis method should be called before the container is started\r\n\r\n**Request:**\r\n```\r\n{\r\n    “ContainerConfig”: {},\r\n    “HostConfig”: {}\r\n}\r\n```\r\n\r\nThe request contains the `ContainerConfig` and `HostConfig` so the policy engine can derive which policies should apply in this instance. In future, this could be expanded to include additional context, for example, the authenticated user that is making the request\r\n\r\n**Response:**\r\n```\r\n{\r\n    “Err”: “”,\r\n    “Action”: “permit|deny”,\r\n    “Policy”: {\r\n        “com.example.network_policy” : “aa12345b”\r\n    },\r\n    “Reason”: “”\r\n}\r\n```\r\n\r\nThe response contains facility to return a human readable error message in the case of a problem in the container configuration.\r\n\r\nThe `Action` field determines whether a container can be run:\r\n- `permit` - run the container without modification\r\n- `deny` -  do not run the container\r\n\r\nIn every case other than `permit`, the `Reason` field should be completed to provide feedback to the user.\r\n\r\nIn all cases other than `deny`, the Map `HostConfig.Policy` should contain results from the policy engine that contains information about any policies that were applied.\r\nThe keys in the `Policy` field should conform to the same reverse DNS notation used by labels.\r\n\r\n## UX Considerations\r\n\r\n### Select a policy engine\r\n\r\n```\r\n$ docker daemon \\\r\n    # Policy Engine Plugin to use\r\n    --policy-engine=mypolicyengine\r\n```\r\n\r\n### Run in-policy container\r\n```\r\n$ docker run -itd --net=prod-foo -l environment=production nginx\r\n959a66911d2ea582b1f9b07cabc6010ca1eb8114d10201041887b783939b241\r\n```\r\n\r\n### Run out-of-policy container\r\n```\r\n$ docker run -itd --net=stage-foo -l environment=production nginx\r\n[Error] Policy Violation: Containers labelled production must be deployed on a network called prod-*\r\n```\r\n\r\n### Swarm Considerations\r\n\r\nThis proposal should work seamlessly with Swarm today, provided that all Engines within a swarm are configured with identical `--policy-engine` flags\r\n\r\nIt is clearly desirable for Swarm to be able to apply policy before the request is dispatched to a Docker Engine. Our recommendation would be to extend Swarm and to allow it to do this using the same plugin protocol… This way, policy could be enforced at both the cluster and the host level\r\n"},"comment":{"url":"https://api.github.com/repos/docker/docker/issues/comments/169134409","html_url":"https://github.com/docker/docker/issues/18647#issuecomment-169134409","issue_url":"https://api.github.com/repos/docker/docker/issues/18647","id":169134409,"user":{"login":"jainvipin","id":9005681,"avatar_url":"https://avatars.githubusercontent.com/u/9005681?v=3","gravatar_id":"","url":"https://api.github.com/users/jainvipin","html_url":"https://github.com/jainvipin","followers_url":"https://api.github.com/users/jainvipin/followers","following_url":"https://api.github.com/users/jainvipin/following{/other_user}","gists_url":"https://api.github.com/users/jainvipin/gists{/gist_id}","starred_url":"https://api.github.com/users/jainvipin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jainvipin/subscriptions","organizations_url":"https://api.github.com/users/jainvipin/orgs","repos_url":"https://api.github.com/users/jainvipin/repos","events_url":"https://api.github.com/users/jainvipin/events{/privacy}","received_events_url":"https://api.github.com/users/jainvipin/received_events","type":"User","site_admin":false},"created_at":"2016-01-05T21:08:24Z","updated_at":"2016-01-05T21:08:24Z","body":"@calavera  Thanks for sharing your thoughts on this. Please allow me to take advantage of `\"very open to reconsider my position\"` part :-)\r\n\r\nThree parts to the response, first discuss the use cases and if they are generic, second one on why in a docker-engine.\r\n\r\n#### Some very simple use cases that I believe are generic:\r\n- Security Zones for networked containers: say two services (tiers) within a tier need a specific security policy between them (only allow port-80, or port-443). This level of security policy is critical to allow for security (and compliance, like PCI). \r\n-  Prioritize network/storage traffic: say two containers belong to 'prod', 'test' and test environments and are indicated so using labels, the policies for 'prod' vs 'test' need to be different to ensure one doesn't affect other. This may include network prioritization, network resource allocation, etc.\r\n\r\nI don't want to burden with more and elaborate use cases here, but there are many that will require drivers to know the network/storage policy for the containers. I will be happy to talk about them in a hangout session if that works best. \r\n\r\n#### Why does it belong in docker-engine:\r\n- Drivers (default drivers or remote drivers) need to know the policy because they become the point of implementation; however drivers can not get this information out of band, because the 'container <-> policy' association can not be delivered to the drivers using the current plugin APIs that drivers (volume/network) provide\r\n- Providing this in docker can also help the end user a consistent way to find out what policies are in place and are enacted upon\r\n\r\n#### Compatibility with disjoint set of plugins:\r\n- We could start off with allowing the above use cases done with `compatible set of plugins/drivers`,\r\n- Work on defining the policy language that for simple use cases that is native to docker that can provide consistent Policy-Ux to the end user, while leaving exotic (one off use cases) to plugins\r\n\r\nEven if you believe these are specific use cases, for that reason the 'default policy plugin' need not be there, but if (remote or local) drivers can get the policy attributes via policy plugin it is a big enabler for the use cases in Docker eco-system.\r\n\r\nI will also let @tomdee, @lxpollitt, @bboreham and others comment on their perspective... \r\n\r\n"}}