Skip to content

Commit

Permalink
feat(k8s): set secret immutable by default for 1.21
Browse files Browse the repository at this point in the history
Fixes #1090

Signed-off-by: Furkan <furkan.turkal@trendyol.com>
Co-authored-by: Batuhan <batuhan.apaydin@trendyol.com>
Co-authored-by: Erkan <erkan.zileli@trendyol.com>
Signed-off-by: Furkan <furkan.turkal@trendyol.com>
  • Loading branch information
3 people committed Nov 22, 2021
1 parent aff2e37 commit ad93a8d
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 10 deletions.
14 changes: 14 additions & 0 deletions pkg/cosign/kubernetes/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (

"k8s.io/client-go/kubernetes"

utilversion "k8s.io/apimachinery/pkg/util/version"
// Initialize all known client auth plugins
_ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/client-go/rest"
Expand Down Expand Up @@ -57,3 +58,16 @@ func Client() (kubernetes.Interface, error) {
}
return kubernetes.NewForConfig(config)
}

func CheckImmutableSecretSupported(client kubernetes.Interface) (bool, error) {
k8sVer, err := client.Discovery().ServerVersion()
if err != nil {
return false, err
}
semVer, err := utilversion.ParseSemantic(k8sVer.String())
if err != nil {
return false, err
}
// https://kubernetes.io/docs/concepts/configuration/secret/#secret-immutable
return semVer.Major() >= 1 && semVer.Minor() >= 21, nil
}
33 changes: 25 additions & 8 deletions pkg/cosign/kubernetes/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"os"
"strings"

"k8s.io/utils/pointer"

"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
Expand Down Expand Up @@ -67,18 +69,22 @@ func KeyPairSecret(ctx context.Context, k8sRef string, pf cosign.PassFunc) error
if err != nil {
return errors.Wrap(err, "new for config")
}
immutable, err := CheckImmutableSecretSupported(client)
if err != nil {
return errors.Wrap(err, "check immutable")
}
var s *v1.Secret
if s, err = client.CoreV1().Secrets(namespace).Get(ctx, name, metav1.GetOptions{}); err != nil {
if k8serrors.IsNotFound(err) {
s, err = client.CoreV1().Secrets(namespace).Create(ctx, secret(keys, namespace, name, nil), metav1.CreateOptions{})
s, err = client.CoreV1().Secrets(namespace).Create(ctx, secret(keys, namespace, name, nil, immutable), metav1.CreateOptions{})
if err != nil {
return errors.Wrapf(err, "creating secret %s in ns %s", name, namespace)
}
} else {
return errors.Wrap(err, "checking if secret exists")
}
} else { // Update the existing secret
s, err = client.CoreV1().Secrets(namespace).Update(ctx, secret(keys, namespace, name, s.Data), metav1.UpdateOptions{})
s, err = client.CoreV1().Secrets(namespace).Update(ctx, secret(keys, namespace, name, s.Data, immutable), metav1.UpdateOptions{})
if err != nil {
return errors.Wrapf(err, "updating secret %s in ns %s", name, namespace)
}
Expand All @@ -96,20 +102,31 @@ func KeyPairSecret(ctx context.Context, k8sRef string, pf cosign.PassFunc) error
// * cosign.key
// * cosign.pub
// * cosign.password
func secret(keys *cosign.Keys, namespace, name string, data map[string][]byte) *v1.Secret {
func secret(keys *cosign.Keys, namespace, name string, data map[string][]byte, immutable bool) *v1.Secret {
if data == nil {
data = map[string][]byte{}
}
data["cosign.key"] = keys.PrivateBytes
data["cosign.pub"] = keys.PublicBytes
data["cosign.password"] = keys.Password()

obj := metav1.ObjectMeta{
Name: name,
Namespace: namespace,
}

// For Kubernetes >= 1.21, set Immutable by default
if immutable {
return &v1.Secret{
ObjectMeta: obj,
Data: data,
Immutable: pointer.Bool(true),
}
}

return &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Data: data,
ObjectMeta: obj,
Data: data,
}
}

Expand Down
7 changes: 5 additions & 2 deletions pkg/cosign/kubernetes/secret_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"reflect"
"testing"

"k8s.io/utils/pointer"

v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

Expand All @@ -41,8 +43,9 @@ func TestSecret(t *testing.T) {
"cosign.pub": []byte("public"),
"cosign.password": nil,
},
Immutable: pointer.Bool(true),
}
actual := secret(keys, namespace, name, nil)
actual := secret(keys, namespace, name, nil, true)
if !reflect.DeepEqual(actual, expect) {
t.Errorf("secret: %v, want %v", expect, actual)
}
Expand Down Expand Up @@ -73,7 +76,7 @@ func TestSecretUpdate(t *testing.T) {
"cosign.password": nil,
},
}
actual := secret(keys, namespace, name, existing)
actual := secret(keys, namespace, name, existing, false)
if !reflect.DeepEqual(actual, expect) {
t.Errorf("secret: %v, want %v", expect, actual)
}
Expand Down

0 comments on commit ad93a8d

Please sign in to comment.