Warning |
---|
This page is work in progress! |
In contrast to the usual one-way SSL authentication where a client verifies the identity of the server, in mutual SSL the server validates the identity of the client so that both parties trust each other. This builds a system that has a very tight security and avoids any requests made to the client to provide the username/password, as long as the server is aware of the certificates that belong to the client.
This section explains how to APIs in WSO2 API Manager can be secured using mutual SSL in addition to OAuth2.
Table of Contents |
---|
Enable securing APIs with mutual SSL
Follow the steps below to enable this feature in WSO2 API Manager.
Create the
AM_API_CLIENT_CERTIFICATE
table in the APIM DB using the appropriate script given below. Note that the database name will depend on the databases present in your environment.Localtabgroup Localtab active true id H2 title H2 Code Block CREATE TABLE IF NOT EXISTS `AM_API_CLIENT_CERTIFICATE` ( `TENANT_ID` INT(11) NOT NULL, `ALIAS` VARCHAR(45) NOT NULL, `API_ID` INTEGER NOT NULL, `CERTIFICATE` BLOB NOT NULL, `REMOVED` BOOLEAN NOT NULL DEFAULT 0, `TIER_NAME` VARCHAR (512), FOREIGN KEY (API_ID) REFERENCES AM_API (API_ID) ON DELETE CASCADE ON UPDATE CASCADE, PRIMARY KEY (`ALIAS`,`TENANT_ID`, `REMOVED`) );
Localtab id MSSQL title MSSQL Code Block IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[AM_API_CLIENT_CERTIFICATE]') AND TYPE IN (N'U')) CREATE TABLE AM_API_CLIENT_CERTIFICATE ( TENANT_ID INTEGER NOT NULL, ALIAS VARCHAR(45) NOT NULL, API_ID INTEGER NOT NULL, CERTIFICATE VARBINARY(MAX) NOT NULL, REMOVED BIT NOT NULL DEFAULT 0, TIER_NAME VARCHAR(512), PRIMARY KEY (ALIAS, TENANT_ID, REMOVED), FOREIGN KEY (API_ID) REFERENCES AM_API(API_ID) ON DELETE CASCADE );
Localtab id MySQL title MySQL Code Block CREATE TABLE IF NOT EXISTS `AM_API_CLIENT_CERTIFICATE` ( `TENANT_ID` INT(11) NOT NULL, `ALIAS` VARCHAR(45) NOT NULL, `API_ID` INTEGER NOT NULL, `CERTIFICATE` BLOB NOT NULL, `REMOVED` BOOLEAN NOT NULL DEFAULT 0, `TIER_NAME` VARCHAR (512), FOREIGN KEY (API_ID) REFERENCES AM_API (API_ID) ON DELETE CASCADE ON UPDATE CASCADE, PRIMARY KEY (`ALIAS`, `TENANT_ID`, `REMOVED`) ) ENGINE=InnoDB;
Localtab id MySQLC title MySQL Cluster Code Block CREATE TABLE IF NOT EXISTS `AM_API_CLIENT_CERTIFICATE` ( `TENANT_ID` INT(11) NOT NULL, `ALIAS` VARCHAR(45) NOT NULL, `API_ID` INTEGER NOT NULL, `CERTIFICATE` BLOB NOT NULL, `REMOVED` BOOLEAN NOT NULL DEFAULT 0, `TIER_NAME` VARCHAR (512), FOREIGN KEY (API_ID) REFERENCES AM_API (API_ID) ON DELETE CASCADE, PRIMARY KEY (`ALIAS`, `TENANT_ID`, `REMOVED`) ) ENGINE=NDB;
Localtab id Oracle title Oracle Code Block CREATE TABLE AM_API_CLIENT_CERTIFICATE ( TENANT_ID INTEGER NOT NULL, ALIAS VARCHAR2(45) NOT NULL, API_ID INTEGER NOT NULL, CERTIFICATE BLOB NOT NULL, REMOVED INTEGER DEFAULT 0 NOT NULL, TIER_NAME VARCHAR2 (512), FOREIGN KEY (API_ID) REFERENCES AM_API (API_ID) ON DELETE CASCADE, PRIMARY KEY (ALIAS, TENANT_ID, REMOVED) ) /
Localtab id OracleR title Oracle_rac Code Block CREATE TABLE AM_API_CLIENT_CERTIFICATE ( TENANT_ID INTEGER NOT NULL, ALIAS VARCHAR2(45) NOT NULL, API_ID INTEGER NOT NULL, CERTIFICATE BLOB NOT NULL, REMOVED INTEGER DEFAULT 0 NOT NULL, TIER_NAME VARCHAR2(512), FOREIGN KEY (API_ID) REFERENCES AM_API (API_ID) ON DELETE CASCADE, PRIMARY KEY (ALIAS, TENANT_ID, REMOVED) ) /
Localtab id PostgreSQL title PostgreSQL Code Block DROP TABLE IF EXISTS AM_API_CLIENT_CERTIFICATE; CREATE TABLE AM_API_CLIENT_CERTIFICATE ( TENANT_ID INTEGER NOT NULL, ALIAS VARCHAR(45) NOT NULL, API_ID INTEGER NOT NULL, CERTIFICATE BYTEA NOT NULL, REMOVED BOOLEAN NOT NULL DEFAULT '0', TIER_NAME VARCHAR(512), FOREIGN KEY (API_ID) REFERENCES AM_API (API_ID) ON DELETE CASCADE, PRIMARY KEY (ALIAS, TENANT_ID, REMOVED) );
Localtab id DB2 title DB2 Code Block CREATE TABLE AM_API_CLIENT_CERTIFICATE ( TENANT_ID INT NOT NULL, ALIAS VARCHAR(45) NOT NULL, API_ID INTEGER NOT NULL, CERTIFICATE BLOB NOT NULL, REMOVED SMALLINT NOT NULL DEFAULT 0, TIER_NAME VARCHAR (512), FOREIGN KEY (API_ID) REFERENCES AM_API (API_ID) ON DELETE CASCADE ON UPDATE CASCADE, PRIMARY KEY (ALIAS, TENANT_ID, REMOVED) )/
Open the <API-M_HOME>/repository/conf/axis2/axis2.xml file. Locate the
transportReceiver
for https as shown below.Code Block <transportReceiver name="https" class="org.apache.synapse.transport.passthru.PassThroughHttpSSLListener">
Change the class name to
org.apache.synapse.transport.passthru.PassThroughHttpMultiSSLListener
. The sample is given below.Code Block <transportReceiver name="https" class="org.apache.synapse.transport.passthru.PassThroughHttpMultiSSLListener">
Add the following parameters under
transportReceiver
similar to the sample given below.Code Block <parameter name="dynamicSSLProfilesConfig"> <filePath>repository/resources/security/listenerprofiles.xml</filePath> <fileReadInterval>600000</fileReadInterval> </parameter> <parameter name="SSLVerifyClient">optional</parameter>
The
dynamicSSLProfilesConfig
specifies the file read to load the dynamic SSL profile and the time interval in which it will be read.
Note that if the fileReadInterval parameter is set to 600000, it will take at least 10 minutes for the gateway to accept a newly added client certificate, since no files will be read during the set interval.Expand title Expand to see the transportReceiver segment after the changes mentioned above have been made... Code Block <transportReceiver name="https" class="org.apache.synapse.transport.passthru.PassThroughHttpMultiSSLListener"> <parameter name="port" locked="false">8243</parameter> <parameter name="non-blocking" locked="false">true</parameter> <!--parameter name="bind-address" locked="false">hostname or IP address</parameter--> <!--parameter name="WSDLEPRPrefix" locked="false">https://apachehost:port/somepath</parameter--> <parameter name="httpGetProcessor" locked="false">org.wso2.carbon.mediation.transport.handlers.PassThroughNHttpGetProcessor</parameter> <parameter name="keystore" locked="false"> <KeyStore> <Location>repository/resources/security/wso2carbon.jks</Location> <Type>JKS</Type> <Password>wso2carbon</Password> <KeyPassword>wso2carbon</KeyPassword> </KeyStore> </parameter> <parameter name="truststore" locked="false"> <TrustStore> <Location>repository/resources/security/client-truststore.jks</Location> <Type>JKS</Type> <Password>wso2carbon</Password> </TrustStore> </parameter> <!-- ============================================== --> <!-- Configuration for Listener Dynamic SSL Profile loading. --> <!-- Configured for 10 mins. --> <!-- ============================================== --> <parameter name="dynamicSSLProfilesConfig"> <filePath>repository/resources/security/listenerprofiles.xml</filePath> <fileReadInterval>600000</fileReadInterval> </parameter> <parameter name="SSLVerifyClient">optional</parameter> <!--<parameter name="SSLVerifyClient">require</parameter> supports optional|require or defaults to none --> </transportReceiver>
Copy the code given below to create the
listenerprofiles.xml
file in the<API-M_HOME>/repository/resources/security
directory.Code Block <?xml version="1.0" encoding="ISO-8859-1"?> <parameter name="SSLProfiles"> <profile> <bindAddress>0.0.0.0</bindAddress> <KeyStore> <Location>repository/resources/security/wso2carbon.jks</Location> <Type>JKS</Type> <Password>wso2carbon</Password> <KeyPassword>wso2carbon</KeyPassword> </KeyStore> <TrustStore> <Location>repository/resources/security/client-truststore.jks</Location> <Type>JKS</Type> <Password>wso2carbon</Password> </TrustStore> <SSLVerifyClient>optional</SSLVerifyClient> </profile> </parameter>
Note The
<API-M_HOME>/repository/resources/security
directory can be changed according to the file path you have configured in Step 2.Open the
<API-M_HOME>/repository/conf/api-manager.xml
file. Set theEnableMTLSForAPIs
parameter totrue
.Code Block <APIManager> ... <EnableMTLSForAPIs>true</EnableMTLSForAPIs>
Restart the server.
Create an API