Documentation and help portal

regigate rule engine file format

Introduction

This document describes and explains the file format used by the regigate rule engine. The rule-file is to be used in the regigate appliance menu (SSH) and must be inserted there for every rule.

File format

File format specification

The configuration file is JSON encoded. This is the general specification for the configuration file:

{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "definitions": {
    "field": {
      "type": "string",
      "enum": ["srcIp", "sender", "recip", "recipDomain", "header",
               "attName", "attType"]
    },
    "meet": {
      "type": "string",
      "enum": ["regex", "inList", "allInList", "contains", "equals"]
    }
  },
  "type": "object",
  "properties": {
    "matchingConditions": {
      "type": "object",
      "patternProperties": {
        ".+": {
          "type": "object",
          "properties": {
            "desc": {"type": "string", "description": "optional comment"},
            "field": {"$ref": "#/definitions/field"},
            "meet": {"$ref": "#/definitions/meet"},
            "criterium": {"type": "string"},
            "caseMatters": {"type": "boolean", "description": "default false"}
          },
          "required": ["field", "meet", "criterium"]
        }
      }
    },
    "rules": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {"type": "string"},
          "desc": {"type": "string", "description": "optional comment"},
          "conditions": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "type": "object",
                  "properties": {
                    "desc": {"type": "string",
                             "description": "optional comment"},
                    "does": {"type": "boolean"},
                    "field": {"$ref": "#/definitions/field"},
                    "meet": {"$ref": "#/definitions/meet"},
                    "criterium": {"type": "string"},
                    "caseMatters": {"type": "boolean",
                                    "description": "default false"}
                  },
                  "required": ["does", "field", "meet", "criterium"]
                },
                {
                  "type": "object",
                  "properties": {
                    "desc": {"type": "string",
                             "description": "optional comment"},
                    "does": {"type": "boolean"},
                    "match": {"type": "string",
                              "description": "existing matchingConditions key"}
                  },
                  "required": ["does", "match"]
                }
              ]
            }
          },
          "action": {
            "type": "string",
            "enum": ["encrypt", "decrypt", "pass", "reject"]
          },
          "tags": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "type": "object",
                  "properties": {
                    "addHeader": {"type": "string",
                                  "description": "header name"},
                    "desc": {"type": "string",
                             "description": "optional comment"},
                    "value": {"type": "string", "description": "header value"}
                  },
                  "required": ["addHeader", "value"]
                },
                {
                  "type": "object",
                  "properties": {
                    "modHeader": {"type": "string",
                                  "description": "header name"},
                    "desc": {"type": "string",
                             "description": "optional comment"},
                    "match": {"type": "string",
                              "description": "regular expression to match"},
                    "caseMatters": {"type": "boolean",
                                    "description": "default false"},
                    "replace": {"type": "string",
                                "description": "replacement for matched regex"}
                  },
                  "required": ["modHeader", "match", "replace" ]
                }
              ]
            }
          },
          "active": {"type": "boolean"}
        }
      },
      "required": ["name", "action", "active"]
    }
  }
}

The above scheme follows the official syntax defined here:
http://json-schema.org/

Matching Conditions

A matchingCondition allows you to define rules faster and more comfortably. A matchingCondition is a predefined condition which can be used later by a simple "does" or "does not" variation using the match property pointing to its name.

Look at this example rule without using a matchingCondition (in the "rules" section of the JSON file):

{ "name" : "encrypt outgoing",
  "desc" : "encrypt everything outgoing except rgf files",
  "conditions" : {
    "does" : false,
    "desc" : "has an rgf file",
    "field" : "attType",
    "meet" : "equals",
    "criterium" : "application/vnd.regify"
  },
  "action" : "encrypt",
  "active" : true
}

The rule below is exactly the same, but uses a matchingCondition named "hasRgf".

Now, the matchingCondition is defined like this (in the "matchingConditions" section of the JSON file):

{
    "hasRgf" : {
      "desc" : "has an rgf file",
      "field" : "attType",
      "meet" : "equals",
      "criterium" : "application/vnd.regify"
    }
}

The rule itself now looks like this (in the "rules" section of the JSON file):

{ "name" : "encrypt outgoing",
  "desc" : "encrypt everything outgoing except rgf files",
  "conditions" : {
    "does" : false, "match" : "hasRgf"
  },
  "action" : "encrypt",
  "active" : true
}

matchingConditions can be reused many times and therefore have the following benefits:

  • If you have to use a value/condition many times (eg IP address of an MTA as source), you have a single point where it is defined.

  • Less text to type.

  • Rules are much easier to read and understand.

Rules

How rules are applied

Paradigm 1

Rules are applied from top to bottom.

Paradigm 2

The first rule that applies stops the rule execution. Any subsequent rules below are ignored.

Paradigm 3

If no rule applies until the end, the message is passed through by default.

Therefore, if you simply define an empty rule file like "{ }", all messages are simply passed through unaltered. This is the default behaviour of a newly created route.

If you prefer to let a regigate route reject all messages that were not handled by a rule, you may add a final blocking rule to reject everything that has not been handled above:

{
  "name": "reject everything",
  "desc": "reject all messages that have not been handled by any previous rule",
  "action": "reject",
  "active": true
}

Rule attributes

The following table shows the possible elements of a rule including their description and default values:

Property Description

name

The name of the rule.

desc

A short description and intent of the rule. You may also add some comments about the conditions here. Optional.

conditions

One or more matchingCondition for this rule. Please see the separate "Rule conditions" section below. If no conditions are defined, the rule will match and its action will be performed.

action

Specifies the action this rule would trigger. Possible values are:

  • encrypt - The message is encrypted and becomes a regimail.

  • decrypt - The message is decrypted if possible.

  • pass - The message is simply passed unaltered.

  • reject - regigate will reject the message with a 5x error. Your mail server will most likely trigger some sort of bounce message to inform the user. The error is accompanied by an English textual description.

tags

Optional. One or more tag rules for this message. Please see the separate tags section below.

active

If the rule is used or not. Set this to false if you do not want this rule to apply. This is handy for testing or if you like to have a rule as a template, but don’t want it to actually apply.

Rule conditions

Every rule may have of one or more conditions. Every condition is an entry in the conditions value of the JSON file. Whenever there are multiple inputs to match, like recipients, headers or attachments, any one match will make the condition match. Multiple conditions are *AND*ed.

There are two ways of defining a condition. You can either:

  1. define all condition parameters directly or

  2. use a matchingCondition (see extra chapter above for matchingConditions).

This table shows you the properties of a complete condition:

Property Description

desc

A short description of the condition. Optional.

does

Boolean value as negotiator. If it is true, the criteria must match. If it is false, the criteria must not match.

field

One of the following fields to check in this condition:

  • sender - The sender e-mail address. Not in the form of "Spongebob Squarepants <\spongebob@glove.world>", but rather in the form of "\spongebob@glove.world" and always lowercase. caseMatters is always false.

  • recip - The recipient e-mail address. Not in the form of "Spongebob Squarepants <\spongebob@glove.world>", but rather in the form of "\spongebob@glove.world" and always lowercase. caseMatters is always false. This also covers CC: and BCC: addresses!

  • recipDomain - The recipient e-mail address domain. So for \spongebob@glove.world, this will evaluate to regify.com and always lowercase. caseMatters is always false. This also covers CC: and BCC: addresses!

  • header - Any MIME header value excluding attachments. Best to compare using regex.

  • srcIp - The source IP of the connecting MTA (eg IP address of an internal, or some internet MTA).

When using per recipient rule matching, the source IP will always be the IP of the internal splitter MTA and will therefore not be of much use.
  • attName - The name of the email attachment. For multiple attachments, it is tested for every attachment.

  • attType - The type of the attachment (like application/vnd.regify). For multiple attachments, it is tested for every attachment.

meet

The comparison function. These are the available comparison functions:

  • regex - Apply a regular expression (in criteria) on the field values.

  • contains - Verify if the field value contains the given criteria.

  • equals - Verify if the field value exactly matches the given criteria.

  • inList - Searches a list of values (criterium is the list name, all list content must be line separated). You copy the list to the regigate appliance using the appliance menu via SSH.

  • allInList - Like "inList" but all possible inputs, for example recipients, must match.

Lists are always compared in a case sensitive manner. caseMatters is ignored. E-mail addresses must be all lowercase to match.

criterium

The comparison field used for the comparison function defined in the meet property.

If you have chosen regex, this is the regular expression to use on field.

If you have chosen inList or allInList, this is the name of the list to use.

If you have chosen contains, this value must be found in the field content.

If you have chosen equals, the field content hat to match this criteria completely.

caseMatters

Boolean value (true/false) if the case matters on the criteria or not. Optional, defaults to false. It is ignored and defaults to false for e-mail addresses. It is also ignored but defaults to true for lists.

This table shows you the properties of a condition that is using a matchingCondition:

Property Description

desc

A short description of the condition. Optional.

does

Boolean value as negotiator. If it is true, the matchingCondition must match. If it is false, the matchingCondition must not match.

match

The name of the matchingCondition to use.

Rule tags

Another feature of rules are tags. Tags are applied when the rule containing them matches. The tags object contains one or more objects that operate on a MIME’s headers. With headers we mean the headers that come before the body of the e-mail. Attachment headers are not affected by this. There are 2 kinds of header rules. addHeader adds a header and modHeader modifies an existing header if the regular expression in match matches. Both can use the following predefined general tokens in their values:

Token Description

$A

The action that was taken. One of encrypt, decrypt or pass. There is no reject, because rejected messages are not altered.

$H

The host name of the regigate machine that processed the message.

$I

The IP number the postfix instance, that processed the message, bound to.

$D

The processing date in RFC 2822 format. (Example "Mon, 14 Aug 2006 02:34:56 -0600")

Here are the details of addHeader:

Property Description

addHeader

The name of a header to unconditionally add.

value

The value of the added header. The entire header will read like the values of addHeader: value.
General token are accepted here.

desc

An optional description which merely serves as a comment.

These are the details of modHeader:

Property Description

modHeader

The name of a header to potentially replace. Only the first header is replaced. Subsequent headers by the same name are ignored.

match

A regular expression used to match all or parts of the given header.

caseMatters

Whether the expression given in match is case sensitive or not. Defaults to false.

replace

An expression to replace the header value with if it matched. Valid replacement tokens are $0-$9 for the groups as well as the general tokens.

desc

An optional description which merely serves as a comment.

Example inbound configuration

The following example file shows various rules for an inbound route. You may use it as a starting template for your own rule set.

{
  "matchingConditions" : {

    "hasRgfMime" : {
      "desc" : "has an rgf file mime-type",
      "field" : "attType",
      "meet" : "equals",
      "criterium" : "application/vnd.regify"
    },

    "hasRgfFile" : {
      "desc" : "attachment name *.rgf",
      "field" : "attName",
      "meet" : "regex",
      "criterium" : "\\.rgf$"
    }
  },

  "rules" : [

    { "name" : "decrypt in",
      "desc" : "decrypt incoming regimail based on mime",
      "conditions" : [
        { "does" : true, "match" : "hasRgfMime" }
      ],
      "action" : "decrypt",
      "tags" : [
        {"addHeader" : "X-regigate", "value" : "Action: $A by $H ($I) on $D"},
        {"modHeader" : "Subject", "desc" : "tag the subject with decryption",
         "match" : "(.*?)( \\(decrypted\\))?$", "caseMatters" : false,
         "replace" : "$1 (decrypted)"}
      ],
      "active" : true
    },

    { "name" : "decrypt in",
      "desc" : "decrypt incoming regimail based on extension",
      "conditions" : [
        { "does" : true, "match" : "hasRgfFile" }
      ],
      "action" : "decrypt",
      "active" : true
    },

    { "name" : "pass in",
      "desc" : "pass other incoming email",
      "action" : "pass",
      "active" : true
    }
  ]
}

Example outbound configuration

The following example file shows various rules for an outbound route. You may use it as a starting template for your own rule set.

{
  "matchingConditions" : {

    "hasRgfMime" : {
      "desc" : "has an rgf file mime-type",
      "field" : "attType",
      "meet" : "equals",
      "criterium" : "application/vnd.regify"
    },

    "hasRgfFile" : {
      "desc" : "attachment name *.rgf",
      "field" : "attName",
      "meet" : "regex",
      "criterium" : "\\.rgf$"
    }
  },

  "rules" : [

    { "name" : "encrypt all in list",
      "desc" : "ecnrypt outgoing email to regify recipients in list",
      "conditions" : [
        { "does" : false, "match" : "hasRgfMime" },
        { "does" : false, "match" : "hasRgfFile" },
        { "desc" : "in regify user list",
          "does" : true,
          "field" : "recip",
          "meet" : "allInList",
          "criterium" : "regifyUsers"
        }
      ],
      "action" : "encrypt",
      "active" : true
    },

    { "name" : "encrypt list",
      "desc" : "ecnrypt outgoing email to regify recipients in list",
      "conditions" : [
        { "does" : false, "match" : "hasRgfMime" },
        { "does" : false, "match" : "hasRgfFile" },
        { "desc" : "in regify user list",
          "does" : true,
          "field" : "recip",
          "meet" : "inList",
          "criterium" : "regifyUsers"
        }
      ],
      "action" : "encrypt",
      "active" : true
    },

    { "name" : "encrypt domains",
      "desc" : "ecnrypt outgoing email to specified domains",
      "conditions" : [
        { "does" : false, "match" : "hasRgfMime" },
        { "does" : false, "match" : "hasRgfFile" },
        { "desc" : "emails with domain...",
          "does" : true,
          "field" : "recipDomain",
          "meet" : "inList",
          "criterium" : "regifyDomains"
        }
      ],
      "action" : "encrypt",
      "active" : true
    },

    { "name" : "encrypt domains",
      "desc" : "ecnrypt outgoing email to @bank.com",
      "conditions" : [
        { "does" : false, "match" : "hasRgfMime" },
        { "does" : false, "match" : "hasRgfFile" },
        { "desc" : "emails to @bank.com",
          "does" : true,
          "field" : "recip",
          "meet" : "contains",
          "criterium" : "@bank.com"
        }
      ],
      "action" : "encrypt",
      "active" : true
    },

    { "name" : "encrypt !rf",
      "desc" : "ecnrypt outgoing where subject starts with !rf",
      "conditions" : [
        { "does" : false, "match" : "hasRgfMime" },
        { "does" : false, "match" : "hasRgfFile" },
        { "desc" : "Subject starts with !rf ",
          "does" : true,
          "field" : "header",
          "meet" : "regex",
          "criterium" : "^Subject:\\s*!rf ",
          "caseMatters" : true
        }
      ],
      "action" : "encrypt",
      "tags" : [
        {"modHeader" : "Subject", "desc" : "remove the !rf prefix",
         "match" : "^(?:\\s*!rf\\s+)(.*?)$", "caseMatters" : false,
                                  "replace" : "$1"}
      ],
      "active" : true
    },

    { "name" : "encrypt X-doEncrypt",
      "desc" : "ecnrypt outgoing where X-doEncrypt header is set",
      "conditions" : [
        { "does" : false, "match" : "hasRgfMime" },
        { "does" : false, "match" : "hasRgfFile" },
        { "desc" : "X-doEncrypt set",
          "does" : true,
          "field" : "header",
          "meet" : "regex",
          "criterium" : "^X-doEncrypt:",
          "caseMatters" : true
        }
      ],
      "action" : "encrypt",
      "tags" : [
        {"modHeader" : "X-doEncrypt", "desc" : "Detail out the X-doEncrypt header",
         "match" : "^.*$", "caseMatters" : false,
         "replace" : "Encrypted by $H ($I) on $D"}
      ],
      "active" : true
    },

    { "name" : "pass out",
      "desc" : "pass outgoing email not meant to be encrypted",
      "action" : "pass",
      "active" : true
    },

    { "name" : "reject out",
      "desc" : "sample deactivated rule",
      "conditions" : [
        { "does" : false, "match" : "hasRgfMime" },
        { "does" : false, "match" : "hasRgfFile" },
        { "desc" : "not in regify user list",
          "does" : false,
          "field" : "recip",
          "meet" : "inList",
          "criterium" : "regifyUsers"
        }
      ],
      "action" : "reject",
      "active" : false
    }
  ]
}