Publié le: 2023-11-02

Accéder à un endpoint sans ressources protégé par RBAC

Lors de l’installation d’un controller Kubernetes, il est possible que l’accès au endpoint /metrics soit interdit:

$ curl -k https://<controller-ip>:8443/metrics
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {

  },
  "status": "Failure",
  "message": "forbidden: User \"system:anonymous\" cannot get path \"/metrics\"",
  "reason": "Forbidden",
  "details": {

  },
  "code": 403
}

Un des cas les plus répandus est la récupération des métriques de composants du controlplane Kubernetes avec Prometheus.

Ici le controller nous identifie en tant qu’utilisateur anonyme system:anonymous. Cela est dû au fait que nous faisons un appel à l’API sans authentification, mais cela peut également arriver si nous utilisons un token JWT via un ServiceAccount.

curl -k -H "Authorization: Bearer <jwt>" https://<controller-ip>:8443/metrics
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "forbidden: User \"system:serviceaccount:my-namespace:my-serviceaccountname\" cannot get path \"/metrics\"",
  "reason": "Forbidden",
  "details": {},
  "code": 403
}

Ici notre token JWT est identifié comme étant celui du service account my-serviceaccountname du namespace my-namespace.

Lorsque cette erreur survient, l’API que vous interrogez est protégée par une revue de ses accès via le système RBAC de Kubernetes. Cette revue est soit faite en direct (dans le cadre de l’APIServer) ou via les SelfSubjectAccessReview (SSAR) (API).

Voici un résumé bref de ce qu’il va se passer en terme de flux au moment de l’appel à /metrics:

SSAR Flow

Le endpoint /metrics (tout comme /healthz et /readyz, par exemple) ne dessert aucune ressource Kubernetes, il s’agit d’un endpoint spécifique au controller. Il sera donc impossible d’y avoir accès au travers d’un Role, vu que la notion de namespace n’existe pas pour les endpoints non liés à une ressource Kubernetes, mais en revanche il est possible de créer un ClusterRole qui autorisera l’accès à ce endpoint.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: controller-metrics
rules:
- apiGroups: [""]
  nonResourceURLs: ["/metrics"]
  verbs: ["get"]

Ensuite on associe ce ClusterRole à un ClusterRoleBinding:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: controller-metrics
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: controller-metrics
subjects:
- kind: ServiceAccount
  name: my-serviceaccountname
  namespace: my-namespace

Point important, comme il s’agit d’un ClusterRole, cela signifie que si vous accordez ce droit à un compte de service il pourra lire ce chemin sur toutes les API l’implémentant et utilisant le système RBAC de Kubernetes en SubjectAccessReview. C’est donc un droit à donner avec parcimonie.

Vous savez maintenant comment gérer ce cas d’erreur.