Sign Up
Log In
Sign Up
Username:
*
Email:
*
Password:
*
Password confirmation:
*
or
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
AppArmor
smar-apparmor-profiles
generate_spec.rb
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File generate_spec.rb of Package smar-apparmor-profiles
#!/usr/bin/env ruby # Generates spec so manual repetition is not necessary require "fileutils" require "pathname" require "yaml" require_relative "systemd_override" def set_log_level(&block) # Set to true to enable trace messages. trace = false #trace = true # Set to true to enable debug messages. debug = false debug = true if trace #debug = true block.call trace, debug end set_log_level do |trace, debug| TRACE = trace DEBUG = debug end def verb(message) puts "[INFO] #{message}" end def debug(message) puts "[DEBUG] #{message}" if DEBUG end def trace(message) puts "[TRACE] #{message}" if TRACE end class GenerateSpec INSTALL_RULES_TARGET_LINE = "___INSTALL_RULES_HERE___" PACKAGES_TARGET_LINE = "___PACKAGES_HERE___" INPUT_FILE = "smar-apparmor-profiles.spec.in" OUTPUT_FILE = "smar-apparmor-profiles.spec" def initialize @packages = load_packages @systemd_override = SystemdOverride.new end def generate install_line_rows = generate_install_lines package_rows = generate_package_rows lines = File.readlines INPUT_FILE lines.each_with_index do |line, line_index| line.strip! if line == INSTALL_RULES_TARGET_LINE # Replace target first to avoid infinite loop. lines[line_index] = "## Generated install commands starts." lines[line_index+=1] = "" install_line_rows.each_with_index do |row, row_index| lines.insert((line_index + row_index), row) end end end # Loop twice so that line indices are correct. lines.each_with_index do |line, line_index| line.strip! if line == PACKAGES_TARGET_LINE # Replace target first to avoid infinite loop. lines[line_index] = "## Generated packages starts." lines[line_index+=1] = "" package_rows.each_with_index do |package, index| trace "index: #{index}, package: “#{package}”" lines.insert((line_index + index), package) # Append newline after package rows. line_index += 1 lines.insert((line_index + index), "\n") end end end File.open OUTPUT_FILE, "w" do |file| file.puts lines end end def finalize @systemd_override.finalize end private def generate_install_lines out = [] @packages.each do |package| definition = generate_install_line package out << definition.join("\n") end out end private def generate_install_line package trace "Generating install line for #{package}" definition = [] package["files"]&.each do |file| definition << "mv profiles/#{file} %{buildroot}%{_sysconfdir}/apparmor.d" end package["local"]&.each do |file| definition << "mv profiles/local/#{file} %{buildroot}%{_sysconfdir}/apparmor.d/local" end package["namespaces"]&.each do |file| unless File.symlink? file definition << "mv namespaces/#{file} %{buildroot}%{_sysconfdir}/apparmor.d/namespaces.d" else # If a file is a symlink, it should be added manually # by the package where it is a symlink to. warn "File #{file} needs to be owned manually (1)." end end package["namespace_directories"]&.each do |directory| definition << "mv namespaces/#{directory}/ %{buildroot}%{_sysconfdir}/apparmor.d/namespaces.d" end package["included_abstractions"]&.each do |file| definition << "mv abstractions/#{file} %{buildroot}%{_sysconfdir}/apparmor.d/abstractions" end package["included_tunables"]&.each do |file| definition << "mv tunables/#{file} %{buildroot}%{_sysconfdir}/apparmor.d/tunables" end package["extra_files"]&.each do |directory, files| extra_files_line definition, directory, files end package["load_profile_by_systemd"]&.each do |service_name, profile_name| @systemd_override.install_lines_for_load_profile_by_systemd definition, package, service_name, profile_name end package["in_directory"]&.each do |target, data| in_directory_lines definition, target, data, parent_package: package end definition end private def in_directory_lines definition, target, package, parent_package: unless package.respond_to? :each_pair STDERR.puts "Syntax error in a YAML config." STDERR.puts "Package “#{parent_package["name"]}” has invalid content in block “in_directory”:" STDERR.puts STDERR.puts package.inspect STDERR.puts STDERR.puts "Maybe you’re missing “files:” keyword to denote a hash?" exit 20 end package["files"]&.each do |file| definition << "mv profiles/#{target}/#{file} %{buildroot}%{_sysconfdir}/apparmor.d" end package["local"]&.each do |file| definition << "mv profiles/#{target}/local/#{file} %{buildroot}%{_sysconfdir}/apparmor.d/local" end package["included_abstractions"]&.each do |file| definition << "mv profiles/#{target}/abstractions/#{file} %{buildroot}%{_sysconfdir}/apparmor.d/abstractions" end package["included_tunables"]&.each do |file| definition << "mv profiles/#{target}/tunables/#{file} %{buildroot}%{_sysconfdir}/apparmor.d/tunables" end if package["extra_files"] extra_files_line definition, "profiles/#{target}", package["extra_files"] end if package["rpm_scriptlets_symlinks"] rpm_scriptlets_symlinks definition, package["rpm_scriptlets_symlinks"] end end private def extra_files_line definition, directory, files case directory when "ssh" directory = "profiles/security/ssh" files.each do |file| destination_dir = File.dirname file definition << "mkdir -p '%{buildroot}%{_sysconfdir}/apparmor.d/#{destination_dir}'" definition << "mv #{directory}/#{file} '%{buildroot}%{_sysconfdir}/apparmor.d/#{destination_dir}'" end when "gcc" directory = "profiles/compilation" files.each do |file| destination_dir = File.dirname file definition << "mkdir -p '%{buildroot}%{_sysconfdir}/apparmor.d/#{destination_dir}'" definition << "mv #{directory}/#{file} '%{buildroot}%{_sysconfdir}/apparmor.d/#{destination_dir}'" end when "shells" directory = "profiles/system/shells" files.each do |file| destination_dir = File.dirname file definition << "mkdir -p '%{buildroot}%{_sysconfdir}/apparmor.d/#{destination_dir}'" definition << "mv #{directory}/#{file} '%{buildroot}%{_sysconfdir}/apparmor.d/#{destination_dir}'" end else files.each do |file| destination_dir = File.dirname file definition << "mkdir -p '%{buildroot}%{_sysconfdir}/apparmor.d/#{destination_dir}'" definition << "mv #{directory}/#{file} '%{buildroot}%{_sysconfdir}/apparmor.d/#{destination_dir}'" end end end private def rpm_scriptlets_symlinks definition, files files.each do |file| rpm_scriptlets_d = "%{buildroot}%{_sysconfdir}/apparmor.d/namespaces.d/rpm-scriptlets.d" profile_name = File.basename file definition << %{ln -t '#{rpm_scriptlets_d}' -s '../../#{profile_name}'} end end # Generates the package rows that are inserted to template spec. private def generate_package_rows out = [] @packages.each do |package| definition = <<~EOF # #{package["name"]} %package -n #{package["name"]}-profiles Summary: AppArmor profiles for #{package["name"]} Supplements: #{package["name"]} BuildArch: noarch EOF package["provides"]&.each do |provided| definition += "Provides: #{provided}-profiles\n" end package["abstractions"]&.each do |abstraction| definition += "Requires: smar-apparmor-profiles-#{abstraction}-abstractions\n" end package["supplements"]&.each do |supplement| definition += "Supplements: #{supplement}\n" end package["requires"]&.each do |required| name = "#{required}-profiles" name = "smar-apparmor-profiles-common" if required == "common" definition += "Requires: #{name}\n" end package["recommends"]&.each do |recommended| name = "#{recommended}-profiles" name = "smar-apparmor-profiles-common" if recommended == "common" definition += "Recommends: #{name}\n" end package["suggests"]&.each do |suggested| name = "#{suggested}-profiles" name = "smar-apparmor-profiles-common" if suggested == "common" definition += "Suggests: #{name}\n" end file_list_clause = %|%files -n #{package["name"]}-profiles| if package["namespace_directories"] && !package["namespace_directories"].empty? raise "This is for now only hacked for rpm-scriptlets. I think." unless package["name"] == "rpm" file_list_clause = %|#{file_list_clause} -f namespace_files.#{package["name"]}| end definition += <<~EOF %description -n #{package["name"]}-profiles AppArmor profiles for #{package["name"]} from project smar-apparmor-profiles. #{file_list_clause} EOF definition = generate_file_rows definition, package out << definition end out end private def generate_file_rows definition, package package["files"]&.each do |file| basename = File.basename file definition += "%config %{_sysconfdir}/apparmor.d/#{basename}\n" end package["local"]&.each do |file| basename = File.basename file definition += "%config(noreplace) %{_sysconfdir}/apparmor.d/local/#{basename}\n" end package["namespaces"]&.each do |file| unless File.symlink? file basename = File.basename file definition += "%config %{_sysconfdir}/apparmor.d/namespaces.d/#{basename}\n" else # If a file is a symlink, it should be added manually # by the package where it is a symlink to. warn "File #{file} needs to be owned manually (2)." end end package["namespace_directories"]&.each do |directory| basename = File.basename directory definition += "%dir %{_sysconfdir}/apparmor.d/namespaces.d/#{basename}\n" #definition += "%config %{_sysconfdir}/apparmor.d/namespaces.d/#{basename}\n" end package["included_abstractions"]&.each do |file| basename = File.basename file definition += "%config(noreplace) %{_sysconfdir}/apparmor.d/abstractions/#{basename}\n" end package["included_tunables"]&.each do |file| basename = File.basename file definition += "%config(noreplace) %{_sysconfdir}/apparmor.d/tunables/#{basename}\n" end package["extra_directories"]&.each do |directory| definition += "%dir %{_sysconfdir}/apparmor.d/#{directory}\n" end package["extra_files"]&.each do |directory, files| config_tag = lambda do |filename| if filename[0..5] == "local/" "%config(noreplace)" else "%config" end end if files.nil? file = directory definition += "#{config_tag.call(file)} %{_sysconfdir}/apparmor.d/#{file}\n" else files.each do |file| definition += "#{config_tag.call(file)} %{_sysconfdir}/apparmor.d/#{file}\n" end end end package["load_profile_by_systemd"]&.each do |service_name, profile_name| definition += load_profile_by_systemd_for_profile service_name, profile_name end package["rpm_scriptlets_symlinks"]&.each do |file| basename = File.basename file definition += "%config %{_sysconfdir}/apparmor.d/namespaces.d/rpm-scriptlets.d/#{basename}\n" end package["in_directory"]&.each do |directory, hashes| hashes.each do |name, values| hash = { name => values } definition = generate_file_rows definition, hash end end definition end private def load_profile_by_systemd_for_profile service_name, profile_name definition = "" if [ "system", "system_conditional" ].include? service_name profile_name.each do |service_name, profile_name| if profile_name.respond_to? :each_pair profile_name = profile_name["profile"] end definition += "%dir %{_unitdir}/#{service_name}.service.d\n" definition += "%{_unitdir}/#{service_name}.service.d/#{profile_name}.conf\n" end return definition end #if [ "user", "user_conditional" ].include? service_name if service_name == "user" profile_name.each do |service_name, profile_name| if profile_name.respond_to? :each_pair profile_name = profile_name["profile"] end definition += "%dir %{_userunitdir}/#{service_name}.service.d\n" definition += "%{_userunitdir}/#{service_name}.service.d/#{profile_name}.conf\n" end return definition end definition += "%dir %{_unitdir}/#{service_name}.service.d\n" definition += "%{_unitdir}/#{service_name}.service.d/#{profile_name}.conf\n" definition end # WARNING: This is not too safe to use, so trust the yaml files. private def load_packages main = YAML.load_file "main.yaml" packages = [] main["includes"].each do |file| packages += YAML.load_file(file) end packages.sort do |a, b| # rpm needs to be first as some other profiles requires # namespaces.d/rpm-scriptlets.d/ dir it creates. next -1 if a["name"] == "rpm" next 1 if b["name"] == "rpm" a["name"] <=> b["name"] end end end generate_spec = GenerateSpec.new generate_spec.generate generate_spec.finalize
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Contact
Support
@OBShq
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor