conssh 0.1.0
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 +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/Conch_drawing.jpg +0 -0
- data/Gemfile +6 -0
- data/README.md +52 -0
- data/Rakefile +6 -0
- data/bin/bundle +105 -0
- data/bin/console +14 -0
- data/bin/conssh +29 -0
- data/bin/htmldiff +29 -0
- data/bin/ldiff +29 -0
- data/bin/rake +29 -0
- data/bin/rspec +29 -0
- data/bin/rubocop +29 -0
- data/bin/ruby-parse +29 -0
- data/bin/ruby-rewrite +29 -0
- data/bin/setup +8 -0
- data/bitbucket-pipelines.yml +20 -0
- data/conssh.gemspec +32 -0
- data/demo/Dockerfile +7 -0
- data/demo/run.sh +32 -0
- data/demo/setup.sh +37 -0
- data/exe/conssh +6 -0
- data/lib/conssh.rb +8 -0
- data/lib/conssh/app.rb +10 -0
- data/lib/conssh/config_writer.rb +22 -0
- data/lib/conssh/inventory.rb +15 -0
- data/lib/conssh/version.rb +3 -0
- data/setup.md +178 -0
- metadata +135 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3747759ebf30a2156d2a3e27b22bb5203010b91c4ce7ddb9c46fa5edcb3ec9da
|
4
|
+
data.tar.gz: 77808aa31fa8e883827484a657527aada101f5c932984c182da989c83ff526d1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2553fd95a8a13aa3fcc942d1d662a094b2c9fdf035fa00b7b0ea8e2f49960c0af079b56dc18107b5e48edb5b49f762b5bc2c28183db42466ac743182adec0e38
|
7
|
+
data.tar.gz: 6843d3750e387672c5c911e8fcce5741c3d5084ec4a57ad39da63b8a8838d52ce02ceb4cfaaffd77cad6a5fbda2f0cbdea61a162f019e3d034d8cc4c0419fab6
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.5
|
data/.travis.yml
ADDED
data/Conch_drawing.jpg
ADDED
Binary file
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Conssh
|
2
|
+
|
3
|
+

|
4
|
+
|
5
|
+
Conssh is a utility to configure SSH. It generates config files with connection
|
6
|
+
information for a fleet of EC2 instances.
|
7
|
+
|
8
|
+
Use it together with an autocompletion tool that understands SSH, like
|
9
|
+
[bash-completion] or [fzf].
|
10
|
+
|
11
|
+
Basic usage:
|
12
|
+
|
13
|
+
```
|
14
|
+
$ AWS_REGION=us-west-1 AWS_PROFILE=staging bundle exec conssh > ~/.ssh/config
|
15
|
+
$ ssh …
|
16
|
+
```
|
17
|
+
|
18
|
+
[bash-completion]: https://github.com/scop/bash-completion
|
19
|
+
[fzf]: https://github.com/junegunn/fzf
|
20
|
+
|
21
|
+
## Background
|
22
|
+
|
23
|
+
It is inspired by similar tools such as [ec2ssh] and [aws-ssh-config].
|
24
|
+
|
25
|
+
This is experimental code. See the issues section for the work to make it more
|
26
|
+
robust.
|
27
|
+
|
28
|
+
Notable features:
|
29
|
+
|
30
|
+
* Written in [Ruby] using version 3 of the [AWS SDK]
|
31
|
+
* Unit tested using the [Moto] mock AWS API server
|
32
|
+
* Packaged as a Ruby gem to use as a library or an executable
|
33
|
+
|
34
|
+
[ec2ssh]: https://github.com/mirakui/ec2ssh
|
35
|
+
[aws-ssh-config]: https://github.com/gianlucaborello/aws-ssh-config
|
36
|
+
[Ruby]: https://www.ruby-lang.org/
|
37
|
+
[AWS SDK]: https://github.com/aws/aws-sdk-ruby/
|
38
|
+
[Moto]: https://github.com/spulec/moto
|
39
|
+
|
40
|
+
## How do I get set up?
|
41
|
+
|
42
|
+
See the [setup](setup.md) document for an early version step-by-step setup.
|
43
|
+
|
44
|
+
## Demo
|
45
|
+
|
46
|
+
Build the docker container and follow the instructions when the container runs.
|
47
|
+
|
48
|
+
```bash
|
49
|
+
cd demo
|
50
|
+
docker build --tag demo .
|
51
|
+
docker run -it demo
|
52
|
+
```
|
data/Rakefile
ADDED
data/bin/bundle
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'bundle' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "rubygems"
|
12
|
+
|
13
|
+
m = Module.new do
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def invoked_as_script?
|
17
|
+
File.expand_path($0) == File.expand_path(__FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
def env_var_version
|
21
|
+
ENV["BUNDLER_VERSION"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def cli_arg_version
|
25
|
+
return unless invoked_as_script? # don't want to hijack other binstubs
|
26
|
+
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
27
|
+
bundler_version = nil
|
28
|
+
update_index = nil
|
29
|
+
ARGV.each_with_index do |a, i|
|
30
|
+
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
31
|
+
bundler_version = a
|
32
|
+
end
|
33
|
+
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
34
|
+
bundler_version = $1 || ">= 0.a"
|
35
|
+
update_index = i
|
36
|
+
end
|
37
|
+
bundler_version
|
38
|
+
end
|
39
|
+
|
40
|
+
def gemfile
|
41
|
+
gemfile = ENV["BUNDLE_GEMFILE"]
|
42
|
+
return gemfile if gemfile && !gemfile.empty?
|
43
|
+
|
44
|
+
File.expand_path("../../Gemfile", __FILE__)
|
45
|
+
end
|
46
|
+
|
47
|
+
def lockfile
|
48
|
+
lockfile =
|
49
|
+
case File.basename(gemfile)
|
50
|
+
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
|
51
|
+
else "#{gemfile}.lock"
|
52
|
+
end
|
53
|
+
File.expand_path(lockfile)
|
54
|
+
end
|
55
|
+
|
56
|
+
def lockfile_version
|
57
|
+
return unless File.file?(lockfile)
|
58
|
+
lockfile_contents = File.read(lockfile)
|
59
|
+
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
60
|
+
Regexp.last_match(1)
|
61
|
+
end
|
62
|
+
|
63
|
+
def bundler_version
|
64
|
+
@bundler_version ||= begin
|
65
|
+
env_var_version || cli_arg_version ||
|
66
|
+
lockfile_version || "#{Gem::Requirement.default}.a"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def load_bundler!
|
71
|
+
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
72
|
+
|
73
|
+
# must dup string for RG < 1.8 compatibility
|
74
|
+
activate_bundler(bundler_version.dup)
|
75
|
+
end
|
76
|
+
|
77
|
+
def activate_bundler(bundler_version)
|
78
|
+
if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
|
79
|
+
bundler_version = "< 2"
|
80
|
+
end
|
81
|
+
gem_error = activation_error_handling do
|
82
|
+
gem "bundler", bundler_version
|
83
|
+
end
|
84
|
+
return if gem_error.nil?
|
85
|
+
require_error = activation_error_handling do
|
86
|
+
require "bundler/version"
|
87
|
+
end
|
88
|
+
return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
89
|
+
warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
|
90
|
+
exit 42
|
91
|
+
end
|
92
|
+
|
93
|
+
def activation_error_handling
|
94
|
+
yield
|
95
|
+
nil
|
96
|
+
rescue StandardError, LoadError => e
|
97
|
+
e
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
m.load_bundler!
|
102
|
+
|
103
|
+
if m.invoked_as_script?
|
104
|
+
load Gem.bin_path("bundler", "bundle")
|
105
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "conssh"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/conssh
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'conssh' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("conssh", "conssh")
|
data/bin/htmldiff
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'htmldiff' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("diff-lcs", "htmldiff")
|
data/bin/ldiff
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'ldiff' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("diff-lcs", "ldiff")
|
data/bin/rake
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rake' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rake", "rake")
|
data/bin/rspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rspec' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rspec-core", "rspec")
|
data/bin/rubocop
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rubocop' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rubocop", "rubocop")
|
data/bin/ruby-parse
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'ruby-parse' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("parser", "ruby-parse")
|
data/bin/ruby-rewrite
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'ruby-rewrite' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("parser", "ruby-rewrite")
|
data/bin/setup
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
image: ruby:2.5.0
|
2
|
+
|
3
|
+
pipelines:
|
4
|
+
default:
|
5
|
+
- step:
|
6
|
+
caches:
|
7
|
+
- bundler
|
8
|
+
- pip
|
9
|
+
- pythonpackages
|
10
|
+
script:
|
11
|
+
- apt-get update
|
12
|
+
- apt-get --assume-yes install --yes python-pip
|
13
|
+
- pip install --user moto flask
|
14
|
+
- bundle install --path vendor/bundle
|
15
|
+
- MOTO_SERVER=~/.local/bin/moto_server rspec
|
16
|
+
|
17
|
+
definitions:
|
18
|
+
caches:
|
19
|
+
bundler: ./vendor
|
20
|
+
pythonpackages: ~/.local
|
data/conssh.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "conssh/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "conssh"
|
8
|
+
spec.version = Conssh::VERSION
|
9
|
+
spec.authors = ["Iain Samuel McLean Elder"]
|
10
|
+
spec.email = ["iainelder@hotmail.co.uk"]
|
11
|
+
|
12
|
+
spec.summary = %q{Configure SSH to connect to an EC2 fleet}
|
13
|
+
spec.description = <<~DESCRIPTION
|
14
|
+
Conssh is a utility to configure SSH. It generates config files with
|
15
|
+
connection information for a fleet of EC2 instances. Use it together with
|
16
|
+
an autocompletion tool that understands SSH, like bash-completion or fzf.
|
17
|
+
DESCRIPTION
|
18
|
+
spec.homepage = "https://bitbucket.org/isme/conssh"
|
19
|
+
|
20
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
21
|
+
f.match(%r{^(test|spec|features)/})
|
22
|
+
end
|
23
|
+
spec.bindir = "exe"
|
24
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
|
+
spec.require_paths = ["lib"]
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
28
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
29
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
30
|
+
|
31
|
+
spec.add_dependency "aws-sdk-ec2", "~> 1.0"
|
32
|
+
end
|
data/demo/Dockerfile
ADDED
data/demo/run.sh
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#/bin/bash
|
2
|
+
|
3
|
+
while : ; do
|
4
|
+
read -p "AWS Profile Name: " profile
|
5
|
+
if [[ "${profile}" = "" ]]; then
|
6
|
+
break
|
7
|
+
fi
|
8
|
+
aws configure --profile "${profile}"
|
9
|
+
done
|
10
|
+
|
11
|
+
read -p "Press a key to edit SSH private key."
|
12
|
+
vim ~/.ssh/id_rsa
|
13
|
+
|
14
|
+
read -p "Press a key to edit SSH public key."
|
15
|
+
vim ~/.ssh/id_rsa.pub
|
16
|
+
|
17
|
+
read -p "Press a key to edit host config."
|
18
|
+
echo "
|
19
|
+
Host <%= profile %>_<%= tags['Name'] %>_<%= instance_id %>
|
20
|
+
Hostname <%= public_dns_name %>
|
21
|
+
" > ~/.ssh/ec2_host.erb
|
22
|
+
vim ~/.ssh/ec2_host.erb
|
23
|
+
|
24
|
+
echo "Generating SSH config..."
|
25
|
+
profile_list=$(grep "\[" ~/.aws/credentials | tr -d '[]' | paste -sd ',' -)
|
26
|
+
/ec2-ssh-config-generator/generate-config.rb "${profile_list}" > ~/.ssh/config
|
27
|
+
|
28
|
+
echo "To regenerate: \`/ec2-ssh-config-generator/generate-config.rb ${profile_list} > ~/.ssh/config\`"
|
29
|
+
|
30
|
+
echo "Type 'ssh **' then TAB to start!"
|
31
|
+
|
32
|
+
bash
|
data/demo/setup.sh
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# A fresh Ubuntu image doesn't have a package list, so we need to update it
|
4
|
+
# first before any of the install commands will work.
|
5
|
+
apt-get update
|
6
|
+
|
7
|
+
# The image doesn't have a bunch of things that you will expect to be there when
|
8
|
+
# you setting up and playing around. I assume you know what these are, let's
|
9
|
+
# just get them installed!
|
10
|
+
apt-get install --yes vim less man wget git
|
11
|
+
|
12
|
+
# The image doesn't have an SSH client either, so let's install that. We will
|
13
|
+
# also quickly set up the usual files with the right permissions so that ssh
|
14
|
+
# won't complain.
|
15
|
+
apt-get install --yes openssh-client
|
16
|
+
mkdir ~/.ssh/
|
17
|
+
touch ~/.ssh/{known_hosts,config,id_rsa,id_rsa.pub}
|
18
|
+
chmod --recursive 0600 ~/.ssh/
|
19
|
+
|
20
|
+
# Installing AWS CLI is not strictly necessary, but it is the easiest way to
|
21
|
+
# configure the AWS profiles.
|
22
|
+
apt-get install --yes awscli
|
23
|
+
|
24
|
+
# Install the best autocomplete tool.
|
25
|
+
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
|
26
|
+
~/.fzf/install --all
|
27
|
+
|
28
|
+
# The config generator is a Ruby app, so we need to install it.
|
29
|
+
# The app is not packaged as a gem but installed from source, so we also have to use bundler
|
30
|
+
# to install the other Ruby dependencies.
|
31
|
+
apt-get install --yes ruby
|
32
|
+
gem install bundler
|
33
|
+
|
34
|
+
# Install the config generator.
|
35
|
+
git clone https://isme@bitbucket.org/isme/ec2-ssh-config-generator.git
|
36
|
+
cd ec2-ssh-config-generator
|
37
|
+
bundle install
|
data/exe/conssh
ADDED
data/lib/conssh.rb
ADDED
data/lib/conssh/app.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Conssh
|
2
|
+
class ConfigWriter
|
3
|
+
|
4
|
+
def initialize(args={})
|
5
|
+
@out = args[:out] || File.new('host_config', 'w+')
|
6
|
+
end
|
7
|
+
|
8
|
+
def render(inst)
|
9
|
+
first, *rest = *Array(inst)
|
10
|
+
render_one(first) if first
|
11
|
+
rest.each do |i|
|
12
|
+
@out.puts
|
13
|
+
render_one(i)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private def render_one(inst)
|
18
|
+
@out.puts("Host #{inst.id}")
|
19
|
+
@out.puts("HostName #{inst.public_ip_address}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/setup.md
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
I assume you have just one SSH keypair to access all of your EC2 instances, and you keep it locally.
|
2
|
+
|
3
|
+
I also assume you need to access instances in multiple accounts and multiple regions.
|
4
|
+
|
5
|
+
I assume you have docker installed and ready to use in your environment.
|
6
|
+
|
7
|
+
Before we start, get the all the credentials required to access the API of your AWS account and the SSH sessions of your EC2 instances.
|
8
|
+
|
9
|
+
The brackets here are just a fancy way to generate filenames with a common prefix. Saves a bit of typing.
|
10
|
+
|
11
|
+
```
|
12
|
+
less ~/.aws/credentials ~/.ssh/id_rsa{,.pub}
|
13
|
+
```
|
14
|
+
|
15
|
+
Start a new Ubuntu container.
|
16
|
+
|
17
|
+
```
|
18
|
+
docker run -it ubuntu:16.04
|
19
|
+
```
|
20
|
+
|
21
|
+
A fresh Ubuntu image doesn't have a package list, so we need to update it first before any of the install commands will work.
|
22
|
+
|
23
|
+
```
|
24
|
+
apt-get update
|
25
|
+
```
|
26
|
+
|
27
|
+
The image doesn't have a bunch of things that you will expect to be there when you setting up and playing around. I assume you know what these are, let's just get them installed!
|
28
|
+
|
29
|
+
```
|
30
|
+
apt-get install vim less man wget git
|
31
|
+
```
|
32
|
+
|
33
|
+
The bash-completion package is also expected, and deserves a special mention here because it's what makes the magic happen later when have the correct SSH config.
|
34
|
+
|
35
|
+
Change the default bindings to make the autocomplete behavior a bit nicer in bash.
|
36
|
+
|
37
|
+
To make it take effect in the existing session we have to source the global profile again.
|
38
|
+
|
39
|
+
```
|
40
|
+
apt-get install bash-completion
|
41
|
+
bind "TAB:menu-complete"
|
42
|
+
bind "set show-all-if-ambiguous on"
|
43
|
+
source /etc/profile
|
44
|
+
```
|
45
|
+
|
46
|
+
The image doesn't have an SSH client either, so let's install that.
|
47
|
+
|
48
|
+
We will also quickly set up the usual file with the right permissions so that ssh won't complain.
|
49
|
+
|
50
|
+
See way below for how to install a later version of the client that supports the Include directive.
|
51
|
+
|
52
|
+
```
|
53
|
+
apt-get install openssh-client
|
54
|
+
mkdir ~/.ssh/
|
55
|
+
touch ~/.ssh/{known_hosts,config,id_rsa,id_rsa.pub}
|
56
|
+
chmod --recursive 0600 ~/.ssh/
|
57
|
+
```
|
58
|
+
|
59
|
+
While we are here, we can configure it with our SSH keys we will use to access the instances.
|
60
|
+
|
61
|
+
```
|
62
|
+
vim ~/.ssh/id_rsa
|
63
|
+
vim ~/.ssh/id_rsa.pub
|
64
|
+
```
|
65
|
+
|
66
|
+
Installing AWS CLI is not strictly necessary, but it is the easiest way to configure the AWS profiles.
|
67
|
+
|
68
|
+
Paste access key and secret key from aws credentials.
|
69
|
+
|
70
|
+
Check it works by querying your user info.
|
71
|
+
|
72
|
+
```
|
73
|
+
apt-get install awscli
|
74
|
+
aws configure --profile staging
|
75
|
+
aws iam get-user --profile staging
|
76
|
+
aws configure --profile production
|
77
|
+
aws iam get-user --profile production
|
78
|
+
```
|
79
|
+
|
80
|
+
As ec2ssh is a Ruby gem, we first have to install Ruby so that we can use gem to install it.
|
81
|
+
|
82
|
+
It unfortunately depends on the Nokogiri gem, so we have to install a bunch of other non-Ruby stuff to make it work.
|
83
|
+
|
84
|
+
```
|
85
|
+
apt-get install ruby
|
86
|
+
apt-get install build-essential patch ruby-dev zlib1g-dev liblzma-dev
|
87
|
+
gem install ec2ssh
|
88
|
+
```
|
89
|
+
|
90
|
+
Run init and check that an empty block is created and that the default config is set up.
|
91
|
+
|
92
|
+
```
|
93
|
+
ec2ssh init
|
94
|
+
cat ~/.ssh/config
|
95
|
+
cat ~/.ec2ssh
|
96
|
+
```
|
97
|
+
|
98
|
+
In the default config you'll see sections for sets of credentials and a list of regions.
|
99
|
+
|
100
|
+
First let's set up the tool to query all regions so we are sure the list is complete.
|
101
|
+
|
102
|
+
```
|
103
|
+
aws ec2 describe-regions --region us-east-1 --query 'Regions[].RegionName' --output text
|
104
|
+
```
|
105
|
+
|
106
|
+
Paste the output of that command into the region directive (there is a commented-out example).
|
107
|
+
|
108
|
+
```
|
109
|
+
vim ~/.ec2ssh
|
110
|
+
```
|
111
|
+
|
112
|
+
The list is static, so you will have to update it when Amazon adds a new region. Thankfully here that happens relatvively infrequently.
|
113
|
+
|
114
|
+
Unfortunately the program queries each region serially, so you might have a to wait a while. It would be great to do the queries in parallel, but it probably requires modifying the program.
|
115
|
+
|
116
|
+
If you don't mind having a copy of your credentials in the ec2ssh config, then set up a staging and a production section with your keys.
|
117
|
+
|
118
|
+
Otherwise see the next section for how to generate an equivalent ssh config using just the prodi
|
119
|
+
|
120
|
+
If no credentials are set in the config, it will use whatever profile is set in the environment.
|
121
|
+
|
122
|
+
If you prefer to manage all your AWS credentials as CLI profiles, then you simulate the behavior with a few extra steps.
|
123
|
+
|
124
|
+
It would be awesome if the program was profile aware, but that probably requires modifying the program.
|
125
|
+
|
126
|
+
```
|
127
|
+
ec2ssh init --path ~/.ssh/config_staging
|
128
|
+
AWS_PROFILE=staging ec2ssh update --path ~/.ssh/config_staging
|
129
|
+
ec2ssh init --path ~/.ssh/config_production
|
130
|
+
AWS_PROFILE=production ec2ssh update --path ~/.ssh/config_production
|
131
|
+
```
|
132
|
+
|
133
|
+
As of SSH 7.3 (Mac OS X Sierra has 7.4) , you can include these compartmentalizied configrations using the new Include directive.
|
134
|
+
|
135
|
+
However, bash and zsh still don't support completion for included configs (although the feature appears to be on its way for zsh).
|
136
|
+
|
137
|
+
For now, the easiest thing is just to combine the two configs together into one file.
|
138
|
+
|
139
|
+
This also has the advantage of working with older versions of SSH that don't support the Include directive (Ubuntu Xenial has 7.2).
|
140
|
+
|
141
|
+
```
|
142
|
+
cat ~/.ssh/config_{staging,production} > ~/.ssh/config
|
143
|
+
```
|
144
|
+
|
145
|
+
Edit the config how we see fit.
|
146
|
+
|
147
|
+
```
|
148
|
+
vim ~/.ec2ssh # add public_ip_address
|
149
|
+
ec2ssh update
|
150
|
+
````
|
151
|
+
|
152
|
+
Bunch of commands to install ssh 7.4, part of ubuntu's latest stable release (Zesty Zapus) and the same version on Mac OS X.
|
153
|
+
|
154
|
+
```
|
155
|
+
wget https://launchpad.net/ubuntu/+source/openssh/1:7.4p1-10/+build/12390736/+files/openssh-client_7.4p1-10_amd64.deb
|
156
|
+
dpkg -i openssh-client_7.4p1-10_amd64.deb
|
157
|
+
wget https://launchpad.net/ubuntu/+source/openssh/1:7.4p1-10/+build/12390736/+files/ssh-krb5_7.4p1-10_all.deb
|
158
|
+
dpkg -i ssh-krb5_7.4p1-10_all.deb
|
159
|
+
wget https://launchpad.net/ubuntu/zesty/amd64/libgssapi-krb5-2/1.15-1
|
160
|
+
wget http://launchpadlibrarian.net/296470446/libgssapi-krb5-2_1.15-1_amd64.deb
|
161
|
+
dpkg -i libgssapi-krb5-2_1.15-1_amd64.deb
|
162
|
+
wget http://launchpadlibrarian.net/296470457/libkrb5support0_1.15-1_amd64.deb
|
163
|
+
dpkg -i libkrb5support0_1.15-1_amd64.deb
|
164
|
+
dpkg -i libgssapi-krb5-2_1.15-1_amd64.deb
|
165
|
+
wget http://launchpadlibrarian.net/296470455/libkrb5-3_1.15-1_amd64.deb
|
166
|
+
deb -i libkrb5-3_1.15-1_amd64.deb
|
167
|
+
dbkg -i libkrb5-3_1.15-1_amd64.deb
|
168
|
+
dpkg -i libkrb5-3_1.15-1_amd64.deb
|
169
|
+
apt-get upgrade
|
170
|
+
wget https://launchpad.net/ubuntu/+source/krb5/1.15-1/+build/11519847/+files/libk5crypto3_1.15-1_amd64.deb
|
171
|
+
dpkg -i libk5crypto3_1.15-1_amd64.deb
|
172
|
+
deb -i libkrb5-3_1.15-1_amd64.deb
|
173
|
+
dpkg -i libkrb5-3_1.15-1_amd64.deb
|
174
|
+
ls *.deb
|
175
|
+
dpkg -i openssh-client_7.4p1-10_amd64.deb
|
176
|
+
dpkg -i libgssapi-krb5-2_1.15-1_amd64.deb
|
177
|
+
dpkg -i openssh-client_7.4p1-10_amd64.deb
|
178
|
+
```
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: conssh
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Iain Samuel McLean Elder
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-03-25 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.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: aws-sdk-ec2
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.0'
|
69
|
+
description: |
|
70
|
+
Conssh is a utility to configure SSH. It generates config files with
|
71
|
+
connection information for a fleet of EC2 instances. Use it together with
|
72
|
+
an autocompletion tool that understands SSH, like bash-completion or fzf.
|
73
|
+
email:
|
74
|
+
- iainelder@hotmail.co.uk
|
75
|
+
executables:
|
76
|
+
- conssh
|
77
|
+
extensions: []
|
78
|
+
extra_rdoc_files: []
|
79
|
+
files:
|
80
|
+
- ".bundle/config"
|
81
|
+
- ".gitignore"
|
82
|
+
- ".rspec"
|
83
|
+
- ".ruby-version"
|
84
|
+
- ".travis.yml"
|
85
|
+
- Conch_drawing.jpg
|
86
|
+
- Gemfile
|
87
|
+
- README.md
|
88
|
+
- Rakefile
|
89
|
+
- bin/bundle
|
90
|
+
- bin/console
|
91
|
+
- bin/conssh
|
92
|
+
- bin/htmldiff
|
93
|
+
- bin/ldiff
|
94
|
+
- bin/rake
|
95
|
+
- bin/rspec
|
96
|
+
- bin/rubocop
|
97
|
+
- bin/ruby-parse
|
98
|
+
- bin/ruby-rewrite
|
99
|
+
- bin/setup
|
100
|
+
- bitbucket-pipelines.yml
|
101
|
+
- conssh.gemspec
|
102
|
+
- demo/Dockerfile
|
103
|
+
- demo/run.sh
|
104
|
+
- demo/setup.sh
|
105
|
+
- exe/conssh
|
106
|
+
- lib/conssh.rb
|
107
|
+
- lib/conssh/app.rb
|
108
|
+
- lib/conssh/config_writer.rb
|
109
|
+
- lib/conssh/inventory.rb
|
110
|
+
- lib/conssh/version.rb
|
111
|
+
- setup.md
|
112
|
+
homepage: https://bitbucket.org/isme/conssh
|
113
|
+
licenses: []
|
114
|
+
metadata: {}
|
115
|
+
post_install_message:
|
116
|
+
rdoc_options: []
|
117
|
+
require_paths:
|
118
|
+
- lib
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 2.7.3
|
132
|
+
signing_key:
|
133
|
+
specification_version: 4
|
134
|
+
summary: Configure SSH to connect to an EC2 fleet
|
135
|
+
test_files: []
|