mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
* feat: Add opt-in support for proxy CA cert installation * fix: Code review fixes * fix: Code review fixes * fix: Code review fixes * fix: Code review fixes * fix: Code review fixes * docs: Add limitation for MacOS MDM script
85 lines
2.3 KiB
Go
85 lines
2.3 KiB
Go
package certmanager
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"crypto/x509"
|
|
"encoding/hex"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
// ExpiryWarnWindow is how close to NotAfter a CA must be before status/doctor
|
|
// surface an expiry warning.
|
|
const ExpiryWarnWindow = 30 * 24 * time.Hour
|
|
|
|
// CAStatus is the reusable status model shared by `cert status`, `setup doctor`,
|
|
// and `setup info`. Disk-side fields are filled by InspectCA; trust fields are
|
|
// filled by the caller from the truststore package (kept here so certmanager
|
|
// stays free of any OS/trust-store import).
|
|
type CAStatus struct {
|
|
KeyPresent bool
|
|
CertPresent bool
|
|
NotAfter time.Time
|
|
Expired bool
|
|
ExpiringSoon bool
|
|
Fingerprint string
|
|
UserTrusted bool
|
|
SystemTrusted bool
|
|
}
|
|
|
|
func (s CAStatus) Trusted() bool { return s.UserTrusted || s.SystemTrusted }
|
|
|
|
// Drift reports on-disk integrity / expiry problems independent of OS trust
|
|
// policy. Trust-store presence is intentionally NOT evaluated here: "not in a
|
|
// store" is normal on Linux (Go honors SSL_CERT_FILE), so consumers interpret
|
|
// trust state per platform.
|
|
func (s CAStatus) Drift() (bool, string) {
|
|
if s.CertPresent && !s.KeyPresent {
|
|
return true, "CA certificate on disk but private key missing"
|
|
}
|
|
if s.KeyPresent && !s.CertPresent {
|
|
return true, "CA private key on disk but certificate missing"
|
|
}
|
|
if s.KeyPresent && s.Expired {
|
|
return true, "CA expired; re-run `pmg setup cert install`"
|
|
}
|
|
return false, ""
|
|
}
|
|
|
|
// InspectCA gathers disk-side CA facts from dir. Absence of the files is not an
|
|
// error; the returned CAStatus simply reports them as not present.
|
|
func InspectCA(dir string) (CAStatus, error) {
|
|
var st CAStatus
|
|
|
|
if _, err := os.Stat(CAKeyPath(dir)); err == nil {
|
|
st.KeyPresent = true
|
|
}
|
|
|
|
certPEM, err := os.ReadFile(CACertPath(dir))
|
|
if err != nil {
|
|
return st, nil
|
|
}
|
|
st.CertPresent = true
|
|
|
|
block, _ := pem.Decode(certPEM)
|
|
if block == nil {
|
|
return st, fmt.Errorf("failed to decode CA certificate PEM")
|
|
}
|
|
|
|
x509Cert, err := x509.ParseCertificate(block.Bytes)
|
|
if err != nil {
|
|
return st, fmt.Errorf("failed to parse CA certificate: %w", err)
|
|
}
|
|
|
|
st.NotAfter = x509Cert.NotAfter
|
|
st.Expired = time.Now().After(x509Cert.NotAfter)
|
|
st.ExpiringSoon = !st.Expired && time.Until(x509Cert.NotAfter) < ExpiryWarnWindow
|
|
|
|
sum := sha256.Sum256(x509Cert.Raw)
|
|
st.Fingerprint = hex.EncodeToString(sum[:])
|
|
|
|
return st, nil
|
|
}
|