sty 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,164 @@
1
+ require_relative 'functions'
2
+ require 'aws-sdk-ec2'
3
+ require 'aws-sdk-ssm'
4
+ require 'optparse'
5
+ require 'ostruct'
6
+ require 'uri'
7
+ require 'pry'
8
+ require 'json'
9
+ require 'os'
10
+
11
+ Aws.config.update(:http_proxy => ENV['https_proxy'])
12
+
13
+ MINIMAL_AGENT_VERSION = '2.3.612.0'
14
+ DEFAULT_REGION = 'ap-southeast-2'
15
+
16
+ class SSM
17
+
18
+ def region
19
+ ENV['AWS_REGION'] || DEFAULT_REGION
20
+ end
21
+
22
+ def ec2
23
+ @ec2 = @ec2 || Aws::EC2::Client.new(region: region)
24
+ end
25
+
26
+ def ssm
27
+ @ssm = @ssm || Aws::SSM::Client.new(region: region)
28
+ end
29
+
30
+ def all_ec2_instances
31
+ ec2.describe_instances.map do |page|
32
+ page.reservations.map { |r| r.instances }
33
+ end.flatten
34
+ end
35
+
36
+ def all_ssm_details
37
+ ssm.describe_instance_information.map do |page|
38
+ page.instance_information_list
39
+ end.flatten
40
+ end
41
+
42
+ def ssm_details
43
+ @ssm_details = @ssm_details || all_ssm_details.map do |i|
44
+ [i.instance_id, i]
45
+ end.to_h
46
+ end
47
+
48
+ def instance_id(instance)
49
+ instance.instance_id
50
+ end
51
+
52
+ def instance_name(instance)
53
+ name_tag = instance.tags.select { |t| t.key == 'Name' }.first
54
+ name_tag ? name_tag.value : "None"
55
+ end
56
+
57
+ def instance_ips(instance)
58
+ instance.network_interfaces.map { |n| n.private_ip_address }
59
+ end
60
+
61
+ def extract_fields(inst)
62
+ [instance_name(inst), instance_id(inst)] + instance_ips(inst)
63
+ end
64
+
65
+ def prepare_regex(names)
66
+ names = ['.'] if names.empty?
67
+ names.map { |n| Regexp.new(Regexp.quote(n), Regexp::IGNORECASE) }
68
+ end
69
+
70
+ def win?(instance)
71
+ instance.platform =~ /windows/i
72
+ end
73
+
74
+ def platform(instance)
75
+ win?(instance) ? magenta("[Win] ") : ""
76
+ end
77
+
78
+ def ping(instance)
79
+ #binding.pry
80
+ status = ssm_details[instance_id(instance)]&.ping_status || 'Unavailable'
81
+ version_str = ssm_details[instance_id(instance)]&.agent_version
82
+ version = Gem::Version.new(version_str || '0')
83
+ reference_version = Gem::Version.new(MINIMAL_AGENT_VERSION)
84
+ old_version = version < reference_version
85
+
86
+ result = "[#{status}#{old_version ? ', old agent' : ''}]"
87
+
88
+ case
89
+ when status == 'Online' && !old_version
90
+ green(result)
91
+ when status == 'Online' && old_version
92
+ yellow(result)
93
+ else
94
+ red(result)
95
+ end
96
+
97
+ end
98
+
99
+ def find(instances, names)
100
+ re = prepare_regex(names)
101
+ instances.select do |i|
102
+ i.state.name == 'running' &&
103
+ extract_fields(i).any? { |f| re.all? { |r| f =~ r } }
104
+ end.sort{|a,b| instance_name(a) <=> instance_name(b)}
105
+ end
106
+
107
+ def print_refine_instances(instances, type)
108
+ puts "Please refine #{type} instance:"
109
+ instances.each_with_index do |inst, idx|
110
+ puts "#{idx}: #{instance_id(inst)} #{ping(inst)} [#{instance_name(inst)}] #{platform(inst)}(#{instance_ips(inst).join(', ')}) "
111
+ end
112
+ end
113
+
114
+ def refine(found)
115
+ if found.size > 1
116
+ refine = nil
117
+ loop do
118
+ yield(found)
119
+ refine = Integer(STDIN.gets.chomp) rescue false
120
+ break if refine && refine < found.size
121
+ end
122
+ target = found[refine]
123
+ else
124
+ target = found.first
125
+ end
126
+ target
127
+ end
128
+
129
+ def session_manager
130
+ case
131
+ when OS.mac?
132
+ "#{dir}/bin/osx/session-manager-plugin"
133
+ when OS.linux?
134
+ "#{dir}/bin/linux/session-manager-plugin"
135
+ else
136
+ raise "The tool doesn't have binary for #{OS.host}"
137
+ end
138
+ end
139
+
140
+ def connect(args)
141
+ found = find(all_ec2_instances, args)
142
+ if found.empty?
143
+ puts "No instances found for search terms: #{args.join(', ')}"
144
+ exit 1
145
+ end
146
+ target = refine(found) {|found| print_refine_instances(found, 'target')}
147
+
148
+ begin
149
+ resp = ssm.start_session(target: instance_id(target))
150
+ rescue Exception => e
151
+ puts red("ERROR! Unable to start session")
152
+ puts white(e.message)
153
+ exit 1
154
+ end
155
+
156
+ mappings = {session_id: 'SessionId', token_value: 'TokenValue', stream_url: 'StreamUrl'}
157
+ reqest_str = resp.to_h.map {|k, v| [mappings[k], v] }.to_h.to_json
158
+ exec "#{session_manager} \'#{reqest_str}\' ap-southeast-2 StartSession"
159
+
160
+ end
161
+
162
+ end
163
+
164
+ SSM.new.connect(ARGV)
@@ -0,0 +1,3 @@
1
+ class Store
2
+
3
+ end
@@ -0,0 +1,7 @@
1
+ lo:
2
+ proxy: http://localhost:3128
3
+ no-proxy: .internal
4
+
5
+ ext:
6
+ proxy: http://proxy:8080
7
+ no-proxy: .internal
@@ -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 |s|
6
+ s.name = 'sty'
7
+ s.version = '0.0.1'
8
+ s.description = "Command line tools"
9
+ s.authors = ["Andrew Sozonnyk"]
10
+ s.email = ''
11
+ s.homepage = 'https://github.com/sozonnyk/sty'
12
+ s.license = 'MIT'
13
+ s.require_paths = %w(lib)
14
+ s.required_ruby_version = ">= 2.0.0"
15
+ s.required_rubygems_version = ">= 1.3.5"
16
+ s.summary = s.description
17
+
18
+ s.files = %w(.document sty.gemspec) + Dir["*.md", "bin/*", "lib/**/*.rb", "*.yaml"]
19
+ s.extensions = ['ext/install/Rakefile']
20
+
21
+ s.add_development_dependency "bundler", ">= 1.0", "< 3"
22
+ s.add_runtime_dependency 'aws-sdk-core', '~> 3'
23
+ s.add_runtime_dependency 'aws-sdk-ec2', '~> 1'
24
+ s.add_runtime_dependency 'aws-sdk-ssm', '~> 1'
25
+ s.add_runtime_dependency 'thor', '~> 0.20'
26
+ s.add_runtime_dependency 'ruby-keychain', '~> 0.3'
27
+ end
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sty
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Sozonnyk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-12-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '3'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '3'
33
+ - !ruby/object:Gem::Dependency
34
+ name: aws-sdk-core
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '3'
47
+ - !ruby/object:Gem::Dependency
48
+ name: aws-sdk-ec2
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1'
61
+ - !ruby/object:Gem::Dependency
62
+ name: aws-sdk-ssm
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1'
75
+ - !ruby/object:Gem::Dependency
76
+ name: thor
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '0.20'
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '0.20'
89
+ - !ruby/object:Gem::Dependency
90
+ name: ruby-keychain
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '0.3'
96
+ type: :runtime
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '0.3'
103
+ description: Command line tools
104
+ email: ''
105
+ executables: []
106
+ extensions:
107
+ - ext/install/Rakefile
108
+ extra_rdoc_files: []
109
+ files:
110
+ - ".document"
111
+ - README.md
112
+ - auth-keys.yaml
113
+ - auth.yaml
114
+ - bin/sty
115
+ - ec2.yaml
116
+ - ext/install/Rakefile
117
+ - lib/sty.rb
118
+ - lib/sty/account.rb
119
+ - lib/sty/auth-rotate.rb
120
+ - lib/sty/auth.rb
121
+ - lib/sty/cli.rb
122
+ - lib/sty/config.rb
123
+ - lib/sty/console.rb
124
+ - lib/sty/dig.rb
125
+ - lib/sty/functions.rb
126
+ - lib/sty/info.rb
127
+ - lib/sty/keychain.rb
128
+ - lib/sty/proxy.rb
129
+ - lib/sty/ssh.rb
130
+ - lib/sty/ssm.rb
131
+ - lib/sty/store.rb
132
+ - proxy.yaml
133
+ - sty.gemspec
134
+ homepage: https://github.com/sozonnyk/sty
135
+ licenses:
136
+ - MIT
137
+ metadata: {}
138
+ post_install_message:
139
+ rdoc_options: []
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: 2.0.0
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: 1.3.5
152
+ requirements: []
153
+ rubygems_version: 3.0.3
154
+ signing_key:
155
+ specification_version: 4
156
+ summary: Command line tools
157
+ test_files: []