It’s almost a right of passage for Cloud engineers. You spend some time developing this cool new app/script that makes your life a little easier. Maybe it automates a complex task, streamlines a process for you or just all around makes life a little easier. You find yourself happy with the outcomes and start basking in the knowledge that this is one less thing you need to worry about… And then it happens. You open your AWS newsfeed one morning to find that the product team at AWS has built the same thing you did. That cool script you spent days/weeks building, is now just a check box on the deployment page. This has happened to me more times than I care to count over my many years of working with AWS… most recently in relation to my recent blog article on Zoom recording downloads.
In my last article (available here) I walked you through how to get a basic web-hook endpoint setup using AWS Lambda and API Gateway and the purposes of building a serverless application that automatically downloads recorded Zoom Meetings. While this is still a perfectly valid way to go about solving the problem, AWS have recently released a new feature to Lambda that makes the process much simpler. Function URLs provides you with a dedicated HTTP(S) endpoint for your Lambda function. This means that we can get very similar functionality to what we got from our previous solution, without having to setup a dedicated API gateway, It’s worth noting that Function URLs lack a lot of the more advanced features the API gateway provide so it’s not a replacement service, simply an alternative solution for basic use cases such as ours. In this article I’ll walk through the process of building out the same Lambda function we built last time, simply using Function URLs rather than API gateway. We’ll then use this function in our future articles as I walk through the remainder of the solution (which has also been updated do to some other recent announcements around AWS Lambda).
Step 1: Creating our Lambda Function
Firstly, we need to create the lambda function that will be responsible for handling the payload coming from Zoom.
– Open the Lambda Management Console which can be found in the Services menu under Compute
- From our Dashboard view, click the “Create Function” button located on the top right of the page. You can also find it via the “Functions” section listed on the left-hand side of the page.
- Next, we want to give our function a name and define the runtime. For the purposes of this example, we’ve used the name “InboundZoomWebhook” and we’ll write it in “Node.js 14.x”. Once all of this is defined we can click “Create Function” (again, for the purposes of the example we are leaving all other settings at their default).
- For our code, all we’ll do is replace the “// TODO implement” line with “console.log(event);” as shown in the below screenshot. Go ahead and click “Deploy” once you’ve made the change.
And that’s it for the lambda function. When the lambda function gets called it will print the event payload to the console and return a 200 status code to the caller.
exports.handler = async (event) => {
console.log(event)
const response = {
statusCode: 200,
body: event,
};
return response;
};
Step 2: Adding a Function URL to our Lambda function.
Rather than adding an API Gateway like we did last time, we’ll instead add a Function URL which we can do from the already open Lambda Management Console.
- Start by opening the “Configuration” screen and selecting “Function URL – new” from the left hand menu
None of the above limitations are a problem for this solution as we only need a simple Lambda function to be called and don’t require and form of authentication (however in a future article we will introduce some basic header validation) which makes them a great option for our use case. To get setup with a function URL
- On the “Function URL” screen, click the “Create function URL” button
On the next screen we need to select an Authentication Type. At this stage our options consist of either AWS_IAM authentication or None. For our purposes as we’ll just have zoom posting us some information, they won’t have an IAM context so we’ll go with None.
- From the “Auth Type” menu… select “NONE”. We can go ahead and leave CORS un-ticked as we won’t require that level of control for our project
Once you select “None” as the “Auth Type” you’ll be presented with the permissions Preview.
- Click “Save” to create the Function URL.
And that’s it. As you can see from the below screenshot, we now have a valid https endpoint that we can use to trigger our lambda function. This is the URL that we can provide Zoom to call once our recording is finished.
Step 3: Configuring Zoom to call our webhook
This is the part where we need to take a step away from AWS for a moment and focus our attention on the Zoom platform instead. We need to tell Zoom that we want them to call our webhook every time they finish processing a video recording.
- To start this we need to head over to the zoom developer site at https://developers.zoom.us
- Go ahead and “Sign In” with the account you use to log into zoom. For me, that’s with my Suite Login
- Once you’re logged in, click “Build App” from the top of the page
- For the moment, we are only after the webhook functionality so for now, we can simply click “Create” for a “Webhook Only” app type.
- For the purposes of this demo, we can call our App “RecordingDownloader” and click “Create” to continue.
- Next, we need to give Zoom some basic details about our application. Go ahead and populate the Basic and Developer Contact Information and click “Continue” (you can skip the Links fields for the moment).
- On the next screen, we are provided with our verification token which Zoom will attach to each notification request. As our API Gateway endpoint is public, anybody could send traffic to it… but we only want to be responding to messages originating from Zoom. This verification token gives us something we can use to verify it’s an authenticated notification. However, for the moment we’ll ignore the token as we simply want to verify we can receive notifications… We’ll add verification in the next article when we start processing the requests. For the moment, just take note that it exists.
Right now, all we want to do is to add an “Event Subscription” that will subscribe us to notifications when particular events within our Zoom account occur.
- To do this, simply tick the toggle next to “Event Subscriptions” and click “Add Event Subscription”
- Next, Give the Subscription a name and enter the URL we were presented when we created our Function URL. Once that’s done we can go ahead and click on “Add Events”.
- On the “Event Types” page we can see all the different events that can occur within our Zoom Tenant. Things from meetings starting, billing and user account activity through to participants accepting/joining/leaving. You can start to see some possibilities around integration you could create, but for now, all we’re interested in is getting a notification when our recordings have been completed and are ready for download. For that, we need to tick the “All Recordings have completed” checkbox under the “Recording” section. Go ahead and click “Done”.
- Next, confirm that we have “1 event added” to our “Events” section, and we can go ahead and click “Save” and then “Continue” to save our changes.
At this point, we should now have an activated application within our Zoom account that will send our API Gateway endpoint a notification every time a recording is finished.
Step 4: Testing our Configuration
Now, all we need to do is go ahead and test our configuration and make sure that we get an output in our CloudWatch logs when we receive a notification from Zoom.
To do this, you’re going to want to start and finish a meeting that’s recorded. You can simply open a “New Meeting” and click “record”. When you end the meeting, the recording should automatically be generated. If all you’re doing is logging in, clicking record and waiting a few seconds before ending the meeting… you should get a notification within a couple of minutes.
After those few minutes have passed, it’s time to check out CloudWatch logs to see if the Lambda function has written anything to our logs.
- start by opening up “CloudWatch” which can be found under “Management & Governance” in the services’ menu of the AWS Management Console.
- Browse to “Log Groups” under “Logs” from the menu on the left-hand side
- Under “Log Groups” you should see a Log Group for the Lambda Function you created back in “Step 1” (in my case “InbouncZoomWebhook”) in the form of “/aws/lambda/%LambdaFunctionName%”. Click on the Log Group Name.
- There will be multiple log streams listed. A log stream is created for each set of executions of a lambda function (for example, each time a new version of the lambda function is deployed). You should see the most recent stream at the top of the list with the “Last Event Time” being similar to when Zoom finished processing your meeting recording. Click on the Log Stream to display the log output from the lambda function.
- And here we can see the console.log output of our Lambda function returning the payload that was sent to me from Zoom when they finished processing my meeting recording. This payload contains the URLs of the files I can download as well as the download token I’ll need to authenticate my request to download the file (certain fields in this screenshot have been blurred for security reasons).
Conclusion
And there we go, we have successfully managed to configure a web-hook in our Zoom Tenant and have it send an event notification to our new Lambda Function URL… solving the first problem we outlined in our quest to automatically download our Brown bag sessions.
In the next article, I’ll walk through the process of how I use the payload coming from Zoom to actually trigger another function in AWS to download the recordings and save them in an S3 bucket for later transfer. We’ll also add some security to our solution in the form of payload verification using the tokens we were provided earlier in this piece. In future articles, I’ll outline the other actions and integrations that I’ve used to automate the entire end-to-end process.