MF-1506 - Group-based Access Control (#1716)

* Move Things and Users to Clients

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>
Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Update Add and Delete Policies (#1792)

* Remove Policy Action Ranks

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Rebase Issues

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix CI Test Errors

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Adding Check on Subject For Clients

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Remove Check Client Exists

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Check When Sharing Clients

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Only Add User to Group When Sharing Things

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Remove clientType

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Minor Fix on ShareClient and Fix Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Policies Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Clean Up Things Authorization

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests on RetrieveAll

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Test ShareThing

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Merge Conflicts

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Remove Adding Policies. Only Use Ownership

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Check If Subject is same as Object

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Move Back To Union As Sometimes Policy is Empty and Fails to Evaluate on Ownership

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Entity Type For Failing Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix BUG in policy evaluation

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Comments Regarding checkAdmin

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests On Rebase

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Combine Authorize For Things and Users

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests On Rebase

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Error on Things SVC `unsupported protocol scheme`

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* Fix Bug on Things Authorization Cache (#1810)

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* Use Password instead of username in MQTT handler

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* Simplify MQTT authorization

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* Fix MQTT tests

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Add More Functions to SDK (#1811)

* Add More Functions to SDK

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Examples to GoDoc

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Update Unassign Interface

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Pass Subject as ID and Not Token on List Channels By Thing

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Bootstrap Errors For Element Check

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add empty line Before Return

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Reorder URLS in things mux

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Listing Things Policies

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Share Thing

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Examples to CLI Docs

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Update Identity To Update Another User

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Identify an Update Policies on Things

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Update Things Policies

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix GoDocs on Disconnect

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Change Authorize To Use AccessRequest

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* For Evaluate Policy Use AccessRequest (#1814)

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Add SDK Tests (#1812)

* Add Things Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Channel Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Certs Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Consumer Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Enrich Group Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Tests For Health

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Tests For Tokens

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Rename SDK for Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Policies Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Linter

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Make Variable Defination Inline

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Make Cache Key Duration Configurable (#1815)

* Make Cache Key Duration Configurable

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Rename ENV Var

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Update GoDocs (#1816)

* Add GoDocs

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Missing GoDoc Files

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Enable godot

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add License Information

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Add Call Home Client to Mainflux services (#1751)

* Move Things and Users to Clients

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>
Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: SammyOina <sammyoina@gmail.com>

* collect and send data package

Signed-off-by: SammyOina <sammyoina@gmail.com>

* create telemetry migrations

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add telemetry endpoints

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add transport

Signed-off-by: SammyOina <sammyoina@gmail.com>

* create service

Signed-off-by: SammyOina <sammyoina@gmail.com>

* remove homing server

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add call home to adapters

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add last seen

Signed-off-by: SammyOina <sammyoina@gmail.com>

* rename logger

Signed-off-by: SammyOina <sammyoina@gmail.com>

* remove homing client

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use unmerged repo

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use renamed module

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update call home version

Signed-off-by: SammyOina <sammyoina@gmail.com>

* edit documentation

Signed-off-by: SammyOina <sammyoina@gmail.com>

* align table

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use alias for call home client

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update callhome

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update call home pkg

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update call home

Signed-off-by: SammyOina <sammyoina@gmail.com>

* fix modules

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use mf build version

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use mf build version

Signed-off-by: SammyOina <sammyoina@gmail.com>

* restore default

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add call home for users and things

Signed-off-by: SammyOina <sammyoina@gmail.com>

* enable opting on call home

Signed-off-by: SammyOina <sammyoina@gmail.com>

* remove full stops

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update callhome client

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add call home to all services

Signed-off-by: SammyOina <sammyoina@gmail.com>

* fix build

Signed-off-by: SammyOina <sammyoina@gmail.com>

* restore sdk tests

Signed-off-by: SammyOina <sammyoina@gmail.com>

* remove unnecessary changes

Signed-off-by: SammyOina <sammyoina@gmail.com>

* restore health_test.go

Signed-off-by: SammyOina <sammyoina@gmail.com>

---------

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>
Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: SammyOina <sammyoina@gmail.com>
Co-authored-by: b1ackd0t <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

---------

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>
Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: SammyOina <sammyoina@gmail.com>
Co-authored-by: b1ackd0t <blackd0t@protonmail.com>
Co-authored-by: Sammy Kerata Oina <44265300+SammyOina@users.noreply.github.com>
This commit is contained in:
Dušan Borovčanin
2023-06-14 12:40:37 +02:00
committed by GitHub
parent 3d0d6e2112
commit 55e09c1921
1516 changed files with 171171 additions and 72075 deletions
+3 -2
View File
@@ -39,6 +39,7 @@ default values.
| MF_PROVISION_BS_CONTENT | Bootstrap service configs content, JSON format | {} |
| MF_PROVISION_CERTS_RSA_BITS | Certificate RSA bits parameter | 4096 |
| MF_PROVISION_CERTS_HOURS_VALID | Number of hours that certificate is valid | "2400h" |
| MF_SEND_TELEMETRY | Send telemetry to mainflux call home server | true |
By default, call to `/mapping` endpoint will create one thing and two channels (`control` and `data`) and connect it. If there is a requirement for different provision layout we can use [config](docker/configs/config.toml) file in addition to environment variables.
@@ -81,13 +82,13 @@ Example of provision layout below
```
## Authentication
In order to create necessary entities provision service needs to authenticate against Mainflux. To provide authentication credentials to the provision service you can pass it in an environment variable or in a config file as Mainflux user and password or as API token (that can be issued on `/users` or `/keys` endpoint of [auth](../auth/README.md)).
In order to create necessary entities provision service needs to authenticate against Mainflux. To provide authentication credentials to the provision service you can pass it in an environment variable or in a config file as Mainflux user and password or as API token that can be issued on `/users/tokens/issue`.
Additionally users or API token can be passed in Authorization header, this authentication takes precedence over others.
* `username`, `password` - (`MF_PROVISION_USER`, `MF_PROVISION_PASSWORD` in [.env](../.env), `mf_user`, `mf_pass` in [config.toml](../docker/addons/provision/configs/config.toml))
* API Key - (`MF_PROVISION_API_KEY` in [.env](../.env) or [config.toml](../docker/addons/provision/configs/config.toml))
* `Authorization: Bearer Token|ApiKey` - request authorization header containing either users token or API key. Check [auth](../auth/README.md).
* `Authorization: Bearer Token` - request authorization header containing either users token.
## Running
Provision service can be run as a standalone or in docker composition as addon to the core docker composition.
+6
View File
@@ -0,0 +1,6 @@
// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0
// Package api contains API-related concerns: endpoint definitions, middlewares
// and all resource representations.
package api
+3 -3
View File
@@ -9,19 +9,19 @@ import (
"fmt"
"time"
log "github.com/mainflux/mainflux/logger"
mflog "github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/provision"
)
var _ provision.Service = (*loggingMiddleware)(nil)
type loggingMiddleware struct {
logger log.Logger
logger mflog.Logger
svc provision.Service
}
// NewLoggingMiddleware adds logging facilities to the core service.
func NewLoggingMiddleware(svc provision.Service, logger log.Logger) provision.Service {
func NewLoggingMiddleware(svc provision.Service, logger mflog.Logger) provision.Service {
return &loggingMiddleware{logger, svc}
}
+18 -16
View File
@@ -5,10 +5,11 @@ package provision
import (
"fmt"
"io/ioutil"
"os"
mfclients "github.com/mainflux/mainflux/pkg/clients"
"github.com/mainflux/mainflux/pkg/errors"
"github.com/mainflux/mainflux/things"
"github.com/mainflux/mainflux/pkg/groups"
"github.com/pelletier/go-toml"
)
@@ -30,7 +31,7 @@ type ServiceConf struct {
MfCertsURL string `toml:"mf_certs_url"`
}
// Bootstrap represetns the Bootstrap config
// Bootstrap represetns the Bootstrap config.
type Bootstrap struct {
X509Provision bool `toml:"x509_provision"`
Provision bool `toml:"provision"`
@@ -38,7 +39,7 @@ type Bootstrap struct {
Content map[string]interface{} `toml:"content"`
}
// Gateway represetns the Gateway config
// Gateway represetns the Gateway config.
type Gateway struct {
Type string `toml:"type" json:"type"`
ExternalID string `toml:"external_id" json:"external_id"`
@@ -49,36 +50,37 @@ type Gateway struct {
CfgID string `toml:"cfg_id" json:"cfg_id"`
}
// Cert represetns the certificate config
// Cert represetns the certificate config.
type Cert struct {
TTL string `json:"ttl" toml:"ttl"`
}
// Config struct of Provision
// Config struct of Provision.
type Config struct {
File string `toml:"file"`
Server ServiceConf `toml:"server" mapstructure:"server"`
Bootstrap Bootstrap `toml:"bootstrap" mapstructure:"bootstrap"`
Things []things.Thing `toml:"things" mapstructure:"things"`
Channels []things.Channel `toml:"channels" mapstructure:"channels"`
Cert Cert `toml:"cert" mapstructure:"cert"`
File string `toml:"file"`
Server ServiceConf `toml:"server" mapstructure:"server"`
Bootstrap Bootstrap `toml:"bootstrap" mapstructure:"bootstrap"`
Things []mfclients.Client `toml:"things" mapstructure:"things"`
Channels []groups.Group `toml:"channels" mapstructure:"channels"`
Cert Cert `toml:"cert" mapstructure:"cert"`
SendTelemetry bool `toml:"-"`
}
// Save - store config in a file
// Save - store config in a file.
func Save(c Config, file string) error {
b, err := toml.Marshal(c)
if err != nil {
return errors.New(fmt.Sprintf("Error reading config file: %s", err))
}
if err := ioutil.WriteFile(file, b, 0644); err != nil {
if err := os.WriteFile(file, b, 0644); err != nil {
return errors.New(fmt.Sprintf("Error writing toml: %s", err))
}
return nil
}
// Read - retrieve config from a file
// Read - retrieve config from a file.
func Read(file string) (Config, error) {
data, err := ioutil.ReadFile(file)
data, err := os.ReadFile(file)
c := Config{}
if err != nil {
return c, errors.New(fmt.Sprintf("Error reading config file: %s", err))
+3
View File
@@ -1,3 +1,6 @@
// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0
// Package provision contains domain concept definitions needed to support
// Provision service feature, i.e. automate provision process.
package provision
+25 -20
View File
@@ -4,7 +4,7 @@ import (
"encoding/json"
"fmt"
"github.com/mainflux/mainflux/logger"
mflog "github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/pkg/errors"
SDK "github.com/mainflux/mainflux/pkg/sdk/go"
)
@@ -65,7 +65,7 @@ type Service interface {
}
type provisionService struct {
logger logger.Logger
logger mflog.Logger
sdk SDK.SDK
conf Config
}
@@ -82,7 +82,7 @@ type Result struct {
}
// New returns new provision service.
func New(cfg Config, sdk SDK.SDK, logger logger.Logger) Service {
func New(cfg Config, sdk SDK.SDK, logger mflog.Logger) Service {
return &provisionService{
logger: logger,
conf: cfg,
@@ -90,7 +90,7 @@ func New(cfg Config, sdk SDK.SDK, logger logger.Logger) Service {
}
}
// Mapping retrieves current configuration
// Mapping retrieves current configuration.
func (ps *provisionService) Mapping(token string) (map[string]interface{}, error) {
userFilter := SDK.PageMetadata{
Email: "",
@@ -106,7 +106,7 @@ func (ps *provisionService) Mapping(token string) (map[string]interface{}, error
}
// Provision is provision method for creating setup according to
// provision layout specified in config.toml
// provision layout specified in config.toml.
func (ps *provisionService) Provision(token, name, externalID, externalKey string) (res Result, err error) {
var channels []SDK.Channel
var things []SDK.Thing
@@ -137,16 +137,16 @@ func (ps *provisionService) Provision(token, name, externalID, externalKey strin
name = thing.Name
}
th.Name = name
thID, err := ps.sdk.CreateThing(th, token)
th, err := ps.sdk.CreateThing(th, token)
if err != nil {
res.Error = err.Error()
return res, errors.Wrap(ErrFailedThingCreation, err)
}
// Get newly created thing (in order to get the key).
th, err = ps.sdk.Thing(thID, token)
th, err = ps.sdk.Thing(th.ID, token)
if err != nil {
e := errors.Wrap(err, fmt.Errorf("thing id: %s", thID))
e := errors.Wrap(err, fmt.Errorf("thing id: %s", th.ID))
return res, errors.Wrap(ErrFailedThingRetrieval, e)
}
things = append(things, th)
@@ -155,15 +155,15 @@ func (ps *provisionService) Provision(token, name, externalID, externalKey strin
for _, channel := range ps.conf.Channels {
ch := SDK.Channel{
Name: channel.Name,
Metadata: channel.Metadata,
Metadata: SDK.Metadata(channel.Metadata),
}
chCreated, err := ps.sdk.CreateChannel(ch, token)
ch, err := ps.sdk.CreateChannel(ch, token)
if err != nil {
return res, err
}
ch, err = ps.sdk.Channel(chCreated, token)
ch, err = ps.sdk.Channel(ch.ID, token)
if err != nil {
e := errors.Wrap(err, fmt.Errorf("channel id: %s", chCreated))
e := errors.Wrap(err, fmt.Errorf("channel id: %s", ch.ID))
return res, errors.Wrap(ErrFailedChannelRetrieval, e)
}
channels = append(channels, ch)
@@ -283,15 +283,17 @@ func (ps *provisionService) createTokenIfEmpty(token string) (string, error) {
}
u := SDK.User{
Email: ps.conf.Server.MfUser,
Password: ps.conf.Server.MfPass,
Credentials: SDK.Credentials{
Identity: ps.conf.Server.MfUser,
Secret: ps.conf.Server.MfPass,
},
}
token, err := ps.sdk.CreateToken(u)
tkn, err := ps.sdk.CreateToken(u)
if err != nil {
return token, errors.Wrap(ErrFailedToCreateToken, err)
}
return token, nil
return tkn.AccessToken, nil
}
func (ps *provisionService) updateGateway(token string, bs SDK.BootstrapConfig, channels []SDK.Channel) error {
@@ -322,7 +324,7 @@ func (ps *provisionService) updateGateway(token string, bs SDK.BootstrapConfig,
if err := json.Unmarshal(b, &th.Metadata); err != nil {
return errors.Wrap(ErrGatewayUpdate, err)
}
if err := ps.sdk.UpdateThing(th, token); err != nil {
if _, err := ps.sdk.UpdateThing(th, token); err != nil {
return errors.Wrap(ErrGatewayUpdate, err)
}
return nil
@@ -336,10 +338,12 @@ func (ps *provisionService) errLog(err error) {
func clean(ps *provisionService, things []SDK.Thing, channels []SDK.Channel, token string) {
for _, t := range things {
ps.errLog(ps.sdk.DeleteThing(t.ID, token))
_, err := ps.sdk.DisableThing(t.ID, token)
ps.errLog(err)
}
for _, c := range channels {
ps.errLog(ps.sdk.DeleteChannel(c.ID, token))
_, err := ps.sdk.DisableChannel(c.ID, token)
ps.errLog(err)
}
}
@@ -351,7 +355,8 @@ func (ps *provisionService) recover(e *error, ths *[]SDK.Thing, chs *[]SDK.Chann
if errors.Contains(err, ErrFailedThingRetrieval) || errors.Contains(err, ErrFailedChannelCreation) {
for _, th := range things {
ps.errLog(ps.sdk.DeleteThing(th.ID, token))
_, err := ps.sdk.DisableThing(th.ID, token)
ps.errLog(err)
}
return
}