View on GitHub

passweaver-api

A collaborative password manager NodeJS API

PassWeaver API

PassWeaver API is a stateless, enterprise-scale, collaborative secrets manager API. It allows to safely store and retreive sensitive data, such as sites passwords, API credentials, network passwords… in other words any information that needs to be encrypted, protected, monitored, shared.

It’s collaborative, meaning that users are organized in groups and protected items are organized in folders: different permissions can be defined for each folder for each user group.

What is it?

PassWeaver API is a full API server, no GUI or CLI: you can easily integrate it with your systems and let it act as a centralized password vault. Instead, for a ready to use, simple yet complete Web GUI to run along the API, have a look at companion app PassWeaver GUI: https://github.com/steunix/passweaver-gui

PassWeaver API is a NodeJS application, released under MIT license, and it uses these (great) opensource libraries, among several others:

See below for a full API documentation.

Dependencies

Features

How it works

PassWeaver API gives you access to the following objects:

Items

An ‘item’ is an entity with a (unecrypted) title, a type field, metadata field, and some encrypted data. PassWeaver API just encrypts “strings”, so your data can be anything that can be converted into a string: there is not built-in logic on the content.

For example, in one item you may store a JSON object that identifies a login:

{
  url: "abc",
  user: "aaa",
  password: ""
}

and in another item you may have something that represents an API credentials set:

{
  clientid: "",
  clientsecret: "",
  url: "",
  scope: ""
}

and in another item you may have just only a flat string.

It’s up to the consumer to decode and handle the data, maybe based on the type field (see Item types below).

An item has also a mandatory title field, that can be searched for and is NOT encrypted: do not use it for storing sensitive information.

The metadata field is NOT encrypted as well but not mandatory, and it allows to store any additional uncrypted info for a given item.

Item types

Item types are categorized, and they just consist of a code and a description.

Folders

Folders, just like in a file system, hold collections of items and/or subfolders. Each folder may hold specific persmissions for a given group, and will inherit parent’s permissions (see ‘Permissions’ below).

PassWeaver API has 2 predefined folders that cannot be modified or deleted:

Personal folders

Each user has a ‘personal’ folder for storing private, not-shared-with-anyone items. In order to use personal folders, users have to set a personal password that will be use for encrypting items inside those folders. Since this password is used to encrypt the key that will be used to encrypt his items (“envelope encryption”), there is no way to recover the items if a user forgets his password.

Users and groups

Users are assigned to groups, and groups have read/write permissions for a given folder.

Users can join any number of groups.

While groups can be nested to form a tree, there is no membership inheritance: if a user is member of a group G, it will not automatically join the “children” of G.

Authentication

PassWeaver supports two authentication methods:

Admins

The Admins built-in group and it’s built-in member user admin are targeted at creating users and groups, and assigning permissions to folders. Both Admins group and admin user cannot be updated or deleted.

Since Admins group members are meant for administration tasks, they have NO access to any items in any folder, and they do not have personal folders either. They can though add and (if empty) remove folders.

If you need someone with full access to all folders, you may create a group with read/write permissions on Root folder and add the user.

Everyone

Another built-in group is Everyone, quite self-explanatory: all created users will be automatically added to this group, and they can’t be removed from it.

Permissions

Permissions are per folder, not per item: you cannot give different permissions to different items in the same folder.

A folder has 2 permissions:

Permissions are granted to groups of users, and not to single users: this is intentional, following the KISS philosophy; in complex environments, permissions for a single user or for a single item are difficult to maintain and very easy to mess with, while group permissions let you have a cleaner and more maintainable configuration.

Following same KISS paradigm, permissions are always inherited. For example, in a company setup you may have these folders:

Suppose that datacenters are managed by different groups of people: you would have a “AzureAdmins” group, along with “AWSAdmins” and “GCPAdmins”, and you would give read+write permissions to each group on its own folder.

You may have a user managing both GPC and AWS, so you would just have to add the user to both “AWSAdmins” and “GCPAdmins”.

But, remember, permissions are always inherited. What does this mean?

If an “AdminGCP” user creates a new folder in “GCP”, let’s suppose “VPNs”, what happens? This folder would inherit the “GCP” permissions, thus, in our example, read+write for “GCPAdmins”. Even if this new “VPNs” folder is given read+write permissions on a completely different group, and not “AdminGCP” explicitly, “AdminGCP” will always have read+write permissions.

In other words, a permission on a folder is granted for itself and all its children folders.

While this may sound as a limitation, in the long run it allows to avoid wild permissions forests, such as “hidden” folders available only to a restricted number of people, in a point of the ‘tree’ where you would not expect it.

That is indeed exactly how user Admin in PassWeaver API works: it’s part of the builtin Admins, which has read+write access to ‘Root’ folder, thus to every folder - due to this kind of inheritance.

One time secrets

OTS are an easy way to share a secret with someone: you provide the data to encrypt and you will receive back a token; accessing the token through the API, you will have access to the the decrypted data, but only once: once “consumed”, the token will be deleted.

This is similar to various public services you can find online.

Encryption

User passwords are hashed using bcrypt algorythm.

Items are encrypted in the database using AES-GCM, using a master key that is read from the file defined in master_key_file config entry.

WARNING: as with any other software using symmetric encryption, if you loose your master key you’re completely screwed and there is no way to recover encrypted data. So be sure to keep your master key safe and properly backed up.

Personal items

Personal items are encrypted with “envelope encryption” first and then reencrypted with master key:

Then, when creating an item in a personal folder:

When reading a personal item:

No keys are retained in memory or cache, everything is recalculated when needed.

Operations log

Passweaver API keeps a log about:

Application logs

PassWeaver API logs every call in a ‘combined log format’. Errors are tracked in a separate log. There are configuration options to customize log files rotation and retention.

Cache

PassWeaver API makes use of a cache in order to avoid too much pressure on the database, especially in relation to permissions and folders tree for each user. You can choose between these cache providers:

The API

Authentication

PassWeaver API is stateless and sessionless and uses SHA-512 signed JWTs for authentication; JWT signing key is randomly generated every time the application is started.

A JWT is returned on successful login, and it must be provided in all subsequent calls - until it expires - in requests header as an “Authorization bearer”.

Responses

PassWeaver API endpoints respond with JSON payloads using standard HTTP response codes, so be sure to handle them correctly:

Along with HTTP response code, you’ll always get this minimum payload:

{
  status: success/failed,
  message: text,
  data: {}
}

In case of errors (status=”failed”), you can find the explanation in the “message” field.

If any data is returned by the endpoint, it will be always encapsulated in the “data” field:

{
  status: success/failed,
  message: text,
  data: { whatever }
}

Install and run

Prerequisites

In order to be able to install PassWeaver API, you need:

A running Redis instance is warmly advised.

Install

Download the source, and install all dependencies with npm:

npm install

Configure

Prepare a master key file and save it on your disk: this file will contain the base64 encoded AES-256 key for encrypting your data. Ensure it is outside the directory where PassWeaver sources are. Keep this file as secret and secure as possible: if you loose it you won’t be able to decrypt your data anymore.

Copy config-skel.json to config.json and adjust the options:

Environment

Passweaver API reads this environment variable:

See Prisma Documentation for further details.

If you’re installing a production environment, don’t forget to set variable NODE_ENV to production, since some of Passweaver API dependencies use that variable to optimize operations.

Database

PassWeaver API uses PostgreSQL as RDBMS and Prisma ORM to access it.

Create an empty database on your existent PostgreSQL instance, and set the environment variable PASSWEAVERAPI_PRISMA_URL accordingly.

Then, from PassWeaver-API directory, run the following commands:

A default user admin will be created with password 0: of course you should change it as soon as possible.

Run

run npm passweaver-api.mjs.

You may want to create a Linux service via systemd or a Windows service via nssm.

Full API documentation

For a full API documentation you can refer to this page