GitHub PullRequestReviewCommentEvent at 2014-11-09 22:58:46
Repository: chef-rfc
Actor: seth
Payload: {"action":"created","comment":{"url":"https://api.github.com/repos/opscode/chef-rfc/pulls/comments/20062441","id":20062441,"diff_hunk":"@@ -0,0 +1,235 @@\n+---\n+RFC: unassigned\n+Author: Noah Kantrowitz <noah@coderanger.net>\n+Status: Draft\n+Type: Standards Track\n+---\n+\n+# Token Authentication for Chef Server\n+\n+Currently the Chef Server currently only supports a single authentication method,\n+using RSA signatures and key pairs. This has worked well for chef-client and\n+knife, but it is less convenient for some other use cases. A token-based\n+authentication method would allow for some additional use cases. This would\n+work by passing an opaque token to the Server which is associated with an\n+existing user or client.\n+\n+## Motivation\n+\n+This proposal covers two, unrelated use cases.\n+\n+    As a web interface developer,\n+    I want to have a simpler web application,\n+    so that maintenance is easier.\n+\n+Adding a token authentication system will allow most of the requests to go\n+directly to the Chef Server (once CORS support is handled). This will\n+drastically reduce the number of API endpoints needed for the web UI, most of\n+which are currently just proxies for the relevant Chef Server functionality.\n+\n+    As a security engineer,\n+    I want to accept secure identity assertions,\n+    so that I can implement object-capability systems.\n+\n+Token authentication provides a simple way to prove your identity to an\n+external system. This is the basic building block of an object-capability\n+system.\n+\n+## Specification\n+\n+### Authenticating with a token\n+\n+Token authentication allows passing an opaque string token as a header in\n+Chef Server API requests.\n+\n+```\n+POST /path HTTP/1.1\n+Host: chef.example.com\n+Authorization: Bearer <token>\n+```\n+\n+The token can also be passed as a query parameter, however this is discouraged\n+due to the risk of inadvertently logging or otherwise exposing the token. The\n+Chef Server itself will not log the token, but HTTP proxies could.\n+\n+```\n+GET /path?access_token=<token> HTTP/1.1\n+Host: chef.example.com\n+```\n+\n+In either case, this is equivalent to key-based authentication from the client\n+or user associated with the token. If the token is invalid or expired, the\n+server must respond HTTP 401.\n+\n+The server must ensure tokens are checked using constant-time comparisons to\n+avoid timing attacks.\n+\n+### Generating a token\n+\n+A new token can generated using the token API:\n+\n+```\n+POST /tokens HTTP/1.1\n+Host: chef.example.com\n+X-Ops-...: ...\n+\n+{}\n+```\n+\n+```\n+HTTP/1.1 200 OK\n+\n+{\"token\": \"<token>\", \"created_at\": \"1970-01-01T00:00:00Z\"}\n+```\n+\n+This new token is associated with the client or user that issued the request to\n+create it.\n+\n+Tokens must be 16 characters from the set `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`.\n+\n+A new token can also be generated for a user from their username and password.\n+This API will be limited to the webui key as it is now. This will allow a web\n+interface to entirely avoid using the impersonation key behavior as it does now.\n+\n+```\n+POST /authenticate_user HTTP/1.1\n+Host: chef.example.com\n+X-Ops-...: ...\n+\n+{\"username\": \"<username>\", \"password\": \"<password>\", \"token\": true}\n+```\n+\n+```\n+HTTP/1.1 200 OK\n+\n+{\"token\": \"<token>\", \"linked\": \"<username>\"}\n+```\n+\n+There is no support for making a token for a different client.\n+\n+Tokens can optionally have a description attached to them:\n+\n+```\n+POST /tokens HTTP/1.1\n+Host: chef.example.com\n+X-Ops-...: ...\n+\n+{\"description\": \"objcap\"}\n+```\n+\n+```\n+HTTP/1.1 200 OK\n+\n+{\"token\": \"<token>\", \"description\": \"objcap\", \"created_at\": \"1970-01-01T00:00:00Z\"}\n+```\n+\n+\n+### Other token operations\n+\n+Tokens support list, read, and delete operations. At this time, tokens are\n+immutable so no support for update operations is required. This may be revised\n+in the future.\n+\n+#### List\n+\n+```\n+GET /tokens HTTP/1.1\n+Host: chef.example.com\n+X-Ops-...: ...\n+```\n+\n+```\n+HTTP/1.1 200 OK\n+\n+{\"<token>\": \"https://chef.example.com/tokens/<token>\"}\n+```\n+\n+This API must be restricted such that only tokens belonging to the current\n+user or client are visible. This does potentially present an escalation\n+vulnerability whereby one compromised token could steal other tokens for the\n+same user. This could be mitigated through per-token permissions detailed below.\n+\n+#### Read\n+\n+```\n+GET /tokens/<token> HTTP/1.1\n+Host: chef.example.com\n+X-Ops-...: ...\n+```\n+\n+```\n+HTTP/1.1 200 OK\n+\n+{\"token\": \"<token>\", \"description\": \"objcap\", \"created_at\": \"1970-01-01T00:00:00Z\"}\n+```\n+\n+#### Delete\n+\n+```\n+DELETE /tokens/<token> HTTP/1.1\n+Host: chef.example.com\n+X-Ops-...: ...\n+```\n+\n+```\n+HTTP/1.1 200 OK\n+```\n+\n+### Token expiration\n+\n+A token can have an expiration timestamp after which is cannot be used. This is\n+set during token creation.\n+\n+```\n+POST /tokens HTTP/1.1\n+Host: chef.example.com\n+X-Ops-...: ...\n+\n+{\"expires\": \"1970-01-01T00:00:00Z\"}","path":"new/token-authentication.md","position":188,"original_position":188,"commit_id":"5ea73a2362acdf51f0789c14d51d61125c2fd05e","original_commit_id":"5ea73a2362acdf51f0789c14d51d61125c2fd05e","user":{"login":"seth","id":1619,"avatar_url":"https://avatars.githubusercontent.com/u/1619?v=3","gravatar_id":"","url":"https://api.github.com/users/seth","html_url":"https://github.com/seth","followers_url":"https://api.github.com/users/seth/followers","following_url":"https://api.github.com/users/seth/following{/other_user}","gists_url":"https://api.github.com/users/seth/gists{/gist_id}","starred_url":"https://api.github.com/users/seth/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seth/subscriptions","organizations_url":"https://api.github.com/users/seth/orgs","repos_url":"https://api.github.com/users/seth/repos","events_url":"https://api.github.com/users/seth/events{/privacy}","received_events_url":"https://api.github.com/users/seth/received_events","type":"User","site_admin":false},"body":"Would the server also get to apply policy about token expiration? I can see wanting to implement a server-based policy that would disallow tokens living beyond some pre-set TTL. But I can also see the benefit of giving users the ability to create short-lived or long-lived tokens depending on their intended use.","created_at":"2014-11-09T22:58:46Z","updated_at":"2014-11-09T22:58:46Z","html_url":"https://github.com/opscode/chef-rfc/pull/65#discussion_r20062441","pull_request_url":"https://api.github.com/repos/opscode/chef-rfc/pulls/65","_links":{"self":{"href":"https://api.github.com/repos/opscode/chef-rfc/pulls/comments/20062441"},"html":{"href":"https://github.com/opscode/chef-rfc/pull/65#discussion_r20062441"},"pull_request":{"href":"https://api.github.com/repos/opscode/chef-rfc/pulls/65"}}},"pull_request":{"url":"https://api.github.com/repos/opscode/chef-rfc/pulls/65","id":24107688,"html_url":"https://github.com/opscode/chef-rfc/pull/65","diff_url":"https://github.com/opscode/chef-rfc/pull/65.diff","patch_url":"https://github.com/opscode/chef-rfc/pull/65.patch","issue_url":"https://api.github.com/repos/opscode/chef-rfc/issues/65","number":65,"state":"open","locked":false,"title":"Token authentication for Chef Server","user":{"login":"coderanger","id":128243,"avatar_url":"https://avatars.githubusercontent.com/u/128243?v=3","gravatar_id":"","url":"https://api.github.com/users/coderanger","html_url":"https://github.com/coderanger","followers_url":"https://api.github.com/users/coderanger/followers","following_url":"https://api.github.com/users/coderanger/following{/other_user}","gists_url":"https://api.github.com/users/coderanger/gists{/gist_id}","starred_url":"https://api.github.com/users/coderanger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coderanger/subscriptions","organizations_url":"https://api.github.com/users/coderanger/orgs","repos_url":"https://api.github.com/users/coderanger/repos","events_url":"https://api.github.com/users/coderanger/events{/privacy}","received_events_url":"https://api.github.com/users/coderanger/received_events","type":"User","site_admin":false},"body":"Ping @smith @seth @mmzyk @danielsdeleo @lamont-granquist.\r\n\r\nHot off the presses, have at it!","created_at":"2014-11-08T23:25:10Z","updated_at":"2014-11-09T22:58:46Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c58e50476d2b2a32a67dcbc09baa6849b6a211c2","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/opscode/chef-rfc/pulls/65/commits","review_comments_url":"https://api.github.com/repos/opscode/chef-rfc/pulls/65/comments","review_comment_url":"https://api.github.com/repos/opscode/chef-rfc/pulls/comments/{number}","comments_url":"https://api.github.com/repos/opscode/chef-rfc/issues/65/comments","statuses_url":"https://api.github.com/repos/opscode/chef-rfc/statuses/5ea73a2362acdf51f0789c14d51d61125c2fd05e","head":{"label":"coderanger:token-auth","ref":"token-auth","sha":"5ea73a2362acdf51f0789c14d51d61125c2fd05e","user":{"login":"coderanger","id":128243,"avatar_url":"https://avatars.githubusercontent.com/u/128243?v=3","gravatar_id":"","url":"https://api.github.com/users/coderanger","html_url":"https://github.com/coderanger","followers_url":"https://api.github.com/users/coderanger/followers","following_url":"https://api.github.com/users/coderanger/following{/other_user}","gists_url":"https://api.github.com/users/coderanger/gists{/gist_id}","starred_url":"https://api.github.com/users/coderanger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coderanger/subscriptions","organizations_url":"https://api.github.com/users/coderanger/orgs","repos_url":"https://api.github.com/users/coderanger/repos","events_url":"https://api.github.com/users/coderanger/events{/privacy}","received_events_url":"https://api.github.com/users/coderanger/received_events","type":"User","site_admin":false},"repo":{"id":22249400,"name":"chef-rfc","full_name":"coderanger/chef-rfc","owner":{"login":"coderanger","id":128243,"avatar_url":"https://avatars.githubusercontent.com/u/128243?v=3","gravatar_id":"","url":"https://api.github.com/users/coderanger","html_url":"https://github.com/coderanger","followers_url":"https://api.github.com/users/coderanger/followers","following_url":"https://api.github.com/users/coderanger/following{/other_user}","gists_url":"https://api.github.com/users/coderanger/gists{/gist_id}","starred_url":"https://api.github.com/users/coderanger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coderanger/subscriptions","organizations_url":"https://api.github.com/users/coderanger/orgs","repos_url":"https://api.github.com/users/coderanger/repos","events_url":"https://api.github.com/users/coderanger/events{/privacy}","received_events_url":"https://api.github.com/users/coderanger/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/coderanger/chef-rfc","description":"Public RFCs for Chef and related projects","fork":true,"url":"https://api.github.com/repos/coderanger/chef-rfc","forks_url":"https://api.github.com/repos/coderanger/chef-rfc/forks","keys_url":"https://api.github.com/repos/coderanger/chef-rfc/keys{/key_id}","collaborators_url":"https://api.github.com/repos/coderanger/chef-rfc/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/coderanger/chef-rfc/teams","hooks_url":"https://api.github.com/repos/coderanger/chef-rfc/hooks","issue_events_url":"https://api.github.com/repos/coderanger/chef-rfc/issues/events{/number}","events_url":"https://api.github.com/repos/coderanger/chef-rfc/events","assignees_url":"https://api.github.com/repos/coderanger/chef-rfc/assignees{/user}","branches_url":"https://api.github.com/repos/coderanger/chef-rfc/branches{/branch}","tags_url":"https://api.github.com/repos/coderanger/chef-rfc/tags","blobs_url":"https://api.github.com/repos/coderanger/chef-rfc/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/coderanger/chef-rfc/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/coderanger/chef-rfc/git/refs{/sha}","trees_url":"https://api.github.com/repos/coderanger/chef-rfc/git/trees{/sha}","statuses_url":"https://api.github.com/repos/coderanger/chef-rfc/statuses/{sha}","languages_url":"https://api.github.com/repos/coderanger/chef-rfc/languages","stargazers_url":"https://api.github.com/repos/coderanger/chef-rfc/stargazers","contributors_url":"https://api.github.com/repos/coderanger/chef-rfc/contributors","subscribers_url":"https://api.github.com/repos/coderanger/chef-rfc/subscribers","subscription_url":"https://api.github.com/repos/coderanger/chef-rfc/subscription","commits_url":"https://api.github.com/repos/coderanger/chef-rfc/commits{/sha}","git_commits_url":"https://api.github.com/repos/coderanger/chef-rfc/git/commits{/sha}","comments_url":"https://api.github.com/repos/coderanger/chef-rfc/comments{/number}","issue_comment_url":"https://api.github.com/repos/coderanger/chef-rfc/issues/comments/{number}","contents_url":"https://api.github.com/repos/coderanger/chef-rfc/contents/{+path}","compare_url":"https://api.github.com/repos/coderanger/chef-rfc/compare/{base}...{head}","merges_url":"https://api.github.com/repos/coderanger/chef-rfc/merges","archive_url":"https://api.github.com/repos/coderanger/chef-rfc/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/coderanger/chef-rfc/downloads","issues_url":"https://api.github.com/repos/coderanger/chef-rfc/issues{/number}","pulls_url":"https://api.github.com/repos/coderanger/chef-rfc/pulls{/number}","milestones_url":"https://api.github.com/repos/coderanger/chef-rfc/milestones{/number}","notifications_url":"https://api.github.com/repos/coderanger/chef-rfc/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/coderanger/chef-rfc/labels{/name}","releases_url":"https://api.github.com/repos/coderanger/chef-rfc/releases{/id}","created_at":"2014-07-25T07:57:57Z","updated_at":"2014-07-24T19:12:14Z","pushed_at":"2014-11-09T06:09:00Z","git_url":"git://github.com/coderanger/chef-rfc.git","ssh_url":"git@github.com:coderanger/chef-rfc.git","clone_url":"https://github.com/coderanger/chef-rfc.git","svn_url":"https://github.com/coderanger/chef-rfc","homepage":null,"size":394,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"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":"opscode:master","ref":"master","sha":"b8bbef8063826572050da5b22507ca64bb41a8b2","user":{"login":"opscode","id":29740,"avatar_url":"https://avatars.githubusercontent.com/u/29740?v=3","gravatar_id":"","url":"https://api.github.com/users/opscode","html_url":"https://github.com/opscode","followers_url":"https://api.github.com/users/opscode/followers","following_url":"https://api.github.com/users/opscode/following{/other_user}","gists_url":"https://api.github.com/users/opscode/gists{/gist_id}","starred_url":"https://api.github.com/users/opscode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opscode/subscriptions","organizations_url":"https://api.github.com/users/opscode/orgs","repos_url":"https://api.github.com/users/opscode/repos","events_url":"https://api.github.com/users/opscode/events{/privacy}","received_events_url":"https://api.github.com/users/opscode/received_events","type":"Organization","site_admin":false},"repo":{"id":15090814,"name":"chef-rfc","full_name":"opscode/chef-rfc","owner":{"login":"opscode","id":29740,"avatar_url":"https://avatars.githubusercontent.com/u/29740?v=3","gravatar_id":"","url":"https://api.github.com/users/opscode","html_url":"https://github.com/opscode","followers_url":"https://api.github.com/users/opscode/followers","following_url":"https://api.github.com/users/opscode/following{/other_user}","gists_url":"https://api.github.com/users/opscode/gists{/gist_id}","starred_url":"https://api.github.com/users/opscode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opscode/subscriptions","organizations_url":"https://api.github.com/users/opscode/orgs","repos_url":"https://api.github.com/users/opscode/repos","events_url":"https://api.github.com/users/opscode/events{/privacy}","received_events_url":"https://api.github.com/users/opscode/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/opscode/chef-rfc","description":"Public RFCs for Chef and related projects","fork":false,"url":"https://api.github.com/repos/opscode/chef-rfc","forks_url":"https://api.github.com/repos/opscode/chef-rfc/forks","keys_url":"https://api.github.com/repos/opscode/chef-rfc/keys{/key_id}","collaborators_url":"https://api.github.com/repos/opscode/chef-rfc/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/opscode/chef-rfc/teams","hooks_url":"https://api.github.com/repos/opscode/chef-rfc/hooks","issue_events_url":"https://api.github.com/repos/opscode/chef-rfc/issues/events{/number}","events_url":"https://api.github.com/repos/opscode/chef-rfc/events","assignees_url":"https://api.github.com/repos/opscode/chef-rfc/assignees{/user}","branches_url":"https://api.github.com/repos/opscode/chef-rfc/branches{/branch}","tags_url":"https://api.github.com/repos/opscode/chef-rfc/tags","blobs_url":"https://api.github.com/repos/opscode/chef-rfc/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/opscode/chef-rfc/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/opscode/chef-rfc/git/refs{/sha}","trees_url":"https://api.github.com/repos/opscode/chef-rfc/git/trees{/sha}","statuses_url":"https://api.github.com/repos/opscode/chef-rfc/statuses/{sha}","languages_url":"https://api.github.com/repos/opscode/chef-rfc/languages","stargazers_url":"https://api.github.com/repos/opscode/chef-rfc/stargazers","contributors_url":"https://api.github.com/repos/opscode/chef-rfc/contributors","subscribers_url":"https://api.github.com/repos/opscode/chef-rfc/subscribers","subscription_url":"https://api.github.com/repos/opscode/chef-rfc/subscription","commits_url":"https://api.github.com/repos/opscode/chef-rfc/commits{/sha}","git_commits_url":"https://api.github.com/repos/opscode/chef-rfc/git/commits{/sha}","comments_url":"https://api.github.com/repos/opscode/chef-rfc/comments{/number}","issue_comment_url":"https://api.github.com/repos/opscode/chef-rfc/issues/comments/{number}","contents_url":"https://api.github.com/repos/opscode/chef-rfc/contents/{+path}","compare_url":"https://api.github.com/repos/opscode/chef-rfc/compare/{base}...{head}","merges_url":"https://api.github.com/repos/opscode/chef-rfc/merges","archive_url":"https://api.github.com/repos/opscode/chef-rfc/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/opscode/chef-rfc/downloads","issues_url":"https://api.github.com/repos/opscode/chef-rfc/issues{/number}","pulls_url":"https://api.github.com/repos/opscode/chef-rfc/pulls{/number}","milestones_url":"https://api.github.com/repos/opscode/chef-rfc/milestones{/number}","notifications_url":"https://api.github.com/repos/opscode/chef-rfc/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/opscode/chef-rfc/labels{/name}","releases_url":"https://api.github.com/repos/opscode/chef-rfc/releases{/id}","created_at":"2013-12-10T22:10:56Z","updated_at":"2014-11-07T21:18:38Z","pushed_at":"2014-11-07T02:09:44Z","git_url":"git://github.com/opscode/chef-rfc.git","ssh_url":"git@github.com:opscode/chef-rfc.git","clone_url":"https://github.com/opscode/chef-rfc.git","svn_url":"https://github.com/opscode/chef-rfc","homepage":null,"size":3194,"stargazers_count":61,"watchers_count":61,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":21,"mirror_url":null,"open_issues_count":27,"forks":21,"open_issues":27,"watchers":61,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/opscode/chef-rfc/pulls/65"},"html":{"href":"https://github.com/opscode/chef-rfc/pull/65"},"issue":{"href":"https://api.github.com/repos/opscode/chef-rfc/issues/65"},"comments":{"href":"https://api.github.com/repos/opscode/chef-rfc/issues/65/comments"},"review_comments":{"href":"https://api.github.com/repos/opscode/chef-rfc/pulls/65/comments"},"review_comment":{"href":"https://api.github.com/repos/opscode/chef-rfc/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/opscode/chef-rfc/pulls/65/commits"},"statuses":{"href":"https://api.github.com/repos/opscode/chef-rfc/statuses/5ea73a2362acdf51f0789c14d51d61125c2fd05e"}}}}