mirror of https://github.com/jumpserver/jumpserver
Merge branch 'v3' of github.com:jumpserver/jumpserver into v3
commit
572f03d844
|
@ -2,11 +2,8 @@ from .mixin import *
|
||||||
from .platform import *
|
from .platform import *
|
||||||
from .asset import *
|
from .asset import *
|
||||||
from .label import *
|
from .label import *
|
||||||
from .accounts import *
|
from .account import *
|
||||||
from .node import *
|
from .node import *
|
||||||
from .domain import *
|
from .domain import *
|
||||||
from .gathered_user import *
|
from .gathered_user import *
|
||||||
from .favorite_asset import *
|
from .favorite_asset import *
|
||||||
from .account_template import *
|
|
||||||
from .account_backup import *
|
|
||||||
from .account_history import *
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
from .account import *
|
||||||
|
from .backup import *
|
||||||
|
from .history import *
|
||||||
|
from .template import *
|
|
@ -9,9 +9,9 @@ from common.drf.filters import BaseFilterSet, UUIDInFilter
|
||||||
from common.mixins import RecordViewLogMixin
|
from common.mixins import RecordViewLogMixin
|
||||||
from common.permissions import UserConfirmation
|
from common.permissions import UserConfirmation
|
||||||
from authentication.const import ConfirmType
|
from authentication.const import ConfirmType
|
||||||
from ..tasks.account_connectivity import test_accounts_connectivity_manual
|
from assets.tasks.account_connectivity import test_accounts_connectivity_manual
|
||||||
from ..models import Account, Node
|
from assets.models import Account, Node
|
||||||
from .. import serializers
|
from assets import serializers
|
||||||
|
|
||||||
__all__ = ['AccountFilterSet', 'AccountViewSet', 'AccountSecretsViewSet', 'AccountTaskCreateAPI']
|
__all__ = ['AccountFilterSet', 'AccountViewSet', 'AccountSecretsViewSet', 'AccountTaskCreateAPI']
|
||||||
|
|
|
@ -4,9 +4,9 @@ from rest_framework import status, viewsets
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from orgs.mixins.api import OrgBulkModelViewSet
|
from orgs.mixins.api import OrgBulkModelViewSet
|
||||||
from .. import serializers
|
from assets import serializers
|
||||||
from ..tasks import execute_account_backup_plan
|
from assets.tasks import execute_account_backup_plan
|
||||||
from ..models import (
|
from assets.models import (
|
||||||
AccountBackupPlan, AccountBackupPlanExecution
|
AccountBackupPlan, AccountBackupPlanExecution
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
from assets.api.accounts import (
|
from .account import (
|
||||||
AccountFilterSet, AccountViewSet, AccountSecretsViewSet
|
AccountFilterSet, AccountViewSet, AccountSecretsViewSet
|
||||||
)
|
)
|
||||||
from common.mixins import RecordViewLogMixin
|
from common.mixins import RecordViewLogMixin
|
||||||
from .. import serializers
|
from assets import serializers
|
||||||
from ..models import Account
|
from assets.models import Account
|
||||||
|
|
||||||
__all__ = ['AccountHistoryViewSet', 'AccountHistorySecretsViewSet']
|
__all__ = ['AccountHistoryViewSet', 'AccountHistorySecretsViewSet']
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from orgs.mixins.api import OrgBulkModelViewSet
|
from orgs.mixins.api import OrgBulkModelViewSet
|
||||||
from ..models import AccountTemplate
|
from assets.models import AccountTemplate
|
||||||
from .. import serializers
|
from assets import serializers
|
||||||
|
|
||||||
|
|
||||||
class AccountTemplateViewSet(OrgBulkModelViewSet):
|
class AccountTemplateViewSet(OrgBulkModelViewSet):
|
|
@ -38,18 +38,19 @@ class Category(PlatformMixin, ChoicesMixin, models.TextChoices):
|
||||||
return {
|
return {
|
||||||
cls.HOST: {
|
cls.HOST: {
|
||||||
'domain_enabled': True,
|
'domain_enabled': True,
|
||||||
'su_enabled': True,
|
'su_enabled': True, 'su_method': 'sudo',
|
||||||
'ping_enabled': True,
|
'ping_enabled': True, 'ping_method': 'ping',
|
||||||
'gather_facts_enabled': True,
|
'gather_facts_enabled': True, 'gather_facts_method': 'gather_facts_posix',
|
||||||
'verify_account_enabled': True,
|
'verify_account_enabled': True, 'verify_account_method': 'verify_account_posix',
|
||||||
'change_password_enabled': True,
|
'change_password_enabled': True, 'change_password_method': 'change_password_posix',
|
||||||
'create_account_enabled': True,
|
'create_account_enabled': True, 'create_account_method': 'create_account_posix',
|
||||||
'gather_accounts_enabled': True,
|
'gather_accounts_enabled': True, 'gather_accounts_method': 'gather_accounts_posix',
|
||||||
'_protocols': ['ssh', 'sftp']
|
'_protocols': ['ssh', 'telnet'],
|
||||||
},
|
},
|
||||||
cls.NETWORKING: {
|
cls.NETWORKING: {
|
||||||
'domain_enabled': True,
|
'domain_enabled': True,
|
||||||
'su_enabled': False,
|
'su_enabled': False,
|
||||||
|
'ping_enabled': True, 'ping_method': 'ping',
|
||||||
'gather_facts_enabled': False,
|
'gather_facts_enabled': False,
|
||||||
'verify_account_enabled': False,
|
'verify_account_enabled': False,
|
||||||
'change_password_enabled': False,
|
'change_password_enabled': False,
|
||||||
|
@ -65,15 +66,28 @@ class Category(PlatformMixin, ChoicesMixin, models.TextChoices):
|
||||||
'change_password_enabled': True,
|
'change_password_enabled': True,
|
||||||
'create_account_enabled': True,
|
'create_account_enabled': True,
|
||||||
'gather_accounts_enabled': True,
|
'gather_accounts_enabled': True,
|
||||||
|
'_protocols': []
|
||||||
},
|
},
|
||||||
cls.WEB: {
|
cls.WEB: {
|
||||||
'domain_enabled': False,
|
'domain_enabled': False,
|
||||||
'su_enabled': False,
|
'su_enabled': False,
|
||||||
|
'ping_enabled': False,
|
||||||
|
'gather_facts_enabled': False,
|
||||||
|
'verify_account_enabled': False,
|
||||||
|
'change_password_enabled': False,
|
||||||
|
'create_account_enabled': False,
|
||||||
|
'gather_accounts_enabled': False,
|
||||||
'_protocols': ['http', 'https']
|
'_protocols': ['http', 'https']
|
||||||
},
|
},
|
||||||
cls.CLOUD: {
|
cls.CLOUD: {
|
||||||
'domain_enabled': False,
|
'domain_enabled': False,
|
||||||
'su_enabled': False,
|
'su_enabled': False,
|
||||||
|
'ping_enabled': False,
|
||||||
|
'gather_facts_enabled': False,
|
||||||
|
'verify_account_enabled': False,
|
||||||
|
'change_password_enabled': False,
|
||||||
|
'create_account_enabled': False,
|
||||||
|
'gather_accounts_enabled': False,
|
||||||
'_protocols': []
|
'_protocols': []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,9 +97,6 @@ class HostTypes(PlatformMixin, ChoicesMixin, models.TextChoices):
|
||||||
LINUX = 'linux', 'Linux'
|
LINUX = 'linux', 'Linux'
|
||||||
WINDOWS = 'windows', 'Windows'
|
WINDOWS = 'windows', 'Windows'
|
||||||
UNIX = 'unix', 'Unix'
|
UNIX = 'unix', 'Unix'
|
||||||
BSD = 'bsd', 'BSD'
|
|
||||||
MACOS = 'macos', 'MacOS'
|
|
||||||
MAINFRAME = 'mainframe', _("Mainframe")
|
|
||||||
OTHER_HOST = 'other_host', _("Other host")
|
OTHER_HOST = 'other_host', _("Other host")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -95,20 +106,26 @@ class HostTypes(PlatformMixin, ChoicesMixin, models.TextChoices):
|
||||||
'_protocols': ['ssh', 'rdp', 'vnc', 'telnet']
|
'_protocols': ['ssh', 'rdp', 'vnc', 'telnet']
|
||||||
},
|
},
|
||||||
cls.WINDOWS: {
|
cls.WINDOWS: {
|
||||||
'_protocols': ['ssh', 'rdp', 'vnc'],
|
'gather_facts_method': 'gather_facts_windows',
|
||||||
|
'verify_account_method': 'verify_account_windows',
|
||||||
|
'change_password_method': 'change_password_windows',
|
||||||
|
'create_account_method': 'create_account_windows',
|
||||||
|
'gather_accounts_method': 'gather_accounts_windows',
|
||||||
|
'_protocols': ['rdp', 'ssh', 'vnc'],
|
||||||
'su_enabled': False
|
'su_enabled': False
|
||||||
},
|
},
|
||||||
cls.MACOS: {
|
cls.UNIX: {
|
||||||
'_protocols': ['ssh', 'vnc']
|
'_protocols': ['ssh', 'vnc']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class NetworkingTypes(PlatformMixin, ChoicesMixin, models.TextChoices):
|
class NetworkingTypes(PlatformMixin, ChoicesMixin, models.TextChoices):
|
||||||
|
GENERAL = 'general', _("General device")
|
||||||
SWITCH = 'switch', _("Switch")
|
SWITCH = 'switch', _("Switch")
|
||||||
ROUTER = 'router', _("Router")
|
ROUTER = 'router', _("Router")
|
||||||
FIREWALL = 'firewall', _("Firewall")
|
FIREWALL = 'firewall', _("Firewall")
|
||||||
OTHER_NETWORK = 'other_network', _("Other device")
|
OTHER_NETWORK = 'other', _("Other device")
|
||||||
|
|
||||||
|
|
||||||
class DatabaseTypes(PlatformMixin, ChoicesMixin, models.TextChoices):
|
class DatabaseTypes(PlatformMixin, ChoicesMixin, models.TextChoices):
|
||||||
|
@ -125,7 +142,12 @@ class DatabaseTypes(PlatformMixin, ChoicesMixin, models.TextChoices):
|
||||||
meta = {}
|
meta = {}
|
||||||
for name, label in cls.choices:
|
for name, label in cls.choices:
|
||||||
meta[name] = {
|
meta[name] = {
|
||||||
'_protocols': [name]
|
'_protocols': [name],
|
||||||
|
'gather_facts_method': f'gather_facts_{name}',
|
||||||
|
'verify_account_method': f'verify_account_{name}',
|
||||||
|
'change_password_method': f'change_password_{name}',
|
||||||
|
'create_account_method': f'create_account_{name}',
|
||||||
|
'gather_accounts_method': f'gather_accounts_{name}',
|
||||||
}
|
}
|
||||||
return meta
|
return meta
|
||||||
|
|
||||||
|
|
|
@ -12,38 +12,15 @@ class Migration(migrations.Migration):
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.AddField(
|
||||||
name='DeviceInfo',
|
model_name='asset',
|
||||||
fields=[
|
name='info',
|
||||||
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
|
field=models.JSONField(blank=True, default=dict, verbose_name='Info'),
|
||||||
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
|
|
||||||
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
|
|
||||||
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
|
|
||||||
('vendor', models.CharField(blank=True, max_length=64, null=True, verbose_name='Vendor')),
|
|
||||||
('model', models.CharField(blank=True, max_length=54, null=True, verbose_name='Model')),
|
|
||||||
('sn', models.CharField(blank=True, max_length=128, null=True, verbose_name='Serial number')),
|
|
||||||
('cpu_model', models.CharField(blank=True, max_length=64, null=True, verbose_name='CPU model')),
|
|
||||||
('cpu_count', models.IntegerField(null=True, verbose_name='CPU count')),
|
|
||||||
('cpu_cores', models.IntegerField(null=True, verbose_name='CPU cores')),
|
|
||||||
('cpu_vcpus', models.IntegerField(null=True, verbose_name='CPU vcpus')),
|
|
||||||
('memory', models.CharField(blank=True, max_length=64, null=True, verbose_name='Memory')),
|
|
||||||
('disk_total', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Disk total')),
|
|
||||||
('disk_info', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Disk info')),
|
|
||||||
('os', models.CharField(blank=True, max_length=128, null=True, verbose_name='OS')),
|
|
||||||
('os_version', models.CharField(blank=True, max_length=16, null=True, verbose_name='OS version')),
|
|
||||||
('os_arch', models.CharField(blank=True, max_length=16, null=True, verbose_name='OS arch')),
|
|
||||||
('hostname_raw', models.CharField(blank=True, max_length=128, null=True, verbose_name='Hostname raw')),
|
|
||||||
('number', models.CharField(blank=True, max_length=128, null=True, verbose_name='Asset number')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'DeviceInfo',
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Host',
|
name='Host',
|
||||||
fields=[
|
fields=[
|
||||||
('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')),
|
('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')),
|
||||||
('device_info', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.deviceinfo', verbose_name='Host')),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -4,46 +4,6 @@ from django.utils import timezone
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
def migrate_hardware(apps, *args):
|
|
||||||
host_model = apps.get_model('assets', 'Host')
|
|
||||||
asset_model = apps.get_model('assets', 'Asset')
|
|
||||||
hardware_model = apps.get_model('assets', 'DeviceInfo')
|
|
||||||
|
|
||||||
created = 0
|
|
||||||
batch_size = 1000
|
|
||||||
|
|
||||||
excludes = ['id', 'host', 'date_updated']
|
|
||||||
fields = [f.name for f in hardware_model._meta.fields]
|
|
||||||
fields = [name for name in fields if name not in excludes]
|
|
||||||
|
|
||||||
while True:
|
|
||||||
start = created
|
|
||||||
end = created + batch_size
|
|
||||||
hosts = host_model.objects.all()[start:end]
|
|
||||||
asset_ids = [h.asset_ptr_id for h in hosts]
|
|
||||||
assets = asset_model.objects.filter(id__in=asset_ids)
|
|
||||||
asset_mapper = {a.id: a for a in assets}
|
|
||||||
|
|
||||||
if not hosts:
|
|
||||||
break
|
|
||||||
|
|
||||||
hardware_infos = []
|
|
||||||
hosts_updated = []
|
|
||||||
for host in hosts:
|
|
||||||
hardware = hardware_model()
|
|
||||||
asset = asset_mapper[host.asset_ptr_id]
|
|
||||||
hardware.date_updated = timezone.now()
|
|
||||||
for name in fields:
|
|
||||||
setattr(hardware, name, getattr(asset, name))
|
|
||||||
hardware_infos.append(hardware)
|
|
||||||
host.device_info_id = hardware.id
|
|
||||||
hosts_updated.append(host)
|
|
||||||
|
|
||||||
hardware_model.objects.bulk_create(hardware_infos, ignore_conflicts=True)
|
|
||||||
host_model.objects.bulk_update(hosts_updated, ['device_info_id'])
|
|
||||||
created += len(hardware_infos)
|
|
||||||
|
|
||||||
|
|
||||||
def migrate_to_host(apps, schema_editor):
|
def migrate_to_host(apps, schema_editor):
|
||||||
asset_model = apps.get_model("assets", "Asset")
|
asset_model = apps.get_model("assets", "Asset")
|
||||||
host_model = apps.get_model("assets", 'Host')
|
host_model = apps.get_model("assets", 'Host')
|
||||||
|
@ -64,6 +24,34 @@ def migrate_to_host(apps, schema_editor):
|
||||||
created += len(hosts)
|
created += len(hosts)
|
||||||
|
|
||||||
|
|
||||||
|
def migrate_hardware_info(apps, *args):
|
||||||
|
asset_model = apps.get_model("assets", "Asset")
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
batch_size = 1000
|
||||||
|
hardware_fields = [
|
||||||
|
'vendor', 'model', 'sn', 'cpu_model', 'cpu_count', 'cpu_cores',
|
||||||
|
'cpu_vcpus', 'memory', 'disk_total', 'disk_info', 'os', 'os_arch',
|
||||||
|
'os_version', 'hostname_raw', 'number'
|
||||||
|
]
|
||||||
|
|
||||||
|
while True:
|
||||||
|
start = count
|
||||||
|
end = count + batch_size
|
||||||
|
assets = asset_model.objects.all()[start:end]
|
||||||
|
if not assets:
|
||||||
|
break
|
||||||
|
|
||||||
|
updated = []
|
||||||
|
for asset in assets:
|
||||||
|
info = {getattr(asset, field) for field in hardware_fields if getattr(asset, field)}
|
||||||
|
if not info:
|
||||||
|
continue
|
||||||
|
asset.info = info
|
||||||
|
updated.append(asset)
|
||||||
|
asset_model.objects.bulk_update(updated, ['info'])
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
@ -71,6 +59,6 @@ class Migration(migrations.Migration):
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
migrations.RunPython(migrate_hardware_info),
|
||||||
migrations.RunPython(migrate_to_host),
|
migrations.RunPython(migrate_to_host),
|
||||||
migrations.RunPython(migrate_hardware),
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -48,6 +48,10 @@ class Migration(migrations.Migration):
|
||||||
fields=[
|
fields=[
|
||||||
('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')),
|
('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')),
|
||||||
('url', models.CharField(max_length=1024, verbose_name='url')),
|
('url', models.CharField(max_length=1024, verbose_name='url')),
|
||||||
|
('autofill', models.CharField(default='basic', max_length=16)),
|
||||||
|
('password_selector', models.CharField(blank=True, default='', max_length=128)),
|
||||||
|
('submit_selector', models.CharField(blank=True, default='', max_length=128)),
|
||||||
|
('username_selector', models.CharField(blank=True, default='', max_length=128))
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
# Generated by Django 3.1.14 on 2022-04-30 14:41
|
# Generated by Django 3.1.14 on 2022-04-30 14:41
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -19,11 +18,6 @@ class Migration(migrations.Migration):
|
||||||
('setting', models.JSONField(default=dict, verbose_name='Setting')),
|
('setting', models.JSONField(default=dict, verbose_name='Setting')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
|
||||||
model_name='platform',
|
|
||||||
name='domain_default',
|
|
||||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.domain', verbose_name='Domain default'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='platform',
|
model_name='platform',
|
||||||
name='domain_enabled',
|
name='domain_enabled',
|
||||||
|
@ -62,12 +56,12 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='platform',
|
model_name='platform',
|
||||||
name='ping_enabled',
|
name='ping_enabled',
|
||||||
field=models.BooleanField(default=False),
|
field=models.BooleanField(default=False, verbose_name='Ping enabled'),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='platform',
|
model_name='platform',
|
||||||
name='ping_method',
|
name='ping_method',
|
||||||
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Ping method'),
|
field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Ping method'),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='platform',
|
model_name='platform',
|
||||||
|
@ -89,4 +83,24 @@ class Migration(migrations.Migration):
|
||||||
name='verify_account_method',
|
name='verify_account_method',
|
||||||
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Verify account method'),
|
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Verify account method'),
|
||||||
),
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='platform',
|
||||||
|
name='gather_accounts_enabled',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='Gather facts enabled'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='platform',
|
||||||
|
name='gather_accounts_method',
|
||||||
|
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Gather facts method'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='platform',
|
||||||
|
name='gather_facts_enabled',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='Gather facts enabled'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='platform',
|
||||||
|
name='gather_facts_method',
|
||||||
|
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Gather facts method'),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -21,6 +21,7 @@ class Migration(migrations.Migration):
|
||||||
fields=[
|
fields=[
|
||||||
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
|
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
|
||||||
('id', models.UUIDField(db_index=True, default=uuid.uuid4)),
|
('id', models.UUIDField(db_index=True, default=uuid.uuid4)),
|
||||||
|
('name', models.CharField(max_length=128, verbose_name='Name')),
|
||||||
('username', models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username')),
|
('username', models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username')),
|
||||||
('password', common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password')),
|
('password', common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password')),
|
||||||
('private_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key')),
|
('private_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key')),
|
||||||
|
@ -38,6 +39,7 @@ class Migration(migrations.Migration):
|
||||||
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
|
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
|
||||||
('asset', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='assets.asset', verbose_name='Asset')),
|
('asset', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='assets.asset', verbose_name='Asset')),
|
||||||
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||||
|
('su_from', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='assets.account', verbose_name='Su from')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'verbose_name': 'historical Account',
|
'verbose_name': 'historical Account',
|
||||||
|
@ -52,6 +54,7 @@ class Migration(migrations.Migration):
|
||||||
fields=[
|
fields=[
|
||||||
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
|
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
|
||||||
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
|
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
|
||||||
|
('name', models.CharField(max_length=128, verbose_name='Name')),
|
||||||
('username', models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username')),
|
('username', models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username')),
|
||||||
('password', common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password')),
|
('password', common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password')),
|
||||||
('private_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key')),
|
('private_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key')),
|
||||||
|
@ -63,12 +66,13 @@ class Migration(migrations.Migration):
|
||||||
('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')),
|
('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')),
|
||||||
('privileged', models.BooleanField(default=False, verbose_name='Privileged account')),
|
('privileged', models.BooleanField(default=False, verbose_name='Privileged account')),
|
||||||
('version', models.IntegerField(default=0, verbose_name='Version')),
|
('version', models.IntegerField(default=0, verbose_name='Version')),
|
||||||
('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.asset', verbose_name='Asset')),
|
('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accounts', to='assets.asset', verbose_name='Asset')),
|
||||||
|
('su_from', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', to='assets.account', verbose_name='Su from')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'verbose_name': 'Account',
|
'verbose_name': 'Account',
|
||||||
'permissions': [('view_accountsecret', 'Can view asset account secret'), ('change_accountsecret', 'Can change asset account secret'), ('view_historyaccount', 'Can view asset history account'), ('view_historyaccountsecret', 'Can view asset history account secret')],
|
'permissions': [('view_accountsecret', 'Can view asset account secret'), ('change_accountsecret', 'Can change asset account secret'), ('view_historyaccount', 'Can view asset history account'), ('view_historyaccountsecret', 'Can view asset history account secret')],
|
||||||
'unique_together': {('username', 'asset')},
|
'unique_together': {('username', 'asset'), ('name', 'asset')},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -40,7 +40,7 @@ def migrate_accounts(apps, schema_editor):
|
||||||
values['version'] = 1
|
values['version'] = 1
|
||||||
|
|
||||||
system_user = auth_book.systemuser
|
system_user = auth_book.systemuser
|
||||||
if auth_book.systemuser:
|
if system_user:
|
||||||
values.update({attr: getattr(system_user, attr) for attr in auth_attrs})
|
values.update({attr: getattr(system_user, attr) for attr in auth_attrs})
|
||||||
values['created_by'] = str(system_user.id)
|
values['created_by'] = str(system_user.id)
|
||||||
values['privileged'] = system_user.type == 'admin'
|
values['privileged'] = system_user.type == 'admin'
|
||||||
|
@ -48,6 +48,7 @@ def migrate_accounts(apps, schema_editor):
|
||||||
auth_book_auth = {attr: getattr(auth_book, attr) for attr in auth_attrs}
|
auth_book_auth = {attr: getattr(auth_book, attr) for attr in auth_attrs}
|
||||||
auth_book_auth = {attr: value for attr, value in auth_book_auth.items() if value}
|
auth_book_auth = {attr: value for attr, value in auth_book_auth.items() if value}
|
||||||
values.update(auth_book_auth)
|
values.update(auth_book_auth)
|
||||||
|
values['name'] = values['username']
|
||||||
|
|
||||||
account = account_model(**values)
|
account = account_model(**values)
|
||||||
accounts.append(account)
|
accounts.append(account)
|
||||||
|
|
|
@ -41,6 +41,11 @@ class Migration(migrations.Migration):
|
||||||
old_name='hostname',
|
old_name='hostname',
|
||||||
new_name='name',
|
new_name='name',
|
||||||
),
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='asset',
|
||||||
|
name='name',
|
||||||
|
field=models.CharField(max_length=128, verbose_name='Name'),
|
||||||
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='asset',
|
model_name='asset',
|
||||||
name='date_updated',
|
name='date_updated',
|
||||||
|
|
|
@ -1,44 +1,10 @@
|
||||||
# Generated by Django 3.2.13 on 2022-08-29 11:46
|
# Generated by Django 3.2.14 on 2022-09-14 12:45
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
from assets.const import Category
|
|
||||||
from assets.models import Type
|
|
||||||
|
|
||||||
|
|
||||||
def update_account_backup_type(apps, schema_editor):
|
|
||||||
backup_model = apps.get_model('assets', 'AccountBackupPlan')
|
|
||||||
all_number = 4294967295
|
|
||||||
asset_number = Type.choices_to_value([Category.HOST])
|
|
||||||
app_number = Type.choices_to_value([
|
|
||||||
Category.NETWORKING, Category.DATABASE, Category.CLOUD, Category.WEB]
|
|
||||||
)
|
|
||||||
|
|
||||||
backup_model.objects.filter(types=255).update(types=all_number)
|
|
||||||
backup_model.objects.filter(types=1).update(types=asset_number)
|
|
||||||
backup_model.objects.filter(types=2).update(types=app_number)
|
|
||||||
|
|
||||||
backup_execution_model = apps.get_model('assets', 'AccountBackupPlanExecution')
|
|
||||||
choices_dict = {
|
|
||||||
'all': Type.get_types(value=all_number),
|
|
||||||
'asset': Type.get_types(value=asset_number),
|
|
||||||
'app': Type.get_types(value=app_number)
|
|
||||||
}
|
|
||||||
qs_dict = {
|
|
||||||
'all': backup_execution_model.objects.filter(plan__types=255),
|
|
||||||
'asset': backup_execution_model.objects.filter(plan__types=1),
|
|
||||||
'app': backup_execution_model.objects.filter(plan__types=2)
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_executions = []
|
|
||||||
for k, qs in qs_dict.items():
|
|
||||||
type_choices = choices_dict[k]
|
|
||||||
for i in qs:
|
|
||||||
i.plan_snapshot['types'] = type_choices
|
|
||||||
backup_executions.append(i)
|
|
||||||
backup_execution_model.objects.bulk_update(backup_executions, fields=['plan_snapshot'])
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('assets', '0106_auto_20220819_1523'),
|
('assets', '0106_auto_20220819_1523'),
|
||||||
]
|
]
|
||||||
|
@ -47,13 +13,6 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='accountbackupplan',
|
model_name='accountbackupplan',
|
||||||
name='types',
|
name='types',
|
||||||
field=models.BigIntegerField(
|
field=models.BigIntegerField(),
|
||||||
choices=[(4294967295, 'All'), (1, 'Linux'), (2, 'Windows'), (4, 'Unix'), (8, 'BSD'), (16, 'MacOS'),
|
|
||||||
(32, 'Mainframe'), (64, 'Other host'), (127, 'Host'), (128, 'Switch'), (256, 'Router'),
|
|
||||||
(512, 'Firewall'), (1024, 'Other device'), (1920, 'NetworkDevice'), (2048, 'MySQL'),
|
|
||||||
(4096, 'MariaDB'), (8192, 'PostgreSQL'), (16384, 'Oracle'), (32768, 'SQLServer'),
|
|
||||||
(65536, 'MongoDB'), (131072, 'Redis'), (260096, 'Database'), (262144, 'Clouding'),
|
|
||||||
(524288, 'Web')], default=4294967295, verbose_name='Type'),
|
|
||||||
),
|
),
|
||||||
migrations.RunPython(update_account_backup_type),
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
# Generated by Django 3.2.14 on 2022-09-01 02:34
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('assets', '0107_alter_accountbackupplan_types'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='platform',
|
|
||||||
name='create_account_enabled',
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='platform',
|
|
||||||
name='create_account_method',
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='platform',
|
|
||||||
name='domain_default',
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='platform',
|
|
||||||
name='domain_enabled',
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='platform',
|
|
||||||
name='ping_enabled',
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='platform',
|
|
||||||
name='ping_method',
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,30 +0,0 @@
|
||||||
# Generated by Django 3.2.14 on 2022-09-01 06:31
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('assets', '0108_auto_20220901_1034'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='host',
|
|
||||||
name='device_info',
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='asset',
|
|
||||||
name='info',
|
|
||||||
field=models.JSONField(blank=True, default=dict, verbose_name='Info'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='database',
|
|
||||||
name='version',
|
|
||||||
field=models.CharField(blank=True, max_length=16, verbose_name='Version'),
|
|
||||||
),
|
|
||||||
migrations.DeleteModel(
|
|
||||||
name='DeviceInfo',
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,43 +0,0 @@
|
||||||
# Generated by Django 3.2.14 on 2022-09-01 07:42
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('assets', '0109_auto_20220901_1431'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='platform',
|
|
||||||
name='create_account_enabled',
|
|
||||||
field=models.BooleanField(default=False, verbose_name='Create account enabled'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='platform',
|
|
||||||
name='create_account_method',
|
|
||||||
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Create account method'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='platform',
|
|
||||||
name='gather_accounts_enabled',
|
|
||||||
field=models.BooleanField(default=False, verbose_name='Gather facts enabled'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='platform',
|
|
||||||
name='gather_accounts_method',
|
|
||||||
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Gather facts method'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='platform',
|
|
||||||
name='gather_facts_enabled',
|
|
||||||
field=models.BooleanField(default=False, verbose_name='Gather facts enabled'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='platform',
|
|
||||||
name='gather_facts_method',
|
|
||||||
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Gather facts method'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,29 +0,0 @@
|
||||||
# Generated by Django 3.2.14 on 2022-09-08 11:58
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('assets', '0110_auto_20220901_1542'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='platform',
|
|
||||||
name='domain_enabled',
|
|
||||||
field=models.BooleanField(default=True, verbose_name='Domain enalbed'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='account',
|
|
||||||
name='asset',
|
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accounts', to='assets.asset', verbose_name='Asset'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='asset',
|
|
||||||
name='name',
|
|
||||||
field=models.CharField(max_length=128, verbose_name='Name'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,38 +0,0 @@
|
||||||
# Generated by Django 3.2.14 on 2022-09-09 11:07
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('assets', '0111_auto_20220908_1958'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='web',
|
|
||||||
name='autofill',
|
|
||||||
field=models.CharField(default='basic', max_length=16),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='web',
|
|
||||||
name='password_selector',
|
|
||||||
field=models.CharField(blank=True, default='', max_length=128),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='web',
|
|
||||||
name='submit_selector',
|
|
||||||
field=models.CharField(blank=True, default='', max_length=128),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='web',
|
|
||||||
name='username_selector',
|
|
||||||
field=models.CharField(blank=True, default='', max_length=128),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='platform',
|
|
||||||
name='domain_enabled',
|
|
||||||
field=models.BooleanField(default=True, verbose_name='Domain enabled'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -3,20 +3,29 @@ from django.utils.translation import gettext_lazy as _
|
||||||
from simple_history.models import HistoricalRecords
|
from simple_history.models import HistoricalRecords
|
||||||
|
|
||||||
from common.utils import lazyproperty
|
from common.utils import lazyproperty
|
||||||
|
|
||||||
from .base import BaseAccount
|
from .base import BaseAccount
|
||||||
|
|
||||||
__all__ = ['Account', 'AccountTemplate']
|
__all__ = ['Account', 'AccountTemplate']
|
||||||
|
|
||||||
|
|
||||||
class Account(BaseAccount):
|
class Account(BaseAccount):
|
||||||
asset = models.ForeignKey('assets.Asset', related_name='accounts', on_delete=models.CASCADE, verbose_name=_('Asset'))
|
asset = models.ForeignKey(
|
||||||
|
'assets.Asset', related_name='accounts',
|
||||||
|
on_delete=models.CASCADE, verbose_name=_('Asset')
|
||||||
|
)
|
||||||
|
su_from = models.ForeignKey(
|
||||||
|
'assets.Account', related_name='su_to', null=True,
|
||||||
|
on_delete=models.SET_NULL, verbose_name=_("Su from")
|
||||||
|
)
|
||||||
version = models.IntegerField(default=0, verbose_name=_('Version'))
|
version = models.IntegerField(default=0, verbose_name=_('Version'))
|
||||||
history = HistoricalRecords()
|
history = HistoricalRecords()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _('Account')
|
verbose_name = _('Account')
|
||||||
unique_together = [('username', 'asset')]
|
unique_together = [
|
||||||
|
('username', 'asset'),
|
||||||
|
('name', 'asset'),
|
||||||
|
]
|
||||||
permissions = [
|
permissions = [
|
||||||
('view_accountsecret', _('Can view asset account secret')),
|
('view_accountsecret', _('Can view asset account secret')),
|
||||||
('change_accountsecret', _('Can change asset account secret')),
|
('change_accountsecret', _('Can change asset account secret')),
|
||||||
|
@ -24,10 +33,6 @@ class Account(BaseAccount):
|
||||||
('view_historyaccountsecret', _('Can view asset history account secret')),
|
('view_historyaccountsecret', _('Can view asset history account secret')),
|
||||||
]
|
]
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
return "{}({})_{}".format(self.asset_name, self.ip, self.username)
|
|
||||||
|
|
||||||
@lazyproperty
|
@lazyproperty
|
||||||
def ip(self):
|
def ip(self):
|
||||||
return self.asset.ip
|
return self.asset.ip
|
||||||
|
|
|
@ -6,7 +6,6 @@ from .common import Asset
|
||||||
|
|
||||||
class Database(Asset):
|
class Database(Asset):
|
||||||
db_name = models.CharField(max_length=1024, verbose_name=_("Database"), blank=True)
|
db_name = models.CharField(max_length=1024, verbose_name=_("Database"), blank=True)
|
||||||
version = models.CharField(max_length=16, verbose_name=_("Version"), blank=True)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{}({}://{}/{})'.format(self.name, self.type, self.ip, self.db_name)
|
return '{}({}://{}/{})'.format(self.name, self.type, self.ip, self.db_name)
|
||||||
|
|
|
@ -3,4 +3,5 @@ from .common import Asset
|
||||||
|
|
||||||
|
|
||||||
class Networking(Asset):
|
class Networking(Asset):
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -71,7 +71,7 @@ class Type(BitOperationChoice):
|
||||||
|
|
||||||
class AccountBackupPlan(CommonModelMixin, PeriodTaskModelMixin, OrgModelMixin):
|
class AccountBackupPlan(CommonModelMixin, PeriodTaskModelMixin, OrgModelMixin):
|
||||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||||
types = models.BigIntegerField(choices=Type.DB_CHOICES, default=Type.ALL, verbose_name=_('Type'))
|
types = models.BigIntegerField()
|
||||||
recipients = models.ManyToManyField(
|
recipients = models.ManyToManyField(
|
||||||
'users.User', related_name='recipient_escape_route_plans', blank=True,
|
'users.User', related_name='recipient_escape_route_plans', blank=True,
|
||||||
verbose_name=_("Recipient")
|
verbose_name=_("Recipient")
|
||||||
|
|
|
@ -9,6 +9,12 @@ __all__ = ['Platform', 'PlatformProtocol']
|
||||||
|
|
||||||
|
|
||||||
class PlatformProtocol(models.Model):
|
class PlatformProtocol(models.Model):
|
||||||
|
SETTING_ATTRS = {
|
||||||
|
'console': True,
|
||||||
|
'security': 'any,tls,rdp',
|
||||||
|
'sftp_enabled': True,
|
||||||
|
'sftp_home': '/tmp'
|
||||||
|
}
|
||||||
name = models.CharField(max_length=32, verbose_name=_('Name'))
|
name = models.CharField(max_length=32, verbose_name=_('Name'))
|
||||||
port = models.IntegerField(verbose_name=_('Port'))
|
port = models.IntegerField(verbose_name=_('Port'))
|
||||||
setting = models.JSONField(verbose_name=_('Setting'), default=dict)
|
setting = models.JSONField(verbose_name=_('Setting'), default=dict)
|
||||||
|
@ -34,6 +40,8 @@ class Platform(models.Model):
|
||||||
domain_enabled = models.BooleanField(default=True, verbose_name=_("Domain enabled"))
|
domain_enabled = models.BooleanField(default=True, verbose_name=_("Domain enabled"))
|
||||||
protocols_enabled = models.BooleanField(default=True, verbose_name=_("Protocols enabled"))
|
protocols_enabled = models.BooleanField(default=True, verbose_name=_("Protocols enabled"))
|
||||||
protocols = models.ManyToManyField(PlatformProtocol, blank=True, verbose_name=_("Protocols"))
|
protocols = models.ManyToManyField(PlatformProtocol, blank=True, verbose_name=_("Protocols"))
|
||||||
|
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"))
|
||||||
gather_facts_enabled = models.BooleanField(default=False, verbose_name=_("Gather facts enabled"))
|
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"))
|
||||||
# 账号有关的
|
# 账号有关的
|
||||||
|
@ -61,71 +69,7 @@ class Platform(models.Model):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def set_default_platforms_ops(platform_model):
|
def set_default_platforms_ops(platform_model):
|
||||||
default_ok = {
|
pass
|
||||||
'su_enabled': True,
|
|
||||||
'su_method': 'sudo',
|
|
||||||
'domain_enabled': True,
|
|
||||||
'change_password_enabled': True,
|
|
||||||
'change_password_method': 'change_password_linux',
|
|
||||||
'verify_account_enabled': True,
|
|
||||||
'verify_account_method': 'ansible_posix_ping',
|
|
||||||
}
|
|
||||||
db_default = {
|
|
||||||
'su_enabled': False,
|
|
||||||
'domain_enabled': True,
|
|
||||||
'change_password_enabled': True,
|
|
||||||
'verify_account_enabled': True,
|
|
||||||
}
|
|
||||||
|
|
||||||
platform_ops_map = {
|
|
||||||
('host', 'linux'): {
|
|
||||||
**default_ok,
|
|
||||||
'change_password_method': 'change_password_linux',
|
|
||||||
'verify_account_method': 'ansible_posix_ping'
|
|
||||||
},
|
|
||||||
('host', 'windows'): {
|
|
||||||
**default_ok,
|
|
||||||
'su_enabled': False,
|
|
||||||
'change_password_method': 'change_password_windows',
|
|
||||||
'verify_account_method': 'ansible_win_ping'
|
|
||||||
},
|
|
||||||
('host', 'unix'): {
|
|
||||||
**default_ok,
|
|
||||||
'verify_account_method': 'ansible_posix_ping',
|
|
||||||
'change_password_method': 'change_password_aix'
|
|
||||||
},
|
|
||||||
('database', 'mysql'): {
|
|
||||||
**db_default,
|
|
||||||
'verify_account_method': 'mysql_ping',
|
|
||||||
'change_password_method': 'change_password_mysql'
|
|
||||||
},
|
|
||||||
('database', 'postgresql'): {
|
|
||||||
**db_default,
|
|
||||||
'verify_account_method': 'postgresql_ping',
|
|
||||||
'change_password_method': 'change_password_postgresql'
|
|
||||||
},
|
|
||||||
('database', 'oracle'): {
|
|
||||||
**db_default,
|
|
||||||
'verify_account_method': 'oracle_ping',
|
|
||||||
'change_password_method': 'change_password_oracle'
|
|
||||||
},
|
|
||||||
('database', 'sqlserver'): {
|
|
||||||
**db_default,
|
|
||||||
'verify_account_method': 'mysql_ping',
|
|
||||||
'change_password_method': 'change_password_sqlserver'
|
|
||||||
},
|
|
||||||
}
|
|
||||||
platforms = platform_model.objects.all()
|
|
||||||
|
|
||||||
updated = []
|
|
||||||
for p in platforms:
|
|
||||||
attrs = platform_ops_map.get((p.category, p.type), {})
|
|
||||||
if not attrs:
|
|
||||||
continue
|
|
||||||
for k, v in attrs.items():
|
|
||||||
setattr(p, k, v)
|
|
||||||
updated.append(p)
|
|
||||||
platform_model.objects.bulk_update(updated, list(default_ok.keys()))
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
|
|
||||||
from django.utils import timezone
|
|
||||||
from django.core.cache import cache
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
@ -21,3 +19,53 @@ def private_key_validator(value):
|
||||||
_('%(value)s is not an even number'),
|
_('%(value)s is not an even number'),
|
||||||
params={'value': value},
|
params={'value': value},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def update_internal_platforms(platform_model):
|
||||||
|
from assets.const import AllTypes
|
||||||
|
|
||||||
|
platforms = [
|
||||||
|
{'name': 'Linux', 'category': 'host', 'type': 'linux'},
|
||||||
|
{'name': 'BSD', 'category': 'host', 'type': 'unix'},
|
||||||
|
{'name': 'Unix', 'category': 'host', 'type': 'unix'},
|
||||||
|
{'name': 'MacOS', 'category': 'host', 'type': 'unix'},
|
||||||
|
{'name': 'Windows', 'category': 'host', 'type': 'unix'},
|
||||||
|
{
|
||||||
|
'name': 'AIX', 'category': 'host', 'type': 'unix',
|
||||||
|
'create_account_method': 'create_account_aix',
|
||||||
|
'change_password_method': 'change_password_aix',
|
||||||
|
},
|
||||||
|
{'name': 'Windows', 'category': 'host', 'type': 'windows'},
|
||||||
|
{'name': 'Windows-TLS', 'category': 'host', 'type': 'windows'},
|
||||||
|
{'name': 'Windows-RDP', 'category': 'host', 'type': 'windows'},
|
||||||
|
|
||||||
|
# 数据库
|
||||||
|
{'name': 'MySQL', 'category': 'database', 'type': 'mysql'},
|
||||||
|
{'name': 'PostgreSQL', 'category': 'database', 'type': 'postgresql'},
|
||||||
|
{'name': 'Oracle', 'category': 'database', 'type': 'oracle'},
|
||||||
|
{'name': 'SQLServer', 'category': 'database', 'type': 'sqlserver'},
|
||||||
|
{'name': 'MongoDB', 'category': 'database', 'type': 'mongodb'},
|
||||||
|
{'name': 'Redis', 'category': 'database', 'type': 'redis'},
|
||||||
|
|
||||||
|
# 网络设备
|
||||||
|
{'name': 'Generic', 'category': 'networking', 'type': 'general'},
|
||||||
|
{'name': 'Huawei', 'category': 'networking', 'type': 'general'},
|
||||||
|
{'name': 'Cisco', 'category': 'networking', 'type': 'general'},
|
||||||
|
{'name': 'H3C', 'category': 'networking', 'type': 'general'},
|
||||||
|
|
||||||
|
# Web
|
||||||
|
|
||||||
|
# Cloud
|
||||||
|
]
|
||||||
|
|
||||||
|
platforms = platform_model.objects.all()
|
||||||
|
|
||||||
|
updated = []
|
||||||
|
for p in platforms:
|
||||||
|
attrs = platform_ops_map.get((p.category, p.type), {})
|
||||||
|
if not attrs:
|
||||||
|
continue
|
||||||
|
for k, v in attrs.items():
|
||||||
|
setattr(p, k, v)
|
||||||
|
updated.append(p)
|
||||||
|
platform_model.objects.bulk_update(updated, list(default_ok.keys()))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
- hosts: {{ account.asset.name }}
|
- hosts: all
|
||||||
vars:
|
vars:
|
||||||
account:
|
account:
|
||||||
username: {{ account.username }}
|
username: {{ account.username }}
|
||||||
|
|
|
@ -4,7 +4,8 @@ from rest_framework import serializers
|
||||||
|
|
||||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||||
from common.drf.serializers import SecretReadableMixin
|
from common.drf.serializers import SecretReadableMixin
|
||||||
from assets.models import Account, AccountTemplate
|
from common.drf.fields import ObjectRelatedField
|
||||||
|
from assets.models import Account, AccountTemplate, Asset
|
||||||
from assets.serializers.base import AuthValidateMixin
|
from assets.serializers.base import AuthValidateMixin
|
||||||
from .common import AccountFieldsSerializerMixin
|
from .common import AccountFieldsSerializerMixin
|
||||||
|
|
||||||
|
@ -14,7 +15,9 @@ class AccountSerializerCreateMixin(serializers.ModelSerializer):
|
||||||
required=False, allow_null=True, write_only=True,
|
required=False, allow_null=True, write_only=True,
|
||||||
label=_('Account template')
|
label=_('Account template')
|
||||||
)
|
)
|
||||||
push_to_asset = serializers.BooleanField(default=False, label=_("Push to asset"), write_only=True)
|
push_now = serializers.BooleanField(
|
||||||
|
default=False, label=_("Push now"), write_only=True
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def validate_template(value):
|
def validate_template(value):
|
||||||
|
@ -39,30 +42,34 @@ class AccountSerializerCreateMixin(serializers.ModelSerializer):
|
||||||
account_template = attrs.pop('template', None)
|
account_template = attrs.pop('template', None)
|
||||||
if account_template:
|
if account_template:
|
||||||
self.replace_attrs(account_template, attrs)
|
self.replace_attrs(account_template, attrs)
|
||||||
push_to_asset = attrs.pop('push_to_asset', False)
|
self.push_now = attrs.pop('push_now', False)
|
||||||
return super().validate(attrs)
|
return super().validate(attrs)
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
instance = super().create(validated_data)
|
||||||
|
if self.push_now:
|
||||||
|
print("Start push account to asset")
|
||||||
|
# Todo: push it
|
||||||
|
pass
|
||||||
|
return instance
|
||||||
|
|
||||||
|
|
||||||
class AccountSerializer(AuthValidateMixin,
|
class AccountSerializer(AuthValidateMixin,
|
||||||
AccountSerializerCreateMixin,
|
AccountSerializerCreateMixin,
|
||||||
AccountFieldsSerializerMixin,
|
AccountFieldsSerializerMixin,
|
||||||
BulkOrgResourceModelSerializer):
|
BulkOrgResourceModelSerializer):
|
||||||
name = serializers.CharField(max_length=128, read_only=True, label=_("Name"))
|
asset = ObjectRelatedField(required=False, queryset=Asset.objects, label=_('Asset'), attrs=('id', 'name', 'ip'))
|
||||||
ip = serializers.ReadOnlyField(label=_("IP"))
|
|
||||||
asset_name = serializers.ReadOnlyField(label=_("Asset"))
|
|
||||||
platform = serializers.ReadOnlyField(label=_("Platform"))
|
platform = serializers.ReadOnlyField(label=_("Platform"))
|
||||||
|
|
||||||
class Meta(AccountFieldsSerializerMixin.Meta):
|
class Meta(AccountFieldsSerializerMixin.Meta):
|
||||||
model = Account
|
model = Account
|
||||||
fields = AccountFieldsSerializerMixin.Meta.fields \
|
fields = AccountFieldsSerializerMixin.Meta.fields \
|
||||||
+ ['template', 'push_to_asset']
|
+ ['template', 'push_now']
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setup_eager_loading(cls, queryset):
|
def setup_eager_loading(cls, queryset):
|
||||||
""" Perform necessary eager loading of data. """
|
""" Perform necessary eager loading of data. """
|
||||||
queryset = queryset.prefetch_related('asset') \
|
queryset = queryset.prefetch_related('asset')
|
||||||
.annotate(ip=F('asset__ip')) \
|
|
||||||
.annotate(asset_name=F('asset__name'))
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ __all__ = ['AccountFieldsSerializerMixin']
|
||||||
class AccountFieldsSerializerMixin(serializers.ModelSerializer):
|
class AccountFieldsSerializerMixin(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
fields_mini = [
|
fields_mini = [
|
||||||
'id', 'name', 'username', 'privileged', 'ip',
|
'id', 'name', 'username', 'privileged',
|
||||||
'asset_name', 'platform', 'version'
|
'platform', 'version'
|
||||||
]
|
]
|
||||||
fields_write_only = ['password', 'private_key', 'public_key', 'passphrase']
|
fields_write_only = ['password', 'private_key', 'public_key', 'passphrase']
|
||||||
fields_other = ['date_created', 'date_updated', 'comment']
|
fields_other = ['date_created', 'date_updated', 'comment']
|
||||||
|
|
|
@ -54,9 +54,12 @@ class AssetAccountSerializer(AccountSerializer):
|
||||||
|
|
||||||
class Meta(AccountSerializer.Meta):
|
class Meta(AccountSerializer.Meta):
|
||||||
fields_mini = [
|
fields_mini = [
|
||||||
'id', 'name', 'username', 'privileged', 'version'
|
'id', 'name', 'username', 'privileged', 'version',
|
||||||
|
]
|
||||||
|
fields_write_only = [
|
||||||
|
'password', 'private_key', 'public_key',
|
||||||
|
'passphrase', 'token', 'push_now'
|
||||||
]
|
]
|
||||||
fields_write_only = ['password', 'private_key', 'public_key', 'passphrase', 'token']
|
|
||||||
fields = fields_mini + fields_write_only
|
fields = fields_mini + fields_write_only
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
('assets', '0111_auto_20220908_1958'),
|
('assets', '0106_auto_20220819_1523'),
|
||||||
('ops', '0022_auto_20220817_1346'),
|
('ops', '0022_auto_20220817_1346'),
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue