Skip to content

Commit

Permalink
NOISSUE - Certs service refactor (#1369)
Browse files Browse the repository at this point in the history
* remove owner id

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* add certs mock

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* remove not wanted changes

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* refactor certs

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* addint tests

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* addint tests

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* adding tests

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* add certs test

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* add certs test

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* add cert test, remove default implementation

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* fix default value for vault host

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* add cert test, remove default implementation

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* linter cleaning

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* fix comments, and logging

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* use mocks from other services

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* rename struct and url path params

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* resolve minor comments

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* resolve comments

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* align url params naming

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* resolve comments

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* resolve comments

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* fix typo

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* resolve comments

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* remove struct revoke

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>

* refactor certRes

Signed-off-by: Mirko Teodorovic <mirko.teodorovic@gmail.com>
  • Loading branch information
mteodor authored Mar 15, 2021
1 parent 30ba38c commit 74aa93f
Show file tree
Hide file tree
Showing 20 changed files with 750 additions and 270 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ MF_CERTS_SIGN_CA_PATH=/etc/ssl/certs/ca.crt
MF_CERTS_SIGN_CA_KEY_PATH=/etc/ssl/certs/ca.key
MF_CERTS_SIGN_HOURS_VALID=2048h
MF_CERTS_SIGN_RSA_BITS=2048
MF_CERTS_VAULT_HOST=http://certs:8200
MF_CERTS_VAULT_HOST=http://vault:8200


### Vault
Expand Down
29 changes: 18 additions & 11 deletions certs/api/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@ func issueCert(svc certs.Service) endpoint.Endpoint {
}
res, err := svc.IssueCert(ctx, req.token, req.ThingID, req.Valid, req.KeyBits, req.KeyType)
if err != nil {
return certsResponse{Error: err.Error()}, nil
return certsRes{}, err
}
return res, nil
return certsRes{
CertSerial: res.Serial,
ThingID: res.ThingID,
CertKey: res.ClientKey,
Cert: res.ClientCert,
CACert: res.IssuingCA,
}, nil
}
}

Expand All @@ -31,25 +37,26 @@ func listCerts(svc certs.Service) endpoint.Endpoint {
return nil, err
}

page, err := svc.ListCerts(ctx, req.token, req.offset, req.limit)
page, err := svc.ListCerts(ctx, req.token, req.thingID, req.offset, req.limit)
if err != nil {
return certsPageRes{
Error: err.Error(),
}, err
return certsPageRes{}, err
}
res := certsPageRes{
pageRes: pageRes{
Total: page.Total,
Offset: page.Offset,
Limit: page.Limit,
},
Certs: []certsResponse{},
Certs: []certsRes{},
}

for _, cert := range page.Certs {
view := certsResponse{
Serial: cert.Serial,
ThingID: cert.ThingID,
view := certsRes{
CertSerial: cert.Serial,
ThingID: cert.ThingID,
CertKey: cert.ClientKey,
Cert: cert.ClientCert,
CACert: cert.IssuingCA,
}
res.Certs = append(res.Certs, view)
}
Expand All @@ -63,6 +70,6 @@ func revokeCert(svc certs.Service) endpoint.Endpoint {
if err := req.validate(); err != nil {
return nil, err
}
return svc.RevokeCert(ctx, req.token, req.ThingID)
return svc.RevokeCert(ctx, req.token, req.certID)
}
}
6 changes: 3 additions & 3 deletions certs/api/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ func (lm *loggingMiddleware) IssueCert(ctx context.Context, token, thingID, days
return lm.svc.IssueCert(ctx, token, thingID, daysValid, keyBits, keyType)
}

func (lm *loggingMiddleware) ListCerts(ctx context.Context, token string, offset, limit uint64) (cp certs.Page, err error) {
func (lm *loggingMiddleware) ListCerts(ctx context.Context, token, thingID string, offset, limit uint64) (cp certs.Page, err error) {
defer func(begin time.Time) {
message := fmt.Sprintf("Method list_certs for token: %s took %s to complete", token, time.Since(begin))
message := fmt.Sprintf("Method list_certs for token: %s and thing id: %s took %s to complete", token, thingID, time.Since(begin))
if err != nil {
lm.logger.Warn(fmt.Sprintf("%s with error: %s.", message, err))
return
}
lm.logger.Info(fmt.Sprintf("%s without errors.", message))
}(time.Now())

return lm.svc.ListCerts(ctx, token, offset, limit)
return lm.svc.ListCerts(ctx, token, thingID, offset, limit)
}

func (lm *loggingMiddleware) RevokeCert(ctx context.Context, token, thingID string) (c certs.Revoke, err error) {
Expand Down
4 changes: 2 additions & 2 deletions certs/api/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ func (ms *metricsMiddleware) IssueCert(ctx context.Context, token, thingID strin
return ms.svc.IssueCert(ctx, token, thingID, daysValid, keyBits, keyType)
}

func (ms *metricsMiddleware) ListCerts(ctx context.Context, token string, offset, limit uint64) (certs.Page, error) {
func (ms *metricsMiddleware) ListCerts(ctx context.Context, token, thingID string, offset, limit uint64) (certs.Page, error) {
defer func(begin time.Time) {
ms.counter.With("method", "list_certs").Add(1)
ms.latency.With("method", "list_certs").Observe(time.Since(begin).Seconds())
}(time.Now())

return ms.svc.ListCerts(ctx, token, offset, limit)
return ms.svc.ListCerts(ctx, token, thingID, offset, limit)
}

func (ms *metricsMiddleware) RevokeCert(ctx context.Context, token, thingID string) (certs.Revoke, error) {
Expand Down
13 changes: 7 additions & 6 deletions certs/api/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ func (req addCertsReq) validate() error {
}

type listReq struct {
token string
offset uint64
limit uint64
thingID string
token string
offset uint64
limit uint64
}

func (req *listReq) validate() error {
Expand All @@ -39,12 +40,12 @@ func (req *listReq) validate() error {
}

type revokeReq struct {
token string
ThingID string `json:"thing_id"`
token string
certID string
}

func (req *revokeReq) validate() error {
if req.token == "" || req.ThingID == "" {
if req.token == "" || req.certID == "" {
return certs.ErrUnauthorizedAccess
}

Expand Down
22 changes: 10 additions & 12 deletions certs/api/responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,15 @@ type pageRes struct {

type certsPageRes struct {
pageRes
Certs []certsResponse `json:"certs"`
Error string `json:"error,omitempty"`
Certs []certsRes `json:"certs"`
}

type certsResponse struct {
ClientCert map[string]string `json:"client_cert"`
ClientKey map[string]string `json:"client_key"`
Serial string `json:"serial"`
ThingID string `json:"thing_id"`
CACert string `json:"ca_cert"`
Error string `json:"error"`
type certsRes struct {
ThingID string `json:"thing_id"`
Cert string `json:"cert"`
CertKey string `json:"cert_key"`
CertSerial string `json:"cert_serial"`
CACert string `json:"ca_cert"`
}

func (res certsPageRes) Code() int {
Expand All @@ -40,14 +38,14 @@ func (res certsPageRes) Empty() bool {
return false
}

func (res certsResponse) Code() int {
func (res certsRes) Code() int {
return http.StatusCreated
}

func (res certsResponse) Headers() map[string]string {
func (res certsRes) Headers() map[string]string {
return map[string]string{}
}

func (res certsResponse) Empty() bool {
func (res certsRes) Empty() bool {
return false
}
21 changes: 9 additions & 12 deletions certs/api/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ func MakeHandler(svc certs.Service) http.Handler {
opts...,
))

r.Get("/certs", kithttp.NewServer(
r.Get("/certs/:thingId", kithttp.NewServer(
listCerts(svc),
decodeListCerts,
encodeResponse,
opts...,
))

r.Delete("/certs/revoke", kithttp.NewServer(
r.Delete("/certs/:certId", kithttp.NewServer(
revokeCert(svc),
decodeRevokeCerts,
encodeResponse,
Expand Down Expand Up @@ -99,9 +99,10 @@ func decodeListCerts(_ context.Context, r *http.Request) (interface{}, error) {
return nil, err
}
req := listReq{
token: r.Header.Get("Authorization"),
limit: l,
offset: o,
token: r.Header.Get("Authorization"),
thingID: bone.GetValue(r, "thingId"),
limit: l,
offset: o,
}
return req, nil
}
Expand Down Expand Up @@ -139,13 +140,9 @@ func decodeCerts(_ context.Context, r *http.Request) (interface{}, error) {
}

func decodeRevokeCerts(_ context.Context, r *http.Request) (interface{}, error) {
if r.Header.Get("Content-Type") != contentType {
return nil, errUnsupportedContentType
}

req := revokeReq{token: r.Header.Get("Authorization")}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, err
req := revokeReq{
token: r.Header.Get("Authorization"),
certID: bone.GetValue(r, "certId"),
}

return req, nil
Expand Down
4 changes: 2 additions & 2 deletions certs/certs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ type Repository interface {
// Save saves cert for thing into database
Save(ctx context.Context, cert Cert) (string, error)

// RetrieveAll retrieve all issued certificates for given owner
RetrieveAll(ctx context.Context, ownerID string, offset, limit uint64) (Page, error)
// RetrieveAll retrieve all issued certificates for given owner and thing id
RetrieveAll(ctx context.Context, ownerID, thingID string, offset, limit uint64) (Page, error)

// Remove certificate from DB for given thing
Remove(ctx context.Context, thingID string) error
Expand Down
87 changes: 87 additions & 0 deletions certs/mocks/certs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0

package mocks

import (
"context"
"sync"

"github.com/mainflux/mainflux/certs"
)

var _ certs.Repository = (*certsRepoMock)(nil)

type certsRepoMock struct {
mu sync.Mutex
counter uint64
certs map[string]certs.Cert
certsByThingID map[string]certs.Cert
}

// NewCertsRepository creates in-memory certs repository.
func NewCertsRepository() certs.Repository {
return &certsRepoMock{
certs: make(map[string]certs.Cert),
certsByThingID: make(map[string]certs.Cert),
}
}

func (c *certsRepoMock) Save(ctx context.Context, cert certs.Cert) (string, error) {
c.mu.Lock()
defer c.mu.Unlock()
c.certs[cert.Serial] = cert
c.certsByThingID[cert.ThingID] = cert
c.counter++
return cert.Serial, nil
}

func (c *certsRepoMock) RetrieveAll(ctx context.Context, ownerID, thingID string, offset, limit uint64) (certs.Page, error) {
c.mu.Lock()
defer c.mu.Unlock()
if limit <= 0 {
return certs.Page{}, nil
}

first := offset + 1
last := first + limit

var crts []certs.Cert
i := uint64(1)
for _, v := range c.certs {
if i >= first && i < last {
crts = append(crts, v)
}
i++
}

page := certs.Page{
Certs: crts,
Total: c.counter,
Offset: offset,
Limit: limit,
}
return page, nil
}

func (c *certsRepoMock) Remove(ctx context.Context, serial string) error {
c.mu.Lock()
defer c.mu.Unlock()
crt, ok := c.certs[serial]
if !ok {
return certs.ErrNotFound
}
delete(c.certs, crt.Serial)
delete(c.certsByThingID, crt.ThingID)
return nil
}

func (c *certsRepoMock) RetrieveByThing(ctx context.Context, thingID string) (certs.Cert, error) {
c.mu.Lock()
defer c.mu.Unlock()
crt, ok := c.certsByThingID[thingID]
if !ok {
return certs.Cert{}, certs.ErrNotFound
}
return crt, nil
}
Loading

0 comments on commit 74aa93f

Please sign in to comment.