na-user User Management Microservice Overview
The na-user microservice is a simple solution for managing users, groups, and permission policies.
Virtually every online service needs to keep track of user data. The na-user microservice is a solution for the vast majority of those use cases. It allows your developers to focus on on your core business needs and avoid reinventing the wheel.
At its core na-user provides a simple REST API for maintaining a database of users and their commonly required metadata. You can add, delete, update, list, and search users, as well as assign them to groups and attach key/value data to their records.
In addition na-user is designed from the ground up to work in modern Kubernetes and Docker production environments. It is scalable, easy to deploy, and requires minimal administration overhead.
- Home Page: https://nulladmin.com/na-user/
- API Reference: https://nulladmin.com/na-user/apireference
Features
-
Basics
- Supports assigning users to groups and partitioning them by domain
- Supports commonly associated user metadata such as contact information verification status, nicknames, birth dates, timezones, social media links and more
- Set arbitrary key/value metadata on user records
- Flexible user id creation, import your own or auto-create random, UUID, or ULID identifiers
- Full Unicode UTF-8 support, including emoji
-
Dev-Ops
- Packaged in a compact Docker container (a standalone daemon server is also available)
- Configuration settings from environment variables or config file
- Metrics endpoint for Prometheus integration
- Health and liveliness endpoints for Kubernetes
- Configurable HTTP server and database timeouts
- Structured JSON logging, suitable for both auditing and debugging use cases
- Default UTC log timestamps
-
Security
- API access with HTTPS Basic Authentication over SSL
- HTTPS API server default of TLS 1.3
- Full TLS key/cert support for connecting to the database
- Secret encryption with 256-bit AES-GCM with a random nonce
- Paging result size configuration for security and performance
- Audit friendly logging
System Architecture
Figure 1 below shows how the na-user service fits into a typical back end infrastructure design.
Figure 1. na-user Architectural Overview
The na-user
service consists of one or more running na-user
Docker
containers and a dedicated user database. The database is provisioned by
the customer who is responsible for its backup and availability.
User requests come in through the website's business logic, typically consisting of a load balancer or ingress controller and whatever site specific services are being provided.
Usually in modern deployments user authentication is done either by a cloud authentication service (e.g. Google Apple, Microsoft, Azure), or an on-premesis software such as Keycloak. Na-user can be used to securely store user passwords for typical userid/password authentication, though this is no longer recommended in favor of modern standards like Webauthn (FIDO) or OAuth.
Note that the na-user
service can provide user state information to any
authentication service via API, such as information on whether the user
is banned or disabled.
At the end of authentication the business logic typically has some sort
of user identifier like a username or UUID. This can then be passed to
the na-user
service to keep track of various customer information.
The service is very flexible about what kind of user IDs it can accept
or generate.
From then on na-user
can be used to keep track of typical customer
information accessible via API for any internal business logic.
This can be usernames, email or postal addresses, screen
names, timezones, language choices, social media links, verification
status, activity timestamps, and so on.
Basically na-user
abstracts the implementation of this sometimes complex
user data infrastructure behind a simple JSON REST API.
Behind the API the na-user
service takes care of the details
of managing and validating user metadata, setting up the database
tables, running efficient SQL queries, marshalling data to JSON,
and dealing with errors.
na-user
also plays nicely with modern Kubernetes environments by providing
standard features such as metrics, health and liveliness endpoints,
OpenTracing spans, secrets handling, and so on.
Authentication Architecture
na-user does not provide end user authentication directly. It is primarily meant to be used as a headless service, downstream from other internal services.
Services and administrators authenticate to na-user using basic HTTP authentication. Note that na-user fully supports the use of SSL/TLS both between services and in its connection to the database.
The recommended setup is to encrypt the link to na-user with SSL/TLS using certificates, and use basic authentication to authorize the API calls.
Note that in Kubernetes environments the network mesh may already encrypt inter-service communications, in which case setting up separate SSL certificates is not needed.
See the API Authentication section for details.
Scaling and High Availability
The simplest architectural use case is to have one na-user
Docker container
talking to one database. Scaling can then be done by simply adding resources
to the virtual or real machine where the services are running.
Since the na-user
container is stateless, scaling can also be done by
increasing the number of the na-user
containers and load balancing between
them. Additionally scaling can be done by adding one or more database
instances and using well known patterns such as read only replicas or
partitioning traffic between multiple masters.
The ability to run multiple load balanced na-user
containers leads naturally
to high availability of the service. You can run multiple na-user
containers
and handle failover at the load balancer level. Alternatively if running
under Kubernetes the system can be set up to respawn the na-user
container
should it fail.
To achieve high availability the backing database must also be set up appropriately, for example with multi master, failover, or disaster recovery features, a topic out of scoope for this guide.
Security
Data You Don't Have
User data is some of the most sensitive data a modern business
posesses. The most secure data is data you don't have. The first line of
defense is simply not to record any data you don't absolutely need. This
is easy to do with na-user
, because virtually all user data it deals with
is optional. The minimal amount of information you need to use na-user
is an
opaque random userid. You can associate a wide variety of typical user information
with that userid, but all of it is optional. Record only what you need.
Transport Security
The na-user
API strives to be secure by design. The HTTP transport only
supports SSL/TLS 1.3. It is expected that internal API
calls to na-user
will be protected by key and certificate files
specified in the configuration. 1
Authentication
API authentication is done by using basic HTTP username/password authentication.
On first startup a secret password for the admin
user is set via
configuration file or environment variable. All subsequent API calls
must use the admin/password combination to authenticate.
See the API Authentication section for details.
Encryption
The na-user
server encrypts certain sensitive values.
The administrator password must be encrypted in the database to
authenticate API calls against a password hash. na-user
uses bcrypt
with a default workfactor of 12 to generate and store password hashes. 2
Certain values such as paging tokens returned by the API must also be signed and encrypted using a configurable encryption secret. This secret is provided in a configuration file or via an environment variable. This secret is used to encrypt using a 256-bit AES-GCM cipher with a random nonce. Signatures use ECDSA curve P256.
IMPORTANT
If running multiple na-user
containers it is important that all containers are
configured with the same encryption secret, or funtionality such as
paging will appear broken to API clients.
Data Encryption at Rest
Storing encrypted user data in the database is out of scope for na-user
. However
it is possible to use native database methods to store all data encrypted.
The following links discuss the options and limitations for data encryption at rest.