{"action":"created","comment":{"url":"https://api.github.com/repos/openshift/origin/pulls/comments/22717934","id":22717934,"diff_hunk":"@@ -0,0 +1,270 @@\n+# Policy\n+\n+## Problem\n+Policy extends the existing authorization rules in Kubernetes (https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/authorization.md) to fulfill requirements around extended verb sets, verb specific attributes, role based management of attribute based access control, and more efficient evaluation of authorization status at larger scales.  For discussion about verbs, see: https://github.com/GoogleCloudPlatform/kubernetes/issues/2877.  For discussion about allowing mutation of some fields in a resource and not others, see: https://github.com/GoogleCloudPlatform/kubernetes/issues/2726.\n+\n+## Use Cases\n+ 1.  I want to apply the same set of policy rules to large numbers of projects.\n+ 1.  I want to change the policy rules for a role and have it applied to all projects using that role.\n+ 1.  I want to have policy changes take effect quickly, without any down time.\n+ 1.  I want to have distinct policy rules to control team membership, project metadata, policy rules for roles, and policy rules for users.\n+ 1.  OpenShift will ship with a set of default roles: view, edit, and admin\n+\n+## Exclusions\n+ 1. UI (cli or graphical).  This document describes what policy can do, the data required to make policy work, and runtime interactions to fulfill the policy.  It does **not** attempt to describe a UI (cli or graphical) on top of basic resource CRUD.\n+ 1. Teams.  This document assumes that a UserInfo object exists and that it has `UserInfo.getUserName() string` and `UserInfo.getTeamNames() []string`.  How that team information is populated and stored is beyond the scope of making effective policy.\n+\n+  \n+## Policy Example\n+Out the box, OpenShift provides three roles: view, edit, and admin.  Viewers are able to see all resources.  Editors are able to view and edit all resources, except ones related to policy and membership.  Admins are able to modify anything.  The roles are expressed like this:\n+```\n+{\n+\t\"kind\": \"role\",\n+\t\"name\": \"view\",\n+\t\"namespace\": \"global\",\n+\t\"rules\": [\n+\t\t{ \"verbs\": [\"watch\", \"list\", \"get\"], \"resourceKinds\": [\"*\"] },\n+\t]\n+}\n+{\n+\t\"kind\": \"role\",\n+\t\"name\": \"edit\",\n+\t\"namespace\": \"global\",\n+\t\"rules\": [\n+\t\t{ \"verbs\": [\"*\"], \"resourceKinds\": [\"*\"] }\n+\t\t{ \"deny\": \"true\", \"verbs\": [\"create\", \"update\", \"delete\"], \"resourceKinds\": [\"PolicyRuleBinding\", \"Role\", RoleBinding\"] }\n+\t]\n+}\n+{\n+\t\"kind\": \"role\",\n+\t\"name\": \"admin\",\n+\t\"namespace\": \"global\",\n+\t\"rules\": [\n+\t\t{ \"verbs\": [\"*\"], \"resourceKinds\": [\"*\"] }\n+\t]\n+}\n+```\n+\n+The global admin (guy who owns the openshift installation), creates a project `chisel` and assigns `Hubert` as the admin for the project using the predefined role.  The permissions are expressed like this:\n+```\n+{\n+\t\"kind\": \"roleBinding\",\n+\t\"name\": \"ProjectAdmins\",\n+\t\"namespace\": \"chisel\",\n+\t\"referencesGlobalRole\": \"true\",\n+\t\"roleName\": \"admin\",\n+\t\"userNames\": [\"Hubert\"]\n+}\n+```\n+\n+`Hubert` now has the power to manage policy on the `chisel` project.  He can grant permission to users who should have access.  In this case, he grants edit permission to `Curt` using the predefined role.\n+```\n+{\n+\t\"kind\": \"roleBinding\",\n+\t\"name\": \"Editors\",\n+\t\"namespace\": \"chisel\",\n+\t\"referencesGlobalRole\": \"true\",\n+\t\"roleName\": \"editor\",\n+\t\"userNames\": [\"Curt\"]\n+}\n+```\n+\n+That covers most cases where global admins want to create projects and delegate the administration of a project to a project admin.  Then the project admin wants to delegate project level permissions to other users.  We can continue the example with `Hubert` (our project admin) wanting to create custom roles and restrictions.\n+\n+`Hubert` needs wants to create a bot that only has permission to touch labels on DeploymentConfigs.  He can create a role like this (note that a role is required because we want to have a set of two rules):\n+```\n+{\n+\t\"kind\": \"role\",\n+\t\"name\": \"deploymentConfigLabelers\",\n+\t\"namespace\": \"chisel\",\n+\t\"rules\": [\n+\t\t{ \"verbs\": [\"watch\", \"list\", \"get\"], \"resourceKinds\": [\"DeploymentConfig\"] },\n+\t\t{ \"verbs\": [\"update\"], \"resourceKinds\": [\"DeploymentConfig\"], \"attributeRestrictions\" : {\"fieldsMutatable\": [\"labels\"]} }\n+\t]\n+}\n+{\n+\t\"kind\": \"roleBinding\",\n+\t\"name\": \"DeploymentConfigLabelerBots\",\n+\t\"namespace\": \"chisel\",\n+\t\"roleName\": \"deploymentConfigLabelers\",\n+\t\"userNames\": [\"ProtectorBot\", \"DeprotectorBot\"]\n+}\n+```\n+\n+Finally, `Hubert` wants to prevent `Curt` from ever deleting a protected deploymentConfig again, so he creates this policyRuleBinding:\n+```\n+{\n+\t\"kind\": \"policyRuleBinding\",\n+\t\"name\": \"FatFingeredEditors\",\n+\t\"namespace\": \"chisel\",\n+\t\"rule\": { \"Deny\": \"true\", \"Verbs\": [\"delete\"], \"ResourceKinds\": [\"DeploymentConfig\"], \"AttributeRestrictions\" : {\"labelsContain\": [\"protected\"]} }","path":"docs/proposals/policy.md","position":100,"original_position":100,"commit_id":"bbf570f90f8384b072fa053861f35cf4a9b8cce6","original_commit_id":"bbf570f90f8384b072fa053861f35cf4a9b8cce6","user":{"login":"liggitt","id":980082,"avatar_url":"https://avatars.githubusercontent.com/u/980082?v=3","gravatar_id":"","url":"https://api.github.com/users/liggitt","html_url":"https://github.com/liggitt","followers_url":"https://api.github.com/users/liggitt/followers","following_url":"https://api.github.com/users/liggitt/following{/other_user}","gists_url":"https://api.github.com/users/liggitt/gists{/gist_id}","starred_url":"https://api.github.com/users/liggitt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liggitt/subscriptions","organizations_url":"https://api.github.com/users/liggitt/orgs","repos_url":"https://api.github.com/users/liggitt/repos","events_url":"https://api.github.com/users/liggitt/events{/privacy}","received_events_url":"https://api.github.com/users/liggitt/received_events","type":"User","site_admin":false},"body":"any reason to not let this express multiple allow/denies the same way a role does?","created_at":"2015-01-09T14:28:44Z","updated_at":"2015-01-09T14:28:44Z","html_url":"https://github.com/openshift/origin/pull/610#discussion_r22717934","pull_request_url":"https://api.github.com/repos/openshift/origin/pulls/610","_links":{"self":{"href":"https://api.github.com/repos/openshift/origin/pulls/comments/22717934"},"html":{"href":"https://github.com/openshift/origin/pull/610#discussion_r22717934"},"pull_request":{"href":"https://api.github.com/repos/openshift/origin/pulls/610"}}},"pull_request":{"url":"https://api.github.com/repos/openshift/origin/pulls/610","id":26757384,"html_url":"https://github.com/openshift/origin/pull/610","diff_url":"https://github.com/openshift/origin/pull/610.diff","patch_url":"https://github.com/openshift/origin/pull/610.patch","issue_url":"https://api.github.com/repos/openshift/origin/issues/610","number":610,"state":"open","locked":false,"title":"Policy proposal","user":{"login":"deads2k","id":8225098,"avatar_url":"https://avatars.githubusercontent.com/u/8225098?v=3","gravatar_id":"","url":"https://api.github.com/users/deads2k","html_url":"https://github.com/deads2k","followers_url":"https://api.github.com/users/deads2k/followers","following_url":"https://api.github.com/users/deads2k/following{/other_user}","gists_url":"https://api.github.com/users/deads2k/gists{/gist_id}","starred_url":"https://api.github.com/users/deads2k/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/deads2k/subscriptions","organizations_url":"https://api.github.com/users/deads2k/orgs","repos_url":"https://api.github.com/users/deads2k/repos","events_url":"https://api.github.com/users/deads2k/events{/privacy}","received_events_url":"https://api.github.com/users/deads2k/received_events","type":"User","site_admin":false},"body":"The basic authorization currently described in kubernetes (https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/authorization.md) doesn't have the all the features we need, so this is a description of how we could build the features we want.  Changes to the \"Runtime Authorization Types\" (not sure how to link into the document) are required and those interfaces and their registration will be required in kubernetes for clean integration with openshift.  The actual implementation (Configtime Authorization Types) could be openshift only and simply registered.\r\n\r\n@smarterclayton @derekwaynecarr @liggitt @jwforres ","created_at":"2015-01-02T13:37:18Z","updated_at":"2015-01-09T14:28:44Z","closed_at":null,"merged_at":null,"merge_commit_sha":"9827e6f3358c2a7c35cd402eb4691258b67b8e83","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/openshift/origin/pulls/610/commits","review_comments_url":"https://api.github.com/repos/openshift/origin/pulls/610/comments","review_comment_url":"https://api.github.com/repos/openshift/origin/pulls/comments/{number}","comments_url":"https://api.github.com/repos/openshift/origin/issues/610/comments","statuses_url":"https://api.github.com/repos/openshift/origin/statuses/bbf570f90f8384b072fa053861f35cf4a9b8cce6","head":{"label":"deads2k:deads-openshift-authorization","ref":"deads-openshift-authorization","sha":"bbf570f90f8384b072fa053861f35cf4a9b8cce6","user":{"login":"deads2k","id":8225098,"avatar_url":"https://avatars.githubusercontent.com/u/8225098?v=3","gravatar_id":"","url":"https://api.github.com/users/deads2k","html_url":"https://github.com/deads2k","followers_url":"https://api.github.com/users/deads2k/followers","following_url":"https://api.github.com/users/deads2k/following{/other_user}","gists_url":"https://api.github.com/users/deads2k/gists{/gist_id}","starred_url":"https://api.github.com/users/deads2k/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/deads2k/subscriptions","organizations_url":"https://api.github.com/users/deads2k/orgs","repos_url":"https://api.github.com/users/deads2k/repos","events_url":"https://api.github.com/users/deads2k/events{/privacy}","received_events_url":"https://api.github.com/users/deads2k/received_events","type":"User","site_admin":false},"repo":{"id":24424126,"name":"origin","full_name":"deads2k/origin","owner":{"login":"deads2k","id":8225098,"avatar_url":"https://avatars.githubusercontent.com/u/8225098?v=3","gravatar_id":"","url":"https://api.github.com/users/deads2k","html_url":"https://github.com/deads2k","followers_url":"https://api.github.com/users/deads2k/followers","following_url":"https://api.github.com/users/deads2k/following{/other_user}","gists_url":"https://api.github.com/users/deads2k/gists{/gist_id}","starred_url":"https://api.github.com/users/deads2k/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/deads2k/subscriptions","organizations_url":"https://api.github.com/users/deads2k/orgs","repos_url":"https://api.github.com/users/deads2k/repos","events_url":"https://api.github.com/users/deads2k/events{/privacy}","received_events_url":"https://api.github.com/users/deads2k/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/deads2k/origin","description":"OpenShift 3 - build, deploy, and manage your applications with Docker and Kubernetes","fork":true,"url":"https://api.github.com/repos/deads2k/origin","forks_url":"https://api.github.com/repos/deads2k/origin/forks","keys_url":"https://api.github.com/repos/deads2k/origin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/deads2k/origin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/deads2k/origin/teams","hooks_url":"https://api.github.com/repos/deads2k/origin/hooks","issue_events_url":"https://api.github.com/repos/deads2k/origin/issues/events{/number}","events_url":"https://api.github.com/repos/deads2k/origin/events","assignees_url":"https://api.github.com/repos/deads2k/origin/assignees{/user}","branches_url":"https://api.github.com/repos/deads2k/origin/branches{/branch}","tags_url":"https://api.github.com/repos/deads2k/origin/tags","blobs_url":"https://api.github.com/repos/deads2k/origin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/deads2k/origin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/deads2k/origin/git/refs{/sha}","trees_url":"https://api.github.com/repos/deads2k/origin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/deads2k/origin/statuses/{sha}","languages_url":"https://api.github.com/repos/deads2k/origin/languages","stargazers_url":"https://api.github.com/repos/deads2k/origin/stargazers","contributors_url":"https://api.github.com/repos/deads2k/origin/contributors","subscribers_url":"https://api.github.com/repos/deads2k/origin/subscribers","subscription_url":"https://api.github.com/repos/deads2k/origin/subscription","commits_url":"https://api.github.com/repos/deads2k/origin/commits{/sha}","git_commits_url":"https://api.github.com/repos/deads2k/origin/git/commits{/sha}","comments_url":"https://api.github.com/repos/deads2k/origin/comments{/number}","issue_comment_url":"https://api.github.com/repos/deads2k/origin/issues/comments/{number}","contents_url":"https://api.github.com/repos/deads2k/origin/contents/{+path}","compare_url":"https://api.github.com/repos/deads2k/origin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/deads2k/origin/merges","archive_url":"https://api.github.com/repos/deads2k/origin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/deads2k/origin/downloads","issues_url":"https://api.github.com/repos/deads2k/origin/issues{/number}","pulls_url":"https://api.github.com/repos/deads2k/origin/pulls{/number}","milestones_url":"https://api.github.com/repos/deads2k/origin/milestones{/number}","notifications_url":"https://api.github.com/repos/deads2k/origin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/deads2k/origin/labels{/name}","releases_url":"https://api.github.com/repos/deads2k/origin/releases{/id}","created_at":"2014-09-24T17:02:12Z","updated_at":"2014-12-19T20:57:28Z","pushed_at":"2015-01-09T14:00:55Z","git_url":"git://github.com/deads2k/origin.git","ssh_url":"git@github.com:deads2k/origin.git","clone_url":"https://github.com/deads2k/origin.git","svn_url":"https://github.com/deads2k/origin","homepage":"https://openshift.github.io","size":19941,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"openshift:master","ref":"master","sha":"e731a369a84d42e68404393887ac828e75e9685a","user":{"login":"openshift","id":792337,"avatar_url":"https://avatars.githubusercontent.com/u/792337?v=3","gravatar_id":"","url":"https://api.github.com/users/openshift","html_url":"https://github.com/openshift","followers_url":"https://api.github.com/users/openshift/followers","following_url":"https://api.github.com/users/openshift/following{/other_user}","gists_url":"https://api.github.com/users/openshift/gists{/gist_id}","starred_url":"https://api.github.com/users/openshift/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openshift/subscriptions","organizations_url":"https://api.github.com/users/openshift/orgs","repos_url":"https://api.github.com/users/openshift/repos","events_url":"https://api.github.com/users/openshift/events{/privacy}","received_events_url":"https://api.github.com/users/openshift/received_events","type":"Organization","site_admin":false},"repo":{"id":22442668,"name":"origin","full_name":"openshift/origin","owner":{"login":"openshift","id":792337,"avatar_url":"https://avatars.githubusercontent.com/u/792337?v=3","gravatar_id":"","url":"https://api.github.com/users/openshift","html_url":"https://github.com/openshift","followers_url":"https://api.github.com/users/openshift/followers","following_url":"https://api.github.com/users/openshift/following{/other_user}","gists_url":"https://api.github.com/users/openshift/gists{/gist_id}","starred_url":"https://api.github.com/users/openshift/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openshift/subscriptions","organizations_url":"https://api.github.com/users/openshift/orgs","repos_url":"https://api.github.com/users/openshift/repos","events_url":"https://api.github.com/users/openshift/events{/privacy}","received_events_url":"https://api.github.com/users/openshift/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/openshift/origin","description":"OpenShift 3 - build, deploy, and manage your applications with Docker and Kubernetes","fork":false,"url":"https://api.github.com/repos/openshift/origin","forks_url":"https://api.github.com/repos/openshift/origin/forks","keys_url":"https://api.github.com/repos/openshift/origin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/openshift/origin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/openshift/origin/teams","hooks_url":"https://api.github.com/repos/openshift/origin/hooks","issue_events_url":"https://api.github.com/repos/openshift/origin/issues/events{/number}","events_url":"https://api.github.com/repos/openshift/origin/events","assignees_url":"https://api.github.com/repos/openshift/origin/assignees{/user}","branches_url":"https://api.github.com/repos/openshift/origin/branches{/branch}","tags_url":"https://api.github.com/repos/openshift/origin/tags","blobs_url":"https://api.github.com/repos/openshift/origin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/openshift/origin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/openshift/origin/git/refs{/sha}","trees_url":"https://api.github.com/repos/openshift/origin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/openshift/origin/statuses/{sha}","languages_url":"https://api.github.com/repos/openshift/origin/languages","stargazers_url":"https://api.github.com/repos/openshift/origin/stargazers","contributors_url":"https://api.github.com/repos/openshift/origin/contributors","subscribers_url":"https://api.github.com/repos/openshift/origin/subscribers","subscription_url":"https://api.github.com/repos/openshift/origin/subscription","commits_url":"https://api.github.com/repos/openshift/origin/commits{/sha}","git_commits_url":"https://api.github.com/repos/openshift/origin/git/commits{/sha}","comments_url":"https://api.github.com/repos/openshift/origin/comments{/number}","issue_comment_url":"https://api.github.com/repos/openshift/origin/issues/comments/{number}","contents_url":"https://api.github.com/repos/openshift/origin/contents/{+path}","compare_url":"https://api.github.com/repos/openshift/origin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/openshift/origin/merges","archive_url":"https://api.github.com/repos/openshift/origin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/openshift/origin/downloads","issues_url":"https://api.github.com/repos/openshift/origin/issues{/number}","pulls_url":"https://api.github.com/repos/openshift/origin/pulls{/number}","milestones_url":"https://api.github.com/repos/openshift/origin/milestones{/number}","notifications_url":"https://api.github.com/repos/openshift/origin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/openshift/origin/labels{/name}","releases_url":"https://api.github.com/repos/openshift/origin/releases{/id}","created_at":"2014-07-30T20:04:05Z","updated_at":"2015-01-09T09:49:50Z","pushed_at":"2015-01-08T19:57:50Z","git_url":"git://github.com/openshift/origin.git","ssh_url":"git@github.com:openshift/origin.git","clone_url":"https://github.com/openshift/origin.git","svn_url":"https://github.com/openshift/origin","homepage":"https://openshift.github.io","size":33401,"stargazers_count":224,"watchers_count":224,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":115,"mirror_url":null,"open_issues_count":57,"forks":115,"open_issues":57,"watchers":224,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/openshift/origin/pulls/610"},"html":{"href":"https://github.com/openshift/origin/pull/610"},"issue":{"href":"https://api.github.com/repos/openshift/origin/issues/610"},"comments":{"href":"https://api.github.com/repos/openshift/origin/issues/610/comments"},"review_comments":{"href":"https://api.github.com/repos/openshift/origin/pulls/610/comments"},"review_comment":{"href":"https://api.github.com/repos/openshift/origin/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/openshift/origin/pulls/610/commits"},"statuses":{"href":"https://api.github.com/repos/openshift/origin/statuses/bbf570f90f8384b072fa053861f35cf4a9b8cce6"}}}}