What is the best way to update CA root certs? I am running the script below every 7 days but I wondered if there is a better way to work out if they actually need updating before downloading, deleting and replacing certs every week.
Also - can running this every week damage flash RAM (or whatever memory is inside it).
So if I run 3 monthly and a cert expires the day after the last script run then potentially I wait 3 months for this remote site to update root certs so the dynamic DNS IP update script can run via https.
It would be very bad practice for a certificate issuer to update their root certs only the day before they expire!
Remember all certs issued to clients depend on the root cert to be valid at least as long as the issued certificate.
As these are valid often for a year, the new root cert should be issued at least a year before the old one expires.
And these are usually valid for 10 years or so.
The first time do not work with “check-certificate=yes” because the certificate is not already present.
Must be done first time manually without “check-certificate=yes”…
also this do not work:
/certificate remove [ find where authority expired ];
because no one certificate is “authority” (authority is just the machine itself that generate certificates)
so that line must be only /certificate remove [find where name~“certs.pem*” expired=yes]
These were the changes which I did because I found it always failed on first run.
This is based off the original code posted by @ilium007, so I made the following changes to make it more reliable.
{
:local retryCount 0;
:local maxRetries 3;
:local success false;
:do {
:while ($retryCount < $maxRetries && !$success) do={
:do {
/tool fetch url=https://mkcert.org/generate/ check-certificate=yes dst-path=cacert.pem;
/certificate remove [ find where authority expired ];
/certificate import file-name=cacert.pem passphrase="";
/file remove cacert.pem;
:log info ("Updated certificate trust store");
:set $success true;
} on-error={
:set $retryCount ($retryCount + 1);
:log error ("Failed to update certificate trust store. Attempt: $retryCount");
:delay 5s; # Delay before retrying
};
}
:if (!$success) do={
/tool e-mail send to="noc@example.io" subject="RouterOS Certificate Update Failed" body="Failed to update the certificate trust store after $maxRetries attempts.";
:log error ("Failed to update certificate trust store after $maxRetries attempts");
}
} on-error={
:log error ("Unexpected error in the update script");
};
}
As mentioned, it will fail first time as @rextended noted because the certs gets deleted on first run, so theres a small loop which will try again until sucessful upto maxRetries count and if it still fails, it will send you a mail.
Update
Just made those changes you spotted, thanks, didnt notice tbh.
{
:local retryCount 0;
:local maxRetries 3;
:local success false;
:do {
:while ($retryCount < $maxRetries && !$success) do={
:do {
/tool fetch url=https://mkcert.org/generate/all/except/nothing check-certificate=yes dst-path=cacert.pem;
:delay 15s; # Wait 15 seconds for download
/certificate remove [find where name~"cacert.pem*" expired=yes];
/certificate import file-name=cacert.pem passphrase="";
/file remove cacert.pem;
:log info ("Updated certificate trust store");
:set $success true;
} on-error={
:set $retryCount ($retryCount + 1);
:log error ("Failed to update certificate trust store. Attempt: $retryCount");
:delay 5s; # Delay before retrying
};
}
:if (!$success) do={
/tool e-mail send to="noc@example.io" subject="RouterOS Certificate Update Failed" body="Failed to update the certificate trust store after $maxRetries attempts.";
:log error ("Failed to update certificate trust store after $maxRetries attempts");
}
} on-error={
:log error ("Unexpected error in the update script");
};
}
Do not worry, is easy…
/file
print file=mkcert.txt
:delay 1s
set mkcert.txt content=“-----BEGIN CERTIFICATE-----\r
\nMIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\r
\nTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\r
\ncmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\r
\nWhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\r
\nZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\r
\nMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\r
\nh77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\r
\n0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\r
\nA5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\r
\nT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\r
\nB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\r
\nB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\r
\nKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\r
\nOlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\r
\njh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\r
\nqHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\r
\nrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\r
\nHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\r
\nhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\r
\nubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\r
\n3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\r
\nNFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\r
\nORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\r
\nTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\r
\njNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\r
\noyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\r
\n4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\r
\nmRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\r
\nemyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\r
\n-----END CERTIFICATE-----”
:delay 1s
/certificate
import file-name=mkcert.txt passphrase=“” name=imported-ca-cert_mkcert
:delay 1s
/file remove [find where name=mkcerts.txt]
:do {
/tool fetch url=https://mkcert.org/generate/all/except/nothing check-certificate=yes dst-path=mkcerts.pem
:delay 1s
remove [find where name~“imported-ca-cert*” and expired=yes]
:delay 1s
import file-name=mkcerts.pem passphrase=“” name=imported-ca-cert
:delay 1s
/file remove [find where name=mkcerts.pem]
:log info “Trust Store: Certificates update from mkcert.org succeeded”
} on-error={
:log error “Trust Store: Unable to update certificates from mkcert.org”
}
This work until Mon, 04 Jun 2035 11:04:38 GMT,
after that date, the embedded cert (on a new machine) must be updated…
And is also possible save “:execute file=result.txt” and send the result.txt file on the email.
certificates-imported: 147
private-keys-imported: 0
files-imported: 1
decryption-failures: 0
keys-with-no-certificate: 0
And is also possible, with scripting, report on log or on mail what and how many certificates deleted (if any), and what and how many certificate added (if any).
Just use the initial run of check-certificate=no then after you have the certs, set back to yes
I have tried to add some logic in but due to the initial import always errors, it always breaks the script anyways. So its much easier to just do the initial with no and then change to yes afterwards, or just use no all the time (not advised).
I believe Mikrotik should be including the rootCA’s as part of their firmware packages like other distro/hardware manufacturers, as they are really part of the OS level and clients shouldnt have to result to installing them for basic functionaly. Installing you own CA’s should only be for certain senarios where you role your own i.e your own pki.