Administrator guide
Joiners, movers and leavers
Have your HR system or identity platform call Warde when someone joins, moves or leaves, and follow what became of each call.
Warde does not detect joiners, movers and leavers. Your HR system or identity platform already does, and knows more about a new joiner than ServiceNow does. Have that process call Warde, and Warde grants the birthright bundles the person should hold, records who has what and why, and tracks the work like any other request.
There are two ways in, and both do the same things:
- a REST endpoint, for SailPoint, an HR system or middleware outside ServiceNow;
- a Script Include,
WardeLifecycleApi, for a flow or script inside ServiceNow.
What you can ask for
| Action | For | What Warde does |
|---|---|---|
grant_template | A joiner, or a mover gaining a bundle | Grants one bundle |
revoke_template | A mover losing a bundle | Removes one bundle |
reconcile | A nightly check, or a mover | Brings the person to exactly the bundles you list: grants what is missing and removes what is not listed. [] means no bundles. |
deprovision | A leaver | Removes every entitlement the person holds through Warde |
Each call raises one ServiceNow request with a line per entitlement, using a hidden catalog item with no approval: your process is the approval. Engine lines go to the fulfilment queue and manual lines become tasks, exactly as for a request.
Set up the caller
- Create a service account for the calling system, and grant it
x_66256_warde.lifecycle_integrationin Guided Setup step 1. Do not give it the administrator role. - Create your birthright bundles. See Access bundles.
- Choose what Warde does by default in Guided Setup step 14.
Who does which part
A bundle often mixes access an engine can grant with access only a person can. Choose which half Warde takes:
| Setting | Warde does | Warde hands back |
|---|---|---|
all (the default) | Everything: engine grants and catalog tasks | Nothing |
auto_only | Only what an engine can grant. No task is raised. | Everything that would have been a task |
manual_only | Only the catalog tasks | Everything an engine could have granted |
The setting is decided by the most specific of three places:
fulfilmentin the call itself;- a row for the calling system on the lifecycle integrations list, matched on the service account (add one from Guided Setup step 14);
- the instance default,
x_66256_warde.lifecycle.fulfilment.
Whatever Warde does not take on comes back in skipped, one entry per entitlement with the reason, so your process knows what is still its job.
The REST endpoint
POST /api/x_66256_warde/lifecycle/event
Content-Type: application/json
Authenticate as the service account, with basic auth or OAuth.
{
"subject": { "field": "employee_number", "value": "E4471" },
"action": "grant_template",
"names": ["Finance Analyst"],
"reason": "Joiner: HR case HRC0012345",
"correlation_id": "hrcase:HRC0012345"
}
| Field | Notes |
|---|---|
subject | {"sys_id": "..."}, or {"field": ..., "value": ...} where field is sys_id, user_name, email or employee_number. Two people matching one value is refused rather than guessed. |
action | grant_template, revoke_template, reconcile or deprovision |
names or templates | Bundle names, or bundle sys_ids. grant_template and revoke_template take exactly one. reconcile takes a list, and must send one. |
fulfilment | Optional: all, auto_only or manual_only |
reason | Recorded on the request and every line. Put your source record's number in it. |
correlation_id | Your own id for this event. It makes the call safe to retry, and it is how you ask about the call later. |
assigned_via | Optional. birthright (the default) or request. Birthright access cannot be removed by the person themselves. |
Responses
| Code | Meaning |
|---|---|
| 202 | Accepted, with lines in flight. Ask about them with the GET below. |
| 200 | Nothing in flight: the person already held the bundle, everything was left to you, or every line was refused. skipped says which. |
| 400 | A bad body, an unknown action, a person who matches nobody or more than one, an unknown bundle, or a refusal |
| 403 | The caller does not hold the lifecycle integration role |
| 500 | Warde wrote nothing. Send it again with the same correlation_id. |
Retries
Send a correlation_id that is specific to one event, such as hrcase: and the case's sys_id. A call sent again with the same id returns the first answer and grants nothing twice. Do not use an id like leaver: and the person's sys_id alone: a rehired person's second leaving would be answered from the first. An id sent again for a different action or bundle is refused.
Ask what became of a call
GET /api/x_66256_warde/lifecycle/event?correlation_id=hrcase:HRC0012345
The reply lists the request and each line with its state: queued, in_progress, complete, failed or cancelled, the date the access was promised by, and the task number for manual work. done is true once nothing is queued or in progress. A failed line can still move, for example when an engine recovers, so keep asking for as long as you want to know.
Warde does not call your system back.
Example
curl -u "$SN_USER:$SN_PASS" -H "Content-Type: application/json" \
-X POST "https://<instance>.service-now.com/api/x_66256_warde/lifecycle/event" \
-d '{ "subject": { "field": "user_name", "value": "ada.okafor" }, "action": "deprovision", "reason": "Leaver: HR case HRC0012399", "correlation_id": "hrcase:HRC0012399" }'
From inside ServiceNow
var api = new x_66256_warde.WardeLifecycleApi();
api.grantTemplate(userId, templateId, opts); // joiner or mover: grant a bundle
api.revokeTemplate(userId, templateId, opts); // mover: remove a bundle
api.reconcile(userId, desiredTemplateIds, opts); // bring the person to exactly these bundles
api.deprovision(userId, opts); // leaver: remove everything
api.status(correlationId); // what became of a call
opts takes reason, assigned_via, fulfilment, correlation_id, and actor, the user recorded on the audit history. Every method returns the same envelope as the REST reply. A script in another scope needs its cross-scope access approved the first time it calls.
What goes in a birthright bundle
If your identity platform already grants birthright access by its own rules, such as ISC role membership criteria or Entra dynamic groups, leave that access out of the bundle, and leave out the platform's birthright role. Under all, Warde would ask the platform for a role it already assigns. The bundle then holds what the platform does not grant, usually the manual remainder. Warde still shows the platform's rule-given access on My Access and in reviews.
Where to see the results
| What | Where |
|---|---|
| One call | The GET above, or the request item the call returned |
| A leaver's removals that have not finished | The Leavers dashboard in the Admin Workspace, with the leaver chosen in its filter, or the report Leaver report: removals not finished |
| Access still active for anyone who has left | The two Access still active after leaving tiles on the Leavers dashboard, or the report Leaver report: access still active. This includes leavers your platform handled without calling Warde. |
| Who holds which bundle | The access bundle holdings list |
| Manual work | The catalog tasks on each collection's support group |
Guided Setup step 14 shows counts of recent lifecycle calls and links to each list.
Limits
- Warde does not create or disable accounts. Access a person cannot get for want of an account comes back in
skipped, and a leaver's accounts are not closed. - Access an engine gives from an attribute and cannot remove on request is skipped, not attempted.
- A removal does not stop a grant the engine already has. It is removed again as it lands.
- A birthright bundle cannot be removed by a request or in a review. Change the rule or the HR details that give it.