Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion service/lib/dinstaller/software/callbacks/signature.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ def setup
Yast::Pkg.CallbackAcceptUnsignedFile(
Yast::FunRef.new(method(:accept_unsigned_file), "boolean (string, integer)")
)
Yast::Pkg.CallbackImportGpgKey(
Yast::FunRef.new(method(:import_gpg_key), "boolean (map <string, any>, integer)")
)
end

# Callback to handle unsigned files
Expand All @@ -62,7 +65,7 @@ def accept_unsigned_file(filename, repo_id)
end

message = format(
"%{source} is not digitally signed. The origin and integrity of the file cannot be "\
"%{source} is not digitally signed. The origin and integrity of the file cannot be " \
"verified. Use it anyway?", source: source
)

Expand All @@ -75,6 +78,28 @@ def accept_unsigned_file(filename, repo_id)
end
end

# Callback to handle signature verification failures
#
# @param key [Hash] GPG key data (id, name, fingerprint, etc.)
# @param _repo_id [Integer] Repository ID
def import_gpg_key(key, _repo_id)
fingerprint = key["fingerprint"].scan(/.{4}/).join(" ")
message = format(
"The key %{id} (%{name}) with fingerprint %{fingerprint} is unknown. " \
"Do you want to trust this key?",
id: key["id"], name: key["name"], fingerprint: fingerprint
)

question = DInstaller::Question.new(
message, options: [:Trust, :Skip], default_option: :Skip
)

ask(question) do |q|
logger.info "#{q.text} #{q.answer}"
q.answer == :Trust
end
end

private

# @return [DBus::Clients::QuestionsManager]
Expand Down
2 changes: 1 addition & 1 deletion service/lib/dinstaller/software/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def probe
Yast::Stage.Set("normal")

start_progress(3)
Yast::PackageCallbacks.InitPackageCallbacks(logger)
progress.step("Initialize target repositories") { initialize_target_repos }
progress.step("Initialize sources") { add_base_repo }
progress.step("Making the initial proposal") do
Expand All @@ -96,7 +97,6 @@ def probe
end

def initialize_target_repos
Yast::PackageCallbacks.InitPackageCallbacks(logger)
Yast::Pkg.TargetInitialize("/")
import_gpg_keys
end
Expand Down
6 changes: 6 additions & 0 deletions service/package/rubygem-d-installer.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Thu Dec 15 13:15:10 UTC 2022 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>

- Implement the ImportGpgKey libzypp callback
(gh#yast/d-installer#371)

-------------------------------------------------------------------
Wed Dec 14 22:38:24 UTC 2022 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>

Expand Down
59 changes: 55 additions & 4 deletions service/test/dinstaller/software/callbacks/signature_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,63 @@
end
end

context "when the repo information is not available"
it "includes a generic message containing the filename" do
context "when the repo information is not available" do
before do
allow(Yast::Pkg).to receive(:SourceGeneralData).with(1)
.and_return(nil)
end

it "includes a generic message containing the filename" do
expect(subject).to receive(:ask) do |question|
expect(question.text).to include("repomd.xml")
end
expect(subject.accept_unsigned_file("repomd.xml", 1))
end
end
end

describe "import_gpg_key" do
let(:asked_question) do
instance_double(DInstaller::Question, text: "Better safe than sorry", answer: answer)
end

let(:answer) { :Trust }

let(:key) do
{
"id" => "0123456789ABCDEF",
"fingerprint" => "2E2EA448C9DDD7A91BC28441AEE969E90F05DB9D",
"name" => "YaST:Head:D-Installer"
}
end

before do
allow(subject).to receive(:ask).and_yield(asked_question)
end

context "when the user answers :Trust" do
let(:answer) { :Trust }

it "returns true" do
expect(subject.import_gpg_key(key, 1)).to eq(true)
end
end

context "when the user answers :Skip" do
let(:answer) { :Skip }

it "returns false" do
expect(subject.import_gpg_key(key, 1)).to eq(false)
end
end

it "includes a message" do
expect(subject).to receive(:ask) do |question|
expect(question.text).to include("repomd.xml")
expect(question.text).to include(key["id"])
expect(question.text).to include(key["name"])
expect(question.text).to include("2E2E A448 C9DD")
end
expect(subject.accept_unsigned_file("repomd.xml", 1))
subject.import_gpg_key(key, 1)
end
end
end