角色功能說明:
- 該角色實現對客戶端主機的安全加固和規避以及回滾功能
角色部署:
- 創建目錄結構,創建軟連接,關聯默認變量文件
WorkDir=~/devops/ansible/os_init && cd ${WorkDir}
RoleName=security_reinforce
mkdir -pv roles/${RoleName}/{defaults,files,handlers,meta,tasks,templates,vars}
ln -s ${WorkDir}/defaults_var.yml roles/${RoleName}/defaults/main.yml
- 配置系統密碼加固模版文件
cat >roles/${RoleName}/templates/login.defs_centos6.j2<<EOF
MAIL_DIR /var/spool/mail
PASS_MAX_DAYS 90
PASS_MIN_DAYS 7
PASS_MIN_LEN 8
PASS_WARN_AGE 30
UID_MIN 500
UID_MAX 60000
GID_MIN 500
GID_MAX 60000
CREATE_HOME yes
UMASK 077
USERGROUPS_ENAB yes
ENCRYPT_METHOD SHA512
EOF
cat >roles/${RoleName}/templates/login.defs_centos7.j2<<EOF
MAIL_DIR /var/spool/mail
PASS_MAX_DAYS 90
PASS_MIN_DAYS 7
PASS_MIN_LEN 8
PASS_WARN_AGE 30
UID_MIN 1000
UID_MAX 60000
SYS_UID_MIN 201
SYS_UID_MAX 999
GID_MIN 1000
GID_MAX 60000
SYS_GID_MIN 201
SYS_GID_MAX 999
CREATE_HOME yes
UMASK 077
USERGROUPS_ENAB yes
ENCRYPT_METHOD SHA512
EOF
- 配置系統密碼pam加固模版文件
cat >roles/${RoleName}/templates/system-auth-ac_centos6.j2<<EOF
auth required pam_env.so
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 500 quiet
auth required pam_deny.so
account required pam_unix.so
account sufficient pam_localuser.so
account sufficient pam_succeed_if.so uid < 500 quiet
account required pam_permit.so
password requisite pam_cracklib.so minlen=8 dcredit=-1 ucredit=-1 ocredit=-1 lcredit=-1 enforce_for_root try_first_pass retry=3 type=
password required pam_pwhistory.so use_authtok remember=3 enforce_for_root
password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password required pam_deny.so
session optional pam_keyinit.so revoke
session required pam_limits.so
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session required pam_unix.so
EOF
cat >roles/${RoleName}/templates/system-auth-ac_centos7.j2<<EOF
auth required pam_env.so
auth required pam_faildelay.so delay=2000000
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 1000 quiet_success
auth required pam_deny.so
account required pam_unix.so
account sufficient pam_localuser.so
account sufficient pam_succeed_if.so uid < 1000 quiet
account required pam_permit.so
password requisite pam_pwquality.so minlen=8 dcredit=-1 ucredit=-1 ocredit=-1 lcredit=-1 enforce_for_root try_first_pass local_users_only retry=3 authtok_type=
password required pam_pwhistory.so use_authtok remember=3 enforce_for_root
password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password required pam_deny.so
session optional pam_keyinit.so revoke
session required pam_limits.so
-session optional pam_systemd.so
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session required pam_unix.so
EOF
- 配置sshd pam加固模版文件
cat >roles/${RoleName}/templates/sshd_centos6.j2<<EOF
auth required pam_tally2.so even_deny_root deny=4 unlock_time=120 root_unlock_time=600
auth required pam_sepermit.so
auth include password-auth
account required pam_nologin.so
account include password-auth
password include password-auth
session required pam_selinux.so close
session required pam_loginuid.so
session required pam_selinux.so open env_params
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include password-auth
EOF
cat >roles/${RoleName}/templates/sshd_centos7.j2<<EOF
auth required pam_tally2.so even_deny_root deny=4 unlock_time=120 root_unlock_time=600
auth required pam_sepermit.so
auth substack password-auth
auth include postlogin
-auth optional pam_reauthorize.so prepare
account required pam_nologin.so
account include password-auth
password include password-auth
session required pam_selinux.so close
session required pam_loginuid.so
session required pam_selinux.so open env_params
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include password-auth
session include postlogin
-session optional pam_reauthorize.so prepare
EOF
- 配置su pam加固模版文件
cat >roles/${RoleName}/templates/su_centos6.j2<<EOF
auth sufficient pam_rootok.so
auth required pam_wheel.so use_uid
auth include system-auth
account sufficient pam_succeed_if.so uid = 0 use_uid quiet
account include system-auth
password include system-auth
session include system-auth
session optional pam_xauth.so
EOF
cat >roles/${RoleName}/templates/su_centos7.j2<<EOF
auth sufficient pam_rootok.so
auth required pam_wheel.so use_uid
auth substack system-auth
auth include postlogin
account sufficient pam_succeed_if.so uid = 0 use_uid quiet
account include system-auth
password include system-auth
session include system-auth
session include postlogin
session optional pam_xauth.so
EOF
- 創建系統密碼規避策略腳本
cat >roles/${RoleName}/files/userPass.sh<<EOF
#!/bin/bash
source ~/.bash_profile
ChangeDateStr=\$(date +%F)
ExpireDateStr=\$(date -d'90 days' +%F)
for user in \$(grep bash /etc/passwd|awk -F':' '{print \$1}')
do chage -d \${ChangeDateStr} -E \${ExpireDateStr} \${user};done
EOF
- 創建角色任務
cat >roles/${RoleName}/tasks/main.yml<<\EOF
---
- name: "系統用戶密碼加固"
template:
src: login.defs_centos{{ ansible_distribution_major_version }}.j2
dest: /etc/login.defs
backup: yes
force: yes
owner: root
group: root
mode: 0644
- name: "已存在系統用戶密碼加固"
shell:
"for user in $(grep bash /etc/passwd|awk -F':' '{print $1}'); \
do chage -m 7 -M 90 -W 30 -d $(date +%F) -E $(date -d'90 days' +%F) ${user};done"
- name: "分發系統用戶密碼加固腳本"
copy:
src: userPass.sh
dest: /root/checkOS
owner: root
group: root
mode: 0644
- name: "部署系統用戶密碼加固規避任務"
cron:
name: "userPass"
job: "/bin/bash /root/checkOS/userPass.sh"
minute: "0"
- name: "系統用戶密碼pam加固"
template:
src: system-auth-ac_centos{{ ansible_distribution_major_version }}.j2
dest: /etc/pam.d/system-auth-ac
backup: yes
force: yes
owner: root
group: root
mode: 0644
- name: "sshd 防暴力破解pam加固"
template:
src: sshd_centos{{ ansible_distribution_major_version }}.j2
dest: /etc/pam.d/sshd
backup: yes
force: yes
owner: root
group: root
mode: 0644
- name: "創建sudoler用戶"
user:
name: sudoler
createhome: yes
groups: wheel
- name: "分發ssh公鑰到sudoler用戶"
authorized_key:
user: sudoler
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
state: present
- name: "限制su pam加固"
template:
src: su_centos{{ ansible_distribution_major_version }}.j2
dest: /etc/pam.d/su
backup: yes
force: yes
owner: root
group: root
mode: 0644
- name: "限制root ssh登陸"
lineinfile:
path: /etc/ssh/sshd_config
regexp: "^PermitRootLogin"
line: "PermitRootLogin no"
- name: "關閉最後一次ssh登陸信息打印"
lineinfile:
path: /etc/ssh/sshd_config
regexp: "^PrintLastLog"
line: "PrintLastLog no"
- name: "打開ssh登陸後的公告信息"
lineinfile:
path: /etc/ssh/sshd_config
regexp: "^PrintMotd"
line: "PrintMotd yes"
- name: "配置公告信息內容"
copy:
dest: /etc/motd
content: "##################################################\n\
#\t{{ target_hostname_prefix }}-{{ ansible_ssh_host }} 登陸成功\n\
##################################################\n"
- name: "重啓sshd服務生效加固項"
service:
name: sshd
state: restarted
- name: "會話超時自動退出"
lineinfile:
path: /etc/profile
line: "export TMOUT=180"
- name: "關閉命令歷史記錄"
lineinfile:
path: /etc/profile
regexp: "^HISTSIZE"
line: "HISTSIZE=0"
- name: "不迴應ping命令"
lineinfile:
path: /etc/sysctl.conf
regexp: "^net.ipv4.icmp_echo_ignore_all"
line: "net.ipv4.icmp_echo_ignore_all = 1"
- name: "執行命令使配置生效"
shell:
"source /etc/profile && sysctl -p"
EOF
- 創建任務playbook並執行
cat >os-init-6.1-${RoleName}-root-setupAll.yml<<EOF
---
- hosts: all
remote_user: root
gather_facts: true
become: no
roles:
- ${RoleName}
EOF
ansible-playbook -i inventory/hosts os-init-6.1-${RoleName}-root-setupAll.yml
重要功能補充:
- 加固項中最爲關鍵的是root ssh遠程登陸限制,該項加固回滾策略爲:
ansible all -i inventory/hosts -u sudoler -b --become-method=su --become-user=root \
-m lineinfile -a "path=/etc/ssh/sshd_config regexp='^PermitRootLogin' line='PermitRootLogin yes'" -K
ansible all -i inventory/hosts -u sudoler -b --become-method=su --become-user=root \
-m service -a "name=sshd state=restarted" -K
-
注意:安全加固後,sudoler用戶只能通過ssh免密登陸,無法通過密碼登陸
-
技巧:可以使用-e傳入密碼來代替-K操作實現非交互
ansible all -i inventory/hosts -u sudoler -b --become-method=su --become-user=root -e 'ansible_become_pass'="vincent" \
-m lineinfile -a "path=/etc/ssh/sshd_config regexp='^PermitRootLogin' line='PermitRootLogin yes'"
ansible all -i inventory/hosts -u sudoler -b --become-method=su --become-user=root -e 'ansible_become_pass'="vincent" \
-m service -a "name=sshd state=restarted"
- 執行過安全加固後,root用戶ssh登陸被限制,需要修改os-init.yml後才能再次執行
- 如果是第一次執行,則不能使用sudoler作爲執行用戶,因爲安全加固之前沒有該用戶
cat >os-init-6.2-${RoleName}-sudoler-resetupAll.yml<<EOF
---
- hosts: all
remote_user: sudoler
gather_facts: true
become: yes
become_user: root
become_method: su
roles:
- ${RoleName}
EOF
ansible-playbook -i inventory/hosts os-init-6.2-${RoleName}-sudoler-resetupAll.yml
- 以playbook的方式回滾掉root遠程登陸限制:
cat >os-init-6.3-${RoleName}-sudoler-rollbackRootssh.yml<<EOF
---
- hosts: all
remote_user: sudoler
gather_facts: false
become: yes
become_user: root
become_method: su
tasks:
- name: "剔除sshd配置"
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^PermitRootLogin'
line: 'PermitRootLogin yes'
- name: "重啓sshd服務"
service:
name: sshd
state: restarted
EOF
ansible-playbook -i inventory/hosts -e 'ansible_become_pass'="vincent" os-init-6.3-${RoleName}-sudoler-rollbackRootssh.yml
- 重新設置root遠程登陸限制:
cat >os-init-6.4-${RoleName}-sudoler-resetupRootssh.yml<<EOF
---
- hosts: all
remote_user: sudoler
gather_facts: false
become: yes
become_user: root
become_method: su
tasks:
- name: "添加sshd配置"
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^PermitRootLogin'
line: 'PermitRootLogin no'
- name: "重啓sshd服務"
service:
name: sshd
state: restarted
EOF
ansible-playbook -i inventory/hosts -e 'ansible_become_pass'="vincent" os-init-6.4-${RoleName}-sudoler-resetupRootssh.yml
TOC