Skip to content

Commit 126692e

Browse files
committed
adding opa configuration
1 parent 30b7d9c commit 126692e

2 files changed

Lines changed: 347 additions & 0 deletions

File tree

docs/configure/opa.md

Lines changed: 347 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,347 @@
1+
# Open policy agent support for Kubernetes with Citrix ADC
2+
3+
Open policy agent (OPA) is an open source, general-purpose policy engine that unifies policy enforcement across different technologies and systems. OPA provides a high-level declarative language that lets you specify policy as code and simple APIs to offload policy decision-making from your software. Using OPA, you can decouple policy decision-making from policy enforcement. You can use OPA to enforce policies through Citrix ADC in a Kubernetes environment.
4+
5+
With OPA, you can create a centralized policy-decision making system for an environment involving multiple Citrix ADCs or multiple devices which are distributed. The advantage of this approach is you have to make changes only on the OPA server for any decision specific changes applicable to multiple devices.
6+
7+
For more information on OPA, see the [OPA documentation](https://www.openpolicyagent.org/docs/latest/).
8+
9+
The OPA integration on Citrix ADC can be supported through HTTP callout, where OPA can be used with or without authentication. An HTTP callout is an HTTP or HTTPS request that the Citrix ADC appliance generates and sends to an external application as part of the policy evaluation.
10+
11+
For more information on the HTTP callout support, see the [HTTP callout documentation](https://docs.citrix.com/en-us/citrix-k8s-ingress-controller/how-to/http-callout.html).
12+
13+
For more information regarding authentication support, see the [Authentication and authorization policies for Kubernetes with Citrix ADC](https://docs.citrix.com/en-us/citrix-k8s-ingress-controller/crds/auth.html).
14+
15+
The following diagram provides an overview of how to integrate OPA with the Citrix ADC cloud native solution.
16+
17+
![OPA integration](../media/opa.png)
18+
19+
In the OPA integration diagram, each number represents the corresponding task in the following list:
20+
21+
1. Creating the required Kubernetes objects using Kubernetes commands. This step should include creating the CRD to send the HTTP callout to the OPA server.
22+
23+
2. Configuring Citrix ADC. Citrix ADC is automatically configured by Citrix ADC ingress controller based on the created Kubernetes objects.
24+
25+
3. Sending user request for resources from client. The user might get authenticated if authentication CRDs are created.
26+
27+
4. Sending HTTP callout to OPA server in JSON format from Citrix ADC carrying authorization parameters.
28+
29+
5. Sending authorization decision from OPA server based on the rules defined in REGO, the policy language for OPA.
30+
31+
6. Sending response to the client based on the authorization decision.
32+
33+
## Example use cases
34+
35+
### Allow or deny access to resources based on the client source IP address
36+
37+
Following is an example HTTP callout policy to the OPA server using rewrite policy CRD to allow or deny access to resources based on the client source IP address and the corresponding OPA rules.
38+
39+
In the example, the OPA server responds with `"result": true` if the client source IP address is 192.2.162.0/24, else it responds with `"result":false`.
40+
41+
```yml
42+
43+
apiVersion: citrix.com/v1
44+
kind: rewritepolicy
45+
metadata:
46+
name: calloutexample
47+
spec:
48+
responder-policies:
49+
- servicenames:
50+
- frontend
51+
responder-policy:
52+
respondwith:
53+
http-payload-string: '"HTTP/1.1 401 Access denied\r\n\r\n"' #Access is denied if the respose from OPA server contains false.
54+
respond-criteria: 'sys.http_callout("callout_name").CONTAINS("false")'
55+
comment: 'Invalid access'
56+
httpcallout_policy:
57+
- name: callout_name
58+
server_ip: "192.2.156.160" #OPA Server IP
59+
server_port: 8181 #OPA Server Port
60+
http_method: 'POST'
61+
host_expr: "\"192.2.156.160\""
62+
url_stem_expr: "\"/v1/data/example/allow\"" #URL stem expression to be used
63+
body_expr: '"{\"input\": {\"clientinfo\": [{\"id\": \"ci\", \"ip\": [\""+ CLIENT.IP.SRC +"\"]}]}}"' #JSON to OPA server carrying client IP
64+
headers:
65+
- name: Content-Type
66+
expr: '"application/json"'
67+
return_type: TEXT
68+
result_expr: "HTTP.RES.BODY(100)"
69+
70+
```
71+
72+
Following are the rules defined through the Rego policy language on the OPA server for the HTTP callout policy for this example:
73+
74+
package example
75+
76+
default allow = false # unless otherwise defined, allow is false
77+
78+
allow = true { # allow is true if...
79+
count(violation) != 0 # the ip matches regex.
80+
}
81+
82+
violation[client.id] { # a client is in the violation set if...
83+
client := input.clientinfo[_]
84+
regex.match("192.2.162.", client.ip[_]) # the client is not part of 192.2.162.0/24 network.
85+
}
86+
87+
### Allow or deny access based on user group after authentication
88+
89+
Following is an example HTTP callout policy to the OPA server using rewrite policy CRD to allow or deny access to resources based on user group after authentication and the corresponding OPA rules.
90+
91+
In this example, the OPA server responds with `"result":true` if the user is part of the `beverages` group, else it responds with `"result":false`.
92+
93+
Following is the HTTP callout policy to the OPA server through the rewrite policy CRD.
94+
95+
```yml
96+
apiVersion: citrix.com/v1
97+
kind: rewritepolicy
98+
metadata:
99+
name: calloutexample
100+
spec:
101+
responder-policies:
102+
- servicenames:
103+
- frontend
104+
responder-policy:
105+
respondwith:
106+
http-payload-string: '"HTTP/1.1 401 Access denied\r\n\r\n"' #Access is denied if the respose from OPA server contains false.
107+
respond-criteria: 'sys.http_callout("callout_name").CONTAINS("false")'
108+
comment: 'Invalid access'
109+
110+
httpcallout_policy:
111+
- name: callout_name
112+
server_ip: "192.2.156.160" #OPA Server IP
113+
server_port: 8181 #OPA Server Port
114+
http_method: 'POST'
115+
host_expr: "\"192.2.156.160\""
116+
url_stem_expr: "\"/v1/data/example/allow\"" #URL stem expression to be used
117+
body_expr: '"{\"input\": {\"users\": [{\"name\": \""+ AAA.USER.NAME +"\", \"group\": [\""+ AAA.USER.GROUPS +"\"]}]}}"' #JSON to OPA server carrying username and group information
118+
headers:
119+
- name: Content-Type
120+
expr: '"application/json"'
121+
return_type: TEXT
122+
result_expr: "HTTP.RES.BODY(100)"
123+
```
124+
125+
Following are the rules defined through the Rego language on the OPA server for this example:
126+
127+
package example
128+
129+
default allow = false # unless otherwise defined, allow is false
130+
131+
allow = true { # allow is true if...
132+
count(isbeveragesuser) != 0 # the user is part of beverages group.
133+
}
134+
135+
isbeveragesuser[user.name] { # a user is beverages user...
136+
user := input.users[_]
137+
user.group[_] == "beverages" # if it is part of beverages group.
138+
}
139+
140+
You can perform authentication using the request header (401 based) or through forms based.
141+
142+
Following is a sample authentication policy using request header-based authentication. In this policy,
143+
local authentication is used.
144+
145+
```yml
146+
apiVersion: citrix.com/v1beta1
147+
kind: authpolicy
148+
metadata:
149+
name: localauth
150+
spec:
151+
servicenames:
152+
- frontend
153+
154+
authentication_mechanism:
155+
using_request_header: 'ON'
156+
157+
authentication_providers:
158+
159+
- name: "local-auth-provider"
160+
basic_local_db:
161+
use_local_auth: 'YES'
162+
163+
authentication_policies:
164+
165+
- resource:
166+
path: []
167+
method: []
168+
provider: ["local-auth-provider"]
169+
170+
authorization_policies:
171+
172+
- resource:
173+
path: []
174+
method: []
175+
claims: []
176+
```
177+
178+
Following is a sample authentication policy using form-based authentication. In this policy, local-based authentication is used.
179+
180+
```yml
181+
182+
apiVersion: citrix.com/v1beta1
183+
kind: authpolicy
184+
metadata:
185+
name: localauth
186+
spec:
187+
servicenames:
188+
- frontend
189+
190+
authentication_mechanism:
191+
using_forms:
192+
authentication_host: "fqdn_authenticaton_host"
193+
authentication_host_cert:
194+
tls_secret: authhost-tls-cert-secret
195+
vip: "192.2.156.156"
196+
197+
authentication_providers:
198+
199+
- name: "local-auth-provider"
200+
basic_local_db:
201+
use_local_auth: 'YES'
202+
203+
authentication_policies:
204+
205+
- resource:
206+
path: []
207+
method: []
208+
provider: ["local-auth-provider"]
209+
210+
211+
authorization_policies:
212+
213+
- resource:
214+
path: []
215+
method: []
216+
claims: []
217+
218+
```
219+
220+
### Allow or deny access based on authentication attributes obtained during authentication
221+
222+
Following is an example HTTP callout policy to the OPA server using the rewrite policy CRD to allow or deny access based on authentication attributes obtained during authentication and the corresponding OPA rules.
223+
224+
In the example, the OPA server responds with `"result":true'` if the user `memberof` attribute contains `grp1`, else it responds with `"result":false`.
225+
226+
The following is the sample HTTP callout policy to the OPA server through the rewrite policy CRD:
227+
228+
```yml
229+
apiVersion: citrix.com/v1
230+
kind: rewritepolicy
231+
metadata:
232+
name: calloutexample
233+
spec:
234+
responder-policies:
235+
- servicenames:
236+
- frontend
237+
responder-policy:
238+
respondwith:
239+
http-payload-string: '"HTTP/1.1 401 Access denied\r\n\r\n"' #Access is denied if the respose from OPA server contains false.
240+
respond-criteria: 'sys.http_callout("callout_name").CONTAINS("false")'
241+
comment: 'Invalid access'
242+
243+
httpcallout_policy:
244+
- name: callout_name
245+
server_ip: "192.2.156.160" #OPA Server IP
246+
server_port: 8181 #OPA Server Port
247+
http_method: 'POST'
248+
host_expr: "\"192.2.156.160\""
249+
url_stem_expr: "\"/v1/data/example/allow\"" #URL stem expression to be used
250+
body_expr: '"{\"input\": {\"users\": [{\"name\": \""+ AAA.USER.NAME +"\", \"attr\": [\""+ aaa.user.attribute("memberof") +"\"]}]}}"' #JSON to OPA server carrying username and "memberof" attribute information
251+
headers:
252+
- name: Content-Type
253+
expr: '"application/json"'
254+
return_type: TEXT
255+
result_expr: "HTTP.RES.BODY(100)"
256+
```
257+
258+
Following are the rules defined through the Rego language on the OPA server for this example:
259+
260+
package example
261+
262+
default allow = false # unless otherwise defined, allow is false
263+
264+
allow = true { # allow is true if...
265+
count(isbeveragesuser) != 0 # the user is part of grp1.
266+
}
267+
268+
isbeveragesuser[user.name] { # a user is part of allow group...
269+
user := input.users[_]
270+
regex.match("CN=grp1", user.attr[_]) # if it is part of grp1 group.
271+
}
272+
273+
You can perform authentication using request header (401 based) or through forms based. In this example, LDAP authentication is used, where the user `memberof` attribute is obtained from the LDAP server during authentication.
274+
275+
Following is a sample authentication policy using request header-based authentication.
276+
277+
```yml
278+
apiVersion: citrix.com/v1beta1
279+
kind: authpolicy
280+
metadata:
281+
name: ldapauth
282+
spec:
283+
servicenames:
284+
- frontend
285+
286+
authentication_mechanism:
287+
using_request_header: 'ON'
288+
289+
authentication_providers:
290+
- name: "ldap-auth-provider"
291+
ldap:
292+
server_ip: "192.2.156.160"
293+
base: 'dc=aaa,dc=local'
294+
login_name: accountname
295+
sub_attribute_name: CN
296+
server_login_credentials: ldapcredential
297+
attributes_to_save: memberof #memberof attribute to be obtained from LDAP server for user
298+
299+
authentication_policies:
300+
- resource:
301+
path: []
302+
method: []
303+
provider: ["ldap-auth-provider"]
304+
305+
authorization_policies:
306+
- resource:
307+
path: []
308+
method: []
309+
claims: []
310+
```
311+
312+
Following is a sample authentication policy using form-based authentication.
313+
314+
```yml
315+
316+
apiVersion: citrix.com/v1beta1
317+
kind: authpolicy
318+
metadata:
319+
name: authhotdrinks
320+
spec:
321+
servicenames:
322+
- frontend
323+
324+
authentication_mechanism:
325+
using_forms:
326+
authentication_host: "fqdn_authenticaton_host"
327+
authentication_host_cert:
328+
tls_secret: authhost-tls-cert-secret
329+
vip: "192.2.156.156"
330+
331+
authentication_providers:
332+
- name: "ldap-auth-provider"
333+
ldap:
334+
server_ip: "192.2.156.160"
335+
base: 'dc=aaa,dc=local'
336+
login_name: accountname
337+
sub_attribute_name: CN
338+
server_login_credentials: ldapcredential
339+
attributes_to_save: memberof #memberof attribute to be obtained from LDAP server for user
340+
341+
authentication_policies:
342+
343+
- resource:
344+
path: []
345+
method: []
346+
provider: ["ldap-auth-provider"]
347+
```

docs/media/opa.png

74 KB
Loading

0 commit comments

Comments
 (0)