Skip to content

Commit

Permalink
moved toward using github as the source for ssh keys
Browse files Browse the repository at this point in the history
  • Loading branch information
malomalo committed Aug 20, 2013
1 parent f413b0a commit 77f520c
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 112 deletions.
8 changes: 2 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
install:
cp ssh-install /usr/local/bin/
cp ssh-package /usr/local/bin/
cp ssh-extract /usr/local/bin/
cp sync-accounts /usr/local/bin/

uninstall:
rm /usr/local/bin/ssh-install
rm /usr/local/bin/ssh-package
rm /usr/local/bin/ssh-extract
rm /usr/local/bin/sync-accounts
36 changes: 13 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,29 @@
SSH Key Managment
=================

These scripts allow you to manage ssh keys for users and groups of users
These scripts allow you to manage ssh keys for users and apps

### Users

User keys are placed in a file with the users name in the `users`
directory. This file contains ssh keys for that user. Each line is one
SSH key and blank lines are ignored.
Users are listed in `permissions.yml`. Users are created and deleted on servers
match the list in `permissions.yml`. SSH keys are retreived from github (user
names are assumed to be the github usernames).

### Groups
### Apps

Group files are placed in file with the group name in the `groups`
directory. This file contains the names of users belonging to the
group. Each line contains the one username. Blank lines are ignored.
If an app user exist on a server the keys for the users listed under that app
are copied over allowing the users to SSH and deploy the app on that server.

Commands
========

### Package

To package the `users` and `groups` for distribution run the `ssh-package
outputfile` script. This will generate a file that can be placed at a
location where other clients can download.

### Extract

`ssh-extract inputfile outputdir` will extract the keys to outputdir.

### Install

`ssh-install http://url/file` will download the file produced by `package` and
go through all the system users. If the username matches one of the user files
then the ssh keys will be placed into authorized_keys. If the username matches
a group name all the ssh keys for that group will be added to authorized_keys
`sync-accounts https://url/to/permissions.yml` will download the permissions
file and sync the users. If a user is in `permissions.yml` that is not on the
system that user will be created. If a user exist on the system but no in
`permissions.yml` that user will be deleated. If an user with the name of an app
exist the keys will be copied to that users `authorized_keys` file.

Installing
==========
Expand All @@ -48,4 +38,4 @@ Installing

You can set up cron to auto updated the ssh keys. Eg:

`0 * * * * /usr/local/bin/ssh-install http://domain.com/keysfile`
`0 * * * * /usr/local/bin/sync-accounts http://domain.com/permissions.yml`
10 changes: 10 additions & 0 deletions permissions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
users:
- github_user_name_1
- github_user_name_2

apps:
app1-staging:
- github_user_name_1
- github_user_name_2
app1-production:
- github_user_name_1
4 changes: 0 additions & 4 deletions ssh-extract

This file was deleted.

76 changes: 0 additions & 76 deletions ssh-install

This file was deleted.

3 changes: 0 additions & 3 deletions ssh-package

This file was deleted.

107 changes: 107 additions & 0 deletions sync-accounts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/usr/bin/env ruby
require 'uri'
require 'yaml'
require 'net/http'
require 'net/https'
require 'fileutils'

def github_keys(user)
http = Net::HTTP.new('github.com', 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

response = http.request(Net::HTTP::Get.new("/#{user}.keys"))
raise 'failure' unless response.is_a?(Net::HTTPOK)
response.body.split("\n")
end

def read_permissions(url)
url = URI.parse(url)
permissions = { 'apps' => {}, 'users' => {} }

yaml = Net::HTTP.start(url.host) do |http|
resp = http.get(url.path)
YAML.load(resp.body)
end

# Add keys to users and apps
yaml['users'].each do |user|
permissions['users'][user] = github_keys(user)
end
yaml['apps'].each do |app, users|
permissions['apps'][app] = users.map{|u| permissions['users'][u] }.flatten
end

permissions
end

def system_users
users = `cat /etc/passwd | grep -v root | grep '/bin/bash'`.split.map do |u|
u =~ /([^\s]+):.*:.*:.*:.*:([^\s]+):\/bin\/bash$/
{:name => $1, :home => $2}
end
users = users.select{|u| u[:home] && u[:name] }
users.select{|u| u[:home].index('/home') == 0 }
end

def system_apps
users = `cat /etc/passwd | grep -v root | grep '/bin/bash'`.split.map do |u|
u =~ /([^\s]+):.*:.*:.*:.*:([^\s]+):\/bin\/bash$/
{:name => $1, :home => $2}
end
users = users.select{|u| u[:home] && u[:name] }
users.select{|u| u[:home].index('/srv') == 0 }
end

def add_system_user(name)
raise "invalid user name '#{name}'" unless name =~ /^[a-z][-a-z0-9]*$/

`adduser #{name} --gecos "" --disabled-password`
`usermod -a -G sudo #{name}`
end

def remove_system_user(name)
`deluser --remove-home #{name}`
end

def write_authorized_keys(user, homedir, keys)
ssh_dir = File.join(homedir, '.ssh')
FileUtils.mkdir_p(ssh_dir)
FileUtils.chown_R(user, user, ssh_dir)
FileUtils.chmod(0700, ssh_dir)

filename = File.join(ssh_dir, 'authorized_keys')
open(filename, 'w') do |file|
keys.each {|k| file.puts(k) }
end
FileUtils.chown(user, user, filename)
FileUtils.chmod(0600, filename)
end


permissions = read_permissions(ARGV[0])

# Create missing users
(permissions['users'].keys - system_users.map{|su| su[:name]}).each do |user|
puts "adding user #{user}"
add_system_user(user)
end

# Removed old users
(system_users.map{|su| su[:name]} - permissions['users'].keys).each do |user|
puts "removing user #{user}"
remove_system_user(user)
end

# Write user ssh keys
system_users.each do |su|
puts "writing authorized_keys for #{su[:name]}"
write_authorized_keys(su[:name], su[:home], permissions['users'][su[:name]])
end

# Write app ssh keys
system_apps.each do |su|
next if !permissions['apps'][su[:name]]
puts "writing authorized_keys for #{su[:name]}"
write_authorized_keys(su[:name], su[:home], permissions['apps'][su[:name]])
end

0 comments on commit 77f520c

Please sign in to comment.