Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add capability to watch multiple namespaces #572

Merged
merged 4 commits into from
Jun 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ original Secret from the SealedSecret.
- [Can I bring my own (pre-generated) certificates?](#can-i-bring-my-own-pre-generated-certificates)
- [How to use kubeseal if the controller is not running within the `kube-system` namespace?](#how-to-use-kubeseal-if-the-controller-is-not-running-within-the-kube-system-namespace)
- [How to verify the images?](#how-to-verify-the-images)
- [How to use one controller for a subset of namespaces](#How-to-use-one-controller-for-a-subset-of-namespaces)

- [Community](#community)
- [Related projects](#related-projects)

Expand Down Expand Up @@ -648,6 +650,10 @@ cosign verify --key .github/workflows/cosign.pub ghcr.io/bitnami-labs/sealed-sec
cosign verify --key .github/workflows/cosign.pub docker.io/bitnami/sealed-secrets-controller:latest
```

### How to use one controller for a subset of namespaces

If you want to use one controller for more than one namespace, but not all namespaces, you can provide additional namespaces using the command line flag `--additional-namespaces=<namespace1>,<namespace2>,<...>`. Make sure you provide appropriate roles and rolebindings in the target namespaces, so the controller can manage the secrets in there.

## Community

- [#sealed-secrets on Kubernetes Slack](https://kubernetes.slack.com/messages/sealed-secrets)
Expand Down
12 changes: 12 additions & 0 deletions cmd/controller/funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,15 @@ func validateKeyPrefix(name string) (string, error) {
}
return name, nil
}

func removeDuplicates(strSlice []string) []string {
allKeys := make(map[string]bool)
list := []string{}
for _, item := range strSlice {
if _, value := allKeys[item]; !value {
allKeys[item] = true
list = append(list, item)
}
}
return list
}
49 changes: 38 additions & 11 deletions cmd/controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,17 @@ const (
)

var (
keyPrefix = flag.String("key-prefix", "sealed-secrets-key", "Prefix used to name keys.")
keySize = flag.Int("key-size", 4096, "Size of encryption key.")
validFor = flag.Duration("key-ttl", 10*365*24*time.Hour, "Duration that certificate is valid for.")
myCN = flag.String("my-cn", "", "Common name to be used as issuer/subject DN in generated certificate.")
printVersion = flag.Bool("version", false, "Print version information and exit")
keyRenewPeriod = flag.Duration("key-renew-period", defaultKeyRenewPeriod, "New key generation period (automatic rotation disabled if 0)")
acceptV1Data = flag.Bool("accept-deprecated-v1-data", true, "Accept deprecated V1 data field.")
keyCutoffTime = flag.String("key-cutoff-time", "", "Create a new key if latest one is older than this cutoff time. RFC1123 format with numeric timezone expected.")
namespaceAll = flag.Bool("all-namespaces", true, "Scan all namespaces or only the current namespace (default=true).")
labelSelector = flag.String("label-selector", "", "Label selector which can be used to filter sealed secrets.")
keyPrefix = flag.String("key-prefix", "sealed-secrets-key", "Prefix used to name keys.")
keySize = flag.Int("key-size", 4096, "Size of encryption key.")
validFor = flag.Duration("key-ttl", 10*365*24*time.Hour, "Duration that certificate is valid for.")
myCN = flag.String("my-cn", "", "Common name to be used as issuer/subject DN in generated certificate.")
printVersion = flag.Bool("version", false, "Print version information and exit")
keyRenewPeriod = flag.Duration("key-renew-period", defaultKeyRenewPeriod, "New key generation period (automatic rotation disabled if 0)")
acceptV1Data = flag.Bool("accept-deprecated-v1-data", true, "Accept deprecated V1 data field.")
keyCutoffTime = flag.String("key-cutoff-time", "", "Create a new key if latest one is older than this cutoff time. RFC1123 format with numeric timezone expected.")
namespaceAll = flag.Bool("all-namespaces", true, "Scan all namespaces or only the current namespace (default=true).")
additionalNamespaces = flag.String("additional-namespaces", "", "Comma-separated list of additional namespaces to be scanned.")
labelSelector = flag.String("label-selector", "", "Label selector which can be used to filter sealed secrets.")

oldGCBehavior = flag.Bool("old-gc-behaviour", false, "Revert to old GC behavior where the controller deletes secrets instead of delegating that to k8s itself.")

Expand Down Expand Up @@ -210,8 +211,9 @@ func main2() error {
initKeyGenSignalListener(trigger)

namespace := v1.NamespaceAll
if !*namespaceAll {
if !*namespaceAll || *additionalNamespaces != "" {
namespace = myNamespace()
log.Printf("Starting informer for namespace: %s\n", namespace)
}

var tweakopts func(*metav1.ListOptions) = nil
Expand All @@ -231,6 +233,31 @@ func main2() error {

go controller.Run(stop)

if *additionalNamespaces != "" {
alemorcuq marked this conversation as resolved.
Show resolved Hide resolved
addNS := removeDuplicates(strings.Split(*additionalNamespaces, ","))

var inf ssinformers.SharedInformerFactory
var ctlr *Controller

for _, ns := range addNS {
if _, err := clientset.CoreV1().Namespaces().Get(ctx, ns, metav1.GetOptions{}); err != nil {
if errors.IsNotFound(err) {
log.Printf("Warning: namespace '%s' doesn't exist\n", ns)
continue
}
return err
}
if ns != namespace {
inf = ssinformers.NewFilteredSharedInformerFactory(ssclientset, 0, ns, tweakopts)
ctlr = NewController(clientset, ssclientset, inf, keyRegistry)
ctlr.oldGCBehavior = *oldGCBehavior
ctlr.updateStatus = *updateStatus
log.Printf("Starting informer for namespace: %s\n", ns)
go ctlr.Run(stop)
}
}
}

cp := func() ([]*x509.Certificate, error) {
cert, err := keyRegistry.getCert()
if err != nil {
Expand Down