Skip to content
This repository has been archived by the owner on Feb 11, 2022. It is now read-only.

ISSUE #423: Support using EC2-generated password as the WinRM password #433

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,41 @@ Vagrant.configure("2") do |config|
end
```

### Windows WinRM passwords

Want to use the EC2-generated Administrator password as the WinRM password for your Windows images? Use `:aws` as the WinRM password, and it will be fetched and decrypted using your private key.

```ruby
Vagrant.configure("2") do |config|
# ... other stuff

config.vm.communicator = "winrm"
config.winrm.username = "Administrator"

config.vm.provider "aws" do |aws, override|
# Indicate that the password should be fetched and decrypted from AWS
override.winrm.password = :aws

# private_key_path needed to decrypt the password
override.ssh.private_key_path = '~/mykey.pem'

# keypair name corresponding to private_key_path
aws.keypair_name = "mykey"

# Use a security group that allows WinRM port inbound (port 5985)
aws.security_groups = ['some_security_group_that_allows_winrm_inbound']

# Enable WinRM on the instance
aws.user_data = <<-USERDATA
<powershell>
Enable-PSRemoting -Force
netsh advfirewall firewall add rule name="WinRM HTTP" dir=in localport=5985 protocol=TCP action=allow
</powershell>
USERDATA
end
end
```

## Development

To work on the `vagrant-aws` plugin, clone this repository out, and use
Expand Down
9 changes: 9 additions & 0 deletions lib/vagrant-aws/action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ def self.action_reload
end
end

def self.action_get_winrm_password
Vagrant::Action::Builder.new.tap do |b|
b.use ConfigValidate
b.use ConnectAWS
b.use GetWinRMPassword
end
end

# The autoload farm
action_root = Pathname.new(File.expand_path("../action", __FILE__))
autoload :ConnectAWS, action_root.join("connect_aws")
Expand All @@ -204,6 +212,7 @@ def self.action_reload
autoload :WarnNetworks, action_root.join("warn_networks")
autoload :ElbRegisterInstance, action_root.join("elb_register_instance")
autoload :ElbDeregisterInstance, action_root.join("elb_deregister_instance")
autoload :GetWinRMPassword, action_root.join("get_winrm_password")
end
end
end
54 changes: 54 additions & 0 deletions lib/vagrant-aws/action/get_winrm_password.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
require "fog"
require "log4r"

module VagrantPlugins
module AWS
module Action
# This action connects to AWS, verifies credentials work, and
# puts the AWS connection object into the `:aws_compute` key
# in the environment.
class GetWinRMPassword
def initialize(app, env)
@app = app
@logger = Log4r::Logger.new("vagrant_aws::action::get_winrm_password")
end

def call(env)
machine = env[:machine]

if machine.config.winrm.password == :aws && machine.config.ssh.private_key_path
machine.ui.info(I18n.t("vagrant_aws.getting_winrm_password"))

aws = env[:aws_compute]
response = aws.get_password_data(machine.id)
password_data = response.body['passwordData']

if password_data
password_data_bytes = Base64.decode64(password_data)

# Try to decrypt the password data using each one of the private key files
# set by the user until we hit one that decrypts successfully
machine.config.ssh.private_key_path.each do |private_key_path|
private_key_path = File.expand_path private_key_path

@logger.info("Decrypting password data using #{private_key_path}")
rsa = OpenSSL::PKey::RSA.new File.read private_key_path
begin
machine.config.winrm.password = rsa.private_decrypt password_data_bytes
@logger.info("Successfully decrypted password data using #{private_key_path}")
rescue OpenSSL::PKey::RSAError
@logger.warn("Failed to decrypt password data using #{private_key_path}")
next
end

break
end
end
end

@app.call(env)
end
end
end
end
end
14 changes: 14 additions & 0 deletions lib/vagrant-aws/capability.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require "vagrant/action/builder"

module VagrantPlugins
module AWS
module Capability
class WinRMInfo
def self.winrm_info(machine)
machine.action("get_winrm_password")
return {}
end
end
end
end
end
7 changes: 7 additions & 0 deletions lib/vagrant-aws/plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ class Plugin < Vagrant.plugin("2")
Provider
end

provider_capability(:aws, :winrm_info) do
setup_logging

require_relative 'capability'
Capability::WinRMInfo
end

# This initializes the internationalization strings.
def self.setup_i18n
I18n.load_path << File.expand_path("locales/en.yml", AWS.source_root)
Expand Down
2 changes: 2 additions & 0 deletions locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ en:
will_not_destroy: |-
The instance '%{name}' will not be destroyed, since the confirmation
was declined.
getting_winrm_password: |-
Getting WinRM password from AWS...

config:
access_key_id_required: |-
Expand Down