mirror of https://github.com/jumpserver/jumpserver
feat: 账号推送附加参数 (#10080)
* feat: 账号推送附加参数 * perf: 通过节点 资产 过滤平台api * perf: push automation params * perf: 修改playbook * perf: params serializer * perf: 账号推送playbook 调整 * perf: Automation serializer add params field * perf: params 非必填 * perf: 添加is_params 给前端判断 * perf: is_params bool * perf: 修改push account ansible逻辑 * perf: 修改获取push_kwargs方法 * perf: platform migrate * perf: 修改api * perf: 单个推送 * perf: push account * perf: 修改asset auto_config --------- Co-authored-by: feng <1304903146@qq.com> Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>pull/10197/head
parent
8e81aee1fd
commit
1eb8e40d3e
|
@ -18,18 +18,18 @@
|
|||
|
||||
- name: remove jumpserver ssh key
|
||||
ansible.builtin.lineinfile:
|
||||
dest: "{{ kwargs.dest }}"
|
||||
regexp: "{{ kwargs.regexp }}"
|
||||
dest: "{{ ssh_params.dest }}"
|
||||
regexp: "{{ ssh_params.regexp }}"
|
||||
state: absent
|
||||
when:
|
||||
- account.secret_type == "ssh_key"
|
||||
- kwargs.strategy == "set_jms"
|
||||
- ssh_params.strategy == "set_jms"
|
||||
|
||||
- name: Change SSH key
|
||||
ansible.builtin.authorized_key:
|
||||
user: "{{ account.username }}"
|
||||
key: "{{ account.secret }}"
|
||||
exclusive: "{{ kwargs.exclusive }}"
|
||||
exclusive: "{{ ssh_params.exclusive }}"
|
||||
when: account.secret_type == "ssh_key"
|
||||
|
||||
- name: Refresh connection
|
||||
|
|
|
@ -18,18 +18,18 @@
|
|||
|
||||
- name: remove jumpserver ssh key
|
||||
ansible.builtin.lineinfile:
|
||||
dest: "{{ kwargs.dest }}"
|
||||
regexp: "{{ kwargs.regexp }}"
|
||||
dest: "{{ ssh_params.dest }}"
|
||||
regexp: "{{ ssh_params.regexp }}"
|
||||
state: absent
|
||||
when:
|
||||
- account.secret_type == "ssh_key"
|
||||
- kwargs.strategy == "set_jms"
|
||||
- ssh_params.strategy == "set_jms"
|
||||
|
||||
- name: Change SSH key
|
||||
ansible.builtin.authorized_key:
|
||||
user: "{{ account.username }}"
|
||||
key: "{{ account.secret }}"
|
||||
exclusive: "{{ kwargs.exclusive }}"
|
||||
exclusive: "{{ ssh_params.exclusive }}"
|
||||
when: account.secret_type == "ssh_key"
|
||||
|
||||
- name: Refresh connection
|
||||
|
|
|
@ -42,7 +42,7 @@ class ChangeSecretManager(AccountBasePlaybookManager):
|
|||
def method_type(cls):
|
||||
return AutomationTypes.change_secret
|
||||
|
||||
def get_kwargs(self, account, secret, secret_type):
|
||||
def get_ssh_params(self, account, secret, secret_type):
|
||||
kwargs = {}
|
||||
if secret_type != SecretType.SSH_KEY:
|
||||
return kwargs
|
||||
|
@ -111,6 +111,7 @@ class ChangeSecretManager(AccountBasePlaybookManager):
|
|||
print(f'Windows {asset} does not support ssh key push')
|
||||
return inventory_hosts
|
||||
|
||||
host['ssh_params'] = {}
|
||||
for account in accounts:
|
||||
h = deepcopy(host)
|
||||
secret_type = account.secret_type
|
||||
|
@ -129,7 +130,7 @@ class ChangeSecretManager(AccountBasePlaybookManager):
|
|||
private_key_path = self.generate_private_key_path(new_secret, path_dir)
|
||||
new_secret = self.generate_public_key(new_secret)
|
||||
|
||||
h['kwargs'] = self.get_kwargs(account, new_secret, secret_type)
|
||||
h['ssh_params'].update(self.get_ssh_params(account, new_secret, secret_type))
|
||||
h['account'] = {
|
||||
'name': account.name,
|
||||
'username': account.username,
|
||||
|
|
|
@ -1,30 +1,6 @@
|
|||
import os
|
||||
import copy
|
||||
|
||||
from accounts.const import AutomationTypes
|
||||
from assets.automations.methods import get_platform_automation_methods
|
||||
|
||||
|
||||
def copy_change_secret_to_push_account(methods):
|
||||
push_account = AutomationTypes.push_account
|
||||
change_secret = AutomationTypes.change_secret
|
||||
copy_methods = copy.deepcopy(methods)
|
||||
for method in copy_methods:
|
||||
if not method['id'].startswith(change_secret):
|
||||
continue
|
||||
copy_method = copy.deepcopy(method)
|
||||
copy_method['method'] = push_account.value
|
||||
copy_method['id'] = copy_method['id'].replace(
|
||||
change_secret, push_account
|
||||
)
|
||||
copy_method['name'] = copy_method['name'].replace(
|
||||
'Change secret', 'Push account'
|
||||
)
|
||||
methods.append(copy_method)
|
||||
return methods
|
||||
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
automation_methods = get_platform_automation_methods(BASE_DIR)
|
||||
|
||||
platform_automation_methods = copy_change_secret_to_push_account(automation_methods)
|
||||
platform_automation_methods = get_platform_automation_methods(BASE_DIR)
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
- hosts: mongodb
|
||||
gather_facts: no
|
||||
vars:
|
||||
ansible_python_interpreter: /usr/local/bin/python
|
||||
|
||||
tasks:
|
||||
- name: Test MongoDB connection
|
||||
mongodb_ping:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
login_database: "{{ jms_asset.spec_info.db_name }}"
|
||||
ssl: "{{ jms_asset.spec_info.use_ssl }}"
|
||||
ssl_ca_certs: "{{ jms_asset.secret_info.ca_cert }}"
|
||||
ssl_certfile: "{{ jms_asset.secret_info.client_key }}"
|
||||
connection_options:
|
||||
- tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}"
|
||||
register: db_info
|
||||
|
||||
- name: Display MongoDB version
|
||||
debug:
|
||||
var: db_info.server_version
|
||||
when: db_info is succeeded
|
||||
|
||||
- name: Change MongoDB password
|
||||
mongodb_user:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
login_database: "{{ jms_asset.spec_info.db_name }}"
|
||||
ssl: "{{ jms_asset.spec_info.use_ssl }}"
|
||||
ssl_ca_certs: "{{ jms_asset.secret_info.ca_cert }}"
|
||||
ssl_certfile: "{{ jms_asset.secret_info.client_key }}"
|
||||
connection_options:
|
||||
- tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}"
|
||||
db: "{{ jms_asset.spec_info.db_name }}"
|
||||
name: "{{ account.username }}"
|
||||
password: "{{ account.secret }}"
|
||||
when: db_info is succeeded
|
||||
register: change_info
|
||||
|
||||
- name: Verify password
|
||||
mongodb_ping:
|
||||
login_user: "{{ account.username }}"
|
||||
login_password: "{{ account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
login_database: "{{ jms_asset.spec_info.db_name }}"
|
||||
ssl: "{{ jms_asset.spec_info.use_ssl }}"
|
||||
ssl_ca_certs: "{{ jms_asset.secret_info.ca_cert }}"
|
||||
ssl_certfile: "{{ jms_asset.secret_info.client_key }}"
|
||||
connection_options:
|
||||
- tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}"
|
||||
when:
|
||||
- db_info is succeeded
|
||||
- change_info is succeeded
|
|
@ -0,0 +1,6 @@
|
|||
id: push_account_mongodb
|
||||
name: Push account for MongoDB
|
||||
category: database
|
||||
type:
|
||||
- mongodb
|
||||
method: push_account
|
|
@ -0,0 +1,43 @@
|
|||
- hosts: mysql
|
||||
gather_facts: no
|
||||
vars:
|
||||
ansible_python_interpreter: /usr/local/bin/python
|
||||
db_name: "{{ jms_asset.spec_info.db_name }}"
|
||||
|
||||
tasks:
|
||||
- name: Test MySQL connection
|
||||
community.mysql.mysql_info:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
filter: version
|
||||
register: db_info
|
||||
|
||||
- name: MySQL version
|
||||
debug:
|
||||
var: db_info.version.full
|
||||
|
||||
- name: Change MySQL password
|
||||
community.mysql.mysql_user:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
name: "{{ account.username }}"
|
||||
password: "{{ account.secret }}"
|
||||
host: "%"
|
||||
priv: "{{ account.username + '.*:USAGE' if db_name == '' else db_name + '.*:ALL' }}"
|
||||
when: db_info is succeeded
|
||||
register: change_info
|
||||
|
||||
- name: Verify password
|
||||
community.mysql.mysql_info:
|
||||
login_user: "{{ account.username }}"
|
||||
login_password: "{{ account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
filter: version
|
||||
when:
|
||||
- db_info is succeeded
|
||||
- change_info is succeeded
|
|
@ -0,0 +1,7 @@
|
|||
id: push_account_mysql
|
||||
name: Push account for MySQL
|
||||
category: database
|
||||
type:
|
||||
- mysql
|
||||
- mariadb
|
||||
method: push_account
|
|
@ -0,0 +1,44 @@
|
|||
- hosts: oracle
|
||||
gather_facts: no
|
||||
vars:
|
||||
ansible_python_interpreter: /usr/local/bin/python
|
||||
|
||||
tasks:
|
||||
- name: Test Oracle connection
|
||||
oracle_ping:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
login_database: "{{ jms_asset.spec_info.db_name }}"
|
||||
mode: "{{ jms_account.mode }}"
|
||||
register: db_info
|
||||
|
||||
- name: Display Oracle version
|
||||
debug:
|
||||
var: db_info.server_version
|
||||
when: db_info is succeeded
|
||||
|
||||
- name: Change Oracle password
|
||||
oracle_user:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
login_database: "{{ jms_asset.spec_info.db_name }}"
|
||||
mode: "{{ jms_account.mode }}"
|
||||
name: "{{ account.username }}"
|
||||
password: "{{ account.secret }}"
|
||||
when: db_info is succeeded
|
||||
register: change_info
|
||||
|
||||
- name: Verify password
|
||||
oracle_ping:
|
||||
login_user: "{{ account.username }}"
|
||||
login_password: "{{ account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
login_database: "{{ jms_asset.spec_info.db_name }}"
|
||||
when:
|
||||
- db_info is succeeded
|
||||
- change_info is succeeded
|
|
@ -0,0 +1,6 @@
|
|||
id: push_account_oracle
|
||||
name: Push account for Oracle
|
||||
category: database
|
||||
type:
|
||||
- oracle
|
||||
method: push_account
|
|
@ -0,0 +1,46 @@
|
|||
- hosts: postgre
|
||||
gather_facts: no
|
||||
vars:
|
||||
ansible_python_interpreter: /usr/local/bin/python
|
||||
|
||||
tasks:
|
||||
- name: Test PostgreSQL connection
|
||||
community.postgresql.postgresql_ping:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
login_db: "{{ jms_asset.spec_info.db_name }}"
|
||||
register: result
|
||||
failed_when: not result.is_available
|
||||
|
||||
- name: Display PostgreSQL version
|
||||
debug:
|
||||
var: result.server_version.full
|
||||
when: result is succeeded
|
||||
|
||||
- name: Change PostgreSQL password
|
||||
community.postgresql.postgresql_user:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
db: "{{ jms_asset.spec_info.db_name }}"
|
||||
name: "{{ account.username }}"
|
||||
password: "{{ account.secret }}"
|
||||
role_attr_flags: LOGIN
|
||||
when: result is succeeded
|
||||
register: change_info
|
||||
|
||||
- name: Verify password
|
||||
community.postgresql.postgresql_ping:
|
||||
login_user: "{{ account.username }}"
|
||||
login_password: "{{ account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
db: "{{ jms_asset.spec_info.db_name }}"
|
||||
when:
|
||||
- result is succeeded
|
||||
- change_info is succeeded
|
||||
register: result
|
||||
failed_when: not result.is_available
|
|
@ -0,0 +1,6 @@
|
|||
id: push_account_postgresql
|
||||
name: Push account for PostgreSQL
|
||||
category: database
|
||||
type:
|
||||
- postgresql
|
||||
method: push_account
|
|
@ -0,0 +1,69 @@
|
|||
- hosts: sqlserver
|
||||
gather_facts: no
|
||||
vars:
|
||||
ansible_python_interpreter: /usr/local/bin/python
|
||||
|
||||
tasks:
|
||||
- name: Test SQLServer connection
|
||||
community.general.mssql_script:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
name: '{{ jms_asset.spec_info.db_name }}'
|
||||
script: |
|
||||
SELECT @@version
|
||||
register: db_info
|
||||
|
||||
- name: SQLServer version
|
||||
set_fact:
|
||||
info:
|
||||
version: "{{ db_info.query_results[0][0][0][0].splitlines()[0] }}"
|
||||
- debug:
|
||||
var: info
|
||||
|
||||
- name: Check whether SQLServer User exist
|
||||
community.general.mssql_script:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
name: '{{ jms_asset.spec_info.db_name }}'
|
||||
script: "SELECT 1 from sys.sql_logins WHERE name='{{ account.username }}';"
|
||||
when: db_info is succeeded
|
||||
register: user_exist
|
||||
|
||||
- name: Change SQLServer password
|
||||
community.general.mssql_script:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
name: '{{ jms_asset.spec_info.db_name }}'
|
||||
script: "ALTER LOGIN {{ account.username }} WITH PASSWORD = '{{ account.secret }}'; select @@version"
|
||||
when: user_exist.query_results[0] | length != 0
|
||||
register: change_info
|
||||
|
||||
- name: Add SQLServer user
|
||||
community.general.mssql_script:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
name: '{{ jms_asset.spec_info.db_name }}'
|
||||
script: "CREATE LOGIN {{ account.username }} WITH PASSWORD = '{{ account.secret }}'; select @@version"
|
||||
when: user_exist.query_results[0] | length == 0
|
||||
register: change_info
|
||||
|
||||
- name: Verify password
|
||||
community.general.mssql_script:
|
||||
login_user: "{{ account.username }}"
|
||||
login_password: "{{ account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
name: '{{ jms_asset.spec_info.db_name }}'
|
||||
script: |
|
||||
SELECT @@version
|
||||
when:
|
||||
- db_info is succeeded
|
||||
- change_info is succeeded
|
|
@ -0,0 +1,6 @@
|
|||
id: push_account_sqlserver
|
||||
name: Push account for SQLServer
|
||||
category: database
|
||||
type:
|
||||
- sqlserver
|
||||
method: push_account
|
|
@ -0,0 +1,93 @@
|
|||
- hosts: demo
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: Test privileged account
|
||||
ansible.builtin.ping:
|
||||
|
||||
- name: Push user
|
||||
ansible.builtin.user:
|
||||
name: "{{ account.username }}"
|
||||
shell: "{{ params.shell }}"
|
||||
home: "{{ '/home/' + account.username }}"
|
||||
groups: "{{ params.groups }}"
|
||||
expires: -1
|
||||
state: present
|
||||
|
||||
- name: "Add {{ account.username }} group"
|
||||
ansible.builtin.group:
|
||||
name: "{{ account.username }}"
|
||||
state: present
|
||||
|
||||
- name: Check home dir exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ '/home/' + account.username }}"
|
||||
register: home_existed
|
||||
|
||||
- name: Set home dir permission
|
||||
ansible.builtin.file:
|
||||
path: "{{ '/home/' + account.username }}"
|
||||
owner: "{{ account.username }}"
|
||||
group: "{{ account.username }}"
|
||||
mode: "0700"
|
||||
when:
|
||||
- home_existed.stat.exists == true
|
||||
|
||||
- name: Add user groups
|
||||
ansible.builtin.user:
|
||||
name: "{{ account.username }}"
|
||||
groups: "{{ params.groups }}"
|
||||
when: params.groups
|
||||
|
||||
- name: Push user password
|
||||
ansible.builtin.user:
|
||||
name: "{{ account.username }}"
|
||||
password: "{{ account.secret | password_hash('sha512') }}"
|
||||
update_password: always
|
||||
when: account.secret_type == "password"
|
||||
|
||||
- name: remove jumpserver ssh key
|
||||
ansible.builtin.lineinfile:
|
||||
dest: "{{ ssh_params.dest }}"
|
||||
regexp: "{{ ssh_params.regexp }}"
|
||||
state: absent
|
||||
when:
|
||||
- account.secret_type == "ssh_key"
|
||||
- ssh_params.strategy == "set_jms"
|
||||
|
||||
- name: Push SSH key
|
||||
ansible.builtin.authorized_key:
|
||||
user: "{{ account.username }}"
|
||||
key: "{{ account.secret }}"
|
||||
exclusive: "{{ ssh_params.exclusive }}"
|
||||
when: account.secret_type == "ssh_key"
|
||||
|
||||
- name: Set sudo setting
|
||||
ansible.builtin.lineinfile:
|
||||
dest: /etc/sudoers
|
||||
state: present
|
||||
regexp: "^{{ account.username }} ALL="
|
||||
line: "{{ account.username + ' ALL=(ALL) NOPASSWD: ' + params.sudo }}"
|
||||
validate: visudo -cf %s
|
||||
when:
|
||||
- params.sudo
|
||||
|
||||
- name: Refresh connection
|
||||
ansible.builtin.meta: reset_connection
|
||||
|
||||
- name: Verify password
|
||||
ansible.builtin.ping:
|
||||
become: no
|
||||
vars:
|
||||
ansible_user: "{{ account.username }}"
|
||||
ansible_password: "{{ account.secret }}"
|
||||
ansible_become: no
|
||||
when: account.secret_type == "password"
|
||||
|
||||
- name: Verify SSH key
|
||||
ansible.builtin.ping:
|
||||
become: no
|
||||
vars:
|
||||
ansible_user: "{{ account.username }}"
|
||||
ansible_ssh_private_key_file: "{{ account.private_key_path }}"
|
||||
ansible_become: no
|
||||
when: account.secret_type == "ssh_key"
|
|
@ -0,0 +1,24 @@
|
|||
id: push_account_aix
|
||||
name: Push account for aix
|
||||
category: host
|
||||
type:
|
||||
- AIX
|
||||
method: push_account
|
||||
params:
|
||||
- name: sudo
|
||||
type: str
|
||||
label: 'Sudo'
|
||||
default: '/bin/whoami'
|
||||
help_text: '使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig'
|
||||
|
||||
- name: shell
|
||||
type: str
|
||||
label: 'Shell'
|
||||
default: '/bin/bash'
|
||||
|
||||
- name: groups
|
||||
type: str
|
||||
label: '用户组'
|
||||
default: ''
|
||||
help_text: '请输入用户组,多个用户组使用逗号分隔(需填写已存在的用户组)'
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
- hosts: demo
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: Test privileged account
|
||||
ansible.builtin.ping:
|
||||
|
||||
- name: Push user
|
||||
ansible.builtin.user:
|
||||
name: "{{ account.username }}"
|
||||
shell: "{{ params.shell }}"
|
||||
home: "{{ '/home/' + account.username }}"
|
||||
groups: "{{ params.groups }}"
|
||||
expires: -1
|
||||
state: present
|
||||
|
||||
- name: "Add {{ account.username }} group"
|
||||
ansible.builtin.group:
|
||||
name: "{{ account.username }}"
|
||||
state: present
|
||||
|
||||
- name: Check home dir exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ '/home/' + account.username }}"
|
||||
register: home_existed
|
||||
|
||||
- name: Set home dir permission
|
||||
ansible.builtin.file:
|
||||
path: "{{ '/home/' + account.username }}"
|
||||
owner: "{{ account.username }}"
|
||||
group: "{{ account.username }}"
|
||||
mode: "0700"
|
||||
when:
|
||||
- home_existed.stat.exists == true
|
||||
|
||||
- name: Add user groups
|
||||
ansible.builtin.user:
|
||||
name: "{{ account.username }}"
|
||||
groups: "{{ params.groups }}"
|
||||
when: params.groups
|
||||
|
||||
- name: Push user password
|
||||
ansible.builtin.user:
|
||||
name: "{{ account.username }}"
|
||||
password: "{{ account.secret | password_hash('sha512') }}"
|
||||
update_password: always
|
||||
when: account.secret_type == "password"
|
||||
|
||||
- name: remove jumpserver ssh key
|
||||
ansible.builtin.lineinfile:
|
||||
dest: "{{ ssh_params.dest }}"
|
||||
regexp: "{{ ssh_params.regexp }}"
|
||||
state: absent
|
||||
when:
|
||||
- account.secret_type == "ssh_key"
|
||||
- ssh_params.strategy == "set_jms"
|
||||
|
||||
- name: Push SSH key
|
||||
ansible.builtin.authorized_key:
|
||||
user: "{{ account.username }}"
|
||||
key: "{{ account.secret }}"
|
||||
exclusive: "{{ ssh_params.exclusive }}"
|
||||
when: account.secret_type == "ssh_key"
|
||||
|
||||
- name: Set sudo setting
|
||||
ansible.builtin.lineinfile:
|
||||
dest: /etc/sudoers
|
||||
state: present
|
||||
regexp: "^{{ account.username }} ALL="
|
||||
line: "{{ account.username + ' ALL=(ALL) NOPASSWD: ' + params.sudo }}"
|
||||
validate: visudo -cf %s
|
||||
when:
|
||||
- params.sudo
|
||||
|
||||
- name: Refresh connection
|
||||
ansible.builtin.meta: reset_connection
|
||||
|
||||
- name: Verify password
|
||||
ansible.builtin.ping:
|
||||
become: no
|
||||
vars:
|
||||
ansible_user: "{{ account.username }}"
|
||||
ansible_password: "{{ account.secret }}"
|
||||
ansible_become: no
|
||||
when: account.secret_type == "password"
|
||||
|
||||
- name: Verify SSH key
|
||||
ansible.builtin.ping:
|
||||
become: no
|
||||
vars:
|
||||
ansible_user: "{{ account.username }}"
|
||||
ansible_ssh_private_key_file: "{{ account.private_key_path }}"
|
||||
ansible_become: no
|
||||
when: account.secret_type == "ssh_key"
|
|
@ -0,0 +1,25 @@
|
|||
id: push_account_posix
|
||||
name: Push account for posix
|
||||
category: host
|
||||
type:
|
||||
- unix
|
||||
- linux
|
||||
method: push_account
|
||||
params:
|
||||
- name: sudo
|
||||
type: str
|
||||
label: 'Sudo'
|
||||
default: '/bin/whoami'
|
||||
help_text: '使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig'
|
||||
|
||||
- name: shell
|
||||
type: str
|
||||
label: 'Shell'
|
||||
default: '/bin/bash'
|
||||
help_text: ''
|
||||
|
||||
- name: groups
|
||||
type: str
|
||||
label: '用户组'
|
||||
default: ''
|
||||
help_text: '请输入用户组,多个用户组使用逗号分隔(需填写已存在的用户组)'
|
|
@ -0,0 +1,30 @@
|
|||
- hosts: demo
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: Test privileged account
|
||||
ansible.windows.win_ping:
|
||||
|
||||
# - name: Print variables
|
||||
# debug:
|
||||
# msg: "Username: {{ account.username }}, Password: {{ account.secret }}"
|
||||
|
||||
- name: Push user password
|
||||
ansible.windows.win_user:
|
||||
fullname: "{{ account.username}}"
|
||||
name: "{{ account.username }}"
|
||||
password: "{{ account.secret }}"
|
||||
password_never_expires: yes
|
||||
groups: "{{ params.groups }}"
|
||||
groups_action: add
|
||||
update_password: always
|
||||
when: account.secret_type == "password"
|
||||
|
||||
- name: Refresh connection
|
||||
ansible.builtin.meta: reset_connection
|
||||
|
||||
- name: Verify password
|
||||
ansible.windows.win_ping:
|
||||
vars:
|
||||
ansible_user: "{{ account.username }}"
|
||||
ansible_password: "{{ account.secret }}"
|
||||
when: account.secret_type == "password"
|
|
@ -0,0 +1,13 @@
|
|||
id: push_account_local_windows
|
||||
name: Push account local account for Windows
|
||||
version: 1
|
||||
method: push_account
|
||||
category: host
|
||||
type:
|
||||
- windows
|
||||
params:
|
||||
- name: groups
|
||||
type: str
|
||||
label: '用户组'
|
||||
default: 'Users,Remote Desktop Users'
|
||||
help_text: '请输入用户组,多个用户组使用逗号分隔(需填写已存在的用户组)'
|
|
@ -31,6 +31,7 @@ class PushAccountManager(ChangeSecretManager, AccountBasePlaybookManager):
|
|||
print(msg)
|
||||
return inventory_hosts
|
||||
|
||||
host['ssh_params'] = {}
|
||||
for account in accounts:
|
||||
h = deepcopy(host)
|
||||
secret_type = account.secret_type
|
||||
|
@ -49,7 +50,7 @@ class PushAccountManager(ChangeSecretManager, AccountBasePlaybookManager):
|
|||
private_key_path = self.generate_private_key_path(new_secret, path_dir)
|
||||
new_secret = self.generate_public_key(new_secret)
|
||||
|
||||
h['kwargs'] = self.get_kwargs(account, new_secret, secret_type)
|
||||
h['ssh_params'].update(self.get_ssh_params(account, new_secret, secret_type))
|
||||
h['account'] = {
|
||||
'name': account.name,
|
||||
'username': account.username,
|
||||
|
|
|
@ -51,7 +51,8 @@ class PushAccountAutomation(ChangeSecretMixin, AccountBaseAutomation):
|
|||
def to_attr_json(self):
|
||||
attr_json = super().to_attr_json()
|
||||
attr_json.update({
|
||||
'username': self.username
|
||||
'username': self.username,
|
||||
'params': self.params,
|
||||
})
|
||||
return attr_json
|
||||
|
||||
|
|
|
@ -27,13 +27,16 @@ class AccountCreateUpdateSerializerMixin(serializers.Serializer):
|
|||
push_now = serializers.BooleanField(
|
||||
default=False, label=_("Push now"), write_only=True
|
||||
)
|
||||
params = serializers.JSONField(
|
||||
decoder=None, encoder=None, required=False, style={'base_template': 'textarea.html'}
|
||||
)
|
||||
on_invalid = LabeledChoiceField(
|
||||
choices=AccountInvalidPolicy.choices, default=AccountInvalidPolicy.ERROR,
|
||||
write_only=True, label=_('Exist policy')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
fields = ['template', 'push_now', 'on_invalid']
|
||||
fields = ['template', 'push_now', 'params', 'on_invalid']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
@ -93,10 +96,10 @@ class AccountCreateUpdateSerializerMixin(serializers.Serializer):
|
|||
initial_data.update(attrs)
|
||||
|
||||
@staticmethod
|
||||
def push_account_if_need(instance, push_now, stat):
|
||||
def push_account_if_need(instance, push_now, params, stat):
|
||||
if not push_now or stat != 'created':
|
||||
return
|
||||
push_accounts_to_assets_task.delay([str(instance.id)])
|
||||
push_accounts_to_assets_task.delay([str(instance.id)], params)
|
||||
|
||||
def get_validators(self):
|
||||
_validators = super().get_validators()
|
||||
|
@ -147,8 +150,9 @@ class AccountCreateUpdateSerializerMixin(serializers.Serializer):
|
|||
|
||||
def create(self, validated_data):
|
||||
push_now = validated_data.pop('push_now', None)
|
||||
params = validated_data.pop('params', None)
|
||||
instance, stat = self.do_create(validated_data)
|
||||
self.push_account_if_need(instance, push_now, stat)
|
||||
self.push_account_if_need(instance, push_now, params, stat)
|
||||
return instance
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
|
@ -156,9 +160,10 @@ class AccountCreateUpdateSerializerMixin(serializers.Serializer):
|
|||
validated_data.pop('username', None)
|
||||
validated_data.pop('on_invalid', None)
|
||||
push_now = validated_data.pop('push_now', None)
|
||||
params = validated_data.pop('params', None)
|
||||
validated_data['source_id'] = None
|
||||
instance = super().update(instance, validated_data)
|
||||
self.push_account_if_need(instance, push_now, 'updated')
|
||||
self.push_account_if_need(instance, push_now, params, 'updated')
|
||||
return instance
|
||||
|
||||
|
||||
|
|
|
@ -7,9 +7,10 @@ from .change_secret import (
|
|||
|
||||
|
||||
class PushAccountAutomationSerializer(ChangeSecretAutomationSerializer):
|
||||
|
||||
class Meta(ChangeSecretAutomationSerializer.Meta):
|
||||
model = PushAccountAutomation
|
||||
fields = [
|
||||
fields = ['params'] + [
|
||||
n for n in ChangeSecretAutomationSerializer.Meta.fields
|
||||
if n not in ['recipients']
|
||||
]
|
||||
|
|
|
@ -15,7 +15,7 @@ __all__ = [
|
|||
queue="ansible", verbose_name=_('Push accounts to assets'),
|
||||
activity_callback=lambda self, account_ids, *args, **kwargs: (account_ids, None)
|
||||
)
|
||||
def push_accounts_to_assets_task(account_ids):
|
||||
def push_accounts_to_assets_task(account_ids, params=None):
|
||||
from accounts.models import PushAccountAutomation
|
||||
from accounts.models import Account
|
||||
|
||||
|
@ -26,6 +26,7 @@ def push_accounts_to_assets_task(account_ids):
|
|||
task_snapshot = {
|
||||
'accounts': [str(account.id) for account in accounts],
|
||||
'assets': [str(account.asset_id) for account in accounts],
|
||||
'params': params or {},
|
||||
}
|
||||
|
||||
tp = AutomationTypes.push_account
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
from rest_framework import generics
|
||||
from rest_framework import serializers
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
|
||||
from assets.const import AllTypes
|
||||
from assets.models import Platform
|
||||
from assets.models import Platform, Node, Asset
|
||||
from assets.serializers import PlatformSerializer
|
||||
from common.api import JMSModelViewSet
|
||||
from common.permissions import IsValidUser
|
||||
from common.serializers import GroupedChoiceSerializer
|
||||
|
||||
__all__ = ['AssetPlatformViewSet']
|
||||
__all__ = ['AssetPlatformViewSet', 'PlatformAutomationMethodsApi']
|
||||
|
||||
|
||||
class AssetPlatformViewSet(JMSModelViewSet):
|
||||
|
@ -18,7 +24,8 @@ class AssetPlatformViewSet(JMSModelViewSet):
|
|||
rbac_perms = {
|
||||
'categories': 'assets.view_platform',
|
||||
'type_constraints': 'assets.view_platform',
|
||||
'ops_methods': 'assets.view_platform'
|
||||
'ops_methods': 'assets.view_platform',
|
||||
'filter_nodes_assets': 'assets.view_platform'
|
||||
}
|
||||
|
||||
def get_queryset(self):
|
||||
|
@ -38,3 +45,44 @@ class AssetPlatformViewSet(JMSModelViewSet):
|
|||
request, message={"detail": "Internal platform"}
|
||||
)
|
||||
return super().check_object_permissions(request, obj)
|
||||
|
||||
@action(methods=['post'], detail=False, url_path='filter-nodes-assets')
|
||||
def filter_nodes_assets(self, request, *args, **kwargs):
|
||||
node_ids = request.data.get('node_ids', [])
|
||||
asset_ids = request.data.get('asset_ids', [])
|
||||
nodes = Node.objects.filter(id__in=node_ids)
|
||||
node_asset_ids = Node.get_nodes_all_assets(*nodes).values_list('id', flat=True)
|
||||
direct_asset_ids = Asset.objects.filter(id__in=asset_ids).values_list('id', flat=True)
|
||||
platform_ids = Asset.objects.filter(
|
||||
id__in=set(list(direct_asset_ids) + list(node_asset_ids))
|
||||
).values_list('platform_id', flat=True)
|
||||
platforms = Platform.objects.filter(id__in=platform_ids)
|
||||
serializer = self.get_serializer(platforms, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
class PlatformAutomationMethodsApi(generics.ListAPIView):
|
||||
permission_classes = (IsValidUser,)
|
||||
|
||||
@staticmethod
|
||||
def automation_methods():
|
||||
return AllTypes.get_automation_methods()
|
||||
|
||||
def generate_serializer_fields(self):
|
||||
data = self.automation_methods()
|
||||
fields = {
|
||||
i['id']: i['params_serializer']()
|
||||
if i['params_serializer'] else None
|
||||
for i in data
|
||||
}
|
||||
return fields
|
||||
|
||||
def get_serializer_class(self):
|
||||
fields = self.generate_serializer_fields()
|
||||
serializer_name = 'AutomationMethodsSerializer'
|
||||
return type(serializer_name, (serializers.Serializer,), fields)
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
data = self.generate_serializer_fields()
|
||||
serializer = self.get_serializer(data)
|
||||
return Response(serializer.data)
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import json
|
||||
import os
|
||||
import shutil
|
||||
import yaml
|
||||
|
||||
from collections import defaultdict
|
||||
from hashlib import md5
|
||||
from socket import gethostname
|
||||
|
||||
import yaml
|
||||
from django.conf import settings
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext as _
|
||||
|
@ -42,6 +41,26 @@ class BasePlaybookManager:
|
|||
self.method_hosts_mapper = defaultdict(list)
|
||||
self.playbooks = []
|
||||
self.gateway_servers = dict()
|
||||
params = self.execution.snapshot.get('params')
|
||||
self.params = params or {}
|
||||
|
||||
def get_params(self, automation, method_type):
|
||||
method_attr = '{}_method'.format(method_type)
|
||||
method_params = '{}_params'.format(method_type)
|
||||
method_id = getattr(automation, method_attr)
|
||||
automation_params = getattr(automation, method_params)
|
||||
serializer = self.method_id_meta_mapper[method_id]['params_serializer']
|
||||
|
||||
if serializer is None:
|
||||
return {}
|
||||
|
||||
data = self.params.get(method_id, {})
|
||||
params = serializer(data).data
|
||||
return {
|
||||
field_name: automation_params.get(field_name, '')
|
||||
if not params[field_name] else params[field_name]
|
||||
for field_name in params
|
||||
}
|
||||
|
||||
@property
|
||||
def platform_automation_methods(self):
|
||||
|
@ -102,8 +121,9 @@ class BasePlaybookManager:
|
|||
return host
|
||||
|
||||
def host_callback(self, host, automation=None, **kwargs):
|
||||
enabled_attr = '{}_enabled'.format(self.__class__.method_type())
|
||||
method_attr = '{}_method'.format(self.__class__.method_type())
|
||||
method_type = self.__class__.method_type()
|
||||
enabled_attr = '{}_enabled'.format(method_type)
|
||||
method_attr = '{}_method'.format(method_type)
|
||||
|
||||
method_enabled = automation and \
|
||||
getattr(automation, enabled_attr) and \
|
||||
|
@ -115,6 +135,7 @@ class BasePlaybookManager:
|
|||
return host
|
||||
|
||||
host = self.convert_cert_to_file(host, kwargs.get('path_dir'))
|
||||
host['params'] = self.get_params(automation, method_type)
|
||||
return host
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -22,6 +22,15 @@ def check_platform_methods(methods):
|
|||
raise ValueError("Duplicate id: {}".format(_id))
|
||||
|
||||
|
||||
def generate_serializer(data):
|
||||
from common.serializers import create_serializer_class
|
||||
params = data.pop('params', None)
|
||||
if not params:
|
||||
return None
|
||||
serializer_name = data['id'].title().replace('_', '') + 'Serializer'
|
||||
return create_serializer_class(serializer_name, params)
|
||||
|
||||
|
||||
def get_platform_automation_methods(path):
|
||||
methods = []
|
||||
for root, dirs, files in os.walk(path, topdown=False):
|
||||
|
@ -34,6 +43,7 @@ def get_platform_automation_methods(path):
|
|||
manifest = yaml.safe_load(f)
|
||||
check_platform_method(manifest, path)
|
||||
manifest['dir'] = os.path.dirname(path)
|
||||
manifest['params_serializer'] = generate_serializer(manifest)
|
||||
methods.append(manifest)
|
||||
|
||||
check_platform_methods(methods)
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
# Generated by Django 3.2.16 on 2023-04-11 10:14
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
from assets.const import AllTypes
|
||||
|
||||
|
||||
def migrate_automation_push_account_params(apps, schema_editor):
|
||||
platform_automation_model = apps.get_model('assets', 'PlatformAutomation')
|
||||
platform_automation_methods = AllTypes.get_automation_methods()
|
||||
methods_id_data_map = {
|
||||
i['id']: None if i['params_serializer'] is None else i['params_serializer']({}).data
|
||||
for i in platform_automation_methods
|
||||
if i['method'] == 'push_account'
|
||||
}
|
||||
automation_objs = []
|
||||
for automation in platform_automation_model.objects.all():
|
||||
push_account_method = automation.push_account_method
|
||||
if not push_account_method:
|
||||
continue
|
||||
value = methods_id_data_map.get(push_account_method)
|
||||
if value is None:
|
||||
continue
|
||||
automation.push_account_params = value
|
||||
automation_objs.append(automation)
|
||||
platform_automation_model.objects.bulk_update(automation_objs, ['push_account_params'])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('assets', '0112_auto_20230404_1631'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='platformautomation',
|
||||
name='change_secret_params',
|
||||
field=models.JSONField(default=dict, verbose_name='Change secret params'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platformautomation',
|
||||
name='gather_accounts_params',
|
||||
field=models.JSONField(default=dict, verbose_name='Gather facts params'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platformautomation',
|
||||
name='gather_facts_params',
|
||||
field=models.JSONField(default=dict, verbose_name='Gather facts params'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platformautomation',
|
||||
name='ping_params',
|
||||
field=models.JSONField(default=dict, verbose_name='Ping params'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platformautomation',
|
||||
name='push_account_params',
|
||||
field=models.JSONField(default=dict, verbose_name='Push account params'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platformautomation',
|
||||
name='verify_account_params',
|
||||
field=models.JSONField(default=dict, verbose_name='Verify account params'),
|
||||
),
|
||||
migrations.RunPython(migrate_automation_push_account_params),
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.16 on 2023-04-13 10:18
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0113_auto_20230411_1814'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='baseautomation',
|
||||
name='params',
|
||||
field=models.JSONField(default=dict, verbose_name='Params'),
|
||||
),
|
||||
]
|
|
@ -1,12 +1,12 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
import json
|
||||
import logging
|
||||
from collections import defaultdict
|
||||
|
||||
from django.db import models
|
||||
from django.forms import model_to_dict
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from assets import const
|
||||
|
@ -181,15 +181,8 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel):
|
|||
}
|
||||
if not automation:
|
||||
return auto_config
|
||||
auto_config.update({
|
||||
'ping_enabled': automation.ping_enabled,
|
||||
'ansible_enabled': automation.ansible_enabled,
|
||||
'push_account_enabled': automation.push_account_enabled,
|
||||
'gather_facts_enabled': automation.gather_facts_enabled,
|
||||
'change_secret_enabled': automation.change_secret_enabled,
|
||||
'verify_account_enabled': automation.verify_account_enabled,
|
||||
'gather_accounts_enabled': automation.gather_accounts_enabled,
|
||||
})
|
||||
|
||||
auto_config.update(model_to_dict(automation))
|
||||
return auto_config
|
||||
|
||||
def get_target_ip(self):
|
||||
|
|
|
@ -19,6 +19,7 @@ class BaseAutomation(PeriodTaskModelMixin, JMSOrgBaseModel):
|
|||
assets = models.ManyToManyField('assets.Asset', blank=True, verbose_name=_("Assets"))
|
||||
type = models.CharField(max_length=16, verbose_name=_('Type'))
|
||||
is_active = models.BooleanField(default=True, verbose_name=_("Is active"))
|
||||
params = models.JSONField(default=dict, verbose_name=_("Params"))
|
||||
|
||||
def __str__(self):
|
||||
return self.name + '@' + str(self.created_by)
|
||||
|
|
|
@ -38,25 +38,40 @@ class PlatformProtocol(models.Model):
|
|||
class PlatformAutomation(models.Model):
|
||||
ansible_enabled = models.BooleanField(default=False, verbose_name=_("Enabled"))
|
||||
ansible_config = models.JSONField(default=dict, verbose_name=_("Ansible config"))
|
||||
|
||||
ping_enabled = models.BooleanField(default=False, verbose_name=_("Ping enabled"))
|
||||
ping_method = models.CharField(max_length=32, blank=True, null=True, verbose_name=_("Ping method"))
|
||||
ping_params = models.JSONField(default=dict, verbose_name=_("Ping params"))
|
||||
|
||||
gather_facts_enabled = models.BooleanField(default=False, verbose_name=_("Gather facts enabled"))
|
||||
gather_facts_method = models.TextField(max_length=32, blank=True, null=True, verbose_name=_("Gather facts method"))
|
||||
gather_facts_method = models.TextField(
|
||||
max_length=32, blank=True, null=True, verbose_name=_("Gather facts method")
|
||||
)
|
||||
gather_facts_params = models.JSONField(default=dict, verbose_name=_("Gather facts params"))
|
||||
|
||||
change_secret_enabled = models.BooleanField(default=False, verbose_name=_("Change secret enabled"))
|
||||
change_secret_method = models.TextField(
|
||||
max_length=32, blank=True, null=True, verbose_name=_("Change secret method")
|
||||
)
|
||||
change_secret_params = models.JSONField(default=dict, verbose_name=_("Change secret params"))
|
||||
|
||||
push_account_enabled = models.BooleanField(default=False, verbose_name=_("Push account enabled"))
|
||||
push_account_method = models.TextField(
|
||||
max_length=32, blank=True, null=True, verbose_name=_("Push account method")
|
||||
)
|
||||
push_account_params = models.JSONField(default=dict, verbose_name=_("Push account params"))
|
||||
|
||||
verify_account_enabled = models.BooleanField(default=False, verbose_name=_("Verify account enabled"))
|
||||
verify_account_method = models.TextField(
|
||||
max_length=32, blank=True, null=True, verbose_name=_("Verify account method"))
|
||||
max_length=32, blank=True, null=True, verbose_name=_("Verify account method")
|
||||
)
|
||||
verify_account_params = models.JSONField(default=dict, verbose_name=_("Verify account params"))
|
||||
|
||||
gather_accounts_enabled = models.BooleanField(default=False, verbose_name=_("Gather facts enabled"))
|
||||
gather_accounts_method = models.TextField(
|
||||
max_length=32, blank=True, null=True, verbose_name=_("Gather facts method")
|
||||
)
|
||||
gather_accounts_params = models.JSONField(default=dict, verbose_name=_("Gather facts params"))
|
||||
|
||||
|
||||
class Platform(JMSBaseModel):
|
||||
|
|
|
@ -51,12 +51,12 @@ class PlatformAutomationSerializer(serializers.ModelSerializer):
|
|||
fields = [
|
||||
"id",
|
||||
"ansible_enabled", "ansible_config",
|
||||
"ping_enabled", "ping_method",
|
||||
"push_account_enabled", "push_account_method",
|
||||
"gather_facts_enabled", "gather_facts_method",
|
||||
"change_secret_enabled", "change_secret_method",
|
||||
"verify_account_enabled", "verify_account_method",
|
||||
"gather_accounts_enabled", "gather_accounts_method",
|
||||
"ping_enabled", "ping_method", "ping_params",
|
||||
"push_account_enabled", "push_account_method", "push_account_params",
|
||||
"gather_facts_enabled", "gather_facts_method", "gather_facts_params",
|
||||
"change_secret_enabled", "change_secret_method", "change_secret_params",
|
||||
"verify_account_enabled", "verify_account_method", "verify_account_params",
|
||||
"gather_accounts_enabled", "gather_accounts_method", "gather_accounts_params",
|
||||
]
|
||||
extra_kwargs = {
|
||||
# 启用资产探测
|
||||
|
|
|
@ -46,6 +46,7 @@ urlpatterns = [
|
|||
path('nodes/<uuid:pk>/tasks/', api.NodeTaskCreateApi.as_view(), name='node-task-create'),
|
||||
|
||||
path('gateways/<uuid:pk>/test-connective/', api.GatewayTestConnectionApi.as_view(), name='test-gateway-connective'),
|
||||
path('platform-automation-methods/', api.PlatformAutomationMethodsApi.as_view(), name='platform-automation-methods'),
|
||||
]
|
||||
|
||||
urlpatterns += router.urls
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
from .common import *
|
||||
from .dynamic import *
|
||||
from .mixin import *
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from rest_framework import serializers
|
||||
|
||||
example_info = [
|
||||
{"name": "name", "label": "姓名", "required": False, "default": "老广", "type": "str"},
|
||||
{"name": "name", "label": "姓名", "required": False, "default": "广州老广", "type": "str"},
|
||||
{"name": "age", "label": "年龄", "required": False, "default": 18, "type": "int"},
|
||||
]
|
||||
|
||||
|
|
Loading…
Reference in New Issue