Administrating Users - NGSI-v2 Smart Supermarket Tutorials
Administrating Users - NGSI-v2 Smart Supermarket Tutorials
FIWARE Security
Background: This tutorial does not use the NGSI-v2 interface directly. it covers
background information about Identity Management, which is then used in
subsequent chapters.
Identity Management
"If one meets a powerful person — ask them five questions: ‘What power have you
got? Where did you get it from? In whose interests do you exercise it? To whom are
you accountable? And how can we get rid of you?’"
— Anthony Wedgwood Benn (The Five Essential Questions of Democracy)
In computer security terminology, Identity management is the security and business discipline
that "enables the right individuals to access the right resources at the right times and for the
right reasons". It addresses the need to ensure appropriate access to resources across disparate
systems.
The FIWARE framework consists of a series of separate components, and the security chapter
aims to implement the common needs of these components regarding who (or what) gets to
access which resources within the system, but before access to resources can be locked down,
the identity of the person (or service) making the request needs to be known. The FIWARE
Keyrock Generic Enabler sets up all the common characteristics of an Identity Management
System out-of-the-box, so that other components are able to use standard authentication
mechanisms to accept or reject requests based on industry standard protocols.
Identity Management therefore covers the issues of how to gain an identity within the system,
the protection of that identity and the surrounding technologies such as passwords and
network protocols.
Additionally, two further non-human application objects can be secured within a FIWARE
application:
IoTAgent - a proxy between IoT Sensors and the Context Broker.
PEPProxy - a middleware for use between generic enablers challenging the rights of a user.
The relationship between the objects can be seen below - the entities marked in red are used
directly within this tutorial:
latest
Video : Introduction To Keyrock
Architecture
This introduction will only make use of one FIWARE component - the Keyrock Identity
Management Generic Enabler. Usage of Keyrock alone is insufficient for an application to
qualify as “Powered by FIWARE”. Additionally, will be persisting user data in a MySQL database.
The overall architecture will consist of the following elements:
One FIWARE Generic Enabler:
Since all interactions between the services are initiated by HTTP requests, the services can be
containerized and run from exposed ports.
latest
Keyrock Configuration
keyrock:
image: quay.io/fiware/idm
container_name: fiware-keyrock
hostname: keyrock
depends_on:
- mysql-db
ports:
- '3005:3005'
- '3443:3443'
environment:
- DATABASE_HOST=mysql-db
- IDM_DB_PASS_FILE=/run/secrets/my_secret_data
- IDM_DB_USER=root
- IDM_HOST=http://localhost:3005
- IDM_PORT=3005
- IDM_HTTPS_ENABLED=true
- IDM_HTTPS_PORT=3443
- IDM_ADMIN_USER=admin
- [email protected]
- IDM_ADMIN_PASS=1234
secrets:
- my_secret_data
Note HTTPS should be used throughout for any secured application, but to do this
properly, Keyrock requires a trusted SSL certificate - the default certificate is self-
certified and available for testing purposes. The certificates can be overridden by
attaching a volume to replace the files under /opt/fiware-idm/certs.
In a production environment, all access should occur over HTTPS, to avoid sending any
sensitive information using plain-text. Alternatively HTTP can be used within a private
network behind a configured HTTPS Reverse Proxy.
The port 3005 offering the HTTP protocol is being exposed for demonstration purposes
only and to simplify the interactions within this tutorial - you may also use HTTPS on
port 3443 with certain caveats.
If you want to use HTTPS to access the REST API when you are using Postman, ensure
that SSL certificate verification is OFF. If you want to use HTTPS to access the web
front-end, please accept any security warnings issued.
IDM_HOST http://localhost:3005 Hostname of the Keyrock App Server - used in activation eMails
when signing up users
IDM_PORT 3005 Port used by the Keyrock App Server for HTTP traffic - this has
been altered from the default 3000 port to avoid clashes
IDM_HTTPS_ENABLED true Whether to offer HTTPS Support - this will use the self-signed certs
unless overridden
IDM_HTTPS_PORT 3443 Port used by the Keyrock App Server for HTTP traffic this has been
altered from the default 443
latest
Note that this example has secured the MySQL password using Docker Secrets By
using IDM_DB_PASS with the _FILE suffix and referring to a secrets file location. This
avoids exposing the password as an ENV variable in plain-text - either in the
Dockerfile Image or as an injected variable which could be read using docker
inspect.
The following list of variables (where used) should be set via secrets with the _FILE
suffix in a Production System:
IDM_SESSION_SECRET
IDM_ENCRYPTION_KEY
IDM_DB_PASS
IDM_DB_USER
IDM_ADMIN_ID
IDM_ADMIN_USER
IDM_ADMIN_EMAIL
IDM_ADMIN_PASS
IDM_EX_AUTH_DB_USER
IDM_EX_AUTH_DB_PASS
MySQL Configuration
mysql-db:
image: mysql:5.7
hostname: mysql-db
container_name: db-mysql
expose:
- '3306'
ports:
- '3306:3306'
networks:
- default
environment:
- 'MYSQL_ROOT_PASSWORD_FILE=/run/secrets/my_secret_data'
- 'MYSQL_ROOT_HOST=172.18.1.5'
volumes:
- mysql-db:/var/lib/mysql
secrets:
- my_secret_data
MYSQL_ROOT_PASSWORD 123. specifies a password that is set for the MySQL root account - secured by Docker
Secrets (see below)
MYSQL_ROOT_HOST root By default, MySQL creates the root'@'localhost account. This account can
only be connected to from inside the container. Setting this environment
variable allows root connections from other hosts
Start Up
To start the installation, do the following:
#!/bin/bash
git clone https://github.com/FIWARE/tutorials.Identity-Management.git
cd tutorials.Identity-Management
git checkout NGSI-v2
./services create
Note The initial creation of Docker images can take up to three minutes
Thereafter, all services can be initialized from the command-line by running the services Bash
script provided within the repository:
./services start
Note: If you want to clean up and start over again you can do so with the following
command:
latest
./services stop
Reading Directly From The Keyrock MySQL Database
All Identify Management records and relationships are held within the attached MySQL
database. This can be accessed by entering the running Docker container as shown:
Where <user> and <password> match the values defined in the docker-compose file for
MYSQL_ROOT_PASSWORD and MYSQL_ROOT_USER. The default values for the tutorial are usually
root and secret.
The Keyrock MySQL database deals with all aspects of application security including storing
users, passwords, etc.; defining access rights and dealing with OAuth2 authorization protocols.
The complete database relationship diagram can be found here.
keyrock URL for the location of the Keyrock service localhost:3005 for HTTP or
localhost:3443 for HTTPS
organization- type of role a user has within an organization either owner or member
role-id member
Tokens are designed to expire after a set period. If the X-Auth-token value you are using has
expired, log-in again to obtain a new token.
Authentication
Video : Creating User Accounts With The Keyrock GUI
Click on the image above to watch a video demonstrating how to create users with the
Keyrock GUI.
Logging In To Keyrock
The Log-in Screen allows an existing user to identify themselves and obtain a token for further
operations. It is the initial start-up screen of the Keyrock GUI - http://localhost:3005/idm
(or https://localhost:3443/idm and accept the warnings).
latest
Enter a username and password to enter the Keyrock application. The default super-user has
the values [email protected] and 1234.
1 Request:
Response:
Tip: Use jq to format the JSON responses in this tutorial. Pipe the result by appending
| jq '.'
The response header returns an X-Subject-token which identifies who has logged on the
application. This token is required in all subsequent requests to gain access
{
"token": {
"methods": ["password"],
"expires_at": "2018-07-30T13:02:37.116Z"
},
"idm_authorization_config": {
"level": "basic",
"authzforce": false
}
}
2 Request:
curl -X GET \
'http://localhost:3005/v1/auth/tokens' \
-H 'Content-Type: application/json' \
-H 'X-Auth-token: {{X-Auth-token}}' \
-H 'X-Subject-token: {{X-Subject-token}}'
Response:
The response will return the details of the associated user:
latest
{
"access_token": "51f2e380-c959-4dee-a0af-380f730137c3",
"expires": "2018-07-30T13:02:37.000Z",
"valid": true,
"User": {
"id": "admin",
"username": "admin",
"email": "[email protected]",
"date_password": "2018-07-30T09:55:38.000Z",
"enabled": true,
"admin": true
}
}
Refresh Token
Tokens are time limited - it is no longer possible to gain access once a token has expired.
However, it is possible to refresh a token for a newer one prior to expiry.
Most applications use this endpoint to avoid timing out a user whilst they are interacting with
the application.
The token value, d848eb12-889f-433b-9811-6a4fbf0b86ca was acquired when the user
logged on for the first time.
3 Request:
Response:
A new token is returned in the X-Subject-Token header:
{
"token": {
"methods": ["token"],
"expires_at": "2018-07-30T13:13:20.567Z"
},
"idm_authorization_config": {
"level": "basic",
"authzforce": false
}
}
Dramatis Personae
The following people legitimately have accounts within the Application:
Alice, she will be the Administrator of the Keyrock Application.
Bob, the Regional Manager of the supermarket chain - he has several store managers under
him:
Manager1
Manager2
Charlie, the Head of Security of the supermarket chain - he has several store detectives
under him:
Detective1
Detective2
Once an account is created, the user is emailed to confirm their existence and activate their
account.
REST API
The REST API is also able to create and amend users without their own interaction - this could
be useful for bulk CRUD actions for example.
Note - an eMail server must be configured to send out invites properly, otherwise the
invitation may be deleted as spam. For testing purposes, it is easier to update the
users table directly: update user set enabled = 1;
All the CRUD actions for Users require an X-Auth-token header from a previously logged in
administrative user to be able to read or modify other user accounts. The standard CRUD
actions are assigned to the appropriate HTTP verbs (POST, GET, PATCH and DELETE) under the
/v1/users endpoint.
Creating Users
To create a new user, send a POST request to the /v1/users endpoint containing the
username,email and password along with the X-Auth-token header from a previously logged
in administrative user.
4 Request:
Response:
The response returns the details of the created user:
latest
{
"user": {
"id": "3b3a5ad5-afd3-4baa-a538-25c7fe7cbf6a",
"image": "default",
"gravatar": false,
"enabled": true,
"admin": false,
"starters_tour_ended": false,
"username": "alice",
"email": "[email protected]",
"date_password": "2018-07-30T12:51:26.813Z"
}
}
To grant super-admin power to a newly created user account, the database can be altered
directly:
latest
curl -iX POST \
'http://localhost:3005/v1/users' \
-H 'Content-Type: application/json' \
-H 'X-Auth-token: {{X-Auth-token}}' \
-d '{
"user": {
"username": "detective1",
"email": "[email protected]",
"password": "test"
}
}'
5 Request:
To request
curl -X GET \
'http://localhost:3005/v1/users/{{user-id}}' \
-H 'Content-Type: application/json' \
-H 'X-Auth-token: {{X-Auth-token}}'
Response:
The response contains basic details of the account in question:
{
"user": {
"id": "96154659-cb3b-4d2d-afef-18d6aec0518e",
"username": "alice",
"email": "[email protected]",
"enabled": true,
"admin": false,
"image": "default",
"gravatar": false,
"date_password": "2018-07-30T09:56:37.000Z",
"description": null,
"website": null
}
}
6 Request:
curl -X GET \
'http://localhost:3005/v1/users' \
-H 'Content-Type: application/json' \
-H 'X-Auth-token: {{X-Auth-token}}'
Response:
The response contains basic details of all accounts:
latest
{
"users": [
{
"id": "06a2140f-ccc3-49e5-82a5-76bae48b38ba",
"username": "alice",
"email": "[email protected]",
"enabled": true,
"gravatar": false,
"date_password": "2018-07-30T11:41:14.000Z",
"description": null,
"website": null
},
{
"id": "27e6ae58-adc1-4aaf-a6a2-f207946ba57e",
"username": "bob",
"email": "[email protected]",
"enabled": true,
"gravatar": false,
"date_password": "2018-07-30T10:01:12.000Z",
"description": null,
"website": null
},
...etc
]
}
Update A User
Within the GUI, users can be updated from the settings page. This can also be done from the
command-line by making PATCH request to /v1/users/<user-id> endpoint when the user
ID is known. The X-Auth-token header must also be set.
7 Request:
Response:
The response lists the fields which have been updated:
{
"values_updated": {
"description": "Alice works for FIWARE",
"website": "http://www.fiware.org"
}
}
Delete A User
Within the GUI, users can delete their account from the settings page, selecting the Cancel
Account Option, once again a super-admin user can do this from the command-line by
sending a DELETE request to the /v1/users/{{user-id}} endpoint. The X-Auth-token
header must also be set.
8 Request:
REST API
Alternatively, the standard CRUD actions are assigned to the appropriate HTTP verbs (POST,
GET, PATCH and DELETE) under the /v1/organizations endpoint.
Create An Organization
To create a new organization, send a POST request to the /v1/organizations endpoint
containing the name and description along with the X-Auth-token header from a previously
logged-in user.
9 Request:
Response:
The Organization is created and the user who created it is automatically assigned as a user.
The response returns UUID to identify the new organization.
{
"organization": {
"id": "18deea43-e12a-4018-a45a-664c3158780d",
"image": "default",
"name": "Security",
"description": "This group is for the store detectives"
}
}
10 Request:
curl -X GET \
'http://localhost:3005/v1/organizations/{{organization-id}}' \
-H 'Content-Type: application/json' \
latest
-H 'X-Auth-token: {{X-Auth-token}}'
Response:
The response returns the details of the organization.
{
"organization": {
"id": "18deea43-e12a-4018-a45a-664c3158780d",
"name": "Security",
"description": "This group is for the store detectives",
"website": null,
"image": "default"
}
}
11 Request:
curl -X GET \
'http://localhost:3005/v1/organizations' \
-H 'Content-Type: application/json' \
-H 'X-Auth-token: {{X-Auth-token}}'
Response:
The response returns the details of the visible organizations.
{
"organizations": [
{
"role": "owner",
"Organization": {
"id": "18deea43-e12a-4018-a45a-664c3158780d",
"name": "Security",
"description": "This group is for the store detectives",
"image": "default",
"website": null
}
},
{
"role": "owner",
"Organization": {
"id": "a45f9b5a-dd23-4d0f-a0d4-e97e2d7431a3",
"name": "Management",
"description": "This group is for the store manangers",
"image": "default",
"website": null
}
}
]
}
Update An Organization
To amend the details of an existing organization, a PATCH request is send to the
/v1/organizations/{{organization-id}} endpoint.
12 Request:
Response:
The response contains a list of the fields which have been amended:
{
"values_updated": {
"name": "FIWARE Security",
"description": "The FIWARE Foundation is the legal independent body
promoting, augmenting open-source FIWARE technologies",
"website": "https://fiware.org"
}
latest
}
Delete An Organization
13 Request:
To add a user as a member of an organization, an owner must make a PUT request as shown,
including the <organization-id> and <user-id> in the URL path and identifying themselves
using an X-Auth-Token in the header.
14 Request:
Response:
The response lists the user's current role within the organization (i.e. member):
{
"user_organization_assignments": {
"role": "member",
"organization_id": "18deea43-e12a-4018-a45a-664c3158780d",
"user_id": "5e482345-2c48-410e-ae03-203d67a43cea"
}
}
15 Request:
Response:
The response lists the user's current role within the organization (i.e. owner):
{
"user_organization_assignments": {
"role": "owner",
"user_id": "5e482345-2c48-410e-ae03-203d67a43cea",
"organization_id": "18deea43-e12a-4018-a45a-664c3158780d"
}
}
latest
List Users Within An Organization
To list the users of an organization using the GUI, just click on the existing organization:
16 Request:
curl -X GET \
'http://localhost:3005/v1/organizations/{{organization-id}}/users' \
-H 'Content-Type: application/json' \
-H 'X-Auth-token: {{X-Auth-token}}'
Response:
The response contains the users list.
{
"organization_users": [
{
"user_id": "admin",
"organization_id": "18deea43-e12a-4018-a45a-664c3158780d",
"role": "owner"
},
{
"user_id": "5e482345-2c48-410e-ae03-203d67a43cea",
"organization_id": "18deea43-e12a-4018-a45a-664c3158780d",
"role": "member"
}
]
}
17 Request:
curl -X GET \
'http://localhost:3005/v1/organizations/{{organization-id}}/users/{{user-
id}}/organization_roles' \
-H 'Content-Type: application/json' \
-H 'X-Auth-token: {{X-Auth-token}}'
Response:
The response returns the role of the given <user-id>:
{
"organization_user": {
"user_id": "5e482345-2c48-410e-ae03-203d67a43cea",
"organization_id": "18deea43-e12a-4018-a45a-664c3158780d",
"role": "member"
}
}
18 Request:
curl -X DELETE \
'http://localhost:3005/v1/organizations/{{organization-id}}/users/{{user-
id}}/organization_roles/member' \
-H 'Content-Type: application/json' \
-H 'X-Auth-token: {{X-Auth-token}}'
latest