Workflow Wednesday: Basics of Building Solid Workflows

Whether you’re building a complex, multi-pronged workflow or a simple workflow that’s just a few steps, there are basic things you can do along the way to ensure that it’s solid. Now, what exactly does “solid” mean here? Well, I’d say it means that your workflow is less error-prone, has handling for when things don’t go quite right, and thus is more stable or reliable overall whenever it runs. And that’s a very good thing in the world of workflows.

So what are these workflow-solidifying basics? There are three specific ones (out of many) that I want to tackle today, and they involve liberal use of:

  1. Decision steps
  2. Filter steps
  3. Artifact cards

Now, let’s dive into these basics a little more to see how they can help. We’ll use a pretty simple workflow example, but it demonstrates these points nonetheless. In our example workflow, what we want to do is take a list of email addresses that we have and use them to add users to a group in Okta. If you’re not familiar with Okta, it’s a widely used identity/access management service.

In this workflow, the first thing we want to do is retrieve our emails. In this case we’ll be extracting them from an email, though you may be getting them from another tool your team uses. So, we’ll extract our email addresses from the email using the ExtractIt plugin, and then we want to process all of them so we can add them in Okta, right? Ah, but not so fast. There’s another thing we should do first:

Decision Step

ex1

There’s a chance that the email received doesn’t contain the email addresses we’re looking for, for whatever reason. Maybe it was sent incorrectly, or maybe the email body is malformed. Either way, we don’t want to proceed with this workflow if we don’t have our emails, because then we’ll be attempting to process nothing. Sounds error-prone to me.

That’s where the decision step in the above image comes in. What we’re doing is checking to see if we actually got any email addresses from our extraction step. If we did, then great, we can move on and process those emails. But if not, then we’re not going to process anything. Here’s what the condition looks like for determining whether we’ve got any emails. It’s basically saying “if these emails are defined (aka if they exist) then we’ll go down the ‘Emails Exist’ path.” Otherwise, we won’t.

condition

By doing this, we’ve already added some sweet built-in error handling to our workflow. And there’s even more we could do with it. Maybe the email not containing any addresses is a sign that something’s wrong, so we should go check it out. At that point you could add another step that alerts you to what’s happened, or does something else to resolve this missing-email issue.

Anyway, now that we’re sure that we’ve got our email addresses, we can go into our processing step. We’re going to be looping over the emails so we can do something to each one of them - you can see this in the Process Emails step above. If you’re new to the concept of loops and want a little more info on using them, check out our post on Loop Step Basics.

Inside our Process Emails loop, we want to take each email address and use it to add the corresponding user to our Okta group. Buuuuut before we do that, there’s something else we want to do that addresses a common issue in scenarios like this one:

Filter Step

ex3

We’re relying on a separate tool or service to retrieve our list of email addresses here (in our case it’s an email, maybe it’s a specific tool for you). That list may contain emails that we don’t necessarily want to add to our Okta group. Maybe it’s emails of a certain domain, or a particular email from a certain user or set of users. Whatever the case, we can solve that and avoid wrongfully adding these users with our filter step.

The filter step allows us to define a condition under which we want the workflow to either stop or continue execution. For our example, let’s say that we only want to add this user to the Okta group if they do NOT have a Rapid7 email address. In other words, this Okta group is for non-Rapid7 users. So how can we do that? We can define the following condition in our filter step.

condition2

It does exactly what it says. If our “Process Emails item” (aka, the email we’re currently processing in our loop) contains “rapid7” then it must be a Rapid7 user, and we want to want to stop execution of the current iteration of the loop and move on to the next one.

So if the list of emails we retrieve just happens to contain a Rapid7 address, whether due to user error or another external issue, this filter step has us covered. By doing this upfront, we’re making our lives a heck of a lot easier by ensuring only the users we want are being added to this Okta group.

Once we do our “Add User to Okta Group” step, we’re pretty much done! The final step we can see here is the “Okta Add Successful?” step, which makes use of one of the most helpful and flexible workflow components in the builder.

Artifact Card

art1

The artifact we’ve added as the last step in our loop provides a super easy way to keep track of exactly what’s going on in the workflow. Here we’re using it as a sort of user-friendly logging to showcase 1. Whether the Okta action was successful, and 2. What user was added. If you’re ever reviewing executions of this workflow for debugging purposes, or just for the sake of understanding it, you can simply refer to this artifact card to find the important details for each iteration of the processing loop.

Also, if you scroll back up to the first image in this post and look under the Emails Don’t Exist path in our decision, you’ll notice the “No Email Addresses Found” step. That’s another artifact card, and there we print out a message telling us that we indeed have no email addresses and thus can’t proceed with processing. It’s another instance of using artifacts to convey a message and allow us to easily understand what happened in our workflow.

In general, artifacts are great for this type of user-friendly logging, almost like breadcrumbs that enable you to more easily see what your workflow did along the way and why. There’s a lot more you can do with them too - since they’re markdown friendly, you can pretty them up to your heart’s content. If you really want to get fancy, check out some of the stuff you can do in artifacts with Handlebars.

So, now we’ve learned a few basic methods we can use in the building process to make workflows even more solid and reliable. The ones we discussed here are:

  1. Decision steps - We checked to ensure our data existed before we processed it. That provides some great built-in error handling.
  2. Filter steps - We made sure that we’re only adding the users we really want to our Okta group. The ones we didn’t want were filtered out.
  3. Artifact cards - We used a couple artifact cards in our workflow to give us easy access to info on what the workflow did and why. Now we have an even clearer picture every time this workflow runs.

Are there any strategies you’ve used when building workflows to help make them more dependable or reliable? Anything you’d do different in this workflow example? Feel free to ask questions or share your own ideas!

4 Likes

helpful thanks. I hadn’t thought of using artifacts for debugging before reading this.

Artifacts are great but the fact it seems impossible to get them into custom investigations is not :frowning: