Cloudpass
Cloudpass is an implementation of Stormpath Identity Management written in Node.js.
It takes care of all the tedious user management tasks for you: account verification and password reset email worfklows, role management, multi-tenancy, SSO...
Persistence of data is done either through PostgreSQL, MySQL, MariaDB, SQLite or MSSQL.
Installation
Debian based distributions
Cloudpass can be installed on Debian and Ubuntu based linux distributions from a package hosted on Bintray. Note that this package depends on PostgreSQL, as it is the default DBMS.
-
Cloupdass needs Node.js 6.x to run, so you will need to add node debian repository to your source list if you have not done so already. You can find instructions here.
-
Add Dhatim Bintray's debian repository in sources.list:
echo "deb http://dl.bintray.com/dhatim/deb stable main" | sudo tee -a /etc/apt/sources.list
-
If it is the first repository from Bintray that you add, you will also need to add Bintray's public key to apt:
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 379CE192D401AB61
-
Now all you need to do is install the cloudpass package:
sudo apt-get update && sudo apt-get install cloudpass
It can take a few minutes. Don't worry, that's just
npm install
doing its job. Subsequent updates will be much faster!
Cloudpass is now installed as a systemd service with no additional configuration needed!
To stop it: sudo systemctl stop cloudpass.service
, or alternatively sudo service cloudpass stop
(the start
and restart
commands are of course also available).
You can see the logs with sudo journaltcl -u cloudpass
.
Docker
An image is available on docker hub. It uses SQLite by default.
Other systems
- Install Node.js (version 6). You can find installation instructions for your system here.
- Clone the repository:
git clone https://github.com/dhatim/cloudpass.git
, or simply download the zip and extract it somewhere. - Run
npm install --production
. - Configure the persistence (c.f. below).
- Start the server with
npm start
.
Configuration
If you installed the debian package, the configuration files are located in /etc/cloudpass
. Else they are in the config
folder of your installation directory.
The default configuration is in default.yaml
. You should not modify this file, but either:
-
create a
local.yaml
file and override the values you need. -
set an environment variable for each configuration value changed. The name of these environment variables can be found in the
custom-environment-variables.yaml
file. -
use a single
NODE_CONFIG
environment variable containing all your configuration changes in JSON format:export NODE_CONFIG='{"persistence":{"database":"cloudpass","username":"postgres","password":"postgres","options": {"host":"customerdb.prod","port":5432}}}' npm start
Don't forget to escape the quotes if you pass this variable to
docker run
:export NODE_CONFIG='{\"persistence\":{\"database\":\"cloudpass\",\"username\":\"postgres\",\"password\":\"postgres\",\"options\":{\"host\":\"customerdb.prod\",\"port\":5432}}}' docker run -e "NODE_CONFIG=$NODE_CONFIG" -P dhatim/cloudpass
There are four configuration sections: server, persistence, email and logging.
Server
-
rootUrl
: In RESTful webservices (which Cloudpass is), resources are identified unique URIs. For instance, the representation of a tenant with idfoo
will look something like this:{ "href": "https://cloudpass.example.com/v1/tenants/foo", "applications":{ "href": "https://cloudpass.example.com/v1/tenants/foo/applications" } }
In this example, the
rootUrl
would behttps://cloudpass.example.com
. Cloudpass has no way of figuring this out on its own because he cannot know if it is being accessed directly or from behind a proxy. IfrootUrl
is left null, all hrefs will be relatives (e.g/tenants/foo
). This should be fine in most cases. However:- this is not necessarily well supported by Stormpath clients. In particular, we had issues with
delete
operations on the Java client. If you are interested, there is a fork fixing this issue. - if you mount Cloudpass after one or more path segments (e.g.
htpp://www.example.com/my/cloudpass/instance/
) and use Sauthc1 authentication (which is the default method on Stormpath clients), then you must provide a rootUrl. It is because Sauthc1 uses the request path to compute its hash. - ID Site makes queries on
href
s so you must also provide a rootUrl if you use it.
- this is not necessarily well supported by Stormpath clients. In particular, we had issues with
-
server.port
: the port on which cloudpass listens. -
clustering
: Set to true to cluster the application in a number of procesess equals to the number of CPU cores (but not more than 4) to speed up response time.
Persistence
database
: name of the database to connect to (irrelevant for SQLite).username
andpassword
: connection credentials.options
: connection options. Cloudpass uses Sequelize internally, and this object is passed as it is to the Sequelize constructor. A list of available options is available in Sequelize documentation.
❗ If you choose a database other than PostgreSQL, you will need to install the corresponding client:
- MySQL or MariaDB:
npm install mysql
- SQLite:
npm install sqlite3
- MSSQL:
npm install tedious
Examples:
Using SQLite is probably the fastest way to start playing around with Cloudpass, as it doesn't require to install a DBMS. But its limited concurrency support would probably make it unusable for a real life usage. The following configuration will store the data in the file 'cloudpass.db', creating if necessary:
persistence:
options:
dialect: sqlite
storage: cloudpass.db
You can also use unix sockets and take profit of peer authentication to avoid having to provide a password in the configuration file:
persistence:
database: cloudpass
options:
dialect: postgres
host: /var/run/postgresql
port: 5432
Or for a plain old user/password authentication, with additional connection pool configuration:
persistence:
database: cloudpass
username: cloudpass
password: wouldntyouliketoknow
options:
dialect: postgres
host: localhost
pool:
minConnections: 5
maxConnections: 10
Cloudpass needs to send emails as parts of email addresses validation or password reset workflows. The default configuration uses direct transport, which is a very good way of getting emails rejected or marked as spam. You should use instead SMTP transport or any other supported Nodemailer transport.
transport.name
: name of the transport method. Leave it tonull
to use SMTP.transport.options
: transport configurationfields
: Optional additional email message fields such as bcc (see the nodemailer page)
SMTP
Example of an SMTP configuration that will send a copy of each email to foo@example.com
and bar@example.com
:
email:
transport:
name: null
options:
direct: false
host: smtp.example.com
port: 587
auth:
user: mailer@example.com
pass: xxxxxxx
fields:
bcc:
- foo@example.com
- bar@example.com
Other transports
See here for a list of available Nodemailer transports. The following example will use nodemailer-mandrill-transport.
-
Navigate to Cloudpass installation directory and install the transport method:
npm install nodemailer-mandrill-transport
-
configure the transport (see the transport documentation for available configuration options):
email: transport: name: nodemailer-mandrill-transport options: auth: apiKey: XXXXXXXXXXXXXX
Mandrill Templates
Mandrill offers the possibility to define email templates. If you do so, you can you can pass your Mandrill template slug to Cloudpass, e.g:
POST /v1/emailTemplates/2da1a3ae-2dcf-4390-b256-d0e8e86a4642
{
"mandrillTemplate" :"welcome-email"
}
You can use in Mandrill templates the same Handlebars placeholders as when you define templates directly in Cloudpass, but they must be lowercased due to Mandrill limitations:
{{account.givenname}}
{{account.surname}}
{{account.fullname}}
{{account.username}}
{{account.email}}
{{account.directory.name}}
{{url}}
{{cptoken}}
{{cptokennamevaluepair}}
Logging
Four loggers can be configured in the logging section:
- sql: logs the SQL queries before execution,
- http: logs the HTTP requests via morgan,
- email: logs when email are sent,
- login: logs the result of logg.
Cloudpass uses winston-config to configure logging. Please refer to the module documentation for the accepted configuration options.
Getting Started
For now we will use cURL, a command line http client available for all platforms. But hopefuly these steps will soon be made easier by a user interface !
The first step is to create a tenant, with yourself as administrator. You must provide for this a tenant name, your email, given name, surname and a password. Your password must be at least 8 character-long, have at least 1 upper case, 1 lower case and 1 numeric character.
curl --data "tenantNameKey=test-tenant&email=test@example.com&givenName=test&surname=test&password=xXx010xXx" http://localhost:10010/registration
Then login to start a session:
curl -c cloudpass-cookie.txt --data "tenantNameKey=test-tenant&email=test@example.com&password=xXx010xXx" http://localhost:10010/login
This will save a session cookie in cloudpass-cookie.txt
. You can use it to query the REST API, for instance to see your account:
curl -L -b cloudpass-cookie.txt http://localhost:10010/v1/accounts/current
Look at the href
property of the returned JSON: you can use it to create an API key linked to your account. Don't forget to change the account URI in the command below !
curl -X POST -b cloudpass-cookie.txt http://localhost:10010/v1/accounts/320c2ac9-913a-4711-813e-78ef04695ddb/apiKeys
Make a note of the id
and secret
properties in the object returned, you will need them to configure your client.
You can also use them instead of cookies to authenticate your requests.
For instance, if the id key is e777909e-854b-4464-bd2c-55f951029c33 and the secret is sFdJN5p2EbT5iSls76vt4x1yyHKAyIq4rvGlzn9mSnj8eYrx5B:
curl -L -u e777909e-854b-4464-bd2c-55f951029c33:sFdJN5p2EbT5iSls76vt4x1yyHKAyIq4rvGlzn9mSnj8eYrx5B http://localhost:10010/v1/tenants/current
Features
REST API
The currently implemented REST API is described here. The list of features is:
- CRUD on Tenant with custom data and to invite users,
- CRUD on application, custom data, accounts and groups, reset password,
- Account policies
- CRUD on API keys
- CRUD on organizations, and account stores.
- Manage sites,
- CRUD on directories, custom data and linkage with accoutn and organization,
- CRUD on groups, custom data,
- CRUD on group memberships,
- Mail templating,
- CRUD on password manangement
Clients
Cloudpass implements the Stormpath REST API. It means that you can use any of the Stormpath open source clients in your application to communicate with Cloudpass. Just make sure to configure the client with a base url pointing to your Cloudpass instance. Example for Java:
Client client = Clients.builder()
.setBaseUrl("http://localhost:10010/v1")
.setApiKey(apiKey)
.build();
ID sites
Cloudpass supports ID sites.
The default one is https://id.stormpath.io, but you can configure it by changing the url
attribute of your tenant's Idsite
resource.
You can read more about ID sites on Stormpath's website.
What's missing ?
Cloudpass is a work in progress and these features are not yet available. Let us know if you need them !
- A user interface
- Social login (other than SAML)
- Oauth token generation
- Account linking
- Email white & black listing
- Multi Factor authentication
Development
First, make sure the devDependencies are installed: npm install
Testing
- To run unit tests:
npm run test:unit
- To run integration tests:
npm run test:integration
- To run both:
npm test
This will produce coverage reports in build/reports/coverage
.
Mocha's spec
reporter is used by default. To use a different reporter, you can change the mocha_reporter
npm config key.
For example to use mocha-sonar-generic-test-coverage-file:
#install & configure sonar generic test coverage reporter
npm install mocha-sonar-generic-test-coverage-file
npm config set cloudpass:mocha_reporter mocha-sonar-generic-test-coverage-file
#run unit & integration tests separately to get distinct report files
GUNIT_FILE=build/reports/ut_report.xml npm run test:unit
GUNIT_FILE=build/reports/it_report.xml npm run test:integration
Debian packaging
npm run deb
will build a debian package in the build
directory.
If you are a member of Dhatim organization on bintray, you can upload new versions in the debian repository:
- set the environment variables
BINTRAY_NAME
(your bintray username) andBINTRAY_KEY
(your bintray API key) - run
npm run deploy-deb
Releasing
If you have write accesses to the github repository, you make releases by simply running npm version <newversion>
or any of the alternative syntaxes.
This will:
- run the tests locally
- bump the version in package.json, commit, tag and push
- from there, travis-ci will automatically build and publish a new version of the debian package.