From RackTables Wiki
Jump to navigation Jump to search

User authentication

Authentication is a way to tell that the remote user is who he or she purports to be. This can be done in three ways, with or without knowing the user's password, and is controlled through an option on the configuration page and via editing parameters in the "secret.php" file in the "inc" folder of your installation. Authentication does not automatically equate to access. All users other than the default "admin" user must be explicitly granted access, either individually, or via group permissions (see the "Permission configuration" section below), as specified under "Configuration: Permissions". If you do not grant access, the user will not be permitted to view any pages. !RackTables traditional account locking works regardless of authentication sources, so one can always disable accounts one by one, if necessary.

Local authentication

This is the oldest (and default) method. Password hashes are stored in SQL database along with all other data. !RackTables checks the passwords itself.

LDAP authentication

Administrator user is the user with user_id 1, which by default maps to username "admin". Administrator is always authenticated locally via the accounts database. Other user accounts are treated the same way by default, but this can be changed. See here for detailed instructions on configuring RackTables for LDAP.

external authentication (since 0.17.0)

In this mode !RackTables only makes sure, that the user is using a username to access. It is assumed, that Apache is configured to authenticate users, in its simplest case:

AuthType basic
AuthName "beware ogres"
AuthUserFile /var/www/racktables/.htpasswd
Require valid-user

After Apache configuration it is necessary to open !RackTables main page and make sure, that Apache really blocks unauthenticated users, whichever means it uses to validate them (htpasswd, LDAP, Kerberos and so on). Only after that the software configuration must be changed to always trust the username provided (because the web-server has already validated it). This is done in secret.php file:

$user_auth_src = 'httpd';

External Authentication with Shibboleth

RackTables is compatible with Shibboleth authentication. It will require the installation of the Sibboleth Service Provider (SP) module for Apache, and for that to be configured to accept identity assertions from an Identity Provider (IDp), Federation, WAYF service or Directory Service.

Detailed installation instructions for the Shibboleth SP are here: https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPLinuxInstall

Be sure that RackTables is properly installed and working with the local administrator account (admin) before setting up Shibboleth.

  • Check that required packages are installed:
$ sudo apt-get install libapache2-mod-shib2
  • Configure shibd for your Fedration or IDp (using the instructions above, or those provided by your IDp or Registry)
  • Enable the shibd
$ sudo update-rc.d shibd enable
  • Enable the Apache modules for Shibboleth and SSL:
$ sudo a2enmod ssl
$ sudo a2enmod shib2
  • Create a SSL secured site for RackTables by createing /etc/apache2/sites-available/racktables-ssl with the content:
<VirtualHost *:443>
        ServerAdmin webmaster@localhost

        DocumentRoot /var/www
        SSLEngine on
        SSLCertificateFile    /etc/ssl/certs/ssl-cert-snakeoil.pem
        SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

        <FilesMatch "\.(cgi|shtml|phtml|php)$">
                SSLOptions +StdEnvVars
        <Directory /usr/lib/cgi-bin>
                SSLOptions +StdEnvVars
        #   "force-response-1.0" for this.
        BrowserMatch "MSIE [2-6]" \
                nokeepalive ssl-unclean-shutdown \
                downgrade-1.0 force-response-1.0
        # MSIE 7 and newer should be able to use keepalive
        BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown

    <Location /racktables>
        AuthType shibboleth
        ShibRequireSession On
        require valid-user
  • Enable the RackTables site in Apache:
$ sudo a2ensite racktables-ssl
  • Restart Shibboleth and Apache:
$ sudo service shibd restart
$ sudo service apache2 restart
  • Edit /var/www/racktables/inc/secret.php and add the following lines:
$user_auth_src = 'httpd';
$require_local_account = FALSE;
  • Use your browser to navigate to your RackTables application using HTTPS (i.e. https://your.server.com/rackspace), you should now be presented with a Shibboleth login from your configured IDp, or Directory service. This should present you with a "Not Authorised" screen, copy the username that Shibboleth has handed RackTables.
  • Comment out the lines added to /var/www/racktables/inc/secret.php in the previous step:
# $user_auth_src = 'httpd';
# $require_local_account = FALSE;
  • Return to RackSpace in your browser and reload the page, login as the local administrator (admin)
  • Create a tag to identify RackTables administrators e.g. 'RackTable Admin'
  • Create a new user with the username you coped previously, and tag it with the administrator tag
  • Edit the RackCode in the Configure -> Permissions tool to give your administrator tag access (this also gives non-admins viewing rights), Verify and Save:
allow {$userid_1} or {$tab_default}
allow {RackTables Admin}
  • Log the local administrator out of the RackSpace web application
  • Return to /var/www/racktables/inc/secret.php and uncomment the lines:
$user_auth_src = 'httpd';
$require_local_account = FALSE;
  • Return to RackSpace in your browser and reload the page. You should now be logged in as your Shibboleth user, and have administrator access.

Note: Replace the snakeoil certificates in the Apache configuration with certificates issued by a proper Certificate Authority, or use self signed certificates. Note: The certificates in the Apache configuration are your Front End certificates presented to the user's browser, they are not the Back End certificates used by Shibboleth to encrypt back-channel communication between a SP and and IDp. Do not secure Apache with certificates found in /etc/shibboleth/ Note: RackTables does not handle user names with special characters (e.g. '@'), which may prevent the use of $username=User@company.url.com rules in RackCode.

logging out

When using external user authentication, special care should be taken to enable logging out of the system. According to HTTP spec, user agent (browser) among other factors uses "authentication realm" to decide, which username and password to send, when requesting each page. When the browser gets HTTP code 401 ("unauthorized"), it resets cached username/password pair for the realm, which is presented in the 401 reply. The "logout" link in !RackTables points to a special location, which always refuses to authenticate, and presents the same realm, which was used for initial authentication. That works fine for local and LDAP authentication, because in both cases the realm comes from the same source. For "httpd" authentication, however, this isn't always true (realms mismatch and cached password isn't reset), so a user often cannot log out by following "logout" link.

To make things working again, it is necessary to make the realm, which Apache presents to the user, match the one, which is seen after following the "logout" link. Let's suppose, you see {{{Snake Oil RackTables access-500}}} after clicking "logout" (500 or other value is often added by Apache PHP module to make things more secure). The setting in htaccess file then should be:

AuthName "Snake Oil RackTables access-500"

After that it's easy to find, that logging out works again.

Resetting administrator password (and username)

mysql> UPDATE UserAccount SET user_name = 'admin', user_password_hash = SHA1('mynewpassword') where user_id = 1;

Failover setup

RackTables' purpose is to aid in troubleshooting, but sometimes the problem makes !RackTables system unavailable itself. A read-only backup replica of the server will help making through the accident faster. The diagram below explains necessary setup:


Vendor sieve (since 0.17.0)

The dictionary is made of many (hundreds) records, most of them being hardware models. The records are usually grouped by OEM brand or product line. It's common to stick with one particular brand and never purchase others. However, by default all records are shown in drop-down SELECT lists on "Properties" tab of each object. It is possible to hide certain option groups from being rendered by default. To do so, navigate to "Configuration", then to "User interface" and switch to "Change". There is an option (empty by default) named "Vendor sieve configuration". Its format is:

Vendor1; Vendor2@X; Vendor3; Vendor4@Y; ...

Here VendorZ is what you see in bold in drop-down list (OPTGROUP, to be specific), and X/Y are optional numeric values of object type. If the object type isn't specified, related vendor is screened out from SELECTs for all object types. So, say, one has Sun (tm) tape libraries, but has no Sun (tm) servers. To hide "Sun" OPTGROUP from the list of server models and leave it on the list of tape libraries, he puts the following into option value:


This way the "HW type" SELECT gets considerably shorter. However, this feature is purely cosmetic: it doesn't remove any data from the SQL database, and doesn't change existing data. If there is a particular server marked as one of Sun (tm) boxes, the record is shown as before and upon going to "Properties" tab the whole "Sun" OPTGROUP is there (because the value is already set). It's possible to change from one Sun model to another in this situation. But once the box is changed to, say, a noname server, the "Sun" OPTGROUP is again gone, as requested by the sieve.


When we create objects, we often (if not always) add some ports to them depending on the type and hardware model. Although RackTables can't yet add ports depending on hardware model (except via SNMP), it is (as of 0.14.12 release) able to automatically add ports upon object creation. This process is controlled by AutoPorts configuration string:

<object type1 id>=<n1>*<port type1 id>*<format1>;<object type2 id>=<n2>*<port type2 id>*<format2>+<n3>*<port type3 id>*<format3>;<object type3 id>=<n4>*<port type4 id>*<format4>+<n5>*<port type5 id>*<format5>...

The default value is "{{{4 = 1*33*kvm + 2*24*eth%u}}}", which makes each new server to have 2 Linux-style GigE ports and 1 KVM port. To make each new PDU bear 6 power plugs in addition to this, the AutoPorts config would be as follows: "4 = 1*33*kvm + 2*24*eth%u; 2 = 6*16*%02u". Exact key values can be found on the dictionary page in chapters PortType and RackObjectType (keys are rendered as mouse hints for each dictionary record). The format string is the one accepted by printf family functions and ports are indexed starting from 0 and upwards.

The feature can also make its work later. When you browse an object, which has no ports yet, but could have (according to AutoPorts configuration), you see additional tab named "AutoPorts". It will present you with its idea of which records could be added, and a button to do so. Once you add any ports to an object by automatic or manual mean, the tab will hide itself.

KVM ports

Since the 0.14.11 release RackTables has 2 distinct port types for physical console: "KVM (host)" and "KVM (console)". Both types more describe the function, than an exact set of connectors. The former one emits video signal and accepts keyboard and/or mice events. The latter one accepts video signal and emits HID events. There's no specification, which mix of DVI, DB15, PS/2, DIN, USB and even Sun connectors is in question for each particular port, hence a variety of cabling and convertors is usually available. One usually just has "console" or "KVM switch" boxes with "KVM (console)" ports and server boxes with "KVM (host)" ports. Then connecting two servers or two pure consoles together wouldn't be possible, as it used to be before.

A known drawback of the new approach is that all the ports (especially connected ones), which were created before the 0.14.11 release, now belong to "KVM (host)" type regardless of their actual function. There are ways to fix this depending on the number of such ports:

  • Small: delete and re-add ports manually.
  • Average: issue UPDATE SQL statement (backup you data first!).
  • Really big: ask for help on the racktables-users mailing list. We might invent an automatic upgrading script.

Fixing the RackCode

It's possible to write RackCode that locks the administrator out, so you can't fix things the usual way. In most situations you can always log in as administrator and fix things, but it's possible to break even this. The following SQL code restores administrator access:

UPDATE Script SET script_text = NULL WHERE script_name = 'RackCodeCache';
UPDATE Script SET script_text = CONCAT('allow {$userid_1} ', script_text) WHERE script_name = 'RackCode';

Permission configuration

If you have issues understanding of how the permissions thing works, try to consider the permissions script as firewall rules.

The current security context (a packet in firewall terms) is sequentially compared to each rule (statement in permissions script), top to bottom. If it matches, the action specified in rule takes place (allow or deny) and the process stops.

The current context is a set of tags originated from the currently logged-in user, an entity being viewed, and navigation data (current page and tab name). These could be either automatic tags or user-assigned tags.

So, the rules like

allow {$userid_1}
allow {$username_jack}

unconditionally allow any context containing tags {$userid_1} or {$username_jack}, which makes those users the power- ones.

But the rule

allow {$username_bill} and {$tab_default}

allows anything to user named 'bill' when he is on 'default' tab. The default tab never contains controls to modify the DB, so the user has read-only permissions if there are no other allowing rules below.

More examples

Note: The RackCode saved in the MySQL database contains hidden characters, such as carriage returns and new lines. RackCode edited using the mysql command line client or using the MySQL Workbench client may not work.

Administrator with unlimited access

allow {$userid_1} # admin is always UID 1 regardless of username

Admin and power user

allow {$userid_1}
allow {$username_jack}

Admin and a group of power users

This approach requires creating a tag (Configuration -> Tag tree) named "power user". Then each user account of the group must be tagged with this tag. After that the following code text would do the trick:

allow {$userid_1}
allow {power user}

This way it's possible to run with the same text, granting and revoking permissions through attaching and removing role tags.

Admin, a group of power users and a group of managers

RackTables pages have tabs. There is always at least one tab, the "default" one. Its name is always "default" and its contents doesn't allow changing things. It may show data about current items and/or links to other pages, but basically it's read-only. This way, having {$tab_default} on the current security context is equivalent to read-only access. Of course, this setup assumes a role tag for managers accounts.

allow {$userid_1} or {power user}
allow {manager} and {$tab_default}

Admin can write, anyone can read

allow {$userid_1} or {$tab_default}

Permitting a user to view his own assets

Let's suppose you are setting up !RackTables for a colocation provider. A customer company, Snake Oil Web Services, wants to see what happened to their 20 servers you have accepted for colocation. They would also like to know which server must use which IP address for things to work. You create a user account, "snakeoil", then create a tag "Snake Oil asset" and use it to tag each of that 20 servers. After that the following code permits them what they need and nothing else:

allow {$username_snakeoil} and {$tab_default} and {Snake Oil asset}

There are things to mention, which aren't obvious:

  1. The user will be able to access only the pages, which display objects. As long as you use "Snake Oil asset" tag to mark servers only, it will get onto the context only in specific locations. IOW, the "snakeoil" account will not be authorized to view even the main page. For this specific case you can provide them with a list of 20 URLs.
  2. When you decide to use a more generic description for the tag, it becomes easy to achieve unexpected results with valid permission rules. Say, if you have a "Snake Oil" tag, some hardware and several user accounts, you may decide to tag not only servers, but accounts as well. This will effectively permit every Snake Oil account to access default tab of every page in the system, because of {Snake Oil} being always present on the security context. That's why the example uses {Snake Oil asset} to help things remain separated.

Disable log delete for everyone

It is usually not desirable to remove log entries (especially accidentally), so you may set this as the first rule of permissions:

deny {$tab_log} and {$op_del}

Headquarters and branch offices

Let's assume having the follwing tag tree:

- assets
-- HQ assets
-- HQ managed
-- Arizona assets
-- Texas assets
- admins
-- HQ admins
-- Arizona admins
-- Texas admins

Then the following ruleset would allow each branch viewing all, but managing only own assets. Some local stuff could be placed under authority of the headquarters (this stuff would be tagged with 2 tags at a time).

allow {admins} and {assets} and {$tab_default}
deny not {HQ admins} and {HQ managed}
allow {Arizona admins} and {Arizona assets}
allow {Texas admins} and {Texas assets}
allow {HQ admins} and ({HQ assets} or {HQ managed})

Disabling Live PTR

If you need to disable the Live PTR functionality, the following steps should be followed.

1. Create a Tag entry for each network you want to disable this functionality for. For example, say there are two networks: "Production" ( and "Office" (, and you only want to disable this functionality on the Production network. You would create a tag called "Production-LAN", then associate the "Production" Network to the "Production-LAN" tag.

2. Go to Configuration > Permissions.

3. Add the below line to the top of the Permissions list and save. (Remember that if you add the deny rule below the allow ones, it won't take affect.)

 deny {$tab_liveptr} and {Production-LAN}

4. Navigate to the Production network under IPv4space section. Click the network, and confirm that the "LivePTR" tab is not available.

Notes about rules/permissions

(Contributed by Michael Tiernan)
(This list is not exhaustive and may inadvertently exclude some edge cases.)

  • Rules are read from top to bottom.
    • To reach the bottom of the rules, no others have had to match. This also means that a matched rule ends the search.
  • Rulesets permit (and encourage):
    • Comments which start with a pound sign "#".
    • Blank lines before/after rules or logical sections.
    • Comments may also be placed at the end of a rule by using "#" to begin the comment.
  • Rules can get you into trouble.
    Good practice suggests you have two different browser windows open at the same time, one logged in as the 'admin' changing the rules and the other as an ordinary user testing these rules.
  • Rules specifying things like "Locations" (see below) can be created by:

(I suggest doing this for your admin user only.)

  1. Go to "My Account" under the configurations tab.
  2. Select "Interface Preferences"
  3. Search for SHOW_AUTOMATIC_TAGS and set it to "Yes"
  4. Save your changes.
  5. Go to the "RackTables" page from the Main page and select the location in question. You will be shown a line that will read something like
    Automatic tags: $any_location, $locationid_43
    telling you what tag represents your location.

Examples of using comments in permissions:

allow {$userid_1}	# Our "admin" user.

This rule references the tag "$locationid_43" which (for this example) is the automatic tag related to the Boston datacenter location.

# Rule added: Thu Aug 23 08:22:10 EDT 2018 by MrTux
# The user Jack is the new manager and admin at our floating facility off of Boston.
allow {$username_jack} and {$locationid_43}    # Jack has no restrictions in Boston.

# Bill is a datacenter worker in Washington DC and we don't want to give him any
# power other than to see what's on the default tabs.
allow {$username_bill} and {$tab_default} and {$locationid_55}	# Bill can only view.
# This rule should be way down the end.
### It says that a user (that did not match any rules above, i.e. ordinary view-only user)
### will be permitted to look at things without being able to change anything
### but *can* change their own password.
allow {$page_myaccount} and {$tab_mypassword}

Defining a new RackTables Object Type

(contributed by Craig Hoffman)

RackTables CircuitExample.PNG

Perhaps you have a piece of equipment that is currently not listed in the default list of RackTables objects. This could be something physical, like an environmental sensor. Or, perhaps, you want to extend RackTables to support something more virtual, like network circuits. (I wanted to have my CircuitDB info in one location. To this end, I created a Rack Row called "Virtual", and a 47U rack called "Circuits". I just stick each of my circuits in there so they don't show up as "Unmounted".)

This process has been discussed from time to time on the mailing list. Here's how you do it:

  • From the Main Menu, select Configuration, Dictionary, and then select the dictionary "ObjectType".
  • Select "Edit" and add the new object type that you wish to create. I extended RackTables to support circuits, so I typed in "Circuit".

Now you need to create a dictionary entry that will be used to tie attributes to.

  • From the Main Menu, select Configuration, Dictionary, and then select "Manage Chapters" at the top. Add a new entry (Circuit ID as my example).

You can now create the attributes that will be assigned to your new dictionary entry. For a circuit, things like circuit ID#, carrier, AS#, contact name, etc. You can always go back and add more attributes as needed.

  • From the Main Menu, select Configuration, Attributes, and Edit Attributes. Create each attribute that you need. Take care in the type of attribute. "String" is probably what you want, when in doubt.

You're just about done. It's time to assign those new attributes to the dictionary entry.

  • From the Main Menu, select Configuration, Attributes, and Edit Map. Select the new attributes and apply it to the new dictionary entry. You probably do not need to do anything with the third dropdown box, "dictionary chapter...".

Now you should be able to go back to the Main Menu, and create some new objects with your new Object Type.

Adding new port types

See adding new port types page to activate hidden port types or to create new ones.

Configuring CLI gateways to network devices

RackTables has some features which need to have CLI access to network devices. Those features are:

  • Live ports (FDB, interface status)
  • Live neighbors (CDP, LLDP)
  • 802.1Q management

RackTables is able to interact with devices through pure TCP terminal session (netcat), telnet or ssh. The administrator is responsible for configuring the protocol, connection options and authentication credentials used to connect to particular devices.

To do so, administrator must include the function terminal_settings into secret.php.

The minimal example of such function:

function terminal_settings ($cell, $params)
        $params[0]['username'] = 'login';
        $params[0]['password'] = 'password';

The defaults of $params[0] array are pretty reasonable, and the only keys which are absolutely needed to be set are 'usermame', 'password' (for netcat or telnet), and 'sudo_user'/'identity_file' (for ssh).

More comprehensive example might look like this:

        if (considerGivenConstraint ($cell, '{$typeid_4} or {Juniper}'))
                $params[0]['protocol'] = 'ssh';
                $params[0]['proto'] = '4';
                $params[0]['sudo_user'] = 'racktables';
                $params[0]['connect_timeout'] = 2;
        elseif (considerGivenConstraint ($cell, '{Switch}'))
                $params[0]['username'] = 'racktables';
                $params[0]['password'] = 'password';
                $params[0]['timeout'] = 60;

        if (considerGivenConstraint ($cell, '{$attr_4_251}')) // IOS 12.1
                $params[0]['protocol'] = 'telnet';

The possible keys in $params[0] can be determined by calling print_r ($params[0]).

To make the remote gateways features work for a particular device, the following conditions should be met:

  • FQDN field of object is set to DNS name or IP address of device
  • SW type field of object is set and supported by particular gateway feature
  • terminal_settings function defined in secret.php

File uploads

There are several settings in the global /etc/php.ini which you may need to modify:

needs to be On
max size for uploaded files (Defaults to 2MB)
max size of all form data submitted via POST (including files)

The following MySQL server parameter may be relevant too:



Adding the following parameter to "secret.php" will enable debugging, which is helpful in tracking down permissions errors (for example).

$debug_mode= 1;

Make sure you disable this by commenting it out or deleting it when you're done debugging! :)