vagrant-rekey-ssh 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 ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ N2NjY2FkMjVlYTI1Zjg0N2M1OTE0OWQ4M2I5NzA1YTYyMDAxMzVlZQ==
5
+ data.tar.gz: !binary |-
6
+ NzlhNmIxMGFjZTcwZDAzNDI4MjJkOWJiMTdhZGUyNjZiYTI0ZDgxYw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NDJiNjc4MjAzMjEyMjgzMGI3MjBiZDFlOWZmNGQzM2UwNzcyOGVkMWUxOTQ2
10
+ ZmY3MzUzNTVmYjIzNDVlM2ZmODM5MmMyMjg4NzdhZTY2ZWMzN2IzOTMzNDcw
11
+ MWZlOWI3ZjBhNTc5ODVjYWQ3MDRkN2Q5ZjQxYTQ4YWM1ZmFhMTg=
12
+ data.tar.gz: !binary |-
13
+ YTk1ZTI3MTRjOTViM2ZjNWUyZGI1Y2UwMDEwYjRhMTJhMGE0NWUxM2ZjN2Nh
14
+ Y2Y4ZTE1MTcwNDA5MzEwNTA2MzgwZmNiMTZjOTNlMzhlMTJiMDgzMTY2MmU3
15
+ NDU5NWFhMWU2YWZjYmY3N2NhNGIyYjAzZDIwMTNhZjFjMjEwODQ=
data/.gitignore ADDED
@@ -0,0 +1,18 @@
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
18
+ Vagrantfile
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in vagrant-rekey-ssh.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ # We depend on Vagrant for development, but we don't add it as a
8
+ # gem dependency because we expect to be installed within the
9
+ # Vagrant environment itself using `vagrant plugin`.
10
+ gem "vagrant", :git => "https://github.com/mitchellh/vagrant.git"
11
+ end
12
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Avishai Ish-Shalom
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,123 @@
1
+ vagrant-rekey-ssh
2
+ =================
3
+
4
+ This is a [vagrant](http://vagrantup.com) plugin that will make your vagrant
5
+ boxes a bit more secure than they currently are.
6
+
7
+ Rationale
8
+ ---------
9
+
10
+ All Vagrant boxes come with the same ssh key and passwords installed. This
11
+ means anyone who can ssh into your VM, will be able to authenticate to it
12
+ if they try the vagrant default credentials. Additionally, vagrant boxes
13
+ come with passwordless sudo privileges, so anyone able to SSH into your
14
+ box will be able to do whatever they want on it.
15
+
16
+ As of Vagrant 1.2.3, for the most part this doesn't matter, because you can
17
+ only access the Vagrant VM from localhost (previous versions allowed access
18
+ from any machine on your local network). However, this becomes *extremely*
19
+ important if you are using a vagrant box that is on a bridged network. If
20
+ your VM is on a bridged network, without other controls in place that means
21
+ *anyone* who has access to your local network can SSH into your VM and get
22
+ root access on it. There are plenty of documented ways of breaking out of a
23
+ VM, so this is clearly a problem that needs to be addressed.
24
+
25
+ Ideally, Vagrant would have something built into it to solve the problem.
26
+ Since that isn't currently the case, I've created this plugin to help.
27
+
28
+ This solution
29
+ -------------
30
+
31
+ The first time that this plugin is ran, it generates a unique SSH key and
32
+ stores it as `~/vagrant.d/less_insecure_private_key`. Whenever you run the
33
+ `vagrant provision` command, this plugin will run a script to check the
34
+ authorized keys for the vagrant user to determine if the insecure key
35
+ public key is present. If it is present, it will replace the key with the
36
+ public key for the generated public key.
37
+
38
+ Additionally, if the insecure public key is present, it will delete the
39
+ passwords for root and vagrant, so that you cannot login using a password.
40
+
41
+ Whenever vagrant tries to SSH into a box using an SSH key, this plugin will
42
+ add the generated SSH key to the list of keys it tries. This ensures that
43
+ you will still be able to SSH into boxes that have the insecure key installed.
44
+
45
+ Installation
46
+ ------------
47
+
48
+ vagrant plugin install vagrant-rekey-ssh
49
+
50
+ Usage
51
+ -----
52
+
53
+ Just install the plugin. It will do its magic automatically when you provision
54
+ a box.
55
+
56
+ To secure already running VMs, you will need to run `vagrant provision` on
57
+ them.
58
+
59
+ Settings
60
+ --------
61
+
62
+ You can set these settings in an individual Vagrantfile, or you can specify
63
+ this in your global Vagrantfile (~/.vagrant.d/Vagrantfile)
64
+
65
+ * `config.rekey_ssh.enable` - Enables or disables the plugin. Default: enabled
66
+
67
+
68
+ Compatibility
69
+ -------------
70
+
71
+ I've only tested this on Vagrant 1.3.5 using the Virtualbox provider on Ubuntu
72
+ and OSX. Let me know if it works on earlier versions of Vagrant, and I'll put
73
+ that here.
74
+
75
+ Known Issues
76
+ ------------
77
+
78
+ This isn't going to work on a Vagrant VM that is running a non-unix operating
79
+ system.
80
+
81
+ I haven't figured out a generic way to override a machine's configuration
82
+ without hooking specific actions, which results in the following bugs that
83
+ I am aware of:
84
+
85
+ * The ssh-config command does not include the correct keys
86
+ * May not work with commands that are not built in to vagrant
87
+
88
+ If you can figure out a good way to fix these, please submit a pull request.
89
+
90
+ Contributing new changes
91
+ ========================
92
+
93
+ 1. Fork this repository
94
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
95
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
96
+ 4. Push to the branch (`git push origin my-new-feature`)
97
+ 5. Create new Pull Request
98
+
99
+ Development
100
+ ===========
101
+
102
+ To work on the `vagrant-rekey-ssh` plugin, clone this repository out, and use
103
+ [Bundler](http://gembundler.com) to get the dependencies:
104
+
105
+ $ bundle
106
+
107
+ You can test the plugin without installing it into your Vagrant environment
108
+ by just creating a `Vagrantfile` in the top level of this directory (it is
109
+ gitignored) that uses it, and uses bundler to execute Vagrant:
110
+
111
+ $ bundle exec vagrant WHATEVER
112
+
113
+ Credits
114
+ =======
115
+
116
+ Since I'm not really a ruby programmer, a lot of the skeleton of this plugin
117
+ came from other Vagrant plugins, particularly `vagrant-ohai` and
118
+ `vagrant-openstack-plugin`.
119
+
120
+ Author
121
+ ======
122
+
123
+ Author:: Dustin Spicuzza (dustin@virtualroadside.com)
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,27 @@
1
+ require "pathname"
2
+ require 'vagrant-rekey-ssh/plugin'
3
+
4
+ module VagrantPlugins
5
+ module RekeySSH
6
+ lib_path = Pathname.new(File.expand_path("../vagrant-rekey-ssh", __FILE__))
7
+ autoload :Errors, lib_path.join("errors")
8
+
9
+ # This initializes the i18n load path so that the plugin-specific
10
+ # translations work.
11
+ def self.init_i18n
12
+ I18n.load_path << File.expand_path("locales/en.yml", source_root)
13
+ I18n.reload!
14
+ end
15
+
16
+ # This returns the path to the source of this plugin.
17
+ #
18
+ # @return [Pathname]
19
+ def self.source_root
20
+ @source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
21
+ end
22
+ end
23
+ end
24
+
25
+ if defined?(Vagrant)
26
+ VagrantPlugins::RekeySSH.init_i18n()
27
+ end
@@ -0,0 +1,59 @@
1
+
2
+ require "vagrant-rekey-ssh/helpers"
3
+
4
+ module VagrantPlugins
5
+ module RekeySSH
6
+ class ActionSecureBox
7
+
8
+ def initialize(app, env)
9
+ @app = app
10
+ @env = env
11
+ @machine = env[:machine]
12
+ @vagrant_insecure_public_key = "AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ=="
13
+ end
14
+
15
+ def call(env)
16
+ @app.call(env)
17
+ return unless @machine.communicate.ready?
18
+
19
+ if @machine.config.rekey_ssh.enable
20
+
21
+ generate_ssh_key
22
+
23
+ key = ssh_public_key()
24
+ unless key.length > 0
25
+ raise Errors::ErrorInvalidGeneratedSshKey
26
+ end
27
+
28
+ # remove the vagrant insecure public key
29
+ cmd = "grep #{@vagrant_insecure_public_key} ~/.ssh/authorized_keys|| exit 1"
30
+ cmd += ";sed -i 's/^.*#{@vagrant_insecure_public_key}.*$/#{key.gsub("/","\\/")} vagrant less insecure private key/' ~/.ssh/authorized_keys || exit 2"
31
+ cmd += ";exit 3"
32
+
33
+ result = @machine.communicate.execute(cmd, sudo: false, error_check: false)
34
+
35
+ if result == 1
36
+ @machine.ui.info(I18n.t("vagrant_rekey_ssh.info.no_key"))
37
+ elsif result == 2
38
+ raise Errors::ErrorReplacingInsecureKey
39
+ elsif result == 3
40
+ @machine.ui.info(I18n.t("vagrant_rekey_ssh.info.key_replaced"))
41
+
42
+ # if the insecure key *was* there, disable the user's and root's password too
43
+ # -> this prevents the user from logging in using 'vagrant'
44
+ # -> we only do this if the insecure key was found, because if it
45
+ # wasn't then perhaps it's a custom box and we shouldn't mess with it
46
+ @machine.communicate.execute("sudo passwd --delete $USER; sudo passwd --delete root", sudo: false)
47
+
48
+ end
49
+
50
+ end
51
+ end
52
+
53
+ protected
54
+
55
+ include VagrantPlugins::RekeySSH::Helpers
56
+
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,43 @@
1
+
2
+ require 'vagrant/util/subprocess'
3
+ require "vagrant-rekey-ssh/helpers"
4
+
5
+ module VagrantPlugins
6
+ module RekeySSH
7
+ class ActionSSHInfo
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @env = env
12
+ @machine = env[:machine]
13
+ end
14
+
15
+ def call(env)
16
+
17
+ if @machine.config.rekey_ssh.enable
18
+
19
+ # ensure we have a key
20
+ generate_ssh_key
21
+
22
+ # if the user's config hasn't specified a key, then set our key
23
+ # in here. We also specify the insecure key too so that it works
24
+ # in case we haven't replaced the key yet.
25
+ # -> TODO: only specify the insecure key when we haven't set the
26
+ # less insecure key on the box.
27
+ if @machine.config.ssh.private_key_path.nil?
28
+ @machine.config.ssh.private_key_path = [ssh_key_path, @machine.env.default_private_key_path]
29
+ end
30
+
31
+ end
32
+
33
+ @app.call(env)
34
+
35
+ end
36
+
37
+ protected
38
+
39
+ include VagrantPlugins::RekeySSH::Helpers
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,24 @@
1
+ module VagrantPlugins
2
+ module RekeySSH
3
+ class Config < Vagrant.plugin(2, :config)
4
+ attr_accessor :enable
5
+
6
+ def initialize
7
+ @enable = UNSET_VALUE
8
+ end
9
+ def finalize!
10
+ @enable = true if @enable == UNSET_VALUE
11
+ end
12
+
13
+ def validate(machine)
14
+ case @enable
15
+ when TrueClass, FalseClass
16
+ {}
17
+ else
18
+ {"enable" => [I18n.t("vagrant_rekey_ssh.config.enable")] }
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module RekeySSH
5
+ module Errors
6
+ class VagrantRekeySSHError < Vagrant::Errors::VagrantError
7
+ error_namespace("vagrant_rekey_ssh.errors")
8
+ end
9
+
10
+ class ErrorSshKeygenNotFound < VagrantRekeySSHError
11
+ error_key(:ssh_keygen_not_found)
12
+ end
13
+
14
+ class ErrorCreatingSshKey < VagrantRekeySSHError
15
+ error_key(:creating_ssh_key)
16
+ end
17
+
18
+ class ErrorInvalidGeneratedSshKey < VagrantRekeySSHError
19
+ error_key(:invalid_generated_ssh_key)
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,36 @@
1
+
2
+ module VagrantPlugins
3
+ module RekeySSH
4
+ module Helpers
5
+
6
+ def generate_ssh_key
7
+ unless ::File.exists?(ssh_key_path)
8
+
9
+ @machine.ui.info(I18n.t("vagrant_rekey_ssh.info.generating_key"))
10
+
11
+ result = Vagrant::Util::Subprocess.execute("ssh-keygen", "-f", ssh_key_path, "-N", "")
12
+
13
+ if result.exit_code != 0
14
+ raise Errors::ErrorCreatingSshKey, exit_code: result.exit_code
15
+ end
16
+
17
+ @machine.ui.info(I18n.t("vagrant_rekey_ssh.info.key_generated", :path => ssh_key_path))
18
+
19
+ end
20
+ end
21
+
22
+ def ssh_public_key
23
+ IO.read(ssh_pubkey_path).scan( /^(\S+\s+\S+).*$/ ).last.first
24
+ end
25
+
26
+ def ssh_key_path
27
+ ::File.join(@env[:home_path], "less_insecure_private_key")
28
+ end
29
+
30
+ def ssh_pubkey_path
31
+ ::File.join(@env[:home_path], "less_insecure_private_key.pub")
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ require "vagrant-rekey-ssh/version"
2
+ require "vagrant/plugin"
3
+
4
+ module VagrantPlugins
5
+ module RekeySSH
6
+ class Plugin < Vagrant.plugin("2")
7
+ name "vagrant-rekey-ssh"
8
+ description <<-DESC
9
+ Automatically secure vagrant boxes with a randomly generated SSH key
10
+ DESC
11
+
12
+ #
13
+ # what I really want to do is wrap the virtualbox provider somehow so we
14
+ # can modify the machine configuration. This is good enough for now..
15
+ #
16
+
17
+ require_relative 'actions/secure_box'
18
+ require_relative 'actions/ssh_info'
19
+
20
+ %w{halt provision reload ssh ssh_run ssh_config up}.each do |action|
21
+ action_hook(:rekey_ssh, "machine_action_#{action}".to_sym) do |hook|
22
+
23
+ hook.before(Vagrant::Action::Builtin::ConfigValidate, ActionSSHInfo)
24
+ hook.before(Vagrant::Action::Builtin::GracefulHalt, ActionSSHInfo)
25
+ hook.before(Vagrant::Action::Builtin::SSHExec, ActionSSHInfo)
26
+
27
+ hook.after(Vagrant::Action::Builtin::Provision, ActionSecureBox)
28
+ end
29
+ end
30
+
31
+ config(:rekey_ssh) do
32
+ require_relative "config"
33
+ Config
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module RekeySSH
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,22 @@
1
+ ---
2
+ en:
3
+ vagrant_rekey_ssh:
4
+ config:
5
+ enable: |-
6
+ Enable must be true or false
7
+
8
+ info:
9
+ generating_key: |-
10
+ Less insecure SSH key not found, generating key
11
+ key_generated: |-
12
+ Less insecure SSH key generated and stored at %{path}
13
+ key_replaced: |-
14
+ Replaced insecure vagrant key with less insecure key!
15
+ no_key: |-
16
+ Insecure vagrant key not present.
17
+
18
+ errors:
19
+ creating_ssh_key: |-
20
+ Error occurred when creating the ssh key (ssh-keygen returned %{exit_code})
21
+ invalid_generated_ssh_key: |-
22
+ Generated SSH key was not in an expected format! Perhaps it was corrupted?
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'vagrant-rekey-ssh/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "vagrant-rekey-ssh"
8
+ spec.version = VagrantPlugins::RekeySSH::VERSION
9
+ spec.authors = ["Dustin Spicuzza"]
10
+ spec.email = ["dustin@virtualroadside.com"]
11
+ spec.description = "Automatically secure vagrant boxes with a randomly generated SSH key"
12
+ spec.summary = "Automatically secure vagrant boxes with a randomly generated SSH key"
13
+ spec.homepage = "https://github.com/virtuald/vagrant-rekey-ssh.git"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-rekey-ssh
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dustin Spicuzza
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-09 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.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Automatically secure vagrant boxes with a randomly generated SSH key
42
+ email:
43
+ - dustin@virtualroadside.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - lib/vagrant-rekey-ssh.rb
54
+ - lib/vagrant-rekey-ssh/actions/secure_box.rb
55
+ - lib/vagrant-rekey-ssh/actions/ssh_info.rb
56
+ - lib/vagrant-rekey-ssh/config.rb
57
+ - lib/vagrant-rekey-ssh/errors.rb
58
+ - lib/vagrant-rekey-ssh/helpers.rb
59
+ - lib/vagrant-rekey-ssh/plugin.rb
60
+ - lib/vagrant-rekey-ssh/version.rb
61
+ - locales/en.yml
62
+ - vagrant-rekey-ssh.gemspec
63
+ homepage: https://github.com/virtuald/vagrant-rekey-ssh.git
64
+ licenses:
65
+ - MIT
66
+ metadata: {}
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 2.1.10
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: Automatically secure vagrant boxes with a randomly generated SSH key
87
+ test_files: []