mcpField
A
acl-management

acl-management

github.com/happy-technologies-llc安全4141 次安装2 天前更新
代码仓库

关于 acl-management

该技能面向 ServiceNow 管理员和安全人员,指导 ACL 的检查、创建、修改与故障排查。内容涵盖表级、字段级和记录级访问控制,以及角色要求和调试方法。

主要功能

  1. 01查询 ACL 及其角色要求
  2. 02创建表级、字段级和记录级 ACL
  3. 03安全修改现有 ACL
  4. 04排查用户权限问题
  5. 05分析 ACL 评估与冲突
  6. 06检查角色组合风险

适用场景

  1. 01为新表或应用配置访问控制
  2. 02调查用户遇到的拒绝访问问题
  3. 03实施字段级或行级权限
  4. 04审查现有权限与 ACL 配置

MCP 相关

该技能使用 ServiceNow MCP 工具查询 ACL、创建或更新规则与角色,并运行脚本辅助调试。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/happy-technologies-llc/happy-platform-skills --skill acl-management

安装后在 Claude Code 中输入/acl-management确认已加载。

详细介绍

ACL 管理

概述

访问控制列表(ACL)是 ServiceNow 安全性的基础。本技能涵盖:

  • 了解 ACL 结构和继承层级
  • 为表、字段和记录创建新的 ACL
  • 安全地修改现有 ACL 规则
  • 排查权限问题
  • ACL 调试技术和工具
  • 基于角色的访问控制最佳实践

使用场景:

  • 为新表或应用设置安全性
  • 排查“拒绝访问”问题
  • 实施字段级安全性
  • 审计和审查现有权限
  • 实施行级安全性(查询条件)

前提条件

  • 角色: security_admin 或 admin
  • 访问权限: sys_security_acl、sys_security_acl_role 表
  • 知识: 了解 ServiceNow 角色和用户组
  • 插件: 核心平台(ACL 为内置功能)

ACL 基础知识

ACL 层级
                    ┌─────────────────┐
                    │  Table ACL (*)  │  ← Broadest
                    │  incident.*     │
                    └────────┬────────┘
                             │
                    ┌────────▼────────┐
                    │  Table.Field    │  ← Field-specific
                    │  incident.state │
                    └────────┬────────┘
                             │
                    ┌────────▼────────┐
                    │ Table.None      │  ← Row-level
                    │ (with script)   │
                    └─────────────────┘  ← Most specific
ACL 操作
操作用途常见用法
read查看记录/字段列表、表单显示
write修改记录/字段表单编辑
create插入新记录创建新记录
delete删除记录删除记录
execute运行脚本/操作UI 操作、处理器
ACL 评估顺序
  1. 最具体的规则优先: 字段 ACL > 表 ACL
  2. 首次匹配: 评估在第一个匹配的 ACL 处停止
  3. 默认拒绝: 没有匹配的 ACL = 拒绝访问
  4. 管理员绕过: 管理员角色可绕过大多数 ACL

操作步骤

阶段 1:了解现有 ACL
1.1 查询表的 ACL

查找特定表的所有 ACL:

Tool: SN-Query-Table
Parameters:
  table_name: sys_security_acl
  query: nameLIKEincident
  fields: name,operation,type,condition,script,active
  limit: 50

按操作类型查找 ACL:

Tool: SN-Query-Table
Parameters:
  table_name: sys_security_acl
  query: name=incident^operation=write
  fields: name,operation,admin_overrides,condition,script,active
  limit: 20
1.2 了解 ACL 结构

获取 ACL 表架构:

Tool: SN-Get-Table-Schema
Parameters:
  table_name: sys_security_acl

ACL 关键字段:

字段类型用途
name字符串表.字段或表.*
operation选项read、write、create、delete、execute
type选项record、client_callable_script_include
condition条件行级安全性的筛选条件
script脚本高级条件逻辑
admin_overrides布尔值允许管理员绕过
active布尔值是否强制执行 ACL
advanced布尔值是否使用脚本条件
1.3 检查 ACL 的角色要求

查找 ACL 所需的角色:

Tool: SN-Query-Table
Parameters:
  table_name: sys_security_acl_role
  query: acl.name=incident.*^acl.operation=write
  fields: acl.name,acl.operation,role.name
  limit: 20
阶段 2:创建新的 ACL
2.1 创建表级 ACL

为自定义表创建读取 ACL:

Tool: SN-Create-Record
Parameters:
  table_name: sys_security_acl
  data:
    name: "u_custom_table.*"
    operation: read
    type: record
    admin_overrides: true
    active: true
    description: "Read access to custom table"

添加角色要求:

Tool: SN-Create-Record
Parameters:
  table_name: sys_security_acl_role
  data:
    acl: [acl_sys_id]
    role: [role_sys_id]
2.2 创建字段级 ACL

保护敏感字段:

Tool: SN-Create-Record
Parameters:
  table_name: sys_security_acl
  data:
    name: "u_custom_table.ssn_number"
    operation: read
    type: record
    admin_overrides: true
    active: true
    description: "Restrict SSN field to authorized users only"

添加多个角色要求:

Tool: SN-Query-Table
Parameters:
  table_name: sys_user_role
  query: nameINhr_admin,security_admin
  fields: sys_id,name
  limit: 10

然后为每个角色执行:

Tool: SN-Create-Record
Parameters:
  table_name: sys_security_acl_role
  data:
    acl: [field_acl_sys_id]
    role: [hr_admin_role_sys_id]
2.3 创建行级 ACL(基于条件)

用户只能查看自己的记录:

Tool: SN-Create-Record
Parameters:
  table_name: sys_security_acl
  data:
    name: "u_custom_table"
    operation: read
    type: record
    condition: "opened_by=javascript:gs.getUserID()"
    admin_overrides: true
    active: true
    description: "Users can only read their own records"
2.4 创建基于脚本的 ACL

需要脚本的复杂逻辑:

Tool: SN-Create-Record
Parameters:
  table_name: sys_security_acl
  data:
    name: "u_custom_table"
    operation: write
    type: record
    advanced: true
    script: |
      // Allow write if user is the owner OR is in the assigned group
      var userId = gs.getUserID();
      var userGroups = gs.getUser().getMyGroups();

      if (current.owner == userId) {
        answer = true;
      } else if (userGroups.indexOf(current.assignment_group.toString()) >= 0) {
        answer = true;
      } else {
        answer = false;
      }
    admin_overrides: true
    active: true
    description: "Allow write for owner or group members"
阶段 3:安全地修改 ACL
3.1 进行重大更改前先停用

暂时停用 ACL:

Tool: SN-Update-Record
Parameters:
  table_name: sys_security_acl
  sys_id: [acl_sys_id]
  data:
    active: false

进行更改:

Tool: SN-Update-Record
Parameters:
  table_name: sys_security_acl
  sys_id: [acl_sys_id]
  data:
    condition: "state!=6^ORassigned_to=javascript:gs.getUserID()"
    description: "Updated condition - users can access non-closed or own records"

测试后重新启用:

Tool: SN-Update-Record
Parameters:
  table_name: sys_security_acl
  sys_id: [acl_sys_id]
  data:
    active: true
3.2 添加/移除角色要求

添加新的角色要求:

Tool: SN-Create-Record
Parameters:
  table_name: sys_security_acl_role
  data:
    acl: [acl_sys_id]
    role: [new_role_sys_id]

移除角色要求:

Tool: SN-Query-Table
Parameters:
  table_name: sys_security_acl_role
  query: acl=[acl_sys_id]^role=[role_sys_id]
  fields: sys_id

# Then delete the record using SN-Update-Record or background script
阶段 4:排查权限问题
4.1 确定阻止访问的 ACL

启用 ACL 调试(基于会话):

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    // This enables debug output for the session
    // Run manually: Navigate to User menu > Impersonate > Check security
    gs.info('To debug ACLs:');
    gs.info('1. Navigate to System Security > Debugging');
    gs.info('2. Or add ?sysparm_security_debug=true to URL');
    gs.info('3. Or impersonate user and check security diagnostics');
  description: "ACL debugging instructions"

检查用户的角色:

Tool: SN-Query-Table
Parameters:
  table_name: sys_user_has_role
  query: user=[user_sys_id]^role.name!=snc_internal
  fields: role.name,granted_by,inherited
  limit: 50

检查用户的组:

Tool: SN-Query-Table
Parameters:
  table_name: sys_user_grmember
  query: user=[user_sys_id]
  fields: group.name,group.sys_id
  limit: 50
4.2 跟踪 ACL 评估

查找适用的 ACL:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var table = 'incident';
    var operation = 'write';
    var fieldName = 'state'; // or '*' for table-level

    var acl = new GlideRecord('sys_security_acl');
    acl.addQuery('name', 'CONTAINS', table);
    acl.addQuery('operation', operation);
    acl.addQuery('active', true);
    acl.orderBy('name');
    acl.query();

    gs.info('ACLs for ' + table + '.' + fieldName + ' (' + operation + '):');
    while (acl.next()) {
      var roles = [];
      var roleGr = new GlideRecord('sys_security_acl_role');
      roleGr.addQuery('acl', acl.sys_id);
      roleGr.query();
      while (roleGr.next()) {
        roles.push(roleGr.role.name.toString());
      }

      gs.info(acl.name + ' - Roles: [' + roles.join(', ') + '] - Condition: ' + acl.condition);
    }
  description: "Trace ACL evaluation for table/operation"
4.3 测试用户访问权限

检查用户是否拥有所需角色:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var userId = '[user_sys_id]';
    var requiredRoles = ['itil', 'incident_manager'];

    var user = new GlideRecord('sys_user');
    user.get(userId);

    gs.info('Checking roles for: ' + user.user_name);

    for (var i = 0; i < requiredRoles.length; i++) {
      var hasRole = new GlideRecord('sys_user_has_role');
      hasRole.addQuery('user', userId);
      hasRole.addQuery('role.name', requiredRoles[i]);
      hasRole.query();

      if (hasRole.hasNext()) {
        gs.info('  HAS: ' + requiredRoles[i]);
      } else {
        gs.warn('  MISSING: ' + requiredRoles[i]);
      }
    }
  description: "Check user role membership"
4.4 常见权限问题

问题:用户可以查看表,但无法查看特定记录

# Check for row-level ACL conditions
Tool: SN-Query-Table
Parameters:
  table_name: sys_security_acl
  query: name=[table_name]^operation=read^conditionISNOTEMPTY
  fields: name,condition,script

问题:用户可以读取,但无法写入

# Compare read vs write ACLs
Tool: SN-Query-Table
Parameters:
  table_name: sys_security_acl
  query: nameLIKE[table_name]^operationINread,write
  fields: name,operation,condition
  limit: 20

问题:字段意外变为只读

# Check field-level ACLs
Tool: SN-Query-Table
Parameters:
  table_name: sys_security_acl
  query: name=[table_name].[field_name]^operation=write
  fields: name,operation,condition,active
阶段 5:ACL 调试工具
5.1 安全诊断工具

对记录运行安全诊断:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var table = 'incident';
    var sysId = '[record_sys_id]';
    var userId = '[user_sys_id]';

    // Impersonate and check access
    var gr = new GlideRecord(table);
    gr.get(sysId);

    var canRead = gr.canRead();
    var canWrite = gr.canWrite();
    var canDelete = gr.canDelete();

    gs.info('Security Diagnostic for ' + table + '/' + sysId);
    gs.info('  Can Read: ' + canRead);
    gs.info('  Can Write: ' + canWrite);
    gs.info('  Can Delete: ' + canDelete);

    // Check field-level access
    var elements = ['state', 'priority', 'assigned_to'];
    for (var i = 0; i < elements.length; i++) {
      var field = elements[i];
      gs.info('  Field ' + field + ' - canRead: ' + gr[field].canRead() +
              ', canWrite: ' + gr[field].canWrite());
    }
  description: "Run security diagnostic on record"
5.2 ACL 规则分析器

分析所有 ACL 是否存在冲突:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var table = 'incident';
    var analysis = {
      table_acls: [],
      field_acls: [],
      potential_conflicts: []
    };

    var acl = new GlideRecord('sys_security_acl');
    acl.addQuery('name', 'STARTSWITH', table);
    acl.addQuery('active', true);
    acl.orderBy('name');
    acl.query();

    while (acl.next()) {
      var aclInfo = {
        name: acl.name.toString(),
        operation: acl.operation.toString(),
        has_condition: acl.condition.toString() !== '',
        has_script: acl.advanced.toString() === 'true'
      };

      if (acl.name.toString().indexOf('.') === -1 ||
          acl.name.toString().endsWith('.*')) {
        analysis.table_acls.push(aclInfo);
      } else {
        analysis.field_acls.push(aclInfo);
      }
    }

    // Check for potential issues
    if (analysis.table_acls.length === 0) {
      analysis.potential_conflicts.push('No table-level ACLs - may be too open or rely on inheritance');
    }

    gs.info('ACL Analysis for ' + table + ':\n' + JSON.stringify(analysis, null, 2));
  description: "Analyze ACLs for conflicts and issues"
5.3 角色提升检查

查找可能存在危险角色组合的用户:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var dangerousCombos = [
      ['admin', 'maint'],
      ['security_admin', 'personalize_dictionary'],
      ['admin', 'soap']
    ];

    var findings = [];

    for (var i = 0; i < dangerousCombos.length; i++) {
      var combo = dangerousCombos[i];

      var users = new GlideRecord('sys_user');
      users.addQuery('active', true);
      users.query();

      while (users.next()) {
        var hasAll = true;
        for (var j = 0; j < combo.length; j++) {
          var roleCheck = new GlideRecord('sys_user_has_role');
          roleCheck.addQuery('user', users.sys_id);
          roleCheck.addQuery('role.name', combo[j]);
          roleCheck.query();
          if (!roleCheck.hasNext()) {
            hasAll = false;
            break;
          }
        }

        if (hasAll) {
          findings.push({
            user: users.user_name.toString(),
            roles: combo
          });
        }
      }
    }

    if (findings.length > 0) {
      gs.warn('Users with dangerous role combinations:');
      gs.info(JSON.stringify(findings, null, 2));
    } else {
      gs.info('No dangerous role combinations found');
    }
  description: "Find users with dangerous role combinations"

最佳实践

设计原则
  1. 最小权限原则: 仅授予所需的最低访问权限
  2. 基于角色的访问: 使用角色,而非单个用户
  3. 尽可能继承: 使用表级 ACL 作为基准
  4. 记录一切: 为所有 ACL 添加说明
  5. 彻底测试: 使用多个用户角色进行验证
常见模式

模式 1:所有者 + 群组访问

// Condition for owner or group member access
opened_by=javascript:gs.getUserID()^ORassignment_group.memberSOME=javascript:gs.getUserID()

模式 2:分层访问

// Managers can see their team's records
var mgr = new GlideRecord('sys_user');
mgr.addQuery('manager', gs.getUserID());
mgr.query();
var users = [gs.getUserID()];
while (mgr.next()) users.push(mgr.sys_id.toString());
answer = gs.getUser().getID() in users.join(',').split(',');

模式 3:基于时间的访问

// Only allow access during business hours
var now = new GlideDateTime();
var hour = now.getLocalTime().getHourOfDay();
answer = (hour >= 8 && hour < 18);

工具使用摘要

操作MCP 工具REST 端点
查询 ACLSN-Query-TableGET /sys_security_acl
创建 ACLSN-Create-RecordPOST /sys_security_acl
更新 ACLSN-Update-RecordPATCH /sys_security_acl
添加角色SN-Create-RecordPOST /sys_security_acl_role
调试 ACLSN-Execute-Background-Script通过 sys_trigger
检查架构SN-Get-Table-SchemaGET /sys_dictionary

故障排除

ACL 未被评估

症状: ACL 更改没有效果 原因: ACL 缓存未清除,或 ACL 未启用 解决方案:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    // Clear ACL cache
    GlideAccessControl.reset();
    gs.info('ACL cache cleared');
  description: "Clear ACL cache"
管理员无法访问记录

症状: 管理员角色被阻止访问记录 原因: ACL 设置了 admin_overrides=false 解决方案:

Tool: SN-Query-Table
Parameters:
  table_name: sys_security_acl
  query: name=[table]^admin_overrides=false
  fields: name,operation,admin_overrides
脚本 ACL 始终失败

症状: 基于脚本的 ACL 从不授予访问权限 原因: 脚本出错或 answer 变量不正确 解决方案:

  • 确认脚本设置了 answer = true 或 answer = false
  • 检查 syslog 中的脚本错误
  • 确保设置了 advanced = true
角色未授予访问权限

症状: 用户拥有角色,但仍被拒绝访问 原因: ACL 要求多个角色(AND),或条件不满足 解决方案:

Tool: SN-Query-Table
Parameters:
  table_name: sys_security_acl_role
  query: acl=[acl_sys_id]
  fields: role.name

默认情况下,必须具备列出的所有角色(AND 逻辑)。

示例

示例 1:保护自定义表
# Step 1: Create table-level read ACL
Tool: SN-Create-Record
Parameters:
  table_name: sys_security_acl
  data:
    name: "u_employee_data.*"
    operation: read
    type: record
    admin_overrides: true
    active: true
    description: "Base read access to employee data"

# Step 2: Add role requirement
Tool: SN-Create-Record
Parameters:
  table_name: sys_security_acl_role
  data:
    acl: [step1_sys_id]
    role: [hr_user_role_sys_id]

# Step 3: Create write ACL (more restrictive)
Tool: SN-Create-Record
Parameters:
  table_name: sys_security_acl
  data:
    name: "u_employee_data.*"
    operation: write
    type: record
    admin_overrides: true
    active: true
    description: "Write access to employee data - HR admins only"

# Step 4: Add admin role requirement
Tool: SN-Create-Record
Parameters:
  table_name: sys_security_acl_role
  data:
    acl: [step3_sys_id]
    role: [hr_admin_role_sys_id]
示例 2:字段级 SSN 保护
# Protect SSN field - only security cleared users
Tool: SN-Create-Record
Parameters:
  table_name: sys_security_acl
  data:
    name: "u_employee_data.ssn"
    operation: read
    type: record
    admin_overrides: false
    active: true
    description: "SSN access restricted - security clearance required"

# Add special role
Tool: SN-Create-Record
Parameters:
  table_name: sys_security_acl_role
  data:
    acl: [ssn_acl_sys_id]
    role: [security_cleared_role_sys_id]

相关技能

  • security/audit-compliance - 审计 ACL 更改
  • security/incident-response - 响应访问违规
  • security/data-classification - 确定需要保护的内容
  • admin/user-provisioning - 管理用户角色

参考资料

评论

支持 Markdown