Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(maint) add ed25519 support #3248

Open
wants to merge 1 commit into
base: main
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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.1", "< 2.0"
spec.add_dependency "CFPropertyList", ">= 2.2"
spec.add_dependency "concurrent-ruby", "~> 1.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
31 changes: 0 additions & 31 deletions documentation/bolt_known_issues.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,37 +73,6 @@ command line with the `--password` option.
- [#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