Skip to content

Commit

Permalink
Validated all policies in docs
Browse files Browse the repository at this point in the history
  • Loading branch information
micahhausler committed Oct 30, 2024
1 parent 8d0668b commit 3cfc8f4
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 96 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ permit (
action == k8s::Action::"create",
resource is k8s::Resource
) when {
resource.apiGroup == "" && // "" is the core API group in Kubernetes
resource.resource == "secret"
};
Expand All @@ -27,18 +28,21 @@ permit (
) when {
principal in k8s::Group::"personal-secret-creators" &&
resource.resource == "secret" &&
resource.apiGroup == "" &&
resource has name &&
resource.name == principal.name
};
// Admission policy enforcing that a secret name in create requests match the user's name
forbid (
principal is k8s::User,
action in k8s::admission::Action::"create",
action == k8s::admission::Action::"create",
resource is core::v1::Secret
) when {
principal in k8s::Group::"personal-secret-creators"
} unless {
resource.name == principal.name
// forbid doesn't apply under these conditions
resource.metadata.name == principal.name
};
```

Expand Down
31 changes: 15 additions & 16 deletions docs/CedarIntroduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@

This guide provides an introduction to Cedar

- [Introduction to Cedar](#introduction-to-cedar)
- [Policy](#policy)
- [Request Evaluation](#request-evaluation)
- [Schema](#schema)

## Policy
If you're not familiar with Cedar, what you need to know is that [Cedar policies] are structured with a Principal, Action, Resource, and optional Condition (PARC). Denials are implicit, but explicit `forbid`s have priority over `permit`s.
If you're not familiar with Cedar, [Cedar policies] are structured with a Principal, Action, Resource, and optional Condition (PARC). Denials are implicit, but explicit `forbid`s have priority over `permit`s.

[Cedar policies]: https://docs.cedarpolicy.com/policies/syntax-policy.html

Expand All @@ -17,16 +12,16 @@ permit (
principal == MyPrincipalType::"some-uuid",
action == Action::"some-action-name",
resource == MyResourceType::"some-uuid"
)
);
forbid (
principal == MyPrincipalType::"some-uuid",
action == Action::"some-other-action-name",
resource == MyResourceType::"some-uuid"
)
);
```

Every principal and resource is an [_entity_][entity], and actions are valid for various principal and resource entity types.
Every principal and resource is an [_entity_][entity], and actions are valid for specific principal and resource entity types.
Entities can also be contained by other entities.
Below is an example of a policy referencing a principal _entity_ group type.
In this example, a principal must be in the specified group, the action must be a "get" or "list", the resource must have an attribute titled `some_attribute_value` with the value `cool_value`, but the resource attribute `my_kind_attribute` must not be `secrets`.
Expand All @@ -39,11 +34,11 @@ permit (
action in [Action::"get", Action::"list"], // match multiple actions
resource is MyResourceType
)
// optional positive condition clause
// optional condition clause that applies the effect when true
when {
resource.some_attribute_name == "cool_value"
}
// optional negating condition clause
// optional negating condition clause, effect does not apply when true
unless {
resource.my_kind_attribute == "secrets"
};
Expand All @@ -57,17 +52,18 @@ In this example, there is a `k8s` namespace with a `User` entity, a `k8s::admiss
```cedar
forbid (
principal is k8s::User,
action is k8s::admission::Action::"create",
action == k8s::admission::Action::"create",
resource is core::v1::ConfigMap
) when {
principal.name == "test-user"
principal.metadata.name == "test-user"
};
```


## Request Evaluation

How does Cedar know if a principal is in a group? When evaluating a request, cedar has several inputs.
How does Cedar know if a principal is in a group?
When evaluating a request, Cedar has several inputs.
(You can play with some examples in the [Cedar Playground](https://www.cedarpolicy.com/en/playground)):

* A JSON list of entity structures to be considered
Expand Down Expand Up @@ -143,9 +139,12 @@ make build
./bin/converter clusterrolebindings > all-crbs.cedar
./bin/converter rolebindings > all-rbs.cedar

# Install cedar
cargo install cedar-policy-cli

# Validate the policies against the schema
cedar validate -s ./k8s-authz-admission.cedarschema.json --schema-format json -p all-crbs.cedar
cedar validate -s ./k8s-authz-admission.cedarschema.json --schema-format json -p all-rbs.cedar
cedar validate -s ./cedarschema/k8s-full.cedarschema --schema-format cedar -p all-crbs.cedar
cedar validate -s ./cedarschema/k8s-full.cedarschema --schema-format cedar -p all-rbs.cedar
```

[cedar_go]: https://pkg.go.dev/github.com/cedar-policy/cedar-go
Expand Down
58 changes: 27 additions & 31 deletions docs/CedarSchemas.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,6 @@ The referenced schemas are primarily created to document the entity shapes and a
[cedar-go]: https://github.com/cedar-policy/cedar-go
[cedar-go-schema]: https://github.com/cedar-policy/cedar-go/issues/2

- [Cedar Schemas](#cedar-schemas)
- [Authorizer cedarschema](#authorizer-cedarschema)
- [Principals](#principals)
- [Actions](#actions)
- [Resources](#resources)
- [Impersonated resources](#impersonated-resources)
- [Principals](#principals-1)
- [Actions](#actions-1)
- [Resources](#resources-1)


## Authorizer cedarschema

For the full authorization schema, see [cedarschema/k8s-authorization.cedarschema](../cedarschema/k8s-authorization.cedarschema).
Expand All @@ -29,19 +18,17 @@ For the full authorization schema, see [cedarschema/k8s-authorization.cedarschem

This project supports the following Principal entities:

* `k8s::Group`. Groups are identified by the group name.
* `k8s::Group`. Groups are identified by the group name in policy.
```cedarschema
entity Group = {
"name": __cedar::String,
};
entity Group;
```
* `k8s::User`. Users are identified by the user's UID as reported by the authenticator.
The group list comes in from the Kubernetes authenticator (webhook, serviceaccount, OIDC, etc), so we dynamically build the list of group Entities for a request.
Kubernetes authenticators can also includes extra key/value information on a user, and that is encoded in the 'extra' attribute.
```cedarschema
entity User in [Group] = {
"extra"?: Set < Extra >,
"name": __cedar::String,
"name": __cedar::String
};
type Extra = {
"key": __cedar::String,
Expand All @@ -53,7 +40,7 @@ This project supports the following Principal entities:
entity ServiceAccount in [Group] = {
"extra"?: Set < Extra >,
"name": __cedar::String,
"namespace": __cedar::String,
"namespace": __cedar::String
};
```
* `k8s::Node`. When a user's name in a [SubjectAccessReview] starts with `system:node:`, the authorizer sets the principal type to `k8s::Node` with the following attributes.
Expand All @@ -62,7 +49,7 @@ This project supports the following Principal entities:
```cedarschema
entity Node in [Group] = {
"extra"?: Set < Extra >,
"name": __cedar::String,
"name": __cedar::String
};
```

Expand All @@ -75,10 +62,11 @@ Authorization actions are pretty simple, just the `verb` name from the Kubernete
```cedar
permit (
principal in k8s::Group::"viewers",
action in [k8s::Action::"get", k8s::Action::"list", k8s::Action:"watch"],
action in [k8s::Action::"get", k8s::Action::"list", k8s::Action::"watch"],
resource is k8s::Resource
) unless {
resource.resource == "secrets"
resource.resource == "secrets" &&
resource.apiGroup == "" // "" is the core API group in Kubernetes
};
```

Expand Down Expand Up @@ -113,19 +101,18 @@ We define two primary resource types for this authorizer:
```
Examples:
```cedar
// allow multiple URLs
permit (
principal in Group::"system:authenticated",
principal in k8s::Group::"system:authenticated",
action == k8s::Action::"get",
resource is k8s::NonResourceURL
) when {
["/version", "/healthz"].contains(resource.path) ||
resource.path like "/healthz/*"
};
```
```cedar
// explicitly list one path
permit (
principal in Group::"version-getter",
principal in k8s::Group::"version-getter",
action == k8s::Action::"get",
resource == k8s::NonResourceURL::"/version"
);
Expand All @@ -146,7 +133,7 @@ We define two primary resource types for this authorizer:
```cedar
// "viewers" group members can get/list/watch any Namespaced other than secrets
permit (
principal in Group::"viewers",
principal in k8s::Group::"viewers",
action in [ k8s::Action::"get", k8s::Action::"list", k8s::Action::"watch"],
resource is k8s::Resource
) unless {
Expand All @@ -158,7 +145,7 @@ We define two primary resource types for this authorizer:
// Allow developers to manage deployments in any namespace other than kube-system or kube-public
permit (
principal in Group::"developers",
principal in k8s::Group::"developers",
action in [
k8s::Action::"get",
k8s::Action::"list",
Expand All @@ -170,9 +157,10 @@ We define two primary resource types for this authorizer:
) when {
resource.resource == "deployments" &&
resource.apiGroup == "apps" &&
resource has namespace // require a namespace name so cluster-scoped collection requests are not permitted
// require a namespace name so cluster-scoped collection requests are not permitted
resource has namespace
} unless {
// permit doesn't apply under these conditions
// permit does not apply under these conditions
resource has namespace &&
["kube-system", "kube-public" ].contains(resource.namespace)
};
Expand Down Expand Up @@ -227,7 +215,7 @@ example-secret Opaque 1 2d20h
$ kubectl get secrets --show-labels
NAME TYPE DATA AGE LABELS
example-secret Opaque 1 2d20h owner=test-user
other-example-secret Opaque 1 2d20h owner=test-user-2
other-example-secret Opaque 1 2d20h owner=prod-user
```

#### Impersonated resources
Expand Down Expand Up @@ -294,6 +282,7 @@ To make an impersonated request as another user, Kubernetes sends multiple autho
) when {
principal.name == "default" &&
principal.namespace == "default" &&
principal has extra &&
principal.extra.contains({
"key": "authentication.kubernetes.io/node-name",
"values": [resource.name]})
Expand Down Expand Up @@ -331,7 +320,10 @@ Admission actions exist in a different Cedar namespace than Authorization, and a
// largely redundant policy, as authorization already only allows non-mutating verbs on resources
forbid (
principal in k8s::Group::"system:viewers",
action in [k8s::admission::Action::"create", k8s::admission::Action::"update", k8s::admission::Action::"delete"],
action in [
k8s::admission::Action::"create",
k8s::admission::Action::"update",
k8s::admission::Action::"delete"],
resource
);
```
Expand All @@ -353,8 +345,12 @@ forbid (
action in [k8s::admission::Action::"create", k8s::admission::Action::"update"],
resource is core::v1::Pod
) when {
resource.spec.hostNetwork
resource has spec &&
resource.spec has hostNetwork &&
resource.spec.hostNetwork == true
} unless {
resource has metadata &&
resource.metadata has namespace &&
resource.metadata.namespace == "kube-system"
};
```
Expand Down
18 changes: 4 additions & 14 deletions docs/Demo.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
# Cedar access controls for Kubernetes Demo

- [Cedar access controls for Kubernetes Demo](#cedar-access-controls-for-kubernetes-demo)
- [Motivation](#motivation)
- [Setup](#setup)
- [Authorization](#authorization)
- [Basic access](#basic-access)
- [Group access](#group-access)
- [Attribute-based access control](#attribute-based-access-control)
- [Impersonation](#impersonation)
- [Admission](#admission)
- [Name selection](#name-selection)
- [Key/Value maps](#keyvalue-maps)

## Motivation

Administrators who want to secure their Kubernetes clusters today have to learn and use multiple different policy languages, and ensure those policies are individually applied on all their clusters.
Expand Down Expand Up @@ -295,8 +283,7 @@ permit (
k8s::admission::Action::"create",
k8s::admission::Action::"update",
k8s::admission::Action::"delete",
k8s::admission::Action::"connect",
],
k8s::admission::Action::"connect"],
resource
);
```
Expand All @@ -314,6 +301,7 @@ permit (
resource is k8s::Resource
) when {
principal.name == "test-user" &&
resource has namespace &&
resource.namespace == "default" &&
// "" is the core API group in Kubernetes
resource.apiGroup == "" &&
Expand All @@ -327,6 +315,8 @@ forbid (
resource is core::v1::ConfigMap
) when {
principal.name == "test-user" &&
resource has metadata &&
resource.metadata has name &&
resource.metadata.name like "prod*"
};
```
Expand Down
11 changes: 0 additions & 11 deletions docs/Development.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
# Development

- [Development](#development)
- [Contributing Guidelines](#contributing-guidelines)
- [Reporting Bugs/Feature Requests](#reporting-bugsfeature-requests)
- [Contributing via Pull Requests](#contributing-via-pull-requests)
- [Finding contributions to work on](#finding-contributions-to-work-on)
- [Code of Conduct](#code-of-conduct)
- [Security issue notifications](#security-issue-notifications)
- [Licensing](#licensing)
- [TODOs](#todos)
- [Converter testing](#converter-testing)

## Contributing Guidelines

Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
Expand Down
8 changes: 0 additions & 8 deletions docs/FutureFeatures.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,6 @@

The following list of feature ideas are not yet built, but potential candidates for addition.

- [Potential Future Feature Ideas](#potential-future-feature-ideas)
- [Multiple tiered policy stores](#multiple-tiered-policy-stores)
- [Amazon Verified Permissions integration](#amazon-verified-permissions-integration)
- [Cluster metadata](#cluster-metadata)
- [Service Control Policies](#service-control-policies)
- [Network Policy integration](#network-policy-integration)


## Multiple tiered policy stores

For this prototype, policies are all defined in as Policy custom resources.
Expand Down
9 changes: 0 additions & 9 deletions docs/Limitations.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
# Limitations

- [Limitations](#limitations)
- [Entity Tags (key/value maps)](#entity-tags-keyvalue-maps)
- [Expressiveness limitations](#expressiveness-limitations)
- [Policy store updates and race conditions](#policy-store-updates-and-race-conditions)
- [Policy store tiers](#policy-store-tiers)
- [No permission enumeration](#no-permission-enumeration)
- [No privilege escalation prevention](#no-privilege-escalation-prevention)


## Entity Tags (key/value maps)

Cedar's Rust implementation and CLI gained support for entity tags (key/value maps) in [Cedar v4.2.0][4.2].
Expand Down
2 changes: 2 additions & 0 deletions docs/RejectedFeatures.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ forbid (
action in [k8s::admission::Action::"create", k8s::admission::Action::"update"],
resource is core::v1::Pod
) when {
resource has metadata &&
resource.metadata has namespace &&
resource.metadata.namespace == "default"
} unless {
context has allContainersInRegistry &&
Expand Down
5 changes: 0 additions & 5 deletions docs/Setup.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
# Setup

- [Setup](#setup)
- [Local Setup with Kind](#local-setup-with-kind)
- [Local Quickstart](#local-quickstart)
- [Convert RBAC policies](#convert-rbac-policies)

## Local Setup with Kind

To run this project locally, you'll need to install [finch][finch], [Go][go], [kubectl][kubectl], [kind][kind], and [kubebuilder][kubebuilder] (if creating/modifying CRDs).
Expand Down

0 comments on commit 3cfc8f4

Please sign in to comment.