-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Prior to this change, the plugin always assumed secrets to be of type `Opaque`. This change introduces the secret type for (de)serialization and adds a small interface that is used to keep the core logic mostly unchanged but handle different types of secrets. Only support for helm was added for now but expanding to more types should be straight-forward Fixes #50
- Loading branch information
Showing
7 changed files
with
328 additions
and
39 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package cmd | ||
|
||
import ( | ||
"compress/gzip" | ||
"encoding/base64" | ||
"fmt" | ||
"io" | ||
"strings" | ||
) | ||
|
||
// SecretDecoder is an interface for decoding various kubernetes secret resources | ||
type SecretDecoder interface { | ||
Decode(input string) (string, error) | ||
} | ||
|
||
// Decode decodes a secret based on its type, currently supporting only Opaque and Helm secrets | ||
func (s Secret) Decode(input string) (string, error) { | ||
switch s.Type { | ||
// TODO handle all secret types | ||
case Opaque: | ||
b64d, err := base64.StdEncoding.DecodeString(input) | ||
if err != nil { | ||
return "", err | ||
} | ||
return string(b64d), nil | ||
case Helm: | ||
b64dk8s, err := base64.StdEncoding.DecodeString(input) | ||
if err != nil { | ||
return "", err | ||
} | ||
b64dhelm, err := base64.StdEncoding.DecodeString(string(b64dk8s)) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
gz, err := gzip.NewReader(strings.NewReader(string(b64dhelm))) | ||
if err != nil { | ||
return "", err | ||
} | ||
defer gz.Close() | ||
|
||
s, err := io.ReadAll(gz) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return string(s), nil | ||
} | ||
|
||
return "", fmt.Errorf("couldn't decode unknown secret type %q", s.Type) | ||
} |
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,105 @@ | ||
package cmd | ||
|
||
import ( | ||
"bytes" | ||
"compress/gzip" | ||
"encoding/base64" | ||
"errors" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestDecode(t *testing.T) { | ||
tests := map[string]struct { | ||
data func() Secret | ||
want string | ||
wantErr error | ||
}{ | ||
// base64 encoded | ||
"opaque": { | ||
func() Secret { | ||
return Secret{ | ||
Data: map[string]string{ | ||
"key": "dGVzdAo=", | ||
}, | ||
Type: Opaque, | ||
} | ||
}, | ||
"test\n", | ||
nil, | ||
}, | ||
// base64 encoded | ||
"opaque invalid": { | ||
func() Secret { | ||
return Secret{ | ||
Data: map[string]string{ | ||
"key": "dGVzdAo}}}=", | ||
}, | ||
Type: Opaque, | ||
} | ||
}, | ||
"", | ||
base64.CorruptInputError(7), | ||
}, | ||
// double base64 encoded + gzip'd | ||
"helm": { | ||
func() Secret { | ||
res := Secret{ | ||
Type: Helm, | ||
} | ||
var buf bytes.Buffer | ||
gz := gzip.NewWriter(&buf) | ||
if _, err := gz.Write([]byte("test\n")); err != nil { | ||
return res | ||
} | ||
if err := gz.Close(); err != nil { | ||
return res | ||
} | ||
|
||
b64k8s := base64.StdEncoding.EncodeToString(buf.Bytes()) | ||
b64helm := base64.StdEncoding.EncodeToString([]byte(b64k8s)) | ||
|
||
res.Data = SecretData{ | ||
"key": b64helm, | ||
} | ||
|
||
return res | ||
}, | ||
"test\n", | ||
nil, | ||
}, | ||
"unknown secret": { | ||
func() Secret { | ||
return Secret{ | ||
Type: "invalid", | ||
} | ||
}, | ||
"", | ||
errors.New("couldn't decode unknown secret type \"invalid\""), | ||
}, | ||
} | ||
|
||
for name, tt := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
t.Parallel() | ||
|
||
data := tt.data() | ||
|
||
got, err := data.Decode(data.Data["key"]) | ||
if err != nil { | ||
if tt.wantErr == nil { | ||
assert.Fail(t, "unexpected error", err) | ||
} else if err.Error() != tt.wantErr.Error() { | ||
assert.Equal(t, tt.wantErr, err) | ||
} | ||
return | ||
} else if tt.wantErr != nil { | ||
assert.Fail(t, "expected error, got nil", tt.wantErr) | ||
return | ||
} | ||
|
||
assert.Equal(t, tt.want, got) | ||
}) | ||
} | ||
} |
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 |
---|---|---|
@@ -1,17 +1,51 @@ | ||
package cmd | ||
|
||
// SecretList represents a list of secrets | ||
type SecretList struct { | ||
Items []Secret `json:"items"` | ||
} | ||
|
||
// Secret represents a kubernetes secret | ||
type Secret struct { | ||
Data SecretData `json:"data"` | ||
Metadata Metadata `json:"metadata"` | ||
Type SecretType `json:"type"` | ||
} | ||
|
||
// SecretData represents the data of a secret | ||
type SecretData map[string]string | ||
|
||
// Metadata represents the metadata of a secret | ||
type Metadata struct { | ||
Name string `json:"name"` | ||
Namespace string `json:"namespace"` | ||
} | ||
|
||
// SecretType represents the type of a secret | ||
// | ||
// Opaque arbitrary user-defined data | ||
// kubernetes.io/service-account-token ServiceAccount token | ||
// kubernetes.io/dockercfg serialized ~/.dockercfg file | ||
// kubernetes.io/dockerconfigjson serialized ~/.docker/config.json file | ||
// kubernetes.io/basic-auth credentials for basic authentication | ||
// kubernetes.io/ssh-auth credentials for SSH authentication | ||
// kubernetes.io/tls data for a TLS client or server | ||
// bootstrap.kubernetes.io/token bootstrap token data | ||
// helm.sh/release.v1 Helm v3 release data | ||
// | ||
// refs: | ||
// - https://kubernetes.io/docs/concepts/configuration/secret/#secret-types | ||
// - https://gist.github.com/DzeryCZ/c4adf39d4a1a99ae6e594a183628eaee | ||
type SecretType string | ||
|
||
const ( | ||
BasicAuth SecretType = "kubernetes.io/basic-auth" | ||
DockerCfg SecretType = "kubernetes.io/dockercfg" | ||
DockerConfigJson SecretType = "kubernetes.io/dockerconfigjson" | ||
Helm SecretType = "helm.sh/release.v1" | ||
Opaque SecretType = "Opaque" | ||
ServiceAccountToken SecretType = "kubernetes.io/service-account-token" | ||
SshAuth SecretType = "kubernetes.io/ssh-auth" | ||
Tls SecretType = "kubernetes.io/tls" | ||
Token SecretType = "bootstrap.kubernetes.io/token" | ||
) |
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
Oops, something went wrong.