{"action":"created","comment":{"url":"https://api.github.com/repos/istio/istio.github.io/pulls/comments/178328722","pull_request_review_id":108374365,"id":178328722,"diff_hunk":"@@ -0,0 +1,311 @@\n+---\n+title: \"Istio Multitenancy Support\"\n+overview: Using Kubernetes namespace and RBAC to create an Istio soft multitenancy environment\n+publish_date: March 21, 2018\n+subtitle: Using multiple Istio control planes and RBAC to create multitenancy\n+attribution: John Joyce and Rich Curran\n+\n+order: 92\n+\n+layout: blog\n+type: markdown\n+redirect_from: \"/blog/soft-multitenancy.html\"\n+---\n+{% include home.html %}\n+Multitenancy is commonly used in many environments across many different applications,\n+but the implementation details and functionality provided on a per tenant basis does not\n+follow one model in all environments.  The [Kubernetes multitenancy working group](\n+https://github.com/kubernetes/community/blob/master/wg-multitenancy/README.md)\n+is working to define the multitenant use cases and functionality that should be available\n+within Kubernetes. From their work so far it is clear that only a \"soft multitenancy\" is\n+possible due to the inability to fully protect against malicious containers or workloads\n+gaining access to the other pods or kernel resources.\n+\n+## Defining soft multitenancy for Istio\n+While discussing the strengths and benefits of deploying applications on top of Istio, it\n+became apparent that there are multitenant use cases for Istio even within this Kubernetes\n+\"soft multitenancy\" definition that does not provide absolute protection amongst tenants.\n+A viable use case for this scenario is shared corporate infrastructure where malicious\n+actions are not expected but a clean separation of the tenants is still required. A few\n+different multitenant models can be considered.\n+1.\tA single mesh with multiple applications, one for each tenant on the mesh. The cluster\n+administrator gets control and visibility mesh wide and across all applications, while the\n+tenant administrator only gets control of a specific application.\n+1.\tA single Istio control plane with multiple meshes, one mesh per tenant. The cluster\n+administrator gets control and visibility across the entire Istio control plane and all\n+meshes, while the tenant administrator only gets control of a specific mesh.\n+1.\tA single Kubernetes control plane with multiple Istio control planes, one per tenant.\n+The cluster administrator gets control and visibility across all the Istio control planes,\n+while the tenant administrator only gets control of a specific Istio instance.\n+1.\tA single cloud environment (cluster controlled), but multiple Kubernetes control planes\n+(tenant controlled).\n+\n+The fourth model doesn’t satisfy most use cases, as most cluster administrators prefer\n+a common Kubernetes control plane which they provide as a PaaS to their tenants.\n+Additionally, case 4 is easily provided in many environments already.\n+\n+Current Istio capabilities are poorly suited to support the first model as it lacks\n+sufficient RBAC capabilities to support cluster versus tenant operations. Additionally,\n+having multiple tenants under one mesh is too insecure with the current mesh model.\n+So option 1 won’t be further evaluated in this blog.\n+\n+Regarding the 2nd option the current Istio paradigm assumes a single mesh per Istio control\n+plane. The needed changes to support this mode are substantial and would also require RBAC\n+changes to the Istio resources. Although some operators might want to provide Istio as PaaS\n+and have resource sharing between tenants, the benefits of sharing an Istio control plane across\n+tenants is marginal compared to sharing a Kubernetes cluster across tenants.\n+\n+Considering aforementioned challenges, this blog will describe how to provide Option 3.\n+Current Istio capabilities are well suited to providing this option as namespace-based scoping\n+is already widely supported in most Istio modules. Best practices for deploying multiple\n+tenant applications per cluster require the use of a namespace. This blog will provide a\n+high level description on the requirements to deploy multiple Istio control planes\n+(one per tenant) on a single Kubernetes cluster.\n+\n+## Deployment details\n+### Multiple Istio control planes\n+Deploying multiple Istio control planes starts by replacing all `namespace` references\n+in a manifest file with the desired namespace. Using istio.yaml as an example, if two tenant\n+level istio control planes are required; the first can use the istio.yaml default name of\n+*istio-system* and a second control plane can be created by generating a new yaml file with\n+a different namespace.\n+```bash\n+cat istio.yaml | sed s/istio-system/istio-system1/g > istio-system1.yaml\n+```\n+Note that the execution of these two yaml files is the responsibility of the cluster\n+administrator, not the tenant level adminstrator. Additional RBAC restrictions will also\n+need to be configured and applied by the cluster administator, limiting the tenant\n+administrator to only the assigned namespace.\n+\n+If the Istio [addons]({{home}}/docs/tasks/telemetry/) are required then the manifests must\n+be updated to match the configured `namespace` in use by the tenant's Istio control plane.\n+\n+### Split common and namespace specific resources\n+The manifest files in the Istio repositories create both common resources that would\n+be used by all Istio control planes as well as resources that are replicated per control\n+plane. Although it is a simple matter to deploy multiple control planes by replacing the\n+*istio-system* namespace references as described above, a better approach is to split the\n+manifests into a common part that is deployed once for all tenants and a per tenant\n+specific portion. All the CustomResourceDefinitions (CRDs), the roles and the role\n+bindings should be separated out from the provided Istio manifests.  Additionally, the\n+roles and role bindings in the provided Istio manifests are probably unsuitable for a\n+multitenant environment and should be modified or augmented as described in the next\n+section.\n+\n+### Kubernetes RBAC for Istio control plane resources\n+To restrict a tenant administrator to a single Istio namespace, the cluster\n+administrator would create a manifest containing, at a minimum, a `Role` and `RoleBinding`\n+similar to the one below. In this example, a tenant administrator named *sales-admin*\n+is limited to the namespace *istio-system1*. A completed manifest would contain many\n+more `apiGroups` under the `Role` providing resource access to the tenant administator.\n+```yaml\n+kind: Role\n+apiVersion: rbac.authorization.k8s.io/v1\n+metadata:\n+  namespace: istio-system1 \n+  name: ns-access-for-sales-admin-istio-system1\n+rules:\n+- apiGroups: [\"\"] # \"\" indicates the core API group\n+  resources: [\"*\"]\n+  verbs: [\"*\"]\n+---\n+kind: RoleBinding\n+apiVersion: rbac.authorization.k8s.io/v1\n+metadata:\n+  name: access-all-istio-system1\n+  namespace: istio-system1\n+subjects:\n+- kind: User\n+  name: sales-admin\n+  apiGroup: rbac.authorization.k8s.io\n+roleRef:\n+  kind: Role\n+  name: ns-access-for-sales-admin-istio-system1\n+  apiGroup: rbac.authorization.k8s.io\n+\n+```\n+\n+### Watching specific namespaces for service discovery\n+In addition to creating RBAC rules limiting the tenant administrator access to a specific Istio\n+control plane, the istio manifest must be updated to specify the application namespace that\n+Pilot should watch for creation of its xDS cache. This is done by starting the Pilot component\n+with the additional command line arguments,  `--appNamespace, ns-1`.  Where *ns-1* is the\n+namespace that the tenant’s application will be deployed in. An example snippet from the\n+istio-system1.yaml file is included below.\n+```yaml\n+apiVersion: extensions/v1beta1\n+kind: Deployment\n+metadata:\n+  name: istio-pilot\n+  namespace: istio-system1\n+  annotations:\n+    sidecar.istio.io/inject: \"false\"\n+spec:\n+  replicas: 1\n+  template:\n+    metadata:\n+      labels:\n+        istio: pilot\n+    spec:\n+      serviceAccountName: istio-pilot-service-account\n+      containers:\n+      - name: discovery\n+        image: docker.io/<user ID>/pilot:<tag>\n+        imagePullPolicy: IfNotPresent\n+        args: [\"discovery\", \"-v\", \"2\", \"--admission-service\", \"istio-pilot\", \"--appNamespace\", \"ns-1\"]\n+        ports:\n+        - containerPort: 8080\n+        - containerPort: 443\n+\n+```\n+\n+### Deploying the tenant application in a namespace\n+Now that the cluster administrator has created the tenant's namespace (ex. *istio-system1*) and\n+the Pilot's service discovery has been configured to watch for a specific application\n+namespace (ex. *ns-1*), create the application manifests to deploy in that tenant's specific\n+namespace. Example:\n+\n+```yaml\n+apiVersion: v1\n+kind: Namespace\n+metadata:\n+  name: ns-1\n+```\n+And add the namespace reference to each resource type included in the applications manifest\n+file.  For example:\n+```yaml\n+apiVersion: v1\n+kind: Service\n+metadata:\n+  name: details\n+  labels:\n+    app: details\n+  namespace: ns-1\n+```\n+Although not shown, the application namespaces will also have RBAC settings limiting access\n+to certain resources. These RBAC settings could be set by the cluster administator and/or\n+the tenant administator.\n+\n+### Using Istioctl commands in a multitenant environment\n+When defining [route rules]({{home}}/docs/reference/config/istio.routing.v1alpha1.html#RouteRule)\n+or [destination policies]({{home}}/docs/reference/config/istio.routing.v1alpha1.html#DestinationPolicy),\n+it is necessary to ensure that the `istioctl` command is scoped to\n+the namespace the Istio control plane is running in to ensure the resource is created\n+in the proper namespace. Additionally, the rule itself must be scoped to the tenant's namespace\n+so that it will be applied properly to that tenant's mesh.  The \"-i\" option is used to create\n+(or get or describe) the rule in the namespace that the istio control plane is deployed in.\n+The \"-n\" option will scope the rule to the tenant's mesh and should be set to the namespace that\n+the tenant's app is deployed in. Note that the -n option can be skipped on the command line if\n+the .yaml file for the resource scopes it properly instead.\n+\n+For example, the following command would be required to add a route rule to the *istio-system1*\n+namespace:\n+```bash\n+istioctl –i istio-system1 create -n ns-1 -f route_rule_v2.yaml\n+```\n+And can be displayed using the command:\n+```bash\n+istioctl -i istio-system1 -n ns-1 get routerule\n+```\n+```bash\n+NAME\t\t\tKIND\t\t\t\t\tNAMESPACE\n+details-Default\t\tRouteRule.v1alpha2.config.istio.io\tns-1\n+productpage-default\tRouteRule.v1alpha2.config.istio.io\tns-1\n+ratings-default\t\tRouteRule.v1alpha2.config.istio.io\tns-1\n+reviews-default\t\tRouteRule.v1alpha2.config.istio.io\tns-1\n+```\n+\n+### Test results\n+Following the instructions above, a cluster administrator can create an environment limiting\n+(via RBAC and namespaces) what a tenant administrator can deploy. \n+\n+After deployment, accessing the Istio control plane pods assigned to a specific tenant\n+administrator is permitted:\n+```bash\n+kubectl get pods -n istio-system\n+```\n+```bash\n+NAME                                      READY     STATUS    RESTARTS   AGE\n+grafana-78d649479f-8pqk9                  1/1       Running   0          1d\n+istio-ca-ffbb75c6f-98w6x                  1/1       Running   0          1d\n+istio-ingress-68d65fc5c6-dnvfl            1/1       Running   0          1d\n+istio-mixer-5b9f8dffb5-8875r              3/3       Running   0          1d\n+istio-pilot-678fc976c8-b8tv6              2/2       Running   0          1d\n+istio-sidecar-injector-7587bd559d-5tgk6   1/1       Running   0          1d\n+prometheus-cf8456855-hdcq7                1/1       Running   0          1d\n+servicegraph-75ff8f7c95-wcjs7             1/1       Running   0          1d\n+```\n+However, accessing all the cluster's pods is not permitted:\n+```bash\n+kubectl get pods --all-namespaces\n+```\n+```bash\n+Error from server (Forbidden): pods is forbidden: User \"dev-admin\" cannot list pods at the cluster scope\n+```\n+And neither is accessing another tenant's namespace:\n+```bash\n+kubectl get pods -n istio-system1\n+```\n+```bash\n+Error from server (Forbidden): pods is forbidden: User \"dev-admin\" cannot list pods in the namespace \"istio-system1\"\n+```\n+\n+The tenant administrator can deploy applications in the application namespace configured for\n+that tenant. As an example, updating the [bookinfo]({{home}}/docs/guides/bookinfo.html)","path":"_blog/2018/soft-multitenancy.md","position":254,"original_position":254,"commit_id":"28159a5533e9e482e402becaaf87e366a3c2565d","original_commit_id":"28159a5533e9e482e402becaaf87e366a3c2565d","user":{"login":"geeknoid","id":22780957,"avatar_url":"https://avatars3.githubusercontent.com/u/22780957?v=4","gravatar_id":"","url":"https://api.github.com/users/geeknoid","html_url":"https://github.com/geeknoid","followers_url":"https://api.github.com/users/geeknoid/followers","following_url":"https://api.github.com/users/geeknoid/following{/other_user}","gists_url":"https://api.github.com/users/geeknoid/gists{/gist_id}","starred_url":"https://api.github.com/users/geeknoid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/geeknoid/subscriptions","organizations_url":"https://api.github.com/users/geeknoid/orgs","repos_url":"https://api.github.com/users/geeknoid/repos","events_url":"https://api.github.com/users/geeknoid/events{/privacy}","received_events_url":"https://api.github.com/users/geeknoid/received_events","type":"User","site_admin":false},"body":"bookinfo -> Bookinfo","created_at":"2018-03-30T17:04:03Z","updated_at":"2018-03-30T17:05:08Z","html_url":"https://github.com/istio/istio.github.io/pull/1119#discussion_r178328722","pull_request_url":"https://api.github.com/repos/istio/istio.github.io/pulls/1119","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/istio/istio.github.io/pulls/comments/178328722"},"html":{"href":"https://github.com/istio/istio.github.io/pull/1119#discussion_r178328722"},"pull_request":{"href":"https://api.github.com/repos/istio/istio.github.io/pulls/1119"}}},"pull_request":{"url":"https://api.github.com/repos/istio/istio.github.io/pulls/1119","id":178332278,"html_url":"https://github.com/istio/istio.github.io/pull/1119","diff_url":"https://github.com/istio/istio.github.io/pull/1119.diff","patch_url":"https://github.com/istio/istio.github.io/pull/1119.patch","issue_url":"https://api.github.com/repos/istio/istio.github.io/issues/1119","number":1119,"state":"open","locked":false,"title":"Add multitenancy blog","user":{"login":"rcurran1","id":3076511,"avatar_url":"https://avatars2.githubusercontent.com/u/3076511?v=4","gravatar_id":"","url":"https://api.github.com/users/rcurran1","html_url":"https://github.com/rcurran1","followers_url":"https://api.github.com/users/rcurran1/followers","following_url":"https://api.github.com/users/rcurran1/following{/other_user}","gists_url":"https://api.github.com/users/rcurran1/gists{/gist_id}","starred_url":"https://api.github.com/users/rcurran1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rcurran1/subscriptions","organizations_url":"https://api.github.com/users/rcurran1/orgs","repos_url":"https://api.github.com/users/rcurran1/repos","events_url":"https://api.github.com/users/rcurran1/events{/privacy}","received_events_url":"https://api.github.com/users/rcurran1/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-03-29T13:41:54Z","updated_at":"2018-03-30T17:05:08Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2139acd96b2ec35ce465c53b9848f53c2dd0274c","assignee":null,"assignees":[],"requested_reviewers":[{"login":"frankbu","id":2752495,"avatar_url":"https://avatars2.githubusercontent.com/u/2752495?v=4","gravatar_id":"","url":"https://api.github.com/users/frankbu","html_url":"https://github.com/frankbu","followers_url":"https://api.github.com/users/frankbu/followers","following_url":"https://api.github.com/users/frankbu/following{/other_user}","gists_url":"https://api.github.com/users/frankbu/gists{/gist_id}","starred_url":"https://api.github.com/users/frankbu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/frankbu/subscriptions","organizations_url":"https://api.github.com/users/frankbu/orgs","repos_url":"https://api.github.com/users/frankbu/repos","events_url":"https://api.github.com/users/frankbu/events{/privacy}","received_events_url":"https://api.github.com/users/frankbu/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[{"id":884247475,"url":"https://api.github.com/repos/istio/istio.github.io/labels/cla:%20yes","name":"cla: yes","color":"a8d14b","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/istio/istio.github.io/pulls/1119/commits","review_comments_url":"https://api.github.com/repos/istio/istio.github.io/pulls/1119/comments","review_comment_url":"https://api.github.com/repos/istio/istio.github.io/pulls/comments{/number}","comments_url":"https://api.github.com/repos/istio/istio.github.io/issues/1119/comments","statuses_url":"https://api.github.com/repos/istio/istio.github.io/statuses/28159a5533e9e482e402becaaf87e366a3c2565d","head":{"label":"rcurran1:rcurran/multitenancy_blog2","ref":"rcurran/multitenancy_blog2","sha":"28159a5533e9e482e402becaaf87e366a3c2565d","user":{"login":"rcurran1","id":3076511,"avatar_url":"https://avatars2.githubusercontent.com/u/3076511?v=4","gravatar_id":"","url":"https://api.github.com/users/rcurran1","html_url":"https://github.com/rcurran1","followers_url":"https://api.github.com/users/rcurran1/followers","following_url":"https://api.github.com/users/rcurran1/following{/other_user}","gists_url":"https://api.github.com/users/rcurran1/gists{/gist_id}","starred_url":"https://api.github.com/users/rcurran1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rcurran1/subscriptions","organizations_url":"https://api.github.com/users/rcurran1/orgs","repos_url":"https://api.github.com/users/rcurran1/repos","events_url":"https://api.github.com/users/rcurran1/events{/privacy}","received_events_url":"https://api.github.com/users/rcurran1/received_events","type":"User","site_admin":false},"repo":{"id":108443824,"name":"istio.github.io","full_name":"rcurran1/istio.github.io","owner":{"login":"rcurran1","id":3076511,"avatar_url":"https://avatars2.githubusercontent.com/u/3076511?v=4","gravatar_id":"","url":"https://api.github.com/users/rcurran1","html_url":"https://github.com/rcurran1","followers_url":"https://api.github.com/users/rcurran1/followers","following_url":"https://api.github.com/users/rcurran1/following{/other_user}","gists_url":"https://api.github.com/users/rcurran1/gists{/gist_id}","starred_url":"https://api.github.com/users/rcurran1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rcurran1/subscriptions","organizations_url":"https://api.github.com/users/rcurran1/orgs","repos_url":"https://api.github.com/users/rcurran1/repos","events_url":"https://api.github.com/users/rcurran1/events{/privacy}","received_events_url":"https://api.github.com/users/rcurran1/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/rcurran1/istio.github.io","description":"Source for the istio.io site","fork":true,"url":"https://api.github.com/repos/rcurran1/istio.github.io","forks_url":"https://api.github.com/repos/rcurran1/istio.github.io/forks","keys_url":"https://api.github.com/repos/rcurran1/istio.github.io/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rcurran1/istio.github.io/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rcurran1/istio.github.io/teams","hooks_url":"https://api.github.com/repos/rcurran1/istio.github.io/hooks","issue_events_url":"https://api.github.com/repos/rcurran1/istio.github.io/issues/events{/number}","events_url":"https://api.github.com/repos/rcurran1/istio.github.io/events","assignees_url":"https://api.github.com/repos/rcurran1/istio.github.io/assignees{/user}","branches_url":"https://api.github.com/repos/rcurran1/istio.github.io/branches{/branch}","tags_url":"https://api.github.com/repos/rcurran1/istio.github.io/tags","blobs_url":"https://api.github.com/repos/rcurran1/istio.github.io/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rcurran1/istio.github.io/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rcurran1/istio.github.io/git/refs{/sha}","trees_url":"https://api.github.com/repos/rcurran1/istio.github.io/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rcurran1/istio.github.io/statuses/{sha}","languages_url":"https://api.github.com/repos/rcurran1/istio.github.io/languages","stargazers_url":"https://api.github.com/repos/rcurran1/istio.github.io/stargazers","contributors_url":"https://api.github.com/repos/rcurran1/istio.github.io/contributors","subscribers_url":"https://api.github.com/repos/rcurran1/istio.github.io/subscribers","subscription_url":"https://api.github.com/repos/rcurran1/istio.github.io/subscription","commits_url":"https://api.github.com/repos/rcurran1/istio.github.io/commits{/sha}","git_commits_url":"https://api.github.com/repos/rcurran1/istio.github.io/git/commits{/sha}","comments_url":"https://api.github.com/repos/rcurran1/istio.github.io/comments{/number}","issue_comment_url":"https://api.github.com/repos/rcurran1/istio.github.io/issues/comments{/number}","contents_url":"https://api.github.com/repos/rcurran1/istio.github.io/contents/{+path}","compare_url":"https://api.github.com/repos/rcurran1/istio.github.io/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rcurran1/istio.github.io/merges","archive_url":"https://api.github.com/repos/rcurran1/istio.github.io/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rcurran1/istio.github.io/downloads","issues_url":"https://api.github.com/repos/rcurran1/istio.github.io/issues{/number}","pulls_url":"https://api.github.com/repos/rcurran1/istio.github.io/pulls{/number}","milestones_url":"https://api.github.com/repos/rcurran1/istio.github.io/milestones{/number}","notifications_url":"https://api.github.com/repos/rcurran1/istio.github.io/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rcurran1/istio.github.io/labels{/name}","releases_url":"https://api.github.com/repos/rcurran1/istio.github.io/releases{/id}","deployments_url":"https://api.github.com/repos/rcurran1/istio.github.io/deployments","created_at":"2017-10-26T17:29:11Z","updated_at":"2018-03-28T20:56:55Z","pushed_at":"2018-03-30T16:19:22Z","git_url":"git://github.com/rcurran1/istio.github.io.git","ssh_url":"git@github.com:rcurran1/istio.github.io.git","clone_url":"https://github.com/rcurran1/istio.github.io.git","svn_url":"https://github.com/rcurran1/istio.github.io","homepage":"https://istio.io/","size":22483,"stargazers_count":0,"watchers_count":0,"language":"HTML","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"istio:master","ref":"master","sha":"f6c4cac1a125212a751cbd9f81d212a74a87be1d","user":{"login":"istio","id":23534644,"avatar_url":"https://avatars1.githubusercontent.com/u/23534644?v=4","gravatar_id":"","url":"https://api.github.com/users/istio","html_url":"https://github.com/istio","followers_url":"https://api.github.com/users/istio/followers","following_url":"https://api.github.com/users/istio/following{/other_user}","gists_url":"https://api.github.com/users/istio/gists{/gist_id}","starred_url":"https://api.github.com/users/istio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/istio/subscriptions","organizations_url":"https://api.github.com/users/istio/orgs","repos_url":"https://api.github.com/users/istio/repos","events_url":"https://api.github.com/users/istio/events{/privacy}","received_events_url":"https://api.github.com/users/istio/received_events","type":"Organization","site_admin":false},"repo":{"id":82706976,"name":"istio.github.io","full_name":"istio/istio.github.io","owner":{"login":"istio","id":23534644,"avatar_url":"https://avatars1.githubusercontent.com/u/23534644?v=4","gravatar_id":"","url":"https://api.github.com/users/istio","html_url":"https://github.com/istio","followers_url":"https://api.github.com/users/istio/followers","following_url":"https://api.github.com/users/istio/following{/other_user}","gists_url":"https://api.github.com/users/istio/gists{/gist_id}","starred_url":"https://api.github.com/users/istio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/istio/subscriptions","organizations_url":"https://api.github.com/users/istio/orgs","repos_url":"https://api.github.com/users/istio/repos","events_url":"https://api.github.com/users/istio/events{/privacy}","received_events_url":"https://api.github.com/users/istio/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/istio/istio.github.io","description":"Source for the istio.io site","fork":false,"url":"https://api.github.com/repos/istio/istio.github.io","forks_url":"https://api.github.com/repos/istio/istio.github.io/forks","keys_url":"https://api.github.com/repos/istio/istio.github.io/keys{/key_id}","collaborators_url":"https://api.github.com/repos/istio/istio.github.io/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/istio/istio.github.io/teams","hooks_url":"https://api.github.com/repos/istio/istio.github.io/hooks","issue_events_url":"https://api.github.com/repos/istio/istio.github.io/issues/events{/number}","events_url":"https://api.github.com/repos/istio/istio.github.io/events","assignees_url":"https://api.github.com/repos/istio/istio.github.io/assignees{/user}","branches_url":"https://api.github.com/repos/istio/istio.github.io/branches{/branch}","tags_url":"https://api.github.com/repos/istio/istio.github.io/tags","blobs_url":"https://api.github.com/repos/istio/istio.github.io/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/istio/istio.github.io/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/istio/istio.github.io/git/refs{/sha}","trees_url":"https://api.github.com/repos/istio/istio.github.io/git/trees{/sha}","statuses_url":"https://api.github.com/repos/istio/istio.github.io/statuses/{sha}","languages_url":"https://api.github.com/repos/istio/istio.github.io/languages","stargazers_url":"https://api.github.com/repos/istio/istio.github.io/stargazers","contributors_url":"https://api.github.com/repos/istio/istio.github.io/contributors","subscribers_url":"https://api.github.com/repos/istio/istio.github.io/subscribers","subscription_url":"https://api.github.com/repos/istio/istio.github.io/subscription","commits_url":"https://api.github.com/repos/istio/istio.github.io/commits{/sha}","git_commits_url":"https://api.github.com/repos/istio/istio.github.io/git/commits{/sha}","comments_url":"https://api.github.com/repos/istio/istio.github.io/comments{/number}","issue_comment_url":"https://api.github.com/repos/istio/istio.github.io/issues/comments{/number}","contents_url":"https://api.github.com/repos/istio/istio.github.io/contents/{+path}","compare_url":"https://api.github.com/repos/istio/istio.github.io/compare/{base}...{head}","merges_url":"https://api.github.com/repos/istio/istio.github.io/merges","archive_url":"https://api.github.com/repos/istio/istio.github.io/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/istio/istio.github.io/downloads","issues_url":"https://api.github.com/repos/istio/istio.github.io/issues{/number}","pulls_url":"https://api.github.com/repos/istio/istio.github.io/pulls{/number}","milestones_url":"https://api.github.com/repos/istio/istio.github.io/milestones{/number}","notifications_url":"https://api.github.com/repos/istio/istio.github.io/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/istio/istio.github.io/labels{/name}","releases_url":"https://api.github.com/repos/istio/istio.github.io/releases{/id}","deployments_url":"https://api.github.com/repos/istio/istio.github.io/deployments","created_at":"2017-02-21T17:19:49Z","updated_at":"2018-03-30T01:02:02Z","pushed_at":"2018-03-30T16:38:46Z","git_url":"git://github.com/istio/istio.github.io.git","ssh_url":"git@github.com:istio/istio.github.io.git","clone_url":"https://github.com/istio/istio.github.io.git","svn_url":"https://github.com/istio/istio.github.io","homepage":"https://istio.io/","size":21497,"stargazers_count":52,"watchers_count":52,"language":"HTML","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":161,"mirror_url":null,"archived":false,"open_issues_count":67,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":161,"open_issues":67,"watchers":52,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/istio/istio.github.io/pulls/1119"},"html":{"href":"https://github.com/istio/istio.github.io/pull/1119"},"issue":{"href":"https://api.github.com/repos/istio/istio.github.io/issues/1119"},"comments":{"href":"https://api.github.com/repos/istio/istio.github.io/issues/1119/comments"},"review_comments":{"href":"https://api.github.com/repos/istio/istio.github.io/pulls/1119/comments"},"review_comment":{"href":"https://api.github.com/repos/istio/istio.github.io/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/istio/istio.github.io/pulls/1119/commits"},"statuses":{"href":"https://api.github.com/repos/istio/istio.github.io/statuses/28159a5533e9e482e402becaaf87e366a3c2565d"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"geeknoid"}}