mirror of
https://github.com/absmach/magistrala.git
synced 2026-06-23 04:10:28 +00:00
NOISSUE - Add cert revocation to SDK (#1693)
* initial commit Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * fix certificate revoking Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * change from mapstructure to json Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * add comments to serial modification Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * fix typo Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * update vault docker version Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * write env variables Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * change env path Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * return revocation time Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * revert to intermediate CA Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * remove deadcode Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * make revoke cert output readable Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * remove keybits and keytype Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * remove dead code Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * make inline Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * add empty line Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * remove commented code Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * remove keyBits Signed-off-by: rodneyosodo <socials@rodneyosodo.com> * remove keyBits Signed-off-by: rodneyosodo <socials@rodneyosodo.com> Signed-off-by: rodneyosodo <socials@rodneyosodo.com> Co-authored-by: rodneyosodo <socials@rodneyosodo.com>
This commit is contained in:
@@ -198,18 +198,12 @@ components:
|
||||
required:
|
||||
- thing_id
|
||||
- ttl
|
||||
- key_bits
|
||||
- key_type
|
||||
properties:
|
||||
thing_id:
|
||||
type: string
|
||||
format: uuid
|
||||
ttl:
|
||||
type: string
|
||||
key_type:
|
||||
type: string
|
||||
key_bits:
|
||||
type: integer
|
||||
|
||||
responses:
|
||||
ServiceError:
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ To issue a certificate:
|
||||
|
||||
TOK=`curl -s --insecure -S -X POST http://localhost/tokens -H 'Content-Type: application/json' -d '{"email":"edge@email.com","password":"12345678"}' | jq -r '.token'`
|
||||
|
||||
curl -s -S -X POST http://localhost:8204/certs -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"thing_id":<thing_id>, "key_bits":2048, "key_type":"rsa"}'
|
||||
curl -s -S -X POST http://localhost:8204/certs -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"thing_id":<thing_id>}'
|
||||
```
|
||||
|
||||
```json
|
||||
|
||||
@@ -16,7 +16,7 @@ func issueCert(svc certs.Service) endpoint.Endpoint {
|
||||
if err := req.validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res, err := svc.IssueCert(ctx, req.token, req.ThingID, req.TTL, req.KeyBits, req.KeyType)
|
||||
res, err := svc.IssueCert(ctx, req.token, req.ThingID, req.TTL)
|
||||
if err != nil {
|
||||
return certsRes{}, err
|
||||
}
|
||||
@@ -91,6 +91,12 @@ func revokeCert(svc certs.Service) endpoint.Endpoint {
|
||||
if err := req.validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return svc.RevokeCert(ctx, req.token, req.certID)
|
||||
res, err := svc.RevokeCert(ctx, req.token, req.certID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return revokeCertsRes{
|
||||
RevocationTime: res.RevocationTime,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ func NewLoggingMiddleware(svc certs.Service, logger log.Logger) certs.Service {
|
||||
return &loggingMiddleware{logger, svc}
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) IssueCert(ctx context.Context, token, thingID, ttl string, keyBits int, keyType string) (c certs.Cert, err error) {
|
||||
func (lm *loggingMiddleware) IssueCert(ctx context.Context, token, thingID, ttl string) (c certs.Cert, err error) {
|
||||
defer func(begin time.Time) {
|
||||
message := fmt.Sprintf("Method issue_cert for token: %s and thing: %s took %s to complete", token, thingID, time.Since(begin))
|
||||
if err != nil {
|
||||
@@ -36,7 +36,7 @@ func (lm *loggingMiddleware) IssueCert(ctx context.Context, token, thingID, ttl
|
||||
lm.logger.Info(fmt.Sprintf("%s without errors.", message))
|
||||
}(time.Now())
|
||||
|
||||
return lm.svc.IssueCert(ctx, token, thingID, ttl, keyBits, keyType)
|
||||
return lm.svc.IssueCert(ctx, token, thingID, ttl)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) ListCerts(ctx context.Context, token, thingID string, offset, limit uint64) (cp certs.Page, err error) {
|
||||
|
||||
@@ -30,13 +30,13 @@ func MetricsMiddleware(svc certs.Service, counter metrics.Counter, latency metri
|
||||
}
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) IssueCert(ctx context.Context, token, thingID string, ttl string, keyBits int, keyType string) (certs.Cert, error) {
|
||||
func (ms *metricsMiddleware) IssueCert(ctx context.Context, token, thingID, ttl string) (certs.Cert, error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "issue_cert").Add(1)
|
||||
ms.latency.With("method", "issue_cert").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return ms.svc.IssueCert(ctx, token, thingID, ttl, keyBits, keyType)
|
||||
return ms.svc.IssueCert(ctx, token, thingID, ttl)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) ListCerts(ctx context.Context, token, thingID string, offset, limit uint64) (certs.Page, error) {
|
||||
|
||||
@@ -10,8 +10,6 @@ const maxLimitSize = 100
|
||||
type addCertsReq struct {
|
||||
token string
|
||||
ThingID string `json:"thing_id"`
|
||||
KeyBits int `json:"key_bits"`
|
||||
KeyType string `json:"key_type"`
|
||||
TTL string `json:"ttl"`
|
||||
}
|
||||
|
||||
@@ -24,7 +22,7 @@ func (req addCertsReq) validate() error {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if req.TTL == "" || req.KeyType == "" || req.KeyBits == 0 {
|
||||
if req.TTL == "" {
|
||||
return apiutil.ErrMissingCertData
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,10 @@ type certsRes struct {
|
||||
created bool
|
||||
}
|
||||
|
||||
type revokeCertsRes struct {
|
||||
RevocationTime time.Time `json:"revocation_time"`
|
||||
}
|
||||
|
||||
func (res certsPageRes) Code() int {
|
||||
return http.StatusOK
|
||||
}
|
||||
@@ -55,3 +59,15 @@ func (res certsRes) Headers() map[string]string {
|
||||
func (res certsRes) Empty() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (res revokeCertsRes) Code() int {
|
||||
return http.StatusOK
|
||||
}
|
||||
|
||||
func (res revokeCertsRes) Headers() map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (res revokeCertsRes) Empty() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
+5
-5
@@ -21,6 +21,8 @@ import (
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
)
|
||||
|
||||
const keyBits = 2048
|
||||
|
||||
var (
|
||||
errPrivateKeyEmpty = errors.New("private key is empty")
|
||||
errPrivateKeyUnsupportedType = errors.New("private key type is unsupported")
|
||||
@@ -32,25 +34,23 @@ type agent struct {
|
||||
AuthTimeout time.Duration
|
||||
TLSCert tls.Certificate
|
||||
X509Cert *x509.Certificate
|
||||
RSABits int
|
||||
TTL string
|
||||
mu sync.Mutex
|
||||
counter uint64
|
||||
certs map[string]pki.Cert
|
||||
}
|
||||
|
||||
func NewPkiAgent(tlsCert tls.Certificate, caCert *x509.Certificate, keyBits int, ttl string, timeout time.Duration) pki.Agent {
|
||||
func NewPkiAgent(tlsCert tls.Certificate, caCert *x509.Certificate, ttl string, timeout time.Duration) pki.Agent {
|
||||
return &agent{
|
||||
AuthTimeout: timeout,
|
||||
TLSCert: tlsCert,
|
||||
X509Cert: caCert,
|
||||
RSABits: keyBits,
|
||||
TTL: ttl,
|
||||
certs: make(map[string]pki.Cert),
|
||||
}
|
||||
}
|
||||
|
||||
func (a *agent) IssueCert(cn string, ttl, keyType string, keyBits int) (pki.Cert, error) {
|
||||
func (a *agent) IssueCert(cn, ttl string) (pki.Cert, error) {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
@@ -139,7 +139,7 @@ func (a *agent) IssueCert(cn string, ttl, keyType string, keyBits int) (pki.Cert
|
||||
ClientCert: cert,
|
||||
ClientKey: key,
|
||||
Serial: x509cert.SerialNumber.String(),
|
||||
Expire: x509cert.NotAfter,
|
||||
Expire: x509cert.NotAfter.Unix(),
|
||||
IssuingCA: x509cert.Issuer.String(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
+29
-80
@@ -6,8 +6,7 @@ package pki
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/api"
|
||||
@@ -19,7 +18,6 @@ const (
|
||||
issue = "issue"
|
||||
cert = "cert"
|
||||
revoke = "revoke"
|
||||
apiVer = "v1"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -32,25 +30,23 @@ var (
|
||||
// ErrFailedCertRevocation indicates failed certificate revocation
|
||||
ErrFailedCertRevocation = errors.New("failed to revoke certificate")
|
||||
|
||||
errFailedVaultCertIssue = errors.New("failed to issue vault certificate")
|
||||
errFailedVaultRead = errors.New("failed to read vault certificate")
|
||||
errFailedCertDecoding = errors.New("failed to decode response from vault service")
|
||||
errFailedCertDecoding = errors.New("failed to decode response from vault service")
|
||||
)
|
||||
|
||||
type Cert struct {
|
||||
ClientCert string `json:"client_cert" mapstructure:"certificate"`
|
||||
IssuingCA string `json:"issuing_ca" mapstructure:"issuing_ca"`
|
||||
CAChain []string `json:"ca_chain" mapstructure:"ca_chain"`
|
||||
ClientKey string `json:"client_key" mapstructure:"private_key"`
|
||||
PrivateKeyType string `json:"private_key_type" mapstructure:"private_key_type"`
|
||||
Serial string `json:"serial" mapstructure:"serial_number"`
|
||||
Expire time.Time `json:"expire" mapstructure:"-"`
|
||||
ClientCert string `json:"client_cert" mapstructure:"certificate"`
|
||||
IssuingCA string `json:"issuing_ca" mapstructure:"issuing_ca"`
|
||||
CAChain []string `json:"ca_chain" mapstructure:"ca_chain"`
|
||||
ClientKey string `json:"client_key" mapstructure:"private_key"`
|
||||
PrivateKeyType string `json:"private_key_type" mapstructure:"private_key_type"`
|
||||
Serial string `json:"serial" mapstructure:"serial_number"`
|
||||
Expire int64 `json:"expire" mapstructure:"expiration"`
|
||||
}
|
||||
|
||||
// Agent represents the Vault PKI interface.
|
||||
type Agent interface {
|
||||
// IssueCert issues certificate on PKI
|
||||
IssueCert(cn string, ttl, keyType string, keyBits int) (Cert, error)
|
||||
IssueCert(cn, ttl string) (Cert, error)
|
||||
|
||||
// Read retrieves certificate from PKI
|
||||
Read(serial string) (Cert, error)
|
||||
@@ -73,8 +69,6 @@ type pkiAgent struct {
|
||||
type certReq struct {
|
||||
CommonName string `json:"common_name"`
|
||||
TTL string `json:"ttl"`
|
||||
KeyBits int `json:"key_bits"`
|
||||
KeyType string `json:"key_type"`
|
||||
}
|
||||
|
||||
type certRevokeReq struct {
|
||||
@@ -83,9 +77,8 @@ type certRevokeReq struct {
|
||||
|
||||
// NewVaultClient instantiates a Vault client.
|
||||
func NewVaultClient(token, host, path, role string) (Agent, error) {
|
||||
conf := &api.Config{
|
||||
Address: host,
|
||||
}
|
||||
conf := api.DefaultConfig()
|
||||
conf.Address = host
|
||||
|
||||
client, err := api.NewClient(conf)
|
||||
if err != nil {
|
||||
@@ -98,44 +91,29 @@ func NewVaultClient(token, host, path, role string) (Agent, error) {
|
||||
role: role,
|
||||
path: path,
|
||||
client: client,
|
||||
issueURL: "/" + apiVer + "/" + path + "/" + issue + "/" + role,
|
||||
readURL: "/" + apiVer + "/" + path + "/" + cert + "/",
|
||||
revokeURL: "/" + apiVer + "/" + path + "/" + revoke,
|
||||
issueURL: "/" + path + "/" + issue + "/" + role,
|
||||
readURL: "/" + path + "/" + cert + "/",
|
||||
revokeURL: "/" + path + "/" + revoke,
|
||||
}
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
func (p *pkiAgent) IssueCert(cn string, ttl, keyType string, keyBits int) (Cert, error) {
|
||||
func (p *pkiAgent) IssueCert(cn, ttl string) (Cert, error) {
|
||||
cReq := certReq{
|
||||
CommonName: cn,
|
||||
TTL: ttl,
|
||||
KeyBits: keyBits,
|
||||
KeyType: keyType,
|
||||
}
|
||||
|
||||
r := p.client.NewRequest("POST", p.issueURL)
|
||||
if err := r.SetJSONBody(cReq); err != nil {
|
||||
return Cert{}, err
|
||||
}
|
||||
|
||||
resp, err := p.client.RawRequest(r)
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
TTL: fmt.Sprintf("%sh", ttl),
|
||||
}
|
||||
|
||||
var certIssueReq map[string]interface{}
|
||||
data, err := json.Marshal(cReq)
|
||||
if err != nil {
|
||||
return Cert{}, err
|
||||
}
|
||||
|
||||
if resp.StatusCode >= http.StatusBadRequest {
|
||||
_, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return Cert{}, err
|
||||
}
|
||||
return Cert{}, errors.Wrap(errFailedVaultCertIssue, err)
|
||||
if err := json.Unmarshal(data, &certIssueReq); err != nil {
|
||||
return Cert{}, nil
|
||||
}
|
||||
|
||||
s, err := api.ParseSecret(resp.Body)
|
||||
s, err := p.client.Logical().Write(p.issueURL, certIssueReq)
|
||||
if err != nil {
|
||||
return Cert{}, err
|
||||
}
|
||||
@@ -149,32 +127,14 @@ func (p *pkiAgent) IssueCert(cn string, ttl, keyType string, keyBits int) (Cert,
|
||||
}
|
||||
|
||||
func (p *pkiAgent) Read(serial string) (Cert, error) {
|
||||
r := p.client.NewRequest("GET", p.readURL+"/"+serial)
|
||||
|
||||
resp, err := p.client.RawRequest(r)
|
||||
s, err := p.client.Logical().Read(p.readURL + serial)
|
||||
if err != nil {
|
||||
return Cert{}, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= http.StatusBadRequest {
|
||||
_, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return Cert{}, err
|
||||
}
|
||||
return Cert{}, errors.Wrap(errFailedVaultRead, err)
|
||||
}
|
||||
|
||||
s, err := api.ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return Cert{}, err
|
||||
}
|
||||
|
||||
cert := Cert{}
|
||||
if err = mapstructure.Decode(s.Data, &cert); err != nil {
|
||||
return Cert{}, errors.Wrap(errFailedCertDecoding, err)
|
||||
}
|
||||
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
@@ -183,34 +143,23 @@ func (p *pkiAgent) Revoke(serial string) (time.Time, error) {
|
||||
SerialNumber: serial,
|
||||
}
|
||||
|
||||
r := p.client.NewRequest("POST", p.revokeURL)
|
||||
if err := r.SetJSONBody(cReq); err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
|
||||
resp, err := p.client.RawRequest(r)
|
||||
var certRevokeReq map[string]interface{}
|
||||
data, err := json.Marshal(cReq)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= http.StatusBadRequest {
|
||||
_, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
return time.Time{}, errors.Wrap(errFailedVaultCertIssue, err)
|
||||
if err := json.Unmarshal(data, &certRevokeReq); err != nil {
|
||||
return time.Time{}, nil
|
||||
}
|
||||
|
||||
s, err := api.ParseSecret(resp.Body)
|
||||
s, err := p.client.Logical().Write(p.revokeURL, certRevokeReq)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
|
||||
rev, err := s.Data["revocation_time"].(json.Number).Float64()
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
|
||||
return time.Unix(0, int64(rev)*int64(time.Millisecond)), nil
|
||||
return time.Unix(0, int64(rev)*int64(time.Second)), nil
|
||||
}
|
||||
|
||||
+4
-4
@@ -31,7 +31,7 @@ var _ Service = (*certsService)(nil)
|
||||
// implementation, and all of its decorators (e.g. logging & metrics).
|
||||
type Service interface {
|
||||
// IssueCert issues certificate for given thing id if access is granted with token
|
||||
IssueCert(ctx context.Context, token, thingID, ttl string, keyBits int, keyType string) (Cert, error)
|
||||
IssueCert(ctx context.Context, token, thingID, ttl string) (Cert, error)
|
||||
|
||||
// ListCerts lists certificates issued for a given thing ID
|
||||
ListCerts(ctx context.Context, token, thingID string, offset, limit uint64) (Page, error)
|
||||
@@ -105,7 +105,7 @@ type Cert struct {
|
||||
Expire time.Time `json:"expire" mapstructure:"-"`
|
||||
}
|
||||
|
||||
func (cs *certsService) IssueCert(ctx context.Context, token, thingID string, ttl string, keyBits int, keyType string) (Cert, error) {
|
||||
func (cs *certsService) IssueCert(ctx context.Context, token, thingID string, ttl string) (Cert, error) {
|
||||
owner, err := cs.auth.Identify(ctx, &mainflux.Token{Value: token})
|
||||
if err != nil {
|
||||
return Cert{}, err
|
||||
@@ -116,7 +116,7 @@ func (cs *certsService) IssueCert(ctx context.Context, token, thingID string, tt
|
||||
return Cert{}, errors.Wrap(ErrFailedCertCreation, err)
|
||||
}
|
||||
|
||||
cert, err := cs.pki.IssueCert(thing.Key, ttl, keyType, keyBits)
|
||||
cert, err := cs.pki.IssueCert(thing.Key, ttl)
|
||||
if err != nil {
|
||||
return Cert{}, errors.Wrap(ErrFailedCertCreation, err)
|
||||
}
|
||||
@@ -130,7 +130,7 @@ func (cs *certsService) IssueCert(ctx context.Context, token, thingID string, tt
|
||||
ClientKey: cert.ClientKey,
|
||||
PrivateKeyType: cert.PrivateKeyType,
|
||||
Serial: cert.Serial,
|
||||
Expire: cert.Expire,
|
||||
Expire: time.Unix(0, int64(cert.Expire)*int64(time.Second)),
|
||||
}
|
||||
|
||||
_, err = cs.certsRepo.Save(context.Background(), c)
|
||||
|
||||
+6
-33
@@ -40,8 +40,6 @@ const (
|
||||
thingKey = "thingKey"
|
||||
thingID = "1"
|
||||
ttl = "1h"
|
||||
keyBits = 2048
|
||||
key = "rsa"
|
||||
certNum = 10
|
||||
|
||||
cfgLogLevel = "error"
|
||||
@@ -96,7 +94,7 @@ func newService(tokens map[string]string) (certs.Service, error) {
|
||||
SignRSABits: cfgSignRSABits,
|
||||
}
|
||||
|
||||
pki := mocks.NewPkiAgent(tlsCert, caCert, cfgSignRSABits, cfgSignHoursValid, authTimeout)
|
||||
pki := mocks.NewPkiAgent(tlsCert, caCert, cfgSignHoursValid, authTimeout)
|
||||
|
||||
return certs.New(auth, repo, sdk, c, pki), nil
|
||||
}
|
||||
@@ -125,7 +123,6 @@ func TestIssueCert(t *testing.T) {
|
||||
thingID string
|
||||
ttl string
|
||||
key string
|
||||
keyBits int
|
||||
err error
|
||||
}{
|
||||
{
|
||||
@@ -133,8 +130,6 @@ func TestIssueCert(t *testing.T) {
|
||||
token: token,
|
||||
thingID: thingID,
|
||||
ttl: ttl,
|
||||
key: key,
|
||||
keyBits: 2048,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
@@ -142,8 +137,6 @@ func TestIssueCert(t *testing.T) {
|
||||
token: token,
|
||||
thingID: "2",
|
||||
ttl: ttl,
|
||||
key: key,
|
||||
keyBits: 2048,
|
||||
err: certs.ErrFailedCertCreation,
|
||||
},
|
||||
{
|
||||
@@ -151,32 +144,12 @@ func TestIssueCert(t *testing.T) {
|
||||
token: wrongValue,
|
||||
thingID: thingID,
|
||||
ttl: ttl,
|
||||
key: key,
|
||||
keyBits: 2048,
|
||||
err: errors.ErrAuthentication,
|
||||
},
|
||||
{
|
||||
desc: "issue new cert for bad key bits",
|
||||
token: token,
|
||||
thingID: thingID,
|
||||
ttl: ttl,
|
||||
key: key,
|
||||
keyBits: -2,
|
||||
err: certs.ErrFailedCertCreation,
|
||||
},
|
||||
{
|
||||
desc: "issue new cert for bad key bits",
|
||||
token: token,
|
||||
thingID: thingID,
|
||||
ttl: ttl,
|
||||
key: key,
|
||||
keyBits: -2,
|
||||
err: certs.ErrFailedCertCreation,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
c, err := svc.IssueCert(context.Background(), tc.token, tc.thingID, tc.ttl, tc.keyBits, tc.key)
|
||||
c, err := svc.IssueCert(context.Background(), tc.token, tc.thingID, tc.ttl)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
cert, _ := readCert([]byte(c.ClientCert))
|
||||
if cert != nil {
|
||||
@@ -190,7 +163,7 @@ func TestRevokeCert(t *testing.T) {
|
||||
svc, err := newService(map[string]string{token: email})
|
||||
require.Nil(t, err, fmt.Sprintf("unexpected service creation error: %s\n", err))
|
||||
|
||||
_, err = svc.IssueCert(context.Background(), token, thingID, ttl, keyBits, key)
|
||||
_, err = svc.IssueCert(context.Background(), token, thingID, ttl)
|
||||
require.Nil(t, err, fmt.Sprintf("unexpected service creation error: %s\n", err))
|
||||
|
||||
cases := []struct {
|
||||
@@ -231,7 +204,7 @@ func TestListCerts(t *testing.T) {
|
||||
require.Nil(t, err, fmt.Sprintf("unexpected service creation error: %s\n", err))
|
||||
|
||||
for i := 0; i < certNum; i++ {
|
||||
_, err = svc.IssueCert(context.Background(), token, thingID, ttl, keyBits, key)
|
||||
_, err = svc.IssueCert(context.Background(), token, thingID, ttl)
|
||||
require.Nil(t, err, fmt.Sprintf("unexpected cert creation error: %s\n", err))
|
||||
}
|
||||
|
||||
@@ -296,7 +269,7 @@ func TestListSerials(t *testing.T) {
|
||||
|
||||
var issuedCerts []certs.Cert
|
||||
for i := 0; i < certNum; i++ {
|
||||
cert, err := svc.IssueCert(context.Background(), token, thingID, ttl, keyBits, key)
|
||||
cert, err := svc.IssueCert(context.Background(), token, thingID, ttl)
|
||||
require.Nil(t, err, fmt.Sprintf("unexpected cert creation error: %s\n", err))
|
||||
|
||||
crt := certs.Cert{
|
||||
@@ -366,7 +339,7 @@ func TestViewCert(t *testing.T) {
|
||||
svc, err := newService(map[string]string{token: email})
|
||||
require.Nil(t, err, fmt.Sprintf("unexpected service creation error: %s\n", err))
|
||||
|
||||
ic, err := svc.IssueCert(context.Background(), token, thingID, ttl, keyBits, key)
|
||||
ic, err := svc.IssueCert(context.Background(), token, thingID, ttl)
|
||||
require.Nil(t, err, fmt.Sprintf("unexpected cert creation error: %s\n", err))
|
||||
|
||||
cert := certs.Cert{
|
||||
|
||||
+42
-11
@@ -6,14 +6,49 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var cmdCerts = []cobra.Command{
|
||||
{
|
||||
Use: "get <cert_serial> <user_auth_token>",
|
||||
Short: "Get certificate",
|
||||
Long: `Gets a certificate for a given cert ID.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) != 2 {
|
||||
logUsage(cmd.Use)
|
||||
return
|
||||
}
|
||||
cert, err := sdk.ViewCert(args[0], args[1])
|
||||
if err != nil {
|
||||
logError(err)
|
||||
return
|
||||
}
|
||||
logJSON(cert)
|
||||
},
|
||||
},
|
||||
{
|
||||
Use: "revoke <thing_id> <user_auth_token>",
|
||||
Short: "Revoke certificate",
|
||||
Long: `Revokes a certificate for a given thing ID.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) != 2 {
|
||||
logUsage(cmd.Use)
|
||||
return
|
||||
}
|
||||
rtime, err := sdk.RevokeCert(args[0], args[1])
|
||||
if err != nil {
|
||||
logError(err)
|
||||
return
|
||||
}
|
||||
logRevokedTime(rtime)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// NewCertsCmd returns certificate command.
|
||||
func NewCertsCmd() *cobra.Command {
|
||||
var keySize uint16
|
||||
var keyType string
|
||||
var ttl uint32
|
||||
|
||||
issueCmd := cobra.Command{
|
||||
Use: "issue <thing_id> <user_auth_token> [--keysize=2048] [--keytype=rsa] [--ttl=8760]",
|
||||
Use: "issue <thing_id> <user_auth_token> [--ttl=8760]",
|
||||
Short: "Issue certificate",
|
||||
Long: `Issues new certificate for a thing`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
@@ -25,7 +60,7 @@ func NewCertsCmd() *cobra.Command {
|
||||
thingID := args[0]
|
||||
valid := strconv.FormatUint(uint64(ttl), 10)
|
||||
|
||||
c, err := sdk.IssueCert(thingID, int(keySize), keyType, valid, args[1])
|
||||
c, err := sdk.IssueCert(thingID, valid, args[1])
|
||||
if err != nil {
|
||||
logError(err)
|
||||
return
|
||||
@@ -34,19 +69,15 @@ func NewCertsCmd() *cobra.Command {
|
||||
},
|
||||
}
|
||||
|
||||
issueCmd.Flags().Uint16Var(&keySize, "keysize", 2048, "certificate key strength in bits: 2048, 4096 (RSA) or 224, 256, 384, 512 (EC)")
|
||||
issueCmd.Flags().StringVar(&keyType, "keytype", "rsa", "certificate key type: RSA or EC")
|
||||
issueCmd.Flags().Uint32Var(&ttl, "ttl", 8760, "certificate time to live in hours")
|
||||
|
||||
cmd := cobra.Command{
|
||||
Use: "certs [issue | get]",
|
||||
Use: "certs [issue | get | revoke ]",
|
||||
Short: "Certificates management",
|
||||
Long: `Certificates management: create certificates for things"`,
|
||||
Long: `Certificates management: issue, get or revoke certificates for things"`,
|
||||
}
|
||||
|
||||
cmdCerts := []cobra.Command{
|
||||
issueCmd,
|
||||
}
|
||||
cmdCerts = append(cmdCerts, issueCmd)
|
||||
|
||||
for i := range cmdCerts {
|
||||
cmd.AddCommand(&cmdCerts[i])
|
||||
|
||||
@@ -6,6 +6,7 @@ package cli
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
prettyjson "github.com/hokaccha/go-prettyjson"
|
||||
@@ -71,6 +72,14 @@ func logCreated(e string) {
|
||||
}
|
||||
}
|
||||
|
||||
func logRevokedTime(t time.Time) {
|
||||
if RawOutput {
|
||||
fmt.Println(t)
|
||||
} else {
|
||||
fmt.Printf(color.BlueString("\nrevoked: %v\n\n"), t)
|
||||
}
|
||||
}
|
||||
|
||||
func convertMetadata(m string) (map[string]interface{}, error) {
|
||||
var metadata map[string]interface{}
|
||||
if m == "" {
|
||||
|
||||
@@ -43,7 +43,6 @@ const (
|
||||
defBSAutoWhitelist = "true"
|
||||
defBSContent = ""
|
||||
defCertsHoursValid = "2400h"
|
||||
defCertsKeyBits = "4096"
|
||||
|
||||
envConfigFile = "MF_PROVISION_CONFIG_FILE"
|
||||
envLogLevel = "MF_PROVISION_LOG_LEVEL"
|
||||
@@ -64,7 +63,6 @@ const (
|
||||
envBSAutoWhiteList = "MF_PROVISION_BS_AUTO_WHITELIST"
|
||||
envBSContent = "MF_PROVISION_BS_CONTENT"
|
||||
envCertsHoursValid = "MF_PROVISION_CERTS_HOURS_VALID"
|
||||
envCertsKeyBits = "MF_PROVISION_CERTS_RSA_BITS"
|
||||
|
||||
contentType = "application/json"
|
||||
)
|
||||
@@ -76,7 +74,6 @@ var (
|
||||
errFailGettingCertSettings = errors.New("failed to get certificate file setting")
|
||||
errFailGettingTLSConf = errors.New("failed to get TLS setting")
|
||||
errFailGettingProvBS = errors.New("failed to get BS url setting")
|
||||
errFailSettingKeyBits = errors.New("failed to set rsa number of bits")
|
||||
errFailedToReadBootstrapContent = errors.New("failed to read bootstrap content from envs")
|
||||
)
|
||||
|
||||
@@ -198,10 +195,6 @@ func loadConfig() (provision.Config, error) {
|
||||
if autoWhiteList && !provisionBS {
|
||||
return provision.Config{}, errors.New("Can't auto whitelist if auto config save is off")
|
||||
}
|
||||
keyBits, err := strconv.Atoi(mainflux.Env(envCertsKeyBits, defCertsKeyBits))
|
||||
if err != nil && provisionX509 {
|
||||
return provision.Config{}, errFailSettingKeyBits
|
||||
}
|
||||
|
||||
var content map[string]interface{}
|
||||
if c := mainflux.Env(envBSContent, defBSContent); c != "" {
|
||||
@@ -227,8 +220,7 @@ func loadConfig() (provision.Config, error) {
|
||||
TLS: tls,
|
||||
},
|
||||
Cert: provision.Cert{
|
||||
TTL: mainflux.Env(envCertsHoursValid, defCertsHoursValid),
|
||||
KeyBits: keyBits,
|
||||
TTL: mainflux.Env(envCertsHoursValid, defCertsHoursValid),
|
||||
},
|
||||
Bootstrap: provision.Bootstrap{
|
||||
X509Provision: provisionX509,
|
||||
|
||||
@@ -155,7 +155,6 @@ MF_PROVISION_BS_SVC_WHITELIST_URL=http://bootstrap:8202/things/state
|
||||
MF_PROVISION_BS_CONFIG_PROVISIONING=true
|
||||
MF_PROVISION_BS_AUTO_WHITELIST=true
|
||||
MF_PROVISION_BS_CONTENT=
|
||||
MF_PROVISION_CERTS_RSA_BITS=4096
|
||||
MF_PROVISION_CERTS_HOURS_VALID=2400h
|
||||
|
||||
# Certs
|
||||
|
||||
@@ -19,7 +19,7 @@ volumes:
|
||||
|
||||
services:
|
||||
vault:
|
||||
image: vault:1.6.2
|
||||
image: vault:1.12.2
|
||||
container_name: mainflux-vault
|
||||
ports:
|
||||
- ${MF_VAULT_PORT}:8200
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
#!/usr/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
scriptdir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
export MAINFLUX_DIR=$scriptdir/../../../
|
||||
|
||||
write_env() {
|
||||
sed -i "s,MF_VAULT_UNSEAL_KEY_1=.*,MF_VAULT_UNSEAL_KEY_1=$(awk -F ": " '$1 == "Unseal Key 1" {print $2}' data/secrets)," $MAINFLUX_DIR/docker/.env
|
||||
sed -i "s,MF_VAULT_UNSEAL_KEY_2=.*,MF_VAULT_UNSEAL_KEY_2=$(awk -F ": " '$1 == "Unseal Key 2" {print $2}' data/secrets)," $MAINFLUX_DIR/docker/.env
|
||||
sed -i "s,MF_VAULT_UNSEAL_KEY_3=.*,MF_VAULT_UNSEAL_KEY_3=$(awk -F ": " '$1 == "Unseal Key 3" {print $2}' data/secrets)," $MAINFLUX_DIR/docker/.env
|
||||
sed -i "s,MF_VAULT_TOKEN=.*,MF_VAULT_TOKEN=$(awk -F ": " '$1 == "Initial Root Token" {print $2}' data/secrets)," $MAINFLUX_DIR/docker/.env
|
||||
}
|
||||
vault() {
|
||||
docker exec -it mainflux-vault vault "$@"
|
||||
}
|
||||
@@ -8,3 +17,5 @@ vault() {
|
||||
mkdir -p data
|
||||
|
||||
vault operator init 2>&1 | tee >(sed -r 's/\x1b\[[0-9;]*m//g' > data/secrets)
|
||||
|
||||
write_env
|
||||
|
||||
@@ -8,7 +8,7 @@ cd $scriptdir
|
||||
|
||||
readDotEnv() {
|
||||
set -o allexport
|
||||
source $MAINFLUX_DIR/.env
|
||||
source $MAINFLUX_DIR/docker/.env
|
||||
set +o allexport
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ export MAINFLUX_DIR=$scriptdir/../../../
|
||||
|
||||
readDotEnv() {
|
||||
set -o allexport
|
||||
source $MAINFLUX_DIR/.env
|
||||
source $MAINFLUX_DIR/docker/.env
|
||||
set +o allexport
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ var (
|
||||
// ErrMissingPolicyAct indicates missing policies action.
|
||||
ErrMissingPolicyAct = errors.New("falmormed policy action")
|
||||
|
||||
// ErrMissingCertData indicates missing cert data (ttl, key_type or key_bits).
|
||||
// ErrMissingCertData indicates missing cert data (ttl).
|
||||
ErrMissingCertData = errors.New("missing certificate data")
|
||||
|
||||
// ErrInvalidTopic indicates an invalid subscription topic.
|
||||
|
||||
+33
-47
@@ -4,10 +4,10 @@
|
||||
package sdk
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
)
|
||||
@@ -16,16 +16,16 @@ const certsEndpoint = "certs"
|
||||
|
||||
// Cert represents certs data.
|
||||
type Cert struct {
|
||||
CACert string `json:"issuing_ca,omitempty"`
|
||||
ClientKey string `json:"client_key,omitempty"`
|
||||
ClientCert string `json:"client_cert,omitempty"`
|
||||
ThingID string `json:"thing_id,omitempty"`
|
||||
CertSerial string `json:"cert_serial,omitempty"`
|
||||
ClientKey string `json:"client_key,omitempty"`
|
||||
ClientCert string `json:"client_cert,omitempty"`
|
||||
Expiration time.Time `json:"expiration,omitempty"`
|
||||
}
|
||||
|
||||
func (sdk mfSDK) IssueCert(thingID string, keyBits int, keyType, valid, token string) (Cert, errors.SDKError) {
|
||||
func (sdk mfSDK) IssueCert(thingID, valid, token string) (Cert, errors.SDKError) {
|
||||
r := certReq{
|
||||
ThingID: thingID,
|
||||
KeyBits: keyBits,
|
||||
KeyType: keyType,
|
||||
Valid: valid,
|
||||
}
|
||||
d, err := json.Marshal(r)
|
||||
@@ -34,63 +34,49 @@ func (sdk mfSDK) IssueCert(thingID string, keyBits int, keyType, valid, token st
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/%s", sdk.certsURL, certsEndpoint)
|
||||
resp, err := request(http.MethodPost, token, url, d)
|
||||
if err != nil {
|
||||
return Cert{}, errors.NewSDKError(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if err := errors.CheckError(resp, http.StatusOK); err != nil {
|
||||
return Cert{}, err
|
||||
_, body, sdkerr := sdk.processRequest(http.MethodPost, url, token, string(CTJSON), d, http.StatusCreated)
|
||||
if sdkerr != nil {
|
||||
return Cert{}, sdkerr
|
||||
}
|
||||
|
||||
var c Cert
|
||||
if err := json.NewDecoder(resp.Body).Decode(&c); err != nil {
|
||||
if err := json.Unmarshal(body, &c); err != nil {
|
||||
return Cert{}, errors.NewSDKError(err)
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (sdk mfSDK) RemoveCert(id, token string) errors.SDKError {
|
||||
resp, err := request(http.MethodDelete, token, fmt.Sprintf("%s/%s", sdk.certsURL, id), nil)
|
||||
if resp != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
func (sdk mfSDK) ViewCert(id, token string) (Cert, errors.SDKError) {
|
||||
url := fmt.Sprintf("%s/%s/%s", sdk.certsURL, certsEndpoint, id)
|
||||
_, body, err := sdk.processRequest(http.MethodGet, url, token, string(CTJSON), nil, http.StatusOK)
|
||||
if err != nil {
|
||||
return errors.NewSDKError(err)
|
||||
return Cert{}, err
|
||||
}
|
||||
switch resp.StatusCode {
|
||||
case http.StatusForbidden:
|
||||
return errors.NewSDKError(errors.ErrAuthorization)
|
||||
default:
|
||||
return errors.CheckError(resp, http.StatusNoContent)
|
||||
|
||||
var cert Cert
|
||||
if err := json.Unmarshal(body, &cert); err != nil {
|
||||
return Cert{}, errors.NewSDKError(err)
|
||||
}
|
||||
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
func (sdk mfSDK) RevokeCert(thingID, certID, token string) errors.SDKError {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func request(method, jwt, url string, data []byte) (*http.Response, errors.SDKError) {
|
||||
req, err := http.NewRequest(method, url, bytes.NewReader(data))
|
||||
func (sdk mfSDK) RevokeCert(id, token string) (time.Time, errors.SDKError) {
|
||||
url := fmt.Sprintf("%s/%s/%s", sdk.certsURL, certsEndpoint, id)
|
||||
_, body, err := sdk.processRequest(http.MethodDelete, url, token, string(CTJSON), nil, http.StatusOK)
|
||||
if err != nil {
|
||||
return nil, errors.NewSDKError(err)
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", jwt)
|
||||
c := &http.Client{}
|
||||
res, err := c.Do(req)
|
||||
if err != nil {
|
||||
return nil, errors.NewSDKError(err)
|
||||
return time.Time{}, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
var rcr revokeCertsRes
|
||||
if err := json.Unmarshal(body, &rcr); err != nil {
|
||||
return time.Time{}, errors.NewSDKError(err)
|
||||
}
|
||||
|
||||
return rcr.RevocationTime, nil
|
||||
}
|
||||
|
||||
type certReq struct {
|
||||
ThingID string `json:"thing_id"`
|
||||
KeyBits int `json:"key_bits"`
|
||||
KeyType string `json:"key_type"`
|
||||
Encryption string `json:"encryption"`
|
||||
Valid string `json:"valid"`
|
||||
ThingID string `json:"thing_id"`
|
||||
Valid string `json:"ttl"`
|
||||
}
|
||||
|
||||
@@ -99,3 +99,7 @@ func (res retrieveKeyRes) Headers() map[string]string {
|
||||
func (res retrieveKeyRes) Empty() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type revokeCertsRes struct {
|
||||
RevocationTime time.Time `json:"revocation_time"`
|
||||
}
|
||||
|
||||
+5
-5
@@ -236,13 +236,13 @@ type SDK interface {
|
||||
Whitelist(cfg BootstrapConfig, token string) errors.SDKError
|
||||
|
||||
// IssueCert issues a certificate for a thing required for mtls.
|
||||
IssueCert(thingID string, keyBits int, keyType, valid, token string) (Cert, errors.SDKError)
|
||||
IssueCert(thingID, valid, token string) (Cert, errors.SDKError)
|
||||
|
||||
// RemoveCert removes a certificate
|
||||
RemoveCert(id, token string) errors.SDKError
|
||||
// ViewCert returns a certificate given certificate ID
|
||||
ViewCert(certID, token string) (Cert, errors.SDKError)
|
||||
|
||||
// RevokeCert revokes certificate with certID for thing with thingID
|
||||
RevokeCert(thingID, certID, token string) errors.SDKError
|
||||
// RevokeCert revokes certificate for thing with thingID
|
||||
RevokeCert(thingID, token string) (time.Time, errors.SDKError)
|
||||
|
||||
// Issue issues a new key, returning its token value alongside.
|
||||
Issue(duration time.Duration, token string) (KeyRes, errors.SDKError)
|
||||
|
||||
+1
-1
@@ -162,7 +162,7 @@ Provision service has `/certs` endpoint that can be used to generate certificate
|
||||
- `users_token` - users authentication token or API token
|
||||
- `thing_id` - id of the thing for which certificate is going to be generated
|
||||
```bash
|
||||
curl -s -X POST http://localhost:8190/certs -H "Authorization: Bearer <users_token>" -H 'Content-Type: application/json' -d '{"thing_id": "<thing_id>", "key_bits":4096, "ttl":"2400h" }'
|
||||
curl -s -X POST http://localhost:8190/certs -H "Authorization: Bearer <users_token>" -H 'Content-Type: application/json' -d '{"thing_id": "<thing_id>", "ttl":"2400h" }'
|
||||
```
|
||||
```json
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@ func (lm *loggingMiddleware) Provision(token, name, externalID, externalKey stri
|
||||
return lm.svc.Provision(token, name, externalID, externalKey)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) Cert(token, thingID, duration string, keyBits int) (cert string, key string, err error) {
|
||||
func (lm *loggingMiddleware) Cert(token, thingID, duration string) (cert string, key string, err error) {
|
||||
defer func(begin time.Time) {
|
||||
message := fmt.Sprintf("Method cert for token: %s and thing: %v took %s to complete", token, thingID, time.Since(begin))
|
||||
if err != nil {
|
||||
@@ -48,7 +48,7 @@ func (lm *loggingMiddleware) Cert(token, thingID, duration string, keyBits int)
|
||||
lm.logger.Info(fmt.Sprintf("%s without errors", message))
|
||||
}(time.Now())
|
||||
|
||||
return lm.svc.Cert(token, thingID, duration, keyBits)
|
||||
return lm.svc.Cert(token, thingID, duration)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) Mapping(token string) (res map[string]interface{}, err error) {
|
||||
|
||||
+1
-3
@@ -51,9 +51,7 @@ type Gateway struct {
|
||||
|
||||
// Cert represetns the certificate config
|
||||
type Cert struct {
|
||||
TTL string `json:"ttl" toml:"ttl"`
|
||||
KeyBits int `json:"key_bits" toml:"key_bits"`
|
||||
KeyType string `json:"key_type"`
|
||||
TTL string `json:"ttl" toml:"ttl"`
|
||||
}
|
||||
|
||||
// Config struct of Provision
|
||||
|
||||
@@ -61,8 +61,7 @@ type Service interface {
|
||||
// A duration string is a possibly signed sequence of decimal numbers,
|
||||
// each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m".
|
||||
// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
|
||||
// keyBits for certificate key
|
||||
Cert(token, thingID, duration string, keyBits int) (string, string, error)
|
||||
Cert(token, thingID, duration string) (string, string, error)
|
||||
}
|
||||
|
||||
type provisionService struct {
|
||||
@@ -216,7 +215,7 @@ func (ps *provisionService) Provision(token, name, externalID, externalKey strin
|
||||
if ps.conf.Bootstrap.X509Provision {
|
||||
var cert SDK.Cert
|
||||
|
||||
cert, err = ps.sdk.IssueCert(thing.ID, ps.conf.Cert.KeyBits, ps.conf.Cert.KeyType, ps.conf.Cert.TTL, token)
|
||||
cert, err = ps.sdk.IssueCert(thing.ID, ps.conf.Cert.TTL, token)
|
||||
if err != nil {
|
||||
e := errors.Wrap(err, fmt.Errorf("thing id: %s", thing.ID))
|
||||
return res, errors.Wrap(ErrFailedCertCreation, e)
|
||||
@@ -224,10 +223,10 @@ func (ps *provisionService) Provision(token, name, externalID, externalKey strin
|
||||
|
||||
res.ClientCert[thing.ID] = cert.ClientCert
|
||||
res.ClientKey[thing.ID] = cert.ClientKey
|
||||
res.CACert = cert.CACert
|
||||
res.CACert = ""
|
||||
|
||||
if needsBootstrap(thing) {
|
||||
if err = ps.sdk.UpdateBootstrapCerts(bsConfig.MFThing, cert.ClientCert, cert.ClientKey, cert.CACert, token); err != nil {
|
||||
if err = ps.sdk.UpdateBootstrapCerts(bsConfig.MFThing, cert.ClientCert, cert.ClientKey, "", token); err != nil {
|
||||
return Result{}, errors.Wrap(ErrFailedCertCreation, err)
|
||||
}
|
||||
}
|
||||
@@ -253,7 +252,7 @@ func (ps *provisionService) Provision(token, name, externalID, externalKey strin
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (ps *provisionService) Cert(token, thingID, ttl string, keyBits int) (string, string, error) {
|
||||
func (ps *provisionService) Cert(token, thingID, ttl string) (string, string, error) {
|
||||
token, err := ps.createTokenIfEmpty(token)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
@@ -263,7 +262,7 @@ func (ps *provisionService) Cert(token, thingID, ttl string, keyBits int) (strin
|
||||
if err != nil {
|
||||
return "", "", errors.Wrap(ErrUnauthorized, err)
|
||||
}
|
||||
cert, err := ps.sdk.IssueCert(th.ID, ps.conf.Cert.KeyBits, ps.conf.Cert.KeyType, ps.conf.Cert.TTL, token)
|
||||
cert, err := ps.sdk.IssueCert(th.ID, ps.conf.Cert.TTL, token)
|
||||
return cert.ClientCert, cert.ClientKey, err
|
||||
}
|
||||
|
||||
@@ -388,7 +387,8 @@ func (ps *provisionService) recover(e *error, ths *[]SDK.Thing, chs *[]SDK.Chann
|
||||
clean(ps, things, channels, token)
|
||||
for _, th := range things {
|
||||
if ps.conf.Bootstrap.X509Provision && needsBootstrap(th) {
|
||||
ps.errLog(ps.sdk.RemoveCert(th.ID, token))
|
||||
_, err := ps.sdk.RevokeCert(th.ID, token)
|
||||
ps.errLog(err)
|
||||
}
|
||||
if needsBootstrap(th) {
|
||||
bs, err := ps.sdk.ViewBootstrap(th.ID, token)
|
||||
|
||||
Reference in New Issue
Block a user