/
github.go
145 lines (116 loc) · 3.91 KB
/
github.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package fetch
import (
"context"
"fmt"
"strings"
log "github.com/Sirupsen/logrus"
"github.com/google/go-github/github"
"golang.org/x/oauth2"
)
// GithubFetchParams contains all parameters what are required for fetching tokens from GitHub
type GithubFetchParams struct {
Token string
TeamNames []string
PublicMembersOnly bool
}
// GitHubOrganisationKeys fetches organization users public SSH key from GitHub
func GitHubOrganisationKeys(organizationName string, params GithubFetchParams) (map[string][]string, error) {
client := getClient(params.Token)
users, err := fetchUsers(client, organizationName, params)
if err != nil {
return map[string][]string{}, err
}
log.Debugf("Users found: %d", len(users))
usernames := []string{}
for _, user := range users {
usernames = append(usernames, *user.Login)
}
return fetchUserKeys(client, usernames, params.Token)
}
// GitHubUsers fetches users public SSH keys from GitHub
func GitHubUsers(usernames []string, token string) (map[string][]string, error) {
client := getClient(token)
return fetchUserKeys(client, usernames, token)
}
// GitHubDeployKeys fetches repositories' SSH keys from GitHub
func GitHubDeployKeys(ownerRepos []string, token string) (map[string][]string, error) {
client := getClient(token)
return fetchDeployKeys(client, ownerRepos, token)
}
func getClient(token string) *github.Client {
if len(token) > 0 {
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: token},
)
return github.NewClient(oauth2.NewClient(oauth2.NoContext, ts))
}
return github.NewClient(nil)
}
func fetchUsers(client *github.Client, organizationName string, params GithubFetchParams) ([]*github.User, error) {
ctx := context.Background()
if len(params.TeamNames) > 0 {
var users []*github.User
for _, teamName := range params.TeamNames {
teamID, err := resolveTeamID(client, organizationName, teamName)
if err != nil {
return []*github.User{}, err
}
teamUsers, _, err := client.Teams.ListTeamMembers(ctx, teamID, &github.TeamListTeamMembersOptions{})
if err != nil {
return []*github.User{}, err
}
users = append(users, teamUsers...)
}
return users, nil
}
users, _, err := client.Organizations.ListMembers(ctx, organizationName, &github.ListMembersOptions{
PublicOnly: params.PublicMembersOnly,
})
return users, err
}
func resolveTeamID(client *github.Client, organizationName, teamName string) (int64, error) {
ctx := context.Background()
teams, _, err := client.Teams.ListTeams(ctx, organizationName, &github.ListOptions{})
if err != nil {
return -1, err
}
for _, team := range teams {
if strings.EqualFold(*team.Name, teamName) || strings.EqualFold(*team.Slug, teamName) {
return *team.ID, nil
}
}
return -1, fmt.Errorf("Unable to find team [%s] from organization [%s]", teamName, organizationName)
}
func fetchUserKeys(client *github.Client, usernames []string, token string) (map[string][]string, error) {
ctx := context.Background()
result := map[string][]string{}
for _, username := range usernames {
keys, _, err := client.Users.ListKeys(ctx, username, &github.ListOptions{})
if err != nil {
return map[string][]string{}, err
}
result[username] = make([]string, len(keys))
for index, key := range keys {
result[username][index] = *key.Key
}
}
return result, nil
}
func fetchDeployKeys(client *github.Client, ownerRepos []string, token string) (map[string][]string, error) {
ctx := context.Background()
result := map[string][]string{}
for _, ownerRepo := range ownerRepos {
ownerRepoSplit := strings.SplitN(ownerRepo, "/", 2)
owner := ownerRepoSplit[0]
repo := ownerRepoSplit[1]
keys, _, err := client.Repositories.ListKeys(ctx, owner, repo, &github.ListOptions{})
if err != nil {
return map[string][]string{}, err
}
result[ownerRepo] = make([]string, len(keys))
for index, key := range keys {
result[ownerRepo][index] = *key.Key
}
}
return result, nil
}