原则
- 尽可能避免在虚机内修改cloudinit/cloudbase-init代码,因为nova侧更加可控,也避免因用户升级回滚掉修改部分
- 尽可能避免用户可以从虚拟机内部获取密码,封堵提权漏洞
方案
启动时
启动时将用户设置/随机生成的密码作为matadata中的admin_pass传入,生效方案同冷修改
热修改
利用qga进行修改,如果qga通讯失败虚机进入error状态,发起工单处理
处理人员见到这个状态后,提示用户进行关机改密码(热更改密码失败,需进行关机修改)
冷修改
植入脚本从metadata中获取admin_pass,利用系统命令修改密码,并给169.254.169.254/openstack/latest/password回一个POST请求
nova收到POST请求后在数据库中将admin_pass条目删除(https://172.18.211.200:8081/gerrit/#/c/591/1)
linux版本脚本,放入/var/lib/cloud/scripts/per-boot,随cloudinit的script_per_boot加载运行
#! /usr/bin/python import os import json import urllib data = urllib.urlopen("http://169.254.169.254/openstack/latest/meta_data.json").read() json_data = json.loads(data) meta = json_data.get("meta") if meta: adminPass = meta.get("admin_pass") if adminPass: os.system("echo 'root:%s' | chpasswd" % adminPass) params = urllib.urlencode({"delete":True}) f = urllib.urlopen("http://169.254.169.254/openstack/latest/password", params) f.read()
windows版本放在cloudbase-init的localscript中,被cloudbase-init加载运行
#! /usr/bin/python import os import sys import json from urllib.request import urlopen from urllib.parse import urlencode try: data = urlopen("http://169.254.169.254/openstack/latest/meta_data.json").read() json_data = json.loads(data.decode('utf-8')) meta = json_data.get("meta") if meta: adminPass = meta.get("admin_pass") if adminPass: print("Get") os.system("net user Administrator /active:yes") os.system("net user Administrator %s" % adminPass) print("Set") params = urlencode({"delete":True}).encode('utf-8') f = urlopen("http://169.254.169.254/openstack/latest/password", params) f.read() print("Post") except Exception as e: print(e) finally: sys.exit(1002)
为什么返回1002?为避免LocalScriptsPlugin将状态设置为PLUGIN_EXECUTION_DONE
兜底方案
evacuate或挂盘
修改密码异常场景
qemu-guest-agent
虚拟机中qemu-guest-agent未正常启动
- HTTP状态码:409
-
返回json格式,其中message为"QEMU guest agent is not connected"
-
{ "conflictingRequest": { "message": "QEMU guest agent is not connected", "code": 409 } }
windows中的内部错误
- HTTP状态码:409
-
返回json格式,其中message格式为"Failed to set admin password on {虚拟机uuid} because internal error: unable to execute QEMU agent command 'guest-set-user-password': failed to set password: {windows返回的错误原因}"
-
{ "conflictingRequest": { "message": "Failed to set admin password on eb3168c2-2b64-470e-ac4c-1bb5c39b4627 because internal error: unable to execute QEMU agent command 'guest-set-user-password': failed to set password: 密码不满足密码策略的要求。检查最小密码长度、密码复杂性和密码历史的要求。", "code": 409 } }