Hiding a sitemap from non-system-admin users? OH 1.x

Tags: #<Tag:0x00007f617bd17610> #<Tag:0x00007f617bd17548> #<Tag:0x00007f617bd17458>

I have several sitemaps for different users, with different functionality needs. I also have a “master” sitemap that is very complex and has lots of settings that non-admin users should never see or touch.

How do I hide the master sitemap from regular users, while still having easy access to it myself, eg from my tablet device?

Ideally I would like OpenHAB to accept multiple http ports to bind so that sitemaps 1 and 2 can be on http port 8080, while sitemap 3 is on port 9040, sitemap 4 on port nnnn where “n” is any available tcp port.

Is this possible, and/or how else can I accomplish partitioning between different users?

Note, I am aware that you can set a mobile app to default to a specific sitemap, but it does not prevent someone from fishing around and easily locating all other sitemaps. In some network-down scenarios I have also seen the tablet app request the user to re-select the default sitemap. What I want is to make it impossible for a given device (or IP /MAC address) to access system-admin-type sitemaps.


Updated:

TL;DR – functionality achieved, scroll down for a solution.

This is not currently possible. I am hopeful that when the new security/roles system is implemented in OH2 this sort of thing will be possible however.

That is what I suspected. Thanks for the feedback. I am looking into using a reverse HTTP proxy such as NGINX to implement per-IP-address blocking. Eg should be possible to tell NGINX, “IPaddresses A thru F sees only /user_sitemap. IP addresses R thru W see /user_sitemap and /admin_sitemap.”

Hopefully the HABdroid and iOS apps will play nicely with this setup.

Won’t be attempting to make this work with SSL or user/pass auth as it will be for the internal LAN only.

Will add on to this thread when I’ve gotten it working.

1 Like

I’ve made good progress on this using the current version of nginx light, but am hung up on an issue that is possibly just nginx-related, but perhaps in may involve OpenHAB as well so I’m putting it out here.

System config: OH 1.8.3 / Ubuntu 16.0.4 LTS, default apache2 conf, everything working smoothly without nginx.

Installed nginx-light 1.10.0 via apt-get, set up config file to listen on port 7090 & reverse proxy for the OpenHAB server on the same server (i.e. localhost:8080.) With a wide-open nginx configuration (no access restrictions attempted, just straight-thru reverse proxying all requests,) everything is hunky-dory and access to OH sitemaps works normally on any device pointed to the alternate :7090 nginx listening port. (ipad, android, web browser.)

When I use an nginx location { } directive to attempt to block access to a specific sitemap (and only that sitemap), I can successfully block access by IP (or whatever other Nginx allow/deny method I wish.) So, access-denial is working fine as well:

From /var/log/nginx/error.log:

2017/01/17 13:00:12 [error] 8486#0: *4 access forbidden by rule, client: 192.168.1.143, server: 127.0.0.1, request: "GET /rest/sitemaps/bach2dop/bach2dop HTTP/1.1", host: "192.168.1.122:7090"

The problem I’m having is that, when the location { } directive is enabled (i.e. defined in the nginx default conf file), and a host is ALLOWED access to the location, nginx spits back the following error:

From /var/log/nginx/error.log:

2017/01/17 13:00:31 [error] 8565#0: *1 open() "/rest/sitemaps/bach2dop/bach2dop" failed (2: No such file or directory), client: 192.168.1.143, server: 127.0.0.1, request: "GET /rest/sitemaps/bach2dop/bach2dop HTTP/1.1", host: "192.168.1.122:7090"

Here’s the relevant section of the nginx conf file I’m using:

##    nginx/1.10.0 (Ubuntu) reverse-proxy configuration to filter requests sent to OpenHAB.

server {
        listen              7090;
        server_name         mydomain_or_myip;


        location / {
                proxy_pass                            http://localhost:8080/;
                proxy_buffering                       off;
                proxy_set_header Host                 $http_host;
                proxy_set_header X-Real-IP            $remote_addr;
                proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto    $scheme;
        }


###  This specific sitemap ("bach2dop.sitemap")  I want to DENY to all IP addresses on the LAN, 
###   EXCEPT for one authorized IP address:

location  ~   /rest\/sitemaps\/bach2dop*.*   {
           satisfy any;
           allow 192.168.1.143;
           deny all;
                proxy_buffering                       off;
                proxy_set_header Host                 $http_host;
                proxy_set_header X-Real-IP            $remote_addr;
                proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto    $scheme;
        }
}

I have tried many different variations of the location ~ regexp match and there is no difference in behavior; I think I’m missing some other nginx config option, or possible I need to tweak something outside of nginx, i.e. in OpenHAB??

Hi @globramma, from what I can see, the bottom location block is working as you’ve told it to. On the instance someone from 192.168.1.143 connects, they are passed through to the /rest/sitemaps/bach2dop location, the problem here is that NGINX doesn’t understand what that location is, so it assumes a file system. You still need to use proxy_pass.

                proxy_pass                            http://localhost:8080/;

This might still not work, but you should see some behavioural changes. I suspect that if it doesn’t you’ll need to adjust or rewrite the location when the client connects.

Your suggestion is helpful but needs one small change:

   proxy_pass                            http://localhost:8080/;

does not work:

user@MyOpenHAB:/etc/nginx/sites-enabled$ sudo nginx -t

nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression, or
inside named location, or inside "if" statement, or inside "limit_except" block in /etc/nginx/sites-
enabled/default:91

Instead, this works fine:

    proxy_pass                            http://localhost:8080;

(without the trailing slash).

I was helped to this understanding by a post on Serverfault: “Nginx regex location doesn’t work with proxy pass.”.

In summary, here is a complete and functional pair of nginx location definitions that accomplish my original intention. Thanks for your assistance.

####  2017-01-16 CUSTOMIZATION for OPENHAB
##    Reverse-proxy configuration to filter requests sent to OpenHAB.
###   First Location definition transparently proxies all requests from OH clients (web or mobile app)
###   Second Location definition filters requests for a specific sitemap, & applies access control rules.
###  

# The nginx proxy server listens on port 7090. (Set to whatever available port you wish.)

server {
	listen             7090;
	server_name         mydomain_or_myip;
	
	## "location /" matches all requests

	location / {
	
	## the proxy_pass line should be the port your OpenHAB server listens on. (Default is 8080.)	
	## If nginx & OpenHAB are on different physical or virtual servers, replace "localhost"
	## with the FQDN, such as:  myserver.mydomain.com

     	proxy_pass                            http://localhost:8080/;
		proxy_buffering                       off;
		proxy_set_header Host                 $http_host;
		proxy_set_header X-Real-IP            $remote_addr;
		proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto    $scheme;
	}


	location  ~   /rest/sitemaps/myPrivateSitemap*.*   {

		## This tells nginx how to handle requests that match the "location" regular-expression 

		allow 192.168.1.143;
	   	deny all; 

			    proxy_pass                            http://localhost:8080;
            	proxy_buffering                       off;
            	proxy_set_header Host                 $http_host;
            	proxy_set_header X-Real-IP            $remote_addr;
            	proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
            	proxy_set_header X-Forwarded-Proto    $scheme;
	}
}