mirror of https://github.com/jumpserver/jumpserver
feat: 同步删除远程机器账号
parent
8f82ca9856
commit
eca50874f0
|
@ -1,9 +1,12 @@
|
||||||
from rest_framework.generics import CreateAPIView
|
from rest_framework.generics import CreateAPIView
|
||||||
from rest_framework.response import Response
|
|
||||||
|
|
||||||
from accounts import serializers
|
from accounts import serializers
|
||||||
from accounts.tasks import verify_accounts_connectivity_task, push_accounts_to_assets_task
|
from accounts.permissions import AccountTaskActionPermission
|
||||||
|
from accounts.tasks import (
|
||||||
|
remove_accounts_task, verify_accounts_connectivity_task, push_accounts_to_assets_task
|
||||||
|
)
|
||||||
from assets.exceptions import NotSupportedTemporarilyError
|
from assets.exceptions import NotSupportedTemporarilyError
|
||||||
|
from authentication.permissions import UserConfirmation, ConfirmType
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'AccountsTaskCreateAPI',
|
'AccountsTaskCreateAPI',
|
||||||
|
@ -12,16 +15,16 @@ __all__ = [
|
||||||
|
|
||||||
class AccountsTaskCreateAPI(CreateAPIView):
|
class AccountsTaskCreateAPI(CreateAPIView):
|
||||||
serializer_class = serializers.AccountTaskSerializer
|
serializer_class = serializers.AccountTaskSerializer
|
||||||
|
permission_classes = (AccountTaskActionPermission,)
|
||||||
|
|
||||||
def check_permissions(self, request):
|
def get_permissions(self):
|
||||||
act = request.data.get('action')
|
act = self.request.data.get('action')
|
||||||
if act == 'push':
|
if act == 'remove':
|
||||||
code = 'accounts.push_account'
|
self.permission_classes = [
|
||||||
else:
|
AccountTaskActionPermission,
|
||||||
code = 'accounts.verify_account'
|
UserConfirmation.require(ConfirmType.PASSWORD)
|
||||||
has = request.user.has_perm(code)
|
]
|
||||||
if not has:
|
return super().get_permissions()
|
||||||
self.permission_denied(request)
|
|
||||||
|
|
||||||
def perform_create(self, serializer):
|
def perform_create(self, serializer):
|
||||||
data = serializer.validated_data
|
data = serializer.validated_data
|
||||||
|
@ -31,6 +34,10 @@ class AccountsTaskCreateAPI(CreateAPIView):
|
||||||
|
|
||||||
if data['action'] == 'push':
|
if data['action'] == 'push':
|
||||||
task = push_accounts_to_assets_task.delay(account_ids, params)
|
task = push_accounts_to_assets_task.delay(account_ids, params)
|
||||||
|
elif data['action'] == 'remove':
|
||||||
|
gather_accounts = data.get('gather_accounts', [])
|
||||||
|
gather_account_ids = [str(a.id) for a in gather_accounts]
|
||||||
|
task = remove_accounts_task.delay(gather_account_ids)
|
||||||
else:
|
else:
|
||||||
account = accounts[0]
|
account = accounts[0]
|
||||||
asset = account.asset
|
asset = account.asset
|
||||||
|
@ -43,9 +50,3 @@ class AccountsTaskCreateAPI(CreateAPIView):
|
||||||
data["task"] = task.id
|
data["task"] = task.id
|
||||||
setattr(serializer, '_data', data)
|
setattr(serializer, '_data', data)
|
||||||
return task
|
return task
|
||||||
|
|
||||||
def get_exception_handler(self):
|
|
||||||
def handler(e, context):
|
|
||||||
return Response({"error": str(e)}, status=401)
|
|
||||||
|
|
||||||
return handler
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
from .push_account.manager import PushAccountManager
|
|
||||||
from .change_secret.manager import ChangeSecretManager
|
|
||||||
from .verify_account.manager import VerifyAccountManager
|
|
||||||
from .backup_account.manager import AccountBackupManager
|
from .backup_account.manager import AccountBackupManager
|
||||||
|
from .change_secret.manager import ChangeSecretManager
|
||||||
from .gather_accounts.manager import GatherAccountsManager
|
from .gather_accounts.manager import GatherAccountsManager
|
||||||
|
from .push_account.manager import PushAccountManager
|
||||||
|
from .remove_account.manager import RemoveAccountManager
|
||||||
|
from .verify_account.manager import VerifyAccountManager
|
||||||
from .verify_gateway_account.manager import VerifyGatewayAccountManager
|
from .verify_gateway_account.manager import VerifyGatewayAccountManager
|
||||||
from ..const import AutomationTypes
|
from ..const import AutomationTypes
|
||||||
|
|
||||||
|
@ -12,6 +13,7 @@ class ExecutionManager:
|
||||||
AutomationTypes.push_account: PushAccountManager,
|
AutomationTypes.push_account: PushAccountManager,
|
||||||
AutomationTypes.change_secret: ChangeSecretManager,
|
AutomationTypes.change_secret: ChangeSecretManager,
|
||||||
AutomationTypes.verify_account: VerifyAccountManager,
|
AutomationTypes.verify_account: VerifyAccountManager,
|
||||||
|
AutomationTypes.remove_account: RemoveAccountManager,
|
||||||
AutomationTypes.gather_accounts: GatherAccountsManager,
|
AutomationTypes.gather_accounts: GatherAccountsManager,
|
||||||
AutomationTypes.verify_gateway_account: VerifyGatewayAccountManager,
|
AutomationTypes.verify_gateway_account: VerifyGatewayAccountManager,
|
||||||
# TODO 后期迁移到自动化策略中
|
# TODO 后期迁移到自动化策略中
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
- hosts: mongodb
|
||||||
|
gather_facts: no
|
||||||
|
vars:
|
||||||
|
ansible_python_interpreter: /opt/py3/bin/python
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: "Remove account"
|
||||||
|
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 | default('') }}"
|
||||||
|
ssl_certfile: "{{ jms_asset.secret_info.client_key | default('') }}"
|
||||||
|
connection_options:
|
||||||
|
- tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}"
|
||||||
|
db: "{{ jms_asset.spec_info.db_name }}"
|
||||||
|
name: "{{ account.username }}"
|
||||||
|
state: absent
|
|
@ -0,0 +1,12 @@
|
||||||
|
id: remove_account_mongodb
|
||||||
|
name: "{{ 'MongoDB account remove' | trans }}"
|
||||||
|
category: database
|
||||||
|
type:
|
||||||
|
- mongodb
|
||||||
|
method: remove_account
|
||||||
|
|
||||||
|
i18n:
|
||||||
|
MongoDB account remove:
|
||||||
|
zh: 使用 Ansible 模块 mongodb 删除账号
|
||||||
|
ja: Ansible モジュール mongodb を使用してアカウントを削除する
|
||||||
|
en: Delete account using Ansible module mongodb
|
|
@ -0,0 +1,18 @@
|
||||||
|
- hosts: mysql
|
||||||
|
gather_facts: no
|
||||||
|
vars:
|
||||||
|
ansible_python_interpreter: /opt/py3/bin/python
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: "Remove account"
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
login_user: "{{ jms_account.username }}"
|
||||||
|
login_password: "{{ jms_account.secret }}"
|
||||||
|
login_host: "{{ jms_asset.address }}"
|
||||||
|
login_port: "{{ jms_asset.port }}"
|
||||||
|
check_hostname: "{{ check_ssl if check_ssl else omit }}"
|
||||||
|
ca_cert: "{{ jms_asset.secret_info.ca_cert | default(omit) if check_ssl else omit }}"
|
||||||
|
client_cert: "{{ jms_asset.secret_info.client_cert | default(omit) if check_ssl else omit }}"
|
||||||
|
client_key: "{{ jms_asset.secret_info.client_key | default(omit) if check_ssl else omit }}"
|
||||||
|
name: "{{ account.username }}"
|
||||||
|
state: absent
|
|
@ -0,0 +1,14 @@
|
||||||
|
id: remove_account_mysql
|
||||||
|
name: "{{ 'MySQL account remove' | trans }}"
|
||||||
|
category: database
|
||||||
|
type:
|
||||||
|
- mysql
|
||||||
|
- mariadb
|
||||||
|
method: remove_account
|
||||||
|
|
||||||
|
i18n:
|
||||||
|
MySQL account remove:
|
||||||
|
zh: 使用 Ansible 模块 mysql_user 删除账号
|
||||||
|
ja: Ansible モジュール mysql_user を使用してアカウントを削除します
|
||||||
|
en: Use the Ansible module mysql_user to delete the account
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
- hosts: oracle
|
||||||
|
gather_facts: no
|
||||||
|
vars:
|
||||||
|
ansible_python_interpreter: /opt/py3/bin/python
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: "Remove account"
|
||||||
|
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 }}"
|
||||||
|
state: absent
|
|
@ -0,0 +1,12 @@
|
||||||
|
id: remove_account_oracle
|
||||||
|
name: "{{ 'Oracle account remove' | trans }}"
|
||||||
|
category: database
|
||||||
|
type:
|
||||||
|
- oracle
|
||||||
|
method: remove_account
|
||||||
|
|
||||||
|
i18n:
|
||||||
|
Oracle account remove:
|
||||||
|
zh: 使用 Python 模块 oracledb 删除账号
|
||||||
|
ja: Python モジュール oracledb を使用してアカウントを検証する
|
||||||
|
en: Using Python module oracledb to verify account
|
|
@ -0,0 +1,15 @@
|
||||||
|
- hosts: postgresql
|
||||||
|
gather_facts: no
|
||||||
|
vars:
|
||||||
|
ansible_python_interpreter: /opt/py3/bin/python
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: "Remove account"
|
||||||
|
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 }}"
|
||||||
|
state: absent
|
|
@ -0,0 +1,12 @@
|
||||||
|
id: remove_account_postgresql
|
||||||
|
name: "{{ 'PostgreSQL account remove' | trans }}"
|
||||||
|
category: database
|
||||||
|
type:
|
||||||
|
- postgresql
|
||||||
|
method: remove_account
|
||||||
|
|
||||||
|
i18n:
|
||||||
|
PostgreSQL account remove:
|
||||||
|
zh: 使用 Ansible 模块 postgresql_user 删除账号
|
||||||
|
ja: Ansible モジュール postgresql_user を使用してアカウントを削除します
|
||||||
|
en: Use the Ansible module postgresql_user to delete the account
|
|
@ -0,0 +1,14 @@
|
||||||
|
- hosts: sqlserver
|
||||||
|
gather_facts: no
|
||||||
|
vars:
|
||||||
|
ansible_python_interpreter: /opt/py3/bin/python
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: "Remove account"
|
||||||
|
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: "DROP USER {{ account.username }}"
|
|
@ -0,0 +1,12 @@
|
||||||
|
id: remove_account_sqlserver
|
||||||
|
name: "{{ 'SQLServer account remove' | trans }}"
|
||||||
|
category: database
|
||||||
|
type:
|
||||||
|
- sqlserver
|
||||||
|
method: remove_account
|
||||||
|
|
||||||
|
i18n:
|
||||||
|
SQLServer account remove:
|
||||||
|
zh: 使用 Ansible 模块 mssql 删除账号
|
||||||
|
ja: Ansible モジュール mssql を使用してアカウントを削除する
|
||||||
|
en: Use Ansible module mssql to delete account
|
|
@ -0,0 +1,25 @@
|
||||||
|
- hosts: demo
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- name: "Get user home directory path"
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: "getent passwd {{ account.username }} | cut -d: -f6"
|
||||||
|
register: user_home_dir
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: "Check if user home directory exists"
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ user_home_dir.stdout }}"
|
||||||
|
register: home_dir
|
||||||
|
when: user_home_dir.stdout != ""
|
||||||
|
|
||||||
|
- name: "Rename user home directory if it exists"
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "mv {{ user_home_dir.stdout }} {{ user_home_dir.stdout }}.bak"
|
||||||
|
when: home_dir.stat.exists and user_home_dir.stdout != ""
|
||||||
|
|
||||||
|
- name: "Remove account"
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ account.username }}"
|
||||||
|
state: absent
|
||||||
|
remove: "{{ home_dir.stat.exists }}"
|
|
@ -0,0 +1,13 @@
|
||||||
|
id: remove_account_posix
|
||||||
|
name: "{{ 'Posix account remove' | trans }}"
|
||||||
|
category: host
|
||||||
|
type:
|
||||||
|
- linux
|
||||||
|
- unix
|
||||||
|
method: remove_account
|
||||||
|
|
||||||
|
i18n:
|
||||||
|
Posix account remove:
|
||||||
|
zh: 使用 Ansible 模块 user 删除账号
|
||||||
|
ja: Ansible モジュール ユーザーを使用してアカウントを削除します
|
||||||
|
en: Use the Ansible module user to delete the account
|
|
@ -0,0 +1,9 @@
|
||||||
|
- hosts: windows
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- name: "Remove account"
|
||||||
|
ansible.windows.win_user:
|
||||||
|
name: "{{ account.username }}"
|
||||||
|
state: absent
|
||||||
|
purge: yes
|
||||||
|
force: yes
|
|
@ -0,0 +1,13 @@
|
||||||
|
id: remove_account_windows
|
||||||
|
name: "{{ 'Windows account remove' | trans }}"
|
||||||
|
version: 1
|
||||||
|
method: remove_account
|
||||||
|
category: host
|
||||||
|
type:
|
||||||
|
- windows
|
||||||
|
|
||||||
|
i18n:
|
||||||
|
Windows account remove:
|
||||||
|
zh: 使用 Ansible 模块 win_user 删除账号
|
||||||
|
ja: Ansible モジュール win_user を使用してアカウントを削除する
|
||||||
|
en: Use the Ansible module win_user to delete an account
|
|
@ -0,0 +1,67 @@
|
||||||
|
import os
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
from django.db.models import QuerySet
|
||||||
|
|
||||||
|
from accounts.const import AutomationTypes
|
||||||
|
from accounts.models import Account
|
||||||
|
from common.utils import get_logger
|
||||||
|
from ..base.manager import AccountBasePlaybookManager
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveAccountManager(AccountBasePlaybookManager):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.host_account_mapper = {}
|
||||||
|
|
||||||
|
def prepare_runtime_dir(self):
|
||||||
|
path = super().prepare_runtime_dir()
|
||||||
|
ansible_config_path = os.path.join(path, 'ansible.cfg')
|
||||||
|
|
||||||
|
with open(ansible_config_path, 'w') as f:
|
||||||
|
f.write('[ssh_connection]\n')
|
||||||
|
f.write('ssh_args = -o ControlMaster=no -o ControlPersist=no\n')
|
||||||
|
return path
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def method_type(cls):
|
||||||
|
return AutomationTypes.remove_account
|
||||||
|
|
||||||
|
def get_gather_accounts(self, privilege_account, gather_accounts: QuerySet):
|
||||||
|
gather_account_ids = self.execution.snapshot['gather_accounts']
|
||||||
|
gather_accounts = gather_accounts.filter(id__in=gather_account_ids)
|
||||||
|
gather_accounts = gather_accounts.exclude(
|
||||||
|
username__in=[privilege_account.username, 'root', 'Administrator']
|
||||||
|
)
|
||||||
|
return gather_accounts
|
||||||
|
|
||||||
|
def host_callback(self, host, asset=None, account=None, automation=None, path_dir=None, **kwargs):
|
||||||
|
if host.get('error'):
|
||||||
|
return host
|
||||||
|
|
||||||
|
gather_accounts = asset.gatheredaccount_set.all()
|
||||||
|
gather_accounts = self.get_gather_accounts(account, gather_accounts)
|
||||||
|
|
||||||
|
inventory_hosts = []
|
||||||
|
|
||||||
|
for gather_account in gather_accounts:
|
||||||
|
h = deepcopy(host)
|
||||||
|
h['name'] += '(' + gather_account.username + ')'
|
||||||
|
self.host_account_mapper[h['name']] = (asset, gather_account)
|
||||||
|
h['account'] = {'username': gather_account.username}
|
||||||
|
inventory_hosts.append(h)
|
||||||
|
return inventory_hosts
|
||||||
|
|
||||||
|
def on_host_success(self, host, result):
|
||||||
|
tuple_asset_gather_account = self.host_account_mapper.get(host)
|
||||||
|
if not tuple_asset_gather_account:
|
||||||
|
return
|
||||||
|
asset, gather_account = tuple_asset_gather_account
|
||||||
|
Account.objects.filter(
|
||||||
|
asset_id=asset.id,
|
||||||
|
username=gather_account.username
|
||||||
|
).delete()
|
||||||
|
gather_account.delete()
|
|
@ -1,4 +1,4 @@
|
||||||
- hosts: mongdb
|
- hosts: mongodb
|
||||||
gather_facts: no
|
gather_facts: no
|
||||||
vars:
|
vars:
|
||||||
ansible_python_interpreter: /opt/py3/bin/python
|
ansible_python_interpreter: /opt/py3/bin/python
|
||||||
|
|
|
@ -24,6 +24,7 @@ class AutomationTypes(models.TextChoices):
|
||||||
push_account = 'push_account', _('Push account')
|
push_account = 'push_account', _('Push account')
|
||||||
change_secret = 'change_secret', _('Change secret')
|
change_secret = 'change_secret', _('Change secret')
|
||||||
verify_account = 'verify_account', _('Verify account')
|
verify_account = 'verify_account', _('Verify account')
|
||||||
|
remove_account = 'remove_account', _('Remove account')
|
||||||
gather_accounts = 'gather_accounts', _('Gather accounts')
|
gather_accounts = 'gather_accounts', _('Gather accounts')
|
||||||
verify_gateway_account = 'verify_gateway_account', _('Verify gateway account')
|
verify_gateway_account = 'verify_gateway_account', _('Verify gateway account')
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('accounts', '0006_gatheredaccount'),
|
('accounts', '0006_gatheredaccount'),
|
||||||
]
|
]
|
||||||
|
@ -12,6 +11,13 @@ class Migration(migrations.Migration):
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AlterModelOptions(
|
migrations.AlterModelOptions(
|
||||||
name='account',
|
name='account',
|
||||||
options={'permissions': [('view_accountsecret', 'Can view asset account secret'), ('view_historyaccount', 'Can view asset history account'), ('view_historyaccountsecret', 'Can view asset history account secret'), ('verify_account', 'Can verify account'), ('push_account', 'Can push account')], 'verbose_name': 'Account'},
|
options={'permissions': [
|
||||||
|
('view_accountsecret', 'Can view asset account secret'),
|
||||||
|
('view_historyaccount', 'Can view asset history account'),
|
||||||
|
('view_historyaccountsecret', 'Can view asset history account secret'),
|
||||||
|
('verify_account', 'Can verify account'),
|
||||||
|
('push_account', 'Can push account'),
|
||||||
|
('remove_account', 'Can remove account'),
|
||||||
|
], 'verbose_name': 'Account'},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -69,6 +69,7 @@ class Account(AbsConnectivity, LabeledMixin, BaseAccount):
|
||||||
('view_historyaccountsecret', _('Can view asset history account secret')),
|
('view_historyaccountsecret', _('Can view asset history account secret')),
|
||||||
('verify_account', _('Can verify account')),
|
('verify_account', _('Can verify account')),
|
||||||
('push_account', _('Can push account')),
|
('push_account', _('Can push account')),
|
||||||
|
('remove_account', _('Can remove account')),
|
||||||
]
|
]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
from rest_framework import permissions
|
||||||
|
|
||||||
|
|
||||||
|
def check_permissions(request):
|
||||||
|
act = request.data.get('action')
|
||||||
|
if act == 'push':
|
||||||
|
code = 'accounts.push_account'
|
||||||
|
elif act == 'remove':
|
||||||
|
code = 'accounts.remove_account'
|
||||||
|
else:
|
||||||
|
code = 'accounts.verify_account'
|
||||||
|
return request.user.has_perm(code)
|
||||||
|
|
||||||
|
|
||||||
|
class AccountTaskActionPermission(permissions.IsAuthenticated):
|
||||||
|
|
||||||
|
def has_permission(self, request, view):
|
||||||
|
return super().has_permission(request, view) \
|
||||||
|
and check_permissions(request)
|
|
@ -10,7 +10,7 @@ from rest_framework.generics import get_object_or_404
|
||||||
from rest_framework.validators import UniqueTogetherValidator
|
from rest_framework.validators import UniqueTogetherValidator
|
||||||
|
|
||||||
from accounts.const import SecretType, Source, AccountInvalidPolicy
|
from accounts.const import SecretType, Source, AccountInvalidPolicy
|
||||||
from accounts.models import Account, AccountTemplate
|
from accounts.models import Account, AccountTemplate, GatheredAccount
|
||||||
from accounts.tasks import push_accounts_to_assets_task
|
from accounts.tasks import push_accounts_to_assets_task
|
||||||
from assets.const import Category, AllTypes
|
from assets.const import Category, AllTypes
|
||||||
from assets.models import Asset
|
from assets.models import Asset
|
||||||
|
@ -458,11 +458,15 @@ class AccountTaskSerializer(serializers.Serializer):
|
||||||
('test', 'test'),
|
('test', 'test'),
|
||||||
('verify', 'verify'),
|
('verify', 'verify'),
|
||||||
('push', 'push'),
|
('push', 'push'),
|
||||||
|
('remove', 'remove'),
|
||||||
)
|
)
|
||||||
action = serializers.ChoiceField(choices=ACTION_CHOICES, write_only=True)
|
action = serializers.ChoiceField(choices=ACTION_CHOICES, write_only=True)
|
||||||
accounts = serializers.PrimaryKeyRelatedField(
|
accounts = serializers.PrimaryKeyRelatedField(
|
||||||
queryset=Account.objects, required=False, allow_empty=True, many=True
|
queryset=Account.objects, required=False, allow_empty=True, many=True
|
||||||
)
|
)
|
||||||
|
gather_accounts = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=GatheredAccount.objects, required=False, allow_empty=True, many=True
|
||||||
|
)
|
||||||
task = serializers.CharField(read_only=True)
|
task = serializers.CharField(read_only=True)
|
||||||
params = serializers.JSONField(
|
params = serializers.JSONField(
|
||||||
decoder=None, encoder=None, required=False,
|
decoder=None, encoder=None, required=False,
|
||||||
|
|
|
@ -2,5 +2,6 @@ from .automation import *
|
||||||
from .backup_account import *
|
from .backup_account import *
|
||||||
from .gather_accounts import *
|
from .gather_accounts import *
|
||||||
from .push_account import *
|
from .push_account import *
|
||||||
|
from .remove_account import *
|
||||||
from .template import *
|
from .template import *
|
||||||
from .verify_account import *
|
from .verify_account import *
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
from celery import shared_task
|
||||||
|
from django.utils.translation import gettext_noop, gettext_lazy as _
|
||||||
|
|
||||||
|
from accounts.const import AutomationTypes
|
||||||
|
from accounts.tasks.common import quickstart_automation_by_snapshot
|
||||||
|
from common.utils import get_logger
|
||||||
|
|
||||||
|
logger = get_logger(__file__)
|
||||||
|
|
||||||
|
__all__ = ['remove_accounts_task']
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task(
|
||||||
|
queue="ansible", verbose_name=_('Remove accounts'),
|
||||||
|
activity_callback=lambda self, gather_account_ids, *args, **kwargs: (gather_account_ids, None)
|
||||||
|
)
|
||||||
|
def remove_accounts_task(gather_account_ids):
|
||||||
|
from accounts.models import GatheredAccount
|
||||||
|
|
||||||
|
gather_accounts = GatheredAccount.objects.filter(
|
||||||
|
id__in=gather_account_ids
|
||||||
|
)
|
||||||
|
task_name = gettext_noop("Remove accounts")
|
||||||
|
|
||||||
|
task_snapshot = {
|
||||||
|
'assets': [str(i.asset_id) for i in gather_accounts],
|
||||||
|
'gather_accounts': [str(i.id) for i in gather_accounts],
|
||||||
|
}
|
||||||
|
|
||||||
|
tp = AutomationTypes.remove_account
|
||||||
|
quickstart_automation_by_snapshot(task_name, tp, task_snapshot)
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Generated by Django 4.1.10 on 2023-12-05 10:03
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
from django.db.models import F
|
||||||
|
|
||||||
|
|
||||||
|
def migrate_automation_ansible_remove_account(apps, *args):
|
||||||
|
automation_model = apps.get_model('assets', 'PlatformAutomation')
|
||||||
|
automation_map = {
|
||||||
|
('oracle',): 'remove_account_oracle',
|
||||||
|
('windows',): 'remove_account_windows',
|
||||||
|
('mongodb',): 'remove_account_mongodb',
|
||||||
|
('linux', 'unix'): 'remove_account_posix',
|
||||||
|
('sqlserver',): 'remove_account_sqlserver',
|
||||||
|
('mysql', 'mariadb'): 'remove_account_mysql',
|
||||||
|
('postgresql',): 'remove_account_postgresql',
|
||||||
|
}
|
||||||
|
|
||||||
|
update_objs = []
|
||||||
|
types = list(reduce(lambda x, y: x + y, automation_map.keys()))
|
||||||
|
qs = automation_model.objects.filter(platform__type__in=types).annotate(tp=F('platform__type'))
|
||||||
|
for automation in qs:
|
||||||
|
for types, method in automation_map.items():
|
||||||
|
if automation.tp in types:
|
||||||
|
automation.remove_account_enabled = True
|
||||||
|
automation.remove_account_method = method
|
||||||
|
break
|
||||||
|
update_objs.append(automation)
|
||||||
|
automation_model.objects.bulk_update(update_objs, ['remove_account_enabled', 'remove_account_method'])
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
('assets', '0125_auto_20231011_1053'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='platformautomation',
|
||||||
|
name='remove_account_enabled',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='Remove account enabled'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='platformautomation',
|
||||||
|
name='remove_account_method',
|
||||||
|
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Remove account method'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='platformautomation',
|
||||||
|
name='remove_account_params',
|
||||||
|
field=models.JSONField(default=dict, verbose_name='Remove account params'),
|
||||||
|
),
|
||||||
|
migrations.RunPython(migrate_automation_ansible_remove_account)
|
||||||
|
]
|
|
@ -72,6 +72,12 @@ class PlatformAutomation(models.Model):
|
||||||
max_length=32, blank=True, null=True, verbose_name=_("Gather facts method")
|
max_length=32, blank=True, null=True, verbose_name=_("Gather facts method")
|
||||||
)
|
)
|
||||||
gather_accounts_params = models.JSONField(default=dict, verbose_name=_("Gather facts params"))
|
gather_accounts_params = models.JSONField(default=dict, verbose_name=_("Gather facts params"))
|
||||||
|
|
||||||
|
remove_account_enabled = models.BooleanField(default=False, verbose_name=_("Remove account enabled"))
|
||||||
|
remove_account_method = models.TextField(
|
||||||
|
max_length=32, blank=True, null=True, verbose_name=_("Remove account method")
|
||||||
|
)
|
||||||
|
remove_account_params = models.JSONField(default=dict, verbose_name=_("Remove account params"))
|
||||||
platform = models.OneToOneField('Platform', on_delete=models.CASCADE, related_name='automation', null=True)
|
platform = models.OneToOneField('Platform', on_delete=models.CASCADE, related_name='automation', null=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue