From 578a5de309ae9ef116cf22c21b1b7710ec410873 Mon Sep 17 00:00:00 2001 From: Nathan Coad Date: Thu, 13 Mar 2025 14:04:07 +1100 Subject: [PATCH] check local clock is accurate --- go.mod | 7 +++++++ go.sum | 6 ++++++ main.go | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 99effde..606926d 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,11 @@ module nathan/go-ntp + go 1.24.1 require github.com/vmware/govmomi v0.43.0 + +require ( + github.com/beevik/ntp v1.4.3 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect +) diff --git a/go.sum b/go.sum index e429be2..e350f68 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,12 @@ +github.com/beevik/ntp v1.4.3 h1:PlbTvE5NNy4QHmA4Mg57n7mcFTmr1W1j3gcK7L1lqho= +github.com/beevik/ntp v1.4.3/go.mod h1:Unr8Zg+2dRn7d8bHFuehIMSvvUYssHMxW3Q5Nx4RW5Q= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/vmware/govmomi v0.30.4 h1:BCKLoTmiBYRuplv3GxKEMBLtBaJm8PA56vo9bddIpYQ= github.com/vmware/govmomi v0.30.4/go.mod h1:F7adsVewLNHsW/IIm7ziFURaXDaHEwcc+ym4r3INMdY= github.com/vmware/govmomi v0.43.0 h1:7Kg3Bkdly+TrE67BYXzRq7ZrDnn7xqpKX95uEh2f9Go= github.com/vmware/govmomi v0.43.0/go.mod h1:IOv5nTXCPqH9qVJAlRuAGffogaLsNs8aF+e7vLgsHJU= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/main.go b/main.go index a877ad4..b5d24e9 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,7 @@ import ( "time" _ "time/tzdata" + "github.com/beevik/ntp" "github.com/vmware/govmomi" "github.com/vmware/govmomi/find" "github.com/vmware/govmomi/view" @@ -39,6 +40,9 @@ var ( hostTimeErrors []HostTimeErrors ) +// maxAllowedDrift is the maximum allowed time difference (1 second). +const maxAllowedDrift = 2 * time.Second + /* type dateInfo struct { types.HostDateTimeInfo @@ -47,6 +51,37 @@ type dateInfo struct { } */ +func checkClockDrift(ntpServers []string) bool { + localTime := time.Now() + inSync := false + + for _, server := range ntpServers { + ntpTime, err := ntp.Time(server) + if err != nil { + log.Printf("Failed to get time from %s: %v\n", server, err) + continue + } + + diff := localTime.Sub(ntpTime) + if diff < 0 { + diff = -diff + } + + log.Printf("NTP Server: %s\n", server) + log.Printf("Local Time: %s\n", localTime) + log.Printf("NTP Time : %s\n", ntpTime) + log.Printf("Time Difference: %v\n", diff) + + if diff <= maxAllowedDrift { + inSync = true + } + + log.Println("----------") + } + + return inSync +} + func prettyPrint(args ...interface{}) { var caller string @@ -82,6 +117,7 @@ func main() { vTZ := flag.String("tz", "Australia/Sydney", "The timezone to use when converting vCenter UTC times") vInsecure := flag.Bool("insecure", true, "Allow insecure connections to vCenter") vAllowedDiff := flag.Int("diff", 300, "Permitted time difference in seconds") + vNtpServers := flag.String("ntp-servers", "pool.ntp.org", "A comma separated list of NTP sources to validate the local system clock") flag.Parse() @@ -99,7 +135,7 @@ func main() { log.Printf("Setting timezone to '%s'\n", *vTZ) location, err = time.LoadLocation(*vTZ) if err != nil { - fmt.Fprintf(os.Stderr, "Error setting timezone to %s : %s\n", *vTZ, err) + log.Printf("Error setting timezone to %s : %s\n", *vTZ, err) os.Exit(1) } @@ -114,6 +150,15 @@ func main() { } } + // Validate system clock + ntpList := strings.FieldsFunc(*vNtpServers, func(r rune) bool { + return r == ',' + }) + if !checkClockDrift(ntpList) { + log.Fatalf("Local system clock is not in sync, unable to proceed") + os.Exit(1) + } + log.Printf("Connecting to vCenter %s\n", u) u.User = url.UserPassword(*vUser, *vPass)