From f4e7f5789761128cafd3269b0f59870f18acf862 Mon Sep 17 00:00:00 2001 From: Kapil Chouhan Date: Thu, 29 Aug 2019 17:02:39 +0530 Subject: [PATCH] Fix for MSYS-447 Generate temporary keypair when none is supplied Signed-off-by: Kapil Chouhan --- lib/chef/knife/ec2_server_create.rb | 19 +++++++++++++ spec/unit/ec2_server_create_spec.rb | 41 +++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/lib/chef/knife/ec2_server_create.rb b/lib/chef/knife/ec2_server_create.rb index b122e286..25c07b12 100644 --- a/lib/chef/knife/ec2_server_create.rb +++ b/lib/chef/knife/ec2_server_create.rb @@ -586,6 +586,7 @@ def plugin_validate_options! Chef::Config[:knife].delete(:aws_ssh_key_id) ui.warn("Use of aws_ssh_key_id option in knife.rb/config.rb config is deprecated, use ssh_key_name option instead.") end + create_key_pair unless config_value(:ssh_key_name) validate_aws_config!(%i{image ssh_key_name aws_access_key_id aws_secret_access_key}) @@ -1180,6 +1181,24 @@ def create_volume_tags(hashed_volume_tags) end end + def create_key_pair + key_name = "#{config[:connection_user]}-#{SecureRandom.hex(10)}" + key_pair = ec2_connection.create_key_pair({ + key_name: key_name, + }) + + save_keypair_file(key_pair) if key_pair + end + + def save_keypair_file(key_pair) + file_path = File.join(Config.config_dir, "#{key_pair.key_name}.pem") + file = File.open(file_path, "w+") { |f| f << key_pair.key_material } + + Chef::Config[:knife][:ssh_key_name] = key_pair.key_name + Chef::Config[:knife][:ssh_identity_file] = file.path + puts "\nGenerated keypair file: #{file.path}" + end + def associate_address(elastic_ip) ec2_connection.associate_address({ allocation_id: elastic_ip.allocation_id, diff --git a/spec/unit/ec2_server_create_spec.rb b/spec/unit/ec2_server_create_spec.rb index 7e643cd3..9f653f27 100644 --- a/spec/unit/ec2_server_create_spec.rb +++ b/spec/unit/ec2_server_create_spec.rb @@ -599,6 +599,47 @@ end end + describe "ssh_key_name option" do + before do + allow(knife_ec2_create).to receive(:ami).and_return(ami) + allow(knife_ec2_create).to receive(:validate_aws_config!) + allow(knife_ec2_create).to receive(:validate_nics!) + end + + context "when ssh_key_name option is not passed on the CLI" do + let(:keypair) do + Aws::EC2::Types::KeyPair.new( + key_fingerprint: "a9:00:ec:1d:bd:80:ae:00", + key_material: "test private key", + key_name: "ubuntu-07f692a0d8d1fcc4a086" + ) + end + let(:file_path) { "/root/.chef/#{keypair.key_name}.pem" } + let(:file_like_object) { double(path: file_path) } + + before do + knife_ec2_create.config[:connection_user] = "ubuntu" + Chef::Config[:knife].delete(:ssh_key_name) + allow(File).to receive(:open).with(file_path, "w+").and_return(file_like_object) + end + + it "should be call create_key_pair method and Generate new keypair" do + expect(ec2_connection).to receive(:create_key_pair).and_return(keypair) + knife_ec2_create.plugin_validate_options! + expect(Chef::Config[:knife][:ssh_key_name]).to eq(keypair.key_name) + expect(Chef::Config[:knife][:ssh_identity_file]).to eq(file_path) + end + end + + context "when ssh_key_name option is passed on the CLI" do + it "should not be call create_key_pair method" do + expect(ec2_connection).not_to receive(:create_key_pair) + knife_ec2_create.plugin_validate_options! + expect(Chef::Config[:knife][:ssh_key_name]).to eq("ssh_key_name") + end + end + end + describe "when configuring the bootstrap process" do before do allow(knife_ec2_create).to receive(:ami).and_return(ami)