Last active
March 30, 2019 05:04
-
-
Save maybe-joe/74bea754c37f616f1596da91b6c9c5bd to your computer and use it in GitHub Desktop.
This snippet of code downloads, decrypts, and decodes private keys and config that shouldn't be hard coded or stored in a repository.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package configuration | |
import ( | |
"bytes" | |
"cloud.google.com/go/storage" | |
"context" | |
"encoding/base64" | |
"golang.org/x/oauth2/google" | |
cloudkms "google.golang.org/api/cloudkms/v1" | |
) | |
// This snippet of code downloads, decrypts, and decodes private keys and config | |
// that shouldn't be hard coded or stored in a repository. | |
// | |
// I use this for things like keys for encrpyting session cookies or private config | |
// reguired to create a firebase admin client. | |
// | |
// I call this code in the root main func of the project. A draw back to this method | |
// is it increases the time taken to restart the server during development (for me this is every file save!). | |
// but the benefit is once the code is deployed revoking a compromised key only requires | |
// a server restart once the new key is uploaded. Also I can use env variables along | |
// with the container environment e.g. app engine to toggle pointing the service | |
// at development resources or production. | |
// | |
// | |
// The commands below use gcloud cli to encrpyt and store json files. | |
// | |
// base64 -i service-private-key.json -o service-private-key.txt | |
// | |
// gcloud kms encrypt \ | |
// --location=global \ | |
// --keyring=gcp-project-id \ | |
// --key=service-private-key \ | |
// --plaintext-file=service-private-key.txt \ | |
// --ciphertext-file=service-private-key.enc | |
// | |
// gsutil cp algolia.enc gs://gcp-project-id-config/ | |
func Config(projectID, bucketName, fileObjectName, keyRing, cryptoKey string) ([]byte, error) { | |
ctx := context.Background() | |
storageClient, err := storage.NewClient(ctx) | |
if err != nil { | |
return nil, err | |
} | |
bucket := storageClient.Bucket(bucketName) | |
fileObject := bucket.Object(fileObjectName) | |
reader, err := fileObject.NewReader(ctx) | |
if err != nil { | |
return nil, err | |
} | |
buffer := new(bytes.Buffer) | |
buffer.ReadFrom(reader) | |
reader.Close() | |
key := "projects/" + projectID + "/locations/global/keyRings/" + keyRing + "/cryptoKeys/" + cryptoKey | |
ciphertext := buffer.Bytes() | |
defaultClient, err := google.DefaultClient(ctx, cloudkms.CloudPlatformScope) | |
if err != nil { | |
return nil, err | |
} | |
cloudkmsService, err := cloudkms.New(defaultClient) | |
if err != nil { | |
return nil, err | |
} | |
req := &cloudkms.DecryptRequest{ | |
Ciphertext: base64.StdEncoding.EncodeToString(ciphertext), | |
} | |
response, err := cloudkmsService.Projects.Locations.KeyRings.CryptoKeys.Decrypt(key, req).Do() | |
if err != nil { | |
return nil, err | |
} | |
content, err := base64.StdEncoding.DecodeString(response.Plaintext) | |
if err != nil { | |
return nil, err | |
} | |
blob, err := base64.StdEncoding.DecodeString(string(content)) | |
if err != nil { | |
return nil, err | |
} | |
return blob, nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment