diff --git a/backend/apps/monitor/migrations/0010_iamuser_deny_policy_exempt.py b/backend/apps/monitor/migrations/0010_iamuser_deny_policy_exempt.py new file mode 100644 index 0000000..c29ac6e --- /dev/null +++ b/backend/apps/monitor/migrations/0010_iamuser_deny_policy_exempt.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.21 on 2026-03-28 16:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('monitor', '0009_iamuser_volc_login_allowed'), + ] + + operations = [ + migrations.AddField( + model_name='iamuser', + name='deny_policy_exempt', + field=models.BooleanField(default=False, help_text='开启后不生成项目隔离 Deny 策略(适用于管理员自用账号)', verbose_name='免除 Deny 策略'), + ), + ] diff --git a/backend/apps/monitor/models.py b/backend/apps/monitor/models.py index 6a1565a..58d036a 100644 --- a/backend/apps/monitor/models.py +++ b/backend/apps/monitor/models.py @@ -62,6 +62,9 @@ class IAMUser(models.Model): triggered_alerts = models.JSONField('已触发的告警阈值', default=list, blank=True, help_text='记录已通知过的百分比,划拨新额度时自动重置') + deny_policy_exempt = models.BooleanField('免除 Deny 策略', default=False, + help_text='开启后不生成项目隔离 Deny 策略(适用于管理员自用账号)') + # --- 停用时保存的策略快照(恢复时自动加回) --- saved_policies_on_disable = models.JSONField('停用时保存的策略', default=list, blank=True, help_text='停用时自动移除的策略列表,恢复时加回') diff --git a/backend/apps/monitor/serializers.py b/backend/apps/monitor/serializers.py index f17bd80..bed8e2a 100644 --- a/backend/apps/monitor/serializers.py +++ b/backend/apps/monitor/serializers.py @@ -42,6 +42,7 @@ class IAMUserSerializer(serializers.ModelSerializer): 'effective_alert_thresholds', 'projects', 'monitored_project_count', 'login_enabled', 'volc_login_allowed', + 'deny_policy_exempt', 'remark', 'created_at', 'updated_at', ] read_only_fields = ['user_id', 'access_key_ids', 'status', @@ -77,6 +78,7 @@ class IAMUserConfigSerializer(serializers.Serializer): ) monitor_enabled = serializers.BooleanField(required=False) auto_disable_enabled = serializers.BooleanField(required=False) + deny_policy_exempt = serializers.BooleanField(required=False) class IAMUserProjectAddSerializer(serializers.Serializer): diff --git a/backend/apps/monitor/views.py b/backend/apps/monitor/views.py index be08cb0..200c889 100644 --- a/backend/apps/monitor/views.py +++ b/backend/apps/monitor/views.py @@ -50,6 +50,12 @@ def _update_deny_policy(user): if not ak: return svc = IAMService(ak, sk) + + if user.deny_policy_exempt: + # 免除 Deny 策略的账号,移除已有的 Deny 策略 + svc.remove_deny_policy(user.username) + return + allowed_projects = list( user.projects.values_list('project_name', flat=True) ) @@ -420,9 +426,16 @@ def iam_user_update_view(request, pk): serializer = IAMUserConfigSerializer(data=request.data, partial=True) serializer.is_valid(raise_exception=True) + deny_changed = 'deny_policy_exempt' in serializer.validated_data and \ + serializer.validated_data['deny_policy_exempt'] != user.deny_policy_exempt + for field, value in serializer.validated_data.items(): setattr(user, field, value) user.save() + + if deny_changed: + _update_deny_policy(user) + return Response(IAMUserSerializer(user).data) diff --git a/frontend/src/views/iam/IAMUserList.vue b/frontend/src/views/iam/IAMUserList.vue index e5f1eda..401fd65 100644 --- a/frontend/src/views/iam/IAMUserList.vue +++ b/frontend/src/views/iam/IAMUserList.vue @@ -155,6 +155,10 @@ {{ configForm.auto_disable_enabled ? '消费达100%额度时自动停用' : '仅通知不停用' }} + + + {{ configForm.deny_policy_exempt ? '不限制项目访问(管理员账号)' : '按关联项目限制访问' }} +