class Inspec::Resources::AuditDaemon

def action_list_for(line)

def action_list_for(line)
  line.scan(/-a ([^,]+),([^ ]+)\s?/).flatten
end

def arch_in(fields)

def arch_in(fields)
  fields.each do |field|
    return field.match(/arch=(\S+)\s?/)[1] if field.start_with?('arch=')
  end
  nil
end

def exit_in(fields)

def exit_in(fields)
  fields.each do |field|
    return field.match(/exit=(\S+)\s?/)[1] if field.start_with?('exit=')
  end
  nil
end

def file_for(line)

def file_for(line)
  line.match(/-w ([^ ]+)\s?/)[1]
end

def file_rules_for(line)

def file_rules_for(line)
  file = file_for(line)
  perms = permissions_for(line)
  key = key_for(line)
  @params.push(
    {
      'file' => file,
      'key' => key,
      'permissions' => perms,
    },
  )
end

def file_syscall_syntax_for(line)

def file_syscall_syntax_for(line)
  line.match(/-F path=(\S+)\s?/)[1]
end

def file_syscall_syntax_rules_for(line)

def file_syscall_syntax_rules_for(line)
  file = file_syscall_syntax_for(line)
  action, list = action_list_for(line)
  fields = rule_fields_for(line)
  key_field, fields_nokey = remove_key_from(fields)
  key = key_in(key_field.join(''))
  perms = perms_in(fields)
  @params.push(
    {
      'file' => file,
      'list' => list,
      'action' => action,
      'fields' => fields,
      'permissions' => perms,
      'key' => key,
      'fields_nokey' => fields_nokey,
    },
  )
end

def initialize

def initialize
  unless inspec.command('/sbin/auditctl').exist?
    raise Inspec::Exceptions::ResourceFailed,
          'Command `/sbin/auditctl` does not exist'
  end
  auditctl_cmd = '/sbin/auditctl -l'
  result = inspec.command(auditctl_cmd)
  if result.exit_status != 0
    raise Inspec::Exceptions::ResourceFailed,
          "Command `#{auditctl_cmd}` failed with error: #{result.stderr}"
  end
  @content = result.stdout
  @params = []
  if @content =~ /^LIST_RULES:/
    raise Inspec::Exceptions::RsourceFailed,
          'The version of audit is outdated.' \
          'The `auditd` resource supports versions of audit >= 2.3.'
  end
  parse_content
end

def is_file?(line)

def is_file?(line)
  line.match(/-w /)
end

def is_file_syscall_syntax?(line)

def is_file_syscall_syntax?(line)
  line.match(/-F path=/)
end

def is_syscall?(line)

def is_syscall?(line)
  line.match(/-S /)
end

def key_for(line)

def key_for(line)
  line.match(/-k ([^ ]+)\s?/)[1] if line.include?('-k ')
end

def key_in(field)

def key_in(field)
  _, v = field.split('=')
  v
end

def parse_content

def parse_content
  @lines = @content.lines.map(&:chomp)
  lines.each do |line|
    if is_file_syscall_syntax?(line)
      file_syscall_syntax_rules_for(line)
    end
    if is_syscall?(line)
      syscall_rules_for(line)
    elsif is_file?(line)
      file_rules_for(line)
    end
  end
end

def path_in(fields)

def path_in(fields)
  fields.each do |field|
    return field.match(/path=(\S+)\s?/)[1] if field.start_with?('path=')
  end
  nil
end

def permissions_for(line)

def permissions_for(line)
  line.match(/-p ([^ ]+)/)[1].scan(/\w/)
end

def perms_in(fields)

def perms_in(fields)
  fields.each do |field|
    return field.match(/perm=(\S+)\s?/)[1].scan(/\w/) if field.start_with?('perm=')
  end
  nil
end

def remove_key_from(fields)

def remove_key_from(fields)
  fields.partition { |x| x.start_with? 'key' }
end

def rule_fields_for(line)

def rule_fields_for(line)
  line.gsub(/-[aS] [^ ]+ /, '').split('-F ').map { |l| l.split(' ') }.flatten
end

def status(name = nil)

def status(name = nil)
  @status_content ||= inspec.command('/sbin/auditctl -s').stdout.chomp
  # See: https://github.com/inspec/inspec/issues/3113
  if @status_content =~ /^AUDIT_STATUS/
    @status_content = @status_content.gsub('AUDIT_STATUS: ', '')
                                     .tr(' ', "\n")
                                     .tr('=', ' ')
  end
  @status_params ||= Hash[@status_content.scan(/^([^ ]+) (.*)$/)]
  return @status_params[name] if name
  @status_params
end

def syscall_rules_for(line)

def syscall_rules_for(line)
  syscalls = syscalls_for(line)
  action, list = action_list_for(line)
  fields = rule_fields_for(line)
  key_field, fields_nokey = remove_key_from(fields)
  key = key_in(key_field.join(''))
  arch = arch_in(fields)
  path = path_in(fields)
  perms = perms_in(fields)
  exit_field = exit_in(fields)
  syscalls.each do |s|
    @params.push(
      {
        'syscall' => s,
        'list' => list,
        'action' => action,
        'fields' => fields,
        'key' => key,
        'arch' => arch,
        'path' => path,
        'permissions' => perms,
        'exit' => exit_field,
        'fields_nokey' => fields_nokey,
      },
    )
  end
end

def syscalls_for(line)

def syscalls_for(line)
  line.scan(/-S ([^ ]+)\s?/).flatten.first.split(',')
end

def to_s

def to_s
  'Auditd Rules'
end