Skip to content

Commit

Permalink
(maint) add ed25519 support
Browse files Browse the repository at this point in the history
rubygems has compiled versions of bcrypt_pbkdf 1.1.0 for windows

addresses #1986 #1987
  • Loading branch information
h0tw1r3 committed Nov 22, 2023
1 parent 2b0d943 commit d0f3fa3
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 53 deletions.
2 changes: 2 additions & 0 deletions bolt.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ Gem::Specification.new do |spec|

spec.add_dependency "addressable", '~> 2.5'
spec.add_dependency "aws-sdk-ec2", '~> 1'
spec.add_dependency "bcrypt_pbkdf", ">= 1.1", "< 2.0"
spec.add_dependency "CFPropertyList", ">= 2.2"
spec.add_dependency "concurrent-ruby", "~> 1.0", "< 1.2.0"
spec.add_dependency "ed25519", ">= 1.3", "< 2.0"
spec.add_dependency "ffi", ">= 1.9.25", "< 2.0.0"
spec.add_dependency "hiera-eyaml", "~> 3"
spec.add_dependency "jwt", "~> 2.2"
Expand Down
36 changes: 0 additions & 36 deletions documentation/bolt_known_issues.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,42 +68,6 @@ such as [`bolt-defaults.yaml`](bolt_defaults_reference.md) or
[inventory file](bolt_inventory_reference.md), or passing the password on the
command line with the `--password` option.

📖 **Related issues**

- [#1986 - Commands fail if in a remote session to
Windows](https://github.com/puppetlabs/bolt/issues/1986)

## Unable to authenticate with ed25519 keys over SSH transport on Windows

By default, Bolt uses the `net-ssh` Ruby libary to connect to targets over SSH.
The `net-ssh` library requires the `ed25519` and `bcrypt_pbkdf` gems as
dependencies, which are not supported in Bolt's packaging process due to issues
with compiling native extensions.

Attempting to authenticate with ed25519 keys over SSH on Windows will result
in an error message similar to this:

```
unsupported key type `ssh-ed25519'
net-ssh requires the following gems for ed25519 support:
* ed25519 (>= 1.2, < 2.0)
* bcrypt_pbkdf (>= 1.0, < 2.0)
```

A workaround is to use native SSH when you need to authenticate with ed25519
keys. When native SSH is enabled, Bolt will use a specified SSH client to
connect to targets instead of the `net-ssh` Ruby library. To learn more about
native SSH, see [native SSH
transport](experimental_features.md#native-ssh-transport).

🧪 Native SSH is
experimental and might change in future minor (y) releases.

📖 **Related issues**

- [#1987 - Unable to authenticate with ed25519 keys over SSH transport
on Windows](https://github.com/puppetlabs/bolt/issues/1987)

## 🧪 Limited Kerberos support over WinRM

🧪 Authenticating with Kerberos over WinRM is considered experimental and is
Expand Down
6 changes: 4 additions & 2 deletions spec/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ RUN adduser bolt sudo

RUN mkdir -p /home/bolt/.ssh
COPY fixtures/keys/id_rsa.pub /home/bolt/.ssh/id_rsa.pub
COPY fixtures/keys/id_rsa.pub /home/bolt/.ssh/authorized_keys
COPY fixtures/keys/id_ed25519.pub /home/bolt/.ssh/id_ed25519.pub
RUN cat /home/bolt/.ssh/*.pub > /home/bolt/.ssh/authorized_keys
RUN chmod 700 /home/bolt/.ssh
RUN chmod 600 /home/bolt/.ssh/authorized_keys
RUN chown -R bolt:sudo /home/bolt
Expand All @@ -41,7 +42,8 @@ RUN echo test | chsh -s /bin/bash test

RUN mkdir -p /home/test/.ssh
COPY fixtures/keys/id_rsa.pub /home/test/.ssh/id_rsa.pub
COPY fixtures/keys/id_rsa.pub /home/test/.ssh/authorized_keys
COPY fixtures/keys/id_ed25519.pub /home/test/.ssh/id_ed25519.pub
RUN cat /home/test/.ssh/*.pub > /home/test/.ssh/authorized_keys
RUN chmod 700 /home/test/.ssh
RUN chmod 600 /home/test/.ssh/authorized_keys
RUN chown -R test:sudo /home/test
Expand Down
37 changes: 24 additions & 13 deletions spec/bolt_server/app_integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,31 @@ def app
expect(result['value']['_output'].chomp).to match(/\w+ got passed the message: Hello!/)
end

it 'runs an echo task using a private key' do
private_key = ENV['BOLT_SSH_KEY'] || Dir["spec/fixtures/keys/id_rsa"][0]
private_key_content = File.read(private_key)
target = conn_target('ssh', options: { 'private-key' => { 'key-data' => private_key_content } })
body = build_task_request('sample::echo',
target,
message: "Hello!")
%w[env rsa ed25519].each do |key_type|
next if key_type == 'env' && ENV['BOLT_SSH_KEY'].nil?

context "runs an echo task using an #{key_type} private key" do
let(:private_key) do
(key_type == 'env') ? ENV['BOLT_SSH_KEY'] : Dir["spec/fixtures/keys/id_#{key_type}"][0]
end

it do
private_key_content = File.read(private_key)
target = conn_target('ssh', options: { 'private-key' => { 'key-data' => private_key_content } })
body = build_task_request('sample::echo',
target,
message: "Hello!")

post path, JSON.generate(body), 'CONTENT_TYPE' => 'text/json'
expect(last_response).to be_ok
expect(last_response.status).to eq(200)
result = JSON.parse(last_response.body)
expect(result).to include('status' => 'success')
expect(result['value']['_output'].chomp).to match(/\w+ got passed the message: Hello!/)
end
end

post path, JSON.generate(body), 'CONTENT_TYPE' => 'text/json'
expect(last_response).to be_ok
expect(last_response.status).to eq(200)
result = JSON.parse(last_response.body)
expect(result).to include('status' => 'success')
expect(result['value']['_output'].chomp).to match(/\w+ got passed the message: Hello!/)
break if key_type == 'env'
end

it 'runs a shareable task' do
Expand Down
8 changes: 8 additions & 0 deletions spec/fixtures/keys/id_ed25519
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACDuFK/VaW7prqpNVY0H+bUTXsbDSeYg5XKlo0AitRXSmAAAALjUlsWQ1JbF
kAAAAAtzc2gtZWQyNTUxOQAAACDuFK/VaW7prqpNVY0H+bUTXsbDSeYg5XKlo0AitRXSmA
AAAECU+JslSRRf+EDh1yWFP6Hue8DrT0M8CGLp1UDKycZnfu4Ur9Vpbumuqk1VjQf5tRNe
xsNJ5iDlcqWjQCK1FdKYAAAAMWplZmZyZXkuY2xhcmtAamVmZnJleWNsYXJrcy1WaXJ0dW
FsLU1hY2hpbmUubG9jYWwBAgME
-----END OPENSSH PRIVATE KEY-----
1 change: 1 addition & 0 deletions spec/fixtures/keys/id_ed25519.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO4Ur9Vpbumuqk1VjQf5tRNexsNJ5iDlcqWjQCK1FdKY testin@tester.son
9 changes: 9 additions & 0 deletions spec/integration/transport/ssh_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
let(:bash_user) { 'test' }
let(:bash_password) { 'test' }
let(:key) { conn_info('ssh')[:key] }
let(:ed25519_key) { File.expand_path(File.join(__dir__, '..', '..', 'fixtures/keys/id_ed25519')) }
let(:command) { "pwd" }

let(:no_host_key_check) { { 'host-key-check' => false, user: user, password: password } }
Expand Down Expand Up @@ -208,6 +209,14 @@ def make_target(host_: hostname, port_: port)
).to eq(true)
end
end

context "with ed25519 private key" do
let(:transport_config) { super().merge({ 'private-key' => ed25519_key }) }

it "executes a command on a host" do
expect(ssh.run_command(target, command).value['stdout']).to eq("/home/#{user}\n")
end
end
end

context "when executing with private key data" do
Expand Down
4 changes: 2 additions & 2 deletions spec/unit/executor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ def mock_node_results
expect(ssh)
.to receive(:with_connection)
.and_raise(
NotImplementedError.new('ed25519 is not supported')
NotImplementedError.new('something is not supported')
)
end

Expand All @@ -580,7 +580,7 @@ def mock_node_results

results.each do |result|
expect(result.error_hash['kind']).to eq('puppetlabs.tasks/exception-error')
expect(result.error_hash['msg']).to eq('ed25519 is not supported')
expect(result.error_hash['msg']).to eq('something is not supported')
end

expect(collector.events.count).to eq(10)
Expand Down

0 comments on commit d0f3fa3

Please sign in to comment.