使用Ansible Galaxy实现安全无忧的自动化部署
作者:Jordan Drysdale
发布时间:2016年7月11日
注意: 本博文中引用的技术和工具可能已过时,不适用于当前情况。然而,这篇博文仍可作为学习机会,并可能更新或集成到现代工具和技术中。
作为一名“蓝队成员”,工作往往充满压力。在具有强大Linux基础设施的环境中工作可能会有所帮助,但Ansible可以极大地提升效率。在所有环境中,无论操作系统如何,我们都需要确保系统的远程访问安全。Ansible Galaxy充满了有趣的角色,可以让蓝队成员的生活更轻松。通过Ansible Galaxy,我们可以利用几个角色快速、有效地保护Linux服务器,并且易于复制。
在保护远程访问时,基于密钥的SSH和有时使用的双因素认证(2FA)可以提供额外的安全层。此外,很难想象放弃防御而“裸奔”,因此防火墙是标准要求。为什么不加入fail2ban来防御通过iptables攻击开放服务的尝试?我非常喜欢这种服务组合。🙂 “哦,你尝试了三次通过HTTPS进行认证?fail2ban,请暂时封锁这个IP。谢谢,好的。”最后但同样重要的是,让我们将所有内容转储到logstash中,在Kibana中进行Geo-IP映射以实现出色的可视化,最终可以安心休息。
首先,检查我们的Ansible版本:
1
2
3
|
ansible@tw17ch01:/etc/ansible/roles/sshd$ dpkg -l |grep ansible
ii ansible 2.1.0.0-1ppa~trusty all
一个极其简单的IT自动化平台
|
接下来,安装、配置和部署SSHd,使用一个包含所有可能变量的Galaxy角色。我们将添加角色,进行一些更改,然后构建一个playbook来部署新角色。链接在此 – https://galaxy.ansible.com/mattwillsher/sshd/
Ansible服务器魔法:
1
2
3
4
5
6
7
8
9
10
|
ansible@tw17ch01:/etc/ansible/playbooks$ sudo ansible-galaxy install mattwillsher.sshd
[sudo]
password for ansible:
– downloading role 'sshd', owned by mattwillsher
– downloading role from https://github.com/willshersystems/ansible-sshd/archive/v0.4.4.tar.gz
– extracting mattwillsher.sshd to /etc/ansible/roles/mattwillsher.sshd
– mattwillsher.sshd was installed successfully
ansible@tw17ch01:/etc/ansible/playbooks$ sudo mv mattwillsher.sshd/sshd/
|
Galaxy角色大部分在其“角色目录”中创建标准结构,如果不存在,
1
2
3
4
5
|
ansible@tw17ch01:/etc/ansible/roles/sshd$ ls
defaults handlers meta tasks tests vars
ansible@tw17ch01:/etc/ansible/roles$ sudo nano sshd/vars/Ubuntu_14.yml
|
*强烈建议修改默认端口,完全禁用root登录,并添加一行PasswordAuthentication no。确保修改的文件适用于部署角色的操作系统。
接下来,安装、配置和部署防火墙以阻止所有内容。链接在此 – https://galaxy.ansible.com/geerlingguy/firewall/
1
2
3
4
5
6
7
8
9
10
|
ansible@tw17ch01:/etc/ansible/roles$ sudo ansible-galaxy install geerlingguy.firewall
[sudo]
password for ansible:
– downloading role 'firewall', owned by geerlingguy
– downloading role from https://github.com/geerlingguy/ansible-role-firewall/archive/1.0.9.tar.gz
– extracting geerlingguy.firewall to /etc/ansible/roles/geerlingguy.firewall
– geerlingguy.firewall was installed successfully
ansible@tw17ch01:/etc/ansible/roles$ sudo mv geerlingguy.firewall/ chains/
|
让我们做一些编辑。
1
|
ansible@tw17ch01:/etc/ansible/roles$ sudo nano chains/defaults/main.yml
|
防火墙修改比sshd角色内置的复杂性更容易理解。我的系统只需要上述列出的SSH端口和HTTPS。对chains角色的另一个修改:
1
|
ansible@tw17ch01:/etc/ansible/roles$ sudo nano chains/templates/firewall.bash.j2
|
我添加了以下规则,因为我现在不关心来自DO droplet的出站流量。
1
2
3
|
# 允许所有出站流量 -
# 您可以/应该修改此规则以仅允许特定流量!
iptables -A OUTPUT -j ACCEPT
|
chains角色应该准备好了。
接下来,安装、配置和部署fail2ban以保护服务。链接在此 – https://galaxy.ansible.com/tersmitten/fail2ban/
1
2
3
4
5
6
7
|
ansible@tw17ch01:/etc/ansible/roles$ sudo ansible-galaxy install tersmitten.fail2ban
- downloading role 'fail2ban', owned by tersmitten
- downloading role from https://github.com/Oefenweb/ansible-fail2ban/archive/v1.5.0.tar.gz
- extracting tersmitten.fail2ban to /etc/ansible/roles/tersmitten.fail2ban
- tersmitten.fail2ban was installed successfully
ansible@tw17ch01:/etc/ansible/roles$ sudo mv tersmitten.fail2ban/ banner/
|
让我们做一些编辑
1
|
ansible@tw17ch01:/etc/ansible/roles$ sudo nano banner/defaults/main.yml
|
我必须对我的sshd服务配置进行一些更改,以反映使用非标准端口的情况。我还添加了HTTPS的服务配置。在查看目录结构的其余部分后,这个角色也准备好了。
最后,安装、配置和部署filebeat以将日志文件发送到有用的目的地。链接在此 – https://galaxy.ansible.com/jpnewman/elk-filebeat/
1
2
3
4
5
6
7
|
ansible@tw17ch01:/etc/ansible/roles$ sudo ansible-galaxy install jpnewman.elk-filebeat
- downloading role 'elk-filebeat', owned by jpnewman
- downloading role from https://github.com/jpnewman/ansible-role-elk-filebeat/archive/master.tar.gz
- extracting jpnewman.elk-filebeat to /etc/ansible/roles/jpnewman.elk-filebeat
- jpnewman.elk-filebeat was installed successfully
ansible@tw17ch01:/etc/ansible/roles$ sudo mv jpnewman.elk-filebeat/ logger/
|
最后,让我们设置TLS日志传输,以便在现有ELK堆栈中进行未来勘探。这假设已经完成了一系列工作:
- 完全可操作的ELK堆栈
- 为logstash部署的TLS/PKI基础设施和证书可通过logger角色部署
- 网络防火墙上的logstash端口转发
- 可选的redis集群处理大量日志处理
1
|
ansible@tw17ch01:/etc/ansible/roles$ sudo nano logger/defaults/main.yml
|
在这里,我修改了elastic和logstash主机以指向基础设施目的地。还记得我们之前讨论过的相当标准的目录结构吗?是的,将您的logstash-forward.crt文件复制到../roles/logger/files/certs/中,playbook智能将交付。我们又准备好了。让我们开始并检查一些事情以确保一切正常。
1
2
3
4
|
ansible@tw17ch01:/etc/ansible/roles$ ls
banner chains logger sshd ### 所有角色都存在
gt; vi ../ansible/hosts #将新主机添加到您的ansible hosts文件中
gt; ansible dropper ping -m 12.34.56.78 | SUCCESS => { "changed": false, "ping": "pong" } ansible@tw17ch01:/etc/ansible/roles$ sudo nano ../playbooks/NewDrop.yml ### 角色很棒。投入时间。 - hosts: all become: yes roles: # 部署标准SSH配置 - { role: sshd } # 安装iptables - { role: chains } # 添加filebeat - { role: logger } # 部署和配置fail2ban - { role: banner }
|
此部署的手动部分在此处发生。SSH到新的droplet并创建一个sudo用户。是的,这可以自动化,我们将在另一天以另一种方式写关于此的内容。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
ssh root@NewDropIP
useradd ansible -m -s /bin/bash
passwd ansible
UNIX Pass:
UNIX Pass:
su - ansible
mkdir .ssh
touch .ssh/authorized_keys
echo "ssh-rsa AAAAB3N <KEY REDACTED> IClTJ1E1 ansible@tw17ch01" >> .ssh/authorized_keys
exit
visudo ## 添加 ansible ALL=(ALL:ALL) ALL
ansible@tw17ch01:/etc/ansible$ sudo nano hosts ### 添加 [dropper] 和 NewDropIP
ansible@tw17ch01:/etc/ansible$
ansible@tw17ch01:/etc/ansible$ ansible-playbook playbooks/NewDrop.yml -l dropper -u ansible -K
SUDO password:
PLAY [all] *********************************************************************
TASK [setup] *******************************************************************
The authenticity of host '12.34.56.78 (12.34.56.78)' can't be established.
ECDSA key fingerprint is 5f:<redacted>:1f.
Are you sure you want to continue connecting (yes/no)? yes
Enter passphrase for key '/home/ansible/.ssh/id_rsa':
ok: [12.34.56.78]
TASK [sshd : Set OS dependent variables] ***************************************
ok: [12.34.56.78] => (item=/etc/ansible/roles/sshd/vars/Ubuntu_14.yml)
TASK [sshd : OS is supported] **************************************************
ok: [12.34.56.78]
TASK [sshd : Installed] ********************************************************
ok: [12.34.56.78] => (item=[u'openssh-server', u'openssh-sftp-server'])
TASK [sshd : Run directory] ****************************************************
ok: [12.34.56.78]
TASK [sshd : Configuration] ****************************************************
changed: [12.34.56.78]
TASK [sshd : Service enabled and running] **************************************
ok: [12.34.56.78]
TASK [sshd : Register that this role has run] **********************************
ok: [12.34.56.78]
TASK [chains : Ensure iptables is installed (RedHat).] *************************
skipping: [12.34.56.78]
TASK [chains : Ensure iptables is installed (Debian).] *************************
ok: [12.34.56.78]
TASK [chains : Flush iptables the first time playbook runs.] *******************
changed: [12.34.56.78]
TASK [chains : Copy firewall script into place.] *******************************
changed: [12.34.56.78]
TASK [chains : Copy firewall init script into place.] **************************
changed: [12.34.56.78]
TASK [chains : Ensure the firewall is enabled and will start on boot.] *********
changed: [12.34.56.78]
TASK [logger : Create directory to store ssl crt] ******************************
changed: [12.34.56.78]
TASK [logger : Copy SSL cert] **************************************************
changed: [12.34.56.78]
TASK [logger : Install Filebeat dependencies] **********************************
ok: [12.34.56.78]
TASK [logger : Check if Filebeat is already at the right version] **************
changed: [12.34.56.78]
TASK [logger : Download Filebeat agent] ****************************************
changed: [12.34.56.78]
TASK [logger : Install Filebeat agent] *****************************************
changed: [12.34.56.78]
TASK [logger : Create directory for Filebeat Configures] ***********************
changed: [12.34.56.78]
TASK [logger : Create directory for Filebeat Configures] ***********************
changed: [12.34.56.78]
TASK [logger : Configure Filebeat] *********************************************
changed: [12.34.56.78]
TASK [logger : Configure Filebeat prospectors] *********************************
[DEPRECATION WARNING]: Using bare variables is deprecated. Update your playbooks ### 需要清理此playbook
so that the environment value uses the full variable syntax
('{{prospectors}}').
This feature will be removed in a future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
changed: [12.34.56.78] => (item={u'paths': [{u'log_paths': [u'/var/log/syslog', u'/var/log/auth.log'], u'document_type': u'syslog'}], u'type': u'syslog', u'id': u'syslog'})
changed: [12.34.56.78] => (item={u'paths': [{u'log_paths': [u'/var/log/*.log'], u'document_type': u'log', u'exclude_files': [u'^syslog
|
太棒了!我们刚刚推出了解决我(或大多数管理员)担心的几乎所有问题的解决方案。让我们通过SSH查看一下,确保没有出现问题,并验证一切正常。
SSH:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
ansible@tw17ch03:~$ cat /etc/ssh/sshd_config
# ansible managed: /etc/ansible/roles/sshd/templates/sshd_config.j2 modified on 2016-04-16 12:32:30 by root on tw17ch01
Port 22444
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
AcceptEnv LANG LC_*
ChallengeResponseAuthentication no
HostbasedAuthentication no
IgnoreRhosts yes
KeyRegenerationInterval 3600
LogLevel INFO
LoginGraceTime 120
PasswordAuthentication no
[...............]
X11Forwarding yes
|
iptables:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
ansible@tw17ch03:~$ sudo iptables -L
[sudo]
password for tendans:
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all — anywhere anywhere
ACCEPT tcp — anywhere anywhere tcp dpt:22444
ACCEPT tcp — anywhere anywhere tcp dpt:https
ACCEPT icmp — anywhere anywhere
ACCEPT udp — anywhere anywhere udp spt:ntp
ACCEPT all — anywhere anywhere state RELATED,ESTABLISHED
LOG all — anywhere anywhere limit: avg 15/min burst 5 LOG level debug prefix “Dropped by firewall: ”
DROP all — anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all — anywhere anywhere
ACCEPT udp — anywhere anywhere udp dpt:ntp
|
FileBeat:
1
2
3
4
5
6
|
ansible@tw17ch03:~$ cat /etc/filebeat/filebeat.yml
################### Filebeat Configuration Example #########################
############################# Filebeat ######################################
filebeat:
# List of prospectors to fetch data.
|
Fail2Ban:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
tendans@tw17ch03:~$ cat /etc/fail2ban/jail.local
# ansible managed: /etc/ansible/roles/banner/templates/etc/fail2ban/jail.local.j2 modified on 2016-05-30 05:57:15 by root on tw17ch01
[……]
[ssh]
enabled = true
port = 22444
filter = sshd
logpath = /var/log/auth.log
maxretry = 6
findtime = 600
[https]
enabled = true
port = https
filter = https
logpath = /var/log/auth.log
maxretry = 6
findtime = 600
|
就是这样,全部完成了。Playbook看起来很好,所有角色都按预期部署。配置文件已更新,SSH允许我们远程访问。哦,对了,这里有一个Kibana可视化,显示了通过FileBeat打包日志传输的远程连接的源Geo-IP映射,并向一位未具名的同事致敬,干杯!