ITSM-led Change Process

Overview

Integrate seamlessly with external ITSM (Information Technology Service Management) solutions to drive automated security policy changes through a structured, approval-driven workflow.

ITSM-led Change Process guides you through using SecureChange and the Workflow Integrator (WFI) application extension to integrate external ITSM platforms with security policy change workflows. In this implementation, the external ITSM platform initiates, controls, and synchronizes approval-driven firewall and access change workflows, while WFI manages the integration points, outbound communication, and payload handling.

When the required integration logic goes beyond WFI configuration, you can extend the workflow with custom mediator-based scripts and a trigger service. This aligns ITSM-driven change processes with security policy enforcement, automation, and governance.

Why this matters
  • Unify security policy change with enterprise IT governance.

  • Align network policy workflows with existing ITSM processes.

  • Synchronize workflow lifecycle events with external ITSM platforms.

Who this is for
  • Change managers responsible for overseeing ITSM and SecureChange integration and ensuring approvals align with governance.

  • Network engineers responsible for automated policy changes executed through ITSM workflows.

  • System engineers responsible for configuring endpoints, credentials, and testing communication.

  • Operational managers responsible for ensuring workflow adoption across teams.

Key capabilities

ITSM-led Change Process leverages:

Prerequisites

Successful completion of:

Step 1: Configure WFI settings and outbound server communication

In this step, you configure the Workflow Integrator (WFI) to integrate with SecureChange.

  • Use Workflow Integrator application from Extensions.

Configure SecureChange connection settings in WFI

After installing WFI, connect it to SecureChange so it can retrieve Access Request workflow information and add the required risk analysis scripts.

Go to WFI > Settings.

Configure:

  • SecureChange connection

    • The FQDN or IP oof the SecureChange server.

    • Login credentials for SecureChange user with the permission - "Create and handle tickets on behalf of another user (via API only)"

  • Email notification: Configure the SMTP server details to send alerts for trigger executions, failures, or status changes.

Leave the other settings unchanged.

See Configuring WFI.

Configure outbound server communication

When you create an integration between a SecureChange workflow and an external system, define the outbound server that WFI uses to send requests.

  • If you integrate with a single external system, define one default outbound server for the workflow.

  • If you integrate with multiple external systems, define a default outbound server and additional outbound servers for the relevant cases.

  • Configure each outbound server in WFI before you use it in a workflow integration.

 

  • Go to WFI > Server.

See Configuring an outbound server.

Configure SecureChange workflows in WFI

In this step, you'll integrate the SecureChangeworkflow in WFI. The integration defines where and when API requests are sent to the external ITSM and what payload is exchanged.

Configure each outbound server in WFI before you use it in a workflow integration.

  • Go to WFI > Workflow > New Workflow.

Workflow, Outbound server
  • Step-level integration points and triggers: Inbound, Outbound, and Step Trigger

  • Workflow-level triggers: Event-driven actions tied to SecureChange lifecycle states that applies to the entire workflow

Placeholders

Configure placeholders to replace template values with actual ticket data when a WFI request is triggered.
When the SecureChange notifies WFI, WFI parses the configured template and automatically replaces placeholders with actual ticket data.

See:

Integrating a workflow with an ITSM solution

Placeholders

Example Access Request workflow

Step 2: Extend workflows with custom scripts

Use custom scripts when WFI configuration alone does not cover the required integration logic. In this implementation, custom scripts let you run additional logic at defined workflow events by using mediator scripts and a trigger service.

Key concepts:
  • Custom scripts: Contain the business logic.

  • Mediator scripts: Bridge SecureChange and the custom scripts.

  • Trigger service or web server: Receives requests from the mediator and runs the custom integration logic.

Example: Prepare a non-Tufin OS platform on Rocky Linux

For a non-Tufin OS deployment on Rocky Linux, start by preparing the platform for the trigger service.

  • Install: Python, pip, pipx, Poetry

Example commands:

  • dnf install python3.11 -y
  • dnf install python3-pip -y
  • python3 -m pip install --user pipx
  • python3 -m pipx ensurepath
  • curl -sSL https://install.python-poetry.org | python3 - --version 1.0.0
  • poetry --version

See Custom scripts for SecureChange workflows.

Create Web Server for custom scripts

Set up and configure a web server using Python FastAPI, Flask, or Node.js to receive requests from the mediator and execute your custom ITSM integration logic.

Trigger service requirements

  • cd /opt

  • mkdir -p trigger-service && curl "https://gitlab.com/api/v4/projects/tufinps%2Ftos2%2Ftrigger-example/repository/archive.tar.gz" | tar -zx -C trigger-service --strip-components 1

  • Edit pyproject.toml:

    • Update python = "~3.11.13"

    • Remote the line dataclasses = "^0.8"

  • Make python3.11 as an alternative to python3 using the command: -update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1

  • update-alternatives --config python3

  • Execute the following commands:

cd trigger-service && \
python3 -m venv venv && \
source venv/bin/activate && \
pip3 install --upgrade pip && \
pip3 install poetry && \
poetry install

Create and deploy mediator script

The mediator is a Bash script that receives XML from SecureChange, encodes it, and sends it to your web server as a JSON payload.

  1. Create script_mediator.sh using the example below as a reference.

    #! /bin/bash

    ARGS=($@)
    TICKET_INFO=$(cat | base64 -w0)

    # User hardcoded arguments 
    HOST=10.244.0.1:8000
    ENDPOINT=trigger_file
    USERNAME=username
    PASSWORD=password
    EXEC_SCRIPT=/opt/trigger-service/test.py

    #all additional arguments taken from SC
    EXEC_ARGS=${ARGS[@]:1}

    # define the payload to send to your webserver
    PAYLOAD="{ \
      \"ticket_info\":\"${TICKET_INFO}\",
      \"event\":\"${SCW_EVENT}\",
      \"args\":\"${EXEC_ARGS}\",
      \"script\":\"${EXEC_SCRIPT}\"
    }"

    RESP=$(curl -sS --fail -X POST -u "${USERNAME}:${PASSWORD}" "${HOST}/${ENDPOINT}" \
        -H "Content-Type: application/json" \
        -d "${PAYLOAD}" 2>&1)

    HTTP_EXT_CODE=$?
    [ $HTTP_EXT_CODE -ne 0 ] && \
        echo $RESP > /dev/stderr && exit $HTTP_EXT_CODE 

    export RESP

    # parse the response json in python, the schema may differ from
    # server to server implementation
    python -c "
    import os, sys, json

    p = json.loads(os.getenv('RESP') or {})
    output = p.get('output', '')
    error = p.get('error', None)
    stderr = error.get('output', '') if error else ''
    ext_code = error.get('returnCode', 0) if error else 0
     
    sys.stdout.write(output)
    if ext_code != 0:
        sys.stderr.write(stderr)
    sys.exit(ext_code)
  2. Make it executable:

    chmod 774 script_mediator.sh
  3. Push it to the SecureChange pod:

    tos scripts sc push /opt/trigger-service/script_mediator.sh

Create and configure trigger service

Create and configure trigger service with environment variables and paths.

  1. Create the file /etc/systemd/system/trigger.service with the following content:

    [Unit]
    Description=Tufin Trigger Service
    After=network.target

    [Service]
    Type=simple
    WorkingDirectory=/opt/trigger-service/
    Environment=PATH=/opt/trigger-service/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    Environment=PYTHONPATH=/opt/trigger-service/venv/lib/python3.11/site-packages:/opt/trigger-service/venv/bin
    Environment=KUBECONFIG=/etc/rancher/k3s/k3s.yaml
    ExecStart=/opt/trigger-service/venv/bin/uvicorn trigger_proxy:app --host 0.0.0.0
    ExecReload=/bin/kill -HUP $MAINPID
    Restart=on-failure

    [Install]
    WantedBy=multi-user.target
  2. Run these commands:

    chmod 644 /etc/systemd/system/trigger.service
    systemctl start trigger
    systemctl enable trigger
    source venv/bin/activate
    pip install "fastapi==0.99.1" "pydantic==1.10.13" –upgrade
    python -c "import fastapi, pydantic; print('fastapi', fastapi.__version__, 'pydantic', pydantic.__version__)"
    deactivate
    systemctl start trigger
    systemctl status trigger 

The status should be up and running.

Create custom Python script

  1. Create a custom script (test.py) to read the XML ticket, interact with SecureChange APIs, and updates fields, using the example below for reference.

    #!/usr/bin/env python3

    import asyncio
    from datetime import datetime
    import json
    from os import getenv
    from sys import stdin
    from xml.etree.ElementTree import fromstring

    import httpx
    from pydantic import AnyUrl, BaseSettings


    class Settings(BaseSettings):
        securechange_url: AnyUrl = "https://<uname>:<password>@<ip>/securechangeworkflow/api/securechange"  # type: ignore

        class Config:
            # .env file overrides
            env_file = ".env"
            env_file_encoding = "utf-8"


    settings = Settings()


    async def get_ticket(ticket_id):
        async with httpx.AsyncClient(
            base_url=settings.securechange_url, verify=False, timeout=30
        ) as client:
            res = await client.get(f"/tickets/{ticket_id}.json")
            res.raise_for_status()
            ticket_json = res.json()
            return ticket_json


    async def update_field(ticket, field_name, value):
        ticket_id = ticket["ticket"]["id"]
        current_step = ticket["ticket"]["steps"]["step"][-1]
        current_task = current_step["tasks"]["task"]
        x = [f for f in current_task["fields"]["field"] if f["name"] == field_name]
        field = x[0] if len(x) > 0 else None
        if not field:
            return None
        field["reason"] = value
        put_field_url = f"/tickets/{ticket_id}/steps/{current_step['id']}/tasks/{current_task['id']}/fields/"
        async with httpx.AsyncClient(
            base_url=settings.securechange_url,
            verify=False,
            timeout=30,
            headers={"Accept": "application/json"},
        ) as client:
            return await client.put(
                put_field_url,
                json={"fields": {"field": [field]}},
            )


    async def process(ticket_id, previous_step):
        ticket = await get_ticket(ticket_id)
        if previous_step != ticket["ticket"]["steps"]["step"][-2]["name"]:
            print("Ticket is no longer at the expected step")
        res = await update_field(
            ticket,
            "Approve Access Request",
            "newval" + str(datetime.now()),
        )
        print(res.text if res else "no field match")
        if res and not res.is_error:
            print("Successfully updated field")
        return res


    async def run_from_stdin():
        scw_event = getenv("SCW_EVENT")
        if scw_event == "ADVANCE":
            ticket_info = stdin.read()

            ticket_info_xml = fromstring(ticket_info)

            # Parse the ticket id
            x = ticket_info_xml.find("id")
            ticket_id = x.text if x is not None else None

            # parse the previous step
            previous_stage = ticket_info_xml.find("current_stage")
            x = previous_stage.find("name")
            previous_step_name = (
                (x.text if x is not None else None) if previous_stage else None
            )
            return await process(ticket_id, previous_step_name)


    if __name__ == "__main__":
        loop = asyncio.get_event_loop()
        loop.run_until_complete(run_from_stdin())
        # asyncio.run(run_from_stdin())
  2. Make it executable:

chmod 7777 test.py

Create SecureChange workflow

Create a SecureChange workflow with these attributes and steps:

  • Workflow type: Access request

  • Workflow name: Mediator Test
  • Step 1: Open Request: Add field: Access Request

  • Step 2: Auto Target: Set step to Auto mode, and enable Designer and Risk analysis

  • Step 3: Approval: Add fields: Access Request and Approve Access Request

  • Save and activate the workflow.

Configure web service triggers

Connect the mediator script you created earlier in SecureChange to interact with your custom script.

  1. Go to Settings > SecureChange API.

  2. Add new script with these settings:

    • Name: Mediator

    • Path: /opt/tufin/data/securechange/scripts/script_mediator.sh

    • Workflow: Mediator Test

    • Trigger: Advance

  3. To validate, click Test.

Validate script

Run a final validation to confirm that the custom script works as expected.

• Create a ticket for the Mediator Test workflow with a sample access request.

• Confirm that the 'Reason' field was updated with timestamp value similar to newval<datetime> confirming that script worked correctly.