Skip to content

Commit

Permalink
use secrets manager to distribute Cloud Storage credentials in stagin…
Browse files Browse the repository at this point in the history
…g and prod
  • Loading branch information
lyuyangh committed Sep 20, 2022
1 parent 873bf71 commit 2a86d65
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 14 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ This repository includes code for frontend and backend of the ExplainaBoard web
- We use docker and gunicorn to deploy both frontend and backend. Frontend is built and copied into the static file folder of Flask. Please see Dockerfile for details.
- To build: `docker build --pull --rm -f "Dockerfile" -t explainaboard-web:0.2.0 "."`
- To run: `docker run --rm -p 5000:5000/tcp explainaboard-web:0.2.0`
- The frontend is served with the flask server at the root url so 5000 is the used to access the UI here.
- connexion is used by swagger/openapi code generation tool and it does not support gunicorn natively. So, currently we use flask server in production. Another option that connexion supports natively is tornado.
- GCP:
- For local development, developers should use their own user accounts to authenticate (please refer to quick start for details)
- For staging and production environments, the service account credentials are passed into the containers as environment variables. The credentials are stored on AWS Secrets Manager.
## More details on frontend and backend
1. Frontend:
Expand Down
4 changes: 2 additions & 2 deletions backend/src/impl/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ AWS_DEFAULT_REGION=
AWS_SECRET_ACCESS_KEY=
AWS_ACCESS_KEY_ID=

GOOGLE_APPLICATION_CREDENTIALS=
GCP_SERVICE_CREDENTIALS= # used for staging and prod environments only (ECS), not intended to local
STORAGE_BUCKET_NAME=
GOOGLE_CLOUD_PROJECT=
GOOGLE_CLOUD_PROJECT=
42 changes: 42 additions & 0 deletions backend/src/impl/init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import logging
import os
from typing import Final

from explainaboard_web.impl.config import (
LocalDevelopmentConfig,
ProductionConfig,
StagingConfig,
)
from flask import Flask


def init(app: Flask) -> Flask:
"""Initializes the flask app"""
_init_config(app)
_init_gcp_credentials()
return app


def _init_config(app: Flask):
FLASK_ENV = os.getenv("FLASK_ENV")
if FLASK_ENV == "production":
app.config.from_object(ProductionConfig())
elif FLASK_ENV == "development":
app.config.from_object(LocalDevelopmentConfig())
elif FLASK_ENV == "staging":
app.config.from_object(StagingConfig())


def _init_gcp_credentials():
"""If the app is running in an ECS container, the GCP credentials
are passed in as an environment variable. This function reads that
variable, writes to a file and points the Google Cloud Storage
client to the correct file to authenticate the service.
"""
if os.environ.get("GCP_SERVICE_CREDENTIALS"):
credentials = os.environ["GCP_SERVICE_CREDENTIALS"]
gcp_credentials_path: Final = "./GCP_SERVICE_CREDENTIALS.json"
with open(gcp_credentials_path, "w") as f:
f.write(credentials)
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = gcp_credentials_path
logging.info("GCP credentials file initialized from environment variable.")
12 changes: 2 additions & 10 deletions backend/templates/__main__.mustache
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import connexion
import os
from explainaboard_web.impl.config import ProductionConfig, StagingConfig, LocalDevelopmentConfig
from explainaboard_web.impl.init import init
from {{packageName}} import encoder

def create_app():
Expand All @@ -9,14 +8,7 @@ def create_app():
app.add_api('swagger.yaml', arguments={'title': '{{appName}}'},
pythonic_params=True, validate_responses=True)

FLASK_ENV = os.getenv('FLASK_ENV')
if FLASK_ENV == 'production':
app.app.config.from_object(ProductionConfig())
elif FLASK_ENV == 'development':
app.app.config.from_object(LocalDevelopmentConfig())
elif FLASK_ENV == 'staging':
app.app.config.from_object(StagingConfig())

app.app = init(app.app)
return app


Expand Down

0 comments on commit 2a86d65

Please sign in to comment.