kopf run --namespace=mynamespace not considered
Long story short
I run
kopf run --namespace=mcm-obs-prod-ago-fr aws_secrets_operator.py
as I am not allowed to act cluster-wide. I had the assumption when adding --namespace=xxx kopf would only act within this namespace. But I receive a lot of
[2025-09-10 18:10:37,647] kopf._core.reactor.o [ERROR ] Request attempt #1/9 failed; will retry: GET https://xxxxxxxxxxx6443/api/v1/namespaces -> APIForbiddenError('namespaces is forbidden: User "xxxxxxxxxx" cannot list resource "namespaces" in API group "" at the cluster scope', {'kind': 'Status', 'apiVersion': 'v1', 'metadata': {}, 'status': 'Failure', 'message': 'namespaces is forbidden: User "xxxxxxxxxxxxxx" cannot list resource "namespaces" in API group "" at the cluster scope', 'reason': 'Forbidden', 'details': {'kind': 'namespaces'}, 'code': 403})
Kopf version
1.38.0
Kubernetes version
OpenShift 4.16.40
Python version
3.9.21
Code
import hashlib
import kopf
import kubernetes
import logging
def compute_secret_hash(secret):
data = secret.data or {}
serialized = "".join(f"{k}:{v}" for k, v in sorted(data.items()))
return hashlib.sha256(serialized.encode()).hexdigest()
def load_service_account_token():
configuration = kubernetes.client.Configuration()
configuration.host = "xxxxxxxxxxxxx" # from oc whoami
configuration.verify_ssl = False
# configuration.ssl_ca_cert = "ca.crt" # path to downloaded CA
with open("sa-token.txt") as f:
token = f.read().strip()
configuration.api_key = {"authorization": "Bearer " + token}
kubernetes.client.Configuration.set_default(configuration)
@kopf.on.startup()
def configure(settings: kopf.OperatorSettings, **_):
#settings.posting.level = 'INFO'
settings.peering.standalone = True
load_service_account_token()
#kubernetes.config.load_incluster_config()
@kopf.on.update('v1', 'secrets')
def secret_changed(name, namespace, body, **kwargs):
logging.info(f"Secret {name} in namespace {namespace} has changed.")
Logs
2025-09-10 18:10:37,587] kopf._core.reactor.r [DEBUG ] Starting Kopf 1.38.0.
[2025-09-10 18:10:37,587] kopf.activities.star [DEBUG ] Activity 'configure' is invoked.
[2025-09-10 18:10:37,588] kopf.activities.star [INFO ] Activity 'configure' succeeded.
[2025-09-10 18:10:37,589] kopf._core.engines.a [INFO ] Initial authentication has been initiated.
[2025-09-10 18:10:37,589] kopf.activities.auth [DEBUG ] Activity 'login_via_client' is invoked.
[2025-09-10 18:10:37,604] kopf.activities.auth [DEBUG ] Client is configured via kubeconfig file.
[2025-09-10 18:10:37,604] kopf.activities.auth [INFO ] Activity 'login_via_client' succeeded.
[2025-09-10 18:10:37,604] kopf._core.engines.a [INFO ] Initial authentication has finished.
[2025-09-10 18:10:37,645] kopf._cogs.clients.w [DEBUG ] Starting the watch-stream for customresourcedefinitions.v1.apiextensions.k8s.io cluster-wide.
[2025-09-10 18:10:37,647] kopf._core.reactor.o [ERROR ] Request attempt #1/9 failed; will retry: GET https://xxxxxxxxxxx6443/api/v1/namespaces -> APIForbiddenError('namespaces is forbidden: User "xxxxxxxxxx" cannot list resource "namespaces" in API group "" at the cluster scope', {'kind': 'Status', 'apiVersion': 'v1', 'metadata': {}, 'status': 'Failure', 'message': 'namespaces is forbidden: User "xxxxxxxxxxxxxx" cannot list resource "namespaces" in API group "" at the cluster scope', 'reason': 'Forbidden', 'details': {'kind': 'namespaces'}, 'code': 403})
Additional information
No response
Hello. Thanks for the report.
That is indeed the behaviour as designed — to scan all the existing namespaces to check if this one exists (and to resolve the ? & * globs, if any).
It seems, you are forbidden from even listing the namespaces. In that case, Kopf will try it a few times, and will fallback to using the specified namespace "as written".
There is a setting settings.scanning.disabled, which should be set to True to prevent such scanning and to fallback to the "as written" approach instantly. Source code & docstrings:
- The setting: https://github.com/nolar/kopf/blob/1.38.0/kopf/_cogs/configs/configuration.py#L238-L254
- The usage: https://github.com/nolar/kopf/blob/1.38.0/kopf/_core/reactor/observation.py#L50 (and a few other places in the same module).
For other readers: please mind that the setting disables BOTH namespace- & resource-scanning, so your resource specifications must be very precise, i.e. including the group, version, and the plural of the resource — not its kinds, aliases, or partial names. In this issue, the …('v1', 'secrets') is sufficiently precise. The full resource specs are given as an example here:
- https://kopf.readthedocs.io/en/stable/resources/#resource-specification
Nevertheless, please keep the issue open — it is indeed a couple of little bugs:
- This setting is completely missing from the docs for some reason — I probably overlooked it.
- The "Access Forbidden" should not be retried in these cases (I thought we already solved this particular issue, hm…).
I will take a look at this improvement some time later — unless it is a blocker now.
Related: #901
Hi,
that setting fixed it, thank you :) In large enterprises (I work for one) you usually do not get cluster-level permissions unless you part of the team that manages the cluster. I am a consumer of the provided cluster and thus, I only have permissions on namespace level. Technical inter-namespace communication must be facilitated via service accounts