This guide provides instructions for semi-automated deployment of FDA MyStudies to Google Cloud. It is designed to be completed in just a few hours.
This document explains how to integrate Terraform’s open-source infrastructure-as-code with continuous integration and continuous deployment (CICD) for a reproducible and easy-to-maintain environment. Kubernetes has been selected as the open-source container orchestration tool for its robust scaling and cluster management. All necessary Terraform templates, setup scripts and Kubernetes configuration files are included in the repository. This guide will explain what cloud services to enable, which configuration parameters to update and provide step-by-step instructions for each manual portion of the process.
This approach to deployment is based on Google Cloud's HIPAA-aligned architecture, which is designed to simplify your compliance journey. You can learn more about this approach to compliance in the Setting up a HIPAA-aligned project solution guide.
Following this guide will result in your own unique instance of the FDA MyStudies platform. The resulting deployment will have the structure illustrated in Figure 1. Each functionally distinct aspect of the platform is deployed into its own cloud project to facilitate compartmentalization and robust access management. Each project and resource is named for its purpose, and has a {PREFIX}-{ENV} label, where {PREFIX} is a consistent name of your choice and {ENV} describes your environment (for example, dev or prod). The list of projects you will create for your deployment is as follows:
| Project | Name | Purpose |
|---|---|---|
| Devops | {PREFIX}-{ENV}-devops |
This project executes the Terraform CICD pipeline that keeps your infrastructure aligned with the state defined in the deployment/terraform/ directory of your GitHub repository |
| Apps | {PREFIX}-{ENV}-apps |
This project stores the container images for each of your FDA MyStudies applications, updates those images with CICD pipelines that monitor changes you make to the application directories of your GitHub repository, and administers the Kubernetes cluster that operates those images (Figure 2 diagrams each the applications and how they related to their data sources) |
| Data | {PREFIX}-{ENV}-data |
This project contains the MySQL databases that support each of the FDA MyStudies applications, and the blob storage buckets that hold study resources and consent documents |
| Firebase | {PREFIX}-{ENV}-firebase |
This project contains the NoSQL database that stores the study response data |
| Networks | {PREFIX}-{ENV}-networks |
This project manages the network policies and firewalls |
| Secrets | {PREFIX}-{ENV}-secrets |
This project manages the deployment’s secrets, such as client ids and client secrets |
| Audit | {PREFIX}-{ENV}-audit |
This project stores the audit logs for the FDA MyStudies platform and applications |
This deployment configures the applications URLs as follows:
| Application | URL | Notes |
|---|---|---|
| Study builder | studies.{PREFIX}-{ENV}.{DOMAIN}/study-builder |
This URL navigates an administrative user to the Study builder user interface |
| Study datastore | studies.{PREFIX}-{ENV}.{DOMAIN}/study-datastore |
This URL is for the Study datastore back-end service |
| Participant manager | participants.{PREFIX}-{ENV}.{DOMAIN}/participant-manager |
This URL navigates an administrative user to the Participant manager user interface |
| Participant manager datastore | participants.{PREFIX}-{ENV}.{DOMAIN}/participant-manager-datastore |
This URL is for the Participant manager datastore back-end service |
| Participant datastore | participants.{PREFIX}-{ENV}.{DOMAIN}/participant-user-datastoreparticipants.{PREFIX}-{ENV}.{DOMAIN}/participant-enroll-datastoreparticipants.{PREFIX}-{ENV}.{DOMAIN}/participant-consent-datastore |
These URLs are for the Participant datastore back-end services |
| Response datastore | participants.{PREFIX}-{ENV}.{DOMAIN}/response-datastore |
This URL is for the Response datastore back-end service |
| Auth server | participants.{PREFIX}-{ENV}.{DOMAIN}/auth-server |
This URL is for the administrative users and study participants to log into their respective applications |
| Hydra | participants.{PREFIX}-{ENV}.{DOMAIN}/oauth2 |
This URL is used by the Auth server to complete OAuth 2.0 consent flows |
More information about the purpose of each application can be found in the Platform Overview guide. Detailed information about configuration and operation of each application can be found in their respective READMEs.
The deployment process takes the following approach:
- Create a copy of the FDA MyStudies repository that you will use for your deployment
- Create the
devopscloud project that will be used to orchestrate your deployment - Connect your cloned FDA MyStudies repository to your
devopsproject and set up the CICD pipelines that will automate the rest of your deployment - Provision the necessary cloud resources using your CICD pipelines
- Set up a second CICD pipeline that will automate creation of your application containers
- Create a Kubernetes cluster to run your application containers
- Create your initial user accounts and configure the required certificates, secrets, URLs, policies and network mesh
- Customize branding and text content as desired
- Create your first study
- Configure and deploy your mobile applications
- Familiarize yourself with:
- Terraform and Terraform Engine
- Kubernetes and Google Kubernetes Engine
- CICD and Google Cloud Build
- IAM and Google Cloud’s resource hierarchy
- Understand how the Terraform config files and cloud resources are named and organized in the deployment:
{PREFIX}is a name you choose for your deployment that will be prepended to various directories, cloud resources and URLs (for example this could be ‘mystudies’){ENV}is a label you choose that will be appended to{PREFIX}in your directories and cloud resources (for example this could be ‘dev’, ‘test’ or ‘prod’){DOMAIN}is the domain you will be using for your URLs (for example, ‘your_company_name.com’ or ‘your_medical_center.edu’)/deployment/deployment.hclis the file where you will specify top-level parameters for your deployment (for example, the values of{PREFIX},{ENV}and{DOMAIN})/deployment/mystudies.hclis the file that represents the overall recipe for the deployment (you will uncomment various aspects of this recipe as your deployment progresses)- The directories created in
/deployment/terraform/by thetfenginecommand represent distinct cloud projects that the CICD pipeline monitors to create, update or destroy resources based on the changes you make to those directories - The other directories in the FDA MyStudies repository map to the various components of the platform and contain Terraform and Kubernetes configuration files, such as
tf-deployment.yamlandtf-service.yaml, that support each component’s deployment
-
Make sure you have access to a Google Cloud environment that contains an organization resource (if you don’t have an organization resource, you can obtain one by creating a Google Workspace and selecting a domain)
-
Confirm the billing account that you will use has quota for 10 or more projects (newly created billing accounts may default to a 3-5 project quota)
- You can test how many projects your billing account can support by manually creating projects and linking them to your billing account, if you are able to link 10 projects to your billing account then you can proceed, otherwise request additional quota (don’t forget to unlink the test projects from your billing account, otherwise your quota may be exhausted)
-
Use the resource manager to create a folder to deploy your FDA MyStudies infrastructure into, for example you could name this folder
{PREFIX}-{ENV}(if you do not have theresourcemanager.folderAdminrole for your organization, you may need to ask your Google Cloud IT administrator to do this for you) -
Confirm you have access to a user account with the following Cloud IAM roles:
roles/resourcemanager.folderAdminfor the folder you createdroles/resourcemanager.projectCreatorfor the folder you createdroles/compute.xpnAdminfor the folder you createdroles/billing.adminfor the billing account that you will use
-
Use the groups manager to create the following administrative IAM groups that will be used during deployment:
Group name Description {PREFIX}-{ENV}-folder-admins@{DOMAIN}Members of this group have the resourcemanager.folderAdmin role for your deployment’s folder (for example, a deployment with prefix mystudies, environmentprodand domainexample.com, would require a group named[email protected]){PREFIX}-{ENV}-devops-owners@{DOMAIN}Members of this group have owners access for the devops project, which is required to make changes to the CICD pipeline and Terraform state {PREFIX}-{ENV}-auditors@{DOMAIN}Members of this group have the iam.securityReviewerrole for your deployment’s folder, and thebigquery.userandstorage.objectViewerroles for your audit log project{PREFIX}-{ENV}-cicd-viewers@{DOMAIN}Members of this group can view CICD results in Cloud Build, for example the results of the terraform planpresubmit andterraform applypostsubmit{PREFIX}-{ENV}-bastion-accessors@{DOMAIN}Members of this group have permission to access the bastion host project, which provides access to the private Cloud SQL instance {PREFIX}-{ENV}-project-owners@{DOMAIN}Members of this group have owners access to each of the deployment’s projects -
Add the user account that you will be using for deployment to these groups (if it is not already a member)
- You can work in an existing environment, or you can configure a new environment by creating a VM instance in the Google Cloud project of your choice (for example, an
e2-mediumGCE VM with Debian GNU/Linux 10 and default settings) - Confirm you have the following dependencies installed and added to your
$PATH:- Install the Google Cloud command line tool
gcloud(already installed if using a Google Compute Engine VM), for example:apt-get install google-cloud-sdk
- Install the Cloud Storage command line tool
gsutil(already installed if using a Google Compute Engine VM) - Install the Kubernetes command line tool
kubectl, for example:sudo apt-get update && sudo apt-get install -y apt-transport-https gnupg2 curl && \ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - && \ echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list && \ sudo apt-get update && \ sudo apt-get install -y kubectl
- Install Terraform 0.12.29, for example:
sudo apt-get install software-properties-common -y && \ curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add - && \ sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main" && \ sudo apt-get update && sudo apt-get install terraform=0.12.29
- Install Terraform Engine, for example:
VERSION=v0.4.0 && \ sudo apt install wget -y && \ sudo wget -O /usr/local/bin/tfengine https://github.com/GoogleCloudPlatform/healthcare-data-protection-suite/releases/download/${VERSION}/tfengine_${VERSION}_linux-amd64 && \ sudo chmod +x /usr/local/bin/tfengine
- Install Git, for example:
sudo apt-get install git
- Install the Google Cloud command line tool
- Duplicate the FDA MyStudies repository, then clone it locally
- Update
/deployment/deployment.hclwith the values for your deployment - Update
/deployment/scripts/set_env_var.shfor your deployment, then use the script to set your environment variables, for example:source set_env_var.sh # executed from your /deployment/scripts directory - Authenticate as a user with the permissions described above (this deployment assumes gcloud and Terraform commands are made as a user, rather than a service account)
- Login and update your application default credentials, for example you could run
gcloud auth login --update-adc(when using a Google Compute Engine VM you must update the application default credentials, otherwise requests will continue to be made with its default service account) - Remember to log your user account out once your deployment is complete
- Login and update your application default credentials, for example you could run
- Generate your Terraform configuration files
- Set the
enable_gcs_backendflag inmystudies.hcltofalse, for example:sed -e 's/enable_gcs_backend = true/enable_gcs_backend = false/g' \ -i.backup $GIT_ROOT/deployment/mystudies.hcl
- Execute the
tfenginecommand to generate the configs (by default, CICD will look for Terraform configs under thedeployment/terraform/directory in the GitHub repo, so set the--output_pathto point to thedeployment/terraform/directory inside the local root of your GitHub repository), for example:tfengine --config_path=$ENGINE_CONFIG --output_path=$GIT_ROOT/deployment/terraform
- Set the
- Use Terraform to create the
{PREFIX}-{ENV}-devopsproject and Terraform state bucket (if this step fails, confirm you have updated your application default credentials and that the required version of Terraform is installed), for example:cd $GIT_ROOT/deployment/terraform/devops terraform init && terraform apply
- Backup the state of your
{PREFIX}-{ENV}-devopsproject to the newly created state bucket by setting theenable_gcs_backendflag inmystudies.hcltotrueand regenerating the Terraform configs, for example:sed -e 's/enable_gcs_backend = false/enable_gcs_backend = true/g' \ -i.backup $GIT_ROOT/deployment/mystudies.hcl tfengine --config_path=$ENGINE_CONFIG --output_path=$GIT_ROOT/deployment/terraform cd $GIT_ROOT/deployment/terraform/devops terraform init -force-copy
- Open Cloud Build in your new
{PREFIX}-{ENV}-devopsproject and connect your cloned GitHub repository (skip adding triggers as Terraform will create them in the next step) - Create the CICD pipeline for your deployment (this will create the Cloud Builder triggers that will run whenever a pull request containing changes to files in
$GIT_ROOT/deployment/terraform/is raised against the GitHub branch that you specified indeployment.hcl), for example:cd $GIT_ROOT/deployment/terraform/cicd terraform init && terraform apply
-
Commit your local git working directory (which now represents your desired infrastructure state) to a new branch in your cloned FDA MyStudies repository, for example using:
cd $GIT_ROOT git checkout -b initial-deployment git add $GIT_ROOT/deployment/terraform git commit -m "Perform initial deployment" git push origin initial-deployment
-
Trigger Cloud Build to run the Terraform pre-submit checks by using this new branch to create a pull request against the branch you specified in
deployment.hcl(you can view the status of your pre-submit checks and re-run jobs as necessary in the Cloud Build history of yourdevopsproject) -
Once your pre-submit checks have completed successfully, and you have received code review approval, merge your pull request into the main branch to trigger the
terraform applypost-submit operation (this operation may take up to 45 minutes - you can view the status of the operation in the Cloud Build history of yourdevopsproject)Note: If your pre-submit checks or post-submit
terraform applyfail with an error related to billing accounts, you may not have the quota necessary to attach all of your projects to the specified billing account. You may need to request additional quota. -
Grant the
roles/ownerpermission to the{PREFIX}-{ENV}-project-owners@{DOMAIN}group for each of your newly created projects
- Determine the name servers that Cloud DNS has allocated to your
{PREFIX}-{ENV}subdomain- Navigate to DNS zones in your
{PREFIX}-{ENV}-appsproject - Click on the zone named
{PREFIX}-{ENV}, then clickRegistrar Setupin the upper right to view the name servers allocated to your subdomain
- Navigate to DNS zones in your
- Update your domain’s DNS settings with your domain registrar to create a delegated subzone with the name servers allocated by Cloud DNS (this process differs across domain registrars - consult your domain registrar’s documentation to determine how to make these changes, or ask your domain’s IT administrator for help)
- If your domain registrar is Google Domains, you can create the delegated subzone as follows:
- Log into Google Domains using the account that administers your domain
- Navigate to the DNS page for your domain and scroll down to the ‘custom resource records’ section (you do not need to make changes in the other sections)
- Create an NS resource record for your {PREFIX}-{ENV} subdomain that matches the name servers specified in Cloud DNS, for example:

- If your domain registrar is Google Domains, you can create the delegated subzone as follows:
- Verify your setup (it may take up to 48 hours for DNS changes to propagate across the internet)
- Create a Native mode Cloud Firestore database in your
{PREFIX}-{ENV}-firebaseproject (the location selected here does not need to match the region configured in yourdeployment.hclfile) - Use Terraform and CICD to create Firestore indexes, a Cloud SQL instance, user accounts and IAM role bindings
- Uncomment the blocks for steps 5.1 through 5.6 in
mystudies.hcl, for example:sed -e 's/#5# //g' -i.backup $GIT_ROOT/deployment/mystudies.hcl
- Regenerate the Terraform configs and commit the changes to your repo, for example:
cd $GIT_ROOT tfengine --config_path=$ENGINE_CONFIG --output_path=$GIT_ROOT/deployment/terraform git checkout -b database-configuration git add $GIT_ROOT/deployment/terraform git commit -m "Configure databases" git push origin database-configuration
- Once your pull request pre-submit checks have completed successfully, and you have received code review approval, merge your pull request to trigger
terraform apply(this may take up to 20 minutes - you can view the status of the operation in the Cloud Build history of yourdevopsproject)
- Uncomment the blocks for steps 5.1 through 5.6 in
- Configure the permissions of your SQL script bucket so that your Cloud SQL instance can import the necessary initialization scripts
- Uncomment the blocks for Steps 6 in
mystudies.hcl, for example:sed -e 's/#6# //g' -i.backup $GIT_ROOT/deployment/mystudies.hcl
- Regenerate the Terraform configs and commit the changes to your repo, for example:
cd $GIT_ROOT tfengine --config_path=$ENGINE_CONFIG --output_path=$GIT_ROOT/deployment/terraform git checkout -b sql-bucket-permissions git add $GIT_ROOT/deployment/terraform git commit -m "Set SQL bucket permissions" git push origin sql-bucket-permissions
- Once your pull request pre-submit checks have completed successfully, and you have received code review approval, merge your pull request to trigger
terraform apply(this may take up to 10 minutes - you can view the status of the operation in the Cloud Build history of yourdevopsproject)
- Uncomment the blocks for Steps 6 in
- Initialize your MySQL databases by importing SQL scripts
- Upload the necessary SQL script files to the
{PREFIX}-{ENV}-mystudies-sql-importstorage bucket that you created during Terraform deployment, for example:gsutil cp \ ${GIT_ROOT}/study-builder/sqlscript/* \ ${GIT_ROOT}/response-datastore/sqlscript/mystudies_response_server_db_script.sql \ ${GIT_ROOT}/participant-datastore/sqlscript/mystudies_app_info_update_db_script.sql \ ${GIT_ROOT}/participant-datastore/sqlscript/mystudies_participant_datastore_db_script.sql \ ${GIT_ROOT}/auth-server/sqlscript/mystudies_oauth_server_hydra_db_script.sql \ ${GIT_ROOT}/hydra/sqlscript/create_hydra_db_script.sql \ gs://${PREFIX}-${ENV}-mystudies-sql-import
- Import the SQL scripts from cloud storage to your Cloud SQL instance, for example:
gcloud sql import sql --project=${PREFIX}-${ENV}-data mystudies gs://${PREFIX}-${ENV}-mystudies-sql-import/create_hydra_db_script.sql -q gcloud sql import sql --project=${PREFIX}-${ENV}-data mystudies gs://${PREFIX}-${ENV}-mystudies-sql-import/mystudies_oauth_server_hydra_db_script.sql -q gcloud sql import sql --project=${PREFIX}-${ENV}-data mystudies gs://${PREFIX}-${ENV}-mystudies-sql-import/HPHC_My_Studies_DB_Create_Script.sql -q gcloud sql import sql --project=${PREFIX}-${ENV}-data mystudies gs://${PREFIX}-${ENV}-mystudies-sql-import/procedures.sql -q gcloud sql import sql --project=${PREFIX}-${ENV}-data mystudies gs://${PREFIX}-${ENV}-mystudies-sql-import/version_info_script.sql -q gcloud sql import sql --project=${PREFIX}-${ENV}-data mystudies gs://${PREFIX}-${ENV}-mystudies-sql-import/mystudies_response_server_db_script.sql -q gcloud sql import sql --project=${PREFIX}-${ENV}-data mystudies gs://${PREFIX}-${ENV}-mystudies-sql-import/mystudies_participant_datastore_db_script.sql -q
- Upload the necessary SQL script files to the
- Enable the Cloud SQL Admin API for your
{PREFIX}-{ENV}-appsproject, for example:gcloud config set project $PREFIX-$ENV-apps && \ gcloud services enable sqladmin.googleapis.com
-
Make a request to increase the Global Compute Engine API Backend Services quota for your
{PREFIX}-{ENV}-appsproject to 20 (if it is not already set at, or beyond, this value) -
Enable CICD for the application directories of your cloned GitHub repository so that changes you make to the application code will automatically build the application containers for your deployment
- Enable Cloud Build in your
{PREFIX}-{ENV}-appsproject and connect your cloned GitHub repository (skip adding triggers as Terraform will create them in the next step) - Uncomment the Cloud Build triggers portion of the apps project (step 7) in
mystudies.hcl, for example:sed -e 's/#7# //g' -i.backup $GIT_ROOT/deployment/mystudies.hcl
- Regenerate the Terraform configs and commit the changes to your repo, for example:
cd $GIT_ROOT tfengine --config_path=$ENGINE_CONFIG --output_path=$GIT_ROOT/deployment/terraform git checkout -b enable-apps-CICD git add $GIT_ROOT/deployment/terraform git commit -m "Enable CICD for applications" git push origin enable-apps-CICD
- Once your pull request pre-submit checks have completed successfully, and you have received code review approval, merge your pull request to trigger
terraform apply(this may take up to 10 minutes - you can view the status of the operation in the Cloud Build history of yourdevopsproject)
- Enable Cloud Build in your
-
Update the Kubernetes and application configuration files with the values specific to your deployment
- Replace the
<PREFIX>,<ENV>and<LOCATION>values for eachtf-deployment.yamlin your repo, for example:find $GIT_ROOT -name 'tf-deployment.yaml' \ -exec sed -e 's/<PREFIX>-<ENV>/'$PREFIX'-'$ENV'/g' \ -e 's/<LOCATION>/'$LOCATION'/g' -i.backup '{}' \;
- Replace the
<PREFIX>,<ENV>and<DOMAIN>values in/deployment/kubernetes/cert.yamland/deployment/kubernetes/ingress.yaml, for example:sed -e 's/<PREFIX>/'$PREFIX'/g' \ -e 's/<ENV>/'$ENV'/g' \ -e 's/<DOMAIN>/'$DOMAIN'/g' -i.backup \ $GIT_ROOT/deployment/kubernetes/cert.yaml sed -e 's/<PREFIX>/'$PREFIX'/g' \ -e 's/<ENV>/'$ENV'/g' \ -e 's/<DOMAIN>/'$DOMAIN'/g' -i.backup \ $GIT_ROOT/deployment/kubernetes/ingress.yaml
- In
/participant-manager/src/environments/environment.prod.ts, replace<BASE_URL>with yourparticipants.{PREFIX}-{ENV}.{DOMAIN}value and<auth-server-client-id>with the value of yourauto-auth-server-client-idsecret (you can find this value in the Secret Manager of your{PREFIX}-{ENV}-secretsproject), for example:gcloud config set project $PREFIX-$ENV-secrets export auth_server_client_id=$( \ gcloud secrets versions access latest --secret="auto-auth-server-client-id") sed -e 's/<BASE_URL>/participants.'$PREFIX'-'$ENV'.'$DOMAIN'/g' \ -e 's/<AUTH_SERVER_CLIENT_ID>/'$auth_server_client_id'/g' -i.backup \ $GIT_ROOT/participant-manager/src/environments/environment.prod.ts
- Commit the changes to your repo, for example:
cd $GIT_ROOT git checkout -b configure-application-properties git add $GIT_ROOT git commit -m "Initial configuration of application properties" git push origin configure-application-properties
- Once your pull request pre-submit checks have completed successfully, and you have received code review approval, merge your pull request to build your container images, after which they will be available in the Container Registry of your apps project at
http://gcr.io/{PREFIX}-{ENV}-apps(this may take up to 10 minutes - you can view the status of the operation in the Cloud Build history of your{PREFIX}-{ENV}-appsproject)
- Replace the
-
Open Secret Manager for your
{PREFIX}-{ENV}-secretsproject and fill in the values for secrets with the prefix “manual-” (or set yourgcloudproject withgcloud config set project $PREFIX-$ENV-secretsand use the commands described below - afterwards clear your shell history withhistory -c)Manually set secret Description When to set Example command manual-mystudies-email-addressThe login of the email account you want MyStudies to use to send system-generated emails Set this value now or enter a placeholder echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-mystudies-email-address" --data-file=-manual-mystudies-email-passwordThe password for that email account Set this value now or enter a placeholder echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-mystudies-email-password" --data-file=-manual-mystudies-contact-email-addressThe email address that the in-app contact and feedback forms will send messages to Set this value now or enter a placeholder echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-mystudies-contact-email-address" --data-file=-manual-mystudies-from-email-addressThe return email address that is shown is system-generated messages (for example, [email protected])Set this value now or enter a placeholder echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-mystudies-from-email-address" --data-file=-manual-mystudies-from-email-domainThe domain of the above email address (just the value after “@”) Set this value now or enter a placeholder echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-mystudies-from-email-domain" --data-file=-manual-mystudies-smtp-hostnameThe hostname for your email account’s SMTP server (for example, smtp.gmail.com)Set this value now or enter a placeholder echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-mystudies-smtp-hostname" --data-file=-manual-mystudies-smtp-use-ip-allowlistTypically ‘false’; if ‘true’, the platform will not authenticate to the email server and will rely on the allowlist configured in the SMTP service Set this value to trueorfalsenow (you can update it later)echo -n "false" | gcloud secrets versions add "manual-mystudies-smtp-use-ip-allowlist" --data-file=-manual-log-pathThe path to a directory within each application’s container where your logs will be written (for example /logs)Set this value now echo -n "/logs" | gcloud secrets versions add "manual-log-path" --data-file=-manual-org-nameThe name of your organization that is displayed to users, for example ‘Sincerely, the manual-org-namesupport team’Set this value now echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-org-name" --data-file=-manual-terms-urlURL for a terms and conditions page that the applications will link to (for example, https://example.com/terms)Set this value now or enter a placeholder echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-terms-url" --data-file=-manual-privacy-urlURL for a privacy policy page that the applications will link to (for example, https://example.com/privacy)Set this value now or enter a placeholder echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-privacy-url" --data-file=-manual-mobile-app-appidThe value of the App ID(15 characters max) that you will configure on the Settings page of the Study builder user interface when you create your first study (you will also use this same value when configuring your mobile applications for deployment)Set now if you know what value you will use when you create your first study - otherwise enter a placeholder and update once you have created a study in the Study builder echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-mobile-app-appid" --data-file=-manual-android-bundle-idThe value of applicationIdthat you will configure inAndroid/app/build.gradleduring Android configuration, for example{PREFIX}_{ENV}.{DOMAIN}(note that some characters are not permitted)If you know what value you will use during Android deployment you can set this now, otherwise enter a placeholder and update later (leave as placeholder if you will be deploying to iOS only) echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-android-bundle-id" --data-file=-manual-fcm-api-urlURL of your Firebase Cloud Messaging API (documentation) Set now if you know what this value will be - otherwise create a placeholder and update after completing your Android deployment (leave as placeholder if you will be deploying to iOS only) echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-fcm-api-url" --data-file=-manual-android-server-keyThe Firebase Cloud Messaging server key that you will obtain during Android configuration Set now if you know what this value will be - otherwise create a placeholder and update after completing your Android deployment (leave as placeholder if you will be deploying to iOS only) echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-android-server-key" --data-file=-manual-android-deeplink-urlThe URL to redirect to after Android login (for example, app://{PREFIX}-{ENV}.{DOMAIN}/mystudies)Set now if you know what this value will be - otherwise create a placeholder and update after completing your Android deployment (leave as placeholder if you will be deploying to iOS only) echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-android-deeplink-url" --data-file=-manual-ios-bundle-idThe value you will obtain from Xcode (Project target > General tab > Identity section > Bundle identifier) during iOS configuration - for a production application, the bundle ID needs to be verified with Apple and is usually a reverse domain name that you own; it is a unique app identifier and application capabilities are mapped to this value (details) Set now if you know what this value will be - otherwise create a placeholder and update after completing your iOS deployment (leave as placeholder if you will be deploying to Android only) echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-ios-bundle-id" --data-file=-manual-ios-certificateThe value of the Base64 converted .p12file that you will obtain during iOS configurationSet now if you know what this value will be - otherwise create a placeholder and update after completing your iOS deployment (leave as placeholder if you will be deploying to Android only) echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-ios-certificate" --data-file=-manual-ios-certificate-passwordThe value of the password for the .p12certificate (necessary if your certificate is encrypted - otherwise leave empty)Set now if you know what this value will be - otherwise create a placeholder and update after completing your iOS deployment (leave as placeholder if you will be deploying to Android only) echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-ios-certificate-password" --data-file=-manual-ios-deeplink-urlThe URL to redirect to after iOS login (for example, app://{PREFIX}-{ENV}.{DOMAIN}/mystudies)Set now if you know what this value will be - otherwise create a placeholder and update after completing your iOS deployment (leave as placeholder if you will be deploying to Android only) echo -n "<SECRET_VALUE>" | gcloud secrets versions add "manual-ios-deeplink-url" --data-file=-Note: When updating secrets after this initial deployment, you must refresh your Kubernetes cluster and restart the relevant pods to ensure the updated secrets are propagated to your applications (you do not need to do this now - only when making updates later), for example you can update your Kubernetes state with:
cd $GIT_ROOT/deployment/terraform/kubernetes terraform init && terraform apply
then, restart the pods by deleting them in the Kubernetes dashboard or running:
APP_PATH=<path_to_component_to_restart> # for example, $GIT_ROOT/auth-server kubectl scale --replicas=0 -f $APP_PATH/tf-deployment.yaml && \ kubectl scale --replicas=1 -f $APP_PATH/tf-deployment.yaml
If you rotate an application’s ‘client_id’ or ‘client_secret’, such as
auto-response-datastore-client-idorauto-response-datastore-secret-key, you must register the new values in Hydra by re-running theregister_clients_in_hydra.shscript or executing the appropriate REST requests directly (see/hydra/README.mdfor more information about working with Hydra manually) -
Finish Kubernetes cluster configuration and deployment
- Configure the remaining resources with Terraform, for example:
cd $GIT_ROOT/deployment/terraform/kubernetes/ terraform init && terraform apply
- Set your
kubectlcredentials, for example:gcloud container clusters get-credentials "$PREFIX-$ENV-gke-cluster" \ --region=$LOCATION --project="$PREFIX-$ENV-apps"
- Apply the pod security policies, for example:
kubectl apply \ -f $GIT_ROOT/deployment/kubernetes/pod_security_policy.yaml \ -f $GIT_ROOT/deployment/kubernetes/pod_security_policy-istio.yaml
- Apply all deployments, for example:
kubectl apply \ -f $GIT_ROOT/study-datastore/tf-deployment.yaml \ -f $GIT_ROOT/response-datastore/tf-deployment.yaml \ -f $GIT_ROOT/participant-datastore/consent-mgmt-module/tf-deployment.yaml \ -f $GIT_ROOT/participant-datastore/enroll-mgmt-module/tf-deployment.yaml \ -f $GIT_ROOT/participant-datastore/user-mgmt-module/tf-deployment.yaml \ -f $GIT_ROOT/study-builder/tf-deployment.yaml \ -f $GIT_ROOT/auth-server/tf-deployment.yaml \ -f $GIT_ROOT/participant-manager-datastore/tf-deployment.yaml \ -f $GIT_ROOT/hydra/tf-deployment.yaml \ -f $GIT_ROOT/participant-manager/tf-deployment.yaml
- Apply all services, for example:
kubectl apply \ -f $GIT_ROOT/study-datastore/tf-service.yaml \ -f $GIT_ROOT/response-datastore/tf-service.yaml \ -f $GIT_ROOT/participant-datastore/consent-mgmt-module/tf-service.yaml \ -f $GIT_ROOT/participant-datastore/enroll-mgmt-module/tf-service.yaml \ -f $GIT_ROOT/participant-datastore/user-mgmt-module/tf-service.yaml \ -f $GIT_ROOT/study-builder/tf-service.yaml \ -f $GIT_ROOT/auth-server/tf-service.yaml \ -f $GIT_ROOT/participant-manager-datastore/tf-service.yaml \ -f $GIT_ROOT/hydra/tf-service.yaml \ -f $GIT_ROOT/participant-manager/tf-service.yaml
- Apply the certificate and the ingress, for example:
kubectl apply \ -f $GIT_ROOT/deployment/kubernetes/cert.yaml \ -f $GIT_ROOT/deployment/kubernetes/ingress.yaml
- Update firewalls:
- Run
kubectl describe ingress $PREFIX-$ENV - Look at the suggested commands under "Events", in the form of "Firewall change required by network admin"
- Run each of the suggested commands
- Run
- Configure the remaining resources with Terraform, for example:
-
Verify the status of your Kubernetes cluster
- Check the Kubernetes ingress dashboard in your
{PREFIX}-{ENV}-appsproject to view the status of your cluster ingress (if status is not green, repeat the firewall step above) - Check the Kubernetes workloads dashboard in your
{PREFIX}-{ENV}-appsproject to view the status of your applications (confirm all applications are green before proceeding - it can take up to 15 minutes for all containers to become operational) - Check the status of your Kubernetes cluster SSL certificates on the certificates page of your
{PREFIX}-{ENV}-appsproject’s load balancing ‘advanced menu’ (both theparticipants.{PREFIX}-{ENV}.{DOMAIN}andstudies.{PREFIX}-{ENV}.{DOMAIN}certificates must be green for your deployment to usehttps)
- Check the Kubernetes ingress dashboard in your
-
Configure your initial application credentials
- Create the
Hydracredentials for server-to-server requests by runningregister_clients_in_hydra.sh, for example:$GIT_ROOT/deployment/scripts/register_clients_in_hydra.sh \ $PREFIX $ENV $DOMAIN
- Create your first admin user account for the
Participant managerapplication by running thecreate_participant_manager_superadmin.shscript to generate and import a SQL dump file for theParticipant datastoredatabase (the password you specify must be at least 8 characters long and contain lower case, upper case, numeric and special characters), for example:$GIT_ROOT/deployment/scripts/create_participant_manager_superadmin.sh \ $PREFIX $ENV <YOUR_DESIRED_LOGIN_EMAIL> <YOUR_DESIRED_PASSWORD>
- Create your first admin user account for the
Study builderapplication by running thecreate_study_builder_superadmin.shscript to generate and import a SQL dump file for theStudy datastoredatabase, for example:sudo apt-get install apache2-utils -y $GIT_ROOT/deployment/scripts/create_study_builder_superadmin.sh \ $PREFIX $ENV <YOUR_DESIRED_LOGIN_EMAIL> <YOUR_DESIRED_PASSWORD>
- Create the
- Navigate your browser to
studies.{PREFIX}-{ENV}.{DOMAIN}/studybuilder/(the trailing slash is necessary) and use the account credentials that you created with thecreate_study_builder_superadmin.shscript to log into theStudy builderuser interface - Change your password, then create any additional administrative accounts that you might need
- Create a new study with the
App IDthat you set in themanual-mobile-app-appidsecret, or choose a newApp IDthat you will updatemanual-mobile-app-appidwith - Publish your study to propagate your study values to the other platform components
- Navigate your browser to
participants.{PREFIX}-{ENV}.{DOMAIN}/participant-manager/(the trailing slash is necessary), then use the account credentials that you created with thecreate_participant_manager_superadmin.shscript to log into theParticipant manageruser interface (if theParticipant Managerapplication fails to load, confirm you are usinghttps- this deployment requireshttpsto be fully operational) - You will be asked to change your password; afterwards you can create any additional administrative accounts that you might need
- Confirm your new study is visible in the
Participant managerinterface
- Follow the instructions in either or both
AndroidandiOSdeployment guides (if you haven’t created a study yet, you can configure the mobile applications with theAPP_IDyou plan on using when you create your first study in theStudy builder) - Open Secret Manager in your
{PREFIX}-{ENV}-secretsproject and update the secrets you previously configured with placeholder values (you can skip this step if you already configured your secrets with the appropriate values - if you do update secret values, make sure to refresh your Kubernetes cluster and applications as described above)manual-mobile-app-appidis the value of theApp ID(15 characters max) that you configured, or will configure, on the Settings page of theStudy buildermanual-android-bundle-idis the value ofapplicationIdthat you configured inAndroid/app/build.gradle, for example{PREFIX}_{ENV}.{DOMAIN}(note that some characters are not permitted)manual-fcm-api-urlis the URL of your Firebase Cloud Messaging APImanual-android-server-keyis your Firebase Cloud Messaging server keymanual-android-deeplink-urlis the URL to redirect to after Android login (for example,app://{PREFIX}-{ENV}.{DOMAIN}/mystudies)manual-ios-bundle-idis the value you obtained from Xcode (in production use-cases, this bundle ID needs to be verified with Apple)manual-ios-certificateis the value of the Base64 converted.p12filemanual-ios-certificate-passwordis the value of the password for the.p12certificatemanual-ios-deeplink-urlis the URL to redirect to after iOS login
- Initialize your
Participant datastoredatabase to work with your mobile applications- Once a study with the
App IDcorresponding to themanual-mobile-app-appidsecret is created and published using theStudy builderuser interface, a corresponding app record will appear in theParticipant manageruser interface (if you created a study before all of your platform components were operational, you can reinitialize this process by using theStudy builderuser interface to pause and resume the study) - Once the
App IDappears inParticipant manager, run thedeployment/scripts/copy_app_info_to_sql.shscript to update the remaining databases, for example:$GIT_ROOT/deployment/scripts/copy_app_info_to_sql.sh $PREFIX $ENV
- Once a study with the
- Remove your user account from the groups you no longer need access to
- Revoke user access in your environment, for example:
gcloud auth revoke <user>@<domain> -q && \ gcloud auth application-default revoke -q
- Optionally, confirm no other users are logged in, for example:
gcloud auth list
Copyright 2020 Google LLC