Search code examples
python-3.xflaskgoogle-app-enginegoogle-secret-manager

Integrate Google Secret Manager with Google App Engine in python3


I have an error when I try to access secret manager from Google App Engine Standard, but if I access from my laptop with the JSON key is fine.

requirements.txt:

Flask
google-cloud-storage
google-cloud-secret-manager
psycopg2

app.yaml

runtime: python39
automatic_scaling:
    max_instances : 2
    max_idle_instances : 1
    target_cpu_utilization : 0.9
    target_throughput_utilization : 0.9
    max_concurrent_requests : 80

Code:

from flask import Flask,render_template, request
from werkzeug.utils import secure_filename
import os
app = Flask(__name__)
@app.route('/s1',methods=['GET'])
def s1():
    from google.cloud import secretmanager
    client = secretmanager.SecretManagerServiceClient()
    return client.access_secret_version(request={"name": "projects/363745113141/secrets/API_OCR/versions/1"}).payload.data.decode("UTF-8")
if __name__ == '__main__':
    app.run()

error 1:

    grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
    
    at ._end_unary_response_blocking ( /layers/google.python.pip/pip/lib/python3.9/site-packages/grpc/_channel.py:849 )
    at .__call__ ( /layers/google.python.pip/pip/lib/python3.9/site-packages/grpc/_channel.py:946 )
    at .error_remapped_callable ( /layers/google.python.pip/pip/lib/python3.9/site-packages/google/api_core/grpc_helpers.py:50 )

error 2:

    google.api_core.exceptions.PermissionDenied: 403 Permission 'secretmanager.versions.access' denied for resource 'projects/363745113141/secrets/API_OCR/versions/1' (or it may not exist).
    
    at .error_remapped_callable ( /layers/google.python.pip/pip/lib/python3.9/site-packages/google/api_core/grpc_helpers.py:52 )
    at .retry_target ( /layers/google.python.pip/pip/lib/python3.9/site-packages/google/api_core/retry.py:190 )
    at .retry_wrapped_func ( /layers/google.python.pip/pip/lib/python3.9/site-packages/google/api_core/retry.py:283 )
    at .__call__ ( /layers/google.python.pip/pip/lib/python3.9/site-packages/google/api_core/gapic_v1/method.py:154 )
    at .access_secret_version ( /layers/google.python.pip/pip/lib/python3.9/site-packages/google/cloud/secretmanager_v1/services/secret_manager_service/client.py:1439 )
    at .accessSecret ( /srv/lib/secretManager.py:18 )
    at .s1 ( /srv/main.py:39 )
    at .dispatch_request ( /layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py:1509 )
    at .full_dispatch_request ( /layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py:1523 )
    at .full_dispatch_request ( /layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py:1525 )
    at .wsgi_app ( /layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py:2077 )

Solution

  • In order to have access to a secret version, you must grant access to it by adding the proper role. As described in the documentation Accessing a secret version:

    Accessing a secret version requires the Secret Manager Secret Accessor role (roles/secretmanager.secretAccessor) on the secret, project, folder, or organization.

    In this tutorial, Share your secrets between your teams and applications with Secret Manager on Google Cloud Platform, it shows how to give access to a given secret:

    If we want to give control the access to our secrets from Secret Manager console, we have to select one secret and press “Show Info Panel” button

    img1

    In the info panel, we want review the actual permission and we can add new member:

    img2

    img3

    And from the info panel, we can modify the access (only if the role is not inherited)

    Here we add the App Engine default service account (or the account you've created to run your App Engine if you have to do so).

    In the Viewing the App Engine default service account documentation, you can view your service accounts:

    1. In the Cloud console, go to the Service accounts page. Go to Service accounts

    2. Select your project.

    3. In the list, locate the email address of the App Engine default service account:

    [email protected]
    

    See also:


    Another approach is to use the account you've been using to do the tests on your laptop (the account used to generate the JSON key) as the account to run your application on App Engine:

    1. By adding the account on your app.yaml file:
    service_account: {SERVICE_ACCOUNT_YOU_WANT_TO_USE_TO_ACCESS_APP_ENGINE}
    
    1. By running the following command to deploy your application:
    gcloud beta app deploy --service-account=<your_service_account> app.yaml
    

    App Engine app's identity is not restricted to the AppEngine default service account anymore. You can deploy with custom service account for each AppEngine app now by following https://cloud.google.com/appengine/docs/standard/python/user-managed-service-accounts#app.yaml.

    These approaches are taken from the following question: Custom service account for App Engine.