Open Policy Agentãå§ãã¦ã¿ãã
Open Policy Agentï¼ä»¥ä¸OPAï¼ãæè¿ã¡ãã£ã¨ãã¤è³ã«ãããã¨ãå¤ããªã£ã¦ããæ°ããã¾ããKubeCon + CloudNativeCon 2017 - Austinã§ãHow Netflix Is Solving Authorization Across Their Cloudããè¦ãã¨ãã«ããããªæãã«èªå¯ãå¤ã«åºããããªã¼ãã¨æã£ãè¨æ¶ãããã¾ãã ãã®è¨äºã§ã¯OPAã®ç°¡åãªç´¹ä»ã¨ãå ¬å¼Tutorialã®Getting Startedãå®è·µããè¨é²ãå ±æãã¾ãï¼
OPAã¨ã¯
OPAã¯æ±ç¨çãªPolicy Engineã¨è¨ããã¦ãã¾ããPolicy Engineã¨ã¯ãå®ç¾©ãããã«ã¼ã«ã«å¾ã£ã¦ 夿ãä¸ããã¨ãã§ããå°éå®¶ ã§ããPolicyã®ä¸ã§ãããã£ã¦ãããã©ããï¼è¦ã¦ãããã©ããï¼ãã«é¢ãããã®ããAccess Policyãã¨å¼ã°ãã馴æã¿ããããã¨æãã¾ãã
ä¾ãã°Webãµã¼ãã¹ã§ã¦ã¼ã¶ã¼Aã®æ å ±ããã°ã¤ã³ä¸ã®ã¦ã¼ã¶ã¼ãè¦ã¦ãããã©ãããã¨ããã®ãDBã«è¦ã«è¡ãã¨ãã«æ¬¡ã®ãããªã³ã¼ã(ããã§ã¯JavaScript)ã«è¦è¦ããããã¯ãã§ãã
// ãã°ã¤ã³ä¸ã®ã¦ã¼ã¶ã¼ãAããã®ããã¼ã¸ã£ã¼ã ã£ããåç §ãã¦OK const canView = login.id === userA.manager_id; if (canView) { // DBããAããã®æ å ±ãåå¾ãã }
ããã¯ããã§ããã«èªããã³ã¼ãã§ãããOPAã使ã£ãå ´åãªã次ã®ããã«æ¸ããã¨ãã§ãã¾ãã
// Aããã®æ å ±ãåç §ãã¦ãããã©ãããã§ãã¯ãã const canView = opa.checkCanView(userA); if (canView) { // DBããåå¾ããå¦çãè¨è¿°ãã }
è¦ã¦ãããã©ããã® å¤æ ãOPAã«ãã¾ããï¼å§è²ï¼ã«ãªã£ããã¨ããã®ã大ããªéãã§ãããããããã¨ã§ã¡ã¤ã³ã®ã¢ããªã±ã¼ã·ã§ã³ã§ã¯ããã£ã¦ãããã©ãããã夿ããå¿ è¦ãç¡ããªããOPAã« èãã°OK ã¨ãªãã¾ãã
- ãæ³¨æãã®ï¼ãOPAã¯å¥ã®ãµã¼ãã¹ã¨ãã¦ç«ã¡ä¸ãã£ã¦ããã®ã§ã
opa.checkCanView
ã®ä¸ã§ã¯ãOPAã¸ã®HTTPãªã¯ã¨ã¹ããå®è¡ããã¦ããã¨æã£ã¦ãã ããã- ãæ³¨æãã®ï¼ãä¸ã®ä¾ã¯OPAã使ã£ã¦REST APIãªã¯ã¨ã¹ãã®èªå¯ãè¡ãä¾ã§ããOPAãå©ç¨ã§ããå ´é¢ã¯ããã ãã§ã¯ãªããDocker, SSH, sudo, Kafka, Kubernetes Admission Controlãªã©å¹ åºãã§ãã詳ããã¯ å ¬å¼ã®Tutorial ãåç §ãã ããã
ã¾ãã login.id == userA.manager_id
ã¨ããã³ã¼ãã¯ã¨ã¦ãç¹ç´°ã§ã id
ã ã£ãã manager_id
ãåºå®ï¼ãã¼ãã³ã¼ãï¼ããã¦ãã¾ã£ã¦ãã¾ãããã®æ¡ä»¶ãå¤ããã¨ãã¡ã¤ã³ã®ã¢ããªã±ã¼ã·ã§ã³ã®ã½ã¼ã¹ã³ã¼ãã«å½±é¿ãåºã¦ãã¾ãã¾ããã¡ãã£ã¨èããã ãã§ãä¸ã®çç±ã§å£ãã¦ãã¾ãããã§ãã
manager_id
ãmanager.id
ã®ããã«æ§é ãå¤ãã£ã- ãã¦ã¼ã¶ã¼Aã®ããã¼ã¸ã£ã¼ãã¨ãã観ç¹ã§ã¯ãªããããã°ã¤ã³ä¸ã®ã¦ã¼ã¶ã¼ã®é¨ä¸ãã¨ãã観ç¹ã«å¤ãã£ã
- ä¾ï¼
login.subordinates.include(userA.id)
- ä¾ï¼
- ãç¹å®ã®ææã«å
¥ç¤¾ãã¦ãããã¨ããæ¡ä»¶ã«å ãã£ã
login.id == userA.manager_id && userA.joined_at.year >= 2019
OPAã«ãã¾ãããã¦ããã°ãã¦ã¼ã¶ã¼Aã¨ããã³ã³ããã¹ããå¤ãããªãéãã¯ãã¡ã¤ã³ã®ã¢ããªã±ã¼ã·ã§ã³ã¸ã®å½±é¿ã¯ããã¾ããã夿´ã¯OPAå´ã§å¸åã§ãã¾ãã
ããã£ã¦ãããã©ããã¯å°éå®¶ã«ãã¾ãããã§ãã¡ã¤ã³ã®ã¢ããªã±ã¼ã·ã§ã³ã¯æ¬æ¥å±ãããã¨æã£ã¦ãã価å¤ã®é¨åã«éä¸ã§ãã¾ãã
ããã§ã¯ãOPAã®ä»çµã¿ãã©ããªã£ã¦ããã®ãã¨ããã®ãè¦ã¦ã¿ã¾ãããï¼
OPAã®Policyè¨èªRego
ããã°ã¤ã³ä¸ã®ã¦ã¼ã¶ã¼ããããã¦ã¼ã¶ã¼ã®ããã¼ã¸ã£ã¼ã ã£ããââã許å¯ãããã¨ããã®ã¯Policyã®ä¸ä¾ã§ããOPAã¯å®ç¾©ãããPolicyã«å¾ã£ã¦ããªã¯ã¨ã¹ãã«å¿ãã夿ãè¿ãã¦ããã¾ããããã¦ãPolicyãæ¸ãéã«Regoã¨å¼ã°ããOPAç¨ã®è¨èªã使ãã¨ããã®ã大ããªç¹å¾´ã§ãã
Regoã¯ãããã°ã©ãã³ã°ãçµé¨ãããã¨ããã人ãªããªãã¨ãªã¼ãèªããã®ã§ã¯ãªãã§ããããï¼é·ããªã£ã¦ãã¾ãã®ã§è©³ãã説æã«ã¤ãã¦ã¯ãã®è¨äºã§ã¯å²æãã¾ãããå ¬å¼ããã¥ã¡ã³ããä¸åº¦ã¯èªãã§è¦ããã¨ããããããã¾ãã
ä»ã®ã¨ããRegoãæ¸ãéã«æå¤§éæ°ãã¤ããªãã¨ãããªãã¨æã£ã¦ãããã¨ã¯ =
ã®æåã§ãã
x := 7 declares that x is a variable local to the rule. Furthermore, the compiler will stop you from writing two such assignments in the same rule, e.g. x := 7; x := 8 creates a compile-time error.
Neither of those are true with x = 7. The rule x = 7 will assign x to 7 if x is unbound, and it will compare x to 7 if x is already bound. Also, if there is a global variable named x, x = 7 will compare that global value of x to 7.
In short, use := if you want assignment inside a rule.
ä½ãè¨ã£ã¦ããã®ãã¨è¨ãã¨ãè¦ã¯å¤æ°ã«å¤ãå
¥ã£ã¦ãããã©ããã§ =
ã¯æåãå¤ããã¨ãããã¨ã§ãã夿°ã«ä½ãå
¥ã£ã¦ããªãã㰠代å
¥
ã«ãªããå
¥ã£ã¦ããã° æ¯è¼
ã«ãªãã¾ãã
OPAã¯Regoç¨ã®REPLãç¨æãã¦ããã®ã§å®éã«ãã£ã¦ã¿ã¾ãããã
$ docker run -it --rm openpolicyagent/opa run > x = 7 Rule 'x' defined in package repl. Type 'show' to see rules. > x = 7 true > x = 8 undefined
1åç®ã¯ x
ã«ä½ãå¤ãå
¥ã£ã¦ããªãã®ã§ 代å
¥
ã«ãªãã¾ãã2åç®ã¯ x
ã«æ¢ã«å¤ãå
¥ã£ã¦ããã®ã§ æ¯è¼
ã«ãªã£ã¦ãçµæã true
ã«ãªã£ã¦ããã®ããããã¾ãã3åç®ã¯ç´æçã«ã¯ false
ã«ãªã£ã¦ã»ããã¨ããã§ããã undefined
ã«ãªãã¾ããããã=
ã®ç¹å¾´ã®æ§ã§ããã true
ã«ãªããã©ãããå¤å®ãã«ããããã true
ã¨å¤å®ã§ããªããã®ã«é¢ãã¦ã¯ undefined
ã«ãªãã¨ããã®ã仿§ã¿ããã§ãã詳ããã¯å
¬å¼ããã¥ã¡ã³ãã® The Basics ã«è¨è¼ãã¦ã¾ãã
ãã®æåã¯ ç´æçãããªã ã®ã§ãå¥é代å
¥ã«ã¯ :=
ã¨ããæ§æãå¢ãã¦ãæ¯è¼ã«ã¯è¦æ
£ãã ==
ã使ããããã«ãªãã¾ããã
$ docker run -it --rm openpolicyagent/opa run > x := 7 Rule 'x' defined in package repl. Type 'show' to see rules. > x == 7 true > x == 8 false
ãã¡ãã®ã»ããã ãã¶ããããããã§ããï¼
Get Startedãã¥ã¼ããªã¢ã«
ãã¦ãRegoã®æ§æã®è©±ããã¦ãPolicyãè¦ãã¥ããã¨æãã®ã§ãå®éã«Policyãæ¸ããªããé°å²æ°ãã¤ããã§ããã¾ããããå ¬å¼ã®ãã¥ã¼ããªã¢ã«ãGet Startedãããã£ã¦ã¿ã¾ãã
ã¾ãã¯ä¸å³ã®ããã«Server, Network, Portæ å ±ããã£ãã¨ãã¾ãã
èªåãä¿æãã¦ãããµã¼ãã¼ãä¸ã®éãã ã¨ãã¦ã
ãããªãã¯ãããã¯ã¼ã¯ã§ã¯æå·åãããéä¿¡ãã許å¯ããªãï¼HTTPã¯NGï¼
ã¨ããPolicyãæã¡ããã¨ãã¾ãããããRegoã§æ¸ãã¦ã¿ã¾ãããã
ã¾ãã¯ä½æ¥ç¨ã®ãã£ã¬ã¯ããªãä½ã£ã¦ãã®ä¸ã«å ¥ãã¾ãã
mkdir opa cd opa
ä¸å³ã®æ
å ±ãJSONã«ãããã®ã data.json
ã¨ãã¦ç¨æãã¾ãã
$ cat >data.json <<EOF { "servers": [ {"id": "s1", "name": "app", "protocols": ["https", "ssh"], "ports": ["p1", "p2", "p3"]}, {"id": "s2", "name": "db", "protocols": ["mysql"], "ports": ["p3"]}, {"id": "s3", "name": "cache", "protocols": ["memcache"], "ports": ["p3"]}, {"id": "s4", "name": "dev", "protocols": ["http"], "ports": ["p1", "p2"]} ], "networks": [ {"id": "n1", "public": false}, {"id": "n2", "public": false}, {"id": "n3", "public": true} ], "ports": [ {"id": "p1", "networks": ["n1"]}, {"id": "p2", "networks": ["n3"]}, {"id": "p3", "networks": ["n2"]} ] } EOF
ä¸ã®ãã¼ã¿ã«å¯¾ãã¦Regoãã¡ã¤ã«ã以ä¸ã®ããã«ãã¦ä½ãã¾ãã
cat >example.rego <<EOF package opa.example import data.servers import data.networks import data.ports public_servers[s] { s := servers[_] s.ports[_] == ports[i].id ports[i].networks[_] == networks[j].id networks[j].public == true } violations[s] { s = servers[_] s.protocols[_] = "http" public_servers[s] } EOF
example.rego
ã¨ããRegoãããã§æ¸ãããã¨ã«ãªãã¾ããæå³ã¨ãã¦ã¯ãã£ãã以ä¸ã®ã¨ããã
opa.example
ã¨ããããã±ã¼ã¸ã宣è¨data
ã¨ãã¦äºãèªã¿è¾¼ãã§ããdata.servers
,data.networks
,data.ports
ãimport
ãã¦ã«ã¼ã«ï¼public_servers
,violations
ï¼ã§ä½¿ããããã«ããpublic_servers[s]
ã«ã¼ã«ã宣è¨servers
ã®ä¸ã§ports
ã§å®£è¨ãã¦ããport
ãnetworks
ã§å®£è¨ãã¦ããnetwork
ã使ã£ã¦ãã¦ãnetwork
ãpublic
ã®ãã®ãpublic_servers
ã¨ãã
violations[s]
ã宣è¨servers
ã®ä¸ã§ãprotocol
ãhttp
ãã¤public_servers
ã«å«ã¾ããserver
ã§ããã°violations
ã¨ãã
ãããå®é opa
ã«èªã¿è¾¼ã¾ãã¦REPLã§ä½¿ã£ã¦ã¿ã¾ãããã
docker run -it --rm -v $(pwd):/tmp/workspace -w /tmp/workspace openpolicyagent/opa run data.json example.rego
ã¾ãããã¼ã¿ããããã¨ã確èªãã¦ã¿ã¾ãã
> data.servers[_] +-------------------------------------------------------------------------------+ | data.servers[_] | +-------------------------------------------------------------------------------+ | {"id":"s1","name":"app","ports":["p1","p2","p3"],"protocols":["https","ssh"]} | | {"id":"s2","name":"db","ports":["p3"],"protocols":["mysql"]} | | {"id":"s3","name":"cache","ports":["p3"],"protocols":["memcache"]} | | {"id":"s4","name":"dev","ports":["p1","p2"],"protocols":["http"]} | +-------------------------------------------------------------------------------+
å
ç¨ç¨æããJSONã®æ
å ±ãèªã¿è¾¼ã¾ãã¦ããã®ããããã¾ãããã§ã¯ public_servers
ã¯ã©ãã§ãããï¼
> data.opa.example.public_servers[_] +-------------------------------------------------------------------------------+ | data.opa.example.public_servers[_] | +-------------------------------------------------------------------------------+ | {"id":"s1","name":"app","ports":["p1","p2","p3"],"protocols":["https","ssh"]} | | {"id":"s4","name":"dev","ports":["p1","p2"],"protocols":["http"]} | +-------------------------------------------------------------------------------+
public == true
ãªãããã¯ã¼ã¯ï¼n3ï¼ã®ä¸ã®ãã¼ãï¼p2ï¼ã使ç¨ãã¦ãã app
㨠dev
ãµã¼ãã¼ãè¿ã£ã¦ãã¦ããã®ããããã¾ããã¡ãªã¿ã« [_]
ã®é¨å㯠_
ã«å¤ãç¡ãã®ã§ å
¨é¨
ã¨ããæå³ã«ãªãã¾ããï¼ãªã®ã§è©²å½ãããµã¼ãã¼ãå
¨é¨åºã¦ã¾ãï¼
ã§ã¯ã violations
ãåæ§ã«è¦ã¦ã¿ã¾ãããã
> data.opa.example.violations[x] +-------------------------------------------------------------------+ | data.opa.example.violations[x] | +-------------------------------------------------------------------+ | {"id":"s4","name":"dev","ports":["p1","p2"],"protocols":["http"]} | +-------------------------------------------------------------------+
ï¼çµæã¯ããªã ãã¦ã¾ãããï¼å
ç¨ã® public_servers
ã®çµæã®ä¸ã§ããããã³ã«ã http
ã使ç¨ãã¦ãã dev
ãµã¼ãã¼ã violation
ã¨ãã¦è¿ã£ã¦ãã¦ããã®ããããã¾ãã
ãã®ããã«ã宣è¨çã«Policyãæ¸ãã¦ãããã¨ãã§ããã®ãOPAã®å¼·ã¿ã§ãï¼
ä½è«ï¼
data.opa.example.violations[_]
ã¨æ¸ããå ´åã«ãªããREPLã§ã¯JSONãè¿ã£ã¦ãã¾ãããx
ã«ããã¨è¡¨ã ã£ãã®ã§ããããã®éãããªãèµ·ããã®ãã¯ã¾ã åå ãã¤ããã¦ãã¾ãããæéãã¿ã¤ãã¦Ownerã«èãã¦ã¿ã¾ãã
ãããã«
ä»åã¯OPAã®æ¦è¦ã¨Policyè¨èªRegoãããã¦REPLã«ã¤ãã¦ç´¹ä»ãã¾ãããã¾ã å ·ä½çã«ã©ã使ãã®ãã¨ããã®ãè¦ãã¥ããé¨åãããã¨æãã¾ãããã®è¨äºã¯ãã£ããããã¾ã§ã¨ãã¾ãï¼
- ãã£ã¦ãããã©ããã夿ãã¦ããã
- ç¹å®ã®æ¡ä»¶ãæºããã¦ãããã©ãããæãã¦ããã
- PolicyãRegoã¨ããç¬èªã®è¨èªã§æ¸ããã¨ãã§ãã
ç¹ã«ã¤ãã¦ã¯ãªãã¨ãªãã¤ã¡ã¼ã¸ã§ããã®ã§ã¯ãªãã§ããããï¼æ¬¡åã¯REPLã§ã¯ãªããå®éã«ããã£ã¦ãããã©ãããã夿ãã¦ãããä½¿ãæ¹ã«ã¤ãã¦ç´¹ä»ãã¾ãï¼
åè
How Netflix Is Solving Authorization Across Their Cloud youtu.be
Intro: Open Policy Agent www.youtube.com