{"action":"created","comment":{"url":"https://api.github.com/repos/openshift/origin/pulls/comments/74069519","id":74069519,"diff_hunk":"@@ -0,0 +1,111 @@\n+package imagepolicy\n+\n+import (\n+\t\"fmt\"\n+\n+\t\"github.com/golang/glog\"\n+\n+\t\"k8s.io/kubernetes/pkg/admission\"\n+\tapierrs \"k8s.io/kubernetes/pkg/api/errors\"\n+\t\"k8s.io/kubernetes/pkg/api/unversioned\"\n+\t\"k8s.io/kubernetes/pkg/util/sets\"\n+\t\"k8s.io/kubernetes/pkg/util/validation/field\"\n+\n+\t\"github.com/openshift/origin/pkg/api/meta\"\n+\t\"github.com/openshift/origin/pkg/image/admission/imagepolicy/rules\"\n+\timageapi \"github.com/openshift/origin/pkg/image/api\"\n+)\n+\n+var errRejectByPolicy = fmt.Errorf(\"this image is prohibited by policy\")\n+\n+func accept(accepter rules.Accepter, resolver imageResolver, m meta.ImageReferenceMutator, attr admission.Attributes, covered policyAttributes, excludedRules sets.String) error {\n+\tgr := attr.GetResource().GroupResource()\n+\trequiresImage := accepter.RequiresImage(gr)\n+\tresolvesImage := accepter.ResolvesImage(gr)\n+\n+\terrs := m.Mutate(func(image string) (string, error) {\n+\t\tok, newImage, err := acceptImage(accepter, resolver, image, gr, covered, requiresImage, resolvesImage, excludedRules)\n+\t\tif err != nil {\n+\t\t\treturn image, err\n+\t\t}\n+\t\tif !ok {\n+\t\t\treturn image, errRejectByPolicy\n+\t\t}\n+\t\treturn newImage, nil\n+\t})\n+\n+\tfor i := range errs {\n+\t\tif errs[i].Detail == errRejectByPolicy.Error() {\n+\t\t\terrs[i].Type = field.ErrorTypeForbidden\n+\t\t} else {\n+\t\t\terrs[i].Detail = fmt.Sprintf(\"this image is prohibited by policy: %s\", errs[i].Detail)\n+\t\t}\n+\t}\n+\n+\tif len(errs) > 0 {\n+\t\tglog.V(5).Infof(\"failed to create: %v\", errs)\n+\t\treturn apierrs.NewInvalid(attr.GetKind().GroupKind(), attr.GetName(), errs)\n+\t}\n+\tglog.V(5).Infof(\"allowed: %#v\", attr)\n+\treturn nil\n+}\n+\n+func acceptImage(accepter rules.Accepter, resolver imageResolver, name string, gr unversioned.GroupResource, covered policyAttributes, requiresImage, resolvesImage bool, excludedRules sets.String) (bool, string, error) {\n+\t// only resolve the image once per pod\n+\tif covered.Has(name) {\n+\t\treturn true, name, nil\n+\t}\n+\t// explicitly allow empty strings to bypass checks\n+\tif len(name) == 0 {\n+\t\treturn true, name, nil\n+\t}\n+\n+\tref, err := imageapi.ParseDockerImageReference(name)\n+\tif err != nil {\n+\t\treturn false, name, err\n+\t}\n+\n+\t// check the decision cache if we've already made a decision on the image\n+\t// TODO: time bound the decision cache so that namespace overrides can take effect\n+\tisDigest := len(ref.ID) > 0\n+\n+\tvar image *imageapi.Image\n+\toriginalName := name\n+\tif requiresImage || (!isDigest && resolvesImage) {\n+\t\timage, err = resolver.Resolve(ref)\n+\t\tswitch {\n+\t\tcase apierrs.IsNotFound(err) && !resolvesImage:\n+\t\t\t// if the referenced image does not exist, and resolution is not required, we'll let\n+\t\t\t// the policy rule decide whether to fail\n+\t\tcase err != nil:\n+\t\t\treturn false, name, err\n+\t\tdefault:\n+\t\t\tglog.V(5).Infof(\"Resolved image %v to %s (%s)\", ref, image.Name, image.DockerImageReference)\n+\t\t\t// resolve the reference to a digest, rather than a tag\n+\t\t\tref.Tag = \"\"\n+\t\t\tref.ID = image.Name\n+\n+\t\t\t// if we should resolve the image, update the image and also check the cache again\n+\t\t\tif resolvesImage {\n+\t\t\t\tname = ref.Exact()\n+\t\t\t\tisDigest = true\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tattr := &rules.ImagePolicyAttributes{\n+\t\tName:          ref,\n+\t\tOriginalName:  name,\n+\t\tResource:      gr,\n+\t\tImage:         image,\n+\t\tExcludedRules: excludedRules,\n+\t}\n+\t// remember under both names\n+\tcovered.Remember(name, attr)\n+\tcovered.Remember(originalName, attr)","path":"pkg/image/admission/imagepolicy/accept.go","position":105,"original_position":105,"commit_id":"f0c24e731883095660d13951792d6b39faa8018e","original_commit_id":"f0c24e731883095660d13951792d6b39faa8018e","user":{"login":"smarterclayton","id":1163175,"avatar_url":"https://avatars.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":"If you're attaching that to the comment above, yes, this is a bug.\n\nOn Tue, Aug 9, 2016 at 9:10 AM, David Eads <notifications@github.com> wrote:\n\n> In pkg/image/admission/imagepolicy/accept.go\n> <https://github.com/openshift/origin/pull/8995#discussion_r74053944>:\n>\n> > +\t\t\t\tname = ref.Exact()\n> > +\t\t\t\tisDigest = true\n> > +\t\t\t}\n> > +\t\t}\n> > +\t}\n> > +\n> > +\tattr := &rules.ImagePolicyAttributes{\n> > +\t\tName:          ref,\n> > +\t\tOriginalName:  name,\n> > +\t\tResource:      gr,\n> > +\t\tImage:         image,\n> > +\t\tExcludedRules: excludedRules,\n> > +\t}\n> > +\t// remember under both names\n> > +\tcovered.Remember(name, attr)\n> > +\tcovered.Remember(originalName, attr)\n>\n> I think this causes problems when you're trying to force resolution. You\n> can end up looking up the old name and not getting the new name you\n> normally return.\n>\n> —\n> You are receiving this because you authored the thread.\n> Reply to this email directly, view it on GitHub\n> <https://github.com/openshift/origin/pull/8995/files/f0c24e731883095660d13951792d6b39faa8018e#r74053944>,\n> or mute the thread\n> <https://github.com/notifications/unsubscribe-auth/ABG_p-wU4Pp8W__b8RtWEWtquZuH24G8ks5qeHwpgaJpZM4IlDlb>\n> .\n>\n","created_at":"2016-08-09T14:31:28Z","updated_at":"2016-08-09T14:31:28Z","html_url":"https://github.com/openshift/origin/pull/8995#discussion_r74069519","pull_request_url":"https://api.github.com/repos/openshift/origin/pulls/8995","_links":{"self":{"href":"https://api.github.com/repos/openshift/origin/pulls/comments/74069519"},"html":{"href":"https://github.com/openshift/origin/pull/8995#discussion_r74069519"},"pull_request":{"href":"https://api.github.com/repos/openshift/origin/pulls/8995"}}},"pull_request":{"url":"https://api.github.com/repos/openshift/origin/pulls/8995","id":71149999,"html_url":"https://github.com/openshift/origin/pull/8995","diff_url":"https://github.com/openshift/origin/pull/8995.diff","patch_url":"https://github.com/openshift/origin/pull/8995.patch","issue_url":"https://api.github.com/repos/openshift/origin/issues/8995","number":8995,"state":"open","locked":false,"title":"Enable a simple image policy admission controller","user":{"login":"smarterclayton","id":1163175,"avatar_url":"https://avatars.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":"This adds an admission controller to OpenShift which can do the following:\r\n\r\n1. Allow admins to reject images that do not resolve to images stored on the cluster\r\n2. Allow admins to reject images with certain annotations, docker image labels, or image labels\r\n3. Allow admins to force images to associate a resource cost with an image (whether arbitrary counted, like \"license.jboss\" = \"1\", or an existing resource like \"cpu\")\r\n4. Allow images to force images to have a node selector constraint associated with them, based on a hardcoded value.\r\n\r\nOpen items:\r\n\r\n1. Allow an admin to bypass policy rules on a per namespace basis\r\n2. Allow an admin/service account to bypass policy rules by virtue of privilege (the ability to mutate images may be considered sufficient)\r\n3. Allow tolerations to be enforced by virtue of image metadata\r\n4. Check permissions on the image before allowing the user to create a pod with it.","created_at":"2016-05-24T02:39:17Z","updated_at":"2016-08-09T14:31:29Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2ebf1ae3243fd05c16b9e5d6b99e4e1b3506449d","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/openshift/origin/pulls/8995/commits","review_comments_url":"https://api.github.com/repos/openshift/origin/pulls/8995/comments","review_comment_url":"https://api.github.com/repos/openshift/origin/pulls/comments{/number}","comments_url":"https://api.github.com/repos/openshift/origin/issues/8995/comments","statuses_url":"https://api.github.com/repos/openshift/origin/statuses/f0c24e731883095660d13951792d6b39faa8018e","head":{"label":"smarterclayton:image_policy","ref":"image_policy","sha":"f0c24e731883095660d13951792d6b39faa8018e","user":{"login":"smarterclayton","id":1163175,"avatar_url":"https://avatars.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},"repo":{"id":22921364,"name":"origin","full_name":"smarterclayton/origin","owner":{"login":"smarterclayton","id":1163175,"avatar_url":"https://avatars.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},"private":false,"html_url":"https://github.com/smarterclayton/origin","description":"OpenShift 3 - build, deploy, and manage your applications with Docker and Kubernetes","fork":true,"url":"https://api.github.com/repos/smarterclayton/origin","forks_url":"https://api.github.com/repos/smarterclayton/origin/forks","keys_url":"https://api.github.com/repos/smarterclayton/origin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/smarterclayton/origin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/smarterclayton/origin/teams","hooks_url":"https://api.github.com/repos/smarterclayton/origin/hooks","issue_events_url":"https://api.github.com/repos/smarterclayton/origin/issues/events{/number}","events_url":"https://api.github.com/repos/smarterclayton/origin/events","assignees_url":"https://api.github.com/repos/smarterclayton/origin/assignees{/user}","branches_url":"https://api.github.com/repos/smarterclayton/origin/branches{/branch}","tags_url":"https://api.github.com/repos/smarterclayton/origin/tags","blobs_url":"https://api.github.com/repos/smarterclayton/origin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/smarterclayton/origin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/smarterclayton/origin/git/refs{/sha}","trees_url":"https://api.github.com/repos/smarterclayton/origin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/smarterclayton/origin/statuses/{sha}","languages_url":"https://api.github.com/repos/smarterclayton/origin/languages","stargazers_url":"https://api.github.com/repos/smarterclayton/origin/stargazers","contributors_url":"https://api.github.com/repos/smarterclayton/origin/contributors","subscribers_url":"https://api.github.com/repos/smarterclayton/origin/subscribers","subscription_url":"https://api.github.com/repos/smarterclayton/origin/subscription","commits_url":"https://api.github.com/repos/smarterclayton/origin/commits{/sha}","git_commits_url":"https://api.github.com/repos/smarterclayton/origin/git/commits{/sha}","comments_url":"https://api.github.com/repos/smarterclayton/origin/comments{/number}","issue_comment_url":"https://api.github.com/repos/smarterclayton/origin/issues/comments{/number}","contents_url":"https://api.github.com/repos/smarterclayton/origin/contents/{+path}","compare_url":"https://api.github.com/repos/smarterclayton/origin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/smarterclayton/origin/merges","archive_url":"https://api.github.com/repos/smarterclayton/origin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/smarterclayton/origin/downloads","issues_url":"https://api.github.com/repos/smarterclayton/origin/issues{/number}","pulls_url":"https://api.github.com/repos/smarterclayton/origin/pulls{/number}","milestones_url":"https://api.github.com/repos/smarterclayton/origin/milestones{/number}","notifications_url":"https://api.github.com/repos/smarterclayton/origin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/smarterclayton/origin/labels{/name}","releases_url":"https://api.github.com/repos/smarterclayton/origin/releases{/id}","deployments_url":"https://api.github.com/repos/smarterclayton/origin/deployments","created_at":"2014-08-13T15:49:23Z","updated_at":"2015-08-31T15:42:11Z","pushed_at":"2016-08-09T03:46:01Z","git_url":"git://github.com/smarterclayton/origin.git","ssh_url":"git@github.com:smarterclayton/origin.git","clone_url":"https://github.com/smarterclayton/origin.git","svn_url":"https://github.com/smarterclayton/origin","homepage":"https://openshift.github.io","size":334258,"stargazers_count":1,"watchers_count":1,"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":1,"default_branch":"master"}},"base":{"label":"openshift:master","ref":"master","sha":"6c50f2007a5426aa71a4aaa6e76302e58196c61e","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":"Enterprise-Ready Kubernetes for Developers","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}","deployments_url":"https://api.github.com/repos/openshift/origin/deployments","created_at":"2014-07-30T20:04:05Z","updated_at":"2016-08-09T11:38:14Z","pushed_at":"2016-08-09T14:25:38Z","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":"http://www.openshift.org","size":560126,"stargazers_count":1573,"watchers_count":1573,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":964,"mirror_url":null,"open_issues_count":1086,"forks":964,"open_issues":1086,"watchers":1573,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/openshift/origin/pulls/8995"},"html":{"href":"https://github.com/openshift/origin/pull/8995"},"issue":{"href":"https://api.github.com/repos/openshift/origin/issues/8995"},"comments":{"href":"https://api.github.com/repos/openshift/origin/issues/8995/comments"},"review_comments":{"href":"https://api.github.com/repos/openshift/origin/pulls/8995/comments"},"review_comment":{"href":"https://api.github.com/repos/openshift/origin/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/openshift/origin/pulls/8995/commits"},"statuses":{"href":"https://api.github.com/repos/openshift/origin/statuses/f0c24e731883095660d13951792d6b39faa8018e"}}}}
{"actor":{"display_login":"smarterclayton"}}