{"action":"created","comment":{"url":"https://api.github.com/repos/ligato/cn-infra/pulls/comments/220258951","pull_request_review_id":158625310,"id":220258951,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIyMDI1ODk1MQ==","diff_hunk":"@@ -0,0 +1,304 @@\n+// Copyright (c) 2018 Cisco and/or its affiliates.\n+//\n+// Licensed under the Apache License, Version 2.0 (the \"License\");\n+// you may not use this file except in compliance with the License.\n+// You may obtain a copy of the License at:\n+//\n+//     http://www.apache.org/licenses/LICENSE-2.0\n+//\n+// Unless required by applicable law or agreed to in writing, software\n+// distributed under the License is distributed on an \"AS IS\" BASIS,\n+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+// See the License for the specific language governing permissions and\n+// limitations under the License.\n+\n+//go:generate protoc --proto_path=model/http-security --gogo_out=model/http-security model/http_security/httpsecurity.proto\n+\n+package security\n+\n+import (\n+\t\"fmt\"\n+\t\"net/http\"\n+\t\"strings\"\n+\t\"time\"\n+\n+\t\"github.com/dgrijalva/jwt-go\"\n+\t\"github.com/gorilla/mux\"\n+\t\"github.com/ligato/cn-infra/logging\"\n+\thttpsecurity \"github.com/ligato/cn-infra/rpc/rest/security/model/http-security\"\n+\t\"github.com/pkg/errors\"\n+\t\"github.com/unrolled/render\"\n+\t\"golang.org/x/crypto/bcrypt\"\n+)\n+\n+const (\n+\t// Helps to obtain authorization header matching the field in a request\n+\tauthHeaderStr = \"authorization\"\n+\t// Used to sign the token // todo maybe use something more secure\n+\tsecret = \"secret\"\n+\t// Admin constant, used to define admin security group and user\n+\tadmin = \"admin\"\n+)\n+\n+const (\n+\t// URL for login. Successful login returns token. Re-login invalidates old token and returns a new one.\n+\tlogin = \"/login\"\n+\t// URL key for logout, invalidates current token.\n+\tlogout = \"/logout\"\n+)\n+\n+// AuthenticatorAPI provides methods for handling permissions\n+type AuthenticatorAPI interface {\n+\t// AddPermissionGroup adds new permission group. PG is defined by name and a set of URL keys. User with\n+\t// permission group enabled has access to that set of keys. PGs with duplicated names are skipped.\n+\tAddPermissionGroup(group ...*httpsecurity.PermissionGroup)\n+\n+\t// Validate serves as middleware used while registering new HTTP handler. For every request, token\n+\t// and permission group is validated.\n+\tValidate(provider http.HandlerFunc) http.HandlerFunc\n+}\n+\n+// Authenticator keeps information about users, permission groups and tokens and processes it\n+type authenticator struct {\n+\tlog logging.Logger\n+\n+\t// Router instance automatically registers login/logout REST API handlers if authentication is enabled\n+\trouter    *mux.Router\n+\tformatter *render.Render\n+\n+\t// User database keeps all known users with permissions and hashed password. Users are loaded from\n+\t// HTTP config file // todo add other options\n+\tuserDb []*httpsecurity.User\n+\t// Permission database is a map of permissions and bound URLs\n+\tgroupDb []*httpsecurity.PermissionGroup\n+\t// Token database keeps information of actual token and its owner.\n+\ttokenDb map[string]string\n+\n+\t// Token claims\n+\texpTime int\n+}\n+\n+// NewAuthenticator prepares new instance of authenticator.\n+func NewAuthenticator(router *mux.Router, expTime int, users []httpsecurity.User, cost int, log logging.Logger) AuthenticatorAPI {\n+\ta := &authenticator{\n+\t\trouter: router,\n+\t\tlog:    log,\n+\t\tformatter: render.New(render.Options{\n+\t\t\tIndentJSON: true,\n+\t\t}),\n+\t\tuserDb:  make([]*httpsecurity.User, 0),\n+\t\ttokenDb: make(map[string]string),\n+\t\texpTime: expTime,\n+\t}\n+\n+\t// Add admin-user, enabled by default, always has access to every URL\n+\tusers = append(users, httpsecurity.User{\n+\t\tName:        admin,\n+\t\tPassword:    \"ligato123\",\n+\t\tPermissions: []string{admin},\n+\t})\n+\n+\tgo func() {\n+\t\t// Process users in go routine, since hashing may take some time\n+\t\tfor _, user := range users {\n+\t\t\t// Password hash cost is currently set via config file. Values allowed by bcrypt are in range 4-31. The min\n+\t\t\t// value will be set if cost is not defined in config file. Keep in mind that high cost values (>10) can\n+\t\t\t// take a lot of time to process.\n+\t\t\thash, err := bcrypt.GenerateFromPassword([]byte(user.Password), cost)\n+\t\t\tif err != nil {\n+\t\t\t\ta.log.Errorf(\"failed to hash password for user %s: %v\", user.Name, err)\n+\t\t\t\tcontinue\n+\t\t\t}\n+\n+\t\t\ta.userDb = append(a.userDb, &httpsecurity.User{\n+\t\t\t\tName:        user.Name,","path":"rpc/rest/security/rest_security.go","position":114,"original_position":114,"commit_id":"42f1af81d8ad534da5cf146b2d40e81cada60ae0","original_commit_id":"42f1af81d8ad534da5cf146b2d40e81cada60ae0","user":{"login":"ondrej-fabry","id":32484950,"node_id":"MDQ6VXNlcjMyNDg0OTUw","avatar_url":"https://avatars1.githubusercontent.com/u/32484950?v=4","gravatar_id":"","url":"https://api.github.com/users/ondrej-fabry","html_url":"https://github.com/ondrej-fabry","followers_url":"https://api.github.com/users/ondrej-fabry/followers","following_url":"https://api.github.com/users/ondrej-fabry/following{/other_user}","gists_url":"https://api.github.com/users/ondrej-fabry/gists{/gist_id}","starred_url":"https://api.github.com/users/ondrej-fabry/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ondrej-fabry/subscriptions","organizations_url":"https://api.github.com/users/ondrej-fabry/orgs","repos_url":"https://api.github.com/users/ondrej-fabry/repos","events_url":"https://api.github.com/users/ondrej-fabry/events{/privacy}","received_events_url":"https://api.github.com/users/ondrej-fabry/received_events","type":"User","site_admin":false},"body":"How do you deal with name collisions here?","created_at":"2018-09-25T16:13:21Z","updated_at":"2018-09-25T16:13:22Z","html_url":"https://github.com/ligato/cn-infra/pull/342#discussion_r220258951","pull_request_url":"https://api.github.com/repos/ligato/cn-infra/pulls/342","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/ligato/cn-infra/pulls/comments/220258951"},"html":{"href":"https://github.com/ligato/cn-infra/pull/342#discussion_r220258951"},"pull_request":{"href":"https://api.github.com/repos/ligato/cn-infra/pulls/342"}}},"pull_request":{"url":"https://api.github.com/repos/ligato/cn-infra/pulls/342","id":217882624,"node_id":"MDExOlB1bGxSZXF1ZXN0MjE3ODgyNjI0","html_url":"https://github.com/ligato/cn-infra/pull/342","diff_url":"https://github.com/ligato/cn-infra/pull/342.diff","patch_url":"https://github.com/ligato/cn-infra/pull/342.patch","issue_url":"https://api.github.com/repos/ligato/cn-infra/issues/342","number":342,"state":"open","locked":false,"title":"basic rest security using tokens","user":{"login":"VladoLavor","id":15376606,"node_id":"MDQ6VXNlcjE1Mzc2NjA2","avatar_url":"https://avatars2.githubusercontent.com/u/15376606?v=4","gravatar_id":"","url":"https://api.github.com/users/VladoLavor","html_url":"https://github.com/VladoLavor","followers_url":"https://api.github.com/users/VladoLavor/followers","following_url":"https://api.github.com/users/VladoLavor/following{/other_user}","gists_url":"https://api.github.com/users/VladoLavor/gists{/gist_id}","starred_url":"https://api.github.com/users/VladoLavor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VladoLavor/subscriptions","organizations_url":"https://api.github.com/users/VladoLavor/orgs","repos_url":"https://api.github.com/users/VladoLavor/repos","events_url":"https://api.github.com/users/VladoLavor/events{/privacy}","received_events_url":"https://api.github.com/users/VladoLavor/received_events","type":"User","site_admin":false},"body":"- authentication enabled/disabled in the config file\r\n- users are loaded from the config file, except admin which is always present (otherwise rest may get inaccessible if no users are loaded since registration is not available yet)\r\n- permission groups can be added to users with URLs specified (again, except admin group which is always present and has access to everything)\r\n- login generates token, log out invalidates it. Token may also expire if time is set in the config file\r\n\r\nSigned-off-by: Vladimir Lavor <vlavor@cisco.com>","created_at":"2018-09-25T07:39:27Z","updated_at":"2018-09-25T16:13:22Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ae48f4707b4848e4096b098ddf88311b1f21fb6c","assignee":{"login":"VladoLavor","id":15376606,"node_id":"MDQ6VXNlcjE1Mzc2NjA2","avatar_url":"https://avatars2.githubusercontent.com/u/15376606?v=4","gravatar_id":"","url":"https://api.github.com/users/VladoLavor","html_url":"https://github.com/VladoLavor","followers_url":"https://api.github.com/users/VladoLavor/followers","following_url":"https://api.github.com/users/VladoLavor/following{/other_user}","gists_url":"https://api.github.com/users/VladoLavor/gists{/gist_id}","starred_url":"https://api.github.com/users/VladoLavor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VladoLavor/subscriptions","organizations_url":"https://api.github.com/users/VladoLavor/orgs","repos_url":"https://api.github.com/users/VladoLavor/repos","events_url":"https://api.github.com/users/VladoLavor/events{/privacy}","received_events_url":"https://api.github.com/users/VladoLavor/received_events","type":"User","site_admin":false},"assignees":[{"login":"VladoLavor","id":15376606,"node_id":"MDQ6VXNlcjE1Mzc2NjA2","avatar_url":"https://avatars2.githubusercontent.com/u/15376606?v=4","gravatar_id":"","url":"https://api.github.com/users/VladoLavor","html_url":"https://github.com/VladoLavor","followers_url":"https://api.github.com/users/VladoLavor/followers","following_url":"https://api.github.com/users/VladoLavor/following{/other_user}","gists_url":"https://api.github.com/users/VladoLavor/gists{/gist_id}","starred_url":"https://api.github.com/users/VladoLavor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VladoLavor/subscriptions","organizations_url":"https://api.github.com/users/VladoLavor/orgs","repos_url":"https://api.github.com/users/VladoLavor/repos","events_url":"https://api.github.com/users/VladoLavor/events{/privacy}","received_events_url":"https://api.github.com/users/VladoLavor/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":906610626,"node_id":"MDU6TGFiZWw5MDY2MTA2MjY=","url":"https://api.github.com/repos/ligato/cn-infra/labels/%E2%9A%A1%EF%B8%8F%20Feature","name":"⚡️ Feature","color":"5319e7","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/ligato/cn-infra/pulls/342/commits","review_comments_url":"https://api.github.com/repos/ligato/cn-infra/pulls/342/comments","review_comment_url":"https://api.github.com/repos/ligato/cn-infra/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ligato/cn-infra/issues/342/comments","statuses_url":"https://api.github.com/repos/ligato/cn-infra/statuses/42f1af81d8ad534da5cf146b2d40e81cada60ae0","head":{"label":"VladoLavor:rest-security","ref":"rest-security","sha":"42f1af81d8ad534da5cf146b2d40e81cada60ae0","user":{"login":"VladoLavor","id":15376606,"node_id":"MDQ6VXNlcjE1Mzc2NjA2","avatar_url":"https://avatars2.githubusercontent.com/u/15376606?v=4","gravatar_id":"","url":"https://api.github.com/users/VladoLavor","html_url":"https://github.com/VladoLavor","followers_url":"https://api.github.com/users/VladoLavor/followers","following_url":"https://api.github.com/users/VladoLavor/following{/other_user}","gists_url":"https://api.github.com/users/VladoLavor/gists{/gist_id}","starred_url":"https://api.github.com/users/VladoLavor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VladoLavor/subscriptions","organizations_url":"https://api.github.com/users/VladoLavor/orgs","repos_url":"https://api.github.com/users/VladoLavor/repos","events_url":"https://api.github.com/users/VladoLavor/events{/privacy}","received_events_url":"https://api.github.com/users/VladoLavor/received_events","type":"User","site_admin":false},"repo":{"id":98873097,"node_id":"MDEwOlJlcG9zaXRvcnk5ODg3MzA5Nw==","name":"cn-infra","full_name":"VladoLavor/cn-infra","private":false,"owner":{"login":"VladoLavor","id":15376606,"node_id":"MDQ6VXNlcjE1Mzc2NjA2","avatar_url":"https://avatars2.githubusercontent.com/u/15376606?v=4","gravatar_id":"","url":"https://api.github.com/users/VladoLavor","html_url":"https://github.com/VladoLavor","followers_url":"https://api.github.com/users/VladoLavor/followers","following_url":"https://api.github.com/users/VladoLavor/following{/other_user}","gists_url":"https://api.github.com/users/VladoLavor/gists{/gist_id}","starred_url":"https://api.github.com/users/VladoLavor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VladoLavor/subscriptions","organizations_url":"https://api.github.com/users/VladoLavor/orgs","repos_url":"https://api.github.com/users/VladoLavor/repos","events_url":"https://api.github.com/users/VladoLavor/events{/privacy}","received_events_url":"https://api.github.com/users/VladoLavor/received_events","type":"User","site_admin":false},"html_url":"https://github.com/VladoLavor/cn-infra","description":"Cloud-native Virtual Network Function (VNF) framework","fork":true,"url":"https://api.github.com/repos/VladoLavor/cn-infra","forks_url":"https://api.github.com/repos/VladoLavor/cn-infra/forks","keys_url":"https://api.github.com/repos/VladoLavor/cn-infra/keys{/key_id}","collaborators_url":"https://api.github.com/repos/VladoLavor/cn-infra/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/VladoLavor/cn-infra/teams","hooks_url":"https://api.github.com/repos/VladoLavor/cn-infra/hooks","issue_events_url":"https://api.github.com/repos/VladoLavor/cn-infra/issues/events{/number}","events_url":"https://api.github.com/repos/VladoLavor/cn-infra/events","assignees_url":"https://api.github.com/repos/VladoLavor/cn-infra/assignees{/user}","branches_url":"https://api.github.com/repos/VladoLavor/cn-infra/branches{/branch}","tags_url":"https://api.github.com/repos/VladoLavor/cn-infra/tags","blobs_url":"https://api.github.com/repos/VladoLavor/cn-infra/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/VladoLavor/cn-infra/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/VladoLavor/cn-infra/git/refs{/sha}","trees_url":"https://api.github.com/repos/VladoLavor/cn-infra/git/trees{/sha}","statuses_url":"https://api.github.com/repos/VladoLavor/cn-infra/statuses/{sha}","languages_url":"https://api.github.com/repos/VladoLavor/cn-infra/languages","stargazers_url":"https://api.github.com/repos/VladoLavor/cn-infra/stargazers","contributors_url":"https://api.github.com/repos/VladoLavor/cn-infra/contributors","subscribers_url":"https://api.github.com/repos/VladoLavor/cn-infra/subscribers","subscription_url":"https://api.github.com/repos/VladoLavor/cn-infra/subscription","commits_url":"https://api.github.com/repos/VladoLavor/cn-infra/commits{/sha}","git_commits_url":"https://api.github.com/repos/VladoLavor/cn-infra/git/commits{/sha}","comments_url":"https://api.github.com/repos/VladoLavor/cn-infra/comments{/number}","issue_comment_url":"https://api.github.com/repos/VladoLavor/cn-infra/issues/comments{/number}","contents_url":"https://api.github.com/repos/VladoLavor/cn-infra/contents/{+path}","compare_url":"https://api.github.com/repos/VladoLavor/cn-infra/compare/{base}...{head}","merges_url":"https://api.github.com/repos/VladoLavor/cn-infra/merges","archive_url":"https://api.github.com/repos/VladoLavor/cn-infra/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/VladoLavor/cn-infra/downloads","issues_url":"https://api.github.com/repos/VladoLavor/cn-infra/issues{/number}","pulls_url":"https://api.github.com/repos/VladoLavor/cn-infra/pulls{/number}","milestones_url":"https://api.github.com/repos/VladoLavor/cn-infra/milestones{/number}","notifications_url":"https://api.github.com/repos/VladoLavor/cn-infra/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/VladoLavor/cn-infra/labels{/name}","releases_url":"https://api.github.com/repos/VladoLavor/cn-infra/releases{/id}","deployments_url":"https://api.github.com/repos/VladoLavor/cn-infra/deployments","created_at":"2017-07-31T09:40:33Z","updated_at":"2018-09-20T13:09:21Z","pushed_at":"2018-09-25T07:47:35Z","git_url":"git://github.com/VladoLavor/cn-infra.git","ssh_url":"git@github.com:VladoLavor/cn-infra.git","clone_url":"https://github.com/VladoLavor/cn-infra.git","svn_url":"https://github.com/VladoLavor/cn-infra","homepage":"","size":74206,"stargazers_count":0,"watchers_count":0,"language":"Go","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","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"ligato:master","ref":"master","sha":"0b5bfe9b247de942c552e455faac7e00e8efcda1","user":{"login":"ligato","id":28989152,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI4OTg5MTUy","avatar_url":"https://avatars0.githubusercontent.com/u/28989152?v=4","gravatar_id":"","url":"https://api.github.com/users/ligato","html_url":"https://github.com/ligato","followers_url":"https://api.github.com/users/ligato/followers","following_url":"https://api.github.com/users/ligato/following{/other_user}","gists_url":"https://api.github.com/users/ligato/gists{/gist_id}","starred_url":"https://api.github.com/users/ligato/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ligato/subscriptions","organizations_url":"https://api.github.com/users/ligato/orgs","repos_url":"https://api.github.com/users/ligato/repos","events_url":"https://api.github.com/users/ligato/events{/privacy}","received_events_url":"https://api.github.com/users/ligato/received_events","type":"Organization","site_admin":false},"repo":{"id":94889501,"node_id":"MDEwOlJlcG9zaXRvcnk5NDg4OTUwMQ==","name":"cn-infra","full_name":"ligato/cn-infra","private":false,"owner":{"login":"ligato","id":28989152,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI4OTg5MTUy","avatar_url":"https://avatars0.githubusercontent.com/u/28989152?v=4","gravatar_id":"","url":"https://api.github.com/users/ligato","html_url":"https://github.com/ligato","followers_url":"https://api.github.com/users/ligato/followers","following_url":"https://api.github.com/users/ligato/following{/other_user}","gists_url":"https://api.github.com/users/ligato/gists{/gist_id}","starred_url":"https://api.github.com/users/ligato/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ligato/subscriptions","organizations_url":"https://api.github.com/users/ligato/orgs","repos_url":"https://api.github.com/users/ligato/repos","events_url":"https://api.github.com/users/ligato/events{/privacy}","received_events_url":"https://api.github.com/users/ligato/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/ligato/cn-infra","description":"A platform for developing cloud-native VNFs","fork":false,"url":"https://api.github.com/repos/ligato/cn-infra","forks_url":"https://api.github.com/repos/ligato/cn-infra/forks","keys_url":"https://api.github.com/repos/ligato/cn-infra/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ligato/cn-infra/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ligato/cn-infra/teams","hooks_url":"https://api.github.com/repos/ligato/cn-infra/hooks","issue_events_url":"https://api.github.com/repos/ligato/cn-infra/issues/events{/number}","events_url":"https://api.github.com/repos/ligato/cn-infra/events","assignees_url":"https://api.github.com/repos/ligato/cn-infra/assignees{/user}","branches_url":"https://api.github.com/repos/ligato/cn-infra/branches{/branch}","tags_url":"https://api.github.com/repos/ligato/cn-infra/tags","blobs_url":"https://api.github.com/repos/ligato/cn-infra/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ligato/cn-infra/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ligato/cn-infra/git/refs{/sha}","trees_url":"https://api.github.com/repos/ligato/cn-infra/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ligato/cn-infra/statuses/{sha}","languages_url":"https://api.github.com/repos/ligato/cn-infra/languages","stargazers_url":"https://api.github.com/repos/ligato/cn-infra/stargazers","contributors_url":"https://api.github.com/repos/ligato/cn-infra/contributors","subscribers_url":"https://api.github.com/repos/ligato/cn-infra/subscribers","subscription_url":"https://api.github.com/repos/ligato/cn-infra/subscription","commits_url":"https://api.github.com/repos/ligato/cn-infra/commits{/sha}","git_commits_url":"https://api.github.com/repos/ligato/cn-infra/git/commits{/sha}","comments_url":"https://api.github.com/repos/ligato/cn-infra/comments{/number}","issue_comment_url":"https://api.github.com/repos/ligato/cn-infra/issues/comments{/number}","contents_url":"https://api.github.com/repos/ligato/cn-infra/contents/{+path}","compare_url":"https://api.github.com/repos/ligato/cn-infra/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ligato/cn-infra/merges","archive_url":"https://api.github.com/repos/ligato/cn-infra/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ligato/cn-infra/downloads","issues_url":"https://api.github.com/repos/ligato/cn-infra/issues{/number}","pulls_url":"https://api.github.com/repos/ligato/cn-infra/pulls{/number}","milestones_url":"https://api.github.com/repos/ligato/cn-infra/milestones{/number}","notifications_url":"https://api.github.com/repos/ligato/cn-infra/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ligato/cn-infra/labels{/name}","releases_url":"https://api.github.com/repos/ligato/cn-infra/releases{/id}","deployments_url":"https://api.github.com/repos/ligato/cn-infra/deployments","created_at":"2017-06-20T12:37:37Z","updated_at":"2018-09-25T12:59:51Z","pushed_at":"2018-09-25T13:04:10Z","git_url":"git://github.com/ligato/cn-infra.git","ssh_url":"git@github.com:ligato/cn-infra.git","clone_url":"https://github.com/ligato/cn-infra.git","svn_url":"https://github.com/ligato/cn-infra","homepage":"","size":74563,"stargazers_count":33,"watchers_count":33,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":28,"mirror_url":null,"archived":false,"open_issues_count":5,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":28,"open_issues":5,"watchers":33,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ligato/cn-infra/pulls/342"},"html":{"href":"https://github.com/ligato/cn-infra/pull/342"},"issue":{"href":"https://api.github.com/repos/ligato/cn-infra/issues/342"},"comments":{"href":"https://api.github.com/repos/ligato/cn-infra/issues/342/comments"},"review_comments":{"href":"https://api.github.com/repos/ligato/cn-infra/pulls/342/comments"},"review_comment":{"href":"https://api.github.com/repos/ligato/cn-infra/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ligato/cn-infra/pulls/342/commits"},"statuses":{"href":"https://api.github.com/repos/ligato/cn-infra/statuses/42f1af81d8ad534da5cf146b2d40e81cada60ae0"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"ondrej-fabry"}}