Run
go get -u github.com/cloudflare/cfssl/cmd/cfssl
go get -u github.com/cloudflare/cfssl/cmd/cfssljson
Set the env variable with the ip of your server (same as in app.yml
):
export SERVER_IP=<Server static IP>
Copy the contents of create-certs.sh to your
Cloud Shell or local environment as create-certs.sh
and run it
with
bash create-certs.sh
Think of a unique storage bucket name (or just use your PROJECT_ID) and run
export GS_BUCKET=gs://<unique bucket name>
Create this bucket with:
gsutil mb $GS_BUCKET
Copy the certificates into the bucket:
gsutil cp cfssl/*.pem $GS_BUCKET
Modify the resource google_compute_instance
in server.tf
, adding a service_account
block:
resource "google_compute_instance" "workshop-server" {
...
service_account {
scopes = ["storage-ro"]
}
}
Add a new systemd unit to cloud-config.yaml
which will download the certificates from the bucket. Change <BUCKET_NAME>
to the one you have just created:
- name: cfssl-download.service
command: start
content: |
[Unit]
Description=Download the server certificates from storage bucket
Before=traefik.service
[Service]
Type=oneshot
ExecStartPre=/usr/bin/docker pull google/cloud-sdk:alpine
ExecStart=/bin/bash -c \
'/usr/bin/docker run --rm --name cfssl-lodwnload \
-v /etc/cfssl:/etc/cfssl \
google/cloud-sdk:alpine gsutil cp gs://<BUCKET_NAME>/{ca,server}* /etc/cfssl'
RemainAfterExit=true
StandardOutput=journal
Now you need to update traefik configuration to read the certificates:
ExecStart=/usr/bin/docker run --rm --name traefik \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /etc/cfssl:/etc/cfssl:ro \
-p 80:80 \
-p 443:443 \
-p 8080:8080 \
traefik \
--api --docker \
--entryPoints='Name:http Address::80 Redirect.EntryPoint:https' \
--entryPoints='Name:https Address::443 TLS:/etc/cfssl/server.pem,/etc/cfssl/server-key.pem CA:/etc/cfssl/ca.pem'
To open 443 port in firewall, change line ports = ["80"]
in server.tf
to ports = ["80", "443"]
resource "google_compute_firewall" "api" {
...
allow {
protocol = "tcp"
ports = ["80", "443"]
}
}
Add more more labels for the whoami
container start command in cloud-config.yaml
:
--label traefik.frontend.entryPoints=http,https \
--label traefik.frontend.redirect.entryPoint=https \
In order to apply the changes to our server, we will need to recreate it. To do so, we need to mark it to be destroyed on the next run:
terraform taint google_compute_instance.workshop-server
Now we can apply the the changes with terraform apply
First, we need to update our .gcloudignore
file to ignore the unnecessary certificates. To do so, add the following:
cfssl/*
!cfssl/*client*.pem
This configuration will make sure that only client.pem
and client-key.pem
are included in the code package.
Now, modify the app code in main.go
file to perform TLS Mutual Auth request to out TLS protected webserver:
- Add new import
"crypto/tls"
:
package main
import (
...
"crypto/tls"
...
)
- Create a custom http client:
var client = &http.Client{}
func init() {
cert, err := tls.LoadX509KeyPair("cfssl/client.pem", "cfssl/client-key.pem")
if err != nil {
log.Fatal(err)
}
client.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
Certificates: []tls.Certificate{cert},
},
}
}
- Replace default http client, with custom one inside a
demoHandler
function. To do so, replace:
rs, err := http.Get(hostEndpoint)
with
rs, err := client.Get(hostEndpoint)
Deploy the new app version with gcloud app deploy
.
Now, you can try to open
<STATIC PUBLIC IP>:80/whoami
- you will see a certificate error
<APP_URL>/demo
- you should see the same output as in previous level (btw, this may take some time to work, be patient)
If you have created a new GCP project for this workshop, you can delete the whole project with all the created resources.
gcloud projects delete $PROJECT_ID
In case you used an old GCP project and you want to delete workshop resources, use the following commands:
terraform destroy
gsutil rm -r gs://$GS_BUCKET
gcloud iam service-accounts delete terraform@${PROJECT_ID}.iam.gserviceaccount.com