Build a Mulesoft API Step By Step - Part 2
This blog will guide you to secure you Mulesoft API that you built earler step by step.
Step-By-Step, Mulesoft, API, API Gateway, Microservice, Beginners, API Security
In my previous blog, Build a Mulesoft API Step By Step - Part 1 we went through a step by step process to build a MuleSoft API from the scratch. We saw RAML, Anypoint Studio, Anypoint Platform, and a lot of new tools. Now let us move on to the next step which is very important from an API Perspective. Security and Gateway. We will see how to secure the API, how to publish the API into the Exchange and How to give access to this API.
- Access to keytool, which should be a part of Java.
- Access to Cloudhub Anypoint Platform (Should have from Part 1)
I will refer from Step 5 as in our previous example we completed till Step 4. So, without any further ado, let us get started securing our API that we built.
Step 5: Make our API secure.
To help us ensure data confidentiality, we can deploy our Mule app using an HTTPS-based service. As a first step, we will create use keytool to create the secure key for our application.
Let us generate a keystore.jks file using the JDK keytool utility on the command line. We must also specify the hostname on the command line to generate a self-signed certificate. For example, the following command with hostname SAN=DNS:localhost,IP:127.0.0.1 creates a keystore.jks file.
We should open Command Prompt of Shell on any of the folder in our computer like /users/<username>/keys or c:\users\<username>\keys if we are on a windows and put in the following commands.
keytool -genkeypair -keystore keystore.jks -dname "CN=<commonName>, OU=<OrgUnit>, O=<Organization>, L=<City>, ST=<State>, C=<Country>" -keypass <somePassword> -storepass <somePassword>-keyalg RSA -sigalg SHA1withRSA -keysize 2048 -alias <commonName> -ext SAN=DNS:localhost,IP:127.0.0.1 -validity 9999
I for example used this:
keytool -genkeypair -keystore keystore.jks -dname "CN=wedointegration, OU=integration, O=wedointegration, L=Irvine, ST=California, C=US" -keypass password123 -storepass password123 -keyalg RSA -sigalg SHA1withRSA -keysize 2048 -alias wedointegration -ext SAN=DNS:localhost,IP:127.0.0.1 -validity 9999 We should drag and drop this file into the /src/main/resources folder in our anypoint studio and when it asks and click Copy files.
We should drag and drop this file into the /src/main/resources folder in our anypoint studio and when it asks and click Copy files.
Once we have copied the file into our studio, the explorer would look like this.
I use the tool KeyStore Explorer for opening or checking the keys and certificates
After creating certificate and the key, it is time to put this into our project. So, let us head back to the Anypoint Studio, go to the file called global.xml, Double Click on the HTTP Listener and change the following.
- Protocol: HTTPS
- Port: 8082
- Go to the second tab called TLS
- Select TLS Configuration: Edit inline.
Fill up the Key Store configuration as below:
Note that we do not have to fill the Trust Store configuration. That would be needed only for 2 Way SSL Communication. Once completed, our global file should have this in the HTTP Listener configuration:
<http:listener-config name="api-httpListenerConfig"> <http:listener-connection host="0.0.0.0" port="8082" protocol="HTTPS"> <tls:context > <tls:key-store type="jks" path="keystore.jks" alias="wedointegration" keyPassword="password123" password="password123" /> </tls:context> </http:listener-connection> </http:listener-config>
Now if we run the application in studio, we should see, that http://localhost:8081/console is no more accessible.
We would have to access https://localhost:8082/console . However, because our certificate being self-signed, we might get some warning in the internet browser.
I use Firefox to pass through that warning and I am able to access this.
Step 7: Put the API into Anypoint Exchange
Now that we have our API up and running with HTTPS, let us move to make our API more discoverable. We would use Anypoint Exchange to deploy our API so that it is discoverable both by users in our organization or by public.
To do this, we should go to Anypoint Platform / Cloudhub, I hope we still remember our user id and password that we created last week. We have to click on the Left Menu, click on Design Center and then select our API, in my case Mule Demo Database API.
On the left top, there is a button called Publish. That should do our trick. Let us click on the publish button. It says publish to Exchange. We will click that button and fill in the details. Most of the details will already be in there.
Once complete we can go to the exchange and our API should be present over there with all the necessary endpoints.
We need to click on the Share Button and go to the public Tab. This would let us deploy our application to public portal.
If we go back to the exchange, we should see our service in the Assets list within our Organization.
Our application should also be visible in the Public Portal which you can navigate from the Left-Hand Menu of the Exchange.
Step 8: Set up API Management using Mule API Gateway
Notice in the above step, that at this point only Mocking service is active for our API. It is not connected to any of the real application. Also, we would have to connect our API to the API Gateway. Let us fix that. For this, we should click on the Left Menu and go to API Manager. We would have to click Manage API from Exchange and select the API we have just published into the Exchange.
Next, we have to select your API name, Asset type as RAML/OAS. Note that we would select Basic Endpoint and not Endpoint with Proxy in Managing Type and select Mule Application and not Non-Mule application. Also, we should check the Mule version option because our Mule application is above Mule 4.
Once we save this, it should create the API with an API Instance. In my case as you see below it is a number 16203283. We would need this number to connect our application to the API using Auto Discovery.
If we click on the Back Button, we can see that our API is unregistered and has 0 client at this time.
Now, in order to connect our Application to the API instance, we would have to go back to our studio and add an Auto Discovery Global Element. We will fill it up with the API Id and the main Flow Name for API. In most case, it will be <api>-main.
Once complete our global.xml should be like this:
<?xml version="1.0" encoding="UTF-8"?> <mule xmlns:api-gateway="http://www.mulesoft.org/schema/mule/api-gateway" xmlns:tls="http://www.mulesoft.org/schema/mule/tls" xmlns:db="http://www.mulesoft.org/schema/mule/db" xmlns:mongo="http://www.mulesoft.org/schema/mule/mongo" xmlns:apikit="http://www.mulesoft.org/schema/mule/mule-apikit" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.mulesoft.org/schema/mule/mule-apikit http://www.mulesoft.org/schema/mule/mule-apikit/current/mule-apikit.xsd http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd http://www.mulesoft.org/schema/mule/mongo http://www.mulesoft.org/schema/mule/mongo/current/mule-mongo.xsd http://www.mulesoft.org/schema/mule/db http://www.mulesoft.org/schema/mule/db/current/mule-db.xsd http://www.mulesoft.org/schema/mule/tls http://www.mulesoft.org/schema/mule/tls/current/mule-tls.xsd http://www.mulesoft.org/schema/mule/api-gateway http://www.mulesoft.org/schema/mule/api-gateway/current/mule-api-gateway.xsd"> <http:listener-config name="api-httpListenerConfig"> <http:listener-connection host="0.0.0.0" port="8082" protocol="HTTPS"> <tls:context > <tls:key-store type="jks" path="keystore.jks" alias="wedointegration" keyPassword="password123" password="password123" /> </tls:context> </http:listener-connection> </http:listener-config> <apikit:config name="api-config" api="api.raml" outboundHeadersMapName="outboundHeaders" httpStatusVarName="httpStatus" /> <db:config name="Database_Config" doc:name="Database Config" doc:id="42b3d660-c98f-481f-a478-7b9f57978bfd" > <db:my-sql-connection host="220.127.116.11" port="3306" user="anupam" password="anupam" database="anupamus_hrtest" /> </db:config> <api-gateway:autodiscovery apiId="16203283" ignoreBasePath="true" doc:name="API Autodiscovery" doc:id="1d09e146-c3e0-4c36-b95d-0e12b3628941" flowRef="api-main" /> </mule>
Now, we would deploy and overwrite the same application that we deployed last time. But before that, we will connect our Anypoint Platform Client Id and Client Secret into the Anypoint Studio. To do this, first we would first go to Anypoint Platform and go to Left Menu and select Access Management. Next we would have to Click Environments and select the environment we want to deploy our application and then copy the Client Id and Client Secret given here.
Then we should go to our Anypoint Studio, Click on the preference and search for API Manager. Fill up the Client Id and Secret here and we can click Validate to confirm.
This should deploy the application into Cloudhub runtime. If we go to the deployment and go to the console using the end point http://mule-demo-database-app-sbox.us-e2.cloudhub.io/console/, like we did last time, we would see 502 Bad Gateway Error. This should be fine because you remember, we have changed our application to HTTPS. So instead point to the https console URL using https://mule-demo-database-app-sbox.us-e2.cloudhub.io/console/ and voila we have access to the endpoint.
Now if we go to the API Manager, we should see the API Endpoint that we defined is now Active.
We can also go to the Anypoint Exchange and click on our Asset. We should see our Sandbox instance showing up in the Asset version.
Now our application is up and running with HTTPs Service and is exposed using Public Portal.
Step 9: Secure our API.
Even though our Application is secure using HTTPS, anyone who knows the endpoint can access our API. This is not ideal because, you would need to put Authorization so that only valid client can access our application. As you can see below, there is not a valid client id or secret that I am using to call my API.
This can be done in various ways, but for us, we will simply use client authentication. So, let us secure our API further.
We have to go to the Anypoint Platform Click on API Manager and Select our API. Next on the left-hand side we should click on Policies and Select Apply new Policy. In the list of policy select Client ID enforcement. Select Configure Policy and then Apply with the default options and the Policy will be deployed in our application.
Also, we will set up an SLA Tier so that we do not face Denial of Service. To Do this we should click on the SLA Tiers in Left-Hand Menu and click Add SLA Tier. We will create one SLA Tier but here you can have multiple tier like Gold, Silver etc.
Now if we use the same endpoint, we would see that it will give us a 401: Unauthorized error.
Finally let us set up some Valid Client to consume our API. This should be done so that the user can have access to our API but can only call certain number of times.
To do this, we should go to Exchange and click on our Application. Now click on the Right dotted menu and select Request Access.
In the Application, we should create a new Application and fill up the name. Other fields are optional and is not needed. Finally select the SLA Tier that was created earlier, and this should give us our New Application Client ID and Secret. If we now use this Client from our postman, we should be able to access the API.
This brings to the end of this blog. Sorry, that the blog might look a bit lengthy however, I put as much details as possible. Do try this and let me know if you face any challenges.
Leave a Comment:
Please login to post comment into this page.