Update secret docs and sample-functions

**What**
- Update the documentation about secret management to note the changed
file location
- Remove the documentation on secret rotation, because this will not
currently work
- Update apikey-secret and ApiKeyProtected-Secrets to read secret values
from both the old and the new locations

**Why**
- Recent updates to faas-swarm and faas-netes changed the mount location
of secrets.  These changes update the docs to reflect this change.

Signed-off-by: Lucas Roesler <roesler.lucas@gmail.com>
This commit is contained in:
Lucas Roesler
2018-05-26 10:02:43 +02:00
committed by Alex Ellis
parent 7b40854cfb
commit 41bda568a7
3 changed files with 34 additions and 11 deletions

View File

@ -4,7 +4,8 @@ OpenFaaS deploys functions as Docker Swarm Services, as result there are several
## Using Environment Variables
First, and least secure, is the ability to set environment variables at deploy time. For example, you might want to set the `NODE_ENV` or `DEBUG` variable. Setting the `NODE_ENV` in the stack file `samples.yml`
First, and least secure, is the ability to set environment variables at deploy time. For example, you might want to set the `NODE_ENV` or `DEBUG` variable. Setting the `NODE_ENV` in the stack file `samples.yml`
```yaml
provider:
name: faas
@ -20,6 +21,7 @@ functions:
```
You can then deploy and invoke the function via the `faas-cli` using
```sh
$ faas-cli deploy -f ./samples.yml
$ faas-cli invoke nodehelloenv
@ -28,12 +30,11 @@ Hello from a production machine
Notice that it is using the value of `NODE_ENV` from the stack file, the default is is `dev`.
## Using Swarm Secrets
_Note_: The examples in the following section require `faas-cli` version `>=0.5.1`.
_Note_: Secrets are mounted as files to `/var/openfaas/secrets`, prior to version `0.8.2` secrets were mounted to `/run/secrets`. The example functions demonstrate a smooth upgrade implementation.
For sensitive value we can leverage the [Docker Swarm Secrets](https://docs.docker.com/engine/swarm/secrets/) feature to safely store and give our functions access to the needed values. Using secrets is a two step process. Take the [ApiKeyProtected](../sample-functions/ApiKeyProtected) example function, when we deploy this function we provide a secret key that it uses to authenticate requests to it. First we must add a secret to the swarm
For sensitive value we can leverage the [Docker Swarm Secrets](https://docs.docker.com/engine/swarm/secrets/) feature to safely store and give our functions access to the needed values. Using secrets is a two step process. Take the [ApiKeyProtected](../sample-functions/ApiKeyProtected) example function, when we deploy this function we provide a secret key that it uses to authenticate requests to it. First we must add a secret to the swarm
```sh
docker secret create secret_api_key ~/secrets/secret_api_key.txt
@ -53,7 +54,6 @@ echo "R^YqzKzSJw51K9zPpQ3R3N" | docker secret create secret_api_key -
Now, with the secret defined, we can deploy the function like this
```sh
$ echo "R^YqzKzSJw51K9zPpQ3R3N" | docker secret create secret_api_key -
$ faas-cli deploy -f ./samples.yml --secret secret_api_key
@ -75,6 +75,7 @@ Access denied!
```
Your `samples.yml` stack file looks like this
```yaml
provider:
name: faas
@ -87,11 +88,11 @@ functions:
image: functions/api-key-protected:latest
```
Note that unlike the `envVars` in the first example, we do not provide the secret value, just a list of names: `"secrets": ["secret_api_key"]`. The secret value has already been securely stored in the Docker swarm. One really great result of this type of configuration is that you can simplify your function code by always referencing the same secret name, no matter the environment, the only change is how the environments are configured.
Note that unlike the `envVars` in the first example, we do not provide the secret value, just a list of names: `"secrets": ["secret_api_key"]`. The secret value has already been securely stored in the Docker swarm. One really great result of this type of configuration is that you can simplify your function code by always referencing the same secret name, no matter the environment, the only change is how the environments are configured.
## Advanced Swarm Secrets
<!-- ## Advanced Swarm Secrets
For various reasons, you might add a secret to the Swarm under a different name than you want to use in your function, e.g. if you are rotating a secret key. The Docker Swarm secret specification allows us some advanced configuration of secrets [by supplying a comma-separated value specifying the secret](https://docs.docker.com/engine/reference/commandline/service_create/#create-a-service-with-secrets). The is best show in an example. Let's change the api key on our example function.
For various reasons, you might add a secret to the Swarm under a different name than you want to use in your function, e.g. if you are rotating a secret key. The Docker Swarm secret specification allows us some advanced configuration of secrets [by supplying a comma-separated value specifying the secret](https://docs.docker.com/engine/reference/commandline/service_create/#create-a-service-with-secrets). The is best show in an example. Let's change the api key on our example function.
First add a new secret key
@ -112,4 +113,4 @@ $ curl -H "Content-Type: application/json" \
Unlocked the function!
```
We reuse the sample stack file as in the previous section.
We reuse the sample stack file as in the previous section. -->

View File

@ -8,10 +8,21 @@ import (
"strings"
)
func getAPISecret(secretName string) (secretBytes []byte, err error) {
// read from the openfaas secrets folder
secretBytes, err = ioutil.ReadFile("/var/openfaas/secrets/" + secretName)
if err != nil {
// read from the original location for backwards compatibility with openfaas <= 0.8.2
secretBytes, err = ioutil.ReadFile("/run/secrets/" + secretName)
}
return secretBytes, err
}
func handle(body []byte) {
key := os.Getenv("Http_X_Api_Key")
secretBytes, err := ioutil.ReadFile("/run/secrets/secret_api_key")
secretBytes, err := getAPISecret("secret_api_key")
if err != nil {
log.Fatal(err)
}

View File

@ -7,12 +7,23 @@ import (
"strings"
)
func getAPISecret(secretName string) (secretBytes []byte, err error) {
// read from the openfaas secrets folder
secretBytes, err = ioutil.ReadFile("/var/openfaas/secrets/" + secretName)
if err != nil {
// read from the original location for backwards compatibility with openfaas <= 0.8.2
secretBytes, err = ioutil.ReadFile("/run/secrets/" + secretName)
}
return secretBytes, err
}
// Handle a serverless request
func Handle(req []byte) string {
key := os.Getenv("Http_X_Api_Key") // converted via the Header: X-Api-Key
secretBytes, err := ioutil.ReadFile("/run/secrets/secret_api_key") // You must create a secret ahead of time named `secret_api_key`
secretBytes, err := getAPISecret("secret_api_key") // You must create a secret ahead of time named `secret_api_key`
if err != nil {
log.Fatal(err)
}