├── VERSION
├── debian
├── compat
├── source
│ └── format
├── docs
├── rules
├── control
├── copyright
└── changelog
├── linux
├── files
│ ├── etc_profile
│ ├── hostname
│ ├── etc_profile_vi_flavors.sh
│ ├── multipath
│ │ ├── _hitachi_vsp1000.conf
│ │ ├── _ibm_storwize.conf
│ │ └── _fujitsu_eternus_dxl.conf
│ ├── 60-net-txqueue.rules
│ ├── sources.list
│ ├── logstash-forwarder.conf
│ ├── collectd_disk.conf
│ ├── collectd_swap.conf
│ ├── governor.conf.jinja
│ ├── cron_users.jinja
│ ├── collectd_bond_status.conf
│ ├── journal.conf
│ ├── login_duo.conf
│ ├── atop.conf
│ ├── systemd.conf
│ ├── sudoer
│ ├── policy-rc.d
│ ├── limits.conf
│ ├── motd.sh
│ ├── dpdk_interfaces
│ ├── mkhomedir
│ ├── setup-loopback-device.upstart
│ ├── systemd-network.conf
│ ├── 95proxies
│ ├── collectd_netlink.conf
│ ├── wireless
│ ├── grub_hugepages
│ ├── telegraf.conf
│ ├── apt.conf
│ ├── collectd_df.conf
│ ├── sudoer-groups
│ ├── sudoer-users
│ ├── apt.conf.d_proxies
│ ├── atop.service
│ ├── openvswitch-switch.systemd
│ ├── bash_history.sh
│ ├── logstash-filter.conf
│ ├── cgconfig.conf
│ ├── ovs_bridge
│ ├── cgrules.conf
│ ├── tty.upstart
│ ├── ovs_port
│ ├── prompt.sh
│ ├── setup-loopback-device.systemd
│ ├── preferences_repo
│ ├── sysfs.conf
│ ├── proxy.sh
│ ├── sudoer-aliases
│ ├── resolv.conf
│ ├── nsswitch.conf
│ ├── multipath.conf
│ ├── etc_environment
│ ├── netconsole.conf
│ ├── pam-add-profile
│ ├── 90autoupdates
│ ├── hosts
│ ├── login.defs.jinja
│ ├── nslcd.conf
│ ├── openvswitch-switch.default
│ ├── modprobe.conf.jinja
│ └── pam-sshd
├── system
│ ├── dpdk.sls
│ ├── doc.sls
│ ├── banner.sls
│ ├── rc.sls
│ ├── bash.sls
│ ├── timezone.sls
│ ├── login_defs.sls
│ ├── iommu.sls
│ ├── haveged.sls
│ ├── directory.sls
│ ├── service.sls
│ ├── sriov.sls
│ ├── policyrcd.sls
│ ├── ld.sls
│ ├── locale.sls
│ ├── apparmor.sls
│ ├── limit.sls
│ ├── autoupdates.sls
│ ├── apt.sls
│ ├── prompt.sls
│ ├── mcelog.sls
│ ├── journal.sls
│ ├── console.sls
│ ├── profile.sls
│ ├── auth
│ │ └── duo.sls
│ ├── selinux.sls
│ ├── grub.sls
│ ├── certificate.sls
│ ├── systemd.sls
│ ├── env.sls
│ ├── group.sls
│ ├── motd.sls
│ ├── cpu.sls
│ ├── netconsole.sls
│ ├── hugepages.sls
│ ├── shell.sls
│ ├── at.sls
│ ├── sysfs.sls
│ ├── config.sls
│ ├── atop.sls
│ ├── job.sls
│ ├── package.sls
│ ├── sudo.sls
│ ├── file.sls
│ └── cron.sls
├── init.sls
├── network
│ ├── resolv.sls
│ ├── dhclient.sls
│ ├── proxy.sls
│ ├── init.sls
│ ├── hostname.sls
│ ├── openvswitch.sls
│ ├── systemd.sls
│ └── host.sls
├── meta
│ ├── meta.yml
│ ├── logrotate.yml
│ ├── grafana.yml
│ ├── sphinx.yml
│ ├── telegraf.yml
│ ├── salt.yml
│ ├── sensu.yml
│ ├── collectd.yml
│ └── graphite.yml
└── storage
│ ├── multipath.sls
│ ├── init.sls
│ ├── loopback.sls
│ ├── mount.sls
│ ├── lvm.sls
│ └── swap.sls
├── tests
├── test-requirements.txt
├── example
│ └── file_template.jinja
├── pillar
│ ├── system_banner.sls
│ ├── system_file.sls
│ ├── network_extended.sls
│ ├── system_extra.sls
│ ├── network_openvswitch.sls
│ ├── storage.sls
│ └── network_openvswitch_dpdk.sls
└── integration
│ └── system
│ ├── sudoer_spec.rb
│ ├── env_spec.rb
│ ├── netconsole_spec.rb
│ ├── profile_spec.rb
│ └── repo_spec.rb
├── .gitignore
├── metadata.yml
├── metadata
└── service
│ ├── system
│ ├── container.yml
│ ├── init.yml
│ └── cis
│ │ ├── cis-3-3-3.yml
│ │ ├── cis-1-1-1-4.yml
│ │ ├── cis-3-5-4.yml
│ │ ├── cis-1-1-1-3.yml
│ │ ├── cis-1-1-1-5.yml
│ │ ├── cis-1-1-1-2.yml
│ │ ├── cis-3-5-3.yml
│ │ ├── cis-1-1-1-1.yml
│ │ ├── cis-6-1-6.yml
│ │ ├── cis-1-5-4.yml
│ │ ├── cis-6-1-8.yml
│ │ ├── cis-1-5-3.yml
│ │ ├── cis-3-5-1.yml
│ │ ├── cis-6-1-4.yml
│ │ ├── cis-6-1-2.yml
│ │ ├── cis-1-1-1-7.yml
│ │ ├── cis-2-3-3.yml
│ │ ├── cis-6-1-7.yml
│ │ ├── cis-6-1-9.yml
│ │ ├── cis-3-2-6.yml
│ │ ├── cis-3-5-2.yml
│ │ ├── cis-2-3-4.yml
│ │ ├── cis-6-1-3.yml
│ │ ├── cis-6-1-5.yml
│ │ ├── cis-3-2-4.yml
│ │ ├── cis-1-1-1-6.yml
│ │ ├── cis-3-1-2.yml
│ │ ├── cis-2-3-1.yml
│ │ ├── cis-3-2-3.yml
│ │ ├── cis-1-1-1-8.yml
│ │ ├── cis-3-2-5.yml
│ │ ├── cis-5-4-1-3.yml
│ │ ├── cis-5-4-1-2.yml
│ │ ├── cis-5-4-1-1.yml
│ │ ├── cis-3-2-2.yml
│ │ ├── cis-1-1-21.yml
│ │ ├── cis-1-5-1.yml
│ │ ├── init.yml
│ │ ├── cis-3-2-7.yml
│ │ ├── cis-3-2-8.yml
│ │ ├── cis-2-3-2.yml
│ │ ├── cis-5-4-4.yml
│ │ └── cis-3-2-1.yml
│ └── support.yml
├── _modules
├── linux_netlink.py
├── linux_hosts.py
└── ovs_config.py
├── LICENSE
├── .kitchen.yml
├── .travis.yml
└── _states
└── ovs_config.py
/VERSION:
--------------------------------------------------------------------------------
1 | 2017.4.1
2 |
--------------------------------------------------------------------------------
/debian/compat:
--------------------------------------------------------------------------------
1 | 9
2 |
--------------------------------------------------------------------------------
/debian/source/format:
--------------------------------------------------------------------------------
1 | 3.0 (native)
2 |
--------------------------------------------------------------------------------
/linux/files/etc_profile:
--------------------------------------------------------------------------------
1 | {{ script }}
2 |
--------------------------------------------------------------------------------
/tests/test-requirements.txt:
--------------------------------------------------------------------------------
1 | jsonschema
2 | reno
3 |
--------------------------------------------------------------------------------
/debian/docs:
--------------------------------------------------------------------------------
1 | README.rst
2 | CHANGELOG.rst
3 | VERSION
4 |
--------------------------------------------------------------------------------
/linux/files/hostname:
--------------------------------------------------------------------------------
1 | {{ pillar.linux.system.name }}
2 |
--------------------------------------------------------------------------------
/debian/rules:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 |
3 | %:
4 | dh $@
5 |
6 |
--------------------------------------------------------------------------------
/tests/example/file_template.jinja:
--------------------------------------------------------------------------------
1 | foo{{ pillar["test"]["example"] }}
2 |
--------------------------------------------------------------------------------
/linux/files/etc_profile_vi_flavors.sh:
--------------------------------------------------------------------------------
1 | set -o vi
2 | export EDITOR=vim
3 | {{ script }}
4 |
--------------------------------------------------------------------------------
/linux/files/multipath/_hitachi_vsp1000.conf:
--------------------------------------------------------------------------------
1 |
2 | # vsp1000 does not have special device config
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .kitchen
2 | .bundle
3 | bundle/
4 | tests/build/
5 | *.swp
6 | *.pyc
7 | .ropeproject
8 | Gemfile*
9 |
--------------------------------------------------------------------------------
/metadata.yml:
--------------------------------------------------------------------------------
1 | name: "linux"
2 | version: "2017.4.1"
3 | source: "https://github.com/salt-formulas/salt-formula-linux"
4 |
--------------------------------------------------------------------------------
/linux/files/60-net-txqueue.rules:
--------------------------------------------------------------------------------
1 | KERNEL=="tap[0-9a-z\-]*", RUN+="/sbin/ip link set %k txqueuelen {{ tap_custom_txqueuelen }}"
2 |
--------------------------------------------------------------------------------
/linux/files/sources.list:
--------------------------------------------------------------------------------
1 | {%- for name, repo in default_repos.items() | sort %}
2 | # Repository {{ name }}
3 | {{ repo.source }}
4 | {%- endfor %}
5 |
--------------------------------------------------------------------------------
/linux/files/logstash-forwarder.conf:
--------------------------------------------------------------------------------
1 | {
2 | "paths": [
3 | "/var/log/syslog",
4 | "/var/log/auth.log"
5 | ],
6 | "fields": { "type": "syslog" }
7 | }
8 |
--------------------------------------------------------------------------------
/linux/files/collectd_disk.conf:
--------------------------------------------------------------------------------
1 |
2 | Globals false
3 |
4 |
5 |
6 | IgnoreSelected {{ plugin.get('ignore_selected', True)|lower }}
7 |
8 |
--------------------------------------------------------------------------------
/linux/files/collectd_swap.conf:
--------------------------------------------------------------------------------
1 |
2 | Globals false
3 |
4 |
5 |
6 | ReportBytes {{ plugin.get('report_bytes', False)|lower }}
7 |
8 |
9 |
--------------------------------------------------------------------------------
/linux/files/governor.conf.jinja:
--------------------------------------------------------------------------------
1 | {% for cpu_core in range(salt['grains.get']('num_cpus', 1)) %}
2 | devices/system/cpu/cpu{{ cpu_core }}/cpufreq/scaling_governor = {{ governor }}
3 | {% endfor %}
4 |
--------------------------------------------------------------------------------
/linux/files/cron_users.jinja:
--------------------------------------------------------------------------------
1 | # This file is managed by Salt, do not edit
2 | {%- for user_name in users %}
3 | {{ user_name }}
4 | {%- endfor %}
5 | {# IMPORTANT: This file SHOULD ends with a newline #}
--------------------------------------------------------------------------------
/linux/system/dpdk.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import network with context %}
2 |
3 | {%- if network.dpdk.enabled and network.dpdk.driver == "vfio" %}
4 | include:
5 | - linux.system.iommu
6 | {%- endif %}
--------------------------------------------------------------------------------
/linux/files/collectd_bond_status.conf:
--------------------------------------------------------------------------------
1 | Import "bond_status"
2 |
3 |
4 | {%- for interface in plugin.get('interfaces', []) %}
5 | Bond "{{ interface }}"
6 | {%- endfor %}
7 |
8 |
--------------------------------------------------------------------------------
/linux/files/journal.conf:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context -%}
2 | #This file is managed by salt
3 | [Journal]
4 | {%- for option, value in settings.items() %}
5 | {{ option }}={{ value }}
6 | {%- endfor -%}
7 |
--------------------------------------------------------------------------------
/linux/files/login_duo.conf:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import auth with context %}
2 | [duo]
3 | ikey = {{ auth.duo.duo_ikey }}
4 | skey = {{ auth.duo.duo_skey }}
5 | host = {{ auth.duo.duo_host }}
6 | pushinfo = yes
7 | failmode = secure
8 |
9 |
--------------------------------------------------------------------------------
/linux/files/atop.conf:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context -%}
2 | # This file /etc/default/atop is managed by Salt linux formula
3 | INTERVAL={{ system.atop.interval }}
4 | LOGPATH={{ system.atop.logpath }}
5 | OUTFILE={{ system.atop.outfile }}
6 |
--------------------------------------------------------------------------------
/linux/files/systemd.conf:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context -%}
2 | {%- for section, options in settings.items() %}
3 | [{{ section }}]
4 | {%- for option, value in options.items() %}
5 | {{ option }}={{ value }}
6 | {%- endfor -%}
7 | {%- endfor -%}
8 |
--------------------------------------------------------------------------------
/linux/files/sudoer:
--------------------------------------------------------------------------------
1 | # sudoer file managed by salt-minion
2 | # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
3 | #
4 | # user {{ user_name }} is system administrator.
5 | # It has passwordless sudo functionality.
6 | {{ user_name }} ALL=(ALL) NOPASSWD:ALL
7 |
--------------------------------------------------------------------------------
/linux/files/policy-rc.d:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context -%}
2 | #!/bin/sh
3 |
4 | while true; do
5 | case $1 in
6 | {%- for policy in system.policyrcd %}
7 | {{ policy.package }}) {{ policy.action }};;
8 | {%- endfor %}
9 | esac
10 | done
11 |
--------------------------------------------------------------------------------
/linux/files/limits.conf:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}{%- set limit = system.limit.get(limit_name) %}# Limits for {{ limit.domain }}
2 | {%- for entry in limit.limits %}
3 | {{ limit.domain }} {{ entry.type }} {{ entry.item }} {{ entry.value }}
4 |
5 | {%- endfor %}
6 |
7 |
--------------------------------------------------------------------------------
/linux/system/doc.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | # This state is obsolete, grains are now managed from salt.minion.grains so we
5 | # will just include it
6 |
7 | include:
8 | - salt.minion.grains
9 |
10 | {%- endif %}
11 |
--------------------------------------------------------------------------------
/metadata/service/system/container.yml:
--------------------------------------------------------------------------------
1 | applications:
2 | - linux
3 | classes:
4 | - service.linux.support
5 | parameters:
6 | linux:
7 | system:
8 | enabled: true
9 | cluster: default
10 | network:
11 | enabled: false
12 | storage:
13 | enabled: false
14 |
--------------------------------------------------------------------------------
/linux/files/motd.sh:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context -%}
2 | {%- for motd in system.motd -%}
3 | {%- if loop.index == index -%}
4 | {%- for name, value in motd.items() -%}
5 | {%- if name == motd_name -%}{{ value }}{%- endif %}
6 | {%- endfor -%}
7 | {%- endif -%}
8 | {%- endfor -%}
9 |
--------------------------------------------------------------------------------
/linux/system/banner.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import banner with context %}
2 |
3 | {%- if banner.get('enabled', False) %}
4 | /etc/issue:
5 | file.managed:
6 | - user: root
7 | - group: root
8 | - mode: 644
9 | - contents_pillar: linux:system:banner:contents
10 | {%- endif %}
11 |
--------------------------------------------------------------------------------
/linux/files/dpdk_interfaces:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import network with context %}
2 | {%- for interface_name, interface in network.interface.items() %}
3 | {%- if 'dpdk' in interface.type and interface.pci is defined %}
4 | pci {{ interface.pci }} {{ interface.driver }}
5 | {%- endif %}
6 | {%- endfor %}
7 |
--------------------------------------------------------------------------------
/linux/files/mkhomedir:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import auth with context %}
2 | Name: Create home directory during login
3 | Default: yes
4 | Priority: 0
5 | Session-Type: Additional
6 | Session-Final:
7 | required pam_mkhomedir.so skel=/etc/skel umask={{ auth.mkhomedir.get('umask', '0022') }} silent
8 |
--------------------------------------------------------------------------------
/linux/files/setup-loopback-device.upstart:
--------------------------------------------------------------------------------
1 | description "Setup {{ device_name }} device"
2 |
3 | start on filesystem
4 |
5 | pre-start exec losetup {{ device_name }} {{ file }}
6 | post-stop exec losetup -d {{ device_name }}
7 |
8 | script
9 | while losetup {{ device_name }} ; do sleep 60 ; done
10 | end script
11 |
--------------------------------------------------------------------------------
/linux/files/systemd-network.conf:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context -%}
2 | {%- for section, options in settings.items() %}
3 |
4 | [{{ section[0].upper() + section[1:] }}]
5 | {%- for option, value in options.items() %}
6 | {{ option[0].upper() + option[1:] }}={{ value }}
7 | {%- endfor %}
8 | {%- endfor %}
9 |
--------------------------------------------------------------------------------
/linux/init.sls:
--------------------------------------------------------------------------------
1 | {%- if pillar.linux is defined %}
2 | include:
3 | {%- if pillar.linux.system is defined %}
4 | - linux.system
5 | {%- endif %}
6 | {%- if pillar.linux.network is defined %}
7 | - linux.network
8 | {%- endif %}
9 | {%- if pillar.linux.storage is defined %}
10 | - linux.storage
11 | {%- endif %}
12 | {%- endif %}
--------------------------------------------------------------------------------
/linux/files/95proxies:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import network with context %}
2 | Acquire::http::proxy "http://{{ network.proxy.host }}:{{ network.proxy.port }}/";
3 | Acquire::ftp::proxy "ftp://{{ network.proxy.host }}:{{ network.proxy.port }}/";
4 | Acquire::https::proxy "http://{{ network.proxy.host }}:{{ network.proxy.port }}/";
5 |
--------------------------------------------------------------------------------
/linux/files/collectd_netlink.conf:
--------------------------------------------------------------------------------
1 |
2 | Globals false
3 |
4 |
5 |
6 | {%- for interface_name in plugin.get('interfaces', []) %}
7 | VerboseInterface "{{ interface_name }}"
8 | {%- endfor %}
9 | IgnoreSelected {{ plugin.get('ignore_selected', False)|lower }}
10 |
11 |
--------------------------------------------------------------------------------
/linux/system/rc.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- if system.rc.local is defined %}
5 |
6 | /etc/rc.local:
7 | file.managed:
8 | - user: root
9 | - group: root
10 | - mode: 755
11 | - contents_pillar: linux:system:rc:local
12 |
13 | {%- endif %}
14 |
15 | {%- endif %}
--------------------------------------------------------------------------------
/linux/system/bash.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- if system.bash.get('preserve_history', False) %}
5 | /etc/profile.d/bash_history.sh:
6 | file.managed:
7 | - source: salt://linux/files/bash_history.sh
8 | - template: jinja
9 | {%- endif %}
10 |
11 | {%- endif %}
12 |
--------------------------------------------------------------------------------
/linux/files/wireless:
--------------------------------------------------------------------------------
1 | {%- set interface = salt['pillar.get']('linux:network:interface:'+interface_name) %}
2 | Interface={{ interface_name }}
3 | Connection=wireless
4 | Security={{ interface.wireless.security }}
5 | ESSID={{ interface.wireless.essid }}
6 | IP=dhcp
7 | Key={{ interface.wireless.key }}
8 | Priority={{ interface.wireless.get('priority', '1') }}
9 |
--------------------------------------------------------------------------------
/linux/files/grub_hugepages:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT {%- for hugepages_type, hugepages in system.kernel.hugepages.items() %}{%- if hugepages.get('default', False) %} default_hugepagesz={{ hugepages.size }} {%- endif %} hugepagesz={{ hugepages.size }} hugepages={{ hugepages.count }} {%- endfor %}"
3 |
--------------------------------------------------------------------------------
/linux/system/timezone.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- if system.timezone is defined %}
5 |
6 | {{ system.timezone }}:
7 | timezone.system:
8 | {%- if grains.get('noservices') %}
9 | - onlyif: /bin/false
10 | {%- endif %}
11 | - utc: {{ system.utc }}
12 |
13 | {%- endif %}
14 |
15 | {%- endif %}
16 |
--------------------------------------------------------------------------------
/linux/files/telegraf.conf:
--------------------------------------------------------------------------------
1 | [[inputs.bond]]
2 | {%- include 'telegraf/files/input/_common.conf' %}
3 | {%- if values.bond_interfaces is defined %}
4 | bond_interfaces = {{ values.bond_interfaces | json }}
5 | {%- endif %}
6 | {%- if values.host_proc is defined %}
7 | host_proc = "{{ values.host_proc | json }}"
8 | {%- endif %}
9 | {%- include 'telegraf/files/input/_filters.conf' %}
10 |
--------------------------------------------------------------------------------
/linux/files/apt.conf:
--------------------------------------------------------------------------------
1 | // apt.conf file managed by salt-minion
2 | // DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
3 |
4 | {%- for key, value in config.items() %}
5 | {{ key }} {% if value is iterable and value is not string %}{ {% for entry in value %}"{{ entry }}";{% endfor %} } {% else %}{{ value }};{% endif %}
6 | {%- endfor %}
7 | {#-
8 | vim: syntax=jinja
9 | -#}
10 |
--------------------------------------------------------------------------------
/linux/files/collectd_df.conf:
--------------------------------------------------------------------------------
1 |
2 | Globals false
3 |
4 |
5 |
6 | {%- for fs_type in plugin.get('fs_types', []) %}
7 | FSType {{ fs_type }}
8 | {%- endfor %}
9 | IgnoreSelected {{ plugin.get('ignore_selected', False)|lower }}
10 | ReportByDevice false
11 | ReportInodes true
12 | ValuesAbsolute true
13 | ValuesPercentage true
14 |
15 |
--------------------------------------------------------------------------------
/linux/system/login_defs.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 | {%- if system.login_defs is defined %}
4 | login_defs:
5 | file.managed:
6 | - name: /etc/login.defs
7 | - source: salt://linux/files/login.defs.jinja
8 | - template: jinja
9 | - user: root
10 | - group: root
11 | - mode: 644
12 | {%- endif %}
13 | {%- endif %}
14 |
--------------------------------------------------------------------------------
/linux/system/iommu.sls:
--------------------------------------------------------------------------------
1 | include:
2 | - linux.system.grub
3 |
4 | /etc/default/grub.d/90-iommu.cfg:
5 | file.managed:
6 | - contents: 'GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT intel_iommu=on iommu=pt"'
7 | - require:
8 | - file: grub_d_directory
9 | {%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
10 | - watch_in:
11 | - cmd: grub_update
12 | {%- endif %}
13 |
--------------------------------------------------------------------------------
/linux/files/sudoer-groups:
--------------------------------------------------------------------------------
1 | # sudoer groups, file managed by salt-minion
2 | # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
3 |
4 | {%- for group,spec in groups.items() %}
5 | %{{ spec.name|default(group) }} {{ spec.get('hosts', ['ALL'])|join(',') }}=({{ spec.get('runas', ['ALL'])|join(', ') }}) {% if spec.get('nopasswd', True) %}NOPASSWD: {% endif %}{{ spec.get('commands', ['ALL'])|join(', ') }}
6 | {%- endfor %}
7 |
8 |
--------------------------------------------------------------------------------
/linux/system/haveged.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 |
3 | {%- if system.haveged.enabled %}
4 |
5 | linux_haveged_pkgs:
6 | pkg.installed:
7 | - name: haveged
8 | - watch_in:
9 | - service: linux_haveged_service
10 |
11 | linux_haveged_service:
12 | service.running:
13 | - name: haveged
14 | - enable: true
15 | - require:
16 | - pkg: linux_haveged_pkgs
17 |
18 | {%- endif %}
19 |
--------------------------------------------------------------------------------
/metadata/service/support.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | linux:
3 | _support:
4 | prometheus:
5 | enabled: true
6 | telegraf:
7 | enabled: true
8 | collectd:
9 | enabled: true
10 | heka:
11 | enabled: true
12 | sensu:
13 | enabled: false
14 | sphinx:
15 | enabled: true
16 | grafana:
17 | enabled: true
18 | fluentd:
19 | enabled: true
20 |
--------------------------------------------------------------------------------
/tests/pillar/system_banner.sls:
--------------------------------------------------------------------------------
1 | linux:
2 | network:
3 | enabled: true
4 | hostname: linux
5 | fqdn: linux.ci.local
6 | system:
7 | enabled: true
8 | name: linux
9 | banner:
10 | enabled: true
11 | contents: |
12 | ================= WARNING =================
13 | This is tcpcloud network.
14 | Unauthorized access is strictly prohibited.
15 | ===========================================
16 |
--------------------------------------------------------------------------------
/linux/network/resolv.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import network with context %}
2 | {%- if network.enabled %}
3 |
4 | /etc/resolv.conf:
5 | file.managed:
6 | - source: salt://linux/files/resolv.conf
7 | - mode: 644
8 | - template: jinja
9 | - follow_symlinks: false
10 | - require:
11 | - service: resolvconf_service
12 |
13 | resolvconf_service:
14 | service.dead:
15 | - name: resolvconf
16 | - enable: false
17 |
18 | {%- endif %}
19 |
--------------------------------------------------------------------------------
/tests/integration/system/sudoer_spec.rb:
--------------------------------------------------------------------------------
1 | describe command('grep "" /etc/sudoers.d/*') do
2 | its('stdout') { should_not match /sudogroup0/ }
3 | its('stdout') { should match /salt-ops ALL=\(DBA\) NOPASSWD/ }
4 | its('stdout') { should match /sudogroup2.*localhost=/ }
5 | its('stdout') { should match /db-ops.*less/ }
6 | its('stdout') { should_not match /sudogroup0/ }
7 | its('stdout') { should_not match /sudogroup1 .* !SUDO_RESTRICTED_SU/ }
8 | end
9 |
--------------------------------------------------------------------------------
/linux/files/sudoer-users:
--------------------------------------------------------------------------------
1 | # sudoer users, file managed by salt-minion
2 | # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
3 |
4 | {%- for user,spec in users.items() %}
5 | {{ spec.name|default(user) }} {{ spec.get('hosts', ['ALL'])|join(',') }}=({{ spec.get('runas', ['ALL'])|join(', ') }}) {% if spec.get('nopasswd', True) %}NOPASSWD:{% endif %}{% if spec.get('setenv', False) %}SETENV:{% endif %} {{ spec.get('commands', ['ALL'])|join(', ') }}
6 | {%- endfor %}
7 |
8 |
--------------------------------------------------------------------------------
/linux/system/directory.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 |
3 | {%- if system.directory is defined %}
4 | {%- for name, dir in system.directory.items() %}
5 |
6 | {{ dir.name|default(name) }}:
7 | file.directory:
8 | {%- if dir %}
9 | {%- for key, value in dir.items() %}
10 | - {{ key }}: {{ value }}
11 | {%- endfor %}
12 | {%- else %}
13 | - name: {{ name }}
14 | {%- endif %}
15 |
16 | {%- endfor %}
17 | {% endif %}
18 |
--------------------------------------------------------------------------------
/linux/files/apt.conf.d_proxies:
--------------------------------------------------------------------------------
1 | {%- if ftp and ftp.lower() != 'none' %}
2 | Acquire::ftp::proxy{%- if external_host %}::{{ external_host }}{% endif %} "{{ ftp }}";
3 | {%- endif %}
4 | {%- if http and http.lower() != 'none' %}
5 | Acquire::http::proxy{%- if external_host %}::{{ external_host }}{% endif %} "{{ http }}";
6 | {%- endif %}
7 | {%- if https and https.lower() != 'none' %}
8 | Acquire::https::proxy{%- if external_host %}::{{ external_host }}{% endif %} "{{ https }}";
9 | {%- endif -%}
10 |
--------------------------------------------------------------------------------
/linux/files/atop.service:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context -%}
2 | [Unit]
3 | Description=atop - advanced interactive monitor
4 | After=syslog.target
5 | ConditionPathExists={{ config_file }}
6 | Documentation=man:atop(1)
7 | Documentation=https://atoptool.nl
8 |
9 | [Service]
10 | EnvironmentFile=-{{ config_file }}
11 | ExecStart=/usr/bin/atop -a -w ${LOGPATH}/daily.log ${INTERVAL}
12 | Restart=always
13 | RestartSec=10
14 |
15 | [Install]
16 | WantedBy=multi-user.target
17 |
--------------------------------------------------------------------------------
/linux/files/openvswitch-switch.systemd:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Open vSwitch
3 | Before=network.target
4 | After=network-pre.target ovsdb-server.service ovs-vswitchd.service
5 | PartOf=network.target
6 | Requires=ovsdb-server.service
7 | Requires=ovs-vswitchd.service
8 |
9 | [Service]
10 | Type=oneshot
11 | ExecStart=/usr/bin/ovs-vsctl set open . external-ids:hostname=%H
12 | ExecReload=/bin/true
13 | ExecStop=/bin/true
14 | RemainAfterExit=yes
15 |
16 | [Install]
17 | WantedBy=multi-user.target
18 |
19 |
--------------------------------------------------------------------------------
/_modules/linux_netlink.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import re
4 |
5 | def __virtual__():
6 | return 'linux_netlink'
7 |
8 | def ls(regex):
9 | """
10 | Provide a list of network interfaces.
11 | """
12 | _lo_re = re.compile(r'^lo$')
13 | _alphanum_re = re.compile(regex)
14 |
15 | def _filter(interface):
16 | return _alphanum_re.match(interface) and not _lo_re.match(interface)
17 |
18 | return filter(_filter, __salt__['grains.get']('ip_interfaces', {}).keys())
19 |
--------------------------------------------------------------------------------
/tests/integration/system/env_spec.rb:
--------------------------------------------------------------------------------
1 |
2 | ## PROXIES
3 | #
4 | describe file('/etc/environment') do
5 | it('should exist')
6 | its('content') { should_not match /HTTPS_PROXY"/ }
7 | its('content') { should match /HTTP_PROXY="http:\/\/127.0.4.2:80"/ }
8 | its('content') { should match /BOB_PATH=/}
9 | its('content') { should match /LC_ALL="C"/ }
10 | its('content') { should match /ftp_proxy=.*127.0.4.3:2121/ }
11 | its('content') { should match /NO_PROXY=.*dummy.net,.local/ }
12 | end
13 |
--------------------------------------------------------------------------------
/linux/system/service.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- for name, service in system.service.items() %}
5 |
6 | linux_service_{{ name }}:
7 | service.{{ service.status }}:
8 | {%- if service.status == 'dead' %}
9 | - enable: {{ service.get('enabled', False) }}
10 | {%- elif service.status == 'running' %}
11 | - enable: {{ service.get('enabled', True) }}
12 | {%- endif %}
13 | - name: {{ name }}
14 |
15 | {%- endfor %}
16 | {%- endif %}
17 |
--------------------------------------------------------------------------------
/linux/files/bash_history.sh:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 |
3 | # History across sessions for Bash
4 | if [ -n "$BASH_VERSION" ]; then
5 | # Avoid duplicates
6 | export HISTCONTROL=ignoredups:erasedups
7 | # When the shell exits, append to the history file instead of overwriting it
8 | shopt -s histappend
9 |
10 | # After each command, append to the history file and reread it
11 | export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"
12 | fi
13 |
--------------------------------------------------------------------------------
/linux/system/sriov.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 |
3 | include:
4 | - linux.system.iommu
5 |
6 | /etc/modprobe.d/sriov.conf:
7 | file.managed:
8 | - contents: |
9 | blacklist ixgbevf
10 | blacklist igbvf
11 | blacklist i40evf
12 |
13 | {%- if system.kernel.get('unsafe_interrupts', false) %}
14 |
15 | /etc/modprobe.d/iommu_unsafe_interrupts.conf:
16 | file.managed:
17 | - contents: options vfio_iommu_type1 allow_unsafe_interrupts=1
18 |
19 | {%- endif %}
20 |
--------------------------------------------------------------------------------
/tests/integration/system/netconsole_spec.rb:
--------------------------------------------------------------------------------
1 |
2 | ## NETCONSOLE
3 | #
4 | describe file('/etc/default/netconsole.conf') do
5 | it('should exist')
6 | its('content') { should match /^PORT="514"/}
7 | its('content') { should match /^netconsole "bond0" "192.168.0.1" "ff:ff:ff:ff:ff:ff"/}
8 | its('content') { should match /^dmesg -n "debug"/}
9 | end
10 |
11 | describe file('/etc/dhcp/dhclient-exit-hooks.d/netconsole') do
12 | it('should exist')
13 | its('content') { should match /netconsole_setup/}
14 | end
15 |
--------------------------------------------------------------------------------
/linux/files/logstash-filter.conf:
--------------------------------------------------------------------------------
1 | filter {
2 | if [type] == "syslog" {
3 | grok {
4 | match => { "message" => "%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:syslog_message}" }
5 | add_field => [ "received_at", "%{@timestamp}" ]
6 | add_field => [ "received_from", "%{host}" ]
7 | }
8 | syslog_pri { }
9 | date {
10 | match => [ "syslog_timestamp", "MMM d HH:mm:ss", "MMM dd HH:mm:ss" ]
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/linux/network/dhclient.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import network with context %}
2 |
3 | {%- if network.dhclient.enabled|default(False) %}
4 |
5 | dhclient_conf:
6 | file.managed:
7 | - name: {{ network.dhclient_config }}
8 | - source: salt://linux/files/dhclient.conf
9 | - template: jinja
10 |
11 | {%- elif network.dhclient.enabled is defined and network.dhclient.enabled == False %}
12 |
13 | kill_dhcp_client:
14 | cmd.run:
15 | - name: "pkill dhclient"
16 | - onlyif: "pgrep dhclient"
17 |
18 | {%- endif %}
19 |
--------------------------------------------------------------------------------
/linux/network/proxy.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import network with context %}
2 | {%- if network.enabled %}
3 |
4 | {%- if grains.os_family == 'Debian' %}
5 |
6 | {%- if network.proxy.host == 'none' %}
7 |
8 | /etc/profile.d/proxy.sh:
9 | file.absent
10 |
11 | /etc/apt/apt.conf.d/95proxies:
12 | file.absent
13 |
14 | {%- else %}
15 |
16 | /etc/apt/apt.conf.d/95proxies:
17 | file.managed:
18 | - template: jinja
19 | - source: salt://linux/files/95proxies
20 |
21 | {%- endif %}
22 |
23 | {%- endif %}
24 |
25 | {%- endif %}
26 |
--------------------------------------------------------------------------------
/linux/system/policyrcd.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | policyrcd_file:
5 | file.managed:
6 | - name: /usr/local/sbin/policy-rc.d
7 | - source: salt://linux/files/policy-rc.d
8 | - mode: 655
9 | - template: jinja
10 |
11 | policyrcd_alternatives:
12 | alternatives.install:
13 | - name: policy-rc.d
14 | - link: /usr/sbin/policy-rc.d
15 | - path: /usr/local/sbin/policy-rc.d
16 | - require:
17 | - file: policyrcd_file
18 |
19 | {%- endif %}
20 |
--------------------------------------------------------------------------------
/tests/integration/system/profile_spec.rb:
--------------------------------------------------------------------------------
1 |
2 | describe file('/etc/profile.d/salt_profile_vi_flavors.sh') do
3 | it('should exist')
4 | its('content') { should match /EDITOR=vim/ }
5 | its('content') { should match /PAGER=view/ }
6 | its('content') { should match /alias vi=vim/ }
7 | end
8 |
9 | describe file('/etc/profile.d/salt_profile_locales.sh') do
10 | it('should exist')
11 | its('content') { should match /LANG=en_US/ }
12 | end
13 |
14 | describe file('/etc/profile.d/prompt.sh') do
15 | it('should exist')
16 | end
17 |
18 |
--------------------------------------------------------------------------------
/tests/integration/system/repo_spec.rb:
--------------------------------------------------------------------------------
1 |
2 | # PROXIES
3 | #
4 | # globally
5 | describe file('/etc/apt/apt.conf.d/99proxies-salt') do
6 | it('should exist')
7 | its('content') { should_not match /ftp/ }
8 | its('content') { should match /proxy "https.*127.0.2.1:4443"/ }
9 | end
10 |
11 | # per repo
12 | describe file('/etc/apt/apt.conf.d/99proxies-salt-opencontrail') do
13 | it('should exist')
14 | its('content') { should_not match /ftp/ }
15 | its('content') { should match /Acquire::https::proxy::ppa.launchpad.net/ }
16 | end
17 |
18 |
--------------------------------------------------------------------------------
/metadata/service/system/init.yml:
--------------------------------------------------------------------------------
1 | applications:
2 | - linux
3 | classes:
4 | - service.linux.support
5 | parameters:
6 | linux:
7 | system:
8 | enabled: true
9 | user:
10 | root:
11 | enabled: true
12 | name: root
13 | home: /root
14 | timezone: Europe/Prague
15 | cluster: default
16 | purge_repos: false
17 | network:
18 | enabled: true
19 | hostname: ${linux:system:name}
20 | fqdn: ${linux:system:name}.${linux:system:domain}
21 | storage:
22 | enabled: true
23 |
--------------------------------------------------------------------------------
/linux/files/cgconfig.conf:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context -%}
2 | ##
3 | ## This is cgconfig configuration file is managed by Salt
4 | ##
5 | {%- for cgroup_name, cg in system.cgroup.group.items() %}
6 | group {{ cgroup_name }} {
7 | {%- for controller_name, controller in cg.controller.items() %}
8 | {{ controller_name }} {
9 | {%- for v_name, v in controller.items() %}
10 | {{ controller_name }}.{{ v_name }}="{{ v.value }}";
11 | {%- endfor %}
12 |
13 | }
14 | {%- endfor %}
15 | }
16 | {%- endfor %}
17 |
--------------------------------------------------------------------------------
/linux/system/ld.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 |
3 | {%- if system.enabled %}
4 |
5 | {%- for key in system.ld.library %}
6 | /etc/ld.so.conf.d/{{ key }}.conf:
7 | file.managed:
8 | - user: root
9 | - group: root
10 | - mode: 644
11 | - contents: |
12 | {% for val in system.ld.library[key] -%}
13 | {{ val }}
14 | {% endfor %}
15 | - watch_in:
16 | - cmd: ldconfig_update
17 | {% endfor %}
18 |
19 | ldconfig_update:
20 | cmd.wait:
21 | - name: ldconfig
22 |
23 | {% endif %}
24 |
--------------------------------------------------------------------------------
/linux/files/ovs_bridge:
--------------------------------------------------------------------------------
1 | auto {{ bridge_name }}
2 | iface {{ bridge_name }} inet {{ bridge.get('proto', 'static' if bridge.address is defined else 'manual') }}
3 | ovs_type {{ bridge.get('ovs_bridge_type', 'OVSBridge') }}
4 | mtu {{ bridge.get('mtu', '1500') }}
5 | {%- if bridge.address is defined %}
6 | address {{ bridge.address }}
7 | netmask {{ bridge.netmask }}
8 | {%- endif %}
9 | {%- if bridge.gateway is defined %}
10 | gateway {{ bridge.gateway }}
11 | {%- endif %}
12 | {%- if bridge.ovs_options is defined %}
13 | ovs_options {{ bridge.ovs_options }}
14 | {%- endif %}
15 |
--------------------------------------------------------------------------------
/linux/meta/meta.yml:
--------------------------------------------------------------------------------
1 | graph:
2 | {%- if pillar.get('linux', {}).system is defined %}
3 | {%- from "linux/map.jinja" import system with context %}
4 | - host: {{ grains.id }}
5 | service: linux.system
6 | type: software-system
7 | relations:
8 | {%- if system.repo is defined %}
9 | {%- for repo_name, repo in system.repo.items() %}
10 | {%- if repo.get('enabled', True) %}
11 | - service: apt.repo
12 | host_external: {{ repo.source }}
13 | direction: source
14 | type: tcp-http
15 | {%- endif %}
16 | {%- endfor %}
17 | {%- endif %}
18 | {%- endif %}
19 |
--------------------------------------------------------------------------------
/_modules/linux_hosts.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | '''
3 | Module for defining new filter for sorting
4 | host names/alias by FQDN first and alphabetically
5 | '''
6 |
7 | from jinja2 import Undefined
8 |
9 | def __virtual__():
10 | return 'linux_hosts'
11 |
12 | def fqdn_sort_fn(n1):
13 | length = len(n1)
14 | return length
15 |
16 | def fqdn_sort_filter(iterable):
17 | if iterable is None or isinstance(iterable, Undefined):
18 | return iterable
19 | # Do effective custom sorting of iterable here
20 | return sorted(set(iterable), key=fqdn_sort_fn)
21 |
--------------------------------------------------------------------------------
/linux/files/cgrules.conf:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context -%}
2 | ##
3 | ## This is cgrules configuration file is managed by Salt
4 | ##
5 | #
6 | {%- for cgroup_name, cg in system.cgroup.group.items() %}
7 | {%- for subject in cg.mapping.subjects %}
8 | {{ subject }}{% raw %} {% endraw %}{%- for controller_name, controller in cg.controller.items() -%}{{ controller_name }}{%- if not loop.last -%},{%- endif -%}{%- endfor -%}{% raw %} {% endraw %}{{ cgroup_name }}
9 | {%- endfor %}
10 | {%- endfor %}
11 |
--------------------------------------------------------------------------------
/linux/files/multipath/_ibm_storwize.conf:
--------------------------------------------------------------------------------
1 |
2 | device {
3 | vendor "IBM"
4 | product "2145"
5 | path_grouping_policy group_by_prio
6 | getuid_callout "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
7 | features "1 queue_if_no_path"
8 | prio alua
9 | path_checker tur
10 | failback immediate
11 | no_path_retry "5"
12 | rr_min_io 1
13 | polling_interval 30
14 | dev_loss_tmo 120
15 | }
16 |
--------------------------------------------------------------------------------
/linux/files/tty.upstart:
--------------------------------------------------------------------------------
1 | # {{ name }} - getty
2 | #
3 | # This service maintains a getty on tty1 from the point the system is
4 | # started until it is shut down again.
5 |
6 | start on stopped rc RUNLEVEL=[2345] and (
7 | not-container or
8 | container CONTAINER=lxc or
9 | container CONTAINER=lxc-libvirt)
10 |
11 | stop on runlevel [!2345]
12 |
13 | respawn
14 | exec /sbin/getty{% if tty.get('autologin', False) %} --autologin {{ tty.autologin }}{% endif %} -8 {{ tty.get('rate', 38400) }} {{ name }}{% if tty.term is defined %} {{ tty.term }}{% endif %}
15 |
--------------------------------------------------------------------------------
/linux/files/ovs_port:
--------------------------------------------------------------------------------
1 | auto {{ port_name }}
2 | allow-{{ port.bridge }} {{ port_name }}
3 | iface {{ port_name }} inet {{ port.get('proto', 'manual') }}
4 | ovs_type {{ port.get('ovs_port_type', 'OVSIntPort') }}
5 | mtu {{ port.get('mtu', '1500') }}
6 | ovs_bridge {{ port.bridge }}
7 | {%- if port.get('proto', 'manual') == 'static' %}
8 | address {{ port.address }}
9 | netmask {{ port.netmask }}
10 | {%- endif %}
11 | {%- if port.gateway is defined %}
12 | gateway {{ port.gateway }}
13 | {%- endif %}
14 | {%- if port.ovs_options is defined %}
15 | ovs_options {{ port.ovs_options }}
16 | {%- endif %}
17 |
--------------------------------------------------------------------------------
/linux/system/locale.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- for locale_name, locale in system.locale.items() %}
5 | {%- if locale.get('enabled', True) %}
6 |
7 | linux_locale_{{ locale_name }}:
8 | locale.present:
9 | - name: {{ locale_name }}
10 |
11 | {%- if locale.get('default', False) %}
12 | linux_locale_default:
13 | locale.system:
14 | - name: {{ locale_name }}
15 | - require:
16 | - locale: linux_locale_{{ locale_name }}
17 | {%- endif %}
18 |
19 | {%- endif %}
20 | {%- endfor %}
21 |
22 | {%- endif %}
23 |
--------------------------------------------------------------------------------
/debian/control:
--------------------------------------------------------------------------------
1 | Source: salt-formula-linux
2 | Maintainer: Ales Komarek
3 | Section: admin
4 | Priority: optional
5 | Build-Depends: salt-master, python, python-yaml, debhelper (>= 9), salt-master, python, python-yaml
6 | Standards-Version: 3.9.6
7 | Homepage: http://www.tcpcloud.eu
8 | Vcs-Browser: https://github.com/tcpcloud/salt-formula-linux
9 | Vcs-Git: https://github.com/tcpcloud/salt-formula-linux.git
10 |
11 | Package: salt-formula-linux
12 | Architecture: all
13 | Depends: ${misc:Depends}
14 | Description: Linux salt formula
15 | Configure Linux operating system.
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014-2015 tcp cloud a. s.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
--------------------------------------------------------------------------------
/linux/files/multipath/_fujitsu_eternus_dxl.conf:
--------------------------------------------------------------------------------
1 |
2 | device {
3 | vendor "FUJITSU"
4 | product "ETERNUS_DXL"
5 | prio alua
6 | path_grouping_policy group_by_prio
7 | path_selector "round-robin 0"
8 | failback immediate
9 | no_path_retry 0 (*1)
10 | path_checker tur
11 | dev_loss_tmo 2097151 (*2)
12 | fast_io_fail_tmo 1
13 | }
14 |
--------------------------------------------------------------------------------
/linux/system/apparmor.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 |
3 | include:
4 | - linux.system.package
5 |
6 | {%- if system.apparmor.enabled %}
7 |
8 | apparmor_service:
9 | service.running:
10 | - name: apparmor
11 | - enable: true
12 | - require:
13 | - pkg: linux_repo_prereq_pkgs
14 |
15 | {%- else %}
16 |
17 | apparmor_service_disable:
18 | service.dead:
19 | - name: apparmor
20 | - enable: false
21 |
22 | apparmor_teardown:
23 | cmd.wait:
24 | - name: /etc/init.d/apparmor teardown
25 | - watch:
26 | - service: apparmor_service_disable
27 |
28 | {%- endif %}
29 |
--------------------------------------------------------------------------------
/linux/system/limit.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- for name, limit in system.limit.items() %}
5 |
6 | linux_limit_{{ name }}:
7 | {%- if limit.get('enabled', True) %}
8 | file.managed:
9 | - name: /etc/security/limits.d/90-salt-{{ name }}.conf
10 | - source: salt://linux/files/limits.conf
11 | - template: jinja
12 | - defaults:
13 | limit_name: {{ name }}
14 | {%- else %}
15 | file.absent:
16 | - name: /etc/security/limits.d/90-salt-{{ name }}.conf
17 | {%- endif %}
18 |
19 | {%- endfor %}
20 |
21 | {%- endif %}
22 |
--------------------------------------------------------------------------------
/linux/files/prompt.sh:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 |
3 | # Don't set special prompt when not using Bash or ZSH
4 | [ -n "$BASH_VERSION" -o -n "$ZSH_VERSION" ] || return 0
5 |
6 | # Don't set prompt on non-interactive shell
7 | [[ $- == *i* ]] || return 0
8 |
9 | {%- for user, prompt in system.prompt.items() %}
10 | {% if user != "default" %}
11 | if [ "$USERNAME" == "{{ user }}" ]; then
12 | export PS1="{{ prompt }} "
13 | return 0
14 | fi
15 | {% endif %}
16 | {%- endfor %}
17 |
18 | {% if system.prompt.default is defined %}
19 | export PS1="{{ system.prompt.default }} "
20 | {%- endif %}
21 |
--------------------------------------------------------------------------------
/linux/files/setup-loopback-device.systemd:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Setup {{ device_name }} device
3 | DefaultDependencies=no
4 | After=systemd-udev-settle.service
5 | Before=lvm2-activation-early.service
6 | Wants=systemd-udev-settle.service
7 |
8 | [Service]
9 | {# The command is prefixed with '-' to consider it a success if the loopback device is already setup #}
10 | ExecStart=-/sbin/losetup {{ device_name }} {{ file }}
11 | {# In order to Salt can recognize oneshot service as running, we need it to remain active after it exited #}
12 | RemainAfterExit=true
13 | Type=oneshot
14 |
15 | [Install]
16 | WantedBy=local-fs.target
17 |
--------------------------------------------------------------------------------
/debian/copyright:
--------------------------------------------------------------------------------
1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
2 | Upstream-Name: salt-formula-linux
3 | Upstream-Contact: Ales Komarek
4 | Source: https://github.com/tcpcloud/salt-formula-linux
5 |
6 | Files: *
7 | Copyright: 2014-2015 tcp cloud a.s.
8 | License: Apache-2.0
9 | Copyright (C) 2014-2015 tcp cloud a.s.
10 | .
11 | Licensed under the Apache License, Version 2.0 (the "License");
12 | you may not use this file except in compliance with the License.
13 | .
14 | On a Debian system you can find a copy of this license in
15 | /usr/share/common-licenses/Apache-2.0.
16 |
--------------------------------------------------------------------------------
/linux/system/autoupdates.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- if system.autoupdates.get('enabled', True) %}
5 |
6 | {%- if system.autoupdates.pkgs %}
7 | linux_autoupdates_packages:
8 | pkg.installed:
9 | - pkgs: {{ system.autoupdates.pkgs | json }}
10 | {%- endif %}
11 |
12 | {%- if grains.os_family == 'Debian' %}
13 | /etc/apt/apt.conf.d/90autoupdates:
14 | file.managed:
15 | - source: salt://linux/files/90autoupdates
16 | - template: jinja
17 | - user: root
18 | - group: root
19 | - mode: 644
20 | {%- endif %}
21 |
22 | {%- endif %}
23 |
24 | {%- endif %}
25 |
--------------------------------------------------------------------------------
/linux/files/preferences_repo:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context -%}
2 | {%- set repo = system.repo[repo_name] -%}
3 | {%- if repo.pinning is defined -%}
4 | {%- for id,pin in repo.pinning|dictsort -%}
5 | {% if pin.get('enabled', False) %}
6 |
7 | Package: {{ pin.get('package','*') }}
8 | Pin: {{ pin.pin }}
9 | Pin-Priority: {{ pin.priority }}
10 | {%- endif %}
11 | {%- endfor -%}
12 | {%- elif repo.pin is defined -%}
13 | {%- for pin in repo.pin -%}
14 | {%- set package = pin.get('package', '*') %}
15 | Package: {{ package }}
16 | Pin: {{ pin.pin }}
17 | Pin-Priority: {{ pin.priority }}
18 | {%- endfor %}
19 | {%- endif -%}
20 |
--------------------------------------------------------------------------------
/linux/files/sysfs.conf:
--------------------------------------------------------------------------------
1 | # Sysfs file for {{ name }} managed by salt-minion(1)
2 | # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
3 |
4 | {%- if sysfs is mapping %}
5 | {%- set sysfs_list = [sysfs] %}
6 | {%- else %}
7 | {%- set sysfs_list = sysfs %}
8 | {%- endif %}
9 |
10 |
11 | {%- for item in sysfs_list %}
12 | {%- for key, value in item.items() %}
13 | {%- if key in ["mode", "owner"] %}
14 | {%- for attr, val in value.items() %}
15 | mode {{ attr }} = {{ val }}
16 | {%- endfor %}
17 | {%- else %}
18 | {{ key }} = {{ value }}
19 | {%- endif %}
20 | {%- endfor %}
21 | {%- endfor %}
22 |
23 | {#-
24 | vim: syntax=jinja
25 | -#}
26 |
--------------------------------------------------------------------------------
/linux/meta/logrotate.yml:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context -%}
2 |
3 | {%- if system.atop.enabled %}
4 | job:
5 | atop:
6 | - files:
7 | - {{ system.atop.logpath }}/atop*
8 | - {{ system.atop.logpath }}/{{ system.atop.outfile }}
9 | options:
10 | - olddir {{ system.atop.logpath }}/old
11 | - compress
12 | - delaycompress
13 | - missingok
14 | - notifempty
15 | - rotate: 10
16 | - daily
17 | - minsize: 20M
18 | - maxsize: 500M
19 | - postrotate: "if ! service atop status > /dev/null; then service atop restart > /dev/null; fi"
20 | {%- endif %}
21 |
--------------------------------------------------------------------------------
/linux/files/proxy.sh:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import network with context %}
2 | export http_proxy="http://{{ network.proxy.host }}:{{ network.proxy.port }}/"
3 | export https_proxy="http://{{ network.proxy.host }}:{{ network.proxy.port }}/"
4 | export ftp_proxy="http://{{ network.proxy.host }}:{{ network.proxy.port }}/"
5 | export no_proxy="localhost,127.0.0.1,localaddress,.localdomain.com"
6 | export HTTP_PROXY="http://{{ network.proxy.host }}:{{ network.proxy.port }}/"
7 | export HTTPS_PROXY="http://{{ network.proxy.host }}:{{ network.proxy.port }}/"
8 | export FTP_PROXY="http://{{ network.proxy.host }}:{{ network.proxy.port }}/"
9 | export NO_PROXY="localhost,127.0.0.1,localaddress,.localdomain.com"
--------------------------------------------------------------------------------
/linux/files/sudoer-aliases:
--------------------------------------------------------------------------------
1 | # sudoer aliases, file managed by salt-minion
2 | # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
3 |
4 | {%- for alias,commands in aliases.get('command',{}).items() %}
5 | Cmnd_Alias {{ alias }}={{ commands|join(', ') }}
6 | {%- endfor %}
7 |
8 | {%- for alias,users in aliases.get('user',{}).items() %}
9 | User_Alias {{ alias }}={{ users|join(', ') }}
10 | {%- endfor %}
11 |
12 | {%- for alias,users in aliases.get('runas',{}).items() %}
13 | Runas_Alias {{ alias }}={{ users|join(', ') }}
14 | {%- endfor %}
15 |
16 | {%- for alias,hosts in aliases.get('host',{}).items() %}
17 | Host_Alias {{ alias }}={{ hosts|join(', ') }}
18 | {%- endfor %}
19 |
20 |
--------------------------------------------------------------------------------
/debian/changelog:
--------------------------------------------------------------------------------
1 | salt-formula-linux (2017.4.1) trusty; urgency=medium
2 |
3 | * New version
4 |
5 | -- Filip Pytloun Tue, 25 Apr 2017 16:05:44 +0200
6 |
7 | salt-formula-linux (2017.4) trusty; urgency=medium
8 |
9 | * New version
10 |
11 | -- Filip Pytloun Tue, 25 Apr 2017 16:03:41 +0200
12 |
13 | salt-formula-linux (0.2) trusty; urgency=medium
14 |
15 | * First public release
16 |
17 | -- Filip Pytloun Tue, 06 Oct 2015 16:38:46 +0200
18 |
19 | salt-formula-linux (0.1) trusty; urgency=medium
20 |
21 | * Initial release
22 |
23 | -- Ales Komarek Thu, 13 Aug 2015 23:23:41 +0200
24 |
--------------------------------------------------------------------------------
/linux/files/resolv.conf:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import network with context %}# Dynamic resolv.conf(5) file for glibc resolver(3) generated by salt-minion(1)
2 | # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
3 | {% if network.resolv.get('search', False) -%}
4 | search {{ network.resolv.search|join(' ') }}
5 | {%- endif %}
6 | {% if network.resolv.get('domain', False) -%}
7 | domain {{ network.resolv.domain }}
8 | {%- endif %}
9 | {%- for nameserver in network.resolv.dns %}
10 | nameserver {{ nameserver }}
11 | {%- endfor %}
12 | {%- if network.resolv.get('options', False) %}
13 | {%- for option in network.resolv.options %}
14 | options {{ option }}
15 | {%- endfor %}
16 | {%- endif %}
17 |
--------------------------------------------------------------------------------
/linux/system/apt.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 | {%- if grains.os_family == 'Debian' %}
4 |
5 | {%- if system.repo|length > 0 %}
6 | include:
7 | - linux.system.repo
8 | {%- endif %}
9 |
10 | {%- for key, config in system.apt.get('config', {}).items() %}
11 |
12 | linux_apt_conf_{{ key }}:
13 | file.managed:
14 | - name: /etc/apt/apt.conf.d/99{{ key }}-salt
15 | - template: jinja
16 | - source: salt://linux/files/apt.conf
17 | - defaults:
18 | config: {{ config|yaml }}
19 | {%- if system.repo|length > 0 %}
20 | - require_in:
21 | - pkg: linux_repo_prereq_pkgs
22 | {%- endif %}
23 |
24 | {%- endfor %}
25 |
26 | {%- endif %}
27 | {%- endif %}
28 |
--------------------------------------------------------------------------------
/linux/storage/multipath.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import storage with context %}
2 | {%- if storage.enabled and storage.multipath.enabled %}
3 |
4 | linux_storage_multipath_packages:
5 | pkg.installed:
6 | - pkgs: {{ storage.multipath.pkgs | json }}
7 |
8 | linux_storage_multipath_config:
9 | file.managed:
10 | - name: /etc/multipath.conf
11 | - source: salt://linux/files/multipath.conf
12 | - template: jinja
13 | - require:
14 | - pkg: linux_storage_multipath_packages
15 |
16 | linux_storage_multipath_service:
17 | service.running:
18 | - enable: true
19 | - name: {{ storage.multipath.service }}
20 | - watch:
21 | - file: linux_storage_multipath_config
22 | - sig: multipathd
23 |
24 | {%- endif %}
25 |
--------------------------------------------------------------------------------
/linux/system/prompt.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | /etc/profile.d/prompt.sh:
5 | file.managed:
6 | - source: salt://linux/files/prompt.sh
7 | - template: jinja
8 |
9 | {%- if grains.os_family == 'Debian' %}
10 | /etc/bash.bashrc:
11 | file.replace:
12 | - pattern: ".*PS1=.*"
13 | - repl: ": # Prompt is set by /etc/profile.d/prompt.sh"
14 |
15 | /etc/skel/.bashrc:
16 | file.replace:
17 | - pattern: ".*PS1=.*"
18 | - repl: ": # Prompt is set by /etc/profile.d/prompt.sh"
19 |
20 | /root/.bashrc:
21 | file.replace:
22 | - pattern: ".*PS1=.*"
23 | - repl: ": # Prompt is set by /etc/profile.d/prompt.sh"
24 | {%- endif %}
25 |
26 | {%- endif %}
27 |
--------------------------------------------------------------------------------
/linux/system/mcelog.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- if system.get('mcelog',{}).get('enabled', False) %}
5 |
6 | mcelog_packages:
7 | pkg.installed:
8 | - name: mcelog
9 |
10 | mcelog_conf:
11 | file.managed:
12 | - name: /etc/mcelog/mcelog.conf
13 | - source: salt://linux/files/mcelog.conf
14 | - template: jinja
15 | - user: root
16 | - group: root
17 | - mode: 644
18 | - require:
19 | - pkg: mcelog_packages
20 |
21 | mce_service:
22 | service.running:
23 | - name: mcelog
24 | - enable: true
25 | - require:
26 | - pkg: mcelog_packages
27 | - watch:
28 | - file: mcelog_conf
29 |
30 | {%- endif %}
31 |
32 | {%- endif %}
33 |
--------------------------------------------------------------------------------
/linux/files/nsswitch.conf:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import ldap with context -%}
2 | # /etc/nsswitch.conf
3 | #
4 | # Example configuration of GNU Name Service Switch functionality.
5 | # If you have the `glibc-doc-reference' and `info' packages installed, try:
6 | # `info libc "Name Service Switch"' for information about this file.
7 |
8 | passwd: compat{%- if ldap.enabled %} ldap{%- endif %}
9 | group: compat{%- if ldap.enabled %} ldap{%- endif %}
10 | shadow: compat{%- if ldap.enabled %} ldap{%- endif %}
11 | gshadow: files
12 |
13 | hosts: files dns
14 | networks: files
15 |
16 | protocols: db files
17 | services: db files
18 | ethers: db files
19 | rpc: db files
20 |
21 | netgroup: nis
22 |
--------------------------------------------------------------------------------
/linux/storage/init.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import storage with context %}
2 | {%- if storage.mount|length > 0 or storage.swap|length > 0 or storage.multipath.enabled or storage.disk|length > 0 or storage.lvm|length > 0 or storage.loopback|length > 0 %}
3 | include:
4 | {%- if storage.loopback|length > 0 %}
5 | - linux.storage.loopback
6 | {%- endif %}
7 | {%- if storage.disk|length > 0 %}
8 | - linux.storage.disk
9 | {%- endif %}
10 | {%- if storage.lvm|length > 0 %}
11 | - linux.storage.lvm
12 | {%- endif %}
13 | {%- if storage.mount|length > 0 %}
14 | - linux.storage.mount
15 | {%- endif %}
16 | {%- if storage.swap|length > 0 %}
17 | - linux.storage.swap
18 | {%- endif %}
19 | {%- if storage.multipath.enabled %}
20 | - linux.storage.multipath
21 | {%- endif %}
22 | {%- endif %}
23 |
--------------------------------------------------------------------------------
/linux/system/journal.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled and grains.get('init', None) == 'systemd' %}
3 |
4 | {%- if system.systemd.journal is defined %}
5 |
6 | linux_systemd_journal_config:
7 | file.managed:
8 | - name: /etc/systemd/journald.conf.d/90-salt.conf
9 | - source: salt://linux/files/journal.conf
10 | - template: jinja
11 | - makedirs: True
12 | - defaults:
13 | settings: {{ system.systemd.journal|tojson }}
14 | - watch_in:
15 | - module: linux_journal_systemd_reload
16 |
17 | linux_journal_systemd_reload:
18 | module.wait:
19 | - name: service.restart
20 | - m_name: systemd-journald
21 | - require:
22 | - module: service.systemctl_reload
23 |
24 | {%- endif %}
25 | {%- endif %}
--------------------------------------------------------------------------------
/linux/system/console.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- if system.console is defined %}
5 |
6 | {%- for tty_name, console in system.console.items() %}
7 |
8 | {%- if grains.get('init', None) == 'upstart' %}
9 | {{ tty_name }}_service_file:
10 | file.managed:
11 | - name: /etc/init/{{ tty_name }}.conf
12 | - source: salt://linux/files/tty.upstart
13 | - template: jinja
14 | - defaults:
15 | name: {{ tty_name }}
16 | tty: {{ console }}
17 | {%- endif %}
18 |
19 | {{ tty_name }}_service:
20 | service.running:
21 | - enable: true
22 | - name: {{ tty_name }}
23 | - watch:
24 | - file: {{ tty_name }}_service_file
25 |
26 | {%- endfor %}
27 |
28 | {%- endif %}
29 |
30 | {%- endif %}
31 |
--------------------------------------------------------------------------------
/linux/files/multipath.conf:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import storage with context %}
2 | ##
3 | ## This is multipath-tools configuration file managed by Salt
4 | ##
5 |
6 | defaults {
7 | # getuid_callout "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
8 | user_friendly_names no
9 | }
10 |
11 | blacklist {
12 | {%- for device in storage.multipath.get('blacklist_devices', []) %}
13 | wwid {{ salt['cmd.shell']('/lib/udev/scsi_id -g -u '+device) }}
14 | {%- endfor %}
15 | devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st|nbd)[0-9]*"
16 | }
17 |
18 | devices {
19 | {%- for backend in storage.multipath.get('backends', []) %}
20 | {%- include "linux/files/multipath/_" + backend + ".conf" %}
21 | {%- endfor %}
22 | }
23 |
--------------------------------------------------------------------------------
/linux/system/profile.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | profile.d_clean:
5 | file.directory:
6 | - name: /etc/profile.d
7 | - clean: true
8 | - exclude_pat: 'E@^((?!salt_profile*).)*$'
9 |
10 | {%- if system.profile|length > 0 %}
11 |
12 | {%- for name, script in system.profile.items() %}
13 | profile.d_script_{{ name }}:
14 | file.managed:
15 | - name: /etc/profile.d/salt_profile_{{ name }}{%if name.split('.')|length == 1 %}.sh{% endif %}
16 | - source:
17 | - salt://linux/files/etc_profile_{{ name }}
18 | - salt://linux/files/etc_profile
19 | - template: jinja
20 | - defaults:
21 | script: {{ script|yaml }}
22 | - require_in:
23 | - file: profile.d_clean
24 | {% endfor %}
25 |
26 | {%- endif %}
27 | {%- endif %}
28 |
29 |
--------------------------------------------------------------------------------
/linux/network/init.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import network with context %}
2 | include:
3 | {%- if network.hostname is defined %}
4 | - linux.network.hostname
5 | {%- endif %}
6 | {%- if network.host|length > 0 or network.get('purge_hosts', True) %}
7 | - linux.network.host
8 | {%- endif %}
9 | {%- if network.dpdk is defined %}
10 | - linux.network.dpdk
11 | {%- endif %}
12 | {%- if network.dhclient is defined %}
13 | - linux.network.dhclient
14 | {%- endif %}
15 | {%- if network.systemd|length > 0 %}
16 | - linux.network.systemd
17 | {%- endif %}
18 | {%- if network.openvswitch is defined %}
19 | - linux.network.openvswitch
20 | {%- endif %}
21 | {%- if network.interface|length > 0 %}
22 | - linux.network.interface
23 | {%- endif %}
24 | {%- if network.resolv is defined %}
25 | - linux.network.resolv
26 | {%- endif %}
27 | - linux.network.proxy
28 |
--------------------------------------------------------------------------------
/linux/system/auth/duo.sls:
--------------------------------------------------------------------------------
1 | {%- if grains['os'] == 'Ubuntu' %}
2 |
3 | package_duo:
4 | pkg.installed:
5 | - name: duo-unix
6 | - skip_verify: True
7 |
8 |
9 | login_duo:
10 | file.managed:
11 | - name: /etc/duo/login_duo.conf
12 | - source: salt://linux/files/login_duo.conf
13 | - template: jinja
14 | - user: 'root'
15 | - group: 'root'
16 | - mode: '0600'
17 |
18 |
19 | pam_duo:
20 | file.managed:
21 | - name: /etc/duo/pam_duo.conf
22 | - source: salt://linux/files/login_duo.conf
23 | - template: jinja
24 | - user: 'root'
25 | - group: 'root'
26 | - mode: '0600'
27 |
28 | pam-sshd_config:
29 | file.managed:
30 | - name: /etc/pam.d/sshd
31 | - user: root
32 | - group: root
33 | - source: salt://linux/files/pam-sshd
34 | - mode: 600
35 | - template: jinja
36 |
37 | {%- endif %}
38 |
39 |
--------------------------------------------------------------------------------
/linux/files/etc_environment:
--------------------------------------------------------------------------------
1 |
2 | {%- for name,value in variables.items() if not name.lower().endswith('_proxy') %}
3 |
4 | {%- if value is sequence and value is not string %}
5 | {{ name }}="{{ value|join(':') }}"
6 |
7 | {%- else %}
8 | {{ name }}="{{ value }}"
9 |
10 | {%- endif %}
11 | {%- endfor %}
12 |
13 | {%- if ftp_proxy and ftp_proxy.lower() != 'none' %}
14 | ftp_proxy="{{ ftp_proxy }}"
15 | FTP_PROXY="{{ ftp_proxy }}"
16 | {%- endif %}
17 |
18 | {%- if http_proxy and http_proxy.lower() != 'none' %}
19 | http_proxy="{{ http_proxy }}"
20 | HTTP_PROXY="{{ http_proxy }}"
21 | {%- endif %}
22 |
23 | {%- if https_proxy and https_proxy.lower() != 'none' %}
24 | https_proxy="{{ https_proxy }}"
25 | HTTPS_PROXY="{{ https_proxy }}"
26 | {%- endif %}
27 |
28 | {%- if no_proxy %}
29 | no_proxy="{{ no_proxy|join(',') }}"
30 | NO_PROXY="{{ no_proxy|join(',') }}"
31 | {%- endif %}
32 |
33 |
--------------------------------------------------------------------------------
/linux/files/netconsole.conf:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | # default port is 514
3 | #PORT=6666
4 | {%- if system.netconsole is mapping and system.netconsole.port is defined %}
5 | PORT="{{ system.netconsole.port }}"
6 | {%- endif %}
7 |
8 | # unicast, could be multiline
9 | #netconsole ens3 192.168.1.32 fa:16:3e:8d:f6:d0
10 | {%- if system.netconsole is mapping and system.netconsole.target is mapping %}
11 | {%- for target, data in system.netconsole.target.items() %}
12 | {%- if data is mapping %}
13 | netconsole "{{ data.get('interface', '${interface}') }}" "{{ target }}" "{{ data.get('mac', '') }}"
14 | {%- endif %}
15 | {%- endfor %}
16 | {%- endif %}
17 |
18 | # set up dmesg log level
19 | # dmesg -n info
20 | {%- if system.netconsole is mapping and system.netconsole.loglevel is defined %}
21 | dmesg -n "{{ system.netconsole.loglevel }}"
22 | {%- endif %}
23 |
--------------------------------------------------------------------------------
/tests/pillar/system_file.sls:
--------------------------------------------------------------------------------
1 | linux:
2 | network:
3 | enabled: true
4 | hostname: linux
5 | fqdn: linux.ci.local
6 | system:
7 | name: linux
8 | enabled: true
9 | file:
10 | /tmp/sample.txt:
11 | source: http://techslides.com/demos/samples/sample.txt
12 | source_hash: 5452459724e85b4e12277d5f8aab8fc9
13 | sample2.txt:
14 | name: /tmp/sample2.txt
15 | source: http://techslides.com/demos/samples/sample.txt
16 | test2:
17 | name: /tmp/test2.txt
18 | contents: |
19 | line1
20 | line2
21 | user: root
22 | group: root
23 | mode: 700
24 | dir_mode: 700
25 | encoding: utf-8
26 | makedirs: true
27 | test3:
28 | name: /tmp/test3.txt
29 | source: salt://linux/files/test/file_template.jinja
30 | template: jinja
31 | test:
32 | example: "bar"
33 |
--------------------------------------------------------------------------------
/linux/files/pam-add-profile:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ "$(basename $EDITOR 2>/dev/null)" == "$(basename $0)" ]; then
4 | PROFILES=$(debconf-get-selections | grep libpam-runtime/profiles | awk '{$1=$2=$3=""; print $0}')
5 |
6 | for profile in ${PROFILE[@]}; do
7 | if [[ $PROFILES =~ $profile ]]; then
8 | continue
9 | else
10 | PROFILES="${PROFILES}, ${profile}"
11 | fi
12 | done
13 |
14 | for profile in /usr/share/pam-configs/*; do
15 | profile_name=$(grep Name: $profile | cut -d ' ' -f 2-)
16 | PROFILES=$(echo $PROFILES | sed s,$(basename $profile),"${profile_name}",g)
17 | done
18 |
19 | cat > $1 <
21 | #
22 | # Remediation
23 | # ===========
24 | # Edit or create the file /etc/modprobe.d/CIS.conf and add the following line:
25 | #
26 | # install hfs /bin/true
27 | #
28 | parameters:
29 | linux:
30 | system:
31 | kernel:
32 | module:
33 | hfs:
34 | install:
35 | command: /bin/true
36 |
37 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-3-5-4.yml:
--------------------------------------------------------------------------------
1 | # 3.5.4 Ensure TIPC is disabled
2 | #
3 | # Description
4 | # ===========
5 | # The Transparent Inter-Process Communication (TIPC) protocol is designed
6 | # to provide communication between cluster nodes.
7 | #
8 | # Rationale
9 | # =========
10 | # If the protocol is not being used, it is recommended that kernel module
11 | # not be loaded, disabling the service to reduce the potential attack surface.
12 | #
13 | # Audit
14 | # =====
15 | # Run the following commands and verify the output is as indicated:
16 | #
17 | # # modprobe -n -v tipc
18 | # install /bin/true
19 | # # lsmod | grep tipc
20 | #
21 | #
22 | # Remediation
23 | # ===========
24 | #
25 | # Edit or create the file /etc/modprobe.d/CIS.conf and add the following line:
26 | #
27 | # install tipc /bin/true
28 | #
29 | parameters:
30 | linux:
31 | system:
32 | kernel:
33 | module:
34 | tipc:
35 | install:
36 | command: /bin/true
37 |
38 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-1-1-1-3.yml:
--------------------------------------------------------------------------------
1 | # 1.1.1.3 Ensure mounting of jffs2 filesystems is disabled
2 | #
3 | # Description
4 | # ===========
5 | # The jffs2 (journaling flash filesystem 2) filesystem type is a
6 | # log-structured filesystem used in flash memory devices.
7 | #
8 | # Rationale
9 | # =========
10 | # Removing support for unneeded filesystem types reduces the local attack
11 | # surface of the system. If this filesystem type is not needed, disable it.
12 | #
13 | # Audit
14 | # =====
15 | # Run the following commands and verify the output is as indicated:
16 | #
17 | # # modprobe -n -v jffs2
18 | # install /bin/true
19 | # # lsmod | grep jffs2
20 | #
21 | #
22 | # Remediation
23 | # ===========
24 | # Edit or create the file /etc/modprobe.d/CIS.conf and add the following line:
25 | #
26 | # install jffs2 /bin/true
27 | #
28 | parameters:
29 | linux:
30 | system:
31 | kernel:
32 | module:
33 | jffs2:
34 | install:
35 | command: /bin/true
36 |
37 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-1-1-1-5.yml:
--------------------------------------------------------------------------------
1 | # 1.1.1.5 Ensure mounting of hfsplus filesystems is disabled
2 | #
3 | # Description
4 | # ===========
5 | # The hfsplus filesystem type is a hierarchical filesystem designed to
6 | # replace hfs that allows you to mount Mac OS filesystems.
7 | #
8 | # Rationale
9 | # =========
10 | # Removing support for unneeded filesystem types reduces the local attack
11 | # surface of the system. If this filesystem type is not needed, disable it.
12 | #
13 | # Audit
14 | # =====
15 | # Run the following commands and verify the output is as indicated:
16 | #
17 | # # modprobe -n -v hfsplus
18 | # install /bin/true
19 | # # lsmod | grep hfsplus
20 | #
21 | #
22 | # Remediation
23 | # ===========
24 | # Edit or create the file /etc/modprobe.d/CIS.conf and add the following line:
25 | #
26 | # install hfsplus /bin/true
27 | #
28 | parameters:
29 | linux:
30 | system:
31 | kernel:
32 | module:
33 | hfsplus:
34 | install:
35 | command: /bin/true
36 |
37 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-1-1-1-2.yml:
--------------------------------------------------------------------------------
1 | # 1.1.1.2 Ensure mounting of freevxfs filesystems is disabled
2 | #
3 | # Description
4 | # ===========
5 | # The freevxfs filesystem type is a free version of the Veritas type
6 | # filesystem. This is the primary filesystem type for HP-UX operating systems.
7 | #
8 | # Rationale
9 | # =========
10 | # Removing support for unneeded filesystem types reduces the local attack
11 | # surface of the system. If this filesystem type is not needed, disable it.
12 | #
13 | # Audit
14 | # =====
15 | # Run the following commands and verify the output is as indicated:
16 | #
17 | # # modprobe -n -v freevxfs
18 | # install /bin/true
19 | # # lsmod | grep freevxfs
20 | #
21 | #
22 | # Remediation
23 | # ===========
24 | # Edit or create the file /etc/modprobe.d/CIS.conf and add the following line:
25 | #
26 | # install freevxfs /bin/true
27 | #
28 | parameters:
29 | linux:
30 | system:
31 | kernel:
32 | module:
33 | freevxfs:
34 | install:
35 | command: /bin/true
36 |
37 |
--------------------------------------------------------------------------------
/linux/network/hostname.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import network with context %}
2 | {%- if network.enabled %}
3 |
4 | {%- if grains.os_family in ['Arch', 'Debian'] %}
5 |
6 | linux_hostname_file:
7 | file.managed:
8 | - name: {{ network.hostname_file }}
9 | - source: salt://linux/files/hostname
10 | - template: jinja
11 | - user: root
12 | - group: root
13 | - mode: 644
14 | - watch_in:
15 | - cmd: linux_enforce_hostname
16 |
17 | {%- endif %}
18 |
19 | {# Change state to proper one, after releasing patch:
20 | https://github.com/saltstack/salt/pull/45748/files/74599bbdfcf99f45d3a31296887097fade31cbf1
21 | linux_enforce_hostname:
22 | network.system:
23 | - enabled: True
24 | - hostname: {{ network.hostname }}
25 | - apply_hostname: True
26 | - retain_settings: True
27 | #}
28 | linux_enforce_hostname:
29 | cmd.run:
30 | - name: hostname {{ network.hostname }}
31 | - unless: test "$(hostname)" = "{{ network.hostname }}"
32 | {%- if grains.get('noservices') %}
33 | - onlyif: /bin/false
34 | {%- endif %}
35 |
36 | {%- endif %}
37 |
--------------------------------------------------------------------------------
/linux/system/grub.sls:
--------------------------------------------------------------------------------
1 | grub_d_directory:
2 | file.directory:
3 | - name: /etc/default/grub.d
4 | - user: root
5 | - group: root
6 | - mode: 755
7 | - makedirs: True
8 |
9 | {%- if grains['os_family'] == 'RedHat' %}
10 | {%- set boot_grub_cfg = '/boot/grub2/grub.cfg' %}
11 | /etc/default/grub:
12 | file.append:
13 | - text:
14 | - for i in $(ls /etc/default/grub.d);do source /etc/default/grub.d/$i ;done
15 |
16 | grub_update:
17 | cmd.wait:
18 | - name: grub2-mkconfig -o {{ boot_grub_cfg }}
19 |
20 | {%- else %}
21 | {%- set boot_grub_cfg = '/boot/grub/grub.cfg' %}
22 |
23 | grub_update:
24 | cmd.wait:
25 | - name: update-grub
26 | {%- if grains.get('virtual_subtype') in ['Docker', 'LXC'] %}
27 | - onlyif: /bin/false
28 | {%- endif %}
29 |
30 | {%- endif %}
31 |
32 | grub_cfg_permissions:
33 | file.managed:
34 | - name: {{ boot_grub_cfg }}
35 | - user: 'root'
36 | - owner: 'root'
37 | - mode: '400'
38 | - replace: false
39 | - onlyif: test -f {{ boot_grub_cfg }}
40 | - require:
41 | - cmd: grub_update
42 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-3-5-3.yml:
--------------------------------------------------------------------------------
1 | # 3.5.3 Ensure RDS is disabled
2 | #
3 | # Description
4 | # ===========
5 | # The Reliable Datagram Sockets (RDS) protocol is a transport layer protocol
6 | # designed to provide low-latency, high-bandwidth communications between
7 | # cluster nodes. It was developed by the Oracle Corporation.
8 | #
9 | # Rationale
10 | # =========
11 | # If the protocol is not being used, it is recommended that kernel module
12 | # not be loaded, disabling the service to reduce the potential attack surface.
13 | #
14 | # Audit
15 | # =====
16 | # Run the following commands and verify the output is as indicated:
17 | #
18 | # # modprobe -n -v rds
19 | # install /bin/true
20 | # # lsmod | grep rds
21 | #
22 | #
23 | # Remediation
24 | # ===========
25 | # Edit or create the file /etc/modprobe.d/CIS.conf and add the following line:
26 | #
27 | # install rds /bin/true
28 | #
29 | parameters:
30 | linux:
31 | system:
32 | kernel:
33 | module:
34 | rds:
35 | install:
36 | command: /bin/true
37 |
38 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-1-1-1-1.yml:
--------------------------------------------------------------------------------
1 | # 1.1.1.1 Ensure mounting of cramfs filesystems is disabled
2 | #
3 | # Description
4 | # ===========
5 | # The cramfs filesystem type is a compressed read-only Linux filesystem
6 | # embedded in small footprint systems. A cramfs image can be used without
7 | # having to first decompress the image.
8 | #
9 | # Rationale
10 | # =========
11 | # Removing support for unneeded filesystem types reduces the local attack
12 | # surface of the server. If this filesystem type is not needed, disable it.
13 | #
14 | # Audit
15 | # =====
16 | # Run the following commands and verify the output is as indicated:
17 | #
18 | # # modprobe -n -v cramfs
19 | # install /bin/true
20 | # # lsmod | grep cramfs
21 | #
22 | #
23 | # Remediation
24 | # ===========
25 | # Edit or create the file /etc/modprobe.d/CIS.conf and add the following line:
26 | #
27 | # install cramfs /bin/true
28 | #
29 | parameters:
30 | linux:
31 | system:
32 | kernel:
33 | module:
34 | cramfs:
35 | install:
36 | command: /bin/true
37 |
38 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-6-1-6.yml:
--------------------------------------------------------------------------------
1 | # CIS 6.1.6 Ensure permissions on /etc/passwd- are configured
2 | #
3 | # Description
4 | # ===========
5 | # The /etc/passwd- file contains backup user account information.
6 | #
7 | # Rationale
8 | # =========
9 | # It is critical to ensure that the /etc/passwd- file is protected from
10 | # unauthorized access. Although it is protected by default, the file
11 | # permissions could be changed either inadvertently or through malicious actions.
12 | #
13 | # Audit
14 | # =====
15 | # Run the following command and verify Uid and Gid are both 0/root and
16 | # Access is 600 or more restrictive:
17 | #
18 | # # stat /etc/passwd-
19 | # Access: (0600/-rw-------) Uid: (0/root) Gid: (0/root)
20 | #
21 | # Remediation
22 | # ===========
23 | # Run the following command to set permissions on /etc/passwd- :
24 | #
25 | # # chown root:root /etc/passwd-
26 | # # chmod 600 /etc/passwd-
27 | #
28 | parameters:
29 | linux:
30 | system:
31 | file:
32 | /etc/passwd-:
33 | user: 'root'
34 | group: 'root'
35 | mode: '0600'
36 |
37 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-1-5-4.yml:
--------------------------------------------------------------------------------
1 | # CIS 1.5.4 Ensure prelink is disabled
2 | #
3 | # Description
4 | # ===========
5 | # prelink is a program that modifies ELF shared libraries and ELF dynamically
6 | # linked binaries in such a way that the time needed for the dynamic linker to
7 | # perform relocations at startup significantly decreases.
8 | #
9 | # Rationale
10 | # =========
11 | # The prelinking feature can interfere with the operation of AIDE, because it
12 | # changes binaries. Prelinking can also increase the vulnerability of the system
13 | # if a malicious user is able to compromise a common library such as libc.
14 | #
15 | # Audit
16 | # =====
17 | # Run the following command and verify prelink is not installed:
18 | #
19 | # # dpkg -s prelink
20 | #
21 | # Remediation
22 | # ===========
23 | # Run the following command to restore binaries to normal:
24 | #
25 | # # prelink -ua
26 | #
27 | # Run the following command to uninstall prelink :
28 | #
29 | # # apt-get remove prelink
30 | #
31 | parameters:
32 | linux:
33 | system:
34 | package:
35 | prelink:
36 | version: removed
37 |
38 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-6-1-8.yml:
--------------------------------------------------------------------------------
1 | # CIS 6.1.8 Ensure permissions on /etc/group- are configured
2 | #
3 | # Description
4 | # ===========
5 | # The /etc/group- file contains a backup list of all the valid groups defined
6 | # in the system.
7 | #
8 | # Rationale
9 | # =========
10 | # It is critical to ensure that the /etc/group- file is protected from
11 | # unauthorized access. Although it is protected by default, the file
12 | # permissions could be changed either inadvertently or through malicious actions.
13 | #
14 | # Audit
15 | # =====
16 | # Run the following command and verify Uid and Gid are both 0/root and
17 | # Access is 600 or more restrictive:
18 | #
19 | # # stat /etc/group-
20 | # Access: (0600/-rw-------) Uid: (0/root) Gid: (0/root)
21 | #
22 | # Remediation
23 | # ===========
24 | # Run the following command to set permissions on /etc/group- :
25 | #
26 | # # chown root:root /etc/group-
27 | # # chmod 600 /etc/group-
28 | #
29 | parameters:
30 | linux:
31 | system:
32 | file:
33 | /etc/group-:
34 | user: 'root'
35 | group: 'root'
36 | mode: '0600'
37 |
38 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-1-5-3.yml:
--------------------------------------------------------------------------------
1 | # 1.5.3 Ensure address space layout randomization (ASLR) is enabled
2 | #
3 | # Description
4 | # ===========
5 | #
6 | # Address space layout randomization (ASLR) is an exploit mitigation technique which
7 | # randomly arranges the address space of key data areas of a process.
8 | #
9 | # Rationale
10 | # =========
11 | #
12 | # Randomly placing virtual memory regions will make it difficult to write memory page
13 | # exploits as the memory placement will be consistently shifting.
14 | #
15 | # Audit
16 | # =====
17 | #
18 | # Run the following command and verify output matches:
19 | #
20 | # # sysctl kernel.randomize_va_space
21 | # kernel.randomize_va_space = 2
22 | #
23 | # Remediation
24 | # ===========
25 | #
26 | # Set the following parameter in the /etc/sysctl.conf file:
27 | #
28 | # kernel.randomize_va_space = 2
29 | #
30 | # Run the following command to set the active kernel parameter:
31 | #
32 | # # sysctl -w kernel.randomize_va_space=2
33 |
34 | parameters:
35 | linux:
36 | system:
37 | kernel:
38 | sysctl:
39 | kernel.randomize_va_space: 2
40 |
41 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-3-5-1.yml:
--------------------------------------------------------------------------------
1 | # 3.5.2 Ensure DCCP is disabled
2 | #
3 | # Description
4 | # ===========
5 | # The Datagram Congestion Control Protocol (DCCP) is a transport layer protocol
6 | # that supports streaming media and telephony. DCCP provides a way to gain
7 | # access to congestion control, without having to do it at the application
8 | # layer, but does not provide in-sequence delivery.
9 | #
10 | # Rationale
11 | # =========
12 | # If the protocol is not required, it is recommended that the drivers not be
13 | # installed to reduce the potential attack surface.
14 | #
15 | # Audit
16 | # =====
17 | # Run the following commands and verify the output is as indicated:
18 | #
19 | # # modprobe -n -v dccp
20 | # install /bin/true
21 | # # lsmod | grep dccp
22 | #
23 | #
24 | # Remediation
25 | # ===========
26 | # Edit or create the file /etc/modprobe.d/CIS.conf and add the following line:
27 | #
28 | # install dccp /bin/true
29 | #
30 | parameters:
31 | linux:
32 | system:
33 | kernel:
34 | module:
35 | dccp:
36 | install:
37 | command: /bin/true
38 |
39 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-6-1-4.yml:
--------------------------------------------------------------------------------
1 | # CIS 6.1.4 Ensure permissions on /etc/group are configured
2 | #
3 | # Description
4 | # ===========
5 | # The /etc/group file contains a list of all the valid groups defined in the
6 | # system. The command below allows read/write access for root and read access
7 | # for everyone else.
8 | #
9 | # Rationale
10 | # =========
11 | # The /etc/group file needs to be protected from unauthorized changes by
12 | # non-privileged users, but needs to be readable as this information is used
13 | # with many non-privileged programs.
14 | #
15 | # Audit
16 | # =====
17 | # Run the following command and verify Uid and Gid are both 0/root and
18 | # Access is 644 :
19 | #
20 | # # stat /etc/group
21 | # Access: (0644/-rw-r--r--) Uid: (0/root) Gid: (0/root)
22 | #
23 | # Remediation
24 | # ===========
25 | # Run the following command to set permissions on /etc/group :
26 | #
27 | # # chown root:root /etc/group
28 | # # chmod 644 /etc/group
29 | #
30 | parameters:
31 | linux:
32 | system:
33 | file:
34 | /etc/group:
35 | user: 'root'
36 | group: 'root'
37 | mode: '0644'
38 |
39 |
--------------------------------------------------------------------------------
/linux/system/certificate.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- if system.ca_certificates is defined %}
5 |
6 | linux_system_ca_certificates:
7 | pkg.installed:
8 | - name: ca-certificates
9 | {%- if system.ca_certificates is mapping %}
10 |
11 | {%- for name, cert in system.ca_certificates.items() %}
12 | {{ system.ca_certs_dir }}/{{ name }}.crt:
13 | file.managed:
14 | - contents_pillar: "linux:system:ca_certificates:{{ name }}"
15 | - watch_in:
16 | - cmd: update_certificates
17 | - require:
18 | - pkg: linux_system_ca_certificates
19 | {%- endfor %}
20 |
21 | {%- else %}
22 | {#- salt-pki way #}
23 |
24 | {%- for certificate in system.ca_certificates %}
25 | {{ system.ca_certs_dir }}/{{ certificate }}.crt:
26 | file.managed:
27 | - source: salt://pki/{{ certificate }}/{{ certificate }}-chain.cert.pem
28 | - watch_in:
29 | - cmd: update_certificates
30 | - require:
31 | - pkg: linux_system_ca_certificates
32 | {%- endfor %}
33 |
34 | {%- endif %}
35 |
36 | update_certificates:
37 | cmd.wait:
38 | - name: {{ system.ca_certs_bin }}
39 |
40 | {%- endif %}
41 |
42 | {%- endif %}
43 |
--------------------------------------------------------------------------------
/linux/system/systemd.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled and grains.get('init', None) == 'systemd' %}
3 | {%- if system.systemd.journal is defined %}
4 | include:
5 | - linux.system.journal
6 | {%- endif %}
7 |
8 | {%- if system.systemd.system is defined %}
9 | linux_systemd_system_config:
10 | file.managed:
11 | - name: /etc/systemd/system.conf.d/90-salt.conf
12 | - source: salt://linux/files/systemd.conf
13 | - template: jinja
14 | - makedirs: True
15 | - defaults:
16 | settings: {{ system.systemd.system }}
17 | - watch_in:
18 | - module: linux_systemd_reload
19 | {%- endif %}
20 |
21 | {%- if system.systemd.user is defined %}
22 | linux_systemd_user_config:
23 | file.managed:
24 | - name: /etc/systemd/user.conf.d/90-salt.conf
25 | - source: salt://linux/files/systemd.conf
26 | - template: jinja
27 | - makedirs: True
28 | - defaults:
29 | settings: {{ system.systemd.user }}
30 | - watch_in:
31 | - module: linux_systemd_reload
32 | {%- endif %}
33 |
34 | linux_systemd_reload:
35 | module.wait:
36 | - name: service.systemctl_reload
37 |
38 | {%- endif %}
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-6-1-2.yml:
--------------------------------------------------------------------------------
1 | # CIS 6.1.2 Ensure permissions on /etc/passwd are configured
2 | #
3 | # Description
4 | # ===========
5 | # The /etc/passwd file contains user account information that is used by
6 | # many system utilities and therefore must be readable for these utilities
7 | # to operate.
8 | #
9 | # Rationale
10 | # =========
11 | # It is critical to ensure that the /etc/passwd file is protected from
12 | # unauthorized write access. Although it is protected by default, the file
13 | # permissions could be changed either inadvertently or through malicious actions.
14 | #
15 | # Audit
16 | # =====
17 | # Run the following command and verify Uid and Gid are both 0/root and
18 | # Access is 644 :
19 | #
20 | # # stat /etc/passwd
21 | # Access: (0644/-rw-r--r--) Uid: (0/root) Gid: (0/root)
22 | #
23 | # Remediation
24 | # ===========
25 | # Run the following command to set permissions on /etc/passwd :
26 | #
27 | # # chown root:root /etc/passwd
28 | # # chmod 644 /etc/passwd
29 | #
30 | parameters:
31 | linux:
32 | system:
33 | file:
34 | /etc/passwd:
35 | user: 'root'
36 | group: 'root'
37 | mode: '0644'
38 |
39 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-1-1-1-7.yml:
--------------------------------------------------------------------------------
1 | # 1.1.1.7 Ensure mounting of udf filesystems is disabled
2 | #
3 | # Description
4 | # ===========
5 | # The udf filesystem type is the universal disk format used to implement
6 | # ISO/IEC 13346 and ECMA-167 specifications. This is an open vendor filesystem
7 | # type for data storage on a broad range of media. This filesystem type is
8 | # necessary to support writing DVDs and newer optical disc formats.
9 | #
10 | # Rationale
11 | # =========
12 | # Removing support for unneeded filesystem types reduces the local attack
13 | # surface of the server. If this filesystem type is not needed, disable it.
14 | #
15 | # Audit
16 | # =====
17 | # Run the following commands and verify the output is as indicated:
18 | #
19 | # # modprobe -n -v udf
20 | # install /bin/true
21 | # # lsmod | grep udf
22 | #
23 | #
24 | # Remediation
25 | # ===========
26 | # Edit or create the file /etc/modprobe.d/CIS.conf and add the following line:
27 | #
28 | # install udf /bin/true
29 | #
30 | parameters:
31 | linux:
32 | system:
33 | kernel:
34 | module:
35 | udf:
36 | install:
37 | command: /bin/true
38 |
39 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-2-3-3.yml:
--------------------------------------------------------------------------------
1 | # 2.3.3 Ensure talk client is not installed
2 | #
3 | # Description
4 | # ===========
5 | # The talk software makes it possible for users to send and receive messages
6 | # across systems through a terminal session. The talk client, which allows
7 | # initialization of talk sessions, is installed by default.
8 | #
9 | # Rationale
10 | # =========
11 | # The software presents a security risk as it uses unencrypted protocols
12 | # for communication.
13 | #
14 | # Audit
15 | # =====
16 | # Run the following command and verify talk is not installed:
17 | #
18 | # dpkg -s talk
19 | #
20 | # Remediation
21 | # ===========
22 | # Run the following command to uninstall talk :
23 | #
24 | # apt-get remove talk
25 | #
26 | # Impact
27 | # ======
28 | # Many insecure service clients are used as troubleshooting tools and in
29 | # testing environments. Uninstalling them can inhibit capability to test
30 | # and troubleshoot. If they are required it is advisable to remove the clients
31 | # after use to prevent accidental or intentional misuse.
32 | #
33 | parameters:
34 | linux:
35 | system:
36 | package:
37 | talk:
38 | version: removed
39 |
40 |
--------------------------------------------------------------------------------
/linux/meta/telegraf.yml:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import monitoring with context %}
2 | agent:
3 | input:
4 | cpu:
5 | percpu: false
6 | totalcpu: true
7 | disk:
8 | ignore_fs:
9 | - aufs
10 | - rootfs
11 | - sysfs
12 | - proc
13 | - devtmpfs
14 | - devpts
15 | - tmpfs
16 | - fusectl
17 | - cgroup
18 | - overlay
19 | diskio:
20 | kernel:
21 | net:
22 | mem:
23 | nstat:
24 | fieldpass:
25 | - packet_drop
26 | - time_squeeze
27 | processes:
28 | swap:
29 | system:
30 | procstat:
31 | process:
32 | sshd:
33 | exe: sshd
34 | cron:
35 | exe: cron
36 | linux_sysctl_fs:
37 | {%- if monitoring.bond_status.interfaces is defined and monitoring.bond_status.interfaces %}
38 | bond:
39 | template: linux/files/telegraf.conf
40 | {%- if monitoring.bond_status.interfaces is list %}
41 | bond_interfaces: {{ monitoring.bond_status.interfaces }}
42 | {%- endif %}
43 | {%- if monitoring.bond_status.host_proc is defined %}
44 | host_proc: {{ monitoring.bond_status.host_proc }}
45 | {%- endif %}
46 | {%- endif %}
47 |
--------------------------------------------------------------------------------
/linux/system/env.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- if system.env|length > 0 %}
5 |
6 | linux_system_environment_proxies:
7 | file.blockreplace:
8 | - name: /etc/environment
9 | - marker_start: '# START - SALT MANAGED VARIABLES, DO NOT EDIT'
10 | - marker_end: '# END - SALT MANAGED VARIABLES'
11 | - template: jinja
12 | - source: salt://linux/files/etc_environment
13 | - append_if_not_found: True
14 | - backup: '.bak'
15 | - show_changes: True
16 | - defaults:
17 | variables: {{ system.env | yaml }}
18 | no_proxy: {{ system.env.get('no_proxy', None) }}
19 | https_proxy: {{ system.env.get('https_proxy', None) }}
20 | http_proxy: {{ system.env.get('http_proxy', None) }}
21 | ftp_proxy: {{ system.env.get('ftp_proxy', None) }}
22 |
23 | {%- else %}
24 |
25 | linux_system_environment_proxies:
26 | file.blockreplace:
27 | - name: /etc/environment
28 | - marker_start: '# SALT MANAGED VARIABLES - DO NOT EDIT - START'
29 | - content: '# '
30 | - marker_end: '# SALT MANAGED VARIABLES - END'
31 | - append_if_not_found: True
32 | - backup: '.bak'
33 | - show_changes: True
34 |
35 | {%- endif %}
36 | {%- endif %}
37 |
--------------------------------------------------------------------------------
/linux/files/90autoupdates:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context -%}
2 |
3 | {%- if system.autoupdates.enabled %}
4 | APT::Periodic::Enable "1";
5 | APT::Periodic::Update-Package-Lists "1";
6 | APT::Periodic::Unattended-Upgrade "1";
7 | {%- else %}
8 | APT::Periodic::Unattended-Upgrade "0";
9 | {%- endif %}
10 |
11 | {%- if system.autoupdates.mail is defined %}
12 | Unattended-Upgrade::Mail "{{ system.autoupdates.mail }}";
13 | {%- endif %}
14 |
15 | {%- if system.autoupdates.mail_only_on_error is defined %}
16 | Unattended-Upgrade::MailOnlyOnError "{{ "true" if system.autoupdates.mail_only_on_error else "false"}}";
17 | {%- endif %}
18 |
19 | {%- if system.autoupdates.remove_unused_dependencies is defined %}
20 | Unattended-Upgrade::Remove-Unused-Dependencies "{{ "true" if system.autoupdates.remove_unused_dependencies else "false"}}";
21 | {%- endif %}
22 |
23 | {%- if system.autoupdates.automatic_reboot is defined %}
24 | Unattended-Upgrade::Automatic-Reboot "{{ "true" if system.autoupdates.automatic_reboot else "false"}}";
25 | {%- endif %}
26 |
27 | {%- if system.autoupdates.automatic_reboot_time is defined %}
28 | Unattended-Upgrade::Automatic-Reboot-Time "{{ system.autoupdates.automatic_reboot_time }}";
29 | {%- endif %}
30 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-6-1-7.yml:
--------------------------------------------------------------------------------
1 | # CIS 6.1.7 Ensure permissions on /etc/shadow- are configured
2 | #
3 | # Description
4 | # ===========
5 | # The /etc/shadow- file is used to store backup information about user
6 | # accounts that is critical to the security of those accounts, such as the
7 | # hashed password and other security information.
8 | #
9 | # Rationale
10 | # =========
11 | # It is critical to ensure that the /etc/shadow- file is protected from
12 | # unauthorized access. Although it is protected by default, the file
13 | # permissions could be changed either inadvertently or through malicious actions.
14 | #
15 | # Audit
16 | # =====
17 | # Run the following command and verify Uid and Gid are both 0/root and
18 | # Access is 600 or more restrictive:
19 | #
20 | # # stat /etc/shadow-
21 | # Access: (0600/-rw-------) Uid: (0/root) Gid: (0/root)
22 | #
23 | # Remediation
24 | # ===========
25 | # Run the following command to set permissions on /etc/shadow- :
26 | #
27 | # # chown root:root /etc/shadow-
28 | # # chmod 600 /etc/shadow-
29 | #
30 | parameters:
31 | linux:
32 | system:
33 | file:
34 | /etc/shadow-:
35 | user: 'root'
36 | group: 'root'
37 | mode: '0600'
38 |
39 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-6-1-9.yml:
--------------------------------------------------------------------------------
1 | # CIS 6.1.9 Ensure permissions on /etc/gshadow- are configured
2 | #
3 | # Description
4 | # ===========
5 | # The /etc/gshadow- file is used to store backup information about groups
6 | # that is critical to the security of those accounts, such as the hashed
7 | # password and other security information.
8 | #
9 | # Rationale
10 | # =========
11 | # It is critical to ensure that the /etc/gshadow- file is protected from
12 | # unauthorized access. Although it is protected by default, the file
13 | # permissions could be changed either inadvertently or through malicious actions.
14 | #
15 | # Audit
16 | # =====
17 | # Run the following command and verify Uid and Gid are both 0/root and
18 | # Access is 600 or more restrictive:
19 | #
20 | # # stat /etc/gshadow-
21 | # Access: (0600/-rw-------) Uid: (0/root) Gid: (0/root)
22 | #
23 | # Remediation
24 | # ===========
25 | # Run the following command to set permissions on /etc/gshadow- :
26 | #
27 | # # chown root:root /etc/gshadow-
28 | # # chmod 600 /etc/gshadow-
29 | #
30 | parameters:
31 | linux:
32 | system:
33 | file:
34 | /etc/gshadow-:
35 | user: 'root'
36 | group: 'root'
37 | mode: '0600'
38 |
39 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-3-2-6.yml:
--------------------------------------------------------------------------------
1 | # 3.2.6 Ensure bogus ICMP responses are ignored
2 | #
3 | # Description
4 | # ===========
5 | # Setting icmp_ignore_bogus_error_responses to 1 prevents the kernel from
6 | # logging bogus responses (RFC-1122 non-compliant) from broadcast reframes,
7 | # keeping file systems from filling up with useless log messages.
8 | #
9 | # Rationale
10 | # =========
11 | # Some routers (and some attackers) will send responses that violate RFC-1122
12 | # and attempt to fill up a log file system with many useless error messages.
13 | #
14 | # Audit
15 | # =====
16 | #
17 | # Run the following commands and verify output matches:
18 | #
19 | # # sysctl net.ipv4.icmp_ignore_bogus_error_responses
20 | # net.ipv4.icmp_ignore_bogus_error_responses = 1
21 | #
22 | # Remediation
23 | # ===========
24 | #
25 | # Set the following parameter in the /etc/sysctl.conf file:
26 | #
27 | # net.ipv4.icmp_ignore_bogus_error_responses = 1
28 | #
29 | # Run the following commands to set the active kernel parameters:
30 | #
31 | # # sysctl -w net.ipv4.icmp_ignore_bogus_error_responses=1
32 | # # sysctl -w net.ipv4.route.flush=1
33 |
34 | parameters:
35 | linux:
36 | system:
37 | kernel:
38 | sysctl:
39 | net.ipv4.icmp_ignore_bogus_error_responses: 1
40 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-3-5-2.yml:
--------------------------------------------------------------------------------
1 | # 3.5.2 Ensure SCTP is disabled
2 | #
3 | # Description
4 | # ===========
5 | # The Stream Control Transmission Protocol (SCTP) is a transport layer
6 | # protocol used to support message oriented communication, with several
7 | # streams of messages in one connection. It serves a similar function as
8 | # TCP and UDP, incorporating features of both. It is message-oriented
9 | # like UDP, and ensures reliable in-sequence transport of messages with
10 | # congestion control like TCP.
11 | #
12 | # Rationale
13 | # =========
14 | # If the protocol is not being used, it is recommended that kernel module
15 | # not be loaded, disabling the service to reduce the potential attack surface.
16 | #
17 | # Audit
18 | # =====
19 | # Run the following commands and verify the output is as indicated:
20 | #
21 | # # modprobe -n -v sctp
22 | # install /bin/true
23 | # # lsmod | grep sctp
24 | #
25 | #
26 | # Remediation
27 | # ===========
28 | #
29 | # Edit or create the file /etc/modprobe.d/CIS.conf and add the following line:
30 | #
31 | # install sctp /bin/true
32 | #
33 | parameters:
34 | linux:
35 | system:
36 | kernel:
37 | module:
38 | sctp:
39 | install:
40 | command: /bin/true
41 |
42 |
--------------------------------------------------------------------------------
/linux/meta/salt.yml:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system,network with context -%}
2 | orchestrate:
3 | system:
4 | priority: 30
5 | network:
6 | priority: 40
7 | storage:
8 | priority: 50
9 | grain:
10 | sphinx:
11 | {%- set service_grains = {'sphinx': {'doc': {}}} %}
12 | {%- for service_name, service in pillar.items() %}
13 | {%- if service.get('_support', {}).get('sphinx', {}).get('enabled', False) %}
14 | {%- set grains_fragment_file = service_name+'/meta/sphinx.yml' %}
15 | {%- macro load_grains_file() %}{% include grains_fragment_file ignore missing %}{% endmacro %}
16 | {%- set grains = load_grains_file()|load_yaml %}
17 | {%- if grains %}
18 | {%- set grains_yaml = load_grains_file()|load_yaml %}
19 | {%- do service_grains.sphinx.doc.update({ service_name: grains_yaml.doc }) %}
20 | {%- endif %}
21 | {%- endif %}
22 | {%- endfor %}
23 | {{ service_grains|yaml(False)|indent(4) }}
24 | {%- set dns_records = [] %}
25 | {%- for host_name, host in network.host.items() %}
26 | {%- if host.get('grain', False) %}
27 | {%- do host.pop('grain') %}
28 | {%- do dns_records.append(host) %}
29 | {%- endif %}
30 | {%- endfor %}
31 | dns_records:
32 | dns_records: {{ dns_records|yaml }}
33 |
--------------------------------------------------------------------------------
/linux/network/openvswitch.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import network with context %}
2 |
3 | {%- if network.get('openvswitch', {}).get('enabled', False) %}
4 |
5 | openvswitch_pkgs:
6 | pkg.installed:
7 | - pkgs: {{ network.ovs_pkgs | json }}
8 |
9 | /etc/default/openvswitch-switch:
10 | file.managed:
11 | - source: salt://linux/files/openvswitch-switch.default
12 | - template: jinja
13 | - require:
14 | - pkg: openvswitch_pkgs
15 |
16 | /etc/systemd/system/openvswitch-switch.service:
17 | file.managed:
18 | - source: salt://linux/files/openvswitch-switch.systemd
19 | - template: jinja
20 | - require:
21 | - pkg: openvswitch_pkgs
22 |
23 | openvswitch_sytemctl_reload:
24 | module.run:
25 | {%- if 'module.run' in salt['config.get']('use_superseded', default=[]) %}
26 | - service.systemctl_reload: []
27 | {%- else %}
28 | - name: service.systemctl_reload
29 | {%- endif %}
30 | - onchanges:
31 | - file: /etc/systemd/system/openvswitch-switch.service
32 |
33 | openvswitch_switch_service:
34 | service.running:
35 | - name: openvswitch-switch
36 | - enable: true
37 | {%- if grains.get('noservices') %}
38 | - onlyif: /bin/false
39 | {%- endif %}
40 | - watch:
41 | - file: /etc/default/openvswitch-switch
42 |
43 | {%- endif %}
44 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-2-3-4.yml:
--------------------------------------------------------------------------------
1 | # 2.3.4 Ensure telnet client is not installed
2 | #
3 | # Description
4 | # ===========
5 | # The telnet package contains the telnet client, which allows users to start
6 | # connections to other systems via the telnet protocol.
7 | #
8 | # Rationale
9 | # =========
10 | # The telnet protocol is insecure and unencrypted. The use of an unencrypted
11 | # transmission medium could allow an unauthorized user to steal credentials.
12 | # The ssh package provides an encrypted session and stronger security and is
13 | # included in most Linux distributions.
14 | #
15 | # Audit
16 | # =====
17 | # Run the following command and verify telnet is not installed:
18 | #
19 | # # dpkg -s telnet
20 | #
21 | # Remediation
22 | # ===========
23 | # Run the following command to uninstall telnet :
24 | #
25 | # # apt-get remove telnet
26 | #
27 | # Impact
28 | # ======
29 | # Many insecure service clients are used as troubleshooting tools and in
30 | # testing environments. Uninstalling them can inhibit capability to test and
31 | # troubleshoot. If they are required it is advisable to remove the clients
32 | # after use to prevent accidental or intentional misuse.
33 | #
34 | parameters:
35 | linux:
36 | system:
37 | package:
38 | telnet:
39 | version: removed
40 |
41 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-6-1-3.yml:
--------------------------------------------------------------------------------
1 | # CIS 6.1.3 Ensure permissions on /etc/shadow are configured
2 | #
3 | # Description
4 | # ===========
5 | # The /etc/shadow file is used to store the information about user accounts
6 | # that is critical to the security of those accounts, such as the hashed
7 | # password and other security information.
8 | #
9 | # Rationale
10 | # =========
11 | # If attackers can gain read access to the /etc/shadow file, they can easily
12 | # run a password cracking program against the hashed password to break it.
13 | # Other security information that is stored in the /etc/shadow file (such
14 | # as expiration) could also be useful to subvert the user accounts.
15 | #
16 | # Audit
17 | # =====
18 | # Run the following command and verify Uid is 0/root , Gid is /shadow ,
19 | # and Access is 640 or more restrictive:
20 | #
21 | # # stat /etc/shadow
22 | # Access: (0640/-rw-r-----) Uid: (0/root) Gid: (42/shadow)
23 | #
24 | # Remediation
25 | # ===========
26 | # Run the one following commands to set permissions on /etc/shadow :
27 | #
28 | # # chown root:shadow /etc/shadow
29 | # # chmod o-rwx,g-wx /etc/shadow
30 | #
31 | parameters:
32 | linux:
33 | system:
34 | file:
35 | /etc/shadow:
36 | user: 'root'
37 | group: 'shadow'
38 | mode: '0640'
39 |
40 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-6-1-5.yml:
--------------------------------------------------------------------------------
1 | # CIS 6.1.5 Ensure permissions on /etc/gshadow are configured
2 | #
3 | # Description
4 | # ===========
5 | # The /etc/gshadow file is used to store the information about groups that
6 | # is critical to the security of those accounts, such as the hashed password
7 | # and other security information.
8 | #
9 | # Rationale
10 | # =========
11 | # If attackers can gain read access to the /etc/gshadow file, they can easily
12 | # run a password cracking program against the hashed password to break it.
13 | # Other security information that is stored in the /etc/gshadow file (such as
14 | # group administrators) could also be useful to subvert the group.
15 | #
16 | # Audit
17 | # =====
18 | # Run the following command and verify verify Uid is 0/root ,
19 | # Gid is /shadow , and Access is 640 or more restrictive:
20 | #
21 | # # stat /etc/gshadow
22 | # Access: (0640/-rw-r-----) Uid: (0/root) Gid: (42/shadow)
23 | #
24 | # Remediation
25 | # ===========
26 | # Run the following commands to set permissions on /etc/gshadow :
27 | #
28 | # # chown root:shadow /etc/gshadow
29 | # # chmod o-rwx,g-rw /etc/gshadow
30 | #
31 | parameters:
32 | linux:
33 | system:
34 | file:
35 | /etc/gshadow:
36 | user: 'root'
37 | group: 'shadow'
38 | mode: '0640'
39 |
40 |
--------------------------------------------------------------------------------
/linux/network/systemd.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import network with context %}
2 | {%- if network.enabled and grains.get('init', None) == 'systemd' %}
3 |
4 | {%- if network.systemd is mapping %}
5 | {%- for config_type, configs in network.systemd.items() %}
6 |
7 | {%- if config_type == 'link' %}
8 | /etc/udev/rules.d/80-net-setup-link.rules:
9 | file.managed:
10 | - makedirs: True
11 | - content: ""
12 | {%- endif %}
13 |
14 | {%- for config_name, config in configs.items() %}
15 | linux_network_systemd_networkd_{{ config_type }}_config_{{ config_name }}:
16 | file.managed:
17 | - name: /etc/systemd/network/{{ config_name }}.{{ config_type }}
18 | - source: salt://linux/files/systemd-network.conf
19 | - template: jinja
20 | - makedirs: True
21 | - defaults:
22 | settings: {{ config }}
23 | - watch_in:
24 | - module: linux_network_systemd_reload
25 | - module: linux_network_systemd_networkd
26 | {%- endfor %}
27 | {%- endfor %}
28 |
29 | linux_network_systemd_reload:
30 | module.wait:
31 | - name: service.systemctl_reload
32 |
33 | linux_network_systemd_networkd:
34 | service.running:
35 | - name: systemd-networkd
36 | - init_delay: 10
37 | - enable: True
38 | - reload: True
39 | - watch:
40 | - module: linux_network_systemd_reload
41 |
42 | {%- endif %}
43 | {%- endif %}
44 |
--------------------------------------------------------------------------------
/linux/system/group.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- macro set_p(paramname, dictvar) -%}
5 | {%- if paramname in dictvar -%}
6 | - {{ paramname }}: {{ dictvar[paramname] }}
7 | {%- endif -%}
8 | {%- endmacro -%}
9 |
10 | {%- for group_name, group in system.group.items() %}
11 |
12 | {%- if group.enabled %}
13 |
14 | system_group_{{ group_name }}:
15 | group.present:
16 | - name: {{ group.get('name', group_name) }}
17 | {%- if group.system is defined and group.system %}
18 | - system: True
19 | {%- endif %}
20 | {%- if group.gid is defined and group.gid %}
21 | - gid: {{ group.gid }}
22 | {%- endif %}
23 | {%- if group.members is defined %}
24 | - members: {{ group.members|json }}
25 | {%- else %}
26 | {%- set requires = [] %}
27 | {%- for user in group.get('addusers', []) %}
28 | {%- if user in system.get('user', {}).keys() %}
29 | {%- do requires.append({'user': 'system_user_'+user}) %}
30 | {%- endif %}
31 | {%- endfor %}
32 | - require: {{ requires|yaml }}
33 | {{ set_p('addusers', group)|indent(2, True) }}
34 | {{ set_p('delusers', group)|indent(2, True) }}
35 | {% endif %}
36 | {%- else %}
37 |
38 | system_group_{{ group_name }}:
39 | group.absent:
40 | - name: {{ group.name }}
41 |
42 | {%- endif %}
43 |
44 | {%- endfor %}
45 |
46 | {%- endif %}
47 |
48 |
--------------------------------------------------------------------------------
/linux/system/motd.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled and system.motd|length > 0 %}
3 |
4 | /etc/update-motd.d:
5 | file.directory:
6 | - clean: true
7 |
8 | {%- if system.motd is string %}
9 |
10 | {#- Set static motd only #}
11 | /etc/motd:
12 | file.managed:
13 | - contents_pillar: linux:system:motd
14 |
15 | {%- else %}
16 |
17 | {%- if grains.oscodename == "jessie" %}
18 | motd_fix_pam_sshd:
19 | file.replace:
20 | - name: /etc/pam.d/sshd
21 | - pattern: "/run/motd.dynamic"
22 | - repl: "/run/motd"
23 | {%- endif %}
24 |
25 | /etc/motd:
26 | file.absent
27 |
28 | exist_/etc/update-motd.d:
29 | file.directory:
30 | - name: /etc/update-motd.d
31 |
32 | {%- for motd in system.motd %}
33 | {%- set motd_index = loop.index %}
34 |
35 | {%- for name, value in motd.items() %}
36 | motd_{{ motd_index }}_{{ name }}:
37 | file.managed:
38 | - name: /etc/update-motd.d/5{{ motd_index }}-{{ name }}
39 | - source: salt://linux/files/motd.sh
40 | - template: jinja
41 | - mode: 755
42 | - require_in:
43 | - file: /etc/update-motd.d
44 | - require:
45 | - file: exist_/etc/update-motd.d
46 | - defaults:
47 | index: {{ motd_index }}
48 | motd_name: {{ name }}
49 | {%- endfor %}
50 |
51 | {%- endfor %}
52 |
53 | {%- endif %}
54 |
55 | {%- endif %}
56 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-3-2-4.yml:
--------------------------------------------------------------------------------
1 | # 3.2.4 Ensure suspicious packets are logged
2 | #
3 | # Description
4 | # ===========
5 | # When enabled, this feature logs packets with un-routable source
6 | # addresses to the kernel log.
7 | #
8 | # Rationale
9 | # =========
10 | # Enabling this feature and logging these packets allows an administrator
11 | # to investigate the possibility that an attacker is sending spoofed
12 | # packets to their system.
13 | #
14 | # Audit
15 | # =====
16 | #
17 | # Run the following commands and verify output matches:
18 | #
19 | # # sysctl net.ipv4.conf.all.log_martians
20 | # net.ipv4.conf.all.log_martians = 1
21 | # # sysctl net.ipv4.conf.default.log_martians
22 | # net.ipv4.conf.default.log_martians = 1
23 | #
24 | # Remediation
25 | # ===========
26 | #
27 | # Set the following parameters in the /etc/sysctl.conf file:
28 | #
29 | # net.ipv4.conf.all.log_martians = 1
30 | # net.ipv4.conf.default.log_martians = 1
31 | #
32 | # Run the following commands to set the active kernel parameters:
33 | #
34 | # # sysctl -w net.ipv4.conf.all.log_martians=1
35 | # # sysctl -w net.ipv4.conf.default.log_martians=1
36 | # # sysctl -w net.ipv4.route.flush=1
37 |
38 | parameters:
39 | linux:
40 | system:
41 | kernel:
42 | sysctl:
43 | net.ipv4.conf.all.log_martians: 1
44 | net.ipv4.conf.default.log_martians: 1
45 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-1-1-1-6.yml:
--------------------------------------------------------------------------------
1 | # 1.1.1.6 Ensure mounting of squashfs filesystems is disabled
2 | #
3 | # Description
4 | # ===========
5 | # The squashfs filesystem type is a compressed read-only Linux filesystem
6 | # embedded in small footprint systems (similar to cramfs). A squashfs image
7 | # can be used without having to first decompress the image.
8 | #
9 | # Rationale
10 | # =========
11 | # Removing support for unneeded filesystem types reduces the local attack
12 | # surface of the server. If this filesystem type is not needed, disable it.
13 | #
14 | # Audit
15 | # =====
16 | # Run the following commands and verify the output is as indicated:
17 | #
18 | # # modprobe -n -v squashfs
19 | # install /bin/true
20 | # # lsmod | grep squashfs
21 | #
22 | #
23 | # Remediation
24 | # ===========
25 | # Edit or create the file /etc/modprobe.d/CIS.conf and add the following line:
26 | #
27 | # install squashfs /bin/true
28 | #
29 | # NOTE
30 | # ====
31 | # In Ubuntu 16.04 squashfs is built into kernel, and 'install' command
32 | # from modprobe.d dir has no effect. However, this is still checked by
33 | # CIS-CAT in Ubuntu 16.04 benchmark v.1.0.0. This was removed in v.1.1.0.
34 | #
35 | parameters:
36 | linux:
37 | system:
38 | kernel:
39 | module:
40 | squashfs:
41 | install:
42 | command: /bin/true
43 |
44 |
--------------------------------------------------------------------------------
/linux/storage/loopback.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import storage with context %}
2 |
3 | {%- if storage.get('enabled', False) %}
4 |
5 | {%- for device, loopback in storage.loopback|dictsort %}
6 |
7 | {%- if loopback.get('enabled', True) %}
8 |
9 | {{ loopback.file }}_directory:
10 | file.directory:
11 | - name: {{ salt['file.dirname'](loopback.file) }}
12 | - makedirs: true
13 | - require_in:
14 | - file: {{ loopback.file }}
15 |
16 | {{ loopback.file }}:
17 | cmd.run:
18 | - name: "truncate --size {{ loopback.size|default('1G') }} {{ loopback.file }}"
19 | - creates: {{ loopback.file }}
20 |
21 | loopback_{{ device }}_init_script:
22 | file.managed:
23 | {%- if grains.get('init', None) == 'upstart' %}
24 | - name: /etc/init/setup-loopback-{{ device }}.conf
25 | - source: salt://linux/files/setup-loopback-device.upstart
26 | {%- else %}
27 | - name: /etc/systemd/system/setup-loopback-{{ device }}.service
28 | - source: salt://linux/files/setup-loopback-device.systemd
29 | {%- endif %}
30 | - template: jinja
31 | - defaults:
32 | file: {{ loopback.file }}
33 | device_name: "/dev/loop{{ loop.index0 }}"
34 |
35 | setup-loopback-{{ device }}:
36 | service.running:
37 | - enable: true
38 | - require:
39 | - cmd: {{ loopback.file }}
40 | - file: loopback_{{ device }}_init_script
41 | {%- endif %}
42 |
43 | {%- endfor %}
44 |
45 | {%- endif %}
46 |
--------------------------------------------------------------------------------
/tests/pillar/system_extra.sls:
--------------------------------------------------------------------------------
1 |
2 | linux:
3 | network:
4 | enabled: true
5 | hostname: linux
6 | fqdn: linux.ci.local
7 | system:
8 | auth:
9 | enabled: true
10 | mkhomedir:
11 | enabled: true
12 | umask: 0027
13 | ldap:
14 | enabled: true
15 | binddn: cn=bind,ou=service_users,dc=example,dc=com
16 | bindpw: secret
17 | uri: ldap://127.0.0.1
18 | base: ou=users,dc=example,dc=com
19 | ldap_version: 3
20 | pagesize: 65536
21 | referrals: off
22 | filter:
23 | passwd: (&(&(objectClass=person)(uidNumber=*))(unixHomeDirectory=*))
24 | shadow: (&(&(objectClass=person)(uidNumber=*))(unixHomeDirectory=*))
25 | group: (&(objectClass=group)(gidNumber=*))
26 | enabled: true
27 | cluster: default
28 | name: linux
29 | timezone: Europe/Prague
30 | console:
31 | tty0:
32 | autologin: root
33 | ttyS0:
34 | autologin: root
35 | rate: 115200
36 | term: xterm
37 | kernel:
38 | sriov: True
39 | isolcpu: 1,2,3,4
40 | hugepages:
41 | large:
42 | default: true
43 | size: 1G
44 | count: 210
45 | mount_point: /mnt/hugepages_1GB
46 | policyrcd:
47 | - package: cassandra
48 | action: exit 101
49 | - package: '*'
50 | action: switch
51 |
--------------------------------------------------------------------------------
/linux/system/cpu.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.cpu.governor is defined %}
3 |
4 | include:
5 | - linux.system.sysfs
6 |
7 | ondemand_service_disable:
8 | service.dead:
9 | - name: ondemand
10 | - enable: false
11 |
12 | {%- if grains.get('virtual', None) in ['physical', None] %}
13 | {#- Governor cannot be set in VMs, etc. #}
14 |
15 | /etc/sysfs.d/governor.conf:
16 | file.managed:
17 | - source: salt://linux/files/governor.conf.jinja
18 | - template: jinja
19 | - user: root
20 | - group: root
21 | - mode: 0644
22 | - defaults:
23 | governor: {{ system.cpu.governor }}
24 | - require:
25 | - file: /etc/sysfs.d
26 |
27 | {% for cpu_core in range(salt['grains.get']('num_cpus', 1)) %}
28 |
29 | {% set core_key = 'devices/system/cpu/cpu' + cpu_core|string + '/cpufreq/scaling_governor' %}
30 | {% if salt['file.file_exists']('/sys/'+ core_key) %}
31 | governor_write_sysfs_cpu_core_{{ cpu_core }}:
32 | module.run:
33 | {%- if 'module.run' in salt['config.get']('use_superseded', default=[]) %}
34 | - sysfs.write:
35 | - key: {{ core_key }}
36 | - value: {{ system.cpu.governor }}
37 | {%- else %}
38 | - name: sysfs.write
39 | - key: {{ core_key }}
40 | - value: {{ system.cpu.governor }}
41 | {%- endif %}
42 | {% endif %}
43 |
44 | {%- endfor %}
45 |
46 | {%- endif %}
47 |
48 | {%- endif %}
49 |
--------------------------------------------------------------------------------
/linux/files/hosts:
--------------------------------------------------------------------------------
1 | {#-
2 | vim: syntax=jinja
3 | -#}
4 | {%- from "linux/map.jinja" import network with context -%}
5 | # hosts(1) file managed by salt-minion(1)
6 | # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
7 |
8 | {%- set hosts = {
9 | '127.0.0.1': [
10 | 'localhost'
11 | ],
12 | '127.0.1.1': [
13 | network.fqdn|default(grains.fqdn),
14 | network.hostname|default(grains.nodename)
15 | ],
16 | '::1': [
17 | 'ip6-localhost',
18 | 'ip6-loopback'
19 | ],
20 | 'fe00::0': [
21 | 'ip6-localnet',
22 | 'ip6-mcastprefix'
23 | ],
24 | 'ff02::1': [
25 | 'ip6-allnodes'
26 | ],
27 | 'ff02::2': [
28 | 'ip6-allrouters'
29 | ],
30 | 'ff02::3': [
31 | 'ip6-allhosts'
32 | ],
33 | } -%}
34 | {%- for name, host in host_dict.items() -%}
35 | {%- for hname in host.names -%}
36 | {%- if hname in hosts.get('127.0.1.1', []) -%}
37 | {%- do hosts.pop('127.0.1.1') -%}
38 | {%- endif %}
39 | {%- endfor %}
40 | {%- do hosts.update({host.address: host.names}) -%}
41 | {%- endfor %}
42 | {% for address, entries in hosts|dictsort %}
43 | {%- if 'linux_hosts.fqdn_sort_filter' in salt.keys() %}
44 | {%- set sorted_entries = salt['linux_hosts.fqdn_sort_filter'](entries) -%}
45 | {%- else %}
46 | {%- set sorted_entries = entries -%}
47 | {%- endif %}
48 | {{ address }} {{ sorted_entries|join(' ') }}
49 | {%- endfor %}
50 |
--------------------------------------------------------------------------------
/linux/system/netconsole.sls:
--------------------------------------------------------------------------------
1 | {% from "linux/map.jinja" import system with context %}
2 | {% if system.enabled and system.netconsole is mapping and system.netconsole.enabled %}
3 |
4 | /etc/dhcp/dhclient-exit-hooks.d/netconsole:
5 | file.managed:
6 | - source: salt://linux/files/netconsole
7 | - makedirs: True
8 |
9 | /etc/network/if-up.d/netconsole:
10 | file.managed:
11 | - source: salt://linux/files/netconsole
12 | - mode: 755
13 | - makedirs: True
14 |
15 | /etc/network/if-down.d/netconsole:
16 | file.managed:
17 | - source: salt://linux/files/netconsole
18 | - mode: 755
19 | - makedirs: True
20 |
21 | /etc/default/netconsole.conf:
22 | file.managed:
23 | - source: salt://linux/files/netconsole.conf
24 | - template: jinja
25 |
26 | {% if system.netconsole is mapping and system.netconsole.target is mapping %}
27 | {% for target, data in system.netconsole.target.items() %}
28 | {% if data is mapping and data.interface is defined %}
29 | /etc/network/if-up.d/netconsole {{ target }} {{ data.interface }}:
30 | cmd.run:
31 | - name: /etc/network/if-up.d/netconsole
32 | - env:
33 | - IFACE: {{ data.interface }}
34 | - METHOD: static
35 | - ADDRFAM: inet
36 | - MODE: start
37 | - onchanges:
38 | - file: /etc/default/netconsole.conf
39 | - require:
40 | - file: /etc/network/if-up.d/netconsole
41 | {% endif %}
42 | {% endfor %}
43 | {% endif %}
44 |
45 | {% endif %}
46 |
--------------------------------------------------------------------------------
/tests/pillar/network_openvswitch.sls:
--------------------------------------------------------------------------------
1 | linux:
2 | system:
3 | enabled: true
4 | domain: local
5 | name: linux
6 | network:
7 | enabled: true
8 | hostname: test01
9 | fqdn: test01.local
10 | network_manager: false
11 | bridge: openvswitch
12 | interface:
13 | br-prv:
14 | enabled: true
15 | type: ovs_bridge
16 | mtu: 65000
17 | br-ens0:
18 | enabled: true
19 | type: ovs_bridge
20 | proto: manual
21 | mtu: 9000
22 | use_interfaces:
23 | - ens0
24 | patch-br-ens0-br-prv:
25 | enabled: true
26 | name: ens0-prv
27 | ovs_type: ovs_port
28 | type: ovs_port
29 | bridge: br-ens0
30 | port_type: patch
31 | peer: prv-ens0
32 | tag: 107
33 | mtu: 65000
34 | patch-br-prv-br-ens0:
35 | enabled: true
36 | name: prv-ens0
37 | bridge: br-prv
38 | ovs_type: ovs_port
39 | type: ovs_port
40 | port_type: patch
41 | peer: ens0-prv
42 | tag: 107
43 | mtu: 65000
44 | ens0:
45 | enabled: true
46 | proto: manual
47 | ovs_port_type: OVSPort
48 | type: ovs_port
49 | ovs_bridge: br-ens0
50 | bridge: br-ens0
51 | bond1:
52 | enabled: true
53 | type: ovs_bond
54 | mode: balance-slb
55 | bridge: br-ex
56 | slaves: eno3 eno4
57 |
58 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-3-1-2.yml:
--------------------------------------------------------------------------------
1 | # 3.1.2 Ensure packet redirect sending is disabled
2 | #
3 | # Description
4 | # ===========
5 | # ICMP Redirects are used to send routing information to other hosts. As a host
6 | # itself does not act as a router (in a host only configuration), there is
7 | # no need to send redirects.
8 | #
9 | # Rationale
10 | # =========
11 | # An attacker could use a compromised host to send invalid ICMP redirects to
12 | # other router devices in an attempt to corrupt routing and have users access
13 | # a system set up by the attacker as opposed to a valid system.
14 | #
15 | # Audit
16 | # =====
17 | #
18 | # Run the following commands and verify output matches:
19 | #
20 | # # sysctl net.ipv4.conf.all.send_redirects
21 | # net.ipv4.conf.all.send_redirects = 0
22 | # # sysctl net.ipv4.conf.default.send_redirects
23 | # net.ipv4.conf.default.send_redirects = 0
24 | #
25 | # Remediation
26 | # ===========
27 | #
28 | # Set the following parameters in the /etc/sysctl.conf file:
29 | #
30 | # net.ipv4.conf.all.send_redirects = 0
31 | # net.ipv4.conf.default.send_redirects = 0
32 | #
33 | # Run the following commands to set the active kernel parameters:
34 | #
35 | # # sysctl -w net.ipv4.conf.all.send_redirects=0
36 | # # sysctl -w net.ipv4.conf.default.send_red
37 |
38 | parameters:
39 | linux:
40 | system:
41 | kernel:
42 | sysctl:
43 | net.ipv4.conf.all.send_redirects: 0
44 | net.ipv4.conf.default.send_redirects: 0
45 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-2-3-1.yml:
--------------------------------------------------------------------------------
1 | # 2.3.1 Ensure NIS Client is not installed
2 | #
3 | # Description
4 | # ===========
5 | # The Network Information Service (NIS), formerly known as Yellow Pages,
6 | # is a client-server directory service protocol used to distribute system
7 | # configuration files. The NIS client ( ypbind ) was used to bind a machine
8 | # to an NIS server and receive the distributed configuration files.
9 | #
10 | # Rationale
11 | # =========
12 | # The NIS service is inherently an insecure system that has been vulnerable
13 | # to DOS attacks, buffer overflows and has poor authentication for querying
14 | # NIS maps. NIS generally has been replaced by such protocols as Lightweight
15 | # Directory Access Protocol (LDAP). It is recommended that the service be
16 | # removed.
17 | #
18 | # Audit
19 | # =====
20 | # Run the following command and verify nis is not installed:
21 | #
22 | # dpkg -s nis
23 | #
24 | # Remediation
25 | # ===========
26 | # Run the following command to uninstall nis:
27 | #
28 | # apt-get remove nis
29 | #
30 | # Impact
31 | # ======
32 | # Many insecure service clients are used as troubleshooting tools and in
33 | # testing environments. Uninstalling them can inhibit capability to test
34 | # and troubleshoot. If they are required it is advisable to remove the clients
35 | # after use to prevent accidental or intentional misuse.
36 | #
37 | parameters:
38 | linux:
39 | system:
40 | package:
41 | nis:
42 | version: removed
43 |
44 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-3-2-3.yml:
--------------------------------------------------------------------------------
1 | # 3.2.3 Ensure secure ICMP redirects are not accepted
2 | #
3 | # Description
4 | # ===========
5 | # Secure ICMP redirects are the same as ICMP redirects, except they come from
6 | # gateways listed on the default gateway list. It is assumed that these
7 | # gateways are known to your system, and that they are likely to be secure.
8 | #
9 | # Rationale
10 | # =========
11 | # It is still possible for even known gateways to be compromised. Setting
12 | # net.ipv4.conf.all.secure_redirects to 0 protects the system from routing
13 | # table updates by possibly compromised known gateways.
14 | #
15 | # Audit
16 | # =====
17 | #
18 | # Run the following commands and verify output matches:
19 | #
20 | # # sysctl net.ipv4.conf.all.secure_redirects
21 | # net.ipv4.conf.all.secure_redirects = 0
22 | # # sysctl net.ipv4.conf.default.secure_redirects
23 | # net.ipv4.conf.default.secure_redirects = 0
24 | #
25 | # Remediation
26 | # ===========
27 | #
28 | # Set the following parameters in the /etc/sysctl.conf file:
29 | #
30 | # net.ipv4.conf.all.secure_redirects = 0
31 | # net.ipv4.conf.default.secure_redirects = 0
32 | #
33 | # Run the following commands to set the active kernel parameters:
34 | #
35 | # # sysctl -w net.ipv4.conf.all.secure_redirects=0
36 | # # sysctl -w net.ipv4.conf.default.secure_redirects=0
37 | # # sysctl -w net.ipv4.route.flush=1
38 |
39 | parameters:
40 | linux:
41 | system:
42 | kernel:
43 | sysctl:
44 | net.ipv4.conf.all.secure_redirects: 0
45 | net.ipv4.conf.default.secure_redirects: 0
46 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-1-1-1-8.yml:
--------------------------------------------------------------------------------
1 | # 1.1.1.8 Ensure mounting of FAT filesystems is disabled
2 | #
3 | # Description
4 | # ===========
5 | # The FAT filesystem format is primarily used on older windows systems and
6 | # portable USB drives or flash modules. It comes in three types FAT12, FAT16,
7 | # and FAT32 all of which are supported by the vfat kernel module.
8 | #
9 | # Rationale
10 | # =========
11 | # Removing support for unneeded filesystem types reduces the local attack
12 | # surface of the server. If this filesystem type is not needed, disable it.
13 | #
14 | # Audit
15 | # =====
16 | # Run the following commands and verify the output is as indicated:
17 | #
18 | # # modprobe -n -v vfat
19 | # install /bin/true
20 | # # lsmod | grep vfat
21 | #
22 | #
23 | # Remediation
24 | # ===========
25 | #
26 | # Edit or create the file /etc/modprobe.d/CIS.conf and add the following line:
27 | #
28 | # install vfat /bin/true
29 | #
30 | # Impact
31 | # ======
32 | # FAT filesystems are often used on portable USB sticks and other flash
33 | # media are commonly used to transfer files between workstations, removing
34 | # VFAT support may prevent the ability to transfer files in this way.
35 | #
36 | # NOTE
37 | # ====
38 | # In Ubuntu 16.04 vfat is built into kernel, and 'install' command
39 | # from modprobe.d dir has no effect. However, this is still checked by
40 | # CIS-CAT in Ubuntu 16.04 benchmark v.1.0.0. This was removed in v.1.1.0.
41 | #
42 | parameters:
43 | linux:
44 | system:
45 | kernel:
46 | module:
47 | vfat:
48 | install:
49 | command: /bin/true
50 |
51 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-3-2-5.yml:
--------------------------------------------------------------------------------
1 | # 3.2.5 Ensure broadcast ICMP requests are ignored
2 | #
3 | # Description
4 | # ===========
5 | # Setting net.ipv4.icmp_echo_ignore_broadcasts to 1 will cause the
6 | # system to ignore all ICMP echo and timestamp requests to broadcast
7 | # and multicast addresses.
8 | #
9 | # Rationale
10 | # =========
11 | # Accepting ICMP echo and timestamp requests with broadcast or multicast
12 | # destinations for your network could be used to trick your host into starting
13 | # (or participating) in a Smurf attack. A Smurf attack relies on an attacker
14 | # sending large amounts of ICMP broadcast messages with a spoofed source
15 | # address. All hosts receiving this message and responding would send
16 | # echo-reply messages back to the spoofed address, which is probably not
17 | # routable. If many hosts respond to the packets, the amount of traffic on
18 | # the network could be significantly multiplied.
19 | #
20 | # Audit
21 | # =====
22 | #
23 | # Run the following commands and verify output matches:
24 | #
25 | # # sysctl net.ipv4.icmp_echo_ignore_broadcasts
26 | # net.ipv4.icmp_echo_ignore_broadcasts = 1
27 | #
28 | # Remediation
29 | # ===========
30 | #
31 | # Set the following parameter in the /etc/sysctl.conf file:
32 | #
33 | # net.ipv4.icmp_echo_ignore_broadcasts = 1
34 | #
35 | # Run the following commands to set the active kernel parameters:
36 | #
37 | # # sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1
38 | # # sysctl -w net.ipv4.route.flush=1
39 |
40 | parameters:
41 | linux:
42 | system:
43 | kernel:
44 | sysctl:
45 | net.ipv4.icmp_echo_ignore_broadcasts: 1
46 |
--------------------------------------------------------------------------------
/linux/files/login.defs.jinja:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import login_defs with context -%}
2 | # This file is managed by Salt, do not edit
3 | {%- set allowed_options = [
4 | 'CHFN_RESTRICT',
5 | 'CONSOLE_GROUPS',
6 | 'CREATE_HOME',
7 | 'DEFAULT_HOME',
8 | 'ENCRYPT_METHOD',
9 | 'ENV_HZ',
10 | 'ENV_PATH',
11 | 'ENV_SUPATH',
12 | 'ERASECHAR',
13 | 'FAIL_DELAY',
14 | 'FAKE_SHELL',
15 | 'GID_MAX',
16 | 'GID_MIN',
17 | 'HUSHLOGIN_FILE',
18 | 'KILLCHAR',
19 | 'LOG_OK_LOGINS',
20 | 'LOG_UNKFAIL_ENAB',
21 | 'LOGIN_RETRIES',
22 | 'LOGIN_TIMEOUT',
23 | 'MAIL_DIR',
24 | 'MAIL_FILE',
25 | 'MAX_MEMBERS_PER_GROUP',
26 | 'MD5_CRYPT_ENAB',
27 | 'PASS_MAX_DAYS',
28 | 'PASS_MIN_DAYS',
29 | 'PASS_WARN_AGE',
30 | 'SHA_CRYPT_MIN_ROUNDS',
31 | 'SHA_CRYPT_MAX_ROUNDS',
32 | 'SULOG_FILE',
33 | 'SU_NAME',
34 | 'SUB_GID_MIN',
35 | 'SUB_GID_MAX',
36 | 'SUB_GID_COUNT',
37 | 'SUB_UID_MIN',
38 | 'SUB_UID_MAX',
39 | 'SUB_UID_COUNT',
40 | 'SYS_GID_MAX',
41 | 'SYS_GID_MIN',
42 | 'SYS_UID_MAX',
43 | 'SYS_UID_MIN',
44 | 'SYSLOG_SG_ENAB',
45 | 'SYSLOG_SU_ENAB',
46 | 'TTYGROUP',
47 | 'TTYPERM',
48 | 'TTYTYPE_FILE',
49 | 'UID_MAX',
50 | 'UID_MIN',
51 | 'UMASK',
52 | 'USERDEL_CMD',
53 | 'USERGROUPS_ENAB'
54 | ] %}
55 | {%- for opt_name in allowed_options %}
56 | {%- if opt_name in login_defs %}
57 | {%- set opt_params = login_defs.get(opt_name) %}
58 | {%- if opt_params.get('enabled', true) %}
59 | {{ opt_name.ljust(20) }} {{ opt_params.value }}
60 | {%- endif %}
61 | {%- endif %}
62 | {%- endfor %}
63 |
--------------------------------------------------------------------------------
/linux/system/hugepages.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 |
3 | include:
4 | - linux.system.grub
5 |
6 | {%- if "pse" in grains.cpu_flags or "pdpe1gb" in grains.cpu_flags or "aarch64" in grains.cpuarch %}
7 |
8 | /etc/default/grub.d/90-hugepages.cfg:
9 | file.managed:
10 | - source: salt://linux/files/grub_hugepages
11 | - template: jinja
12 | - require:
13 | - file: grub_d_directory
14 | {%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
15 | - watch_in:
16 | - cmd: grub_update
17 |
18 | {%- endif %}
19 |
20 | {%- for hugepages_type, hugepages in system.kernel.hugepages.items() %}
21 |
22 | hugepages_mount_{{ hugepages_type }}:
23 | mount.mounted:
24 | - name: {{ hugepages.mount_point }}
25 | - device: Hugetlbfs-kvm-{{ hugepages.size|lower }}
26 | - fstype: hugetlbfs
27 | - mkmnt: true
28 | - opts: mode=775,pagesize={{ hugepages.size }}
29 | - mount: {{ hugepages.mount|default('true') }}
30 |
31 | # Make hugepages available right away with a temporary systctl write
32 | # This will be handled via krn args after reboot, so don't use `sysctl.present`
33 | {%- if hugepages.get('default', False) %}
34 | hugepages_sysctl_vm_nr_hugepages:
35 | cmd.run:
36 | - name: "sysctl vm.nr_hugepages={{ hugepages.count }}"
37 | - unless: "sysctl vm.nr_hugepages | grep -qE '{{ hugepages.count }}'"
38 | {%- endif %}
39 |
40 | {%- endfor %}
41 |
42 | {%- endif %}
43 |
44 | # systemd always creates default mount point at /dev/hugepages
45 | # we have to disable it, as we configure our own mount point for DPDK.
46 | mask_dev_hugepages:
47 | cmd.run:
48 | - name: "systemctl mask dev-hugepages.mount"
49 |
--------------------------------------------------------------------------------
/linux/system/shell.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 | {%- if system.shell is defined %}
4 |
5 | {%- if system.shell.umask is defined %}
6 | etc_bash_bashrc_umask:
7 | file.blockreplace:
8 | - name: /etc/bash.bashrc
9 | - marker_start: "# BEGIN CIS 5.4.4 default user umask"
10 | - marker_end: "# END CIS 5.4.4 default user umask"
11 | - content: "umask {{ system.shell.umask }}"
12 | - append_if_not_found: True
13 | - onlyif: test -f /etc/bash.bashrc
14 |
15 | etc_profile_umask:
16 | file.blockreplace:
17 | - name: /etc/profile
18 | - marker_start: "# BEGIN CIS 5.4.4 default user umask"
19 | - marker_end: "# END CIS 5.4.4 default user umask"
20 | - content: "umask {{ system.shell.umask }}"
21 | - append_if_not_found: True
22 | - onlyif: test -f /etc/profile
23 | {%- endif %}
24 |
25 | {%- if system.shell.timeout is defined %}
26 | etc_bash_bashrc_timeout:
27 | file.blockreplace:
28 | - name: /etc/bash.bashrc
29 | - marker_start: "# BEGIN CIS 5.4.5 default user shell timeout"
30 | - marker_end: "# END CIS 5.4.5 default user shell timeout"
31 | - content: "TMOUT={{ system.shell.timeout }}"
32 | - append_if_not_found: True
33 | - onlyif: test -f /etc/bash.bashrc
34 |
35 | etc_profile_timeout:
36 | file.blockreplace:
37 | - name: /etc/profile
38 | - marker_start: "# BEGIN CIS 5.4.5 default user shell timeout"
39 | - marker_end: "# END CIS 5.4.5 default user shell timeout"
40 | - content: "TMOUT={{ system.shell.timeout }}"
41 | - append_if_not_found: True
42 | - onlyif: test -f /etc/profile
43 | {%- endif %}
44 | {%- endif %}
45 | {%- endif %}
46 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-5-4-1-3.yml:
--------------------------------------------------------------------------------
1 | # CIS 5.4.1.3 Ensure password expiration warning days is 7 or more (Scored)
2 | #
3 | # Description
4 | # ===========
5 | # The PASS_WARN_AGE parameter in /etc/login.defs allows an administrator to
6 | # notify users that their password will expire in a defined number of days.
7 | # It is recommended that the PASS_WARN_AGE parameter be set to 7 or more days.
8 | #
9 | # Rationale
10 | # =========
11 | # Providing an advance warning that a password will be expiring gives users
12 | # time to think of a secure password. Users caught unaware may choose a simple
13 | # password or write it down where it may be discovered.
14 | #
15 | # Audit
16 | # =====
17 | # Run the following command and verify PASS_WARN_AGE is 7 or more:
18 | #
19 | # # grep PASS_WARN_AGE /etc/login.defs
20 | # PASS_WARN_AGE 7
21 | #
22 | # Verify all users with a password have their number of days of warning before
23 | # password expires set to 7 or more:
24 | #
25 | # # egrep ^[^:]+:[^\!*] /etc/shadow | cut -d: -f1
26 | #
27 | # # chage --list
28 | # Number of days of warning before password expires: 7
29 | #
30 | # Remediation
31 | # ===========
32 | #
33 | # Set the PASS_WARN_AGE parameter to 7 in /etc/login.defs :
34 | #
35 | # PASS_WARN_AGE 7
36 | #
37 | # Modify user parameters for all users with a password set to match:
38 | #
39 | # # chage --warndays 7
40 | #
41 | # Notes
42 | # =====
43 | # You can also check this setting in /etc/shadow directly. The 6th field
44 | # should be 7 or more for all users with a password.
45 | #
46 | parameters:
47 | linux:
48 | system:
49 | login_defs:
50 | PASS_WARN_AGE:
51 | value: 7
52 |
53 |
--------------------------------------------------------------------------------
/linux/system/at.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 |
3 | {%- if system.at.enabled is defined and system.at.enabled %}
4 |
5 | at_packages:
6 | pkg.installed:
7 | - names: {{ system.at.pkgs }}
8 |
9 | at_services:
10 | service.running:
11 | - enable: true
12 | - names: {{ system.at.services }}
13 | - require:
14 | - pkg: at_packages
15 | {%- if grains.get('noservices') %}
16 | - onlyif: /bin/false
17 | {%- endif %}
18 |
19 | {%- set allow_users = [] %}
20 | {%- for user_name, user_params in system.at.get('user', {}).items() %}
21 | {%- set user_enabled = user_params.get('enabled', false) and
22 | system.get('user', {}).get(
23 | user_name, {'enabled': true}).get('enabled', true) %}
24 | {%- if user_enabled %}
25 | {%- do allow_users.append(user_name) %}
26 | {%- endif %}
27 | {%- endfor %}
28 |
29 | etc_at_allow:
30 | {%- if allow_users %}
31 | file.managed:
32 | - name: /etc/at.allow
33 | - template: jinja
34 | - source: salt://linux/files/cron_users.jinja
35 | - user: root
36 | - group: daemon
37 | - mode: 0640
38 | - defaults:
39 | users: {{ allow_users | yaml }}
40 | - require:
41 | - cron_packages
42 | {%- else %}
43 | file.absent:
44 | - name: /etc/at.allow
45 | {%- endif %}
46 |
47 |
48 | {#
49 | /etc/at.deny should be absent to comply with
50 | CIS 5.1.8 Ensure at/cron is restricted to authorized users
51 | #}
52 | etc_at_deny:
53 | file.absent:
54 | - name: /etc/at.deny
55 |
56 | {%- else %}
57 |
58 | fake_linux_system_at:
59 | test.nop:
60 | - comment: Fake state to satisfy 'require sls:linux.system.at'
61 |
62 | {%- endif %}
63 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-5-4-1-2.yml:
--------------------------------------------------------------------------------
1 | # CIS 5.4.1.2 Ensure minimum days between password changes is 7 or more (Scored)
2 | #
3 | # Description
4 | # ===========
5 | # The PASS_MIN_DAYS parameter in /etc/login.defs allows an administrator to
6 | # prevent users from changing their password until a minimum number of days
7 | # have passed since the last time the user changed their password. It is
8 | # recommended that PASS_MIN_DAYS parameter be set to 7 or more days.
9 | #
10 | # Rationale
11 | # =========
12 | # By restricting the frequency of password changes, an administrator can
13 | # prevent users from repeatedly changing their password in an attempt to
14 | # circumvent password reuse controls.
15 | #
16 | # Audit
17 | # =====
18 | # Run the following command and verify PASS_MIN_DAYS is 7 or more:
19 | #
20 | # # grep PASS_MIN_DAYS /etc/login.defs
21 | # PASS_MIN_DAYS 7
22 | #
23 | # Verify all users with a password have their minimum days between password
24 | # change set to 7 or more:
25 | #
26 | # # egrep ^[^:]+:[^\!*] /etc/shadow | cut -d: -f1
27 | #
28 | # # chage --list
29 | # Minimum number of days between password change: 7
30 | #
31 | # Remediation
32 | # ===========
33 | # Set the PASS_MIN_DAYS parameter to 7 in /etc/login.defs :
34 | #
35 | # PASS_MIN_DAYS 7
36 | #
37 | # Modify user parameters for all users with a password set to match:
38 | #
39 | # # chage --mindays 7
40 | #
41 | # Notes
42 | # =====
43 | # You can also check this setting in /etc/shadow directly. The 5th field
44 | # should be 7 or more for all users with a password.
45 | #
46 | parameters:
47 | linux:
48 | system:
49 | login_defs:
50 | PASS_MIN_DAYS:
51 | value: 7
52 |
53 |
--------------------------------------------------------------------------------
/linux/system/sysfs.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 |
3 | linux_sysfs_package:
4 | pkg.installed:
5 | - pkgs:
6 | - sysfsutils
7 | - refresh: true
8 |
9 | /etc/sysfs.d:
10 | file.directory:
11 | - require:
12 | - pkg: linux_sysfs_package
13 |
14 | {% set apply = system.get('sysfs', {}).pop('enable_apply', True) %}
15 |
16 | {%- for name, sysfs in system.get('sysfs', {}).items() %}
17 |
18 | /etc/sysfs.d/{{ name }}.conf:
19 | file.managed:
20 | - source: salt://linux/files/sysfs.conf
21 | - template: jinja
22 | - user: root
23 | - group: root
24 | - mode: 0644
25 | - defaults:
26 | name: {{ name }}
27 | sysfs: {{ sysfs|yaml }}
28 | - require:
29 | - file: /etc/sysfs.d
30 |
31 | {%- if sysfs is mapping %}
32 | {%- set sysfs_list = [sysfs] %}
33 | {%- else %}
34 | {%- set sysfs_list = sysfs %}
35 | {%- endif %}
36 |
37 | {%- if apply %}
38 |
39 | {%- for item in sysfs_list %}
40 | {%- set list_idx = loop.index %}
41 | {%- for key, value in item.items() %}
42 | {%- if key not in ["mode", "owner"] %}
43 | {%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
44 | {#- Sysfs cannot be set in docker, LXC, etc. #}
45 | linux_sysfs_write_{{ list_idx }}_{{ name }}_{{ key }}:
46 | module.run:
47 | {%- if 'module.run' in salt['config.get']('use_superseded', default=[]) %}
48 | - sysfs.write:
49 | - key: {{ key }}
50 | - value: {{ value }}
51 | {%- else %}
52 | - name: sysfs.write
53 | - key: {{ key }}
54 | - value: {{ value }}
55 | {%- endif %}
56 | {%- endif %}
57 | {%- endif %}
58 | {%- endfor %}
59 |
60 | {%- endfor %}
61 |
62 | {%- endif %}
63 |
64 | {%- endfor %}
65 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-5-4-1-1.yml:
--------------------------------------------------------------------------------
1 | # CIS 5.4.1.1 Ensure password expiration is 90 days or less (Scored)
2 | #
3 | # Description
4 | # ===========
5 | # The PASS_MAX_DAYS parameter in /etc/login.defs allows an administrator to
6 | # force passwords to expire once they reach a defined age. It is recommended
7 | # that the PASS_MAX_DAYS parameter be set to less than or equal to 90 days.
8 | #
9 | # Rationale
10 | # =========
11 | # The window of opportunity for an attacker to leverage compromised credentials
12 | # or successfully compromise credentials via an online brute force attack is
13 | # limited by the age of the password. Therefore, reducing the maximum age of a
14 | # password also reduces an attacker's window of opportunity.
15 | #
16 | # Audit
17 | # =====
18 | # Run the following command and verify PASS_MAX_DAYS is 90 or less:
19 | #
20 | # # grep PASS_MAX_DAYS /etc/login.defs
21 | # PASS_MAX_DAYS 90
22 | #
23 | # Verify all users with a password have their maximum days between password
24 | # change set to 90 or less:
25 | #
26 | # # egrep ^[^:]+:[^\!*] /etc/shadow | cut -d: -f1
27 | #
28 | # # chage --list
29 | # Maximum number of days between password change: 90
30 | #
31 | # Remediation
32 | # ===========
33 | # Set the PASS_MAX_DAYS parameter to 90 in /etc/login.defs :
34 | #
35 | # PASS_MAX_DAYS 90
36 | #
37 | # Modify user parameters for all users with a password set to match:
38 | #
39 | # # chage --maxdays 90
40 | #
41 | # Notes
42 | # =====
43 | # You can also check this setting in /etc/shadow directly. The 5th field
44 | # should be 90 or less for all users with a password.
45 | #
46 | parameters:
47 | linux:
48 | system:
49 | login_defs:
50 | PASS_MAX_DAYS:
51 | value: 90
52 |
53 |
--------------------------------------------------------------------------------
/linux/system/config.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- macro load_support_file(file, pillar, grains) %}{% include file %}{% endmacro %}
3 |
4 | {%- if system.enabled %}
5 |
6 | {%- for config_name, config in system.get('config', {}).items() %}
7 | {%- if config.enabled|default(True) %}
8 | {%- for service_name in config.pillar.keys() %}
9 | {%- if pillar.get(service_name, {}).get('_support', {}).get('config', {}).get('enabled', False) %}
10 | {%- set support_fragment_file = service_name+'/meta/config.yml' %}
11 | {%- set service_config_files = load_support_file(support_fragment_file, config.pillar, config.get('grains', {}))|load_yaml %}
12 | {%- for service_config_name, service_config in service_config_files.config.items() %}
13 |
14 | {{ service_config.path }}:
15 | file.managed:
16 | - source: {{ service_config.source }}
17 | - user: {{ config.get('user', service_config.get('user', 'root')) }}
18 | - group: {{ config.get('group', service_config.get('group', 'root')) }}
19 | - mode: {{ config.get('mode', service_config.get('mode', '644')) }}
20 | {%- if service_config.template is defined %}
21 | - template: {{ service_config.template }}
22 | {%- endif %}
23 | - makedirs: true
24 | - defaults:
25 | pillar: {{ config.pillar|yaml }}
26 | grains: {{ config.get('grains', {}) }}
27 | {%- for key, value in service_config.get('defaults', {}).items() %}
28 | {{ key }}: {{ value }}
29 | {%- endfor %}
30 |
31 | {%- endfor %}
32 | {%- endif %}
33 | {%- endfor %}
34 | {%- else %}
35 | {# TODO: configmap not using support between formulas #}
36 | {%- endif %}
37 | {%- endfor %}
38 |
39 | {%- endif %}
40 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-3-2-2.yml:
--------------------------------------------------------------------------------
1 | # 3.2.2 Ensure ICMP redirects are not accepted
2 | #
3 | # Description
4 | # ===========
5 | # ICMP redirect messages are packets that convey routing information and tell
6 | # your host (acting as a router) to send packets via an alternate path. It is
7 | # a way of allowing an outside routing device to update your system routing
8 | # tables. By setting net.ipv4.conf.all.accept_redirects to 0, the system will
9 | # not accept any ICMP redirect messages, and therefore, won't allow outsiders
10 | # to update the system's routing tables.
11 | #
12 | # Rationale
13 | # =========
14 | # Attackers could use bogus ICMP redirect messages to maliciously alter the
15 | # system routing tables and get them to send packets to incorrect networks and
16 | # allow your system packets to be captured.
17 | #
18 | # Audit
19 | # =====
20 | #
21 | # Run the following commands and verify output matches:
22 | #
23 | # # sysctl net.ipv4.conf.all.accept_redirects
24 | # net.ipv4.conf.all.accept_redirects = 0
25 | # # sysctl net.ipv4.conf.default.accept_redirects
26 | # net.ipv4.conf.default.accept_redirects = 0
27 | #
28 | # Remediation
29 | # ===========
30 | #
31 | # Set the following parameters in the /etc/sysctl.conf file:
32 | #
33 | # net.ipv4.conf.all.accept_redirects = 0
34 | # net.ipv4.conf.default.accept_redirects = 0
35 | #
36 | # Run the following commands to set the active kernel parameters:
37 | #
38 | # # sysctl -w net.ipv4.conf.all.accept_redirects=0
39 | # # sysctl -w net.ipv4.conf.default.accept_redirects=0
40 | # # sysctl -w net.ipv4.route.flush=1
41 |
42 | parameters:
43 | linux:
44 | system:
45 | kernel:
46 | sysctl:
47 | net.ipv4.conf.all.accept_redirects: 0
48 | net.ipv4.conf.default.accept_redirects: 0
49 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-1-1-21.yml:
--------------------------------------------------------------------------------
1 | # CIS 1.1.21 Disable Automounting
2 | #
3 | # Description
4 | # ===========
5 | # autofs allows automatic mounting of devices, typically including CD/DVDs
6 | # and USB drives.
7 | #
8 | # Rationale
9 | # =========
10 | # With automounting enabled anyone with physical access could attach a USB
11 | # drive or disc and have its contents available in system even if they lacked
12 | # permissions to mount it themselves.
13 | #
14 | # Audit
15 | # =====
16 | # Run the following command to verify autofs is not enabled:
17 | #
18 | # # systemctl is-enabled autofs
19 | # disabled
20 | #
21 | # Verify result is not "enabled".
22 | #
23 | # Remediation
24 | # ===========
25 | #
26 | # Run the following command to disable autofs :
27 | #
28 | # # systemctl disable autofs
29 | #
30 | # Impact
31 | # ======
32 | # The use portable hard drives is very common for workstation users. If your
33 | # organization allows the use of portable storage or media on workstations
34 | # and physical access controls to workstations is considered adequate there
35 | # is little value add in turning off automounting.
36 | #
37 | # Notes
38 | # =====
39 | # This control should align with the tolerance of the use of portable drives
40 | # and optical media in the organization. On a server requiring an admin to
41 | # manually mount media can be part of defense-in-depth to reduce the risk of
42 | # unapproved software or information being introduced or proprietary software
43 | # or information being exfiltrated. If admins commonly use flash drives and
44 | # Server access has sufficient physical controls, requiring manual mounting
45 | # may not increase security.
46 | #
47 | parameters:
48 | linux:
49 | system:
50 | service:
51 | autofs:
52 | status: disabled
53 |
54 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-1-5-1.yml:
--------------------------------------------------------------------------------
1 | # CIS 1.5.1 Ensure core dumps are restricted (Scored)
2 | #
3 | # Description
4 | # ===========
5 | #
6 | # A core dump is the memory of an executable program. It is generally used to determine
7 | # why a program aborted. It can also be used to glean confidential information from a core
8 | # file. The system provides the ability to set a soft limit for core dumps, but this can be
9 | # overridden by the user.
10 | #
11 | # Rationale
12 | # =========
13 | #
14 | # Setting a hard limit on core dumps prevents users from overriding the soft variable. If core
15 | # dumps are required, consider setting limits for user groups (see limits.conf(5) ). In
16 | # addition, setting the fs.suid_dumpable variable to 0 will prevent setuid programs from
17 | # dumping core.
18 | #
19 | # Audit
20 | # =====
21 | #
22 | # Run the following commands and verify output matches:
23 | #
24 | # # grep "hard core" /etc/security/limits.conf /etc/security/limits.d/*
25 | # * hard core 0
26 | # # sysctl fs.suid_dumpable
27 | # fs.suid_dumpable = 0
28 | #
29 | # Remediation
30 | # ===========
31 | #
32 | # Add the following line to the /etc/security/limits.conf file or a
33 | # /etc/security/limits.d/* file:
34 | #
35 | # * hard core 0
36 | #
37 | # Set the following parameter in the /etc/sysctl.conf file:
38 | #
39 | # fs.suid_dumpable = 0
40 | #
41 | # Run the following command to set the active kernel parameter:
42 | #
43 | # # sysctl -w fs.suid_dumpable=0
44 |
45 | parameters:
46 | linux:
47 | system:
48 | limit:
49 | cis:
50 | enabled: true
51 | domain: '*'
52 | limits:
53 | - type: 'hard'
54 | item: 'core'
55 | value: 0
56 | kernel:
57 | sysctl:
58 | fs.suid_dumpable: 0
59 |
60 |
--------------------------------------------------------------------------------
/linux/storage/mount.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import storage with context %}
2 | {%- if storage.enabled %}
3 |
4 | {%- for name, mount in storage.mount|dictsort %}
5 |
6 | {%- if mount.enabled %}
7 |
8 | {%- if not mount.file_system in ['nfs', 'nfs4', 'cifs', 'tmpfs', 'none'] %}
9 |
10 | mkfs_{{ mount.device}}:
11 | cmd.run:
12 | - name: "mkfs.{{ mount.file_system }} -L {{ name }} {{ mount.device }}"
13 | - onlyif: "test `blkid {{ mount.device }} | grep -q TYPE;echo $?` -eq 1"
14 | - require_in:
15 | - mount: {{ mount.path }}
16 | {%- if mount.file_system == 'xfs' %}
17 | - require:
18 | - pkg: xfs_packages_{{ mount.device }}
19 |
20 | xfs_packages_{{ mount.device }}:
21 | pkg.installed:
22 | - name: xfsprogs
23 | {%- endif %}
24 |
25 | {%- endif %}
26 |
27 | {%- if mount.file_system == 'nfs' %}
28 | linux_storage_nfs_packages_{{ mount.path }}:
29 | pkg.installed:
30 | - pkgs: {{ storage.nfs.pkgs | json }}
31 | {%- endif %}
32 |
33 | {{ mount.path }}:
34 | mount.mounted:
35 | - order: 1
36 | - device: {{ mount.device }}
37 | - fstype: {{ mount.file_system }}
38 | - mkmnt: True
39 | - opts: {{ mount.get('opts', 'defaults,noatime') }}
40 | - dump: {{ mount.dump|default('0', true) }}
41 | - pass_num: {{ mount.pass_num|default('0', true) }}
42 | {%- if mount.file_system == 'xfs' %}
43 | - require:
44 | - pkg: xfs_packages_{{ mount.device }}
45 | {%- endif %}
46 |
47 | {%- if mount.user is defined %}
48 | {{ mount.path }}_permissions:
49 | file.directory:
50 | - name: {{ mount.path }}
51 | - user: {{ mount.user }}
52 | - group: {{ mount.get('group', 'root') }}
53 | - mode: {{ mount.get('mode', 755) }}
54 | - require:
55 | - mount: {{ mount.path }}
56 | {%- endif %}
57 |
58 | {%- endif %}
59 |
60 | {%- endfor %}
61 |
62 | {%- endif %}
63 |
--------------------------------------------------------------------------------
/linux/system/atop.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 |
3 | {%- if system.atop.enabled %}
4 |
5 | atop_packages:
6 | pkg.installed:
7 | - name: atop
8 |
9 | atop_defaults:
10 | file.managed:
11 | - name: /etc/default/atop
12 | - source: salt://linux/files/atop.conf
13 | - template: jinja
14 | - user: root
15 | - group: root
16 | - mode: 644
17 |
18 | atop_logpath:
19 | file.directory:
20 | - name: {{ system.atop.logpath }}
21 | - user: root
22 | - group: root
23 | - mode: 750
24 | - makedirs: true
25 |
26 | {%- if grains.get('init', None) == 'systemd' %}
27 | atop_systemd_file:
28 | file.managed:
29 | - name: /etc/systemd/system/atop.service
30 | - source: salt://linux/files/atop.service
31 | - user: root
32 | - mode: 644
33 | - defaults:
34 | service_name: atop
35 | config_file: /etc/default/atop
36 | autostart: {{ system.atop.autostart }}
37 | - template: jinja
38 | - require_in:
39 | - service: atop_service
40 | {%- endif %}
41 |
42 | atop_service:
43 | service.running:
44 | - name: atop
45 | - enable: {{ system.atop.autostart }}
46 | - watch:
47 | - file: atop_defaults
48 | {%- if grains.get('noservices') %}
49 | - onlyif: /bin/false
50 | {%- endif %}
51 |
52 | {%- else %}
53 |
54 | atop_service_stop:
55 | service.dead:
56 | - name: atop
57 | - enable: false
58 | - require_in:
59 | - pkg: atop_pkg_purge
60 | {%- if grains.get('noservices') %}
61 | - onlyif: /bin/false
62 | {%- endif %}
63 |
64 | atop_defaults_purge:
65 | file.absent:
66 | - names:
67 | - /etc/default/atop
68 | - /etc/systemd/system/atop.service
69 | - require:
70 | - pkg: atop_pkg_purge
71 |
72 | atop_pkg_purge:
73 | pkg.purged:
74 | - name: atop
75 |
76 | {%- endif %}
77 |
--------------------------------------------------------------------------------
/linux/files/nslcd.conf:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import ldap with context -%}
2 | # /etc/nslcd.conf
3 | # nslcd configuration file. See nslcd.conf(5)
4 | # for details.
5 |
6 | # The user and group nslcd should run as.
7 | uid {{ ldap.uid }}
8 | gid {{ ldap.gid }}
9 |
10 | {%- if ldap.enabled %}
11 |
12 | {%- if ldap.uri is defined %}
13 | # The location at which the LDAP server(s) should be reachable.
14 | uri {{ ldap.uri }}
15 | {%- endif %}
16 |
17 | {%- if ldap.base is defined %}
18 | # The search base that will be used for all queries.
19 | base {{ ldap.base }}
20 | {%- endif %}
21 |
22 | # The LDAP protocol version to use.
23 | ldap_version {{ ldap.version }}
24 |
25 | {%- if ldap.binddn is defined %}
26 | # The DN to bind with for normal lookups.
27 | binddn {{ ldap.binddn }}
28 | {%- if ldap.bindpw is defined %}
29 | bindpw {{ ldap.bindpw }}
30 | {%- endif %}
31 | {%- endif %}
32 |
33 | {%- if ldap.rootpwmoddn is defined %}
34 | # The DN used for password modifications by root.
35 | rootpwmoddn {{ ldap.rootpwmoddn }}
36 | {%- endif %}
37 |
38 | # SSL options
39 | #ssl off
40 | #tls_reqcert never
41 | #tls_cacertfile /etc/ssl/certs/ca-certificates.crt
42 |
43 | # The search scope.
44 | scope {{ ldap.scope }}
45 |
46 | {%- if ldap.pagesize is defined %}
47 | pagesize {{ ldap.pagesize }}
48 | {%- endif %}
49 | {%- if ldap.referrals is defined %}
50 | referrals {{ ldap.referrals }}
51 | {%- endif %}
52 |
53 | {%- if ldap.filter is defined %}
54 | # Filters
55 | {%- for key, value in ldap.filter.items() %}
56 | filter {{ key }} {{ value }}
57 | {%- endfor %}
58 | {%- endif %}
59 | {%- if ldap.map is defined %}
60 | # Mappings
61 | {%- for map_name,map in ldap.map.items() %}
62 | {%- for key, value in map.items() %}
63 | map {{ map_name }} {{ key }} {{ value }}
64 | {%- endfor %}
65 | {%- endfor %}
66 | {%- endif %}
67 |
68 | {%- endif %}
69 |
--------------------------------------------------------------------------------
/linux/system/job.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | include:
5 | - linux.system.user
6 | - linux.system.cron
7 |
8 | {%- for name, job in system.job.items() %}
9 | {%- set job_user = job.get('user', 'root') %}
10 |
11 | linux_job_{{ job.command }}:
12 | {%- if job.get('enabled', True) %}
13 | cron.present:
14 | - name: >
15 | {{ job.command }}
16 | {%- if job.get('identifier', True) %}
17 | - identifier: {{ job.get('identifier', job.get('name', name)) }}
18 | {%- endif %}
19 | {%- if job.get('commented', False) %}
20 | - commented: True
21 | {%- endif %}
22 | - user: {{ job_user }}
23 | {%- if job.special is defined %}
24 | - special: '{{ job.special }}'
25 | {%- else %}
26 | {%- if job.minute is defined %}
27 | - minute: '{{ job.minute }}'
28 | {%- endif %}
29 | {%- if job.hour is defined %}
30 | - hour: '{{ job.hour }}'
31 | {%- endif %}
32 | {%- if job.daymonth is defined %}
33 | - daymonth: '{{ job.daymonth }}'
34 | {%- endif %}
35 | {%- if job.month is defined %}
36 | - month: '{{ job.month }}'
37 | {%- endif %}
38 | {%- if job.dayweek is defined %}
39 | - dayweek: '{{ job.dayweek }}'
40 | {%- endif %}
41 | {%- endif %}
42 | - require:
43 | - sls: linux.system.cron
44 | {%- if job_user in system.get('user', {}).keys() %}
45 | - user: system_user_{{ job_user }}
46 | {%- endif %}
47 | {%- else %}
48 | cron.absent:
49 | - name: {{ job.command }}
50 | {%- if job.get('identifier', True) %}
51 | - identifier: {{ job.get('identifier', job.get('name', name)) }}
52 | {%- endif %}
53 | - user: {{ job_user }}
54 | {%- endif %}
55 | {%- endfor %}
56 | {%- endif %}
57 |
--------------------------------------------------------------------------------
/linux/system/package.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- set pkgs_groups = {
5 | 'latest': [],
6 | 'purged': [],
7 | 'removed': [],
8 | 'installed': [],
9 | } %}
10 | {%- for name, package in system.package.items() %}
11 |
12 | {%- if package.repo is defined or package.hold is defined or package.verify is defined %}
13 | linux_extra_package_{{ name }}:
14 | {%- if package.version is defined %}
15 | {%- if package.version == 'latest' %}
16 | pkg.latest:
17 | {%- elif package.version == 'purged' %}
18 | pkg.purged:
19 | {%- elif package.version == 'removed' %}
20 | pkg.removed:
21 | {%- else %}
22 | pkg.installed:
23 | - version: {{ package.version }}
24 | {%- endif %}
25 | {%- else %}
26 | pkg.installed:
27 | {%- endif %}
28 | - name: {{ name }}
29 | {%- if package.repo is defined %}
30 | - fromrepo: {{ package.repo }}
31 | {%- endif %}
32 | {%- if package.hold is defined %}
33 | - hold: {{ package.hold }}
34 | {%- endif %}
35 | {%- if package.verify is defined %}
36 | - skip_verify: {{ "False" if package.verify else "True" }}
37 | {%- endif %}
38 | {%- else %}
39 | {%- if package.version is not defined %}
40 | {%- do pkgs_groups['installed'].append(name) %}
41 | {%- elif package.version in ('latest', 'purged', 'removed') %}
42 | {%- do pkgs_groups[package.version].append(name) %}
43 | {%- else %}
44 | {%- do pkgs_groups['installed'].append({name: package.version}) %}
45 | {%- endif %}
46 | {%- endif %}
47 |
48 | {%- endfor %}
49 |
50 | {%- for pkgs_group, pkgs in pkgs_groups.items() %}
51 | {%- if pkgs %}
52 | linux_extra_packages_{{ pkgs_group }}:
53 | pkg.{{ pkgs_group }}:
54 | - pkgs: {{ pkgs | json }}
55 | {%- endif %}
56 | {%- endfor %}
57 |
58 | {%- endif %}
59 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/init.yml:
--------------------------------------------------------------------------------
1 | classes:
2 | - service.linux.system.cis.cis-1-1-1-1
3 | - service.linux.system.cis.cis-1-1-1-2
4 | - service.linux.system.cis.cis-1-1-1-3
5 | - service.linux.system.cis.cis-1-1-1-4
6 | - service.linux.system.cis.cis-1-1-1-5
7 | - service.linux.system.cis.cis-1-1-1-6
8 | - service.linux.system.cis.cis-1-1-1-7
9 | - service.linux.system.cis.cis-1-1-1-8
10 | - service.linux.system.cis.cis-1-1-14_15_16
11 | - service.linux.system.cis.cis-1-1-21
12 | - service.linux.system.cis.cis-1-5-1
13 | - service.linux.system.cis.cis-1-5-3
14 | - service.linux.system.cis.cis-1-5-4
15 | - service.linux.system.cis.cis-2-3-1
16 | - service.linux.system.cis.cis-2-3-2
17 | - service.linux.system.cis.cis-2-3-3
18 | - service.linux.system.cis.cis-2-3-4
19 | - service.linux.system.cis.cis-3-1-2
20 | - service.linux.system.cis.cis-3-2-1
21 | - service.linux.system.cis.cis-3-2-2
22 | - service.linux.system.cis.cis-3-2-3
23 | - service.linux.system.cis.cis-3-2-4
24 | - service.linux.system.cis.cis-3-2-5
25 | - service.linux.system.cis.cis-3-2-6
26 | - service.linux.system.cis.cis-3-2-7
27 | - service.linux.system.cis.cis-3-2-8
28 | # Temp. disable PROD-22520
29 | #- service.linux.system.cis.cis-3-3-3
30 | - service.linux.system.cis.cis-3-5-1
31 | - service.linux.system.cis.cis-3-5-2
32 | - service.linux.system.cis.cis-3-5-3
33 | - service.linux.system.cis.cis-3-5-4
34 | - service.linux.system.cis.cis-5-4-1-1
35 | - service.linux.system.cis.cis-5-4-1-2
36 | - service.linux.system.cis.cis-5-4-1-3
37 | - service.linux.system.cis.cis-5-4-4
38 | - service.linux.system.cis.cis-6-1-2
39 | - service.linux.system.cis.cis-6-1-3
40 | - service.linux.system.cis.cis-6-1-4
41 | - service.linux.system.cis.cis-6-1-5
42 | - service.linux.system.cis.cis-6-1-6
43 | - service.linux.system.cis.cis-6-1-7
44 | - service.linux.system.cis.cis-6-1-8
45 | - service.linux.system.cis.cis-6-1-9
46 |
--------------------------------------------------------------------------------
/tests/pillar/storage.sls:
--------------------------------------------------------------------------------
1 | linux:
2 | system:
3 | enabled: true
4 | name: linux
5 | domain: local
6 | network:
7 | enabled: true
8 | hostname: linux
9 | fqdn: linux.ci.local
10 | storage:
11 | enabled: true
12 | swap:
13 | file:
14 | enabled: true
15 | engine: file
16 | device: /tmp/loop_dev2
17 | size: 5
18 | mount:
19 | # NOTE: simple dummy loop devices, use for test purposes only
20 | dev0:
21 | enabled: false
22 | device: /tmp/loop_dev0
23 | path: /tmp/node/dev0
24 | file_system: xfs
25 | opts: noatime,nobarrier,logbufs=8,nobootwait,nobarrier
26 | user: root
27 | group: root
28 | mode: 755
29 | dev1:
30 | enabled: true
31 | device: /tmp/loop_dev1
32 | path: /mnt
33 | file_system: ext4
34 | #opts: noatime,nobarrier,logbufs=8,nobootwait,nobarrier
35 | user: root
36 | group: root
37 | lvm:
38 | vg0:
39 | name: vg0-dummy
40 | enabled: true
41 | devices:
42 | - /tmp/loop_dev3
43 | volume:
44 | lv01:
45 | size: 5M
46 | mount:
47 | device: /dev/vg0/lv01
48 | path: /mnt/lv01
49 | lv02:
50 | size: 5M
51 | mount:
52 | device: /dev/vg0/lv02
53 | path: /mnt/lv02
54 | file_system: ext4
55 | lv03:
56 | size: 5M
57 | mount:
58 | device: /dev/vg0/lv03
59 | path: /mnt/lv03
60 | file_system: xfs
61 | disk:
62 | first_drive:
63 | name: /tmp/loop_dev4
64 | type: gpt
65 | partitions:
66 | - size: 5
67 | type: fat32
68 | - size: 5
69 | type: fat32
70 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-3-2-7.yml:
--------------------------------------------------------------------------------
1 | # 3.2.7 Ensure Reverse Path Filtering is enabled
2 | #
3 | # Description
4 | # ===========
5 | # Setting net.ipv4.conf.all.rp_filter and net.ipv4.conf.default.rp_filter to 1
6 | # forces the Linux kernel to utilize reverse path filtering on a received
7 | # packet to determine if the packet was valid. Essentially, with reverse path
8 | # filtering, if the return packet does not go out the same interface that the
9 | # corresponding source packet came from, the packet is dropped (and logged if
10 | # log_martians is set).
11 | #
12 | # Rationale
13 | # =========
14 | # Setting these flags is a good way to deter attackers from sending your system
15 | # bogus packets that cannot be responded to. One instance where this feature
16 | # breaks down is if asymmetrical routing is employed. This would occur when
17 | # using dynamic routing protocols (bgp, ospf, etc) on your system. If you are
18 | # using asymmetrical routing on your system, you will not be able to enable
19 | # this feature without breaking the routing.
20 | #
21 | # Audit
22 | # =====
23 | #
24 | # Run the following commands and verify output matches:
25 | #
26 | # # sysctl net.ipv4.conf.all.rp_filter
27 | # net.ipv4.conf.all.rp_filter = 1
28 | # # sysctl net.ipv4.conf.default.rp_filter
29 | # net.ipv4.conf.default.rp_filter = 1
30 | #
31 | # Remediation
32 | # ===========
33 | #
34 | # Set the following parameters in the /etc/sysctl.conf file:
35 | #
36 | # net.ipv4.conf.all.rp_filter = 1
37 | # net.ipv4.conf.default.rp_filter = 1
38 | #
39 | # Run the following commands to set the active kernel parameters:
40 | #
41 | # # sysctl -w net.ipv4.conf.all.rp_filter=1
42 | # # sysctl -w net.ipv4.conf.default.rp_filter=1
43 | # # sysctl -w net.ipv4.route.flush=1
44 |
45 | parameters:
46 | linux:
47 | system:
48 | kernel:
49 | sysctl:
50 | net.ipv4.conf.all.rp_filter: 1
51 | net.ipv4.conf.default.rp_filter: 1
52 |
--------------------------------------------------------------------------------
/linux/meta/sensu.yml:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system,network,storage,monitoring with context -%}
2 | check:
3 | local_linux_system_zombie_procs:
4 | command: "PATH=$PATH:/usr/lib64/nagios/plugins:/usr/lib/nagios/plugins check_procs -w {{ monitoring.zombie.warn }} -c {{ monitoring.zombie.crit }} -s Z"
5 | interval: 60
6 | occurrences: 3
7 | subscribers:
8 | - local-linux-system
9 | local_linux_system_total_procs:
10 | command: "PATH=$PATH:/usr/lib64/nagios/plugins:/usr/lib/nagios/plugins check_procs -w {{ monitoring.procs.warn }} -c {{ monitoring.procs.crit }}"
11 | interval: 60
12 | occurrences: 5
13 | subscribers:
14 | - local-linux-system
15 | local_linux_system_load:
16 | command: "PATH=$PATH:/usr/lib64/nagios/plugins:/usr/lib/nagios/plugins check_load -r -w {{ monitoring.load.warn }} -c {{ monitoring.load.crit }}"
17 | interval: 60
18 | occurrences: 1
19 | subscribers:
20 | - local-linux-system
21 | {%- if storage.swap|length > 0 %}
22 | local_linux_storage_swap_usage_{{ system.name|replace('.', '-') }}-{{ system.domain|replace('.', '-') }}:
23 | command: "PATH=$PATH:/usr/lib64/nagios/plugins:/usr/lib/nagios/plugins check_swap -a -w {{ monitoring.swap.warn }} -c {{ monitoring.swap.crit }}"
24 | interval: 60
25 | occurrences: 1
26 | subscribers:
27 | - {{ system.name|replace('.', '-') }}-{{ system.domain|replace('.', '-') }}
28 | {%- endif %}
29 | local_linux_storage_disk_usage:
30 | command: "PATH=$PATH:/usr/lib64/nagios/plugins:/usr/lib/nagios/plugins check_disk -w {{ monitoring.disk.warn }} -c {{ monitoring.disk.crit }} -p / -p /var -p /usr -p /tmp -p /var/log"
31 | interval: 60
32 | occurrences: 1
33 | subscribers:
34 | - local-linux-storage
35 | local_linux_network_fqdn:
36 | command: "PATH=$PATH:/etc/sensu/plugins check_fqdn.py -n :::hostname::: -f :::fqdn:::"
37 | interval: 60
38 | occurrences: 1
39 | subscribers:
40 | - local-linux-network
41 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-3-2-8.yml:
--------------------------------------------------------------------------------
1 | # 3.2.8 Ensure TCP SYN Cookies is enabled
2 | #
3 | # Description
4 | # ===========
5 | # When tcp_syncookies is set, the kernel will handle TCP SYN packets normally
6 | # until the half-open connection queue is full, at which time, the SYN cookie
7 | # functionality kicks in. SYN cookies work by not using the SYN queue at all.
8 | # Instead, the kernel simply replies to the SYN with a SYN|ACK, but will
9 | # include a specially crafted TCP sequence number that encodes the source and
10 | # destination IP address and port number and the time the packet was sent.
11 | # A legitimate connection would send the ACK packet of the three way handshake
12 | # with the specially crafted sequence number. This allows the system to verify
13 | # that it has received a valid response to a SYN cookie and allow the
14 | # connection, even though there is no corresponding SYN in the queue.
15 | #
16 | # Rationale
17 | # =========
18 | # Attackers use SYN flood attacks to perform a denial of service attacked on a
19 | # system by sending many SYN packets without completing the three way handshake.
20 | # This will quickly use up slots in the kernel's half-open connection queue and
21 | # prevent legitimate connections from succeeding. SYN cookies allow the system
22 | # to keep accepting valid connections, even if under a denial of service attack.
23 | #
24 | # Audit
25 | # =====
26 | #
27 | # Run the following commands and verify output matches:
28 | #
29 | # # sysctl net.ipv4.tcp_syncookies
30 | # net.ipv4.tcp_syncookies = 1
31 | #
32 | # Remediation
33 | # ===========
34 | #
35 | # Set the following parameter in the /etc/sysctl.conf file:
36 | #
37 | # net.ipv4.tcp_syncookies = 1
38 | #
39 | # Run the following commands to set the active kernel parameters:
40 | #
41 | # # sysctl -w net.ipv4.tcp_syncookies=1
42 | # # sysctl -w net.ipv4.route.flush=1
43 |
44 | parameters:
45 | linux:
46 | system:
47 | kernel:
48 | sysctl:
49 | net.ipv4.tcp_syncookies: 1
50 |
--------------------------------------------------------------------------------
/linux/meta/collectd.yml:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import monitoring with context %}
2 | local_plugin:
3 | linux_network_netlink:
4 | plugin: netlink
5 | template: linux/files/collectd_netlink.conf
6 | ignore_selected: {{ monitoring.netlink.ignore_selected }}
7 | {%- if monitoring.netlink.interfaces is list and monitoring.netlink.interfaces|length > 0 %}
8 | {%- set interfaces = monitoring.netlink.interfaces %}
9 | {%- else %}
10 | {%- set interfaces = salt['linux_netlink.ls'](monitoring.netlink.interface_regex) %}
11 | {%- endif %}
12 | {%- if interfaces %}
13 | interfaces:
14 | {%- for interface_name in interfaces|sort %}
15 | - {{ interface_name }}
16 | {%- endfor %}
17 | {%- endif %}
18 | linux_system_cpu:
19 | plugin: cpu
20 | linux_system_entropy:
21 | plugin: entropy
22 | linux_system_load:
23 | plugin: load
24 | linux_system_contextswitch:
25 | plugin: contextswitch
26 | linux_system_memory:
27 | plugin: memory
28 | linux_system_uptime:
29 | plugin: uptime
30 | linux_system_users:
31 | plugin: users
32 | linux_storage_df:
33 | plugin: df
34 | template: linux/files/collectd_df.conf
35 | ignore_selected: True
36 | fs_types:
37 | - rootfs
38 | - sysfs
39 | - proc
40 | - devtmpfs
41 | - devpts
42 | - tmpfs
43 | - fusectl
44 | - cgroup
45 | - overlay
46 | linux_storage_disk:
47 | plugin: disk
48 | template: linux/files/collectd_disk.conf
49 | ignore_selected: True
50 | linux_storage_swap:
51 | plugin: swap
52 | template: linux/files/collectd_swap.conf
53 | report_bytes: True
54 | {%- if monitoring.bond_status.interfaces is defined and monitoring.bond_status.interfaces is list %}
55 | linux_bond_status:
56 | plugin: python
57 | template: linux/files/collectd_bond_status.conf
58 | interfaces:
59 | {%- for interface in monitoring.bond_status.interfaces %}
60 | - {{ interface }}
61 | {%- endfor %}
62 | {%- endif %}
63 |
--------------------------------------------------------------------------------
/linux/files/openvswitch-switch.default:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import network with context %}
2 | {%- set openvswitch = network.openvswitch %}
3 | # This is a POSIX shell fragment -*- sh -*-
4 |
5 | # FORCE_COREFILES: If 'yes' then core files will be enabled.
6 | # FORCE_COREFILES=yes
7 |
8 | # OVS_CTL_OPTS: Extra options to pass to ovs-ctl. This is, for example,
9 | # a suitable place to specify --ovs-vswitchd-wrapper=valgrind.
10 | # OVS_CTL_OPTS=
11 |
12 | # OVS_VSWITCHD_OPTS: Extra options to pass to ovs-ctl.
13 | # Options to start Open vSwitch daemon with.
14 | # Example: '-vconsole:dbg -vsyslog:dbg -vfile:dbg -vFACILITY:clock2'
15 | # OVS_VSWITCHD_OPTS=
16 | {%- if openvswitch.get('logging', {}).vswitchd is defined %}
17 | {%- set _vswitchd_opts = [] %}
18 | {%- for opt in ['console', 'file', 'syslog'] %}
19 | {%- if openvswitch.logging.vswitchd.get(opt) %}
20 | {%- do _vswitchd_opts.append("-v"+ opt + ":" + openvswitch.logging.vswitchd.get(opt)) %}
21 | {%- endif %}
22 | {%- endfor %}
23 | {%- if openvswitch.logging.vswitchd.facility is defined %}
24 | {%- do _vswitchd_opts.append("-vFACILITY:" + openvswitch.logging.vswitchd.facility) %}
25 | {%- endif %}
26 | OVS_VSWITCHD_OPTS="{{ ' '.join(_vswitchd_opts) }}"
27 | {%- endif %}
28 |
29 | # OVSDB_OPTS: Extra options to pass to ovs-ctl.
30 | # Options to start Open vSwitch DB daemon with.
31 | # Example: '-vconsole:dbg -vsyslog:dbg -vfile:dbg -vFACILITY:clock2'
32 | # OVSDB_OPTS=
33 | {%- if openvswitch.get('logging', {}).ovsdb is defined %}
34 | {%- set _ovsdb_opts = [] %}
35 | {%- for opt in ['console', 'file', 'syslog'] %}
36 | {%- if openvswitch.logging.ovsdb.get(opt) %}
37 | {%- do _ovsdb_opts.append("-v" + opt + ":" + openvswitch.logging.ovsdb.get(opt)) %}
38 | {%- endif %}
39 | {%- endfor %}
40 | {%- if openvswitch.logging.ovsdb.facility is defined %}
41 | {%- do _ovsdb_opts.append("-vFACILITY:" + openvswitch.logging.ovsdb.facility) %}
42 | {%- endif %}
43 | OVSDB_OPTS="{{ ' '.join(_ovsdb_opts) }}"
44 | {%- endif %}
45 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-2-3-2.yml:
--------------------------------------------------------------------------------
1 | # 2.3.2 Ensure rsh client is not installed
2 | #
3 | # Description
4 | # ===========
5 | # The rsh package contains the client commands for the rsh services.
6 | #
7 | # Rationale
8 | # =========
9 | # These legacy clients contain numerous security exposures and have been
10 | # replaced with the more secure SSH package. Even if the server is removed,
11 | # it is best to ensure the clients are also removed to prevent users from
12 | # inadvertently attempting to use these commands and therefore exposing
13 | # their credentials. Note that removing the rsh package removes the
14 | # clients for rsh , rcp and rlogin .
15 | #
16 | # Audit
17 | # =====
18 | # Run the following commands and verify rsh is not installed:
19 | #
20 | # dpkg -s rsh-client
21 | # dpkg -s rsh-redone-client
22 | #
23 | # Remediation
24 | # ===========
25 | # Run the following command to uninstall rsh :
26 | #
27 | # apt-get remove rsh-client rsh-redone-client
28 | #
29 | # Impact
30 | # ======
31 | # Many insecure service clients are used as troubleshooting tools and in
32 | # testing environments. Uninstalling them can inhibit capability to test
33 | # and troubleshoot. If they are required it is advisable to remove the
34 | # clients after use to prevent accidental or intentional misuse.
35 | #
36 | # NOTE
37 | # ====
38 | # It is not possible to remove rsh-client by means of SaltStack because
39 | # of the way SaltStack checks that package was really removed. 'rsh-client'
40 | # is "provided" by openssh-client package, and SaltStack thinks that
41 | # it is the same as 'rsh-client is installed'. So each time we try to
42 | # remove 'rsh-client' on a system where 'openssh-client' is installed
43 | # (that's almost every system), we got state failure.
44 | # This was fixed in upstream SaltStack in 2018, not sure where we start using
45 | # this version. Until that moment 'rsh-client' should remain unmanaged.
46 | #
47 | parameters:
48 | linux:
49 | system:
50 | package:
51 | # rsh-client:
52 | # version: removed
53 | rsh-redone-client:
54 | version: removed
55 |
56 |
--------------------------------------------------------------------------------
/linux/system/sudo.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- if system.get('sudo', {}).get('enabled', False) %}
5 |
6 | {%- if system.get('sudo', {}).get('aliases', False) is mapping %}
7 | /etc/sudoers.d/90-salt-sudo-aliases:
8 | file.managed:
9 | - source: salt://linux/files/sudoer-aliases
10 | - template: jinja
11 | - user: root
12 | - group: root
13 | - mode: 440
14 | - defaults:
15 | aliases: {{ system.sudo.aliases|yaml }}
16 | - check_cmd: /usr/sbin/visudo -c -f
17 | {%- else %}
18 | /etc/sudoers.d/90-salt-sudo-aliases:
19 | file.absent:
20 | - name: /etc/sudoers.d/90-salt-sudo-aliases
21 | {%- endif %}
22 |
23 |
24 | {%- if system.get('sudo', {}).get('users', False) is mapping %}
25 | /etc/sudoers.d/91-salt-sudo-users:
26 | file.managed:
27 | - source: salt://linux/files/sudoer-users
28 | - template: jinja
29 | - user: root
30 | - group: root
31 | - mode: 440
32 | - defaults:
33 | users: {{ system.sudo.users|yaml }}
34 | - check_cmd: /usr/sbin/visudo -c -f
35 | {%- else %}
36 | /etc/sudoers.d/91-salt-sudo-users:
37 | file.absent:
38 | - name: /etc/sudoers.d/91-salt-sudo-users
39 | {%- endif %}
40 |
41 | {%- if system.get('sudo', {}).get('groups', False) is mapping %}
42 | /etc/sudoers.d/91-salt-sudo-groups:
43 | file.managed:
44 | - source: salt://linux/files/sudoer-groups
45 | - template: jinja
46 | - user: root
47 | - group: root
48 | - mode: 440
49 | - defaults:
50 | groups: {{ system.sudo.groups|yaml }}
51 | - check_cmd: /usr/sbin/visudo -c -f
52 | {%- else %}
53 | /etc/sudoers.d/91-salt-sudo-groups:
54 | file.absent:
55 | - name: /etc/sudoers.d/91-salt-sudo-groups
56 | {%- endif %}
57 |
58 | {%- else %}
59 |
60 | /etc/sudoers.d/90-salt-sudo-aliases:
61 | file.absent:
62 | - name: /etc/sudoers.d/90-salt-sudo-aliases
63 |
64 | /etc/sudoers.d/91-salt-sudo-users:
65 | file.absent:
66 | - name: /etc/sudoers.d/91-salt-sudo-users
67 |
68 | /etc/sudoers.d/91-salt-sudo-groups:
69 | file.absent:
70 | - name: /etc/sudoers.d/91-salt-sudo-groups
71 |
72 | {%- endif %}
73 | {%- endif %}
74 |
--------------------------------------------------------------------------------
/linux/system/file.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 | {%- if system.enabled %}
3 |
4 | {%- for file_name, file in system.file.items() %}
5 |
6 | linux_file_{{ file_name }}:
7 | {%- if file.absent is defined and file.absent is sameas true %}
8 | file.absent:
9 |
10 | {%- elif file.serialize is defined %}
11 | file.serialize:
12 | - formatter: {{ file.serialize }}
13 | {%- if file.contents is defined %}
14 | - dataset: {{ file.contents|json }}
15 | {%- elif file.contents_pillar is defined %}
16 | - dataset_pillar: {{ file.contents_pillar }}
17 | {%- endif %}
18 |
19 | {%- else %}
20 | file.managed:
21 | {%- if file.source is defined %}
22 | - source: {{ file.source }}
23 | {%- if file.hash is defined %}
24 | - source_hash: {{ file.hash }}
25 | {%- else %}
26 | - skip_verify: True
27 | {%- endif %}
28 | {%- if file.template is defined %}
29 | - template: {{ file.template }}
30 | {%- if file.defaults is defined %}
31 | - defaults: {{ file.defaults|json }}
32 | {%- endif %}
33 | {%- if file.context is defined %}
34 | - context: {{ file.context|json }}
35 | {%- endif %}
36 | {%- endif %}
37 | {%- elif file.contents is defined %}
38 | - contents: {{ file.contents|json }}
39 | {%- elif file.contents_pillar is defined %}
40 | - contents_pillar: {{ file.contents_pillar }}
41 | {%- elif file.contents_grains is defined %}
42 | - contents_grains: {{ file.contents_grains }}
43 | {%- endif %}
44 |
45 | {%- endif %}
46 | {%- if file.name is defined %}
47 | - name: {{ file.name }}
48 | {%- else %}
49 | - name: {{ file_name }}
50 | {%- endif %}
51 | - makedirs: {{ file.get('makedirs', 'True') }}
52 | - replace: {{ file.get('replace', 'True') }}
53 | - user: {{ file.get('user', 'root') }}
54 | - group: {{ file.get('group', 'root') }}
55 | {%- if file.mode is defined %}
56 | - mode: {{ file.mode }}
57 | {%- endif %}
58 | {%- if file.dir_mode is defined %}
59 | - dir_mode: {{ file.dir_mode }}
60 | {%- endif %}
61 | {%- if file.encoding is defined %}
62 | - encoding: {{ file.encoding }}
63 | {%- endif %}
64 |
65 | {%- endfor %}
66 |
67 | {%- endif %}
68 |
--------------------------------------------------------------------------------
/tests/pillar/network_openvswitch_dpdk.sls:
--------------------------------------------------------------------------------
1 | linux:
2 | system:
3 | enabled: true
4 | domain: local
5 | name: linux
6 | network:
7 | enabled: true
8 | hostname: test01
9 | fqdn: test01.local
10 | network_manager: false
11 | bridge: openvswitch
12 | dpdk:
13 | enabled: true
14 | driver: uio
15 | openvswitch:
16 | pmd_cpu_mask: "0x6"
17 | dpdk_socket_mem: "1024"
18 | dpdk_lcore_mask: "0x400"
19 | memory_channels: "2"
20 | vhost_socket_dir:
21 | name: "openvswitch-vhost"
22 | path: "/run/openvswitch-vhost"
23 | interface:
24 | eth0:
25 | enabled: true
26 | type: eth
27 | proto: manual
28 | ovs_bridge: br-prv
29 | dpdk0:
30 | name: enp5s0f1
31 | pci: "0000:05:00.1"
32 | driver: igb_uio
33 | bond: dpdkbond0
34 | enabled: true
35 | type: dpdk_ovs_port
36 | dpdk1:
37 | name: enp5s0f2
38 | pci: "0000:05:00.2"
39 | driver: igb_uio
40 | bond: dpdkbond0
41 | enabled: true
42 | type: dpdk_ovs_port
43 | dpdk2:
44 | name: enp6s0f1
45 | pci: "0000:06:00.1"
46 | driver: igb_uio
47 | bond: dpdkbond1
48 | enabled: true
49 | type: dpdk_ovs_port
50 | dpdk3:
51 | name: enp6s0f2
52 | pci: "0000:06:00.2"
53 | driver: igb_uio
54 | bond: dpdkbond1
55 | enabled: true
56 | type: dpdk_ovs_port
57 | dpdkbond0:
58 | enabled: true
59 | bridge: br-prv
60 | type: dpdk_ovs_bond
61 | mode: active-backup
62 | dpdkbond1:
63 | enabled: true
64 | bridge: br-mesh
65 | type: dpdk_ovs_bond
66 | mode: balance-slb
67 | br-prv:
68 | enabled: true
69 | type: dpdk_ovs_bridge
70 | br-mesh:
71 | tag: 1302
72 | enabled: true
73 | type: dpdk_ovs_bridge
74 | address: 1.2.3.4
75 | netmask: 255.255.255.252
76 | dummy0:
77 | enabled: true
78 | name: dummy0
79 | proto: manual
80 | ovs_port_type: OVSIntPort
81 | type: ovs_port
82 | ovs_bridge: br-prv
83 | bridge: br-prv
84 |
--------------------------------------------------------------------------------
/.kitchen.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: docker
4 | hostname: linux-formula
5 | run_options: -v /dev/log:/dev/log:ro
6 |
7 | provisioner:
8 | name: salt_solo
9 | salt_install: bootstrap
10 | salt_bootstrap_url: https://bootstrap.saltstack.com
11 | salt_version: latest
12 | require_chef: false
13 | log_level: error
14 | formula: linux
15 | grains:
16 | noservices: true
17 | state_top:
18 | base:
19 | "*":
20 | - linux
21 | pillars:
22 | top.sls:
23 | base:
24 | "*":
25 | - linux
26 |
27 | verifier:
28 | name: inspec
29 | sudo: true
30 |
31 | platforms:
32 | - name: <%=ENV['PLATFORM'] || 'saltstack-ubuntu-xenial-salt-stable' %>
33 | driver_config:
34 | image: <%=ENV['PLATFORM'] || 'epcim/salt:saltstack-ubuntu-xenial-salt-stable'%>
35 | platform: ubuntu
36 |
37 |
38 | suites:
39 |
40 | - name: network
41 | provisioner:
42 | pillars-from-files:
43 | linux.sls: tests/pillar/network.sls
44 |
45 | #- name: storage
46 | #provisioner:
47 | #pillars-from-files:
48 | #linux.sls: tests/pillar/storage.sls
49 | #init_environment: |
50 | #sudo mkdir -p /tmp/node
51 | #sudo dd if=/dev/zero of=/tmp/loop_dev0 bs=1024 count=$((30*1024));
52 | #sudo dd if=/dev/zero of=/tmp/loop_dev1 bs=1024 count=$((30*1024));
53 | #sudo dd if=/dev/zero of=/tmp/loop_dev2 bs=1024 count=$((30*1024));
54 | #sudo dd if=/dev/zero of=/tmp/loop_dev3 bs=1024 count=$((30*1024));
55 | #sudo dd if=/dev/zero of=/tmp/loop_dev4 bs=1024 count=$((30*1024));
56 | #sudo mkfs.ext4 /tmp/loop_dev1
57 | #sudo mkswap /tmp/loop_dev2
58 | #sudo chown root /tmp/loop_dev*;
59 | #sudo chmod 0600 /tmp/loop_dev*;
60 |
61 | - name: system
62 | provisioner:
63 | pillars-from-files:
64 | linux.sls: tests/pillar/system.sls
65 |
66 | - name: system_file
67 | provisioner:
68 | pillars-from-files:
69 | linux.sls: tests/pillar/system_file.sls
70 | pillars_from_directories:
71 | - source: tests/example
72 | dest: srv/salt/linux/files/test
73 |
74 | - name: duo
75 | provisioner:
76 | pillars-from-files:
77 | linux.sls: tests/pillar/system_duo.sls
78 |
79 | # vim: ft=yaml sw=2 ts=2 sts=2 tw=125
80 |
--------------------------------------------------------------------------------
/linux/storage/lvm.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import storage with context %}
2 | {%- if storage.enabled %}
3 |
4 | linux_lvm_pkgs:
5 | pkg.installed:
6 | - pkgs: {{ storage.lvm_pkgs | json }}
7 |
8 |
9 | /etc/lvm/lvm.conf:
10 | file.managed:
11 | - source: salt://linux/files/lvm.conf
12 | - template: jinja
13 | - require:
14 | - pkg: linux_lvm_pkgs
15 |
16 | lvm_services:
17 | service.running:
18 | - enable: true
19 | - names: {{ storage.lvm_services }}
20 | - require:
21 | - file: /etc/lvm/lvm.conf
22 | - watch:
23 | - file: /etc/lvm/lvm.conf
24 |
25 | {%- for vgname, vg in storage.lvm.items() %}
26 |
27 | {%- if vg.get('enabled', True) %}
28 |
29 | {%- for dev in vg.devices %}
30 | lvm_{{ vg.get('name', vgname) }}_pv_{{ dev }}:
31 | lvm.pv_present:
32 | - name: {{ dev }}
33 | - require:
34 | - pkg: linux_lvm_pkgs
35 | - file: /etc/lvm/lvm.conf
36 | - service: lvm_services
37 | - require_in:
38 | - lvm: lvm_vg_{{ vg.get('name', vgname) }}
39 | {%- endfor %}
40 |
41 | lvm_vg_{{ vg.get('name', vgname) }}:
42 | lvm.vg_present:
43 | - name: {{ vg.get('name', vgname) }}
44 | - devices: {{ vg.devices|join(',') }}
45 |
46 | {%- for lvname, volume in vg.get('volume', {}).items() %}
47 |
48 | lvm_{{ vg.get('name', vgname) }}_lv_{{ volume.get('name', lvname) }}:
49 | lvm.lv_present:
50 | - order: 1
51 | - name: {{ volume.get('name', lvname) }}
52 | - vgname: {{ vg.get('name', vgname) }}
53 | - size: {{ volume.size }}
54 | {%- if (volume.force is defined and volume.force is sameas true) or
55 | (volume.get('name', lvname) not in grains.lvm[vg.get('name', vgname)]) %}
56 | - force: True
57 | {%- else %}
58 | - force: False
59 | {%- endif %}
60 | - require:
61 | - lvm: lvm_vg_{{ vg.get('name', vgname) }}
62 | {%- if (volume.mount is defined) and
63 | (volume.get('name', lvname) not in grains.lvm[vg.get('name', vgname)]) %}
64 | - require_in:
65 | - mount: {{ volume.mount.path }}
66 | {%- if not volume.mount.get('file_system', None) in ['nfs', 'nfs4', 'cifs', 'tmpfs', None] %}
67 | - cmd: mkfs_{{ volume.mount.device}}
68 | {%- endif %}
69 | {%- endif %}
70 |
71 | {%- endfor %}
72 |
73 | {%- endif %}
74 |
75 | {%- endfor %}
76 |
77 | {%- endif %}
78 |
--------------------------------------------------------------------------------
/linux/system/cron.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context %}
2 |
3 | {%- if system.cron.enabled is defined and system.cron.enabled %}
4 |
5 | cron_packages:
6 | pkg.installed:
7 | - names: {{ system.cron.pkgs }}
8 |
9 | cron_services:
10 | service.running:
11 | - enable: true
12 | - names: {{ system.cron.services }}
13 | - require:
14 | - pkg: cron_packages
15 | {%- if grains.get('noservices') %}
16 | - onlyif: /bin/false
17 | {%- endif %}
18 |
19 | {%- set allow_users = [] %}
20 | {%- for user_name, user_params in system.cron.get('user', {}).items() %}
21 | {%- set user_enabled = user_params.get('enabled', false) and
22 | system.get('user', {}).get(
23 | user_name, {'enabled': true}).get('enabled', true) %}
24 | {%- if user_enabled %}
25 | {%- do allow_users.append(user_name) %}
26 | {%- endif %}
27 | {%- endfor %}
28 |
29 | etc_cron_allow:
30 | {%- if allow_users %}
31 | file.managed:
32 | - name: /etc/cron.allow
33 | - template: jinja
34 | - source: salt://linux/files/cron_users.jinja
35 | - user: root
36 | - group: crontab
37 | - mode: 0640
38 | - defaults:
39 | users: {{ allow_users | yaml }}
40 | - require:
41 | - cron_packages
42 | {%- else %}
43 | file.absent:
44 | - name: /etc/cron.allow
45 | {%- endif %}
46 |
47 | {#
48 | /etc/cron.deny should be absent to comply with
49 | CIS 5.1.8 Ensure at/cron is restricted to authorized users
50 | #}
51 | etc_cron_deny:
52 | file.absent:
53 | - name: /etc/cron.deny
54 |
55 | etc_crontab:
56 | file.managed:
57 | - name: /etc/crontab
58 | - user: root
59 | - group: root
60 | - mode: 0600
61 | - replace: False
62 | - require:
63 | - cron_packages
64 |
65 | etc_cron_dirs:
66 | file.directory:
67 | - names:
68 | - /etc/cron.d
69 | - /etc/cron.daily
70 | - /etc/cron.hourly
71 | - /etc/cron.monthly
72 | - /etc/cron.weekly
73 | - user: root
74 | - group: root
75 | - dir_mode: 0600
76 | - recurse:
77 | - ignore_files
78 | - require:
79 | - cron_packages
80 |
81 | {%- else %}
82 |
83 | fake_linux_system_cron:
84 | test.nop:
85 | - comment: Fake state to satisfy 'require sls:linux.system.cron'
86 |
87 | {%- endif %}
88 |
--------------------------------------------------------------------------------
/linux/files/modprobe.conf.jinja:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import system with context -%}
2 | # This file is managed by Salt, do not edit.
3 | {%- set module_content = system.kernel.module.get(module_name) %}
4 | {%- if module_content.get('blacklist', false) %}
5 | blacklist {{ module_name }}
6 | {%- endif %}
7 | {%- for alias, params in module_content.get('alias', {}) | dictsort %}
8 | {%- if params.get('enabled', true) %}
9 | alias {{ alias }} {{ module_name }}
10 | {%- endif %}
11 | {%- endfor %}
12 | {%- set options = [] %}
13 | {%- for option, params in module_content.get('option', {}) | dictsort %}
14 | {%- if params is mapping %}
15 | {%- if params.get('enabled', true) and params.value is defined %}
16 | {%- do options.append(option ~ '=' ~ params.value) %}
17 | {%- endif %}
18 | {%- else %}
19 | {%- do options.append(option ~ '=' ~ params) %}
20 | {%- endif %}
21 | {%- endfor %}
22 | {%- if options | length > 0 %}
23 | options {{ module_name }} {{ options | join(' ')}}
24 | {%- endif %}
25 | {%- if module_content.install is defined %}
26 | {%- if module_content.install.get('enabled', true) and module_content.install.command is defined %}
27 | install {{ module_name }} {{ module_content.install.command }}
28 | {%- endif %}
29 | {%- endif %}
30 | {%- if module_content.remove is defined %}
31 | {%- if module_content.remove.get('enabled', true) and module_content.remove.command is defined %}
32 | remove {{ module_name }} {{ module_content.remove.command }}
33 | {%- endif %}
34 | {%- endif %}
35 | {%- if module_content.softdep is defined %}
36 | {%- set pre = [] %}
37 | {%- set post = [] %}
38 | {%- for pos, params in module_content.softdep.get('pre', {}) | dictsort %}
39 | {%- if params.get('enabled', true) and params.value is defined %}
40 | {%- do pre.append(params.value) %}
41 | {%- endif %}
42 | {%- endfor %}
43 | {%- for pos, params in module_content.softdep.get('post', {}) | dictsort %}
44 | {%- if params.get('enabled', true) and params.value is defined %}
45 | {%- do post.append(params.value) %}
46 | {%- endif %}
47 | {%- endfor %}
48 | {%- if pre | length + post | length > 0 %}
49 | softdep {{ module_name }}{% if pre | length > 0 %} pre: {{ pre | join(' ') }}{% endif %}{% if post | length > 0 %} post: {{ post | join(' ') }}{% endif %}
50 | {%- endif %}
51 | {%- endif %}
52 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-5-4-4.yml:
--------------------------------------------------------------------------------
1 | # CIS 5.4.4 Ensure default user umask is 027 or more restrictive (Scored)
2 | #
3 | # Description
4 | # ===========
5 | # The default umask determines the permissions of files created by users.
6 | # The user creating the file has the discretion of making their files and
7 | # directories readable by others via the chmod command. Users who wish to
8 | # allow their files and directories to be readable by others by default may
9 | # choose a different default umask by inserting the umask command into the
10 | # standard shell configuration files ( .profile , .bashrc , etc.) in their
11 | # home directories.
12 | #
13 | # Rationale
14 | # =========
15 | # Setting a very secure default value for umask ensures that users make a
16 | # conscious choice about their file permissions. A default umask setting of
17 | # 077 causes files and directories created by users to not be readable by
18 | # any other user on the system. A umask of 027 would make files and
19 | # directories readable by users in the same Unix group, while a umask of 022
20 | # would make files readable by every user on the system.
21 | #
22 | # Audit
23 | # =====
24 | # Run the following commands and verify all umask lines returned are 027 or
25 | # more restrictive.
26 | #
27 | # # grep "^umask" /etc/bash.bashrc
28 | # umask 027
29 | # # grep "^umask" /etc/profile
30 | # umask 027
31 | #
32 | # Remediation
33 | # ===========
34 | # Edit the /etc/bash.bashrc and /etc/profile files (and the appropriate files
35 | # for any other shell supported on your system) and add or edit any umask
36 | # parameters as follows:
37 | #
38 | # umask 027
39 | #
40 | # Notes
41 | # =====
42 | # The audit and remediation in this recommendation apply to bash and shell.
43 | # If other shells are supported on the system, it is recommended that their
44 | # configuration files also are checked.
45 | #
46 | # Other methods of setting a default user umask exist however the shell
47 | # configuration files are the last run and will override other settings if
48 | # they exist therefore our recommendation is to configure in the shell
49 | # configuration files. If other methods are in use in your environment they
50 | # should be audited and the shell configs should be verified to not override.
51 | #
52 | parameters:
53 | linux:
54 | system:
55 | shell:
56 | umask: "027"
57 |
58 |
--------------------------------------------------------------------------------
/metadata/service/system/cis/cis-3-2-1.yml:
--------------------------------------------------------------------------------
1 | # 3.2.1 Ensure source routed packets are not accepted
2 | #
3 | # Description
4 | # ===========
5 | # In networking, source routing allows a sender to partially or fully specify
6 | # the route packets take through a network. In contrast, non-source routed
7 | # packets travel a path determined by routers in the network. In some cases,
8 | # systems may not be routable or reachable from some locations (e.g. private
9 | # addresses vs. Internet routable), and so source routed packets would need
10 | # to be used.
11 | #
12 | # Rationale
13 | # =========
14 | # Setting `net.ipv4.conf.all.accept_source_route` and
15 | # `net.ipv4.conf.default.accept_source_route` to 0 disables the system from
16 | # accepting source routed packets. Assume this system was capable of routing
17 | # packets to Internet routable addresses on one interface and private addresses
18 | # on another interface. Assume that the private addresses were not routable to
19 | # the Internet routable addresses and vice versa. Under normal routing
20 | # circumstances, an attacker from the Internet routable addresses could not use
21 | # the system as a way to reach the private address systems. If, however, source
22 | # routed packets were allowed, they could be used to gain access to the private
23 | # address systems as the route could be specified, rather than rely on routing
24 | # protocols that did not allow this routing.
25 | #
26 | # Audit
27 | # =====
28 | #
29 | # Run the following commands and verify output matches:
30 | #
31 | # # sysctl net.ipv4.conf.all.accept_source_route
32 | # net.ipv4.conf.all.accept_source_route = 0
33 | # # sysctl net.ipv4.conf.default.accept_source_route
34 | # net.ipv4.conf.default.accept_source_route = 0
35 | #
36 | # Remediation
37 | # ===========
38 | #
39 | # Set the following parameters in the /etc/sysctl.conf file:
40 | #
41 | # net.ipv4.conf.all.accept_source_route = 0
42 | # net.ipv4.conf.default.accept_source_route = 0
43 | #
44 | # Run the following commands to set the active kernel parameters:
45 | #
46 | # # sysctl -w net.ipv4.conf.all.accept_source_route=0
47 | # # sysctl -w net.ipv4.conf.default.accept_source_route=0
48 | # # sysctl -w net.ipv4.route.flush=1
49 |
50 | parameters:
51 | linux:
52 | system:
53 | kernel:
54 | sysctl:
55 | net.ipv4.conf.all.accept_source_route: 0
56 | net.ipv4.conf.default.accept_source_route: 0
57 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | python:
3 | - "2.7.13"
4 | sudo: required
5 | services:
6 | - docker
7 |
8 | addons:
9 | apt:
10 | packages:
11 | - apt-transport-https
12 |
13 | install:
14 | - pip install PyYAML
15 | - pip install virtualenv
16 | - |
17 | test -e Gemfile || cat < Gemfile
18 | source 'https://rubygems.org'
19 | gem 'rake'
20 | gem 'test-kitchen'
21 | gem 'kitchen-docker'
22 | gem 'kitchen-inspec'
23 | gem 'inspec', '<3.0.0'
24 | #Version was frozen, because of issues in the version of inspec >3.0.0 -- see https://mirantis.jira.com/browse/PROD-24324 for more info
25 | gem 'kitchen-salt', :git => 'https://github.com/salt-formulas/kitchen-salt.git'
26 | - bundle install
27 |
28 | env:
29 | - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2017.7 SUITE=network
30 | - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2017.7 SUITE=system
31 | - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2018.3 SUITE=network
32 | - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2018.3 SUITE=system
33 | - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2018.3 SUITE=duo
34 | - PLATFORM=netmanagers/salt-2019.2-py3:ubuntu-18.04 SUITE=network
35 | # - PLATFORM=netmanagers/salt-2019.2-py3:ubuntu-18.04 SUITE=system
36 | # - PLATFORM=netmanagers/salt-2019.2-py3:ubuntu-18.04 SUITE=duo
37 | # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 SUITE=network
38 | # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 SUITE=system
39 | # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2018.3 SUITE=network
40 | # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2018.3 SUITE=system
41 | # - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2016.3 SUITE=system
42 | # - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2016.3 SUITE=network
43 | before_script:
44 | - set -o pipefail
45 | - make test | tail
46 |
47 | script:
48 | - test ! -e .kitchen.yml || bundle exec kitchen converge ${SUITE} || true
49 | - test ! -e .kitchen.yml || bundle exec kitchen verify ${SUITE} -t tests/integration
50 |
51 | notifications:
52 | webhooks:
53 | urls:
54 | - https://webhooks.gitter.im/e/6123573504759330786b
55 | on_success: change # options: [always|never|change] default: always
56 | on_failure: never # options: [always|never|change] default: always
57 | on_start: never # options: [always|never|change] default: always
58 | on_cancel: never # options: [always|never|change] default: always
59 | on_error: never # options: [always|never|change] default: always
60 | email: false
61 |
--------------------------------------------------------------------------------
/linux/files/pam-sshd:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import auth with context %}
2 |
3 | # PAM configuration for the Secure Shell service
4 |
5 | {%- if auth.duo.enabled %}
6 | auth required /lib64/security/pam_duo.so
7 | account required pam_nologin.so
8 |
9 | # Standard Un*x authentication.
10 | #@include common-auth
11 | {%- else %}
12 | # Standard Un*x authentication.
13 | @include common-auth
14 | {%- endif %}
15 |
16 | # Disallow non-root logins when /etc/nologin exists.
17 | account required pam_nologin.so
18 |
19 | # Uncomment and edit /etc/security/access.conf if you need to set complex
20 | # access limits that are hard to express in sshd_config.
21 | # account required pam_access.so
22 |
23 | # Standard Un*x authorization.
24 | @include common-account
25 |
26 | # SELinux needs to be the first session rule. This ensures that any
27 | # lingering context has been cleared. Without this it is possible that a
28 | # module could execute code in the wrong domain.
29 | session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
30 |
31 | # Set the loginuid process attribute.
32 | session required pam_loginuid.so
33 |
34 | # Create a new session keyring.
35 | session optional pam_keyinit.so force revoke
36 |
37 | # Standard Un*x session setup and teardown.
38 | @include common-session
39 |
40 | # Print the message of the day upon successful login.
41 | # This includes a dynamically generated part from /run/motd.dynamic
42 | # and a static (admin-editable) part from /etc/motd.
43 | session optional pam_motd.so motd=/run/motd.dynamic
44 | session optional pam_motd.so noupdate
45 |
46 | # Print the status of the user's mailbox upon successful login.
47 | session optional pam_mail.so standard noenv # [1]
48 |
49 | # Set up user limits from /etc/security/limits.conf.
50 | session required pam_limits.so
51 |
52 |
53 | # Read environment variables from /etc/environment and
54 | # /etc/security/pam_env.conf.
55 | session required pam_env.so # [1]
56 | # In Debian 4.0 (etch), locale-related environment variables were moved to
57 | # /etc/default/locale, so read that as well.
58 | session required pam_env.so user_readenv=1 envfile=/etc/default/locale
59 |
60 | # SELinux needs to intervene at login time to ensure that the process starts
61 | # in the proper default security context. Only sessions which are intended
62 | # to run in the user's context should be run after this.
63 | session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
64 |
65 | # Standard Un*x password updating.
66 | @include common-password
67 |
68 |
--------------------------------------------------------------------------------
/_states/ovs_config.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | '''
3 | Management of Open vSwitch configuration
4 | ========================================
5 |
6 | The OVS config can be managed with the ovs_config state module:
7 |
8 | .. code-block:: yaml
9 |
10 | other_config:dpdk-init:
11 | ovs_config.present:
12 | - value: True
13 |
14 | other_config:dpdk-extra:
15 | ovs_config.present:
16 | - value: -n 12 --vhost-owner libvirt-qemu:kvm --vhost-perm 0664
17 |
18 | external_ids:
19 | ovs_config.absent
20 | '''
21 |
22 |
23 | def __virtual__():
24 | '''
25 | Only make these states available if Open vSwitch is installed.
26 | '''
27 | return 'ovs_config.list' in __salt__
28 |
29 |
30 | def present(name, value, wait=True):
31 | '''
32 | Ensures that the named config exists, eventually creates it.
33 |
34 | Args:
35 | name/value: The name/value of the config entry.
36 | wait: Whether wait for ovs-vswitchd to reconfigure itself according to the modified database.
37 | '''
38 | ret = {'name': name, 'changes': {}, 'result': False, 'comment': ''}
39 | ovs_config = __salt__['ovs_config.list']()
40 |
41 | if name in ovs_config and ovs_config[name] == str(value).lower():
42 | ret['result'] = True
43 | ret['comment'] = '{0} is already set to {1}.'.format(name, value)
44 | else:
45 | config_updated = __salt__['ovs_config.set'](name, value, wait)
46 | if config_updated:
47 | ret['result'] = True
48 | ret['comment'] = '{0} is updated.'.format(name)
49 | ret['changes'] = { name: 'Updated to {0}'.format(value) }
50 | else:
51 | ret['result'] = False
52 | ret['comment'] = 'Unable to update config of {0}.'.format(name)
53 |
54 | return ret
55 |
56 |
57 | def absent(name):
58 | '''
59 | Ensures that the named config does not exist, eventually deletes it.
60 |
61 | Args:
62 | name: The name of the config entry.
63 |
64 | '''
65 | ret = {'name': name, 'changes': {}, 'result': False, 'comment': ''}
66 | ovs_config = __salt__['ovs_config.list']()
67 |
68 | if ':' in name and name not in ovs_config:
69 | ret['result'] = True
70 | ret['comment'] = '{0} does not exist.'.format(name)
71 | else:
72 | config_removed = __salt__['ovs_config.remove'](name)
73 | if config_removed:
74 | ret['result'] = True
75 | ret['comment'] = '{0} is removed.'.format(name)
76 | ret['changes'] = { name: '{0} removed'.format(name) }
77 | else:
78 | ret['result'] = False
79 | ret['comment'] = 'Unable to delete config of {0}.'.format(name)
80 |
81 | return ret
82 |
--------------------------------------------------------------------------------
/linux/meta/graphite.yml:
--------------------------------------------------------------------------------
1 | rewrite_rule:
2 | "\.cpu-idle\.value$": ".idle"
3 | "\.cpu-interrupt\.value$": ".interrupt"
4 | "\.cpu-nice\.value$": ".nice"
5 | "\.cpu-softirq\.value$": ".softirq"
6 | "\.cpu-steal\.value$": ".steal"
7 | "\.cpu-system\.value$": ".system"
8 | "\.cpu-user\.value$": ".user"
9 | "\.cpu-wait\.value$": ".wait"
10 | "\.cpu\.idle$": ".idle"
11 | "\.cpu\.interrupt$": ".interrupt"
12 | "\.cpu\.nice$": ".nice"
13 | "\.cpu\.softirq$": ".softirq"
14 | "\.cpu\.steal$": ".steal"
15 | "\.cpu\.system$": ".system"
16 | "\.cpu\.user$": ".user"
17 | "\.cpu\.wait$": ".wait"
18 | "\.cpu-idle$": ".idle"
19 | "\.cpu-interrupt$": ".interrupt"
20 | "\.cpu-nice$": ".nice"
21 | "\.cpu-softirq$": ".softirq"
22 | "\.cpu-steal$": ".steal"
23 | "\.cpu-system$": ".system"
24 | "\.cpu-user$": ".user"
25 | "\.cpu-wait$": ".wait"
26 | "\.cpu-": ".cpu."
27 | "\.df_complex-free\.value$": ".free"
28 | "\.df_complex-reserved\.value$": ".reserved"
29 | "\.df_complex-used\.value$": ".used"
30 |
31 | "\.df_complex-free$": ".free"
32 | "\.df_complex-reserved$": ".reserved"
33 | "\.df_complex-used$": ".used"
34 | "\.df_complex\.free$": ".free"
35 | "\.df_complex\.reserved$": ".reserved"
36 | "\.df_complex\.used$": ".used"
37 | "\.df-": ".partition."
38 | "\.df\.": ".partition."
39 |
40 | "\.disk_merged\.read$": ".merged_reads"
41 | "\.disk_merged\.write$": ".merged_writes"
42 | "\.disk_octets\.read$": ".read_octets"
43 | "\.disk_octets\.write$": ".write_octets"
44 | "\.disk_ops\.read$": ".read_ops"
45 | "\.disk_ops\.write$": ".write_ops"
46 | "\.disk_time\.read$": ".read_time"
47 | "\.disk_time\.write$": ".write_time"
48 | "\.disk-": ".disk."
49 |
50 | "\.entropy\.entropy\.value$": ".system.entropy"
51 | "\.entropy\.entropy$": ".system.entropy"
52 |
53 | "\.if_errors\.tx": ".tx_errors"
54 | "\.if_errors\.rx": ".rx_errors"
55 | "\.if_octets\.tx": ".tx_octets"
56 | "\.if_octets\.rx": ".rx_octets"
57 | "\.if_packets\.tx": ".tx_packets"
58 | "\.if_packets\.rx": ".rx_packets"
59 | "\.interface-": ".interface."
60 |
61 | "load\.load\.midterm$": "load.mid_term"
62 | "load\.load\.shortterm$": "load.short_term"
63 | "load\.load\.longterm$": "load.long_term"
64 |
65 | "memory\.memory-buffered\.value$": "memory.buffered"
66 | "memory\.memory-cached\.value$": "memory.cached"
67 | "memory\.memory-free\.value$": "memory.free"
68 | "memory\.memory-used\.value$": "memory.used"
69 | "memory\.memory\.buffered$": "memory.buffered"
70 | "memory\.memory\.cached$": "memory.cached"
71 | "memory\.memory\.free$": "memory.free"
72 | "memory\.memory\.used$": "memory.used"
73 | "memory\.memory-buffered$": "memory.buffered"
74 | "memory\.memory-cached$": "memory.cached"
75 | "memory\.memory-free$": "memory.free"
76 | "memory\.memory-used$": "memory.used"
77 |
--------------------------------------------------------------------------------
/linux/storage/swap.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import storage with context %}
2 | {%- if storage.enabled %}
3 |
4 | {%- if storage.swap.enabled is not defined or storage.swap.enabled %}
5 |
6 | {%- for swap_name, swap in storage.swap.items() %}
7 |
8 | {%- if swap.enabled %}
9 |
10 | {%- if swap.engine == 'partition' %}
11 |
12 | linux_create_swap_partition_{{ swap.device }}:
13 | cmd.run:
14 | - name: 'mkswap {{ swap.device }}'
15 | - unless: file -L -s {{ swap.device }} | grep -q 'swap file'
16 |
17 | linux_set_swap_partition_{{ swap.device }}:
18 | cmd.run:
19 | - name: 'swapon {{ swap.device }}'
20 | - unless: grep $(readlink -f {{ swap.device }}) /proc/swaps
21 | - require:
22 | - cmd: linux_create_swap_partition_{{ swap.device }}
23 |
24 | {{ swap.device }}:
25 | mount.swap:
26 | - persist: True
27 | - require:
28 | - cmd: linux_set_swap_partition_{{ swap.device }}
29 |
30 | {%- elif swap.engine == 'file' %}
31 |
32 | linux_create_swap_file_{{ swap.device }}:
33 | cmd.run:
34 | - name: 'dd if=/dev/zero of={{ swap.device }} bs=1048576 count={{ swap.size }} && chmod 0600 {{ swap.device }}'
35 | - creates: {{ swap.device }}
36 |
37 | linux_set_swap_file_{{ swap.device }}:
38 | cmd.wait:
39 | - name: 'mkswap {{ swap.device }}'
40 | - watch:
41 | - cmd: linux_create_swap_file_{{ swap.device }}
42 |
43 | linux_set_swap_file_status_{{ swap.device }}:
44 | cmd.run:
45 | - name: 'swapon {{ swap.device }}'
46 | - unless: grep {{ swap.device }} /proc/swaps
47 | - require:
48 | - cmd: linux_set_swap_file_{{ swap.device }}
49 |
50 | {{ swap.device }}:
51 | mount.swap:
52 | - persist: True
53 | - require:
54 | - cmd: linux_set_swap_file_{{ swap.device }}
55 |
56 | {%- endif %}
57 |
58 | {%- else %}
59 |
60 | {{ swap.device }}:
61 | module.run:
62 | {%- if 'module.run' in salt['config.get']('use_superseded', default=[]) %}
63 | - mount.rm_fstab:
64 | - m_name: none
65 | - device: {{ swap.device }}
66 | {%- else %}
67 | - name: mount.rm_fstab
68 | - m_name: none
69 | - device: {{ swap.device }}
70 | {%- endif %}
71 | - onlyif: grep -q {{ swap.device }} /etc/fstab
72 |
73 | linux_disable_swap_{{ swap.engine }}_{{ swap.device }}:
74 | cmd.run:
75 | {%- if swap.engine == 'partition' %}
76 | - name: 'swapoff {{ swap.device }}'
77 | {%- elif swap.engine == 'file' %}
78 | - name: 'swapoff {{ swap.device }} && rm -f {{ swap.device }}'
79 | {%- endif %}
80 | - onlyif: file -L -s {{ swap.device }} | grep -q 'swap file'
81 |
82 | {%- endif %}
83 |
84 | {%- endfor %}
85 |
86 | {%- elif storage.swap.enabled is defined and not storage.swap.enabled %}
87 |
88 | linux_disable_swap:
89 | cmd.run:
90 | - name: 'swapoff -a'
91 |
92 | {%- endif %}
93 |
94 | {%- endif %}
95 |
--------------------------------------------------------------------------------
/linux/network/host.sls:
--------------------------------------------------------------------------------
1 | {%- from "linux/map.jinja" import network with context %}
2 | {%- if network.enabled %}
3 |
4 | {%- set host_dict = network.host %}
5 |
6 | {%- if network.mine_dns_records %}
7 |
8 | {%- for node_name, node_grains in salt['mine.get']('*', 'grains.items').items() %}
9 | {%- if node_grains.get('dns_records', []) is iterable %}
10 | {%- for record in node_grains.get('dns_records', []) %}
11 | {%- set record_key = node_name ~ '-' ~ loop.index %}
12 | {%- do host_dict.update({ record_key: {'address': record.address, 'names': record.names} }) %}
13 | {%- endfor %}
14 | {%- endif %}
15 | {%- endfor %}
16 |
17 | {%- endif %}
18 |
19 | {%- if network.get('purge_hosts', false) %}
20 |
21 | linux_hosts:
22 | file.managed:
23 | - name: /etc/hosts
24 | - source: salt://linux/files/hosts
25 | - template: jinja
26 | - defaults:
27 | host_dict: {{ host_dict|yaml }}
28 |
29 | {%- else %}
30 |
31 | {%- for name, host in host_dict.items() %}
32 |
33 | {%- if host.names is defined %}
34 |
35 | {%- set clearers = [] %}
36 | {%- for etc_addr, etc_names in salt.hosts.list_hosts().items() %}
37 | {%- set names_to_clear = [] %}
38 | {%- for host_name in host.names %}
39 | {%- if (host.address != etc_addr) and host_name in etc_names %}
40 | {%- do names_to_clear.append(host_name) %}
41 | {%- endif %}
42 | {%- endfor %}
43 | {%- if names_to_clear != [] %}
44 | {%- set clearer = "linux_host_" + name + "_" + etc_addr + "_clear" %}
45 | {%- do clearers.append(clearer) %}
46 |
47 | {{ clearer }}:
48 | host.absent:
49 | - ip: {{ etc_addr }}
50 | - names: {{ names_to_clear }}
51 |
52 | {%- endif %}
53 | {%- endfor %}
54 |
55 | linux_host_{{ name }}:
56 | host.present:
57 | - ip: {{ host.address }}
58 | - names: {{ host.names }}
59 | - require: {{ clearers }}
60 |
61 | {%- if host.address in grains.ipv4 and host.names|length > 1 %}
62 |
63 | {%- if host.names.1 in host.names.0 %}
64 | {%- set before = host.names.1 + " " + host.names.0 %}
65 | {%- set after = host.names.0 + " " + host.names.1 %}
66 | {%- elif host.names.0 in host.names.1 %}
67 | {%- set before = host.names.0 + " " + host.names.1 %}
68 | {%- set after = host.names.1 + " " + host.names.0 %}
69 | {%- endif %}
70 |
71 | linux_host_{{ name }}_order_fix:
72 | module.run:
73 | {%- if 'module.run' in salt['config.get']('use_superseded', default=[]) %}
74 | - file.replace:
75 | - path: /etc/hosts
76 | - pattern: {{ before }}
77 | - repl: {{ after }}
78 | {%- else %}
79 | - name: file.replace
80 | - path: /etc/hosts
81 | - pattern: {{ before }}
82 | - repl: {{ after }}
83 | {%- endif %}
84 | - watch:
85 | - host: linux_host_{{ name }}
86 | - onlyif:
87 | - grep -q "{{ before }}" /etc/hosts
88 |
89 | {%- endif %}
90 |
91 | {%- endif %}
92 |
93 | {%- endfor %}
94 |
95 | {%- endif %}
96 |
97 | {%- endif %}
98 |
--------------------------------------------------------------------------------
/_modules/ovs_config.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | '''
3 | Support for Open vSwitch database configuration.
4 |
5 | '''
6 | from __future__ import absolute_import
7 |
8 | import logging
9 | import salt.utils.path
10 |
11 | log = logging.getLogger(__name__)
12 |
13 |
14 | def __virtual__():
15 | '''
16 | Only load the module if Open vSwitch is installed
17 | '''
18 | if salt.utils.path.which('ovs-vsctl'):
19 | return 'ovs_config'
20 | return False
21 |
22 |
23 | def _retcode_to_bool(retcode):
24 | '''
25 | Evaluates ovs-vsctl command`s retcode value.
26 |
27 | Args:
28 | retcode: Value of retcode field from response.
29 | '''
30 | return True if retcode == 0 else False
31 |
32 |
33 | def set(cfg, value, wait=True):
34 | '''
35 | Updates a specified configuration entry.
36 |
37 | Args:
38 | cfg/value: a config entry to update
39 | wait: wait or not for ovs-vswitchd to reconfigure itself before it exits.
40 |
41 | CLI Example:
42 | .. code-block:: bash
43 |
44 | salt '*' ovs_config.set other_config:dpdk-init true
45 | '''
46 | wait = '' if wait else '--no-wait '
47 |
48 | cmd = 'ovs-vsctl {0}set Open_vSwitch . {1}="{2}"'.format(wait, cfg, str(value).lower())
49 | result = __salt__['cmd.run_all'](cmd)
50 | return _retcode_to_bool(result['retcode'])
51 |
52 |
53 | def remove(cfg):
54 | '''
55 | Removes a specified configuration entry.
56 |
57 | Args:
58 | cfg: a config entry to remove
59 |
60 | CLI Example:
61 | .. code-block:: bash
62 |
63 | salt '*' ovs_config.remove other_config
64 | '''
65 | if ':' in cfg:
66 | section, key = cfg.split(':')
67 | cmd = 'ovs-vsctl remove Open_vSwitch . {} {}'.format(section, key)
68 | else:
69 | cmd = 'ovs-vsctl clear Open_vSwitch . ' + cfg
70 |
71 | result = __salt__['cmd.run_all'](cmd)
72 | return _retcode_to_bool(result['retcode'])
73 |
74 |
75 | def list():
76 | '''
77 | Return a current config of Open vSwitch
78 |
79 | CLI Example:
80 |
81 | .. code-block:: bash
82 |
83 | salt '*' ovs_config.list
84 | '''
85 | cmd = 'ovs-vsctl list Open_vSwitch .'
86 | result = __salt__['cmd.run_all'](cmd)
87 |
88 | if result['retcode'] == 0:
89 | config = {}
90 | for l in result['stdout'].splitlines():
91 | cfg, value = map((lambda x: x.strip()), l.split(' : '))
92 | if value.startswith('{') and len(value) > 2:
93 | for i in value[1:-1].replace('"', '').split(', '):
94 | _k, _v = i.split('=')
95 | config['{}:{}'.format(cfg,_k)] = _v
96 | else:
97 | config[cfg] = value
98 |
99 | return config
100 | else:
101 | return False
102 |
--------------------------------------------------------------------------------