Manage Access to Security Reports¶
In Starboard security reports are stored as CRD instances (e.g. VulnerabilityReport and ConfigAuditReport objects).
With Kubernetes RBAC, a cluster administrator can choose the following levels of granularity to manage access to security reports:
- Grant administrative access to view any report in any namespace.
- Grant coarse-grained access to view any report in a specified namespace.
- Grant fine-grained access to view a specified report in a specified namespace.
Even though you can achieve fine-grained access control with Kubernetes RBAC configuration, it is very impractical to do so with security reports. Mainly because security reports are associated with ephemeral Kubernetes objects such as Pods and ReplicaSets.
To sum up, we only recommend using administrative and coarse-grained levels to manage access to security reports.
Continue reading to see examples of managing access to VulnerabilityReport objects at different levels of granularity.
Create Namespaces and Deployments¶
Let's consider a multitenant cluster with two nginx
Deployments in foo
and bar
namespaces. There's also the
redis
Deployment in the foo
namespace.
kubectl create namespace foo
kubectl create deploy nginx --image nginx:1.16 --namespace foo
kubectl create deploy redis --image redis:5 --namespace foo
kubectl create namespace bar
kubectl create deploy nginx --image nginx:1.16 --namespace bar
When we scan them Starboard will create VulnerabilityReports which are named by revision kind (replicaset
)
concatenated with revision name (nginx-7967dc8bfd
) and container name (nginx
).
starboard scan vulnerabilityreports deploy/nginx --namespace foo
starboard scan vulnerabilityreports deploy/redis --namespace foo
starboard scan vulnerabilityreports deploy/nginx --namespace bar
Tip
For workloads with multiple containers we'll have multiple instances of VulnerabilityReports with the same prefix
(replicaset-nginx-7967dc8bfd-
) but different suffixes that correspond to container names.
$ kubectl tree deploy nginx --namespace foo
NAMESPACE NAME READY REASON AGE
foo Deployment/nginx - 21m
foo └─ReplicaSet/nginx-7967dc8bfd - 21m
foo ├─Pod/nginx-7967dc8bfd-gqw8h True 21m
foo └─VulnerabilityReport/replicaset-nginx-7967dc8bfd-nginx - 4m36s
$ kubectl tree deploy nginx --namespace bar
NAMESPACE NAME READY REASON AGE
bar Deployment/nginx - 20m
bar └─ReplicaSet/nginx-f4cc56f6b - 20m
bar ├─Pod/nginx-f4cc56f6b-9cd45 True 20m
bar └─VulnerabilityReport/replicaset-nginx-f4cc56f6b-nginx - 2m12s
$ kubectl tree deploy redis --namespace foo
NAMESPACE NAME READY REASON AGE
foo Deployment/redis - 74m
foo └─ReplicaSet/redis-79c5cc7cf8 - 74m
foo ├─Pod/redis-79c5cc7cf8-fz99f True 74m
foo └─VulnerabilityReport/replicaset-redis-79c5cc7cf8-redis - 74m
Choose Access Level¶
To manage access to VulnerabilityReport instances a cluster administrator will typically create Role or ClusterRole objects and bind them to subjects (users, groups, or service accounts) by creating RoleBinding or ClusterRoleBinding objects.
With Kubernetes RBAC there are three different granularity levels at which you can grant access to VulnerabilityReports:
- Cluster - a subject can view any report in any namespace
- Namespace - a subject can view any report in a specified namespace
- Security Report - a subject can view a specified report in a specified namespace
Grant Access to View any VulnerabilityReport in any Namespace¶
kubectl create clusterrole view-vulnerabilityreports \
--resource vulnerabilityreports \
--verb get,list,watch
kubectl create clusterrolebinding dpacak-can-view-vulnerabilityreports \
--clusterrole view-vulnerabilityreports \
--user dpacak
$ kubectl get vulnerabilityreports -A --as dpacak
NAMESPACE NAME REPOSITORY TAG SCANNER AGE
bar replicaset-nginx-f4cc56f6b-nginx library/nginx 1.16 Trivy 40m
foo replicaset-nginx-7967dc8bfd-nginx library/nginx 1.16 Trivy 43m
$ kubectl get vulnerabilityreports -A --as zpacak
Error from server (Forbidden): vulnerabilityreports.khulnasoft.github.io is f
orbidden: User "zpacak" cannot list resource "vulnerabilityreports" in API grou
p "khulnasoft.github.io" at the cluster scope
$ kubectl who-can get vulnerabilityreports -A
No subjects found with permissions to get vulns assigned through RoleBindings
CLUSTERROLEBINDING SUBJECT TYPE SA-NAMESPACE
cluster-admin system:masters Group
dpacak-can-view-vulnerabilityreports dpacak User
system:controller:generic-garbage-collector generic-garbage-collector ServiceAccount kube-system
system:controller:namespace-controller namespace-controller ServiceAccount kube-system
Note
The who-can command is a kubectl plugin that shows who has RBAC permissions to perform actions on different resources in Kubernetes.
Grant Access to View any VulnerabilityReport in the foo Namespace¶
kubectl create clusterrole view-vulnerabilityreports \
--resource vulnerabilityreports \
--verb get,list,watch
kubectl create rolebinding dpacak-can-view-vulnerabilityreports \
--namespace foo \
--clusterrole view-vulnerabilityreports \
--user dpacak
$ kubectl get vulnerabilityreports --namespace foo --as dpacak
NAME REPOSITORY TAG SCANNER AGE
replicaset-nginx-7967dc8bfd-nginx library/nginx 1.16 Trivy 51m
$ kubectl get vulnerabilityreports --namespace bar --as dpacak
Error from server (Forbidden): vulnerabilityreports.khulnasoft.github.io is f
orbidden: User "dpacak" cannot list resource "vulnerabilityreports" in API grou
p "khulnasoft.github.io" in the namespace "bar"
Grant Access to View the replicaset-nginx-7967dc8bfd-nginx VulnerabilityReport in the foo Namespace¶
Even though you can grant access to a single VulnerabilityReport by specifying its name when you create Role or ClusterRole objects, in practice it's not manageable for these reasons:
- The name of a ReplicaSet (e.g.
nginx-7967dc8bfd
) and hence the name of the corresponding VulnerabilityReport (e.g.replicaset-nginx-7967dc8bfd-nginx
) change over time. This requires that Role or ClusterObject will be updated respectively. - We create a VulnerabilityReport for each container of a Kubernetes workload. Therefore, managing such fine-grained permissions is even more cumbersome.
- Last but not least, the naming convention is an implementation details that's likely to change when we add support for mutable tags or implement caching of scan results.
kubectl create role view-replicaset-nginx-7967dc8bfd-nginx \
--namespace foo \
--resource vulnerabilityreports \
--resource-name replicaset-nginx-7967dc8bfd-nginx \
--verb get
kubectl create rolebinding dpacak-can-view-replicaset-nginx-7967dc8bfd-nginx \
--namespace foo \
--role view-replicaset-nginx-7967dc8bfd-nginx \
--user dpacak
$ kubectl get vuln -n foo replicaset-nginx-7967dc8bfd-nginx --as dpacak
NAME REPOSITORY TAG SCANNER AGE
replicaset-nginx-7967dc8bfd-nginx library/nginx 1.16 Trivy 163m
$ kubectl get vuln -n foo replicaset-redis-79c5cc7cf8-redis --as dpacak
Error from server (Forbidden): vulnerabilityreports.khulnasoft.github.io "rep
licaset-redis-79c5cc7cf8-redis" is forbidden: User "dpacak" cannot get resource
"vulnerabilityreports" in API group "khulnasoft.github.io" in the namespace "
foo"
$ kubectl who-can get vuln/replicaset-nginx-7967dc8bfd-nginx -n foo
ROLEBINDING NAMESPACE SUBJECT TYPE SA-NAMESPACE
dpacak-can-view-replicaset-nginx-7967dc8bfd-nginx foo dpacak User
CLUSTERROLEBINDING SUBJECT TYPE SA-NAMESPACE
cluster-admin system:masters Group
system:controller:generic-garbage-collector generic-garbage-collector ServiceAccount kube-system
system:controller:namespace-controller namespace-controller ServiceAccount kube-system