* upstream has new options now included in formula * updated pillar.example with new options * inspec tests for this new options are in place Also: * tests are included in travis Signed-off-by: Felipe Zipitria <fzipitria@perceptyx.com>tags/v0.10.0
## Define the rest of the matrix based on Kitchen testing | ## Define the rest of the matrix based on Kitchen testing | ||||
# Make sure the instances listed below match up with | # Make sure the instances listed below match up with | ||||
# the `platforms` defined in `kitchen.yml` | # the `platforms` defined in `kitchen.yml` | ||||
- env: INSTANCE=repositories-debian-10-master-py3 | |||||
- env: INSTANCE=preferences-debian-10-master-py3 | |||||
# - env: INSTANCE=repositories-ubuntu-1804-master-py3 | |||||
# - env: INSTANCE=repositories-debian-10-master-py3 | |||||
# - env: INSTANCE=preferences-debian-10-master-py3 | |||||
# - env: INSTANCE=unattended-debian-10-master-py3 | |||||
- env: INSTANCE=debian-10-master-py3 | |||||
- env: INSTANCE=repositories-ubuntu-1804-master-py3 | |||||
# - env: INSTANCE=preferences-ubuntu-1804-master-py3 | # - env: INSTANCE=preferences-ubuntu-1804-master-py3 | ||||
- env: INSTANCE=repositories-debian-9-2019-2-py3 | |||||
# - env: INSTANCE=unattended-ubuntu-1804-master-py3 | |||||
# - env: INSTANCE=ubuntu-1804-master-py3 | |||||
# - env: INSTANCE=repositories-debian-9-2019-2-py3 | |||||
- env: INSTANCE=preferences-debian-9-2019-2-py3 | - env: INSTANCE=preferences-debian-9-2019-2-py3 | ||||
- env: INSTANCE=repositories-ubuntu-1804-2019-2-py3 | |||||
- env: INSTANCE=preferences-ubuntu-1804-2019-2-py3 | |||||
# - env: INSTANCE=unattended-debian-9-2019-2-py3 | |||||
# - env: INSTANCE=debian-9-2019-2-py3 | |||||
# - env: INSTANCE=repositories-ubuntu-1804-2019-2-py3 | |||||
# - env: INSTANCE=preferences-ubuntu-1804-2019-2-py3 | |||||
- env: INSTANCE=unattended-ubuntu-1804-2019-2-py3 | |||||
# - env: INSTANCE=ubuntu-1804-2019-2-py3 | |||||
## Define the release stage that runs `semantic-release` | ## Define the release stage that runs `semantic-release` | ||||
- stage: 'release' | - stage: 'release' |
######################################################################## | |||||
# File managed by Salt at <{{ source }}>. | |||||
# Your changes will be overwritten. | |||||
######################################################################## | |||||
{% set apt = pillar.get('apt', {}) -%} | {% set apt = pillar.get('apt', {}) -%} | ||||
{% set unattended = apt.get('unattended', {}) -%} | {% set unattended = apt.get('unattended', {}) -%} | ||||
{% set allowed_origins = unattended.get('allowed_origins', ['${distro_id}:${distro_codename}-security']) -%} | {% set allowed_origins = unattended.get('allowed_origins', ['${distro_id}:${distro_codename}-security']) -%} | ||||
{% set auto_fix_interrupted_dpkg = unattended.get('auto_fix_interrupted_dpkg', 'true') -%} | {% set auto_fix_interrupted_dpkg = unattended.get('auto_fix_interrupted_dpkg', 'true') -%} | ||||
{% set minimal_steps = unattended.get('minimal_steps', 'false') -%} | {% set minimal_steps = unattended.get('minimal_steps', 'false') -%} | ||||
{% set install_on_shutdown = unattended.get('install_on_shutdown', 'false') -%} | {% set install_on_shutdown = unattended.get('install_on_shutdown', 'false') -%} | ||||
{% set mail = unattended.get('mail', 'root') -%} | |||||
{% set mail = unattended.get('mail', '') -%} | |||||
{% set sender = unattended.get('sender', 'root') -%} | |||||
{% set mail_only_on_error = unattended.get('mail_only_on_error', 'false') -%} | {% set mail_only_on_error = unattended.get('mail_only_on_error', 'false') -%} | ||||
{% set remove_unused_dependencies = unattended.get('remove_unused_dependencies', 'true') -%} | |||||
{% set mail_report = unattended.get('mail_report', 'on-change') -%} | |||||
{% if mail_only_on_error -%} | |||||
{% set mail_report = 'only-on-error' -%} | |||||
{% endif -%} | |||||
{% if mail_report not in ['always', 'only-on-error', 'on-change'] -%} | |||||
{{ raise('apt-formula: mail_report should be one of "always", "only-on-error" or "on-change".') }} | |||||
{% endif -%} | |||||
{% set remove_unused_dependencies = unattended.get('remove_unused_dependencies', 'false') -%} | |||||
{% set remove_new_unused_dependencies = unattended.get('remove_new_unused_dependencies', 'true') -%} | |||||
{% set automatic_reboot = unattended.get('automatic_reboot', 'false') -%} | {% set automatic_reboot = unattended.get('automatic_reboot', 'false') -%} | ||||
{% set automatic_reboot_time = unattended.get('automatic_reboot_time', 'now') -%} | {% set automatic_reboot_time = unattended.get('automatic_reboot_time', 'now') -%} | ||||
{% set dl_limit = unattended.get('dl_limit', '0') -%} | {% set dl_limit = unattended.get('dl_limit', '0') -%} | ||||
{% set syslog_enable = unattended.get('syslog_enable', 'false') -%} | |||||
{% set syslog_facility = unattended.get('syslog_facility', 'daemon') -%} | |||||
{% set package_whitelist_strict = unattended.get('package_whitelist_strict', 'false') -%} | |||||
{% set keep_debs_after_install = unattended.get('keep_debs_after_install', 'false') -%} | |||||
{% set dpkg_options = unattended.get('dpkg_options', '') -%} | |||||
{% set update_days = unattended.get('update_days', '') -%} | |||||
Unattended-Upgrade::Allowed-Origins { | Unattended-Upgrade::Allowed-Origins { | ||||
{%- for pattern in allowed_origins %} | {%- for pattern in allowed_origins %} | ||||
"{{ pattern }}"; | "{{ pattern }}"; | ||||
Unattended-Upgrade::MinimalSteps "{{ minimal_steps }}"; | Unattended-Upgrade::MinimalSteps "{{ minimal_steps }}"; | ||||
Unattended-Upgrade::InstallOnShutdown "{{ install_on_shutdown }}"; | Unattended-Upgrade::InstallOnShutdown "{{ install_on_shutdown }}"; | ||||
Unattended-Upgrade::Mail "{{ mail }}"; | Unattended-Upgrade::Mail "{{ mail }}"; | ||||
Unattended-Upgrade::MailOnlyOnError "{{ mail_only_on_error }}"; | |||||
Unattended-Upgrade::Sender "{{ sender }}"; | |||||
Unattended-Upgrade::MailReport "{{ mail_report }}"; | |||||
Unattended-Upgrade::Remove-Unused-Dependencies "{{ remove_unused_dependencies }}"; | Unattended-Upgrade::Remove-Unused-Dependencies "{{ remove_unused_dependencies }}"; | ||||
Unattended-Upgrade::Remove-New-Unused-Dependencies "{{ remove_new_unused_dependencies }}"; | |||||
Unattended-Upgrade::Automatic-Reboot "{{ automatic_reboot }}"; | Unattended-Upgrade::Automatic-Reboot "{{ automatic_reboot }}"; | ||||
Unattended-Upgrade::Automatic-Reboot-Time "{{ automatic_reboot_time }}"; | Unattended-Upgrade::Automatic-Reboot-Time "{{ automatic_reboot_time }}"; | ||||
Unattended-Upgrade::SyslogEnable "{{ syslog_enable }}"; | |||||
Unattended-Upgrade::SyslogFacility "{{ syslog_facility }}"; | |||||
Unattended-Upgrade::Keep-Debs-After-Install "{{ keep_debs_after_install }}"; | |||||
Unattended-Upgrade::Package-Whitelist-Strict "{{ package_whitelist_strict }}"; | |||||
{% if update_days and update_days | is_list -%} | |||||
Unattended-Upgrade::Update-Days {"{{ update_days | join('";"') }}"}; | |||||
{% endif -%} | |||||
Acquire::http::Dl-Limit "{{ dl_limit }}"; | Acquire::http::Dl-Limit "{{ dl_limit }}"; | ||||
{% if dpkg_options -%} | |||||
Dpkg::Options {"{{ dpkg_options }}"}; | |||||
{% endif -%} |
verifier: | verifier: | ||||
inspec_tests: | inspec_tests: | ||||
- path: test/integration/preferences | - path: test/integration/preferences | ||||
- name: unattended | |||||
provisioner: | |||||
state_top: | |||||
base: | |||||
'*': | |||||
- apt.unattended | |||||
pillars: | |||||
top.sls: | |||||
base: | |||||
'*': | |||||
- apt | |||||
pillars_from_files: | |||||
apt.sls: test/salt/pillar/unattended.pillar.sls | |||||
verifier: | |||||
inspec_tests: | |||||
- path: test/integration/unattended |
minimal_steps: false | minimal_steps: false | ||||
install_on_shutdown: false | install_on_shutdown: false | ||||
mail: root | mail: root | ||||
mail_only_on_error: false | |||||
sender: root | |||||
# Prefer using `mail_report: 'only-on-error'` over old syntax, | |||||
# mail_only_on_error: false` | |||||
# allowed values: 'always', 'only-on-error', 'on-change' | |||||
mail_report: 'only-on-error' | |||||
remove_unused_dependencies: true | remove_unused_dependencies: true | ||||
automatic_reboot: false | automatic_reboot: false | ||||
dl_limit: 0 | dl_limit: 0 | ||||
unattended_upgrade: 1 | unattended_upgrade: 1 | ||||
auto_clean_interval: 7 | auto_clean_interval: 7 | ||||
verbose: 2 | verbose: 2 | ||||
syslog_enable: true | |||||
syslog_facility: 'auth' | |||||
dpkg_options: '--force-confold' | |||||
update_days: ['Mon', 'Fri'] | |||||
package_whitelist_strict: false | |||||
keep_debs_after_install: false | |||||
listchanges: | listchanges: | ||||
profiles: | profiles: | ||||
comps: [main, contrib, non-free] | comps: [main, contrib, non-free] | ||||
arch: [amd64, i386] | arch: [amd64, i386] | ||||
type: [binary, source] | type: [binary, source] | ||||
key_url: https://ftp-master.debian.org/keys/archive-key-10-security.asc | |||||
updates: | updates: | ||||
distro: stable-updates | distro: stable-updates | ||||
url: http://deb.debian.org/debian/ | url: http://deb.debian.org/debian/ | ||||
comps: [main, contrib, non-free] | comps: [main, contrib, non-free] | ||||
key_url: https://ftp-master.debian.org/keys/archive-key-10.asc | |||||
raspbian: | raspbian: | ||||
distro: wheezy | |||||
distro: stable | |||||
url: http://archive.raspbian.org/raspbian | url: http://archive.raspbian.org/raspbian | ||||
type: [source] | type: [source] | ||||
key_url: https://archive.raspbian.org/raspbian.public.key | key_url: https://archive.raspbian.org/raspbian.public.key |
# InSpec Profile: `unattended` | |||||
This shows the implementation of the `unattended` InSpec [profile](https://github.com/inspec/inspec/blob/master/docs/profiles.md). | |||||
## Verify a profile | |||||
InSpec ships with built-in features to verify a profile structure. | |||||
```bash | |||||
$ inspec check unattended | |||||
Summary | |||||
------- | |||||
Location: unattended | |||||
Profile: profile | |||||
Controls: 4 | |||||
Timestamp: 2019-06-24T23:09:01+00:00 | |||||
Valid: true | |||||
Errors | |||||
------ | |||||
Warnings | |||||
-------- | |||||
``` | |||||
## Execute a profile | |||||
To run all **supported** controls on a local machine use `inspec exec /path/to/profile`. | |||||
```bash | |||||
$ inspec exec unattended | |||||
.. | |||||
Finished in 0.0025 seconds (files took 0.12449 seconds to load) | |||||
8 examples, 0 failures | |||||
``` | |||||
## Execute a specific control from a profile | |||||
To run one control from the profile use `inspec exec /path/to/profile --controls name`. | |||||
```bash | |||||
$ inspec exec unattended --controls package | |||||
. | |||||
Finished in 0.0025 seconds (files took 0.12449 seconds to load) | |||||
1 examples, 0 failures | |||||
``` | |||||
See an [example control here](https://github.com/inspec/inspec/blob/master/examples/profile/controls/example.rb). |
# frozen_string_literal: true | |||||
audit = command( | |||||
"/usr/bin/apt-config dump --no-empty --format '%f=%v%n' Unattended-Upgrade" | |||||
).stdout | |||||
options = { | |||||
assignment_regex: /^\s*([^=]*?)\s*=\s*(.*?)\s*$/, | |||||
multiple_values: true | |||||
} | |||||
control 'Apt unattended upgrades' do | |||||
title 'should be configured' | |||||
describe file('/etc/apt/apt.conf.d/50unattended-upgrades') do | |||||
it { should be_file } | |||||
it { should be_owned_by 'root' } | |||||
it { should be_grouped_into 'root' } | |||||
its('mode') { should cmp '0644' } | |||||
end | |||||
describe file('/etc/apt/apt.conf.d/10periodic') do | |||||
it { should exist } | |||||
it { should be_owned_by 'root' } | |||||
it { should be_grouped_into 'root' } | |||||
its('mode') { should cmp '0644' } | |||||
its(:content) do | |||||
should match( | |||||
'APT::Periodic::Enable "1";' | |||||
) | |||||
end | |||||
end | |||||
describe parse_config(audit, options) do | |||||
its('Unattended-Upgrade::Allowed-Origins::') { should include 'origin1' } | |||||
its('Unattended-Upgrade::Mail') { should include 'root' } | |||||
its('Unattended-Upgrade::MailReport') { should include 'only-on-error' } | |||||
its('Unattended-Upgrade::Package-Blacklist::') { should include 'salt-test' } | |||||
its('Unattended-Upgrade::Automatic-Reboot') { should include 'False' } | |||||
its('Unattended-Upgrade::SyslogEnable') { should include 'True' } | |||||
its('Unattended-Upgrade::SyslogFacility') { should include 'auth' } | |||||
its('Unattended-Upgrade::Remove-Unused-Dependencies') { should include 'True' } | |||||
its('Unattended-Upgrade::Keep-Debs-After-Install') { should include 'False' } | |||||
its('Unattended-Upgrade::Update-Days::') { should include 'Wed' } | |||||
end | |||||
end |
# -*- coding: utf-8 -*- | |||||
# vim: ft=yaml | |||||
--- | |||||
name: unattended | |||||
title: apt formula | |||||
maintainer: SaltStack Formulas | |||||
license: Apache-2.0 | |||||
summary: Verify that the apt unattended preferences are configured correctly | |||||
supports: | |||||
- platform-name: debian | |||||
- platform-name: ubuntu |
# -*- coding: utf-8 -*- | |||||
# vim: ft=yaml | |||||
--- | |||||
apt: | |||||
unattended: | |||||
allowed_origins: | |||||
- origin1 | |||||
package_blacklist: | |||||
- salt-test | |||||
origins_patterns: | |||||
- origin=SaltStack | |||||
- origin=Debian,archive=stable,label=Debian-Security | |||||
auto_fix_interrupted_dpkg: true | |||||
minimal_steps: false | |||||
install_on_shutdown: false | |||||
mail: root | |||||
sender: root | |||||
mail_report: 'always' | |||||
remove_unused_dependencies: true | |||||
automatic_reboot: false | |||||
dl_limit: 0 | |||||
enabled: 1 | |||||
update_package_lists: 1 | |||||
download_upgradeable_packages: 1 | |||||
unattended_upgrade: 1 | |||||
auto_clean_interval: 7 | |||||
verbose: 2 | |||||
syslog_enable: true | |||||
syslog_facility: 'auth' | |||||
dpkg_options: '--force-confold' | |||||
update_days: ['Mon', 'Wed'] | |||||
package_whitelist_strict: false | |||||
keep_debs_after_install: false |