diff --git a/service/lib/agama/autoyast/converter.rb b/service/lib/agama/autoyast/converter.rb index 171b8ba42b..d719df4e97 100755 --- a/service/lib/agama/autoyast/converter.rb +++ b/service/lib/agama/autoyast/converter.rb @@ -26,6 +26,7 @@ require "agama/autoyast/product_reader" require "agama/autoyast/root_reader" require "agama/autoyast/scripts_reader" +require "agama/autoyast/security_reader" require "agama/autoyast/software_reader" require "agama/autoyast/storage_reader" require "agama/autoyast/user_reader" @@ -52,7 +53,15 @@ class Converter # Sections which have a corresponding reader. The reader is expected to be # named in Pascal case and adding "Reader" as suffix (e.g., "L10nReader"). SECTIONS = [ - "files", "localization", "product", "root", "scripts", "software", "storage", "user" + "files", + "localization", + "product", + "root", + "scripts", + "security", + "software", + "storage", + "user" ].freeze # Builds the Agama profile diff --git a/service/lib/agama/autoyast/security_reader.rb b/service/lib/agama/autoyast/security_reader.rb new file mode 100755 index 0000000000..72de0d4a27 --- /dev/null +++ b/service/lib/agama/autoyast/security_reader.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +# Copyright (c) [2025] SUSE LLC +# +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of version 2 of the GNU General Public License as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, contact SUSE LLC. +# +# To contact SUSE LLC about this file by physical or electronic mail, you may +# find current contact information at www.suse.com. + +require "yast" + +# :nodoc: +module Agama + module AutoYaST + # Builds the Agama "security" section from an AutoYaST profile. + class SecurityReader + # @param profile [ProfileHash] AutoYaST profile + def initialize(profile) + @profile = profile + end + + # Returns a hash corresponding to Agama "product" section. + # + # If there is no software-related information, it returns an empty hash. + # + # @return [Hash] Agama "software" section + def read + suse_register = profile.fetch_as_hash("suse_register") + fingerprint = suse_register["reg_server_cert_fingerprint"] + algorithm = suse_register["reg_server_cert_fingerprint_type"] + + # Both the fingerprint and the algorithm must be provided in a valid AutoYaST profile. + # Moreover, Agama does not support an equivalent to (so far). + return {} unless fingerprint && algorithm + + ssl_certificate = { "fingerprint" => fingerprint, "algorithm" => algorithm } + { "security" => { "sslCertificates" => [ssl_certificate] } } + end + + private + + attr_reader :profile + end + end +end diff --git a/service/package/rubygem-agama-yast.changes b/service/package/rubygem-agama-yast.changes index 051331f50e..7099fa6bb2 100644 --- a/service/package/rubygem-agama-yast.changes +++ b/service/package/rubygem-agama-yast.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Fri Apr 25 13:36:13 UTC 2025 - Ancor Gonzalez Sosa + +- AutoYaST profile compatibility: + and (related to + gh#agama-project/agama#2270). + ------------------------------------------------------------------- Thu Apr 24 17:18:04 UTC 2025 - Knut Anderssen diff --git a/service/share/autoyast-compat.json b/service/share/autoyast-compat.json index 31e4dee24d..5c9691de4c 100644 --- a/service/share/autoyast-compat.json +++ b/service/share/autoyast-compat.json @@ -440,9 +440,17 @@ "agama": "product.registrationCode" }, { "key": "reg_server", "support": "planned" }, - { "key": "reg_server_cert", "support": "planned" }, - { "key": "reg_server_cert_fingerprint", "support": "planned" }, - { "key": "reg_server_cert_fingerprint_type", "support": "planned" }, + { "key": "reg_server_cert", "support": "no" }, + { + "key": "reg_server_cert_fingerprint", + "support": "yes", + "agama": "security.sslCertificates[].fingerprint" + }, + { + "key": "reg_server_cert_fingerprint_type", + "support": "yes", + "agama": "security.sslCertificates[].algorithm" + }, { "key": "addons[]", "support": "yes", diff --git a/service/test/agama/autoyast/security_reader_test.rb b/service/test/agama/autoyast/security_reader_test.rb new file mode 100644 index 0000000000..b8469a65f9 --- /dev/null +++ b/service/test/agama/autoyast/security_reader_test.rb @@ -0,0 +1,105 @@ +# frozen_string_literal: true + +# Copyright (c) [2025] SUSE LLC +# +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of version 2 of the GNU General Public License as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, contact SUSE LLC. +# +# To contact SUSE LLC about this file by physical or electronic mail, you may +# find current contact information at www.suse.com. + +require_relative "../../test_helper" +require "yast" +require "agama/autoyast/security_reader" + +Yast.import "Profile" + +describe Agama::AutoYaST::SecurityReader do + let(:profile) { {} } + + subject do + described_class.new(Yast::ProfileHash.new(profile)) + end + + describe "#read" do + context "when there is no scripts sections" do + let(:profile) { {} } + + it "returns an empty hash" do + expect(subject.read).to be_empty + end + end + + context "when the profile only specifies a certificate URL" do + let(:profile) do + { + "suse_register" => { + "reg_server_cert" => "http://smt.example.com/smt.crt" + } + } + end + + it "returns an empty hash" do + expect(subject.read).to be_empty + end + end + + context "when the profile specifies fingerprint without type" do + let(:profile) do + { + "suse_register" => { + "reg_server_cert_fingerprint" => "01:12:23:34:45" + } + } + end + + it "returns an empty hash" do + expect(subject.read).to be_empty + end + end + + context "when the profile specifies a type with no corresponding fingerprint" do + let(:profile) do + { + "suse_register" => { + "reg_server_cert_fingerprint_type" => "SHA256" + } + } + end + + it "returns an empty hash" do + expect(subject.read).to be_empty + end + end + + context "when the profile specifies a fingerprint and its type" do + let(:profile) do + { + "suse_register" => { + "reg_server_cert_fingerprint" => "01:12:23:34:45", + "reg_server_cert_fingerprint_type" => "SHA256" + } + } + end + + it "creates a security section with one certificate" do + certificates = subject.read["security"]["sslCertificates"] + expect(certificates.size).to eq 1 + expect(certificates.first).to include( + "fingerprint" => "01:12:23:34:45", "algorithm" => "SHA256" + ) + end + end + end +end