{"action":"created","comment":{"url":"https://api.github.com/repos/kubernetes/community/pulls/comments/111309323","pull_request_review_id":32544818,"id":111309323,"diff_hunk":"@@ -0,0 +1,190 @@\n+# Requirements\n+\n+This document considers \"customer facing\" entities. For our purposes these are\n+the Kubernetes API, and running workloads.\n+\n+1. Kubernetes needs to be safe in a multi-tenant environment\n+2. Securing Kubernetes should be easy\n+\n+This document uses the \"[CIA triad](https://en.wikipedia.org/wiki/Information_security#Key_concepts)\" for analyzing these goals.\n+\n+# Kubernetes API access controls\n+\n+Kubernetes needs access controls capable of protecting the CIA of cluster\n+resources in a multi-tenant environment.\n+\n+## Concerns with method based access controls\n+\n+Many Kubernetes deployments provide method based access control (e.g.,\n+list pods). This is akin to securing \\*nix with permissions on the \"open\"\n+syscall. To allow more than privileged user, ACLs should be placed on nouns, not\n+verbs.\n+\n+## Concerns with implicit relationships\n+\n+Kubernetes' implicit object relationships create subtle dangers.\n+\n+1. The \"create pod\" privilege allows a user to mount a secret, even if the user\n+   cannot \"get secrets\". This is a failure of confidentiality.\n+2. The \"create pod\" privilege can be used to place a pod behind a service, even\n+   if the user cannot \"update service\". This is a failure of integrity.\n+3. The \"create pod\" privilege can be used to place a pod behind a deployment,\n+   which can be used to starve legitimate replicas. This is a failure of\n+   integrity, and availability.\n+\n+This isn't a complete list of such dangers, but it's sufficient to show that\n+access controls on an object are insufficient to guarantee CIA. Access controls\n+are also needed on the relationships between objects.\n+\n+## Label ACLs (implicit ownership)\n+\n+Label ACLs are sometimes suggested as a method to provide access control on\n+object-object relationships. Special permissions would be required to create or\n+query an ACL'ed label. This approach is both complex and insufficient.\n+\n+1. The accidental omission of a label means that the system fails open.\n+2. It becomes increasingly difficult to reason about permissions, especially if\n+   set-based label selectors are used.\n+3. Can ACLs be created on existing labels?\n+   1. Yes: clients can be locked out of their workloads.\n+   2. No: workloads must be restarted to change permissions.\n+\n+This approach also perturbs the existing behavior of label selectors. Does the\n+\"list pod\" permission allow me to see pods with contentious ACLs? What about\n+\"list secrets\"?\n+\n+Finally, this approach is insufficent, because not all relationships are defined\n+by label selectors. Notably, secrets cannot be protected by label ACLs.\n+\n+## Explicit \"ownership\" (recommended)\n+\n+Explicit owners can be used to limit access to both objects and relationships. A\n+service would reject both unauthorized changes to its body, and unauthorized\n+pods as backends.\n+\n+The simplicity and correctness of this method recommend it.\n+\n+### Namespace as \"owner\"\n+\n+By scoping method permissions to namespaces, a crude ownership model can be\n+constructed (all objects are owned by a namespace, and object-object\n+relationships must have the same owner). The advantage of this approach is that\n+it's possible today.\n+\n+There are also disadvantages to this method.\n+\n+1. Not all resources are namespaced (e.g., nodes and volumes)\n+2. The myriad escalations and CIA failures make it harder to [separate\n+   privileges](https://en.wikipedia.org/wiki/Privilege_separation)\n+   within a namespace.","path":"contributors/design-proposals/security-model.md","position":79,"original_position":79,"commit_id":"399861831da685703543497ebf54ed479c56ed76","original_commit_id":"399861831da685703543497ebf54ed479c56ed76","user":{"login":"smarterclayton","id":1163175,"avatar_url":"https://avatars3.githubusercontent.com/u/1163175?v=3","gravatar_id":"","url":"https://api.github.com/users/smarterclayton","html_url":"https://github.com/smarterclayton","followers_url":"https://api.github.com/users/smarterclayton/followers","following_url":"https://api.github.com/users/smarterclayton/following{/other_user}","gists_url":"https://api.github.com/users/smarterclayton/gists{/gist_id}","starred_url":"https://api.github.com/users/smarterclayton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smarterclayton/subscriptions","organizations_url":"https://api.github.com/users/smarterclayton/orgs","repos_url":"https://api.github.com/users/smarterclayton/repos","events_url":"https://api.github.com/users/smarterclayton/events{/privacy}","received_events_url":"https://api.github.com/users/smarterclayton/received_events","type":"User","site_admin":false},"body":"Note that separating privileges within a namespace has never been a core goal of Kubernetes - the original security model explicitly describes namespaces as a security boundary, rather than within a namespace.  Sub-namespace separation should be possible, although I don't know that I think it is required if namespace separation can better model actual user intent.","created_at":"2017-04-13T04:22:34Z","updated_at":"2017-04-13T04:22:34Z","html_url":"https://github.com/kubernetes/community/pull/532#discussion_r111309323","pull_request_url":"https://api.github.com/repos/kubernetes/community/pulls/532","_links":{"self":{"href":"https://api.github.com/repos/kubernetes/community/pulls/comments/111309323"},"html":{"href":"https://github.com/kubernetes/community/pull/532#discussion_r111309323"},"pull_request":{"href":"https://api.github.com/repos/kubernetes/community/pulls/532"}}},"pull_request":{"url":"https://api.github.com/repos/kubernetes/community/pulls/532","id":115667210,"html_url":"https://github.com/kubernetes/community/pull/532","diff_url":"https://github.com/kubernetes/community/pull/532.diff","patch_url":"https://github.com/kubernetes/community/pull/532.patch","issue_url":"https://api.github.com/repos/kubernetes/community/issues/532","number":532,"state":"open","locked":false,"title":"High-level discussion of k8s' security model for user-facing surfaces.","user":{"login":"Q-Lee","id":13410337,"avatar_url":"https://avatars3.githubusercontent.com/u/13410337?v=3","gravatar_id":"","url":"https://api.github.com/users/Q-Lee","html_url":"https://github.com/Q-Lee","followers_url":"https://api.github.com/users/Q-Lee/followers","following_url":"https://api.github.com/users/Q-Lee/following{/other_user}","gists_url":"https://api.github.com/users/Q-Lee/gists{/gist_id}","starred_url":"https://api.github.com/users/Q-Lee/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Q-Lee/subscriptions","organizations_url":"https://api.github.com/users/Q-Lee/orgs","repos_url":"https://api.github.com/users/Q-Lee/repos","events_url":"https://api.github.com/users/Q-Lee/events{/privacy}","received_events_url":"https://api.github.com/users/Q-Lee/received_events","type":"User","site_admin":false},"body":"This is a little different from Clayton's threat model (#504), but has a non-zero intersection.\r\n\r\nI would like to nail down the direction for Kubernetes' security model.","created_at":"2017-04-13T01:23:25Z","updated_at":"2017-04-13T04:22:34Z","closed_at":null,"merged_at":null,"merge_commit_sha":"131db4384c8d8471e440247317ac78c91f45c6f8","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/kubernetes/community/pulls/532/commits","review_comments_url":"https://api.github.com/repos/kubernetes/community/pulls/532/comments","review_comment_url":"https://api.github.com/repos/kubernetes/community/pulls/comments{/number}","comments_url":"https://api.github.com/repos/kubernetes/community/issues/532/comments","statuses_url":"https://api.github.com/repos/kubernetes/community/statuses/399861831da685703543497ebf54ed479c56ed76","head":{"label":"Q-Lee:master","ref":"master","sha":"399861831da685703543497ebf54ed479c56ed76","user":{"login":"Q-Lee","id":13410337,"avatar_url":"https://avatars3.githubusercontent.com/u/13410337?v=3","gravatar_id":"","url":"https://api.github.com/users/Q-Lee","html_url":"https://github.com/Q-Lee","followers_url":"https://api.github.com/users/Q-Lee/followers","following_url":"https://api.github.com/users/Q-Lee/following{/other_user}","gists_url":"https://api.github.com/users/Q-Lee/gists{/gist_id}","starred_url":"https://api.github.com/users/Q-Lee/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Q-Lee/subscriptions","organizations_url":"https://api.github.com/users/Q-Lee/orgs","repos_url":"https://api.github.com/users/Q-Lee/repos","events_url":"https://api.github.com/users/Q-Lee/events{/privacy}","received_events_url":"https://api.github.com/users/Q-Lee/received_events","type":"User","site_admin":false},"repo":{"id":87246008,"name":"community","full_name":"Q-Lee/community","owner":{"login":"Q-Lee","id":13410337,"avatar_url":"https://avatars3.githubusercontent.com/u/13410337?v=3","gravatar_id":"","url":"https://api.github.com/users/Q-Lee","html_url":"https://github.com/Q-Lee","followers_url":"https://api.github.com/users/Q-Lee/followers","following_url":"https://api.github.com/users/Q-Lee/following{/other_user}","gists_url":"https://api.github.com/users/Q-Lee/gists{/gist_id}","starred_url":"https://api.github.com/users/Q-Lee/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Q-Lee/subscriptions","organizations_url":"https://api.github.com/users/Q-Lee/orgs","repos_url":"https://api.github.com/users/Q-Lee/repos","events_url":"https://api.github.com/users/Q-Lee/events{/privacy}","received_events_url":"https://api.github.com/users/Q-Lee/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Q-Lee/community","description":"Kubernetes community content","fork":true,"url":"https://api.github.com/repos/Q-Lee/community","forks_url":"https://api.github.com/repos/Q-Lee/community/forks","keys_url":"https://api.github.com/repos/Q-Lee/community/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Q-Lee/community/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Q-Lee/community/teams","hooks_url":"https://api.github.com/repos/Q-Lee/community/hooks","issue_events_url":"https://api.github.com/repos/Q-Lee/community/issues/events{/number}","events_url":"https://api.github.com/repos/Q-Lee/community/events","assignees_url":"https://api.github.com/repos/Q-Lee/community/assignees{/user}","branches_url":"https://api.github.com/repos/Q-Lee/community/branches{/branch}","tags_url":"https://api.github.com/repos/Q-Lee/community/tags","blobs_url":"https://api.github.com/repos/Q-Lee/community/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Q-Lee/community/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Q-Lee/community/git/refs{/sha}","trees_url":"https://api.github.com/repos/Q-Lee/community/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Q-Lee/community/statuses/{sha}","languages_url":"https://api.github.com/repos/Q-Lee/community/languages","stargazers_url":"https://api.github.com/repos/Q-Lee/community/stargazers","contributors_url":"https://api.github.com/repos/Q-Lee/community/contributors","subscribers_url":"https://api.github.com/repos/Q-Lee/community/subscribers","subscription_url":"https://api.github.com/repos/Q-Lee/community/subscription","commits_url":"https://api.github.com/repos/Q-Lee/community/commits{/sha}","git_commits_url":"https://api.github.com/repos/Q-Lee/community/git/commits{/sha}","comments_url":"https://api.github.com/repos/Q-Lee/community/comments{/number}","issue_comment_url":"https://api.github.com/repos/Q-Lee/community/issues/comments{/number}","contents_url":"https://api.github.com/repos/Q-Lee/community/contents/{+path}","compare_url":"https://api.github.com/repos/Q-Lee/community/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Q-Lee/community/merges","archive_url":"https://api.github.com/repos/Q-Lee/community/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Q-Lee/community/downloads","issues_url":"https://api.github.com/repos/Q-Lee/community/issues{/number}","pulls_url":"https://api.github.com/repos/Q-Lee/community/pulls{/number}","milestones_url":"https://api.github.com/repos/Q-Lee/community/milestones{/number}","notifications_url":"https://api.github.com/repos/Q-Lee/community/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Q-Lee/community/labels{/name}","releases_url":"https://api.github.com/repos/Q-Lee/community/releases{/id}","deployments_url":"https://api.github.com/repos/Q-Lee/community/deployments","created_at":"2017-04-04T23:50:46Z","updated_at":"2017-04-04T23:50:48Z","pushed_at":"2017-04-10T17:35:56Z","git_url":"git://github.com/Q-Lee/community.git","ssh_url":"git@github.com:Q-Lee/community.git","clone_url":"https://github.com/Q-Lee/community.git","svn_url":"https://github.com/Q-Lee/community","homepage":"","size":7574,"stargazers_count":0,"watchers_count":0,"language":"Makefile","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"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":"kubernetes:master","ref":"master","sha":"b3ef6e2800935b10284b9f32ebbfa86c0c625dda","user":{"login":"kubernetes","id":13629408,"avatar_url":"https://avatars1.githubusercontent.com/u/13629408?v=3","gravatar_id":"","url":"https://api.github.com/users/kubernetes","html_url":"https://github.com/kubernetes","followers_url":"https://api.github.com/users/kubernetes/followers","following_url":"https://api.github.com/users/kubernetes/following{/other_user}","gists_url":"https://api.github.com/users/kubernetes/gists{/gist_id}","starred_url":"https://api.github.com/users/kubernetes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kubernetes/subscriptions","organizations_url":"https://api.github.com/users/kubernetes/orgs","repos_url":"https://api.github.com/users/kubernetes/repos","events_url":"https://api.github.com/users/kubernetes/events{/privacy}","received_events_url":"https://api.github.com/users/kubernetes/received_events","type":"Organization","site_admin":false},"repo":{"id":57939112,"name":"community","full_name":"kubernetes/community","owner":{"login":"kubernetes","id":13629408,"avatar_url":"https://avatars1.githubusercontent.com/u/13629408?v=3","gravatar_id":"","url":"https://api.github.com/users/kubernetes","html_url":"https://github.com/kubernetes","followers_url":"https://api.github.com/users/kubernetes/followers","following_url":"https://api.github.com/users/kubernetes/following{/other_user}","gists_url":"https://api.github.com/users/kubernetes/gists{/gist_id}","starred_url":"https://api.github.com/users/kubernetes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kubernetes/subscriptions","organizations_url":"https://api.github.com/users/kubernetes/orgs","repos_url":"https://api.github.com/users/kubernetes/repos","events_url":"https://api.github.com/users/kubernetes/events{/privacy}","received_events_url":"https://api.github.com/users/kubernetes/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/kubernetes/community","description":"Kubernetes community content","fork":false,"url":"https://api.github.com/repos/kubernetes/community","forks_url":"https://api.github.com/repos/kubernetes/community/forks","keys_url":"https://api.github.com/repos/kubernetes/community/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kubernetes/community/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kubernetes/community/teams","hooks_url":"https://api.github.com/repos/kubernetes/community/hooks","issue_events_url":"https://api.github.com/repos/kubernetes/community/issues/events{/number}","events_url":"https://api.github.com/repos/kubernetes/community/events","assignees_url":"https://api.github.com/repos/kubernetes/community/assignees{/user}","branches_url":"https://api.github.com/repos/kubernetes/community/branches{/branch}","tags_url":"https://api.github.com/repos/kubernetes/community/tags","blobs_url":"https://api.github.com/repos/kubernetes/community/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kubernetes/community/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kubernetes/community/git/refs{/sha}","trees_url":"https://api.github.com/repos/kubernetes/community/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kubernetes/community/statuses/{sha}","languages_url":"https://api.github.com/repos/kubernetes/community/languages","stargazers_url":"https://api.github.com/repos/kubernetes/community/stargazers","contributors_url":"https://api.github.com/repos/kubernetes/community/contributors","subscribers_url":"https://api.github.com/repos/kubernetes/community/subscribers","subscription_url":"https://api.github.com/repos/kubernetes/community/subscription","commits_url":"https://api.github.com/repos/kubernetes/community/commits{/sha}","git_commits_url":"https://api.github.com/repos/kubernetes/community/git/commits{/sha}","comments_url":"https://api.github.com/repos/kubernetes/community/comments{/number}","issue_comment_url":"https://api.github.com/repos/kubernetes/community/issues/comments{/number}","contents_url":"https://api.github.com/repos/kubernetes/community/contents/{+path}","compare_url":"https://api.github.com/repos/kubernetes/community/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kubernetes/community/merges","archive_url":"https://api.github.com/repos/kubernetes/community/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kubernetes/community/downloads","issues_url":"https://api.github.com/repos/kubernetes/community/issues{/number}","pulls_url":"https://api.github.com/repos/kubernetes/community/pulls{/number}","milestones_url":"https://api.github.com/repos/kubernetes/community/milestones{/number}","notifications_url":"https://api.github.com/repos/kubernetes/community/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kubernetes/community/labels{/name}","releases_url":"https://api.github.com/repos/kubernetes/community/releases{/id}","deployments_url":"https://api.github.com/repos/kubernetes/community/deployments","created_at":"2016-05-03T03:36:05Z","updated_at":"2017-04-12T17:54:46Z","pushed_at":"2017-04-13T01:55:55Z","git_url":"git://github.com/kubernetes/community.git","ssh_url":"git@github.com:kubernetes/community.git","clone_url":"https://github.com/kubernetes/community.git","svn_url":"https://github.com/kubernetes/community","homepage":"","size":8084,"stargazers_count":328,"watchers_count":328,"language":"Makefile","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":311,"mirror_url":null,"open_issues_count":118,"forks":311,"open_issues":118,"watchers":328,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/kubernetes/community/pulls/532"},"html":{"href":"https://github.com/kubernetes/community/pull/532"},"issue":{"href":"https://api.github.com/repos/kubernetes/community/issues/532"},"comments":{"href":"https://api.github.com/repos/kubernetes/community/issues/532/comments"},"review_comments":{"href":"https://api.github.com/repos/kubernetes/community/pulls/532/comments"},"review_comment":{"href":"https://api.github.com/repos/kubernetes/community/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/kubernetes/community/pulls/532/commits"},"statuses":{"href":"https://api.github.com/repos/kubernetes/community/statuses/399861831da685703543497ebf54ed479c56ed76"}}}}
{"actor":{"display_login":"smarterclayton"}}