Skip to content

Commit 64acc04

Browse files
committed
Version 1.0.0
0 parents  commit 64acc04

File tree

11 files changed

+1319
-0
lines changed

11 files changed

+1319
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
8

Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM node:8-alpine
2+
3+
WORKDIR /app
4+
ADD package.json /app/package.json
5+
RUN npm install
6+
ADD . /app
7+
8+
EXPOSE 3000
9+
CMD /app/node_modules/.bin/fastify index.js

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# [authorizedkeys-github](https://github.com/marcbachmann/authorizedkeys-github) [![](https://img.shields.io/docker/automated/marcbachmann/authorizedkeys-github.svg)](https://hub.docker.com/r/marcbachmann/authorizedkeys-github)
2+
3+
A server that fetches public keys of all members of a github team and writes them into an `.ssh/authorized_keys` file.
4+
5+
You can see a list of all users and their keys on `http://localhost:3000/`
6+
7+
### Usage
8+
9+
```bash
10+
docker run -it -v /root/.ssh:/user/.ssh -p 3000:3000 \
11+
-e 'GITHUB_TOKEN=your-github-token' \
12+
-e 'GITHUB_ORG=upfrontIO' \
13+
-e 'GITHUB_TEAM=Livingdocs' \
14+
-e 'AUTHORIZED_KEYS_PATH=/Users/marcbachmann/.ssh/authorized_keys' \
15+
marcbachmann/authorizedkeys-github
16+
17+
# or
18+
19+
docker run -it -v /root/.ssh:/user/.ssh -p 3000:3000 \
20+
-e 'GITHUB_TOKEN=your-github-token' \
21+
-e 'GITHUB_TEAM_ID=352089' \
22+
-e 'AUTHORIZED_KEYS_PATH=/user/.ssh/authorized_keys' \
23+
marcbachmann/authorizedkeys-github
24+
```

circle.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
dependencies:
2+
cache_directories:
3+
- ~/.npm
4+
pre:
5+
- rm -Rf ./node_modules
6+
override:
7+
- nvm install && nvm alias default $(cat .nvmrc)
8+
- npm install
9+
10+
test:
11+
override:
12+
- npm test

index.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
module.exports = function (fastify, opts, cb) {
2+
const log = fastify.logger.logger
3+
const GITHUB_TOKEN = process.env.GITHUB_TOKEN
4+
const GITHUB_ORG = process.env.GITHUB_ORG
5+
const GITHUB_TEAM = process.env.GITHUB_TEAM
6+
const GITHUB_TEAM_ID = process.env.GITHUB_TEAM_ID
7+
const AUTHORIZED_KEYS_PATH = process.env.AUTHORIZED_KEYS_PATH
8+
const SYNC_INTERVAL = process.env.SYNC_INTERVAL
9+
10+
if (!GITHUB_TOKEN) throw new Error('The env variable GITHUB_TOKEN is required')
11+
if (!AUTHORIZED_KEYS_PATH) throw new Error('The env variable AUTHORIZED_KEYS_PATH is required')
12+
if (!GITHUB_TEAM_ID && !(GITHUB_ORG && GITHUB_TEAM)) throw new Error('The env variable GITHUB_TEAM_ID or the combination of GITHUB_ORG and GITHUB_TEAM are required.')
13+
14+
const keys = require('./keys')({token: GITHUB_TOKEN})
15+
const getParams = {org: GITHUB_ORG, teamName: GITHUB_TEAM, teamId: GITHUB_TEAM_ID}
16+
17+
setInterval(sync, SYNC_INTERVAL || 5*60 * 1000)
18+
sync()
19+
20+
function sync () {
21+
keys.get(getParams).then(function (users) {
22+
require('./update')(AUTHORIZED_KEYS_PATH, users, function (err) {
23+
if (err) {
24+
log.fatal(err)
25+
process.exit(1)
26+
}
27+
})
28+
}).catch(function (err) {
29+
log.fatal(err)
30+
process.exit(1)
31+
})
32+
}
33+
34+
fastify.get('/', (req, rep) => keys.get(getParams))
35+
36+
cb()
37+
}

keys.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
const GitHubApi = require('github')
2+
const headers = {'user-agent': 'authorizedkeys-github-server'}
3+
const timeout = 5000
4+
5+
module.exports = function (opts) {
6+
const token = opts.token
7+
opts = Object.assign({timeout, headers}, opts)
8+
opts.token = undefined
9+
10+
const client = new GitHubApi(opts)
11+
client.authenticate({type: 'token', token})
12+
13+
return {
14+
get: function (query) {
15+
return getMembers(client, query).then(getKeysOfUsers.bind(null, client))
16+
}
17+
}
18+
}
19+
20+
function getMembers (client, {teamId, org, teamName}) {
21+
let q
22+
if (teamId) return getTeamMembers(client, teamId)
23+
24+
if (!org) throw new Error('The option `org` is required.')
25+
if (!teamName) throw new Error('The option `teamName` is required.')
26+
return client.orgs.getTeams({org}).then(getMembersByTeamArray(client, teamName))
27+
}
28+
29+
function getMembersByTeamArray (client, teamName) {
30+
return function (res) {
31+
const team = res.data.find((t) => t.name === teamName)
32+
if (!team) throw new Error(`No team found with the name '${teamName}'`)
33+
return getTeamMembers(client, team.id)
34+
}
35+
}
36+
37+
function getTeamMembers (client, id) {
38+
return client.orgs.getTeamMembers({id}).then((res) => res.data.filter((m) => m.type === 'User'))
39+
}
40+
41+
function getKeysOfUsers (client, users) {
42+
const getKey = getKeyOfUser.bind(null, client)
43+
return Promise.all(users.map(getKey)).then(function (keyz) {
44+
return users.map(function (user, i) {
45+
return {
46+
id: user.id,
47+
login: user.login,
48+
avatar_url: user.avatar_url,
49+
keys: keyz[i]
50+
}
51+
})
52+
})
53+
}
54+
55+
function getKeyOfUser (client, user) {
56+
return client.users.getKeysForUser({username: user.login}).then((res) => res.data.map((k) => k.key))
57+
}

0 commit comments

Comments
 (0)