|
1 | 1 | package cache |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "crypto/sha256" |
| 5 | + "encoding/hex" |
4 | 6 | "encoding/json" |
5 | 7 | "fmt" |
6 | 8 | "net" |
7 | 9 | "os" |
8 | 10 | "reflect" |
9 | 11 | "sort" |
| 12 | + "strconv" |
10 | 13 | "strings" |
11 | 14 | "sync" |
12 | 15 | "sync/atomic" |
@@ -178,11 +181,13 @@ const ( |
178 | 181 | type Context struct { |
179 | 182 | k8sVersion string |
180 | 183 | ocVersion string |
181 | | - RancherEP string // from yaml/helm chart |
182 | | - RancherSSO bool // from yaml/helm chart |
183 | | - TelemetryFreq uint // from yaml |
184 | | - CheckDefAdminFreq uint // from yaml, in minutes |
185 | | - CspPauseInterval uint // from yaml, in minutes |
| 184 | + RancherEP string // from yaml/helm chart |
| 185 | + RancherSSO bool // from yaml/helm chart |
| 186 | + TelemetryFreq uint // from yaml |
| 187 | + KeyRotationDuration time.Duration // from yaml |
| 188 | + CheckKeyRotationDuration time.Duration // from yaml |
| 189 | + CheckDefAdminFreq uint // from yaml, in minutes |
| 190 | + CspPauseInterval uint // from yaml, in minutes |
186 | 191 | LocalDev *common.LocalDevice |
187 | 192 | EvQueue cluster.ObjectQueueInterface |
188 | 193 | AuditQueue cluster.ObjectQueueInterface |
@@ -1679,6 +1684,9 @@ func startWorkerThread(ctx *Context) { |
1679 | 1684 | groupMetricCheckTicker := time.NewTicker(groupMetricCheckPeriod) |
1680 | 1685 | policyMetricCheckTicker := time.NewTicker(policyMetricCheckPeriod) |
1681 | 1686 |
|
| 1687 | + keyRotationCheckTicker := time.NewTicker(cctx.CheckKeyRotationDuration) |
| 1688 | + log.WithFields(log.Fields{"CheckKeyRotationDuration": cctx.CheckKeyRotationDuration, "KeyRotationDuration": cctx.KeyRotationDuration}).Info() |
| 1689 | + |
1682 | 1690 | wlSuspected := utils.NewSet() // supicious workload ids |
1683 | 1691 | pruneKvTicker := time.NewTicker(pruneKVPeriod) |
1684 | 1692 | pruneWorkloadKV(wlSuspected) // the first scan |
@@ -1742,6 +1750,8 @@ func startWorkerThread(ctx *Context) { |
1742 | 1750 | cacheMutexUnlock() |
1743 | 1751 | case <-pruneKvTicker.C: |
1744 | 1752 | pruneWorkloadKV(wlSuspected) |
| 1753 | + case <-keyRotationCheckTicker.C: |
| 1754 | + checkKeyRotation() |
1745 | 1755 | case <-scannerTicker.C: |
1746 | 1756 | if isScanner() { |
1747 | 1757 | // Remove stalled scanner |
@@ -2031,6 +2041,33 @@ func startWorkerThread(ctx *Context) { |
2031 | 2041 | log.WithFields(log.Fields{"name": o.Name, "domain": o.Domain}).Info("deleted") |
2032 | 2042 | } |
2033 | 2043 | } |
| 2044 | + case resource.RscTypeSecret: |
| 2045 | + var err error |
| 2046 | + var lock cluster.LockInterface |
| 2047 | + for i := 0; i < 4; i++ { |
| 2048 | + var encKeys common.EncKeys |
| 2049 | + var currEncKeyVer string |
| 2050 | + lock, err = clusHelper.AcquireLock(share.CLUSStoreSecretKey, time.Duration(time.Second)*4) |
| 2051 | + if err == nil { |
| 2052 | + if encKeys, currEncKeyVer, _, err = resource.RetrieveStorePassphrases(); err == nil { |
| 2053 | + if len(encKeys) > 0 { |
| 2054 | + if err = common.InitAesGcmKey(encKeys, currEncKeyVer); err == nil { |
| 2055 | + log.Info("store passphrases reloaded") |
| 2056 | + clusHelper.ReleaseLock(lock) |
| 2057 | + break |
| 2058 | + } |
| 2059 | + log.WithFields(log.Fields{"i": i, "lead": isLeader(), "err": err}).Error("Failed to init AesGcm") |
| 2060 | + } |
| 2061 | + } else { |
| 2062 | + log.WithFields(log.Fields{"i": i, "err": err}).Error("Failed to reloaded store passphrases") |
| 2063 | + } |
| 2064 | + clusHelper.ReleaseLock(lock) |
| 2065 | + } |
| 2066 | + time.Sleep(time.Second) |
| 2067 | + } |
| 2068 | + if err != nil { |
| 2069 | + log.WithFields(log.Fields{"err": err}).Error("Failed to reloaded store passphrases") |
| 2070 | + } |
2034 | 2071 | /* |
2035 | 2072 | case resource.RscTypeMutatingWebhookConfiguration: |
2036 | 2073 | var n, o *resource.AdmissionWebhookConfiguration |
@@ -2108,6 +2145,54 @@ func startWorkerThread(ctx *Context) { |
2108 | 2145 | }() |
2109 | 2146 | } |
2110 | 2147 |
|
| 2148 | +func checkKeyRotation() { |
| 2149 | + if !isLeader() { |
| 2150 | + return |
| 2151 | + } |
| 2152 | + |
| 2153 | + if valueBackup, _ := cluster.Get(share.CLUSSystemEncMigratedKey); len(valueBackup) > 0 { |
| 2154 | + var cfgEncBackup share.CLUSSystemConfigEncMigrated |
| 2155 | + if err := json.Unmarshal(valueBackup, &cfgEncBackup); err == nil { |
| 2156 | + if time.Now().UTC().After(cfgEncBackup.EncDataExpirationTime) { |
| 2157 | + // the backup is expired |
| 2158 | + _ = cluster.Delete(share.CLUSSystemEncMigratedKey) |
| 2159 | + log.Info("encryption-migrated config backup is deleted") |
| 2160 | + } |
| 2161 | + } |
| 2162 | + } |
| 2163 | + |
| 2164 | + value, _ := cluster.Get(share.CLUSNextKeyRotationTSKey) |
| 2165 | + if len(value) == 0 { |
| 2166 | + _ = kv.SetNextKeyRotationTime(cctx.KeyRotationDuration) |
| 2167 | + return |
| 2168 | + } |
| 2169 | + i, err := strconv.ParseInt(string(value), 10, 64) |
| 2170 | + if err != nil { |
| 2171 | + return |
| 2172 | + } |
| 2173 | + nextKeyRotationTime := time.Unix(i, 0) |
| 2174 | + if time.Now().After(nextKeyRotationTime) { |
| 2175 | + if err := resource.AddStorePassphrase(); err == nil { |
| 2176 | + if err = kv.SetNextKeyRotationTime(cctx.KeyRotationDuration); err == nil { |
| 2177 | + alert := "Important: Please backup the data in Kubernetes secret neuvector-store-secret reset by NeuVector" |
| 2178 | + b := sha256.Sum256([]byte(alert)) |
| 2179 | + key := hex.EncodeToString(b[:]) |
| 2180 | + allUser := clusHelper.GetAllUsers(access.NewReaderAccessControl()) |
| 2181 | + for _, user := range allUser { |
| 2182 | + accepted := utils.NewSetFromStringSlice(user.AcceptedAlerts) |
| 2183 | + if accepted.Contains(key) { |
| 2184 | + accepted.Remove(key) |
| 2185 | + user.AcceptedAlerts = accepted.ToStringSlice() |
| 2186 | + if err = clusHelper.PutUser(user); err != nil { |
| 2187 | + log.WithFields(log.Fields{"": user.Fullname, "err": err}).Error() |
| 2188 | + } |
| 2189 | + } |
| 2190 | + } |
| 2191 | + } |
| 2192 | + } |
| 2193 | + } |
| 2194 | +} |
| 2195 | + |
2111 | 2196 | // handler of K8s resource watcher calls cbResourceWatcher() which sends to orchObjChan/objChan |
2112 | 2197 | // [2021-02-15] CRD-related resource changes do not call this function. |
2113 | 2198 | // |
|
0 commit comments