Thursday, July 13, 2017

Securing Kibana with an IIS Reverse Proxy and Windows Authentication

In the absence of Elastic’s for-pay X-Pack add-on package, the Elastic stack is lacking several notable features which, in my opinion, are absolutely required if it is to be used in production. One such feature is user authentication. Once you’ve configured Kibana to be accessible over the network, any Joe or Sally with network access can browse to or stumble upon your Kibana dashboard and start digging through your log data. Not great.

In this post, we’ll take a few simple steps toward providing some basic security for our Elastic front-end, while remaining free of cost and entirely in the Windows world. We’ll accomplish that by installing IIS on our Elastic server, and configuring it as a reverse proxy for Kibana, authenticated to a security group of our choosing.

Why Use a Reverse Proxy?

Since Kibana doesn’t support any sort of authentication mechanism out of the box, we have to be creative. By using the reverse proxy feature in the URL Rewrite extension for IIS, we can use IIS as a middleman between our clients and the otherwise unprotected Kibana UI. We'll restrict Kibana connections to the local server only, and set IIS as the gatekeeper for outside connections. Conveniently, this also enables us to configure SSL within IIS as we would with any other website.

Getting Started

To start, we need to ensure that Kibana is only listening for connections on localhost (127.0.0.1). We’ll do that by reviewing the Kibana configuration file and verifying with netstat. If you followed my previous guide on installing the Elastic stack, the defaults should already be set correctly for what we are doing now.

  • Locate the kibana.yml configuration file in the config directory and open it with a text editor. Unless you’ve modified these values, at the top of the file you should see server.port: 5601 and server.host: “localhost”. These are the settings that we want, as server.host: “localhost” will prevent Kibana from accepting connections from anywhere other than the local server. The server.port value doesn’t really matter as we’re only using it locally on this server, so I’ve kept the default there as well.


  • If you’re using a firewall (like Windows Firewall) on the local server or a hardware appliance on your network, you can go ahead and close port 5601 at this stage, if necessary. Nothing will be accessing the server over the network on that port once we’re done.
  • As the final check of our Kibana configuration, we can use netstat to validate that Kibana is listening on 127.0.0.1:5601, as that’s where we’ll be pointing our IIS Reverse Proxy.


Install IIS Components

To start off, we’ll need to install the Web Server role along with URL Authorization, Windows Authentication, and Management Tools. You can accomplish this manually via the Add Roles and Features Wizard in Server Manager or via Powershell.


Install-WindowsFeature Web-Server, Web-Url-Auth, Web-Windows-Auth -IncludeManagementTools

With the required features installed, it’s time to configure our reverse proxy.

Configure the IIS Reverse Proxy

Rather than trying to reinvent the wheel, I followed parts one and two of this fantastic guide on Microsoft Blogs for the reverse proxy setup, which I’ll be recapping below. The guide contains a lot more detail on the why and how, if you’re interested. I did not follow part 3 of the guide as it was not necessary.


  • Launch IIS and select the website you'll be configuring as the reverse proxy. Click on the URL Rewrite feature in the center panel.


  • Then, Add Rule(s)... in the Actions panel on the right.


  • In the Add Rule(s) dialog, select Reverse Proxy and click OK.


  • Click OK again to enable proxy functionality within Application Request Routing.



  • In the Add Reverse Proxy Rules dialog under Inbound Rules, we’ll give it our Kibana URL (localhost:5601) as the location where requests will be forwarded. We also want to enable Rewriting of domain names under Outbound Rules and populate the external URL for our server under the To: field. In this case the external URL will be whatever our clients on the network will type into their browsers to access Kibana. I’m just using the server name in my lab environment. Click OK to complete the dialog.

Now we have the basic reverse proxy routing in place, but we’re not quite done yet. If we try to access Kibana via IIS at this stage, we’re greeted with an unfriendly 500.52 error.


What’s happening is that Kibana is using HTTP compression when returning results to IIS, and the URL Rewrite module can’t modify the response when it's compressed. The workaround for this is to configure IIS to tell Kibana not to return compressed responses.

  • With our website selected let’s go back to the URL Rewrite module. This time we’ll choose View Server Variables…


  • On the Allowed Server Variables screen, choose Add… to add a new server variable called HTTP_ACCEPT_ENCODING, and click OK. Follow the same process to add a second variable called HTTP_X_ORIGINAL_ACCEPT_ENCODING.

  • Next, go back to URL Rewrite rules and select the inbound rule. Then click Edit…


  • On the Edit Inbound Rule screen, expand the Server Variables section and click Add… Select the HTTP_X_ORIGINAL_ACCEPT_ENCODING variable that we created earlier from the Server variable name: drop-down box. Under Value: type {HTTP_ACCEPT_ENCODING}. Be sure to include the curly braces so the rule knows to use the value of that variable. Click OK.

  • Click Add… again to add another server variable. This time select HTTP_ACCEPT_ENCODING from the drop down box, and type any text value into the Value: field. What we need to do here is set the value of this variable to be empty, but this field won’t accept a blank value so we’re giving it any text value so we can save the variable, and we’ll update the value in the next step. I typed “123” as my value.




  • With both variables set, click Apply in the Actions panel.



  • Now we need to replace our arbitrary text value (“123” in my case) with a blank. This is done in our website’s web.config file. Since I’m using the Default Web Site, that’s located in C:\inetpub\wwwroot. Open the web.config file in a text editor and find the text value that you entered. Select the value between the quotes and delete it, leaving just the quotes. Save the file.
Before:

After:

That addresses the inbound portion of our configuration, now we need to address outbound traffic.

  • Under URL Rewrite, click Add Rule(s)... again, this time selecting Blank rule under Outbound rules.


  • We’ll name our new rule RestoreAcceptEncoding, and select <Create New Precondition…> from the drop-down menu. On the Add Precondition screen, provide the name NeedsRestoringAcceptEncoding and ensure Regular Expressions is selected from the Using: drop-down menu.


  • Click Add… to add a new condition. For the Condition input: type {HTTP_X_ORIGINAL_ACCEPT_ENCODING}, again making sure to include the curly braces. Under pattern, type ‘.+’. Click OK. Click OK again to close the Add Precondition dialog.




  • Still under the Edit Outbound Rule screen, find the Match section and set the Matching scope: to Server Variable. Type HTTP_ACCEPT_ENCODING as the Variable name:. For the pattern, type ‘^(.*)’.



  • Lastly under the Action section, ensure that Action type: is set to Rewrite. For the Value: type {HTTP_X_ORIGINAL_ACCEPT_ENCODING}, again being sure to include the curly braces. Then, click Apply.



If everything has gone according to plan, reverse proxying from IIS to Kibana should now be working. If you type http://localhost into a web browser on the Elastic server, you should see Kibana being served via IIS over port 80.

Securing Kibana

And now, finally, we can do what we set out to do: Add some security to Kibana so it isn’t openly accessible to anyone on our network.

Configure SSL Certificate

In order to ensure that we’re not passing credentials over the network in the clear, we need to configure IIS with an SSL certificate and bind it to our website. If you want to generate a certificate for this server from your internal CA or a public CA, that’s perfectly fine. I’m going to use a self-signed certificate for this lab.


  • Select the server name in the left-hand panel, and then choose the Server Certificates option.


  • We then choose Create Self-Signed Certificate… from the Actions pane.



  • Type the name you want to use for referencing this certificate. I just used the server name. Click OK.



  • With the certificate created, we can go ahead and bind it to our website. To do that, expand the server in IIS and select the website.



  • Then, select Bindings… from the Actions pane.



  • On the Site Bindings screen, choose Add…



  • On the Add Site Binding screen, choose HTTPS as the type and select your certificate from the SSL certificate: drop-down menu.



  • Click OK again to add the site binding, and then click Close to close the Site Bindings screen. Now we’ll be able to access our website over HTTPS.

Configuring User Authentication

The final step for this guide is to enable user authentication for our Kibana proxy. What I’ve elected to do in my lab environment is configure an Active Directory group with members that I’ve chosen to grant access to Kibana. This same process could also be done with a local Windows group, or individually selected user accounts if desired.

From my lab’s domain controller, I’ve created a security group called Role-G-ElasticAdmins. The specific group name isn't important. This is the naming convention that I use for denoting that this is a Global security group and it is for granting a particular business Role to a set of users. In this case, the only user with permission to access Kibana will be the SMBAdmin user.



  • Back on our Elastic server in IIS, we need to select our website and choose the Authentication option.



  • Within Authentication, we need to set Anonymous Authentication to Disabled, and set Windows Authentication to Enabled.



  • Back to the main IIS screen, we’ll now select Authorization Rules.



  • We need to delete the Allow -> All Users rule that is created by default. Then, click Add Allow Rule… in the Actions pane.



  • On the Add Allow Authorization Rule dialog, we want to select the radio button for Specified roles or user groups:, and type the name of the group for which we’re allowing access. Then, click OK.


That concludes the configuration. Let’s test it out.


  • Open a web browser on the Elastic server and type https://localhost. If all has gone according to plan, you should be prompted to enter credentials (you may have to bypass the certificate warning if you used a self-signed certificate like I did).





  • After entering your credentials, you should be greeted with the familiar Kibana interface. Take note of the address bar to ensure that you’ve accessed the site over HTTPS.


We’re now successfully proxying Kibana’s unsecured web interface on port 5601 through IIS, secured with HTTPS encryption and Windows authentication. To make the secure interface available over the network you simply need to permit HTTPS/TCP 443 through your firewall(s) as you would with any other website, and use a web browser on your client machine to browse to it by DNS name or IP address.

7 comments:

  1. From the bottom of my heart , thank you for this post...

    ReplyDelete
  2. Thanks a lot for your Great article.

    ReplyDelete
  3. Great post, explained all steps, kudo

    ReplyDelete
  4. From the bottom of mine and my team's heart, a greatness personified thank you! you have saved my job during the covid times.

    ReplyDelete
  5. very good instructions. This helped me a lot, thanks a bunch !

    ReplyDelete