Skip to content

Commit

Permalink
Replace ssh-keygen usage with just some Ruby code
Browse files Browse the repository at this point in the history
  • Loading branch information
imobachgs committed Nov 8, 2018
1 parent 23e648d commit 3f13449
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 18 deletions.
5 changes: 0 additions & 5 deletions package/yast2-users.spec
Expand Up @@ -38,8 +38,6 @@ BuildRequires: yast2-perl-bindings
BuildRequires: yast2-security
BuildRequires: yast2-testsuite
BuildRequires: rubygem(%rb_default_ruby_abi:rspec)
# ssh-keygen
BuildRequires: openssh

Requires: cracklib
Requires: perl-Digest-SHA1
Expand All @@ -66,9 +64,6 @@ Requires: yast2-core >= 2.21.0

Requires: yast2-ruby-bindings >= 1.0.0

# ssh-keygen
Requires: openssh

Summary: YaST2 - User and Group Configuration
License: GPL-2.0
Group: System/YaST
Expand Down
33 changes: 23 additions & 10 deletions src/lib/users/ssh_public_key.rb
Expand Up @@ -19,7 +19,8 @@
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "yast2/execute"
require "digest"
require "base64"

module Y2Users
# This class is a simplified representation of a OpenSSH public key.
Expand All @@ -40,15 +41,15 @@ class InvalidKey < StandardError; end
#
# @raise InvalidKey
def initialize(raw)
@fingerprint = fingerprint_from(raw)
@raw = raw.strip
@fingerprint = calculate_fingerprint
end

# Returns the key comment
#
# @return [String] Comment field
def comment
@comment ||= @raw.split(" ")[2]
@comment ||= raw.split(" ")[2]
end

# Returns the string version of the public key
Expand All @@ -58,19 +59,31 @@ def to_s
@raw
end

# Fingeprint formatted in a similar way to ssh-keygen
#
# It adds the used hash and removes the trailing "=" characters (they are
# just padding).
#
# @see https://github.com/openssh/openssh-portable/blob/1a4a9cf80f5b92b9d1dadd0bfa8867c04d195391/sshkey.c#L955
def formatted_fingerprint
fp = fingerprint.sub(/\=+\Z/, "")
"SHA256:#{fp}"
end

private

attr_reader :raw

KEY_REGEXP = /(ssh|ecdsa)-\S+ (\S+)/.freeze

# Gets the fingerprint for the given OpenSSH public key
#
# @return [String] Key fingerprint
# @raise InvalidKey
def fingerprint_from(raw)
output = Yast::Execute.locally!(
["echo", raw], ["ssh-keygen", "-l", "-f", "/dev/stdin"], stdout: :capture
)
output.split(" ")[1].to_s
rescue Cheetah::ExecutionFailed
raise InvalidKey
def calculate_fingerprint
key = @raw[KEY_REGEXP, 2]
raise InvalidKey unless key
Digest::SHA256.base64digest(Base64.decode64(key))
end
end
end
2 changes: 1 addition & 1 deletion src/lib/users/widgets/public_key_selector.rb
Expand Up @@ -163,7 +163,7 @@ def blk_device_selector
# @return [Yast::Term]
def public_key_content
VBox(
Left(Label(value.fingerprint)),
Left(Label(value.formatted_fingerprint)),
HBox(
Left(Label(value.comment)),
Right(PushButton(Id(:remove), Opt(:notify), Yast::Label.RemoveButton))
Expand Down
9 changes: 8 additions & 1 deletion test/lib/users/ssh_public_key_test.rb
Expand Up @@ -39,7 +39,14 @@

describe "#fingerprint" do
it "returns the key fingerprint" do
expect(subject.fingerprint).to eq("SHA256:uadPyDQj9VlFZVjK8UNp57jOnWwzGgKQJpeJEhZyV0I")
expect(subject.fingerprint).to eq("uadPyDQj9VlFZVjK8UNp57jOnWwzGgKQJpeJEhZyV0I=")
end
end

describe "#formatted_fingerprint" do
it "returns the key fingerprint using the ssh-keygen style" do
expect(subject.formatted_fingerprint)
.to eq("SHA256:uadPyDQj9VlFZVjK8UNp57jOnWwzGgKQJpeJEhZyV0I")
end
end

Expand Down
2 changes: 1 addition & 1 deletion test/lib/users/widgets/public_key_selector_test.rb
Expand Up @@ -105,7 +105,7 @@
let(:value) { key }

it "includes the key fingerprint and the comment" do
expect(widget.contents.to_s).to include(key.fingerprint)
expect(widget.contents.to_s).to include(key.formatted_fingerprint)
expect(widget.contents.to_s).to include(key.comment)
end

Expand Down

0 comments on commit 3f13449

Please sign in to comment.