Transcript
the rule development kit. So, what is that? It is a kit that we've developed to help you write your cloud rules. So, you know, you can test these, you can, you know, make sure that your logic is sound before they're uploaded to your tenant. And it's a pretty helpful tool I found when making rules. So, I'm going to show how this works today by developing a rule, a generic rule. We're going to create two functions in this rule. One is it's basically going to take in a date array. So, an array of dates will be able to specify what format those dates are in. And then it's going to perform two functions. So, we'll write two functions to get the date that's the farthest out and get the date that is the nearest or closest to today or even in the past. So, and then the other thing we'll do is we can specify the output format of that date. So, yeah, let's get started. First thing I want to do is just set up the rule development kit. So, I'll show how this is done on my screen here. So, I'm on developer.salepoint.com. We can go to Identity Security Cloud and go to Tools, Rule Development Kit. And so, this gives you kind of like an overview of what the rule development kit is, what kind of requirements. So, yeah, it requires Java, Apache Maven. We're going to be running some Maven install commands and test commands. So, we got some instructions there on how to get those installed. And then you can clone the project. It's just on our open source repo here, the rule development kit. So, you know, you can clone that right down and we'll get started. So, I already have it cloned. So, I will open that up in IntelliJ here. So, here is the rule development kit. So, we have some folders here for our rules. So, these are just a few example rules that we've created just to show you kind of how to get started with this and how you can mock your data to test your logic. And then you have a test folder which will include the tests for those rules. So, one thing that I was asked about recently in the community, this actually was asked about when I think I initially announced this tool at on the live stream probably like six or eight months ago now. But basically, we wanted the ability to download our cloud rules to this tool. So, if you caught an earlier session, the SailPoint CLI, we actually have that functionality now in the CLI. So, I'm going to show how that works again. So, I'll go into source, main, Java. And Java. And now, source. I want to be in resources here. Okay. So, we already have a folder for rules. But I'm going to do the download command here in the SailPoint CLI to add the rules that are in our tenants. So, if I do sail rule download, I just want cloud rules. So, I'm going to do dash dash cloud on the end of that. So, I'll run that here. And what this should do is go out to the tenant, grab our cloud rules, convert that back into XML, and then hopefully, yeah, there we go. So, if I click on this one, there is one of our cloud rules in our DevRel tenant. So, I'm connected to our DevRel tenant for the team. And yeah. So, that's a simple way to get your rules down to be ready to test and start developing. So, I'm going to get rid of that for now. So, now, we're going to get started on writing the rule I was talking about earlier. Basically, getting a date array and filtering that out with the farthest date or the nearest date. So, let's get started. What I want to do first is I'll get some kind of starter code in here. So, I'm going to add a new rule. Let's call this rule. It's going to be a generic rule. And I'll call it date functions. And that rule needs to be in XML. I'm going to copy over some starter code here for myself. There we go. This little green highlighting here, I'm not sure how visible that is on the screen there, but I'm going to get rid of it for a second and reset that up. Basically, what that's doing is all of these classes here that I'm importing are available to me. But if I start typing here, like, let's do util, like, nothing happens. So, when you're writing your rule, it's nice to have code completion. So, what we can do is right-click inside of this XML source and click on Show Context Actions and then click on Inject Language or Reference. And if we scroll down here, what we want is JShell Snippet. So, if I click on that, now you can see that green highlighting comes back. And if I start typing that util again, now you can see I get some IntelliSense come up and I have my functions available. So, that's pretty nice when you're developing your rules to be able to do that. So, the next thing I want to do is actually set up the test for this so that we can start passing in data, making sure that data is coming through as we mock it. And then we'll start developing the rule. We'll kind of keep jumping back and forth as we develop parts of the rule between the test and the rule itself. So, let's do that. So, under my test Java directory, I'm going to create a new Java class. I'm just going to call this DateFunctionsTest. And I'm actually going to copy over some starter code here as well, but I'll walk through it. So, we want the package sale point. That's where we'll get our, like, tools, our general exception. If we had these any sale point.object classes in here for, like, getting identity or application, those would all be at the top here. Then we get a logger so we can log out statements in our XML rule so we can see what that would look like. And then we would need the rule file name. So, this is going to be now my rule generic. So, copy path and I just need the file name here. So, if I copy that, paste it there, that should be set up. That is not the function we want. So, let's do test. This will be testFarthestDate. All right. And so, what we're going to do is set up a, the BeanShell interpreter. We're going to set up that instance. We're going to set up the variables that we're going to pass into the interpreter which will then get input into the XML. And you'll see how all that works here soon. But we'll go line by line here. So, setting up the interpreter, we'll do interpreter i equals new interpreter. And then we want, let's just do string result for the result of the rule. And then, let's just mock out what a date array might look like coming in from Identity Security Cloud. So, I tried actually using a date array, like as an array. I wasn't able to get that working quite the way I wanted to. So, what I'm going to be doing is having it as a CSV value and then splitting that in the rule back out into an array to then parse and loop through it to find the date that's farthest away here. Okay. So, we got our date array. Let's just start with that for now. I'll do i.set. So, this is how you pass variables into your XML rule. So, the first one I want to set is log. So, you'll see that log gets highlighted. So, basically, I'm passing in this logger to the XML. So, if I look back here, when I do log.error, this should be something more like log.info probably. I'll just do debug. And all I want to do is print out our date array for now just to make sure that this is, in fact, injecting what we want into the XML. So, I'll go back to my test and let's set up that date array. So, date array, and let's pass that in. The next thing we want to do is actually get the source of that rule. So, you can see it's wrapped in a source tag here. We want to grab that out and then feed that into our interpreter. So, we can do that with the rule XML utils. So, we click that, read source from file path, and then we want to pass the file name. So, then we'll do result equals string. I want the string results and i.eval from source. Okay. So, what's this doing? This is reading that rule XML to get the source out and then it's calling the interpreter and then evaluate that code. So, since we've set these variables for the interpreter, once we evaluate the code, those will get injected in. But let's make sure that is, in fact, true. Let's do log.info bean shell script returned, our result. Okay. So, result actually is probably going to be null right now, but we should get a log message with our array that we have here. So, we have a couple of dates. Let's see, one, two, three, four dates. So, we get that, we should get that data array back. So, let's run this. If I just click on this little play button, it's going to run that test. And there we go. So, it did, in fact, give us a null value back, but that, we expected that to happen. And then here we go, dev rel generic rule, and then our date array is right there. Cool. So, we are passing data correctly. Let's continue on writing the rule. So, what we want to do next is split out those dates back into a date array. We need to get in our input format, our output format. We need to, we're going to be using the simple date format to kind of parse the input output formats into date objects so that we can do like parsing and then compare, is this date after one another or is it before one another for the nearest person. So, let's take a look at what that looks like. So, we want, as I said, the string do dates, and that's actually going to be a string array. And we'll do date array.split, and we'll split on comma. And then, let's make this, that should work. And then we'll do list date array list equals arrays.asList, and then we'll pass in our dates. So, now we have that list of dates. Now, let's look at getting our input and output formats here. So, the string out there, let's do input first. So, input format equals input format. And then we'll do string output format equals output. Okay. So, we got some squiggly lines here. Basically, that means we're not passing that in. So, let's go ahead and pass that in. Over here, let's set those up. So, I do have those formats. I'm just going to copy There we go. So, the input format is two-digit month, two-digit day, the four-digit year, and then the hours and minutes. And so, you'll see that matches here. But we want the output format to be in the full year, dash, two-digit month, dash, day-day, and the hour, minutes, and seconds, with the times there and added on there. All right. So, we can pass those in. So, as before, we'll do i.setInputFormat. And you want to make sure that as you pass these in, that it does match exactly what you're expecting it to go into. That is important. And we'll do i.set. All right. So, that should take care of our input and output formats. Let's make sure that is true. Let's just log those out. And I'm actually going to make a mistake here on purpose, just to show you what it does when you do, in fact, make like a syntax error or anything like that. So, if I run this again, just by hitting the rerun here, I should get an error. There we go. Perfect. So, it'll kind of tell you, like, what's going on here, like, a, like, method debug string, comma string wasn't found. And you can go back and be like, oh, okay, it's not a comma there. I should be appending that with my debug output. If I run it again, there we go. And, in fact, we do get our input and output formats. So, that's perfect. I'm going to get rid of those debug statements here. The next thing we want to do is instantiate those simple date format objects. So, we'll do SDF in equals new simple date format. And then we're going to give it the input format. And we'll set up the other one. That is not right. Simple date format SDF out. And we'll give it the new format output format. Make sure that didn't, it did. Okay. I don't want that. All right. And now we can kind of start writing our rule. So, first thing I want to do is a switch operation. And we're going to pass in the operation. So, when you go to use this rule, you can basically have the same code, have the same rule. But if you want it to run the get farthest date, you can pass in that operation text. Or if you want it to get the nearest date, you can pass in that operation. And depending which one you pass in, in the transform, we'll see that towards the end here is what it's going to run, the function it's going to run and return you. So, as I said, we want to do the switch statement. And I'm going to add that operation over here. String operation, get farthest date. And we need to send it through our interpreter. There we go. All right. So, now we can have access to that variable. So, in the case of get farthest date, let's see. Let's just do return get farthest date. We're actually going to write a function that will return our date. But just right now, to show how this works. Case get nearest date. And then if we don't specify anything, we're just going to return null. Okay. So, let's test that that does work. If we do operation as farthest date, let's run it. So, beanshell script returned get farthest date. So, our script ran. We got into the case of get farthest date. So, it returned get farthest date there. Let's change that to nearest to make sure that our switch statement is working. And there we go. Cool. So, now we can write our functions to actually parse those dates and return us our results. So, let's do that again in the XML. Let's create a function here for we wanted to return a string. Get farthest date. That is going to take a list of our data ray. It's going to take the string input format and string output format. And then what we'll do is set up a variable to hold the current farthest date out. So, the first time through, we won't have anything to compare it to. So, we'll just assign that to the farthest date. And then the next time through, we'll see is the next date after the current farthest date. If that's the case, we'll reassign it. Otherwise, just continue through the loop of the data ray. So, let's write that code here. Farthest date equals null. So, we'll do four. Let's see the date or let's do a string date. Date array list. If we'll do detail, is null or empty. So, what this does is checks is the farthest date null or an empty string. So, that'll help us in making sure that we don't run into any null pointers. And then if that is the case, we want to assign it. So, farthest date equals date. And then else if we're going to do the SFDN, the simple date format input. So, we can do the input.parse. And then we want to parse the date. And then, so once it's parsed, now we have it in a simple date format. So, they give us some nice operations to say, is this date after one another? So, we can type that in here. After. And then we want to check, is it after the farthest date? There we go. Okay. So, and actually, we want to parse the farthest date too. So, SFDN parse farthest date. Then we'll assign it. If it is, in fact, after, we'll assign it the date. And then we want to return. So, outside of this for loop, we want to return the farthest date, but we want to return it in the format that we requested. So, we can do sfdout.format. And then we need to make it sfdn.parse our farthest date. So, that should be all that we need. And then now I want to call this. And you know what? I actually don't need these two strings. So, all I need there is my date array list. So, if I come down here and do return, get farthest date, and passing in our date array list. Let's see if that works. So I would be expecting this to return, let's see. So that's 1-21-2013, 1-20-2013, 1-22, and 1-21. So this should return 1-22-2013 at 15-13. So, let's make sure that that is the case. We'll run our rule again. And I did not change this back. So, we want it to do get farthest date, because that's the one we just coded. Run it again. And there we go. So, we got our date back that we were expecting, and it is in the format that we expected. I'm going to add a space here to make that a tiny bit more readable. There we go. Very nice. So, okay. Let's write the get nearest date one. So, let's go back to our XML here. To speed this up, I'm going to, let's see, copy this over. And we'll do get nearest date. That looks good. And then loop through that. We're going to change this to nearest date, which means I need to change it here, here. Okay, that's looking good. And then I think all we want to do is change this to, is it before, not after. So, is the date we're looping through before the nearest date that's already assigned, either by the first operation through, or first iteration through, or if we're in the second or third iteration checking that, that nearest date. So then we'll add that here. Get nearest date, passing in our data array list. And now this one should work too. So, let's change that back. Actually, what I'll do is add another test. So, I'll copy this one we already have. So, we name that test, test farthest date. So, we'll call this test nearest date. And then I need, I need that at the top here. So, I should just have at test, and that should resolve that. Perfect. And then we want to change this to get nearest date. Okay, so this should get the one that is the earliest, or the one in the past. So, what would that be? We got a 120, that looks like the lowest, 121. Okay, so I would expect it to return 120, 2013, at 1048. So, let's make sure that that is in fact correct. So, I'm going to get this out of the way for a second. So, I have another play button here just by the nearest date. So, I'll click that first to run that test only. And it didn't work. Cool. Well, let's debug this. Let's see, get undefined argument, farthest date. Clearly, I missed something. Get nearest date, there it is. Cool. Alright, let's run this again. Okay, so that was the only thing I messed up there. So, there we go. It's returning the nearest date. We got the 2013, 120, at 1048. Okay, so is there anything else we need to do here? I think that completes our rule. If you wanted to run, so this runs, as I said, one at a time here. But if you wanted to run both, there is a play button at the top of the class, the DateFunctionsTest class. So, if I ran both of these, we can see BeanShellShift returned, here's our get farthest date, and then here's our get nearest date. So, it can return both, or run both those tests at once. This is a Maven project, so you could set this up in kind of like a CI-CD environment to say, once you're done changing your rule, run your tests. If something fails, then don't push anything, don't update anything. So, you could do that if you wanted to. Let's see here. So, let's take a look at how this would work when we actually call it in the Identity Security Cloud. So, what I'll do for this is go back here and open up our tenant. Let's log in here. I'm going to pull out my phone quick here to enter this code. Perfect. So, I'm going to be testing this on an example delimited file source that I've set up. So, let's take a look at that source. So, we go to Admin, Connections, Sources. Let's look at, I think it's on the second page in our tenant. There we go. And, I believe Louis is the identity I want to use here. Let's look at his account for this source. Okay. So, I have three dates here that I'm going to be using to test this. So, let's try that out. So, let's... I'm going to open up... How do I want to do this? I'm going to use a tool I wrote in Python to test transform. So, I can test this route with the transform. So, I'm going to open up that project here. That'll probably look okay. So, let's create a new... Let's see. Date, transform.json. And, let's create this transform. Okay. So, I'm going to create a new date. So, I'm going to create a new date. So, I'm going to create a new date. Okay. So, we want to give it a name. Let's do date functions test. It needs a type. And, that is going to be a type of rule. So, you need the type rule if you're going to do a generic function. Or, a generic rule, sorry. Attributes is just an array. The name is going to be the name of our rule, which is just date functions. One thing I'll mention here is that, you know, typically with a cloud rule, you know, you'll develop it, and then you'll need to submit it to professional services. So, I did that in the background. Obviously, I couldn't have done that live. So, that rule is actually already uploaded to our tenant. And so, it's available for me to use. So, the name of that rule is date functions. And so, now I can pass in my variables, just like I was doing in the beanshell interpreter. I can pass in the data array. And, that is going to be a static transform. And, we're going to do first date. It's going to be... We're going to want to pull that from a... We're going to use a first valid here. So, if for some reason the date doesn't exist on the source, we're going to replace that date with something that's hard-coded here. So, let's go ahead and see what that would look like. So, we'll do type. We want first valid. First. And, the attributes for that are going to be values. You can see in GitHub, Copilot's trying to suggest stuff for me. Unfortunately, it doesn't know transforms. Count attribute. All right. Just checking the time here. I'm going to actually copy these in. I'm going to go a little bit faster, and then I'll explain the whole transform. I think that'll go a little better. Okay, so there is our first date. So, then we need a second date. And... Second date, then third date. Let's format that. And then we want our value, which is going to be all of those separated by a comma. Okay, so if I go through this quick, we got a first valid. We're going to first try and pull the account attribute first date from the example CSV source. So, if I get back here, that's going to be this value. We're going to then pull the second date. If that's not there, we're going to use the one I have hardcoded. And then, it's going to try and pull the third date. I'm going to go back here. And so, that's that set of it. So, then we have that kind of comma-separated value in that date array. And then, the next thing we want to do is specify our input format. So, we'll do input format is... the same one we wrote in our rule. Output format is the same one we wrote in our rule. And then, we're going to do... I'm going to do get farthest date. Okay. So, that should be our entire rule. So, we pass in the first date, the second date, third date, comma-separated values there. We got our input format, our output format, and operation. So, these will match exactly what we look to pull in with the rule. So, if I go back to the XML quick before I run this, we can see here, data array is getting passed in right there, input format, output format. We haven't initialized these values. They're getting passed in by Identity Security Cloud. Okay. So, let's get this running now. So, I'll run Python test transform, and I'm going to pass it that transform we just wrote. And, okay, example CSV source is the source I want. And we're going to test this on the Lewis identity. And there we go. So, let's make sure that is right. Okay. 2024, 01, 20. And that is the farthest date out of these three. 2023, 2024, 2021. Yep. So, there we go. Chose the second date and returned that one. So, we walked through developing a rule, you know, mocking our data. We tested it kind of end-to-end here. So, we're always looking to improve this experience. If you have any suggestions or thoughts to improve the rule development kit, please, please share them with us. But that's it for me in this session. We'll see you in the next one. ♪♪♪