diff --git a/gso/migrations/versions/2023-06-26_e57ebfade80b_add_iptrunk_modify_workflow.py b/gso/migrations/versions/2023-06-26_e57ebfade80b_add_iptrunk_modify_workflow.py
new file mode 100644
index 0000000000000000000000000000000000000000..cad31c4d8c9436c98513757b14b8b3fa6d18f394
--- /dev/null
+++ b/gso/migrations/versions/2023-06-26_e57ebfade80b_add_iptrunk_modify_workflow.py
@@ -0,0 +1,39 @@
+"""add Iptrunk modify workflow.
+
+Revision ID: e57ebfade80b
+Revises: 7694b98571f8
+Create Date: 2023-06-26 12:20:16.828055
+
+"""
+import sqlalchemy as sa
+from alembic import op
+
+# revision identifiers, used by Alembic.
+revision = 'e57ebfade80b'
+down_revision = '7694b98571f8'
+branch_labels = None
+depends_on = None
+
+
+from orchestrator.migrations.helpers import create_workflow, delete_workflow
+
+new_workflows = [
+    {
+        "name": "modify_generic",
+        "target": "MODIFY",
+        "description": "Modify IP trunk",
+        "product_type": "Iptrunk"
+    }
+]
+
+
+def upgrade() -> None:
+    conn = op.get_bind()
+    for workflow in new_workflows:
+        create_workflow(conn, workflow)
+
+
+def downgrade() -> None:
+    conn = op.get_bind()
+    for workflow in new_workflows:
+        delete_workflow(conn, workflow["name"])
diff --git a/gso/products/product_blocks/__init__.py b/gso/products/product_blocks/__init__.py
index d1f718d83ec9df7d2b68374f4a7149168dac76b2..221e9d44891e867eb511b23f3347615b8e36bd89 100644
--- a/gso/products/product_blocks/__init__.py
+++ b/gso/products/product_blocks/__init__.py
@@ -1,8 +1,8 @@
-from enum import IntEnum
+from enum import Enum
 
 
-class PhyPortCapacity(IntEnum):
-    ONE = 1
-    TEN = 10
-    HUNDRED = 100
-    FOUR_HUNDRED = 400
+class PhyPortCapacity(Enum):
+    ONE = "1g"
+    TEN = "10g"
+    HUNDRED = "100g"
+    FOUR_HUNDRED = "400g"
diff --git a/gso/translations/en-GB.json b/gso/translations/en-GB.json
index c340082fc6574fd66ec32249296eeb4cda445dd4..418e7e852d144fe0f98d0bd9417a7b90cef63bfe 100644
--- a/gso/translations/en-GB.json
+++ b/gso/translations/en-GB.json
@@ -32,6 +32,8 @@
         }
     },
     "workflow": {
-         "modify_isis_metric": "Modify the ISIS metric."
-    }
+         "modify_isis_metric": "Modify the ISIS metric",
+         "modify_generic": "Modify Trunk interface", 
+         "confirm_info": "Please verify this form looks correct."
+	    }
 }
diff --git a/gso/workflows/__init__.py b/gso/workflows/__init__.py
index 77366536d0b024d4ae7837ad7a11e74bf3816612..61f560b81b02bf2e5c4ed7df0d89a92ff4171c86 100644
--- a/gso/workflows/__init__.py
+++ b/gso/workflows/__init__.py
@@ -4,12 +4,16 @@ init class that imports all workflows into GSO.
 from orchestrator.workflows import LazyWorkflowInstance
 
 LazyWorkflowInstance("gso.workflows.device.create_device", "create_device")
-LazyWorkflowInstance("gso.workflows.device.terminate_device",
-                     "terminate_device")
+LazyWorkflowInstance(
+    "gso.workflows.device.terminate_device", "terminate_device"
+)
 LazyWorkflowInstance("gso.workflows.device.get_facts", "get_facts")
 LazyWorkflowInstance("gso.workflows.iptrunk.create_iptrunk", "create_iptrunk")
+LazyWorkflowInstance("gso.workflows.iptrunk.modify_generic", "modify_generic")
 LazyWorkflowInstance("gso.workflows.iptrunk.terminate_iptrunk",
                      "terminate_iptrunk")
 LazyWorkflowInstance("gso.workflows.iptrunk.modify_isis_metric",
                      "modify_isis_metric")
+LazyWorkflowInstance("gso.workflows.iptrunk.modify_generic",
+                     "modify_generic")
 LazyWorkflowInstance("gso.workflows.site.create_site", "create_site")
diff --git a/gso/workflows/device/get_facts.py b/gso/workflows/device/get_facts.py
index 024631740dfbfacd229a1d442d26c0d274af5e8e..a50caee3a8fe3eba6811107615d1eca0f2ea58c4 100644
--- a/gso/workflows/device/get_facts.py
+++ b/gso/workflows/device/get_facts.py
@@ -1,9 +1,11 @@
 from orchestrator.forms import FormPage
 from orchestrator.forms.validators import Label
 from orchestrator.targets import Target
+
 # from orchestrator.types import SubscriptionLifecycle
 from orchestrator.types import InputForm, UUIDstr
 from orchestrator.workflow import done, init, step, workflow
+
 # from orchestrator.workflows.steps import (
 #     resync,
 #     set_status,
@@ -21,10 +23,8 @@ def initial_input_form_generator(
     subscription = Device.from_subscription(subscription_id)
 
     class TerminateForm(FormPage):
-        are_you_sure: Label = (
-            f"Are you sure you want to get facts from \
+        are_you_sure: Label = f"Are you sure you want to get facts from \
             {subscription.description}?"
-        )
 
     return TerminateForm
 
@@ -48,7 +48,8 @@ def get_facts(subscription_id) -> None:
 @workflow(
     "Get Facts from Device",
     initial_input_form=wrap_modify_initial_input_form(
-                       initial_input_form_generator),
+        initial_input_form_generator
+    ),
     target=Target.SYSTEM,
 )
 def get_facts_from_device():
diff --git a/gso/workflows/iptrunk/modify_generic.py b/gso/workflows/iptrunk/modify_generic.py
new file mode 100644
index 0000000000000000000000000000000000000000..9c3c633c352be9c555ca6afa39d92b58bb3ffcfe
--- /dev/null
+++ b/gso/workflows/iptrunk/modify_generic.py
@@ -0,0 +1,240 @@
+import ipaddress
+from orchestrator.forms import FormPage, ReadOnlyField
+from orchestrator.targets import Target
+from orchestrator.types import FormGenerator, State
+from orchestrator.types import UUIDstr
+from orchestrator.workflow import done, init, step, workflow
+from orchestrator.workflows.steps import resync
+from orchestrator.workflows.steps import store_process_subscription, unsync
+from orchestrator.workflows.utils import wrap_modify_initial_input_form
+from orchestrator.forms.validators import Choice, UniqueConstrainedList
+from gso.products.product_blocks.iptrunk import IptrunkType
+from gso.products.product_blocks import PhyPortCapacity
+
+from gso.products.product_types.iptrunk import (
+    Iptrunk,
+)
+from gso.services import provisioning_proxy
+from gso.services.provisioning_proxy import (
+    confirm_pp_results,
+    await_pp_results,
+)
+
+
+def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
+    subscription = Iptrunk.from_subscription(subscription_id)
+
+    class ModifyIptrunkForm(FormPage):
+        geant_s_sid: str = subscription.iptrunk.geant_s_sid
+        iptrunk_description: str = subscription.iptrunk.iptrunk_description
+        iptrunk_type: IptrunkType = subscription.iptrunk.iptrunk_type
+        iptrunk_speed: PhyPortCapacity = subscription.iptrunk.iptrunk_speed
+        iptrunk_minimum_links: int = subscription.iptrunk.iptrunk_minimum_links
+        iptrunk_isis_metric: int = ReadOnlyField(
+            subscription.iptrunk.iptrunk_isis_metric
+        )
+        iptrunk_ipv4_network: ipaddress.IPv4Network = ReadOnlyField(
+            subscription.iptrunk.iptrunk_ipv4_network
+        )
+        iptrunk_ipv6_network: ipaddress.IPv6Network = ReadOnlyField(
+            subscription.iptrunk.iptrunk_ipv6_network
+        )
+
+    initial_user_input = yield ModifyIptrunkForm
+
+    class AeMembersListA(UniqueConstrainedList[str]):
+        min_items = initial_user_input.iptrunk_minimum_links
+
+    class ModifyIptrunkSideAForm(FormPage):
+        class Config:
+            title = "Provide subscription details for side A of the trunk."
+
+        iptrunk_sideA_node: str = ReadOnlyField(
+            subscription.iptrunk.iptrunk_sideA_node.device_fqdn
+        )
+        iptrunk_sideA_ae_iface: str = ReadOnlyField(
+            subscription.iptrunk.iptrunk_sideA_ae_iface
+        )
+        iptrunk_sideA_ae_geant_a_sid: str = (
+            subscription.iptrunk.iptrunk_sideA_ae_geant_a_sid
+        )
+        iptrunk_sideA_ae_members: AeMembersListA = (
+            subscription.iptrunk.iptrunk_sideA_ae_members
+        )
+        iptrunk_sideA_ae_members_descriptions: AeMembersListA = (
+            subscription.iptrunk.iptrunk_sideA_ae_members_description
+        )
+
+    user_input_side_a = yield ModifyIptrunkSideAForm
+
+    class AeMembersListB(UniqueConstrainedList[str]):
+        min_items = len(user_input_side_a.iptrunk_sideA_ae_members)
+        max_items = len(user_input_side_a.iptrunk_sideA_ae_members)
+
+    class ModifyIptrunkSideBForm(FormPage):
+        class Config:
+            title = "Provide subscription details for side B of the trunk."
+
+        iptrunk_sideB_node: str = ReadOnlyField(
+            subscription.iptrunk.iptrunk_sideB_node.device_fqdn
+        )
+        iptrunk_sideB_ae_iface: str = ReadOnlyField(
+            subscription.iptrunk.iptrunk_sideB_ae_iface
+        )
+        iptrunk_sideB_ae_geant_a_sid: str = (
+            subscription.iptrunk.iptrunk_sideB_ae_geant_a_sid
+        )
+        iptrunk_sideB_ae_members: AeMembersListB = (
+            subscription.iptrunk.iptrunk_sideB_ae_members
+        )
+        iptrunk_sideB_ae_members_descriptions: AeMembersListB = (
+            subscription.iptrunk.iptrunk_sideB_ae_members_description
+        )
+
+    user_input_side_b = yield ModifyIptrunkSideBForm
+
+    return (
+        initial_user_input.dict()
+        | user_input_side_a.dict()
+        | user_input_side_b.dict()
+    )
+
+
+@step("Update subscription")
+def modify_iptrunk_subscription(
+    subscription: Iptrunk,
+    geant_s_sid: str,
+    iptrunk_type: IptrunkType,
+    iptrunk_description: str,
+    iptrunk_speed: str,
+    iptrunk_minimum_links: int,
+    iptrunk_sideA_ae_geant_a_sid: str,
+    iptrunk_sideA_ae_members: list[str],
+    iptrunk_sideA_ae_members_descriptions: list[str],
+    iptrunk_sideB_ae_geant_a_sid: str,
+    iptrunk_sideB_ae_members: list[str],
+    iptrunk_sideB_ae_members_descriptions: list[str],
+) -> State:
+    subscription.iptrunk.geant_s_sid = geant_s_sid
+    subscription.iptrunk.iptrunk_description = iptrunk_description
+    subscription.iptrunk.iptrunk_type = iptrunk_type
+    subscription.iptrunk.iptrunk_speed = iptrunk_speed
+    subscription.iptrunk.iptrunk_minimum_links = iptrunk_minimum_links
+
+    subscription.iptrunk.iptrunk_sideA_ae_geant_a_sid = (
+        iptrunk_sideA_ae_geant_a_sid
+    )
+    subscription.iptrunk.iptrunk_sideA_ae_members = iptrunk_sideA_ae_members
+    subscription.iptrunk.iptrunk_sideA_ae_members_description = (
+        iptrunk_sideA_ae_members_descriptions
+    )
+
+    subscription.iptrunk.iptrunk_sideB_ae_geant_a_sid = (
+        iptrunk_sideB_ae_geant_a_sid
+    )
+    subscription.iptrunk.iptrunk_sideB_ae_members = iptrunk_sideB_ae_members
+    subscription.iptrunk.iptrunk_sideB_ae_members_description = (
+        iptrunk_sideB_ae_members_descriptions
+    )
+
+    subscription.description = f"IP trunk, geant_s_sid:{geant_s_sid}"
+
+    return {"subscription": subscription}
+
+
+@step("Provision IP trunk interface [DRY RUN]")
+def provision_ip_trunk_iface_dry(
+    subscription: Iptrunk, process_id: UUIDstr
+) -> State:
+    provisioning_proxy.provision_ip_trunk(
+        subscription, process_id, "trunk_interface"
+    )
+
+    return {
+        "subscription": subscription,
+        "label_text": (
+            "Provision of the Trunk interface [DRY] "
+            "Please refresh to get the results of the playbook"
+        ),
+    }
+
+
+@step("Provision IP trunk interface [FOR REAL]")
+def provision_ip_trunk_iface_real(
+    subscription: Iptrunk, process_id: UUIDstr
+) -> State:
+    provisioning_proxy.provision_ip_trunk(
+        subscription, process_id, "trunk_interface", False
+    )
+
+    return {
+        "subscription": subscription,
+        "label_text": (
+            "Provision of the Trunk interface [REAL] "
+            "Please refresh to get the results of the playbook"
+        ),
+    }
+
+
+@step("Provision IP trunk LLDP interface [DRY RUN]")
+def provision_ip_trunk_lldp_iface_dry(
+    subscription: Iptrunk, process_id: UUIDstr
+) -> State:
+    provisioning_proxy.provision_ip_trunk(
+        subscription, process_id, "lldp_interface"
+    )
+
+    return {
+        "subscription": subscription,
+        "label_text": (
+            "Provision of the LLDP interface [DRY]"
+            "Please refresh to get the results of the playbook"
+        ),
+    }
+
+
+@step("Provision IP trunk LLDP interface [FOR REAL]")
+def provision_ip_trunk_lldp_iface_real(
+    subscription: Iptrunk, process_id: UUIDstr
+) -> State:
+    provisioning_proxy.provision_ip_trunk(
+        subscription, process_id, "lldp_interface", False
+    )
+
+    return {
+        "subscription": subscription,
+        "label_text": (
+            "Provision of the LLDP interface [REAL]"
+            "Please refresh to get the results of the playbook"
+        ),
+    }
+
+
+@workflow(
+    "Modify IP trunk",
+    initial_input_form=wrap_modify_initial_input_form(
+        initial_input_form_generator
+    ),
+    target=Target.MODIFY,
+)
+def modify_generic():
+    return (
+        init
+        >> store_process_subscription(Target.MODIFY)
+        >> unsync
+        >> modify_iptrunk_subscription
+        >> provision_ip_trunk_iface_dry
+        >> await_pp_results
+        >> confirm_pp_results
+        >> provision_ip_trunk_iface_real
+        >> await_pp_results
+        >> confirm_pp_results
+        >> provision_ip_trunk_lldp_iface_dry
+        >> await_pp_results
+        >> confirm_pp_results
+        >> provision_ip_trunk_lldp_iface_real
+        >> await_pp_results
+        >> confirm_pp_results
+        >> resync
+        >> done
+    )
diff --git a/gso/workflows/site/create_site.py b/gso/workflows/site/create_site.py
index aa92be43b8c11bdddf0aa99e819f45916447ffb1..0773d71c3ccdea5103211dabd94358d73201658b 100644
--- a/gso/workflows/site/create_site.py
+++ b/gso/workflows/site/create_site.py
@@ -45,16 +45,16 @@ def create_subscription(product: UUIDstr) -> State:
 
 @step("Initialize subscription")
 def initialize_subscription(
-        subscription: site.SiteInactive,
-        site_name: str,
-        site_city: str,
-        site_country: str,
-        site_country_code: str,
-        site_latitude: float,
-        site_longitude: float,
-        site_bgp_community_id: int,
-        site_internal_id: int,
-        site_tier: site_pb.SiteTier
+    subscription: site.SiteInactive,
+    site_name: str,
+    site_city: str,
+    site_country: str,
+    site_country_code: str,
+    site_latitude: float,
+    site_longitude: float,
+    site_bgp_community_id: int,
+    site_internal_id: int,
+    site_tier: site_pb.SiteTier,
 ) -> State:
     subscription.site.site_name = site_name
     subscription.site.site_city = site_city
@@ -78,16 +78,17 @@ def initialize_subscription(
 @workflow(
     "Create Site",
     initial_input_form=wrap_create_initial_input_form(
-        initial_input_form_generator),
+        initial_input_form_generator
+    ),
     target=Target.CREATE,
 )
 def create_site():
     return (
-            init
-            >> create_subscription
-            >> store_process_subscription(Target.CREATE)
-            >> initialize_subscription
-            >> set_status(SubscriptionLifecycle.ACTIVE)
-            >> resync
-            >> done
+        init
+        >> create_subscription
+        >> store_process_subscription(Target.CREATE)
+        >> initialize_subscription
+        >> set_status(SubscriptionLifecycle.ACTIVE)
+        >> resync
+        >> done
     )