Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/kubernetes/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为GKE auth生成的令牌缺少权限_Python_Kubernetes_Google Cloud Platform_Kubernetes Python Client - Fatal编程技术网

Python 为GKE auth生成的令牌缺少权限

Python 为GKE auth生成的令牌缺少权限,python,kubernetes,google-cloud-platform,kubernetes-python-client,Python,Kubernetes,Google Cloud Platform,Kubernetes Python Client,我尝试在Google Kubernetes(GKE)中以自动化的方式创建角色 为此,我使用python客户端库,但我不想对kubectl和kubeconfig或gcloud有任何依赖性 我使用一个服务帐户(带有来自GCP的json密钥文件),它有权在名称空间中创建角色(它是一个集群管理员)。当我使用此命令给出的访问令牌时: gcloud auth activate-service-account --key-file=credentials.json gcloud auth print-acc

我尝试在Google Kubernetes(GKE)中以自动化的方式创建角色

为此,我使用python客户端库,但我不想对kubectl和kubeconfig或gcloud有任何依赖性

我使用一个服务帐户(带有来自GCP的json密钥文件),它有权在名称空间中创建角色(它是一个集群管理员)。当我使用此命令给出的访问令牌时:

gcloud auth activate-service-account --key-file=credentials.json 
gcloud auth print-access-token
它起作用了

但是,当我尝试自己生成令牌时,我可以创建名称空间和其他标准资源,但在角色方面,我有一个错误:

E           kubernetes.client.rest.ApiException: (403)
E           Reason: Forbidden
E           HTTP response headers: HTTPHeaderDict({'Audit-Id': 'b89b0fc2-9350-456e-9eca-730e7ad2cea1', 'Content-Type': 'application/json', 'Date': 'Tue, 26 Feb 2019 20:35:20 GMT', 'Content-Length': '1346'})
E           HTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"roles.rbac.authorization.k8s.io \"developers\" is forbidden: attempt to grant extra privileges: [{[*] [apps] [statefulsets] [] []} {[*] [apps] [deployments] [] []} {[*] [autoscaling] [horizontalpodautoscalers] [] []} {[*] [] [pods] [] []} {[*] [] [pods/log] [] []} {[*] [] [pods/portforward] [] []} {[*] [] [serviceaccounts] [] []} {[*] [] [containers] [] []} {[*] [] [services] [] []} {[*] [] [secrets] [] []} {[*] [] [configmaps] [] []} {[*] [extensions] [ingressroutes] [] []} {[*] [networking.istio.io] [virtualservices] [] []}] user=\u0026{100701357824788592239  [system:authenticated] map[user-assertion.cloud.google.com:[AKUJVp+KNvF6jw9II+AjCdqjbC0vz[...]hzgs0JWXOyk7oxWHkaXQ==]]} ownerrules=[{[create] [authorization.k8s.io] [selfsubjectaccessreviews selfsubjectrulesreviews] [] []} {[get] [] [] [] [/api /api/* /apis /apis/* /healthz /openapi /openapi/* /swagger-2.0.0.pb-v1 /swagger.json /swaggerapi /swaggerapi/* /version /version/]}] ruleResolutionErrors=[]","reason":"Forbidden","details":{"name":"developers","group":"rbac.authorization.k8s.io","kind":"roles"},"code":403}
我使用的是同一个服务帐户,所以我猜gcloud做的事情比我的脚本还多

下面是我用来生成令牌的python代码:

def _get_token(self) -> str:
    # See documentation here
    # https://developers.google.com/identity/protocols/OAuth2ServiceAccount
    epoch_time = int(time.time())
    # Generate a claim from the service account file.
    claim = {
        "iss": self._service_account_key["client_email"],
        "scope": "https://www.googleapis.com/auth/cloud-platform",
        "aud": "https://www.googleapis.com/oauth2/v4/token",
        "exp": epoch_time + 3600,
        "iat": epoch_time
    }
    # Sign claim with JWT.
    assertion = jwt.encode(
        claim,
        self._service_account_key["private_key"],
        algorithm='RS256'
    ).decode()
    # Create payload for API.
    data = urlencode({
        "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
        "assertion": assertion
    })
    # Request the access token.
    result = requests.post(
        url="https://www.googleapis.com/oauth2/v4/token",
        headers={
            "Content-Type": "application/x-www-form-urlencoded"
        },
        data=data
    )
    result.raise_for_status()
    return json.loads(result.text)["access_token"]

def _get_api_client(self) -> client.ApiClient:
    configuration = client.Configuration()
    configuration.host = self._api_url
    configuration.verify_ssl = self._tls_verify
    configuration.api_key = {
        "authorization": f"Bearer {self._get_token()}"
    }
    return client.ApiClient(configuration)
以及创建角色的函数(生成403错误):

如果我用从gcloud中提取的令牌短路了_get_token方法,它就会工作

我想这与我创建令牌的方式有关(缺少范围?),但我没有找到任何关于它的文档

回答:

添加一个作用域就可以了!非常感谢:

# Generate a claim from the service account file.
        claim = {
            "iss": self._service_account_key["client_email"],
            "scope": " ".join([
                "https://www.googleapis.com/auth/cloud-platform",
                "https://www.googleapis.com/auth/userinfo.email"
            ]),
            "aud": "https://www.googleapis.com/oauth2/v4/token",
            "exp": epoch_time + 3600,
            "iat": epoch_time
        }

因此,如果您查看
print access token
的代码,您可以看到访问令牌通常是在没有作用域的情况下打印的。你看,

try:
  creds = client.GoogleCredentials.get_application_default()
except client.ApplicationDefaultCredentialsError as e:
  log.debug(e, exc_info=True)
  raise c_exc.ToolException(str(e))

if creds.create_scoped_required():
   ...
然后你会看到:

显然,在您的代码中,您将获得带有
https://www.googleapis.com/auth/cloud-platform
范围。您可以尝试删除它或尝试使用,因为您正在指定:
“iss”:self.\u service\u account\u key[“client\u email”]


您可以随时检查
gcloud auth activate service account--key file=credentials.json
存储在
~/.config
下的内容。所以您知道
gcloud auth print access token
使用什么。请注意,根据,商店的格式似乎是。

您正在使用的服务帐户没有群集管理员角色,或者您没有将服务帐户电子邮件地址添加到
kubectl create clusterrolebinding群集管理员绑定--clusterrole群集管理员--user service_account_电子邮件
我将确保两者都是设置正确。问题在于缺少电子邮件作用域!非常感谢!
try:
  creds = client.GoogleCredentials.get_application_default()
except client.ApplicationDefaultCredentialsError as e:
  log.debug(e, exc_info=True)
  raise c_exc.ToolException(str(e))

if creds.create_scoped_required():
   ...
def create_scoped_required(self):
    """Whether this Credentials object is scopeless.
    create_scoped(scopes) method needs to be called in order to create
    a Credentials object for API calls.
    """
    return False