Examples

1. Hosting Use Case

In this example number 1, assume our “virtual” company runs a Hosting Business.

The companies customer data including a) Internet Domains and b) DNS Hostnames should be manageable by different sub systems.

Note

Example number 1 will only cover Local Service Mapping without Python Application Server / Multi-Tier abstraction.

Note

In example number 4 we will dig a little deeper and include those aspects, even Service Scaling and Load Balancing.

1.1. Basic OOP Relations

The hosting service offers the customer to buy (add, delete) domains and manage the domains DNS host entries (add, update, delete).

- Customer
  + Domain(s)
    + Hostname(s)
  • Customer has 1:n relation to Domain

  • Domain has 1:n relation to Host

1.2. Relations Diagram

image - microesb example1, relations

1.3. Encapsulation / Domain Data

It is a common design approach to encapsulate each logical segment into a single, separated “flat” service endpoint.

  1. Separated (parametrized) insertDomain

  2. Separated (parametrized) updateDomain

  3. Separated (parametrized) deleteDomain

  4. Separated (parametrized) insertHost

  5. Separated (parametrized) updatetHost

  6. Separated (parametrized) deletetHost

Imagine this like a simple, parametrized function() call / “flat”, non-hierachical.

1.4. Encapsulation The Better Way

We could do this much easier, preserve (database) transactions and save a lot of administrative / maintaining effort.

If we could already process structured hierachical metadata in the service input, these endpoints would be reduced to the following.

  1. Separated (hierachical metadata) insertUserDomain

  2. Separated (hierachical metadata) updatetUserDomain

  3. Separated (hierachical metadata) deleteUserDomain

Note

Also the microesb`s service processing is able to handle multiple (list) user requests containing domain / host data in one single webservice call.

Note

Example number 1 only covers 1. “insertUserDomain”.

1.5. Example Call Meta-Data

The following example service call metadata will instruct the backend to do the following tasks when using backend configuration from section 1.7. Backend Config / Service Mapping and code from section 1.8. Python Implementation.

  1. Loop on User [ “testuser1” ]

  2. Start database transaction

  3. Get user id by user name

  4. Insert Domain “testdomain1.com” if it does not exist

  5. Insert Hostname (MX type) with value “mx01.mailserver.com” and priority 1

  6. Insert Hostname (A type) with value “mx01.mailserver.com” and ttl 36000 seconds

  7. Commit on success or rollback database transaction on failure

 1service_metadata = {
 2    'SYSServiceID': 'insertUserDomain',
 3    'data': [
 4        {
 5            'User':
 6            {
 7                'SYSServiceMethod': 'init',
 8                'name': 'testuser1',
 9                'Domain': {
10                    'SYSServiceMethod': 'add',
11                    'name': 'testdomain1',
12                    'ending': 'com',
13                    'Host': [
14                        {
15                            'SYSServiceMethod': 'add',
16                            'type': 'MX',
17                            'value': 'mx01.mailserver.com',
18                            'priority': 1
19                        },
20                        {
21                            'SYSServiceMethod': 'add',
22                            'name': 'host1',
23                            'type': 'A',
24                            'value': '5.44.111.165',
25                            'ttl': 36000
26                        }
27                    ]
28                }
29            }
30        }
31    ]
32}

1.6. Database Tables (PostgreSQL)

The following database tables are used in this example.

  • sys_core.”user”

  • sys_core.”domain”

  • sys_dns.”dnsrecord”

The following SQL code is an excerpt (create tables) of the complete database creation SQL script found in the example folder.

 1\connect "hosting-example"
 2
 3-- Table: sys_core.user
 4CREATE TABLE IF NOT EXISTS sys_core."user"
 5(
 6    id bigint NOT NULL DEFAULT nextval('sys_core.user_id_seq'::regclass),
 7    name character varying NOT NULL,
 8    CONSTRAINT user_pkey PRIMARY KEY (id)
 9);
10
11-- Table: sys_core.domain
12CREATE TABLE IF NOT EXISTS sys_core."domain"
13(
14    id bigint NOT NULL DEFAULT nextval('sys_core.domain_id_seq'::regclass),
15    name text NOT NULL,
16    ending character varying,
17    creator_user_id bigint NOT NULL,
18    CONSTRAINT domain_pkey PRIMARY KEY (id),
19    CONSTRAINT admin_user_id_fk FOREIGN KEY (creator_user_id)
20        REFERENCES sys_core."user" (id) MATCH FULL
21        ON UPDATE NO ACTION
22        ON DELETE CASCADE
23);
24
25-- Table: sys_dns.dnsrecord
26CREATE TABLE IF NOT EXISTS sys_dns."dnsrecord"
27(
28    id integer NOT NULL DEFAULT nextval('sys_dns.dnsrecord_id_seq'::regclass),
29    domain_id integer NOT NULL,
30    name character varying(255) NULL,
31    type character varying(10) NOT NULL,
32    content character varying(65535) NOT NULL,
33    ttl integer,
34    prio integer,
35    CONSTRAINT dnsrecord_pkey PRIMARY KEY (id),
36    CONSTRAINT domain_id_fk FOREIGN KEY (domain_id)
37        REFERENCES sys_core.domain (id) MATCH SIMPLE
38        ON UPDATE NO ACTION
39        ON DELETE CASCADE,
40    CONSTRAINT c_lowercase_name CHECK (name::text = lower(name::text))
41);

1.7. Backend Config / Service Mapping

The following dictionary data describes how to configure the microesb`s backend to run this example.

1.7.1. Service Property Mapping

 1service_properties = {
 2    'User': {
 3        'properties': {
 4            'name': {
 5                'type': 'str',
 6                'default': None,
 7                'required': True,
 8                'description': 'Textual UserID'
 9            },
10            'dbcon': {
11                'type': 'classref',
12                'default': None,
13                'required': True,
14                'description': 'Database Connection Ref'
15            }
16        },
17        'methods': ['init']
18    },
19    'Domain': {
20        'properties': {
21            'name': {
22                'type': 'str',
23                'default': None,
24                'required': True,
25                'description': 'Domain Name'
26            },
27            'ending': {
28                'type': 'str',
29                'default': None,
30                'required': True,
31                'description': 'Domain Ending'
32            }
33        },
34        'methods': ['add', 'delete']
35    },
36    'Host': {
37        'properties': {
38            'name': {
39                'type': 'str',
40                'default': None,
41                'required': False,
42                'description': 'DNS Name'
43            },
44            'type': {
45                'type': 'str',
46                'default': None,
47                'required': True,
48                'description': 'DNS Type'
49            },
50            'value': {
51                'type': 'str',
52                'default': None,
53                'required': True,
54                'description': 'DNS Value'
55            },
56            'ttl': {
57                'type': 'int',
58                'default': 3600,
59                'required': False,
60                'description': 'DNS Time To Live'
61            },
62            'priority': {
63                'type': 'int',
64                'default': None,
65                'required': False,
66                'description': 'MX Type Priority'
67            }
68        },
69        'methods': ['add', 'update', 'delete']
70    }
71}

1.7.2. Hierachical Class Reference

 1class_reference = {
 2    'User': {
 3        'property_ref': 'User',
 4        'children': {
 5            'Domain': {
 6                'property_ref': 'Domain',
 7                'children': {
 8                    'Host': {
 9                        'property_ref': 'Host'
10                    }
11                }
12            }
13        }
14    }
15}

1.7.3. Class Mapping

1class_mapping = {
2    'User': 'User',
3    'Domain': 'Domain',
4    'Host': 'Host'
5}

1.8. Python Implementation

The following code covers the implementation part.

1.8.1. Class Definition

  1import psycopg2
  2
  3from microesb import microesb
  4
  5
  6class User(microesb.ClassHandler):
  7
  8    def __init__(self):
  9        super().__init__()
 10        self.DB_user_id = None
 11
 12    def init(self):
 13        with self.dbcon.cursor() as crs:
 14            crs.execute("""
 15                SELECT id
 16                    FROM sys_core."user"
 17                WHERE
 18                    "name" = %s""",
 19                (self.name,)
 20            )
 21            row = crs.fetchone()
 22            self.DB_user_id = row[0]
 23
 24
 25class Domain(microesb.ClassHandler):
 26
 27    def __init__(self):
 28        super().__init__()
 29        self.DB_domain_id = None
 30
 31    def add(self):
 32
 33        self.DB_user_id = self.parent_object.DB_user_id
 34        self.dbcon = self.parent_object.dbcon
 35        print("DB_user_id:{} name:{} ending:{}".format(
 36            self.DB_user_id, self.name, self.ending)
 37        )
 38
 39        print("Insert Domain")
 40
 41        with self.dbcon.cursor() as crs:
 42            crs.execute(
 43                """
 44                SELECT id
 45                    FROM sys_core."domain"
 46                WHERE
 47                    creator_user_id = %s AND "name" = %s AND ending = %s""",
 48                (self.DB_user_id, self.name, self.ending,)
 49            )
 50            try:
 51                row = crs.fetchone()
 52                self.DB_domain_id = row[0]
 53            except Exception as e:
 54                pass
 55
 56        print("DB_domain_id:{}".format(self.DB_domain_id))
 57
 58        with self.dbcon.cursor() as crs:
 59            crs.execute(
 60                """
 61                INSERT INTO sys_core."domain"
 62                    (creator_user_id, "name", ending)
 63                VALUES
 64                    (%s, %s, %s)
 65                ON CONFLICT (creator_user_id, "name", ending) DO NOTHING
 66                RETURNING id
 67                """,
 68                (self.DB_user_id, self.name, self.ending)
 69            )
 70            try:
 71                row = crs.fetchone()
 72                self.DB_domain_id = row[0]
 73            except Exception as e:
 74                pass
 75
 76
 77class Host(microesb.MultiClassHandler):
 78
 79    def __init__(self):
 80        super().__init__()
 81        self.name = None
 82        self.priority = None
 83        self.ttl = None
 84
 85    def add(self):
 86        self.dbcon = self.parent_object.dbcon
 87        self.DB_user_id = self.parent_object.DB_user_id
 88        self.DB_domain_id = self.parent_object.DB_domain_id
 89
 90        print("Host add() called")
 91
 92        print("DB_user_id:{} DB_domain_id:{}".format(
 93            self.DB_user_id, self.DB_domain_id)
 94        )
 95
 96        try:
 97            with self.dbcon.cursor() as crs:
 98                crs.execute(
 99                    """
100                    INSERT INTO sys_dns."dnsrecord"
101                        (domain_id, "name", "type", content, ttl, prio)
102                    VALUES
103                        (%s, %s, %s, %s, %s, %s)""",
104                    (
105                        self.DB_domain_id,
106                        self.name,
107                        self.type,
108                        self.value,
109                        self.ttl,
110                        self.priority
111                    )
112                )
113        except Exception as e:
114            print("Insert excetion:{}".format(e))

1.8.2. Main / Service Call

 1import psycopg2
 2
 3from microesb import microesb
 4
 5from service_properties import service_properties
 6from class_reference import class_reference
 7from class_mapping import class_mapping
 8from service_call_metadata import service_metadata
 9
10
11class_mapper = microesb.ClassMapper(
12    class_references=class_reference,
13    class_mappings=class_mapping,
14    class_properties=service_properties
15)
16
17try:
18    dbcon = psycopg2.connect("dbname='hosting-example' user='postgres' host='localdb'")
19    dbcon.autocommit = False
20except Exception as e:
21    print('DB connection error: {}'.format(e))
22    exit(0)
23
24service_metadata['data'][0]['User']['dbcon'] = dbcon
25
26try:
27    microesb.ServiceExecuter().execute(
28        class_mapper=class_mapper,
29        service_data=service_metadata
30    )
31except Exception as e:
32    print('Service execution error: {}'.format(e))
33
34try:
35    dbcon.commit()
36    dbcon.close()
37except Exception as e:
38    print('DB close error: {}'.format(e))

1.8.3. Passing Parameters

To enable database transactions (disabled autocommit) inside main.py we have to open the database connection inside main.py and pass it into the implementation code.

Inside service_properties.py (line 10 - 15), we will define the property with id ‘dbcon’ which will be used to pass the database connection.

'dbcon': {
    'type': 'classref',
    'default': None,
    'required': True,
    'description': 'Database Connection Ref'
}

Inside main.py (line 24) the service properties value can be set (decorated) inside service call metadata dictionary.

service_metadata['data'][0]['User']['dbcon'] = dbcon

1.8.4. Execute Example

Change to the example path and execute the main.py file.

python3 ./main.py

1.8.5. Post Excecution

After executing you will find the new created domain inside sys_core.”domain” table and two related host records inside sys_dns.”dnsrecord” table.

Note

There are no unique constraints which forbid multiple dns entry inserts, calling the script multiple times duplicates dns records.

2. PKI Provisioning / Class Types

Example number 1 only covers a “plain” database model without local (e.g. bash) or remote (webservice) invocations.

Note

Example number 2 is a stripped-down excerpt from PKI management to show how virtual class types and clean OOP model setup are working.

2.1. CA Cert Relations

image - microesb example2, relations ca
  • CA == Certificate Authority

  • HSM == Hardware Security Module / Smartcard

  1. A CA is the root of a PKI (Public Key Infrastructure)

  2. A functioning CA needs a CA Certificate signed by unique Private Key (on protected HSM or software generated)

If no Smartcard / SmartcardContainer reference will be given, the Private Key used for the CA certificate will be generated by OpenSSL (marked optional in the diagram).

Note

A CA also can be setup in a hierarchical way (chain), this is called Intermediate CA. Our example only covers root CA processing without chaining.

2.2. Server Cert Relations

image - microesb example2, relations server

When a Server Certificate will be generated, a CA Certificate and its Private Key are required to guarantee that the Server Certifiate has been issued by the correct CA.

To run a TLS based server the Server Certificate (including Public Key), the Server Certificates Private Key and the CA Cert or CA Cert Chain (if Intermediate CA) is required.

Note

A Certificates X.509 v3 Extension(s) (OIDs) define the exact Certificates usage (e.g. Email Encryption, Transport Layer Encryption or similar).

2.3. Client Cert Relations

image - microesb example2, relations client

To generate a Client Certificate, additionally to the CA Certificate and its Private Key the relevant Server Certificate and its Private Key is required.

2.4. Service Workflow

The implemented example Service Workflow provides Certificate Generation for CertCA, CertServer and CertClient Certificates.

For all Certificate Types it will be checked, if a Smartcard reference has been provided. If yes, the keypair will be generated on card, if not the Private Key will be generated by openssl.

If a Smartcard is referenced inside Service Call Metadata, related data will be selected from database.

Also after successful Certificate Generation, relevant data will be stored inside database.

Note

To emphasize the presentation of the workflow only dummy routines / methods and print() statements have been used for illustration.

2.5. Implementation

  1import abc
  2
  3from microesb import microesb
  4
  5
  6class Cert(microesb.ClassHandler):
  7
  8    __metaclass__ = abc.ABCMeta
  9
 10    def __init__(self):
 11        super().__init__()
 12
 13    @abc.abstractmethod
 14    def _load_ref_cert_data(self):
 15        """ Abstract _load_ref_cert_data() method.
 16        """
 17
 18    @abc.abstractmethod
 19    def _gen_openssl_cert(self):
 20        """ Abstract _gen_openssl_cert() method.
 21        """
 22
 23    @abc.abstractmethod
 24    def _insert_cert_db_data(self):
 25        """ Abstract _insert_cert_db_data() method.
 26        """
 27
 28    def gen_cert(self):
 29
 30        self._load_ref_cert_data()
 31
 32        if getattr(self, 'Smartcard') is not None:
 33            self._hsm_gen_keypair()
 34        else:
 35            self._gen_openssl_privkey()
 36
 37        self._gen_openssl_cert()
 38        self._insert_cert_db_data()
 39
 40    def _gen_openssl_privkey(self):
 41        print('Gen openssl private key.')
 42
 43    def _get_cert_dbdata_by_id(self):
 44        print('Get cert data from db. Type: {}.'.format(self.type))
 45
 46    def _hsm_gen_keypair(self):
 47        print('Smartcard container label:{}'.format(
 48            self.Smartcard.SmartcardContainer.label)
 49        )
 50        self.Smartcard.gen_keypair()
 51
 52
 53class CertCA(Cert):
 54    def __init__(self):
 55        self.type = 'ca'
 56        super().__init__()
 57
 58    def _load_ref_cert_data(self):
 59        pass
 60
 61    def _gen_openssl_cert(self):
 62        print('Gen openssl cert type:{}.'.format(self.type))
 63
 64    def _insert_cert_db_data(self):
 65        print('Insert cert data type:{} into db.'.format(self.type))
 66
 67
 68class CertServer(Cert):
 69    def __init__(self):
 70        self.type = 'server'
 71        super().__init__()
 72
 73    def _load_ref_cert_data(self):
 74        self.CertCA._get_cert_dbdata_by_id()
 75
 76    def _gen_openssl_cert(self):
 77        print('Gen openssl cert type:{}, rel to CA.'.format(self.type))
 78
 79    def _insert_cert_db_data(self):
 80        print('Insert cert data type:{} into db.'.format(self.type))
 81
 82
 83class CertClient(Cert):
 84    def __init__(self):
 85        self.type = 'client'
 86        super().__init__()
 87
 88    def _load_ref_cert_data(self):
 89        self.CertCA._get_cert_dbdata_by_id()
 90        self.CertServer._get_cert_dbdata_by_id()
 91
 92    def _gen_openssl_cert(self):
 93        print('Gen openssl cert type:{}, rel to cCA and cServer.'.format(self.type))
 94
 95    def _insert_cert_db_data(self):
 96        print('Insert cert data type:{} into db.'.format(self.type))
 97
 98
 99class Smartcard(microesb.ClassHandler):
100    def __init__(self):
101        super().__init__()
102
103    def gen_keypair(self):
104        print('Gen keypair on smartcard:{} with keypair label:{}'.format(
105            self.label,
106            self.SmartcardContainer.label
107        ))
108
109
110class SmartcardContainer(microesb.ClassHandler):
111    def __init__(self):
112        super().__init__()

2.6. Clean OOP Model

To get a clean OOP model inside the implementation class hierarchy, the following design aspects have been selected.

Note

Virtual Class Types require a Base Class iheriting microesb.ClassHandler and minimal 1 Child Class inheriting the Base Class.

class Cert(microesb.ClassHandler):

    __metaclass__ = abc.ABCMeta

    def __init__(self):
        super().__init__()
class CertCA(Cert):

    def __init__(self):
        self.type = 'ca'
        super().__init__()

2.6.1. Abstract Methods

The “Cert” base class provides 3 private abstract methods because the processing logic differs for each Certificate Type.

  • _load_ref_cert_data()

  • _gen_openssl_cert()

  • _insert_cert_db_data()

class CertCA(Cert):

def _load_ref_cert_data(self):
    pass
class CertServer(Cert):

def _load_ref_cert_data(self):
    self.CertCA._get_cert_dbdata_by_id()
class CertClient(Cert):

def _load_ref_cert_data(self):
    self.CertCA._get_cert_dbdata_by_id()
    self.CertServer._get_cert_dbdata_by_id()

2.6.2. Generic Template Methods

The following methods are generic template methods to be inherited to each Child Class.

  • _gen_openssl_privkey()

  • _get_cert_dbdata_by_id()

  • _hsm_gen_keypair()

2.7. Accessing Properties

The clean OOP model makes accessing hierarchical Class Instance Properties very easy.

All Virtual Imlementation Class Instances are able to do the following to access its own (self) Smartcard Containers Label.

self.Smartcard.SmartcardContainer.label

In CertClient and CertServer it is also possible to access the CertCA Smartcard Properties (Referenced Classes in Class Reference Config) to fill with data drom database inside _get_cert_dbdata_by_id().

self.CertCA.Smartcard.SmartcardContainer.label

2.8. Class Import

The Class Import Config must include all Implementation Classes except the Base Class(es).

1import_classes = {
2    'service_implementation': [
3        'CertCA',
4        'CertServer',
5        'CertClient',
6        'Smartcard',
7        'SmartcardContainer'
8    ]
9}

2.9. Service Execution

Currently, the Service Registry feature is unimplemented. Excecution is only possible as a single service foreach Certificate Type.

2.9.1. CertCA Type

 1from microesb import microesb
 2
 3from class_reference import class_reference_ca as class_reference
 4from service_properties import service_properties
 5from class_mapping import class_mapping
 6from service_call_metadata import service_metadata_ca as service_metadata
 7
 8
 9class_mapper = microesb.ClassMapper(
10    class_references=class_reference,
11    class_mappings=class_mapping,
12    class_properties=service_properties
13)
14
15try:
16    res = microesb.ServiceExecuter().execute(
17        class_mapper=class_mapper,
18        service_data=service_metadata
19    )
20except Exception as e:
21    print('Service execution error: {}'.format(e))

Output must look like this after executing.

python3 ./main-ca.py

Gen keypair on smartcard:smartcard_ca_card with keypair label:keypair_ca1
Gen openssl cert type:ca.
Insert cert data type:ca into db.

2.9.2. CertServer Type

 1from microesb import microesb
 2
 3from class_reference import class_reference_server as class_reference
 4from service_properties import service_properties
 5from class_mapping import class_mapping
 6from service_call_metadata import service_metadata_server as service_metadata
 7
 8
 9class_mapper = microesb.ClassMapper(
10    class_references=class_reference,
11    class_mappings=class_mapping,
12    class_properties=service_properties
13)
14
15try:
16    res = microesb.ServiceExecuter().execute(
17        class_mapper=class_mapper,
18        service_data=service_metadata
19    )
20except Exception as e:
21    print('Service execution error: {}'.format(e))

Output must look like this after executing.

python3 ./main-server.py

Get cert data from db. Type: ca.
Smartcard container label:testserver1_keypair
Gen keypair on smartcard:smartcard_customer1 with keypair label:testserver1_keypair
Gen openssl cert type:server, rel to CA.
Insert cert data type:server into db.

2.9.3. CertClient Type

 1from microesb import microesb
 2
 3from class_reference import class_reference_client as class_reference
 4from service_properties import service_properties
 5from class_mapping import class_mapping
 6from service_call_metadata import service_metadata_client as service_metadata
 7
 8
 9class_mapper = microesb.ClassMapper(
10    class_references=class_reference,
11    class_mappings=class_mapping,
12    class_properties=service_properties
13)
14
15try:
16    res = microesb.ServiceExecuter().execute(
17        class_mapper=class_mapper,
18        service_data=service_metadata
19    )
20except Exception as e:
21    print('Service execution error: {}'.format(e))

Output must look like this after executing.

python3 ./main-client.py

Get cert data from db. Type: ca.
Get cert data from db. Type: server.
Smartcard container label:testserver1_client1_keypair
Gen keypair on smartcard:smartcard_customer1 with keypair label:testserver1_client1_keypair
Gen openssl cert type:client, rel to cCA and cServer.
Insert cert data type:client into db.

2.10. Class Reference

The root classes “CertCA”, “CertServer” and “CertClient” must have property_ref point to ‘Cert’ properties defined in Service Properties Config.

The following requirements must be met for successful referencing.

  • Class Reference mapping (property_ref) always must map to Base Class (Cert)

  • Base Class (Cert) must exist in Implementation

  • Base Class (Cert) must be inherited by Virtual Class(es) (CertCA …) in Implementation

  • Properties inside Service Property Config must be defined for given Base Class (Cert)

  • Class Mapping Config must include Virtual Class(es) (CertCA …)

  • Virtual Class(es) (CertCA …) must be referenced in Import Configuration

The following Class Reference Config contains all three Cert Types (CA, Server and Client).

 1class_reference_ca = {
 2    'CertCA': {
 3        'property_ref': 'Cert',
 4        'children': {
 5            'Smartcard': {
 6                'property_ref': 'Smartcard',
 7                'children': {
 8                    'SmartcardContainer': {
 9                        'property_ref': 'SmartcardContainer'
10                    }
11                }
12            }
13        }
14    }
15}
16
17class_reference_server = {
18    'CertServer': {
19        'property_ref': 'Cert',
20        'children': {
21            'Smartcard': {
22                'property_ref': 'Smartcard',
23                'children': {
24                    'SmartcardContainer': {
25                        'property_ref': 'SmartcardContainer'
26                    }
27                }
28            },
29            'CertCA': {
30                'property_ref': 'Cert',
31                'children': {
32                    'Smartcard': {
33                        'property_ref': 'Smartcard',
34                        'children': {
35                            'SmartcardContainer': {
36                                'property_ref': 'SmartcardContainer'
37                            }
38                        }
39                    }
40                }
41            }
42        }
43    }
44}
45
46class_reference_client = {
47    'CertClient': {
48        'property_ref': 'Cert',
49        'children': {
50            'Smartcard': {
51                'property_ref': 'Smartcard',
52                'children': {
53                    'SmartcardContainer': {
54                        'property_ref': 'SmartcardContainer'
55                    }
56                }
57            },
58            'CertCA': {
59                'property_ref': 'Cert',
60                'children': {
61                    'Smartcard': {
62                        'property_ref': 'Smartcard',
63                        'children': {
64                            'SmartcardContainer': {
65                                'property_ref': 'SmartcardContainer'
66                            }
67                        }
68                    }
69                }
70            },
71            'CertServer': {
72                'property_ref': 'Cert',
73                'children': {
74                    'Smartcard': {
75                        'property_ref': 'Smartcard',
76                        'children': {
77                            'SmartcardContainer': {
78                                'property_ref': 'SmartcardContainer'
79                            }
80                        }
81                    }
82                }
83            }
84        }
85    }
86}

2.11. Class Mapping

The Class Mapping Config.

1class_mapping = {
2    'CertCA': 'CertCA',
3    'CertServer': 'CertServer',
4    'CertClient': 'CertClient',
5    'Smartcard': 'Smartcard',
6    'SmartcardContainer': 'SmartcardContainer'
7}

Note

All Virtual Class Types classes always must reference themselves. Only Alias Class Mapping uses non-self-mapping (see 3. Alias Class Mapping).

2.12. Service Properties

The Service Property Config.

 1service_properties = {
 2    'SYSBackendMethods': [
 3        ('gen_cert', 'on_recursion_finish')
 4    ],
 5    'Cert': {
 6        'properties': {
 7            'id': {
 8                'type': 'str',
 9                'default': None,
10                'required': True,
11                'description': 'Textual cert database id'
12            },
13            'country': {
14                'type': 'str',
15                'default': 'DE',
16                'required': True,
17                'description': 'Certificate country ref'
18            },
19            'state': {
20                'type': 'str',
21                'default': None,
22                'required': True,
23                'description': 'Certificate state ref'
24            },
25            'locality': {
26                'type': 'str',
27                'default': None,
28                'required': True,
29                'description': 'Certificate locality ref'
30            },
31            'org': {
32                'type': 'str',
33                'default': None,
34                'required': True,
35                'description': 'Certificate organization ref'
36            },
37            'org_unit': {
38                'type': 'str',
39                'default': None,
40                'required': True,
41                'description': 'Certificate organization unit ref'
42            },
43            'common_name': {
44                'type': 'str',
45                'default': None,
46                'required': True,
47                'description': 'Certificate common name'
48            },
49            'email': {
50                'type': 'str',
51                'default': None,
52                'required': True,
53                'description': 'Certificate email ref'
54            },
55            'valid_days': {
56                'type': 'int',
57                'default': 365,
58                'required': True,
59                'description': 'Certificate validity range in days'
60            }
61        },
62        'methods': ['gen_cert']
63    },
64    'Smartcard': {
65        'properties': {
66            'label': {
67                'type': 'str',
68                'default': None,
69                'required': True,
70                'description': 'Smartcard textual label'
71            },
72            'user_pin': {
73                'type': 'str',
74                'default': None,
75                'required': True,
76                'description': 'Smartcard pin'
77            }
78        }
79    },
80    'SmartcardContainer': {
81        'properties': {
82            'label': {
83                'type': 'str',
84                'default': None,
85                'required': True,
86                'description': 'Container object on smartcards textual label'
87            }
88        }
89    }
90}

2.13. Service Call Metadata

The Service Call Metadata for all Cert Types.

 1service_metadata_ca = {
 2    'SYSServiceID': 'generateCertCA',
 3    'data': [
 4        {
 5            'CertCA': {
 6                'id': 'test-ca1',
 7                'Smartcard': {
 8                    'label': 'smartcard_ca_card',
 9                    'user_pin': 'pin1',
10                    'SmartcardContainer': {
11                        'label': 'keypair_ca1'
12                    }
13                },
14                'country': 'DE',
15                'state': 'Berlin',
16                'locality': 'Berlin',
17                'org': 'WEBcodeX',
18                'org_unit': 'Security',
19                'common_name': 'testca@domain.com',
20                'email': 'pki@webcodex.de',
21                'valid_days': 365
22            }
23        }
24    ]
25}
26
27service_metadata_server = {
28    'SYSServiceID': 'generateCertServer',
29    'data': [
30        {
31            'CertServer': {
32                'id': 'test-server1',
33                'CertCA': {
34                    'id': 'test-ca1'
35                },
36                'Smartcard': {
37                    'label': 'smartcard_customer1',
38                    'user_pin': 'pin2',
39                    'SmartcardContainer': {
40                        'label': 'testserver1_keypair'
41                    }
42                },
43                'country': 'DE',
44                'state': 'Berlin',
45                'locality': 'Berlin',
46                'org': 'WEBcodeX',
47                'org_unit': 'Security',
48                'common_name': 'testserver@domain.com',
49                'email': 'pki@webcodex.de',
50                'valid_days': 365
51            }
52        }
53    ]
54}
55
56service_metadata_client = {
57    'SYSServiceID': 'generateCertClient',
58    'data': [
59        {
60            'CertClient': {
61                'id': 'test-client1',
62                'CertCA': {
63                    'id': 'test-ca1'
64                },
65                'CertServer': {
66                    'id': 'test-server1'
67                },
68                'Smartcard': {
69                    'label': 'smartcard_customer1',
70                    'user_pin': 'pin2',
71                    'SmartcardContainer': {
72                        'label': 'testserver1_client1_keypair'
73                    }
74                },
75                'country': 'DE',
76                'state': 'Berlin',
77                'locality': 'Berlin',
78                'org': 'WEBcodeX',
79                'org_unit': 'Security',
80                'common_name': 'testclient1@domain.com',
81                'email': 'pki@webcodex.de',
82                'valid_days': 365
83            }
84        }
85    ]
86}

3. Alias Class Mapping

Alias Class Mapping must be used if you want to setup multiple Child Class Instances.

3.1. Requirements

The Alias Definition must exist in Class Maping Config and map to an existing Implementation Class.

Children to classes defined inside Class Reference Config must map to the Alias Class(es).

The Alias Class property_ref property in Class Reference Config always must reference an existing Implementation Class.

3.2. Example

config = {
    'class_mapping': {
        'Test': 'Test',
        'Test2Ref1': 'Test2',
        'Test2Ref2': 'Test2'
    },
    'class_reference': {
        'Test': {
            'property_ref': 'Test',
            'children': {
                'Test2Ref1': {
                    'property_ref': 'Test2'
                },
                'Test2Ref1': {
                    'property_ref': 'Test2'
                }
            }
        }
    }
}

4. SOA on Kubernetes

Example including working docker container(s) / Kubernetes Minikube setup on the way (right after FalconAS milestone “HTTP1/1 implementation” has been adapted).

See: https://github.com/WEBcodeX1/http-1.2.