Skip to content

Commit

Permalink
Add OPA example (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
zalbiraw authored May 28, 2024
1 parent 6d39003 commit a091ac4
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ Please see this [page](docs/FEATURES_MATRIX.md) for Tyk deployments compatibilit
- [keycloak-jwt](src/deployments/keycloak-jwt): stands up a Keycloak JWT Authentication example with Tyk.
- [keycloak-sso](src/deployments/keycloak-sso): stands up a Keycloak SSO example with the Tyk dashboard.
- [newrelic](src/deployments/newrelic): deploys Newrelic and stands up a Tyk pump to push analytics data from the Tyk platform to Newrelic.
- [opa](src/deployments/opa): enables Open Policy Agent to allow for Dashboard APIs governance.
- [operator](src/deployments/operator): deploys the [Tyk Operator](https://github.com/TykTechnologies/tyk-operator) and its dependency [cert-manager](https://github.com/jetstack/cert-manager).
- [operator-federation](src/deployments/operator-federation): stands up a Federation v1 API examples using the tyk-operator.
- [operator-graphql](src/deployments/operator-graphql): stands up a GraphQL API examples using the tyk-operator.
Expand Down
5 changes: 4 additions & 1 deletion docs/FEATURES_MATRIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
| keycloak-jwt | N/A | N/A | :white_check_mark: | :white_check_mark: | N/A | N/A | N/A |
| keycloak-sso | N/A | N/A | :white_check_mark: | N/A | N/A | N/A | N/A |
| newrelic | :warning: | :white_check_mark: | :white_check_mark: | N/A | N/A | [nri-bundle](https://helm-charts.newrelic.com/) | 5.0.75 |
| opa | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
| operator | :white_check_mark: | :white_check_mark: | :white_check_mark: | N/A | N/A | [tyk-helm](https://helm.tyk.io/public/helm/charts)/tyk-operator | 0.17.0 |
| operator-federation | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :no_entry: | N/A | N/A |
| operator-graphql | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | N/A | N/A | N/A |
Expand All @@ -44,6 +45,7 @@
| keycloak-jwt | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| keycloak-sso | N/A | :white_check_mark: | :white_check_mark: | N/A |
| newrelic | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| opa | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| operator | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| operator-federation | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| operator-graphql | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
Expand Down Expand Up @@ -72,8 +74,9 @@
| keycloak-dcr | N/A | N/A | N/A |
| keycloak-jwt | N/A | N/A | N/A |
| keycloak-sso | N/A | N/A | N/A |
| operator | N/A | N/A | N/A |
| newrelic | N/A | N/A | N/A |
| opa | N/A | N/A | N/A |
| operator | N/A | N/A | N/A |
| operator-federation | :white_check_mark: | :x: | :x: |
| operator-graphql | N/A | N/A | N/A |
| operator-httpbin | :white_check_mark: | :x: | :x: |
Expand Down
31 changes: 31 additions & 0 deletions src/deployments/opa/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
## Open Policy Agent
Enables Open Policy Agent to manage Tyk Dashboard API.

### Example
```
./up.sh --deployments opa tyk-stack
```

### Support
| Item | Status |
|:------------:|:------:|
| OpenShift | N/A |
| ARM | N/A |
| CI Tests | N/A |
| Postman Test | N/A |
| SSL | N/A |

### Supported Service Types with `--expose` flag
| Item | Status |
|:-------------:|:------:|
| Port Forward | N/A |
| Ingress | N/A |
| Load Balancer | N/A |

| Icon | Description |
|:------------------:|:-------------------------:|
| :white_check_mark: | Supported and tested |
| :warning: | Not tested |
| :x: | Not supported |
| :no_entry: | Not supported by the tool |

110 changes: 110 additions & 0 deletions src/deployments/opa/dashboard.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Default OPA rules
package dashboard_users
default request_intent = "write"
request_intent = "read" { input.request.method == "GET" }
request_intent = "read" { input.request.method == "HEAD" }
request_intent = "delete" { input.request.method == "DELETE" }
# Set of rules to define which permission is required for a given request intent.
# read intent requires, at a minimum, the "read" permission
intent_match("read", "read")
intent_match("read", "write")
intent_match("read", "admin")
# write intent requires either the "write" or "admin" permission
intent_match("write", "write")
intent_match("write", "admin")
# delete intent requires either the "write" or "admin permission
intent_match("delete", "write")
intent_match("delete", "admin")
# Helper to check if the user has "admin" permissions
default is_admin = false
is_admin {
input.user.user_permissions["IsAdmin"] == "admin"
}
# Check if the request path matches any of the known permissions.
# input.permissions is an object passed from the Tyk Dashboard containing mapping between user permissions (“read”, “write” and “deny”) and the endpoint associated with the permission.
# (eg. If “deny” is the permission for Analytics, it means the user would be denied the ability to make a request to ‘/api/usage’.)
#
# Example object:
# "permissions": [
# {
# "permission": "analytics",
# "rx": "\\/api\\/usage"
# },
# {
# "permission": "analytics",
# "rx": "\\/api\\/uptime"
# }
# ....
# ]
#
# The input.permissions object can be extended with additional permissions (eg. you could create a permission called ‘Monitoring’ which gives “read” access to the analytics API ‘/analytics’).
# This is can be achieved inside this script using the array.concat function.
request_permission[role] {
perm := input.permissions[_]
regex.match(perm.rx, input.request.path)
role := perm.permission
}
# --------- Start "deny" rules -----------
# A deny object contains a detailed reason behind the denial.
default allow = false
allow { count(deny) == 0 }
deny["User is not active"] {
not input.user.active
}
# If a request to an endpoint does not match any defined permissions, the request will be denied.
deny[x] {
count(request_permission) == 0
x := sprintf("This action is unknown. You do not have permission to access '%v'.", [input.request.path])
}
deny[x] {
perm := request_permission[_]
perm != "ResetPassword"
not is_admin
not input.user.user_permissions[perm]
x := sprintf("You do not have permission to access '%v'.", [input.request.path])
}
# Deny requests for non-admins if the intent does not match or does not exist.
deny[x] {
perm := request_permission[_]
not is_admin
not intent_match(request_intent, input.user.user_permissions[perm])
x := sprintf("You do not have permission to carry out '%v' operation.", [request_intent, input.request.path])
}
# If the "deny" rule is found, deny the operation for admins
deny[x] {
perm := request_permission[_]
is_admin
input.user.user_permissions[perm] == "deny"
x := sprintf("You do not have permission to carry out '%v' operation.", [request_intent, input.request.path])
}
# Do not allow users (excluding admin users) to reset the password of another user.
deny[x] {
request_permission[_] = "ResetPassword"
not is_admin
user_id := split(input.request.path, "/")[3]
user_id != input.user.id
x := sprintf("You do not have permission to reset the password for other users.", [user_id])
}
# Do not allow admin users to reset passwords if it is not allowed in the global config
deny[x] {
request_permission[_] == "ResetPassword"
is_admin
not input.config.security.allow_admin_reset_password
not input.user.user_permissions["ResetPassword"]
x := "You do not have permission to reset the password for other users. As an admin user, this permission can be modified using OPA rules."
}
# --------- End "deny" rules ----------
# --------- Start "custom" rules -----------
deny[x] {
request_permission[_] == "apis"
request_intent = "write"
input.request.body.api_definition.use_go_plugin_auth == true
x := "You are not permitted you use Custom Go Plugin Authetication."
}

patch_request[x] {
request_permission[_] == "apis"
request_intent = "write"
x := {"api_definition": {"config_data":{"OPARule": "Injected"}}}
}
# --------- End "custom" rules ----------
7 changes: 7 additions & 0 deletions src/deployments/opa/main.safe.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
if [ -z "$opaRegistered" ]; then
opaRegistered=true;

opaDeploymentPath="src/deployments/opa";

source "$opaDeploymentPath/main.sh";
fi
24 changes: 24 additions & 0 deletions src/deployments/opa/main.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
logger "$INFO" "enabling OPA management for Dashboard API...";

kubectl create configmap opa-rules \
--from-file="$opaDeploymentPath/dashboard.rego" \
--dry-run=client -o=yaml | \
kubectl apply --namespace "$namespace" -f - > /dev/null;

args+=( \
--set "tyk-dashboard.dashboard.extraEnvs[$dashExtraEnvsCtr].name=TYK_DB_SECURITY_OPENPOLICY_ENABLED" \
--set-string "tyk-dashboard.dashboard.extraEnvs[$dashExtraEnvsCtr].value=true" \
--set "tyk-dashboard.dashboard.extraEnvs[$((dashExtraEnvsCtr + 1))].name=TYK_DB_SECURITY_OPENPOLICY_ENABLEAPI" \
--set-string "tyk-dashboard.dashboard.extraEnvs[$((dashExtraEnvsCtr + 1))].value=true" \
--set "tyk-dashboard.dashboard.extraVolumes[$dashExtraVolumesCtr].name=opa-rules" \
--set "tyk-dashboard.dashboard.extraVolumes[$dashExtraVolumesCtr].configMap.name=opa-rules" \
--set "tyk-dashboard.dashboard.extraVolumeMounts[$dashExtraVolumeMountsCtr].name=opa-rules" \
--set "tyk-dashboard.dashboard.extraVolumeMounts[$dashExtraVolumeMountsCtr].mountPath=/opt/tyk-dashboard/schemas/dashboard.rego" \
--set "tyk-dashboard.dashboard.extraVolumeMounts[$dashExtraVolumeMountsCtr].subPath=dashboard.rego" \
);

dashExtraEnvsCtr=$((dashExtraEnvsCtr + 2));
dashExtraVolumesCtr=$((dashExtraVolumesCtr + 1));
dashExtraVolumeMountsCtr=$((dashExtraVolumeMountsCtr + 1));

addDeploymentArgs "${args[@]}";

0 comments on commit a091ac4

Please sign in to comment.