Skip to content

Commit

Permalink
feat: Unix系统下支持无免密sudo权限账号安装agent (closed TencentBlueKing#1675)
Browse files Browse the repository at this point in the history
  • Loading branch information
chalice-1831 committed Sep 3, 2024
1 parent a5e8332 commit c8f1429
Show file tree
Hide file tree
Showing 15 changed files with 455 additions and 159 deletions.
16 changes: 12 additions & 4 deletions apps/backend/agent/solution_maker.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,12 @@ def get_run_cmd_base_params(self) -> typing.List[str]:
f"-s {self.pipeline_id}",
]

if self.host_ap.is_use_sudo:
run_dir = f'GSE_AGENT_RUN_DIR={self.agent_config["run_path"]}'
data_dir = f'GSE_AGENT_DATA_DIR={self.agent_config["data_path"]}'
log_dir = f'GSE_AGENT_LOG_DIR={self.agent_config["log_path"]}'
run_cmd_params.append(f"-v {run_dir} {data_dir} {log_dir}")

# 系统开启使用密码注册 Windows 服务时,需额外传入 -U -P 参数,用于注册 Windows 服务,详见 setup_agent.bat 脚本
if self.need_encrypted_password():
# GSE 密码注册场景暂不启用国密,使用固定 RSA 的方式
Expand Down Expand Up @@ -304,7 +310,7 @@ def get_run_cmd_base_params(self) -> typing.List[str]:

return list(filter(None, run_cmd_params))

def add_sudo_to_cmds(self, execution_solution: ExecutionSolution):
def add_sudo_to_cmds(self, execution_solution: ExecutionSolution, is_use_sudo: bool = True):
# 非 Windows 机器使用 sudo 权限执行命令
# PAgent 依赖 setup_pagent.py 添加 sudo
# Windows Cygwin sudo command not found:Cygwin 本身通过 administrator 启动,无需 sudo
Expand All @@ -317,15 +323,16 @@ def add_sudo_to_cmds(self, execution_solution: ExecutionSolution):
):
return

sudo_cmd: str = "sudo " if is_use_sudo else ""
for execution_solution_step in execution_solution.steps:
if execution_solution_step.type != constants.CommonExecutionSolutionStepType.COMMANDS.value:
continue
for execution_solution_content in execution_solution_step.contents:
if execution_solution_content.name == "run_cmd":
shell_pkg: str = ("bash", "ksh")[self.host.os_type == constants.OsType.AIX]
execution_solution_content.text = f'sudo {shell_pkg} -c "{execution_solution_content.text}"'
execution_solution_content.text = f'{sudo_cmd}{shell_pkg} -c "{execution_solution_content.text}"'
else:
execution_solution_content.text = f"sudo {execution_solution_content.text}"
execution_solution_content.text = f"{sudo_cmd}{execution_solution_content.text}"

def combine_cmd_step(self, execution_solution: ExecutionSolution):
for execution_solution_step in execution_solution.steps:
Expand Down Expand Up @@ -533,7 +540,8 @@ def make(self) -> ExecutionSolution:
execution_solution: ExecutionSolution = self._make()
if self.is_combine_cmd_step:
self.combine_cmd_step(execution_solution)
self.add_sudo_to_cmds(execution_solution)

self.add_sudo_to_cmds(execution_solution, self.host_ap.is_superuser)
return execution_solution


Expand Down
16 changes: 16 additions & 0 deletions apps/backend/components/collections/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,22 @@ def request_single_job_and_create_map(
account_alias = (settings.BACKEND_UNIX_ACCOUNT, settings.BACKEND_WINDOWS_ACCOUNT)[
os_type == constants.OsType.WINDOWS
]

account_set: set = ()
for host in job_params["target_server"][host_interaction_from]:
if host_interaction_from == "host_id_list":
account = models.Host.objects.get(bk_host_id=host).identity.account
account_set.add(account)

if host_interaction_from == "ip_list":
account = models.Host.objects.get(inner_ip=host["ip"]).identity.account
account_set.add(account)

if len(account_set) > 1:
raise AppBaseException(_("目标机器账户不一致,请检查"))

account_alias = account_set.pop()

script_language = (constants.ScriptLanguageType.SHELL.value, constants.ScriptLanguageType.BAT.value)[
os_type == constants.OsType.WINDOWS
]
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/components/collections/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1204,7 +1204,7 @@ def _execute(self, data, parent_data, common_data: PluginCommonData):
"proc_name": package_control.process_name or plugin.name,
"setup_path": process_status.setup_path,
"pid_path": process_status.pid_path,
"user": constants.ACCOUNT_MAP.get(host.os_type, "root"),
"user": host.identity.account,
},
"control": gse_control,
"resource": host_id__resource_policy_map[bk_host_id]["resource"],
Expand Down
18 changes: 18 additions & 0 deletions apps/node_man/migrations/0083_accesspoint_is_use_sudo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.4 on 2024-08-26 08:39

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("node_man", "0082_host_dept_name"),
]

operations = [
migrations.AddField(
model_name="accesspoint",
name="is_use_sudo",
field=models.BooleanField(default=True, verbose_name="是否使用sudo"),
),
]
1 change: 1 addition & 0 deletions apps/node_man/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,7 @@ class AccessPoint(models.Model):
proxy_package = JSONField(_("Proxy上的安装包"), default=list)
outer_callback_url = models.CharField(_("节点管理外网回调地址"), max_length=128, blank=True, null=True, default="")
callback_url = models.CharField(_("节点管理内网回调地址"), max_length=128, blank=True, null=True, default="")
is_use_sudo = models.BooleanField(_("是否使用sudo"), default=True)

@property
def file_endpoint_info(self) -> EndpointInfo:
Expand Down
2 changes: 2 additions & 0 deletions apps/node_man/serializers/ap.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class ListSerializer(serializers.ModelSerializer):
is_default = serializers.BooleanField(label=_("是否默认接入点,不可删除"))
proxy_package = serializers.JSONField(label=_("Proxy上的安装包"))
file_cache_dirs = serializers.SerializerMethodField(label=_("文件缓存目录"))
is_use_sudo = serializers.BooleanField(label=_("是否使用sudo"))

def to_representation(self, instance):
ret = super(ListSerializer, self).to_representation(instance)
Expand Down Expand Up @@ -117,6 +118,7 @@ class ZKSerializer(serializers.Serializer):
bscp_config = serializers.DictField(_("BSCP配置"), required=False)
outer_callback_url = serializers.CharField(label=_("节点管理外网回调地址"), required=False, allow_blank=True)
callback_url = serializers.CharField(label=_("节点管理内网回调地址"), required=False, allow_blank=True)
is_use_sudo = serializers.BooleanField(label=_("是否使用sudo"), required=False, default=True)

def validate(self, data):
gse_version_list: List[str] = list(set(AccessPoint.objects.values_list("gse_version", flat=True)))
Expand Down
23 changes: 20 additions & 3 deletions script_tools/agent_tools/agent2/setup_agent.sh
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ validate_setup_path () {
/sys
/sbin
/root
/home
)

local invalid_path=(
Expand Down Expand Up @@ -314,6 +313,10 @@ check_heathz_by_gse () {
}

remove_crontab () {
if [ $IS_SUPER == false ]; then
return
fi

local tmpcron
tmpcron=$(mktemp "$TMP_DIR"/cron.XXXXXXX)

Expand All @@ -327,6 +330,10 @@ remove_crontab () {
}

setup_startup_scripts () {
if [ $IS_SUPER == false ]; then
return
fi

check_rc_file
local rcfile=$RC_LOCAL_FILE

Expand Down Expand Up @@ -475,7 +482,10 @@ remove_agent () {

log remove_agent - "trying to remove old agent directory(${AGENT_SETUP_PATH}/${AGENT_CLEAN_UP_DIRS[@]})"
cd "${AGENT_SETUP_PATH}" || return 0
for file in `lsattr -R |egrep "i-" |awk '{print $NF}'`;do echo "--- $file" && chattr -i $file ;done

if [ $IS_SUPER == true ]; then
for file in `lsattr -R |egrep "i-" |awk '{print $NF}'`;do echo "--- $file" && chattr -i $file ;done
fi
cd -

if [[ "$REMOVE" == "TRUE" ]]; then
Expand Down Expand Up @@ -686,7 +696,7 @@ _OO_
}

validate_vars_string () {
echo "$1" | grep -Pq '^[a-zA-Z_][a-zA-Z0-9]+='
echo "$1" | grep -Pq '^[a-zA-Z_][a-zA-Z0-9_]*='
}

check_pkgtool () {
Expand Down Expand Up @@ -886,6 +896,13 @@ while getopts n:t:I:i:l:s:uc:r:x:p:e:a:k:N:v:oT:RDO:E:A:V:B:S:Z:K:F arg; do
esac
done

IS_SUPER=true
if sudo -n true 2>/dev/null; then
IS_SUPER=true
else
IS_SUPER=false
fi

## 检查自定义环境变量
for var_name in ${VARS_LIST//;/ /}; do
validate_vars_string "$var_name" || fail "$var_name is not a valid name"
Expand Down
22 changes: 19 additions & 3 deletions script_tools/agent_tools/agent2/setup_agent.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ validate_setup_path () {
/sys
/sbin
/root
/home
)

local invalid_path=(
Expand Down Expand Up @@ -314,6 +313,10 @@ check_heathz_by_gse () {
}

remove_crontab () {
if [ $IS_SUPER == false ]; then
return
fi

local tmpcron
tmpcron=$(mktemp "$TMP_DIR"/cron.XXXXXXX)

Expand All @@ -332,6 +335,10 @@ get_daemon_file () {
}

setup_startup_scripts () {
if [ $IS_SUPER == false ]; then
return
fi

get_daemon_file
touch $DAEMON_FILE_PATH$DAEMON_FILE_NAME
bash -c "cat >$DAEMON_FILE_NAME" << EOF
Expand Down Expand Up @@ -487,7 +494,9 @@ remove_agent () {

log remove_agent - "trying to remove old agent directory(${AGENT_SETUP_PATH}/${AGENT_CLEAN_UP_DIRS[@]})"
cd "${AGENT_SETUP_PATH}"
for file in `ls -lR@ |ggrep -E "i-" |awk '{print $NF}'`;do echo "--- $file" && chattr -i $file ;done
if [ $IS_SUPER == true ]; then
for file in `ls -lR@ |ggrep -E "i-" |awk '{print $NF}'`;do echo "--- $file" && chattr -i $file ;done
fi
cd -

if [[ "$REMOVE" == "TRUE" ]]; then
Expand Down Expand Up @@ -696,7 +705,7 @@ _OO_
}

validate_vars_string () {
echo "$1" | grep -Pq '^[a-zA-Z_][a-zA-Z0-9]+='
echo "$1" | grep -Pq '^[a-zA-Z_][a-zA-Z0-9_]*='
}

check_pkgtool () {
Expand Down Expand Up @@ -897,6 +906,13 @@ while getopts n:t:I:i:l:s:uc:r:x:p:e:a:k:N:v:oT:RDO:E:A:V:B:S:Z:K:F arg; do
esac
done

IS_SUPER=true
if sudo -n true 2>/dev/null; then
IS_SUPER=true
else
IS_SUPER=false
fi

## 检查自定义环境变量
for var_name in ${VARS_LIST//;/ /}; do
validate_vars_string "$var_name" || fail "$var_name is not a valid name"
Expand Down
16 changes: 15 additions & 1 deletion script_tools/agent_tools/agent2/setup_proxy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,10 @@ report_mkdir () {
}

remove_crontab () {
if [ $IS_SUPER == false ]; then
return
fi

local tmpcron
tmpcron=$(mktemp "$TMP_DIR"/cron.XXXXXXX)

Expand All @@ -308,6 +312,10 @@ remove_crontab () {
}

setup_startup_scripts () {
if [ $IS_SUPER == false ]; then
return
fi

check_rc_file
local rcfile=$RC_LOCAL_FILE

Expand Down Expand Up @@ -646,7 +654,7 @@ _OO_
}

validate_vars_string () {
echo "$1" | grep -Pq '^[a-zA-Z_][a-zA-Z0-9]+='
echo "$1" | grep -Pq '^[a-zA-Z_][a-zA-Z0-9_]*='
}

check_pkgtool () {
Expand Down Expand Up @@ -858,6 +866,12 @@ while getopts n:t:I:i:l:s:uc:r:x:p:e:a:k:N:g:v:oT:RO:E:A:V:B:S:Z:K:F arg; do
esac
done

IS_SUPER=true
if sudo -n true 2>/dev/null; then
IS_SUPER=true
else
IS_SUPER=false
fi

## 检查自定义环境变量
for var_name in ${VARS_LIST//;/ /}; do
Expand Down
Loading

0 comments on commit c8f1429

Please sign in to comment.