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.
An image is available on docker hub. It uses SQLite by default.
git clone https://github.com/dhatim/cloudpass.git, or simply download the zip and extract it somewhere.npm install --production.npm start.The configuration files are located in the config folder of the 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.
rootUrl: In RESTful webservices (which Cloudpass is), resources are identified unique URIs. For instance, the representation of a tenant with id foo 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 be https://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.
If rootUrl is left null, all hrefs will be relatives (e.g /tenants/foo). This should be fine in most cases. However:
delete operations on the Java client. If you are interested, there is a fork fixing this issue.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.hrefs so you must also provide a rootUrl if you use it.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.
database: name of the database to connect to (irrelevant for SQLite).username and password: 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.:exclamation: If you choose a database other than PostgreSQL, you will need to install the corresponding client:
npm install mysqlnpm install sqlite3npm install tediousExamples:
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 to null to use SMTP.transport.options: transport configurationfields: Optional additional email message fields such as bcc (see the nodemailer page)Example of an SMTP configuration that will send a copy of each email to [email protected] and [email protected]:
email:
transport:
name: null
options:
direct: false
host: smtp.example.com
port: 587
auth:
user: [email protected]
pass: xxxxxxx
fields:
bcc:
- [email protected]
- [email protected]
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 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}}{{this.url}} (the use of this is necessary because url is also the name of a Handlebars helper function){{cptoken}}{{cptokennamevaluepair}}Invitation emails can additionnaly use the following placeholders:
{{application.name}}{{organization.name}}{{organization.namekey}}{{organization.description}}{{fromAccount.givenName}}{{fromAccount.fullName}}{{fromAccount.surname}}{{fromAccount.username}}{{fromAccount.email}}Loggers can be configured in the logging section:
gc section)Each logger can use multiple transports.
console, file, http, stream)sentrygraylog_ovhconsole) can be omitted.src/helpers/logging_transports.For example:
logging:
transports:
sentry:
module: sentry
dsn: ...
level: error
graylog:
module: graylog_ovh
graylogHost: ...
graylogOvhTokenValue: ...
level: info
graylog_audit:
module: graylog_ovh
graylogHost: ...
graylogOvhTokenValue: ...
level: info
loggers:
audit:
transports: [console, sentry, graylog_audit]
level: info
sql:
transports: [console, sentry, graylog]
level: info
http:
transports: [console, sentry, graylog]
level: info
email:
transports: [console, sentry, graylog]
level: info
sso:
transports: [console, sentry, graylog]
level: info
gc:
transports: [console, sentry, graylog]
level: warn
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 protected]&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 protected]&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
The currently implemented REST API is described here. The list of features is:
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();
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.
Cloudpass is a work in progress and these features are not yet available. Let us know if you need them !
First, make sure the devDependencies are installed: npm install
npm run test:unitnpm run test:integrationnpm testThis 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
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:
Content type
Image
Digest
Size
125.8 MB
Last updated
about 5 years ago
docker pull dhatim/cloudpass