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