gas2 0.1.7b
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.textile +66 -0
- data/bin/gas +53 -0
- data/lib/gas.rb +171 -0
- data/lib/gas/config.rb +148 -0
- data/lib/gas/gitconfig.rb +46 -0
- data/lib/gas/github_speaker.rb +219 -0
- data/lib/gas/prompter.rb +169 -0
- data/lib/gas/settings.rb +28 -0
- data/lib/gas/ssh.rb +305 -0
- data/lib/gas/user.rb +33 -0
- data/lib/gas/version.rb +6 -0
- data/spec/integration/ssh_spec.rb +338 -0
- data/spec/spec_helper.rb +148 -0
- data/spec/unit/config_spec.rb +83 -0
- data/spec/unit/gitconfig_spec.rb +85 -0
- data/spec/unit/github_speaker_spec.rb +107 -0
- data/spec/unit/settings_spec.rb +56 -0
- data/spec/unit/user_spec.rb +28 -0
- metadata +233 -0
data/lib/gas/ssh.rb
ADDED
@@ -0,0 +1,305 @@
|
|
1
|
+
module Gas
|
2
|
+
class Ssh
|
3
|
+
require 'highline/import'
|
4
|
+
require 'net/https'
|
5
|
+
require 'json'
|
6
|
+
require 'digest/md5'
|
7
|
+
extend Prompter
|
8
|
+
|
9
|
+
def self.corresponding_rsa_files_exist?(nickname = '')
|
10
|
+
nickname = @uid if nickname == ''
|
11
|
+
return true if File.exists? "#{GAS_DIRECTORY}/#{nickname}_id_rsa" and File.exists? "#{GAS_DIRECTORY}/#{nickname}_id_rsa.pub"
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
# Copies a key pair from ~/.ssh to .gas/Nickname*
|
16
|
+
def self.use_current_rsa_files_for_this_user(test = nil)
|
17
|
+
@uid = test unless test.nil?
|
18
|
+
FileUtils.cp("#{SSH_DIRECTORY}/id_rsa", "#{GAS_DIRECTORY}/#{@uid}_id_rsa")
|
19
|
+
FileUtils.cp("#{SSH_DIRECTORY}/id_rsa.pub", "#{GAS_DIRECTORY}/#{@uid}_id_rsa.pub")
|
20
|
+
FileUtils.chmod 0700, "#{GAS_DIRECTORY}/#{@uid}_id_rsa"
|
21
|
+
FileUtils.chmod 0700, "#{GAS_DIRECTORY}/#{@uid}_id_rsa.pub"
|
22
|
+
return true
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.ssh_dir_contains_rsa?
|
26
|
+
return true if File.exists?(SSH_DIRECTORY + "/id_rsa") or File.exists?(SSH_DIRECTORY + "/id_rsa.pub")
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
|
30
|
+
# Generates a new sshkey putting it in ~/.gas/nickname_id_rsa
|
31
|
+
# This function can get a little tricky. It's best to strip off the comment here,
|
32
|
+
# because github API doesn't retain the comment...
|
33
|
+
def self.generate_new_rsa_keys_in_gas_dir
|
34
|
+
puts "Generating new ssh key..."
|
35
|
+
|
36
|
+
begin
|
37
|
+
k = SSHKey.generate() # (:comment => "#{@email}")
|
38
|
+
|
39
|
+
publ = k.ssh_public_key
|
40
|
+
privl = k.private_key
|
41
|
+
|
42
|
+
my_file_privl = File.open(GAS_DIRECTORY + "/#{@uid}_id_rsa",'w',0700)
|
43
|
+
my_file_privl.write(privl)
|
44
|
+
my_file_privl.close
|
45
|
+
|
46
|
+
my_file_publ = File.open(GAS_DIRECTORY + "/#{@uid}_id_rsa.pub",'w',0700)
|
47
|
+
my_file_publ.write(publ)
|
48
|
+
my_file_publ.close
|
49
|
+
|
50
|
+
return true
|
51
|
+
rescue
|
52
|
+
puts "Fatal Error: Something unexpected happened while writing to #{GAS_DIRECTORY}/#{@uid}_id_rsa"
|
53
|
+
puts "SSH key not saved."
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# This function creates the ssh keys if needed and puts them in ~/.gas/NICKNAME_id_rsa and ...rsa.pub
|
59
|
+
def self.setup_ssh_keys(user)
|
60
|
+
@uid = user.nickname
|
61
|
+
@email = user.email
|
62
|
+
|
63
|
+
if Gas::Prompter.user_wants_gas_to_handle_rsa_keys?
|
64
|
+
if corresponding_rsa_files_exist?(@uid) and Gas::Prompter.user_wants_to_use_key_already_in_gas?(@uid)
|
65
|
+
return true # We don't need to do anything because the .gas directory is already setup
|
66
|
+
elsif !corresponding_rsa_files_exist?(@uid) and ssh_dir_contains_rsa? and Gas::Prompter.user_wants_to_use_key_already_in_ssh? # Check ~/.ssh for a current id_rsa file, if yes, "Do you want to use the current id_rsa file to be used as your key?"
|
67
|
+
use_current_rsa_files_for_this_user # copies the keys from ~/.ssh instead of generating new keys if desired/possible
|
68
|
+
return true
|
69
|
+
else
|
70
|
+
return generate_new_rsa_keys_in_gas_dir
|
71
|
+
end
|
72
|
+
|
73
|
+
else # !Gas::Prompter.user_wants_gas_to_handle_rsa_keys?
|
74
|
+
# check if ~/.gas/rsa exists, if it does, promt the user
|
75
|
+
# because that key must be destroyed (if the user really doesn't want gas handling keys for this user)
|
76
|
+
if corresponding_rsa_files_exist?(@uid) #in ~/.gas/
|
77
|
+
delete_associated_local_keys!(@uid) if Gas::Prompter.user_wants_to_remove_the_keys_that_already_exist_for_this_user?(@uid)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
# This huge method handles the swapping of id_rsa files on the hdd
|
84
|
+
def self.swap_in_rsa(nickname)
|
85
|
+
@uid = nickname # woah, this is extremely sloppy I think... in order to use any other class methods,
|
86
|
+
# I need to write to @uid or it will
|
87
|
+
# Have the dumb information from the last time it registered a new git author?
|
88
|
+
|
89
|
+
if corresponding_rsa_files_exist?
|
90
|
+
if ssh_dir_contains_rsa?
|
91
|
+
if current_key_already_backed_up?
|
92
|
+
write_to_ssh_dir!
|
93
|
+
else
|
94
|
+
if Gas::Prompter.user_wants_to_overwrite_existing_rsa_key?
|
95
|
+
write_to_ssh_dir!
|
96
|
+
else
|
97
|
+
puts "Proceeding without swapping rsa keys (aborting)."
|
98
|
+
end
|
99
|
+
end
|
100
|
+
else # if no ~/.ssh/id_rsa exists... no overwrite potential... so just write away
|
101
|
+
write_to_ssh_dir!
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
def self.write_to_ssh_dir!
|
108
|
+
supress_process_output = "> /dev/null 2>&1"
|
109
|
+
supress_process_output = "> NUL" if IS_WINDOWS
|
110
|
+
|
111
|
+
# remove the current key from the ssh-agent session (key will no longer be used with github)
|
112
|
+
system("ssh-add -d #{SSH_DIRECTORY}/id_rsa #{supress_process_output}") if is_ssh_agent_there?
|
113
|
+
|
114
|
+
FileUtils.cp(GAS_DIRECTORY + "/#{@uid}_id_rsa", SSH_DIRECTORY + "/id_rsa")
|
115
|
+
FileUtils.cp(GAS_DIRECTORY + "/#{@uid}_id_rsa.pub", SSH_DIRECTORY + "/id_rsa.pub")
|
116
|
+
|
117
|
+
FileUtils.chmod(0700, SSH_DIRECTORY + "/id_rsa")
|
118
|
+
FileUtils.chmod(0700, SSH_DIRECTORY + "/id_rsa.pub")
|
119
|
+
|
120
|
+
if is_ssh_agent_there?
|
121
|
+
`ssh-add #{SSH_DIRECTORY}/id_rsa #{supress_process_output}` # you need to run this command to get the private key to be set to active on unix based machines. Not sure what to do for windows yet...
|
122
|
+
|
123
|
+
if $?.exitstatus == 1 # exit status 1 means failed
|
124
|
+
puts "Looks like there may have been a fatal error in registering the rsa key with ssh-agent. Might be worth looking into"
|
125
|
+
raise "Exit code on ssh-add command line was one meaning: Error!"
|
126
|
+
end
|
127
|
+
|
128
|
+
else
|
129
|
+
puts "Slight Error: The key should now be in ~/.ssh so that's good, BUT ssh-add could not be found. If you're using windows, you'll need to use git bash or cygwin to emulate this unix command and actually do uploads."
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
# This function scans each file in a directory to check
|
135
|
+
# to see if it is the same file which it's being compared against
|
136
|
+
# dir_to_scan The target directory you'd like to scan
|
137
|
+
# file_to_compare The file's path that you're expecting to find
|
138
|
+
def self.scan_for_file_match(file_to_compare, dir_to_scan)
|
139
|
+
pattern = get_md5_hash(file_to_compare)
|
140
|
+
|
141
|
+
@files = Dir.glob(dir_to_scan + "/*" + file_to_compare.split(//).last(1).to_s)
|
142
|
+
|
143
|
+
@files.each do |file|
|
144
|
+
return true if get_md5_hash(file) == pattern
|
145
|
+
end
|
146
|
+
|
147
|
+
return false
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.current_key_already_backed_up?
|
151
|
+
if scan_for_file_match(SSH_DIRECTORY + "/id_rsa", GAS_DIRECTORY) and scan_for_file_match(SSH_DIRECTORY + "/id_rsa.pub", GAS_DIRECTORY)
|
152
|
+
return true
|
153
|
+
else
|
154
|
+
return false
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.get_md5_hash(file_path)
|
159
|
+
if File.exists? file_path
|
160
|
+
file = File.open(file_path, "rb")
|
161
|
+
hash = Digest::MD5.hexdigest(file.read)
|
162
|
+
file.close
|
163
|
+
return hash
|
164
|
+
end
|
165
|
+
return nil
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
def self.upload_public_key_to_github(user, github_speaker = nil)
|
170
|
+
if Gas::Prompter.user_wants_to_install_key_to_github?
|
171
|
+
key_installation_routine!(user, nil, github_speaker)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
def self.key_installation_routine!(user = nil, rsa_test = nil, github_speaker = nil)
|
177
|
+
@uid = user.nickname unless user.nil? # allows for easy testing
|
178
|
+
|
179
|
+
rsa_key = get_associated_rsa_key(@uid).first
|
180
|
+
rsa_key = rsa_test unless rsa_test.nil?
|
181
|
+
return false if rsa_key.nil?
|
182
|
+
|
183
|
+
# TODO: Impliment a key ring system where you store your key on your github in a repository, only it's encrypted. And to decrypt it, there is
|
184
|
+
# A file in your .gas folder!!! That sounds SO fun!
|
185
|
+
github_speaker = GithubSpeaker.new(user) if github_speaker.nil?
|
186
|
+
|
187
|
+
puts github_speaker.status
|
188
|
+
|
189
|
+
if github_speaker.status == :bad_credentials
|
190
|
+
puts "Invalid credentials. Skipping upload of keys to github. "
|
191
|
+
puts "To try again, type $ gas ssh #{@uid}"
|
192
|
+
return false
|
193
|
+
end
|
194
|
+
|
195
|
+
result = github_speaker.post_key!(rsa_key)
|
196
|
+
|
197
|
+
if result
|
198
|
+
puts "Key uploaded successfully!"
|
199
|
+
return true
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# Get's the ~/.gas/user_id_rsa and ~/.gas/user_id_rsa.pub strings associated with
|
204
|
+
# the specified user and returns it as an array. Returns array with two nils if there's no keys
|
205
|
+
# [pub_rsa, priv_rsa]
|
206
|
+
def self.get_associated_rsa_key(nickname)
|
207
|
+
pub_path = "#{GAS_DIRECTORY}/#{nickname}_id_rsa.pub"
|
208
|
+
priv_path = "#{GAS_DIRECTORY}/#{nickname}_id_rsa"
|
209
|
+
|
210
|
+
if File.exists? pub_path and File.exists? priv_path
|
211
|
+
pub_file = File.open(pub_path, "rb")
|
212
|
+
pub_rsa = pub_file.read.strip
|
213
|
+
pub_file.close
|
214
|
+
if pub_rsa.count(' ') == 2 # special trick to split off the trailing comment text because github API won't store it.
|
215
|
+
pub_rsa = pub_rsa.split(" ")
|
216
|
+
pub_rsa = "#{rsa[0]} #{rsa[1]}"
|
217
|
+
end
|
218
|
+
|
219
|
+
priv_file = File.open(priv_path, "rb")
|
220
|
+
priv_rsa = priv_file.read.strip
|
221
|
+
priv_file.close
|
222
|
+
|
223
|
+
return [pub_rsa, priv_rsa]
|
224
|
+
end
|
225
|
+
return [nil, nil]
|
226
|
+
end
|
227
|
+
|
228
|
+
# Cross-platform way of finding an executable in the $PATH.
|
229
|
+
# returns nil if command not present
|
230
|
+
#
|
231
|
+
# which('ruby') #=> /usr/bin/ruby
|
232
|
+
def self.which(cmd)
|
233
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
234
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
235
|
+
exts.each { |ext|
|
236
|
+
exe = "#{path}/#{cmd}#{ext}"
|
237
|
+
return exe if File.executable? exe
|
238
|
+
}
|
239
|
+
end
|
240
|
+
return nil
|
241
|
+
end
|
242
|
+
|
243
|
+
def self.is_ssh_agent_there?
|
244
|
+
return false if which("ssh-add").nil?
|
245
|
+
return true
|
246
|
+
end
|
247
|
+
|
248
|
+
# deletes the ssh keys associated with a user
|
249
|
+
def self.delete(nickname)
|
250
|
+
return false unless user_has_ssh_keys?(nickname) # return if no keys
|
251
|
+
|
252
|
+
case Gas::Prompter.user_wants_to_delete_all_ssh_data?
|
253
|
+
when "a"
|
254
|
+
delete_associated_github_keys!(nickname)
|
255
|
+
delete_associated_local_keys!(nickname)
|
256
|
+
when "l"
|
257
|
+
delete_associated_local_keys!(nickname)
|
258
|
+
when "g"
|
259
|
+
delete_associated_github_keys!(nickname)
|
260
|
+
when "n"
|
261
|
+
return false
|
262
|
+
end
|
263
|
+
|
264
|
+
end
|
265
|
+
|
266
|
+
def self.user_has_ssh_keys?(nickname)
|
267
|
+
return false if get_associated_rsa_key(nickname).first.nil?
|
268
|
+
return true
|
269
|
+
end
|
270
|
+
|
271
|
+
def self.delete_associated_github_keys!(nickname)
|
272
|
+
rsa = get_associated_rsa_key(nickname).first
|
273
|
+
|
274
|
+
credentials = get_nils
|
275
|
+
|
276
|
+
github_speaker = GithubSpeaker.new(nickname, credentials[:username], credentials[:password])
|
277
|
+
|
278
|
+
result = github_speaker.remove_key! rsa
|
279
|
+
puts "The key for this user was not in the specified github account's public keys section." if !result
|
280
|
+
end
|
281
|
+
|
282
|
+
# this is just for testing... it gets stubbed... otherwise, the nils are normal and allow for
|
283
|
+
# normal prompting for username and password from within the GithubSpeaker class
|
284
|
+
def self.get_nils; { :username => nil, :password => nil };end
|
285
|
+
|
286
|
+
def self.delete_associated_local_keys!(nickname)
|
287
|
+
puts "Removing associated keys from local machine..."
|
288
|
+
puts
|
289
|
+
|
290
|
+
ssh_file = get_md5_hash("#{SSH_DIRECTORY}/id_rsa")
|
291
|
+
gas_file = get_md5_hash("#{GAS_DIRECTORY}/#{nickname}_id_rsa")
|
292
|
+
|
293
|
+
return false if gas_file.nil? # if the gas file doesn't exist, return from this function safely, otherwise both objects could be nil, pass this check, and then fuck up our interpreter with file not found errors
|
294
|
+
|
295
|
+
if ssh_file == gas_file
|
296
|
+
File.delete("#{SSH_DIRECTORY}/id_rsa")
|
297
|
+
File.delete("#{SSH_DIRECTORY}/id_rsa.pub")
|
298
|
+
end
|
299
|
+
|
300
|
+
File.delete("#{GAS_DIRECTORY}/#{nickname}_id_rsa")
|
301
|
+
File.delete("#{GAS_DIRECTORY}/#{nickname}_id_rsa.pub")
|
302
|
+
end
|
303
|
+
|
304
|
+
end
|
305
|
+
end
|
data/lib/gas/user.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Gas
|
2
|
+
|
3
|
+
# Class that contains data for a git user
|
4
|
+
class User
|
5
|
+
attr_reader :name, :email, :nickname
|
6
|
+
|
7
|
+
|
8
|
+
# @param [String] name The name of the user
|
9
|
+
# @param [String] email The email of the user
|
10
|
+
# @param [String] nickname A nickname for the user, not used when parsing from gitconfig
|
11
|
+
def initialize(name, email, nickname = '')
|
12
|
+
@name = name
|
13
|
+
@email = email
|
14
|
+
@nickname = nickname
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the git format of user
|
19
|
+
# @return [String]
|
20
|
+
def git_user
|
21
|
+
to_s false
|
22
|
+
end
|
23
|
+
|
24
|
+
# Overides to_s to output in the correct format
|
25
|
+
# @param [Boolean] use_nickname Defaults to true
|
26
|
+
# @return [String]
|
27
|
+
def to_s(use_nickname = true)
|
28
|
+
" [#{use_nickname ? @nickname : 'user'}]\n name = #{@name}\n email = #{@email}"
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
data/lib/gas/version.rb
ADDED
@@ -0,0 +1,338 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
|
3
|
+
require './lib/gas'
|
4
|
+
|
5
|
+
require 'rspec/mocks'
|
6
|
+
require 'rspec/mocks/standalone'
|
7
|
+
require 'pry'
|
8
|
+
|
9
|
+
|
10
|
+
describe Gas::Ssh do
|
11
|
+
before :all do
|
12
|
+
@nickname = "thisaccountmaybedeletedmysteriously"
|
13
|
+
@name = "tim T"
|
14
|
+
@email = "tim@timmy.com"
|
15
|
+
end
|
16
|
+
|
17
|
+
before :each do
|
18
|
+
@uid = "teddy"
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "SSH key file handling..." do
|
22
|
+
|
23
|
+
before :all do
|
24
|
+
Gas::Prompter.stub!(:user_wants_to_delete_all_ssh_data?).and_return("l") # only delete's local keys
|
25
|
+
end
|
26
|
+
|
27
|
+
after :all do
|
28
|
+
Gas::Prompter.unstub!(:user_wants_to_delete_all_ssh_data?)
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "Detecting when files are missing..." do
|
32
|
+
it "should detect when an id_rsa isn't in the .gas directory" do
|
33
|
+
Gas::Ssh.corresponding_rsa_files_exist?(@uid).should be_false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "Detecting when files exist..." do
|
38
|
+
before :each do
|
39
|
+
create_user_no_git @uid, @uid, "a@b.com"
|
40
|
+
end
|
41
|
+
|
42
|
+
after :each do
|
43
|
+
delete_user_no_git @uid
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should detect when an id_rsa is already in the .gas directory' do
|
47
|
+
Gas::Ssh.corresponding_rsa_files_exist?(@uid).should be_true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "File System Changes..." do
|
52
|
+
|
53
|
+
it 'should create ssh keys in .gas && Gas.remove should be able to remove those files' do
|
54
|
+
STDIN.stub!(:gets).and_return("y\n") # forces the dialogs to
|
55
|
+
Gas::Ssh.stub!(:upload_public_key_to_github).and_return(false)
|
56
|
+
|
57
|
+
lambda do
|
58
|
+
Gas.add(@nickname,@name,@email)
|
59
|
+
end.should change{count_of_files_in(GAS_DIRECTORY)}.by(2)
|
60
|
+
|
61
|
+
lambda do
|
62
|
+
Gas.delete(@nickname)
|
63
|
+
end.should change{count_of_files_in(GAS_DIRECTORY)}.by(-2)
|
64
|
+
|
65
|
+
STDIN.unstub!(:gets)
|
66
|
+
Gas::Ssh.unstub!(:upload_public_key_to_github)
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
describe 'For the ssh directory...' do
|
71
|
+
before :each do
|
72
|
+
clean_out_ssh_directory
|
73
|
+
clean_out_gas_directory(@nickname)
|
74
|
+
|
75
|
+
# a second user for deleting
|
76
|
+
@nickname2 = "thisaccountmaybedeletedmysteriously2"
|
77
|
+
@name2 = "tim T2"
|
78
|
+
@email2 = "tim@timmy.com2"
|
79
|
+
|
80
|
+
create_user_no_git(@nickname2, @name2, @email2)
|
81
|
+
end
|
82
|
+
|
83
|
+
after :each do
|
84
|
+
Gas.delete(@nickname)
|
85
|
+
delete_user_no_git(@nickname2)
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
it "if there's no key in .ssh, the use command should place a key there" do
|
90
|
+
|
91
|
+
Gas.use @nickname2
|
92
|
+
# 3) The .ssh directory should now contain that file
|
93
|
+
File.exist?(SSH_DIRECTORY + "/id_rsa.pub").should be_true
|
94
|
+
end
|
95
|
+
|
96
|
+
it "shouldn't overwrite an existing key in ~/.ssh that isn't backed up in .gas and the user aborts" do
|
97
|
+
# 2) Create a bogus id_rsa in the .ssh directory
|
98
|
+
id_rsa, id_rsa_pub = plant_bogus_rsa_keys_in_ssh_directory
|
99
|
+
# 3) Switch to that user
|
100
|
+
Gas::Prompter.stub!(:user_wants_to_overwrite_existing_rsa_key?).and_return(false)
|
101
|
+
Gas.use @nickname2
|
102
|
+
Gas::Prompter.unstub!(:user_wants_to_overwrite_existing_rsa_key?)
|
103
|
+
# 4) The .ssh directory should not be changed
|
104
|
+
File.open(SSH_DIRECTORY + "/id_rsa", "r") do |f|
|
105
|
+
f.read.strip.should eq id_rsa
|
106
|
+
end
|
107
|
+
File.open(SSH_DIRECTORY + "/id_rsa.pub", "r") do |f|
|
108
|
+
f.read.strip.should eq id_rsa_pub
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should overwrite an existing, unbacked-up key in ~/.ssh if user wants" do
|
113
|
+
# 2) Create a bogus id_rsa in the .ssh directory
|
114
|
+
id_rsa, id_rsa_pub = plant_bogus_rsa_keys_in_ssh_directory
|
115
|
+
# 3) Switch to that user
|
116
|
+
Gas::Prompter.stub!(:user_wants_to_overwrite_existing_rsa_key?).and_return(true)
|
117
|
+
Gas.use @nickname2
|
118
|
+
Gas::Prompter.unstub!(:user_wants_to_overwrite_existing_rsa_key?)
|
119
|
+
# 4) The .ssh directory should not be changed
|
120
|
+
File.open(SSH_DIRECTORY + "/id_rsa", "r") do |f|
|
121
|
+
f.read.strip.should_not eq id_rsa
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
it "If there's a key in ~/.ssh that's backed up in .gas" do
|
126
|
+
# 1) Create an alternate user
|
127
|
+
create_user_no_git(@nickname, @name, @email)
|
128
|
+
rsa, rsa_pub = Gas::Ssh.get_associated_rsa_key(@nickname)
|
129
|
+
rsa2, rsa2_pub = Gas::Ssh.get_associated_rsa_key(@nickname2)
|
130
|
+
# 2)
|
131
|
+
Gas.use @nickname2
|
132
|
+
File.open(SSH_DIRECTORY + "/id_rsa.pub", "r") do |f|
|
133
|
+
f.read.strip.should eq rsa2
|
134
|
+
end
|
135
|
+
Gas.use @nickname
|
136
|
+
File.open(SSH_DIRECTORY + "/id_rsa.pub", "r") do |f|
|
137
|
+
f.read.strip.should eq rsa
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should delete the key in .ssh when the user is deleted" do
|
142
|
+
create_user_no_git(@nickname, @name, @email)
|
143
|
+
File.exists?(GAS_DIRECTORY + "/#{@nickname}_id_rsa").should be_true
|
144
|
+
Gas.delete @nickname
|
145
|
+
File.exists?(GAS_DIRECTORY + "/#{@nickname}_id_rsa").should be_false
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should be able to copy ssh keys in the ssh' do
|
149
|
+
# put a key pair in the ssh directory
|
150
|
+
mock_text = "this is a mock ssh file"
|
151
|
+
File.open(SSH_DIRECTORY + "/id_rsa","w+") do |f|
|
152
|
+
f.write(mock_text)
|
153
|
+
end
|
154
|
+
File.open(SSH_DIRECTORY + "/id_rsa.pub","w+") do |f|
|
155
|
+
f.write(mock_text)
|
156
|
+
end
|
157
|
+
|
158
|
+
File.exists?(GAS_DIRECTORY + "/#{@nickname}_id_rsa").should be_false
|
159
|
+
File.exists?(GAS_DIRECTORY + "/#{@nickname}_id_rsa.pub").should be_false
|
160
|
+
|
161
|
+
Gas::Ssh.use_current_rsa_files_for_this_user(@nickname)
|
162
|
+
|
163
|
+
File.exists?(GAS_DIRECTORY + "/#{@nickname}_id_rsa").should be_true
|
164
|
+
File.exists?(GAS_DIRECTORY + "/#{@nickname}_id_rsa.pub").should be_true
|
165
|
+
|
166
|
+
File.read(GAS_DIRECTORY + "/#{@nickname}_id_rsa") do |f|
|
167
|
+
f.read.should == mock_text # this part doesn't work... hmmm...
|
168
|
+
end
|
169
|
+
|
170
|
+
File.delete(GAS_DIRECTORY + "/#{@nickname}_id_rsa")
|
171
|
+
File.delete(GAS_DIRECTORY + "/#{@nickname}_id_rsa.pub")
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
|
176
|
+
it "should have a UTILITY for deleting rsa files of user" do
|
177
|
+
lambda do
|
178
|
+
Gas::Ssh.delete_associated_local_keys!(@nickname2)
|
179
|
+
end.should change{count_of_files_in(GAS_DIRECTORY)}.by(-2)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
describe "Networking stuff..." do
|
188
|
+
before :all do
|
189
|
+
# make sure sample key is deleted in the github web client if you incur issues
|
190
|
+
@username = "aTestGitAccount"
|
191
|
+
@password = "plzdon'thackthetestaccount1"
|
192
|
+
|
193
|
+
config = "[#{@nickname}]\n name = #{@name}\n email = #{@email}\n\n[user2]\n name = foo\n email = bar"
|
194
|
+
@config = Gas::Config.new nil, config
|
195
|
+
@user = @config.users[0]
|
196
|
+
|
197
|
+
@credentials = {:username => @username, :password => @password}
|
198
|
+
|
199
|
+
# Code to prepare the github environment for testing
|
200
|
+
@sample_rsa = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDn74QR9yHb+hcid8iH3+FTaEwnKtwjttseJDbIA2PaivN2uvESrvHlp8Ss/cRox3fFu34QR5DpdOhlfULjTX7yKVuxhaNrAJaqg8rX8hgr9U1Botnyy1DBueEyyA3o1fxRkmwTf6FNnkt1BxWP635tD0lbmUubwaadXjQqPOf3Uw=="
|
201
|
+
|
202
|
+
Gas.delete(@nickname)
|
203
|
+
Gas::Ssh.stub!(:get_username_and_password_and_authenticate).and_return(@credentials)
|
204
|
+
|
205
|
+
VCR.use_cassette('instantiate_github_speaker', :record => :new_episodes) do
|
206
|
+
@github_speaker = Gas::GithubSpeaker.new(@user, @username, @password)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
after :all do
|
211
|
+
Gas.delete(@nickname)
|
212
|
+
Gas::Ssh.unstub!(:get_username_and_password_and_authenticate)
|
213
|
+
end
|
214
|
+
|
215
|
+
describe "Should remove and insert keys into github" do
|
216
|
+
it 'UTILITY: should insert a new key into github and conversly remove that key' do
|
217
|
+
initial_request = ''
|
218
|
+
subsequent_request = ''
|
219
|
+
|
220
|
+
VCR.use_cassette('get_keys-find_none') do
|
221
|
+
initial_request = get_keys(@username, @password).length
|
222
|
+
end
|
223
|
+
|
224
|
+
VCR.use_cassette('key_installation_routine-Add_key', :record => :new_episodes) do
|
225
|
+
Gas::Ssh.key_installation_routine!(@user, @sample_rsa, @github_speaker)
|
226
|
+
end
|
227
|
+
|
228
|
+
VCR.use_cassette('get_keys-find_one') do
|
229
|
+
subsequent_request = get_keys(@username, @password).length
|
230
|
+
end
|
231
|
+
|
232
|
+
(subsequent_request - initial_request).should be(1)
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'should remove the key that it just inserted, so DONT RUN ALONE' do
|
236
|
+
initial_request = ''
|
237
|
+
subsequent_request = ''
|
238
|
+
|
239
|
+
VCR.use_cassette('get_keys-find_one') do
|
240
|
+
initial_request = get_keys(@username, @password).length
|
241
|
+
end
|
242
|
+
|
243
|
+
VCR.use_cassette('key_installation_routine-Remove_key') do
|
244
|
+
lambda do
|
245
|
+
@github_speaker.remove_key! @sample_rsa
|
246
|
+
end.should change{get_keys(@username, @password).length}.by(-1)
|
247
|
+
end
|
248
|
+
|
249
|
+
VCR.use_cassette('get_keys-find_none') do
|
250
|
+
subsequent_request = get_keys(@username, @password).length
|
251
|
+
end
|
252
|
+
|
253
|
+
(subsequent_request - initial_request).should be(-1)
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
257
|
+
|
258
|
+
|
259
|
+
it "should add ssh keys to github when user is created, and delete them when destroyed" do
|
260
|
+
# yes, delete all
|
261
|
+
Gas::Prompter.stub!(:user_wants_to_delete_all_ssh_data?).and_return("a") # all keys, local and github
|
262
|
+
# create new user and use ssh handling
|
263
|
+
Gas::Prompter.stub!(:user_wants_gas_to_handle_rsa_keys?).and_return(true)
|
264
|
+
Gas::Prompter.stub!(:user_wants_to_use_key_already_in_ssh?).and_return(false)
|
265
|
+
Gas::Prompter.stub!(:user_wants_to_install_key_to_github?).and_return(true)
|
266
|
+
|
267
|
+
VCR.use_cassette('add-on-crteation-delete-on-deletion', :record => :new_episodes) do
|
268
|
+
lambda do
|
269
|
+
Gas.add(@nickname,@name,@email, @github_speaker)
|
270
|
+
end.should change{get_keys(@username, @password).length}.by(1)
|
271
|
+
|
272
|
+
lambda do
|
273
|
+
Gas::Ssh.stub!(:get_nils).and_return({ :username => @username, :password => @password })
|
274
|
+
Gas.delete(@nickname)
|
275
|
+
Gas::Ssh.unstub!(:get_nils)
|
276
|
+
end.should change{get_keys(@username, @password).length}.by(-1)
|
277
|
+
end
|
278
|
+
|
279
|
+
Gas::Prompter.unstub!(:user_wants_to_delete_all_ssh_data?)
|
280
|
+
Gas::Prompter.unstub!(:user_wants_gas_to_handle_rsa_keys?)
|
281
|
+
Gas::Prompter.unstub!(:user_wants_to_use_key_already_in_ssh?)
|
282
|
+
Gas::Prompter.unstub!(:user_wants_to_install_key_to_github?)
|
283
|
+
end
|
284
|
+
|
285
|
+
it "Gas.Delete should be able to remove the id_rsa from .gas" do
|
286
|
+
Gas::Prompter.stub!(:user_wants_to_delete_all_ssh_data?).and_return("a")
|
287
|
+
Gas::Prompter.stub!(:user_wants_gas_to_handle_rsa_keys?).and_return(true)
|
288
|
+
Gas::Prompter.stub!(:user_wants_to_use_key_already_in_ssh?).and_return(false)
|
289
|
+
Gas::Prompter.stub!(:user_wants_to_install_key_to_github?).and_return(true)
|
290
|
+
|
291
|
+
VCR.use_cassette('add-on-crteation-delete-on-deletion') do
|
292
|
+
lambda do
|
293
|
+
Gas.add(@nickname,@name,@email, @github_speaker)
|
294
|
+
end.should change{count_of_files_in(GAS_DIRECTORY)}.by(2)
|
295
|
+
|
296
|
+
lambda do
|
297
|
+
Gas::Ssh.stub!(:get_nils).and_return({:username => @username, :password => @password })
|
298
|
+
Gas.delete(@nickname)
|
299
|
+
Gas::Ssh.unstub!(:get_nils)
|
300
|
+
end.should change{count_of_files_in(GAS_DIRECTORY)}.by(-2)
|
301
|
+
end
|
302
|
+
|
303
|
+
Gas::Prompter.unstub!(:user_wants_to_delete_all_ssh_data?)
|
304
|
+
Gas::Prompter.unstub!(:user_wants_gas_to_handle_rsa_keys?)
|
305
|
+
Gas::Prompter.unstub!(:user_wants_to_use_key_already_in_ssh?)
|
306
|
+
Gas::Prompter.unstub!(:user_wants_to_install_key_to_github?)
|
307
|
+
end
|
308
|
+
|
309
|
+
it 'Gas.ssh(nickname) should be able to add ssh support to a legacy user or an opt-out' do
|
310
|
+
Gas::Prompter.stub!(:user_wants_gas_to_handle_rsa_keys?).and_return(false)
|
311
|
+
Gas.add(@nickname,@name,@email)
|
312
|
+
Gas::Prompter.unstub!(:user_wants_gas_to_handle_rsa_keys?)
|
313
|
+
|
314
|
+
Gas::Prompter.stub!(:user_wants_gas_to_handle_rsa_keys?).and_return(true)
|
315
|
+
Gas::Ssh.stub!(:upload_public_key_to_github)
|
316
|
+
|
317
|
+
lambda do
|
318
|
+
Gas.ssh(@nickname)
|
319
|
+
end.should change{count_of_files_in(GAS_DIRECTORY)}.by(2)
|
320
|
+
|
321
|
+
Gas::Ssh.delete_associated_local_keys!(@nickname)
|
322
|
+
|
323
|
+
Gas::Prompter.unstub!(:user_wants_gas_to_handle_rsa_keys?)
|
324
|
+
Gas::Ssh.unstub!(:upload_public_key_to_github)
|
325
|
+
end
|
326
|
+
|
327
|
+
|
328
|
+
|
329
|
+
it "Should be able to tell if it's ever used this key under this ISP provider before and then warn the user"
|
330
|
+
|
331
|
+
it 'Should have the ability to show if the author is associated with a specific github account NAME, stored in gas.accouts file'
|
332
|
+
|
333
|
+
it 'Should have the ability to link up with non-github git-daemons'
|
334
|
+
|
335
|
+
end
|
336
|
+
|
337
|
+
|
338
|
+
end
|