I have in the former two “REST easy with kbmMW” articles shown, how to make a REST server with kbmMW, and how to use that REST server to easily return and store data from/to a database all in less than 30 lines of real code.
This blog post will center around how to ensure that communication with the server stays protected using SSL (Secure Socket Layer). In other words, how to make the REST server talk HTTPS rather than HTTP.
There are multiple ways to secure a kbmMW based application server with SSL, but I will focus on one simple way to do it using OpenSSL.
First we should create a certificate we can use. SSL certificates can be purchased from various places where they sell official certificates, or you can create one that is self signed. A self signed certificate is generally as secure as anything else, but it is not automatically trusted by other servers, which may flag your certificate as unsafe.
For inhouse use however, a self signed certificate is usually fine.
There are many places on the internet explaining the procedure of how to create SSL certificates using OpenSSL. You can click here for one of them.
After you have gotten access to either a bought or a homemade certificate, we can continue integrating it with the REST server.
Add a TIdServerIOHandlerSSLOpenSSL component to the main form (Unit7).
You will need to set it’s SSLOptions properties like this:
- SSLOptions.Mode must be sslmServer
- Of the supported SSLOptions.SSLVersions I will suggest enabling only sslvTLSv1_2
Leave the remaining properties as is at the moment.
Now double click the OnGetPassword event handler of the IdServerIOHandlerSSLOpenSSL1 component to write some code in an event handler.
procedure TForm7.IdServerIOHandlerSSLOpenSSL1GetPassword(var Password: string); begin Password:='yourCertificatePassword'; end;
The code going in the event should simply return the password you used when you created the private part of the certificate. It is required by OpenSSL to have access to this, to be able to use your private key.
Despite the above example, I would suggest you, not to hardcode the password inside your application, but rather read it from an external configuration file, of security reasons, in case your REST server executable got leaked elsewhere.
But for the current sample, with a homemade sample certificate, we can do with the hardcoded password.
Next we need to tell the kbmMW server side transport to let the OpenSSL code handle the main communication of our data. One part of that is to write an event handler for the OnConnect event of the kbmMWTCPIPIndyServerTransport1 component.
procedure TForm7.kbmMWTCPIPIndyServerTransport1Connect(AContext: TIdContext); begin if AContext.Connection.IOHandler is TIdSSLIOHandlerSocketBase then TIdSSLIOHandlerSocketBase(AContext.Connection.IOHandler). PassThrough:=false; end;
To make the compiler happy, we also need to add IdContext to the interface sections uses clause.
uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, kbmMWCustomTransport, kbmMWServer, kbmMWTCPIPIndyServerTransport, kbmMWRESTTransStream, kbmMWCustomConnectionPool, kbmMWCustomSQLMetaData, kbmMWSQLiteMetaData, kbmMWSQLite, kbmMWORM, IdBaseComponent, IdComponent, IdServerIOHandler, IdSSL, IdSSLOpenSSL, IdContext;
And finally we need to link the SSL component to the server transport, and make the certificate files available to OpenSSL.
We do that by writing the following piece of code, for example in the OnCreate event handler of the main form (containing the kbmMW Indy server transport).
procedure TForm7.FormCreate(Sender: TObject); begin ORM:=TkbmMWORM.Create(kbmMWSQLiteConnectionPool1); ORM.CreateTable(TContact); // Make sure that the server is now listening on port 443 which is // the default port for HTTPS communication. kbmMWTCPIPIndyServerTransport1.Bindings.Items.Port:=443; IdServerIOHandlerSSLOpenSSL1.SSLOptions.CertFile:='YourCertificateFile.cer'; IdServerIOHandlerSSLOpenSSL1.SSLOptions.KeyFile:='YourPrivateKeyFile.key'; // Optional root certificate file if purchased certificate or empty if self signed. IdServerIOHandlerSSLOpenSSL1.SSLOptions.RootCertFile:=''; kbmMWTCPIPIndyServerTransport1.IdTCPServer.IOHandler:=IdServerIOHandlerSSLOpenSSL1; kbmMWServer1.AutoRegisterServices; kbmMWServer1.Active:=true; end;
Make sure that the files YourCertificateFile.cer and YourPrivateKeyFile.key is available to the REST executable when it runs, but also make sure that they are not accessible for download for anyone else. It’s of high importance that those files (along with your private key password) is kept a secret for anybody else.
As you may notice, we change the port number for the first binding from 80 to 443, since we want to support the standard HTTPS port. You may also notice that it is possible to provide a Root certificate file. The Root certificate file typically contains a chain of public certificates that can be used by OpenSSL and browsers to verify that your own certificate is a valid and trusted certificate generated by the entity from which you have the root certificate.
Self signed certificates usually do not need any root certificate files.
Now your REST server is ready serving clients securely over SSL.