我正在尝试使用Axios客户端在我的Node.js应用程序中获取(GCS)的图像文件。在开发模式下,使用我的个人电脑,我传递一个比勒令牌,所有的工作正常。
但是,我需要在引擎(GKE)上托管的集群中使用这一点。
我通过工作负载标识方法创建了一个服务帐户(GSA),然后使用kubernetes帐户(KSA)进行了验证,但是当我尝试通过我的应用程序的一个端点获取文件时,我收到的是:
{"statusCode":401,"message":"Unauthorized"}少了些什么?
更新:我所做的:
https://cloud.google.com/iam/docs/creating-managing-service-accounts
# gke-access-gcs.ksa.yaml file
apiVersion: v1
kind: ServiceAccount
metadata:
name: gke-access-gcskubectl apply -f gke-access-gcs.ksa.yamlgcloud iam service-accounts add-iam-policy-binding \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:cluster_project.svc.id.goog[k8s_namespace/ksa_name]" \
gsa_name@gsa_project.iam.gserviceaccount.comkubectl annotate serviceaccount \
--namespace k8s_namespace \
ksa_name \
iam.gke.io/gcp-service-account=gsa_name@gsa_project.iam.gserviceaccount.comgcloud projects add-iam-policy-binding project-id \
--member=serviceAccount:gsa-account@project-id.iam.gserviceaccount.com \
--role=roles/storage.objectAdminkubectl run -it \
--image google/cloud-sdk:slim \
--serviceaccount ksa-name \
--namespace k8s-namespace \
workload-identity-test上述命令工作正常。注意,传递了--serviceaccount和workload-identity。这对GKE来说是必要的吗?
PS:我不知道这是否会影响,但我在项目中使用SQL和代理。
发布于 2020-09-28 07:21:07
编辑
问题中描述的问题与axios客户端不使用这一工作负载标识利用的应用程序默认凭据(作为官方谷歌库)机制有关。ADC检查:
GOOGLE_APPLICATION_CREDENTIALS,则ADC将使用变量指向的服务帐户文件。GOOGLE_APPLICATION_CREDENTIALS,ADC将使用计算引擎、Google引擎、App、Cloud和Cloud函数提供的默认服务帐户。--
这意味着axios客户端将需要返回到Bearer token 身份验证方法,以便在Google .上进行身份验证。
使用Bearer token的身份验证在正式文档中描述如下:
API认证 若要使用OAuth 2.0向云存储XML API或JSON API发出请求,请在每个需要身份验证的请求中将应用程序的访问令牌包含在
Authorization头中。您可以从OAuth 2.0游乐场生成一个访问令牌。 授权:无记名OAUTH2_TOKEN 下面是一个在桶中列出对象的请求示例。 JSON API 使用对象资源的列表方法。 获取/存储/v1/b/示例-桶/o/1.1主机: www.googleapis.com授权:承载www.googleapis.com -- Cloud.google.com:存储: Docs: Api身份验证
我已经包含了使用Axios查询云存储的代码片段的基本示例(需要$ npm install axios):
const Axios = require('axios');
const config = {
headers: { Authorization: 'Bearer ${OAUTH2_TOKEN}' }
};
Axios.get(
'https://storage.googleapis.com/storage/v1/b/BUCKET-NAME/o/',
config
).then(
(response) => {
console.log(response.data.items);
},
(err) => {
console.log('Oh no. Something went wrong :(');
// console.log(err) <-- Get the full output!
}
);我在下面的工作负载标识设置示例中附带了一个node.js官方库代码片段,因为它可能对其他社区成员有用。
当我成功地使用Workload Identity和一个简单的nodejs应用程序从GCP bucket发送和检索数据时,我发布了这个答案。
我包括了一些疑难解答潜在问题的要点。
步骤:
GKE集群是否启用了Workload Identity。Kubernetes service account是否与Google Service account相关联。Google Service account。Google Service account是否具有访问bucket的正确权限。您还可以跟踪正式文档:
假设:
awesome-project <- 的项目(ID) --它是唯一的示例bucket-namespace的Kubernetes命名空间bucket-service-account的Kubernetes服务帐户google-bucket-service-account的谷歌服务帐户workload-bucket-example <- 的云存储桶--它是唯一的示例我包括了命令:
$ kubectl create namespace bucket-namespace
$ kubectl create serviceaccount --namespace bucket-namespace bucket-service-account
$ gcloud iam service-accounts create google-bucket-service-account
$ gcloud iam service-accounts add-iam-policy-binding --role roles/iam.workloadIdentityUser --member "serviceAccount:awesome-project.svc.id.goog[bucket-namespace/bucket-service-account]" google-bucket-service-account@awesome-project.iam.gserviceaccount.com
$ kubectl annotate serviceaccount --namespace bucket-namespace bucket-service-account iam.gke.io/gcp-service-account=google-bucket-service-account@awesome-project-ID.iam.gserviceaccount.com使用上面链接的指南,检查验证API的服务帐户:
$ kubectl run -it --image google/cloud-sdk:slim --serviceaccount bucket-service-account --namespace bucket-namespace workload-identity-test$ gcloud auth list的输出应显示:
Credentialed Accounts
ACTIVE ACCOUNT
* google-bucket-service-account@AWESOME-PROJECT.iam.gserviceaccount.com
To set the active account, run:
$ gcloud config set account `ACCOUNT`之前创建的Google服务帐户应该出现在输出中!
此外,还需要将服务帐户的权限添加到桶中。你可以:
Cloud Console$ gsutil iam ch serviceAccount:google-bucket-service-account@awesome-project.iam.gserviceaccount.com:roles/storage.admin gs://workload-bucket-example要从workload-bucket-example下载文件,可以使用以下代码:
// Copyright 2020 Google LLC
/**
* This application demonstrates how to perform basic operations on files with
* the Google Cloud Storage API.
*
* For more information, see the README.md under /storage and the documentation
* at https://cloud.google.com/storage/docs.
*/
const path = require('path');
const cwd = path.join(__dirname, '..');
function main(
bucketName = 'workload-bucket-example',
srcFilename = 'hello.txt',
destFilename = path.join(cwd, 'hello.txt')
) {
const {Storage} = require('@google-cloud/storage');
// Creates a client
const storage = new Storage();
async function downloadFile() {
const options = {
// The path to which the file should be downloaded, e.g. "./file.txt"
destination: destFilename,
};
// Downloads the file
await storage.bucket(bucketName).file(srcFilename).download(options);
console.log(
`gs://${bucketName}/${srcFilename} downloaded to ${destFilename}.`
);
}
downloadFile().catch(console.error);
// [END storage_download_file]
}
main(...process.argv.slice(2));代码是准确的副本,来自:
运行此代码应该会产生一个输出:
root@ubuntu:/# nodejs app.js
gs://workload-bucket-example/hello.txt downloaded to /hello.txt.root@ubuntu:/# cat hello.txt
Hello there!https://stackoverflow.com/questions/63664800
复制相似问题