Learn Python with Talk Python's 270 hours of courses

#294: oso authorizes Python Transcript

Recorded on Friday, Oct 23, 2020.

00:00 When we think about accounts and security, we often think about identity,

00:03 logging in and proving who we are. But for many applications, especially internal apps at large

00:07 organizations, that's just step one. The next step is what can we do and what can we not do?

00:13 On this episode, you'll learn about a new library called Oso. It's a declarative way to create

00:18 policy code that maps your mental model for who is allowed to do what in your system.

00:22 We have two guests, Graham Neary and Sam Scott from the Oso Project to tell us all about it.

00:27 This is Talk Python to Me, episode 294, recorded October 23rd, 2020.

00:32 Welcome to Talk Python to Me, a weekly podcast on Python, the language, the libraries, the ecosystem

00:50 and the personalities. This is your host, Michael Kennedy. Follow me on Twitter where I'm at

00:55 M. Kennedy and keep up with the show and listen to past episodes at talkpython.fm and follow the

01:00 show on Twitter via at Talk Python. Before we get to the interview, let me tell you about a brand new

01:06 course that we just launched. At Talk Python, we run a bunch of web apps and web APIs. These power

01:11 the training courses as well as the mobile apps on iOS and Android. If I had to build these from scratch

01:17 again today, there's no doubt which framework I would use. It's FastAPI. To me, FastAPI is the

01:23 embodiment of modern Python and modern APIs. You have beautiful usage of type annotations. You have

01:29 model binding and validation with Pydantic, and you have first class async and await support.

01:34 If you're building or rebuilding a web app, you owe it to yourself to check out our newest course,

01:40 Modern APIs with FastAPI over at Talk Python Training. This is the first course in a series

01:45 we're building on FastAPI. And for just $39, it'll take you from interested to production with Fast

01:51 API. To learn more and get started today, just visit talkpython.fm/FastAPI or click the link in

01:58 your podcast player show notes. Sam, Graham, welcome to Talk Python to me.

02:03 Thanks for having us.

02:04 Thanks.

02:04 Yeah, it's great to have you guys here. I'm excited to talk about this whole managing what

02:11 people can do on computers from a slightly different perspective from the authorization

02:16 side of things, which I think gets underserved in programming in general. So that's going to be a lot

02:21 of fun. But before we get to all that stuff, let's start with your stories. How'd you get into

02:25 programming in Python? Sam, you want to go first?

02:27 Yeah, sure. So I think for me, it was probably the kind of typical programmer entry, which was

02:34 I had a very monotonous data entry job, which I was like, surely there's a better way. I was

02:40 young enough that I reached for BB macros. A few years later, though, I actually ended up picking up

02:46 Python, primarily through my math degree. I had a professor who was very into number theory and

02:52 worked on the SageMath package.

02:54 Oh, yeah. SageMath is fantastic. Yeah, I've had William Stein on.

02:57 It is incredible. Oh, nice.

02:59 Yeah, it's cool what they're doing.

03:00 Yeah. I actually dug up, that was my first open source contribution. There's a SageMath ticket

03:05 from a good nine years ago.

03:06 Okay, cool.

03:07 Yeah.

03:08 What kind of math were you studying?

03:10 So that was during undergrad maths. And so that stuff was, yeah, that was kind of the number

03:14 theoretical side of things. After that, I actually went on to do a master's in cryptography

03:18 and a PhD in cryptography and security, which is...

03:21 Oh, nice.

03:22 ...how I got here, basically.

03:24 Yeah, yeah. It's sort of indirectly.

03:26 Roundabout leads you here.

03:28 Yep.

03:28 Graham, how about yourself?

03:29 I actually, I took an entry-level CS course when I was an undergrad. And actually, at the

03:35 end of my undergraduate experience, which took me way farther than I ever would have expected

03:40 it to. And I don't get to do that much programming on a day-to-day basis, but I try to whenever I

03:45 can, including at a recent company hackathon. So I still like to dabble when I can.

03:51 Yeah, yeah. Super. These days, you both work at Oso?

03:54 Yeah.

03:54 Give us the rundown on, well, I guess, maybe introduce what Oso is, your company, since you

03:59 both work there. And then what do you guys do day-to-day?

04:01 Yeah. So Oso is a company. What we're all about is putting security in the hands of developers.

04:08 That's how Sam and I got to know each other. That's the thing that we really connected on

04:13 as the thing that we want to do. And the way that we think about doing that is by building

04:19 consumer quality developer tools for security. And so the area that we're starting, which is the area

04:24 that we'll talk to you about today, is authorization. But that's really sort of the ethos of the company.

04:29 And what's nice for Sam and me, I think for a lot of founders, it's not always clear how to think

04:35 about division of responsibility. But for Sam and me, it tends to be pretty clear.

04:39 I take responsibility for the business side of the company. So sales, marketing,

04:45 financing, everything on the operational side. Sam is responsible for everything on the technical

04:53 side of the business. So running the engineering team, Sam built the first versions of the product

04:57 by himself, and we share responsibility for the product roadmap.

05:01 Yeah. Sounds pretty clear. And I think it's a cool project. How long has the company been around for?

05:06 It's not super old, right?

05:07 So we've been working together for a little over two years, but we only open sourced the project about 10 weeks ago.

05:15 Okay. So in the open source side, it's quite new, but yeah, still two years is pretty young for

05:19 a company. And it's easy to think of the stuff that you're building just as technology. And it's clearly

05:25 like developer tools and APIs and things like that. But man, that marketing stuff and getting the word

05:30 out and sales, without that, you just can't go, man.

05:34 Yeah, that's the hard stuff.

05:36 Exactly. Give me some cryptography and some compiling and language interop, but don't make me write a landing page.

05:43 Now, I'm serious, though, that is a super hard part of, such a critical part of technical companies,

05:51 open source companies, and so on. And it's easy to overlook that side.

05:55 Yeah, absolutely. But it's fun.

05:57 Yeah, for sure.

05:58 So we're going to talk about one of the three A's. I was recently told there might be four A's in this

06:04 whole identity authorization sort of story, but I don't remember what the fourth one is. So I'm going

06:09 to go with the three A's. We've got authentication. We've got authorization. So authentication, who are

06:15 you? Authorization. Okay, now I know who you are. What can you do? And then auditing, what have you

06:21 done? Right? You guys, you're a fan of the middle A.

06:24 Yeah, that's right. Yeah. And I think you just about nailed it. And a lot of the products out

06:29 there really focus a lot on authentication, which is, I think, the thing that most, for instance,

06:35 consumer users would be most familiar with, like logging into it, getting a login page, having

06:41 your username and password, doing things like password reset, or more recently, things like

06:46 two-factor authentication, how all that stuff is managed. That's the authentication bit, just making

06:51 sure that you can get in the door.

06:52 Even the sign-in with Google, sign-in with GitHub is really primarily about just, usually that's about

06:59 two things. One, who are you? And then sometimes it's about what part of GitHub do you want to let

07:05 this app access, or what part of this app do you want to let access your Google data? But it's not,

07:10 it doesn't work in the reverse way. It doesn't tell you what the user's allowed to do on that

07:14 application. It's just connecting those two apps together from a data side. So even the social

07:20 auth stuff is really just authentication. Yeah, those lines get pretty blurry, right? Because you're

07:24 allowing some other website to access information about yourself so they can check who you are.

07:28 So there is an element of authorization going on between those two services. But you're right,

07:33 like the result of that is authentication.

07:34 Yeah, I guess when I say that there's not any really authorization, I'm thinking that

07:39 that doesn't tell the app what you're allowed to do, but it does tell, like say Twitter,

07:44 what, like, are you allowed, is this app allowed to tweet on your behalf according to Twitter?

07:49 Yes, exactly.

07:50 Right. But it doesn't help within your app. Like if I want an app, I want to know like, okay,

07:55 this user, they can view invoices, but they can't create invoices.

07:59 Precisely.

08:00 But they can't ever see the bank details of anyone like that.

08:03 Right.

08:03 There's no social auth that's going to help you with that side of the story is what I was thinking.

08:07 That's exactly right.

08:08 Right. That's fundamentally an authorization question, what you just asked.

08:12 Yeah. Okay.

08:13 Exactly.

08:13 Cool. And so this is the core problem that you guys are trying to solve. And we're going to talk

08:18 about some of the open source stuff that you've done and the Python APIs and all that. But maybe

08:24 let's just continue this part of the conversation by talking about some common access patterns.

08:29 And what is out there? Like we talked about the social auth and what that means. We talked about

08:33 creating users with usernames and passwords. And what are some of the patterns you all are seeing

08:38 out there?

08:38 Yeah. So basically every application out there needs to let its users in some way,

08:44 shape or form, see their data and do something to their data. And so fundamentally that's doing

08:49 some kind of authorization. And then you'll have, so in a basic like social app, that might be like,

08:54 what posts can you see and what posts can you edit or something like that? And then you'll have.

08:59 Yeah. So in some sense, I guess there's like an implicit or default authorization that every

09:04 application has. And it's usually I can see my stuff in public stuff and that's it, right? Like,

09:10 right. There's no rules like, okay, when I go to Twitter, I just see my stuff in public stuff,

09:16 right? I could go to my profile, but there's no expectation I would ever be able to see someone

09:21 else's profile and those sorts of things. So I guess if you don't do anything, that's generally the

09:26 access pattern people have is I create an account and that account can see its stuff.

09:30 Yes, absolutely. And I think that's kind of like the common paradigm in particular in like a consumer

09:36 application context, particularly when you start to look at like business to business applications,

09:41 you end up with like very quickly, the patterns get a lot more complex. So could be an HR application

09:49 or a CRM application or a medical records application. And very quickly, what people will do in building

09:57 these types of apps is they'll reach for a pattern called roles. Well, they'll group a set of

10:02 permissions or capabilities together, they'll lump them together into something called a role.

10:06 They'll say anyone that has this role, like admin or billing or nurse or whatever it may be can do

10:13 these sets of things. And then if you want to be able to do those things, you got to get assigned that

10:17 role. And that's kind of like a handy thing, because it means that every time you want to make sure that

10:21 someone can do those things, you don't have to repeat that work, which is kind of nice, right?

10:26 But also kind of limited, because effectively, what that's doing is it's creating is sort of

10:32 representing all your permissions as like a two by two, you basically have a bunch of roles on one axis,

10:37 and you've got a bunch of capabilities on another axis. And the truth is that most apps don't,

10:42 they're sort of like underlying like data model isn't a two by two, they may be,

10:47 they may have all kinds of other things going on. They may have, they may want to represent

10:51 hierarchical patterns, like to represent an organization, they may want to represent inheritance,

10:56 they may want to represent some kind of graph. And so like, oftentimes, after you adopt a role model,

11:03 Let me throw an idea out here, and you can tell me what you think of that. Like, so for example,

11:06 if I'm a manager at a company, I can see my work, right, plus my team's work.

11:12 Exactly.

11:13 Right. But I don't want to see another team's work. I don't want that person to be able to see

11:17 everyone's work, just the people for whom they are the manager like that scene. And then you know,

11:21 how do you, you can't really easily manage that setup, right?

11:25 That's a perfect example, because that's not a role. That's like a manager in that context isn't a

11:31 static thing that you just assigned to someone that's kind of dynamic, based on where you sit in the org,

11:36 you might be a manager of one team, you might be a VP, in which case you're a manager of like five teams.

11:42 And so it's not this thing that's assigned to you. It's more like a function of maybe some other data

11:47 that sits elsewhere in your application. Yeah.

11:49 So you end up having to do all kinds of crazy things to hack around the role model and make

11:54 that work for your application, which is all the kinds of stuff that we see. That's where it starts

11:59 to get fun.

11:59 Yeah, exactly. So that's probably means like, instead of just having say, a decorator or some

12:05 simple if statement that says, if they are a manager, there's usually like some custom logic

12:11 checking in that section, right? There's like code that's been written somewhere,

12:14 the checks, you know, like basically does those things and looks like I'm a manager,

12:19 but who do they manage and so on. Then all of a sudden, this roles idea sort of,

12:24 it somewhat falls down and you're coding in the logic into your app, right?

12:28 Right. And there's like, you know, other examples of where the sort of roles model stops and other

12:34 things begin. And you sort of have to start just adding more, whatever it is, if statements,

12:40 or maybe you bring the logic to some other part of the application, because that's where it makes

12:43 more sense to you. But yeah, the example you gave is a perfect one.

12:47 The thing about that kind of stuff that scares me is what if I forgot, right? I've got a web app

12:53 with hundreds of endpoints. One of the one section is like an admin section. And if that

13:00 doesn't do the proper checks, all sorts of badness is going to happen, right?

13:04 Absolutely.

13:05 So you put your code in there. I mean, I don't know. How do you guys feel about that? Because

13:09 I'm always like, I'm triple checking it. And then I'm like, I got to go back and check this again.

13:13 Like this is, this could be bad.

13:15 It's super, super common. And that's where we see, we see a lot, you know, at larger organizations,

13:20 that's where often like a security team will spend a large portion of that time. I've heard

13:25 security teams who have like their own little regex that they use to go and find like every method and see if

13:29 it has the piece of code they're expecting to see, or they sit on every code review so they can make

13:33 sure that one's not missed. That for people without that kind of security team though, then yeah, it's

13:37 just a case of hoping you don't forget it.

13:39 Yeah.

13:40 Oh, you might also even do the, it might also be kind of the opposite of that, which is that like,

13:44 you might be good enough to include the logic everywhere, but rather than trying to

13:48 sufficiently extend your like roles model to account for all the different like intricate scenarios

13:54 that you're trying to properly represent, you might just say, ah, we'll just like, let this person be

13:59 an admin or something like that, just so that they can do the thing that they need to do inside your

14:04 application. And then all of a sudden what you end up with is all these scenarios where people, or

14:08 for instance, like internal services are over-provisioned because that was the fastest way to make it

14:13 possible for them to get done the thing that they needed to get done.

14:16 Yeah.

14:16 Which can be equally painful to undo later on or risky.

14:21 Yeah. It definitely sounds risky. Like it's, it's easy to have the admin, non-admin flag and just

14:26 go with that. But that's probably fine for like a small team, but as you grow, it's no longer going

14:32 to work.

14:32 Talk Python to me is partially supported by our training courses. Do you want to learn Python,

14:39 but you can't bear to subscribe to yet another service at Talk Python Training? We hate subscriptions

14:45 too. That's where our course bundle gives you full access to the entire library of courses

14:49 for one fair price. That's right. With a course bundle, you save 70% off the full price of our

14:55 courses and you own them all forever. That includes courses published at the time of the purchase,

15:01 as well as courses released within about a year of the bundle. So stop subscribing and start learning

15:06 at talk python.com.

15:12 talk about some of the coding approaches in like current Python projects. And I guess I talked about

15:19 one, Sam, you put down as like a DIY, do it yourself. And that's the, well, if we got to have managers and

15:26 people for whom they manage, we've got to, we just write some code and sort of put that logic in there.

15:32 And maybe you've got that overlaid on some groups. Maybe give us some of the common approaches

15:37 you might see in like common Python web apps.

15:39 Yeah. So overwhelmingly common is that this is kind of seen as just the regular code in applications,

15:46 just the things you have to do in an app to build it. So, you know, in that case, it just ends up

15:51 baked into, you know, every method you have is going to have a certain amount of this logic.

15:54 Like I think either you're going to see people who are just sprinkling this throughout the code base,

15:59 adding them where it's necessary. And that's just kind of like handles or like considered something

16:04 they just deal with. Or sometimes people will try and go the approach of like stretching that out,

16:08 pulling it out through into, you know, maybe something like a decorator, like you said.

16:11 And that ends up becoming this like 500 line decorator, which has, you know,

16:17 10 levels of nesting and if statements and things like that.

16:20 Yeah. Decorators are already hard to put your mind around. Although that's what I do on my stuff.

16:25 I'll have like a, I'm like a permissions decorator. At least the thing that I like about that,

16:30 even though it has some disadvantages. The thing that I like is I can go to the functions and I

16:35 don't have to read the function and know, is this thing being dealt with? Like,

16:38 does it have the decorator? Then the function is okay. You know what I mean?

16:41 Yep. Yep, exactly. And there's, so I mean that, you know, that is like one set of things and it's

16:46 not like nothing exists to do these things we're talking about, like depending on the application,

16:50 right? So a lot of the kind of stuff we've been describing doesn't have to happen in the codes.

16:55 It might be stored in a, like I didn't see management system or something like, you know,

17:00 active directory. It's typically, this is a place where you can store all the information about

17:04 users and you can add them to groups and assign them permissions to different things.

17:08 That is sort of like the manual admin approach, which probably a lot of people might be familiar

17:12 with as a way to maybe like manage permissions inside an organization, but it's not kind of suitable

17:17 for the kinds of things we've been talking about for like a, an application,

17:21 B2B application or a consumer application where you don't want to have someone manually going into

17:26 like an active directory thing and like assigning people roles and permissions.

17:28 Right.

17:29 So that's kind of like one set. And then I think similarly, some of the Python frameworks out there,

17:33 for example, have built-in things for similar patterns. There's Django has things like Django admin,

17:38 which again is sort of baked in UI and system to manage like users and permissions,

17:43 but it's kind of more of like the AD flavor. It's like a UI where someone might manually go in

17:48 and configure, you know, all right, Sam is in this group and this group can do these things or Sam

17:52 can do these permissions, not for the sort of like, how am I going to provide a consistent interface to

17:58 all of my end users? Like how do I do that sort of dynamic automatic configuration?

18:02 How do you feel about multi-tenant apps? So I've got a cloud service and maybe I've got one company

18:09 and within that company, they have certain roles, but then other customers come along,

18:14 they buy a setup for their system. You know, think like Slack or GitHub with organizations or

18:21 something like that.

18:21 So you just gave two very interesting examples. I think GitHub is a pretty good example of doing

18:27 multi-tenancy and in a reasonable way in that you have your single user account and you can belong to

18:32 many organizations. You can have different roles inside the organizations. You can have,

18:37 you can even have roles inside repositories, although it's not that obvious, but you can be a,

18:41 you know, owner or a collaborator of a repository. Right. And it sort of kind of like handles all of

18:45 those in the sort of reasonably consistent way that if you don't dig too deep, it kind of makes sense.

18:50 But you can imagine you're on the backend to support that. What are they having to do is have a reasonably

18:55 complex data relationship model between users, organizations, repositories. If you go deeper,

19:02 right, there's like teams, sub-teams, infinitely recursive sub-teams, things like that.

19:06 Yeah. Yeah. Slack, I feel like they did the, at least initially, they kind of forced you to create

19:12 an account for every workspace. So presumably on the backend, this looks like somewhat different

19:16 where they didn't try and make it so that like you could map a user to multiple organizations with roles.

19:20 It's like you have a user inside an organization and they have a role.

19:24 Yeah.

19:24 And this, I think this is probably, I can imagine this might be something based on how they originally

19:29 did authorization. It sort of might've even painted them into a corner where they are now sort of stuck

19:33 with a model. It's hard to get away from.

19:34 Yeah. Side note or sidebar. I, I, the Slack authentication model drives me crazy,

19:39 but I can't just log in and see what groups I'm like.

19:42 I'm with you.

19:43 I got to remember the pre, the pre, the, the, the.

19:46 It's brutal.

19:47 First part of the domain that belongs to it. And then the password may or may not be the same.

19:52 And it's like, what am I, why am I doing this? It's so brutal, man.

19:55 Yeah. I'm not saying it's because the authorization approach was wrong, but maybe it was.

20:00 Well, but I mean, it just, it shows that you need to be careful about this, like how you

20:04 think about this. And yeah, the fact that we are talking about it at all means that it's

20:10 like an issue for users and people experience in an ideal world. You shouldn't even think

20:15 about it. You're just like, well, oh yeah, I guess I didn't really think about it, but

20:17 yeah, that it is restricting to me what I should be doing and it just works. Right.

20:22 Yep. Yep.

20:23 Yeah. And you bring up an interesting point.

20:24 It's why people say architecture is like wet cement.

20:30 That's right. For a while. Yeah.

20:33 Yeah, absolutely.

20:34 Yeah. I was just going to say the idea about it being exposed to users as well. This is a

20:38 really interesting one. It's, I think a lot of the struggles or frustrations people have

20:43 with security, but it's done similar things as well, where you end up, you're trying to

20:46 use a website or something and have these like crazy complicated permission role systems

20:50 where you're trying to like decide what you can do within the app. And when you talk to

20:54 teams like that, you realize it's because they've like influenced an authorization

20:57 system and they're basically just like exposing the internals of that to the end users. So

21:02 you kind of almost need to understand how the app works in order to decide what you can

21:06 do inside it. And that is just kind of crazy.

21:08 Yeah, for sure. So you all saw a problem out there and Sam, you built this policy system,

21:14 this authorization system. And I guess one of the things we want to be clear about is I see this as

21:19 an advantage. Is it is not as specifically not about logging in users, managing their passwords or

21:26 their party off stuff. It's about once you know who someone is, regardless, like you can have using

21:31 password, you can have Google login, whatever you feel like once you've got that now, what can they do?

21:36 Right. That's exactly right. And in addition to that, it can be can have them multiple different

21:41 ways that people authenticate or have identities, right? They might log in the web app, they might

21:45 have an API key. And authorization might depend on that. That was like a main input to these decisions.

21:50 Yeah, interesting. Like so for our mobile apps, for the training courses, we have you log in with

21:55 using password, but then it actually exchanges an API key, basically, the login gets your API key. And

22:01 then from there on, it's exchanged with all the calls. So yeah, I hadn't even really thought about

22:06 the API side of things as well. But that makes a lot of sense that you'd want to separate those.

22:10 Yep.

22:11 Yeah, it doesn't matter how you log in, if it's API key, or you do with the username passwords,

22:15 like, all right, well, now we're going to figure out what they can do. So I guess tell me what problems

22:19 it was that you saw, you're like, well, we got to do this differently. And then tell us about

22:24 Oso, and like how we can use it in Python and so on.

22:28 Yeah, absolutely. So the, I think the biggest problem that we saw out there is that pretty

22:34 much every single engineering team we've seen out there that we've spoken to has repeated this work

22:38 themselves from scratch. In all the ways we just discussed, right, whether it's through their code,

22:43 as a decorator, whatever it is, like everybody's repeating the same work. And nobody's going to get

22:48 it like perfect on the first attempt. And so they end up, you know, having to iterate and refactor

22:51 over time and add things. So they don't quite get it right.

22:54 Well, and another thing, the way I think about this stuff is this adds no value to your application

22:59 in a like sort of unique feature aspect. It's like one of those things that it has to exist.

23:05 It's table stakes for being in the game, but it's not like somebody's like, I love that app because

23:10 the author is so, or the author is so, like, it's only like drag and molasses if you have to do it

23:17 yourself and you get it wrong, but it's not a bonus. So it's the reason I say it's not something

23:23 you want to like try to invent in or whatever, right? You just want it to work really well and

23:27 get out of your way.

23:28 Absolutely.

23:28 Exactly. It's one of those, if you do it right, they won't even know it's there kind of thing.

23:32 Yeah, exactly.

23:33 So yeah, so that's basically what we're out there to solve is to make that experience

23:37 for everyone involved, like that much better for the developers who are building this and spending

23:41 time on it and hopefully not getting it wrong to the end users who are like dealing with these

23:45 crazy two by two matrices of permissions to navigate. So basically the way we solve this

23:50 is through open source policy engine called Oso. And it's kind of two main pieces of this.

23:54 There is the policy language called Polar. This is what you write your authorization logic in.

23:59 I can speak about that in a bit more in a sec.

24:01 Yeah.

24:02 But that's sort of piece one. And then piece two is the library, which is the policy engine

24:06 itself reads in those policy files and basically has a very, very simple API, a single method

24:11 effectively to make an authorization decision.

24:14 Right. And forward, like I was looking through some of your docs and say for Flask, you have

24:18 some built in integration.

24:20 Yeah, that's right.

24:21 Right. You create a Flask Oso thing and you just say initialize the app, you give it the

24:25 Flask app and then you tell it what routes to authorize basically.

24:29 Exactly. Yeah. So the library itself is actually available for multiple languages.

24:32 So currently we support Python, Ruby, Node.js, Java and Rust. So that's kind of like the core

24:39 of this. And then we build additional framework integration. So you're exactly right.

24:43 You know, we have one for Flask and one for Django. And for each of those, we try and provide

24:47 sort of framework idiomatic approaches to authorization. So, you know, I think, you know,

24:52 Flask is pretty keen with things like decorators. With Django, it's more about malware and automatically

24:57 registering and making available like the underlying data models.

25:00 How hard would it be to add it to a new shiny framework that didn't make your list? Like,

25:05 I'm super excited about FastAPI right now.

25:08 Yeah.

25:08 Yeah.

25:08 Right. Looking really nice, but probably you don't have integration with that yet. It seems

25:13 like it probably wouldn't be that hard to replicate what you've done with Flask or something along

25:17 those lines.

25:19 Each framework integration is effectively equivalent to how hard it is to add Oso to

25:22 your application in general. And we're talking about pip install Oso, then creating new Oso

25:28 objects, loading a policy file, and you're good to go.

25:31 And so, you know, in the case of Django, for example, we'll register automatically like the

25:36 Django models because the policy file can actually access objects and classes from your application.

25:41 So, you know, there's a little bit of work there where we just like automatically register those

25:44 for you.

25:44 Right. Yeah. It's very Django-like to do that.

25:47 Exactly.

25:47 Nice. Okay. So I talked about this complicated story of I want to be the manager, but there's

25:54 only some people where I am the manager of, and I could be managed myself and so on.

26:01 There's other people who I have no relationship with other than co-employee and so on.

26:05 One of the options was we could write code in the application to do that.

26:08 Yep.

26:09 It sounds like this Polar Language policy file is where that would go here. Is that right?

26:15 Yeah, that's right. So the Polar Language is a declarative language. It actually takes

26:19 inspiration from a logic programming language called Prolog. It's sort of this decades-old,

26:23 pretty well-established logic programming language. But Prolog itself typically is,

26:28 it's kind of been known to have a pretty high, like, barriers to entry, kind of hard to learn.

26:32 Yeah.

26:32 So we sort of, you know, that's what we started with, though, but then we basically pushed

26:35 ourselves to make it as easy to use as something like Python. And so, like, along the way, you

26:39 know, we've added stuff that you would expect to find in Python. You can look up attributes on

26:44 your Python objects. You can call methods. You can use variable and keyword arguments. The logic

26:49 is written and the letters as opposed to, you know, some arcane glyph, things like that.

26:53 Yeah.

26:53 So that's the language. So that's Polar. And then so, but basically, you know, by building

26:57 on something like Prolog, it actually makes writing, expressing logic, like you just, like you said,

27:01 around representing complex hierarchies or things like that, it's actually a very, very powerful way

27:06 to represent those. You can write a recursive rule like that, which says you're a manager of an

27:10 employee if you are the employee's manager or you're the employee's manager's manager or something

27:14 like that. You can write like a little recursive rule in a couple of lines. You can now use that

27:19 like throughout your policy. So you could write another rule, which would say managers can read,

27:23 or like a user can read some employee, some personnel data if they're the target employee's

27:29 manager.

27:29 Right.

27:29 And, you know, those two rules now combine together. You have, you've just written those

27:33 like kind of in your flat policy. And the underlying engine is basically the one that kind of navigates

27:37 through those searches through and tries to find if that's true or not.

27:40 Cool. And I'm looking through those syntax here. It's clearly not Python, but it's not that far

27:45 from Python. You know what I mean? It's like a Python person could jump in here and go,

27:50 okay, well, I'm creating an object. Yeah. I got to put the new keyword, but new person

27:53 and such and such. That seems pretty straightforward.

27:56 Yeah.

27:57 Yeah.

27:57 Yeah. The rules look like methods. They have type specializers, which look exactly the same

28:01 like Python type ones do, but they're actually enforced at runtime.

28:05 Okay.

28:05 Things like that.

28:06 So how's data get from like my application over into one of these policy execution instances,

28:13 like calling and running the policy. Basically I've got like a user in my, I don't know,

28:19 request session or something like that.

28:22 Yeah. So they just get, they get passed straight in, right? So the, the also library in the Python

28:26 app, you just pass it in regular objects from Python. You pass in the request user, you pass

28:31 in the thing they're trying to access. And basically we sort of the policy engine, there

28:36 is a sort of a, an interface between the sort of Python specific library and the internal policy

28:41 engine that it lets Python deal with the objects, but it can do the sort of policy evaluation

28:45 over those objects. And it doesn't need to know what they are. It's just like, if you say user

28:50 dot username, once the policy evaluator gets there, it'll be like, Hey, Python, what's the,

28:55 what's the user's username? And it just says, Oh, it's this, it's Sam. And it continues

28:59 on. It's like, cool. Now I know it's the string. Yeah. Nice. Super cool. So one of the things

29:04 that's interesting about Python and some of the other languages you mentioned with the

29:07 integration, right? Like Ruby, for example, is that we have a REPL read eval print loop,

29:12 right? If you just type Python, hopefully that runs Python three, not type Python three. And

29:17 you just get your triple, triple greater than REPL. And you can start typing in Python commands

29:22 and going from there. And I do feel sometimes people are learning Python. They lean too heavily

29:27 on that. Like they don't just go create a file because it's like a pain to make any corrections

29:30 and stuff, but it is really nice as an exploratory mode. And what surprised me when we spoke first

29:37 about this is you guys have a REPL for this polar policy thing, right?

29:41 We do. We have, we exactly, we have a REPL and we have a debugger and the debugger as well.

29:46 And a debugger. That's right. Because like, okay, as you said, right, it's clearly not Python,

29:51 but it kind of looks like Python, but the underlying model is different to what we're expecting.

29:55 It's not imperative. It's logic based, it's declarative. And so we appreciate there is

29:59 a degree of like having to learn how the language works. And so for us though,

30:02 if you're going to build a language, you want the power of a language.

30:05 You want to have a REPL that you can dive into and like test things out and check

30:08 something as simple as syntax or just to sense check that you got the expector result back.

30:13 And so we have a REPL, you can load in your policy files and it allows you to sort of

30:17 interactively query them. So, you know, you can just like dive in and make sure things are

30:21 working as you'd expect.

30:22 Yeah. I suspect that that would be hugely valuable. I mean, I haven't actually tried it,

30:26 but you know, I think of things like YAML configuration files and stuff and you're just

30:31 like, it's not working. Why does it not work? You know, it's like, it's those times you just

30:36 want to yell at your computer. You're like, why don't you work? It looks right.

30:40 You know, like, ah, indentation.

30:43 Yeah. Or something, right? Oh man. It's like, oh, it's coming back as a single key,

30:48 not a list in the way you put it in YAML or whatever it is, right? Like having the ability

30:52 to like step through it is really interesting.

30:55 Yeah. The debugger is great fun for exactly that. You just drop into the debugger and just

30:58 kind of like hammer next and just like watch it doing its thing.

31:01 Yeah. Do you have, or have you dreamed of any like IDE integrations like VS Code or PyCharm

31:08 or more broadly IntelliJ? Yeah. So I think dream is partially the right,

31:13 the right word for it. You know, we currently do have syntax highlighting available for VS Codes.

31:17 I think there's actually a Vim config out there as well. There is so much stuff we want to do with

31:21 like the, you know, language server protocol and hooking up the debugger to IDs like VS Codes that

31:26 you get that experience like in your, in your IDE. Yeah. There's a ton of other stuff we want to do.

31:31 Cool. All right. Well, I've been beating my example of manager, employee to death. Give us some more use cases or you might see people using this kind of stuff.

31:41 Yeah. So I think one of the, one of the kind of initial users we have for this is,

31:46 is kind of your prototypical authorization use case. They are building electronic health record software

31:53 deployed currently in hospitals and the stuff they come up with like every day just astonishes me.

31:59 Some of the authorization, but you know, there you get like, can imagine the really classical stuff,

32:04 which is like, you can doctor can see your patient's records if they saw them in the last seven days,

32:08 or if they have an upcoming visit, like that's the kind of level of granularity,

32:11 like a hospital might want to go down to. Yeah. Yeah. That sounds like a perfect use case.

32:15 You know, just here's a general heuristic for deciding whether some company or organization

32:21 might have a good use for this. If they use SharePoint, what do you think about that?

32:27 That's a pretty good one. I feel like SharePoint is like, it's just like all these weird permissions

32:31 and it's all about like, well, we can't really, I don't know. Just, I always feel like, all right,

32:35 this is like messed up enough that you really need some help here.

32:38 So I thought you're going to go maybe a different direction with that, which is if you would be

32:42 sort of embarrassed or out of business, if some of your data was exposed, then you probably need this.

32:47 Also. Yeah. Yeah, for sure. For sure. All right. So give us some more examples.

32:52 So we, I mean, you spoke about like the social media one at the beginning, which is

32:55 kind of an interesting one because there's a, there's a few slides of that. And actually we

32:58 recently did a bunch of like blog posts on a little social media feed app that we're putting together.

33:02 But even some of the simple ones that, you know, that you mentioned can be reasonably complex.

33:06 Users can see posts they posted or they can see their friends posts. They can see them,

33:11 you know, if maybe if they were like tagged in a post, things like that, they can be pretty involved

33:15 in like having to really look at like the post and where it was put and like who was referenced in it,

33:18 things like that. There's kind of the two sides of that as well, you know, there's like the users of that.

33:22 And then internally how a company like Twitter manages how employees can access things.

33:28 And obviously this was a pretty hot topic not too long ago.

33:31 It was super hot. Yeah. There was a, gosh, I I'm blanking on the details. Maybe you remember

33:37 I didn't tell people, but yeah, there was, it had to do with celebrities, right?

33:40 Right. It was, I think it was effectively the internal employees of Twitter were able to do way

33:45 more than they should be, such as post on behalf of anybody. Exactly.

33:49 Yeah. Which no one should ever really need to have, but I imagine it's a pretty convenient way to build

33:53 it. Well, you want to test how it looks.

33:55 You see that a lot and you see a lot for legitimate reasons, right? Like your customer is having a

33:59 problem. They're like, Hey, I'm unable to, maybe it's not tweet, you know, but I'm, you know,

34:02 I'm unable to do this in my account. You want your support to be able to like step in and help them

34:06 out and be like, Oh yeah, like I can see your permissions aren't quite right. Let me try this.

34:11 So like, you know, there are very legitimate reasons that you'd have that much power, but

34:13 it just like overlays this like entire extra dimension. It's like your user submissions and

34:18 then like your customer support reps behaving as if they're a user, but we're different and so on.

34:23 And it's one thing if that's like internal data and okay, so they probably shouldn't be able to do

34:27 this, but if you log in as them, they can like in the app, you could maybe do a little more within it,

34:32 but it's another to have that on production in a live broadcast of the world. Like I can make

34:39 this random politician or celebrity say this, do this thing. And to a varying degree, it'll be

34:46 believed, right? Yep. Yep. And then, yeah, so that's, so those are good ones. And you know,

34:51 then beyond that, all of the kind of typical cases you can imagine very common inside like an HR thing

34:56 because of like the manager employee relationship you mentioned, right? Very organizationally driven up

35:00 in access control. So in HR or payroll, things like that, you'll see this a lot.

35:04 Similarly in like banking and finance, like any of those cases where you imagine that the data is

35:09 sensitive and you have some concept of groups or hierarchies, organizations is where this like comes

35:14 up a lot. Yeah. Yeah. Cool. So you said the language is available or the API is available for a lot of

35:21 different languages. And one of the things that's interesting here is you all decided to build it

35:26 with Rust. That's right. Which is a pretty hot, neat language. And at some point though,

35:32 Rust has to talk to Python. So I've seen a few examples of people creating the traditional example

35:38 is I'm going to create some lower level thing for Python. So I'm going to use C. Maybe I'll go crazy

35:43 and use C++, but expose it as C. But I think I'd rather write Rust. How did you, how did you pull that

35:51 off? How did you do that integration? Yeah. So the ecosystem for sort of embedding Rust in Python

35:56 or actually, or even vice versa, you know, embedding Python and Rust or calling into Python from Rust.

36:00 There's actually, there's a few tools out there which solve that kind of specific problem

36:03 that they have interfaces specifically for exposing a Rust struct as a Python class, things like that.

36:09 We didn't really have that option available to us because we wanted to support multiple languages.

36:12 We sort of needed some of an API that was simple enough that it wouldn't matter the language or the

36:18 runtime. You can bind the Python and Rust tightly together as an option. And probably if your goal

36:23 is only to write it as a base for some Python thing, it might make sense. But exactly. That

36:27 wasn't your goal, right? No, exactly. So instead we sort of, okay, one of the engineers on the team

36:34 had this pretty great vision of how this would look, which is sort of like a kind of an event driven API.

36:39 So like all of the Rust code is driven through like a very, very simple API from like the host language

36:44 side. So from like Python or Ruby, it's like a simple API, just kind of like do the next thing.

36:49 Like the internal polar evaluation is done through virtual machines. It's like virtual machine, go do

36:54 your next instruction, go do your next instruction. And it kind of returns a JSON blob of data back to say,

36:59 like I said earlier, Hey, what's the username field on the objects number one, which maybe is the user

37:05 type samples. So there's kind of this, this really nice like conversation between the Python and Rust

37:09 where Python is like, Hey, do more work, do more work, do more work until Rust comes back and says like,

37:13 I need more information, which means that like, there is no, when, when the policy is not running,

37:18 there's no like background thread. There's no, there's nothing like running there. It's Python

37:23 is free to kind of pause that virtual machine for as long as it needs. In the case of things like node,

37:27 we haven't done this for Python yet, but in the case of nodes, if you have asynchronous codes,

37:31 that all just works. It's like super nice.

37:34 Yeah. Oh yeah. That's cool. That would be nice in Python. Also my mention of FastAPI earlier.

37:39 Yeah. Yeah. That one's all about the async and await. So it's not quite yet a big deal,

37:44 but it's like some of the new frameworks are going down that path. At the same time,

37:48 you could still use it. It just won't benefit from the async and await, I would suspect.

37:51 Right. Exactly. So where this would matter, and this, and I mean, this would be essentially a pretty

37:55 important thing to do for something like FastAPIs. If, you know, as I said, the, because the policy

38:00 language can call into the application to fetch data, that called might itself resolving like a

38:05 database query. Yeah. And so maybe if you're running multiple threads, you're trying to

38:08 serve multiple requests, like you're going to want that async so that the policy is asynchronously

38:12 getting that data back. Yeah, for sure. Every time you can await some other external resource,

38:17 you're just better off for doing it. Yeah. Exactly.

38:20 Okay. Very cool. Well, it sounds like a neat integration and I guess it's a challenge I didn't

38:26 really expect. Like I figured you would have to integrate it with Rust, but I didn't expect like the,

38:30 we needed to be sort of bi-directional communication and work across the different languages. That's a

38:36 pretty good accomplishment. Yeah.

38:37 Yeah. It was, I mean, it was a lot of fun to build. I have to say though, the hardest part of it all was

38:41 the, the packaging and CI, funnily enough, because now we have this Rust library we're trying to add to

38:48 a, add to the Python package. We, I can't remember what number we're up to at this point, but we have

38:53 maybe like 300 CI jobs for every operating system, Python version to test like every combination.

39:01 So you want to do like build a wheel for like macOS on Python 3.8, macOS on Python 3.9 and so on. Yeah.

39:09 Exactly. So you have the, there's like the many Linux, I think it's a format would be it or a spec or

39:14 something that we use the kind of the many Linux Python approach so that we can build all these,

39:18 pre-build all these wheels, including the Rust code. But once you get them out,

39:22 you want to make sure that those 50 different wheels you built are all work still.

39:25 Yeah, exactly. Exactly. Is this interaction, this Rust Python interaction layer,

39:32 part of the open source stuff that you have out there?

39:34 Absolutely. Everything is open source. Yeah.

39:37 Yeah. Actually, we'll probably see a blog post coming fairly soon on how we built that. Cause I

39:40 think it is, it's like a really nice, simple approach to doing this kind of thing. And

39:45 I'm personally a huge, huge Rust fan. That's kind of a big reason why we're using it. And so I'd love to

39:49 see people taking this approach to building this like cross platform, cross language,

39:53 you know, Rust cores. I think that'd be awesome.

39:55 Yeah. Neat. All right, Graham, let me throw it back to you with a business question.

39:59 Sure.

40:00 Yeah. So we've been talking about how cool it is that this is open source. And yet we started off a

40:05 conversation saying you guys started the business two years ago. I'm really fascinated and admire

40:10 companies that are able to make legitimate, meaningful open source things, and then use

40:16 some interesting extra, the thing that you get more if you support them or if you buy some product or

40:23 service from them. And it sounds like that that is the kind of thing you all are building as well,

40:28 right? Because the library and the debugger and the REPL and all that stuff is open source on GitHub,

40:32 people can fork it today. And that's that, right?

40:35 Absolutely.

40:35 Okay. So what's the story? What is your specific plan here?

40:38 Yeah. So in the near term, we're focused on open source. And the reason for that is we believe that

40:47 the right way to build this company and the right way to build this community is to put enough weight

40:53 behind the body of people who are actually writing code in Polar and giving them everything that they

41:02 need to be successful. And so that's like the focus for us for the next year, two years plus.

41:07 When we think about, obviously, we're a company and we have every intention of being around for the

41:11 long term. And so the way that we need to do that is to create a sustainable business. So the way that

41:15 we think about doing that is by offering a path for teams that want to run and secure Oso in production

41:22 and giving them things that make that really viable and easy. So I'll give you some examples.

41:27 You know, right now, Oso is packaged as a library. Imagine a scenario where you want to run a bunch of

41:33 Oso libraries in a microservices context. And we've had folks already ask us for this today. So now

41:39 you've got a bunch of libraries with different policies running across a bunch of different

41:44 services. And you want a way to ensure that those always have the most up-to-date policy, the most

41:49 up-to-date version of the library. And you're doing that and they're all properly versioned and so on and

41:54 so forth. So an Oso service that would handle something like that is one way you could imagine

41:59 monetizing.

42:00 Right. Because if you're one of these complicated SharePoint sort of organizations, there's stuff

42:05 everywhere, like everywhere. And it's so easy for like one app to get its policy out of sync with the

42:10 other. And how do you know you've got them all? Like, it just sounds like a nightmare.

42:13 Yeah. Or security teams equally have asked us, I mean, Oso being a library on the critical path

42:19 of every request puts it in a unique position to be auditing requests, which is something that you

42:26 talked about back at the beginning. And this is something that a lot of security teams,

42:30 surprisingly, really struggle with. It's not an easy problem to solve. And but it's something that

42:36 this particular piece of software is in a unique position to do. And so you could easily imagine

42:41 Oso providing auditing capabilities to security teams in the future, showing them who was authorized

42:46 to do what at what point. And because we're making the authorization decision or so, we can actually tell

42:51 them why they were authorized. Oh, because they were in this role, because they sit in this department,

42:55 and they report up to this person, stuff like that.

42:58 Yeah, that's super interesting. Because you're right, you are already in the middle of all those

43:03 exchanges. So it's easy for you to add that visibility.

43:07 Yeah. So I mean, for us, as I said, like the philosophy is relatively clear, we want to give

43:12 developers the tools that they need to be successful with Oso period, and that technology will always be

43:17 open source. The way that we think about the technology that we'll use to sustain the commercial

43:23 side of the business will be the sort of organizational pieces that larger businesses rely on in order to

43:30 be secure, be compliant, run large operational teams and applications in production.

43:36 Yeah, cool. Well, I think that's a it sounds like a pretty solid idea, right? You've got this legitimate

43:43 open source thing that's meaningful and useful, and grow that and get the companies that got the deep

43:49 pockets who are often unlikely or unwilling or incapable of contributing back to open source,

43:55 give them a thing that they'll pay for that it will indirectly basically give back to open source.

44:00 Absolutely. I mean, as an example, before this, I worked at an open source company called MongoDB,

44:06 and over for many, many years, and over that period of time, we invested several hundred million

44:13 dollars worth of R&D into the database product, which is directly straight from the companies that

44:19 were providing revenue to the business through the paid products. So it's a very clear tie between,

44:25 you know, the companies paying money to the company building the product itself.

44:28 Yeah, I was going to ask you about MongoDB as well, like what inspiration you got there. Because

44:32 I think one of the things that were started, at least me and the folks who I've spoken to are

44:37 starting to realize is that it doesn't matter how much money a company has, they won't donate.

44:43 The idea of a donation is like, I don't know where that goes into the accounting spreadsheet. It doesn't

44:49 make sense. I can't tell my shareholders that we donate a million dollars to Django. Because I don't know,

44:56 it just doesn't make they just can't put that into their structure, right. But we pay for service level

45:02 agreements, we pay for additional services, we pay for better support, like that fits into their

45:09 accounting software. And I think that's the story that's going to work. And so if you can offer them

45:14 something more, they're very likely to pay for it to get that like you are.

45:18 Yeah, absolutely. And I think for us, again, like whatever, there's books upon books upon books

45:22 written about this topic, not in the context of open source software, but like in the context of like

45:27 philosophy over like, in the like, you know, 16th, 17th, 18th century, you know, people writing about

45:32 tragic of the commons, this is not a new topic, like in the world. Yeah.

45:36 But in the context of like, open source, our philosophy is we need to give something that's

45:41 good enough for someone to be able to use on their own, where they wouldn't feel like they're going to

45:45 be held hostage if they're not going to pay money. That's just not a sensible thing for anyone to do.

45:49 We try to put ourselves in the shoes of our users, we would never adopt a product where we felt we'd be

45:54 at risk of being held hostage. But yeah, but instead, give them an opportunity where, hey,

45:59 here's something that you can, that you can take advantage of, and that you can get value from.

46:03 And then if you find yourself in this other scenario where you think you want to, you want to get

46:08 something like auditing, you want to get additional visibility, you want this way to run something at

46:12 scale, then we're going to be there for you. And we're going to provide a commercial product for you in

46:16 that situation. Yeah, that's fantastic. And I'm a huge fan of MongoDB. I told you this earlier,

46:21 before we hit record, but all of our stuff runs on Mongo, and it's has for five, six years. It's been

46:26 beautiful. I actually just looked at the Stack Overflow developer survey from 2020.

46:33 And under the most wanted database, MongoDB is out by like 5% above Postgres. And then it's like,

46:39 those are the two that are way out front. So pretty neat. What lessons did you take from that,

46:43 your time at MongoDB that maybe you wouldn't have otherwise brought to this venture?

46:48 By far, the number one thing that I learned there is focus on the developer. And I mean, if you look at

46:55 the mission and vision of our company, it's we put security in the hands of the makers. That is

46:59 all we care about. We have a singular focus on developers. If you woke up anyone on the team and

47:07 shook them at night and you ask them, who is the number one focus of this company, I guarantee you that

47:11 anyone would say developers. And that has been clear from the beginning and will continue to be

47:16 clear for us. And that was definitely the main thing I took away from my time at MongoDB.

47:20 Yeah. Yeah. Super cool. All right. Awesome. Well, I think we're about out of time,

47:24 but what a neat project and I wish you guys good luck with it. Let me ask you the final two questions

47:30 though, before you get out of here. Graham, I'll start with you first. If you're going to write

47:33 some code, what editor do you use these days? So you do some, not a ton, but if you are, what are you

47:38 using?

47:38 It was definitely VS Code.

47:40 All right. Right on. That's a popular one. Sam?

47:42 Yeah. I think that's probably because of my love of VS Code and I've forced it on Graham.

47:48 Yes. Influenced by Sam for sure.

47:51 He went through his computer, uninstalled all the stuff that wasn't VS Code. Well,

47:55 you got to edit something. Here you go.

47:56 Text edit is gone. Sorry.

48:01 Yeah. It's kind of stunned me how VS Code's like gradually seems to be taken over the world,

48:06 but yeah.

48:07 It's interesting. I find it surprises me a little bit because it came out of the whole Microsoft

48:11 side of things. I thought that there would be a lot of communities that would go, just no.

48:15 Yeah.

48:16 But it's somehow it's hit the right notes and people really love it. So yeah, it's definitely

48:22 successful these days. And then a notable PI PI package, anything, Sam, you've come across maybe

48:27 that like cool libraries like, oh man, you should really know about this. Or maybe we did our Rust

48:32 integration with that or so on.

48:34 So funnily enough. So one of the things I find always hilarious about Python is sometimes I'm not

48:39 even aware if I'm using package or it's just built into the standard library. Yeah. So like,

48:44 I'm a big fan of like all the typing stuff that Python has been like gradually adding in.

48:48 I think partially that's because I went through my like Rust phase and now I'm back and running all

48:52 the types. So definitely all the typing extensions.

48:55 I love the type stuff. I put it all like all the Python code that I write on the boundaries,

48:59 like say not every bit of code, but where like some part of code is written and some other part

49:04 is going to be sort of externally consuming it. Types go on that straight away.

49:08 And yeah, I think it's another standard library stuff, but I love all the metaprogramming stuff

49:12 you can do with Python. It's, you can really do some crazy stuff with it, but it's, it's kind of fun.

49:18 Yeah. Awesome. I'll throw two things out there for people that are like really related there. So my

49:24 py is a static type checker that will verify all the types you put in are consistent. And then there's

49:30 my pyc, which will actually compile the native code. Some of your Python based on those types.

49:36 I understand. I haven't done anything meaningful with it, but anyway, a bunch of fun stuff around the

49:40 types out there. Indeed. Yep. Yep. All right. Final call to action. People are interested in

49:45 letting someone else handle their authorization and some library, maybe putting that into one of these

49:50 polar files. How do they get started? What do they do if they want to get started with your projects?

49:54 You guys go to a oso HQ.com probably the fastest way. There's a big button on the front that'll take

50:00 you to the quick start. I would check that out. Awesome. All right. Well, thank you both for being

50:03 on the show and for working on this project for the last couple of years. It looks really helpful.

50:07 Thanks for having us. Awesome. It was great to be here. Thank you. Yep. You bet. Bye-bye guys.

50:12 See you. Bye.

50:14 This has been another episode of Talk Python to Me. Our guests in this episode were Graham Neary

50:19 and Sam Scott. It's been brought to you by us over at Talk Python Training.

50:22 Want to level up your Python? If you're just getting started, try my Python Jumpstart by Building 10 Apps

50:29 course. Or if you're looking for something more advanced, check out our new async course that digs

50:34 into all the different types of async programming you can do in Python. And of course, if you're interested

50:39 in more than one of these, be sure to check out our everything bundle. It's like a subscription

50:43 that never expires. Be sure to subscribe to the show. Open your favorite podcatcher and search for

50:48 Python. We should be right at the top. You can also find the iTunes feed at /itunes, the Google Play

50:54 feed at /play, and the direct RSS feed at /rss on talkpython.fm. This is your host,

51:00 Michael Kennedy. Thanks so much for listening. I really appreciate it. Now get out there and write some Python code.

51:05 We'll see you next time.

Back to show page
Talk Python's Mastodon Michael Kennedy's Mastodon