require "inspec/resources/command" # Usage: # describe yum do # its('repos') { should exist } # end # # describe yum do # its('repos') { should include 'base/7/x86_64' } # its('epel') { should exist } # its('epel') { should be_enabled } # end # # Filter for a specific repo by name # - use full identifier e.g. 'updates/7/x86_64' # - use short identifier e.g. 'updates' # # describe yum.repo('epel') do # it { should exist } # it { should be_enabled } # its('baseurl') { should include 'mycompany.biz' } # end # # deprecated: # describe yumrepo('epel') do # it { should exist } # it { should be_enabled } # end module Inspec::Resources class Yum < Inspec.resource(1) name "yum" supports platform: "unix" desc "Use the yum InSpec audit resource to test the configuration of Yum repositories." example <<~EXAMPLE describe yum.repo('name') do it { should exist } it { should be_enabled } end EXAMPLE # returns all repositories # works as following: # search for Repo-id # parse data in hashmap # store data in object # until \n def repositories return @cache if defined?(@cache) # parse the repository data from yum # we cannot use -C, because this is not reliable and may lead to errors @command_result = inspec.command("yum -v repolist all") @content = @command_result.stdout @cache = [] repo = {} in_repo = false @content.each_line do |line| # detect repo start in_repo = true if line =~ /^\s*Repo-id\s*:\s*(.*)\b/ # detect repo end if line == "\n" && in_repo in_repo = false @cache.push(repo) repo = {} end # parse repo content if in_repo == true val = /^\s*([^:]*?)\s*:\s*(.*?)\s*$/.match(line) repo[repo_key(strip(val[1]))] = strip(val[2]) end end @cache end def repos repositories.map { |repo| repo["id"] } end def repo(repo) YumRepo.new(self, repo) end # alias for yum.repo('reponame') def method_missing(name) repo(name.to_s) unless name.nil? end def to_s "Yum Repository" end private # Removes lefthand and righthand whitespace def strip(value) value&.strip end # Optimize the key value def repo_key(key) return key if key.nil? key.gsub("Repo-", "").downcase end end class YumRepo def initialize(yum, reponame) @yum = yum @reponame = reponame end # extracts the shortname from a repo id # e.g. extras/7/x86_64 -> extras def shortname(id) val = %r{^\s*([^/]*?)/(.*?)\s*$}.match(id) val.nil? ? nil : val[1] end def info return @cache if defined?(@cache) selection = @yum.repositories.select { |e| e["id"] == @reponame || shortname(e["id"]) == @reponame } @cache = selection.empty? ? {} : selection.first @cache end def exist? !info.empty? end def enabled? return false unless exist? info["status"] == "enabled" end # provide a method for each of the repo metadata items we know about %i{ baseurl expire filename mirrors pkgs size status updated }.each do |key| define_method key do info[key.to_s] end end def to_s "YumRepo #{@reponame}" end end end