Every web development company with a few years of portfolio must have the problem we were facing: Maintaining access to a lot of servers! Loadbalancers, webservers, file servers, database servers etc… Once in a while a new user needs access to a specific machine or access needs to be revoked. The physical action of revoking or giving access is normally done by a systems administrator. But what if this needs to be done on multiple servers?
When all servers are self maintained you would probably start using a technique like NIS (Network Information Service), which is capable of adding credentials to a Unix system. Most of the time though a lot of companies don’t host themselves and use 3rd-party hosting services with FTP and/or SSH access. When you are in this situation maintenance can be though, hence this blog post about our solution.
Because FTP is not the ‘most’ secure solution we only opt-in for the SSH access to machines, for which we’ve build a centralized solution for maintaining secure and easy access to different machines.
At Enrise we are using OpenSSH public key authentication on a per user basis. Every user has a personal public/private key pair which gives acces to SSH/SFTP related services. The public key is stored in a LDAP directory which is the core location of credentials for every user. Because every public key is accessible via LDAP we can easily build a management tool that will help us in distributing these keys to the different servers that people need access to.
A simple representation of a management interface is a matrix defining all the users and servers one has to access as shown below:
|Server A||Server B||Server C|
In this representation all the users are read from the LDAP directory and the servers are stored in simple database.
Creating authorized keys for a user is done using not more then one simple command on a Linux system:
ssh-keygen -t rsa -f sshkey
In this case we are creating a key of the type RSA with a file named sshkey. It will ask you to provide a personal password for the keyfile, adding more security to your private key file. The public part of the key file can be exchanged to any location you would like, in our case the LDAP directory.
Using the same keygen we also need to create a super key which can be used for communicating to all servers. Without this super key we can’t push our enabled users to the different systems.
Reading from LDAP
A lot of projects at Enrise are built using Zend Framework. Zend_Ldap is one of the components that is pre-provided for querying a LDAP directory. Below is an example for querying the LDAP returning the info we need for populating the first column of our matrix. This example uses the displayname, unique ID and public sshkey which was stored in the LDAP tree.
Storing the server / user data
The information on the first row of the matrix and the checked boxes also need storage. A simple Sqlite or MySQL database suffices. For a server the following minimal info is required:
- ip address
- ssh port
- ssh user
Using these fields we can setup access to the server. Remember the super key that needed to be generated? The public part must be connected to every server you define in your database. This can be done using the ssh-copy-id command which sends your key to a remote host and sets the correct ssh configuration for the defined user:
ssh-copy-id -i super-key.pub '-p <ssh-port> <ssh-user>@<ip address>'
When this is done a system supplied with the private part of the ssh key file can access every account that is defined in the database.
The ssh-copy-id command creates a ~/.ssh/authorized_keys file on the system that is defined. The contents of that file is not limited to the public key file part just provided. It can contain multiple key files for allowing access to multiple users.
So to finalize, we need a link table that connects the LDAP user id’s to the server id’s defined in the server table. That link table is the step for generating an authorized keys file with multiple keys that can be automatically pushed to the different servers. Have a look at the following PHP example:
Access control maintenance can be a lot of work, but as we demoed here using some simple connections life can be made easy. Maintainable secure access to every system, without filling in a password every time. Canceling out the weakest link: a user that needs to remember a lot of passwords which in result leads to weaker password security.
There is a downside though: This tool can be a single point of attack for getting access to systems. Before implementing such a structure, you also need to think of the security aspects involved. Securing the server running this software is a prerequisite!