diff --git a/proto/acl.proto b/proto/acl.proto
index 3dba735dccf44d584a998eb02b4835bac7ceddd1..f691c3dbd102927636515fd22575b3f263943406 100644
--- a/proto/acl.proto
+++ b/proto/acl.proto
@@ -46,6 +46,7 @@ message AclMatch {
   uint32 dst_port         = 6;
   uint32 start_mpls_label = 7;
   uint32 end_mpls_label   = 8;
+  string flags            = 9;
 }
 
 message AclAction {
diff --git a/proto/context.proto b/proto/context.proto
index d5022ac292f04cd2e9b80f690be3077e7aedd868..1f8b0ce194b3ca04c162b7feb0548cdc4d9bc965 100644
--- a/proto/context.proto
+++ b/proto/context.proto
@@ -498,6 +498,7 @@ message ConfigRule_Custom {
 message ConfigRule_ACL {
   EndPointId endpoint_id = 1;
   acl.AclRuleSet rule_set = 2;
+  string interface = 3;
 }
 
 message ConfigRule {
diff --git a/src/device/service/drivers/openconfig/templates/__init__.py b/src/device/service/drivers/openconfig/templates/__init__.py
index 87eea1f0b6673c4bff3222598d81a16b383b4c3b..dcd3cf6836ca41fce3e2b54ead209daeafa4355d 100644
--- a/src/device/service/drivers/openconfig/templates/__init__.py
+++ b/src/device/service/drivers/openconfig/templates/__init__.py
@@ -27,6 +27,9 @@ from .NetworkInstances import parse as parse_network_instances
 from .RoutingPolicy import parse as parse_routing_policy
 from .Acl import parse as parse_acl
 from .Inventory import parse as parse_inventory
+from .acl.acl_adapter import acl_cr_to_dict
+from .acl.acl_adapter_ipinfusion_proprietary import acl_cr_to_dict_ipinfusion_proprietary
+
 LOGGER = logging.getLogger(__name__)
 
 ALL_RESOURCE_KEYS = [
@@ -113,16 +116,26 @@ def compose_config( # template generation
 
     elif (message_renderer == "jinja"):
         templates =[]
-        template_name = '{:s}/edit_config.xml'.format(RE_REMOVE_FILTERS.sub('', resource_key))
-        templates.append(JINJA_ENV.get_template(template_name))
-
         if "acl_ruleset" in resource_key:                                               # MANAGING ACLs
-            templates =[]
-            templates.append(JINJA_ENV.get_template('acl/acl-set/acl-entry/edit_config.xml'))
-            templates.append(JINJA_ENV.get_template('acl/interfaces/ingress/edit_config.xml'))
-        data : Dict[str, Any] = json.loads(resource_value)
+            if True: #vendor == 'ipinfusion': #! ipinfusion proprietary netconf receipe is used temporarily
+                acl_entry_path = 'acl/acl-set/acl-entry/edit_config_ipinfusion_proprietary.xml'
+                acl_ingress_path = 'acl/interfaces/ingress/edit_config_ipinfusion_proprietary.xml'
+                data : Dict[str, Any] = acl_cr_to_dict_ipinfusion_proprietary(resource_value, delete=delete)
+            else:
+                acl_entry_path = 'acl/acl-set/acl-entry/edit_config.xml'
+                acl_ingress_path = 'acl/interfaces/ingress/edit_config.xml'
+                data : Dict[str, Any] = acl_cr_to_dict(resource_value, delete=delete)
+            if delete: # unpair acl and interface before removing acl
+                templates.append(JINJA_ENV.get_template(acl_ingress_path))
+                templates.append(JINJA_ENV.get_template(acl_entry_path))
+            else:
+                templates.append(JINJA_ENV.get_template(acl_entry_path))
+                templates.append(JINJA_ENV.get_template(acl_ingress_path))
+        else:
+            template_name = '{:s}/edit_config.xml'.format(RE_REMOVE_FILTERS.sub('', resource_key))
+            templates.append(JINJA_ENV.get_template(template_name))
+            data : Dict[str, Any] = json.loads(resource_value)
         operation = 'delete' if delete else 'merge'
-
         return [
             '<config>{:s}</config>'.format(
             template.render(**data, operation=operation, vendor=vendor).strip())
diff --git a/src/device/service/drivers/openconfig/templates/acl/__init__.py b/src/device/service/drivers/openconfig/templates/acl/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..f80ccfd52ebfd4fa1783267201c52eb7381741bf
--- /dev/null
+++ b/src/device/service/drivers/openconfig/templates/acl/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
\ No newline at end of file
diff --git a/src/device/service/drivers/openconfig/templates/acl/acl-set/acl-entry/edit_config_ipinfusion_proprietary.xml b/src/device/service/drivers/openconfig/templates/acl/acl-set/acl-entry/edit_config_ipinfusion_proprietary.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d0210a66c1b5d7de1a4be479cd79e9b48131e2a0
--- /dev/null
+++ b/src/device/service/drivers/openconfig/templates/acl/acl-set/acl-entry/edit_config_ipinfusion_proprietary.xml
@@ -0,0 +1,34 @@
+<acl xmlns="http://www.ipinfusion.com/yang/ocnos/ipi-acl">
+  <acl-sets>
+    <acl-set {% if operation == 'delete' %}operation="delete"{% endif %}>
+      <name>{{name}}</name>
+      {% if type is defined %}<type>{{type}}</type>{% endif %}
+      <config>
+        <name>{{name}}</name>
+        {% if type is defined %}<type>{{type}}</type>{% endif %}
+      </config>
+      {% if operation != 'delete' %}
+      <acl-entries>
+        <acl-entry>
+          <sequence-id>{{sequence_id}}</sequence-id>
+          <config>
+            <sequence-id>{{sequence_id}}</sequence-id>
+          </config>
+          <ipv4>
+            <config>
+              <source-address>{{source_address}}</source-address>
+              <destination-address>{{destination_address}}</destination-address>
+              <dscp>{{dscp}}</dscp>
+              <protocol-tcp />
+              <tcp-source-port>{{source_port}}</tcp-source-port>
+              <tcp-destination-port>{{destination_port}}</tcp-destination-port>
+              <tcp-flags>{{tcp_flags}}</tcp-flags>
+              <forwarding-action>{{forwarding_action}}</forwarding-action>
+            </config>
+          </ipv4>
+        </acl-entry>
+      </acl-entries>
+      {% endif %}
+    </acl-set>
+  </acl-sets>
+</acl>
\ No newline at end of file
diff --git a/src/device/service/drivers/openconfig/templates/acl/acl_adapter.py b/src/device/service/drivers/openconfig/templates/acl/acl_adapter.py
new file mode 100644
index 0000000000000000000000000000000000000000..244c4b61609ee7566ec36758c47150588d580aaf
--- /dev/null
+++ b/src/device/service/drivers/openconfig/templates/acl/acl_adapter.py
@@ -0,0 +1,75 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from typing import Dict, TypedDict
+
+from ..ACL.ACL_multivendor import RULE_TYPE_MAPPING, FORWARDING_ACTION_MAPPING, LOG_ACTION_MAPPING
+
+class ACLRequestData(TypedDict):
+    name: str  # acl-set name
+    type: str  # acl-set type
+    sequence_id: int  # acl-entry sequence-id
+    source_address: str
+    destination_address: str
+    forwarding_action: str
+    id: str  # interface id
+    interface: str
+    subinterface: int
+    set_name_ingress: str  # ingress-acl-set name
+    type_ingress: str  # ingress-acl-set type
+    all: bool
+    dscp: int
+    protocol: int
+    tcp_flags: str
+    source_port: int
+    destination_port: int
+
+def acl_cr_to_dict(acl_cr_dict: Dict, subinterface:int = 0) -> Dict:
+    rule_set = acl_cr_dict['rule_set']
+    rule_set_entry = rule_set['entries'][0]
+    rule_set_entry_match = rule_set_entry['match']
+    rule_set_entry_action = rule_set_entry['action']
+
+    name: str = rule_set['name']
+    type: str = RULE_TYPE_MAPPING[rule_set["type"]]
+    sequence_id = rule_set_entry['sequence_id']
+    source_address = rule_set_entry_match['src_address']
+    destination_address = rule_set_entry_match['dst_address']
+    forwarding_action: str = FORWARDING_ACTION_MAPPING[rule_set_entry_action['forward_action']]
+    interface_id = acl_cr_dict['interface']
+    interface = interface_id
+    set_name_ingress = name
+    type_ingress = type
+
+    return ACLRequestData(
+        name=name,
+        type=type,
+        sequence_id=sequence_id,
+        source_address=source_address,
+        destination_address=destination_address,
+        forwarding_action=forwarding_action,
+        id=interface_id,
+        interface=interface,
+        # subinterface=subinterface,
+        set_name_ingress=set_name_ingress,
+        type_ingress=type_ingress,
+        all=True,
+        dscp=18,
+        protocol=6,
+        tcp_flags='TCP_SYN',
+        source_port=22,
+        destination_port=80
+    )
+
+    
\ No newline at end of file
diff --git a/src/device/service/drivers/openconfig/templates/acl/acl_adapter_ipinfusion_proprietary.py b/src/device/service/drivers/openconfig/templates/acl/acl_adapter_ipinfusion_proprietary.py
new file mode 100644
index 0000000000000000000000000000000000000000..79db6ad98120377fca2e2ead0039370c8d2e6645
--- /dev/null
+++ b/src/device/service/drivers/openconfig/templates/acl/acl_adapter_ipinfusion_proprietary.py
@@ -0,0 +1,65 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from typing import Dict, TypedDict
+
+
+RULE_TYPE_MAPPING = {
+    'ACLRULETYPE_IPV4'     : 'ip',
+}
+
+FORWARDING_ACTION_MAPPING = {
+    'ACLFORWARDINGACTION_DROP'     : 'deny',
+    'ACLFORWARDINGACTION_ACCEPT'   : 'permit',
+}
+
+class ACLRequestData(TypedDict):
+    name: str  # acl-set name
+    type: str  # acl-set type
+    sequence_id: int  # acl-entry sequence-id
+    source_address: str
+    destination_address: str
+    forwarding_action: str
+    interface: str
+    dscp: int
+    tcp_flags: str
+    source_port: int
+    destination_port: int
+
+def acl_cr_to_dict_ipinfusion_proprietary(acl_cr_dict: Dict, delete: bool = False) -> Dict:
+    rule_set = acl_cr_dict['rule_set']
+    name: str = rule_set['name']
+    type: str = RULE_TYPE_MAPPING[rule_set["type"]]
+    interface = acl_cr_dict['interface'][5:] # remove preceding `PORT-` characters
+    if delete:
+        return ACLRequestData(name=name, type=type, interface=interface)
+    rule_set_entry = rule_set['entries'][0]
+    rule_set_entry_match = rule_set_entry['match']
+    rule_set_entry_action = rule_set_entry['action']
+
+    return ACLRequestData(
+        name=name,
+        type=type,
+        sequence_id=rule_set_entry['sequence_id'],
+        source_address=rule_set_entry_match['src_address'],
+        destination_address=rule_set_entry_match['dst_address'],
+        forwarding_action=FORWARDING_ACTION_MAPPING[rule_set_entry_action['forward_action']],
+        interface=interface,
+        dscp=rule_set_entry_match["dscp"],
+        tcp_flags=rule_set_entry_match["flags"],
+        source_port=rule_set_entry_match['src_port'],
+        destination_port=rule_set_entry_match['dst_port']
+    )
+
+    
\ No newline at end of file
diff --git a/src/device/service/drivers/openconfig/templates/acl/interfaces/ingress/edit_config_ipinfusion_proprietary.xml b/src/device/service/drivers/openconfig/templates/acl/interfaces/ingress/edit_config_ipinfusion_proprietary.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6e502154f16a7a9d4ce0afc0c49ab96b3a2bd979
--- /dev/null
+++ b/src/device/service/drivers/openconfig/templates/acl/interfaces/ingress/edit_config_ipinfusion_proprietary.xml
@@ -0,0 +1,26 @@
+<acl xmlns="http://www.ipinfusion.com/yang/ocnos/ipi-acl">
+  <interfaces>
+    <interface>
+      <name>{{interface}}</name>
+      <config>
+        <name>{{interface}}</name>
+      </config>
+      <ingress-acl-sets>
+        <ingress-acl-set {% if operation == "delete" %}operation="delete"{% endif %}>
+          {% if type is defined %}<acl-type>{{type}}</acl-type>{% endif %}
+          <access-groups>
+            <access-group>
+              <acl-name>{{name}}</acl-name>
+              <config>
+                <acl-name>{{name}}</acl-name>
+              </config>
+            </access-group>
+          </access-groups>
+          <config>
+            {% if type is defined %}<acl-type>{{type}}</acl-type>{% endif %}
+          </config>
+        </ingress-acl-set>
+      </ingress-acl-sets>
+    </interface>
+  </interfaces>
+</acl>
\ No newline at end of file
diff --git a/src/nbi/requirements.in b/src/nbi/requirements.in
index 6e3eb94404f9d12431c715080cf210a02c7c82f4..7a7b1cffb6b1d1d02a30893135f3294f1502fe73 100644
--- a/src/nbi/requirements.in
+++ b/src/nbi/requirements.in
@@ -24,3 +24,4 @@ pyang==2.6.0
 git+https://github.com/robshakir/pyangbind.git
 requests==2.27.1
 werkzeug==2.3.7
+pydantic==2.6.3
diff --git a/src/nbi/service/__main__.py b/src/nbi/service/__main__.py
index 8834e45a2779c8d422ba1f9878c435f14a2f43db..2a8a2251dbe7bd66d89c2f37b1b189aa565650a6 100644
--- a/src/nbi/service/__main__.py
+++ b/src/nbi/service/__main__.py
@@ -26,6 +26,7 @@ from .rest_server.nbi_plugins.ietf_l2vpn import register_ietf_l2vpn
 from .rest_server.nbi_plugins.ietf_l3vpn import register_ietf_l3vpn
 from .rest_server.nbi_plugins.ietf_network import register_ietf_network
 from .rest_server.nbi_plugins.ietf_network_slice import register_ietf_nss
+from .rest_server.nbi_plugins.ietf_acl import register_ietf_acl
 
 terminate = threading.Event()
 LOGGER = None
@@ -68,6 +69,7 @@ def main():
     register_ietf_l3vpn(rest_server)  # Registering L3VPN entrypoint
     register_ietf_network(rest_server)
     register_ietf_nss(rest_server)  # Registering NSS entrypoint
+    register_ietf_acl(rest_server)
     rest_server.start()
 
     # Wait for Ctrl+C or termination signal
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/__init__.py b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..6c1353bff1ee848a176106c698c5d42d90806d56
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/__init__.py
@@ -0,0 +1,42 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from flask_restful import Resource
+
+from nbi.service.rest_server.nbi_plugins.ietf_acl.acl_service import ACL
+from nbi.service.rest_server.nbi_plugins.ietf_acl.acl_services import ACLs
+from nbi.service.rest_server.RestServer import RestServer
+
+URL_PREFIX = "/restconf/data"
+
+
+def __add_resource(rest_server: RestServer, resource: Resource, *urls, **kwargs):
+    urls = [(URL_PREFIX + url) for url in urls]
+    rest_server.add_resource(resource, *urls, **kwargs)
+
+
+def register_ietf_acl(rest_server: RestServer):
+    __add_resource(
+        rest_server,
+        ACLs,
+        "/device=<device_uuid>/ietf-access-control-list:acls",
+        "/device=<device_uuid>/ietf-access-control-list:acls",
+    )
+
+    __add_resource(
+        rest_server,
+        ACL,
+        "/device=<device_uuid>/ietf-access-control-list:acl=<acl_name>",
+        "/device=<device_uuid>/ietf-access-control-list:acl=<acl_name>/",
+    )
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/acl_service.py b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/acl_service.py
new file mode 100644
index 0000000000000000000000000000000000000000..466a68efc8b6c966dd3a282fcd5a394f4dae70a8
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/acl_service.py
@@ -0,0 +1,98 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+import re
+import json
+
+from flask_restful import Resource
+from werkzeug.exceptions import NotFound
+
+from nbi.service.rest_server.nbi_plugins.tools.Authentication import HTTP_AUTH
+from common.proto.acl_pb2 import AclRuleTypeEnum
+from common.proto.context_pb2 import (
+    ConfigActionEnum,
+    ConfigRule,
+    Device,
+    DeviceId,
+)
+from common.tools.object_factory.Device import json_device_id
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from context.client.ContextClient import ContextClient
+from device.client.DeviceClient import DeviceClient
+
+
+from .ietf_acl_parser import ietf_acl_from_config_rule_resource_value
+
+LOGGER = logging.getLogger(__name__)
+
+ACL_CONIG_RULE_KEY = r'\/device\[.+\]\/endpoint\[(.+)\]/acl_ruleset\[{}\]'
+
+
+class ACL(Resource):
+    # @HTTP_AUTH.login_required
+    def get(self, device_uuid: str, acl_name: str):
+        RE_ACL_CONIG_RULE_KEY = re.compile(ACL_CONIG_RULE_KEY.format(acl_name))
+
+        context_client = ContextClient()
+        device_client = DeviceClient()
+
+        _device = context_client.GetDevice(DeviceId(**json_device_id(device_uuid)))
+
+
+        for cr in _device.device_config.config_rules:
+            if cr.WhichOneof('config_rule') == 'custom':
+                if ep_uuid_match := RE_ACL_CONIG_RULE_KEY.match(cr.custom.resource_key):
+                    endpoint_uuid = ep_uuid_match.groups(0)[0]
+                    resource_value_dict = json.loads(cr.custom.resource_value)
+                    LOGGER.debug(f'P99: {resource_value_dict}')
+                    return ietf_acl_from_config_rule_resource_value(resource_value_dict)
+        else:
+            raise NotFound(f'ACL not found')
+
+    # @HTTP_AUTH.login_required
+    def delete(self, device_uuid: str, acl_name: str):
+        RE_ACL_CONIG_RULE_KEY = re.compile(ACL_CONIG_RULE_KEY.format(acl_name))
+
+        context_client = ContextClient()
+        device_client = DeviceClient()
+
+        _device = context_client.GetDevice(DeviceId(**json_device_id(device_uuid)))
+
+
+        for cr in _device.device_config.config_rules:
+            if cr.WhichOneof('config_rule') == 'custom':
+                if ep_uuid_match := RE_ACL_CONIG_RULE_KEY.match(cr.custom.resource_key):
+                    endpoint_uuid = ep_uuid_match.groups(0)[0]
+                    resource_value_dict = json.loads(cr.custom.resource_value)
+                    type_str = resource_value_dict['rule_set']['type']
+                    interface = resource_value_dict['interface']
+                    break
+        else:
+            raise NotFound(f'ACL not found')
+        
+        acl_config_rule = ConfigRule()
+        acl_config_rule.action = ConfigActionEnum.CONFIGACTION_DELETE
+        acl_config_rule.acl.rule_set.name = acl_name
+        acl_config_rule.acl.interface = interface
+        acl_config_rule.acl.rule_set.type = getattr(AclRuleTypeEnum, type_str)
+        acl_config_rule.acl.endpoint_id.device_id.device_uuid.uuid = device_uuid
+        acl_config_rule.acl.endpoint_id.endpoint_uuid.uuid = endpoint_uuid
+
+        device = Device()
+        device.CopyFrom(_device)
+        del device.device_config.config_rules[:]
+        device.device_config.config_rules.append(acl_config_rule)
+        response = device_client.ConfigureDevice(device)
+        return (response.device_uuid.uuid).strip("\"\n")
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/acl_services.py b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/acl_services.py
new file mode 100644
index 0000000000000000000000000000000000000000..2d03e61b6ebb518d661e0e6147e84a4d16b99a17
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/acl_services.py
@@ -0,0 +1,68 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+from typing import Dict
+
+from flask import request
+from flask_restful import Resource
+from werkzeug.exceptions import NotFound
+
+from common.proto.context_pb2 import Device, DeviceId
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from common.tools.object_factory.Device import json_device_id
+from context.client.ContextClient import ContextClient
+from device.client.DeviceClient import DeviceClient
+
+from nbi.service.rest_server.nbi_plugins.tools.Authentication import HTTP_AUTH
+
+from .ietf_acl_parser import config_rule_from_ietf_acl
+
+LOGGER = logging.getLogger(__name__)
+
+class ACLs(Resource):
+    # @HTTP_AUTH.login_required
+    def get(self):
+        return {}
+
+    # @HTTP_AUTH.login_required
+    def post(self, device_uuid: str):
+        if not request.is_json:
+            raise UnsupportedMediaType("JSON pyload is required")
+        request_data: Dict = request.json
+        LOGGER.debug("Request: {:s}".format(str(request_data)))
+        attached_interface = request_data["ietf-access-control-list"]["acls"]['attachment-points']['interface'][0]['interface-id']
+
+        context_client = ContextClient()
+        device_client = DeviceClient()
+
+        _device = context_client.GetDevice(DeviceId(**json_device_id(device_uuid)))
+        
+        for ep in _device.device_endpoints:
+            if ep.name == attached_interface:
+                endpoint_uuid = ep.endpoint_id.endpoint_uuid.uuid
+                break
+        else:
+            raise NotFound(f'interface {attached_interface} not found in device {device_uuid}')
+
+        acl_config_rule = config_rule_from_ietf_acl(request_data, device_uuid, endpoint_uuid, sequence_id=1, subinterface=0)
+
+        LOGGER.info(f"ACL Config Rule: {grpc_message_to_json_string(acl_config_rule)}")
+
+        device = Device()
+        device.CopyFrom(_device)
+        del device.device_config.config_rules[:]
+        device.device_config.config_rules.append(acl_config_rule)
+        response = device_client.ConfigureDevice(device)
+        return (response.device_uuid.uuid).strip("\"\n")
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/ietf_acl_parser.py b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/ietf_acl_parser.py
new file mode 100644
index 0000000000000000000000000000000000000000..b378153f82eb4d1138a16ae0300bb8ca0a21444e
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/ietf_acl_parser.py
@@ -0,0 +1,164 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from typing import List, Dict, Optional, TypedDict
+from pydantic import BaseModel, Field
+
+from common.proto.acl_pb2 import AclForwardActionEnum, AclRuleTypeEnum, AclEntry
+from common.proto.context_pb2 import ConfigActionEnum, ConfigRule
+
+class Ipv4(BaseModel):
+    dscp: int = 0
+    source_ipv4_network: str = Field(serialization_alias="source-ipv4-network", default="") 
+    destination_ipv4_network: str = Field(serialization_alias="destination-ipv4-network", default="") 
+
+class Port(BaseModel):
+    port: int = 0
+    operator: str = "eq"
+
+class Tcp(BaseModel):
+    flags: str = ""
+    source_port: Port = Field(serialization_alias="source-port", default_factory=lambda: Port())
+    destination_port: Port = Field(serialization_alias="destination-port", default_factory=lambda: Port())
+
+class Matches(BaseModel):
+    ipv4: Ipv4 = Ipv4()
+    tcp: Tcp = Tcp()
+
+class Action(BaseModel):
+    forwarding: str = ""
+
+class Ace(BaseModel):
+    name: str = "custom_rule"
+    matches: Matches = Matches()
+    actions: Action = Action()
+
+class Aces(BaseModel):
+    ace: List[Ace] = [Ace()]
+
+class Acl(BaseModel):
+    name: str = ""
+    type: str = ""
+    aces: Aces = Aces()
+
+class Name(BaseModel):
+    name: str = ""
+
+class AclSet(BaseModel):
+    acl_set: List[Name] = Field(serialization_alias="acl-set", default=[Name()])
+
+class AclSets(BaseModel):
+    acl_sets: AclSet = Field(serialization_alias="acl-sets", default=AclSet())
+
+class Ingress(BaseModel):
+    ingress: AclSets = AclSets()
+
+class Interface(BaseModel):
+    interface_id: str = Field(serialization_alias="interface-id", default="")
+    ingress: Ingress = Ingress()
+
+class Interfaces(BaseModel):
+    interface: List[Interface] = [Interface()]
+
+class AttachmentPoints(BaseModel):
+    attachment_points: Interfaces = Field(serialization_alias="attachment-points", default=Interfaces())
+
+class Acls(BaseModel):
+    acl: List[Acl] = [Acl()]
+    attachment_points: AttachmentPoints = Field(serialization_alias="attachment-points", default=AttachmentPoints())
+
+class IETF_ACL(BaseModel):
+    acls: Acls = Acls()
+    
+
+IETF_TFS_RULE_TYPE_MAPPING = {
+    "ipv4-acl-type": "ACLRULETYPE_IPV4",
+    "ipv6-acl-type": "ACLRULETYPE_IPV6",
+}
+
+IETF_TFS_FORWARDING_ACTION_MAPPING = {
+    "drop": "ACLFORWARDINGACTION_DROP",
+    "accept": "ACLFORWARDINGACTION_ACCEPT",
+}
+
+TFS_IETF_RULE_TYPE_MAPPING = {
+    "ACLRULETYPE_IPV4": "ipv4-acl-type",
+    "ACLRULETYPE_IPV6":     "ipv6-acl-type",
+}
+
+TFS_IETF_FORWARDING_ACTION_MAPPING = {
+    "ACLFORWARDINGACTION_DROP":     "drop",
+    "ACLFORWARDINGACTION_ACCEPT": "accept",
+}
+
+def config_rule_from_ietf_acl(
+    request: Dict,
+    device_uuid: str,
+    endpoint_uuid: str,
+    sequence_id: int,
+    subinterface: int,
+) -> ConfigRule:
+    the_acl = request["ietf-access-control-list"]["acls"]["acl"][0]
+    acl_ip_data = the_acl["aces"]["ace"][0]["matches"]["ipv4"]
+    acl_tcp_data = the_acl["aces"]["ace"][0]["matches"]["tcp"]
+    attachemnt_interface = request["ietf-access-control-list"]["acls"]['attachment-points']['interface'][0]
+    source_address = acl_ip_data["source-ipv4-network"]
+    destination_address = acl_ip_data["destination-ipv4-network"]
+    source_port = acl_tcp_data['source-port']['port']
+    destination_port = acl_tcp_data['destination-port']['port']
+    ietf_action = the_acl["aces"]["ace"][0]["actions"]["forwarding"]
+    interface_id = attachemnt_interface['interface-id']
+
+    acl_config_rule = ConfigRule()
+    acl_config_rule.action = ConfigActionEnum.CONFIGACTION_SET
+    acl_config_rule.acl.interface = interface_id
+    acl_endpoint_id = acl_config_rule.acl.endpoint_id
+    acl_endpoint_id.device_id.device_uuid.uuid = device_uuid
+    acl_endpoint_id.endpoint_uuid.uuid = endpoint_uuid
+    acl_rule_set = acl_config_rule.acl.rule_set
+    acl_rule_set.name = the_acl["name"]
+    acl_rule_set.type = getattr(AclRuleTypeEnum, IETF_TFS_RULE_TYPE_MAPPING[the_acl['type']])
+    acl_rule_set.description = (
+        f'{ietf_action} {the_acl["type"]}: {source_address}:{source_port}->{destination_address}:{destination_port}'
+    )
+    acl_entry = AclEntry()
+    acl_entry.sequence_id = sequence_id
+    acl_entry.match.src_address = source_address
+    acl_entry.match.dst_address = destination_address
+    acl_entry.match.src_port = source_port
+    acl_entry.match.dst_port = destination_port
+    acl_entry.match.dscp = acl_ip_data["dscp"]
+    acl_entry.match.flags = acl_tcp_data["flags"]
+    acl_entry.action.forward_action = getattr(AclForwardActionEnum, IETF_TFS_FORWARDING_ACTION_MAPPING[ietf_action])
+    acl_rule_set.entries.append(acl_entry)
+
+    return acl_config_rule
+
+def ietf_acl_from_config_rule_resource_value(config_rule_rv: Dict) -> Dict:
+    rule_set = config_rule_rv['rule_set']
+    acl_entry = rule_set['entries'][0]
+    match_ = acl_entry['match']
+
+    ipv4 = Ipv4(dscp=match_["dscp"], source_ipv4_network=match_["src_address"], destination_ipv4_network=match_["dst_address"])
+    tcp = Tcp(flags=match_["flags"], source_port=Port(port=match_["src_port"]), destination_port=Port(port=match_["dst_port"]))
+    matches = Matches(ipvr=ipv4, tcp=tcp)
+    aces = Aces(ace=[Ace(matches=matches, actions=Action(forwarding=TFS_IETF_FORWARDING_ACTION_MAPPING[acl_entry["action"]["forward_action"]]))])
+    acl = Acl(name=rule_set["name"], type=TFS_IETF_RULE_TYPE_MAPPING[rule_set["type"]], aces=aces)
+    acl_sets = AclSets(acl_sets=AclSet(acl_set=[Name(name=rule_set["name"])]))
+    ingress = Ingress(ingress=acl_sets)
+    interfaces = Interfaces(interface=[Interface(interface_id=config_rule_rv["interface"], ingress=ingress)])
+    acls = Acls(acl=[acl], attachment_points=AttachmentPoints(attachment_points=interfaces))
+    ietf_acl = IETF_ACL(acls=acls)
+
+    return ietf_acl.model_dump(by_alias=True)
\ No newline at end of file
diff --git a/src/nbi/tests/data/ietf_acl.json b/src/nbi/tests/data/ietf_acl.json
new file mode 100644
index 0000000000000000000000000000000000000000..3cbdd0c6705a8797c051a21aecec98f14576fcbd
--- /dev/null
+++ b/src/nbi/tests/data/ietf_acl.json
@@ -0,0 +1,56 @@
+{
+    "ietf-access-control-list": {
+        "acls": {
+            "acl": [
+                {
+                    "name": "sample-ipv4-acl",
+                    "type": "ipv4-acl-type",
+                    "aces": {
+                        "ace": [
+                            {
+                                "name": "rule1",
+                                "matches": {
+                                    "ipv4": {
+                                        "dscp": 18,
+                                        "source-ipv4-network": "192.168.10.6/24",
+                                        "destination-ipv4-network": "192.168.20.6/24"
+                                    },
+                                    "tcp": {
+                                        "flags": "syn",
+                                        "source-port": {
+                                            "port": 1444,
+                                            "operator": "eq"
+                                        },
+                                        "destination-port": {
+                                            "port": 1333,
+                                            "operator": "eq"
+                                        }
+                                    }
+                                },
+                                "actions": {
+                                    "forwarding": "drop"
+                                }
+                            }
+                        ]
+                    }
+                }
+            ],
+            "attachment-points": {
+                "interface": [
+                    {
+                        "interface-id": "PORT-ce1",
+                        "ingress": {
+                            "acl-sets": {
+                                "acl-set": [
+                                    {
+                                        "name": "sample-ipv4-acl"
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                ]
+            }
+        }
+    }
+}
\ No newline at end of file