[英]Google Service Account's Private Key problems with .NET client tool used to publish Android app to Google Play Console
我正在创建一个名为 google-play-publisher 的开源工具,开发为 .NET 7 REST API 委托给Google API .NET Client 。
我的想法是在我的 GitLab CI/CD 管道中将它作为容器(即服务)运行,以便将 Android 应用程序(即:aab 文件)上传到 Google Play 开发人员,因为它公开了一个我可以使用curl
调用的简单端点像这样:
curl -XPOST --data-binary @your_file.aab http://localhost:5000/api/apps/<your_package_name>/tracks/<track_name>
使持续交付变得方便。
我拥有让它工作所需的一切,包括具有适当角色和凭据的 Google 服务帐户,这是我的 Google Play 控制台已知的。
我将密钥下载为 JSON 格式,它的格式如下(假值):
{
"type": "service_account",
"project_id": "pc-api-...",
"private_key_id": "5342dce..",
"private_key": "-----BEGIN PRIVATE KEY-----\nbunchofcharacters\nandmorecharactes=\n-----END PRIVATE KEY-----\n",
"client_email": "publisher@pc-api-foo-iam.gserviceaccount.com",
"client_id": "123456",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/publisher@pc-api-foo-iam.gserviceaccount.com"
}
注意: -----BEGIN PRIVATE KEY-----
和-----END PRIVATE KEY-----\n
是非常必要的。 如果删除,Google API .NET 客户端库将失败。
从那以后,我只需要 6 件事:
type
project_id
private_key_id
private_key
client_email
client_id
为了获得 Google Publisher v3 API 的授权,并将特定 package 的 AAB 上传到特定轨道。
应用程序只需要在启动时注入这 6 个设置,方法是在appsettings.json
中配置它们,或者在启动容器时作为环境变量注入。 到目前为止相当标准。
我的appsettings.json
看起来像这样(使用凭证 json 中的正确值)
"ServiceAccount": {
"PrivateKey": "***",
"ClientEmail": "***",
"ProjectId": "***",
"Type": "***",
"PrivateKeyId": "***",
"ClientId": "***"
},
当我使用正确的值配置此appsettings.json
时,一切正常。
但我不想将appsettings.json
用于机密。 我需要使用环境变量,以便我可以将该工具与 docker 一起使用,并在启动容器/服务时注入变量。
但是当将该工具作为 docker 容器或作为 GitLab CI/CD 管道内的服务运行时,我遇到了一些问题。
当我像这样将工具(版本 0.1.8)作为 docker 容器运行时
docker run \
--name google-play-publisher \
-p 5000:80 \
-e ServiceAccount__PrivateKey="-----BEGIN PRIVATE KEY-----\nbunchofcharacters\nandmorecharactes=\n-----END PRIVATE KEY-----\n" \
-e ServiceAccount__ClientEmail="publisher@pc-api-foo-iam.gserviceaccount.com" \
-e ServiceAccount__ProjectId="pc-api-..."\
-e ServiceAccount__Type="service_account" \
-e ServiceAccount__PrivateKeyId="5342dce.." \
-e ServiceAccount__ClientId="123456" \
registry.gitlab.com/roundev/devops/google-play-publisher:0.1.8
然后我发布一个package的aab 文件
curl -XPOST --data-binary @my_file.aab http://localhost:5000/api/apps/com.foo.app/tracks/production
认证失败
System.ArgumentException: PKCS8 data must be contained within '-----BEGIN PRIVATE KEY-----' and '-----END PRIVATE KEY-----'. (Parameter 'pkcs8PrivateKey')
因为docker run
似乎不喜欢传递带有\n
字符等的特殊环境变量。
它无法屏蔽它,这是一个问题,然后有些东西不起作用但我还看不到错误(没有显示错误,管道通过但 AAB 未上传,所以我需要想办法读取 GitLab CI/CD 服务日志,为此出自 scope)
我想在 base64 中编码私钥(不确定是否有其他选择)以获得以下优势:
但这显示了一个不同的问题。 使用在线 base 64 编码器并在代码中对其进行解码以生成 google 身份验证凭据是行不通的。 \n
字符似乎把事情搞砸了。
我尝试了不同的变体,但在使用 Google Publisher API 时,我总是遇到一些invalid_token
问题。
// Functions used for encoding and decoding
string EncodeBase64(string text)
{
var textBytes = Encoding.UTF8.GetBytes(text);
var result = Convert.ToBase64String(textBytes);
return result;
}
string DecodeBase64(string base64Text)
{
var base64EncodedBytes = Convert.FromBase64String(base64Text);
var result = Encoding.UTF8.GetString(base64EncodedBytes);
return result;
}
我还没有找到一个好的解决方案,可以让我:
appsetting.json
运行它一样工作必须有一个使用某种编码/解码私钥的好的解决方案。 但是怎么办?
我已经用十六进制方法解决了它。
基本上,解决方案是按原样获取private_key
的 Json 值,并将其转换为十六进制,例如使用此在线工具https://codebeautify.org/string-hex-converter所以私钥看起来像这样"-----BEGIN PRIVATE KEY-----\nfoo...\nbar\n-----END PRIVATE KEY-----\n"
现在看起来像这样2d2d2d2d2d424...b45592d2d2d2d2d5c6e
该字符串具有以下特征:
private_key
:private class JsonCredentials
{
public string Type { get; init; } = string.Empty;
public string PrivateKeyId { get; init; } = string.Empty;
public string PrivateKeyHex { get; init; } = string.Empty;
public string PrivateKey => ToJsonValue(PrivateKeyHex);
public string ClientEmail { get; init; } = string.Empty;
public string ProjectId { get; init; } = string.Empty;
public string ClientId { get; init; } = string.Empty;
private string ToJsonValue(string hexadecimalValue)
{
var hexadecimalValueBytes = Convert.FromHexString(hexadecimalValue);
var result = Encoding.UTF8.GetString(hexadecimalValueBytes);
var unescapedResult = Regex.Unescape(result);
return unescapedResult;
}
}
有关详细信息,请参阅我的开源存储库: https://gitlab.com/roundev/devops/google-play-publisher并尝试一下。
我相信您的问题是密钥中转义的新行 (/n),特别是使用 base 64 方法。
尝试通过将密钥粘贴到在线 base 64 编码器来生成 base 64 字符串,如下所示:
-----BEGIN PRIVATE KEY-----
Whatever
-----END PRIVATE KEY-----
而不是:
-----BEGIN PRIVATE KEY-----/nWhatever/n-----END PRIVATE KEY-----/n
与 Gitlab 相同。使用正确的换行符而不是/n粘贴您的密钥
关于docker run ,显然/n没有被解析为新行并按字面意思理解,因此您需要研究如何解决这个问题。 但基本上要么用代码中的新行替换它们,要么用 go 替换 base 64 string road。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.