> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/lifecycle/verify-connection.md).

# Verify connectivity to the target

Prove a connector can actually reach its target — read the connector status, then the reply, then the target itself, and know what a green chip does not prove.

## What this is, and when you need it

This is the page to read before you trust a green managed system. It takes you from a saved, active managed system to evidence that a real target object was created, read back and removed — which is the only proof that means anything.

**Test Connection in OpenIAM does not contact the target.** It reads the most recent heartbeat reply that a connector left in the `connectorreply` search index, and reports success if any of them says `Ok`. Everything else on this page follows from that one fact.

The specific risk is a false pass. A connector that authenticates to the *wrong* tenant, or that answers a heartbeat it implements as a no-op, produces exactly the same green chip as a fully working integration. Verify at the far end.

## At a glance

|                          |                                                                                                                                                                                                                                                                                   |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **You will end up with** | Evidence the connection is real: a `connectorreply` document with `operation = "TESTCONNECTION"` and `status = "Ok"`, **and** a target object created, read back from the target and removed. Nothing changes until those last steps                                              |
| **Where**                | **Provisioning → Managed System**, the connectivity dashboard at `/webconsole/mngsystemlist`; the queue-level checks are in the broker's management interface for vhost `openiam_connector`                                                                                       |
| **You need first**       | A saved managed system with a connector assigned and `IS_ACTIVE = 'Y'` — the sweepers skip inactive and manual systems entirely — the **Managed Systems** menu resource (`MNGSYS_MENU_ITEM`, under **Provisioning**), and the broker's management interface or someone who has it |
| **Takes**                | 10 minutes for the dashboard and the reply; 30–45 minutes to prove the target end to end                                                                                                                                                                                          |
| **Reversible**           | Yes — everything up to the disposable object is a read; what cannot be undone is proving a connection with a delete, a disable or a password reset instead of a read, or exposing a credential, which must then be rotated                                                        |

## Before you begin

* Read access to the `connectorreply` index, or to the Webconsole dashboard at `/webconsole/mngsystemlist` that renders it.
* A `<TEST_USER>` and a disposable target object you can create, read and remove, in the container the managed system is scoped to.
* The connector definition's `CONNECTOR_QUEUE` value and access to the RabbitMQ management interface for vhost `openiam_connector` — needed only if the connector never answers.

## Prove the connection

Work outward from OpenIAM's own evidence to the target itself. Each step is worth more than the one before it.

{% stepper %}
{% step %}

### Read the connector status on the dashboard

Look for a `connectorreply` document with this `managedSystemId` and `operation = "TESTCONNECTION"`. The dashboard at `/webconsole/mngsystemlist` renders exactly this: the **Running connector status** column shows a chip per reply, or `No active connectors found` when there are none, or a **Manual** chip for a manual system.

| What you see                               | Meaning                                                                                                                                                                                           |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| No document, and a `SERVICE_DOWN` document | The connector has never answered — either nothing is consuming its request queue, or the broadcast expired unconsumed after 30 s. Start at [Diagnose by layer](#diagnose-by-layer).               |
| No document, no `SERVICE_DOWN`             | Either you looked in the window between the sweeper deleting the old reply and the new one arriving, or the down check has not run yet (it starts 90 s after IDM startup). Look again after 60 s. |
| Document with `status = "Error"`           | The connector is alive and consuming. It tried and failed. **Read `lastError`.** This is a configuration problem, not a runtime one.                                                              |
| Document with `status = "Ok"`              | Move outward.                                                                                                                                                                                     |
| {% endstep %}                              |                                                                                                                                                                                                   |

{% step %}

### Read the reply before you change anything

Open the **Connector Replies** dialog from the dashboard's last column. It pages, so widen the page size before concluding a reply is absent. Its columns map onto the reply document's own fields: **Application ID** (`applicationId`), **Object Name** (`targetIdentity`), **Object Type** (`targetIdentityType`), **Status** (`status`), **Operation** (`operation`), **Date** (`date`) and **Error** (`lastError`). The document also carries `connector`, `connectorId`, `host`, `lastStatus` and `provisionRequestId`.

`provisionRequestId` is the link back into the request chain: it is the `provisionconnectorrequest` document ID, which in turn carries `provisionSessionRequestId` pointing at the `provisionrequest` document. Record it. The first failure is more diagnostic than anything produced after a restart.
{% endstep %}

{% step %}

### Prove the target with a harmless read

A green heartbeat says the connector answered; it does not say the credential can read your container. The cheapest target-aware proof is a **search**, and the cheapest way to trigger one is a synchronization or a reconciliation scoped to a filter that matches one known test object.

For a reconciliation: create the config with every situation on `NOTHING` and a target filter that matches your one test account, and read the CSV report. Nothing is written on either side, but the connector performs a real search and the report shows what came back. See [Configure reconciliation](/administration-guide/lifecycle/configure-reconciliation.md#worked-example-a-first-reconciliation-against-a-test-ou).

Do **not** start with a delete, a disable or a password reset. Each exercises different target rights and each is hard to reverse.
{% endstep %}

{% step %}

### Prove the contract with one disposable object

Now provision `<TEST_USER>`, with the operation captured in [simulation mode](/administration-guide/lifecycle/simulation-mode.md) first if you want to read the generated request before it is sent. Then, and only then, apply it and follow all four indexes:

`provisionrequest` → `provisionconnectorrequest` → `connectorreply` → the object in the target.

Confirm the account is in the container you configured. Confirm `LOGIN.PROV_STATUS` reached a terminal success (`CREATED`, `SAVED`, `UPDATED`, `ENABLED`) and not a `FAIL_*` or `PENDING_*` value.
{% endstep %}

{% step %}

### Test each operation separately

Read, create, modify, add a membership, set a password, disable, delete. They map to different `*_HNDLR` values and different target permissions, and it is normal for a service account to be able to create a user and not to modify a protected group's membership. The connector replies per operation; do not summarise a multi-step business action as one result.
{% endstep %}
{% endstepper %}

## Verification

Connectivity is verified when the record contains all six:

1. The managed system's `MANAGED_SYS_ID`, name, `IS_ACTIVE`, `CONNECTOR_ID`, `HOST_URL`/`CONNECTION_STRING` and the container it is scoped to.
2. A `connectorreply` document with `operation = "TESTCONNECTION"` and `status = "Ok"`, with its `date` and `host`.
3. A target-aware read that returned the object you expected and nothing you did not.
4. One disposable object created, read back **from the target**, and removed.
5. The matching audit trail: `PROVISIONING_TEST` for the connection test, `PROVISIONING_ADD` for the create, `CONNECTOR_RESPONSE` for the reply. All three retentions ship `-1`.
6. `LOGIN.PROV_STATUS` for the test identity at a terminal success value.

## When it goes wrong

### Diagnose by layer

Work outward from the runtime: each layer's fix is useless while the layer inside it is broken. When there is no reply at all, start on the RabbitMQ management interface, vhost `openiam_connector`, and look for a queue named `<CONNECTOR_QUEUE>_Request` bound to exchange `CONNECTOR_EXCHANGE` with routing key equal to its own name, and a **non-zero consumer count**. Zero consumers, or no queue at all, and everything below is noise — start the connector package, and if the queue is missing entirely wait one 60-second sweep, because the heartbeat sweeper re-binds it.

| Symptom                                                        | Layer                             | Evidence to collect                                                                                                                                         | Correction                                                                                                                                                                                 |
| -------------------------------------------------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `No active connectors found` chip, `SERVICE_DOWN` doc present  | Runtime                           | Connector process state; RabbitMQ consumer count on `<CONNECTOR_QUEUE>_Request`                                                                             | Start the package. Confirm it is configured for the exact queue name in `PROVISION_CONNECTOR.CONNECTOR_QUEUE`.                                                                             |
| Queue exists, messages accumulate, no consumers                | Runtime                           | A consumer count of `0` on `<CONNECTOR_QUEUE>_Request` in the broker's management UI                                                                        | The process is not connected. Check its own credentials for vhost `openiam_connector`.                                                                                                     |
| Queue missing right after a restart                            | Binding order                     | The IDM bound queues at startup before any connector existed                                                                                                | Wait 60 s; the heartbeat sweep re-binds every time it runs.                                                                                                                                |
| Requests consumed, `<CONNECTOR_QUEUE>_Response` stays empty    | Runtime                           | Connector-side logs                                                                                                                                         | For the .NET runner family, the log and response channels are separate from the request handler; a connector can consume and never answer. Check its LogService.                           |
| Reply `status = "Error"`, `lastError` names a host or port     | Network / endpoint                | `HOST_URL`, `PORT`, DNS and firewall **from the connector host**                                                                                            | Fix the endpoint. Reachability from your workstation is irrelevant.                                                                                                                        |
| Reply `status = "Error"`, `lastError` names authentication     | Credential                        | `USER_ID` format, secret age, target-side account state, TLS client requirements                                                                            | Rotate and update the least-privilege service account. Watch the format — the AD connector expects `DOMAIN\user`, LDAP a bind DN, JDBC a database login.                                   |
| Reply `Ok`, search returns nothing                             | Scope / filter / read permission  | `MNG_SYS_OBJECT_MATCH.SEARCH_BASE_DN`, `SEARCH_FILTER`, `SEARCH_SCOPE`; whether the connector received them as `SEARCH_BASE_DN` and `LOOKUP_QUERY`          | Fill Search Base DN separately from Base DN. Confirm the filter's placeholder syntax matches the connector's.                                                                              |
| Read works, create fails                                       | Target authorization or mapping   | The create operation's `connectorreply`; required target attributes; the policy map                                                                         | Add the missing mapping or grant the missing right on the **container**, not domain-wide.                                                                                                  |
| Create works, membership fails                                 | Target authorization on the group | The membership operation's own reply                                                                                                                        | Grant write on that group. Do not solve it with a broad administrative role.                                                                                                               |
| Create works, disable or delete fails                          | Operation semantics               | `SUSPEND_HNDLR` / `DELETE_HNDLR`, the `ON_DELETE` resource property, connector support                                                                      | Confirm the connector implements the operation, and that `ON_DELETE` names the one you intend.                                                                                             |
| Green heartbeat, every business operation fails                | Health-check depth                | Whether the connector's test handler contacts the target at all                                                                                             | Treat the heartbeat and each lifecycle operation as separate facts. `TEST_CONNECTION_HNDLR` is what the connector was told to use; if it is blank, the connector's default may be a no-op. |
| Green heartbeat, the **wrong** directory changed               | Environment                       | `HOST_URL` / `CONNECTION_STRING`, base DN, target object audit                                                                                              | Untick **Active**, stop schedules, invoke the incident path, then correct the boundary. This is the one failure OpenIAM will never flag.                                                   |
| Synchronization refuses to start, `FAIL_CONNECTION`            | Coupling                          | Starting a synchronization tests the connection first, and for a `CONNECTOR_ASYNC` source that means the managed system named on the configuration          | Fix the managed system's heartbeat. The sync only wants to read, but it will not start without one.                                                                                        |
| Reply `Ok` from one node, failures in practice                 | Clustering                        | Test Connection passes when **any** reply says `Ok`                                                                                                         | Inspect every reply in the dialog, not the aggregate chip.                                                                                                                                 |
| **Retry** in the reply dialog reports success, nothing happens | Product defect                    | The button reports `RETRY_POSTED_SUCCESS` and submits no retry at all. There is no `RETRY_PROVISIONING` audit entry afterwards, which is how you confirm it | Do not use it. The working retry path is described in [Configure provisioning](/administration-guide/lifecycle/configure-provisioning.md#recovering-a-failed-request).                     |

### Reading the queue names for yourself

If you need to establish the queue names for yourself rather than trusting a document:

{% code overflow="wrap" %}

```sql
SELECT m.MANAGED_SYS_ID, m.NAME AS MANAGED_SYSTEM, m.IS_ACTIVE, m.IS_MANUAL_SYSTEM,
       c.CONNECTOR_ID, c.NAME AS CONNECTOR,
       CONCAT(c.CONNECTOR_QUEUE, '_Request')  AS REQUEST_QUEUE,
       CONCAT(c.CONNECTOR_QUEUE, '_Response') AS RESPONSE_QUEUE,
       c.IS_URGENT_CONNECTOR_QUEUE_ENABLED, c.URGENT_CONNECTOR_QUEUE
FROM   MANAGED_SYS m
       LEFT JOIN PROVISION_CONNECTOR c ON c.CONNECTOR_ID = m.CONNECTOR_ID
WHERE  m.IS_ACTIVE = 'Y' AND m.IS_MANUAL_SYSTEM = 'N';
```

{% endcode %}

Everything those queues live on: vhost `openiam_connector`, exchange `CONNECTOR_EXCHANGE` for operations and `CONNECTOR_BROADCAST_EXCHANGE` (fan-out) for the heartbeat. The IDM side's own queues — `ProvisionQueue`, `ProvisionDispatcherQueue`, `ProvisionConnectorQueue`, `ManagedSysQueue` — are on vhost `openiam_idm`, exchange `IDM_EXCHANGE`, each named after its class. Synchronization is on `openiam_synchronization` / `SYNCHRONIZATION_EXCHANGE`, reconciliation on `openiam_reconciliation` / `RECONCILIATION_EXCHANGE`.

## Rollback

Verification is read-only up to the point where you create a disposable object. If you created one, remove it through the deprovisioning path you are about to rely on — that tests the reverse direction for free — and confirm at the target. If you changed an endpoint or credential to make the test pass, restore the recorded previous value and re-verify, or promote the change deliberately. If a secret was exposed, rotate it; do not restore it.

## How connectivity is actually decided

Nothing below changes what you do; it explains why the dashboard behaves the way it does, and it is the material to reach for when the evidence itself looks wrong.

### The three mechanisms, and which one you are looking at

| Mechanism               | Runs where              | Cadence                                                                            | Produces                                                                                                                                                 |
| ----------------------- | ----------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Heartbeat broadcast** | IDM service             | `org.openiam.idm.connector.health.check.sweeptime`, shipped **`60000` ms**         | A `connectorreply` document per replying connector with `operation = "TESTCONNECTION"`                                                                   |
| **Test Connection**     | IDM service, on request | On demand, and automatically after every managed-system save                       | A `SUCCESS`/`FAILURE` response derived from those documents. Audited `PROVISIONING_TEST`.                                                                |
| **Down check**          | IDM service             | `org.openiam.idm.connector.service.down.check.sweep.time`, shipped **`300000` ms** | A `SERVICE_DOWN` document plus a `MNG_SYS_CONNECTION_ERROR` email on the transition into failure, and `MNG_SYS_CONNECTION_SUCCESS` on the transition out |

#### The heartbeat, exactly

The sweep runs every `org.openiam.idm.connector.health.check.sweeptime` milliseconds, starting as soon as the IDM service is up, and for each automatically provisioned managed system it does the following:

1. If the system is **manual** or **inactive**, delete its `TESTCONNECTION` replies and move on. That is why a manual system is quiet and an inactive one goes grey rather than red.
2. Re-bind `<CONNECTOR_QUEUE>_Request` and `<CONNECTOR_QUEUE>_Response`, and the urgent queue if `IS_URGENT_CONNECTOR_QUEUE_ENABLED`. This exists specifically to recover from a start-up ordering problem, so a missing binding heals within one interval and needs no restart.
3. Decrypt `MANAGED_SYS.PSWD` and every password-typed managed-system attribute, so the connector receives usable credentials.
4. Read the current `TESTCONNECTION` reply, copy its `lastStatus` onto the outgoing DTO, then **delete** the reply.
5. Publish a test-connection broadcast to exchange `CONNECTOR_BROADCAST_EXCHANGE` (fan-out) with routing key `broadcast.<CONNECTOR_QUEUE>_Request.test`, message header `VIRTUAL_HOST = openiam_connector`, header `API_NAME = TestConnection`, and **`expiration = "30000"`** — the message self-destructs after 30 seconds if nothing consumes it.

Step 4 is the one that matters for interpretation: **the reply is deleted before the new one is requested.** So there is a window in every cycle where a perfectly healthy managed system has no reply document, and a permanently dead one has none either. Do not read the dashboard once and conclude.

The whole sweep is guarded by a cluster-wide lock named `CONNECTOR_HEALTH_CHECK_LOCK`, held for `0.9 × sweeptime`, so exactly one IDM node broadcasts per interval.

#### Test Connection, exactly

It reads the stored `TESTCONNECTION` replies for the managed system and answers success if **at least one** of them says `Ok`; if there are none, or none says `Ok`, it answers failure with `FAIL_CONNECTION`. Nothing is sent to the connector at the moment you press it.

The two values you will see in a reply's `status` are the strings **`Ok`** and **`Error`**. The "at least one" rule is deliberate — one connector definition can have several connector instances running, and the test is meant to pass if any of them is alive. In a clustered connector deployment a green result therefore means *some* node is healthy, not all of them; open the reply list and read every row rather than trusting the aggregate.

Because the test only reads stored replies, and OpenIAM runs it immediately after every successful managed-system save, a brand-new managed system reports a connection failure on its first save and looks fine a minute later. Wait out one health-check interval and save again rather than changing the credential. Success message key `MANAGED_SYS_TEST_CONFIRM`, failure `MANAGED_SYS_TEST_CONNECT_FAILRE`.

#### The down check and its notifications

The down check starts 90 seconds after the service comes up, takes a cluster-wide lock so only one node runs it, and looks at active, non-manual managed systems other than the default managed system. It compares two document sets — the `TESTCONNECTION` replies and any `SERVICE_DOWN` reply:

| `TESTCONNECTION` docs | `SERVICE_DOWN` doc | Action                                                                                                                    |
| --------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| none                  | none               | Create a `SERVICE_DOWN` doc (`status = "Error"`), notify with template `MNG_SYS_CONNECTION_ERROR`                         |
| present               | present            | Delete the `SERVICE_DOWN` doc, notify with template `MNG_SYS_CONNECTION_ERROR`'s counterpart `MNG_SYS_CONNECTION_SUCCESS` |
| none                  | present            | *nothing* — the alert is not repeated                                                                                     |
| present               | none               | *nothing* — the steady healthy state                                                                                      |

So the alert fires **once per transition**, not on every sweep. Recipients are every user in the group named by `org.openiam.defaultNotificationGroup`, shipped `SYSTEM_NOTIFICATION`. The templates are `MAIL_TEMPLATE` IDs `190` (subject `[ALERT] Healthcheck on <managed system name>`) and `191` (`[RESOLVED] Healthcheck on …`), which ship as of 4.1.10.0. Four parameters are supplied to the template — `MANAGED_SYSTEM`, from which the template can reach `.name`, `.hostUrl` and `.port`; `HOST_URL`, taken from `org.openiam.webconsole.defaultBaseDomain`; `MANAGED_SYSTEM_ERROR`; and `DATE`.

Confirm both are present and enabled on your deployment before you rely on the alert: `SELECT ID, TEMPLATE_NAME, IS_ENABLED FROM MAIL_TEMPLATE WHERE ID IN ('190','191')`.

{% hint style="warning" %}
The `SERVICE_DOWN` document is manufactured **by OpenIAM**, not by the connector. Its `status` is always `"Error"` and it has no `lastError`. If the only document you have is a `SERVICE_DOWN`, the connector never answered — there is nothing to read a target-side error out of, because no target was contacted.
{% endhint %}

### What green does and does not prove

| Observation                                               | Proves                                                                                               | Does not prove                                                                                                                                   |
| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| Managed system `IS_ACTIVE = 'Y'`                          | OpenIAM will use it for provisioning                                                                 | Anything about the connector or the target                                                                                                       |
| Save succeeded                                            | The row persisted                                                                                    | That any value in it is correct or reachable                                                                                                     |
| `connectorreply` doc exists, `status = "Ok"`              | A connector process consumed the broadcast and answered affirmatively within the last sweep interval | That it answered about *your* target, that the credential has the permissions the operations need, or that the endpoint is the right environment |
| The connector implements a real target-aware test handler | Whatever that handler tests                                                                          | The operations it does not test — create, membership, password and delete each need different target rights                                      |
| A provisioning `connectorreply` says success              | The connector reported success for that one operation                                                | That the resulting target object is correct. Read it back.                                                                                       |
| The target object is correct                              | The business outcome occurred                                                                        | That the *next* run will work, or that retention and scheduling are configured                                                                   |

The one failure worse than red is a green connection to the wrong environment, and nothing in OpenIAM can detect it.

## Related

* [Connectors and managed systems](/administration-guide/lifecycle/connectors-and-managed-systems.md) — queue naming, and runtime versus configuration.
* [Configure a managed system](/administration-guide/lifecycle/configure-managed-system.md) — the fields the heartbeat carries to the connector.
* [Configure provisioning](/administration-guide/lifecycle/configure-provisioning.md) — what to do with a failed operation, and the real retry path.
* [Search indexes and the authorization graph](/administration-guide/reference/search-indexes.md) — `connectorreply` and the request chain.
* [Audit actions and retention](/administration-guide/reference/audit-actions-and-retention.md) — `PROVISIONING_TEST`, `CONNECTOR_RESPONSE`.

*Applies to OpenIAM 2026.8.1. Last reviewed 7 August 2026.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/lifecycle/verify-connection.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
