2

我一直在尝试使用 Google Cloud Functions (python 3.7) 来克隆 Google Source Repository。我正在使用GitPython库,并且该 Cloud Functions 的服务帐户对我要克隆的存储库具有Source Repository Reader访问权限。

最初,我尝试将gcloud.sh credential.helper传递给 git config,但似乎 Cloud SDK 未安装在 Cloud Functions 环境中(至少在 Python 3.7 环境中)。这是我的代码的要点:

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方法将询问UsernamePassword

git.exc.GitCommandError: Cmd('git') failed due to: exit code(128) cmdline: git fetch -v origin stderr: 'fatal: could not read Username for 'https://source.developers.google.com ':输入/输出错误'

我只能找到以下答案来传递令牌以及git clone命令,但它没有回答如何传递令牌:

在不使用 gcloud 的情况下克隆 Google Source Repository

如果我从 cloud shell 启动该命令,它将被挂起:

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 密钥作为一种克隆方法,因为我想稍后将其部署到生产环境中,并且轮换密钥会很麻烦。

4

1 回答 1

1

询问的用户名只不过是服务帐户地址和凭据,可以是临时生成的 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 存储桶中。但这不在这个问题的范围内。

于 2020-09-23T11:05:53.183 回答