mcpField
G
grc-compliance

grc-compliance

github.com/serac-labsセキュリティ7773 回インストール9 週間前に更新
リポジトリ

grc-compliance について

ServiceNow のガバナンス、リスク、コンプライアンスを扱うスキルで、ポリシー、コントロール、リスク、監査の管理例を紹介します。リスク評価やコンプライアンス集計に加え、MCP ツールによる照会とスキャンも扱います。

主な機能

  1. 01コンプライアンスポリシーの作成と更新
  2. 02コントロールとテストの管理
  3. 03リスクの作成とスコア評価
  4. 04監査案件と指摘事項の管理
  5. 05コンプライアンス状況の集計
  6. 06スクリプト例によるレコード操作

活用シーン

  1. 01ポリシーとコントロールの記録作成
  2. 02リスクの評価とレベル分け
  3. 03監査案件と指摘事項の記録
  4. 04コンプライアンス概要データの作成

MCP 対応

ServiceNow MCP ツールで GRC テーブルを照会し、スクリプトをテストし、コンプライアンススキャンとリスク評価を実行する方法を説明します。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/serac-labs/serac --skill grc-compliance

インストール後、Claude Code で/grc-complianceを入力して読み込まれたか確認します。

詳細

ServiceNow 向け GRC とコンプライアンス

GRC(ガバナンス、リスク、コンプライアンス)は、組織のポリシー、リスク、規制コンプライアンスを管理します。

GRC アーキテクチャ

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

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

主なテーブル

テーブル用途
sn_compliance_policyコンプライアンスポリシー
sn_compliance_control統制
sn_compliance_control_test統制テスト
sn_risk_riskリスクレコード
sn_audit_engagement監査エンゲージメント

ポリシー(ES5)

ポリシーの作成
// 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()
ポリシーのライフサイクル
// 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 }
}

統制(ES5)

統制の作成
// 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()
統制テスト
// 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
}

リスク管理(ES5)

リスクの作成
// 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()
リスク評価
// 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
}

監査(ES5)

監査エンゲージメントの作成
// 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()
監査結果
// 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()
}

コンプライアンスレポート(ES5)

コンプライアンスダッシュボードのデータ
// 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 ツール統合

利用可能なツール
ツール用途
snow_query_tableGRC テーブルのクエリ
snow_execute_scriptGRC スクリプトのテスト
snow_run_compliance_scanコンプライアンス監査の実行
snow_grc_risk_manage (action='assess')リスク評価
ワークフローの例
// 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({
  script: `
        var summary = getComplianceSummary();
        gs.info(JSON.stringify(summary));
    `,
})

ベストプラクティス

  1. 明確なオーナーシップ - ポリシー/統制/リスクのオーナーを割り当てます
  2. 定期的なレビュー - 定期的な評価をスケジュールします
  3. 証拠の収集 - 統制の有効性を記録します
  4. リスクの定量化 - 一貫したスコアリングを使用します
  5. 監査証跡 - すべての変更を追跡します
  6. 自動化 - 可能な場合はテストを自動化します
  7. レポート作成 - コンプライアンスダッシュボードを定期的に作成します
  8. ES5 のみ - 最新の JavaScript 構文は使用しません

コメント