Files
Dušan Borovčanin 61d0427898 NOISSUE - Rename to Magistrala (#3427)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-04-06 15:23:42 +02:00

307 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Groups
The Groups service exposes HTTP and gRPC APIs for organizing entities into hierarchical groups within a domain, managing membership, permissions, and roles. It handles group lifecycle (create/update/enable/disable/delete), parent/child relationships, listings (flat or tree), and role-based access.
For a deeper overview of Magistrala, see the [official documentation][doc].
## Configuration
The service is configured via environment variables (unset values fall back to defaults).
| Variable | Description | Default |
| ------------------------------------ | ------------------------------------------------------------------------ | ------------------------------ |
| `MG_GROUPS_LOG_LEVEL` | Log level for Groups (debug, info, warn, error) | debug |
| `MG_GROUPS_HTTP_HOST` | Groups service HTTP host | groups |
| `MG_GROUPS_HTTP_PORT` | Groups service HTTP port | 9004 |
| `MG_GROUPS_HTTP_SERVER_CERT` | Path to PEM-encoded HTTP server certificate | "" |
| `MG_GROUPS_HTTP_SERVER_KEY` | Path to PEM-encoded HTTP server key | "" |
| `MG_GROUPS_HTTP_SERVER_CA_CERTS` | Path to trusted CA bundle for the HTTP server | "" |
| `MG_GROUPS_HTTP_CLIENT_CA_CERTS` | Path to client CA bundle to require HTTP mTLS | "" |
| `MG_GROUPS_GRPC_HOST` | Groups service gRPC host | groups |
| `MG_GROUPS_GRPC_PORT` | Groups service gRPC port | 7004 |
| `MG_GROUPS_GRPC_SERVER_CERT` | Path to PEM-encoded gRPC server certificate | "" |
| `MG_GROUPS_GRPC_SERVER_KEY` | Path to PEM-encoded gRPC server key | "" |
| `MG_GROUPS_GRPC_SERVER_CA_CERTS` | Path to trusted CA bundle for the gRPC server | "" |
| `MG_GROUPS_GRPC_CLIENT_CA_CERTS` | Path to client CA bundle to require gRPC mTLS | "" |
| `MG_GROUPS_DB_HOST` | Database host address | groups-db |
| `MG_GROUPS_DB_PORT` | Database host port | 5432 |
| `MG_GROUPS_DB_USER` | Database user | magistrala |
| `MG_GROUPS_DB_PASS` | Database password | magistrala |
| `MG_GROUPS_DB_NAME` | Name of the database used by the service | groups |
| `MG_GROUPS_DB_SSL_MODE` | Database connection SSL mode (disable, require, verify-ca, verify-full) | disable |
| `MG_GROUPS_DB_SSL_CERT` | Path to the PEM-encoded certificate file | "" |
| `MG_GROUPS_DB_SSL_KEY` | Path to the PEM-encoded key file | "" |
| `MG_GROUPS_DB_SSL_ROOT_CERT` | Path to the PEM-encoded root certificate file | "" |
| `MG_GROUPS_INSTANCE_ID` | Groups instance ID (auto-generated when empty) | "" |
| `MG_GROUPS_EVENT_CONSUMER` | NATS consumer name for domain events | groups |
| `MG_SPICEDB_HOST` | SpiceDB host for policy checks | magistrala-spicedb |
| `MG_SPICEDB_PORT` | SpiceDB port | 50051 |
| `MG_SPICEDB_SCHEMA_FILE` | Path to SpiceDB schema file used to seed available actions | "/schema.zed" |
| `MG_SPICEDB_PRE_SHARED_KEY` | SpiceDB preshared key | 12345678 |
| `MG_ES_URL` | Event store URL | nats://nats:4222 |
| `MG_JAEGER_URL` | Jaeger server URL | <http://jaeger:4318/v1/traces> |
| `MG_JAEGER_TRACE_RATIO` | Trace sampling ratio | 1.0 |
| `MG_SEND_TELEMETRY` | Send telemetry to the Magistrala call-home server | true |
| `MG_AUTH_GRPC_URL` | Auth service gRPC URL | "" |
| `MG_AUTH_GRPC_TIMEOUT` | Auth service gRPC request timeout | 1s |
| `MG_AUTH_GRPC_CLIENT_CERT` | Path to the PEM-encoded Auth gRPC client certificate | "" |
| `MG_AUTH_GRPC_CLIENT_KEY` | Path to the PEM-encoded Auth gRPC client key | "" |
| `MG_AUTH_GRPC_SERVER_CA_CERTS` | Path to the PEM-encoded Auth gRPC trusted CA bundle | "" |
| `MG_GROUPS_CALLOUT_URLS` | Comma-separated list of HTTP callout targets invoked on group operations | "" |
| `MG_GROUPS_CALLOUT_METHOD` | HTTP method for callouts (POST or GET) | POST |
| `MG_GROUPS_CALLOUT_TLS_VERIFICATION` | Verify TLS certificates for callouts | false |
| `MG_GROUPS_CALLOUT_TIMEOUT` | Callout request timeout | 10s |
| `MG_GROUPS_CALLOUT_CA_CERT` | CA bundle for verifying callout targets | "" |
| `MG_GROUPS_CALLOUT_CERT` | Client certificate for mTLS callouts | "" |
| `MG_GROUPS_CALLOUT_KEY` | Client key for mTLS callouts | "" |
| `MG_GROUPS_CALLOUT_OPERATIONS` | Comma-separated list of operation names that should trigger callouts | "" |
**Note**: Set `MG_GROUPS_CALLOUT_OPERATIONS` to a subset of `OpCreateGroup`, `OpViewGroup`, `OpUpdateGroup`, `OpEnableGroup`, `OpDisableGroup`, `OpDeleteGroup`, `OpListGroups`, `OpHierarchy`, `OpAddParentGroup`, `OpRemoveParentGroup`, `OpAddChildrenGroups`, `OpRemoveChildrenGroups`, `OpRemoveAllChildrenGroups`, or `OpListChildrenGroups` to filter which actions produce callouts.
## Deployment
The service ships as a Docker container. See the [`groups` section](https://github.com/absmach/magistrala/blob/main/docker/docker-compose.yaml#L950-L1035) in `docker-compose.yaml` for deployment configuration.
To build and run locally:
```bash
# download the latest version of the service
git clone https://github.com/absmach/magistrala
cd magistrala
# compile the groups service
make groups
# copy binary to $GOBIN
make install
# set the environment variables and run the service
MG_GROUPS_LOG_LEVEL=debug \
MG_GROUPS_HTTP_HOST=groups \
MG_GROUPS_HTTP_PORT=9004 \
MG_GROUPS_HTTP_SERVER_CERT="" \
MG_GROUPS_HTTP_SERVER_KEY="" \
MG_GROUPS_GRPC_HOST=groups \
MG_GROUPS_GRPC_PORT=7004 \
MG_GROUPS_GRPC_SERVER_CERT="" \
MG_GROUPS_GRPC_SERVER_KEY="" \
MG_GROUPS_GRPC_SERVER_CA_CERTS="" \
MG_GROUPS_GRPC_CLIENT_CA_CERTS="" \
MG_GROUPS_DB_HOST=groups-db \
MG_GROUPS_DB_PORT=5432 \
MG_GROUPS_DB_USER=magistrala \MG_GROUPS_DB_PASS=magistrala \MG_GROUPS_DB_NAME=groups \
MG_GROUPS_DB_SSL_MODE=disable \
MG_GROUPS_DB_SSL_CERT="" \
MG_GROUPS_DB_SSL_KEY="" \
MG_GROUPS_DB_SSL_ROOT_CERT="" \
MG_AUTH_GRPC_URL="" \
MG_AUTH_GRPC_TIMEOUT=1s \
MG_AUTH_GRPC_CLIENT_CERT="" \
MG_AUTH_GRPC_CLIENT_KEY="" \
MG_AUTH_GRPC_SERVER_CA_CERTS="" \
MG_DOMAINS_GRPC_URL=domains:7003 \
MG_DOMAINS_GRPC_TIMEOUT=1s \
MG_DOMAINS_GRPC_CLIENT_CERT="" \
MG_DOMAINS_GRPC_CLIENT_KEY="" \
MG_DOMAINS_GRPC_SERVER_CA_CERTS="" \
MG_CHANNELS_GRPC_URL=channels:7005 \
MG_CHANNELS_GRPC_TIMEOUT=1s \
MG_CHANNELS_GRPC_CLIENT_CERT="" \
MG_CHANNELS_GRPC_CLIENT_KEY="" \
MG_CHANNELS_GRPC_SERVER_CA_CERTS="" \
MG_CLIENTS_GRPC_URL=clients:7000 \
MG_CLIENTS_GRPC_TIMEOUT=1s \
MG_CLIENTS_GRPC_CLIENT_CERT="" \
MG_CLIENTS_GRPC_CLIENT_KEY="" \
MG_CLIENTS_GRPC_SERVER_CA_CERTS="" \
MG_SPICEDB_HOST=localhost \
MG_SPICEDB_PORT=50051 \
MG_SPICEDB_SCHEMA_FILE=schema.zed \
MG_SPICEDB_PRE_SHARED_KEY=12345678 \
MG_ES_URL=nats://localhost:4222 \
MG_JAEGER_URL=<http://localhost:4318/v1/traces> \
MG_JAEGER_TRACE_RATIO=1.0 \
MG_GROUPS_CALLOUT_URLS="" \
MG_GROUPS_CALLOUT_METHOD=POST \
MG_GROUPS_CALLOUT_TLS_VERIFICATION=false \
MG_GROUPS_CALLOUT_TIMEOUT=10s \
MG_GROUPS_CALLOUT_CA_CERT="" \
MG_GROUPS_CALLOUT_CERT="" \
MG_GROUPS_CALLOUT_KEY="" \
MG_GROUPS_CALLOUT_OPERATIONS="" \
MG_SEND_TELEMETRY=true \
MG_GROUPS_INSTANCE_ID="" \
$GOBIN/magistrala-groups
```
## Usage
Groups supports the following operations:
| Operation | Description |
| ---------------------------------- | ----------------------------------------------------------------------- |
| `create` | Create a new group within a domain |
| `list` | List groups (flat list or tree) with filters for metadata, tags, status |
| `get` | Retrieve a single group (optionally with role memberships) |
| `update` | Update a groups name, description, tags, or metadata |
| `enable` / `disable` | Enable or disable a group |
| `delete` | Permanently delete a group |
| `add-parent` / `remove-parent` | Assign or remove a parent group |
| `add-children` / `remove-children` | Attach or detach child groups (or remove all children) |
| `list-children` | List children at specific depth ranges |
| `hierarchy` | Fetch ancestors/descendants as a tree or list |
| `roles` | Create/list/update/delete group roles; manage role actions and members |
### API Examples
#### Create a Group
```bash
curl -X POST http://localhost:9004/<domainID>/groups \
-H "Authorization: Bearer <your_access_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "edge-devices",
"description": "All edge devices",
"metadata": { "region": "eu-west-1" },
"tags": ["iot","edge"],
"parent_id": "",
"status": "enabled"
}'
```
#### List Groups (flat)
```bash
curl -X GET "http://localhost:9004/<domainID>/groups?limit=10&status=enabled" \
-H "Authorization: Bearer <your_access_token>"
```
#### Retrieve a Group (with Roles)
```bash
curl -X GET "http://localhost:9004/<domainID>/groups/<groupID>?roles=true" \
-H "Authorization: Bearer <your_access_token>"
```
#### Update a Group
```bash
curl -X PUT http://localhost:9004/<domainID>/groups/<groupID> \
-H "Authorization: Bearer <your_access_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "edge-ops",
"description": "Edge operations",
"metadata": { "region": "eu-west-1", "env": "prod" },
"tags": ["iot","ops"]
}'
```
#### Enable or Disable a Group
```bash
curl -X POST http://localhost:9004/<domainID>/groups/<groupID>/enable \
-H "Authorization: Bearer <your_access_token>"
curl -X POST http://localhost:9004/<domainID>/groups/<groupID>/disable \
-H "Authorization: Bearer <your_access_token>"
```
#### Manage Hierarchy
```bash
# Add a parent
curl -X POST http://localhost:9004/<domainID>/groups/<groupID>/parents \
-H "Authorization: Bearer <your_access_token>" \
-H "Content-Type: application/json" \
-d '{ "parent_id": "<parentID>" }'
# List children between levels 1 and 2
curl -X GET "http://localhost:9004/<domainID>/groups/<groupID>/children?start_level=1&end_level=2&limit=10" \
-H "Authorization: Bearer <your_access_token>"
```
## Roles Management for Groups
Group roles use the shared role manager. Supported operations mirror domain roles (create, list, view, update, delete roles; add/list/remove actions; add/list/remove members; list available actions).
Example: create a group role
```bash
curl -X POST http://localhost:9004/<domainID>/groups/<groupID>/roles \
-H "Authorization: Bearer <your_access_token>" \
-H "Content-Type: application/json" \
-d '{
"role_name": "group-admin",
"optional_actions": ["manage_role_permission", "update_permission"],
"optional_members": ["<userID>"]
}'
```
List available actions for groups:
```bash
curl -X GET http://localhost:9004/<domainID>/groups/roles/available-actions \
-H "Authorization: Bearer <your_access_token>"
```
## Implementation Details
- Groups are stored in PostgreSQL with `ltree` paths for hierarchy queries; domain migrations are applied alongside group migrations for referential integrity.
- Role tables are provisioned per entity with a `groups_` prefix.
- Event notifications are published to `MG_ES_URL`; domain events are consumed to keep group data aligned.
- Authorization and roles are enforced through SpiceDB and shared policy middleware.
- Optional HTTP callouts (pre-operation hooks) are controlled via `MG_GROUPS_CALLOUT_*`.
- Observability: Jaeger tracing, Prometheus metrics at `/metrics`, and a `/health` endpoint.
### Groups Table
| Column | Type | Description |
| ------------- | ------------- | ------------------------------------------------------ |
| `id` | VARCHAR(36) | UUID of the group (primary key) |
| `parent_id` | VARCHAR(36) | Optional parent group (self-referential FK) |
| `domain_id` | VARCHAR(36) | Owning domain |
| `name` | VARCHAR(1024) | Group name |
| `description` | VARCHAR(1024) | Optional description |
| `metadata` | JSONB | Arbitrary metadata |
| `tags` | TEXT[] | Group tags |
| `path` | LTREE | Hierarchical path for fast ancestor/descendant queries |
| `created_at` | TIMESTAMPTZ | Creation timestamp |
| `updated_at` | TIMESTAMPTZ | Last update timestamp |
| `updated_by` | VARCHAR(254) | Actor who last updated the group |
| `status` | SMALLINT | 0 = enabled, 1 = disabled, 2 = deleted |
## Best Practices
- Model hierarchy deliberately: keep depth reasonable and avoid cycles by design.
- Use tags/metadata to segment groups by environment, region, or ownership for filtering.
- Prefer `disable` before `delete` when you need reversible off-boarding.
- Use roles sparingly and audit with `list-role-members`; grant only required actions.
- Fetch children with bounded levels to keep queries efficient.
- Limit callouts to necessary operations via `MG_GROUPS_CALLOUT_OPERATIONS`.
## Versioning and Health Check
The Groups service exposes `/health` with status and build metadata.
```bash
curl -X GET http://localhost:9004/health \
-H "accept: application/health+json"
```
Example response:
```json
{
"status": "pass",
"version": "0.18.0",
"commit": "7d6f4dc4f7f0c1fa3dc24eddfb18bb5073ff4f62",
"description": "groups service",
"build_time": "1970-01-01_00:00:00"
}
```
For full API coverage, see the [Groups API documentation](https://docs.api.magistrala.absmach.eu/?urls.primaryName=api%2Fgroups.yaml).
[doc]: https://magistrala.absmach.eu/docs/