/google-sign-storage-url

Google Cloud Storage V4 signing storage url API

Primary LanguageGo

Sign Storage Url API

This is a micro service that implement the V4 signing process with Cloud Storage tools on Google Cloud Function. You don't need to write the signing process in you program. Just call this Sign Storage Url API after you deploy to google cloud function.

Before Start

Environment Variable

Environment Varibale Required Description
SERVICE_JSON_FILE required This is a key for signing storage. see [Get Signed Url Key](#Get Signed Url Key)
BUCKET_NAME optional Add the multiple buckets separated by colon : to your white lists or leave blank for all buckets.

Setup Google Cloud Project

Create a Google Cloud Project from here and set on terminal.

export ProjectID=<project_id>

# Set Project ID
gcloud config set project ${ProjectID}

Create Google Cloud Storage If Needed

You can change the storage location and default storage class.

export BucketName=<bucket_name>

# Create Bucket
gsutil mb -b on -c Standard -p ${ProjectID} -l asia gs://${BucketName}

Get Signed Url Key

After running the commands below, you will get the signed-url-key.json file under the current folder. You will need it on the next step.

# Create Service Account
gcloud iam service-accounts create "signed-url" --display-name "signed-url"

# Grant Service Account with storage object admin
gcloud projects add-iam-policy-binding ${ProjectID} \
  --member serviceAccount:signed-url@${ProjectID}.iam.gserviceaccount.com \
  --role roles/storage.objectAdmin

# Create Key
gcloud iam service-accounts keys create signed-url-key.json --iam-account signed-url@${ProjectID}.iam.gserviceaccount.com

Deploy to Google cloud Function

Varibale Required Description
bucket required The bucket you want to access. You are able to skip this variable if there is only one bucket name in BUCKET_NAME.
method required What action you want to process.
object required The file name you want to access.
time optional How much time (minute) the sign url is valid. 15 minutes is default value.

Allow All Storage Bucket

gcloud functions deploy sign --entry-point=SignedUrl --runtime=go111 --trigger-http --quiet \
  --set-env-vars SERVICE_JSON_FILE=signed-url-key.json

Testing

You can get the signed url from running the following command

curl -k -X POST -F "bucket=<bucket-name>" -F "method=POST" -F "object=hello.txt" https://<gcloud-function-url>/sign

Add the optional time:

curl -k -X POST -F "bucket=<bucket-name>" -F "method=POST" -F "object=hello.txt" -F "time=30" https://<gcloud-function-url>/sign

Limit Multiple Storage Bucket

If you want to contraint which bucket is allowed to access, adding the BUCKET_NAME variable spliting each bucket with colon :

# multiple buckets
gcloud functions deploy sign --entry-point=SignedUrl --runtime=go111 --trigger-http --quiet \
  --set-env-vars SERVICE_JSON_FILE=signed-url-key.json,BUCKET_NAME=<bucket-name1>:<bucket-name2>

Testing

You can get the signed url from running the following command

curl -k -X POST -F "bucket=<bucket-name>" -F "method=POST" -F "object=hello.txt" https://<gcloud-function-url>/sign

Limit Single Storage Bucket

gcloud functions deploy sign --source=src --entry-point=SignedUrl --runtime=go113 --trigger-http --quiet \
  --set-env-vars SERVICE_JSON_FILE=signed-url-key.json,BUCKET_NAME=<bucket-name1>

Testing

You can ignore bucket form data if you depoly a single storage bucket

curl -k -X POST -F "method=POST" -F "object=hello.txt" https://<gcloud-function-url>/sign

Create CI/CD Deploy Key (Optional)

This key can be used in CI/CD.

Grant the Required permission:

  • roles/iam.serviceAccountUser: Can act as the service account to start a Google Cloud Function.
  • roles/cloudfunctions.developer: Deploy to Google Cloud Function
  • roles/storage.admin: Create or delete a storage, and sign the storage url
# Create Service Account
gcloud iam service-accounts create "deploy-app" --display-name "deploy-app"

# Grant Service Account with cloud functions developer for deploy
gcloud projects add-iam-policy-binding ${ProjectID} \
  --member serviceAccount:deploy-app@${ProjectID}.iam.gserviceaccount.com \
  --role roles/iam.serviceAccountUser
gcloud projects add-iam-policy-binding ${ProjectID} \
  --member serviceAccount:deploy-app@${ProjectID}.iam.gserviceaccount.com \
  --role roles/cloudfunctions.developer
gcloud projects add-iam-policy-binding ${ProjectID} \
  --member serviceAccount:deploy-app@${ProjectID}.iam.gserviceaccount.com \
  --role roles/storage.admin

# Create Key
gcloud iam service-accounts keys create deploy-key.json --iam-account deploy-app@${ProjectID}.iam.gserviceaccount.com

Import As Package

import "github.com/akiirobot/sign-storage-url/src/sign"

url, err := sign.Sign(serviceAccount, whiteListBucket, objectName, method, bucket, timeStamp)
if err != nil {
  log.Fatalln(err)
  http.Error(w, "403 - Status Forbidden - " + err.Error(), http.StatusForbidden)
}