# copyright: 2015, Vulcano Security GmbH

# The file format consists of
# - username
# - password
# - userid
# - groupid
# - user id info
# - home directory
# - command

require "inspec/utils/parser"
require "inspec/utils/filter"
require "inspec/utils/file_reader"

module Inspec::Resources
  class Passwd < Inspec.resource(1)
    name "passwd"
    supports platform: "unix"
    desc "Use the passwd InSpec audit resource to test the contents of /etc/passwd, which contains the following information for users that may log into the system and/or as users that own running processes."
    example <<~EXAMPLE
      describe passwd do
        its('users') { should_not include 'forbidden_user' }
      end

      describe passwd.uids(0) do
        its('users') { should cmp 'root' }
      end

      describe passwd.shells(/nologin/) do
        # find all users with a nologin shell
        its('users') { should_not include 'my_login_user' }
      end
    EXAMPLE

    include Inspec::Utils::PasswdParser
    include FileReader

    attr_reader :params
    attr_reader :content
    attr_reader :lines

    def initialize(path = nil, opts = nil)
      opts ||= {}
      @path = path || "/etc/passwd"
      @content = opts[:content] || read_file_content(@path, allow_empty: true)
      @lines = @content.to_s.split("\n")
      @params = parse_passwd(@content)
    end

    filter = FilterTable.create
    filter.register_column(:users, field: "user")
      .register_column(:passwords, field: "password")
      .register_column(:uids,      field: "uid")
      .register_column(:gids,      field: "gid")
      .register_column(:descs,     field: "desc")
      .register_column(:homes,     field: "home")
      .register_column(:shells,    field: "shell")

    # rebuild the passwd line from raw content
    filter.register_custom_property(:content) do |t, _|
      t.entries.map do |e|
        [e.user, e.password, e.uid, e.gid, e.desc, e.home, e.shell].join(":")
      end.join("\n")
    end

    filter.install_filter_methods_on_resource(self, :params)

    def to_s
      "/etc/passwd"
    end
  end
end
