-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
130 lines (110 loc) · 3.24 KB
/
main.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
package main
import (
"flag"
"fmt"
"log"
"os"
"os/user"
"path/filepath"
"strings"
)
const usageMessage = `
'ghkeys' uses the GitHub API to get the SSH keys of individual users and/or
members of teams and either print them or write them to authorized_keys files.
Pass a single 'username' argument to only print/write keys for that user.
Usage:
ghkeys [-config="/path/to/config.yml"] [-write] [username]
`
var (
// VERSION swapped out by `go build -ldflags "-X main.VERSION 1.2.3"`
VERSION = "0.0.10"
configFilename = flag.String("config", "config.yml", "Path to yaml config file")
debug = flag.Bool("d", false, "Add debugging output")
showVersion = flag.Bool("version", false, "Display the version number")
writeToFile = flag.Bool("write", false, "Write keys to users' authorized_keys files")
)
func printVersion() {
fmt.Printf("ghkeys version %s\n", VERSION)
}
func usage() {
printVersion()
fmt.Println(usageMessage + "\nFlags:")
flag.PrintDefaults()
}
func check(err error) {
if err != nil {
log.Fatal(err)
}
}
type usernameKeys struct {
username string
keys []string
}
func getUsernamesKeys(config config, client *githubClient, singleUsername string) map[string][]string {
usernamesKeys := make(map[string][]string)
usernameCount := 0
usernameKeysChan := make(chan usernameKeys)
for _, user := range config.Users {
if singleUsername == "" || singleUsername == user.Username {
usernameCount++
go func(username string, users, teams []string) {
keys := client.getKeysOfUsersAndTeams(users, teams)
usernameKeysChan <- usernameKeys{username: username, keys: keys}
}(user.Username, user.GithubUsers, user.GithubTeams)
}
}
for i := 0; i < usernameCount; i++ {
tempUsernameKeys := <-usernameKeysChan
usernamesKeys[tempUsernameKeys.username] = tempUsernameKeys.keys
}
return usernamesKeys
}
func getAuthorizedKeysFilename(userHomeDir string) string {
authorizedKeysFilename := filepath.Join(userHomeDir, ".ssh", "authorized_keys")
return authorizedKeysFilename
}
func getKeysOutput(keys []string) string {
keysOutput := strings.Join(keys, "\n")
return keysOutput
}
func writeKeysToUserAuthorizedKeysFile(keys []string, userHomeDir string) error {
authorizedKeysFilename := getAuthorizedKeysFilename(userHomeDir)
authorizedKeysFile, err := os.Create(authorizedKeysFilename)
if err != nil {
return err
}
defer authorizedKeysFile.Close()
keysOutput := getKeysOutput(keys) + "\n"
_, err = authorizedKeysFile.WriteString(keysOutput)
return err
}
func main() {
flag.Usage = usage
flag.Parse()
if *showVersion {
printVersion()
os.Exit(0)
}
config, err := newConfig(*configFilename)
check(err)
// TODO: validate config values
client := newGithubClient(config.GithubToken)
if *debug {
if rate, _, err := client.RateLimit(); err == nil {
log.Printf("GitHub API Rate Limit: %#v\n", rate)
}
}
usernamesKeys := getUsernamesKeys(config, client, flag.Arg(0))
for username, keys := range usernamesKeys {
if *writeToFile {
if user, err := user.Lookup(username); err == nil {
err = writeKeysToUserAuthorizedKeysFile(keys, user.HomeDir)
check(err)
} else {
log.Printf("User '%s' not found, no keys written.\n", username)
}
} else {
fmt.Println(getKeysOutput(keys))
}
}
}