-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Prow secret agent: Add secret parsing hook mechanism
This change addresses an old TODO of mine to add a parsing hook mechanism to the secret agent. We need this for the github rsa key, where we will currently panic if we get something that is not parseable. This change uses generics, so before we can merge it, we need to update to go 1.18. This change consists of: * Adding a new AddWithParser func to the secret package that will executed a passed parsing func as a post-load hook and not load a secret that doesn't parse * Update the data map of the secret agent to not use []byte as key type but an interface. This is needed because the type information of generics is inaccessible at runtime, which means a generic type is not really a type that can be referenced elsewhere, only concrete instantiations of it can - But there might be more than one, which is the reason for using generics in the first place, thus we are required to generalize them back throgh the interface * This also means that the only way of getting the parsed secret is by using a getter returned by AddWithParser - This is different from raw secrets, where we can get them later using the path (as they all have the same type)
- Loading branch information
1 parent
991be95
commit 0e771b6
Showing
5 changed files
with
248 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* | ||
Copyright 2022 The Kubernetes Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package secret | ||
|
||
import ( | ||
"os" | ||
"sync" | ||
"time" | ||
|
||
"github.com/sirupsen/logrus" | ||
) | ||
|
||
type parsingSecretReloader[T any] struct { | ||
lock sync.RWMutex | ||
path string | ||
rawValue []byte | ||
parsed T | ||
parsingFN func([]byte) (T, error) | ||
} | ||
|
||
func (p *parsingSecretReloader[T]) start(reloadCensor func()) error { | ||
raw, parsed, err := loadSingleSecretWithParser(p.path, p.parsingFN) | ||
if err != nil { | ||
return err | ||
} | ||
p.lock.Lock() | ||
p.rawValue = raw | ||
p.parsed = parsed | ||
p.lock.Unlock() | ||
reloadCensor() | ||
|
||
go p.reloadSecret(reloadCensor) | ||
return nil | ||
} | ||
|
||
func (p *parsingSecretReloader[T]) reloadSecret(reloadCensor func()) { | ||
var lastModTime time.Time | ||
logger := logrus.NewEntry(logrus.StandardLogger()) | ||
|
||
skips := 0 | ||
for range time.Tick(1 * time.Second) { | ||
if skips < 600 { | ||
// Check if the file changed to see if it needs to be re-read. | ||
secretStat, err := os.Stat(p.path) | ||
if err != nil { | ||
logger.WithField("secret-path", p.path).WithError(err).Error("Error loading secret file.") | ||
continue | ||
} | ||
|
||
recentModTime := secretStat.ModTime() | ||
if !recentModTime.After(lastModTime) { | ||
skips++ | ||
continue // file hasn't been modified | ||
} | ||
lastModTime = recentModTime | ||
} | ||
|
||
raw, parsed, err := loadSingleSecretWithParser(p.path, p.parsingFN) | ||
if err != nil { | ||
logger.WithField("secret-path", p.path).WithError(err).Error("Error loading secret.") | ||
continue | ||
} | ||
|
||
p.lock.Lock() | ||
p.rawValue = raw | ||
p.parsed = parsed | ||
p.lock.Unlock() | ||
reloadCensor() | ||
|
||
skips = 0 | ||
} | ||
|
||
} | ||
|
||
func (p *parsingSecretReloader[T]) getRaw() []byte { | ||
p.lock.RLock() | ||
defer p.lock.RUnlock() | ||
return p.rawValue | ||
} | ||
|
||
func (p *parsingSecretReloader[T]) get() T { | ||
p.lock.RLock() | ||
defer p.lock.RUnlock() | ||
return p.parsed | ||
} |
Oops, something went wrong.