grc-compliance
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGRC & 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 ResponsePolicy (sn_compliance_policy)
└── Policy Statements
└── Controls (sn_compliance_control)
└── Control Tests
└── Test Results
Risk (sn_risk_risk)
├── Risk Assessment
└── Risk ResponseKey Tables
关键数据表
| Table | Purpose |
|---|---|
| Compliance policies |
| Controls |
| Control tests |
| Risk records |
| Audit engagements |
| 数据表 | 用途 |
|---|---|
| 合规政策 |
| 控制措施 |
| 控制测试 |
| 风险记录 |
| 审计项目 |
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
可用工具
| Tool | Purpose |
|---|---|
| Query GRC tables |
| Test GRC scripts |
| Run compliance audits |
| Risk assessment |
| 工具 | 用途 |
|---|---|
| 查询 GRC 数据表 |
| 测试 GRC 脚本 |
| 执行合规审计 |
| 风险评估 |
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
最佳实践
- Clear Ownership - Assign policy/control/risk owners
- Regular Reviews - Schedule periodic assessments
- Evidence Collection - Document control effectiveness
- Risk Quantification - Use consistent scoring
- Audit Trail - Track all changes
- Automation - Automate testing where possible
- Reporting - Regular compliance dashboards
- ES5 Only - No modern JavaScript syntax
- 明确所有权 - 为政策/控制措施/风险分配负责人
- 定期审查 - 安排周期性评估
- 证据收集 - 记录控制措施的有效性
- 风险量化 - 使用统一的评分标准
- 审计追踪 - 跟踪所有变更记录
- 自动化 - 尽可能自动化测试流程
- 报告机制 - 定期生成合规仪表盘
- 仅支持 ES5 - 不使用现代 JavaScript 语法