Skip to content

Commit

Permalink
Merge branch 'master' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
tsandall committed Sep 22, 2020
2 parents e88579b + 36781fb commit 729f909
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 15 deletions.
10 changes: 10 additions & 0 deletions ast/builtins.go
Expand Up @@ -130,6 +130,7 @@ var DefaultBuiltins = [...]*Builtin{
JSONUnmarshal,
Base64Encode,
Base64Decode,
Base64IsValid,
Base64UrlEncode,
Base64UrlDecode,
URLQueryDecode,
Expand Down Expand Up @@ -1231,6 +1232,15 @@ var Base64Decode = &Builtin{
),
}

// Base64IsValid verifies the input string is base64 encoded.
var Base64IsValid = &Builtin{
Name: "base64.is_valid",
Decl: types.NewFunction(
types.Args(types.S),
types.B,
),
}

// Base64UrlEncode serializes the input string into base64url encoding.
var Base64UrlEncode = &Builtin{
Name: "base64url.encode",
Expand Down
14 changes: 14 additions & 0 deletions capabilities.json
Expand Up @@ -195,6 +195,20 @@
"type": "function"
}
},
{
"name": "base64.is_valid",
"decl": {
"args": [
{
"type": "string"
}
],
"result": {
"type": "boolean"
},
"type": "function"
}
},
{
"name": "base64url.decode",
"decl": {
Expand Down
55 changes: 40 additions & 15 deletions docs/content/envoy-authorization.md
Expand Up @@ -4,10 +4,10 @@ kind: tutorial
weight: 8
---

[Envoy](https://www.envoyproxy.io/docs/envoy/v1.10.0/intro/what_is_envoy) is a
[Envoy](https://www.envoyproxy.io/docs/envoy/v1.14.4/intro/what_is_envoy) is a
L7 proxy and communication bus designed for large modern service oriented
architectures. Envoy (v1.7.0+) supports an [External Authorization
filter](https://www.envoyproxy.io/docs/envoy/v1.10.0/intro/arch_overview/ext_authz_filter.html)
filter](https://www.envoyproxy.io/docs/envoy/v1.14.4/intro/arch_overview/security/ext_authz_filter)
which calls an authorization service to check if the incoming request is
authorized or not.

Expand All @@ -27,8 +27,8 @@ policies over the HTTP request body.

This tutorial requires Kubernetes 1.14 or later. To run the tutorial locally, we
recommend using
[minikube](https://kubernetes.io/docs/getting-started-guides/minikube) in
version `v1.0+` with Kubernetes 1.14 (which is the default).
[minikube](https://minikube.sigs.k8s.io/docs/start/) in
version `v1.0+` with Kubernetes 1.14+.

## Steps

Expand Down Expand Up @@ -264,7 +264,7 @@ spec:
ports:
- containerPort: 8080
- name: envoy
image: envoyproxy/envoy:v1.10.0
image: envoyproxy/envoy:v1.14.4
securityContext:
runAsUser: 1111
volumeMounts:
Expand Down Expand Up @@ -322,32 +322,57 @@ spec:
kubectl apply -f deployment.yaml
```

Check that the Pod shows `3/3` containers `READY` the `STATUS` as `Running`:

```bash
kubectl get pod

NAME READY STATUS RESTARTS AGE
example-app-67c644b9cb-bbqgh 3/3 Running 0 8s
```

> The `proxy-init` container installs iptables rules to redirect all container
traffic through the Envoy proxy sidecar. More information can be found
[here](https://github.com/open-policy-agent/contrib/tree/master/envoy_iptables).


### 5. Create a Service to expose HTTP server

In a second terminal, start a [minikube tunnel](https://minikube.sigs.k8s.io/docs/handbook/accessing/#using-minikube-tunnel) to allow for use of the `LoadBalancer` service type.

```bash
kubectl expose deployment example-app --type=NodePort --name=example-app-service --port=8080
minikube tunnel
```

In the first terminal, create a `LoadBalancer` service for the deployment.

```bash
kubectl expose deployment example-app --type=LoadBalancer --name=example-app-service --port=8080
```

Check that the Service shows an `EXTERNAL-IP`:

```bash
kubectl get service example-app-service

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
example-app-service LoadBalancer 10.109.64.199 10.109.64.199 8080:32170/TCP 5s
```

Set the `SERVICE_URL` environment variable to the service's IP/port.

**minikube:**

```bash
export SERVICE_PORT=$(kubectl get service example-app-service -o jsonpath='{.spec.ports[?(@.port==8080)].nodePort}')
export SERVICE_HOST=$(minikube ip)
export SERVICE_URL=$SERVICE_HOST:$SERVICE_PORT
export SERVICE_HOST=$(kubectl get service example-app-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export SERVICE_URL=$SERVICE_HOST:8080
echo $SERVICE_URL
```

**minikube (example):**

```bash
192.168.99.113:31056
10.109.64.199:8080
```

### 6. Exercise the OPA policy
Expand All @@ -362,21 +387,21 @@ export BOB_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYWRtaW4iLCJzd
Check that `Alice` can get employees **but cannot** create one.

```bash
curl -i -H "Authorization: Bearer "$ALICE_TOKEN"" http://$SERVICE_URL/people
curl -i -H "Authorization: Bearer "$ALICE_TOKEN"" -d '{"firstname":"Charlie", "lastname":"OPA"}' -H "Content-Type: application/json" -X POST http://$SERVICE_URL/people
curl -i -H "Authorization: Bearer $ALICE_TOKEN" http://$SERVICE_URL/people
curl -i -H "Authorization: Bearer $ALICE_TOKEN" -d '{"firstname":"Charlie", "lastname":"OPA"}' -H "Content-Type: application/json" -X POST http://$SERVICE_URL/people
```

Check that `Bob` can get employees and also create one.

```bash
curl -i -H "Authorization: Bearer "$BOB_TOKEN"" http://$SERVICE_URL/people
curl -i -H "Authorization: Bearer "$BOB_TOKEN"" -d '{"firstname":"Charlie", "lastname":"Opa"}' -H "Content-Type: application/json" -X POST http://$SERVICE_URL/people
curl -i -H "Authorization: Bearer $BOB_TOKEN" http://$SERVICE_URL/people
curl -i -H "Authorization: Bearer $BOB_TOKEN" -d '{"firstname":"Charlie", "lastname":"Opa"}' -H "Content-Type: application/json" -X POST http://$SERVICE_URL/people
```

Check that `Bob` **cannot** create an employee with the same firstname as himself.

```bash
curl -i -H "Authorization: Bearer "$BOB_TOKEN"" -d '{"firstname":"Bob", "lastname":"Rego"}' -H "Content-Type: application/json" -X POST http://$SERVICE_URL/people
curl -i -H "Authorization: Bearer $BOB_TOKEN" -d '{"firstname":"Bob", "lastname":"Rego"}' -H "Content-Type: application/json" -X POST http://$SERVICE_URL/people
```

## Wrap Up
Expand Down
25 changes: 25 additions & 0 deletions test/cases/testdata/base64builtins/test-base64builtins-0935.yaml
@@ -0,0 +1,25 @@
cases:
- data: {}
modules:
- |
package generated
p = x {
base64.is_valid("aGVsbG8=", x)
}
note: base64builtins/is_valid-true
query: data.generated.p = x
want_result:
- x: true
- data: {}
modules:
- |
package generated
p = x {
base64.is_valid("{'not':'base64'}", x)
}
note: base64builtins/is_valid-false
query: data.generated.p = x
want_result:
- x: false
11 changes: 11 additions & 0 deletions topdown/encoding.go
Expand Up @@ -69,6 +69,16 @@ func builtinBase64Decode(a ast.Value) (ast.Value, error) {
return ast.String(result), err
}

func builtinBase64IsValid(a ast.Value) (ast.Value, error) {
str, err := builtins.StringOperand(a, 1)
if err != nil {
return nil, err
}

_, err = base64.StdEncoding.DecodeString(string(str))
return ast.Boolean(err == nil), nil
}

func builtinBase64UrlEncode(a ast.Value) (ast.Value, error) {
str, err := builtins.StringOperand(a, 1)
if err != nil {
Expand Down Expand Up @@ -230,6 +240,7 @@ func init() {
RegisterFunctionalBuiltin1(ast.JSONUnmarshal.Name, builtinJSONUnmarshal)
RegisterFunctionalBuiltin1(ast.Base64Encode.Name, builtinBase64Encode)
RegisterFunctionalBuiltin1(ast.Base64Decode.Name, builtinBase64Decode)
RegisterFunctionalBuiltin1(ast.Base64IsValid.Name, builtinBase64IsValid)
RegisterFunctionalBuiltin1(ast.Base64UrlEncode.Name, builtinBase64UrlEncode)
RegisterFunctionalBuiltin1(ast.Base64UrlDecode.Name, builtinBase64UrlDecode)
RegisterFunctionalBuiltin1(ast.URLQueryDecode.Name, builtinURLQueryDecode)
Expand Down

0 comments on commit 729f909

Please sign in to comment.