Applications Area Working Group M. O'Connell
Internet-Draft DNS International
Expires: January 2, 2016 July 1, 2015

Dynamic Business-Rule Implementation and Execution Framework
draft-oconnell-dbrief-01

Abstract

This memo details the structure for implementing a process of routines or functions that govern any generic task in order to achieve compliance to predefined a technical framework.

Status of This Memo

This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at http://datatracker.ietf.org/drafts/current/.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

This Internet-Draft will expire on January 2, 2016.

Copyright Notice

Copyright (c) 2015 IETF Trust and the persons identified as the document authors. All rights reserved.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.

1. Introduction

A challenge facing most complex systems is an inherant inflexibility in the implementation of dynamic legal and technical policies. When an industry is in constant flux it can increase workload on developers to maintain the software standards while still allowing for future extensibility. A formalised policy document is a requirement in almost every industry however conversion of the formalised policy document into working machine code is a time consuming and tedious process, which is furthermore fraught with hidden complexity and errors. The Policy Engine defined in this document aims at alleviating the implementation of formalised policy in a structured and concise format.

1.1. Structure

1.1.1. Technical

The Policy Engine is a structured XML document which contains a scriptable language as a series of activities and logical branches. Compiled language or compiled policy engine implementation falls out of the scope of this document. The intention of the Policy Engine is to operate on XML based payloads but this could be adapted to work on any message format.

1.1.2. Methodology

In order to deal with unknown requirements and future extensibility the Unix philosophy was adopted. The following Unix philosophy rules (From Wikipedia) should be assimilated when developing the policy code:

The Policy Engine is assembled using parts of the Policy Code in an ordered and controlled environment. Meta-Functions should be implemented in order to traverse, invoke, or destroy current tasks.

1.1.3. Hierarchical Structure

The business rules are stored in a hierarchical structure as detailed below

+------+                                                        
| ROOT |                                                        
+---+--+                                                        
    |    +-----------+---------------------+-------------------+
    +----> VARIABLES | LIBRARY DEFINITIONS | XPATH CONSTRAINTS |
    |    +-----------+---------------------+-------------------+
    |    +---------+                                            
    +----> OBJECTS |                                            
         +----+----+                                            
              |      +--------+                                 
              +------> EVENTS |                                 
                     +----+---+                                 
                          |     +------------+                  
                          +-----> ACTIVITIES <-----------------+
                                +------+-----+                 |
                                       |       +--------+      |
                                       |       | LINE 1 |      |
                                       +-------> LINE 2 |      |
                                       |       | LINE n |      |
                                       |       +--------+      |
                                       |       +------------+  |
                                       +-------> ACTIVITIES +--+
                                       |       +------------+  |
                                       |           XXXXXX      |
                                       |         XX      XX    |
                                       +------>XXX BRANCH XXX+-+
                                       |         XX      XX     
                                       |           XXXXXX       
                                       |       +---------+      
                                       +-------> FINALLY |      
                                               +---------+      
                       
            

Figure 1

1.2. implementation

Conversion and implementation can begin as soon as a formalised policy document has been released. The document should outline a clear process to adhere to when performing a routine. Bullet point based procedures are the easiest to implement on condition each bullet point defines a single task to perform. Each bullet point should be able to be converted into usable machine code known as Policy Code. The Policy Engine can begin construction once the textual elements have been converted to Policy Code.

Appendix A. Acknowledgements

(In no particular order)

Appendix B. EPP Registry Example

A sample policy XML file built by a specialised user interface

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<pc:policyConfig xmlns:pc="urn:ietf:params:xml:ns:dns:policyconf">
  <pc:policyParameters pc:policyIdentifier="test">
    <pc:constants>
      <pc:values pc:name="Root">mygtld</pc:values>
      <pc:values pc:name="banned_domain_list">[]</pc:values>
      <pc:values pc:name="banned_contact_list">[]</pc:values>
      <pc:values pc:name="banned_host_list">[]</pc:values>
      <pc:values pc:name="GracePeriod">5 days</pc:values>
      <pc:values pc:name="PendingReleasePeriod">5 days</pc:values>
      <pc:values pc:name="PendingTerminationPeriod">5 days</pc:values>
      <pc:values pc:name="PendingUpdatePeriod">5 days</pc:values>
      <pc:values pc:name="PendingTransferUpdatePeriod">5 days</pc:values>
    </pc:constants>
    <pc:libraries>
      <pc:library pc:name="PolicyExec" pc:path="lib/elib/PolicyExec.py" pc:prefix="PolicyExec" pc:type="Python"/> 
    </pc:libraries>
    <pc:constraints>
      <pc:policylimit pc:xpath="//domain:name" pc:minlen="1" pc:maxlen="255" 
      pc:regex="^[A-Za-z0-9\-]+\.[A-Za-z0-9\-]+$" pc:code="2306"
      pc:desc="Incorrectly formatted domain name"/> 
      <pc:policylimit pc:xpath="//contact:street" pc:minlen="8" pc:maxlen="255"/> 
      <pc:policylimit pc:xpath="//contact:city" pc:minlen="2" pc:maxlen="255" pc:regex=""/>
      <pc:policylimit pc:xpath="//contact:state" pc:minlen="2" pc:maxlen="255" pc:regex=""/>
      <pc:policylimit pc:xpath="//contact:email" pc:minlen="1" pc:maxlen="255" pc:regex="[A-Z0-9._%-]+@[A-Z0-9.-]+$"/>
      <pc:policylimit pc:xpath="//domain:hostObj" pc:mincount="0" pc:maxcount="5" pc:regex=""/>
      <pc:policylimit pc:xpath="//domain:hostAttr" pc:mincount="0" pc:maxcount="5" pc:regex=""/>
    </pc:constraints>
  </pc:policyParameters>
  <pc:objects pc:name="Domain">
    <pc:events pc:name="Create">
      <pc:activities pc:name="Permission">
        <pc:rules>PolicyExec.checkPermission(request, clID, objectname, eventname)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Validation">
        <pc:children pc:name="Availability">
          <pc:rules>PolicyExec.domain_isAvailable(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="MandatoryValues">
          <pc:rules>PolicyExec.domain_mandatoryValues(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="FormatCheck">
          <pc:rules>PolicyExec.validation(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="BannedListCheck">
          <pc:rules>PolicyExec.checkBannedList(request.find(fns(&quot;{domain}name&quot;)).text,
          banned_domain_list)</pc:rules> </pc:children>
        <pc:children pc:name="InBailiwickCheck">
          <pc:rules>PolicyExec.host_inbailiwickCheck(request)</pc:rules>
        </pc:children>
      </pc:activities>
      <pc:activities pc:name="Accounting">
        <pc:children pc:name="AccountValid"/>
      </pc:activities>
      <pc:activities pc:name="Nameservers">
        <pc:rules>PolicyExec.domain_nameserverCheck(request)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Billing"/>
      <pc:activities pc:name="ContactState:Linked">
        <pc:rules>PolicyExec.contact_adjustState(clID, &quot;Linked&quot;)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Timer:Domain,GracePeriod">
        <pc:rules>PolicyExec.startTimer(request, &quot;Domain&quot;,
        &quot;GracePeriod&quot;, \GracePeriod)</pc:rules> </pc:activities>
    </pc:events>
    <pc:events pc:name="Delete">
      <pc:activities pc:name="StatusCheck">
        <pc:rules>PolicyExec.domain_statusCheck(request, [&quot;Active&quot;,
        &quot;Ok&quot;])</pc:rules> </pc:activities>
      <pc:activities pc:name="Permission">
        <pc:rules>PolicyExec.checkPermission(request, clID, objectname, eventname)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Existence">
        <pc:rules>PolicyExec.domain_exists(request)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="DependencyCheck">
        <pc:rules>PolicyExec.domain_dependencyCheck(request)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="GracePeriodCheck">
        <pc:branch pc:decision="PolicyExec.domain_isInGracePeriod(request)">
          <pc:answerTrue pc:name="InGracePeriod">
            <pc:children pc:name="Accounting"/>
            <pc:children pc:name="Timer:Domain,PendingRelease">
              <pc:rules>PolicyExec.startTimer(request, &quot;Domain&quot;,
              &quot;PendingRelease&quot;, PendingReleasePeriod)</pc:rules> </pc:children>
          </pc:answerTrue>
          <pc:answerFalse pc:name="OutOfGracePeriod">
            <pc:children pc:name="Timer:Domain,PendingSuspension">
              <pc:rules>PolicyExec.startTimer(request, &quot;Domain&quot;,
              &quot;PendingTermination&quot;,  PendingTerminationPeriod)</pc:rules> </pc:children>
          </pc:answerFalse>
        </pc:branch>
      </pc:activities>
    </pc:events>
    <pc:events pc:name="Update">
      <pc:activities pc:name="StatusCheck">
        <pc:rules>PolicyExec.domain_statusCheck(request, [&quot;Active&quot;,
        &quot;Ok&quot;])</pc:rules> </pc:activities>
      <pc:activities pc:name="Permission">
        <pc:rules>PolicyExec.checkPermission(request, clID, objectname, eventname)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Existence">
        <pc:rules>PolicyExec.domain_exists(request)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Validation">
        <pc:children pc:name="MandatoryValues">
          <pc:rules>PolicyExec.domain_mandatoryValues(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="FormatCheck">
          <pc:rules>PolicyExec.validation(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="InBailiwickCheck">
          <pc:rules>PolicyExec.host_inbailiwickCheck(request)</pc:rules>
        </pc:children>
      </pc:activities>
      <pc:activities pc:name="Nameservers">
        <pc:rules>PolicyExec.domain_nameserverCheck(request)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Timer:Domain,PendingUpdate">
        <pc:rules>PolicyExec.startTimer(request, &quot;Domain&quot;,
        &quot;PendingUpdate&quot;, PendingUpdatePeriod)</pc:rules> </pc:activities>
    </pc:events>
    <pc:events pc:name="Transfer">
      <pc:activities pc:name="StatusCheck">
        <pc:rules>PolicyExec.domain_statusCheck(request, [&quot;Active&quot;,
        &quot;Ok&quot;])</pc:rules> </pc:activities>
      <pc:activities pc:name="Permission">
        <pc:rules>PolicyExec.checkPermission(request, clID, objectname, eventname)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Existence">
        <pc:rules>PolicyExec.domain_exists(request)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="GracePeriodCheck">
        <pc:rules>PolicyExec.domain_isInGracePeriod(request)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Validation">
        <pc:children pc:name="MandatoryValues">
          <pc:rules>PolicyExec.domain_mandatoryValues(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="FormatCheck">
          <pc:rules>PolicyExec.validation(request)</pc:rules>
        </pc:children>
      </pc:activities>
      <pc:activities pc:name="Timer:Domain,PendingTransferUpdate">
        <pc:rules>PolicyExec.startTimer(request, &quot;Domain&quot;,
        &quot;PendingTransferUpdate&quot;, \PendingTransferUpdatePeriod)</pc:rules> 
      </pc:activities>
      <pc:activities pc:name="BeginTransfer">
        <pc:rules>PolicyExec.domain_startTransfer(request, clID)</pc:rules>
      </pc:activities>
    </pc:events>
    <pc:events pc:name="GracePeriod">
      <pc:activities pc:name="DomainState:Active">
        <pc:rules>PolicyExec.domain_adjustState(request, &quot;Active&quot;)</pc:rules>
      </pc:activities>
    </pc:events>
    <pc:events pc:name="PendingUpdate">
      <pc:activities pc:name="DomainState:Active">
        <pc:rules>PolicyExec.domain_adjustState(request, &quot;Active&quot;)</pc:rules>
      </pc:activities>
    </pc:events>
    <pc:events pc:name="PendingTransferUpdate">
      <pc:activities pc:name="DomainState:Active">
        <pc:rules>PolicyExec.domain_adjustState(request, &quot;Active&quot;)</pc:rules>
      </pc:activities>
    </pc:events>
    <pc:events pc:name="Check">
      <pc:activities pc:name="Failure"/>
    </pc:events>
  </pc:objects>
  <pc:objects pc:name="Contact">
    <pc:events pc:name="Create">
      <pc:activities pc:name="Permission">
        <pc:rules>PolicyExec.checkPermission(request, clID, objectname, eventname)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Validation">
        <pc:children pc:name="Availability">
          <pc:rules>PolicyExec.contact_isAvailable(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="MandatoryValues">
          <pc:rules>PolicyExec.contact_mandatoryValues(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="FormatCheck">
          <pc:rules>PolicyExec.validation(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="BannedListCheck">
          <pc:rules>PolicyExec.checkBannedList(request, banned_contact_list)</pc:rules>
        </pc:children>
      </pc:activities>
      <pc:activities pc:name="ContactState:OK">
        <pc:rules>PolicyExec.contact_adjustState(clID, &quot;Ok&quot;)</pc:rules>
      </pc:activities>
    </pc:events>
    <pc:events pc:name="Delete">
      <pc:activities pc:name="StatusCheck">
        <pc:rules>PolicyExec.contact_statusCheck(request, [&quot;Ok&quot;])</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Permission">
        <pc:rules>PolicyExec.checkPermission(request, clID, objectname, eventname)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Existence">
        <pc:rules>PolicyExec.contact_exists(request)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="DependencyCheck">
        <pc:rules>PolicyExec.contact_dependencyCheck(request)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="ContactState:Deleted">
        <pc:rules>PolicyExec.contact_adjustState(clID, &quot;Deleted&quot;)</pc:rules>
      </pc:activities>
    </pc:events>
    <pc:events pc:name="Update">
      <pc:activities pc:name="StatusCheck">
        <pc:rules>PolicyExec.contact_statusCheck(request, [&quot;Ok&quot;])</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Permission">
        <pc:rules>PolicyExec.checkPermission(request, clID, objectname, eventname)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Existence">
        <pc:rules>PolicyExec.contact_exists(request)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Validation">
        <pc:children pc:name="MandatoryValues">
          <pc:rules>PolicyExec.contact_mandatoryValues(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="FormatCheck">
          <pc:rules>PolicyExec.validation(request)</pc:rules>
        </pc:children>
      </pc:activities>
    </pc:events>
  </pc:objects>
  <pc:objects pc:name="Host">
    <pc:events pc:name="Create">
      <pc:activities pc:name="Permission">
        <pc:rules>PolicyExec.checkPermission(request, clID, objectname, eventname)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Validation">
        <pc:children pc:name="Availability">
          <pc:rules>PolicyExec.host_isAvailable(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="MandatoryValues">
          <pc:rules>PolicyExec.host_mandatoryValues(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="FormatCheck">
          <pc:rules>PolicyExec.validation(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="BannedListCheck">
          <pc:rules>PolicyExec.checkBannedList(request, banned_host_list)</pc:rules>
        </pc:children>
        <pc:children pc:name="InBailiwickCheck">
          <pc:rules>PolicyExec.host_inbailiwickCheck(request)</pc:rules>
        </pc:children>
      </pc:activities>
      <pc:activities pc:name="Nameservers">
        <pc:rules>PolicyExec.domain_nameserverCheck(request)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="ContactState:Linked">
        <pc:rules>PolicyExec.contact_adjustState(clID, &quot;Linked&quot;)</pc:rules>
      </pc:activities>
    </pc:events>
    <pc:events pc:name="Delete">
      <pc:activities pc:name="Permission">
        <pc:rules>PolicyExec.checkPermission(request, clID, objectname, eventname)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Existence">
        <pc:rules>PolicyExec.host_exists(request)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="DependencyCheck">
        <pc:rules>PolicyExec.host_dependencyCheck(request)</pc:rules>
      </pc:activities>
    </pc:events>
    <pc:events pc:name="Update">
      <pc:activities pc:name="Permission">
        <pc:rules>PolicyExec.checkPermission(request, clID, objectname, eventname)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Existence">
        <pc:rules>PolicyExec.host_exists(request)</pc:rules>
      </pc:activities>
      <pc:activities pc:name="Validation">
        <pc:children pc:name="MandatoryValues">
          <pc:rules>PolicyExec.host_mandatoryValues(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="FormatCheck">
          <pc:rules>PolicyExec.validation(request)</pc:rules>
        </pc:children>
        <pc:children pc:name="InBailiwickCheck">
          <pc:rules>PolicyExec.host_inbailiwickCheck(request)</pc:rules>
        </pc:children>
      </pc:activities>
      <pc:activities pc:name="Nameservers">
        <pc:rules>PolicyExec.domain_nameserverCheck(request)</pc:rules>
      </pc:activities>
    </pc:events>
  </pc:objects>
</pc:policyConfig>
  
          

The above is an example of an EPP Registry Implementation, note the use of the Library Prefix as defined in the libraries section

Appendix C. XML Schema

<?xml version="1.0" encoding="UTF-8"?>

<!-- (c) Domain Name Services (Pty) Ltd. 2014. All rights reserved. -->

<schema xmlns="http://www.w3.org/2001/XMLSchema" 
        targetNamespace="urn:ietf:params:xml:ns:dns:policyconf" 
        xmlns:tns="urn:ietf:params:xml:ns:dns:policyconf"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xlink="http://www.w3.org/1999/xlink"
        elementFormDefault="qualified" attributeFormDefault="qualified" version="1_0">

  <element name="policyConfig">
    <complexType>
      <sequence>
        <element name="copyright" type="string" minOccurs="0"/>
        <element name="policyParameters" type="tns:policyParameters" minOccurs="0"/>
        <element name="objects" type="tns:object" minOccurs="0" maxOccurs="unbounded"/>
      </sequence>
    </complexType>
  </element>
  
  <complexType name="event">
    <sequence>
      <element name="activities" type="tns:activity" minOccurs="0" maxOccurs="unbounded"/>
    </sequence>
    <attribute name="name" type="string" use="required"/>
  </complexType>
  
  <complexType name="object">
    <sequence>
      <element name="events" type="tns:event" minOccurs="0" maxOccurs="unbounded"/>
    </sequence>
    <attribute name="name" type="string" use="required"/>
  </complexType>
  
  <complexType name="activity">
    <sequence>
      <element name="rules" type="string" minOccurs="0" maxOccurs="unbounded"/>
      <element name="branch" type="tns:booleanBranch" minOccurs="0"/>
      <element name="children" type="tns:activity" minOccurs="0" maxOccurs="unbounded"/>
      <element name="finally" type="tns:activity" minOccurs="0" maxOccurs="1"/>
    </sequence>
    <attribute name="name" type="string" use="required"/>
  </complexType>
  
  <complexType name="booleanBranch">
    <sequence>
      <element name="answerTrue" type="tns:activity" minOccurs="1" maxOccurs="1"/>
      <element name="answerFalse" type="tns:activity" minOccurs="1" maxOccurs="1"/>
    </sequence>
    <attribute name="decision" type="string" use="required"/>
  </complexType>
  
  <complexType name="policyParameters">
    <sequence>
      <element name="constants" type="tns:constants" minOccurs="0"/>
      <element name="libraries" type="tns:libraries" minOccurs="0"/>
      <element name="constraints" type="tns:constraints" minOccurs="0"/>
    </sequence>
    <attribute name="policyIdentifier" type="string" use="optional"/>
  </complexType>
  
  <complexType name="libraries">
    <sequence>
      <element name="library" type="tns:library" minOccurs="0" maxOccurs="unbounded"/>
    </sequence>
  </complexType>
  
  <complexType name="library">
    <attribute name="name" type="string" use="required"/>
    <attribute name="path" type="string" use="required"/>
    <attribute name="prefix" type="string"/>
    <attribute name="type" type="tns:libraryType" default="Python"/>
  </complexType>
  
  <complexType name="constants">
    <sequence>
      <element name="values" minOccurs="0" maxOccurs="unbounded">
        <complexType>
          <simpleContent>
            <extension base="string">
              <attribute name="name" type="string" use="required"/>
              <attribute name="comment" type="string"/>
            </extension>
          </simpleContent>
        </complexType>
      </element>
    </sequence>
  </complexType>
  
  <complexType name="constraints">
    <sequence>
      <element name="policylimit" type="tns:policyLimit" minOccurs="0" maxOccurs="unbounded"/>
    </sequence>
  </complexType>
  
  <complexType name="policyLimit">
    <attribute name="xpath" type="string" use="required"/>
    <attribute name="minlen" type="int"/>
    <attribute name="maxlen" type="int"/>
    <attribute name="mincount" type="int"/>
    <attribute name="maxcount" type="int"/>
    <attribute name="regex" type="string"/>
    <attribute name="code" type="int"/>
    <attribute name="desc" type="string"/>
  </complexType>
  
  <simpleType name="libraryType">
    <restriction base="NMTOKEN">
      <enumeration value="Python"/>
    </restriction>
  </simpleType>
</schema> 

        

Author's Address

Michael J O'Connell Domain Name Services (Pty) Ltd COZA House Gazelle Close, Corporate Park South Midrand, Gauteng 1685 ZA Phone: +27 11 568 2812 EMail: mike@dnservices.co.za URI: http://dns.net.za/

Table of Contents