Enable deprecated key type and host key algorithm

Recent versions of OpenSSH remove support of ssh-rsa key types and host
key algorithms from the default conection configuration. Set options to
enable them and provide a configuration option which can disable them if
required.
This commit is contained in:
Chris Roberts 2023-05-22 17:09:47 -07:00
parent 2092df529a
commit 0a20379b1a
7 changed files with 165 additions and 10 deletions

View File

@ -146,6 +146,13 @@ module Vagrant
"-o", "UserKnownHostsFile=/dev/null"] "-o", "UserKnownHostsFile=/dev/null"]
end end
if !ssh_info[:disable_deprecated_algorithms]
command_options += [
"-o", "PubkeyAcceptedKeyTypes=+ssh-rsa",
"-o", "HostKeyAlgorithms=+ssh-rsa",
]
end
# If we're not in plain mode and :private_key_path is set attach the private key path(s). # If we're not in plain mode and :private_key_path is set attach the private key path(s).
if !plain_mode && options[:private_key_path] if !plain_mode && options[:private_key_path]
options[:private_key_path].each do |path| options[:private_key_path].each do |path|

View File

@ -55,7 +55,8 @@ module VagrantPlugins
proxy_command: ssh_info[:proxy_command], proxy_command: ssh_info[:proxy_command],
ssh_command: ssh_info[:ssh_command], ssh_command: ssh_info[:ssh_command],
forward_env: ssh_info[:forward_env], forward_env: ssh_info[:forward_env],
config: ssh_info[:config] config: ssh_info[:config],
disable_deprecated_algorithms: ssh_info[:disable_deprecated_algorithms]
} }
# Render the template and output directly to STDOUT # Render the template and output directly to STDOUT

View File

@ -18,6 +18,7 @@ module VagrantPlugins
attr_accessor :dsa_authentication attr_accessor :dsa_authentication
attr_accessor :extra_args attr_accessor :extra_args
attr_accessor :remote_user attr_accessor :remote_user
attr_accessor :disable_deprecated_algorithms
def initialize def initialize
@host = UNSET_VALUE @host = UNSET_VALUE
@ -35,6 +36,7 @@ module VagrantPlugins
@dsa_authentication = UNSET_VALUE @dsa_authentication = UNSET_VALUE
@extra_args = UNSET_VALUE @extra_args = UNSET_VALUE
@remote_user = UNSET_VALUE @remote_user = UNSET_VALUE
@disable_deprecated_algorithms = UNSET_VALUE
end end
def finalize! def finalize!
@ -51,6 +53,7 @@ module VagrantPlugins
@dsa_authentication = true if @dsa_authentication == UNSET_VALUE @dsa_authentication = true if @dsa_authentication == UNSET_VALUE
@extra_args = nil if @extra_args == UNSET_VALUE @extra_args = nil if @extra_args == UNSET_VALUE
@config = nil if @config == UNSET_VALUE @config = nil if @config == UNSET_VALUE
@disable_deprecated_algorithms = false if @disable_deprecated_algorithms == UNSET_VALUE
@connect_timeout = DEFAULT_SSH_CONNECT_TIMEOUT if @connect_timeout == UNSET_VALUE @connect_timeout = DEFAULT_SSH_CONNECT_TIMEOUT if @connect_timeout == UNSET_VALUE
if @private_key_path && !@private_key_path.is_a?(Array) if @private_key_path && !@private_key_path.is_a?(Array)

View File

@ -36,3 +36,7 @@ Host <%= host_key %>
<% if proxy_command -%> <% if proxy_command -%>
ProxyCommand <%= proxy_command %> ProxyCommand <%= proxy_command %>
<% end -%> <% end -%>
<% if !disable_deprecated_algorithms -%>
PubkeyAcceptedKeyTypes +ssh-rsa
HostKeyAlgorithms +ssh-rsa
<% end -%>

View File

@ -56,6 +56,8 @@ Host #{machine.name}
IdentityFile /home/vagrant/.private/keys.key IdentityFile /home/vagrant/.private/keys.key
IdentitiesOnly yes IdentitiesOnly yes
LogLevel FATAL LogLevel FATAL
PubkeyAcceptedKeyTypes +ssh-rsa
HostKeyAlgorithms +ssh-rsa
SSHCONFIG SSHCONFIG
end end
@ -178,5 +180,31 @@ Host #{machine.name}
expect(output).to include("Include /custom/ssh/config") expect(output).to include("Include /custom/ssh/config")
end end
it "includes enabling ssh-rsa key types and host algorithms" do
output = ""
allow(subject).to receive(:safe_puts) do |data|
output += data if data
end
subject.execute
expect(output).to include("PubkeyAcceptedKeyTypes +ssh-rsa")
expect(output).to include("HostKeyAlgorithms +ssh-rsa")
end
it "does not enable ssh-rsa key types and host algorithms when disabled" do
allow(machine).to receive(:ssh_info) { ssh_info.merge(disable_deprecated_algorithms: true) }
output = ""
allow(subject).to receive(:safe_puts) do |data|
output += data if data
end
subject.execute
expect(output).not_to include("PubkeyAcceptedKeyTypes +ssh-rsa")
expect(output).not_to include("HostKeyAlgorithms +ssh-rsa")
end
end end
end end

View File

@ -87,7 +87,55 @@ describe Vagrant::Util::SSH do
expect(described_class.exec(ssh_info)).to eq(nil) expect(described_class.exec(ssh_info)).to eq(nil)
expect(Vagrant::Util::SafeExec).to have_received(:exec) expect(Vagrant::Util::SafeExec).to have_received(:exec)
.with(ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL","-o", "Compression=yes", "-o", "DSAAuthentication=yes", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-i", ssh_info[:private_key_path][0]) .with(
ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL",
"-o", "Compression=yes",
"-o", "DSAAuthentication=yes",
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "PubkeyAcceptedKeyTypes=+ssh-rsa",
"-o", "HostKeyAlgorithms=+ssh-rsa",
"-i", ssh_info[:private_key_path][0],
)
end
context "when deprecated algorithms are disabled" do
let(:ssh_info) {{
host: "localhost",
port: 2222,
username: "vagrant",
disable_deprecated_algorithms: true,
}}
it "does not include options to enable ssh-rsa key types and host key algorithms" do
expect(Vagrant::Util::SafeExec).to receive(:exec) do |*args|
args.each do |arg|
expect(arg).not_to eq("PubkeyAcceptedKeyTypes=+ssh-rsa")
expect(arg).not_to eq("HostKeyAlgorithms=+ssh-rsa")
end
end
described_class.exec(ssh_info)
end
end
context "when deprecated algorithms are not disabled" do
let(:ssh_info) {{
host: "localhost",
port: 2222,
username: "vagrant",
}}
it "includes options to enable ssh-rsa key types and host key algorithms" do
expect(Vagrant::Util::SafeExec).to receive(:exec) do |*args|
expect(
args.any? { |arg| arg == "PubkeyAcceptedKeyTypes=+ssh-rsa" }
).to be_truthy
expect(
args.any? { |arg| arg == "HostKeyAlgorithms=+ssh-rsa" }
).to be_truthy
end
described_class.exec(ssh_info)
end
end end
context "when using '%' in a private_key_path" do context "when using '%' in a private_key_path" do
@ -106,7 +154,16 @@ describe Vagrant::Util::SSH do
described_class.exec(ssh_info) described_class.exec(ssh_info)
expect(Vagrant::Util::SafeExec).to have_received(:exec) expect(Vagrant::Util::SafeExec).to have_received(:exec)
.with(ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL","-o", "Compression=yes", "-o", "DSAAuthentication=yes", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-o", "IdentityFile=\"/tmp/percent%%folder\"") .with(
ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL",
"-o", "Compression=yes",
"-o", "DSAAuthentication=yes",
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "PubkeyAcceptedKeyTypes=+ssh-rsa",
"-o", "HostKeyAlgorithms=+ssh-rsa",
"-o", "IdentityFile=\"/tmp/percent%%folder\"",
)
end end
end end
@ -125,7 +182,14 @@ describe Vagrant::Util::SSH do
expect(described_class.exec(ssh_info)).to eq(nil) expect(described_class.exec(ssh_info)).to eq(nil)
expect(Vagrant::Util::SafeExec).to have_received(:exec) expect(Vagrant::Util::SafeExec).to have_received(:exec)
.with(ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-i", ssh_info[:private_key_path][0]) .with(
ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL",
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "PubkeyAcceptedKeyTypes=+ssh-rsa",
"-o", "HostKeyAlgorithms=+ssh-rsa",
"-i", ssh_info[:private_key_path][0],
)
end end
end end
@ -143,7 +207,12 @@ describe Vagrant::Util::SSH do
expect(described_class.exec(ssh_info)).to eq(nil) expect(described_class.exec(ssh_info)).to eq(nil)
expect(Vagrant::Util::SafeExec).to have_received(:exec) expect(Vagrant::Util::SafeExec).to have_received(:exec)
.with(ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL", "-i", ssh_info[:private_key_path][0]) .with(
ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL",
"-o", "PubkeyAcceptedKeyTypes=+ssh-rsa",
"-o", "HostKeyAlgorithms=+ssh-rsa",
"-i", ssh_info[:private_key_path][0],
)
end end
end end
@ -162,7 +231,13 @@ describe Vagrant::Util::SSH do
expect(described_class.exec(ssh_info, {plain_mode: true})).to eq(nil) expect(described_class.exec(ssh_info, {plain_mode: true})).to eq(nil)
expect(Vagrant::Util::SafeExec).to have_received(:exec) expect(Vagrant::Util::SafeExec).to have_received(:exec)
.with(ssh_path, "localhost", "-p", "2222", "-o", "LogLevel=FATAL", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null") .with(
ssh_path, "localhost", "-p", "2222", "-o", "LogLevel=FATAL",
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "PubkeyAcceptedKeyTypes=+ssh-rsa",
"-o", "HostKeyAlgorithms=+ssh-rsa",
)
end end
end end
@ -180,7 +255,16 @@ describe Vagrant::Util::SSH do
expect(described_class.exec(ssh_info)).to eq(nil) expect(described_class.exec(ssh_info)).to eq(nil)
expect(Vagrant::Util::SafeExec).to have_received(:exec) expect(Vagrant::Util::SafeExec).to have_received(:exec)
.with(ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-i", ssh_info[:private_key_path][0],"-o", "ForwardX11=yes", "-o", "ForwardX11Trusted=yes") .with(
ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL",
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "PubkeyAcceptedKeyTypes=+ssh-rsa",
"-o", "HostKeyAlgorithms=+ssh-rsa",
"-i", ssh_info[:private_key_path][0],
"-o", "ForwardX11=yes",
"-o", "ForwardX11Trusted=yes",
)
end end
end end
@ -198,7 +282,15 @@ describe Vagrant::Util::SSH do
expect(described_class.exec(ssh_info)).to eq(nil) expect(described_class.exec(ssh_info)).to eq(nil)
expect(Vagrant::Util::SafeExec).to have_received(:exec) expect(Vagrant::Util::SafeExec).to have_received(:exec)
.with(ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-i", ssh_info[:private_key_path][0],"-o", "ForwardAgent=yes") .with(
ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL",
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "PubkeyAcceptedKeyTypes=+ssh-rsa",
"-o", "HostKeyAlgorithms=+ssh-rsa",
"-i", ssh_info[:private_key_path][0],
"-o", "ForwardAgent=yes",
)
end end
end end
@ -216,7 +308,15 @@ describe Vagrant::Util::SSH do
expect(described_class.exec(ssh_info)).to eq(nil) expect(described_class.exec(ssh_info)).to eq(nil)
expect(Vagrant::Util::SafeExec).to have_received(:exec) expect(Vagrant::Util::SafeExec).to have_received(:exec)
.with(ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-i", ssh_info[:private_key_path][0], "-L", "8008:localhost:80") .with(
ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL",
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "PubkeyAcceptedKeyTypes=+ssh-rsa",
"-o", "HostKeyAlgorithms=+ssh-rsa",
"-i", ssh_info[:private_key_path][0],
"-L", "8008:localhost:80",
)
end end
end end
@ -234,7 +334,15 @@ describe Vagrant::Util::SSH do
expect(described_class.exec(ssh_info)).to eq(nil) expect(described_class.exec(ssh_info)).to eq(nil)
expect(Vagrant::Util::SafeExec).to have_received(:exec) expect(Vagrant::Util::SafeExec).to have_received(:exec)
.with(ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-i", ssh_info[:private_key_path][0], "-6") .with(
ssh_path, "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL",
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "PubkeyAcceptedKeyTypes=+ssh-rsa",
"-o", "HostKeyAlgorithms=+ssh-rsa",
"-i", ssh_info[:private_key_path][0],
"-6",
)
end end
end end

View File

@ -27,6 +27,10 @@ defaults are typically fine, but you can fine tune whatever you would like.
- `config.ssh.config` (string) - Path to a custom ssh_config file to use for configuring - `config.ssh.config` (string) - Path to a custom ssh_config file to use for configuring
the SSH connections. the SSH connections.
- `config.ssh.disable_deprecated_algorithms` (boolean) - If `true`, this setting will
not configure the SSH client to allow connecting to a host using ssh-rsa key types
and host key algorithms. Defaults to false.
- `config.ssh.dsa_authentication` (boolean) - If `false`, this setting will not include - `config.ssh.dsa_authentication` (boolean) - If `false`, this setting will not include
`DSAAuthentication` when ssh'ing into a machine. If this is not set, it will `DSAAuthentication` when ssh'ing into a machine. If this is not set, it will
default to `true` and `DSAAuthentication=yes` will be used with ssh. default to `true` and `DSAAuthentication=yes` will be used with ssh.