diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..d12b0a8762 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# 2 space indentation +[{*.sh}] +indent_style = space +indent_size = 2 diff --git a/doc/boot_arguments.md b/doc/boot_arguments.md index f31be92504..cc66b2c612 100644 --- a/doc/boot_arguments.md +++ b/doc/boot_arguments.md @@ -26,3 +26,15 @@ agama.web.ssl=true agama.web.ssl_cert=http://192.168.122.1/mycert.pem agama.web. ``` Changing complex options (e.g., collections) is not supported yet. + +## Proxy Setup + +Agama supports proxy setup using the `proxy=` kernel command line option like +`proxy=http://192.168.122.1:3128` when the installation requires to use an HTTP, HTTPS or FTP +source. The supported proxy URL format is: protocol://[user[:password]@]host[:port] + +When the installation system boots, the agama-proxy-setup service will read the proxy URL to be +used from the kernel command line options or through the dracut ask prompt configuration file +writing it to the /etc/sysconfig/proxy. After that the microOS Tools setup-systemd-proxy-env +systemd service will make the proxy variables from that file available to all the systemd units +writing a systemd config file with all the variables as Enviroment ones. diff --git a/service/agama.gemspec b/service/agama.gemspec index 805729197b..bb2b561d4a 100644 --- a/service/agama.gemspec +++ b/service/agama.gemspec @@ -40,7 +40,7 @@ Gem::Specification.new do |spec| spec.homepage = "https://github.com/openSUSE/agama" spec.license = "GPL-2.0-only" spec.files = Dir["lib/**/*.rb", "bin/*", "share/*", "etc/*"] - spec.executables = ["agamactl"] + spec.executables = ["agamactl", "agama-proxy-setup"] spec.metadata = { "rubygems_mfa_required" => "true" } spec.required_ruby_version = ">= 2.5.0" diff --git a/service/bin/agama-proxy-setup b/service/bin/agama-proxy-setup new file mode 100755 index 0000000000..8d16341175 --- /dev/null +++ b/service/bin/agama-proxy-setup @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require "agama/proxy_setup" + +Agama::ProxySetup.instance.run diff --git a/service/lib/agama/proxy_setup.rb b/service/lib/agama/proxy_setup.rb new file mode 100644 index 0000000000..9852db68ca --- /dev/null +++ b/service/lib/agama/proxy_setup.rb @@ -0,0 +1,109 @@ +# frozen_string_literal: true + +# Copyright (c) [2023] 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" +require "uri" + +module Agama + # This class is responsible of parsing the proxy url from the kernel cmdline or configured + # through the dracut ask prompt configuration file (/etc/cmdline-menu.conf) during the boot + # proccess of the system writing the configuration to /etc/sysconfig/proxy + class ProxySetup + include Singleton + include Yast + include Logger + + CMDLINE_PATH = "/proc/cmdline" + CMDLINE_MENU_CONF = "/etc/cmdline-menu.conf" + + # @return [URI::Generic] + attr_accessor :proxy + + # Constructor + def initialize + Yast.import "Proxy" + end + + def run + read + write + end + + private + + def read + self.proxy = proxy_from_cmdline || proxy_from_dracut + end + + def proxy_from_dracut + return unless File.exist?(CMDLINE_MENU_CONF) + + options = File.read(CMDLINE_MENU_CONF) + proxy_url_from(options) + end + + def proxy_url_from(options) + proxy_url = options.split.find { |o| o.start_with?(/proxy/i) } + return unless proxy_url + + URI(proxy_url.downcase.gsub("proxy=", "")) + end + + def proxy_from_cmdline + return unless File.exist?(CMDLINE_PATH) + + options = File.read(CMDLINE_PATH) + proxy_url_from(options) + end + + def proxy_import_settings + proto = proxy.scheme + # save user name and password separately + settings = { + "proxy_user" => proxy.user, + "proxy_password" => proxy.password, + "enabled" => true + } + proxy.user = nil + proxy.password = nil + + settings["#{proto}_proxy"] = proxy.to_s + # Use the proxy also for https and ftp + if proto == "http" + settings["https_proxy"] = proxy.to_s + settings["ftp_proxy"] = proxy.to_s + end + settings + end + + def write + return unless proxy + + settings = proxy_import_settings + Proxy.Import(settings) + + log.info "Writing proxy settings: #{proxy.scheme}_proxy = '#{proxy}'" + log.debug "Writing proxy settings: #{settings}" + + Proxy.Write + end + end +end diff --git a/service/package/gem2rpm.yml b/service/package/gem2rpm.yml index 945bc01132..cc70ad5bc8 100644 --- a/service/package/gem2rpm.yml +++ b/service/package/gem2rpm.yml @@ -8,7 +8,8 @@ install -D -m 0644 %{buildroot}%{gem_base}/gems/%{mod_full_name}/share/dbus.conf %{buildroot}%{_datadir}/dbus-1/agama.conf install --directory %{buildroot}%{_datadir}/dbus-1/agama-services install -m 0644 --target-directory=%{buildroot}%{_datadir}/dbus-1/agama-services %{buildroot}%{gem_base}/gems/%{mod_full_name}/share/org.opensuse.Agama*.service - install -D -m 0644 %{buildroot}%{gem_base}/gems/%{mod_full_name}/share/systemd.service %{buildroot}%{_unitdir}/agama.service + install -D -m 0644 %{buildroot}%{gem_base}/gems/%{mod_full_name}/share/agama.service %{buildroot}%{_unitdir}/agama.service + install -D -m 0644 %{buildroot}%{gem_base}/gems/%{mod_full_name}/share/agama-proxy-setup.service %{buildroot}%{_unitdir}/agama-proxy-setup.service install -D -m 0644 %{buildroot}%{gem_base}/gems/%{mod_full_name}/etc/agama.yaml %{buildroot}%{_sysconfdir}/agama.yaml :main: :preamble: |- @@ -36,4 +37,5 @@ %dir %{_datadir}/dbus-1/agama-services\n %{_datadir}/dbus-1/agama-services/org.opensuse.Agama*.service\n %{_unitdir}/agama.service\n + %{_unitdir}/agama-proxy-setup.service\n %config %{_sysconfdir}/agama.yaml\n" diff --git a/service/package/rubygem-agama.changes b/service/package/rubygem-agama.changes index 4ea828cd84..5fded27b4d 100644 --- a/service/package/rubygem-agama.changes +++ b/service/package/rubygem-agama.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Fri Aug 18 14:17:13 UTC 2023 - Knut Anderssen + +- Add proxy setup support (bsc#1212677, gh#openSUSE/agama#696). + ------------------------------------------------------------------- Mon Aug 7 10:52:35 UTC 2023 - Imobach Gonzalez Sosa diff --git a/service/share/agama-proxy-setup.service b/service/share/agama-proxy-setup.service new file mode 100644 index 0000000000..3a46bbc232 --- /dev/null +++ b/service/share/agama-proxy-setup.service @@ -0,0 +1,12 @@ +[Unit] +Description=Configure wide proxy setup for agama and systemd services +Before=agama.service +Wants=local-fs.target + +[Service] +Type=oneshot +ExecStart=/usr/bin/agama-proxy-setup + +[Install] +WantedBy=default.target + diff --git a/service/share/systemd.service b/service/share/agama.service similarity index 100% rename from service/share/systemd.service rename to service/share/agama.service diff --git a/service/test/agama/proxy_setup_test.rb b/service/test/agama/proxy_setup_test.rb new file mode 100644 index 0000000000..484541296a --- /dev/null +++ b/service/test/agama/proxy_setup_test.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +# Copyright (c) [2023] 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 "agama/proxy_setup" + +describe Agama::ProxySetup do + subject(:proxy) { described_class.instance } + before do + proxy.proxy = nil + end + + describe "#run" do + let(:file_content) { "proxy=#{proxy_url}" } + let(:proxy_url) { "https://yast:1234@192.168.122.1:3128" } + + before do + allow(Yast::Proxy).to receive(:Read) + allow(Yast::Proxy).to receive(:Write) + end + + context "when some configuration is given through the kernel command line" do + before do + allow(proxy).to receive(:proxy_from_cmdline).and_return(URI(proxy_url)) + allow(proxy).to receive(:write) + end + + it "reads the given proxy configuraion" do + expect(proxy.proxy).to be_nil + proxy.run + expect(proxy.proxy).to be_a(URI) + end + + it "writes the proxy configuration to /etc/sysconfig/proxy" do + allow(proxy).to receive(:write).and_call_original + expect(Yast::Proxy).to receive(:Write) + proxy.run + config = Yast::Proxy.Export + expect(config).to include("https_proxy" => "https://192.168.122.1:3128", + "proxy_password" => "1234", + "proxy_user" => "yast", + "enabled" => true) + end + + context "when an http url is given" do + let(:proxy_url) { "http://192.168.122.1:3128" } + + it "sets also the https and ftp with the same url" do + allow(proxy).to receive(:write).and_call_original + proxy.run + config = Yast::Proxy.Export + expect(config).to include("http_proxy" => "http://192.168.122.1:3128", + "https_proxy" => "http://192.168.122.1:3128", + "ftp_proxy" => "http://192.168.122.1:3128", + "enabled" => true) + end + end + end + end +end diff --git a/setup-service.sh b/setup-service.sh index 2e84ec9a58..4760be186f 100755 --- a/setup-service.sh +++ b/setup-service.sh @@ -76,7 +76,7 @@ $SUDO cp -v $MYDIR/service/share/dbus.conf /usr/share/dbus-1/agama.conf sudosed "s@\(Exec\)=/usr/bin/@\1=$MYDIR/service/bin/@" $SVC $DBUSDIR/$SVC done sudosed "s@\(ExecStart\)=/usr/bin/@\1=$MYDIR/service/bin/@" \ - systemd.service /usr/lib/systemd/system/agama.service + agama.service /usr/lib/systemd/system/agama.service ) # and same for rust service