Welcome to "This is my Architecture."
I'm Matt from AWS.
Today, I'm joined by Roaan from Atlassian.
Thanks for joining.
- Hi, Matt, thanks for having me.
- So, I'm a big Atlassian fan,
Jira, Confluence, a lot of great products.
But today we're going to talk about
something called Atlassian Forge, right?
- That's correct.
- So tell us about Atlassian Forge.
- Atlassian Forge
is Atlassian's next-generation platform,
enabling customers and developers,
third-party vendors to develop customer applications
and extend our product.
- Okay, so what does that mean?
Like making different Atlassian products work together?
- It allows them to make products work together,
they can both custom add-ons.
If they want to share data from another data source,
they can share it in Confluence, for example.
- So I could take a Jira ticket, for example,
and show it in Confluence?
- You can take a Jira ticket and show it in Confluence.
- Okay, cool.
Well, let's dig in to how that actually works.
So I see we have CLI and Browser.
How does this all begin?
- So they're basically two parts to the Forge platform.
The first part has to do with deployment,
because we're deploying customer code.
The second part has to do with invocation
of that customer code,
where we actually execute the code that was deployed. - OK
- So I'll take you through the first part.
So it starts with a developer writing code
in JavaScript typically.
I then deploy that using our CLI
to one of our services.
- So when you say deploying code or deploying an application,
does that mean a Lamdba function I'm guessing,
or how does it represent?
- It will eventually turn out to be a Lambda function.
To them it looks like a normal JavaScript function,
which we translate into a Lambda function.
- OK, so the customer in your case
is not writing a Lambda function;
they're writing the code
and deploying through a web service on EC2.
- That's correct.
These web services are behind ALB,
so it can scale to handle the load from various customers.
- Okay, and you said scaling.
Are you talking like hundreds of customers,
thousand of customers?
What kind of scale are we talking about?
- We're talking thousands of customers.
- Wow, okay.
So, scalable, sort of, application injection
to your whatever you want to call it.
- Exactly.
- And so what happens next?
- So we need to keep track of all the deployments we want to do.
To do that we store the state in DynamoDB.
This allows us to know the progress of a deployment;
whether it's completed, filed, et cetera,
so we can report back to the user
as to what happened to their deployment.
- Great, yeah, Dynamo DB and noSQL database
is great for storing things like state, for example.
- Exactly.
- Now you have multiple EC2s with an SQS queue in the middle.
Why do you have this architecture?
- Well as we mentioned previously, we have thousands of customers
that potentially want to do deployment,
and we are typically limit on the control plane on Lambda
on how many invocations we can do,
how many Lambdas we can create in a certain time interval.
To account for that,
what we do is we queue the deployment request onto SQS.
Then on the back end, we have a service
that reads the deployment request from SQS.
It can then, in its own time,
create the Lambda when it's allowed to do that.
So it won't be rate-limited.
- Great, so to avoid rate limiting
for creating new functions in Lambda,
you sort of separated by having a queue in the middle
so you can pull them off the queue as you go?
- Exactly.
- OK, now I see there's a line here though.
Does that denote a VPC or an account boundary?
What's going on here?
- The line here is an account boundary.
So for us, trust or security is extremely important.
So the customer code runs in its own account.
There's nothing else in that account.
And the Forge platform runs in a separate account.
That does not touch the customer Lambda account
or the Lambda account does not touch our Forge account.
- So the Atlassian Forge platform,
like other Atlassian products, I imagine,
is a SaaS application, multi-tenant?
- That's correct.
- Is this part over here with Lambda functions also multi-tenant?
Or is it one per customer?
How does it work?
- That is multi-tenant.
So a Lambda can be shared between multiple customers.
- Okay, well then how do you handle security considerations?
- That's a very good point.
As you know, Lambdas can keep static
between invocations,
and since we'll have multiple customer,
different customer requests coming through the Lambda,
that's not an ideal state to be in.
So what we do on every request,
we spin up a v8 isolate to run a customer's code
in that specific isolate.
- So you wouldn't want, for example,
like a global variable
that could be available between the two invocations
to be shared between customers?
- Exactly.
So even though the customer
might write code that tries to do that,
what we do,
because we spin up an isolate on every invocation,
and delete the isolate after the invocation
that global variable disappears again.
- So, some of our viewers
may not be familiar with isolates.
Can you tell us a little bit more about that?
- v8 isolate is a JavaScript v8 engine construct
that allows JavaScript to spin up a very small,
almost like a virtual machine in which they run JavaScript
with nothing in that virtual machine.
So that virtual machine can almost do nothing.
It can't do anything really,
and we have to allow it to do very specific things.
- Okay, and then you can explicitly wipe it out
when it terminates or if it's not used or whatever.
- Exactly, once the request is finished, we delete the isolate,
leaving all traces of all the code all the variables,
are gone, disappeared.
- Interesting. I love that multi-level security approach
to really make it safe and secure for your customers.
Okay, so I understand how you load the application
you've de-coupled it with a queue in the middle,
you create the Lambda function with the customer code
and you store the state in Dynamo DB.
It all makes sense so far.
It's a good, secure architecture.
What's happens next?
- So now we've got the Lambda deployed,
but Lambda's sitting there doing nothing.
It's not much use.
So we have the browser
that now needs to invite the Lambda.
What happens in that case is,
the browser makes a call to one of our internal services.
That does various things.
It checks security permissions;
is the user behind the browser
allowed to execute that Lambda?
It finds the right Lambda associated with that user
with that product.
Once it's found that information,
it goes in and invokes the Lambda.
- So, in addition to authentication,
there's a bunch of logic that happens at this level
and that it picks up the Lambda
that's associated with that request
and returns the data to the user?
- Exactly, because no data stored in the Lambda
and the service actually sends the correct parameters
to the Lambda, so the Lambda knows what to do.
So once the Lambda's executed,
we can get information from other systems,
from other products, from whatever it feels like,
it will return that data
and a page fragment will be constructed,
which is returned to the browser.
And the browser will then reinvent that page fragment.
- OK, well I really like how you approach security.
You're really making it a secure, safe offering
for your customers with the account boundaries,
with the isolates, having all sorts of techniques.
You scale by adding things like SQS
and scalable tiers behind ALB.
It's really an elegant architecture.
- Thank you very much.
As you mentioned,
security is of primary concern for us.
That's why we have these multiple layers of security,
so that in case something goes wrong,
an attack will have to go through various layers
to even affect anything else
- Great, well, like we always say,
security is job zero.
- Exactly.
- So thanks for sharing this with us.
- Thank you very much.
- And thank you for watching "This is My Architecture."