opa
Open Policy Agent (OPA)を活用し、Kubernetesなどの環境におけるポリシーをコードで定義・適用することで、セキュリティポリシーの一貫性と自動化を促進し、開発者がより安全なシステムを構築するSkill。
📜 元の英語説明(参考)
Expert guidance for OPA (Open Policy Agent), the CNCF policy engine for unified authorization across the stack. Helps developers write Rego policies for Kubernetes admission control, API authorization, infrastructure-as-code validation, and data filtering — enforcing security policies as code.
🇯🇵 日本人クリエイター向け解説
Open Policy Agent (OPA)を活用し、Kubernetesなどの環境におけるポリシーをコードで定義・適用することで、セキュリティポリシーの一貫性と自動化を促進し、開発者がより安全なシステムを構築するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o opa.zip https://jpskill.com/download/15198.zip && unzip -o opa.zip && rm opa.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/15198.zip -OutFile "$d\opa.zip"; Expand-Archive "$d\opa.zip" -DestinationPath $d -Force; ri "$d\opa.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
opa.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
opaフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
OPA — Open Policy Agent
概要
OPA (Open Policy Agent) は、スタック全体で統一された認可を行うための CNCF ポリシーエンジンです。開発者が Kubernetes のアドミッションコントロール、API 認可、Infrastructure-as-Code の検証、データフィルタリングのための Rego ポリシーを作成するのを支援し、セキュリティポリシーをコードとして適用します。
手順
Rego Policy Language
# policy/authz.rego — API 認可ポリシー
package authz
import rego.v1
default allow := false
# 管理者ユーザーは何でもできる
allow if {
input.user.role == "admin"
}
# ユーザーは自分のデータを読み取ることができる
allow if {
input.method == "GET"
input.path[0] == "users"
input.path[1] == input.user.id
}
# ユーザーは自分のプロファイルを更新できる
allow if {
input.method in {"PUT", "PATCH"}
input.path[0] == "users"
input.path[1] == input.user.id
not input.body.role # 自分のロールは変更できない
}
# チームメンバーはチームリソースを読み取ることができる
allow if {
input.method == "GET"
input.path[0] == "teams"
team_id := input.path[1]
team_id in input.user.teams
}
# マネージャーは10,000ドル未満の経費を承認できる
allow if {
input.method == "POST"
input.path == ["expenses", "approve"]
input.user.role == "manager"
input.body.amount < 10000
}
# 監査証跡のための拒否理由
reasons contains msg if {
not allow
input.user.role != "admin"
msg := sprintf("User %s with role %s denied access to %s %s",
[input.user.id, input.user.role, input.method, concat("/", input.path)])
}
Kubernetes Admission Control (Gatekeeper)
# Gatekeeper ConstraintTemplate — 再利用可能なポリシーテンプレートを定義する
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
openAPIV3Schema:
type: object
properties:
labels:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
import rego.v1
violation contains {"msg": msg} if {
provided := {label | input.review.object.metadata.labels[label]}
required := {label | label := input.parameters.labels[_]}
missing := required - provided
count(missing) > 0
msg := sprintf("Missing required labels: %v", [missing])
}
---
# 制約を適用する — すべてのデプロイメントはこれらのラベルを持つ必要がある
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: require-team-labels
spec:
match:
kinds:
- apiGroups: ["apps"]
kinds: ["Deployment"]
parameters:
labels:
- "app.kubernetes.io/name"
- "app.kubernetes.io/managed-by"
- "team"
# root として実行されているコンテナをブロックする
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8snoroot
spec:
crd:
spec:
names:
kind: K8sNoRoot
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8snoroot
import rego.v1
violation contains {"msg": msg} if {
container := input.review.object.spec.containers[_]
not container.securityContext.runAsNonRoot
msg := sprintf("Container %s must set runAsNonRoot: true", [container.name])
}
violation contains {"msg": msg} if {
container := input.review.object.spec.containers[_]
container.securityContext.runAsUser == 0
msg := sprintf("Container %s must not run as root (UID 0)", [container.name])
}
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sNoRoot
metadata:
name: no-root-containers
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
- apiGroups: ["apps"]
kinds: ["Deployment", "StatefulSet"]
API Integration
// src/middleware/opa-authz.ts — OPA をバックエンドとした API 認可
import type { Request, Response, NextFunction } from "express";
const OPA_URL = process.env.OPA_URL ?? "http://opa:8181";
export async function authorize(req: Request, res: Response, next: NextFunction) {
const input = {
method: req.method,
path: req.path.split("/").filter(Boolean),
user: {
id: req.user?.id,
role: req.user?.role,
teams: req.user?.teams ?? [],
},
body: req.body,
};
const response = await fetch(`${OPA_URL}/v1/data/authz/allow`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ input }),
});
const { result } = await response.json();
if (result) {
next();
} else {
res.status(403).json({ error: "Forbidden" });
}
}
// 使用法: app.use(authorize);
Terraform Validation
# policy/terraform.rego — apply 前に Terraform プランを検証する
package terraform
import rego.v1
# パブリックな S3 バケットを拒否する
deny contains msg if {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
resource.change.after.acl == "public-read"
msg := sprintf("S3 bucket %s must not be public", [resource.address])
}
# RDS インスタンスで暗号化を必須にする
deny contains msg if {
resource := input.resource_changes[_]
resource.type == "aws_db_instance"
not resource.change.after.storage_encrypted
msg := sprintf("RDS instance %s must have encryption enabled", [resource.address])
}
# インスタンスサイズを制限する
deny contains msg if {
resource := input.resource_changes[_]
resource.type == "aws_instance"
not resource.change.after.instance_type in allowed_instance_types
msg := sprintf("Instance %s uses %s, allowed: %v",
[resource.address, resource.change.after.instance_type, allowed_instance_types])
}
allowed_instance_types := {"t3.micro", "t3.small", "t3.medium", "m5.large"}
# OPA で Terraform プランを検証する
terraform plan -out=plan.tfplan
terraform show -json plan.tfplan > plan.json
opa eval -d policy/ -i 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
OPA — Open Policy Agent
Overview
OPA (Open Policy Agent), the CNCF policy engine for unified authorization across the stack. Helps developers write Rego policies for Kubernetes admission control, API authorization, infrastructure-as-code validation, and data filtering — enforcing security policies as code.
Instructions
Rego Policy Language
# policy/authz.rego — API authorization policy
package authz
import rego.v1
default allow := false
# Admin users can do anything
allow if {
input.user.role == "admin"
}
# Users can read their own data
allow if {
input.method == "GET"
input.path[0] == "users"
input.path[1] == input.user.id
}
# Users can update their own profile
allow if {
input.method in {"PUT", "PATCH"}
input.path[0] == "users"
input.path[1] == input.user.id
not input.body.role # Can't change own role
}
# Team members can read team resources
allow if {
input.method == "GET"
input.path[0] == "teams"
team_id := input.path[1]
team_id in input.user.teams
}
# Managers can approve expenses under $10,000
allow if {
input.method == "POST"
input.path == ["expenses", "approve"]
input.user.role == "manager"
input.body.amount < 10000
}
# Deny reasons for audit trail
reasons contains msg if {
not allow
input.user.role != "admin"
msg := sprintf("User %s with role %s denied access to %s %s",
[input.user.id, input.user.role, input.method, concat("/", input.path)])
}
Kubernetes Admission Control (Gatekeeper)
# Gatekeeper ConstraintTemplate — define reusable policy templates
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
openAPIV3Schema:
type: object
properties:
labels:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
import rego.v1
violation contains {"msg": msg} if {
provided := {label | input.review.object.metadata.labels[label]}
required := {label | label := input.parameters.labels[_]}
missing := required - provided
count(missing) > 0
msg := sprintf("Missing required labels: %v", [missing])
}
---
# Apply the constraint — all deployments must have these labels
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: require-team-labels
spec:
match:
kinds:
- apiGroups: ["apps"]
kinds: ["Deployment"]
parameters:
labels:
- "app.kubernetes.io/name"
- "app.kubernetes.io/managed-by"
- "team"
# Block containers running as root
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8snoroot
spec:
crd:
spec:
names:
kind: K8sNoRoot
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8snoroot
import rego.v1
violation contains {"msg": msg} if {
container := input.review.object.spec.containers[_]
not container.securityContext.runAsNonRoot
msg := sprintf("Container %s must set runAsNonRoot: true", [container.name])
}
violation contains {"msg": msg} if {
container := input.review.object.spec.containers[_]
container.securityContext.runAsUser == 0
msg := sprintf("Container %s must not run as root (UID 0)", [container.name])
}
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sNoRoot
metadata:
name: no-root-containers
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
- apiGroups: ["apps"]
kinds: ["Deployment", "StatefulSet"]
API Integration
// src/middleware/opa-authz.ts — OPA-backed API authorization
import type { Request, Response, NextFunction } from "express";
const OPA_URL = process.env.OPA_URL ?? "http://opa:8181";
export async function authorize(req: Request, res: Response, next: NextFunction) {
const input = {
method: req.method,
path: req.path.split("/").filter(Boolean),
user: {
id: req.user?.id,
role: req.user?.role,
teams: req.user?.teams ?? [],
},
body: req.body,
};
const response = await fetch(`${OPA_URL}/v1/data/authz/allow`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ input }),
});
const { result } = await response.json();
if (result) {
next();
} else {
res.status(403).json({ error: "Forbidden" });
}
}
// Usage: app.use(authorize);
Terraform Validation
# policy/terraform.rego — Validate Terraform plans before apply
package terraform
import rego.v1
# Deny public S3 buckets
deny contains msg if {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
resource.change.after.acl == "public-read"
msg := sprintf("S3 bucket %s must not be public", [resource.address])
}
# Require encryption on RDS instances
deny contains msg if {
resource := input.resource_changes[_]
resource.type == "aws_db_instance"
not resource.change.after.storage_encrypted
msg := sprintf("RDS instance %s must have encryption enabled", [resource.address])
}
# Limit instance sizes
deny contains msg if {
resource := input.resource_changes[_]
resource.type == "aws_instance"
not resource.change.after.instance_type in allowed_instance_types
msg := sprintf("Instance %s uses %s, allowed: %v",
[resource.address, resource.change.after.instance_type, allowed_instance_types])
}
allowed_instance_types := {"t3.micro", "t3.small", "t3.medium", "m5.large"}
# Validate Terraform plan with OPA
terraform plan -out=plan.tfplan
terraform show -json plan.tfplan > plan.json
opa eval -d policy/ -i plan.json "data.terraform.deny"
Installation
# CLI
brew install opa
# Docker
docker run -p 8181:8181 openpolicyagent/opa run --server
# Kubernetes (Gatekeeper)
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/v3.15.0/deploy/gatekeeper.yaml
Examples
Example 1: Setting up Opa for a microservices project
User request:
I have a Node.js API and a React frontend running in Docker. Set up Opa for monitoring/deployment.
The agent creates the necessary configuration files based on patterns like # Gatekeeper ConstraintTemplate — define reusable policy tem, sets up the integration with the existing Docker setup, configures appropriate defaults for a Node.js + React stack, and provides verification commands to confirm everything is working.
Example 2: Troubleshooting kubernetes admission control issues
User request:
Opa is showing errors in our kubernetes admission control. Here are the logs: [error output]
The agent analyzes the error output, identifies the root cause by cross-referencing with common Opa issues, applies the fix (updating configuration, adjusting resource limits, or correcting syntax), and verifies the resolution with appropriate health checks.
Guidelines
- Policy as code — Store policies in Git alongside application code; review policy changes in PRs
- Rego testing — Write unit tests for policies:
opa test policy/ -v; catch policy bugs before deployment - Gatekeeper for K8s — Use OPA Gatekeeper for admission control; enforce policies at deploy time, not just at runtime
- Centralize authorization — Move authorization logic from application code to OPA; one policy engine across all services
- Deny by default — Start with
default allow := false; explicitly grant access rather than revoking - Bundle for distribution — Package policies as OPA bundles; deploy to OPA instances via bundle server
- Terraform validation — Validate
terraform planoutput with OPA beforeterraform apply; prevent misconfigurations - Audit logging — Log OPA decisions for compliance; track who accessed what and which policy allowed/denied it