Skip to content

Latest commit

 

History

History
379 lines (253 loc) · 10.6 KB

01-gcp.md

File metadata and controls

379 lines (253 loc) · 10.6 KB

Google Cloud Platform Setup

We chosen to put the project in GCP because they handle security, backup, auto scaling and many things that are expensive to do by ourselves.

We need several things in order to make the project work and maintainable:

  • a VPC network, in order to build a private network for our application, without any public IP

  • a Cloud SQL, that will store data of the application

  • a Bastion, in order to connect to the Cloud SQL from home (to access or migrate it)

  • an App Engine, which will expose the app outside

  • Cloud Function to receive webhook from twilio (sms status/response)

  • Cloud Tasks queues to do flow control between twilio webhook and the app engine

Do not mess up with any of the fields, especially the "locations" (europe-west1 here) as Google do not allow to update an app engine instance once it has been created. Yeah, you can have many Compute Engine instances, many Cloud SQL instances, but only one f*cking App Engine instance that is not modifiable.

Make sure the application is working locally

You will find some help in the CONTRIBUTING and in the development setup.

Creating a new Google Cloud Platform project

  1. Go to https://console.cloud.google.com

  2. Click on "Select a project"

  3. Click on "New Project"

  4. Choose a name for the project and click "Create"

  5. Select the new project in the "Select a project" menu

Creating a VPC network

  1. Click on the Menu, and then "VCP Network" in the Networking part.

  2. Click "Create VPC Network"

  3. Configure your VPC with the following parameters:


  4. Open your VPC network in order to set firewall rules:

  5. Click on "Firewall rules"

  6. Click "Add firewall rule"

  7. Add the "ingress" firewall rule

  8. Click "Add firewall rule"

  9. Add the "egress" firewall rule

  10. Go to https://console.cloud.google.com/marketplace/details/google/vpcaccess.googleapis.com?project=covid-fight-redcall&folder=&organizationId= and enable the Serverless VPC Access API

  11. Go to "Serverless VPC Connector" and "Create Connector"

  12. Fill up the form, keep the VPC connector name, it will be used in configuration

Creating a Bastion

  1. Click on the menu, then "Compute Engine" in Compute category, then "VM instances".

  2. Click "Create"

  3. Set-up the compute engine as follow, taking care of the red parts, and click on "Management, Security, Disks...".

  4. On Management tab, make sure "On host maintenance" is set to "Migrate VM Instance"

  5. On Security tab, check "Turn on Secure Boot"

  6. On Network tab, select the VPC created earlier and click "Done"

Creating a Cloud SQL instance

  1. In the Menu, choose "SQL" under "Storage" category.

  2. Click "Create instance"

  3. Click "MySQL"

  4. Enter your db information and press Create. Care about the "Region".

  5. Click on your Cloud SQL instance

  6. Go to "Connections" tab

  7. Choose "Private IP" (accept when you will be prompted to enable Network API) and select your network, press Save.

  8. Go to the "Databases" tab

  9. Click "Create database"

  10. Add your database information.

  11. Click on "Users" tab

  12. Click on "Add user"

  13. Create your new user. Keep those credentials safe, you'll need them soon.

  14. Go back to "Overview"

  15. Look up for your private IP address and set it in your dotenv (deploy/<your project>/dotenv), in the " DATABASE_HOST" variable.

Creating an App Engine instance

  1. Go to the Menu, then "App Engine" in the "Compute" category, then "Dashboard"

  2. Click "Create Application"

  3. Choose the same zone as you chosen in your VPC network

  4. Select PHP and Standard

  5. Click "I'll do it later" at the bottom left

Creating a Google Service Account

In order to write logs, our application requires a google service account.

  1. Go to the Menu, then "IAM & Admin", then "Service Accounts"

  2. Click "Create Service account"

  3. Enter your service account details (they don't really matter)

  4. Add the "Logs Writer" permission

  5. Click "Create Key"

  6. Choose the JSON format and press "Create"

  7. You will download a JSON file. Place it in deploy/<your project>/google-service-account.json

Creating a Custom Domain

In order to reach out the application from a custom domain name, we should configure it.

  1. Go to the Menu, then "App Engine" in "Compute" category, then "Settings"

  2. Click on "Custom domain" tab

  3. Click "Add a custom domain" and follow the verification process

  4. Remove the extra "www." if you are using a subdomain and press "Save mappings"

  5. Save the Google DNS zones into your domain name configuration

  6. The format should look like this in your registrar

Enable Text To Speech API

If you want to enable voice calls, you need to enable the Text To Speech API.

  1. In the menu, go to "Marketplace" under "Product"

  2. Search for "Text To Speech"

  3. Click on Google Text To Speech

  4. Click "Enable" button

Create a Cloud Storage bucket

Voice calls generate several files that are exposed on Google Storage in order to limit the number of hits on the app.

  1. In the menu, go to Storage under the "Storage" category, and click "Browse".

  2. Click "Create new bucket"

  3. Select a name for the bucket

  4. Select "Multi Region" and "Europe"

  5. Choose "Standard" storage class

  6. Select "Uniform" access control

  7. Set a retention policy of 1 day (it's 7 on the screenshot, but don't mind, put 1, at that time I've mixed up with deletion rule)

  8. In the menu, got o "IAM & Admin" on Product section, and go to "IAM"

  9. Find the service account created for the RedCall app, and click "Edit"

  10. Add Storage Object Admin role and click "Save" (note: screenshot is outdated)

  11. We now need to configure objects auto deletion: go back to the "Storage" section

  12. Click on the bucket you've just created to open it

  13. Click on "Bucket Lock" tab

  14. Click on "Add lifecycle rule"

  15. Tick "Age" and put 7 days

  16. Tick "Delete"

  17. Save

Create Cloud Task queues

In order to delegate sending messages a secure way (with retry, rate limits etc), we need several Cloud Task queues:

Warning: do not copy/paste, the first command will prompt you to enable the API.

# We send 10 sms/second
gcloud tasks queues create messages-sms
gcloud tasks queues update messages-sms \
    --max-dispatches-per-second=10 \
    --max-concurrent-dispatches=30 \
    --max-attempts=100 \
    --min-backoff=1s \
    --max-backoff=5s

# We send 5 calls/second (warning: Twilio's default is 1, check your Twilio Voice API CPS)
gcloud tasks queues create messages-call
gcloud tasks queues update messages-call \
    --max-dispatches-per-second=5 \
    --max-concurrent-dispatches=30 \
    --max-attempts=100 \
    --min-backoff=1s \
    --max-backoff=5s

# We can send up to 600 emails/second but don't want to destroy the instance
gcloud tasks queues create messages-email
gcloud tasks queues update messages-email \
    --max-dispatches-per-second=500 \
    --max-concurrent-dispatches=30 \
    --max-attempts=100 \
    --min-backoff=1s \
    --max-backoff=5s

Check the App\Queues class for the full list of queues used by the app.

You now need to add few permissions in your service account.

  1. In the menu, got o "IAM & Admin" on Product section, and go to "IAM"

  2. Find your app service account, and click "Edit"

  3. Add "Cloud Tasks Enqueuer" and "App Engine Viewer" roles, the second one lets the app use an App Engine handler for the tasks.

If you don't want to use GCP, you can set another processor in config/services.yaml, see in src/Communication/Processor to see the list of available processors.


Create Cloud Functions & Task queues to handle twilio webhook

Add the following variables in your .env:

GCP_QUEUE_WEBHOOK_RESPONSE='webhook-sms-responses'
GCP_QUEUE_WEBHOOK_STATUS='webhook-sms-status'
GCP_FUNCTION_TWILIO_STATUS=webHooksToTasksSMSStatus
GCP_FUNCTION_TWILIO_RESPONSE=webHooksToTasksSMSResponse

Run gcp/deploy/init/init_api.sh once per environment.

This will perform the following :

  • Enable required APIs
  • create a service account and set the appropriate right to run the cloud functions
  • create the cloud tasks queues

Then run gcp/deploy/deploy.sh to deploy the cloud functions

This will perform the following :

  • create a temporary directory and copy the sources of the cloud function in it
  • update the code with the cloud function name 'webHooksToTasksSMSStatus'
  • deploy
  • rename again the cloud function name to 'webHooksToTasksSMSResponse'

This creates two endpoint for webhooks that will post on different queues depending it's a SMS status or SMS response from twilio

To run a test (using curl), you can run gcp/test/cloudFunctions/twilioWebhooks/sendPost.sh This will post sample message with headers to the cloud functions, that should forward this to the AppEngine via Cloud Tasks

Go back