Spec-Zone.ru › Chef 16

Chef InSpec DSL

[править на GitHub]

Chef InSpec — это фреймворк выполнения и язык правил, используемый для определения требований к соответствию, безопасности и политике. Он включает в себя набор ресурсов, которые помогут вам быстро и легко написать контрольные точки аудита. Синтаксис, используемый как для аудита открытого исходного кода, так и для аудита соответствия Chef, одинаков. Фреймворк ресурсов Chef InSpec с открытым исходным кодом совместим с соответствием Chef.

Chef InSpec DSL — это Ruby DSL для написания контрольных точек аудита, который включает в себя ресурсы аудита, которые вы можете вызвать.

В следующих разделах описан синтаксис и показаны некоторые простые примеры использования ресурсов Chef InSpec.

Синтаксис

Следующий ресурс тестирует конфигурацию сервера |ssh|. Например, простое правило может быть описано как:

describe sshd_config do
  its('Port') { should cmp 22 }
end

В различных сценариях использования, таких как внедрение соответствия ИТ по разным отделам, становится удобно расширять правило метаданными. Каждое правило может определять дополнительные impact, title или desc. Пример выглядит так:

control 'sshd-8' do
  impact 0.6
  title 'Server: Configure the service port'
  desc 'Always specify which port the SSH server should listen.'
  desc 'rationale', 'This ensures that there are no unexpected settings' # Requires Chef InSpec >=2.3.4
  tag 'ssh','sshd','openssh-server'
  tag cce: 'CCE-27072-8'
  ref 'NSA-RH6-STIG - Section 3.5.2.1', url: 'https://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf'

  describe sshd_config do
    its('Port') { should cmp 22 }
  end
end

где

  • 'sshd-8' — имя правила
  • impact, title, и desc определяют метаданные, которые полностью описывают важность правила, его назначение, с кратким и полным описанием
  • desc при передаче только одного аргумента устанавливает описание по умолчанию. Начиная с Chef InSpec 2.3.4, при передаче 2 аргументов (см.: 'rationale') он будет использовать первый аргумент в качестве заголовка при отображении в Automate
  • impact — строка или число, измеряющее важность результатов соответствия. Действительные строки для влияния — none, low, medium, high, и critical. Значения основаны на CVSS 3.0. Числовое значение должно быть в диапазоне от 0.0 до 1.0. Диапазоны значений:
    • 0.0 to <0.01 — это правила без влияния, они только предоставляют информацию
    • 0.01 to <0.4 — это правила с низким влиянием
    • 0.4 to <0.7 — это правила со средним влиянием
    • 0.7 to <0.9 — это правила с высоким влиянием
    • 0.9 to 1.0 — это критические правила
  • tag — это необязательная метаинформация с ключами или парами ключ-значение
  • ref — ссылка на внешний документ
  • describe — блок, который содержит по крайней мере одно испытание. Блок control должен содержать по крайней мере один блок describe, но может содержать любое необходимое количество
  • sshd_config — ресурс Chef InSpec. Полный список ресурсов Chef InSpec см. в документации по ресурсам Chef InSpec
  • its('Port') — соответствие; { should eq '22' } — тест. Блок describe должен содержать по крайней мере одно соответствие, но может содержать любое необходимое количество

Расширенные концепции

Проверка, проходит ли хотя бы одно условие с помощью describe.one

С помощью Chef InSpec вы можете проверить, истинно ли по крайней мере одно из набора проверок. Например, если вы настраиваете параметр в двух разных местах, то можете проверить, установлен ли параметр A или параметр B. Выполните эту задачу с помощью блока describe.one. describe.one определяет набор блоков describe , где должен пройти только один блок.

describe.one do
  describe ConfigurationA do
    its('setting_1') { should eq true }
  end

  describe ConfigurationB do
    its('setting_2') { should eq true }
  end
end

describe.one заметки по использованию

  • Блок describe.one проходит, если один из его вложенных блоков describe содержит все утверждения, которые проходят проверку. Блок describe.one требует, чтобы весь блок describe прошел проверку, а не только одно утверждение.
  • Chef InSpec всегда будет оценивать все тесты, содержащиеся в describe.one. Он не прерывается при оценке проходящего блока describe.
  • Вложение блока describe.one внутри другого блока describe.one не поддерживается.

Конфиденциальные ресурсы

В некоторых случаях вам может потребоваться писать проверки, которые включают ресурсы с конфиденциальным содержимым, например, ресурс файла. В случае сбоя вы можете подавить вывод. Сделайте это, добавив флаг :sensitive к определению ресурса:

describe file('/tmp/mysecretfile'), :sensitive do
  its('content') { should match /secret_info/ }
end

Примеры

В следующих примерах показаны простые проверки соответствия, использующие один блок control.

Проверка системного журнала событий

Следующий тест показывает, как проверить машины под управлением Windows 2012 R2, чтобы убедиться, что включена сложность паролей:

control 'windows-account-102' do
  impact 'critical'
  title 'Windows Password Complexity is Enabled'
  desc 'Password must meet complexity requirement'
  describe security_policy do
    its('PasswordComplexity') { should cmp 1 }
  end
end

Проверка, пустые ли пароли PostgreSQL

Следующий тест показывает, как проверить машины под управлением PostgreSQL, чтобы убедиться, что пароли не пустые.

control 'postgres-7' do
  impact 1.0
  title "Don't allow empty passwords"
  describe postgres_session('user', 'pass').query("SELECT * FROM pg_shadow WHERE passwd IS NULL;") do
    its('output') { should cmp '' }
  end
end

Проверка, находятся ли пароли MySQL в переменной среды

Следующий тест показывает, как проверить машины под управлением MySQL, чтобы убедиться, что пароли не хранятся в ENV:

control 'mysql-3' do
  impact 1.0
  title 'Do not store your MySQL password in your ENV'
  desc '
    Storing credentials in your ENV may easily expose
    them to an attacker. Prevent this at all costs.
  '
  describe command('env') do
    its('stdout') { should_not match /^MYSQL_PWD=/ }
  end
end

Проверка, является ли /etc/ssh каталогом

Следующий тест показывает, как проверить машины, чтобы убедиться, что /etc/ssh является каталогом:

control 'basic-1' do
  impact 1.0
  title '/etc/ssh should be a directory'
  desc '
    In order for OpenSSH to function correctly, its
    configuration path must be a folder.
  '
  describe file('/etc/ssh') do
    it { should be_directory }
  end
end

Проверка, запущен ли Apache

Следующий тест показывает, как проверить машины, чтобы убедиться, что Apache включен и запущен:

control 'apache-1' do
  impact 'medium'
  title 'Apache2 should be configured and running'
  describe service(apache.service) do
    it { should be_enabled }
    it { should be_running }
  end
end

Проверка, установлены ли небезопасные пакеты

Следующий тест показывает, как проверить машины на наличие небезопасных пакетов:

control 'cis-os-services-5.1.3' do
  impact 0.7
  title '5.1.3 Ensure rsh client is not installed'
  describe package('rsh') do
    it { should_not be_installed }
  end
  describe package('rsh-redone-client') do
    it { should_not be_installed }
  end
end

Проверка ключей реестра Windows

Следующий тест показывает, как проверить машины, чтобы убедиться, что режим безопасного поиска DLL включен:

control 'windows-base-101' do
  impact 1.0
  title 'Safe DLL Search Mode is Enabled'
  desc '
    @link: https://msdn.microsoft.com/en-us/library/ms682586(v=vs.85).aspx
  '
  describe registry_key('HKLM\\System\\CurrentControlSet\\Control\\Session Manager') do
    it { should exist }
    it { should_not have_property_value('SafeDllSearchMode', :type_dword, '0') }
  end
end

Использование only_if для исключения определенного правила

В этом примере показано, как пропустить определенные правила, если условия не выполнены, используя only_if. В этом примере правило не будет выполнено, если команда redis-cli не существует. Необязательное сообщение может указать причину пропуска.

control 'nutcracker-connect-redis-001' do
  impact 'critical'
  title 'Check if nutcracker can pass commands to redis'
  desc 'execute redis-cli set key command, to check connectivity of the service'

  only_if('redis is not installed.') do
    command('redis-cli').exist?
  end

  describe command('redis-cli SET test_inspec "HELLO"') do
    its('stdout') { should match /OK/ }
  end
end

В этом примере проверяется, установлены ли определенные пакеты pip, но только если существует ‘/root/.aws’:

control 'pip-packages-installed' do
  title 'Check if essential pips are installed'
  only_if('aws-cli config not created.') do
    directory('/root/.aws').exist?
  end
  %w(aws-mfa PyYAML awscli).each do |aws_pip_deps|
    describe pip(aws_pip_deps) do
      it { should be_installed }
    end
  end
end

Комбинирование этого с другими условными операторами, такими как проверка существования файлов, может помочь в тестировании различных путей тестов с помощью Chef InSpec. С помощью этого метода вы можете пропускать определенные правила, которые бы на 100% потерпели неудачу из-за способа подготовки серверов, но вы знаете, что те же наборы правил повторно используются позже в разных обстоятельствах разными командами.

Некоторые замечания о only_if:

  • only_if применяется ко всему блоку control. Если результаты блока only_if оцениваются как ложные, все ресурсы Chef InSpec, упомянутые в блоке describe , не будут выполняться. Кроме того, содержимое блоков describe не будет выполняться. Однако базовые выражения Ruby и базовые ресурсы Chef InSpec (не связанные с блоком describe) перед оператором only_if будут выполняться

Для иллюстрации:

control "whatruns" do
  command("do_something") # This will ALWAYS run
  describe command("do_another_thing") do # This will not run
    command("do_yet_another_thing") # This will not run
  end
  only_if { false }
  command("do_something_else") # This will not run
end
  • Только одно only_if разрешено в блоке control . Если несколько блоков only_if присутствуют, только последний блок only_if будет учтен
  • Если используется вне блока управления, only_if пропускает все правила в текущем файле
  • Для реализации сложной логики используйте операторы Ruby 'или' (||) и 'и' (&&) внутри блока only_if:
  only_if('ready for launch') do
    rocket_is_ready && weather_is_clear
  end

Дополнительные метаданные для правил

Следующий пример иллюстрирует различные способы добавления тегов и ссылок к control

control 'ssh-1' do
  impact 1.0

  title 'Allow only SSH Protocol 2'
  desc '
    Only SSH protocol version 2 connections should be permitted.
    The default setting in /etc/ssh/sshd_config is correct, and can be
    verified by ensuring that the following line appears: Protocol 2
  '

  tag 'production','development'
  tag 'ssh','sshd','openssh-server'

  tag cce: 'CCE-27072-8'
  tag disa: 'RHEL-06-000227'

  tag remediation: 'stig_rhel6/recipes/sshd-config.rb'
  tag remediation: 'https://supermarket.chef.io/cookbooks/ssh-hardening'

  ref 'NSA-RH6-STIG - Section 3.5.2.1', url: 'https://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf'
  ref 'http://people.redhat.com/swells/scap-security-guide/RHEL/6/output/ssg-centos6-guide-C2S.html'

  describe ssh_config do
    its('Protocol') { should cmp 2 }
  end
end

Использование Ruby в InSpec

Chef InSpec DSL — это язык на основе Ruby. Это позволяет гибко использовать код Ruby в правилах:

json_obj = json('/file.json')
json_obj['keys'].each do |value|
  ..
end

Ruby предоставляет много возможностей, но их следует ограничивать в правилах, чтобы они оставались переносимыми и понятными. См. наш справочник по стилю профиля.

Ядра и настраиваемые ресурсы написаны как обычные классы Ruby, которые наследуют от Inspec.resource.

Интерактивная отладка с помощью Pry

Вот пример правила Chef InSpec, которое использует переменные Ruby для инициализации ресурса Chef InSpec один раз и использования содержимого в нескольких тестах.

control 'check-perl' do
  impact 0.3
  title 'Check perl compiled options and permissions'
  perl_out = command('perl -V')
  #require 'pry'; binding.pry;
  describe perl_out do
    its('exit_status') { should eq 0 }
    its('stdout') { should match /USE_64_BIT_ALL/ }
    its('stdout') { should match /useposix=true/ }
    its('stdout') { should match /-fstack-protector/ }
  end

  # extract an array of include directories
  perl_inc = perl_out.stdout.partition('@INC:').last.strip.split("\n")
  # ensure include directories are only writable by 'owner'
  perl_inc.each do |path|
    describe directory(path.strip) do
      it { should_not be_writable.by 'group' }
      it { should_not be_writable.by 'other' }
    end
  end
end

Полезный, но расширенный совет по Ruby. В предыдущем примере я закомментировал строку require 'pry'; binding.pry;. Если вы удалите префикс # и запустите правило, выполнение остановится на этой строке и предоставит вам оболочку pry. Используйте ее для отладки, вывода переменных, просмотра доступных методов и т. д. Для приведенного выше примера:

[1] pry> perl_out.exit_status
=> 0
[2] pry> perl_out.stderr
=> ""
[3] pry> ls perl_out
Inspec::Plugins::Resource#methods: inspect
Inspec::Resources::Cmd#methods: command  exist?  exit_status  result  stderr  stdout  to_s
Inspec::Resource::Registry::Command#methods: inspec
instance variables: @__backend_runner__  @__resource_name__  @command  @result
[4] pry> perl_out.stdout.partition('@INC:').last.strip.split("\n")
=> ["/Library/Perl/5.18/darwin-thread-multi-2level",
 "    /Library/Perl/5.18",
...REDACTED...
[5] pry> exit    # or abort

Вы можете использовать pry как в DSL правил, так и в ресурсах. Аналогично, для разработки и тестирования вы можете использовать inspec shell, основанный на pry, например:

$ inspec shell
Welcome to the interactive InSpec Shell
To find out how to use it, type: help

inspec> command('ls ~/projects/github/inspec/docs').stdout
=> "README.md\nconfig.md\ndev\ndsl_inspec.md\ndsl_resource.md\nglossary.md\nhabitat.md\ninputs.md\ninspec_and_friends.md\nmatchers.md\nmigration.md\nplatforms.md\nplugin_kitchen_inspec.md\nplugins.md\nprofiles.md\nreporters.md\nresources\nshared\nshell.md\nstyle.md\nwaivers.md\n"
inspec> command('ls ~/projects/github/inspec/docs').stdout.split("\n").first
=> "README.md"

inspec> help command
Name: command

Description:
Use the command InSpec audit resource to test an arbitrary command that is run on the system.

Example:
describe command('ls -al /') do
  it { should exist }
  its('stdout') { should match /bin/ }
  its('stderr') { should eq '' }
  its('exit_status') { should eq 0 }
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/dsl_inspec/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API