1--- 2title: "Secrets" 3date: 2019-03-21T17:42:18-07:00 4lastmod: 2019-07-29T12:00:00-07:00 5showInSidenav: true 6toc: true 7--- 8 9The [`secrets` package][] provides access to key management services in a 10portable way. This guide shows how to work with secrets in the Go CDK. 11 12<!--more--> 13 14Cloud applications frequently need to store sensitive information like web 15API credentials or encryption keys in a medium that is not fully secure. For 16example, an application that interacts with GitHub needs to store its OAuth2 17client secret and use it when obtaining end-user credentials. If this 18information was compromised, it could allow someone else to impersonate the 19application. In order to keep such information secret and secure, you can 20encrypt the data, but then you need to worry about rotating the encryption 21keys and distributing them securely to all of your application servers. 22Most Cloud providers include a key management service to perform these tasks, 23usually with hardware-level security and audit logging. 24 25The [`secrets` package][] supports encryption and decryption operations. 26 27Subpackages contain driver implementations of secrets for various services, 28including Cloud and on-prem solutions. You can develop your application 29locally using [`localsecrets`][], then deploy it to multiple Cloud providers with 30minimal initialization reconfiguration. 31 32[`secrets` package]: https://godoc.org/gocloud.dev/secrets 33[`localsecrets`]: https://godoc.org/gocloud.dev/secrets/localsecrets 34 35## Opening a SecretsKeeper {#opening} 36 37The first step in working with your secrets is 38to instantiate a portable [`*secrets.Keeper`][] for your service. 39 40The easiest way to do so is to use [`secrets.OpenKeeper`][] and a service-specific 41URL pointing to the keeper, making sure you ["blank import"][] the driver 42package to link it in. 43 44```go 45import ( 46 "gocloud.dev/secrets" 47 _ "gocloud.dev/secrets/<driver>" 48) 49... 50keeper, err := secrets.OpenKeeper(context.Background(), "<driver-url>") 51if err != nil { 52 return fmt.Errorf("could not open keeper: %v", err) 53} 54defer keeper.Close() 55// keeper is a *secrets.Keeper; see usage below 56... 57``` 58 59See [Concepts: URLs][] for general background and the [guide below][] 60for URL usage for each supported service. 61 62Alternatively, if you need 63fine-grained control over the connection settings, you can call the constructor 64function in the driver package directly (like `awskms.OpenKeeper`). 65 66```go 67import "gocloud.dev/secrets/<driver>" 68... 69keeper, err := <driver>.OpenKeeper(...) 70... 71``` 72 73You may find the [`wire` package][] useful for managing your initialization code 74when switching between different backing services. 75 76See the [guide below][] for constructor usage for each supported service. 77 78[`*secrets.Keeper`]: https://godoc.org/gocloud.dev/secrets#Keeper 79[`secrets.OpenKeeper`]: 80https://godoc.org/gocloud.dev/secrets#OpenKeeper 81["blank import"]: https://golang.org/doc/effective_go.html#blank_import 82[Concepts: URLs]: {{< ref "/concepts/urls.md" >}} 83[guide below]: {{< ref "#services" >}} 84[`wire` package]: http://github.com/google/wire 85 86## Using a SecretsKeeper {#using} 87 88Once you have [opened a secrets keeper][] for the secrets provider you want, 89you can encrypt and decrypt small messages using the keeper. 90 91[opened a secrets keeper]: {{< ref "#opening" >}} 92 93### Encrypting Data {#encrypt} 94 95To encrypt data with a keeper, you call `Encrypt` with the byte slice you 96want to encrypt. 97 98{{< goexample src="gocloud.dev/secrets.ExampleKeeper_Encrypt" imports="0" >}} 99 100### Decrypting Data {#decrypt} 101 102To decrypt data with a keeper, you call `Decrypt` with the byte slice you 103want to decrypt. This should be data that you obtained from a previous call 104to `Encrypt` with a keeper that uses the same secret material (e.g. two AWS 105KMS keepers created with the same customer master key ID). The `Decrypt` 106method will return an error if the input data is corrupted. 107 108{{< goexample src="gocloud.dev/secrets.ExampleKeeper_Decrypt" imports="0" >}} 109 110### Large Messages {#large-messages} 111 112The secrets keeper API is designed to work with small messages (i.e. <10 KiB 113in length.) Cloud key management services are high latency; using them for 114encrypting or decrypting large amounts of data is prohibitively slow (and in 115some providers not permitted). If you need your application to encrypt or 116decrypt large amounts of data, you should: 117 1181. Generate a key for the encryption algorithm (16KiB chunks with 119 [`secretbox`][] is a reasonable approach). 1202. Encrypt the key with secret keeper. 1213. Store the encrypted key somewhere accessible to the application. 122 123When your application needs to encrypt or decrypt a large message: 124 1251. Decrypt the key from storage using the secret keeper 1262. Use the decrypted key to encrypt or decrypt the message inside your 127 application. 128 129[`secretbox`]: https://godoc.org/golang.org/x/crypto/nacl/secretbox 130 131### Keep Secrets in Configuration {#runtimevar} 132 133Once you have [opened a secrets keeper][] for the secrets provider you want, 134you can use a secrets keeper to access sensitive configuration stored in an 135encrypted `runtimevar`. 136 137First, you create a [`*runtimevar.Decoder`][] configured to use your secrets 138keeper using [`runtimevar.DecryptDecode`][]. In this example, we assume the 139data is a plain string, but the configuration could be a more structured 140type. 141 142{{< goexample src="gocloud.dev/runtimevar.ExampleDecryptDecode" imports="0" >}} 143 144Then you can pass the decoder to the runtime configuration provider of your 145choice. See the [Runtime Configuration How-To Guide][] for more on how to set up 146runtime configuration. 147 148[opened a secrets keeper]: {{< ref "#opening" >}} 149[Runtime Configuration How-To Guide]: {{< ref "/howto/runtimevar/_index.md" >}} 150[`*runtimevar.Decoder`]: https://godoc.org/gocloud.dev/runtimevar#Decoder 151[`runtimevar.DecryptDecode`]: https://godoc.org/gocloud.dev/runtimevar#DecryptDecode 152 153## Other Usage Samples 154 155* [CLI Sample](https://github.com/google/go-cloud/tree/master/samples/gocdk-secrets) 156* [Secrets package examples](https://godoc.org/gocloud.dev/secrets#example-package) 157 158## Supported Services {#services} 159 160### Google Cloud Key Management Service {#gcp} 161 162The Go CDK can use keys from Google Cloud Platform's [Key Management 163Service][GCP KMS] (GCP KMS) to keep information secret. GCP KMS URLs are 164similar to [key resource IDs][]. 165 166[GCP KMS]: https://cloud.google.com/kms/ 167[key resource IDs]: https://cloud.google.com/kms/docs/object-hierarchy#key 168 169`secrets.OpenKeeper` will use Application Default Credentials; if you have 170authenticated via [`gcloud auth login`][], it will use those credentials. See 171[Application Default Credentials][GCP creds] to learn about authentication 172alternatives, including using environment variables. 173 174[GCP creds]: https://cloud.google.com/docs/authentication/production 175[`gcloud auth login`]: https://cloud.google.com/sdk/gcloud/reference/auth/login 176 177{{< goexample "gocloud.dev/secrets/gcpkms.Example_openFromURL" >}} 178 179#### GCP Constructor {#gcp-ctor} 180 181The [`gcpkms.OpenKeeper`][] constructor opens a GCP KMS key. You must first 182obtain [GCP credentials][GCP creds] and then create a gRPC connection to GCP KMS. 183 184{{< goexample "gocloud.dev/secrets/gcpkms.ExampleOpenKeeper" >}} 185 186[`gcpkms.OpenKeeper`]: https://godoc.org/gocloud.dev/secrets/gcpkms#OpenKeeper 187 188### AWS Key Management Service {#aws} 189 190The Go CDK can use customer master keys from Amazon Web Service's [Key 191Management Service][AWS KMS] (AWS KMS) to keep information secret. AWS KMS 192URLs can use the key's ID, alias, or Amazon Resource Name (ARN) to identify 193the key. You should specify the `region` query parameter to ensure your 194application connects to the correct region. 195 196[AWS KMS]: https://aws.amazon.com/kms/ 197 198`secrets.OpenKeeper` will create a default AWS Session with the 199`SharedConfigEnable` option enabled; if you have authenticated with the AWS CLI, 200it will use those credentials. See [AWS Session][] to learn about authentication 201alternatives, including using environment variables. 202 203[AWS Session]: https://docs.aws.amazon.com/sdk-for-go/api/aws/session/ 204 205{{< goexample "gocloud.dev/secrets/awskms.Example_openFromURL" >}} 206 207#### AWS Constructor {#aws-ctor} 208 209The [`awskms.OpenKeeper`][] constructor opens a customer master key. You must 210first create an [AWS session][] with the same region as your key and then 211connect to KMS: 212 213{{< goexample "gocloud.dev/secrets/awskms.ExampleOpenKeeper" >}} 214 215[`awskms.OpenKeeper`]: https://godoc.org/gocloud.dev/secrets/awskms#OpenKeeper 216[AWS session]: https://docs.aws.amazon.com/sdk-for-go/api/aws/session/ 217 218### Azure KeyVault {#azure} 219 220The Go CDK can use keys from [Azure KeyVault][] to keep information secret. 221`secrets.OpenKeeper` will use [default credentials from the environment][Azure 222Environment Auth], unless you set the environment variable 223`AZURE_KEYVAULT_AUTH_VIA_CLI` to `true`, in which case it will use 224credentials from the `az` command line. 225 226Azure KeyVault URLs are based on the [Azure Key object identifer][Azure Key ID]: 227 228{{< goexample "gocloud.dev/secrets/azurekeyvault.Example_openFromURL" >}} 229 230[Azure KeyVault]: https://azure.microsoft.com/en-us/services/key-vault/ 231[Azure Environment Auth]: https://docs.microsoft.com/en-us/go/azure/azure-sdk-go-authorization#use-environment-based-authentication 232[Azure Key ID]: https://docs.microsoft.com/en-us/azure/key-vault/about-keys-secrets-and-certificates 233 234#### Azure Constructor {#azure-ctor} 235 236The [`azurekeyvault.OpenKeeper`][] constructor opens an Azure KeyVault key. 237 238{{< goexample "gocloud.dev/secrets/azurekeyvault.ExampleOpenKeeper" >}} 239 240[`azurekeyvault.OpenKeeper`]: https://godoc.org/gocloud.dev/secrets/azurekeyvault#OpenKeeper 241 242### HashiCorp Vault {#vault} 243 244The Go CDK can use the [transit secrets engine][] in [Vault][] to keep 245information secret. Vault URLs only specify the key ID. The Vault server 246endpoint and authentication token are specified using the environment 247variables `VAULT_SERVER_URL` and `VAULT_SERVER_TOKEN`, respectively. 248 249{{< goexample "gocloud.dev/secrets/hashivault.Example_openFromURL" >}} 250 251[Vault]: https://www.vaultproject.io/ 252[transit secrets engine]: https://www.vaultproject.io/docs/secrets/transit/index.html 253 254#### HashiCorp Vault Constructor {#vault-ctor} 255 256The [`hashivault.OpenKeeper`][] constructor opens a transit secrets engine 257key. You must first connect to your Vault instance. 258 259{{< goexample "gocloud.dev/secrets/hashivault.ExampleOpenKeeper" >}} 260 261[`hashivault.OpenKeeper`]: https://godoc.org/gocloud.dev/secrets/hashivault#OpenKeeper 262 263### Local Secrets {#local} 264 265The Go CDK can use local encryption for keeping secrets. Internally, it uses 266the [NaCl secret box][] algorithm to perform encryption and authentication. 267 268{{< goexample "gocloud.dev/secrets/localsecrets.Example_openFromURL" >}} 269 270[NaCl secret box]: https://godoc.org/golang.org/x/crypto/nacl/secretbox 271 272#### Local Secrets Constructor {#local-ctor} 273 274The [`localsecrets.NewKeeper`][] constructor takes in its secret material as 275a `[]byte`. 276 277{{< goexample "gocloud.dev/secrets/localsecrets.ExampleNewKeeper" >}} 278 279[`localsecrets.NewKeeper`]: https://godoc.org/gocloud.dev/secrets/localsecrets#NewKeeper 280 281