coi-gov-pl/puppet-jboss

View on GitHub
lib/puppet_x/coi/jboss/internal/securitydomain_auditor.rb

Summary

Maintainability
A
2 hrs
Test Coverage
# Internal class to audits what is the state of securitydomain in Jboss instance
# Do not use outside of securitydomain provider
class PuppetX::Coi::Jboss::Internal::SecurityDomainAuditor
  # Standard constructor
  # @param resource [Hash] standard puppet resource object
  # @param cli_executor [PuppetX::Coi::Jboss::Internal::CliExecutor] that will handle execution of command
  # @param compilator [PuppetX::Coi::Jboss::Internal::CommandCompilator] object that handles
  # compilaton of command to be executed
  # @param destroyer [PuppetX::Coi::Jboss::Internal::SecurityDomainDestroyer] object that handles removing of
  # securitydomain
  def initialize(resource, cli_executor, compilator, destroyer)
    @resource = resource
    @cli_executor = cli_executor
    @compilator = compilator
    @destroyer = destroyer
  end

  def state
    exists?
    fetch_securtydomain_state
  end

  # Method that checks if securitydomain exists
  # @return [Boolean] returns true if security-domain exists in any state
  def exists?
    return @result unless @result.nil?
    raw_result = read_resource_recursive
    unless raw_result[:result]
      Puppet.debug 'Security Domain does NOT exist'
      return false
    end
    Puppet.debug("Raw result: #{raw_result.inspect}")
    @result = resolve_state(raw_result[:data], @resource)
    @result
  end

  private

  # Internal mathod that saves current state of every subpath of securitydomain
  def fetch_securtydomain_state
    data = @state
    fetched_state = PuppetX::Coi::Jboss::Internal::State::SecurityDomainState.new
    if data['security-domain'][(@resource[:name]).to_s]
      if data['security-domain'][(@resource[:name]).to_s]['cache-type'].nil?
        Puppet.debug('cache-type is nil')
        fetched_state.is_cache_default = false
      else
        fetched_state.is_cache_default = true
      end
      auth = data['security-domain'][(@resource[:name]).to_s]['authentication']
      if auth.nil?
        Puppet.debug('Authentication is nil')
        fetched_state.is_authentication = false
      else
        fetched_state.is_authentication = true
      end
      if !auth.nil? && (data['security-domain'][(@resource[:name]).to_s]['authentication']['classic']['login-modules'].nil? || data['security-domain'][(@resource[:name]).to_s]['authentication']['classic']['login-modules'][0]['module-options'].nil?)
        Puppet.debug('Login modules are nil')
        fetched_state.is_login_modules = false
      end
    end

    fetched_state
  end

  # Method that handles execution of command
  def read_resource_recursive
    cmd = @compilator.compile(
      @resource[:runasdomain],
      @resource[:profile],
      '/subsystem=security:read-resource(recursive=true)'
    )
    conf = {
      :controller => @resource[:controller],
      :ctrluser   => @resource[:ctrluser],
      :ctrlpasswd => @resource[:ctrlpasswd]
    }
    try = PuppetX::Coi::Jboss::Value::Try::ZERO
    @cli_executor.execute_and_get(cmd, @resource[:runasdomain], conf, try)
  end

  # Method prepares lines outputed by JBoss CLI tool, changing output to be readable in Ruby
  # @param lines [string[]]
  def preparelines(lines)
    lines.
      gsub(/\((\"[^\"]+\") => (\"[^\"]+\")\)/, '\1 => \2').
      gsub(/\[((?:[\n\s]*\"[^\"]+\" => \"[^\"]+\",?[\n\s]*)+)\]/m, '{\1}')
  end

  # Method that checks current situation of security-domain in Jboss instance
  # @param actual_data [Hash] output of recursive read of security-domain resource
  # @param resource [Hash] reference to standard puppet resource object
  # @return [Boolean] return true if security-domain with given name exists in any state
  def resolve_state(actual_data, resource)
    @state = actual_data
    unless actual_data.key? 'security-domain'
      Puppet.debug('There is no securitydomain at all')
      return false
    end

    Puppet.debug "Security Domain exists: #{actual_data.inspect}"

    givenhash = build_givenhash(resource)

    path_in_state = [
      'security-domain',
      resource[:name].to_s,
      'authentication',
      'classic',
      'login-modules',
      0,
      'module-options'
    ]

    nil_checker = get_nillable_from_hash_iterative(actual_data, path_in_state)

    Puppet.debug("Value of nil checker: #{nil_checker}")
    return false if nil_checker.nil?

    state_login_modules = array_keys_to_hash_value(actual_data, path_in_state)
    existinghash = build_existinghash(state_login_modules)

    if !existinghash.nil? && !givenhash.nil? && existinghash != givenhash
      diff = givenhash.to_a - existinghash.to_a
      Puppet.notice("Security domain should be recreated. Diff: #{diff.inspect}")
      Puppet.debug("Security domain moduleoptions existing hash => #{existinghash.inspect}")
      Puppet.debug("Security domain moduleoptions given hash => #{givenhash.inspect}")
      @destroyer.destroy(resource)
      return false
    end
    true
  end

  # Method that will build hash that holds informations about state that is desired
  # @param data [Hash]
  # @return [Hash] givenhash with informations about setting of security-domain
  def build_givenhash(data)
    givenhash = {}
    unless data[:moduleoptions].nil?
      data[:moduleoptions].each do |key, value|
        givenhash[key.to_s] = value.to_s.tr("\n", ' ').strip
      end
    end
    givenhash
  end

  # Method that will build hash that holds informations about actual settings of security-domain
  # @param data [Hash]
  # @return [Hash] existinghash with informations about desired setting of security-domain
  def build_existinghash(data)
    existinghash = {}
    data.each do |key, value|
      existinghash[key.to_s] = value.to_s.tr("\n", ' ').strip
    end
    existinghash
  end

  # Method that return value of last given in param
  # @param data [Hash] hash that holds desired information
  # @param keys [Array] array of keys in correct order that will be used to exctract value
  # @return [Object] tmp_data value of last key in keys parameter
  def array_keys_to_hash_value(data, keys)
    tmp_data = data
    keys.each do |key|
      tmp_data = tmp_data[key]
    end
    tmp_data
  end

  # Iterative method that check if there is nil value in given hash under keys that are given
  # as parameters
  # @param hash [Hash] hash that will be checked
  # @param keys [Array] keys that will be used to check if their value is null
  # @return [String] result will be nil if there is nill value under key in given hash or true if there is no nil value
  def get_nillable_from_hash_iterative(hash, keys)
    data = hash
    keys.each do |key|
      return nil if data[key].nil?
      data = data[key]
    end
  end
end