Merge pull request #9380 from jumpserver/pr@dev@perf_asset_info

perf: 优化 asset info
pull/9384/head
老广 2023-01-31 19:37:51 +08:00 committed by GitHub
commit fa6d819f10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 181 additions and 162 deletions

View File

@ -10,12 +10,12 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_database: "{{ jms_asset.specific.db_name }}"
ssl: "{{ jms_asset.specific.use_ssl }}"
ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}"
ssl_certfile: "{{ jms_asset.specific.client_key }}"
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.specific.allow_invalid_cert}}"
- tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}"
register: db_info
- name: Display MongoDB version
@ -29,13 +29,13 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_database: "{{ jms_asset.specific.db_name }}"
ssl: "{{ jms_asset.specific.use_ssl }}"
ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}"
ssl_certfile: "{{ jms_asset.specific.client_key }}"
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.specific.allow_invalid_cert}}"
db: "{{ jms_asset.specific.db_name }}"
- 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
@ -47,12 +47,12 @@
login_password: "{{ account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_database: "{{ jms_asset.specific.db_name }}"
ssl: "{{ jms_asset.specific.use_ssl }}"
ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}"
ssl_certfile: "{{ jms_asset.specific.client_key }}"
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.specific.allow_invalid_cert}}"
- tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}"
when:
- db_info is succeeded
- change_info is succeeded
- db_info is succeeded
- change_info is succeeded

View File

@ -10,7 +10,7 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_database: "{{ jms_asset.specific.db_name }}"
login_database: "{{ jms_asset.spec_info.db_name }}"
mode: "{{ jms_account.mode }}"
register: db_info
@ -25,7 +25,7 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_database: "{{ jms_asset.specific.db_name }}"
login_database: "{{ jms_asset.spec_info.db_name }}"
mode: "{{ jms_account.mode }}"
name: "{{ account.username }}"
password: "{{ account.secret }}"
@ -38,8 +38,8 @@
login_password: "{{ account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_database: "{{ jms_asset.specific.db_name }}"
login_database: "{{ jms_asset.spec_info.db_name }}"
mode: "{{ account.mode }}"
when:
- db_info is succeeded
- change_info is succeeded
- db_info is succeeded
- change_info is succeeded

View File

@ -10,7 +10,7 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_db: "{{ jms_asset.specific.db_name }}"
login_db: "{{ jms_asset.spec_info.db_name }}"
register: db_info
- name: Display PostgreSQL version
@ -24,7 +24,7 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
db: "{{ jms_asset.specific.db_name }}"
db: "{{ jms_asset.spec_info.db_name }}"
name: "{{ account.username }}"
password: "{{ account.secret }}"
when: db_info is succeeded
@ -36,7 +36,7 @@
login_password: "{{ account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
db: "{{ jms_asset.specific.db_name }}"
db: "{{ jms_asset.spec_info.db_name }}"
when:
- db_info is succeeded
- change_info is succeeded
- db_info is succeeded
- change_info is succeeded

View File

@ -10,38 +10,38 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.specific.db_name }}'
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: SQLServer version
set_fact:
info:
version: "{{ db_info.query_results[0][0][0][0].splitlines()[0] }}"
- debug:
var: info
- 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.specific.db_name }}'
script: "ALTER LOGIN {{ account.username }} WITH PASSWORD = '{{ account.secret }}'; select @@version"
when: db_info is succeeded
register: change_info
- 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: db_info is succeeded
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.specific.db_name }}'
script: |
SELECT @@version
when:
- db_info is succeeded
- change_info is succeeded
- 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

View File

@ -10,12 +10,12 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_database: "{{ jms_asset.specific.db_name }}"
ssl: "{{ jms_asset.specific.use_ssl }}"
ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}"
ssl_certfile: "{{ jms_asset.specific.client_key }}"
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.specific.allow_invalid_cert}}"
- tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}"
filter: users
register: db_info

View File

@ -10,7 +10,7 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_database: "{{ jms_asset.specific.db_name }}"
login_database: "{{ jms_asset.spec_info.db_name }}"
mode: "{{ jms_account.mode }}"
filter: users
register: db_info

View File

@ -10,7 +10,7 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_db: "{{ jms_asset.specific.db_name }}"
login_db: "{{ jms_asset.spec_info.db_name }}"
filter: "roles"
register: db_info

View File

@ -10,9 +10,9 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_database: "{{ jms_asset.specific.db_name }}"
ssl: "{{ jms_asset.specific.use_ssl }}"
ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}"
ssl_certfile: "{{ jms_asset.specific.client_key }}"
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.specific.allow_invalid_cert}}"
- tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}"

View File

@ -10,5 +10,5 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_database: "{{ jms_asset.specific.db_name }}"
login_database: "{{ jms_asset.spec_info.db_name }}"
mode: "{{ jms_account.mode }}"

View File

@ -10,4 +10,4 @@
login_password: "{{ account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
db: "{{ jms_asset.specific.db_name }}"
db: "{{ jms_asset.spec_info.db_name }}"

View File

@ -10,6 +10,6 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.specific.db_name }}'
name: '{{ jms_asset.spec_info.db_name }}'
script: |
SELECT @@version

View File

@ -1,7 +1,7 @@
from django.db.models import QuerySet
from common.utils import get_logger
from accounts.const import AutomationTypes, Connectivity
from common.utils import get_logger
from ..base.manager import PushOrVerifyHostCallbackMixin, AccountBasePlaybookManager
logger = get_logger(__name__)
@ -29,4 +29,4 @@ class VerifyAccountManager(PushOrVerifyHostCallbackMixin, AccountBasePlaybookMan
def on_host_error(self, host, error, result):
account = self.host_account_mapper.get(host)
account.set_connectivity(Connectivity.FAILED)
account.set_connectivity(Connectivity.ERR)

View File

@ -29,8 +29,7 @@ class Migration(migrations.Migration):
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('org_id',
models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('connectivity', models.CharField(choices=[('unknown', 'Unknown'), ('ok', 'Ok'), ('failed', 'Failed')],
default='unknown', max_length=16, verbose_name='Connectivity')),
('connectivity', models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity')),
('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')),
('name', models.CharField(max_length=128, verbose_name='Name')),
('username', models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username')),

View File

@ -50,7 +50,7 @@ class BaseAccount(JMSOrgBaseModel):
return bool(self.username)
@property
def specific(self):
def spec_info(self):
data = {}
if self.secret_type != SecretType.SSH_KEY:
return data

View File

@ -68,14 +68,14 @@ class BaseAccountSerializer(AuthValidateMixin, BulkOrgResourceModelSerializer):
fields_mini = ['id', 'name', 'username']
fields_small = fields_mini + [
'secret_type', 'secret', 'has_secret', 'passphrase',
'privileged', 'is_active', 'specific',
'privileged', 'is_active', 'spec_info',
]
fields_other = ['created_by', 'date_created', 'date_updated', 'comment']
fields = fields_small + fields_other
read_only_fields = [
'has_secret', 'specific',
'has_secret', 'spec_info',
'date_verified', 'created_by', 'date_created',
]
extra_kwargs = {
'specific': {'label': _('Specific')},
'spec_info': {'label': _('Spec info')},
}

View File

@ -2,7 +2,6 @@
#
import django_filters
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
from rest_framework.decorators import action
from rest_framework.response import Response
@ -72,11 +71,13 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet):
("platform", serializers.PlatformSerializer),
("suggestion", serializers.MiniAssetSerializer),
("gateways", serializers.GatewaySerializer),
("spec_info", serializers.SpecSerializer),
)
rbac_perms = (
("match", "assets.match_asset"),
("platform", "assets.view_platform"),
("gateways", "assets.view_gateway"),
("spec_info", "assets.view_asset"),
)
extra_filter_backends = [LabelFilterBackend, IpInFilterBackend, NodeFilterBackend]
@ -94,6 +95,11 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet):
serializer = super().get_serializer(instance=asset.platform)
return Response(serializer.data)
@action(methods=["GET"], detail=True, url_path="spec-info")
def spec_info(self, *args, **kwargs):
asset = super().get_object()
return Response(asset.spec_info)
@action(methods=["GET"], detail=True, url_path="gateways")
def gateways(self, *args, **kwargs):
asset = self.get_object()

View File

@ -10,12 +10,12 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_database: "{{ jms_asset.specific.db_name }}"
ssl: "{{ jms_asset.specific.use_ssl }}"
ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}"
ssl_certfile: "{{ jms_asset.specific.client_key }}"
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.specific.allow_invalid_cert}}"
- tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}"
register: db_info
- name: Define info by set_fact

View File

@ -10,7 +10,7 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_database: "{{ jms_asset.specific.db_name }}"
login_database: "{{ jms_asset.spec_info.db_name }}"
mode: "{{ jms_account.mode }}"
register: db_info

View File

@ -10,7 +10,7 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_db: "{{ jms_asset.specific.db_name }}"
login_db: "{{ jms_asset.spec_info.db_name }}"
register: db_info
- name: Define info by set_fact

View File

@ -10,9 +10,9 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_database: "{{ jms_asset.specific.db_name }}"
ssl: "{{ jms_asset.specific.use_ssl }}"
ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}"
ssl_certfile: "{{ jms_asset.specific.client_key }}"
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.specific.allow_invalid_cert}}"
- tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}"

View File

@ -10,5 +10,5 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_database: "{{ jms_asset.specific.db_name }}"
login_database: "{{ jms_asset.spec_info.db_name }}"
mode: "{{ jms_account.mode }}"

View File

@ -10,4 +10,4 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
login_db: "{{ jms_asset.specific.db_name }}"
login_db: "{{ jms_asset.spec_info.db_name }}"

View File

@ -10,6 +10,6 @@
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.specific.db_name }}'
name: '{{ jms_asset.spec_info.db_name }}'
script: |
SELECT @@version

View File

@ -1,5 +1,5 @@
from common.utils import get_logger
from assets.const import AutomationTypes, Connectivity
from common.utils import get_logger
from ..base.manager import BasePlaybookManager
logger = get_logger(__name__)
@ -28,7 +28,7 @@ class PingManager(BasePlaybookManager):
def on_host_error(self, host, error, result):
asset, account = self.host_asset_and_account_mapper.get(host)
asset.set_connectivity(Connectivity.FAILED)
asset.set_connectivity(Connectivity.ERR)
if not account:
return
account.set_connectivity(Connectivity.FAILED)
account.set_connectivity(Connectivity.ERR)

View File

@ -1,12 +1,12 @@
import socket
import paramiko
import paramiko
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from common.utils import get_logger
from assets.models import Gateway
from assets.const import AutomationTypes, Connectivity
from assets.models import Gateway
from common.utils import get_logger
logger = get_logger(__name__)
@ -100,10 +100,10 @@ class PingGatewayManager:
@staticmethod
def on_host_error(gateway, account, error):
logger.info('\033[31m {} -> {} 原因: {} \033[0m\n'.format(gateway, account, error))
gateway.set_connectivity(Connectivity.FAILED)
gateway.set_connectivity(Connectivity.ERR)
if not account:
return
account.set_connectivity(Connectivity.FAILED)
account.set_connectivity(Connectivity.ERR)
@staticmethod
def before_runner_start():

View File

@ -3,9 +3,9 @@ from django.utils.translation import ugettext_lazy as _
class Connectivity(TextChoices):
UNKNOWN = 'unknown', _('Unknown')
UNKNOWN = '-', _('Unknown')
OK = 'ok', _('Ok')
FAILED = 'failed', _('Failed')
ERR = 'err', _('Error')
class AutomationTypes(TextChoices):

View File

@ -13,7 +13,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='asset',
name='connectivity',
field=models.CharField(choices=[('unknown', 'Unknown'), ('ok', 'Ok'), ('failed', 'Failed')], default='unknown', max_length=16, verbose_name='Connectivity'),
field=models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity'),
),
migrations.AddField(
model_name='asset',
@ -23,7 +23,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='authbook',
name='connectivity',
field=models.CharField(choices=[('unknown', 'Unknown'), ('ok', 'Ok'), ('failed', 'Failed')], default='unknown', max_length=16, verbose_name='Connectivity'),
field=models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity'),
),
migrations.AddField(
model_name='authbook',
@ -33,7 +33,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='historicalauthbook',
name='connectivity',
field=models.CharField(choices=[('unknown', 'Unknown'), ('ok', 'Ok'), ('failed', 'Failed')], default='unknown', max_length=16, verbose_name='Connectivity'),
field=models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity'),
),
migrations.AddField(
model_name='historicalauthbook',

View File

@ -34,6 +34,13 @@ def migrate_macos_platform(apps, schema_editor):
platform_model.objects.using(db_alias).filter(id=old_macos.id).delete()
def migrate_connectivity(apps, schema_editor):
db_alias = schema_editor.connection.alias
asset_model = apps.get_model('assets', 'Asset')
asset_model.objects.using(db_alias).filter(connectivity='unknown').update(connectivity='-')
asset_model.objects.using(db_alias).filter(connectivity='failed').update(connectivity='err')
class Migration(migrations.Migration):
dependencies = [
('assets', '0096_auto_20220426_1550'),
@ -43,4 +50,5 @@ class Migration(migrations.Migration):
migrations.RunPython(create_internal_platforms),
migrations.RunPython(update_user_platforms),
migrations.RunPython(migrate_macos_platform),
migrations.RunPython(migrate_connectivity),
]

View File

@ -52,11 +52,7 @@ class Migration(migrations.Migration):
migrations.AlterModelOptions(
name='asset',
options={'ordering': ['name'],
'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'),
('test_assetconnectivity', 'Can test asset connectivity'),
('push_assetaccount', 'Can push account to asset'),
('match_asset', 'Can match asset'), ('add_assettonode', 'Add asset to node'),
('move_assettonode', 'Move asset to node')], 'verbose_name': 'Asset'},
'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('push_assetaccount', 'Can push account to asset'), ('test_account', 'Can verify account'), ('match_asset', 'Can match asset'), ('add_assettonode', 'Add asset to node'), ('move_assettonode', 'Move asset to node')], 'verbose_name': 'Asset'},
),
migrations.AlterUniqueTogether(
name='accountbackupplan',

View File

@ -10,8 +10,8 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _
from assets import const
from common.utils import lazyproperty
from common.db.fields import EncryptMixin
from common.utils import lazyproperty
from orgs.mixins.models import OrgManager, JMSOrgBaseModel
from ..base import AbsConnectivity
from ..platform import Platform
@ -113,45 +113,47 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel):
verbose_name=_("Nodes"))
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
labels = models.ManyToManyField('assets.Label', blank=True, related_name='assets', verbose_name=_("Labels"))
info = models.JSONField(verbose_name='Info', default=dict, blank=True)
info = models.JSONField(verbose_name='Info', default=dict, blank=True) # 资产的一些信息,如 硬件信息
objects = AssetManager.from_queryset(AssetQuerySet)()
def __str__(self):
return '{0.name}({0.address})'.format(self)
@property
def specific(self):
instance = getattr(self, self.category, None)
if not instance:
return {}
specific_fields = self.get_specific_fields(instance)
@staticmethod
def get_spec_values(instance, fields):
info = {}
for i in specific_fields:
for i in fields:
v = getattr(instance, i.name)
if isinstance(i, models.JSONField) and not isinstance(v, (list, dict)):
v = json.loads(v)
info[i.name] = v
return info
@property
@lazyproperty
def spec_info(self):
instance = getattr(self, self.category, None)
if not instance:
return []
specific_fields = self.get_specific_fields(instance)
info = [
{
'label': i.verbose_name,
'name': i.name,
'value': getattr(instance, i.name)
}
for i in specific_fields
]
return info
return {}
spec_fields = self.get_spec_fields(instance)
return self.get_spec_values(instance, spec_fields)
@staticmethod
def get_spec_fields(instance, secret=False):
spec_fields = [i for i in instance._meta.local_fields if i.name != 'asset_ptr']
spec_fields = [i for i in spec_fields if isinstance(i, EncryptMixin) == secret]
return spec_fields
@lazyproperty
def enabled_info(self):
def secret_info(self):
instance = getattr(self, self.category, None)
if not instance:
return {}
spec_fields = self.get_spec_fields(instance, secret=True)
return self.get_spec_values(instance, spec_fields)
@lazyproperty
def auto_info(self):
platform = self.platform
automation = self.platform.automation
return {
@ -165,12 +167,6 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel):
'gather_accounts_enabled': automation.gather_accounts_enabled,
}
@staticmethod
def get_specific_fields(instance):
specific_fields = [i for i in instance._meta.local_fields if i.name != 'asset_ptr']
specific_fields = [i for i in specific_fields if not isinstance(i, EncryptMixin)]
return specific_fields
def get_target_ip(self):
return self.address

View File

@ -18,7 +18,7 @@ __all__ = [
'AssetSerializer', 'AssetSimpleSerializer', 'MiniAssetSerializer',
'AssetTaskSerializer', 'AssetsTaskSerializer', 'AssetProtocolsSerializer',
'AssetDetailSerializer', 'DetailMixin', 'AssetAccountSerializer',
'AccountSecretSerializer'
'AccountSecretSerializer', 'SpecSerializer'
]
@ -113,13 +113,25 @@ class AccountSecretSerializer(SecretReadableMixin, CommonModelSerializer):
}
class SpecSerializer(serializers.Serializer):
# 数据库
db_name = serializers.CharField(label=_("Database"), max_length=128, required=False)
use_ssl = serializers.BooleanField(label=_("Use SSL"), required=False)
allow_invalid_cert = serializers.BooleanField(label=_("Allow invalid cert"), required=False)
# Web
autofill = serializers.CharField(label=_("Auto fill"), required=False)
username_selector = serializers.CharField(label=_("Username selector"), required=False)
password_selector = serializers.CharField(label=_("Password selector"), required=False)
submit_selector = serializers.CharField(label=_("Submit selector"), required=False)
script = serializers.JSONField(label=_("Script"), required=False)
class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSerializer):
category = LabeledChoiceField(choices=Category.choices, read_only=True, label=_('Category'))
type = LabeledChoiceField(choices=AllTypes.choices(), read_only=True, label=_('Type'))
labels = AssetLabelSerializer(many=True, required=False, label=_('Label'))
protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'))
accounts = AssetAccountSerializer(many=True, required=False, write_only=True, label=_('Account'))
enabled_info = serializers.DictField(read_only=True, label=_('Enabled info'))
class Meta:
model = Asset
@ -127,11 +139,11 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali
fields_small = fields_mini + ['is_active', 'comment']
fields_fk = ['domain', 'platform']
fields_m2m = [
'nodes', 'labels', 'protocols', 'nodes_display', 'accounts'
'nodes', 'labels', 'protocols',
'nodes_display', 'accounts'
]
read_only_fields = [
'category', 'type', 'info', 'enabled_info',
'connectivity', 'date_verified',
'category', 'type', 'connectivity', 'date_verified',
'created_by', 'date_created'
]
fields = fields_small + fields_fk + fields_m2m + read_only_fields
@ -235,11 +247,13 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali
class DetailMixin(serializers.Serializer):
accounts = AssetAccountSerializer(many=True, required=False, label=_('Accounts'))
spec_info = serializers.DictField(label=_('Spec info'), read_only=True)
auto_info = serializers.DictField(read_only=True, label=_('Auto info'))
def get_field_names(self, declared_fields, info):
names = super().get_field_names(declared_fields, info)
names.extend([
'accounts', 'info', 'specific', 'spec_info'
'accounts', 'info', 'spec_info', 'auto_info'
])
return names

View File

@ -31,7 +31,8 @@ class _ConnectionTokenAssetSerializer(serializers.ModelSerializer):
model = Asset
fields = [
'id', 'name', 'address', 'protocols',
'category', 'type', 'org_id', 'specific'
'category', 'type', 'org_id', 'spec_info',
'secret_info',
]

View File

@ -105,7 +105,7 @@ class JMSInventory:
'id': str(asset.id), 'name': asset.name, 'address': asset.address,
'type': asset.type, 'category': asset.category,
'protocol': asset.protocol, 'port': asset.port,
'specific': asset.specific,
'spec_info': asset.spec_info,
'protocols': [{'name': p.name, 'port': p.port} for p in protocols],
},
'jms_account': {

View File

@ -4,13 +4,13 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from accounts.models import Account
from assets.const import Category, AllTypes
from assets.models import Node, Asset, Platform
from accounts.models import Account
from assets.serializers.asset.common import AssetProtocolsSerializer
from common.serializers.fields import ObjectRelatedField, LabeledChoiceField
from perms.serializers.permission import ActionChoicesField
from orgs.mixins.serializers import OrgResourceModelSerializerMixin
from perms.serializers.permission import ActionChoicesField
__all__ = [
'NodePermedSerializer', 'AssetPermedSerializer',
@ -32,7 +32,7 @@ class AssetPermedSerializer(OrgResourceModelSerializerMixin):
"id", "name", "address", 'domain', 'platform',
"comment", "org_id", "is_active",
]
fields = only_fields + ['protocols', 'category', 'type', 'specific'] + ['org_name']
fields = only_fields + ['protocols', 'category', 'type', 'spec_info'] + ['org_name']
read_only_fields = fields

View File

@ -87,13 +87,13 @@ class WebAPP(object):
self.account = account
self.platform = platform
self.extra_data = self.asset.specific
self.extra_data = self.asset.spec_info
self._steps = list()
autofill_type = self.asset.specific.autofill
autofill_type = self.asset.spec_info.autofill
if autofill_type == "basic":
self._steps = self._default_custom_steps()
elif autofill_type == "script":
script_list = self.asset.specific.script
script_list = self.asset.spec_info.script
steps = sorted(script_list, key=lambda step_item: step_item.step)
for item in steps:
val = item.value
@ -105,24 +105,24 @@ class WebAPP(object):
def _default_custom_steps(self) -> list:
account = self.account
specific_property = self.asset.specific
spec_info = self.asset.spec_info
default_steps = [
Step({
"step": 1,
"value": account.username,
"target": specific_property.username_selector,
"target": spec_info.username_selector,
"command": "type"
}),
Step({
"step": 2,
"value": account.secret,
"target": specific_property.password_selector,
"target": spec_info.password_selector,
"command": "type"
}),
Step({
"step": 3,
"value": "",
"target": specific_property.submit_selector,
"target": spec_info.submit_selector,
"command": "click"
})
]

View File

@ -11,7 +11,6 @@ if sys.platform == 'win32':
)
from common import wait_pid, BaseApplication
_default_path = r'C:\Program Files\PremiumSoft\Navicat Premium 16\navicat.exe'
@ -24,7 +23,7 @@ class AppletApplication(BaseApplication):
self.privileged = self.account.privileged
self.host = self.asset.address
self.port = self.asset.get_protocol_port(self.protocol)
self.db = self.asset.specific.db_name
self.db = self.asset.spec_info.db_name
self.name = '%s-%s' % (self.host, self.db)
self.pid = None
self.app = None