由于我们有海外业务,于是就要接受GDPR检查,在检查里有一项就是要求不可以在/etc/sudoers
文件里配置普通用户 ALL=(root) NOPASSWD:ALL
这一项,要根据实际需要缩小范围,于是就要用ansible-playbook去批量修改这个问题。
获取AWS的外网IP
AWS的EC2控制台跟阿里云不一样,不提供一个类似excel表格来获取当前区域内所有云服务器的资料。于是只能通过API获取,不过好在AWS的python SDK比较简单。
首先先pip install boto3
和pip install awscli
。然后再命令行执行aws configure
,分别输入自己的AK、SK以及其他资料如下:
1
2
3
4AWS Access Key ID [None]: 你的AK
AWS Secret Access Key [None]: 你的SK
Default region name [None]: 对应区域 详情可见:https://docs.aws.amazon.com/general/latest/gr/rande.html
Default output format [None]: json #建议选择json
然后就会在/root/.aws
(普通用户就会在/homt/用户名/)下看到config
和credentials
,这里面就是你刚刚输入的内容。
获取所有running状态的ec2的内网IP地址的脚本如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import boto3
def main():
ec2 = boto3.resource('ec2')
instances = ec2.instances.filter(
Filters=[{'Name': 'instance-state-name', 'Values': ['running']}]
)
for instance in instances:
print(instance.private_ip_address) # 获取内网IP地址
print(instance.public_ip_address) # 获取公网IP地址
print(instance.tags) #服务器名称
if __name__ == '__main__':
main()
简单的一匹。
编写play-book
获取到了该区域所有的服务器内网IP之后,先在vim状态下使用:g/^172./d
,把老网段的服务器(172开头)的IP过滤掉。然后编写playbook,如下:
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- hosts: all #默认执行hosts里的所有IP
remote_user: root
any_errors_fatal: no
gather_facts: no #不采集对方机器的数据,提高执行速度
serial:
- 5 #5台机器一组
tasks:
- name: judge NOPASSWD:ALL
shell: grep "zabbix ALL=(root) NOPASSWD" /etc/sudoers
ignore_errors: True
register: result
- name: change
lineinfile:
dest: /etc/sudoers
state: present
regexp: '^zabbix '
line: 'zabbix ALL=(root) NOPASSWD: /usr/bin/python'
when: result.stdout.find("NOPASSWD:ALL") != -1
- name: del
lineinfile:
dest: /etc/sudoers
state: absent
regexp: 'NOPASSWD:ALL$' # 将所有NOPASSWD:ALL结尾的字段删除
这里有一点要注意,如果使用shell去用sed -i
写的话,那么面临一个很尬的境地:ansible-playbook对冒号空格
的搭配默认会识别成key:value
的形式。
比如说,在shell里使用sed -i 's/NOPASSWD:ALL/NOPASSWD: \/usr\/bin\/python/g' /etc/sudoers
是OK的,但是在shell就会爆格式错误,然后执意要走shell的话,就会可能掉入嵌套地狱…
如果想要在文件后追加多行
ansible里的lineinfile
模块是常见的修改文件内容的模块,但是如果要在文件末尾追加多行内容,一般人可能会想到使用with_items
搭配lineinfile
做循环。其实在ansible 2+的版本有一个更加优雅的方法:blockinfile
,写法如下:
1
2
3
4
5
6
7
8
9tasks:
- name: addApollo
blockinfile: |
dest=/tmp/chenprofile #目标文件
backup=yes
content="export public_cloud_config_host=apollo.imou.com
export public_cloud_config_port=28080
export public_cloud_config_group=default
export public_cloud_config_namespace=imou.commonsource.mysql,imou.commonsource.cs,imou.commonsource.redis,imou.commonsource.mq,imou.commonsource.lb,imou.saascommonconfig,imou.originalcommonconfig,application"
然后去对应的文件就能看到结果,但是要注意,这里使用等号,而不是冒号,用冒号会报错,可能是ansible的一个小bug。
补充
- 如果发现本机已经安装了
awscli
,但是爆错aws: command not found
,检查一下python的virtualenv
环境是否正确; - 如果目标机器不在默认的
inventory
文件里被设置,可以通过加逗号的方式被ansible识别,比如ansible all -i 172.16.1.7, -m ping
; - 如果playbook想指定其他
inventory
文件,使用-i参数;