Protect your function app with Azure KeyVault
Tags: serverless, webdev, tutorial, node
Published: 2019-09-26 06:18:31

> This article is part of [#ServerlessSeptember](https://dev.to/azure/serverless-september-content-collection-2fhb). You'll find other helpful articles, detailed tutorials, and videos in this all-things-Serverless content collection. New articles are published every day — that's right, every day — from community members and cloud advocates in the month of September. 

> Find out more about how Microsoft Azure enables your Serverless functions at [https://docs.microsoft.com/azure/azure-functions/](https://docs.microsoft.com/azure/azure-functions/?WT.mc_id=servsept_devto-blog-cxa).
 

You should never store secrets in code. But what if your function need access to a secret, ie. a connection string to a storage blob?  You can store those secrets in [Azure KeyVault](https://azure.microsoft.com/en-us/services/key-vault/) and securely reference said secrets in your function app.

The rest of this article is going to show you how to set this up without using Azure Portal.

> If you want to learn more about how to better secure your function app, take a look at this article by Function PM Matthew

> {% link mattchenderson/they-can-t-hack-your-servers-if-you-don-t-have-any-servers-right-246a %}


# Pre-requisites

## Azure CLI

[Installation guide](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)

## jq

a lightweight and flexible [command-line JSON processor](https://stedolan.github.io/jq/) that I promise you'll be using over and over again

## A deployed function app

This can either be done through

1. [azure-cli](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-azure-function-azure-cli)

1. Serverless framework - recommended since this article is building upon the sample app walk through from yesterday

{% link mydiemho/create-and-deploy-azure-functions-with-serverless-20ai %}


# Walk-through

All the scripts I mentioned below can be find in this accompanying repo

{% github mydiemho/myho-serverless-demo no-readme %}

> Feel free to change the chosen resource name in the scripts to something else, but beware that different resource have different naming restrictions.

> Refer to the [Azure resources naming convention guide](https://docs.microsoft.com/en-us/azure/architecture/best-practices/naming-conventions#general) if you're having trouble using 
your desire values.

---

## Log in

```bash
az account show # list all subscriptions you have access to 
az account set --subscription <SUB_ID> # id of the sub you want to use
az login
```

---

## Clone repo

```bash
git clone git@github.com:mydiemho/myho-serverless-demo.git
cd myho-serverless-demo
```

---

## Set up keyVault

```bash
./scripts/create-keyvault.sh
```

The script will create a resource group and a keyVault.

---

## Add secrets

```bash
./scripts/add-secrets.sh AwesomeSecret AwesomeSecretValue
```

> The script takes 2 inputs: the secret key and the secret value.  If you do not pass in any inputs, the default key and value will be used.

Take note of the `secret url` in the output, you'll need it in a later step

## Grant function app read permission

In order for the app the reference keyVault secrets, you have to add the app to the keyVault's access policies.

### Behind the scene

The steps involved in doing this is:

1. Adding a system-assigned identity to the function app <sup>[1](https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity)</sup>

1. Add this identity as access policy to keyVault

### How-to

You'll have to first deploy a function app, then you can using the following script to grant access to the app

```bash
./scripts/grant-app-access.sh <APP_RESOURCE_GROUP> <APP_NAME>
```

Once the script finish, you can check the portal and see that a new access policy has been added to the function app

![KeyVault access policies portal](https://thepracticaldev.s3.amazonaws.com/i/72gw3roswpm4olw54l12.png)

---

## Add new app setting

We'll add the keyvault secret reference as an app setting <sup>[*](https://docs.microsoft.com/en-us/azure/azure-functions/functions-how-to-use-azure-function-app-settings)</sup>.  App settings are available as environment variables to function handlers.  

Using serverless, anything under the `environment` section will be created as app settings.  

> Make sure to replace the url with the one generated in [add secrets](#add-secrets)

```yaml

# see https://github.com/mydiemho/myho-serverless-demo/blob/master/serverless.yml#L29
  
  environment: # these will be created as application settings
    SUPER_SECRET: "@Microsoft.KeyVault(SecretUri=https://myho-serverless-demo-kv.vault.azure.net/secrets/MySuperSecretName/88df087331004326994047248b0b6b67)"

```

---

## Add new function

You can either update the handler code for one of the function or create a new function.  For this example, I choose to create a new function called `secrets`.

### update serverless.yml

add the following section to your yaml below existing functions

```yaml

# see https://github.com/mydiemho/myho-serverless-demo/blob/master/serverless.yml#L93

  secrets:
    handler: src/handlers/secrets.printSecrets
    events:
      - http: true
        x-azure-settings:
          methods:
            - GET
          authLevel: anonymous
```

### add handler code

Add a new file `src/handlers/secrets.js`


```bash

# https://github.com/mydiemho/myho-serverless-demo/blob/master/src/handlers/secrets.js

"use strict";

const superSecret = process.env["SUPER_SECRET"];

module.exports.printSecrets = async function(context, req) {
  context.log(
    "JavaScript HTTP trigger function processed a request to display the secret in keyvault."
  );

  context.res = {
    // status: 200, /* Defaults to 200 */
    // FOR DEMO PURPOSE: DO NOT LOG SECRETS IN PRODUCTION
    body: `Shhhhh.. it's a secret: ${superSecret}`
  };
};

```

---

## Deploy new changes

Once you've done all the set up, you're now ready to test out your new function app that is referencing KeyVault


```bash
sls deploy
```

> If you're having trouble deploying, refer to this article to make sure you have done all the pre-requisites {% link mydiemho/create-and-deploy-azure-functions-with-serverless-20ai %}

### Verify changes

After deploy, you can hit the function url, apim url, or using the `invoke` command to test your changes.


```bash
➜ sls invoke -f secrets                                                                             
Serverless: Logging into Azure

...

Serverless: Invoking function secrets with GET request
Serverless: "Shhhhh.. it's a secret: ItIsASecret"

```