softasap.sa_box_bootstap
使用示例:
简单的
roles:
- {
role: "sa-box-bootstrap",
deploy_user: "{{jenkins_user}}",
deploy_user_authorized_keys: "{{jenkins_authorized_keys}}",
timezone: "Europe/Kiev"
}
高级
vars:
- root_dir: ..
- jenkins_user: jenkins
jenkins_authorized_keys:
- "{{playbook_dir}}/components/files/ssh/vyacheslav1.pub"
- "{{playbook_dir}}/components/files/ssh/vyacheslav2.pub"
- "{{playbook_dir}}/components/files/ssh/vyacheslav3.pub"
- "{{playbook_dir}}/components/files/ssh/vyacheslav4.pub"
- timezone: "Europe/Kiev"
pre_tasks:
- debug: msg="预处理任务部分"
roles:
- {
role: "sa-box-bootstrap",
deploy_user: "{{jenkins_user}}",
deploy_user_key: "{{playbook_dir}}/components/files/ssh/jenkins_rsa",
deploy_user_pub_key: "{{playbook_dir}}/components/files/ssh/jenkins_rsa.pub",
deploy_user_authorized_keys: "{{jenkins_authorized_keys}}",
timezone: "Europe/Kiev",
option_copy_initial_authorized_keys: true,
option_enforce_ssh_keys_login: true,
option_file2ban: true,
option_firewall: true,
option_monit: true
}
重要提示:如果您不指定 deploy_user_sudo_password
参数,则创建的部署用户将可以无需密码确认执行 sudo。虽然在某些情况下这样可以,但增加额外的安全级别永远是好的,因此:
请求 sudo 密码的部署用户
vars:
- user_authorized_keys:
- "~/.ssh/id_rsa.pub"
- user_sudo_pass: "secret"
roles:
- {
role: "sa-box-bootstrap",
deploy_user: "slavko",
deploy_user_authorized_keys: "{{user_authorized_keys}}",
deploy_user_sudo_password: "{{user_sudo_pass | password_hash('sha512')}}",
option_enforce_ssh_keys_login: yes
}
如果您有需要输入 sudo 密码的部署用户,则需要通过 ansible_become_password
参数提供该密码。
注册
$BOX_PLAYBOOK
$BOX_NAME
$BOX_ADDRESS
$BOX_USER
$BOX_PWD
详细程度 4
设置 box_address $BOX_ADDRESS
设置 ansible_become_password secret
配置 $BOX_NAME
准备您的盒子以进行部署
背景
如今,部署从裸金属服务器转向迅速启动的虚拟机,例如亚马逊、Digital Ocean 和基于 OpenStack 的提供商提供的虚拟机。因此,盒子的配置不再需要手动管理步骤。可用的选项之一是使用预先配置好的盒子镜像。另外一种方法是从初始系统重启开始,并根据项目需求使用一些配置工具(如 Ansible、Chef 或 Puppet)进行配置。
进行自定义配置的第一步是进行基本的盒子安全设置,因为在某些情况下会得到一个带有 root 密码的全新安装盒子。
让我与您分享关于初始盒子安全设置的快速方案,这应该适用于大多数网络部署。
需要解决的挑战
在文章的最后,我们应该能够为 Ubuntu 14.04 LTS 虚拟服务器提供安全设置。
- 配置防火墙,仅允许 22、443 和 80 端口。
- 为部署用户注册您的公钥。
- 加固 SSH,仅允许通过密钥进行授权。
- 设置自动化进程,禁止互联网上那些试图猜测您的 SSH 用户访问的人员。
引导盒子角色
Ansible 提供一个很好的重用部署片段的概念,称为角色。所以让我们来看看 sa-box-bootstrap 角色的功能:
配置选项
以下变量可以被重写:
- root_dir - 必需,Ansible 开发者食谱 仓库
- option_enforce_ssh_keys_login (true|false) - 是否强制执行 SSH 安全
- ufw_rules_default - 默认防火墙策略。在大多数情况下保持不变
- ufw_rules_allow - 一组要配置的入站规则
- sshd_config_lines - SSHD 配置中需要的更改以保障盒子安全。
- option_file2ban - 如果为 true,将额外引入 file2ban 包
- whitelistedips - 被视为安全的 IP 地址集合 - 您的办公室网关、构建服务器等;用于防止您被意外地阻止。
第一步:启用防火墙
第一步是安装和配置 ufw 防火墙:
- include: "{{root_dir}}/tasks_ufw.yml"
默认情况下,适用以下防火墙规则(允许任何外发请求以及内部 HTTP、HTTPS 和 SSH):
ufw_rules_default:
- {
policy: deny,
direction: incoming
}
- {
policy: allow,
direction: outgoing
}
ufw_rules_allow:
- {
port: 80,
proto: tcp
}
- {
port: 443,
proto: tcp
}
- {
port: 22,
proto: tcp
}
您可以重写这些变量以符合您的需求。
第二步:创建部署用户
如果您打算在此盒子上工作和进行配置,您很可能不希望以 root 身份进行操作。因此,第二步是创建一个部署用户,由提供的 SSH 密钥集授权,并可以在没有密码的情况下成为 sudo 用户(自动配置的基本要求)。
- include: "{{root_dir}}/use/__create_deploy_user.yml user={{deploy_user}} group={{deploy_user}} home=/home/{{deploy_user}}"
when: deploy_user is defined
- name: SSH | 授权密钥
authorized_key: user={{deploy_user}} key="{{ lookup('file', item) }}"
when: deploy_user_keys is defined
with_items: "{{deploy_user_keys}}"
sudo: yes
您可以在 playbook 中定义用户,例如:
jenkins_user: jenkins
jenkins_authorized_keys:
- "{{playbook_dir}}/components/files/ssh/vyacheslav.pub"
然后将其作为参数传递给角色:
roles:
- {
role: "sa-box-bootstrap",
root_dir: "{{playbook_dir}}/public/ansible_developer_recipes",
deploy_user: "{{jenkins_user}}",
deploy_user_keys: "{{jenkins_authorized_keys}}"
}
第三步:加固 SSH(可选)
- name: SSH | 强制 SSH 密钥安全
lineinfile: dest=/etc/ssh/sshd_config regexp="{{item.regexp}}" line="{{item.line}}"
with_items: "{{sshd_config_lines}}"
when: option_enforce_ssh_keys_login
become: true
tags: ssh
如果变量 option_enforce_ssh_keys_login 被设置为 true,则 sshd 配置将根据 sshd_config_lines 规则进行修改。默认情况下,使用 v2 协议,禁止 root 登录和密码认证。
第四步:禁止那些试图猜测您 SSH 用户访问的可疑人员
如果变量 option_file2ban 被设置为 true,将安装特殊工具 file2ban。它将监视失败的 SSH 登录尝试并禁止入侵者。为了防止意外被封锁,良好的做法是将您的 IP 地址放入白名单,单个 IP 和网络掩码都支持,例如:
whitelistedips:
- 127.0.0.1
- 127.0.0.1/8
创建您自己的盒子引导项目
让我们准备一个基本的引导项目,以便将来使用。它包括以下文件:
- bootstrap.sh - 安装 ansible 及其依赖项。
- init.sh - 初始化
- .projmodules - 完全兼容 .gitmodules 的 git 语法,指定将被 playbook 使用的依赖项列表。特别是,它包括 ansible - 默认开发者食谱(包含一组方便的部署食谱的仓库)以及名为 sa-box-bootstrap 的 ansible 角色,负责盒子的安全步骤。
[submodule "public/ansible_developer_recipes"]
path = public/ansible_developer_recipes
url = [email protected]: Voronenko/ansible-developer_recipes.git
[submodule "roles/sa-box-bootstrap"]
path = roles/sa-box-bootstrap
url = [email protected]: softasap/sa-box-bootstrap.git
- hosts - 在这里列出提供给您的初始盒子凭据。
[bootstrap]
box_bootstrap ansible_ssh_host=192.168.0.17 ansible_ssh_user=your_user ansible_ssh_pass=your_password
- box_vars.yml - 在这里设置特定环境的重写,如您首选的部署用户名和密钥。
- box_bootstrap.yml - 在这里安排您的盒子配置步骤。盒子安全设置只是第一步。为了重写 sa-box-bootstrap 的参数,请像下面的示例那样传递参数。
- hosts: all
vars_files:
- ./box_vars.yml
roles:
- {
role: "sa-box-bootstrap",
root_dir: "{{playbook_dir}}/public/ansible_developer_recipes",
deploy_user: "{{my_deploy_user}}",
deploy_user_keys: "{{my_deploy_authorized_keys}}"
}
代码运行
您可以从仓库下载代码 https://github.com/Voronenko/devops-bootstrap-box-template。要使用它,您可以将其分支,调整参数以满足您的需求,然后使用。调整内容包括创建 box_vars.yml 文件。您可以在这里重写任何提到的变量。最低需要的设置是 deploy_user 和您的公钥。
box_deploy_user: jenkins
box_deploy_authorized_keys:
- "{{playbook_dir}}/components/files/ssh/vyacheslav.pub"
确保您安装了 ansible(使用 bootstrap.sh 安装)并克隆了角色目录(使用 init.sh)。然后运行 setup.sh。如果一切配置正确,您将看到类似于以下内容:
PLAY [all] ********************************************************************
收集事实 ***************************************************************
ok: [box_bootstrap]
任务: [sa-box-bootstrap | 正确设置主机名] ****************************
changed: [box_bootstrap]
任务: [sa-box-bootstrap | debug var="ufw_rules_allow"] ************************
ok: [box_bootstrap] => {
"var": {
"ufw_rules_allow": [
{
"port": 80,
"proto": "tcp"
},
{
"port": 443,
"proto": "tcp"
},
{
"port": 22,
"proto": "tcp"
}
]
}
}
任务: [sa-box-bootstrap | UFW | 重置] *************************************
ok: [box_bootstrap]
任务: [sa-box-bootstrap | UFW | 配置入站/出站默认值] *********
ok: [box_bootstrap] => (item={'policy': 'deny', 'direction': 'incoming'})
ok: [box_bootstrap] => (item={'policy': 'allow', 'direction': 'outgoing'})
任务: [sa-box-bootstrap | UFW | 配置允许入站流量的规则] ****
ok: [box_bootstrap] => (item={'port': 80, 'proto': 'tcp'})
ok: [box_bootstrap] => (item={'port': 443, 'proto': 'tcp'})
ok: [box_bootstrap] => (item={'port': 22, 'proto': 'tcp'})
任务: [sa-box-bootstrap | UFW | 配置来自特定主机的入站流量的规则] ***
skipping: [box_bootstrap] => (item=ufw_rules_allow_from_hosts)
任务: [sa-box-bootstrap | UFW | 启用防火墙] ************************************
changed: [box_bootstrap]
任务: [sa-box-bootstrap | Monit | 检查是否已安装] **********************
changed: [box_bootstrap]
任务: [sa-box-bootstrap | Monit | libssl-dev 依赖项] **********************
changed: [box_bootstrap]
任务: [sa-box-bootstrap | Monit | 下载] ***********************************
changed: [box_bootstrap]
任务: [sa-box-bootstrap | Monit | 安装] ************************************
changed: [box_bootstrap]
任务: [sa-box-bootstrap | debug msg="创建部署用户 {{my_deploy_user}}:{{my_deploy_user}} 的主目录为 /home/{{my_deploy_user}}"] ***
ok: [box_bootstrap] => {
"msg": "创建部署用户 jenkins:jenkins 的主目录为 /home/jenkins"
}
任务: [sa-box-bootstrap | 部署用户 | 创建组] ***********************
changed: [box_bootstrap]
任务: [sa-box-bootstrap | 部署用户 | 创建用户] ************************
changed: [box_bootstrap]
任务: [sa-box-bootstrap | 部署用户 | 检查密钥是否存在] *******************
ok: [box_bootstrap]
任务: [sa-box-bootstrap | 部署用户 | 从 {{ansible_user_id}} 复制 authorized_keys] ***
skipping: [box_bootstrap]
任务: [sa-box-bootstrap | 部署用户 | 设置 authorized_keys 权限] ****
skipping: [box_bootstrap]
任务: [sa-box-bootstrap | 部署用户 | 确保 sudoers 不提示密码] ****
changed: [box_bootstrap]
任务: [sa-box-bootstrap | SSH | 授权密钥] *******************************
changed: [box_bootstrap] => (item=/home/slavko/labs/devops-bootstrap-box-template/components/files/ssh/vyacheslav.pub)
任务: [sa-box-bootstrap | SSH | 强制 SSH 密钥安全] ********************
ok: [box_bootstrap] => (item={'regexp': '^Protocol.*', 'line': 'Protocol 2'})
changed: [box_bootstrap] => (item={'regexp': '^PermitRootLogin.*', 'line': 'PermitRootLogin no'})
ok: [box_bootstrap] => (item={'regexp': '^RSAAuthentication.*', 'line': 'RSAAuthentication yes'})
ok: [box_bootstrap] => (item={'regexp': '^PubkeyAuthentication.*', 'line': 'PubkeyAuthentication yes'})
ok: [box_bootstrap] => (item={'regexp': '^ChallengeResponseAuthentication.*', 'line': 'ChallengeResponseAuthentication no'})
changed: [box_bootstrap] => (item={'regexp': '^PasswordAuthentication.*', 'line': 'PasswordAuthentication no'})
changed: [box_bootstrap] => (item={'regexp': '^MaxAuthTries.*', 'line': 'MaxAuthTries 3'})
任务: [sa-box-bootstrap | SSH | 重启 SSHD] *********************************
changed: [box_bootstrap]
任务: [sa-box-bootstrap | 安装基础 Ubuntu 包] ***********************
changed: [box_bootstrap] => (item=unzip,mc)
PLAY 结果 ********************************************************************
box_bootstrap : ok=21 changed=13 unreachable=0 failed=0
最后 - 您得到了一个安全的盒子,拥有您指定的 sudo 权限的部署用户,仅允许通过您设置的密钥进行授权。根用户无法登录。根据您的规则,仅允许某些入站端口。
用 NMap 检查并尝试登录:
ssh 192.168.0.17
权限被拒绝 (publickey)。
ssh -ldeploy_user 192.168.0.17
欢迎来到 Ubuntu 14.04.2 LTS (GNU/Linux 3.13.0-32-generic x86_64)
deploy_user@LABBOX17:~$
关注点
您可以重用这个 playbook 来创建自己的盒子引导项目,并重用该角色以更快地以安全的方式配置您的环境。