Serverless framework with Azure Functions

Recently an update to Azure Functions has been published containing proxies and integration with Serverless framework. In a nutshell it's a tool for building serverless architectures. Don't get the name fool you - in fact there's a server behind the whole functionality and still all principals regarding web development are true. What in reality it gives you is focusing only on the very functionality of your application. There're no pipelines, layers or areas - you're going to ensure that each component follows the single responsibility pattern and can be deployed separately. 

We're going to build a very simple application using Azure Functions and Serverless to present the current capabilities of the integration.

Provisioning you environment

I decided, that the easiest solution here is to obtain a pre-configured Ubuntu VM with installed NodeJS - you can easiliy get it from the marketplace in the portal. Once you have it, connect to it(as usual in my case, from Windows PuTTY seems like the best idea) and we can start. Type in following commands:

sudo npm install -g serverless
serverless install --url https://github.com/azure/boilerplate-azurefunctions --name ServerlessExample

Those two will:

  • install Serverless globally
  • install a new service locally using name ServerlessExample

Once it's finished, you can go to the ServerlessExample directory - you'll see some files which are the core of our application. In fact, this boilerplate gives us all we need to get started as the example is fully functional.

Deploying a function

Before you're able to deploy your function to Azure you have to provide a credentials for deployment. The whole process is pretty well described here, however I attaching it here with my comments because in my case it didn't go as flawlessly as I thought:

\
bitnami@nodejsblog:~$ sudo npm i -g azure-cli
bitnami@nodejsblog:~$ azure login
bitnami@nodejsblog:~$ azure account show
bitnami@nodejsblog:~$ azure login
bitnami@nodejsblog:~$ azure ad app create -n service_name --home-page http://www.my-app.org --identifier-uris https://www.my-app.org/example -p pass
bitnami@nodejsblog:~$ azure ad sp create -a application_id
bitnami@nodejsblog:~$ azure role assignment create --objectId object_id  -o Contributor
bitnami@nodejsblog:~$ export azureSubId='<subscriptionId>'
bitnami@nodejsblog:~$ export azureServicePrincipalTenantId='<tenantId>'
bitnami@nodejsblog:~$ export azureServicePrincipalClientId='<servicePrincipalName>'
bitnami@nodejsblog:~$ export azureServicePrincipalPassword='<password>'

Note that I used azure ad app create command additionally - in my case it was not possible to simply create a service principal using only a name and a password.

You can ensure that you've added environment variables using printenv command. Once you configured your credentials, go to the directory of your service and just run:

/
serverless deploy

You should see following output:

/
Serverless: Packaging service...
Serverless: Logging in to Azure
Serverless: Creating resource group: ServerlessExampleKamz-rg
Serverless: Creating function app: ServerlessExampleKamz
Serverless: Waiting for Kudu endpoint...
Serverless: Parsing Azure Functions Bindings.json...
Serverless: Building binding for function: httpjs event: httpTrigger
Serverless: Packaging function: httpjs
Serverless: Building binding for function: queuejs event: queueTrigger
Serverless: Building binding for function: queuejs event: blob
Serverless: Packaging function: queuejs
Serverless: Syncing Triggers....Response statuscode: 200
Serverless: Running Kudu command del package.json...
Serverless: Running Kudu command npm install --production...
Serverless: Successfully created Function App

Now when you go to the portal, you'll see a new resource group created and function deployed.

In the next post we'll try to do more advanced configuration and consider involving VSTS and incorporating the framework into our build/release pipeline.

Azure Functions proxy - overview

Azure Functions are great for building a bigger solution, which contains smaller services representing logical separation of different responsibilities. There's however a problem if you'd like to encapsulate logic what can be accessed and which HTTP methods are allowed. Additional problem arises if you're going to somehow avoid passing function keys to each application consuming or using your function. Fortunately Microsoft has just published a public preview of Azure Functions proxy - a very simple yet powerful concept, which allows you to overcome mentioned problems and make your functions to even more fun to work with.

Special thanks to @marekgrabarz for making me aware of this feature and encouraging to write some words about it.

Hide your functions

Actually to take advantage of this feature there's one requirement - a Function app. If you don't have one, quickly go to Azure Portal and create one!

Once you have your Function app created, simply click on it. You will see a Function app screen with a new feature added:

as you can see it's still in preview so it may be still a bit unstable, but it won't bother us in this moment. To be actually able to use proxies, you have to enable them. Go to the Function app settings and turn proxies on in the Proxies(preview) section. Now we can do some real work!

Create a simple function, for which we'll create a proxy. For the testing scenario I created a following function:

/
using System.Net;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{    
    return req.CreateResponse(HttpStatusCode.OK, "You called ProxiedFunction1!");
}

now with a function created, we can create a proxy for it. To do so, follow below steps:

  1. Click on the New proxy button
  2. Give it an unique name and template(I used proxy/function1)
  3. For Backend URL you have to use any URL you'd like to forward a request to(in my case it was my function Function URL with the key)
  4. Simply click a Create button

Now try to access your proxy by going to https://{your_function_app).azurewebsites.net/{template} - if you used the same function as me, you'll get "You called ProxiedFunction1!" as a response. You can create as many proxies as you want and connect them to the resource of your choice(it can be a function, a web app or other endpoint accessible with HTTP). Your possibilities are unlimited here.

Parameters and application settings

You can also create a proxy in more generic way simply using parameter in your route. Consider following example:

Whatever you pass as a {function} parameter, it will be routed to the ProxiedFunction1 function

Additionally you can reference application settings what can be helpful if you're searching for more flexibility. Let's create another proxy like this:

What is more, I added MY_SECRET key with a value of a5gYhj87Hgsta to the app settings. How when I try to access proxy, I can go to https://my-app.azurewebsites.net/proxy/secret/a5gYhj87Hgsta and get desired results. If a secret doesn't match, you'll get HTTP 404 instead.

Alternatives

Currently alternative to this kind of proxy is using Application Gateway or API Management. The advantage of this solution is its simplicity and cost related - since Azure Functions are free for the first 1M requests*, it's possible that in the beginning you will be running this solution for free.

Summary

Currently proxies for Azure Functions are limited in functionality by the preview version. Fortunately the team responsible for this component promised many enhancements implemented soon - can't wait to test them :)

* considering duplicated request when a proxy rewrites it, depending on how proxy is treated in pricing, it can be lowered to 0.5M free requests