问题描述
我一直在尝试使用Google Cloud Functions(python 3.7)来基本上克隆Google Source Repository。我正在使用GitPython库,该Cloud Functions的服务帐户对要克隆的存储库具有 Source Repository Reader 源访问权限。
最初,我尝试将gcloud.sh credential.helper传递给git config,但是似乎Cloud SDK环境中(至少在Python 3.7环境中)未安装Cloud SDK。这是我的代码要点:
from git import Repo
import tempfile
def git_clone():
local_repo = tempfile.gettempdir()+'/localrepo'
repo = Repo.init(local_repo)
origin = repo.create_remote('origin','https://source.developers.google.com/p/PROJECT/r/REPO')
repo.config_writer().set_value("user","name","gsr-to-gcs-backup-function").release()
repo.config_writer().set_value("user","email","gsr-to-gcs-backup-function@PROJECT.iam.gserviceaccount.com").release()
repo.config_writer().set_value("credential \"https://source.developers.google.com\"","helper","gcloud.sh").release()
assert origin.exists()
assert origin == repo.remotes.origin == repo.remotes['origin']
origin.fetch()
如果在Cloud Functions上运行,该函数将引发以下错误,因为默认情况下,如果没有凭据帮助程序, https 方法将要求输入用户名和密码。
git.exc.GitCommandError:Cmd('git')失败的原因是:退出代码(128) cmdline:git fetch -v origin stderr:'致命:无法读取用户名 对于“ https://source.developers.google.com”:输入/输出错误”
我只能找到下面的答案来传递令牌以及 git clone 命令,但它没有回答如何传递令牌:
Clone Google Source Repository without gcloud
如果我从云外壳启动该命令,它将被挂起:
gcloud auth git-helper store --account=YOUR_ACCOUNT --ignore-unkNown $@
Repo.clone_from("https://source.developers.google.com/p/PROJECT/r/REPO",tempfile.gettempdir(),multi_options=['--config credential.helper={}'.format(MYTOKEN)],branch='master')
我不想放置SSH密钥作为克隆方法,因为我想稍后将其部署到生产中,并且旋转密钥会很麻烦。
解决方法
询问的用户名不过是服务帐户地址和凭据,可以是临时生成的OAuth 2.0访问令牌。所以,我最终要做的是:
from git import Repo
import tempfile
import urllib.parse
import google.auth
import google.auth.transport.requests
def get_token():
creds,project = google.auth.default()
# creds.valid is False,and creds.token is None
# # Need to refresh credentials to populate those
auth_req = google.auth.transport.requests.Request()
creds.refresh(auth_req)
# Now you can use creds.token
return creds.token
def url_parse():
query = 'gsr-to-gcs-backup-function@PROJECT.iam.gserviceaccount.com'
return urllib.parse.quote(query)
def git_clone():
encoded_url = url_parse()
credentials = get_token()
local_repo = tempfile.gettempdir()+'/localrepo'
Repo.clone_from(f"https://{encoded_url}:{credentials}@source.developers.google.com/p/PROJECT/r/REPO",local_repo,branch='master')
def main(*args):
git_clone()
注意:这只是我的代码的一部分。我想要将其复制到GCS存储桶中。但这超出了这个问题的范围。