shadow ресурс
Используйте ресурс аудита Chef InSpec, чтобы проверить содержимое /etc/shadow, которое содержит данные паролей, доступные только пользователю root. shadow — это ресурс множественного числа. Как и все ресурсы множественного числа, он работает путём поиска по нескольким записям в файле shadow.
Формат /etc/shadow включает:
- Имя пользователя
- Хэшированный пароль для этого пользователя
- Последнюю дату смены пароля в виде числа дней, прошедших с 1 января 1970 года
- Минимальное количество дней, в течение которых пароль должен существовать, прежде чем его можно будет изменить
- Максимальное количество дней, по истечении которых пароль необходимо сменить
- Количество дней, в течение которых пользователю сообщается о том, что его пароль истекает
- Количество дней, в течение которых пользователь должен быть неактивным, прежде чем его учетная запись будет отключена
- Дату отключения учетной записи пользователя в виде числа дней, прошедших с 1 января 1970 года
Эти записи определены как строки, разделённые двоеточием, по одной строке на пользователя в файле:
dannos:Gb7crrO5CDF.:10063:0:99999:7:::
Ресурс shadow понимает этот формат, позволяет искать по полям и предоставляет свойства выбранных пользователей.
Доступность
Установка
Этот ресурс распространяется вместе с самим Chef InSpec. Вы можете использовать его автоматически.
Версия
Этот ресурс впервые стал доступен в версии v1.0.0 InSpec.
Параметры ресурса
Ресурс shadow принимает один необязательный параметр: путь к файлу shadow. Если он опущен, предполагается /etc/shadow.
# Expect a file to exist at the default location and have 32 users
describe shadow do
its('count') { should eq 32 }
end
# Use a custom location
describe shadow('/etc/my-custom-place/shadow') do
its('count') { should eq 32 }
end
Примеры
Блок ресурса shadow использует where для фильтрации записей из файла shadow. Если where опущено, выбираются все записи.
# Select all users. Among them, there should not be a user with the name 'forbidden_user'.
describe shadow do
its('users') { should_not include 'forbidden_user' }
end
# Ensure there is only one user named 'root' (Select all with name 'root', then count them).
describe shadow.where(user: 'root') do
its('count') { should eq 1 }
end
Используйте where для соответствия любым из поддерживаемых критериям фильтрации. where имеет форму метода для простого равенства и форму блока для более сложных запросов.
# Method form, simple
# Select just the root user (direct equality)
describe shadow.where(user: 'root') do
its ('count') { should eq 1 }
end
# Method form, with a regex
# Select all users whose names begin with smb
describe shadow.where(user: /^smb/) do
its ('count') { should eq 2 }
end
# Block form
# Select users whose passwords have expired
describe shadow.where { expiry_date > 0 } do
# This test directly asserts that there should be 0 such users
its('count') { should eq 0 }
# But if the count test fails, this test outputs the users that are causing the failure.
its('users') { should be_empty }
end
Используйте where с синтаксисом expect, чтобы отобразить всех пользователей (которые не отключены и не заблокированы) без паролей, хэшированных с помощью SHA512.
# Users with password fields that are not *, !, or don't begin with $6$
bad_users = inspec.shadow.where { password !~ /^[*!]$|^\$6\$.*/ }.users
describe 'Password hashes in /etc/shadow' do
it 'should only contain SHA512 hashes' do
message = "Users without SHA512 hashes: #{bad_users.join(', ')}"
expect(bad_users).to be_empty, message
end
end
Свойства
В качестве ресурса множественного числа все свойства shadow возвращают списки (то есть, массивы Ruby). include и be_empty являются двумя полезными обработчиками при работе со списками. Вы также можете выполнять манипуляции со списками, такие как вызов uniq, sort, count, first, last, min, и max.
users
Список строк, представляющих имена пользователей, соответствующие фильтру.
describe shadow
its('users') { should include 'root' }
end
passwords
Список строк, представляющих зашифрованные строки паролей для записей, соответствующих фильтру where. Каждая строка может не быть зашифрованным паролем, а скорее * или аналогичным, что указывает на то, что прямые логины запрещены. Разные операционные системы используют разные флаги здесь (например, *LK* для указания того, что учетная запись заблокирована).
# Use uniq to remove duplicates, then determine
# if the only password left on the list is '*'
describe shadow.where(user: /adm$/) do
its('passwords.uniq.first') { should cmp '*' }
its('passwords.uniq.count') { should eq 1 }
end
last_changes
Список целых чисел, указывающих количество дней с 1 января 1970 года, прошедших с момента смены пароля для каждой соответствующей записи.
# Ensure all entries have changed their password in the last 90 days. (Probably want a filter on that)
describe shadow do
its('last_changes.min') { should be < Date.today - 90 - Date.new(1970,1,1) }
end
min_days
Список целых чисел, отражающих минимальное количество дней, в течение которых должен существовать пароль, прежде чем его можно будет изменить, для пользователей, соответствующих фильтру.
# min_days seems crazy today; make sure it is zero for everyone
describe shadow do
its('min_days.uniq') { should eq [0] }
end
max_days
Список целых чисел, отражающих максимальное количество дней, по истечении которых пароль должен быть изменен для каждого пользователя, соответствующего фильтру.
# Make sure there is no policy allowing longer than 90 days
describe shadow do
its('max_days.max') { should be < 90 }
end
warn_days
Список целых чисел, отражающих количество дней, в течение которых пользователю сообщается об истечении срока действия пароля для каждого пользователя, соответствующего фильтру.
# Ensure everyone gets the same 7-day policy
describe shadow do
its('warn_days.uniq.count') { should eq 1 }
its('warn_days.uniq.first') { should eq 7 }
end
inactive_days
Список целых чисел, отражающих количество дней, в течение которых пользователь должен быть неактивным, прежде чем его учетная запись будет отключена для каждого пользователя, соответствующего фильтру.
# Ensure everyone except admins has an stale policy of no more than 14 days
describe shadow.where { user !~ /adm$/ } do
its('inactive_days.max') { should be <= 14 }
end
expiry_dates
Список целых чисел, отражающих количество дней с 1 января 1970 года, в течение которых учетная запись пользователя была отключена для каждого пользователя, соответствующего фильтру. Значение nil если учетная запись не истекла.
# No one should have an expired account.
describe shadow do
its('expiry_dates.compact') { should be_empty }
end
count
Свойство count проверяет количество записей, соответствующих фильтру.
# Should probably only have one root user
describe shadow.user('root') do
its('count') { should eq 1 }
end
Критерии фильтрации
Вы можете использовать любой из этих критериев фильтрации с функцией where. Они названы в честь столбцов в файле shadow. Каждый из них имеет связанное свойство свойство списка.
user
Строка имени пользователя. Всегда присутствует. Не обязательно уникальна.
# Expect all users whose name ends in adm to have a disabled password via the '*' flag
describe shadow.where(user: /adm$/) do
its('password.uniq') { should eq ['*'] }
end
password
Зашифрованные строки паролей или строка статуса учетной записи. Каждая строка может не быть зашифрованным паролем, а скорее * или аналогичным, что указывает на то, что прямые логины запрещены. Разные операционные системы используют другие флаги здесь (например, *LK* для указания того, что учетная запись заблокирована).
# Find 'locked' accounts and ensure 'nobody' is on the list
describe shadow.where(password: '*LK*') do
its('users') { should include 'nobody' }
end
last_change
Целое число, отражающее количество дней с 1 января 1970 года с момента последней смены пароля пользователя.
# Find users who have not changed their password within 90 days
describe shadow.where { last_change > Date.today - 90 - Date.new(1970,1,1) } do
its('users') { should be_empty }
end
min_days
Целое число, отражающее минимальное количество дней, которые пользователь должен ждать, прежде чем снова изменить пароль.
# Find users who have a nonzero wait time
describe shadow.where { min_days > 0 } do
its('users') { should be_empty }
end
max_days
Целое число, отражающее максимальное количество дней, в течение которых пользователь может обойтись без смены пароля.
# All users should have a 30-day policy
describe shadow.where { max_days != 30 } do
its('users') { should be_empty }
end
warn_days
Целое число, отражающее количество дней до истечения срока действия пароля, когда пользователь получает уведомление.
# All users should have a 7-day warning policy
describe shadow.where { warn_days != 7 } do
its('users') { should be_empty }
end
inactive_days
Целое число, отражающее количество дней, которые должны пройти, прежде чем пользователь, который не входил в систему, будет отключен.
# Ensure everyone has a stale policy of no more than 14 days.
describe shadow.where { inactive_days.nil? || inactive_days > 14 } do
its('users') { should be_empty }
end
expiry_date
Целое число, отражающее количество дней с 1 января 1970 года, в которые пользователь был отключен. Критерий expiry_date равен nil для включённых пользователей.
# Ensure no one is disabled due to a old password
describe shadow.where { !expiry_date.nil? } do
its('users') { should be_empty }
end
# Ensure no one is disabled for more than 14 days
describe shadow.where { !expiry_date.nil? && expiry_date - Date.new(1970,1,1) > 14} do
its('users') { should be_empty }
end
Обработчики
У этого ресурса нет специфичных для ресурса обработчиков.
Полный список доступных обработчиков см. на нашей странице Универсальные обработчики.
© Chef Software, Inc.
Licensed under the Creative Commons Attribution 3.0 Unported License.
The Chef™ Mark and Chef Logo are either registered trademarks/service marks or trademarks/servicemarks of Chef, in the United States and other countries and are used with Chef Inc's permission.
We are not affiliated with, endorsed or sponsored by Chef Inc.
https://docs.chef.io/inspec/resources/shadow/