vagrant-rekey-ssh 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []