grc-compliance

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GRC & Compliance for ServiceNow

ServiceNow 下的 GRC 与合规管理

GRC (Governance, Risk, Compliance) manages organizational policies, risks, and regulatory compliance.
GRC(治理、风险、合规)用于管理组织的政策、风险以及法规合规性。

GRC Architecture

GRC 架构

Policy (sn_compliance_policy)
    └── Policy Statements
        └── Controls (sn_compliance_control)
            └── Control Tests
                └── Test Results

Risk (sn_risk_risk)
    ├── Risk Assessment
    └── Risk Response
Policy (sn_compliance_policy)
    └── Policy Statements
        └── Controls (sn_compliance_control)
            └── Control Tests
                └── Test Results

Risk (sn_risk_risk)
    ├── Risk Assessment
    └── Risk Response

Key Tables

关键数据表

TablePurpose
sn_compliance_policy
Compliance policies
sn_compliance_control
Controls
sn_compliance_control_test
Control tests
sn_risk_risk
Risk records
sn_audit_engagement
Audit engagements
数据表用途
sn_compliance_policy
合规政策
sn_compliance_control
控制措施
sn_compliance_control_test
控制测试
sn_risk_risk
风险记录
sn_audit_engagement
审计项目

Policies (ES5)

政策管理(仅支持 ES5)

Create Policy

创建政策

javascript
// Create compliance policy (ES5 ONLY!)
var policy = new GlideRecord('sn_compliance_policy');
policy.initialize();

// Basic info
policy.setValue('name', 'Information Security Policy');
policy.setValue('description', 'Enterprise information security requirements');
policy.setValue('short_description', 'InfoSec Policy');

// Classification
policy.setValue('category', 'security');
policy.setValue('type', 'corporate');

// Owner
policy.setValue('owner', policyOwnerSysId);
policy.setValue('owning_group', securityTeamSysId);

// Status
policy.setValue('state', 'draft');

// Dates
policy.setValue('effective_date', '2024-01-01');
policy.setValue('review_date', '2025-01-01');

policy.insert();
javascript
// Create compliance policy (ES5 ONLY!)
var policy = new GlideRecord('sn_compliance_policy');
policy.initialize();

// Basic info
policy.setValue('name', 'Information Security Policy');
policy.setValue('description', 'Enterprise information security requirements');
policy.setValue('short_description', 'InfoSec Policy');

// Classification
policy.setValue('category', 'security');
policy.setValue('type', 'corporate');

// Owner
policy.setValue('owner', policyOwnerSysId);
policy.setValue('owning_group', securityTeamSysId);

// Status
policy.setValue('state', 'draft');

// Dates
policy.setValue('effective_date', '2024-01-01');
policy.setValue('review_date', '2025-01-01');

policy.insert();

Policy Lifecycle

政策生命周期

javascript
// Transition policy state (ES5 ONLY!)
function transitionPolicy(policySysId, newState, notes) {
    var policy = new GlideRecord('sn_compliance_policy');
    if (!policy.get(policySysId)) {
        return { success: false, message: 'Policy not found' };
    }

    var validTransitions = {
        'draft': ['review', 'retired'],
        'review': ['approved', 'draft'],
        'approved': ['published', 'draft'],
        'published': ['review', 'retired'],
        'retired': ['draft']
    };

    var currentState = policy.getValue('state');

    if (!validTransitions[currentState] ||
        validTransitions[currentState].indexOf(newState) === -1) {
        return { success: false, message: 'Invalid transition' };
    }

    policy.setValue('state', newState);

    if (newState === 'published') {
        policy.setValue('published_date', new GlideDateTime());
    }

    if (notes) {
        policy.work_notes = notes;
    }

    policy.update();

    return { success: true, state: newState };
}
javascript
// Transition policy state (ES5 ONLY!)
function transitionPolicy(policySysId, newState, notes) {
    var policy = new GlideRecord('sn_compliance_policy');
    if (!policy.get(policySysId)) {
        return { success: false, message: 'Policy not found' };
    }

    var validTransitions = {
        'draft': ['review', 'retired'],
        'review': ['approved', 'draft'],
        'approved': ['published', 'draft'],
        'published': ['review', 'retired'],
        'retired': ['draft']
    };

    var currentState = policy.getValue('state');

    if (!validTransitions[currentState] ||
        validTransitions[currentState].indexOf(newState) === -1) {
        return { success: false, message: 'Invalid transition' };
    }

    policy.setValue('state', newState);

    if (newState === 'published') {
        policy.setValue('published_date', new GlideDateTime());
    }

    if (notes) {
        policy.work_notes = notes;
    }

    policy.update();

    return { success: true, state: newState };
}

Controls (ES5)

控制措施管理(仅支持 ES5)

Create Control

创建控制措施

javascript
// Create compliance control (ES5 ONLY!)
var control = new GlideRecord('sn_compliance_control');
control.initialize();

// Basic info
control.setValue('name', 'Access Control Review');
control.setValue('description', 'Quarterly review of user access rights');
control.setValue('short_description', 'Access Review Control');

// Link to policy
control.setValue('policy', policySysId);

// Classification
control.setValue('type', 'detective');  // preventive, detective, corrective
control.setValue('category', 'access_control');
control.setValue('frequency', 'quarterly');

// Owner
control.setValue('owner', controlOwnerSysId);

// Testing
control.setValue('test_frequency', 'quarterly');
control.setValue('test_type', 'manual');

// Status
control.setValue('state', 'draft');

control.insert();
javascript
// Create compliance control (ES5 ONLY!)
var control = new GlideRecord('sn_compliance_control');
control.initialize();

// Basic info
control.setValue('name', 'Access Control Review');
control.setValue('description', 'Quarterly review of user access rights');
control.setValue('short_description', 'Access Review Control');

// Link to policy
control.setValue('policy', policySysId);

// Classification
control.setValue('type', 'detective');  // preventive, detective, corrective
control.setValue('category', 'access_control');
control.setValue('frequency', 'quarterly');

// Owner
control.setValue('owner', controlOwnerSysId);

// Testing
control.setValue('test_frequency', 'quarterly');
control.setValue('test_type', 'manual');

// Status
control.setValue('state', 'draft');

control.insert();

Control Testing

控制测试

javascript
// Create control test (ES5 ONLY!)
function createControlTest(controlSysId, testData) {
    var test = new GlideRecord('sn_compliance_control_test');
    test.initialize();

    test.setValue('control', controlSysId);
    test.setValue('name', testData.name);
    test.setValue('description', testData.description);

    // Test details
    test.setValue('test_type', testData.type);  // design, operating
    test.setValue('planned_start', testData.plannedStart);
    test.setValue('planned_end', testData.plannedEnd);

    // Assignment
    test.setValue('assigned_to', testData.tester);

    // Status
    test.setValue('state', 'open');

    return test.insert();
}

// Record test result
function recordTestResult(testSysId, result) {
    var test = new GlideRecord('sn_compliance_control_test');
    if (!test.get(testSysId)) {
        return false;
    }

    test.setValue('state', 'closed');
    test.setValue('result', result.outcome);  // pass, fail, not_tested
    test.setValue('actual_end', new GlideDateTime());
    test.setValue('findings', result.findings);
    test.setValue('evidence', result.evidence);

    // If failed, create issue
    if (result.outcome === 'fail') {
        createComplianceIssue(test, result);
    }

    test.update();
    return true;
}
javascript
// Create control test (ES5 ONLY!)
function createControlTest(controlSysId, testData) {
    var test = new GlideRecord('sn_compliance_control_test');
    test.initialize();

    test.setValue('control', controlSysId);
    test.setValue('name', testData.name);
    test.setValue('description', testData.description);

    // Test details
    test.setValue('test_type', testData.type);  // design, operating
    test.setValue('planned_start', testData.plannedStart);
    test.setValue('planned_end', testData.plannedEnd);

    // Assignment
    test.setValue('assigned_to', testData.tester);

    // Status
    test.setValue('state', 'open');

    return test.insert();
}

// Record test result
function recordTestResult(testSysId, result) {
    var test = new GlideRecord('sn_compliance_control_test');
    if (!test.get(testSysId)) {
        return false;
    }

    test.setValue('state', 'closed');
    test.setValue('result', result.outcome);  // pass, fail, not_tested
    test.setValue('actual_end', new GlideDateTime());
    test.setValue('findings', result.findings);
    test.setValue('evidence', result.evidence);

    // If failed, create issue
    if (result.outcome === 'fail') {
        createComplianceIssue(test, result);
    }

    test.update();
    return true;
}

Risk Management (ES5)

风险管理(仅支持 ES5)

Create Risk

创建风险记录

javascript
// Create risk record (ES5 ONLY!)
var risk = new GlideRecord('sn_risk_risk');
risk.initialize();

// Basic info
risk.setValue('name', 'Data Breach Risk');
risk.setValue('description', 'Risk of unauthorized access to customer data');
risk.setValue('short_description', 'Data Breach');

// Classification
risk.setValue('category', 'security');
risk.setValue('subcategory', 'data_protection');

// Risk assessment
risk.setValue('inherent_likelihood', 3);   // 1-5 scale
risk.setValue('inherent_impact', 5);       // 1-5 scale
// Inherent risk = likelihood x impact

// Controls that mitigate this risk
risk.setValue('controls', controlSysIds);  // Comma-separated

// Residual risk (after controls)
risk.setValue('residual_likelihood', 2);
risk.setValue('residual_impact', 5);

// Owner
risk.setValue('owner', riskOwnerSysId);

// Status
risk.setValue('state', 'assess');

risk.insert();
javascript
// Create risk record (ES5 ONLY!)
var risk = new GlideRecord('sn_risk_risk');
risk.initialize();

// Basic info
risk.setValue('name', 'Data Breach Risk');
risk.setValue('description', 'Risk of unauthorized access to customer data');
risk.setValue('short_description', 'Data Breach');

// Classification
risk.setValue('category', 'security');
risk.setValue('subcategory', 'data_protection');

// Risk assessment
risk.setValue('inherent_likelihood', 3);   // 1-5 scale
risk.setValue('inherent_impact', 5);       // 1-5 scale
// Inherent risk = likelihood x impact

// Controls that mitigate this risk
risk.setValue('controls', controlSysIds);  // Comma-separated

// Residual risk (after controls)
risk.setValue('residual_likelihood', 2);
risk.setValue('residual_impact', 5);

// Owner
risk.setValue('owner', riskOwnerSysId);

// Status
risk.setValue('state', 'assess');

risk.insert();

Risk Assessment

风险评估

javascript
// Calculate risk score (ES5 ONLY!)
function calculateRiskScore(likelihood, impact) {
    var score = likelihood * impact;

    var rating = 'low';
    if (score >= 20) {
        rating = 'critical';
    } else if (score >= 12) {
        rating = 'high';
    } else if (score >= 6) {
        rating = 'medium';
    }

    return {
        score: score,
        rating: rating
    };
}

// Assess risk and update record (ES5 ONLY!)
function assessRisk(riskSysId, assessment) {
    var risk = new GlideRecord('sn_risk_risk');
    if (!risk.get(riskSysId)) {
        return false;
    }

    // Update inherent risk
    risk.setValue('inherent_likelihood', assessment.inherentLikelihood);
    risk.setValue('inherent_impact', assessment.inherentImpact);

    var inherentScore = calculateRiskScore(
        assessment.inherentLikelihood,
        assessment.inherentImpact
    );
    risk.setValue('inherent_risk_score', inherentScore.score);
    risk.setValue('inherent_risk_rating', inherentScore.rating);

    // Update residual risk
    risk.setValue('residual_likelihood', assessment.residualLikelihood);
    risk.setValue('residual_impact', assessment.residualImpact);

    var residualScore = calculateRiskScore(
        assessment.residualLikelihood,
        assessment.residualImpact
    );
    risk.setValue('residual_risk_score', residualScore.score);
    risk.setValue('residual_risk_rating', residualScore.rating);

    // Assessment metadata
    risk.setValue('assessed_date', new GlideDateTime());
    risk.setValue('assessed_by', gs.getUserID());
    risk.setValue('state', 'monitor');

    risk.update();

    return true;
}
javascript
// Calculate risk score (ES5 ONLY!)
function calculateRiskScore(likelihood, impact) {
    var score = likelihood * impact;

    var rating = 'low';
    if (score >= 20) {
        rating = 'critical';
    } else if (score >= 12) {
        rating = 'high';
    } else if (score >= 6) {
        rating = 'medium';
    }

    return {
        score: score,
        rating: rating
    };
}

// Assess risk and update record (ES5 ONLY!)
function assessRisk(riskSysId, assessment) {
    var risk = new GlideRecord('sn_risk_risk');
    if (!risk.get(riskSysId)) {
        return false;
    }

    // Update inherent risk
    risk.setValue('inherent_likelihood', assessment.inherentLikelihood);
    risk.setValue('inherent_impact', assessment.inherentImpact);

    var inherentScore = calculateRiskScore(
        assessment.inherentLikelihood,
        assessment.inherentImpact
    );
    risk.setValue('inherent_risk_score', inherentScore.score);
    risk.setValue('inherent_risk_rating', inherentScore.rating);

    // Update residual risk
    risk.setValue('residual_likelihood', assessment.residualLikelihood);
    risk.setValue('residual_impact', assessment.residualImpact);

    var residualScore = calculateRiskScore(
        assessment.residualLikelihood,
        assessment.residualImpact
    );
    risk.setValue('residual_risk_score', residualScore.score);
    risk.setValue('residual_risk_rating', residualScore.rating);

    // Assessment metadata
    risk.setValue('assessed_date', new GlideDateTime());
    risk.setValue('assessed_by', gs.getUserID());
    risk.setValue('state', 'monitor');

    risk.update();

    return true;
}

Audits (ES5)

审计管理(仅支持 ES5)

Create Audit Engagement

创建审计项目

javascript
// Create audit engagement (ES5 ONLY!)
var audit = new GlideRecord('sn_audit_engagement');
audit.initialize();

audit.setValue('name', 'Q1 2024 SOX Audit');
audit.setValue('description', 'Quarterly SOX compliance audit');
audit.setValue('type', 'compliance');

// Dates
audit.setValue('planned_start', '2024-01-15');
audit.setValue('planned_end', '2024-02-15');

// Scope
audit.setValue('scope', 'Financial controls, access management');

// Team
audit.setValue('lead_auditor', auditorSysId);
audit.setValue('audit_team', auditTeamSysId);

// Status
audit.setValue('state', 'planning');

audit.insert();
javascript
// Create audit engagement (ES5 ONLY!)
var audit = new GlideRecord('sn_audit_engagement');
audit.initialize();

audit.setValue('name', 'Q1 2024 SOX Audit');
audit.setValue('description', 'Quarterly SOX compliance audit');
audit.setValue('type', 'compliance');

// Dates
audit.setValue('planned_start', '2024-01-15');
audit.setValue('planned_end', '2024-02-15');

// Scope
audit.setValue('scope', 'Financial controls, access management');

// Team
audit.setValue('lead_auditor', auditorSysId);
audit.setValue('audit_team', auditTeamSysId);

// Status
audit.setValue('state', 'planning');

audit.insert();

Audit Findings

审计发现记录

javascript
// Create audit finding (ES5 ONLY!)
function createAuditFinding(auditSysId, findingData) {
    var finding = new GlideRecord('sn_audit_finding');
    finding.initialize();

    finding.setValue('engagement', auditSysId);
    finding.setValue('title', findingData.title);
    finding.setValue('description', findingData.description);

    // Severity
    finding.setValue('severity', findingData.severity);  // critical, high, medium, low

    // Related control
    if (findingData.control) {
        finding.setValue('control', findingData.control);
    }

    // Recommendation
    finding.setValue('recommendation', findingData.recommendation);

    // Owner for remediation
    finding.setValue('owner', findingData.owner);

    // Due date for remediation
    finding.setValue('due_date', findingData.dueDate);

    finding.setValue('state', 'open');

    return finding.insert();
}
javascript
// Create audit finding (ES5 ONLY!)
function createAuditFinding(auditSysId, findingData) {
    var finding = new GlideRecord('sn_audit_finding');
    finding.initialize();

    finding.setValue('engagement', auditSysId);
    finding.setValue('title', findingData.title);
    finding.setValue('description', findingData.description);

    // Severity
    finding.setValue('severity', findingData.severity);  // critical, high, medium, low

    // Related control
    if (findingData.control) {
        finding.setValue('control', findingData.control);
    }

    // Recommendation
    finding.setValue('recommendation', findingData.recommendation);

    // Owner for remediation
    finding.setValue('owner', findingData.owner);

    // Due date for remediation
    finding.setValue('due_date', findingData.dueDate);

    finding.setValue('state', 'open');

    return finding.insert();
}

Compliance Reporting (ES5)

合规报告(仅支持 ES5)

Compliance Dashboard Data

合规仪表盘数据

javascript
// Get compliance summary (ES5 ONLY!)
function getComplianceSummary() {
    var summary = {
        policies: { total: 0, published: 0, review_needed: 0 },
        controls: { total: 0, effective: 0, failed: 0 },
        risks: { critical: 0, high: 0, medium: 0, low: 0 },
        audits: { open: 0, findings: 0 }
    };

    // Policies
    var ga = new GlideAggregate('sn_compliance_policy');
    ga.addAggregate('COUNT');
    ga.groupBy('state');
    ga.query();

    while (ga.next()) {
        var count = parseInt(ga.getAggregate('COUNT'), 10);
        summary.policies.total += count;
        if (ga.getValue('state') === 'published') {
            summary.policies.published = count;
        }
    }

    // Risks by rating
    ga = new GlideAggregate('sn_risk_risk');
    ga.addQuery('active', true);
    ga.addAggregate('COUNT');
    ga.groupBy('residual_risk_rating');
    ga.query();

    while (ga.next()) {
        var rating = ga.getValue('residual_risk_rating');
        var riskCount = parseInt(ga.getAggregate('COUNT'), 10);
        if (summary.risks.hasOwnProperty(rating)) {
            summary.risks[rating] = riskCount;
        }
    }

    return summary;
}
javascript
// Get compliance summary (ES5 ONLY!)
function getComplianceSummary() {
    var summary = {
        policies: { total: 0, published: 0, review_needed: 0 },
        controls: { total: 0, effective: 0, failed: 0 },
        risks: { critical: 0, high: 0, medium: 0, low: 0 },
        audits: { open: 0, findings: 0 }
    };

    // Policies
    var ga = new GlideAggregate('sn_compliance_policy');
    ga.addAggregate('COUNT');
    ga.groupBy('state');
    ga.query();

    while (ga.next()) {
        var count = parseInt(ga.getAggregate('COUNT'), 10);
        summary.policies.total += count;
        if (ga.getValue('state') === 'published') {
            summary.policies.published = count;
        }
    }

    // Risks by rating
    ga = new GlideAggregate('sn_risk_risk');
    ga.addQuery('active', true);
    ga.addAggregate('COUNT');
    ga.groupBy('residual_risk_rating');
    ga.query();

    while (ga.next()) {
        var rating = ga.getValue('residual_risk_rating');
        var riskCount = parseInt(ga.getAggregate('COUNT'), 10);
        if (summary.risks.hasOwnProperty(rating)) {
            summary.risks[rating] = riskCount;
        }
    }

    return summary;
}

MCP Tool Integration

MCP 工具集成

Available Tools

可用工具

ToolPurpose
snow_query_table
Query GRC tables
snow_execute_script_with_output
Test GRC scripts
snow_audit_compliance
Run compliance audits
snow_assess_risk
Risk assessment
工具用途
snow_query_table
查询 GRC 数据表
snow_execute_script_with_output
测试 GRC 脚本
snow_audit_compliance
执行合规审计
snow_assess_risk
风险评估

Example Workflow

工作流示例

javascript
// 1. Query active policies
await snow_query_table({
    table: 'sn_compliance_policy',
    query: 'state=published',
    fields: 'name,category,effective_date,review_date'
});

// 2. Find high risks
await snow_query_table({
    table: 'sn_risk_risk',
    query: 'residual_risk_rating=high^ORresidual_risk_rating=critical',
    fields: 'name,category,residual_risk_score,owner'
});

// 3. Get compliance summary
await snow_execute_script_with_output({
    script: `
        var summary = getComplianceSummary();
        gs.info(JSON.stringify(summary));
    `
});
javascript
// 1. Query active policies
await snow_query_table({
    table: 'sn_compliance_policy',
    query: 'state=published',
    fields: 'name,category,effective_date,review_date'
});

// 2. Find high risks
await snow_query_table({
    table: 'sn_risk_risk',
    query: 'residual_risk_rating=high^ORresidual_risk_rating=critical',
    fields: 'name,category,residual_risk_score,owner'
});

// 3. Get compliance summary
await snow_execute_script_with_output({
    script: `
        var summary = getComplianceSummary();
        gs.info(JSON.stringify(summary));
    `
});

Best Practices

最佳实践

  1. Clear Ownership - Assign policy/control/risk owners
  2. Regular Reviews - Schedule periodic assessments
  3. Evidence Collection - Document control effectiveness
  4. Risk Quantification - Use consistent scoring
  5. Audit Trail - Track all changes
  6. Automation - Automate testing where possible
  7. Reporting - Regular compliance dashboards
  8. ES5 Only - No modern JavaScript syntax
  1. 明确所有权 - 为政策/控制措施/风险分配负责人
  2. 定期审查 - 安排周期性评估
  3. 证据收集 - 记录控制措施的有效性
  4. 风险量化 - 使用统一的评分标准
  5. 审计追踪 - 跟踪所有变更记录
  6. 自动化 - 尽可能自动化测试流程
  7. 报告机制 - 定期生成合规仪表盘
  8. 仅支持 ES5 - 不使用现代 JavaScript 语法