Add and update tests for insecure private keys
Updates existing test coverage to use insecure private key collection and adds testing for behavior changes within the communicator and the keypair utility.
This commit is contained in:
parent
e0dbbcc04c
commit
602d42bbc8
@ -242,6 +242,10 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do
|
||||
let(:openssh){ :openssh }
|
||||
let(:private_key_file){ double("private_key_file") }
|
||||
let(:path_joiner){ double("path_joiner") }
|
||||
let(:algorithms) { double(:algorithms) }
|
||||
let(:transport) { double(:transport, algorithms: algorithms) }
|
||||
let(:valid_key_types) { [] }
|
||||
let(:server_data) { { host_key: valid_key_types} }
|
||||
|
||||
before do
|
||||
allow(Vagrant::Util::Keypair).to receive(:create).
|
||||
@ -255,6 +259,8 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do
|
||||
allow(path_joiner).to receive(:join).and_return(private_key_file)
|
||||
allow(guest).to receive(:capability).with(:insert_public_key)
|
||||
allow(guest).to receive(:capability).with(:remove_public_key)
|
||||
allow(connection).to receive(:transport).and_return(transport)
|
||||
allow(algorithms).to receive(:instance_variable_get).with(:@server_data).and_return(server_data)
|
||||
end
|
||||
|
||||
after{ communicator.ready? }
|
||||
@ -280,6 +286,53 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do
|
||||
it "should remove the default public key" do
|
||||
expect(guest).to receive(:capability).with(:remove_public_key, any_args)
|
||||
end
|
||||
|
||||
context "with server algorithm support data" do
|
||||
context "when no key type matches are found" do
|
||||
it "should default to rsa type" do
|
||||
expect(Vagrant::Util::Keypair).to receive(:create).
|
||||
with(type: :rsa).and_call_original
|
||||
end
|
||||
end
|
||||
|
||||
context "when rsa is the only match" do
|
||||
let(:valid_key_types) { ["ssh-edsca", "ssh-rsa"] }
|
||||
|
||||
it "should use rsa type" do
|
||||
expect(Vagrant::Util::Keypair).to receive(:create).
|
||||
with(type: :rsa).and_call_original
|
||||
end
|
||||
end
|
||||
|
||||
context "when ed25519 and rsa are both available" do
|
||||
let(:valid_key_types) { ["ssh-ed25519", "ssh-rsa"] }
|
||||
|
||||
it "should use ed25519 type" do
|
||||
expect(Vagrant::Util::Keypair).to receive(:create).
|
||||
with(type: :ed25519).and_call_original
|
||||
end
|
||||
end
|
||||
|
||||
context "when ed25519 is the only match" do
|
||||
let(:valid_key_types) { ["ssh-edsca", "ssh-ed25519"] }
|
||||
|
||||
it "should use ed25519 type" do
|
||||
expect(Vagrant::Util::Keypair).to receive(:create).
|
||||
with(type: :ed25519).and_call_original
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when an error is encountered getting server data" do
|
||||
before do
|
||||
expect(connection).to receive(:transport).and_raise(StandardError)
|
||||
end
|
||||
|
||||
it "should default to rsa key" do
|
||||
expect(Vagrant::Util::Keypair).to receive(:create).
|
||||
with(type: :rsa).and_call_original
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -929,6 +982,45 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do
|
||||
end
|
||||
end
|
||||
|
||||
describe ".insecure_key?" do
|
||||
let(:key_data) { "" }
|
||||
let(:key_file) {
|
||||
if !@key_file
|
||||
f = Tempfile.new
|
||||
f.write(key_data)
|
||||
f.close
|
||||
@key_file = f.path
|
||||
end
|
||||
@key_file
|
||||
}
|
||||
|
||||
after { File.delete(key_file) }
|
||||
|
||||
context "when using rsa private key" do
|
||||
let(:key_data) { File.read(Vagrant.source_root.join("keys", "vagrant.key.rsa")) }
|
||||
|
||||
it "should match as insecure key" do
|
||||
expect(communicator.send(:insecure_key?, key_file)).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context "when using ed25519 private key" do
|
||||
let(:key_data) { File.read(Vagrant.source_root.join("keys", "vagrant.key.ed25519")) }
|
||||
|
||||
it "should match as insecure key" do
|
||||
expect(communicator.send(:insecure_key?, key_file)).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context "when using unknown private key" do
|
||||
let(:key_data) { "invalid data" }
|
||||
|
||||
it "should not match as insecure key" do
|
||||
expect(communicator.send(:insecure_key?, key_file)).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe ".generate_environment_export" do
|
||||
it "should generate bourne shell compatible export" do
|
||||
expect(communicator.send(:generate_environment_export, "TEST", "value")).to eq("export TEST=\"value\"\n")
|
||||
|
||||
@ -729,7 +729,9 @@ describe Vagrant::Machine do
|
||||
provider_ssh_info[:private_key_path] = nil
|
||||
instance.config.ssh.private_key_path = nil
|
||||
|
||||
expect(ssh_klass).to receive(:check_key_permissions).once.with(Pathname.new(instance.env.default_private_key_path.to_s))
|
||||
instance.env.default_private_key_paths.each do |key_path|
|
||||
expect(ssh_klass).to receive(:check_key_permissions).once.with(Pathname.new(key_path.to_s))
|
||||
end
|
||||
instance.ssh_info
|
||||
end
|
||||
|
||||
@ -773,7 +775,7 @@ describe Vagrant::Machine do
|
||||
instance.config.ssh.private_key_path = nil
|
||||
|
||||
expect(instance.ssh_info[:private_key_path]).to eq(
|
||||
[instance.env.default_private_key_path.to_s]
|
||||
instance.env.default_private_key_paths
|
||||
)
|
||||
end
|
||||
|
||||
@ -783,7 +785,7 @@ describe Vagrant::Machine do
|
||||
instance.config.ssh.keys_only = false
|
||||
|
||||
expect(instance.ssh_info[:private_key_path]).to eq(
|
||||
[instance.env.default_private_key_path.to_s]
|
||||
instance.env.default_private_key_paths
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@ -1,34 +1,60 @@
|
||||
require "openssl"
|
||||
require "ed25519"
|
||||
require "net/ssh"
|
||||
|
||||
require File.expand_path("../../../base", __FILE__)
|
||||
|
||||
require "vagrant/util/keypair"
|
||||
|
||||
describe Vagrant::Util::Keypair do
|
||||
describe ".create" do
|
||||
it "generates a usable keypair with no password" do
|
||||
# I don't know how to validate the final return value yet...
|
||||
pubkey, privkey, _ = described_class.create
|
||||
describe Vagrant::Util::Keypair::Rsa do
|
||||
describe ".create" do
|
||||
it "generates a usable keypair with no password" do
|
||||
# I don't know how to validate the final return value yet...
|
||||
pubkey, privkey, _ = described_class.create
|
||||
|
||||
pubkey = OpenSSL::PKey::RSA.new(pubkey)
|
||||
privkey = OpenSSL::PKey::RSA.new(privkey)
|
||||
pubkey = OpenSSL::PKey::RSA.new(pubkey)
|
||||
privkey = OpenSSL::PKey::RSA.new(privkey)
|
||||
|
||||
encrypted = pubkey.public_encrypt("foo")
|
||||
decrypted = privkey.private_decrypt(encrypted)
|
||||
encrypted = pubkey.public_encrypt("foo")
|
||||
decrypted = privkey.private_decrypt(encrypted)
|
||||
|
||||
expect(decrypted).to eq("foo")
|
||||
expect(decrypted).to eq("foo")
|
||||
end
|
||||
|
||||
it "generates a keypair that requires a password" do
|
||||
pubkey, privkey, _ = described_class.create("password")
|
||||
|
||||
pubkey = OpenSSL::PKey::RSA.new(pubkey)
|
||||
privkey = OpenSSL::PKey::RSA.new(privkey, "password")
|
||||
|
||||
encrypted = pubkey.public_encrypt("foo")
|
||||
decrypted = privkey.private_decrypt(encrypted)
|
||||
|
||||
expect(decrypted).to eq("foo")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "generates a keypair that requires a password" do
|
||||
pubkey, privkey, _ = described_class.create("password")
|
||||
describe Vagrant::Util::Keypair::Ed25519 do
|
||||
describe ".create" do
|
||||
it "generates a usable keypair with no password" do
|
||||
pubkey, ossh_privkey, _ = described_class.create
|
||||
|
||||
pubkey = OpenSSL::PKey::RSA.new(pubkey)
|
||||
privkey = OpenSSL::PKey::RSA.new(privkey, "password")
|
||||
|
||||
encrypted = pubkey.public_encrypt("foo")
|
||||
decrypted = privkey.private_decrypt(encrypted)
|
||||
privkey = Net::SSH::Authentication::ED25519::PrivKey.read(ossh_privkey, "").sign_key
|
||||
pubkey = Ed25519::VerifyKey.new(pubkey)
|
||||
|
||||
expect(decrypted).to eq("foo")
|
||||
message = "vagrant test"
|
||||
signature = privkey.sign(message)
|
||||
expect(pubkey.verify(signature, message)).to be_truthy
|
||||
end
|
||||
|
||||
it "does not generate a keypair that requires a password" do
|
||||
expect {
|
||||
described_class.create("my password")
|
||||
}.to raise_error(NotImplementedError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user