improved stuff, can't remember except better user handling
This commit is contained in:
parent
0ab9081564
commit
291aeb98ed
269
collab.rb
269
collab.rb
|
@ -1,62 +1,189 @@
|
|||
require 'fileutils'
|
||||
|
||||
POSIX_NAME_PREFIX = "emacs"
|
||||
USER_LOCATION = "./users/"
|
||||
|
||||
$projects = []
|
||||
$users = []
|
||||
$id_map = {}
|
||||
$project_id_map = {}
|
||||
$user_id_map = {}
|
||||
|
||||
|
||||
#####################
|
||||
# User manipulation #
|
||||
#####################
|
||||
|
||||
class User
|
||||
attr_accessor :id, :path, :posixname
|
||||
attr_accessor :id, :keypath
|
||||
attr_reader :keys
|
||||
|
||||
def to_s
|
||||
"#{@id}"
|
||||
end
|
||||
|
||||
def initialize(id)
|
||||
@id = id
|
||||
@keypath = "#{USER_LOCATION}#{id}"
|
||||
refresh_keys
|
||||
end
|
||||
|
||||
def add_key_from_string(keystring)
|
||||
unless valid_pubkey? keystring
|
||||
raise InvalidSSHPubKey, "Public key not valid"
|
||||
end
|
||||
ks = keystring.split(" ");
|
||||
key = SSHKey.new(ks[0][4..6], ks[1], ks[2])
|
||||
|
||||
unless @keys.include? key
|
||||
@keys << key
|
||||
else
|
||||
raise DuplicateSSHPubKey, "Public key is already added to user"
|
||||
end
|
||||
|
||||
flush
|
||||
refresh_keys
|
||||
flush_projects_with_user(self)
|
||||
end
|
||||
|
||||
def remove_key(key)
|
||||
@keys.delete(key)
|
||||
flush
|
||||
refresh_keys
|
||||
flush_projects_with_user(self)
|
||||
end
|
||||
|
||||
def refresh_keys
|
||||
File.open(@keypath,"r") do |f|
|
||||
@keys = f.read.split("\n").select{ |line| line[0..2] == "ssh" }.map{ |ks| k = ks.split(" "); SSHKey.new(k[0][4..6], k[1], k[2]) }
|
||||
end
|
||||
end
|
||||
|
||||
def flush
|
||||
File.open(@keypath,"w+") do |key_file|
|
||||
@keys.each do |key|
|
||||
key_file << "#{key.to_s}\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def add_user(id)
|
||||
user = User.new(id)
|
||||
$users << user
|
||||
$user_id_map[id] = user
|
||||
end
|
||||
|
||||
def get_user_by_id(id)
|
||||
$user_id_map[id]
|
||||
end
|
||||
|
||||
def validate_password
|
||||
|
||||
end
|
||||
|
||||
########################
|
||||
# Project manipulation #
|
||||
########################
|
||||
|
||||
class Project
|
||||
attr_accessor :id, :path, :posixname, :users
|
||||
attr_reader :keys
|
||||
|
||||
def initialize
|
||||
@users = []
|
||||
end
|
||||
|
||||
def to_s
|
||||
"#{@id}, #{@path}"
|
||||
end
|
||||
end
|
||||
|
||||
def add_key(key)
|
||||
@keys << key
|
||||
end
|
||||
|
||||
def get_user(id)
|
||||
$id_map[id]
|
||||
end
|
||||
def add_user(user)
|
||||
@users << user
|
||||
user.keys.each do |key|
|
||||
p key
|
||||
add_key(key)
|
||||
end
|
||||
flush
|
||||
refresh
|
||||
end
|
||||
|
||||
def add_user(user)
|
||||
$users << user
|
||||
$id_map[user.id] = user
|
||||
end
|
||||
def remove_user(user)
|
||||
@user.delete(user)
|
||||
flush
|
||||
refresh
|
||||
end
|
||||
|
||||
def create_user(id)
|
||||
if not system("useradd -m #{POSIX_NAME_PREFIX}#{id}") then
|
||||
raise "User creation failed"
|
||||
def refresh
|
||||
@users = File.open("#{@path}/.ssh/users","r") do |f|
|
||||
f.read.split("\n").map{|id| p id; puts $user_id_map; get_user_by_id(id)}
|
||||
end
|
||||
p @users
|
||||
@keys = extract_ssh_pubkeys("#{@path}/.ssh/authorized_keys")
|
||||
end
|
||||
|
||||
def flush
|
||||
File.open("#{@path}/.ssh/users","w+") do |user_file|
|
||||
@users.each do |u|
|
||||
user_file << "#{u.id}\n"
|
||||
end
|
||||
end
|
||||
|
||||
get_ssh_keyfile(self,"w+") do |key_file|
|
||||
@users.each do |user|
|
||||
user.keys.each do |key|
|
||||
key_file << "#{key.to_s}\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
user = User.new
|
||||
user.id = id
|
||||
user.path = "/home/#{POSIX_NAME_PREFIX}#{id}"
|
||||
user.posixname = "#{POSIX_NAME_PREFIX}#{id}"
|
||||
$users << user
|
||||
$id_map[id] = user
|
||||
end
|
||||
|
||||
FileUtils.mkdir "#{user.path}/.ssh"
|
||||
FileUtils.touch "#{user.path}/.ssh/authorized_keys"
|
||||
FileUtils.chown_R user.id, user.id, "#{user.path}/.ssh"
|
||||
def get_project(id)
|
||||
$project_id_map[id]
|
||||
end
|
||||
|
||||
def add_project(project)
|
||||
$projects << project
|
||||
$project_id_map[project.id] = project
|
||||
end
|
||||
|
||||
def create_project(id)
|
||||
if not system("useradd -m #{POSIX_NAME_PREFIX}#{id}") then
|
||||
raise "Project creation failed"
|
||||
end
|
||||
|
||||
user
|
||||
project = Project.new
|
||||
project.id = id
|
||||
project.path = "/home/#{POSIX_NAME_PREFIX}#{id}"
|
||||
project.posixname = "#{POSIX_NAME_PREFIX}#{id}"
|
||||
$projects << project
|
||||
$project_id_map[id] = project
|
||||
|
||||
FileUtils.mkdir "#{project.path}/.ssh"
|
||||
FileUtils.touch "#{project.path}/.ssh/authorized_keys"
|
||||
FileUtils.touch "#{project.path}/.ssh/users"
|
||||
FileUtils.chown_R project.id, project.id, "#{project.path}/.ssh"
|
||||
|
||||
project
|
||||
end
|
||||
|
||||
def remove_user(user)
|
||||
system("userdel -r #{user.posixname}")
|
||||
$users.remove(user)
|
||||
$id_map[id] = nil
|
||||
def remove_project(project)
|
||||
system("userdel -r #{project.posixname}")
|
||||
$projects.remove(project)
|
||||
$project_id_map[id] = nil
|
||||
end
|
||||
|
||||
def user_by_posix_name(posix_name)
|
||||
user = User.new
|
||||
user.id = posix_name[POSIX_NAME_PREFIX.length..-1]
|
||||
user.path = "/home/#{posix_name}"
|
||||
user.posixname = posix_name
|
||||
user
|
||||
def project_by_posix_name(posix_name)
|
||||
project = Project.new
|
||||
project.id = posix_name[POSIX_NAME_PREFIX.length..-1]
|
||||
project.path = "/home/#{posix_name}"
|
||||
project.posixname = posix_name
|
||||
project
|
||||
end
|
||||
|
||||
####################
|
||||
|
@ -89,35 +216,44 @@ class SSHKey
|
|||
end
|
||||
end
|
||||
|
||||
def get_ssh_keyfile(user,mode,&block)
|
||||
file = File.open("#{user.path}/.ssh/authorized_keys",mode)
|
||||
class InvalidSSHPubKey < StandardError
|
||||
end
|
||||
|
||||
class DuplicateSSHPubKey < StandardError
|
||||
end
|
||||
|
||||
def get_ssh_keyfile(project,mode,&block)
|
||||
file = File.open("#{project.path}/.ssh/authorized_keys",mode)
|
||||
return file unless block_given?
|
||||
yield(file)
|
||||
ensure
|
||||
file.close
|
||||
end
|
||||
|
||||
def get_ssh_pubkeys(user)
|
||||
extract_ssh_pubkeys("#{user.path}/.ssh/authorized_keys")
|
||||
def get_ssh_pubkeys(project)
|
||||
extract_ssh_pubkeys("#{project.path}/.ssh/authorized_keys")
|
||||
end
|
||||
|
||||
def add_ssh_pubkey(user,key)
|
||||
if not valid_pubkey? key then raise "Public key not valid" end
|
||||
get_ssh_keyfile(user,"a") do |key_file|
|
||||
# Deprecate
|
||||
def add_ssh_pubkey(project,key)
|
||||
unless valid_pubkey? key
|
||||
raise InvalidSSHPubKey, "Public key not valid"
|
||||
end
|
||||
get_ssh_keyfile(project,"a") do |key_file|
|
||||
key_file << "#{key.to_s}\n"
|
||||
end
|
||||
end
|
||||
|
||||
def reset_pubkeys(user)
|
||||
FileUtils.rm "#{user.path}/.ssh/authorized_keys"
|
||||
FileUtils.touch "#{user.path}/.ssh/authorized_keys"
|
||||
FileUtils.chown_R user.id, user.id, "#{user.path}/.ssh"
|
||||
def reset_pubkeys(project)
|
||||
FileUtils.rm "#{project.path}/.ssh/authorized_keys"
|
||||
FileUtils.touch "#{project.path}/.ssh/authorized_keys"
|
||||
FileUtils.chown_R project.id, project.id, "#{project.path}/.ssh"
|
||||
end
|
||||
|
||||
def remove_ssh_pubkey(user,key)
|
||||
keys = get_ssh_pubkeys(user)
|
||||
reset_pubkeys(user)
|
||||
keys.each{ |k| unless k == key then add_ssh_pubkey(user,k) end}
|
||||
def remove_ssh_pubkey(project,key)
|
||||
keys = get_ssh_pubkeys(project)
|
||||
reset_pubkeys(project)
|
||||
keys.each{ |k| unless k == key then add_ssh_pubkey(project,k) end}
|
||||
end
|
||||
|
||||
def remove_ssh_pubkey_by_key
|
||||
|
@ -149,23 +285,40 @@ end
|
|||
|
||||
|
||||
###########
|
||||
# User DB #
|
||||
# Project DB #
|
||||
###########
|
||||
|
||||
def reload_users_from_passwd
|
||||
$users = []
|
||||
def reload_projects_from_passwd
|
||||
$projects = []
|
||||
`cut -d: -f1 /etc/passwd`.split("\n").
|
||||
select{|u| u.start_with? POSIX_NAME_PREFIX}.
|
||||
map{|u| user_by_posix_name(u)}.
|
||||
each{|u| add_user(u)}
|
||||
map{|u| project_by_posix_name(u)}.
|
||||
each{|u| add_project(u)}
|
||||
$projects.each{|p| p.refresh}
|
||||
end
|
||||
|
||||
def reload_users_from_dir
|
||||
`ls -1 #{USER_LOCATION}`.split("\n").
|
||||
map{|u| User.new(u)}.
|
||||
each{|u| add_user(u.id)}
|
||||
end
|
||||
|
||||
def flush_all_to_disk
|
||||
$users.each {|u| u.flush}
|
||||
$projects.each {|p| p.flush}
|
||||
end
|
||||
|
||||
def flush_projects_with_user(user)
|
||||
$projects.select{|p| p.users.include? user}.each do |p|
|
||||
p.flush
|
||||
end
|
||||
end
|
||||
|
||||
################################################
|
||||
|
||||
reload_users_from_passwd
|
||||
reload_users_from_dir
|
||||
reload_projects_from_passwd
|
||||
|
||||
|
||||
#remove_user 5
|
||||
#create_user 3
|
||||
#add_ssh_pubkey(get_user(3), "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7ZKN2fKcUQUaQqDjNCQQBSdqBVGX7lprNCJmceDBfybhbnuZJ8KvzJJIJIIbzqheW5BVCfkWJY6OgkpAumLWSRCS5n2+AnDHwQgpKDS93OeV+9/kattVtsVUBZaghymyJ2UfA0r918dkxcT9SZbNSl9raiDUUmj3JY8UM219BQP7BRqoZ6e/YZz9lO7ORy6yQT6fIMaVOaZcoDPr6oyNJfadm9POvS/Wl63onoRI9dzpHQG9RuHCcUhHJhkGtzY7GeRWc85WqA9Q4vYo0SK5Je9BG1cvAAVTfV+eYEJEiSDMwWj60roH0C3/ipmzxD/kWqg6YBJWL+XAyQkDnmbuD christoffermadsen@strawberry.thedevcave.net")
|
||||
#remove_project 5
|
||||
#create_project 3
|
||||
#add_ssh_pubkey(get_project(3), "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7ZKN2fKcUQUaQqDjNCQQBSdqBVGX7lprNCJmceDBfybhbnuZJ8KvzJJIJIIbzqheW5BVCfkWJY6OgkpAumLWSRCS5n2+AnDHwQgpKDS93OeV+9/kattVtsVUBZaghymyJ2UfA0r918dkxcT9SZbNSl9raiDUUmj3JY8UM219BQP7BRqoZ6e/YZz9lO7ORy6yQT6fIMaVOaZcoDPr6oyNJfadm9POvS/Wl63onoRI9dzpHQG9RuHCcUhHJhkGtzY7GeRWc85WqA9Q4vYo0SK5Je9BG1cvAAVTfV+eYEJEiSDMwWj60roH0C3/ipmzxD/kWqg6YBJWL+XAyQkDnmbuD christoffermadsen@strawberry.thedevcave.net")
|
||||
|
|
79
prompt.rb
79
prompt.rb
|
@ -1,51 +1,92 @@
|
|||
require_relative 'collab'
|
||||
require 'tty-prompt'
|
||||
require 'colorize'
|
||||
|
||||
$prompt = TTY::Prompt.new
|
||||
|
||||
$login = "root"
|
||||
|
||||
def init
|
||||
choices = %w(Keys Users Quit)
|
||||
puts "Logged in as " + $login.colorize(:cyan) + "\n"
|
||||
choices = %w(Users Projects Quit)
|
||||
case $prompt.select("What do you want to do?", choices)
|
||||
when "Projects"
|
||||
projects
|
||||
when "Users"
|
||||
users
|
||||
when "Keys"
|
||||
keys
|
||||
when "Quit"
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
def keys
|
||||
def users
|
||||
choices = $users
|
||||
user = $prompt.select("Pick a user", choices)
|
||||
keys_user(user)
|
||||
end
|
||||
|
||||
def keys_user(user)
|
||||
choices = {'List keys' => :list ,'Add key' => :add, 'Remove key' => :remove, 'Reset authorized_keys' => :reset}
|
||||
case $prompt.select("What do you want to do for user #{user}?", choices)
|
||||
choices = {'List keys' => :list ,'Add key' => :add, 'Remove key' => :remove}
|
||||
case $prompt.select("What do you want to do?", choices)
|
||||
when :list
|
||||
get_ssh_pubkeys(user).each{|k| puts k.pretty}
|
||||
user.keys.each{|k| puts k.pretty}
|
||||
keys_user user
|
||||
when :add
|
||||
key = $prompt.ask("Please enter a valid public SSH key", echo: false)
|
||||
add_ssh_pubkey(user,key)
|
||||
when :remove
|
||||
keys = get_ssh_pubkeys(user)#.map{|k| puts k.pretty}
|
||||
key = $prompt.select("Select the key to delete", keys)
|
||||
unless $prompt.no?("Are you sure you want to delete this key?")
|
||||
remove_ssh_pubkey(user,key)
|
||||
begin
|
||||
user.add_key_from_string(key)
|
||||
rescue InvalidSSHPubKey => e
|
||||
puts e.message.colorize(:red)
|
||||
keys_user(user)
|
||||
rescue DuplicateSSHPubKey => e
|
||||
puts e.message.colorize(:red)
|
||||
keys_user(user)
|
||||
end
|
||||
when :reset
|
||||
unless $prompt.no?("Are you sure you want to reset the keys for this user?")
|
||||
unless $prompt.no?("Really sure?")
|
||||
reset_pubkeys(user)
|
||||
end
|
||||
when :remove
|
||||
choices = user.keys.map { |k| [k.pretty, k] }.to_h
|
||||
key = $prompt.select("Select the key to remove", choices)
|
||||
unless $prompt.no?("Are you sure you want to remove this key?")
|
||||
user.remove_key(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def projects
|
||||
choices = $projects
|
||||
project = $prompt.select("Pick a project", choices)
|
||||
keys_project(project)
|
||||
end
|
||||
|
||||
def keys_project(project)
|
||||
choices = {'List users' => :list,
|
||||
'Add user' => :add,
|
||||
'Select users with access' => :select}
|
||||
case $prompt.select("What do you want to do?", choices)
|
||||
when :list
|
||||
project.users.each {|u| puts u.id}
|
||||
when :add
|
||||
choices = $users
|
||||
user = $prompt.select("Pick a user", choices)
|
||||
project.add_user(user)
|
||||
puts "Added user #{user} to #{project}".colorize(:green)
|
||||
when :select
|
||||
choices = $users
|
||||
# Mark already added users as "default"
|
||||
counter = 1
|
||||
defaults = []
|
||||
choices.each do |u|
|
||||
if project.users.include? u then
|
||||
defaults << counter
|
||||
end
|
||||
counter += 1
|
||||
end
|
||||
users = $prompt.multi_select("Select users", choices, default: defaults)
|
||||
project.users = users
|
||||
project.flush
|
||||
project.refresh
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
while true
|
||||
init
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue
Block a user