How to Store the PIN Code in the Google Cloud Storage?

X-Road Autologin utility can be used to automatically enter the PIN code after xroad-signer has started. The utility can be used to automate entering the PIN code after rebooting the host server. This article explains how the PIN code can be securely stored in the Google Cloud Storage so that the Autologin utility is able to read it from there.

Google Cloud Storage is unified object storage to store data in Google's cloud. Google Cloud Storage always encrypts data both in transit and at rest. In this case Cloud Storage is used to provide a secure storage to the PIN code. For additional security, customer-managed or customer-supplied encryption key can be used to encrypt the PIN code at rest.

More information about the Google Cloud Storage can be found at: https://cloud.google.com/storage/

Accessing the Data

Google Cloud Storage can be accessed in multiple ways: web portal, gsutil, Deployment Manager Templates and programming language specific libraries. Below there's an example how to access an existing file using bash.

Get object "file.txt" from bucket "niis-bucket"
# Step 1: Fetch an access token from an instance that has an associated service account      

$ curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" -H "Metadata-Flavor: Google"

{
  "access_token": "...",
  "expires_in": 3057,
  "token_type": "Bearer"
}

# Step 2: Pass the access token received from the previous HTTP GET call to the Google API
# Note that "niis-bucket" is the name of the Cloud Storage bucket and "file.txt" is the name of the object containing the secret

$ curl -H "Authorization: Bearer <ACCESS_TOKEN>" "https://www.googleapis.com/storage/v1/b/niis-bucket/o/file.txt?alt=media"

MySecret

The example above to work the virtual machine on which the commands are run must have a service account, and the service account must have a permission to read the Cloud Storage object containing the secret. If the bucket uses fine-grained access control, the service account must have READER permissions assigned for the object containing the secret. Instead, if the bucket uses uniform access control, the service account must have objectViewer (roles/storage.objectViewer) IAM role assigned for the bucket storing the object containing the secret. Main difference between the two access control modes is that fine-grained mode supports access control on both bucket and object-level, and uniform mode supports access control on bucket-level only.

Before running the commands above the following steps must be completed:

  1. Create a virtual machine with a user-managed service account.
  2. Create a Cloud Storage bucket.
    1. Select access control mode (fine-grained / uniform) based on your requirements.
    2. Based on the security requirements, select Google-managed (default) or customer-managed encryption key.
      1. In case a customer-managed encryption key is used, the key ring containing the key must be located in the same location (region / multi-region) where the Cloud Storage bucket is located.
  3. Create a new file on your workstation, store a secret in the file and upload the file to the Cloud Storage bucket.
  4. Give the service account access to the whole bucket (objectViewer role) OR the object containing the secret (READER permissions).
    1. It is highly recommended to remove any additional and/or default permissions (legacy roles) from the bucket that are not needed, e.g. project editor, project viewer.

Once the steps 1-4 have been completed, the script below can be used for testing. The script requires two arguments:  1) Bucket name (BUCKET_NAME) and 2) the name of the object containing the secret (OBJECT_NAME). If the name of the Key Vault is "niis-bucket" and the name of the secret is "file.txt", the script is executed like this:

$ ./test.sh niis-bucket file.txt

./test.sh <KEY_VAULT_NAME> <SECRET_NAME>
#!/bin/bash
TOKEN=$(curl --silent "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" -H "Metadata-Flavor: Google" | jq -r '.access_token')
PIN_CODE=$(curl --silent -H "Authorization: Bearer $TOKEN" "https://www.googleapis.com/storage/v1/b/<BUCKET_NAME>/o/<OBJECT_NAME>?alt=media")
echo "${PIN_CODE}"
exit 0

Storing Security Server PIN Code in Cloud Storage

Security Server PIN code can be stored in Cloud Storage. In that case a custom bash script (/usr/share/xroad/autologin/custom-fetch-pin.sh) must be implemented according to the auto-login documentation. The script must fetch the PIN code from Cloud Storage and output the PIN code to stdout. Curl and jq must be installed on the host server. The host server must have a service account that has sufficient permissions to read the Cloud Storage object storing the PIN code.

Curl and jq must be installed on the host server.

The host server must have a service account that has sufficient permissions to read the Cloud Storage object storing the PIN code.


/usr/share/xroad/autologin/custom-fetch-pin.sh
#!/bin/bash
TOKEN=$(curl --silent "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" -H "Metadata-Flavor: Google" | jq -r '.access_token')
PIN_CODE=$(curl --silent -H "Authorization: Bearer $TOKEN" "https://www.googleapis.com/storage/v1/b/<BUCKET_NAME>/o/<OBJECT_NAME>?alt=media")
echo "${PIN_CODE}"
exit 0