55 "fmt"
66 "os"
77 "path/filepath"
8+ "time"
89
910 "github.com/massalabs/station/int/configuration"
1011 "github.com/massalabs/station/pkg/certificate"
@@ -28,31 +29,19 @@ func Check() error {
2829
2930 certPath := filepath .Join (caRootPath , configuration .CertificateAuthorityFileName )
3031
31- isBrandNewCA := false
32-
33- _ , err = os .Stat (certPath )
34- if os .IsNotExist (err ) {
35- err = certificate .GenerateCA (
36- configuration .OrganizationName ,
37- configuration .CertificateAuthorityKeyFileName ,
38- configuration .CertificateAuthorityFileName ,
39- caRootPath ,
40- )
41- if err != nil {
42- return caNonBlockingError ("failed to generate new CA" , err )
43- }
44-
45- logger .Infof ("A new CA was generated at %s." , certPath )
46-
47- // A new CA was generated, we need to clean the certificates.
48- isBrandNewCA = true
32+ // Ensure CA certificate exists and is valid
33+ isBrandNewCA , err := ensureValidCA (certPath , caRootPath )
34+ if err != nil {
35+ return caNonBlockingError ("failed to ensure valid CA" , err )
4936 }
5037
38+ // Check certificate in system store
5139 err = checkCertificate (certPath )
5240 if err != nil {
5341 resultErr = caNonBlockingError ("Error while checking certificate" , err )
5442 }
5543
44+ // Check NSS configuration
5645 err = checkNSS (certPath , isBrandNewCA )
5746 if err != nil {
5847 resultErr = caNonBlockingError ("Error while checking NSS" , err )
@@ -61,6 +50,54 @@ func Check() error {
6150 return resultErr
6251}
6352
53+ // ensureValidCA ensures that a valid CA certificate exists at the specified path.
54+ // It returns true if a new CA was generated, false if existing CA is valid.
55+ func ensureValidCA (certPath , caRootPath string ) (bool , error ) {
56+ // Check if certificate file exists
57+ _ , err := os .Stat (certPath )
58+ if os .IsNotExist (err ) {
59+ logger .Infof ("Certificate file does not exist, generating new CA..." )
60+ return true , generateCA (caRootPath , "certificate file does not exist" )
61+ }
62+
63+ // Certificate file exists, validate it
64+ existingCert , loadErr := certificate .LoadCertificate (certPath )
65+ if loadErr != nil {
66+ logger .Warnf ("Failed to load existing certificate: %v, generating new one" , loadErr )
67+ return true , generateCA (caRootPath , "failed to load existing certificate" )
68+ }
69+
70+ // Check if certificate is expired
71+ if existingCert .NotAfter .Before (time .Now ()) {
72+ logger .Warnf ("Certificate is expired (NotAfter=%s), generating new one" , existingCert .NotAfter .String ())
73+ return true , generateCA (caRootPath , "certificate is expired" )
74+ }
75+
76+ // Certificate is valid
77+ logger .Debugf ("Certificate is valid until %s" , existingCert .NotAfter .String ())
78+ return false , nil
79+ }
80+
81+ // generateCA generates a new CA certificate with consistent parameters and logging.
82+ func generateCA (caRootPath , reason string ) error {
83+ logger .Infof ("Generating new CA certificate (reason: %s)..." , reason )
84+
85+ err := certificate .GenerateCA (
86+ configuration .OrganizationName ,
87+ configuration .CertificateAuthorityKeyFileName ,
88+ configuration .CertificateAuthorityFileName ,
89+ caRootPath ,
90+ )
91+ if err != nil {
92+ return fmt .Errorf ("failed to generate CA certificate: %w" , err )
93+ }
94+
95+ certPath := filepath .Join (caRootPath , configuration .CertificateAuthorityFileName )
96+ logger .Infof ("New CA certificate generated successfully at %s" , certPath )
97+
98+ return nil
99+ }
100+
64101// nonBlockingError logs a non blocking error. It always returns a `nil` error to be used in `return`.
65102func nonBlockingError (context string , consequence string , err error ) error {
66103 if err != nil {
@@ -78,27 +115,49 @@ func caNonBlockingError(context string, err error) error {
78115
79116// checkCertificate checks the certificate configuration.
80117func checkCertificate (certPath string ) error {
118+ // Load certificate
119+ certCA , err := loadCertificate (certPath )
120+ if err != nil {
121+ return err
122+ }
123+
124+ // Check if certificate is trusted by the operating system
125+ return ensureCertificateInSystemStore (certCA )
126+ }
127+
128+ // loadCertificate loads a certificate.
129+ func loadCertificate (certPath string ) (* x509.Certificate , error ) {
81130 certCA , err := certificate .LoadCertificate (certPath )
82131 if err != nil {
83- return fmt .Errorf ("failed to load the CA: %w" , err )
132+ return nil , fmt .Errorf ("failed to load the CA: %w" , err )
84133 }
85134
86- // disable linting as we don't care about checking specific attributes
87- //nolint:exhaustruct
88- _ , err = certCA .Verify (x509.VerifyOptions {})
135+ return certCA , nil
136+ }
137+
138+ // ensureCertificateInSystemStore ensures the certificate is trusted by the operating system.
139+ func ensureCertificateInSystemStore (certCA * x509.Certificate ) error {
140+ // Check if certificate is already trusted by the OS
141+ //nolint:exhaustruct // We don't care about checking specific attributes
142+ _ , err := certCA .Verify (x509.VerifyOptions {})
89143 if err != nil {
90- logger .Debug ("the CA is not known by the operating system." )
144+ logger .Debug ("Certificate is not trusted by the operating system, adding to store" )
145+ return addCertificateToSystemStore (certCA )
146+ }
91147
92- err := store .Add (certCA )
93- if err != nil {
94- return fmt .Errorf ("failed to add the CA to the operating system: %w" , err )
95- }
148+ logger .Debug ("Certificate is already trusted by the operating system" )
149+ return nil
150+ }
96151
97- logger .Debug ("the CA was added to the operating system." )
98- } else {
99- logger .Debug ("the CA is known by the operating system." )
152+ // addCertificateToSystemStore adds a certificate to the operating system store.
153+ func addCertificateToSystemStore (certCA * x509.Certificate ) error {
154+ err := store .Add (certCA )
155+ if err != nil {
156+ logger .Errorf ("Failed to add certificate to operating system: %v" , err )
157+ return fmt .Errorf ("failed to add the CA to the operating system: %w" , err )
100158 }
101159
160+ logger .Debug ("Certificate successfully added to the operating system store" )
102161 return nil
103162}
104163
0 commit comments