shadow ресурс
Используйте 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/