Skip to content

Production checklist for the Isomer team

Preston Lim edited this page Dec 2, 2019 · 38 revisions

Checklist for Isomer websites

Netlify Performance

Remember to enable asset optimization. This allows Netlify to minify and compress our JS and CSS files, as well as images.

Netlify Cache Purge

Add the following outgoing webhook to the Netlify production site. This allows Netlify to inform and purge the KeyCDN cache when the production site has been deployed successfully.

https://<KEYCDN_API_KEY>@api.keycdn.com/zones/purge/<KEYCDN_ZONE_ID>.json

Netlify Security

Ensure that there is a netlify.toml file in the root folder of the GitHub repository with the following HTTP security header configuration:

[[headers]]
  for = "/*"
  [headers.values]
    X-XSS-Protection = "1; mode=block"
    Referrer-Policy = "no-referrer"
    X-Content-Type-Options = "nosniff"
    X-Frame-Options = "deny"
    Content-Security-Policy = "default-src 'self'; script-src 'self' https://assets.dcube.cloud https://*.wogaa.sg https://assets.adobedtm.com https://www.google-analytics.com https://cdnjs.cloudflare.com https://va.ecitizen.gov.sg https://*.cloudfront.net https://printjs-4de6.kxcdn.com https://unpkg.com https://wogadobeanalytics.sc.omtrdc.net 'unsafe-eval'; object-src 'self'; style-src 'self' https://fonts.googleapis.com/ https://*.cloudfront.net https://va.ecitizen.gov.sg https://*.wogaa.sg https://cdnjs.cloudflare.com https://datagovsg.github.io 'unsafe-inline'; img-src *; media-src *; frame-src https://wogaa.demdex.net/ https://*.youtube.com https://*.youtube-nocookie.com https://*.vimeo.com; frame-ancestors 'none'; font-src * data:; connect-src 'self' https://dpm.demdex.net https://www.google-analytics.com https://stats.g.doubleclick.net https://*.wogaa.sg https://va.ecitizen.gov.sg https://ifaqs.flexanswer.com https://*.cloudfront.net https://fonts.googleapis.com https://cdnjs.cloudflare.com https://wogadobeanalytics.sc.omtrdc.net; report-uri https://www.infocommsociety.com/~yicheng/csp-report/"

How to test

Test the HTTP security configuration here: https://securityheaders.com/


KeyCDN - Zone

Enforce HTTPS

To ensure that users are served our site pages over HTTPS only, set the following configuration on the KeyCDN console:

Force SSL: Enabled

Custom SSL

To ensure that users are served our site pages over HTTPS only, set the following configuration on the KeyCDN console. Additionally, add the correct Custom SSL Private Key and Custom SSL Certificate into the console.

SSL: Custom

Query String

To prevent query string caching behavior on the netlify site (this disrupts our search), set the following configuration on the KeyCDN console:

Ignore Query String: Disabled

Canonical Header

To prevent an attacker from discovering the Netlify origin server, set the following configuration on the KeyCDN console:

Canonical Header: Disabled

How to test

Test it by checking that the link rel canonical header is not present among the HTTP headers

E.g.

> curl -I https://www.tech.gov.sg

Max Expiry

To make KeyCDN cache the page content for at most 5 mins. This ensures that website contents are updated within 5-10 mins of deployment.

Max Expiry controls the duration of time that KeyCDN caches a piece of content before it goes back to the origin server to retrieve that content.

Max Expiry: 5

KeyCDN - Zonealias

KeyCDN requires a Zone to be set up, as well as a Zonealias record. Remember to set up the Zonealias to allow KeyCDN to display the website to users.

How to test

Test it by setting your local DNS to the to-be-used domain and verify that you can view the site on your browser.

You can make your testing process in this step easier by using the local-cname package.


Creating a Certificate Signing Request (CSR)

Before a government agency user can purchase an SSL certificate, the Isomer team needs to generate a CSR and a private key.

To do so, we use OpenSSL. First, download OpenSSL (for Mac) using the following command:

brew install openssl

Next, generate the CSR and private key:

openssl req -new -newkey rsa:2048 -nodes -keyout <site.gov.sg>.key -out <site.gov.sg>.csr -sha256

If you already have an existing private key, you can use it as an input to generate the CSR:

openssl req -new -key <path to key>.key -out <site.gov.sg>.csr -sha256

Fill up the CSR in the following way:

Country Name (2 letter code) []:SG
State or Province Name (full name) []:Singapore
Locality Name (eg, city) []:Singapore
Organization Name (eg, company) []:< your organization name, for e.g. Prime Minister's Office Strategy Group>
Organizational Unit Name (eg, section) []: ITD
Common Name (eg, fully qualified host name) []:< {agency}.gov.sg for example, csf.gov.sg >
Email Address []:< email of contact person at agency, for example, [email protected] >

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:<leave blank>

Finally, save the CSR and private key into the Isomer Admin Vault of 1Password. Send the CSR to the government agency user.


Creating a CSR for multi-domain SSL certs

Create a file called multisan.conf with the following contents:

[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
default_keyfile = < your fully qualified host name followed by .key, {agency}.gov.sg.key, or for example, csf.gov.sg.key >
prompt = no

[req_distinguished_name]
C = SG
ST = Singapore
L = Singapore
O = < your organization name, for e.g. Prime Minister's Office Strategy Group>
OU = ITD
CN = < your fully qualified host name: {agency}.gov.sg, for example, csf.gov.sg >

[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = < your alternative domains >
DNS.2 = < your alternative domains >
DNS.3 = < your alternative domains >

Then, you run the following command in the same directory:

openssl req -new -nodes -out {agency.gov.sg}.csr -sha256 -config multisan.conf

NGINX Redirection Server

Please refer to the Isomer redirection repo for details.


Travis Tests

We have set up some tests on Travis - specifically, the Isomer Checker tests and Lighthouse tests for accessibility.

Initial Setup

In order for the script to work, the package @isomerpages/isomerpages-travisci-scripts must be installed from npm first. In the root directory of the repo, run:

npm init
npm install @isomerpages/isomerpages-travisci-scripts

.travis.yml

Add the following .travis.yml file into the site repo

#.travis.yml
git:
  depth: 3

matrix:
  include:
    - language: ruby
      dist: trusty
      script:
        - bundle exec jekyll build
      cache: bundler

    - language: node_js
      dist: trusty
      node_js: "node"
      script: node travis-script.js
      cache: npm
      addons:
        chrome: stable

travis-script.js

Add the following travis-script.js file into the root folder of the repo:

//travis-script.js
const travisScript = require("@isomerpages/isomerpages-travisci-scripts");
const travisBranch = process.env.TRAVIS_BRANCH;

if(travisBranch == "master") {
  travisScript.runAll();
}
else {
  travisScript.testsOnly();
}

Travis Console Configuration

Go to the specific repo settings in Travis. Set the following Travis environmental variables.

  • KEYCDN_API_KEY - obtained from 1Password's isomer admin vault. Hide this value in the Travis logs
  • KEYCDN_ZONE_ID - obtained from KeyCDN's Zone ID. Display this value in the Travis logs
  • NETLIFY_ACCESS_TOKEN - obtained from 1Password's isomer admin vault. Hide this value in the Travis logs
  • NETLIFY_SITE_ID - obtained from Netlify's site information >> API ID. Display this value in the Travis logs
  • SLACK_URI - the Slack webhook URL for error messages, obtained from https://api.slack.com/. Hide this value in the Travis logs
  • SLACK_ALERT_URI - same process as SLACK_URI, but for the #alerts channel. Hide this value in the Travis logs
  • PROD_URL - the full URL of the production site, e.g. https://www.isomer.gov.sg/. This will the target of the Lighthouse tests. Display this value in the Travis logs
  • STAGING_URL - the full URL of the staging site, e.g. https://isomer-techgovsg-staging.netlify.com/. This will be the target of the Lighthouse tests. Display this value in the Travis logs

Set up cron jobs for Travis to run a build for the master and staging branches automatically weekly (the setting can be found below the environmental variables section). Set Options to Always run.


Isomer Accessibility

Check that the color contrast in the website (foreground: #FFFFFF, background: all the colors on the site) is greater than 4.5. This is to ensure that isomer fulfills the WCAG AA standard for color contrast.

How to test

Test it by checking that all color combinations in the custom.scss file pass the min. color contrast here: https://webaim.org/resources/contrastchecker/


Site Configuration

In _config.yml in the root directory, make sure the following configuration are set to their proper values:

  • url - set this to the base url of the website, e.g. https://www.site.gov.sg
  • resources_name - set this to the name of the resource room folder
  • feedback_form_url - set this to the form.sg feedback from URL
  • exclude: [travis-script.js, .travis.yml, README.md, package.json, package-lock.json, node_modules, vendor/bundle/, vendor/cache/, vendor/gems/, vendor/ruby/, Gemfile, Gemfile.lock] - this ensures that files that are used for the build do not appear on the live site. Unfortunately, child sites do not inherit this configuration from our parent theme
  • title, title-abbreviated, email, description - self explanatory, consult the agency for the details if needed

In homepage.yml under the _data folder, make sure the following configuration are set:

  • favicon - relative path to the favicon image file in .ico format
  • shareicon - relative path to the image to appear on all pages when shared via WhatsApp, Facebook, etc. This image must be in .png format and of size 600px by 600px
  • agency-logo - relative path to the agency logo to be placed at the navbar
  • show-reach - set to true if the agency wants a link to REACH at the footer in compliance with DSS. Omit this option or set to false to remove the link

Final Cleanups

  • Remember to update the production URL on the GitHub repository description
  • Create a Slack channel for the site. Even if the agency is not using Slack, it can be a good idea to create a channel for the site so that we are alerted when issues arise
  • Remember to enable branch protection for master