{"action":"created","comment":{"url":"https://api.github.com/repos/openshift/origin/pulls/comments/91299370","pull_request_review_id":11805333,"id":91299370,"diff_hunk":"@@ -0,0 +1,129 @@\n+# Image Signing\n+\n+## Abstract\n+\n+This proposal describes the process of verifying the signatures of Docker Images and\n+enforce enforce policy that will prevent the image from running in the cluster if the\n+image signature is not trusted.\n+\n+## Use-cases\n+\n+* As an admin, I want to be able to add trusted GPG public keys to my cluster and determine through policy\n+  the keys that are required to run certain images\n+* As an user, I want to be able to see what images are signed and if the signature is trusted\n+\n+## Overview\n+\n+### Signing Images with Skopeo\n+\n+The current signing mechanism for Docker image is to use the\n+[Skopeo](https://github.com/projectatomic/skopeo/blob/master/docs/skopeo.1.md) tool which\n+will sign the Docker image locally, using the GPG key and attach the signature to the\n+Docker Image. The Docker image is then pushed to a Docker Registry with enabled signature\n+storage.\n+\n+Signature verification [policy\n+files](https://github.com/containers/image/blob/master/docs/policy.json.md) are used to\n+define policy, e.g. trusted keys, applicable when deciding whether to accept an image, or\n+individual signatures of that image, as valid:\n+\n+```json\n+{\n+  \"default\": [{\"type\": \"reject\"}],\n+  \"transports\": {\n+    \"atomic\": {\n+      \"172.30.62.231:5000\": [\n+      {\n+        \"type\": \"signedBy\",\n+        \"keyType\": \"GPGKeys\",\n+        \"keyPath\": \"/keys/public.gpg\"\n+      }\n+      ]\n+    },\n+    \"docker\": {\n+      \"docker.io/openshift\": [{\"type\": \"insecureAcceptAnything\"}]\n+    }\n+  }\n+}\n+```\n+\n+In this example, the default policy is set to reject all Docker images by default and\n+whitelist only images that are pushed in the OpenShift Integrated Registry and signed\n+using the public GPG key.\n+It also whitelists all Docker images from the OpenShift DockerHub repository.\n+\n+To sign an Docker image, you have to execute the following command:\n+\n+```console\n+$ skopeo --tls-verify=false copy --sign-by user@example.com docker://docker.io/myrepo/image:latest \\\n+  atomic:172.30.74.246:5000/mynamespce/image:latest\n+```\n+\n+When this command is executed, skopeo will ask you to enter the password the\n+*user@example.com* GPG key, sign the local image and push the signed image into OpenShift\n+Integrated Registry.\n+\n+### Kubernetes `ImagePolicyWebhook` Admission Controller\n+\n+Kubernetes provides the\n+[ImagePolicyWebhook](http://kubernetes.io/docs/admin/admission-controllers/#imagepolicywebhook)\n+to allow a backend webhook to make admission decisions about whether an image specified by\n+the container inside a Pod is allowed to run in the cluster or not.\n+\n+To configure this you have to specify a backed HTTPS service that Kubernetes will send the\n+`ImageReview` objects as a payload, expecting the `ImageReview` in return with the\n+*status* field set to indicate allowance or rejection of the image(s).\n+\n+## Assumptions and Constraints\n+\n+The assumption is that we provide a HTTPS backend that implements the `ImagePolicyWebhook`\n+by making calls into Skopeo [go library](https://github.com/containers/image) to evaluate\n+the policy.json file provided by the cluster admin.\n+\n+Kubernetes requirements for the ImagePolicyWebhook backend are:\n+\n+* The admission controller config file (`--admission-controller-config-file`) to set configuration options for\n+  the behavior of the backend\n+* The admission config file must reference a kubeconfig formatted file which sets up the connection\n+  to the backend\n+* The backend must communicate over TLS\n+\n+The image verification backend requirements are:\n+\n+* Policy file must be provided\n+* All public GPG keys must be available for the the backend server\n+* The backend must have view access to all images in the registry specified in policy file\n+\n+The assumption is then that we will run the backend HTTPS server as a part of OpenShift\n+infrastructure, similar to how we run Docker Registry or the HAProxy router.\n+\n+### Policy\n+\n+The policy must be provided in order for Skopeo to match the provided image with the rules\n+and public GPG keys. There are couple possibilities how the policy file might be provided\n+to the backend server:\n+\n+* A `ConfigMap` provided by the cluster administrator with custom policies set based on","path":"docs/proposals/image-signing.md","position":106,"original_position":106,"commit_id":"46f30d97b252fe9ff2ae008872099be1250e770a","original_commit_id":"46f30d97b252fe9ff2ae008872099be1250e770a","user":{"login":"pweil-","id":5230419,"avatar_url":"https://avatars.githubusercontent.com/u/5230419?v=3","gravatar_id":"","url":"https://api.github.com/users/pweil-","html_url":"https://github.com/pweil-","followers_url":"https://api.github.com/users/pweil-/followers","following_url":"https://api.github.com/users/pweil-/following{/other_user}","gists_url":"https://api.github.com/users/pweil-/gists{/gist_id}","starred_url":"https://api.github.com/users/pweil-/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pweil-/subscriptions","organizations_url":"https://api.github.com/users/pweil-/orgs","repos_url":"https://api.github.com/users/pweil-/repos","events_url":"https://api.github.com/users/pweil-/events{/privacy}","received_events_url":"https://api.github.com/users/pweil-/received_events","type":"User","site_admin":false},"body":"Also discuss why we do or do not need a per-namespace policy","created_at":"2016-12-07T14:10:06Z","updated_at":"2016-12-07T14:10:52Z","html_url":"https://github.com/openshift/origin/pull/12170#discussion_r91299370","pull_request_url":"https://api.github.com/repos/openshift/origin/pulls/12170","_links":{"self":{"href":"https://api.github.com/repos/openshift/origin/pulls/comments/91299370"},"html":{"href":"https://github.com/openshift/origin/pull/12170#discussion_r91299370"},"pull_request":{"href":"https://api.github.com/repos/openshift/origin/pulls/12170"}}},"pull_request":{"url":"https://api.github.com/repos/openshift/origin/pulls/12170","id":96907941,"html_url":"https://github.com/openshift/origin/pull/12170","diff_url":"https://github.com/openshift/origin/pull/12170.diff","patch_url":"https://github.com/openshift/origin/pull/12170.patch","issue_url":"https://api.github.com/repos/openshift/origin/issues/12170","number":12170,"state":"open","locked":false,"title":"Proposal: Use ImagePolicyWebhook to verify image signatures","user":{"login":"mfojtik","id":44136,"avatar_url":"https://avatars.githubusercontent.com/u/44136?v=3","gravatar_id":"","url":"https://api.github.com/users/mfojtik","html_url":"https://github.com/mfojtik","followers_url":"https://api.github.com/users/mfojtik/followers","following_url":"https://api.github.com/users/mfojtik/following{/other_user}","gists_url":"https://api.github.com/users/mfojtik/gists{/gist_id}","starred_url":"https://api.github.com/users/mfojtik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mfojtik/subscriptions","organizations_url":"https://api.github.com/users/mfojtik/orgs","repos_url":"https://api.github.com/users/mfojtik/repos","events_url":"https://api.github.com/users/mfojtik/events{/privacy}","received_events_url":"https://api.github.com/users/mfojtik/received_events","type":"User","site_admin":false},"body":"This proposal describes the process of verifying the signatures of Docker Images and\r\nenforce enforce policy that will prevent the image from running in the cluster if the\r\nimage signature is not trusted.\r\n\r\nPOC: https://github.com/openshift/origin/compare/master...mfojtik:image-signing?expand=1","created_at":"2016-12-07T11:44:22Z","updated_at":"2016-12-07T14:10:52Z","closed_at":null,"merged_at":null,"merge_commit_sha":"187dd19b6d684c678dfab8e7d1e7787e48e9257a","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/openshift/origin/pulls/12170/commits","review_comments_url":"https://api.github.com/repos/openshift/origin/pulls/12170/comments","review_comment_url":"https://api.github.com/repos/openshift/origin/pulls/comments{/number}","comments_url":"https://api.github.com/repos/openshift/origin/issues/12170/comments","statuses_url":"https://api.github.com/repos/openshift/origin/statuses/46f30d97b252fe9ff2ae008872099be1250e770a","head":{"label":"mfojtik:image-signing-proposal","ref":"image-signing-proposal","sha":"46f30d97b252fe9ff2ae008872099be1250e770a","user":{"login":"mfojtik","id":44136,"avatar_url":"https://avatars.githubusercontent.com/u/44136?v=3","gravatar_id":"","url":"https://api.github.com/users/mfojtik","html_url":"https://github.com/mfojtik","followers_url":"https://api.github.com/users/mfojtik/followers","following_url":"https://api.github.com/users/mfojtik/following{/other_user}","gists_url":"https://api.github.com/users/mfojtik/gists{/gist_id}","starred_url":"https://api.github.com/users/mfojtik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mfojtik/subscriptions","organizations_url":"https://api.github.com/users/mfojtik/orgs","repos_url":"https://api.github.com/users/mfojtik/repos","events_url":"https://api.github.com/users/mfojtik/events{/privacy}","received_events_url":"https://api.github.com/users/mfojtik/received_events","type":"User","site_admin":false},"repo":{"id":22954249,"name":"origin","full_name":"mfojtik/origin","owner":{"login":"mfojtik","id":44136,"avatar_url":"https://avatars.githubusercontent.com/u/44136?v=3","gravatar_id":"","url":"https://api.github.com/users/mfojtik","html_url":"https://github.com/mfojtik","followers_url":"https://api.github.com/users/mfojtik/followers","following_url":"https://api.github.com/users/mfojtik/following{/other_user}","gists_url":"https://api.github.com/users/mfojtik/gists{/gist_id}","starred_url":"https://api.github.com/users/mfojtik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mfojtik/subscriptions","organizations_url":"https://api.github.com/users/mfojtik/orgs","repos_url":"https://api.github.com/users/mfojtik/repos","events_url":"https://api.github.com/users/mfojtik/events{/privacy}","received_events_url":"https://api.github.com/users/mfojtik/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mfojtik/origin","description":"OpenShift 3 - build, deploy, and manage your applications with Docker and Kubernetes","fork":true,"url":"https://api.github.com/repos/mfojtik/origin","forks_url":"https://api.github.com/repos/mfojtik/origin/forks","keys_url":"https://api.github.com/repos/mfojtik/origin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mfojtik/origin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mfojtik/origin/teams","hooks_url":"https://api.github.com/repos/mfojtik/origin/hooks","issue_events_url":"https://api.github.com/repos/mfojtik/origin/issues/events{/number}","events_url":"https://api.github.com/repos/mfojtik/origin/events","assignees_url":"https://api.github.com/repos/mfojtik/origin/assignees{/user}","branches_url":"https://api.github.com/repos/mfojtik/origin/branches{/branch}","tags_url":"https://api.github.com/repos/mfojtik/origin/tags","blobs_url":"https://api.github.com/repos/mfojtik/origin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mfojtik/origin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mfojtik/origin/git/refs{/sha}","trees_url":"https://api.github.com/repos/mfojtik/origin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mfojtik/origin/statuses/{sha}","languages_url":"https://api.github.com/repos/mfojtik/origin/languages","stargazers_url":"https://api.github.com/repos/mfojtik/origin/stargazers","contributors_url":"https://api.github.com/repos/mfojtik/origin/contributors","subscribers_url":"https://api.github.com/repos/mfojtik/origin/subscribers","subscription_url":"https://api.github.com/repos/mfojtik/origin/subscription","commits_url":"https://api.github.com/repos/mfojtik/origin/commits{/sha}","git_commits_url":"https://api.github.com/repos/mfojtik/origin/git/commits{/sha}","comments_url":"https://api.github.com/repos/mfojtik/origin/comments{/number}","issue_comment_url":"https://api.github.com/repos/mfojtik/origin/issues/comments{/number}","contents_url":"https://api.github.com/repos/mfojtik/origin/contents/{+path}","compare_url":"https://api.github.com/repos/mfojtik/origin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mfojtik/origin/merges","archive_url":"https://api.github.com/repos/mfojtik/origin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mfojtik/origin/downloads","issues_url":"https://api.github.com/repos/mfojtik/origin/issues{/number}","pulls_url":"https://api.github.com/repos/mfojtik/origin/pulls{/number}","milestones_url":"https://api.github.com/repos/mfojtik/origin/milestones{/number}","notifications_url":"https://api.github.com/repos/mfojtik/origin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mfojtik/origin/labels{/name}","releases_url":"https://api.github.com/repos/mfojtik/origin/releases{/id}","deployments_url":"https://api.github.com/repos/mfojtik/origin/deployments","created_at":"2014-08-14T13:11:47Z","updated_at":"2016-01-12T09:38:06Z","pushed_at":"2016-12-07T14:06:41Z","git_url":"git://github.com/mfojtik/origin.git","ssh_url":"git@github.com:mfojtik/origin.git","clone_url":"https://github.com/mfojtik/origin.git","svn_url":"https://github.com/mfojtik/origin","homepage":"https://openshift.github.io","size":421147,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"openshift:master","ref":"master","sha":"5c6a1d473c6a5a1a15ede004f0fb86aeae6d339b","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 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-12-07T08:48:08Z","pushed_at":"2016-12-07T14:06:42Z","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":675573,"stargazers_count":2113,"watchers_count":2113,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1403,"mirror_url":null,"open_issues_count":1167,"forks":1403,"open_issues":1167,"watchers":2113,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/openshift/origin/pulls/12170"},"html":{"href":"https://github.com/openshift/origin/pull/12170"},"issue":{"href":"https://api.github.com/repos/openshift/origin/issues/12170"},"comments":{"href":"https://api.github.com/repos/openshift/origin/issues/12170/comments"},"review_comments":{"href":"https://api.github.com/repos/openshift/origin/pulls/12170/comments"},"review_comment":{"href":"https://api.github.com/repos/openshift/origin/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/openshift/origin/pulls/12170/commits"},"statuses":{"href":"https://api.github.com/repos/openshift/origin/statuses/46f30d97b252fe9ff2ae008872099be1250e770a"}}}}
{"actor":{"display_login":"pweil-"}}