* kube: Return errors when users aren't allowed to list resources
Previously to this commit, if the user was denied to list resources from
a certain namespace, Teleport would return an empty list instead of
returning an error if it's impossible for the request to match any
resource in that namespace.
This commit returns an error for cases where the role's
`kubernetes_resources` denies any resource to be returned. This is a
small nit to incorporate some customer expectations.
Signed-off-by: Tiago Silva <tiago.silva@goteleport.com>
* Update lib/utils/replace.go
Co-authored-by: Hugo Shaka <hugo.hervieux@goteleport.com>
* handle code review suggestions
* Update lib/utils/replace.go
Co-authored-by: Anton Miniailo <anton@goteleport.com>
* fix test names
---------
Signed-off-by: Tiago Silva <tiago.silva@goteleport.com>
Co-authored-by: Hugo Shaka <hugo.hervieux@goteleport.com>
Co-authored-by: Anton Miniailo <anton@goteleport.com>
Prefer the stdlib version of the experimental package.
Includes a depguard update to prevent future regressions,
as well as an e-ref update to appease depguard.
Generated with:
$ gofmt -w -r '"golang.org/x/exp/slices" -> "slices"' . && \
make fix-imports
This PR adds a RBAC controll logic for Kubernetes Custom Resources.
Access to clustom resources is determined by the access level of the
namespace resource where the custom resource is defined.
This is a special case because custom resources are not defined in the
user's resources list.
Signed-off-by: Tiago Silva <tiago.silva@goteleport.com>
This PR corrects the behavior of handling namespaces for Kubernetes
per-Resource RBAC.
The new behavior allows accessing the resources withing the namespace
`someNamespace` if a rule `kind: namespace, name: someNamespace` is
defined for `kubernetes_resources`.
It also allows users to see namespaces (list, get or watch requests) if
they have other resources defined for the namepsace without requiring
explicit rules for `kind:namespace, name: someNamespace`.
As an example:
```yaml
allow:
kubernetes_resources:
- kind: namespace
name: someNamespace
- kind: pod
namespace: otherNamespace
name: *
```
Reads as: the user has access to everything in namespace someNamespace
AND to pods in otherNamespace.
```
$ kubectl get ns
someNamespace
otherNamespace
```
Pods:
```
$ kubectl get pods -n someNamespace
pod1
pod2
$ kubectl get pods -n otherNamespace
pod3
pod4
```
Other resources:
```
$ kubectl get secret -n someNamespace
secret1
secret2
$ kubectl get secret -n otherNamespace
REQUEST IS DENIED
```
* Extend Teleport RBAC to suport Kubernetes Verbs
This PR extends Teleport per-Resource RBAC to support Kubernetes verbs
restriction. With this change it's possible to restrict certain actions
allowed by the underlying `kubernetes_users` and `kubernetes_resources`.
Supported verbs:
- `get`
- `create`
- `update`
- `patch`
- `delete`
- `list`
- `watch`
- `deletecollection`
Fixes#27095
* address timr's comments
* assign wildcard to verbs for role <7
* address marco's reviews
This PR introduces a new role version - `v7` - to support other
Kubernetes resources such as `Deployments`, `Statefulsets`... while
keeping compatibility with previous role versions.
This PR adds the following validations:
- `v6`, `v5`, `v4`: `kubernetes_resources` can only include `kind: pod`
resources
- `v7`: `kubernetes_resources` can include wildcards or other
resourceces (to be introduced by #26244.
It also adds a role version downgrade (v13 clients connecting to v14
auth server) where we downgrade the role's version and remove unsuported
kubernetes_resources from the resource list.
Part of #20811
Okta Import Rules will now use Teleport style regexes as opposed to raw
regexp. This will maintain parity with the way the rest of Teleport handles
matching.
* Add benchmark for ListNodes
* Move RBAC logging to trace level
BenchmarkListNodes is twice as slow when RBAC logging is enabled.
By switching RBAC logging from debug to trace we can eliminate
the performance hit while still providing a way for users to opt
in to the behavior if they need to debug RBAC.
* Intern compiled regular expressions
Profiles of the benchmark test revealed that the `regexp.Compile`
done within `utils.matchString` was the most cpu and memory intensive
portion of the tests. By leveraging a `lru.Cache` to intern the
compiled regular expressions we get quite a performance improvement.
* Only fetch a single page of resources
Increases the request limit prior to loading the resources from
the cache so that we load enough items in a single page to determine
the start key of the next page.
* Remove version checking from `services.UnmarshalServer`
Unmarshal directly to a `types.ServerV2` instead of first creating
a `types.ResourceHeader` to inspect the version. There is only a
single version for `types.ServerV2` making the check unnecessary.
* Add `GetLabel` to `types.ResourceWithLables`
`GetAllLabels` can be overkill if one simply needs to look up the
value for a particular label. It creates a new `map[string]string`
and copies all of a resources existing labels. RBAC decisions
driven by labels incurred the penalty of the copy each time access
was checked. The impact of the copy is much more noticeable when
a resource has several labels or really long strings in the key
or value.
By leveraging `GetLabel` RBAC can avoid copying the labels altogether
and simply lookup each label key when required.
This PR introduces a mechanism to control access to Pods in Kubernetes clusters based on access criteria defined in user Roles or Resource Access Requests.
New `Role` version - `v6` - introduced a new field `kubernetes_resources` that allows admins to restrict access to a subset of cluster resources based on the configuration provided.
This PR implements the resource control for `pods` and allows
```yaml
kubernetes_resources:
- kind: pod
name: nginx-*
namespace: default
- kind: pod
name: *
namespace: dev
```
It also implements the logic blocks for supporting Resource Access Requests to Kubernetes Pods. The tsh boilerplate is not included in this PR and will be included in future PRs.
An example of usage:
```
tsh request search --kind pod --kube-cluster=minikube
Name Namespace Labels Resource ID
--------------------------------- --------- -------------------------------------- ---------------------------------------------
nginx-deployment-6595874d85-6j2zm default app=nginx,pod-template-hash=6595874d85 /tele.teleport.local/pod/minikube/default/...
nginx-deployment-6595874d85-7xgmb default app=nginx,pod-template-hash=6595874d85 /tele.teleport.local/pod/minikube/default/...
nginx-deployment-6595874d85-c4kz8 default app=nginx,pod-template-hash=6595874d85 /tele.teleport.local/pod/minikube/default/...
test default run=test /tele.teleport.local/pod/minikube/default/...
To request access to these resources, run
> tsh request create --resource /tele.teleport.local/pod/minikube/default/nginx-deployment-6595874d85-6j2zm --resource /tele.teleport.local/pod/minikube/default/nginx-deployment-6595874d85-7xgmb --resource /tele.teleport.local/pod/minikube/default/nginx-deployment-6595874d85-c4kz8 --resource /tele.teleport.local/pod/minikube/default/test \
--reason <request reason>
```
Part of #18434
This commit reduces the number of `log.Debug`s in the trait loop evaluation in case of a mismatch.
This commit also optimizes the trait eval loop ensuring that each regexp is compiled at-most once, and only if strictly needed.
Introduce new make targets to check and add license headers to files
("make lint-license" and "make fix-license"). License checking is now a part of
"make lint" as well.
Initial attempts used goheader, but it caused "make lint-go" to become about 9x
slower (if not more), plus it only targets go files. Google's addlicense is fast
enough and targets however many file types we want.
Existing files that were missing licenses got the header added, using the
current year as the license date.
* Introduce lint-license and fix-license make targets
* Ignore generated files
* Add license to go files
* Replace irregular licenses with standard copyright/license
* Add license to proto files
* Install addlicense in build.assets Dockerfile
This commit adds two extensions to template variables
in roles and adds support for regular expressions
and group captures in role mapping of trusted clusters.
1. Roles node_labels can expand variables from traits:
allow:
node_labels:
'{{external.key}}': '{{external.val}}'
deny:
node_labels:
'{{external.key}}': '{{external.val}}'
If traits variable is not found, label key pair in allow or
deny rule will be set to empty key or value, so if 'external.val'
trait is missing, the resulting role will not match
allow or deny rule:
allow:
node_labels:
'': 'val'
deny:
node_labels:
'': 'val'
Same thing will happen for missing value:
allow:
node_labels:
'key': ''
deny:
node_labels:
'key': ''
2. Trusted cluster role mapping can now
support advanced expressions:
a. Glob values will math any string, including
empty one
role_map:
- remote: 'cluster-*'
local: [clusteradmin]
a. Regular expression syntax is supported:
Syntax: https://github.com/google/re2/wiki/Syntax
Brackets can be used as a capture group and referred
to with expand variable:
role_map:
- remote: '^clusteradmin-(.*)$'
local: [unprivileged-$1]
Will map incoming role 'clusteradmin-account-1' to 'guest-account-1'.
3. Same regular expression syntax is supported for SAML and OIDC
mappings:
a. Glob matches of values instead of static matches:
claims_to_roles:
- {claim: "roles", value: "gravitational/*", roles: ["clusteradmin"]}
b. Regexp matches with subgroup expands:
attributes_to_roles:
- {name: "roles", value: "^gravitational/(.*)$", roles: ["cluster-$1"]}