diff --git a/apps/assets/migrations/0112_gateway_to_asset.py b/apps/assets/migrations/0112_gateway_to_asset.py index da43b3a84..67c874761 100644 --- a/apps/assets/migrations/0112_gateway_to_asset.py +++ b/apps/assets/migrations/0112_gateway_to_asset.py @@ -1,6 +1,7 @@ # Generated by Django 3.2.13 on 2022-09-29 11:03 from django.db import migrations + from assets.const.host import GATEWAY_NAME @@ -70,4 +71,18 @@ class Migration(migrations.Migration): operations = [ migrations.RunPython(migrate_gateway_to_asset), + migrations.DeleteModel( + name='Gateway', + ), + migrations.CreateModel( + name='Gateway', + fields=[ + ], + options={ + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('assets.host',), + ), ] diff --git a/apps/assets/migrations/0113_alter_accounttemplate_options.py b/apps/assets/migrations/0113_alter_accounttemplate_options.py index e635426c1..9488b5499 100644 --- a/apps/assets/migrations/0113_alter_accounttemplate_options.py +++ b/apps/assets/migrations/0113_alter_accounttemplate_options.py @@ -1,10 +1,9 @@ # Generated by Django 3.2.14 on 2022-11-28 10:39 -from django.db import migrations +from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('assets', '0112_gateway_to_asset'), ] @@ -12,6 +11,33 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( name='accounttemplate', - options={'permissions': [('view_accounttemplatesecret', 'Can view asset account template secret'), ('change_accounttemplatesecret', 'Can change asset account template secret')], 'verbose_name': 'Account template'}, + options={'permissions': [('view_accounttemplatesecret', 'Can view asset account template secret'), + ('change_accounttemplatesecret', 'Can change asset account template secret')], + 'verbose_name': 'Account template'}, + ), + migrations.AddField( + model_name='database', + name='allow_invalid_cert', + field=models.BooleanField(default=False, verbose_name='Allow invalid cert'), + ), + migrations.AddField( + model_name='database', + name='ca_cert', + field=models.TextField(blank=True, verbose_name='CA cert'), + ), + migrations.AddField( + model_name='database', + name='client_cert', + field=models.TextField(blank=True, verbose_name='Client cert'), + ), + migrations.AddField( + model_name='database', + name='client_key', + field=models.TextField(blank=True, verbose_name='Client key'), + ), + migrations.AddField( + model_name='database', + name='use_ssl', + field=models.BooleanField(default=False, verbose_name='Use SSL'), ), ] diff --git a/apps/assets/migrations/0114_node_domain.py b/apps/assets/migrations/0114_node_domain.py index 0149a5d11..1abcde400 100644 --- a/apps/assets/migrations/0114_node_domain.py +++ b/apps/assets/migrations/0114_node_domain.py @@ -1,14 +1,37 @@ # Generated by Django 3.2.14 on 2022-11-29 05:14 from django.db import migrations, models -import django.db.models.deletion -# TODO 最后去掉这个迁移 class Migration(migrations.Migration): dependencies = [ ('assets', '0113_alter_accounttemplate_options'), ] operations = [ + migrations.AddField( + model_name='database', + name='allow_invalid_cert', + field=models.BooleanField(default=False, verbose_name='Allow invalid cert'), + ), + migrations.AddField( + model_name='database', + name='ca_cert', + field=models.TextField(blank=True, verbose_name='CA cert'), + ), + migrations.AddField( + model_name='database', + name='client_cert', + field=models.TextField(blank=True, verbose_name='Client cert'), + ), + migrations.AddField( + model_name='database', + name='client_key', + field=models.TextField(blank=True, verbose_name='Client key'), + ), + migrations.AddField( + model_name='database', + name='use_ssl', + field=models.BooleanField(default=False, verbose_name='Use SSL'), + ), ] diff --git a/apps/assets/migrations/0115_auto_20221130_1118.py b/apps/assets/migrations/0115_auto_20221130_1118.py deleted file mode 100644 index 3d5fc9b20..000000000 --- a/apps/assets/migrations/0115_auto_20221130_1118.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 3.2.14 on 2022-11-30 03:18 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0114_node_domain'), - ] - - operations = [ - migrations.AddField( - model_name='database', - name='allow_invalid_cert', - field=models.BooleanField(default=False, verbose_name='Allow invalid cert'), - ), - migrations.AddField( - model_name='database', - name='ca_cert', - field=models.TextField(blank=True, verbose_name='CA cert'), - ), - migrations.AddField( - model_name='database', - name='client_cert', - field=models.TextField(blank=True, verbose_name='Client cert'), - ), - migrations.AddField( - model_name='database', - name='client_key', - field=models.TextField(blank=True, verbose_name='Client key'), - ), - migrations.AddField( - model_name='database', - name='use_ssl', - field=models.BooleanField(default=False, verbose_name='Use SSL'), - ), - ] diff --git a/apps/assets/migrations/0116_delete_gateway.py b/apps/assets/migrations/0116_delete_gateway.py deleted file mode 100644 index 9ccb1c1b7..000000000 --- a/apps/assets/migrations/0116_delete_gateway.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-01 07:08 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0115_auto_20221130_1118'), - ] - - operations = [ - migrations.DeleteModel( - name='Gateway', - ), - ] diff --git a/apps/assets/migrations/0117_gateway.py b/apps/assets/migrations/0117_gateway.py deleted file mode 100644 index 6bf8ce138..000000000 --- a/apps/assets/migrations/0117_gateway.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-01 07:21 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0116_delete_gateway'), - ] - - operations = [ - migrations.CreateModel( - name='Gateway', - fields=[ - ], - options={ - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('assets.host',), - ), - ] diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index e9df9d33b..97ef3b5ff 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -278,7 +278,7 @@ class ConnectionTokenViewSet(ExtraActionApiMixin, RootOrgViewMixin, JMSModelView data = serializer.validated_data user = self.get_user(serializer) asset = data.get('asset') - account_name = data.get('account_name') + account_name = data.get('account') data['org_id'] = asset.org_id data['user'] = user data['value'] = random_string(16) diff --git a/apps/authentication/migrations/0015_auto_20221205_1136.py b/apps/authentication/migrations/0015_auto_20221205_1136.py new file mode 100644 index 000000000..7de71fe5c --- /dev/null +++ b/apps/authentication/migrations/0015_auto_20221205_1136.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.14 on 2022-12-05 03:36 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ('authentication', '0014_auto_20221122_2152'), + ] + + operations = [ + migrations.RenameField( + model_name='connectiontoken', + old_name='account_name', + new_name='account', + ), + ] diff --git a/apps/authentication/models/connection_token.py b/apps/authentication/models/connection_token.py index 93b137923..1b8e27085 100644 --- a/apps/authentication/models/connection_token.py +++ b/apps/authentication/models/connection_token.py @@ -28,7 +28,7 @@ class ConnectionToken(OrgModelMixin, JMSBaseModel): 'assets.Asset', on_delete=models.SET_NULL, null=True, blank=True, related_name='connection_tokens', verbose_name=_('Asset'), ) - account_name = models.CharField(max_length=128, verbose_name=_("Account name")) # 登录账号Name + account = models.CharField(max_length=128, verbose_name=_("Account name")) # 登录账号Name input_username = models.CharField(max_length=128, default='', blank=True, verbose_name=_("Input username")) input_secret = EncryptCharField(max_length=64, default='', blank=True, verbose_name=_("Input secret")) protocol = models.CharField(max_length=16, default=Protocol.ssh, verbose_name=_("Protocol")) @@ -74,7 +74,7 @@ class ConnectionToken(OrgModelMixin, JMSBaseModel): def permed_account(self): from perms.utils import PermAccountUtil permed_account = PermAccountUtil().validate_permission( - self.user, self.asset, self.account_name + self.user, self.asset, self.account ) return permed_account @@ -86,6 +86,12 @@ class ConnectionToken(OrgModelMixin, JMSBaseModel): def expire_at(self): return self.permed_account.date_expired.timestamp() + @lazyproperty + def connect_method_object(self): + from terminal.const import TerminalType + method = TerminalType.get_connect_method(self.connect_method, protocol=self.protocol) + return method + def is_valid(self): if self.is_expired: error = _('Connection token expired at: {}').format(as_current_tz(self.date_expired)) @@ -97,13 +103,13 @@ class ConnectionToken(OrgModelMixin, JMSBaseModel): is_valid = False error = _('No asset or inactive asset') return is_valid, error - if not self.account_name: + if not self.account: error = _('No account') raise PermissionDenied(error) if not self.permed_account or not self.permed_account.actions: msg = 'user `{}` not has asset `{}` permission for login `{}`'.format( - self.user, self.asset, self.account_name + self.user, self.asset, self.account ) raise PermissionDenied(msg) @@ -116,15 +122,15 @@ class ConnectionToken(OrgModelMixin, JMSBaseModel): return self.asset.platform @lazyproperty - def account(self): + def account_object(self): from assets.models import Account if not self.asset: return None - account = self.asset.accounts.filter(name=self.account_name).first() - if self.account_name == '@INPUT' or not account: + account = self.asset.accounts.filter(name=self.account).first() + if self.account == '@INPUT' or not account: data = { - 'name': self.account_name, + 'name': self.account, 'username': self.input_username, 'secret_type': 'password', 'secret': self.input_secret, diff --git a/apps/authentication/serializers/connect_token_secret.py b/apps/authentication/serializers/connect_token_secret.py index dd8804ac7..48f86ba50 100644 --- a/apps/authentication/serializers/connect_token_secret.py +++ b/apps/authentication/serializers/connect_token_secret.py @@ -84,14 +84,14 @@ class _ConnectionTokenPlatformSerializer(PlatformSerializer): class ConnectionTokenSecretSerializer(OrgResourceModelSerializerMixin): user = _ConnectionTokenUserSerializer(read_only=True) asset = _ConnectionTokenAssetSerializer(read_only=True) - account = _ConnectionTokenAccountSerializer(read_only=True) + account = _ConnectionTokenAccountSerializer(read_only=True, source='account_object') gateway = _ConnectionTokenGatewaySerializer(read_only=True) platform = _ConnectionTokenPlatformSerializer(read_only=True) acl_command_groups = _ConnectionTokenACLCmdGroupSerializer(read_only=True, many=True) actions = ActionChoicesField() expire_at = serializers.IntegerField() expire_now = serializers.BooleanField(label=_('Expired now'), write_only=True, default=True) - connect_method = serializers.CharField(label=_('Connect method'), write_only=True, default='ssh') + connect_method = serializers.SerializerMethodField(label=_('Connect method')) class Meta: model = ConnectionToken @@ -99,7 +99,19 @@ class ConnectionTokenSecretSerializer(OrgResourceModelSerializerMixin): 'id', 'value', 'user', 'asset', 'account', 'platform', 'acl_command_groups', 'protocol', 'gateway', 'actions', 'expire_at', 'expire_now', + 'connect_method' ] extra_kwargs = { 'value': {'read_only': True}, } + + def get_connect_method(self, obj): + from terminal.const import TerminalType + from common.utils import get_request_os + request = self.context.get('request') + if request: + os = get_request_os(request) + else: + os = 'windows' + method = TerminalType.get_connect_method(obj.connect_method, protocol=obj.protocol, os=os) + return method diff --git a/apps/authentication/serializers/connection_token.py b/apps/authentication/serializers/connection_token.py index dddcd0866..b627db320 100644 --- a/apps/authentication/serializers/connection_token.py +++ b/apps/authentication/serializers/connection_token.py @@ -16,7 +16,7 @@ class ConnectionTokenSerializer(OrgResourceModelSerializerMixin): model = ConnectionToken fields_mini = ['id', 'value'] fields_small = fields_mini + [ - 'user', 'asset', 'account_name', 'input_username', + 'user', 'asset', 'account', 'input_username', 'input_secret', 'connect_method', 'protocol', 'actions', 'date_expired', 'date_created', 'date_updated', 'created_by', 'updated_by', 'org_id', 'org_name', diff --git a/apps/terminal/const.py b/apps/terminal/const.py index 6d7a14f9d..c5ceb3c94 100644 --- a/apps/terminal/const.py +++ b/apps/terminal/const.py @@ -229,7 +229,7 @@ class TerminalType(TextChoices): return protocols @classmethod - def get_connect_method(cls, name, protocol, os): + def get_connect_method(cls, name, protocol, os='linux'): methods = cls.get_protocols_connect_methods(os) protocol_methods = methods.get(protocol, []) for method in protocol_methods: @@ -267,7 +267,6 @@ class TerminalType(TextChoices): protocol_web_methods = set(web_methods.get(protocol, [])) \ & set(component_protocol.get('web_methods', [])) - print("protocol_web_methods", protocol, protocol_web_methods) methods[protocol.value].extend([ { 'component': component.value,