Transcript
This transcript was autogenerated. To make changes, submit a PR.
Okay. Hi everyone. Conferences have changed a
little this year. We're doing a lot of virtual conferences, which is really
cool to me because it means we can do more of them. So my
name is Josh Stella. I'm the co founder and chief technology
officer at Fug. And what we do at Fug is
cloud security. But what I'm going to talk about today
is open policy agent addressing cloud security with,
as they call it, OPA. So a little bit
of what we will cover on the agenda. I'm going
to go through an overview of misconfiguration risk
in the cloud era. This is the big attack vector on cloud is
misconfiguration of cloud resources. I'm going to explain thats a little bit
why we believe policy as code, which is what OPA
does, is really mandatory for successful
security and compliance. Manual processes just don't cut it
anymore. I'm going to go into an
introduction of OPA and show you their website and
talk a little bit about the language and so on and some of the
ecosystem of tools that fuge contributes. CTO quite a lot.
We're going CTO drill in to the OPA toolbox for
the cloud security use case. OPA gets used for all kinds of stuff now,
but we're going to drill in for cloud security and
then a little bit on getting started with policy
code using OPA. Now this is pre recorded so we can't take live questions,
but I hope this is at least a really good
introduction. CTO the topic. So what is cloud
misconfiguration? The first thing to understand about it
is it is a major security risk, the major
security risk in cloud. So nearly
all successful attacks on cloud services are the
result of customer misconfiguration, mismanagement and
mistakes, according to Neil McDonald from Gartner.
Gartner just last week put out some new research saying
that cloud misconfiguration is a greater
threat, is a greater attack surface, a greater vulnerability than
workload security, which is all we used to care about.
So this is a big deal. Now we at Fugue
every year do a big survey of folks who are
operating Atscale on cloud and thats 93%
figure came from that survey. Over 300 companies and
organizations operating at large atscale on cloud and 93%
were concerned about a major security breach due to misconfiguration.
I was pleased with that number, but the 7%
that aren't represented probably going to show up in
the news. If you're not worried about this,
you should be because even the experts find
it quite challenging. And by the way, before founding Fuge, I worked at AWS
as a principal solution architect for national security kinds
of environments. So this is a huge problem.
Now, if you were to read the news and
if the news were fully accurate, you would think
that object storage access policies, object storage
would be the number one misconfiguration concern.
But when we asked people what their main security
risk concerns are around misconfiguration, the very first answer
was identity and access management. And I was super pleased
to see this because that's true. IAM is
really a network is
the right way to think about it. And getting it correct is
extraordinarily difficult and complex. And if you get it wrong,
it can have just devastating consequences. So number
one answer, obviously thats are not exclusive
of each other. Number two answer,
security group rules. But essentially firewall rules,
TCP IP based ingress and egress.
Yeah, one of the things that I get
to do it's a lot of fun, is when a breach
hits the press, I and my team will try to
recreate it. And you don't always have enough
information to go on, but you always learn something.
And one of the things that we've learned is that most of
these breaches are a combination of a problem with IAM,
a two liberal ingress ports somewhere, and then
ultimately getting to the object storage access
policies to steal data.
Also very common hack is stealing data at an
s. Three is kind of the one everyone talks about. Happens rarely
because it's just a public bucket. So that is
a simple interpretation versus those
reality. But people also do stuff like stand up crypto
mining in your cloud accounts, there's all kinds of things they can do. And then
fourth among our respondents was encryption in
transit disabled. All right,
so what we've learned over years of doing this,
and this is kind of allfube does, is that cloud misconfiguration
is pretty much universally overlooked
in some way or another. I have yet
to see an organization that had it perfect.
And there are reasons for this, valid reasons.
That quote from Gartner sounded a little pejorative
of cloud users, of customers, of cloud. It's actually
very hard to get thats stuff right. So every time somebody hits the news,
I feel bad for them. I don't think they're fools. It's hard.
Many dangerous cloud misconfigurations are not recognized
as misconfigurations by the security team.
And there is a reason for that, which is most security teams
are at least somewhat reliant or heavily reliant on compliance
frameworks to give them guidance, best practices.
There's NIST, there's soc two,
there's cis benchmark. Well, those are
behind the times. And so all kinds
of dangerous misconfigurations can exist
even when you're doing things right according to those standards.
So the security team doesn't see it as a misconfiguration,
because the compliance framework they're reliant on doesn't see it as
a misconfiguration. And therefore they are exceedingly common
in enterprise cloud environments. And because of
the changing nature of cloud, the constant mutation of
infrastructure in cloud, this is akin to needles continuously
appearing in a haystack. So a little
bit about hacker strategy, and by the way, all these things relate back to policy
as code, so stick with me here. Hacker strategy
has evolved over the years, kind of the traditional
Hollywood version. Know bad
actors breaking in and stealing your data is that they first
identify the target organization and then they search for vulnerabilities,
or maybe use phishing or something to create vulnerabilities
and then attack and steal data. This does still
happen in the world. A relatively recent example of this
was North Korea did not like a movie that Sony pictures made,
and so stole their email and they targeted
Sony. But this is not how most main real
approaches happen anymore. What instead is happening is
that the bad actors, often in organized networks or distributed
networks, are running automation to find
misconfigured resources. And a
friend of mine who just focuses on this area
told me that the average length of time between
a resource going on the Internet can IP address or a DNS record or
whatever, and it getting scanned for vulnerabilities is
about seven minutes. Once it's
found, the bad guys are going to hit it even faster than that.
I've seen as fast as multiple times a second where
bad guys are examining your critical infrastructure.
That's Internet facing, looking for those ways in. So what
the bad guys do is they run all this automation, they constantly run it,
and they get up in the morning and they get their coffee and they see,
oh, there's a bank with a vulnerability, oh, there's a
major manufacturer, and then they already know
what the misconfiguration is and how they can exploit it,
because that's what their automation has looking for. So if you don't think
people care enough about your organization for them to target you, it doesn't
matter. As soon as you're putting things online, bad guys are finding
them. And if you have anything they care about,
they know, they have an enumeration of what you're vulnerable
to. And this is why I said earlier,
the manual approach is no longer good enough. It's just simply
not fast enough. And it's not thorough enough because the bad actors are using
automation and you have to use automation and policy
as code is a really super thorough
and helpful way to do that.
So the attack surface on
cloud is complex and ever expanding. So in the data center days
there is still physical infrastructure in the cloud, but that's all abstracted
away by the cloud service providers, right? But in the old days, you would buy
switches, you would buy servers, you would buy firewalls, you'd shove
them in a rack, and three or five years later you might recapitalize
those. These things were replaced them. In other
words, pretty static, right? Pretty static.
And they were manually deployed, configured and maintained.
That slow manual process gave
all kinds of teams the time to
examine that infrastructure for security and other reasons,
because it moved slowly. I mean, I've sat in change control boards.
We were talking about which ports should be allowed to be open on a
firewall. And there's some canonical document thats says this is
what can be allowed, and there's a teams who own
that. Well, the cloud's completely different than
that. You can try to do that in cloud, but you'll
fail. I've seen organizations try to treat it like a data
center. It doesn't work. Engineers are smarter
than that, and they find ways around your slow
moving controls. The whole point of cloud is to go fast. And so you
have software defined infrastructure, which is highly dynamic,
and all of it is deployed, configured and maintained via APIs.
Now those APIs giveth and taketh
away. What they give is this ability to
go as fast as you want, to experiment, to iterate. And that's awesome.
And that's one of the key benefits of cloud. The APIs also
give us the ability to use software engineering
and computer science to check the efficacy
and safety of our infrastructure. You could not do that
in the data center. It was manual, right?
But those APIs also take away the
friction, the slowness for manual checks to
be effective. So the developers themselves are now building
and modifying their own infrastructure environments.
So this is why we believe strongly that you have to
use policy as code for any kind of security at
scale on cloud. Because in the data center days, the infrastructure security
operations teams would build out infrastructure
and then hand resources off to those
business units that were building applications and validations
and audits were generally performed infrequently and manually.
And the data center never had a control plane API that was complete.
Right? So in the cloud era this gets flipped
upside down. Instead of the developers getting slotted into
existing infrastructure that's run by the infrastructure teams,
the developers are ad hoc building infrastructure. I built
this morning a global network in
about five minutes. Well that would have been a months long
project in the data center world. And this is a reality we
just have to deal with because it is going to continue.
So the world's flipped over. Now the developers are building the infrastructure
via APIs, but we
gain the ability. Now you can still do, and we see this
all the time at fug out there in the world folks that are still doing
manual validation, audits, remediation.
But it's kind of nuts because the bad guys remember, are automated.
So what you can do now is use policy as
code in order to go as fast
or faster and be preventative against these
kinds of risks. And what this really does is the policy has
code then empowers engineers to own the security of their cloud
based systems successfully. You can make it repeatable,
you can make it testable, shareable, scalable, peer reviewed,
all the good stuff you get when you're talking about writing code.
All right, so what is policy as code versus other things?
In traditional programming languages, general purpose programming languages,
what you're really doing is expressing some kind
of logic and data manipulation, data processing and logic.
So your logical functions, and I mean this with a small f, I don't
mean formal functions, although those two are expressed
as code. And then your tooling, your compiler,
your interpreter, your linter, your ide provides a
feedback loop that tells you whether it is
going to work or at least give you a lot of hints, right? If you
try to multiply a string times a floating point,
your compiler or interpreter will probably tell you, at least tell you that you might
not be wanting to do that. That's going to have a weird result, but probably
will tell you you're not allowed to do that without a cast, right?
So a lot of people think who aren't programmers and
my background is in programming and software architecture, think thats
programmers are people that have thats big complex machine in their head
and they just write it down. It doesn't really work that way.
The way it works is you are trying things and
your tooling is telling you where you're making a mistake.
Not all mistakes. You still have to have a lot of judgment and a lot
of taste and your own opinions.
But the tooling is helping you along the way, every step of the way.
Well, policy as code is that same feedback
loop around security. So your security
posture can be expressed, has code,
and then the tooling can tell you if what
you're doing from a security perspective is
correct or dangerous. In the same way the compiler interpreter will
tell you if your functions will function. A policy
has code engine. A good one will tell you if what you're doing is secure
and meets policy. And by the way,
this is an immediate gain in
terms of productivity. Because if, as a developer,
if my tooling is now telling me, hey, you can't have that
particular port open to the whole Internet on a security group,
I don't have to wait for a security audit to tell me that. My tooling
tells me that, and I can fix it without any humans getting in the loop.
So really powerful stuff.
So we at Fug are super excited about open policy
agent. We actually have a lot of formative patents
in the area of policy as code at fugue, and had written our whole
own compiled language around it and so on.
But then when OPA came out, and that's what the creators
call it, OPA. When OPA came out,
we saw what had the potential to be a standard,
and there really has never been one. There have been some absolutely horrible
XML expressions of policy that don't do anything,
don't have any functional aspect, any runtime aspect. But in
terms of an actual working open source standard,
and I don't mean standards body, I mean de facto standard agreed upon by
a lot of folks. That's never been the case with policy as code.
And we saw OPA as a potential real
win in this area. It's also very know,
a lot of times technology pops up that we look at and
I think, yeah, OPA is really nicely done.
It's pretty elegant. It really started taking off when
it became sponsored by the Cloud Native Computing foundation.
Who are the folks that manage Kubernetes? So when we got on board,
it was real early days. Now a those lot of folks are using
this like Pinterest and Netflix and all kinds of
people. I went out to give a talk at the OPa
day at Kubecon
last year, and it was standing room only and all
kinds of big companies there. Okay.
Opa has a language called Rego.
I don't know why people make naming choices, but the language has a different
name. It's Rego. It's a really cool, simple language.
It's really declarative, and it's sort of
like a query language. In fact, I think of it as a query language,
but a declarative one, and it can validate any
JSON data structure. Well, just about everything
can get expressed as JSON these days. So you can compare
that using OPA and using the regular language. You can assert
declarations about what you expect and don't expect there to be in JSON,
and then it will examine it and tell you whether or not
that's true. And that means you can use this for a whole
lot of use cases. So the normal ones that
I saw out at Kubecon and that I read about all
the time are people using OPA on a transaction basis. In microservice
architectures, where individual calls from microservice
a to microservice B to microservice Z are
getting evaluated as to whether or not that call is legal.
We use it in a totally different way at Fug. We use it for
cloud configuration of cloud infrastructure,
and it scales really nicely.
We do over a billion evaluations of policy a day in our
SaaS platform. We have added
quite a bit to the tooling ecosystem, which we'll show you.
We've got an open source project called Regula for checking terraform
using OPA, and we've also got a much
faster evaluator and better dev tools,
breakpoints and stuff like that. Okay,
I'm not going to read through this, but until OPA,
you really kind of had three choices. Two are shown here.
One was a proprietary policy as code,
which was usually expressed as some kind of pseudo
language baked into a vendor's product,
often a kind of subset of SQL or something like this.
And it was specific to that product. You still see that now with lots
of vendors out there? Oh yeah, we do policy as code, and you look under
the hood and it's something that only works with their stuff.
There are all kinds of problems with that. We as an industry are familiar with
those. The second one we don't have on here is people
trying to build policy libraries into general purpose languages.
I personally have seen a lot of these and I don't think any of them
are very good. And the reason is this is its own domain
and it can be done much better with a
domain specific language, which is what Rego is.
So open policy agent I mentioned, you can use it across lots of
use cases. There's a robust ecosystem and community that's
only growing, and that means your engineers will want
to learn it. Whereas if you tell an engineer, go learn some proprietary language
that's baked into some big enterprise
y product that doesn't usually, unless it just
becomes absolutely dominant, doesn't usually become a good career skill,
but OPA is pretty good career skill.
All right. A myth that needs busting
is that to do policy as code in the cloud,
you first have to do infrastructure as code.
That's not true. You can do policy as code
right now, no matter how you built your cloud infrastructure.
In fact, it's important cto get it in place.
If you haven't gone to infrastructure as code yet, it's important to get it in
place up front. Also, very few organizations standardize
on single infrastructure as code products. You might have some terraform and some cloud formation
and some ansible scattered around an organization. Well, if your
policy has code is dependent on infrastructure as code, you now need that
many policy as code solutions with different policies and rules. It's a
really bad idea. Well, you want to check policy up
front, but you need the same policy to work all
the way through into the runtime.
Yeah. So we believe that policy as code really has to take priority over
infrastructure has code. I mean, by all means do both,
but policy as code can be its whole own separate project.
Most of our customers that are implementing it do it that way. They don't
go and impose on the team that's building out terraform stuff to do
policy because it's a separate concern and they just
offer it as a service. And then ultimately, over time,
it becomes important enough that it's mandated.
All right, where you need policy as code
is throughout the entire software development lifecycle.
And they have to be the same policies,
like literally the same files, the same rego files in
OPA's case. Otherwise, you're going to get different
results at different stages, and that is going to sow confusion and
create vulnerabilities. So what do I mean by the whole SDLC?
You got to start in design, or at least you want
to, so that, like for example, we have
this project called Regula that's out on GitHub. I'll show it to you open
source project, and it will check your terraform plan
files against OPA policies. Well, those same
OPA policies can then be loaded into a CI CD
pipeline. So first you check your infrastructure
as code if you're doing that. But next in your CI CD pipeline,
you can check the dev environment post deployment
to see if it's valid and should be allowed to go to stage
or prod. Right. So you can gate your
deployments using policy as code, and then finally
you're not done yet. That's all the day one
stuff, it's day two on. That is hard in this
industry, right? Any of us who've built stuff know that. So you have to be
constantly checking against those same policies against that infrastructure.
Because the stuff is mutable, right? Somebody can have a maintenance
window and go in and make a change, and that's not in
your design or deploy stage, but now it's in your production and maybe
it's a dangerous change. So you need it the whole way through.
I would argue you absolutely need it
in the enforce and I would go enforce
first, then deploy, then design. Unless you want to go
across the board. It's really not that hard.
All right, let's switch from slides.
I normally spend a whole lot of time at the terminal, but this is
less a live demonstration and more a talk on
a topic. So I apologize for all the slides. All right. What I'm showing
you here is actually our diagrams
that we generated in Fug. And the reason I'm showing this is to contextualize how
we're using OPA for cloud configuration.
So just to make clear what fug
is going CTO do in this case is go scan your those environment,
collect all of the configuration information, and then we can do
computation on it, such as drawing diagrams and comparing to
OPA policies. So just a little explanation of what you're looking
at. This is the Internet. It's going into some different VPC
networks through Internet gateways, load balancers,
compute instances, et cetera. All right? And if I select
one of these things, I can get all of its configuration information.
However, using OPA, I can show errors
in compliance. So a bunch of stuff just turned red.
Those are things that are failing our policy as
code evaluations. Okay, so let's take a look at this VPC
network you can see down here.
VPC default security group should restrict all traffic.
Configuring all VPC default security groups should restrict all
traffic encourages. Least I'm not going to read the whole thing.
Basically, every time you build a VPC on AWS, if you didn't know this,
you get with it for free. A highly insecure security group
that allows egress on all ports, which is a really bad idea.
So we're telling you that, and the way we're telling you that is by evaluating
OPA a rego policy against that infrastructure.
Okay, so this is one way. And by the way, there's a version of
this thats is free forever for small scale deployments.
You can go CTO, fug dot Co and use it for free
forever. I think up to 1500 cloud resources,
something like that.
We've organized them in our own world into control families
that you might have heard of, cis GDPR, HIPAA, NIST, et cetera. We have a
few best practices in here where every time we kind of
perform an autopsy on a real breach in the real
world or do a simulation of it, we look for ways we can use
OPA to tell our customers if
they have vulnerabilities that the bad guys used in
that breach. And the answer is almost always thats there are new things that we
learn. So for example,
iam role assumption is a really scary one.
And I think I'm going to do another talk somewhere in this conference about
and show you and steal some data and that'll be fun.
Okay, so that's a little bit on how you can use it at the
runtime. This is running infrastructure.
But what about,
actually, I'm going to change gears here and I'm going to
say what is OPA? I've described it,
but this is openpolyagent.org.
The Styra folks are the inventors of OPA and
the maintainers of it. We mentioned before it's
declarative policy. And here you can see it for Kubernetes envoy
and application code. But what
I want to get to is this bit right here. So you've
got some architectural flexibility. What OPA is, it's a language
and then it's an evaluation of that language in
the runtime. You can use it in two modes,
those same implementation.
You can run it as a demon and basically stand
it up as its own microservice in your service architecture.
Or you can run, it has a library. And this is really nice
because depending on what your use case is,
one might be more appropriate. I mentioned we do lots and lots
and lots of OPA evaluation. So we run as a library because we can't afford
the network overhead, right. It's got to be fast. So we bake it
in, but you can also stand it up as a demon and then you have
less policy to manage,
right. In terms of where the policies live and so on.
It's a really cool thing. And you can go, let's go to their GitHub
here and it's
written in go code. And let's take a look at the adopters.
So these are folks who are using OPA. And you'll
recognize some of these names. Atlassian,
BNY Mellon, Capital one, chef,
Cloudflare, fuge were here. We were actually a very
early adopter this list has gotten much more impressive since
we kind of signed up for using OPA, Goldman Sachs,
Intuit, Netflix, Pinterest,
SAP. So, yelp, when you're
thinking about adopting an open source tool,
and by those way, when you adopt a policy as code tool,
you're making an investment that's going to last for a long time because you're going
to build up a bunch of code, right? And replacing
code is really expensive. I view all lines of code
as financial liabilities to the company.
They are things you're stuck to. Well, this should give
you some ability to sleep at night knowing that
this isn't going anywhere and in fact, it's going to grow.
So that's pretty cool. So, yeah, go check out open policy agent
itself. I'll show you a couple of
projects we've put out. And once I've
given you this tour, I'm actually going to open a code editor and
show you a little bit of code. But if you don't write code, don't be
scared, it'll be fine. I'm going to be really explanatory.
Okay. And you'll read some of these and you'll say, well, I could do that.
All right, so regular is for use with
terraform, and what it will do is
when you do terraform, you go through a step called the plan
stage. Regula will then
examine that plan against a collection of
rego policies, of OPA policies, and it will approve
or reject it based on whether it breaks those policies.
So you can see here we've built into
the open source tool, a bunch of stuff on AWS,
GCP, and Azure, making sure
33 89 isn't open and 22 isn't open, and making
sure kms crypto keys are rotated at some reasonable
frequency, et cetera. So a lot of this stuff comes out of the box.
You need OPA and terraform, or if you want.
Where is the link? Yeah, you can run it has a GitHub action.
So GitHub actions, if you've not used them, are really cool.
They're essentially spinning up containers in GitHub's
infrastructure and running it for you.
So you can just hit our GitHub action. You don't have to
install anything, and you'll
get that answer that way, but you can run it locally, too.
This is actually pretty much just a shell script
and a whole bunch of work we did in Rego.
Rego is quite powerful, and we've solved a lot of the
kind of annoying things about writing infrastructure policies in Rego
for you as libraries, but it's very, very simple project.
We also have out there a project, again open source on
GitHub called Frego, which is the Fugue rego toolset.
We wanted breakpoints. We're writing really fancy Rego at Fug.
We do a lot of this. So we wanted really good developer tools.
So standard OPA comes with a repl
and some other tooling, but we wanted, like I said, breakpoints and the ability to
go and change values and do the stuff that you do as a programmer
when you're writing sophisticated things. So we wrote Frego.
Frego also is a super fast evaluator of
OPA policies on large data sets, which is a
lot of what fugue does. So it runs like a hundred times faster than stock
OpA for that large data set use.
Uh, you're welcome to contribute to these. I mentioned the other one is
all Rego and OPA and a shell script.
This one's written in Haskell. So if we have any haskellers
out there who are into policy as code, you can check this
out. Okay, let's look at some
actual code.
All right, let's just walk through this real quick. In fact, I pointed
out this one to you when
we were going through the GitHub repo. So this is those
kms rotate rule, right?
So we can give it a name. We can call this package rules
kms rotate. Well, that doesn't seem like a big deal, unless you
can't give things names, unless you can organize things.
And this is why having a real domain specific language that's thought
through and is full featured, it has those capabilities.
Okay, so here we're just defining a couple of things. We're saying the resource
type we're looking for is AWS KMS key.
By the way, we can do this cool thing of mapping to controls,
right? So this is mapped to cis two eight,
and then we keep our own enumeration
of the rules we're adding into regular. All right,
so this is just kind of the setup. And then here
is the entire logic block. All right,
so what we're saying here is default,
allow equal false meaning by default,
don't allow things, allow equal false.
And then we say, but allow
if those input enable key rotation is true,
right? Very simple declaration and gets you right
to the point. So let's see if I can find.
Our team has been like cleaning up and organizing
so much stuff in here that the big complex regos
are now kind of abstracted into libraries, but this one's a
little fancier right here our package is rules,
VPC, flow log. And here we're doing an import.
Okay, we can import libraries. It's a real language.
And here we're saying the resource type is just multiple. In other
words, we're going to deal with that as we go. We've got our control mapping.
Hey, it's comments. Comments are important in source
code. This is a real language. I'm going to keep
saying that. But you need these features to have a maintainable
set of code. And policy has code. You're going to live with it for
a long time, right? So you have to have it be maintainable.
So here we're just giving some explanation.
Every flow log in the template. So flow logs equal fugue
resources. Now why does it say fugue resources? Because we've
given you a bunch of libraries like fug
reggae right here that are going to help you a lot. So here you can
see we've done a lot of work to
take all the fancy stuff and make it so you don't
have to do that with regular. So one of the
things I think is critically important when evaluating
a language I have like my first test, I don't care if it's imperative
or functional or object oriented, they're all fine for different things.
But the main thing I want to understand is, is it easy to do
simple stuff? One answer
has CTo be yes. And two, can you do really sophisticated
stuff and does it hold up well in both of those use cases? And I'm
very pleased that they designed Rego and OPa quite well.
And the answer is yes. So I'm not going to walk you through all this
code, but the important thing to take from this is
even doing sophisticated things is possible, right?
And this is 35 lines of code,
and a few of them are, it's probably ten lines of
actual logic in here. Not super hard to reason about.
Pretty easy, very easy to learn, actually. And you
can take advantage of stuff like all this work we've done in
already, abstracting things and things like regular.
And there are others out there doing this,
so some getting started resources. By the way, what I
would suggest the best starting place is,
and this is going to sound self serving, but honestly, it will let you see
what OPA can do without you having to invest any work,
is if you go to fube Co, let me show you thats you
can get this kind of evaluation of your existing
cloud infrastructure against all these control families in OPA.
And you can also cloud your own OPA into fuge, your own rega
for your own controls, and then you don't have to worry at all about
having to download OPA or learn the language. You can
start experimenting with the capabilities right away. On the other hand,
you can use the GitHub action on regular if you're using terraform super easily
out of the you know, if you're like me and you like to
download source code and compile it yourself and really look
under the hood, go to the GitHub repo at open policy agent and have a
blast. So these are the
resources I showed you. I think that's about
what I've got for you today. So thanks much
for spending your time with me. And by the way, I'm Josh at Fug
Fugue Co. Feel free to reach out
to me and I try to answer everyone who does.
So thanks very much.