Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenWrt: LuCI: how to implement limited user access

Goal: two users root and user. Root can access everything via web-interface, but user should see only some parts of the menus.

One option would be to pass "sysauth" option to every module in question. That is not very practical, because the user would see every menu entry and would get login page for every menu he is not allowed to.

My idea is to figure out who is logged on and then do nothing in the index() function of each restricted module. So far I couldn't find such a function in LuCI API (http://luci.subsignal.org/api/luci/), that would return a current logged user.

I know how to add additional users in OpenWrt/LuCI (https://forum.openwrt.org/viewtopic.php?pid=163013#p163013). But it is only a part of the solution.

Any idea, how to achieve my goal?

like image 860
yegorich Avatar asked Aug 22 '13 09:08

yegorich


2 Answers

I ended up creating a Lua function like described here: http://lua-users.org/wiki/SaveTableToFile, to find and remove unneeded keys from the table.

function remove_idx(  tbl, index )

   -- initiate variables for save procedure
   local tables,lookup = { tbl },{ [tbl] = 1 }

   for idx,t in ipairs( tables ) do
      local thandled = {}

      for i,v in ipairs( t ) do
     thandled[i] = true
     local stype = type( v )
     -- only handle value
     if stype == "table" then
        if not lookup[v] then
           table.insert( tables, v )
           lookup[v] = #tables
        end
     else
        if i == index then
           t[i] = nil
           return
        end
     end
      end

      for i,v in pairs( t ) do
     -- escape handled values
     if (not thandled[i]) then

        local flag = 0
        local stype = type( i )
        -- handle index
        if stype == "table" then
           if not lookup[i] then
          table.insert( tables,i )
          lookup[i] = #tables
           end
        else
           flag = 1
           if i == index then
          t[i] = nil
          return
           end
        end

        if flag == 1 then
           stype = type( v )
           -- handle value
           if stype == "table" then
          if not lookup[v] then
             table.insert( tables,v )
             lookup[v] = #tables
          end
           else
          if i == index then
             t[i] = nil
             return
          end
           end
        end

     end
      end
   end
end 

And then inserted my user check and page delete after in libs/web/luasrc/dispatcher.lua dispatch():

if c and c.index then
    local tpl = require "luci.template"

    if util.copcall(tpl.render, "indexer", {}) then
        return true
    end
 end

That's how I remove unneeded pages depending on who is logged in:

    if ctx.authuser == "user" then
            remove_idx(ctx.tree, "packages")
            remove_idx(ctx.tree, "leds")
    end

It is a little bit quick and dirty, but it works. Please note, that direct access by manipulating the URL is still possible.

Update

LuCI2 will provide ACL support und multi-user environment: http://git.openwrt.org/?p=project/luci2/ui.git;a%3Dsummary

like image 73
yegorich Avatar answered Sep 23 '22 14:09

yegorich


If you'd like to create multiple OpenWRT Luci users with varying access, you can following these steps:

  1. Create a local user account
  2. Add the user to the RCP configuration and define access level

See sample excerpt from /etc/config/rpcd config below:

config login                     
        option username 'adminuser'
        option password '$p$adminuser'
        list read '*'
        list write '*'
                              
config login                     
        option username 'readonlyuser'
        option password '$p$readonlyuser'
        list read '*'

This also works if you're obtaining an authentication token for JSON-RPC calls to Luci.

like image 40
empiric53 Avatar answered Sep 19 '22 14:09

empiric53