Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MF-1676 - Make Bootstrap fetch Certs data on demand #1669

Open
wants to merge 81 commits into
base: main
Choose a base branch
from

Conversation

arvindh123
Copy link
Contributor

@arvindh123 arvindh123 commented Nov 18, 2022

What does this do?

Renew the expired cert, If the cert is not available in bootstrap and thing service, then it will remove all the certs.

Which issue(s) does this PR fix/relate to?

Resolves #1677 and partially #1678.

List any changes that modify/break current functionality

Have you included tests for your changes?

Did you document any new/modified functionality?

Notes

@arvindh123
Copy link
Contributor Author

@mainflux/maintainers
Hello,
At present, in certs table, one thing can have Mutiple certificate, in cert table one thing will Mutiple expired certificate,
So if this PR tries to renew all the expired certificate of one thing, then there will be lot of certificates for a thing,
So to solve this problem, this PR is approach in different way, One thing can have one certificate.
The cert service will renew expired thing certificate and update the serial number in cert table.

Comment on lines 83 to 89
defESURL = "localhost:6379"
defESPass = ""
defESDB = "0"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like these are not used.

Copy link
Contributor Author

@arvindh123 arvindh123 Nov 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still Work in Progress for this variables, ES is used to get notification of deleted things

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed unsed

return c.token, nil
}

func (c *bootstrapClient) UpdateCerts(ctx context.Context, thingID, clientCert, clientKey, caCert string) error {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we use c.sdk.UpdateBootstrapCerts here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I will try to use c.sdk.UpdateBootstrapCerts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dborovcanin, we can't use c.sdk.UpdateBootstrapCerts , since SDK simply reply with status , and we need more detailed about the response body
https://github.com/mainflux/mainflux/blob/d73a5d53fec0313a51ca933321ea75de7ad0c90e/pkg/sdk/go/bootstrap.go#L180

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dborovcanin, we can't use c.sdk.UpdateBootstrapCerts , since SDK simply reply with status , and we need more detailed about the response body

https://github.com/mainflux/mainflux/blob/d73a5d53fec0313a51ca933321ea75de7ad0c90e/pkg/sdk/go/bootstrap.go#L180

Is this only because SDK does not return return error based on the reponse, but on status code? In that case, we should update SDK to return more specifc error.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it use sdk now

certs/certs.go Outdated
ListExpiredCerts(ctx context.Context, timeBefore time.Duration, limit, offset uint64) (Page, error)

// AutoRetrieveByThingID retrieves list of certificate for a given thing ID without owner ID , used for AutoRenew process
AutoRetrieveByThingID(ctx context.Context, thingID string) (Cert, error)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for the Auto prefix, it sounds misleading (I know we don't take owner ID into account, but that's fine because we do not have another repo method that does).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The repo method RetrieveByThing do the same but with owner ID

RetrieveByThing(ctx context.Context, ownerID, thingID string, offset, limit uint64) (Page, error)

So to identify the function with name I kept like that way. I can't able to think for another name at that time , Could you suggest a better name or prefix ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can make it a single method (RetrieveByThingID) and make it use userID only if present (i.e. ignore if empty, the same way search and filtering by some criteria usually work). On the service level, you decide how to handle authorization.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the AutoRetrieveByThingID functions are no more need , the function are removed
the AutoRemoveByThingID function name changed to ThingCertsRevokeHandler

@@ -102,6 +102,31 @@ func (cr certsRepository) Save(ctx context.Context, cert certs.Cert) (string, er
return cert.Serial, nil
}

func (cr certsRepository) Update(ctx context.Context, cert certs.Cert) error {
q := `UPDATE certs SET serial = :serial, expire = :expire WHERE thing_id = :thing_id AND owner_id = :owner_id`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix formatting.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope, I fixed the formatting

@@ -170,6 +195,77 @@ func (cr certsRepository) RetrieveBySerial(ctx context.Context, ownerID, serialI
return c, nil
}

func (cr certsRepository) ListExpiredCerts(ctx context.Context, timeBefore time.Duration, limit, offset uint64) (certs.Page, error) {
whereClause := fmt.Sprintf("WHERE expire <= now() - interval '%s'", timeBefore)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure using Database server time is better than using service time? It's possible that those two are not the same and this can be a source of the sneaky errors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I agree with your point, I will change the approch

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one doesn't seem addressed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, expire calculate from service time

certs/service.go Outdated
// Renew the exipred certificate from certs repo
RenewCerts(ctx context.Context, bsUpdateRenewCert bool) error

// Automattically trigger RenewCert function for given renew interval time
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix typo Automatically and add a comment for the next method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No more this function is needed in code. It was removed

Signed-off-by: Arvindh <[email protected]>
Signed-off-by: Arvindh <[email protected]>
@@ -90,3 +90,42 @@ func (lm *loggingMiddleware) RevokeCert(ctx context.Context, token, thingID stri

return lm.svc.RevokeCert(ctx, token, thingID)
}

func (lm *loggingMiddleware) RenewCerts(ctx context.Context, bsUpdateRenewCert bool) (err error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please align the log message with the rest of the service: Method <method name> <other useful info> took <duration> to complete <errors if any>.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method returns only error
The error contains all the details,

// ErrUnexpectedBSResponse indicates unexpected response from Bootstrap service.
ErrUnexpectedBSResponse = errors.New("unexpected Bootstrap service response")

ErrUnableToAccess = errors.New("unable to access bootstrap service")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comments for exported errors.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't forget to address this one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return c.token, nil
}

func (c *bootstrapClient) UpdateCerts(ctx context.Context, thingID, clientCert, clientKey, caCert string) error {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about this?

}
return errors.New(string(b))
}
func request(ctx context.Context, method, url string, data []byte, header map[string]string) (*http.Response, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add an empty line between methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

certs/certs.go Outdated
Comment on lines 42 to 46
// // AutoRetrieveByThingID retrieves list of certificate for a given thing ID without owner ID , used for AutoRenew process
// AutoRetrieveByThingID(ctx context.Context, thingID string) (Cert, error)

// // AutoRemoveByThingID removes certificate from DB for a given thing ID without owner ID , used for AutoRenew process
// AutoRemoveByThingID(ctx context.Context, thingID string) error
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove commented code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The functions no more needed removed

@@ -170,6 +195,77 @@ func (cr certsRepository) RetrieveBySerial(ctx context.Context, ownerID, serialI
return c, nil
}

func (cr certsRepository) ListExpiredCerts(ctx context.Context, timeBefore time.Duration, limit, offset uint64) (certs.Page, error) {
whereClause := fmt.Sprintf("WHERE expire <= now() - interval '%s'", timeBefore)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one doesn't seem addressed.

Comment on lines 268 to 297
// func (cr certsRepository) AutoRetrieveByThingID(ctx context.Context, thingID string) (certs.Cert, error) {
// q := `SELECT thing_id, owner_id, serial, expire FROM certs WHERE thing_id = $1`
// var dbcrt dbCert
// var c certs.Cert
// if err := cr.db.QueryRowxContext(ctx, q, thingID).StructScan(&dbcrt); err != nil {
// pqErr, ok := err.(*pq.Error)
// if err == sql.ErrNoRows || ok && errInvalid == pqErr.Code.Name() {
// return c, errors.Wrap(errors.ErrNotFound, err)
// }

// return c, errors.Wrap(errors.ErrViewEntity, err)
// }
// c = toCert(dbcrt)
// return c, nil
// }

// func (cr certsRepository) AutoRemoveByThingID(ctx context.Context, thingID string) error {
// if _, err := cr.AutoRetrieveByThingID(ctx, thingID); err != nil {
// return errors.Wrap(errors.ErrRemoveEntity, err)
// }
// q := `DELETE FROM certs WHERE thing_id = :thingID`
// var c certs.Cert
// c.ThingID = thingID
// dbcrt := toDBCert(c)
// if _, err := cr.db.NamedExecContext(ctx, q, dbcrt); err != nil {
// return errors.Wrap(errors.ErrRemoveEntity, err)
// }
// return nil
// }

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove commented code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

Comment on lines 10 to 14
type updateChannelEvent struct {
id string
name string
metadata map[string]interface{}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

certs/service.go Outdated
ErrFailedCertRevocation = errors.New("failed to revoke certificate")
ErrFailedCertRevocation = errors.New("failed to revoke certificate in PKI")

errThingNotInBS = errors.New("Thing not found in bootstrap service")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment exported errors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@dborovcanin dborovcanin changed the title MF-1668: Auto renewal of expired certificates from the PKI issuer MF-1668 - Auto renewal of expired certificates from the PKI issuer Jan 4, 2023
@arvindh123 arvindh123 changed the title MF-1668 - Auto renewal of expired certificates from the PKI issuer MF-1676 Make Bootstrap fetch Certs data on demand & MF - 1677 Enable multiple certificates for a single Thing Jan 17, 2023
@dborovcanin dborovcanin changed the title MF-1676 Make Bootstrap fetch Certs data on demand & MF - 1677 Enable multiple certificates for a single Thing MF-1676 - Make Bootstrap fetch Certs data on demand Jan 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enable multiple certificates for a single Thing
3 participants