Skip to content

Commit 545b209

Browse files
authored
Merge pull request ernoaapa#16 from arnested/deploy-key
Add `--deploy-key` parameter
2 parents 88a1a31 + cf3b80b commit 545b209

File tree

4 files changed

+80
-9
lines changed

4 files changed

+80
-9
lines changed

README.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ fetch-ssh-keys github --organization my-awesome-company --team my-lovely-team --
1919

2020
# Fetch 'ernoaapa' and 'arnested' public keys
2121
fetch-ssh-keys github --user ernoaapa --user arnested --token YOUR-TOKEN-HERE ./the-keys
22+
23+
# Fetch 'ernoaapa/fetch-ssh-keys' deploy keys (requires a Github token with the `repo` or `public_repo` scope)
24+
fetch-ssh-keys github --deploy-key ernoaapa/fetch-ssh-keys --token YOUR-TOKEN-HERE ./the-keys
2225
```
2326

2427
Tool can be used for example to automatically update `.ssh/authorized_keys` file by giving path to `.ssh/authorized_keys` as last argument and adding the script to cron job.
@@ -40,10 +43,13 @@ Tool can be used for example to automatically update `.ssh/authorized_keys` file
4043
| --organization | Name of the organization which members keys to pick |
4144
| --team | Name or slug of the team which members keys to pick |
4245
| --user | Name of the user which keys to pick |
46+
| --deploy-key | Name of the owner/repo which deploy keys to pick |
4347
| --token | GitHub API token to use for communication. Without token you get only public members of the organization. |
4448
| --public-only | Return only members what are publicly members of the given organization |
4549

46-
You can give `--organisation` (optionally combined with `--team` flag) and/or one or more `--user` flags.
50+
You can give `--organisation` (optionally combined with `--team` flag) and/or one or more `--user` or `--deploy-key` flags.
51+
52+
The `--deploy-key` parameter requires a Github token with the `repo` or `public_repo` scope.
4753

4854
## Development
4955
### Get dependencies

fetch/github.go

+31-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ func GitHubUsers(usernames []string, token string) (map[string][]string, error)
4040
return fetchUserKeys(client, usernames, token)
4141
}
4242

43+
// GitHubDeployKeys fetches repositories' SSH keys from GitHub
44+
func GitHubDeployKeys(ownerRepos []string, token string) (map[string][]string, error) {
45+
client := getClient(token)
46+
return fetchDeployKeys(client, ownerRepos, token)
47+
}
48+
4349
func getClient(token string) *github.Client {
4450
if len(token) > 0 {
4551
ts := oauth2.StaticTokenSource(
@@ -61,7 +67,7 @@ func fetchUsers(client *github.Client, organizationName string, params GithubFet
6167
return []*github.User{}, err
6268
}
6369

64-
teamUsers, _, err := client.Organizations.ListTeamMembers(ctx, teamID, &github.OrganizationListTeamMembersOptions{})
70+
teamUsers, _, err := client.Teams.ListTeamMembers(ctx, teamID, &github.TeamListTeamMembersOptions{})
6571
if err != nil {
6672
return []*github.User{}, err
6773
}
@@ -81,7 +87,7 @@ func fetchUsers(client *github.Client, organizationName string, params GithubFet
8187
func resolveTeamID(client *github.Client, organizationName, teamName string) (int64, error) {
8288
ctx := context.Background()
8389

84-
teams, _, err := client.Organizations.ListTeams(ctx, organizationName, &github.ListOptions{})
90+
teams, _, err := client.Teams.ListTeams(ctx, organizationName, &github.ListOptions{})
8591
if err != nil {
8692
return -1, err
8793
}
@@ -114,3 +120,26 @@ func fetchUserKeys(client *github.Client, usernames []string, token string) (map
114120

115121
return result, nil
116122
}
123+
124+
func fetchDeployKeys(client *github.Client, ownerRepos []string, token string) (map[string][]string, error) {
125+
ctx := context.Background()
126+
127+
result := map[string][]string{}
128+
for _, ownerRepo := range ownerRepos {
129+
ownerRepoSplit := strings.SplitN(ownerRepo, "/", 2)
130+
owner := ownerRepoSplit[0]
131+
repo := ownerRepoSplit[1]
132+
keys, _, err := client.Repositories.ListKeys(ctx, owner, repo, &github.ListOptions{})
133+
if err != nil {
134+
return map[string][]string{}, err
135+
}
136+
137+
result[ownerRepo] = make([]string, len(keys))
138+
139+
for index, key := range keys {
140+
result[ownerRepo][index] = *key.Key
141+
}
142+
}
143+
144+
return result, nil
145+
}

fetch/github_deploy_key_test.go

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// +build deploy_key
2+
3+
package fetch
4+
5+
import (
6+
"os"
7+
"testing"
8+
9+
log "github.com/Sirupsen/logrus"
10+
11+
"github.com/stretchr/testify/assert"
12+
)
13+
14+
func TestFetchDeployKeys(t *testing.T) {
15+
log.SetLevel(log.DebugLevel)
16+
17+
keys, err := GitHubDeployKeys([]string{"arnested/fetch-ssh-keys"}, os.Getenv("GITHUB_TOKEN"))
18+
19+
assert.NoError(t, err, "Fetch GitHub keys returned error")
20+
assert.Equal(t, 1, len(keys), "should return SSH keys for 'arnested/fetch-ssh-keys'")
21+
assert.True(t, len(keys["arnested/fetch-ssh-keys"]) > 0, "should return 'arnested/fetch-ssh-keys' deploy SSH key")
22+
assert.True(t, len(keys["arnested/fetch-ssh-keys"][0]) > 0, "should not return empty key for 'arnested/fetch-ssh-keys'")
23+
}

main.go

+19-6
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ func main() {
6464
},
6565
cli.StringSliceFlag{
6666
Name: "user",
67-
Usage: "Return given user public ssh keys (this option can be used multiple times for multiple users)",
67+
Usage: "Return given `USER` public ssh keys (this option can be used multiple times for multiple users)",
68+
},
69+
cli.StringSliceFlag{
70+
Name: "deploy-key",
71+
Usage: "Return given `OWNER/REPO` deploy ssh keys (this option can be used multiple times for multiple repositories)",
6872
},
6973
},
7074
Action: func(c *cli.Context) error {
@@ -73,10 +77,12 @@ func main() {
7377
organisation = c.String("organization")
7478
teams = c.StringSlice("team")
7579
users = c.StringSlice("user")
80+
ownerRepos = c.StringSlice("deploy-key")
7681
publicOnly = c.Bool("public-only")
7782

78-
orgKeys map[string][]string
79-
userKeys map[string][]string
83+
deployKeys map[string][]string
84+
orgKeys map[string][]string
85+
userKeys map[string][]string
8086

8187
target = c.Args().Get(0)
8288
fileMode = os.FileMode(c.GlobalInt("file-mode"))
@@ -86,8 +92,8 @@ func main() {
8692
err error
8793
)
8894

89-
if organisation == "" && len(users) == 0 {
90-
return fmt.Errorf("You must give either --organisation or --user parameter")
95+
if organisation == "" && len(users) == 0 && len(ownerRepos) == 0 {
96+
return fmt.Errorf("You must give either --organisation or --user or --deploy-key parameter")
9197
}
9298

9399
if c.IsSet("organization") {
@@ -108,7 +114,14 @@ func main() {
108114
}
109115
}
110116

111-
return output.Write(format, target, fileMode, utils.MergeKeys(orgKeys, userKeys), comment)
117+
if c.IsSet("deploy-key") {
118+
deployKeys, err = fetch.GitHubDeployKeys(ownerRepos, token)
119+
if err != nil {
120+
return errors.Wrap(err, "Failed to fetch GitHub repositories' deploy keys")
121+
}
122+
}
123+
124+
return output.Write(format, target, fileMode, utils.MergeKeys(orgKeys, userKeys, deployKeys), comment)
112125
},
113126
},
114127
}

0 commit comments

Comments
 (0)