diff --git a/README.md b/README.md index d8b7837..6cddfe0 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,11 @@ Secret keys are normalized automatically. The `-` will be `_` and the letters wi be converted to upper case (for example a secret with key `secret_key` and `secret-key` will become `SECRET_KEY`). +#### Reserved Service Names + +Starting with version 3.0, the service name "_chamber" is reserved for chamber's +internal use. You will be warned when using the service for any chamber operation. + #### Tagging on Write ```bash diff --git a/cmd/root.go b/cmd/root.go index 5eab037..3230d8a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -117,6 +117,9 @@ func validateService(service string) error { if !validServicePathFormat.MatchString(service) { return fmt.Errorf("Failed to validate service name '%s'. Only alphanumeric, dashes, forward slashes, full stops and underscores are allowed for service names. Service names must not start or end with a forward slash", service) } + if store.ReservedService(service) { + fmt.Fprintf(os.Stderr, "Service name %s is reserved for chamber's own use and will be prohibited in a future version. Please switch to a different service name.\n", service) + } return nil } @@ -125,6 +128,9 @@ func validateServiceWithLabel(service string) error { if !validServicePathFormatWithLabel.MatchString(service) { return fmt.Errorf("Failed to validate service name '%s'. Only alphanumeric, dashes, forward slashes, full stops and underscores are allowed for service names, and colon followed by a label name. Service names must not start or end with a forward slash or colon", service) } + if store.ReservedService(service) { + fmt.Fprintf(os.Stderr, "Service name %s is reserved for chamber's own use and will be prohibited in a future version. Please switch to a different service name.\n", service) + } return nil } diff --git a/cmd/root_test.go b/cmd/root_test.go index 276ee27..a09f6c3 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -51,6 +51,7 @@ func TestValidateService_Path(t *testing.T) { "foo-bar/foo-bar", "foo/bar/foo", "foo/bar/foo-bar", + "_chamber", // currently valid, but will be prohibited in a future version } for _, k := range validServicePathFormat { @@ -86,6 +87,7 @@ func TestValidateService_PathLabel(t *testing.T) { "foo/bar/foo:current", "foo/bar/foo-bar:current", "foo/bar/foo-bar", + "_chamber", // currently valid, but will be prohibited in a future version } for _, k := range validServicePathFormatWithLabel { diff --git a/store/store.go b/store/store.go index 3495ff7..f62495c 100644 --- a/store/store.go +++ b/store/store.go @@ -6,6 +6,15 @@ import ( "time" ) +const ( + // ChamberService is the name of the service reserved for chamber's own use. + ChamberService = "_chamber" +) + +func ReservedService(service string) bool { + return service == ChamberService +} + type ChangeEventType int const ( @@ -29,22 +38,25 @@ var ( ErrSecretNotFound = errors.New("secret not found") ) +// SecretId is the compound key for a secret. type SecretId struct { Service string Key string } +// Secret is a secret with metadata. type Secret struct { Value *string Meta SecretMetadata } -// A secret without any metadata +// RawSecret is a secret without any metadata. type RawSecret struct { Value string Key string } +// SecretMetadata is metadata about a secret. type SecretMetadata struct { Created time.Time CreatedBy string @@ -59,6 +71,7 @@ type ChangeEvent struct { Version int } +// Store is an interface for a secret store. type Store interface { Write(ctx context.Context, id SecretId, value string) error WriteWithTags(ctx context.Context, id SecretId, value string, tags map[string]string) error diff --git a/store/store_test.go b/store/store_test.go new file mode 100644 index 0000000..ad8ed01 --- /dev/null +++ b/store/store_test.go @@ -0,0 +1,12 @@ +package store + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestReservedService(t *testing.T) { + assert.True(t, ReservedService(ChamberService)) + assert.False(t, ReservedService("not-reserved")) +}