New post

Find

Please note that this post is obsolete.
Article
· Jan 10, 2017 9m read

Creating SSL-Enabled Mirror Using Public Key Infrastructure (PKI)

NB. Please be advised that PKI is not intended to produce certificates for secure production systems. You should make alternate arrangements to create certificates for your productions.
NB. PKI is deprecated as of IRIS 2024.1: documentation and announcement.

In this post, I am going to detail how to set up a mirror using SSL, including generating the certificates and keys via the Public Key Infrastructure built in to Caché. The goal of this is to take you from new installations to a working mirror with SSL, including a primary, backup, and DR async member, along with a mirrored database. I will not go into security recommendations or restricting access to the files. This is meant to just simply get a mirror up and running. Example screenshots are taken on a 2016.1 version of Caché, so yours may look slightly different.

Step 1: Configure Certificate Authority (CA) Server

On one of your instances (in my case the one that will be the first mirror member configured), go to the System Management Portal and go to the [System Administration -> Security -> Public Key Infrastructure] page. Here you will ‘Configure local Certificate Authority server’.

You can choose whatever File name root (this is the file name only, no path or extension) and Directory you want to have these files in. I’ll use ‘CA_Server’ as the File name root, and the directory will be my <install-dir>/mgr/CAServer/. This will avoid future confusion when the client keys and certificates are put into the <install-dir>/mgr/ folder, as I’ll be using my first mirror member as the CA Server. Go to the next page.

You will then need to enter a password, and I’ll use ‘server_password’ in my example. You can then assign attribute values for your Distinguished Name. I’ll set Country to ‘US’ and Common Name to ‘CASrv’. You can accept defaults for validity periods, leave the email section blank, and save.

You should see a message about files getting generated (.cer, .key, and .srl) in the directory you configured.

Step 2: Generate Key/Certificate For First Mirror Member

At this point, you need to generate the certificate and keys for the instance that will become your first mirror member. This time, go to the System Management Portal where you will set up the first mirror member, and go to the [System Administration -> Security -> Public Key Infrastructure] page again (see screenshot above). You need to ‘Configure local Certificate Authority client’. For the ‘Certificate Authority server hostname’, you need to put either the machine name or IP address of the instance you used for step 1, and for the ‘Certificate Authority WebServer port number’ use that instance’s web server port (you can get this from the URL in that instance’s Management portal):

Make sure you are using the port number for the instance you configured as the CA Server, not the one you are setting up as the client (though they may be the same). You can put your own name as the technical contact (the phone number and email are optional) and save.

Now you should go to ‘Submit Certificate Signing Request to Certificate Authority server’. You’ll need a file name (I’m using ‘MachineA_client’) and password (‘MachineA_password’) as well as again setting values for a Distinguished Name (Country=’US’ and Common Name=’MachineA’). Note that for each certificate you make, at least one of these values must be different than what was entered for the CA certificate. Otherwise, you may run into failures at a later step.

At this point, you’ll need to go to the machine you configured to be your CA Server. From the same page, you need to ‘Process pending Certificate Signing Requests’. You should see one like this:

You should process this request, leaving default values, and ‘Issue Certificate’. You’ll need to enter your CA Server password from step 1 (‘server_password’ for me).

Finally, you need to get the certificate. Back on the first mirror member machine, from the same page, go to ‘Get Certificate(s) from Certificate Authority server’, and click ‘Get’ like here:

You should then see a message indicating that the certificate was saved in the <install>/mgr/ directory of your instance.

Step 3: Configure The Mirror On First Mirror Member

First, start the ISCAgent per this documentation (and set it to start automatically on system startup if you don’t want to have to do this every time your machine reboots).

Then, in the System Management Portal, go to the [System Administration -> Configuration -> Mirror Settings -> Enable Mirror Service] page to enable the service (if it isn’t already enabled). Next, go to the ‘Create a Mirror’ page in the same menu.

You will need to enter a mirror name (‘PKIMIRROR’ in my case). You should click ‘Set up SSL/TLS’, and then enter the information there. If this is not the same machine where you configured the CA Server, you’ll need to get a copy of the CA Server certificate (‘CA_Server.cer’) on this machine. You can do this in the ‘Get Certificate(s) from Certificate Authority server’ page:

Back in the ‘Set up SSL/TLS’ page, the first line is asking for that CA server certificate. You should leave the ‘Certificate Revocation list’ blank. If you want to use this, please contact the WRC. For ‘This server’s credentials’, you’ll need to enter the certificate and key that we generated in step 2. They will be in the <install>/mgr/ directory. You’ll also need to enter your password here (click the ‘Enter new password’ button as shown). This password is the one you chose in step 2 (‘MachineA_password’ for me). In my example, I am only allowing TLS v1.2 protocol as shown below.

For this example, I won’t use an arbiter or a Virtual IP, so you can un-check those boxes in the ‘Create Mirror’ page. We’ll accept the defaults for ‘Compression’, ‘Mirror Member Name’, and ‘Mirror Agent Port’ (since I didn’t configure the ISCAgent to be on a different port), but I’m going to change the ‘Superserver Address’ to use an IP instead of a host name (personal preference). Just make sure that the other future mirror members are able to reach this machine at the address you choose. Once you save this, take a look at the mirror monitor [System Operation -> Mirror Monitor]. It should look something like this:

If you see that it’s still in a ‘Transition’ status, wait a few seconds and refresh the page. Note that these statuses were enhanced in 2016.2. You can see what they look like in the latest released version here.

Step 4: Generate Key/Certificate For Second Failover Mirror Member

This is the same process as step 2, but I’ll replace anything with ‘MachineA’ in the name with ‘MachineB’. As I mentioned before, make sure you change at least 1 of the fields in the Distinguished Name section from the CA certificate. You also need to be sure you get the correct certificate in the Get Certificate step, as you may see more than one option.

Step 5: Join Mirror as Failover Member

Just like you did for the first mirror member, you need to start the ISCAgent and enable the mirror service for this instance (refer to step 3 for details on how to do this). Then, you can join the mirror as a failover member at [System Administration -> Configuration -> Mirror Settings -> Join as Failover].

 

You’ll need the ‘Mirror Name’, ‘Agent Address on Other System’ (the same as the one you configured as the Superserver address for the other member), and the instance name of the now-primary instance.

After you click ‘Next’, you should see a message indicating that the mirror requires SSL, so you should again use the ‘Set up SSL/TLS’ link. As in step 3, you’ll need the CA Server certificate (same file we used in step 3, refer to that step for how to retrieve it), and you’ll replace machine A’s files and password with machine B’s for this dialog.

Again, I’m only using TLSv1.2. Once you’ve saved that, you should be able to add information about this mirror member. Again, I’m going to change the hostnames to IP’s, but feel free to use any IP/hostname that the other member can contact this machine on. Note that the IP’s are the same for my members, as I have set this up with multiple instances on the same server.

When you save this, you should see a message telling you not to forget to add this node to the primary’s configuration.

Step 6: Authorize 2nd Failover Member on the Primary Member

Now we need to go back to the now primary instance where we created the mirror. From the [System Administration -> Configuration -> Mirror Settings -> Edit Mirror] page, you should see a box at the bottom titled ‘Pending New Members’ including the 2nd failover member that you just added. Check the box for that member and click Authorize (there should be a dialog popup to confirm).

Now if you go back to [System Operation -> Mirror Monitor], it should look like this (similar on both instances):

Again, if you see a ‘Transition’ status, wait a few seconds and refresh the page.

Step 7: Generate Key/Certificate for Async Member

This is the same as step 2, but I’ll replace anything with ‘MachineA’ in the name with ‘MachineC’. As I mentioned before, make sure you change at least 1 of the fields in the Distinguished Name section from the CA certificate. Make sure you get the correct certificate in the ‘Get Certificate’ page, as you may see more than one option.

Step 8: Join Mirror as Async Member

This is similar to step 5. The only difference is that you may only be asked to configure 1 address (this depends what version you’re running), and you have the added option for an Async Member System Type (I will use Disaster Recovery, but you’re welcome to use one of the reporting options). You’ll again see a message about requiring SSL, and you’ll need to set that up similarly (MachineC instead of MachineB). Again, you’ll see a message after saving the configuration indicating that you should add this instance as an authorized async on the failover nodes.

Step 9: Authorize Async Member on the Primary Member

Follow the same procedure as in step 6. Note that this procedure has been simplified in recent versions to match behavior for a 2nd failover member. Previously, you needed to manually add authorized async member information. Once this complete, there is one extra step to make sure the mirror monitors are in sync. You should go to the [System Operation -> Mirror Monitor] on the 2nd failover member (now the backup), and click ‘Stop mirror’. After that’s complete, you should then click ‘Start mirror’. This is just to make sure that instance retrieves the information about the async member. It should not be required in later versions. The mirror monitor should now look like this:

Step 10: Add a Mirrored Database

Having a mirror is no fun if you can’t mirror any data, so we may as well create a mirrored database. We will also create a namespace for this database. Go to your primary instance. First, go to [System Administration -> Configuration -> System Configuration -> Namespaces] and click ‘Create New Namespace’ from that page.

We’ll call this ‘MIRROR’, and we’ll need to click ‘Create New Database’ next to ‘Select an existing database for Globals’. You’ll need to enter a name (‘MIRROR’) and directory for this new database. On the next page, be sure to change the ‘Mirrored database?’ drop-down to yes (THIS IS ESSENTIAL). The mirror name will default to the database name you chose. You can change it if you wish. We will use the default setting for all other options for the database (you can change them if you want, but this database must be journaled, as it is mirrored). Once you finish that, you will return to the namespace creation page, where you should select this new database for both ‘Globals and ‘Routines’. You can accept the defaults for the other options (don’t copy the namespace from anywhere).

Repeat this process for the backup and async. Make sure to use the same mirror name for the database. Since it’s a newly created mirrored database, there is no need to take a backup of the file and restore onto the other members.

Congratulations, you now have a working mirror using SSL with 3 members sharing a mirrored database!

Other reference documentation:

Create a mirror

Create mirrored database

Create namespace and database

Edit failover member (contains some information on adding SSL to an existing mirror)

7 Comments
Discussion (7)0
Log in or sign up to continue
Question
· Jan 6, 2017

What is the best method for copying Mappings and Routines?

Currently, we have an application running in one namespace ("Database B") that has globals and routines mapped to another database ("Database A"). After enforcing clean up on Database A, we found that 90% of the disk is free. We would like to compact Database A and release the unused space. However, we are running OpenVMS, which seems to be the issue.

For databases consisting of only globals, we are able to use ^GBLOCKCOPY; however, we need to ensure that the routines and mappings are also copied.

What would be the best recommended way to do this?

8 Comments
Discussion (8)0
Log in or sign up to continue
Question
· Jan 3, 2017

Deciphering Error Messages

When deciphering an error message (<MAXSTRING>main+45^LBZNSJHCACUPLB), my understanding is the error offset is 45 lines from "main".  If there are "go sub" entries within this 45 lines, do you count the lines in the "go sub" section or do you do a straight count of lines ignoring the "go sub" section?

2 Comments
Discussion (2)0
Log in or sign up to continue
Article
· Dec 29, 2016 10m read

Creating a Custom Application Monitor Class and an Alert

When an error occurs in your application, simply logging it might be enough. But for certain errors, you might want to send a notification to people right away. There are three ways to generate custom email notifications from InterSystems IRIS.

  1. Write code that uses ##class(%SYS.System).WriteToConsoleLog() to write a custom message to the Messages Log with the appropriate Alert Level. Then, configure InterSystems IRIS Monitor to send email when any messages with that Alert Level appear in the Messages Log. This is the simplest option. It requires editing your application code to call WriteToConsoleLog(). Also note that application errors, other than truly serious ones, probably don't belong in the Messages Log. Documentation for this option is here: https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=GC...
  2. Create a custom Application Monitor class, by extending %Monitor.Adaptor, that collects sample data (usually some application-specific data or condition) and records the sample history. Then, configure an Application Monitor Alert to send an email notification when the sampled information satisfies a custom condition. This option provides more control and flexibility than option #1. ​This article provides step-by-step instructions for this option, along with sample code. Documentation for this option is here: https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls...
  3. Create custom sensor, subscriber and notifier classes by extending %SYS.Monitor.AbstractSensor, %SYS.Monitor.AbstractSubscriber, and %SYS.Monitor.AbstractNotification, respectively, and configure them to collect sample data, test the data, and send email notifications. This option, while being more complex than the first two, provides the most control and flexibility. For example, multiple subscriber classes could share the same notifier class. Documentation for this option is here: https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls....
Note: While this article is about InterSystems IRIS, it also applies to Caché.

OK, here are the step-by-step instructions. Be strong...there are 12 steps.

Step 1. Create a custom Application Monitor class that inherits from %Monitor.Adaptor. You'll write custom methods in this class to collect and store sample data. Once the class is running, you can query this data and/or view it using a generated web page. In a later step, you'll define an Application Monitor Alert, with conditions on this data that trigger notifications.

Note: Since our example class monitors the Application Error Log (which is in the %SYS namespace), the class runs in the %SYS namespace. You can also create a custom class in a non-%SYS namespace. Before creating your class, you must run %SYSMONMGR in the namespace, option 5>2>3 (Register Monitor System Classes). Your custom class won't compile until you do this.

 

Step 2. Add properties to your class for the sample data that you want to collect, store, and test. The datatypes for these properties must be one of: %Monitor.Gauge, %Monitor.Integer, %Monitor.Numeric, %Monitor.String. Optionally, provide a CAPTION parameter as a more human-readable name for each property. The generated web page will use the CAPTION instead of the property name as the label for the data.

Step 3. If your class collects and stores multiple rows of data (as our example class does), add an INDEX property that specifies the property or properties (comma-delimited) that form the unique primary key for a row of sample data.

Step 4. If the methods in your class need some additional helper properties (our example class has several), add them to your class. Mark these properties [Internal], so that the data in these properties isn't stored as part of the sample data.

Step 5. There are four methods inherited from %Monitor.Adaptor that you can override.

  • Startup(): (optional) code called once for this class when Application Monitor starts.
  • Shutdown(): (optional) code called once for this class when Application Monitor stops.
  • Initialize(): (optional) code called at the beginning of each sampling interval for this class to start the collection of samples. To signal that no sample data was retrieved, Initialize() returns 0. If sample data was retrieved, it returns $$$OK.
  • GetSample(): (required) code called repeatedly to collect a row of sample data. To signal that there are no more rows of sample data, GetSample() returns 0. Otherwise, it returns $$$OK.

Step 6. Compile your class. This generates another class that is both a persistent class (for storage of the sample data) and a web page (for viewing the sample data). If your custom class is named MyPackage.MyClass, the generated class is named MyPackage.Sample.MyClass, and the associated SQL table is named MyPackage_Sample.MyClass.

Do the rest of the steps below using the %SYSMONMGR utility in Terminal. The steps use this syntax (1>2>3) as a convention for navigating the menus and sub-menus of %SYSMONMGR (choose option 1, then option 2, then option 3).

Step 7. In the namespace where you want to run your custom Application Monitor class, run ^%SYSMONMGR. Use 5>2>1 to activate your custom class. Enter ? at the Class? prompt to see a list of Application Monitor classes. Yours will probably be listed at the end, after all the built-in %classes.

%SYS>do ^%SYSMONMGR

1) Start/Stop System Monitor
2) Set System Monitor Options
3) Configure System Monitor Classes
4) View System Monitor State
5) Manage Application Monitor
6) Manage Health Monitor
7) View System Data
8) Exit

Option? 5

1) Set Sample Interval
2) Manage Monitor Classes
3) Change Default Notification Method
4) Manage Email Options
5) Manage Alerts
6) Exit

Option? 2

1) Activate/Deactivate Monitor Class
2) List Monitor Classes
3) Register Monitor System Classes
4) Remove/Purge Monitor Class
5) Set Class Sample Interval
6) Exit

Option? 1

Class? ?

 Num  MetricsClassName               Activated

  1)  %Monitor.System.HistoryMemory  N
 <… output omitted …>
 19)  Demo.MonitorErrors             N

Class? 19 Demo.MonitorErrors
Activate class? Yes => Yes

Step 8. (Optional) Use 5>2>5 to set a custom sampling interval for your class. The default class sampling interval of 0 means that your class doesn't have a custom interval. Instead, the interval will be the longer of the Application Monitor interval (set using 5>1, default = 30 seconds) or the System Monitor interval (set using 2>1, default = 30 seconds).

Step 9. Use 5>4 to specify the following email settings for the Application Monitor in this namespace:

  • Use option 3 to set the outgoing email server name.
  • (Optional) Use option 5 to set the username and password used to authenticate to the outgoing email server.
  • Use option 2 to set the sender's email address.
  • Use option 4 to set the list of email recipients.
  • Use option 6 to send a test email to all recipients.
  • Once everything is configured correctly, use option 1 to enable email.
%SYS>do ^%SYSMONMGR

1) Start/Stop System Monitor
2) Set System Monitor Options
3) Configure System Monitor Classes
4) View System Monitor State
5) Manage Application Monitor
6) Manage Health Monitor
7) View System Data
8) Exit

Option? 5

1) Set Sample Interval
2) Manage Monitor Classes
3) Change Default Notification Method
4) Manage Email Options
5) Manage Alerts
6) Exit

Option? 4

1) Enable/Disable Email
2) Set Sender
3) Set Server
4) Manage Recipients
5) Set Authorization
6) Test Email
7) Exit

Option? 3

Mail server? mail.YourCompany.com

1) Enable/Disable Email
2) Set Sender
3) Set Server
4) Manage Recipients
5) Set Authorization
6) Test Email
7) Exit

Option? 2

Sender? sender@YourCompany.com

1) Enable/Disable Email
2) Set Sender
3) Set Server
4) Manage Recipients
5) Set Authorization
6) Test Email
7) Exit

Option? 4

1) List Recipients
2) Add Recipient
3) Remove Recipient
4) Exit

Option? 1
name1@YourCompany.com

1) List Recipients
2) Add Recipient
3) Remove Recipient
4) Exit

Option? 2

Email Address? name2@YourCompany.com

1) List Recipients
2) Add Recipient
3) Remove Recipient
4) Exit

Option? 

1) Enable/Disable Email
2) Set Sender
3) Set Server
4) Manage Recipients
5) Set Authorization
6) Test Email
7) Exit

Option? 6

Sending email on Mail Server mail.YourCompany.com
From: sender@YourCompany.com
To: name1@ YourCompany.com, name2@YourCompany.com

Option? 1
Email is currently OFF
Change Email setting? No => yes

Step 10. Use 5>5>1 to create an Alert, by answering the following prompts. The new Alert is automatically enabled.

  • Alert Name. You'll see this name when listing existing Alerts.
  • Application Name. This name appears as data in the SQL table along with the sample data. This allows different Alerts to share the same Application Monitor class.
  • Action. 1 (Email). Note: Option 5>3 of %SYSMONMGR allows you to set Email as the default action for all Application Monitor Alerts.
  • Raise this alert during sampling? Accept the default Yes. This causes the next 3 prompts to appear (Class, Property, and Evaluation Expression). 
  • Class. Your custom class.
  • Property. Enter ? to see a list of your sample data properties. It's common to simply select all the properties, one at a time, from your custom class (the properties marked [Internal] won't appear). Complete the list by pressing <Enter> at the prompt. The next prompt (Evaluation Expression) can only test properties you select here. The selected properties will also appear in the email notification.
  • Evaluation Expression. A condition using ObjectScript syntax, using %1 for the first property in the list from the last step, %2 for the second property, and so on. Note that values such as dates and times are evaluated while in external format, so the expression might require conversion functions such as $zdh or $zth for converting dates/times. (our example Alert uses time conversion functions).
  • Notify once only? Should the notification be sent the first time the Alert is triggered or each time the Alert is triggered?
%SYS>do ^%SYSMONMGR

1) Start/Stop System Monitor
2) Set System Monitor Options
3) Configure System Monitor Classes
4) View System Monitor State
5) Manage Application Monitor
6) Manage Health Monitor
7) View System Data
8) Exit

Option? 5

1) Set Sample Interval
2) Manage Monitor Classes
3) Change Default Notification Method
4) Manage Email Options
5) Manage Alerts
6) Exit

Option? 5

1) Create Alert
2) Edit Alert
3) List Alerts
4) Delete Alert
5) Enable/Disable Alert
6) Exit

Option? 1
Alert name? Demo
Application? %SYS => Demo
Action (0=default,1=email,2=method)? 1 => 
Raise this alert during sampling? Yes => Yes
Class? Demo.MonitorErrors
Property? ?

 Num  Name                           Activated
  1)  Earliest                       Y
  2)  ErrorCount                     Y
  3)  Latest                         Y
  4)  Name                           Y
  5)  Phone                          Y

Property? 4 Name
Property? 5 Phone
Property? 2 ErrorCount
Property? 1 Earliest
Property? 3 Latest
Property? Properties list: Name,Phone,ErrorCount,Earliest,Latest

Evaluation expression (e.g., "%1=99")? (%3>3)&&($zth(%5)>$zth(%4))
Expression expands to: If (ErrorCount>3)&&($zth(Latest)>$zth(Earliest)). OK? Yes => Yes
Notify once only? No => No

Step 11. To activate your class and your Alert, you must restart System Monitor, using 1>2 to stop it, and 1>1 to start it again. If you want, you can use option 4 to check the System Monitor State. You should see "%SYS.Monitor.AppMonSensor OK" in the list.

Step 12. If you ever need to edit your custom class, recompiling it deactivates the class and resets the (optional) Class Sample Interval override. Therefore, you must reactivate the class, reset the Class Sample Interval, and restart the System Monitor (repeat steps, 7, 8, and 11).

Congratulations, you're done!

Now you can run the provided test code to generate some data that meets the condition to trigger the alert.

%SYS>do ##class(Demo.TestErrorMonitor).Errors()
Problem with Employee: Roger Kovalev (822-825-8470)
Problem with Employee: Roger Kovalev (822-825-8470)
Problem with Employee: Roger Kovalev (822-825-8470)
Problem with Employee: Roger Kovalev (822-825-8470)
Problem with Employee: Roger Kovalev (822-825-8470)

Look at the sampled data in the SQL table, running this query in %SYS:

Look at the web page. The URL will be something like this: http://localhost:57772/csp/sys/Demo.Sample.MonitorErrors.cls.

Important notes and reminders about the provided example classes:

Demo.MonitorErrors and Demo.TestErrorMonitor must be loaded and compiled in %SYS.

The examples of the Initialize() and GetSample() methods in the documentation (http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...) use Initialize() to execute a query, and GetSample() to retrieve a row of the result set and copy the data into the sample properties for storage. The example we're using for this article takes a different approach:

  • Initialize() executes a query and loops through all the rows, filtering them so only rows with a particular error are stored in the FilteredRows multidimensional property. This method also initializes a Key property for later use by GetSample().
  • GetSample() loops through the FilteredRows (using the Key Property), retrieves each filtered row, and copies the data into the sample properties for storage.

While this article is about InterSystems IRIS, it also applies to Caché.

3 Comments
Discussion (3)1
Log in or sign up to continue
Question
· Dec 27, 2016

Using global mapping for redirecting new entries into global

Currently, namespace Alpha is configured to use database AlphaDB as its global database. How would we go about having namespace Alpha configured to use database AlphaDB for its global database except where global ^Customers(CustomerId) has a CustomerId greater than 10M, which we would like to have it redirected to database BetaDB.

In other words, ^|"AlphaDB"|Customers contains all customers between 1 and 10,000,000; and ^|"BetaDB"|Customers contains all customers greater than 10,000,000. Any help would be appreciated.

4 Comments
Discussion (4)0
Log in or sign up to continue