> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/harness-solutions-factory/3.0/use-hsf/hsf-plugins/harness-idp-resource-manager.md).

# IDP Resource Manager Plugin

The Harness IDP Resource Manager plugin provides full lifecycle management for [Harness Internal Developer Portal (IDP)](https://app.gitbook.com/s/1bzrz9ybUGCcYdvS4u0z/README) entities. Use it in your Harness pipelines to register, update, query, and remove IDP entities such as workflows, resources, systems, and components. The plugin also supports backwards compatibility with IDP 1.0-style configurations via Git sync.

### Important notes <a href="#important-notes" id="important-notes"></a>

{% hint style="info" %}

* The plugin requires Python 3.11+ and Docker with `buildx` support at runtime.
* The `remove` operation is **destructive and irreversible**. Always verify `PLUGIN_SCOPES` before running.
* The `view` mode requires IDP 2.0. It is not supported on IDP 1.0 accounts.
* `PLUGIN_PROJECT_ID` requires `PLUGIN_ORG_ID` to be set. Project-scoped operations without an org will fail.
* `PLUGIN_HARNESS_URL` is deprecated. Use `PLUGIN_HARNESS_URI` for all new configurations.
  {% endhint %}

### Plugin image <a href="#plugin-image" id="plugin-image"></a>

```
harnesssolutionfactory/harness-idp-resource-manager:latest
```

### Operation modes <a href="#operation-modes" id="operation-modes"></a>

Set `PLUGIN_SWITCH` to control what the plugin does. If not set, the plugin defaults to `main`.

| Mode                | Description                                                                   |
| ------------------- | ----------------------------------------------------------------------------- |
| `main` / `register` | Register or upsert IDP entities from a registration file or filter template   |
| `register_multi`    | Register multiple resources using a shared payload template with substitution |
| `view`              | List all entities of a specified type. Requires IDP 2.0                       |
| `check`             | Verify IDP 2.0 compatibility and resource existence at a given scope          |
| `property`          | Update a custom metadata property on an existing entity                       |
| `remove`            | ⚠️ Delete all entities at the specified scope(s). Destructive operation       |
| `children`          | Register child entities from a parent template directory                      |
| `legacy`            | Register entities using IDP 1.0-style Git sync                                |

### Supported entity types <a href="#supported-entity-types" id="supported-entity-types"></a>

Set `PLUGIN_ENTITY_TYPE` to target a specific kind of IDP catalog entity. Applies to all modes except `check`.

| Value       | Description                                                 |
| ----------- | ----------------------------------------------------------- |
| `workflow`  | IDP software templates / workflows                          |
| `resource`  | Infrastructure or platform resources                        |
| `system`    | Logical groupings of related components                     |
| `component` | Services, libraries, websites, or other software components |

### Use in Harness pipelines <a href="#use-in-harness-pipelines" id="use-in-harness-pipelines"></a>

Add the plugin as a **Plugin** step in your stage. The examples below cover each operation mode.

{% hint style="info" %}
Go to [Custom plugins](/continuous-integration/use-harness-ci/use-harness-ci/use-drone-plugins/custom_plugins.md#variables-in-plugin-scripts) to review how Harness Plugin Steps require the scripts to support environment variables with a prefix of `PLUGIN_`. However, when referring to these variables in the Harness pipeline plugin step, you must remove the prefix. For example, `PLUGIN_HARNESS_URI` becomes `HARNESS_URI`. This accounts for the appearance of a discrepancy between the actual environment variables and the settings on the plugin step.
{% endhint %}

#### Register workflows <a href="#register-workflows" id="register-workflows"></a>

Register workflows from the Harness Template Library using a registration file:

```yaml
- step:
    type: Plugin
    name: Register Workflows
    identifier: register_workflows
    description: Register IDP workflows from the template library
    spec:
      connectorRef: <+input>
      image: harnesssolutionfactory/harness-idp-resource-manager:latest
      settings:
        HARNESS_URI: <+pipeline.variables.hsf_account_url>
        HARNESS_ACCT: <+account.identifier>
        HARNESS_API_KEY: <+pipeline.variables.HARNESS_PLATFORM_KEY>
        SWITCH: register
        ENTITY_TYPE: workflow
        WORKING_DIR: <+stepGroup.steps.Clone_Repository.spec.cloneDirectory>
        REGISTRATION_FILE: idp_registration_mgr.yaml
        FILTER_TEMPLATE: <+pipeline.variables.filter_template>
        INCLUDE_CHILDREN: <+pipeline.variables.include_children>
        ORG_ID: <+pipeline.variables.org_id>
        PROJECT_ID: <+pipeline.variables.project_id>
        DEBUG_MODE: "false"
```

#### Register resources from a Jinja2 template <a href="#register-resources-from-a-jinja2-template" id="register-resources-from-a-jinja2-template"></a>

Register IDP resources by rendering a Jinja2 template with a JSON payload:

```yaml
- step:
    type: Plugin
    name: Register Resources
    identifier: register_resources
    description: Register IDP resources using a Jinja2 template and JSON payload
    spec:
      connectorRef: <+input>
      image: harnesssolutionfactory/harness-idp-resource-manager:latest
      settings:
        HARNESS_URI: <+pipeline.variables.hsf_account_url>
        HARNESS_ACCT: <+account.identifier>
        HARNESS_API_KEY: <+pipeline.variables.HARNESS_PLATFORM_KEY>
        SWITCH: register
        ENTITY_TYPE: resource
        WORKING_DIR: <+stepGroup.steps.Clone_Repository.spec.cloneDirectory>
        ENTITY_TEMPLATE: idp_resource_templates/default_hsf_workspace_resource.yaml.j2
        ENTITY_PAYLOAD: '{"resource_name":"Account Workspace","is_resource_drifted":"true","workspace_uri":"https://app.harness.io/ng/account/ABC123/module/iacm/orgs/my-org/projects/my-project/workspaces/my-workspace"}'
        ORG_ID: Harness_Platform_Management
        PROJECT_ID: Solutions_Factory
        DEBUG_MODE: "false"
```

#### Register systems from a static entity file <a href="#register-systems-from-a-static-entity-file" id="register-systems-from-a-static-entity-file"></a>

Register IDP systems directly from a YAML entity file without template rendering:

```yaml
- step:
    type: Plugin
    name: Register Systems
    identifier: register_systems
    description: Register IDP systems from a static entity file
    spec:
      connectorRef: <+input>
      image: harnesssolutionfactory/harness-idp-resource-manager:latest
      settings:
        HARNESS_URI: <+pipeline.variables.hsf_account_url>
        HARNESS_ACCT: <+account.identifier>
        HARNESS_API_KEY: <+pipeline.variables.HARNESS_PLATFORM_KEY>
        SWITCH: register
        ENTITY_TYPE: system
        WORKING_DIR: <+stepGroup.steps.Clone_Repository.spec.cloneDirectory>
        ENTITY_FILE: lob/core.yaml
        ORG_ID: Harness_Platform_Management
        PROJECT_ID: Solutions_Factory
        USE_TEMPLATE_MGR: "false"
```

#### Register components <a href="#register-components" id="register-components"></a>

Register IDP components from a static entity file:

```yaml
- step:
    type: Plugin
    name: Register Components
    identifier: register_components
    description: Register IDP components from a static entity file
    spec:
      connectorRef: <+input>
      image: harnesssolutionfactory/harness-idp-resource-manager:latest
      settings:
        HARNESS_URI: <+pipeline.variables.hsf_account_url>
        HARNESS_ACCT: <+account.identifier>
        HARNESS_API_KEY: <+pipeline.variables.HARNESS_PLATFORM_KEY>
        SWITCH: register
        ENTITY_TYPE: component
        WORKING_DIR: <+stepGroup.steps.Clone_Repository.spec.cloneDirectory>
        ENTITY_FILE: lob/core.yaml
        ORG_ID: Harness_Platform_Management
        PROJECT_ID: Solutions_Factory
        USE_TEMPLATE_MGR: "false"
```

#### Query entities <a href="#query-entities" id="query-entities"></a>

List all existing entities of a given type:

```yaml
- step:
    type: Plugin
    name: Get Workflows
    identifier: get_workflows
    description: Retrieve all existing workflows from IDP
    spec:
      connectorRef: <+input>
      image: harnesssolutionfactory/harness-idp-resource-manager:latest
      settings:
        HARNESS_URI: <+pipeline.variables.hsf_account_url>
        HARNESS_ACCT: <+account.identifier>
        HARNESS_API_KEY: <+pipeline.variables.HARNESS_PLATFORM_KEY>
        SWITCH: view
        ENTITY_TYPE: workflow
```

#### Check entity existence at scope <a href="#check-entity-existence-at-scope" id="check-entity-existence-at-scope"></a>

Verify IDP 2.0 compatibility and whether resources exist at a given scope:

```yaml
- step:
    type: Plugin
    name: Check Resources
    identifier: check_resources
    description: Check if resources exist at a specific org and project scope
    spec:
      connectorRef: <+input>
      image: harnesssolutionfactory/harness-idp-resource-manager:latest
      settings:
        HARNESS_URI: <+pipeline.variables.hsf_account_url>
        HARNESS_ACCT: <+account.identifier>
        HARNESS_API_KEY: <+pipeline.variables.HARNESS_PLATFORM_KEY>
        SWITCH: check
        ORG_ID: CDK_Prod
        PROJECT_ID: Enterprise_IT_IOPS_Orchestration
```

#### Update a custom property <a href="#update-a-custom-property" id="update-a-custom-property"></a>

Update a dot-notation metadata property on an existing entity:

```yaml
- step:
    type: Plugin
    name: Update Resource Properties
    identifier: update_resource_props
    description: Set a custom metadata property on an existing IDP resource
    spec:
      connectorRef: <+input>
      image: harnesssolutionfactory/harness-idp-resource-manager:latest
      settings:
        HARNESS_URI: <+pipeline.variables.hsf_account_url>
        HARNESS_ACCT: <+account.identifier>
        HARNESS_API_KEY: <+pipeline.variables.HARNESS_PLATFORM_KEY>
        SWITCH: property
        ENTITY_TYPE: resource
        ENTITY_ID: account_workspace
        HSF_PROPERTY: metadata.hsf.is_drifted
        HSF_VALUE: "false"
        ORG_ID: Harness_Platform_Management
        PROJECT_ID: Solutions_Factory
```

#### Remove entities at scope <a href="#remove-entities-at-scope" id="remove-entities-at-scope"></a>

{% hint style="danger" %}
This is a destructive, irreversible operation. All entities at the specified scope(s) will be permanently deleted. Verify `PLUGIN_SCOPES` before running.
{% endhint %}

```yaml
- step:
    type: Plugin
    name: Delete Workflows
    identifier: delete_workflows
    description: Remove all workflows at a specified scope
    spec:
      connectorRef: <+input>
      image: harnesssolutionfactory/harness-idp-resource-manager:latest
      settings:
        HARNESS_URI: <+pipeline.variables.hsf_account_url>
        HARNESS_ACCT: <+account.identifier>
        HARNESS_API_KEY: <+pipeline.variables.HARNESS_PLATFORM_KEY>
        SWITCH: remove
        ENTITY_TYPE: workflow
        SCOPES: account.Harness_Platform_Management
```

***

### Settings reference <a href="#settings-reference" id="settings-reference"></a>

#### Connection and authentication <a href="#connection-and-authentication" id="connection-and-authentication"></a>

| Setting                  | Type   | Required | Default | Description                                                                                     |
| ------------------------ | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------- |
| `PLUGIN_HARNESS_URI`     | String | Yes      | N/A     | Base URL of the Harness platform. Example: `https://app.harness.io`                             |
| `PLUGIN_HARNESS_ACCT`    | String | Yes      | N/A     | Your Harness account identifier. Example: `HT1234569XFhhslllddd12`                              |
| `PLUGIN_HARNESS_API_KEY` | String | Yes      | N/A     | API token with permissions to manage IDP entities. Example: `pat.xxxxx`                         |
| `PLUGIN_HARNESS_URL`     | String | No       | N/A     | **Deprecated.** Alternative variable for the Harness API URL. Use `PLUGIN_HARNESS_URI` instead. |

#### Operation control <a href="#operation-control" id="operation-control"></a>

| Setting              | Type   | Required | Default    | Description                                                                                                             |
| -------------------- | ------ | -------- | ---------- | ----------------------------------------------------------------------------------------------------------------------- |
| `PLUGIN_SWITCH`      | String | No       | `main`     | Operation mode. Go to [Operation modes](#operation-modes) for accepted values.                                          |
| `PLUGIN_ENTITY_TYPE` | String | No       | `workflow` | Type of IDP entity to manage. Accepted values: `workflow`, `resource`, `system`, `component`. Not used in `check` mode. |
| `PLUGIN_DEBUG_MODE`  | String | No       | `false`    | Set to `true` to enable verbose debug logging.                                                                          |

#### Scope and organization <a href="#scope-and-organization" id="scope-and-organization"></a>

| Setting             | Type   | Required | Default       | Description                                                                                                                                                                               |
| ------------------- | ------ | -------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PLUGIN_ORG_ID`     | String | No       | Account scope | Organization identifier. If omitted, operations default to account scope.                                                                                                                 |
| `PLUGIN_PROJECT_ID` | String | No       | Account scope | Project identifier. Requires `PLUGIN_ORG_ID` to be set.                                                                                                                                   |
| `PLUGIN_SCOPES`     | String | No       | N/A           | Scope(s) for `remove` operations. Accepts comma-separated values. Format: `all`, `account`, `account.ORG_ID`, or `account.ORG_ID.PROJ_ID`. Example: `account.Harness_Platform_Management` |

#### File and directory configuration <a href="#file-and-directory-configuration" id="file-and-directory-configuration"></a>

| Setting                    | Type   | Required    | Default                             | Description                                                                                                                                                                                                          |
| -------------------------- | ------ | ----------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PLUGIN_WORKING_DIR`       | String | No          | `/harness/harness-template-library` | Full path to the directory containing configuration or template files.                                                                                                                                               |
| `PLUGIN_REGISTRATION_FILE` | String | Conditional | N/A                                 | YAML file (relative to `PLUGIN_WORKING_DIR`) that lists entities to register. Required if `PLUGIN_FILTER_TEMPLATE` is not set. Applies to `main`, `register`, `children` modes. Example: `idp_registration_mgr.yaml` |

#### Template and entity registration <a href="#template-and-entity-registration" id="template-and-entity-registration"></a>

| Setting                   | Type          | Required    | Default | Description                                                                                                                                                                                                                         |
| ------------------------- | ------------- | ----------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PLUGIN_FILTER_TEMPLATE`  | String        | Conditional | N/A     | Workflow, template name, or directory name within `PLUGIN_WORKING_DIR` to register. Required if `PLUGIN_REGISTRATION_FILE` is not set. Applies to `main`, `register`, `children`, `legacy` modes. Example: `sto-sast-primer`        |
| `PLUGIN_FILTER_TAG`       | String        | No          | N/A     | Tag filter for narrowing entity results in `view` mode. Example: `managed_entity`                                                                                                                                                   |
| `PLUGIN_INCLUDE_CHILDREN` | String        | No          | `no`    | Set to `yes` to load child entities from the `PLUGIN_FILTER_TEMPLATE` directory. Applies to `main`, `register`, `children`, `legacy` modes.                                                                                         |
| `PLUGIN_ENTITY_FILE`      | String        | Conditional | N/A     | Path to a YAML entity definition file, relative to `PLUGIN_WORKING_DIR`. Required for non-template registration in `register` mode. Example: `lob/core.yaml`                                                                        |
| `PLUGIN_ENTITY_TEMPLATE`  | String        | Conditional | N/A     | Path to a Jinja2 template file, relative to `PLUGIN_WORKING_DIR`. Required when using template rendering. Example: `idp_resource_templates/default_hsf_workspace_resource.yaml.j2`                                                  |
| `PLUGIN_ENTITY_PAYLOAD`   | String (JSON) | Conditional | N/A     | JSON object with variables for Jinja2 template injection. Required when `PLUGIN_ENTITY_TEMPLATE` is set. Applies to `register` and `register_multi` modes. Example: `'{"resource_name":"workspace","workspace_uri":"https://..."}'` |
| `PLUGIN_USE_TEMPLATE_MGR` | String        | No          | `true`  | Set to `true` to use Jinja2 template rendering. Set to `false` to use static entity files.                                                                                                                                          |

#### Entity management <a href="#entity-management" id="entity-management"></a>

| Setting            | Type   | Required    | Default | Description                                                                                                                                    |
| ------------------ | ------ | ----------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `PLUGIN_ENTITY_ID` | String | Conditional | N/A     | Identifier of the entity to update or delete. Required for entity-specific operations in `remove` and `property` modes. Example: `my_resource` |
| `PLUGIN_RESOURCES` | String | Conditional | N/A     | Comma-separated list of resource names for `register_multi` mode. Example: `lab,lab_workshop`                                                  |

#### Custom properties <a href="#custom-properties" id="custom-properties"></a>

| Setting               | Type   | Required                 | Default | Description                                                                              |
| --------------------- | ------ | ------------------------ | ------- | ---------------------------------------------------------------------------------------- |
| `PLUGIN_HSF_PROPERTY` | String | Yes (in `property` mode) | N/A     | Dot-notation path of the metadata property to update. Example: `metadata.hsf.is_drifted` |
| `PLUGIN_HSF_VALUE`    | String | Yes (in `property` mode) | N/A     | Value to assign to `PLUGIN_HSF_PROPERTY`. Example: `false`                               |

#### Legacy settings <a href="#legacy-settings" id="legacy-settings"></a>

| Setting              | Type   | Required               | Default | Description                                              |
| -------------------- | ------ | ---------------------- | ------- | -------------------------------------------------------- |
| `PLUGIN_REPO_BRANCH` | String | Yes (in `legacy` mode) | `main`  | Git branch used for IDP 1.0-style Git sync registration. |

***

### Local development <a href="#local-development" id="local-development"></a>

#### Docker examples <a href="#docker-examples" id="docker-examples"></a>

The plugin can be run directly with Docker for local testing. Mount your local template library into the container so the plugin can locate entity files.

**Register workflows:**

```bash
docker run --rm -it \
  -e PLUGIN_HARNESS_URI=https://app.harness.io \
  -e PLUGIN_HARNESS_ACCT=your_account_id \
  -e PLUGIN_HARNESS_API_KEY=your_api_key \
  -e PLUGIN_SWITCH=register \
  -e PLUGIN_ENTITY_TYPE=workflow \
  -e PLUGIN_WORKING_DIR=/harness/harness-template-library \
  -e PLUGIN_REGISTRATION_FILE=idp_registration_mgr.yaml \
  -e PLUGIN_DEBUG_MODE=true \
  -v /path/to/template-library:/harness/harness-template-library \
  -v $(pwd):/harness \
  harnesssolutionfactory/harness-idp-resource-manager:latest
```

**Register resources with a Jinja2 template:**

```bash
docker run --rm -it \
  -e PLUGIN_HARNESS_URI=https://app.harness.io \
  -e PLUGIN_HARNESS_ACCT=your_account_id \
  -e PLUGIN_HARNESS_API_KEY=your_api_key \
  -e PLUGIN_SWITCH=register \
  -e PLUGIN_ENTITY_TYPE=resource \
  -e PLUGIN_WORKING_DIR=/harness/harness-template-library \
  -e PLUGIN_ENTITY_TEMPLATE=idp_resource_templates/default_hsf_workspace_resource.yaml.j2 \
  -e 'PLUGIN_ENTITY_PAYLOAD={"resource_name":"my-workspace","is_resource_drifted":"false","workspace_uri":"https://app.harness.io/..."}' \
  -e PLUGIN_ORG_ID=my_org \
  -e PLUGIN_PROJECT_ID=my_project \
  -e PLUGIN_DEBUG_MODE=true \
  -v /path/to/template-library:/harness/harness-template-library \
  -v $(pwd):/harness \
  harnesssolutionfactory/harness-idp-resource-manager:latest
```

**View all workflows:**

```bash
docker run --rm -it \
  -e PLUGIN_HARNESS_URI=https://app.harness.io \
  -e PLUGIN_HARNESS_ACCT=your_account_id \
  -e PLUGIN_HARNESS_API_KEY=your_api_key \
  -e PLUGIN_SWITCH=view \
  -e PLUGIN_ENTITY_TYPE=workflow \
  harnesssolutionfactory/harness-idp-resource-manager:latest
```

**Update a custom property:**

```bash
docker run --rm -it \
  -e PLUGIN_HARNESS_URI=https://app.harness.io \
  -e PLUGIN_HARNESS_ACCT=your_account_id \
  -e PLUGIN_HARNESS_API_KEY=your_api_key \
  -e PLUGIN_SWITCH=property \
  -e PLUGIN_ENTITY_TYPE=resource \
  -e PLUGIN_ENTITY_ID=my_resource \
  -e PLUGIN_HSF_PROPERTY=metadata.hsf.is_drifted \
  -e PLUGIN_HSF_VALUE=false \
  -e PLUGIN_ORG_ID=my_org \
  -e PLUGIN_PROJECT_ID=my_project \
  harnesssolutionfactory/harness-idp-resource-manager:latest
```
