turnstyl 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Y2ZhY2ZmOTE4NzU0ZTliZDFkMzU1ZDRjZjRmZGI0OTM2NDU4NDk2OA==
5
+ data.tar.gz: !binary |-
6
+ NjkxMDAwYjhmYmUyYmY3NjM0NDc2M2Y1ZWQ0ODZlOGVhMzc5NDc0YQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ MWQ3YjQwMWE0NzkxNjhiMzAwM2E3M2FhNTA3NjJmMjkyNTFmNjVkYmM1MDM2
10
+ YTJlYjhlZTk1MTQ5YTNkOGFkYjdlNWQzZGIyYzJlZGY0OGQzODgwMDhlOGUw
11
+ MGNiZGJhZWQyZGExZWFjZmM3OGZkMzNmODJjMzExOTA1ZDNiMzA=
12
+ data.tar.gz: !binary |-
13
+ ZjI2MDY0NTkxZjNhYzAwNDNhZDgwY2EzZjZiYjJjMzE3NGUxNWFhZTIxZjZj
14
+ ZDVkYmJmZTg2MjQwYmJmZTExZTU0ODcxOTBhYTk1NGMzNmNiZjQ2ZWQxYmZh
15
+ NGVhY2U3MjdkZWJlY2RhMWE0MjBlNjI2MDRlN2FmYWNhNDk1NjA=
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in turnstyl-client.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Ole Reifschneider, Chris Floess
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # Turnstyl::Client
2
+
3
+ [![Build Status](https://travis-ci.org/Tranquility/turnstyl.png)](https://travis-ci.org/Tranquility/turnstyl)
4
+
5
+ Commandline utility for managing ssh access
6
+
7
+ ## Installation
8
+
9
+ $ gem install turnstyl-client
10
+
11
+ ## Usage
12
+
13
+ Turnstyl-client expects a config file in your home folder named ".turnstyl-config"
14
+ in which you list the github users that are allowed to access your system.
15
+
16
+
17
+ userlist = [ "githubuser1", "githubuser2", "...", "githubuser99" ]
18
+
19
+
20
+ ## Contributing
21
+
22
+ 1. Fork it
23
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
24
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
25
+ 4. Push to the branch (`git push origin my-new-feature`)
26
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+ task :default => :spec
5
+ RSpec::Core::RakeTask.new
data/bin/turnstyl ADDED
@@ -0,0 +1,17 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require_relative '../lib/turnstyl/client'
4
+ require 'optparse'
5
+
6
+ options = {}
7
+ option_parser = OptionParser.new do |opts|
8
+ opts.on("-f","--force", "Overwrite existing authorized_keys file") do
9
+ options[:force] = true
10
+ end
11
+ end
12
+ option_parser.parse!
13
+
14
+ # puts "force option is #{options[:force]}"
15
+
16
+ Turnstyl::Client.new.run(options[:force])
17
+
@@ -0,0 +1,114 @@
1
+ require 'toml'
2
+ require 'io/console'
3
+
4
+ module Turnstyl
5
+ class Client
6
+ def self.home_folder
7
+ Dir.home
8
+ end
9
+
10
+ def initialize
11
+ @config_path = File.expand_path(Client.home_folder+"/.turnstyl_config")
12
+ if config_file_missing?
13
+ puts <<-TEXT
14
+
15
+ Unable to run without a config file.
16
+
17
+ Try something like this in ~/.turnstyl_config
18
+
19
+ userlist = [ "githubuser1", "githubuser2", "...", "githubuser99" ]
20
+
21
+ TEXT
22
+ exit 1
23
+ end
24
+ end
25
+
26
+ def run(force)
27
+ if force
28
+ update_authorized_keys
29
+ else
30
+ update_authorized_keys_carefully
31
+ end
32
+ end
33
+
34
+ def update_authorized_keys_carefully
35
+ if authorized_key_missing?
36
+ update_authorized_keys
37
+ elsif config_changed?
38
+ print "Authorized keys file exists. Overwrite? [y/N/b/?]? "
39
+ input = STDIN.gets.chomp
40
+ case input
41
+ when "y"
42
+ update_authorized_keys
43
+ when "b"
44
+ create_backup
45
+ update_authorized_keys
46
+ when "?"
47
+ display_help
48
+ update_authorized_keys_carefully
49
+ else
50
+ puts "\nDoing nothing ..."
51
+ end
52
+ end
53
+ end
54
+
55
+ def update_authorized_keys
56
+ settings = load_settings
57
+ authorized_users = settings["userlist"]
58
+ keys = []
59
+ if authorized_users.empty?
60
+ keys << '# YOU HAVE NOT AUTHORIZED ANYONE TO LOGIN'
61
+ else
62
+ authorized_users.each do |person|
63
+ keys = keys + Communicator.new.get_keys_from(person)
64
+ end
65
+ end
66
+ File.open(Client.home_folder+'/.ssh/authorized_keys', 'w+') do |file|
67
+ file.write(keys.join("\n") << "\n")
68
+ end
69
+ puts "\nkeys updated..."
70
+ end
71
+
72
+ def authorized_key_missing?
73
+ !File.exist? Client.home_folder+"/.ssh/authorized_keys"
74
+ end
75
+
76
+ def config_file_missing?
77
+ !File.exist? Client.home_folder+"/.turnstyl_config"
78
+ end
79
+
80
+ def config_changed?
81
+ File.mtime(@config_path) > File.mtime(Client.home_folder+"/.ssh/authorized_keys")
82
+ end
83
+
84
+ def update_necessary?
85
+ authorized_key_missing? || config_changed?
86
+ end
87
+
88
+ def create_backup
89
+ puts "\nMaking a backup ..."
90
+ number = Dir.glob(Client.home_folder+'/.ssh/authorized_keys*').count
91
+ puts number
92
+ FileUtils.mv(Client.home_folder+"/.ssh/authorized_keys", Client.home_folder+"/.ssh/authorized_keys.bak"+number.to_s)
93
+ end
94
+
95
+ private
96
+
97
+ def load_settings
98
+ TOML.load_file(@config_path)
99
+ end
100
+
101
+ def display_help
102
+ puts <<-HERE
103
+
104
+ You tried to let turnstyl manage your authorized_keys file, but there is an
105
+ existing authorized_keys file and you have to decide what you want to do with
106
+ it.
107
+
108
+ If you're sure you want to overwrite it choose "y" if you want to backup your
109
+ existing file choose "b"
110
+
111
+ HERE
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,14 @@
1
+ require 'rest_client'
2
+ require 'json'
3
+
4
+ class Communicator
5
+
6
+ def get_keys_from person
7
+ keys = []
8
+ response = RestClient.get "https://api.github.com/users/#{person}/keys"
9
+ JSON.parse(response).each do |hash|
10
+ keys << hash['key']
11
+ end
12
+ keys
13
+ end
14
+ end
@@ -0,0 +1,2 @@
1
+ require_relative 'client/client'
2
+ require_relative 'client/communicator'
@@ -0,0 +1,21 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+
18
+ def base_path
19
+ File.expand_path('../../', __FILE__)
20
+ end
21
+ end
@@ -0,0 +1,161 @@
1
+ require 'spec_helper'
2
+ require_relative '../../../lib/turnstyl/client'
3
+
4
+ module Turnstyl
5
+ describe Client do
6
+ let(:dummy_home) { base_path+'/spec/dummy_home_folder' }
7
+ let(:key_file) { dummy_home+'/.ssh/authorized_keys' }
8
+ let(:config_file) { dummy_home+'/.turnstyl_config' }
9
+ let(:turnstyl_client) {Client.new}
10
+
11
+ before do
12
+ Client.any_instance.stub(:config_file_missing?).and_return(false)
13
+ FileUtils.mkdir_p base_path+"/spec/dummy_home_folder/.ssh"
14
+ Client.stub(:home_folder).and_return(dummy_home)
15
+ turnstyl_client.stub(:puts)
16
+ turnstyl_client.stub(:print)
17
+ end
18
+
19
+ after do
20
+ FileUtils.rm_rf dummy_home
21
+ end
22
+
23
+ describe '#initialize' do
24
+ it 'raises exception if config file is missing' do
25
+ Client.any_instance.stub(:config_file_missing?).and_return(true)
26
+ expect { Client.new.run nil }.to raise_error(SystemExit)
27
+ end
28
+ end
29
+
30
+ describe '#run' do
31
+ it 'does not overwrite the authorized_keys file' do
32
+ turnstyl_client.should_receive(:update_authorized_keys_carefully)
33
+
34
+ turnstyl_client.run(false)
35
+ end
36
+
37
+ it 'overwrites the authorized_keys file if forced' do
38
+ turnstyl_client.should_receive(:update_authorized_keys)
39
+
40
+ turnstyl_client.run(false)
41
+ end
42
+ end
43
+
44
+ describe '#update_authorized_keys' do
45
+ it 'creates authorized_keys file' do
46
+ turnstyl_client.should_receive(:load_settings).and_return("userlist" => [])
47
+
48
+ File.exist?(key_file).should be_false
49
+ turnstyl_client.update_authorized_keys
50
+ File.exist?(key_file).should be_true
51
+ end
52
+
53
+ it 'adds a comment when there are no authorized keys file' do
54
+ turnstyl_client.should_receive(:load_settings).and_return("userlist" => [])
55
+ turnstyl_client.update_authorized_keys
56
+
57
+ File.read(key_file).should eq "# YOU HAVE NOT AUTHORIZED ANYONE TO LOGIN\n"
58
+ end
59
+
60
+ it 'obtains key and writes them into the authorized_keys file' do
61
+ Communicator.any_instance.stub(:get_keys_from).and_return(['12345', '67890'])
62
+ turnstyl_client.should_receive(:load_settings).and_return("userlist" => ['flooose'])
63
+ turnstyl_client.update_authorized_keys
64
+ File.read(key_file).should eq "12345\n67890\n"
65
+ end
66
+ end
67
+
68
+ describe '#update_authorized_keys_carefully' do
69
+ let(:some_time) { Time.now }
70
+ before do
71
+ turnstyl_client.stub(:authorized_key_missing?).and_return(false)
72
+ end
73
+
74
+ it 'updates the keys if the authoized keys file is missing' do
75
+ turnstyl_client.stub(:authorized_key_missing?).and_return(true)
76
+ turnstyl_client.should_receive(:update_authorized_keys)
77
+
78
+ turnstyl_client.update_authorized_keys_carefully
79
+ end
80
+
81
+ it 'does not overwrite authorized_keys file if configuration not changed' do
82
+ STDIN.stub(:gets).and_return('y')
83
+ File.should_receive(:mtime).with(config_file).and_return(some_time)
84
+ File.should_receive(:mtime).with(key_file).and_return(some_time + 2)
85
+
86
+ turnstyl_client.should_not_receive(:update_authorized_keys)
87
+ turnstyl_client.run nil
88
+ end
89
+
90
+ it 'overwrites authorized_keys file if configuration changed' do
91
+ STDIN.stub(:gets).and_return('y')
92
+ File.should_receive(:mtime).with(config_file).and_return(some_time + 2)
93
+ File.should_receive(:mtime).with(key_file).and_return(some_time)
94
+
95
+ turnstyl_client.should_receive(:update_authorized_keys)
96
+ turnstyl_client.run nil
97
+ end
98
+
99
+ it 'asks the user for feedback when the authorized_keys file exists' do
100
+ turnstyl_client.stub(:authorized_key_missing?).and_return(true)
101
+ turnstyl_client.stub(:update_authorized_keys)
102
+
103
+ turnstyl_client.run nil
104
+ end
105
+
106
+ context 'user gives feedback' do
107
+ before do
108
+ turnstyl_client.stub(:config_file_missing?).and_return(false)
109
+ turnstyl_client.stub(:config_changed?).and_return(true)
110
+ turnstyl_client.stub(:authorized_key_missing?).and_return(false)
111
+ end
112
+
113
+ it 'updates authorized_keys file if user inputs "y"' do
114
+ STDIN.stub(:gets).and_return('y')
115
+ turnstyl_client.should_receive(:update_authorized_keys)
116
+
117
+ turnstyl_client.run nil
118
+ end
119
+
120
+ it 'updates authorized_keys file and creates backup first if user inputs "b"' do
121
+ STDIN.stub(:gets).and_return('b')
122
+
123
+ turnstyl_client.should_receive(:create_backup)
124
+ turnstyl_client.should_receive(:update_authorized_keys)
125
+
126
+ turnstyl_client.run nil
127
+ end
128
+
129
+ it 'displays help if user inputs "?"' do
130
+ STDIN.stub(:gets).and_return('?', 'n')
131
+
132
+ turnstyl_client.should_receive(:display_help)
133
+ turnstyl_client.should_not_receive(:update_authorized_keys)
134
+
135
+ turnstyl_client.run nil
136
+ end
137
+
138
+ it 'it does not update authorized_keys file if user inputs "n"' do
139
+ STDIN.stub(:gets).and_return('n')
140
+
141
+ turnstyl_client.should_not_receive(:update_authorized_keys)
142
+
143
+ turnstyl_client.run nil
144
+ end
145
+ end
146
+
147
+ describe '#create_backup' do
148
+ it 'renames the current authorized_keys file' do
149
+ FileUtils.touch key_file
150
+ FileUtils.touch key_file+".bak1"
151
+ File.exist?(key_file).should be_true
152
+
153
+ turnstyl_client.create_backup
154
+
155
+ File.exist?(key_file).should be_false
156
+ File.exist?(key_file+".bak2").should be_true
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
data/turnstyl.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "turnstyl"
7
+ spec.version = "0.1.1"
8
+ spec.authors = ["Ole Reifschneider", "Chris Floess"]
9
+ spec.email = ["mail@ole-reifschneider.de", "skeptikos@gmail.com"]
10
+ spec.description = %q{Commandline utility for managing ssh access}
11
+ spec.summary = %q{Commandline utility for managing ssh access}
12
+ spec.homepage = "https://github.com/Tranquility/turnstyl"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "rest-client"
21
+ spec.add_dependency "json"
22
+ spec.add_dependency "toml-rb"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rspec"
27
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: turnstyl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Ole Reifschneider
8
+ - Chris Floess
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-08-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rest-client
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ! '>='
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ! '>='
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: json
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: toml-rb
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: bundler
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: '1.3'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.3'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rake
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: rspec
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ description: Commandline utility for managing ssh access
99
+ email:
100
+ - mail@ole-reifschneider.de
101
+ - skeptikos@gmail.com
102
+ executables:
103
+ - turnstyl
104
+ extensions: []
105
+ extra_rdoc_files: []
106
+ files:
107
+ - .gitignore
108
+ - .rspec
109
+ - .travis.yml
110
+ - Gemfile
111
+ - LICENSE.txt
112
+ - README.md
113
+ - Rakefile
114
+ - bin/turnstyl
115
+ - lib/turnstyl/client.rb
116
+ - lib/turnstyl/client/client.rb
117
+ - lib/turnstyl/client/communicator.rb
118
+ - spec/spec_helper.rb
119
+ - spec/turnstyl/client/client_spec.rb
120
+ - turnstyl.gemspec
121
+ homepage: https://github.com/Tranquility/turnstyl
122
+ licenses:
123
+ - MIT
124
+ metadata: {}
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 2.0.3
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: Commandline utility for managing ssh access
145
+ test_files:
146
+ - spec/spec_helper.rb
147
+ - spec/turnstyl/client/client_spec.rb