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 (#318)
* 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
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user