{"action":"created","comment":{"url":"https://api.github.com/repos/coreos/dex/pulls/comments/84959258","pull_request_review_id":5703860,"id":84959258,"diff_hunk":"@@ -0,0 +1,161 @@\n+# Storage options\n+\n+Dex requires persisting state to perform various tasks such as track refresh tokens, preventing replays, and rotating keys. This document is a summary of the storage configurations supported by dex.\n+\n+Regardless of the implementation, dex saves sensitive data in its backing storage: signing keys, bcrypt'd passwords, etc. Storage breaches are serious because attacks may propagate to any application which relies on dex. Whatever storage option used, transport security and database ACLs are both musts.\n+\n+## Caveat: Running replicated instances\n+\n+Validation is still being done to ensure correctness when multiple instances of dex are using the same backing storage. While everything \"should just work\", edge cases require time to investigate and write tests for. This work can be followed on the issue tracker [here](https://github.com/coreos/dex/issues/600).\n+\n+For now, instances should run a single instance of dex and occationally run two during upgrades.\n+\n+## Kubernetes third party resources\n+\n+NOTE: Dex requires Kubernetes version 1.4+.\n+\n+Kubernetes third party resources are a way for applications to create new resources types in the Kubernetes API. This allows dex to run on top of an existing Kubernetes cluster without the need for an external database. While this storage may not be appropriate for a large number of users, it's extremely effective for may Kubernetes use cases.\n+\n+The `ThirdPartyResource` type acts as a description for the new resource a user wishes to create. The following an example of a resource managed by dex:\n+\n+```\n+kind: ThirdPartyResource\n+apiVersion: extensions/v1beta1\n+metadata:\n+  name: o-auth2-client.oidc.coreos.com\n+versions:\n+  - v1\n+description: \"An OAuth2 client.\"\n+```\n+\n+Once the `ThirdPartyResource` is created, custom resources can be created at a namespace level (though there will be a gap between the `ThirdPartyResource` being created and the API server accepting the custom resource). While most fields are user defined, the API server still respects the common `ObjectMeta` and `TypeMeta` values. For example names are still restricted to a small set of characters, and the `resourceVersion` field can be used for an [atomic compare and swap](https://github.com/kubernetes/kubernetes/blob/release-1.4/docs/devel/api-conventions.md#concurrency-control-and-consistency).\n+\n+The following is an example of a custom `OAuth2Client` resource:\n+\n+```\n+# Standard Kubernetes resource fields\n+kind: OAuth2Client\n+apiVersion: oidc.coreos.com/v1\n+metadata:\n+  namespace: foobar\n+  name: client-foo\n+\n+# Custom fields defined by dex.\n+clientID: \"aclientid\"\n+clientSecret: \"clientsecret\"\n+redirectURIs:\n+- \"https://app.example.com/callback\"\n+```\n+\n+The `ThirdPartyResource` type and the custom resources can be queried, deleted, and edited like any other resource using `kubectl`.\n+\n+```\n+kubectl get thirdpartyresources # list third party resources registered on the clusters\n+kubectl get --namespace=foobar oauth2clients # list oauth2 clients in a given namespace\n+```\n+\n+To reduce administrative overhead, dex creates and manages its own third party resources and may create new ones during upgrades. While not strictly required we feel this is important for reasonable updates. Though, as a result, dex requires access to the non-namespaced `ThirdPartyResource` type. For example, clusters using RBAC authorization would need to create the following roles and bindings:\n+\n+```\n+kind: ClusterRole\n+apiVersion: rbac.authorization.k8s.io/v1alpha1\n+metadata:\n+  name: dex\n+rules:\n+  - apiGroups: [\"oidc.coreos.com\"] # API group created by dex\n+    resources: [\"*\"]\n+    verbs: [\"*\"]\n+    nonResourceURLs: []\n+  - apiGroups: [\"extensions\"]\n+    resources: [\"thirdpartyresources\"]\n+    verbs: [\"create\"] # To manage its own resources identity must be able to create thirdpartyresources.\n+    nonResourceURLs: []\n+---\n+kind: ClusterRoleBinding\n+apiVersion: rbac.authorization.k8s.io/v1alpha1\n+metadata:\n+  name: dex\n+subjects:\n+  - kind: ServiceAccount\n+    name: dex                 # Service account assigned to the dex pod.\n+    namespace: demo-namespace # The namespace dex is running in.\n+roleRef:\n+  kind: ClusterRole\n+  name: identity\n+  apiVersion: rbac.authorization.k8s.io/v1alpha1\n+```\n+\n+The storage configuration is extremely limited since installations running outside a Kubernetes cluster would likely prefer a different storage option. An example configuration for dex running inside Kubernetes:\n+\n+```\n+storage:\n+  type: kubernetes\n+  config:\n+    inCluster: true\n+```\n+\n+Dex determines the namespace it's running in by parsing the service account token automatically mounted into its pod.\n+\n+## SQL\n+\n+Dex supports two flavors of SQL, SQLite3 and Postgres. MySQL and CockroachDB may be added at a later time.\n+\n+Migrations are performed automatically on the first connection to the SQL server (it does not support rolling back). Because of this, dex requires being able to add and alter the tables for its database.\n+\n+NOTE: Previous versions of dex required symmetric keys to encrypt certain values before sending them to the database. This feature has not been ported to V2 yet, though it may be added later (but possibly without a migration path for users of the current implementation).\n+\n+### SQLite3\n+\n+SQLite3 is the recommended storage for users who want to stand up dex quickly. It is __not__ appropriate for real workloads.\n+\n+The SQLite3 configuration takes a single argument, the database file.\n+\n+```\n+storage:\n+  type: sqlite3\n+  config:\n+    file: /var/dex/dex.db\n+```\n+\n+Because SQLite3 uses file locks to prevent race conditions, if the \":memory:\" value is provided dex will automatically disable support for concurrent database queries.\n+\n+### Postgres\n+\n+Dex authenticates to Postgres with a username and password. As stated above, because dex performs migrations, it requires privileged access to its own database. Database table names are not configurable, and to prevent table name clashes with other applications admins should expect to dedicated a database for dex's sole use. \n+\n+```\n+CREATE DATABASE dex_db;\n+CREATE USER dex WITH PASSWORD '66964843358242dbaaa7778d8477c288';\n+GRANT ALL PRIVILEGES ON DATABASE dex_db TO dex;\n+```\n+\n+An example config for Postgres setup using these values:\n+\n+```\n+storage:\n+  type: postgres\n+  config:\n+    database: dex_db\n+    user: dex\n+    password: 66964843358242dbaaa7778d8477c288\n+    ssl:\n+      mode: verify-ca\n+      caFile: /etc/dex/postgres.ca\n+```\n+\n+The SSL \"mode\" corresponds to the `github.com/lib/pq` package [connection options](https://godoc.org/github.com/lib/pq#hdr-Connection_String_Parameters). If unspecified, dex defaults to the strictest mode \"verify-full\".\n+\n+## Adding a new storage options\n+\n+Each storage implementation bears a large ongoing maintenance cost and needs to be updated every time a feature requires storing a new type. Bugs often require in depth knowledge of the backing software, and much of this work will be done by developers who are not the original authors. Changes to dex which add new storage implementations are not merged lightly.\n+\n+Those who still want to construct a proposal for a new storage should review the following packages:","path":"Documentation/storage.md","position":152,"original_position":152,"commit_id":"ef8f39a0fe772b5ef7e4e2e4830e179b2fce0c88","original_commit_id":"ef8f39a0fe772b5ef7e4e2e4830e179b2fce0c88","user":{"login":"ericchiang","id":2342749,"avatar_url":"https://avatars.githubusercontent.com/u/2342749?v=3","gravatar_id":"","url":"https://api.github.com/users/ericchiang","html_url":"https://github.com/ericchiang","followers_url":"https://api.github.com/users/ericchiang/followers","following_url":"https://api.github.com/users/ericchiang/following{/other_user}","gists_url":"https://api.github.com/users/ericchiang/gists{/gist_id}","starred_url":"https://api.github.com/users/ericchiang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ericchiang/subscriptions","organizations_url":"https://api.github.com/users/ericchiang/orgs","repos_url":"https://api.github.com/users/ericchiang/repos","events_url":"https://api.github.com/users/ericchiang/events{/privacy}","received_events_url":"https://api.github.com/users/ericchiang/received_events","type":"User","site_admin":false},"body":"Wouldn't that imply that it's part of the SQL section (as it's not)?","created_at":"2016-10-25T17:42:50Z","updated_at":"2016-10-25T17:42:50Z","html_url":"https://github.com/coreos/dex/pull/632#discussion_r84959258","pull_request_url":"https://api.github.com/repos/coreos/dex/pulls/632","_links":{"self":{"href":"https://api.github.com/repos/coreos/dex/pulls/comments/84959258"},"html":{"href":"https://github.com/coreos/dex/pull/632#discussion_r84959258"},"pull_request":{"href":"https://api.github.com/repos/coreos/dex/pulls/632"}}},"pull_request":{"url":"https://api.github.com/repos/coreos/dex/pulls/632","id":90672790,"html_url":"https://github.com/coreos/dex/pull/632","diff_url":"https://github.com/coreos/dex/pull/632.diff","patch_url":"https://github.com/coreos/dex/pull/632.patch","issue_url":"https://api.github.com/repos/coreos/dex/issues/632","number":632,"state":"open","locked":false,"title":"Documentation: add a document on storage options","user":{"login":"ericchiang","id":2342749,"avatar_url":"https://avatars.githubusercontent.com/u/2342749?v=3","gravatar_id":"","url":"https://api.github.com/users/ericchiang","html_url":"https://github.com/ericchiang","followers_url":"https://api.github.com/users/ericchiang/followers","following_url":"https://api.github.com/users/ericchiang/following{/other_user}","gists_url":"https://api.github.com/users/ericchiang/gists{/gist_id}","starred_url":"https://api.github.com/users/ericchiang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ericchiang/subscriptions","organizations_url":"https://api.github.com/users/ericchiang/orgs","repos_url":"https://api.github.com/users/ericchiang/repos","events_url":"https://api.github.com/users/ericchiang/events{/privacy}","received_events_url":"https://api.github.com/users/ericchiang/received_events","type":"User","site_admin":false},"body":"fyi @dghubble there's some third party resource docs here.","created_at":"2016-10-24T19:04:59Z","updated_at":"2016-10-25T17:42:50Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5e09f2d0ae30ff0ea1751d61bfb90be15438615f","assignee":{"login":"ElijahCaine","id":1897147,"avatar_url":"https://avatars.githubusercontent.com/u/1897147?v=3","gravatar_id":"","url":"https://api.github.com/users/ElijahCaine","html_url":"https://github.com/ElijahCaine","followers_url":"https://api.github.com/users/ElijahCaine/followers","following_url":"https://api.github.com/users/ElijahCaine/following{/other_user}","gists_url":"https://api.github.com/users/ElijahCaine/gists{/gist_id}","starred_url":"https://api.github.com/users/ElijahCaine/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ElijahCaine/subscriptions","organizations_url":"https://api.github.com/users/ElijahCaine/orgs","repos_url":"https://api.github.com/users/ElijahCaine/repos","events_url":"https://api.github.com/users/ElijahCaine/events{/privacy}","received_events_url":"https://api.github.com/users/ElijahCaine/received_events","type":"User","site_admin":false},"assignees":[{"login":"ElijahCaine","id":1897147,"avatar_url":"https://avatars.githubusercontent.com/u/1897147?v=3","gravatar_id":"","url":"https://api.github.com/users/ElijahCaine","html_url":"https://github.com/ElijahCaine","followers_url":"https://api.github.com/users/ElijahCaine/followers","following_url":"https://api.github.com/users/ElijahCaine/following{/other_user}","gists_url":"https://api.github.com/users/ElijahCaine/gists{/gist_id}","starred_url":"https://api.github.com/users/ElijahCaine/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ElijahCaine/subscriptions","organizations_url":"https://api.github.com/users/ElijahCaine/orgs","repos_url":"https://api.github.com/users/ElijahCaine/repos","events_url":"https://api.github.com/users/ElijahCaine/events{/privacy}","received_events_url":"https://api.github.com/users/ElijahCaine/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/coreos/dex/pulls/632/commits","review_comments_url":"https://api.github.com/repos/coreos/dex/pulls/632/comments","review_comment_url":"https://api.github.com/repos/coreos/dex/pulls/comments{/number}","comments_url":"https://api.github.com/repos/coreos/dex/issues/632/comments","statuses_url":"https://api.github.com/repos/coreos/dex/statuses/ef8f39a0fe772b5ef7e4e2e4830e179b2fce0c88","head":{"label":"ericchiang:dev-docs-storage-options","ref":"dev-docs-storage-options","sha":"ef8f39a0fe772b5ef7e4e2e4830e179b2fce0c88","user":{"login":"ericchiang","id":2342749,"avatar_url":"https://avatars.githubusercontent.com/u/2342749?v=3","gravatar_id":"","url":"https://api.github.com/users/ericchiang","html_url":"https://github.com/ericchiang","followers_url":"https://api.github.com/users/ericchiang/followers","following_url":"https://api.github.com/users/ericchiang/following{/other_user}","gists_url":"https://api.github.com/users/ericchiang/gists{/gist_id}","starred_url":"https://api.github.com/users/ericchiang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ericchiang/subscriptions","organizations_url":"https://api.github.com/users/ericchiang/orgs","repos_url":"https://api.github.com/users/ericchiang/repos","events_url":"https://api.github.com/users/ericchiang/events{/privacy}","received_events_url":"https://api.github.com/users/ericchiang/received_events","type":"User","site_admin":false},"repo":{"id":47153053,"name":"dex","full_name":"ericchiang/dex","owner":{"login":"ericchiang","id":2342749,"avatar_url":"https://avatars.githubusercontent.com/u/2342749?v=3","gravatar_id":"","url":"https://api.github.com/users/ericchiang","html_url":"https://github.com/ericchiang","followers_url":"https://api.github.com/users/ericchiang/followers","following_url":"https://api.github.com/users/ericchiang/following{/other_user}","gists_url":"https://api.github.com/users/ericchiang/gists{/gist_id}","starred_url":"https://api.github.com/users/ericchiang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ericchiang/subscriptions","organizations_url":"https://api.github.com/users/ericchiang/orgs","repos_url":"https://api.github.com/users/ericchiang/repos","events_url":"https://api.github.com/users/ericchiang/events{/privacy}","received_events_url":"https://api.github.com/users/ericchiang/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ericchiang/dex","description":"dex is an OpenID Connect Identity Provider...and more!","fork":true,"url":"https://api.github.com/repos/ericchiang/dex","forks_url":"https://api.github.com/repos/ericchiang/dex/forks","keys_url":"https://api.github.com/repos/ericchiang/dex/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ericchiang/dex/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ericchiang/dex/teams","hooks_url":"https://api.github.com/repos/ericchiang/dex/hooks","issue_events_url":"https://api.github.com/repos/ericchiang/dex/issues/events{/number}","events_url":"https://api.github.com/repos/ericchiang/dex/events","assignees_url":"https://api.github.com/repos/ericchiang/dex/assignees{/user}","branches_url":"https://api.github.com/repos/ericchiang/dex/branches{/branch}","tags_url":"https://api.github.com/repos/ericchiang/dex/tags","blobs_url":"https://api.github.com/repos/ericchiang/dex/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ericchiang/dex/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ericchiang/dex/git/refs{/sha}","trees_url":"https://api.github.com/repos/ericchiang/dex/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ericchiang/dex/statuses/{sha}","languages_url":"https://api.github.com/repos/ericchiang/dex/languages","stargazers_url":"https://api.github.com/repos/ericchiang/dex/stargazers","contributors_url":"https://api.github.com/repos/ericchiang/dex/contributors","subscribers_url":"https://api.github.com/repos/ericchiang/dex/subscribers","subscription_url":"https://api.github.com/repos/ericchiang/dex/subscription","commits_url":"https://api.github.com/repos/ericchiang/dex/commits{/sha}","git_commits_url":"https://api.github.com/repos/ericchiang/dex/git/commits{/sha}","comments_url":"https://api.github.com/repos/ericchiang/dex/comments{/number}","issue_comment_url":"https://api.github.com/repos/ericchiang/dex/issues/comments{/number}","contents_url":"https://api.github.com/repos/ericchiang/dex/contents/{+path}","compare_url":"https://api.github.com/repos/ericchiang/dex/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ericchiang/dex/merges","archive_url":"https://api.github.com/repos/ericchiang/dex/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ericchiang/dex/downloads","issues_url":"https://api.github.com/repos/ericchiang/dex/issues{/number}","pulls_url":"https://api.github.com/repos/ericchiang/dex/pulls{/number}","milestones_url":"https://api.github.com/repos/ericchiang/dex/milestones{/number}","notifications_url":"https://api.github.com/repos/ericchiang/dex/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ericchiang/dex/labels{/name}","releases_url":"https://api.github.com/repos/ericchiang/dex/releases{/id}","deployments_url":"https://api.github.com/repos/ericchiang/dex/deployments","created_at":"2015-11-30T23:40:27Z","updated_at":"2016-01-11T18:47:27Z","pushed_at":"2016-10-24T23:14:56Z","git_url":"git://github.com/ericchiang/dex.git","ssh_url":"git@github.com:ericchiang/dex.git","clone_url":"https://github.com/ericchiang/dex.git","svn_url":"https://github.com/ericchiang/dex","homepage":"https://coreos.com/blog/announcing-dex/","size":9911,"stargazers_count":0,"watchers_count":0,"language":"Go","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":"coreos:dev","ref":"dev","sha":"ba9f6c6cd68be8734b97400c66a016b4c3149f52","user":{"login":"coreos","id":3730757,"avatar_url":"https://avatars.githubusercontent.com/u/3730757?v=3","gravatar_id":"","url":"https://api.github.com/users/coreos","html_url":"https://github.com/coreos","followers_url":"https://api.github.com/users/coreos/followers","following_url":"https://api.github.com/users/coreos/following{/other_user}","gists_url":"https://api.github.com/users/coreos/gists{/gist_id}","starred_url":"https://api.github.com/users/coreos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coreos/subscriptions","organizations_url":"https://api.github.com/users/coreos/orgs","repos_url":"https://api.github.com/users/coreos/repos","events_url":"https://api.github.com/users/coreos/events{/privacy}","received_events_url":"https://api.github.com/users/coreos/received_events","type":"Organization","site_admin":false},"repo":{"id":40916314,"name":"dex","full_name":"coreos/dex","owner":{"login":"coreos","id":3730757,"avatar_url":"https://avatars.githubusercontent.com/u/3730757?v=3","gravatar_id":"","url":"https://api.github.com/users/coreos","html_url":"https://github.com/coreos","followers_url":"https://api.github.com/users/coreos/followers","following_url":"https://api.github.com/users/coreos/following{/other_user}","gists_url":"https://api.github.com/users/coreos/gists{/gist_id}","starred_url":"https://api.github.com/users/coreos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coreos/subscriptions","organizations_url":"https://api.github.com/users/coreos/orgs","repos_url":"https://api.github.com/users/coreos/repos","events_url":"https://api.github.com/users/coreos/events{/privacy}","received_events_url":"https://api.github.com/users/coreos/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/coreos/dex","description":"OpenID Connect Identity (OIDC) and OAuth 2.0 Provider with Pluggable Connectors","fork":false,"url":"https://api.github.com/repos/coreos/dex","forks_url":"https://api.github.com/repos/coreos/dex/forks","keys_url":"https://api.github.com/repos/coreos/dex/keys{/key_id}","collaborators_url":"https://api.github.com/repos/coreos/dex/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/coreos/dex/teams","hooks_url":"https://api.github.com/repos/coreos/dex/hooks","issue_events_url":"https://api.github.com/repos/coreos/dex/issues/events{/number}","events_url":"https://api.github.com/repos/coreos/dex/events","assignees_url":"https://api.github.com/repos/coreos/dex/assignees{/user}","branches_url":"https://api.github.com/repos/coreos/dex/branches{/branch}","tags_url":"https://api.github.com/repos/coreos/dex/tags","blobs_url":"https://api.github.com/repos/coreos/dex/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/coreos/dex/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/coreos/dex/git/refs{/sha}","trees_url":"https://api.github.com/repos/coreos/dex/git/trees{/sha}","statuses_url":"https://api.github.com/repos/coreos/dex/statuses/{sha}","languages_url":"https://api.github.com/repos/coreos/dex/languages","stargazers_url":"https://api.github.com/repos/coreos/dex/stargazers","contributors_url":"https://api.github.com/repos/coreos/dex/contributors","subscribers_url":"https://api.github.com/repos/coreos/dex/subscribers","subscription_url":"https://api.github.com/repos/coreos/dex/subscription","commits_url":"https://api.github.com/repos/coreos/dex/commits{/sha}","git_commits_url":"https://api.github.com/repos/coreos/dex/git/commits{/sha}","comments_url":"https://api.github.com/repos/coreos/dex/comments{/number}","issue_comment_url":"https://api.github.com/repos/coreos/dex/issues/comments{/number}","contents_url":"https://api.github.com/repos/coreos/dex/contents/{+path}","compare_url":"https://api.github.com/repos/coreos/dex/compare/{base}...{head}","merges_url":"https://api.github.com/repos/coreos/dex/merges","archive_url":"https://api.github.com/repos/coreos/dex/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/coreos/dex/downloads","issues_url":"https://api.github.com/repos/coreos/dex/issues{/number}","pulls_url":"https://api.github.com/repos/coreos/dex/pulls{/number}","milestones_url":"https://api.github.com/repos/coreos/dex/milestones{/number}","notifications_url":"https://api.github.com/repos/coreos/dex/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/coreos/dex/labels{/name}","releases_url":"https://api.github.com/repos/coreos/dex/releases{/id}","deployments_url":"https://api.github.com/repos/coreos/dex/deployments","created_at":"2015-08-17T17:57:06Z","updated_at":"2016-10-25T17:05:35Z","pushed_at":"2016-10-25T17:30:38Z","git_url":"git://github.com/coreos/dex.git","ssh_url":"git@github.com:coreos/dex.git","clone_url":"https://github.com/coreos/dex.git","svn_url":"https://github.com/coreos/dex","homepage":"https://coreos.com/blog/announcing-dex/","size":10434,"stargazers_count":974,"watchers_count":974,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":163,"mirror_url":null,"open_issues_count":113,"forks":163,"open_issues":113,"watchers":974,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/coreos/dex/pulls/632"},"html":{"href":"https://github.com/coreos/dex/pull/632"},"issue":{"href":"https://api.github.com/repos/coreos/dex/issues/632"},"comments":{"href":"https://api.github.com/repos/coreos/dex/issues/632/comments"},"review_comments":{"href":"https://api.github.com/repos/coreos/dex/pulls/632/comments"},"review_comment":{"href":"https://api.github.com/repos/coreos/dex/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/coreos/dex/pulls/632/commits"},"statuses":{"href":"https://api.github.com/repos/coreos/dex/statuses/ef8f39a0fe772b5ef7e4e2e4830e179b2fce0c88"}}}}
{"actor":{"display_login":"ericchiang"}}