 Hi everyone, so I think I'm recording now, let me see, hope everyone can hear me. So this is going to be a quick demo although it may depend on the times because I want to wait until we can see a sync on Azure and it's probably going to be around maybe 10 pass, something like that. So yeah, so let's see if I have time to do a quick intro before that happens. Anyway, and that's a random guess because I've been writing down when it actually did the sync and it's quite random. So if a couple of planets align and then the moon as well, it may happen, but we'll see. Anyway, I reckon around 10 pass. So let's see if I can go quickly through the basics before that. So ACIM is just basically a protocol that allows us to synchronize users and groups, although at the moment to be only support users and just a few features. From a identity provider such as Azure, Alt and so on, they may have an active directory with a few users and we may want to synchronize those users with other applications. In this case is GitLab. It's a few requirements. So at GitLab, we have the group SSO and that needs to be configured first, which is basically these settings over here. We have these enabled. I don't mind showing the fingerprints or anything because this is just one of instance they have anyway in digital origin. That needs to be configured. Then we have this feature flag that hopefully in the future can be removed, but we need to enable it first. And then there's this new configuration. Unfortunately, I think it just got merged on Friday evening, meaning that I couldn't get an image with this to install in my instance. So I don't have this final bit here, which is just to generate the token basically. I already have done that using the console. So it's missing here, but I manually do it. In the future I'm going to have this, hopefully in RC3, I think. But the rest is merged and what we supported at the moment is these three endpoints, create, update and delete. Delete is the provision. The configuration itself is pretty straightforward. It's just click and generate the SCIM token and then on Azure it gets a bit more complicated. Before, I'm going to quickly show you that and hopefully before the next sync happens. So this is the provisioning tab, which is where we configure all of that. There's the SSO tab here. This is the application that I install. I'm using the group SSO, which basically, if you go through those settings, which is not part of SCIM or anything, it's just the normal group SSO. You basically end up configuring this page here, this single sign on. And then after that there's the provisioning tab, which is what's important here. We have bad luck because it just synced on 03 again. It was a bit random, so 03. It was just 13 minutes. So hopefully, it's not going to sync again until 20 something. So we got time before we do some changes and then we see this syncing, which is what I wanted to show. So the next thing is configuring Azure. But before that, anyone have any questions so far? I know I did this a bit quick, so let me know. Yeah, just one question. So this screen you are showing now is the Azure portal. So when you sign up, you get this screen or how do you get this one? So yeah, that's a good question because it's not even easy to get here. So basically, this is obviously the identity provider's portal in this case is Azure. And when you go to the portal itself, I think there are some resources, I think, linked from the group SSO page where you configure the group SSO. It tells you see your identity provider's documentation. And there's this thing for Azure. And this is basically what I've done. And it guides you through that portal actually. And you can see Active Directory. So that is the thing. You need an Active Directory thing. And in here, basically, you need to create a new enterprise application. All of that, again, is all in here. So I'm not going to stay much longer here. But in enterprise applications, I already configure this one, which is GitHub Test. And then there you go. You reach this thing. There's obviously loads of terms, loads of links. So it's a bit difficult. But I think as long as you follow the documentation, then probably we won't get lost. Does that answer your question? Yeah, definitely. Thanks. So for the benefit of testing this, when other tests in the future, obviously, they might test with Azure or something else, specifically for Azure, is there a cost to say associated with creating an enterprise application and maintaining the test set of users? Yes. So I could only have done this because I requested a trial. And I think it lasts like one month or two months, maybe. And after that, I additionally requested through support that they extended my trial to continue testing this. And so, yeah, this is a cost associated. Obviously not for me. But if you want to keep maintaining this, we should probably have a proper account. I think we may have something already, I don't know. But I didn't ask because obviously, it was just, yeah, it was easy to set up for me just using the trial thing for now. But yeah, we do need a proper account. Cool. So, yeah, as I mentioned, there's the singles and L page. And that documentation together with this will allow you to configure that. Yeah, I won't dig into this because it's just not part of the SCIM. But the provisioning link, it is. And in here, we have, sorry, this is the API, configuring GitLab, and then configuring, sorry, SCIM, let's see, if the top part goes, I can click on it. Maybe this bit. Confirmation Azure. Yeah, so there's a few things to do here and once we have the token from GitLab, we have to configure the provisioning and the mapping. Basically, we have to enter the unencrytized which GitLab already gives you. So it gives you this URL and the token, basically. Then we can click on test connection to see if that's working. And if it's set up, then you say, yeah, it's authorized, blah, blah, blah. And then it's good. Then this important, because if anything fails, then it will send you an email there. And this is important for the cases when we have an error or a timeout, something that doesn't respond, like GitLab is done or something, then we will receive a notification there. I think that's pretty much it for the admin details. Then we have the mappings and this is a bit tricky. But once we click here, now that we implemented these three endpoints and the API, which is here, so we have a way to get a list of some of the users, we can get a single sum of the user, create an user and update and then remove. This is not being used by Azure because we do an update with an attribute, which is active. Identity removal, if active is false. Where Azure is normally, you set this to false and then normally we just get rid of the users straight away. We remove the identity and remove the group membership. Where Azure then waits one month until it sends that elite, which for us is not useful, but it's already implemented. So if the user is still there, it will do the same thing as we do when we receive the active flag as false. It will just get rid of the membership and delete that entity so they couldn't sign in using Azure. So back to the configuration, the mapping. Yeah, this is basically, we have a few updates here and this is how, this is the, where the name of the attributes as Azure names them, like obviously the ID, blah, blah, blah, and then this is the mapping that we need to use for us. Some of them are really following the SCIM protocol, like emails, blah, blah, blah, work. That has to be like that. I want to follow it strictly. There's a few things here that I changed. Mainly the object ID set to the ID, which is the the object ID is an UID that Azure generates and is unique. And that identifies the user and it's also the same as the extend UID, which we have being, I think we call it something else, name ID. But this name ID essentially ends up as the external ID in the love. The external is a field in the identity, extend UID. And that's how we match the user, basically. So, as long as that's set to the, then, some small things that we have to do, so we map the object ID as the ID, the external ID is the same. This is because, this is a bit of a workaround, because I have to map the external ID to see here, obviously to the external ID again, because when we update a user, when we get a user or query for users, or delete a user, we always get the external ID as the ID. But when we actually create the user, for some reason it doesn't pass the ID. So, I have to pass the external ID to know that beforehand. Even though in the mappings, and I'm going to show you here, there's an advanced options here. We can click on edit attributes and you will see that it's primary and it's always required. But for some reason, it doesn't send, it doesn't get sent with the create endpoint. So, as I work around, and this is something you need to take into account, I just pass the, I just duplicate that as the external ID, basically. So, I can get that information from the create endpoint. Let me see the one thing provisioning. Well, that's pretty much it. But before, let me just double check when this was synced. So, it says, I'll refresh this actually, on three, because I think it's about to be synced soon. And I want to do a few things first before that, which is, in users and groups, we have one in there, which is Gen4 as a test. I'm going to remove that user, which basically means that in GitLab, at the moment, we have these members synced. Gen4 is user4 there. So, if I delete it, I will expect that to get removed with the next thing, within a sync in GitLab. So, let me just remove that one, move the assignment, and I'm going to add users to this group, which means that adding a user will sync the user. So, that was user4, I think. I'm going to add user5, for example. Okay. So, we have a new user there, and we deleted one, which means that in the next sync, we will see user5, and we won't see user4 there, if the sync goes well. And we can then also look in the locks to see what happened, and dig a bit more into these later. But, yeah, I just want to do these now, because then when the sync happens, we can actually see an action. Back to the configuring the provisioning. Let's see what I mean. So, the mappings, basically, at the moment, we can't, it's pretty much the same as the default from Azure, but there were a couple of changes that I mentioned to do with the object ID, mainly, so we can pass the ID, and we have that unique identifier. The other thing that I couldn't work around is when I edit a user, there's an email field, and it doesn't matter what you use here, it never gets synced. There's nothing getting passed as the email, even if the attribute is mapped here. So, there's a mail attribute, which I may not have enough, but that's because it doesn't work, basically. So, if I add a new mapping, it's probably a mail one, and it should target email equals work, something like that. It's really a sign, so it doesn't come up there. So, that one is actually mapped to the, let me see, username somewhere. Yeah, use a principal name, and this is because, as I let you out, an email field, well, it's not an email field, but it's just a username, but that's the word for now. So, we can add the email there, and then it will it will get synced as the email, because we need the email for creating an account. So, let me just go up here. That would be this one, basically. Another thing we do is we pick the username for gilab as this bit here, and that's mapped here somewhere, here, mail nickname as the username, because we do, you need the username as well. So, that's what we use, basically, this one, and it doesn't matter if this user five is already, is existing already, because in gilab, we just add a new number there until, until it finds something that is unique, basically. So, there's no problem really, as long as we have this populated, and this is mandatory anyway. So, yeah, let's back to the attributes. That's pretty much it from here. Basically, just a copy and paste of what I have in the documentation, somewhere here. It's just this, and then we need to make sure that the ID is required, and it's the primary, obviously. I think that's my default, anyway. Then the last thing is just setting the provisioning status to home. So, we go back, save that, then scroll down, this has to be on, and then we want to sync only assigned users and groups. Otherwise, it will sync everything in the Active Directory, and that would be too much normally, because we are just mapping a group. Another thing in mappings that is not here because I've removed it is, and this is synchronizing the users, but there's another option to synchronize groups. We're not supporting that, but we could synchronize multiple groups as well. So, as long as this is on, then should there be any errors? It will probably show there, and if everything is fine, we'll tell you here. We have synchronized four objects, blah, blah, blah, top user, and it will tell you when the last sync happened, but it was successful. It's a bit of a guess when this happens, around about 20 minutes, every 20 minutes. Let me just refer to that page and see if it's the same. So, it's all three, so hopefully it will happen before this meeting finishes anyway. But yeah, when that happens, we'll see the only request here, and I can show you some already anyway. But yeah, let me know if you have any questions so far. James, I have a question. So, I guess the get-us request, I guess that supports pagination, which is determined by the sync protocol. In theory, yes, but it doesn't, because we don't fully support those endpoints. So, basically, the get-alist of some users, it only returns a single user at the moment, based on the unique ID, because this is only used as part of the sync, and what happens with Azure, and this is something I don't know if other identity providers do the same when they want to sync something, but they will send us something like this, exactly like this, basically, because this is what they send, and then they say ID equals blah, because this is unique, it will only show us one user. So, yeah, at the moment, we didn't implement pagination, but yeah, it's not. This is no useful unless it's used as part of the sync, basically. So, this one and the single one, I needed to implement them because of the synchronizing. That makes sense. I think that answers my next question as well, because I think I was, I guess what happens is the identity provider goes through all of its users, and then for each one tries to make sure that they're synchronized. So, it doesn't come to GitLab and say, give me a list of all of your users, and then it checks against itself to see what happens. So, yeah, that makes sense to me. All right, perfect. What happens or what's the behaviour at the moment if the token was incorrect? Obviously, I guess it would return some sort of forbidden, but what's the behaviour from the identity provider? Is that when they would send an email to say that there's been an issue? Yeah, and also, I mean, when you configure that, there's a test connection. So, that will fail. And actually, I don't think it will let you save the page unless this passes. So, that's what happened. So, if you click on test connections, you will get that as well. You can check here, and it sends a get to users as well with a filter, blah, blah, blah. Yeah. And this is always 200, even if there's no users or anything, because it follows the protocol. So, it returns this response, basically. So, if there's no results, I would just say total results are zero, and then it would, this would be an empty array for resources. Okay, well, let's wait as well, see if this synchronised. But I think that's probably pretty much it. Let me see. So, yeah, this one, as I mentioned, well, the only tricky thing here is that we have a filter expression. And at the moment, we only support the equals matcher, because there's a bunch of them, basically, in the protocol. But what is useful for us is the equals, because that's being used as part of the sync from Azure. But as you can see, there are loads of them, and you can group and do other funny stuff in there. We don't support any of that. But yeah, it's very basic at the moment, but it does allow you to do the basic thing, which is create and synchronise that user, and then delete it, update it, and so on. Yeah, the same thing with the operations, with the update. Let me show you. Update a single summary user. We have, um, so this is just a patch to the end point with the path in the ID. And there's a few options here, but they're all of JSON string. And you can see how one looks like, like these, basically, operations op add path is the filled, and this is just a SCIM filled and formatted, and the new value, basically. And again, we don't support many, but we support replacing that. Another useful thing is the body locks. When we click there, well, useful when it actually syncs this properly. It hasn't been updated since 343, I don't know why, but these tell us what was happening. And for instance, export success, this was before probably when we created it, it was updated. So user was updated in the app and modified properties. I probably changed, oh, okay. So this was when I, before I was testing this, I was deleting the user. And what happens when you delete it, just pass the active flag to false. And so this is what happened. And this is practically what we'll see, as well, after the next sync. Although I can probably show you here, because there's a bit of of a delay, as you can see. And the last one was, was that. There's a few uses that when they get deleted, the azure still tries to sync them as to see what happened to these users. Is this back alive or is it actually deleted? And there's a few, a few that say import, like these that, well, it wasn't found, basically. So we return, not a formal form, we put it on an actual azure, not actual ACIM response, saying that you can find this user. This one was a success. So this is the ID and it was retrieved. And user five was there. So it was active. So these are quite useful, especially to debug what's going on. And normally if something happens, you will see an error there instead of success. And, and the good thing is that you can see here, the reason you will see the response from, from us, from gilab, saying, hey, maybe the email is not unique, for instance, that will, through a conflict error, or, or something else happened, then it will, it will, it will tell you that exactly what happened. So let me go back to provision and see if this has been synced or free. Okay. Taking some time. Yeah, 29. Okay. So let's see. Yeah, we can see that something happened there. But before I dig into that, let me quickly show you this. So we had this user, user four that was there, and we added a new one, user five. So if I refresh this page, if there were not errors, hopefully, but there might be. Oh, I know what happened. Well, that's good, because we'll be showing the error anyway. So that user got deleted. But the other one didn't because I, that user wasn't, was still existing, basically. I think I added it first, and then I deleted it. But from just from just the identity and the membership, but it is itself what was existing. So, and I forgot to delete it. But let me see if that will happen anyway. So, but actually, let's check. We can see the logs because there's no delay. Let's see if we're lucky enough. And error has occurred. Well, we would see the error details are not helpful. Never. So we need to think into the, into this. Actually, it did sync here. So let's see. Failure, this one. Well, it was useful anyway. Failure to create is a five and conflict, which is what I assume. And this is our response. E-mail has already been taken. So, and that was the problem there. Because the user is still assisted without email. And the email has to be unique. But let's see what happened in the lab itself. And just over the half past, but I will do this quickly. So, if else queries this with this, tries to find this user here. Okay, this is the one. So, and these was probably a 200, but we say, hey, it doesn't exist. Then, hold on, this is a patch. No, this is the post. No, this is the wrong one, actually. This is the one that responds with, okay. Because we're not querying the, we're getting a single user. So that responds with a 404. Let's see. Yeah, there. That's the one. So, when we added the new user, user five, we, so the sync queries for that user, and it says, well, it doesn't exist. And then you can see here, because the users, this is a 200, but it does the ID equals plan. And then the next thing, because it doesn't exist, it does the post here. And it responds with a 409, because in this case, the user exists already with this unit. Then, I think, let me see if there's an active, you know, yeah. And we also deleted one user, which is user four, and it's this one over here. And we can see that it sends the active flag to false. And that's what happened there when we deleted it. So it's no longer there. Okay, I think that's pretty much it. I know I rushed a bit there, but let me know if you've had any questions. Yeah, I found that really useful. Thank you. And one very quick question, I don't know if it'll be a quick answer. In this scenario, we basically sync in all users from, as you're across to GitLab. And is there any way to kind of like tag certain users as having GitLab role or permission, so they can include users? Well, here's the thing. We don't support roles as in, well, there's a role attribute in SCIM, but we don't support them as in GitLab permissions like this. So we're not mapping, we just create them with a default of guest. So we don't map the role, but we can be used to only map certain users. Let me just show you quickly. So if we go to provisioning. So this is not mapping all active directory, it's just mapping these groups because this is not the whole active directory. The whole active directory has got more users. And I can show you maybe here. So if I click on users, there's a bunch there, but we only, we have to explicitly add them to this group. So that's one thing. And the other thing is that in provisioning, there's an option to, let me see, could be here, I'm not sure, but there was an option to map, source, oh there you go, that's the one, scope. So we can add a scope there and only maybe check the role or something, or check some attributes and only map those that match those attributes basically. So that could be configurable as well, even within the group. And cool. Any more questions? Okay, well, thanks very much. And yeah, let me know if you have any, any other questions you can post in the managed channel. Thanks a lot. Have a good day. Thanks James.