2019-10-07 08:14:47 -06:00
|
|
|
// Copyright (c) Mainflux
|
2019-01-09 15:42:23 +01:00
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
|
|
package bootstrap
|
|
|
|
|
|
|
|
import (
|
2019-08-02 14:35:31 +02:00
|
|
|
"crypto/aes"
|
|
|
|
"crypto/cipher"
|
|
|
|
"crypto/rand"
|
|
|
|
"encoding/json"
|
|
|
|
"io"
|
2019-01-09 15:42:23 +01:00
|
|
|
"net/http"
|
|
|
|
)
|
|
|
|
|
|
|
|
// bootstrapRes represent Mainflux Response to the Bootatrap request.
|
|
|
|
// This is used as a response from ConfigReader and can easily be
|
|
|
|
// replace with any other response format.
|
|
|
|
type bootstrapRes struct {
|
2023-07-31 15:17:14 +03:00
|
|
|
ThingID string `json:"thing_id"`
|
|
|
|
ThingKey string `json:"thing_key"`
|
|
|
|
Channels []channelRes `json:"channels"`
|
2019-08-02 14:35:31 +02:00
|
|
|
Content string `json:"content,omitempty"`
|
2019-05-22 23:22:19 +02:00
|
|
|
ClientCert string `json:"client_cert,omitempty"`
|
|
|
|
ClientKey string `json:"client_key,omitempty"`
|
2019-08-02 14:35:31 +02:00
|
|
|
CACert string `json:"ca_cert,omitempty"`
|
2019-01-30 16:40:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type channelRes struct {
|
|
|
|
ID string `json:"id"`
|
|
|
|
Name string `json:"name,omitempty"`
|
|
|
|
Metadata interface{} `json:"metadata,omitempty"`
|
2019-01-09 15:42:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (res bootstrapRes) Code() int {
|
|
|
|
return http.StatusOK
|
|
|
|
}
|
|
|
|
|
|
|
|
func (res bootstrapRes) Headers() map[string]string {
|
|
|
|
return map[string]string{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (res bootstrapRes) Empty() bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2019-08-02 14:35:31 +02:00
|
|
|
type reader struct {
|
|
|
|
encKey []byte
|
|
|
|
}
|
2019-01-09 15:42:23 +01:00
|
|
|
|
|
|
|
// NewConfigReader return new reader which is used to generate response
|
|
|
|
// from the config.
|
2019-08-02 14:35:31 +02:00
|
|
|
func NewConfigReader(encKey []byte) ConfigReader {
|
|
|
|
return reader{encKey: encKey}
|
2019-01-09 15:42:23 +01:00
|
|
|
}
|
|
|
|
|
2019-08-02 14:35:31 +02:00
|
|
|
func (r reader) ReadConfig(cfg Config, secure bool) (interface{}, error) {
|
2019-01-30 16:40:37 +01:00
|
|
|
var channels []channelRes
|
2023-07-31 15:17:14 +03:00
|
|
|
for _, ch := range cfg.Channels {
|
2019-01-30 16:40:37 +01:00
|
|
|
channels = append(channels, channelRes{ID: ch.ID, Name: ch.Name, Metadata: ch.Metadata})
|
|
|
|
}
|
2019-02-06 10:28:54 +01:00
|
|
|
|
2019-01-09 15:42:23 +01:00
|
|
|
res := bootstrapRes{
|
2023-07-31 15:17:14 +03:00
|
|
|
ThingKey: cfg.ThingKey,
|
|
|
|
ThingID: cfg.ThingID,
|
|
|
|
Channels: channels,
|
2019-08-02 14:35:31 +02:00
|
|
|
Content: cfg.Content,
|
2019-05-22 23:22:19 +02:00
|
|
|
ClientCert: cfg.ClientCert,
|
|
|
|
ClientKey: cfg.ClientKey,
|
2019-08-02 14:35:31 +02:00
|
|
|
CACert: cfg.CACert,
|
|
|
|
}
|
|
|
|
if secure {
|
|
|
|
b, err := json.Marshal(res)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return r.encrypt(b)
|
2019-01-09 15:42:23 +01:00
|
|
|
}
|
2019-02-06 10:28:54 +01:00
|
|
|
|
2019-01-09 15:42:23 +01:00
|
|
|
return res, nil
|
|
|
|
}
|
2019-08-02 14:35:31 +02:00
|
|
|
|
|
|
|
func (r reader) encrypt(in []byte) ([]byte, error) {
|
|
|
|
block, err := aes.NewCipher(r.encKey)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
ciphertext := make([]byte, aes.BlockSize+len(in))
|
|
|
|
iv := ciphertext[:aes.BlockSize]
|
|
|
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
stream := cipher.NewCFBEncrypter(block, iv)
|
|
|
|
stream.XORKeyStream(ciphertext[aes.BlockSize:], in)
|
|
|
|
return ciphertext, nil
|
|
|
|
}
|