 Hello. Thank you all for coming. My name is Jennifer Hammond, and I've been an engineer at Pivotal for about four years. I spent about the last two of those years working on the UAA, which for anyone who doesn't know, is the identity and authorization component within Cloud Foundry. And as part of that work, I've really had a lot of opportunities to connect with other teams that are using UAA, other release authors trying to integrate different pieces of the component, as well as working with customers, and learning a lot about where their pain points are with the UAA. Over time, certain patterns emerge. And after you get asked the same question enough times, you realize, OK, this is a usability problem. The existing CLI out there in the wild has many of these sort of problems. And so as a result, I decided at some point that I really wanted to try to rewrite the CLI in Golang. And that's the work I'm going to be talking to you about today. This started as a side project and kind of migrated into a real thing that's being supported by the current UAA team. We've had collaboration from people at several companies, as well as people from three different teams at Pivotal. I want to give a special shout out to Joshua Karp from 18F. He gave our very first unsolicited pull request. And for me, that was a real milestone, because it sort of validated in my mind, like, OK, this is something people are interested in. They think it's valuable. They're going to work on it, too. And in addition to that, gotten some really great Golang expertise from members of the PCFS team. And I can't tell you it's been a real pleasure to work with this group. So today, my goal here is for this to be accessible to everyone. I don't know what any of your backgrounds are, but often I go to these identity-related talks, and they're very, like, if you're not deep in the weeds of how all this stuff works, you don't get a lot out of it. And I don't want this to be that kind of talk. So I'm going to first say a little bit about UAA's role on the platform, just so we all have a shared understanding. Then go into some of the problems with the Ruby-based CLI that we've had and how that's informed some decisions for the new CLI going forward. I'm going to show a bit about what those interactions look like today, and then say a few words about what's ahead. But first, I want to tell a little story. So I flew in yesterday from California and in the US, where I'm from, all the electrical outlets look like this thing on the right. I always thought they kind of look like sad faces, but I don't know, maybe that's just me. So I was in my hotel room and sort of confronted by what you see on the left, which is this very geometrically interesting Swedish electrical outlet, not Swedish, excuse me, Swiss electrical outlet. And I was thinking, oh my gosh, how am I going to practice this presentation? I can't plug in my laptop. This is a problem. And I had planned ahead to some extent. I knew that in Europe and around the world, there's different standards. And so I brought some adapters. Turns out none of the ones I brought were going to work for this type of outlet. So I went down to the front desk and I said, please help me. I'm a stupid American and I can't charge my electronics. And of course, this happens a lot in hotels. So they had this universal adapter. And I thought, OK, great, like I'm all good now. It's going to be fine. But of course, I got it back to my room and I realized I actually have some additional requirements, which is that I not only needed something to plug an American plug into, it needed to accommodate this rather large charging brick on my Mac charger. And so that was like kind of a setback. I realized that using the other adapters I had, I could stack them together and build this terrible thing that sticks out about a foot from the wall. And that was working for a little while. The plug kept falling out. And it also just seemed like probably not good for the outlet. So I made some modifications. I realized, OK, I have these nail clippers, nail tremors, and I was able to actually modify this adapter to accept my electrical plug and move forward. And so the lesson that I wanted to take from this, the reason I'm talking about it now, is that adapters are extremely valuable. Like without this, I wouldn't be able to run through these slides in the privacy of my hotel room, but also fairly complex. And they need to be working just so. And that's the problem, I guess, the value proposition of the UAA within Cloud Foundry is that it's acting as an identity adapter. And in a world with many competing standards, all solving the same or similar problems in slightly different ways, the UAA is wanting to be that super adapter that will let you bring all of your identity information, no matter the source, and plug it directly into the platform. So I thought this is a good visual metaphor of the many different identity standards versus the super adapter that you want. And so here's a cartoon of Cloud Foundry. The idea here is that it doesn't matter or shouldn't matter for companies where your user information is living. It could be in an LDAP server, a SAML server, maybe a cloud identity service that you're using. And as long as those things are exposing some kind of standards-based interface, you should be able to plug those directly into UAA and have users logging in and pushing apps and doing all the things that we like to do with Cloud Foundry. Everything within the platform, and I've only shown a few of the components, of course. They interact with OAuth only, which is an identity standard we have for solving the problem of delegated authorization. And so this is a simple-looking diagram, but it's providing a huge value. And as a result, you see UAAs all over in our various different products in our ecosystem. Every Bosh director has a UAA inside of it. Every Cloud Foundry deployment has multiple UAAs inside of it. Many people are running concourse and authenticating using UAA. And in addition, the UAA is baked into numerous proprietary products, Pivotal's distributions that I've shown here. And just in a little while that I've been at this conference, I've talked to several other people about other products that are also using the UAA because this functionality is very valuable. Another thing that we see is most customers of any size are running multiple foundations. It's like they have many deployments of Cloud Foundry. And this is where the story gets kind of gross, where this integration between your external identity providers and the UAA gets pretty complicated as you add more and more things to this picture. I've only shown three here, but it's not uncommon to hear if customers are running 10, 20, 50, 100 Cloud Foundry deployments. And managing all this configuration is quite painful. And so the image I had in my mind as I was putting together these slides was like at Christmas time, when you pull out the lights because you want to create this magical atmosphere of the holidays. And but first, you have to untangle this gnarly mess of tangled up lights. It's just not quite delivering on the promise of what you really want to get out of it. And so if we're going to have a really scalable platform, we also need scalable administration tools because what we have already today is some tools that are fairly confusing for integrators and operators. It's like sometimes a bottleneck for them in managing these environments. It also comes back as like a tax on the development team. That's where I feel the pain. If I'm on one of these teams, if I'm on UAA, and I'm having to divert a lot of my attention to helping people manage and configure these environments because they're lacking some understanding or the tools that we have aren't meeting their needs. And the third and probably most important thing is that if there's opportunity for confusion or things take a long time to update your configurations and things, there's an opportunity to make mistakes, I would say. And this is not an area where you want to leave yourself open to making mistakes because there's a large security implication of doing so. So next I want to talk about some of the things that observations that I made, learnings, I would say, from my experience of trying to help people use the existing Ruby CLI. And so the number one thing is that install experience matters. Today to get the Ruby CLI, sometimes you tell people, oh, just install this gem. Gem install CFUAAC. And if you're a Ruby developer, that's like, all right, great. We're all good. But most people are not Ruby developers. And we see that actually in the real world, people sometimes need to do these things in air-gapped environments. Sometimes they're operating on a Windows platform where it's difficult to get Ruby installed. And even frankly, if they're not under any of those constraints, if you're not a Ruby developer, it's kind of like, it's just not reasonable to tell someone, first install a development environment that you don't care about in order to use this tool. Yeah. And so what we've seen across many different projects is a shift towards using Golang for their CLIs. This is what you see with Docker. You see this with Bosch. I could name a bunch of others. And it simplifies this process to simply download a binary and run it. And so that sort of was guiding our choice because we're sort of achieving this benefit. The Golang has made it very easy to compile binaries for different platforms. And also, we're able to leverage CLI frameworks because so many people are writing CLIs in Golang. There's actually really great tooling around doing that. So we don't have to reinvent the wheel on how do you parse command line options, things of that nature. So it's pretty easy. The next thing I sort of observed is that ecosystems tend to seem to guide people's expectations for how to use a CLI. I can't tell you the number of times I've had people say, OK, I found this documentation that told me do this command uac-token-client-get. But what does that mean? And the name of the command doesn't communicate any information about it. They're just like, they're very confused. So cosmetically right away, one thing that stands out is that we're not even naming this CLI in the way that other projects in this ecosystem are doing so. So if the Bosch CLI is called Bosch and the CF CLI is called CF, CRETAB CLI is called CRETAB, then naturally the UAA CLI should be called the UAA. And so that's what you'll see now. If you go check out the go lang CLI, it's called UAA. And this gives it an additional benefit that there won't be any confusion as we update documentation. You'll see documentation using this new CLI, and it'll have this different name. I think that's one of the pain points that the Bosch community, users of the Bosch CLI, felt in the migration was that if you were looking at a piece of documentation, it wasn't immediately clear if you were dealing with the Ruby CLI or the newer go lang CLI. So this will help with that as well. Another thing that we see in these other CLIs that I consider to be part of our ecosystem is they follow this verb noun syntax. Sorry. There is, yes, I'll show the link at the end and you can go check it out. So it's still a work in progress, I would say, but there's quite a lot of functionality already in it. So this, coming back to this slide, sorry, I didn't say it, this question was, is the CLI available today? And the answer is yes. All right, so coming back to this slide, we wanna follow along with how other people are doing things and follow this verb noun. In the UAAC Ruby tool, we had this sort of crazy sub-command system which leads to confusion for a number of reasons. People are often, I've been asked many times, what does token owner get mean? It means get a token with the password grant type. How would you know that? You wouldn't. And then people are also like, what's up with this get keyword? Why do you need that? And it just doesn't really make a lot of sense. So we've kind of shifted to this verb noun syntax. I think these names are a little more clear and they're quite long. There's obviously opportunity to introduce some aliases and things, but at least as a first pass, we wanted to get in line with these other tools. Number three I would say is that people do want to help themselves. And when they come to me for help, usually they've gone through a number of different things already. They try to Google search. They've often tried to view help information in the CLI, which the Ruby CLI in the past didn't really include much useful information. If they're customers, they've often reached out to our commercial support at Pivotal and the Pivotal support person is escalating to me because they actually don't know the answer. And so that's just like, that's not a good experience for anybody. So I really tried to push for having much better help inside the tool itself. And if you look at, these are just some example questions that we get a lot. Like why didn't my token contain the expected scopes? Or why do I need a client to get a token? Some of these like reveal a lack of understanding of the identity domain, the basic concepts about OAuth, others like this last question, what skim filters does UAA support? To me that says the person has some knowledge about what the spec is that they're trying to leverage. And so there's a wide range of knowledge levels that we see in our users. It's important to like try to meet them where they are. And so, how that manifests in the CLI is that we wanna have as much useful information in the help strings as possible. And I'm sure you've probably all had the experience of looking at a man page, trying to figure out how to use a command and really not coming away with any useful understanding. So I don't wanna promote that. And I've tried to include some realistic copy-pasteable examples in the help strings. And also some like just really straightforward troubleshooting tips for common problems. Some of these other ones like meaningful error messages, that's more aspirational, that's like a longer term thing that will require some changes in the UAA, I would say, the UAA server. And actually like just language, using the right words so that when people view something they don't understand it in the help, they can go to the internet and find other resources. When you add all these things up together, these are like low tech, super low tech things, but communication is really powerful. And you can actually give people a better experience simply by putting the information where they need it. And this is just a screenshot from one of the help strings for searching about users that's demonstrating like how can you query the UAA for certain things? Like how would you find a user whose email is bob at example.com? Well, there's an example right there. And that's one less question coming to me in Slack because we have like actual real examples here. And thing number four, and this is the last sort of category of major problem I would say with the old tool is that it didn't lend itself to automation. And that's an essential use case when you're talking about scaling out your usage of UAA. Here I've shown some example output from one of the commands of the old CLI that for some reason it looks like Yamalish, but it's really not. And you're missing things like a colon here, a bit further down, there's a list, a space delimited list that's like oddly formatted. And if you're trying to like take this output and script it in any way around what you're getting back, like you're not gonna have a good time. It's like really the worst case scenario because you initially have the reaction like, oh yeah, this is great, it's just Yamal and then no, it's really not. It's not Yamal at all. And so super high priority has been the outputs from this new tool need to be parsable consistently. So far we've done a lot with JSON because JSON, all JSON is also valid Yamal. So if you have a tool that wants Yamal, you can input JSON, it's kind of neat that way. We've had like explicit testing around exit codes to make sure that when an error has occurred, the tool's gonna like tell your script that something bad happened. And then also thinking about making sure we can accept non-interactive inputs and environment variables, things like that. So that concludes sort of the overview of learnings. And next I wanna shift into a bit of an example. It's a bit contrived. I want us to imagine that we, the audience, are trying to create a client registration in the UAA for the CF CLI for the first time. So it's as if that CLI doesn't exist and you're trying to develop it yourself. So as in any OAuth thing, well first, OAuth is a standard for solving the problem of delegated authorization, which is a lot of words. What it basically means is you as a user want to use a piece of software to perform some actions on your behalf. And the OAuth standard describes these four different roles that are involved in that type of thing. So resource owner, that's the user. I think we all know who that is. In this scenario that we're talking about, the client, the thing that wants to perform actions on your behalf is gonna be the CLI itself. The auth server, that's the UAA. Its job is to authenticate users. In other words, verify that they are who they say they are because they provided the username and password. It also keeps track of what permissions users have and knows how to issue and validate tokens. And finally, the resource server, which is any API basically that requires a token to access it, would be said to be a resource server. So in our world, these roles, they map like this. So I sort of called some of them out already. Cloud controller is the resource server. The client is the CLI. And so if you're in a scenario where the user wants to do a CF log in, I hope we've all had this experience, you type, you, the user, type that into your computer. You provide your username and password to the CLI. The CLI will turn around and make a request to UAA to request a token. It passes some information with this request. It's gonna send the client ID and client secret, as well as the username and password. And assuming that all checks out, the UAA is gonna reply back with the token that it asked for, which the CLI is gonna save off in a text file. So that when the user types their next command, the user says, hey, I want a CF push. Well, now the CLI will say, okay, I can do that for you, because I have a token. So now I'm gonna request, I'm gonna post your app over to Cloud Controller with this token. And if all goes well, you'll get a 200 back. So what you've seen here is a password grant type Oauthflow. And so, if I'm trying to create a new integration between UAA and a client, the first thing I would do is sketch out something like this and figure out what the different roles are. Having done that, I would move on to actually setting up those configurations to test them out. So with the new CLI, or actually with any CLI, the first thing you always do is target the environment that you're hitting. I just put in a local host URL, but in real life, it would be some kind of UAA in the cloud. The next thing I need to do is retrieve a token with an administrative scope, because I need that token in order to do the other actions, like creating a client, creating a user, all those things. So yeah, I just do this get client credentials token admin command. Most distributions or instances of UAA will have an administrative client in them. Obviously, your secret's not going to be admin secret. But you would have to look in your deployment manifest or your ops manager credentials tab. It depends how you deploy your UAA. But someone available to you should know how to find that secret. And having done that, this UAA context command, you can use that to view the token that it retrieved. So that's like kind of getting set up. Once you've done that, you can create a client like this. And there shouldn't be any surprises here. We have to provide the client ID, which is CF, and a client secret. In this case, the client secret is empty string. And the reason for that is that with the CF CLI, we want anyone to be able to download CF and point it at any cloud foundry deployment. The only way to accomplish that is to have a constant value, a known constant value for the client secret. And someone back in the day decided that empty secret was the good value to use for known constant client secret. You have to tell the UAA what type of grant types are allowed to be used with this client. And finally, what scopes does this client need? Now, the real CF CLI is requesting a lot more scopes than just Cloud Controller admin. But if you're putting yourself in the shoes of the person who's creating that client, you're not gonna add everything to begin with. You're gonna start small and iterate. And so for this example, I just put in Cloud Controller admin as a good starting place. Yeah, so that should succeed because we have a token with administrative scope. And before we can test it out, we have to also create a user. So this is kind of what a create user command would look like. I really enjoyed Dr. Seuss as a child. I was lately enjoyed sharing that with my nephews. So I always use Dr. Seuss in my examples. Pretty straightforward, you need a password and an email address. The names are optional. And we also need to assign membership to our test user. So we're giving him membership in the Cloud Controller admin group. So this is where it all comes together. So now that we have that client and we have that test user, we can use this different token command, get password token, passing all four pieces of information. The client ID, the client secret, the username and the password to get that token. And this is exactly what the CF CLI does today. So from there, as an app developer at the developer of the CLI, I can continue iterating like adding memberships and adding scopes to build up a token with all the capabilities that I need. So where are we today? Gentleman in the front asked earlier, is this available today? And the answer is yes. There is a publicly available Go CLI. It has most of the CRUD operations that you need on major resources like clients, users and groups. We've also implemented all of the token commands for the major grant types, as well as the UAA curl command. And so the initial goal for this project was to replace the functionality of UAAC so that we can fully deprecate it. There's a few things still outstanding that I've listed here. I think external group mappings seems like the most important one because I know people use that quite a lot. But overall, it's getting very close to feature parity with the Ruby CLI. And looking ahead, I think I've talked a lot about these things that are important for app developers. Where we really wanna get to is having a nicer experience for platform operators who are configuring identity. This is future. This doesn't exist today. But we've seen and learned from the experience of people with the Bosch CLI and the Fly CLI that when you have these really large configuration objects you need to manage. A file-based configuration is really the way to go. And so something like this, where you would have a YAML file to provide that configuration for your identity zones and identity providers, I think is where we're headed. So that's all I had to say. Thank you all for listening to my talk. I hope you'll check out the repo here at Cloud Foundry Incubator slash UAA CLI. Give it a spin and let us know any feedback. Let me check the time. Okay, we have about five minutes left, so if anyone has any questions, I'm happy to take them.