1

我在使用 GCP 中的云函数时遇到了困难,该函数在使用基本 GET 请求调用时应该返回存储在 GCS 存储桶中的原始 XML。它在没有任何类型的身份验证的情况下工作正常,但是由于我将 Flask-HTTPAuth 包添加到混合中以便在暴露端点之前添加一些安全措施,应用程序部署得很好,但是在没有任何提示的情况下崩溃一旦被调用。SD Logging 中的错误如下:

severity: "DEBUG"  
textPayload: "Function execution took 1847 ms, finished with status: 'crash'"  
timestamp: "2020-07-15T17:22:15.158036700Z"

有问题的功能(匿名):

from flask import Flask, request, jsonify, make_response, abort
from flask_httpauth import HTTPBasicAuth
from google.cloud import storage, secretmanager
import google.cloud.logging
import logging
import sys

app = Flask(__name__)
auth = HTTPBasicAuth()

PROJECT_ID = 'example_project'
GCS_BUCKET = 'example_bucket'
users = ['example_user']

# Instantiate logger
client = google.cloud.logging.Client()
client.get_default_handler()
client.setup_logging()

@auth.verify_password
def verify_password(username, password):
    # Instantiate the Secret Manager client.
    sm_client = secretmanager.SecretManagerServiceClient()

    # Load secrets
    name = sm_client.secret_version_path(PROJECT_ID, 'example_secrets_ref', 1)
    secrets_pass = sm_client.access_secret_version(name)
    passwords = [secrets_pass]
    if username in users and password in passwords:
        logging.info('auth success')
        return username
    logging.info('auth fail')
    return abort(403)

@app.route('/')
@auth.login_required
def latest_xml():
    try:
        request_json = request.get_json()#silent=True)
        storage_client = storage.Client(project=PROJECT_ID)
        bucket = storage_client.get_bucket(GCS_BUCKET)
        blob = bucket.get_blob('latest_pull.xml')
        latest_xml = blob.download_as_string()
        logging.info('Loaded blob from GCS')
        return(latest_xml)
    except exception as e:
        logging.error(str(e))
        logging.error("Failed to load blob from GCS")
        sys.exit(1)

if __name__ == '__main__':
    app.run()

我尝试将入口点设置为 main 函数和 auth 函数均无​​济于事。我的问题是:甚至可以在 GCP 云功能中使用基本身份验证,还是我在这里吠叫错误的树?

4

1 回答 1

3

您的函数不强制执行http 函数的标准签名

def latest_xml(request):
  ...

在这里,您使用了一个烧瓶 Web 服务器,它不需要,也没有被 Cloud Functions 使用。但是,我建议您查看Cloud Run,并添加一个简单通用的 Dockerfile 来部署. 您可以将“功能”按原样部署在容器中,并具有与 Cloud Functions 相同的行为。

编辑

使用flask 时,该request对象对于每个请求都是全局的。你像这样使用它:

       request_json = request.get_json()#silent=True)

使用 Cloud Functions,此对象会被 Cloud Functions 平台捕获并将参数传递给您的函数。

request对象中,您有请求的主体,例如在 GET 中无用。而且,所有请求上下文:标头、用户代理、源 IP、...

于 2020-07-22T09:40:56.557 回答