feat: Integration with Cumulocity CA#3259
Conversation
844dc34 to
284c8ee
Compare
284c8ee to
fba8ed6
Compare
5f284b5 to
5335af8
Compare
Robot Results
|
8ee9b20 to
abfa57e
Compare
Cert renewalTo start out, the certificate renewal will be facilitated by an external process (default using system timer service) to actively renew the certificate. In order to make it easy for external processes to trigger a certificate renewal, there needs to be a way a process can check if the certificate is about to expire (with the minimum value as defined in The command used to check the validity of the certificate should produce the following exit code, so that the calling process can respond accordingly. There are several options where the above certificate validity can be placed, below are some options. Inspiration for this type of renewal is taken from smallstep Option 1: New subcommand to check if the cert needs renewal or nottedge cert needs-renewal c8yExit codes:
Option 2: Flag in renew commandtedge cert renew c8y --needs-renewalExit codes:
|
I would return a non |
Yes basically. The renewal might not work, but at least it will be attempted. This choice was also taken from the smallstep cli command, step certificate needs-renewal Below is the example of the exist code description from their docs:
|
Implemented with ea03cc5 |
| } | ||
| }; | ||
|
|
||
| if is_self_signed { |
There was a problem hiding this comment.
It would be useful if we allow users to migrate from a self-signed certificate to a certificate issued by the Cumulocity CA, as this is probably the position that a lot of thin-edge.io c8y users are currently in.
So it would be useful to be able to control whether we're re-creating a new self-signed certificate, or doing the default action to request a new certificate via the new Cumulocity CA service.
There was a problem hiding this comment.
Good point. Indeed, directly asking c8y CA for a renewal should work in such a case despite the current certificate having not been issued by v8y.
There was a problem hiding this comment.
Yeah I can confirm that Cumulocity can issue a new certificate to the device (as it is using the JWT for validation and not the certificate, which works nicely)
There was a problem hiding this comment.
I see two options, my preference being for the second one.
implicit:
When the certificate is used to connect c8y, try first to post the renewal request to c8y CA and fallback to a self-signed certificate when the response is a 404 and the current certificate is self-signed.
- Warn the user when the new certificate is self-signed: this certificate has to be uploaded on the tenant to be trusted.
- Pros: No new command line options
- Cons: the command seems simpler to use, but it is not, as a second critical step might be required.
explicit:
Add a --self-signed option (which default is false).
- When
--self-signedis false and the endpoint is c8y, then request the renewal to c8y CA. Let the current certificate unchanged if this fails. - Return an error if
--self-signedis true but the certificate is not self-signed. - Return an error if
--self-signedis false and the endpoint is not c8y. - Cons: This changes how
tedge cert renewbehaves - Pros: Make self-signed certificates second-class citizens
There was a problem hiding this comment.
It would be useful if we allow users to migrate from a self-signed certificate to a certificate issued by the Cumulocity CA, as this is probably the position that a lot of thin-edge.io c8y users are currently in.
Similarly, we can support users moving away from device passwords.
So it would be useful to be able to control whether we're re-creating a new self-signed certificate, or doing the default action to request a new certificate via the new Cumulocity CA service.
And, along the same lines, it would be useful to improve tedge cert download or tedge cert renew so a very first certificate can be retrieved using the renewal API and authenticating via JWT.
There was a problem hiding this comment.
Add a
--self-signedoption (which default is false).
Implemented: db15855
rina23q
left a comment
There was a problem hiding this comment.
The changes are very clear and easy to read. I was not able to test with c8y fully since my tenant is missing something for now. I'll test again once my tenant issue is solved.
rina23q
left a comment
There was a problem hiding this comment.
It works like a charm, really nice feature! Now it's super easy to register a device in c8y!
reubenmiller
left a comment
There was a problem hiding this comment.
Approved (from a functional level). It has all of the fundamental elements to build a renewal service on top.
Bravo555
left a comment
There was a problem hiding this comment.
As for the code itself, LGTM, only managed to find a single typo. But are documentation additions, like a reference or a user guide planned in this PR or in a follow-up?
Cargo.toml
Outdated
| proptest = "1.0" | ||
| quote = "1" | ||
| rand = "0.8" | ||
| rasn = "0.18.0" |
There was a problem hiding this comment.
question: Is there a specific reason why we're not using the latest version?
There was a problem hiding this comment.
Regarding crate versions, long time ago, we decided to specify until minor version (like 0.18), but I see now our Cargo.toml is mixed of major.minor.patch and major.minor. I'm also curious why here is 3 digits.
There was a problem hiding this comment.
Because not compatible with our current MSRV.
Added a comment and removed the patch suffix: e777d3e
| /// This can be used to bypass the default behavior | ||
| /// which is to forward the renewal request to the cloud CA | ||
| /// even if the current certificate has not been signed by this CA. | ||
| /// In most case, the default behavior is what you want: |
There was a problem hiding this comment.
typo:
| /// In most case, the default behavior is what you want: | |
| /// In most cases, the default behavior is what you want: |
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
| #[tedge_config(example = "365d", default(from_str = "365d"))] | ||
| requested_duration: SecondsOrHumanTime, | ||
|
|
||
| /// Minimum validity duration bellow which a new certificate should be requested |
There was a problem hiding this comment.
| /// Minimum validity duration bellow which a new certificate should be requested | |
| /// Minimum validity duration below which a new certificate should be requested |
| #[clap(verbatim_doc_comment)] | ||
| /// Request and download the device certificate from Cumulocity | ||
| /// | ||
| /// - Generate a private key and Signing Certificate Request (CSR) for the device |
There was a problem hiding this comment.
| /// - Generate a private key and Signing Certificate Request (CSR) for the device | |
| /// - Generate a private key and Certificate Signing Request (CSR) for the device |
| /// - Generate a private key and Signing Certificate Request (CSR) for the device | ||
| /// - Upload this CSR on Cumulocity, using the provided device identifier and security token | ||
| /// - Loop till the device is registered by an administrator and the CSR accepted | ||
| /// - Store the certificate created by Cumulocity |
There was a problem hiding this comment.
| /// - Store the certificate created by Cumulocity | |
| /// - Download and store the certificate created by Cumulocity |
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Previously, this command was only able to show the device certificate (for some cloud profile) Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
The current implementation is simplified knowing that `tedge cert renew` only supports self-signed certificates and certificates signed by c8y and more precisely by the CA of the c8y tenant the device is connected to. Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
This licence is indirectly required by `rasn-cms` the crate used to decode pkcs#7 certificates received from EST. Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
…gned Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
|
|
||
| impl DownloadCertCmd { | ||
| async fn download_device_certificate(&self) -> Result<(), Error> { | ||
| let (common_name, security_token) = self.get_registration_data()?; |
There was a problem hiding this comment.
This should probably use spawn_blocking
Proposed changes
Make sure the current certificate is not erased on renewalThis will be done by an external tool (wrapping the renewal with a reconnect and a rollback on error)Types of changes
Paste Link to the issue
#3248
Checklist
cargo fmtas mentioned in CODING_GUIDELINEScargo clippyas mentioned in CODING_GUIDELINESFurther comments