feat: add Deny policy exempt toggle for admin sub-accounts
- New deny_policy_exempt field on IAMUser model - Toggle in monitoring config dialog - Exempt accounts skip Deny policy creation - Changing the toggle immediately updates/removes Deny policy Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5b997bc1a7
commit
9f00e6996b
@ -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 策略'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -62,6 +62,9 @@ class IAMUser(models.Model):
|
|||||||
triggered_alerts = models.JSONField('已触发的告警阈值', default=list, blank=True,
|
triggered_alerts = models.JSONField('已触发的告警阈值', default=list, blank=True,
|
||||||
help_text='记录已通知过的百分比,划拨新额度时自动重置')
|
help_text='记录已通知过的百分比,划拨新额度时自动重置')
|
||||||
|
|
||||||
|
deny_policy_exempt = models.BooleanField('免除 Deny 策略', default=False,
|
||||||
|
help_text='开启后不生成项目隔离 Deny 策略(适用于管理员自用账号)')
|
||||||
|
|
||||||
# --- 停用时保存的策略快照(恢复时自动加回) ---
|
# --- 停用时保存的策略快照(恢复时自动加回) ---
|
||||||
saved_policies_on_disable = models.JSONField('停用时保存的策略', default=list, blank=True,
|
saved_policies_on_disable = models.JSONField('停用时保存的策略', default=list, blank=True,
|
||||||
help_text='停用时自动移除的策略列表,恢复时加回')
|
help_text='停用时自动移除的策略列表,恢复时加回')
|
||||||
|
|||||||
@ -42,6 +42,7 @@ class IAMUserSerializer(serializers.ModelSerializer):
|
|||||||
'effective_alert_thresholds',
|
'effective_alert_thresholds',
|
||||||
'projects', 'monitored_project_count',
|
'projects', 'monitored_project_count',
|
||||||
'login_enabled', 'volc_login_allowed',
|
'login_enabled', 'volc_login_allowed',
|
||||||
|
'deny_policy_exempt',
|
||||||
'remark', 'created_at', 'updated_at',
|
'remark', 'created_at', 'updated_at',
|
||||||
]
|
]
|
||||||
read_only_fields = ['user_id', 'access_key_ids', 'status',
|
read_only_fields = ['user_id', 'access_key_ids', 'status',
|
||||||
@ -77,6 +78,7 @@ class IAMUserConfigSerializer(serializers.Serializer):
|
|||||||
)
|
)
|
||||||
monitor_enabled = serializers.BooleanField(required=False)
|
monitor_enabled = serializers.BooleanField(required=False)
|
||||||
auto_disable_enabled = serializers.BooleanField(required=False)
|
auto_disable_enabled = serializers.BooleanField(required=False)
|
||||||
|
deny_policy_exempt = serializers.BooleanField(required=False)
|
||||||
|
|
||||||
|
|
||||||
class IAMUserProjectAddSerializer(serializers.Serializer):
|
class IAMUserProjectAddSerializer(serializers.Serializer):
|
||||||
|
|||||||
@ -50,6 +50,12 @@ def _update_deny_policy(user):
|
|||||||
if not ak:
|
if not ak:
|
||||||
return
|
return
|
||||||
svc = IAMService(ak, sk)
|
svc = IAMService(ak, sk)
|
||||||
|
|
||||||
|
if user.deny_policy_exempt:
|
||||||
|
# 免除 Deny 策略的账号,移除已有的 Deny 策略
|
||||||
|
svc.remove_deny_policy(user.username)
|
||||||
|
return
|
||||||
|
|
||||||
allowed_projects = list(
|
allowed_projects = list(
|
||||||
user.projects.values_list('project_name', flat=True)
|
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 = IAMUserConfigSerializer(data=request.data, partial=True)
|
||||||
serializer.is_valid(raise_exception=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():
|
for field, value in serializer.validated_data.items():
|
||||||
setattr(user, field, value)
|
setattr(user, field, value)
|
||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
|
if deny_changed:
|
||||||
|
_update_deny_policy(user)
|
||||||
|
|
||||||
return Response(IAMUserSerializer(user).data)
|
return Response(IAMUserSerializer(user).data)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -155,6 +155,10 @@
|
|||||||
<el-switch v-model="configForm.auto_disable_enabled" />
|
<el-switch v-model="configForm.auto_disable_enabled" />
|
||||||
<span class="switch-hint">{{ configForm.auto_disable_enabled ? '消费达100%额度时自动停用' : '仅通知不停用' }}</span>
|
<span class="switch-hint">{{ configForm.auto_disable_enabled ? '消费达100%额度时自动停用' : '仅通知不停用' }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="免除 Deny 策略">
|
||||||
|
<el-switch v-model="configForm.deny_policy_exempt" />
|
||||||
|
<span class="switch-hint">{{ configForm.deny_policy_exempt ? '不限制项目访问(管理员账号)' : '按关联项目限制访问' }}</span>
|
||||||
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="configVisible = false">取消</el-button>
|
<el-button @click="configVisible = false">取消</el-button>
|
||||||
@ -488,6 +492,7 @@ function openConfig(row) {
|
|||||||
alert_thresholds: [...(row.alert_thresholds?.length ? row.alert_thresholds : row.effective_alert_thresholds || [50, 80, 90])],
|
alert_thresholds: [...(row.alert_thresholds?.length ? row.alert_thresholds : row.effective_alert_thresholds || [50, 80, 90])],
|
||||||
monitor_enabled: row.monitor_enabled,
|
monitor_enabled: row.monitor_enabled,
|
||||||
auto_disable_enabled: row.auto_disable_enabled,
|
auto_disable_enabled: row.auto_disable_enabled,
|
||||||
|
deny_policy_exempt: row.deny_policy_exempt || false,
|
||||||
}
|
}
|
||||||
newStep.value = null
|
newStep.value = null
|
||||||
configVisible.value = true
|
configVisible.value = true
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user