aws_csshx 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ *.swo
5
+ *.swp
6
+ Manifest
7
+ .rvmrc
@@ -0,0 +1,8 @@
1
+ ### aws_csshx 0.1.1 2012-05-04
2
+
3
+ * Added command line switches (Eric Lubow)
4
+ * Added config file support using .csshrc (Eric Lubow)
5
+
6
+ ### aws_csshx 0.1.0 2012-05-01
7
+
8
+ * Initial vesion (Russell Bradberry)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in aws_csshx.gemspec
4
+ gemspec
@@ -0,0 +1,18 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ aws_csshx (0.0.1)
5
+ right_aws
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ right_aws (3.0.4)
11
+ right_http_connection (>= 1.2.5)
12
+ right_http_connection (1.3.0)
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ aws_csshx!
@@ -0,0 +1,8 @@
1
+ # AWS CSSHX Wrapper
2
+
3
+ This is a wrapper script for ClusterSSHX (csshx). It allows the user the ability to ssh to all machines in an AWS security group using a specific key and user for those machines.
4
+
5
+ ## Installation
6
+
7
+ gem install aws_csshx
8
+
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/TODO.md ADDED
@@ -0,0 +1,3 @@
1
+ ### TODO List for aws_csshx
2
+
3
+ * Add ability to use -H/--hosts to tack on additional hosts to the SSH cluster
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "aws_csshx/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "aws_csshx"
7
+ s.version = AwsCsshx::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Russell Bradberry", "Eric Lubow"]
10
+ s.email = ["eric@lubow.org"]
11
+ s.homepage = ""
12
+ s.summary = %q{csshx wrapper that interacts with your AWS account for group ssh sessions}
13
+ s.description = %q{csshx wrapper that interacts with your AWS account for group ssh sessions}
14
+
15
+ s.add_dependency 'right_aws'
16
+
17
+ s.rubyforge_project = "aws_csshx"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+ end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+ require 'aws_csshx'
5
+
6
+ exit AwsCsshx::Application.run!(*ARGV)
@@ -0,0 +1,8 @@
1
+ require 'etc'
2
+ require 'right_aws'
3
+
4
+ require 'aws_csshx/application'
5
+ require 'aws_csshx/configuration_file'
6
+ require 'aws_csshx/misc'
7
+ require 'aws_csshx/options'
8
+ require 'aws_csshx/version'
@@ -0,0 +1,94 @@
1
+ module AwsCsshx
2
+ class Application
3
+ attr :options
4
+
5
+ class << self
6
+
7
+ def csshx_exists?
8
+ `which csshx > /dev/null 2>&1`
9
+ end
10
+
11
+ def aws_settings_exist?
12
+ @options[:aws_access_key] and @options[:aws_secret_key] and @options[:aws_region] and File.exists?(@options[:ec2_private_key])
13
+ end
14
+
15
+ def has_servers?(list)
16
+ server_list.count > 0 ? true : false
17
+ end
18
+
19
+ def run!(*arguments)
20
+ @options = {}
21
+
22
+ # No need to go further unless csshX exists
23
+ abort('csshX file is required') unless csshx_exists?
24
+
25
+ begin
26
+ # First we load the config file and then process the command line
27
+ # options since they take precedence.
28
+
29
+ # Load the config file if it exists
30
+ conf_file = "#{Etc.getpwuid.dir}/.csshrc"
31
+ if File.exists?(conf_file)
32
+ config = AwsCsshx::ConfigurationFile.new(conf_file)
33
+ @options = config.options
34
+ end
35
+
36
+ command_line_options = AwsCsshx::Options.new(arguments)
37
+ @options.merge!(command_line_options[:options])
38
+ @options = AwsCsshx::Misc.symbolize_hash_keys(@options)
39
+
40
+ # Load the new config file if different
41
+ if conf_file != @options[:conf] and File.exists?(conf_file)
42
+ config = AwsCsshx::ConfigurationFile.new(@options[:conf])
43
+ end
44
+
45
+ # Deal with the option issues
46
+ if command_line_options[:invalid_argument]
47
+ $stderr.puts command_line_options[:invalid_argument]
48
+ @options[:help] = true
49
+ end
50
+
51
+ # Show the version screen and bounce if requested
52
+ if @options[:version]
53
+ puts "#{$0} #{AwsCsshx::VERSION}"
54
+ return 0
55
+ end
56
+
57
+ # Show the help screen and bounce if requested
58
+ if @options[:help]
59
+ puts command_line_options.opts
60
+ return 0
61
+ end
62
+
63
+ # Stop here without all our AWS settings
64
+ abort("Invalid AWS settings") unless aws_settings_exist?
65
+
66
+ abort("Cannot continue without AWS security group (-g)") unless @options[:group]
67
+ @server_list = aws_server_list_by_group @options[:group]
68
+
69
+ if has_servers? @server_list
70
+ `csshx --login #{@options[:login]} --ssh_args='-i #{@options[:ec2_private_key]}' #{@server_list.join(' ')}`
71
+ puts "Opened connections to #{@server_list.count} servers in the '#{@options[:group]}' security group."
72
+ else
73
+ puts "No servers found...bailing out!"
74
+ end
75
+ rescue Exception => e
76
+ puts "Error: #{e.inspect}"
77
+ puts "Trace: #{e.backtrace.join('\n')}"
78
+ end
79
+
80
+ # Exit cleanly
81
+ return 0
82
+ end
83
+
84
+ def aws_server_list_by_group(group)
85
+ @ec2_api ||= RightAws::Ec2.new(@options[:aws_access_key], @options[:aws_secret_key])
86
+
87
+ @ec2_api.describe_instances.reject{|i| i[:aws_state] != "running"}.map do |instance|
88
+ instance[:dns_name] if instance[:groups].map{|g| g[:group_name]}.include?(group)
89
+ end.compact
90
+ end
91
+
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,82 @@
1
+ # TODO Create config option errors handling class
2
+ # TODO Ensure environment variables exist before blindly setting options to them
3
+ module AwsCsshx
4
+ class ConfigurationFile
5
+ attr :options
6
+
7
+ CONFIG_OPTS = %q{ec2_private_key aws_access_key aws_secret_key aws_region}
8
+
9
+ def initialize(conf)
10
+ @config_file = conf
11
+ @options = {}
12
+ if File.exists?(conf)
13
+ load_config_from_file @config_file
14
+ else
15
+ raise FileDoesNotExist, "Config file #{@config_file} cannot be found."
16
+ end
17
+ end
18
+
19
+ # Iterate over the config file line by line and throw away things not in our config opts array
20
+ def load_config_from_file(file)
21
+ f = File.open(file, "r")
22
+ f.each_line do |line|
23
+ field,value = line.split('=')
24
+ next if field.nil? or value.nil?
25
+ field.strip!.downcase!
26
+ value.strip!
27
+ next unless CONFIG_OPTS.include?(field)
28
+ @options[field] =
29
+ if field == 'ec2_private_key' then set_ec2_private_key(value)
30
+ elsif field == 'aws_access_key' then set_aws_access_key(value)
31
+ elsif field == 'aws_secret_key' then set_aws_secret_key(value)
32
+ elsif field == 'aws_region' then set_aws_region(value)
33
+ else puts "No such option #{field} skipping..."
34
+ end
35
+ end
36
+ end
37
+
38
+
39
+ #
40
+ # Private(ish) methods for config settings
41
+ #
42
+
43
+ def set_aws_region(val)
44
+ if val
45
+ val
46
+ elsif ENV['AWS_REGION']
47
+ ENV['AWS_REGION']
48
+ else
49
+ 'us-east-1'
50
+ end
51
+ end
52
+
53
+ def set_aws_secret_key(val)
54
+ if val
55
+ val
56
+ elsif ENV['AWS_SECRET_KEY']
57
+ ENV['AWS_SECRET_KEY']
58
+ elsif ENV['AMAZON_SECRET_ACCESS_KEY']
59
+ ENV['AMAZON_SECRET_ACCESS_KEY']
60
+ end
61
+ end
62
+
63
+ def set_aws_access_key(val)
64
+ if val
65
+ val
66
+ elsif ENV['AWS_ACCESS_KEY']
67
+ ENV['AWS_ACCESS_KEY']
68
+ elsif ENV['AMAZON_ACCESS_KEY_ID']
69
+ ENV['AMAZON_ACCESS_KEY_ID']
70
+ end
71
+ end
72
+
73
+ def set_ec2_private_key(key_file)
74
+ if File.exists?(key_file)
75
+ key_file
76
+ else
77
+ puts "#{key_file} does not exist, using default."
78
+ ENV['EC2_PRIVATE_KEY']
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,13 @@
1
+ module AwsCsshx
2
+ class Misc
3
+ class << self
4
+
5
+ def symbolize_hash_keys(hash)
6
+ hsh = {}
7
+ hash.each_pair { |k,v| hsh[k.downcase.to_sym] = v }
8
+ hsh
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,89 @@
1
+ module AwsCsshx
2
+ class Options < Hash
3
+ attr_reader :opts, :orig_args
4
+
5
+ def initialize(args)
6
+ super()
7
+
8
+ user_home = ENV['HOME']
9
+
10
+ @orig_args = args.clone
11
+
12
+ options = {}
13
+
14
+ require 'optparse'
15
+ @opts = OptionParser.new do |o|
16
+ o.banner = "Usage: #{File.basename($0)} <file1> <file2> ..."
17
+
18
+ o.separator ""
19
+ o.separator "AWS Options"
20
+
21
+ options[:group] = 'default'
22
+ o.on( '-g', '--group <group>', 'AWS security group name to use for the csshX sessions' ) do |group|
23
+ options[:group] = group
24
+ end
25
+
26
+ o.on( '-i', '--aws-identity <identity>', 'Use this keyfile as your SSH private key' ) do |identity|
27
+ options[:ec2_private_key] = identity
28
+ end
29
+
30
+ o.on( '-r', '--aws-region <region>', 'AWS region to query for the csshX sessions (default: us-east-1)' ) do |region|
31
+ options[:aws_region] = region
32
+ end
33
+
34
+ o.separator ""
35
+ o.separator "csshX Options"
36
+
37
+ options[:login] = 'root'
38
+ o.on( '-l', '--login <login>', 'User login to use for the csshX sessions (default: root)' ) do |login|
39
+ options[:login] = login
40
+ end
41
+
42
+ options[:csshx_opts] = ''
43
+ o.on( '-o', '--csshx-opts <csshx_opts>', 'Pass the options listed directly to csshx' ) do |csshx_opts|
44
+ options[:csshx_opts] = csshx_opts
45
+ end
46
+
47
+ options[:iterm2] = false
48
+ o.on( '-2', '--iterm2', 'Use csshX.iterm instead of csshx' ) do |iterm2|
49
+ options[:iterm2] = true
50
+ end
51
+
52
+ o.separator ""
53
+
54
+ options[:conf] = "#{Etc.getpwuid.dir}/.csshrc"
55
+ o.on( '-c', '--conf <file>', 'aws_csshX config file (default: .csshrc)' ) do |file|
56
+ if File.exists?(file)
57
+ options[:conf] = file
58
+ else
59
+ raise FileDoesNotExist, "Config file #{file} cannot be found."
60
+ end
61
+ end
62
+
63
+ o.on('-V', '--version', "Display version information") do
64
+ options[:version] = true
65
+ end
66
+
67
+ options[:help] = false
68
+ o.on( '-h', '--help', 'Display this help screen' ) do
69
+ options[:help] = true
70
+ end
71
+
72
+ o.separator ""
73
+ o.separator "Examples:"
74
+ o.separator " Cluster SSH to all machines in the 'utility' security group:"
75
+ o.separator " #{File.basename($0)} -g utility"
76
+ o.separator ""
77
+ end
78
+
79
+ begin
80
+ @opts.parse!(args)
81
+ self[:options] = options
82
+ rescue OptionParser::InvalidOption => e
83
+ self[:invalid_argument] = e.message
84
+ @opts.parse(args, flags={ :delete_invalid_opts => true })
85
+ self[:options] = options
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,3 @@
1
+ module AwsCsshx
2
+ VERSION = "0.1.1"
3
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aws_csshx
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Russell Bradberry
9
+ - Eric Lubow
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-05-04 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: right_aws
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ description: csshx wrapper that interacts with your AWS account for group ssh sessions
32
+ email:
33
+ - eric@lubow.org
34
+ executables:
35
+ - aws_csshx
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - .gitignore
40
+ - Changelog.md
41
+ - Gemfile
42
+ - Gemfile.lock
43
+ - README.md
44
+ - Rakefile
45
+ - TODO.md
46
+ - aws_csshx.gemspec
47
+ - bin/aws_csshx
48
+ - lib/aws_csshx.rb
49
+ - lib/aws_csshx/application.rb
50
+ - lib/aws_csshx/configuration_file.rb
51
+ - lib/aws_csshx/misc.rb
52
+ - lib/aws_csshx/options.rb
53
+ - lib/aws_csshx/version.rb
54
+ homepage: ''
55
+ licenses: []
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubyforge_project: aws_csshx
74
+ rubygems_version: 1.8.18
75
+ signing_key:
76
+ specification_version: 3
77
+ summary: csshx wrapper that interacts with your AWS account for group ssh sessions
78
+ test_files: []