From 25ea439ad747c68fb33dad7dfff38d5ffef1676c Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 08:19:01 -0400 Subject: [PATCH 01/27] fix: update key mgmt flags to consistent format --- cmd/base-keys.go | 54 +-- cmd/kas-keys.go | 87 +++-- docs/man/policy/kas-registry/key/_index.md | 6 +- .../policy/kas-registry/key/base/_index.md | 12 +- docs/man/policy/kas-registry/key/base/get.md | 7 +- docs/man/policy/kas-registry/key/base/set.md | 27 +- docs/man/policy/kas-registry/key/create.md | 61 ++- docs/man/policy/kas-registry/key/get.md | 34 +- docs/man/policy/kas-registry/key/list.md | 33 +- docs/man/policy/kas-registry/key/update.md | 17 +- e2e/base-key.bats | 112 +++--- e2e/kas-keys.bats | 354 +++++++++--------- pkg/utils/identifier.go | 73 ++++ pkg/utils/identifier_test.go | 92 +++++ 14 files changed, 584 insertions(+), 385 deletions(-) create mode 100644 pkg/utils/identifier.go create mode 100644 pkg/utils/identifier_test.go diff --git a/cmd/base-keys.go b/cmd/base-keys.go index 3854eb0b..937a8591 100644 --- a/cmd/base-keys.go +++ b/cmd/base-keys.go @@ -2,10 +2,12 @@ package cmd import ( "errors" + "fmt" "github.com/evertras/bubble-table/table" "github.com/opentdf/otdfctl/pkg/cli" "github.com/opentdf/otdfctl/pkg/man" + "github.com/opentdf/otdfctl/pkg/utils" "github.com/opentdf/platform/protocol/go/policy/kasregistry" "github.com/spf13/cobra" ) @@ -27,34 +29,34 @@ const ( var policyKasRegistryBaseKeysCmd *cobra.Command func getKasKeyIdentifier(c *cli.Cli) (*kasregistry.KasKeyIdentifier, error) { - keyID := c.Flags.GetOptionalString("keyId") - kasID := c.Flags.GetOptionalString("kasId") - kasName := c.Flags.GetOptionalString("kasName") - kasURI := c.Flags.GetOptionalString("kasUri") - - var identifier *kasregistry.KasKeyIdentifier - if keyID != "" { - identifier = &kasregistry.KasKeyIdentifier{ - Kid: keyID, - } - switch { - case kasID != "": - identifier.Identifier = &kasregistry.KasKeyIdentifier_KasId{ - KasId: kasID, - } - case kasName != "": - identifier.Identifier = &kasregistry.KasKeyIdentifier_Name{ - Name: kasName, - } - case kasURI != "": - identifier.Identifier = &kasregistry.KasKeyIdentifier_Uri{ - Uri: kasURI, - } - default: - return nil, errors.New("at least one of 'kasId', 'kasName', or 'kasUri' must be provided with 'keyId'") - } + // This function is called when the user provides a human-readable key ID + // via the --key flag and identifies the KAS it belongs to via the --kas flag. + humanReadableKeyID := c.Flags.GetRequiredString("key") // Flag for the key's human-readable ID + kasIdentifierInput := c.Flags.GetRequiredString("kas") // Flag for KAS ID, URI, or Name + + // Basic validation, though GetRequiredString should handle empty inputs. + if humanReadableKeyID == "" { + return nil, errors.New("--key (human-readable key ID) cannot be empty") + } + if kasIdentifierInput == "" { + return nil, errors.New("--kas (KAS identifier) cannot be empty") } + identifier := &kasregistry.KasKeyIdentifier{ + Kid: humanReadableKeyID, + } + + kasInputType := utils.ClassifyString(kasIdentifierInput) + switch kasInputType { + case utils.StringTypeUUID: + identifier.Identifier = &kasregistry.KasKeyIdentifier_KasId{KasId: kasIdentifierInput} + case utils.StringTypeURI: + identifier.Identifier = &kasregistry.KasKeyIdentifier_Uri{Uri: kasIdentifierInput} + case utils.StringTypeGeneric: + identifier.Identifier = &kasregistry.KasKeyIdentifier_Name{Name: kasIdentifierInput} + default: // Catches StringTypeUnknown and any other unexpected types + return nil, fmt.Errorf("invalid KAS identifier: '%s'. Must be a KAS UUID, URI, or Name", kasIdentifierInput) + } return identifier, nil } diff --git a/cmd/kas-keys.go b/cmd/kas-keys.go index a48c40fe..66f181d3 100644 --- a/cmd/kas-keys.go +++ b/cmd/kas-keys.go @@ -1,6 +1,7 @@ package cmd import ( + "context" "encoding/base64" "errors" "fmt" @@ -10,6 +11,7 @@ import ( "github.com/opentdf/otdfctl/pkg/cli" "github.com/opentdf/otdfctl/pkg/handlers" "github.com/opentdf/otdfctl/pkg/man" + "github.com/opentdf/otdfctl/pkg/utils" "github.com/opentdf/platform/lib/ocrypto" "github.com/opentdf/platform/protocol/go/policy" "github.com/spf13/cobra" @@ -243,10 +245,8 @@ func policyCreateKasKey(cmd *cobra.Command, args []string) { h := NewHandler(c) defer h.Close() - keyID := c.Flags.GetRequiredString("keyId") - kasID := c.Flags.GetOptionalString("kasId") - kasURI := c.Flags.GetOptionalString("kasUri") - kasName := c.Flags.GetOptionalString("kasName") + keyIdentifier := c.Flags.GetRequiredString("key") + kasIdentifier := c.Flags.GetRequiredString("kas") metadataLabels = c.Flags.GetStringSlice("label", metadataLabels, cli.FlagsStringSliceOptions{Min: 0}) alg, err := algToEnum(c.Flags.GetRequiredString("alg")) @@ -259,23 +259,23 @@ func policyCreateKasKey(cmd *cobra.Command, args []string) { cli.ExitWithError("Invalid mode", err) } - wrappingKeyID = c.Flags.GetOptionalString("wrappingKeyId") + wrappingKeyID = c.Flags.GetOptionalString("wrapping-key-id") if mode != policy.KeyMode_KEY_MODE_PUBLIC_KEY_ONLY && wrappingKeyID == "" { formattedMode, _ := enumToMode(mode) - cli.ExitWithError(fmt.Sprintf("wrappingKeyId is required for mode %s", formattedMode), nil) + cli.ExitWithError(fmt.Sprintf("wrapping-key-id is required for mode %s", formattedMode), nil) } - providerConfigID = c.Flags.GetOptionalString("providerConfigId") + providerConfigID = c.Flags.GetOptionalString("provider-config-id") if (mode == policy.KeyMode_KEY_MODE_PROVIDER_ROOT_KEY || mode == policy.KeyMode_KEY_MODE_REMOTE) && providerConfigID == "" { formattedMode, _ := enumToMode(mode) - cli.ExitWithError(fmt.Sprintf("providerConfigId is required for mode %s", formattedMode), nil) + cli.ExitWithError(fmt.Sprintf("provider-config-id is required for mode %s", formattedMode), nil) } var publicKeyCtx *policy.PublicKeyCtx var privateKeyCtx *policy.PrivateKeyCtx switch mode { case policy.KeyMode_KEY_MODE_CONFIG_ROOT_KEY: - wrappingKey := c.Flags.GetRequiredString("wrappingKey") + wrappingKey := c.Flags.GetRequiredString("wrapping-key") privateKeyPem, publicKeyPem, err := generateKeys(alg) if err != nil { cli.ExitWithError("Failed to generate keys", err) @@ -296,9 +296,9 @@ func policyCreateKasKey(cmd *cobra.Command, args []string) { WrappedKey: privPemBase64, } case policy.KeyMode_KEY_MODE_PROVIDER_ROOT_KEY: - providerConfigID = c.Flags.GetRequiredString("providerConfigId") - publicPem := c.Flags.GetRequiredString("pubPem") - privatePem := c.Flags.GetRequiredString("privatePem") + providerConfigID = c.Flags.GetRequiredString("provider-config-id") + publicPem := c.Flags.GetRequiredString("public-key-pem") + privatePem := c.Flags.GetRequiredString("private-key-pem") _, err = base64.StdEncoding.DecodeString(publicPem) if err != nil { cli.ExitWithError("pem must be base64 encoded", err) @@ -315,8 +315,8 @@ func policyCreateKasKey(cmd *cobra.Command, args []string) { WrappedKey: privatePem, } case policy.KeyMode_KEY_MODE_REMOTE: - pem := c.Flags.GetRequiredString("pubPem") - providerConfigID = c.Flags.GetRequiredString("providerConfigId") + pem := c.Flags.GetRequiredString("public-key-pem") + providerConfigID = c.Flags.GetRequiredString("provider-config-pem") _, err = base64.StdEncoding.DecodeString(pem) if err != nil { @@ -330,7 +330,7 @@ func policyCreateKasKey(cmd *cobra.Command, args []string) { KeyId: wrappingKeyID, } case policy.KeyMode_KEY_MODE_PUBLIC_KEY_ONLY: - pem := c.Flags.GetRequiredString("pubPem") + pem := c.Flags.GetRequiredString("public-key-pem") _, err = base64.StdEncoding.DecodeString(pem) if err != nil { cli.ExitWithError("pem must be base64 encoded", err) @@ -344,21 +344,15 @@ func policyCreateKasKey(cmd *cobra.Command, args []string) { cli.ExitWithError("Invalid mode", nil) } - if kasID == "" { - kas, err := h.GetKasRegistryEntry(c.Context(), handlers.KasIdentifier{ - Name: kasName, - URI: kasURI, - }) - if err != nil { - cli.ExitWithError("Failed to get kas registry entry", err) - } - kasID = kas.GetId() + kasIdentifier, err = resolveKasIdentifier(c.Context(), kasIdentifier, h) + if err != nil { + cli.ExitWithError("Invalid kas identifier", err) } kasKey, err := h.CreateKasKey( c.Context(), - kasID, - keyID, + kasIdentifier, + keyIdentifier, alg, mode, publicKeyCtx, @@ -440,7 +434,7 @@ func policyListKasKeys(cmd *cobra.Command, args []string) { limit := c.Flags.GetRequiredInt32("limit") offset := c.Flags.GetRequiredInt32("offset") - algArg := c.Flags.GetOptionalString("alg") + algArg := c.Flags.GetOptionalString("algorithm") var alg policy.Algorithm if algArg != "" { var err error @@ -449,15 +443,16 @@ func policyListKasKeys(cmd *cobra.Command, args []string) { cli.ExitWithError("Invalid algorithm", err) } } - kasID := c.Flags.GetOptionalString("kasId") - kasName := c.Flags.GetOptionalString("kasName") - kasURI := c.Flags.GetOptionalString("kasUri") + kasIdentifier := c.Flags.GetRequiredString("kas") + + kasIdentifier, err := resolveKasIdentifier(c.Context(), kasIdentifier, h) + if err != nil { + cli.ExitWithError("Invalid kas identifier", err) + } // Get the list of keys. keys, page, err := h.ListKasKeys(c.Context(), limit, offset, alg, handlers.KasIdentifier{ - ID: kasID, - Name: kasName, - URI: kasURI, + ID: kasIdentifier, }) if err != nil { cli.ExitWithError("Failed to list kas keys", err) @@ -529,6 +524,32 @@ func policyListKasKeys(cmd *cobra.Command, args []string) { HandleSuccess(cmd, "", t, keys) } +func resolveKasIdentifier(ctx context.Context, ident string, h handlers.Handler) (string, error) { + // Use the ClassifyString helper to determine how to look up the KAS + kasLookup := handlers.KasIdentifier{} + kasInputType := utils.ClassifyString(ident) + + switch kasInputType { + case utils.StringTypeUUID: + return ident, nil + case utils.StringTypeURI: + kasLookup.URI = ident + case utils.StringTypeGeneric: + kasLookup.Name = ident + default: + return "", errors.New("invalid kas identifier") + } + + if kasInputType != utils.StringTypeUUID { + resolvedKas, err := h.GetKasRegistryEntry(ctx, kasLookup) + if err != nil { + return "", errors.Join(errors.New("failed to get kas registry entry"), err) + } + return resolvedKas.GetId(), nil + } + return "", nil +} + func init() { // Create Kas Key createDoc := man.Docs.GetCommand("policy/kas-registry/key/create", diff --git a/docs/man/policy/kas-registry/key/_index.md b/docs/man/policy/kas-registry/key/_index.md index b543dbb2..f2b727cb 100644 --- a/docs/man/policy/kas-registry/key/_index.md +++ b/docs/man/policy/kas-registry/key/_index.md @@ -8,8 +8,10 @@ command: - k flags: - name: json - description: output single command in JSON (overrides configured output format) + description: Output the result of a subcommand in JSON format (overrides configured output format). This is an inherited flag. default: 'false' --- -Set of commands for managing KAS keys used with OpenTDF platform. +Provides a set of subcommands for managing cryptographic keys within the Key Access Server (KAS) registry. +These keys are essential for encryption and decryption operations within the OpenTDF platform. +Operations include creating, retrieving, listing, updating, and managing the platform's base key. diff --git a/docs/man/policy/kas-registry/key/base/_index.md b/docs/man/policy/kas-registry/key/base/_index.md index 0c0580bb..8be6308c 100644 --- a/docs/man/policy/kas-registry/key/base/_index.md +++ b/docs/man/policy/kas-registry/key/base/_index.md @@ -1,19 +1,19 @@ --- -title: Base Key Operations +title: Platform Base Key Management command: name: base hidden: true - aliases: - - k flags: - name: json - description: output single command in JSON (overrides configured output format) + description: Output the result of a subcommand in JSON format (overrides configured output format). This is an inherited flag. default: 'false' --- -Set of operations to be used for setting and getting base platform keys. -These base platform keys will be used to encrypt data in the following cases: +Provides subcommands for managing the platform's base cryptographic key. +This base key is a fallback used for encryption operations in specific scenarios: - No attributes present when encrypting a file - No keys associated with an attribute + +Available operations include `get` to retrieve the current base key and `set` to designate a new base key. diff --git a/docs/man/policy/kas-registry/key/base/get.md b/docs/man/policy/kas-registry/key/base/get.md index e4674e1d..54558401 100644 --- a/docs/man/policy/kas-registry/key/base/get.md +++ b/docs/man/policy/kas-registry/key/base/get.md @@ -3,13 +3,16 @@ title: Get Base Key command: name: get aliases: - - g + - g --- -Command for getting the platform base key. +Command for retrieving information about the currently configured platform base key. This key is used for encryption operations when no attributes are present or when attributes lack associated keys. + +The command will display details such as the key's identifier (KeyID or UUID) and the Key Access Server (KAS) it is registered with. ## Examples +Retrieve the platform base key information in the default (human-readable) format: ``` otdfctl policy kas-registry key base get ``` diff --git a/docs/man/policy/kas-registry/key/base/set.md b/docs/man/policy/kas-registry/key/base/set.md index f0538f51..aab90a55 100644 --- a/docs/man/policy/kas-registry/key/base/set.md +++ b/docs/man/policy/kas-registry/key/base/set.md @@ -5,30 +5,23 @@ command: aliases: - s flags: - - name: id - shorthand: i - description: ID of the key to retrieve - - name: keyId + - name: key shorthand: k - description: KeyID of the key to retrieve - - name: kasUri - shorthand: u - description: URI of the Key access server that the key is assigned to. - - name: kasName - shorthand: n - description: Name of the Key access server that the key is assigned to. - - name: kasId - shorthand: d - description: Id of the Key access server that the key is assigned to. + description: The KeyID (human-readable identifier) or the internal UUID of an existing key within the specified KAS. This key will be designated as the platform base key. The system will attempt to resolve the provided value as either a UUID or a KeyID. + required: true + - name: kas + description: Specify the Key Access Server (KAS) where the key (identified by `--key`) is registered. The KAS can be identified by its ID, URI, or Name. + required: true --- -Command for setting a base key to be used for encryption operations on data where no attributes are present or where no keys are present on found attributes. +Command for setting a base key to be used for encryption operations on data where no attributes are present or where no keys are present on found attributes. The key to be set as the base key must be identified using its KeyID or UUID via the `--key` flag, and the KAS it belongs to must be specified with the `--kas` flag. ## Examples +Set the platform base key using the internal UUID of a key from a KAS specified by its URI: ``` -otdfctl policy kas-registry key base set --id 8af2059f-5d0b-46c2-84f0-bed8a6101d90 +otdfctl policy kas-registry key base set --key 8af2059f-5d0b-46c2-84f0-bed8a6101d90 --kas https://kas.example.com/kas -otdfctl policy kas-registry key base set --kasUri +otdfctl policy kas-registry key base set --key my-platform-base-key-v1 --kas primary-key-access-server ``` diff --git a/docs/man/policy/kas-registry/key/create.md b/docs/man/policy/kas-registry/key/create.md index bf176a44..5fe2223e 100644 --- a/docs/man/policy/kas-registry/key/create.md +++ b/docs/man/policy/kas-registry/key/create.md @@ -5,46 +5,45 @@ command: aliases: - c flags: - - name: keyId - description: Name for the Key + - name: key-id + description: A unique, often human-readable, identifier for the new key to be created. required: true - - name: alg + - name: algorithm shorthand: a - description: Algorithm for the key + description: Algorithm for the new key (see table below for options). required: true - name: mode shorthand: m - description: Describes how the private key is managed + description: Describes how the private key is managed (see table below for options). required: true - - name: kasId - description: Key Access Server ID - - name: kasUri - description: The FQN of the KAS server - - name: kasName - description: Key Access Server name - - name: wrappingKeyId - description: KeyId that wraps the asymmetric key. - - name: wrappingKey + - name: kas + description: Specify the Key Access Server (KAS) where the new key will be created. The KAS can be identified by its ID, URI, or Name. + required: true + - name: wrapping-key-id + description: Identifier related to the wrapping key. Its meaning depends on the `mode`. For `local` mode, it's a descriptive ID for the `wrappingKey` you provide. For `provider` or `remote` mode, it's the ID of the key within the external provider/system used for wrapping. + - name: wrapping-key shorthand: w - description: The key used to wrap the generated private key. (Must be generated with AES cipher, and base64 encoded) - - name: privatePem - description: The private key pem, encrypted by an AES 32 byte key, base64 encoded. - - name: providerConfigId + description: The symmetric key material (AES cipher, base64 encoded) used to wrap the generated private key. Primarily used when `mode` is `local`. + - name: private-key-pem + description: The private key PEM (encrypted by an AES 32-byte key, then base64 encoded). Used when importing an existing key pair, typically with `provider` mode. + - name: provider-config-id shorthand: p - description: Configuration ID for the key provider, if applicable. When mode is `"provider"` we will use the provider to wrap the key. - - name: pubPem + description: Configuration ID for the key provider. Often required when `mode` is `provider` or `remote` and an external key provider is used. + - name: public-key-pem shorthand: e - description: The base64 encoded public key pem to be used with `"remote"` and `"public_key"` modes. + description: The base64 encoded public key PEM. Required for `remote` and `public_key` modes, and can be used with `provider` mode if importing an existing key pair. - name: label shorthand: l - description: Metadata labels for the provider config + description: Comma-separated key=value pairs for metadata labels to associate with the new key (e.g., "owner=team-a,env=production"). --- -Creates a new key that for a specified Key Access Server, which will be used -for encrypting and decrypting data keys. +Creates a new cryptographic key within a specified Key Access Server (KAS). +This key is primarily used for encrypting and decrypting data keys in the TDF (Trusted Data Format) ecosystem, forming a crucial part of data protection policies. ## Examples +### Create a key in `local` mode +The KAS generates the key pair, and the private key is wrapped by the provided `wrappingKey`. The KAS is identified by its ID. ```shell otdfctl key create --keyId "aws-key" --alg "rsa:2048" --mode "local" --kasId 891cfe85-b381-4f85-9699-5f7dbfe2a9ab --wrappingKeyId "virtru-stored-key" --wrappingKey "YWVzIGtleQ==" @@ -63,7 +62,7 @@ otdfctl key create --keyId "aws-key" --alg "rsa:2048" --mode "remote" --kasUri " otdfctl key create --keyId "aws-key" --alg "rsa:2048" --mode "public_key" --kasUri "https://test-kas.com" --pubPem "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tXG5NSUlDL1RDQ0FlV2dBd0lCQWdJVVNIVEoyYnpBaDdkUW1tRjAzcTZJcS9uMGw5MHdEUVlKS29aSWh2Y05BUUVMXG5CUUF3RGpFTU1Bb0dBMVVFQXd3RGEyRnpNQjRYRFRJME1EWXdOakUzTkRZMU5Gb1hEVEkxTURZd05qRTNORFkxXG5ORm93RGpFTU1Bb0dBMVVFQXd3RGEyRnpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDXG5BUUVBeE4zQVBpaFRpb2pjYUg2b1dqMXRNdFpNYWFaK0lBMXF0cUZtcHk1Rmc4RDViRXNQNzM2R3h6VU1Gc01WXG5zaHJLRVh6OGRZOUtwMjN1SXd5ZUMwUlBXTGU1eElmVGtKVWJ5THBxR2RsRWdxajEwUlE4a1NWcTI3MFhQRVMyXG5HWlVpajJEdUpWZndwVHBMemN0aTJQc2dFT29PS0M2Tm5uQUkwTlMxbWFvLzJEeFF4cy9EOWhBSmpHZHB6eW1iXG54aTJUeEdudllidm9mQ1BkOFJkRlRDUHZnd0tMUzcrTXFCY21pYzlWZFg5MVFOT1BtclAzcklvS3RqamQrNVBZXG5sL3o3M1BBeFIzSzNTSXpJWkx2SXRxMmFob2JPT01pU3h3OHNvT2xPZEhOVUpUcEVDY2R1aFJicXVxbUs2ZlR3XG5WT2ZyY1JRaGhVNFRrRHU5MkxJN1NnbE9XUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVZGd4eDdVNUFRZ2ZpXG5pUVd1M2toaTl5bmVFVm93SHdZRFZSMGpCQmd3Rm9BVWRneHg3VTVBUWdmaWlRV3Uza2hpOXluZUVWb3dEd1lEXG5WUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQVRjTFliSG9tSmdMUS9INmlEdmNBXG5JcElTRi9SY3hnaDdObklxUmtCK1RtNHhObE5ISXhsNFN6K0trRVpFUGgwV0tJdEdWRGozMjkzckFyUk9FT1hJXG50Vm1uMk9CdjlNLzVEUWtIajc2UnU0UFEyVGNMMENBQ2wxSktmcVhMc01jNkhIVHA4WlRQOGxNZHBXNGt6RWMzXG5mVnRndnRwSmM0V0hkVUlFekF0VGx6WVJxSWJ5eUJNV2VUalh3YTU0YU12M1JaUWRKK0MwZWh3V1REUURwaDduXG5LWTMrN0cwZW5ORVZ0eVc0ZHR4dlFRYmlkTWFueTBKRXByNlFwUG14QzhlMFoyM2RNRGRrUjFJb1Q5OVBoZFcvXG5RQzh4TWp1TENpUkVWN2E2ZTJNeENHajNmeHJuTVh3T0lxTzNBek5zd2UyYW1jb3oya3R1b3FnRFRZbG8rRmtLXG41dz09XG4tLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tXG4=" ``` -1. The `"alg"` specifies the key algorithm: +1. The `"algorithm"` specifies the key algorithm: | Key Algorithm | | -------------- | @@ -75,9 +74,9 @@ otdfctl key create --keyId "aws-key" --alg "rsa:2048" --mode "public_key" --kasU 2. The `"mode"` specifies where the key that is encrypting TDFs is stored. All keys will be encrypted when stored in Virtru's DB, for modes `"local"` and `"provider"` - | Mode | Description | - | ---------------- | ------------------------------------------------------------------------------------------------------- | - | `local` | Root Key is stored within Virtru's database and the symmetric wrapping key is stored in KAS | - | `provider` | Root Key is stored within Virtru's database and the symmetric wrapping key is stored externally | - | `remote` | Root Key and wrapping key are stored remotely | - | `public_key` | Root Key and wrapping key are stored remotely. Use this when importing another org's policy information | + | Mode | Description | + | ------------ | ------------------------------------------------------------------------------------------------------- | + | `local` | Root Key is stored within Virtru's database and the symmetric wrapping key is stored in KAS | + | `provider` | Root Key is stored within Virtru's database and the symmetric wrapping key is stored externally | + | `remote` | Root Key and wrapping key are stored remotely | + | `public_key` | Root Key and wrapping key are stored remotely. Use this when importing another org's policy information | diff --git a/docs/man/policy/kas-registry/key/get.md b/docs/man/policy/kas-registry/key/get.md index 929f1934..fc25d06b 100644 --- a/docs/man/policy/kas-registry/key/get.md +++ b/docs/man/policy/kas-registry/key/get.md @@ -5,22 +5,26 @@ command: aliases: - g flags: - - name: id - shorthand: i - description: ID of the key to retrieve - - name: keyId + - name: key shorthand: k - description: KeyID of the key to retrieve - - name: kasUri - shorthand: u - description: URI of the Key access server that the key is assigned to. - - name: kasName - shorthand: n - description: Name of the Key access server that the key is assigned to. - - name: kasId - shorthand: d - description: Id of the Key access server that the key is assigned to. + description: The KeyID (human-readable identifier) or the internal UUID of the key to retrieve from the specified KAS. The system will attempt to resolve the provided value as either a UUID or a KeyID. + required: true + - name: kas + description: Specify the Key Access Server (KAS) where the key (identified by `--key`) is registered. The KAS can be identified by its ID, URI, or Name. + required: true --- -This command retrieves details of a specific key by sending a `GetKeyRequest` to the platform. +This command retrieves detailed information about a specific key registered within a Key Access Server (KAS). You must specify the key using its KeyID or UUID and the KAS it belongs to. + +## Examples + +Retrieve details for a key identified by its UUID from a KAS specified by its URI: +``` +otdfctl policy kas-registry key get --key "123e4567-e89b-12d3-a456-426614174000" --kas "https://kas.example.com/kas" +``` + +Retrieve details for a key identified by its human-readable KeyID from a KAS specified by its name, and output in JSON format: +``` +otdfctl policy kas-registry key get --key "my-specific-key-v2" --kas "Secondary KAS" --json +``` diff --git a/docs/man/policy/kas-registry/key/list.md b/docs/man/policy/kas-registry/key/list.md index 88108669..773fcb62 100644 --- a/docs/man/policy/kas-registry/key/list.md +++ b/docs/man/policy/kas-registry/key/list.md @@ -16,15 +16,28 @@ command: - name: alg shorthand: a description: Key Algorithm to filter for - - name: kasId - shorthand: i - description: The id of the kas to filter for - - name: kasName - shorthand: n - description: The name of the kas to filter for - - name: kasUri - shorthand: u - description: The uri of the kas to filter for + - name: kas + description: Specify the Key Access Server (KAS) where the key (identified by `--key`) is registered. The KAS can be identified by its ID, URI, or Name. + required: true --- -List KAS Keys. You can filter based on algorithm, and kas id, name, or uri. +This command lists keys registered within a specified Key Access Server (KAS). You must specify the KAS using its ID, URI, or Name. + +The list can be filtered by key algorithm. Pagination is supported using `limit` and `offset` flags to manage the number of results returned. + +## Examples + +List the first 10 keys from a KAS specified by its URI: +``` +otdfctl policy kas-registry key list --kas "https://kas.example.com/kas" --limit 10 --offset 0 +``` + +List keys from a KAS named "Primary KAS", filtering for keys using the "RSA:2048" algorithm, and output in JSON format: +``` +otdfctl policy kas-registry key list --kas "Primary KAS" --alg "RSA:2048" --limit 20 --offset 0 --json +``` + +List the next 5 keys (skipping the first 5) from a KAS identified by its ID: +``` +otdfctl policy kas-registry key list --kas "kas-id-12345" --limit 5 --offset 5 +``` diff --git a/docs/man/policy/kas-registry/key/update.md b/docs/man/policy/kas-registry/key/update.md index 947aedfc..02946f9d 100644 --- a/docs/man/policy/kas-registry/key/update.md +++ b/docs/man/policy/kas-registry/key/update.md @@ -1,5 +1,5 @@ --- -title: Update KAS Key +title: Update Key Access Server Key command: name: update aliases: @@ -7,11 +7,20 @@ command: flags: - name: id shorthand: i - description: ID of the key to update + description: The internal UUID of the key to be updated. required: true - name: label shorthand: l - description: Metadata labels for the provider config + description: Comma-separated key=value pairs for metadata labels (e.g., "owner=team-a,env=production"). Providing new labels will replace any existing labels on the key. --- -Updates an existing key KAS key's metadata. +This command updates the key for an existing key registered in a Key Access Server (KAS). +You must identify the key using its UUID via the `--id` flag. +Currently, this command primarily supports updating the metadata labels associated with the key. + +## Examples + +Update key identified by its UUID: +``` +otdfctl policy kas-registry key update --id "123e4567-e89b-12d3-a456-426614174000" --label "status=active,project=phoenix" +``` diff --git a/e2e/base-key.bats b/e2e/base-key.bats index 07b0c86d..9ae5198e 100644 --- a/e2e/base-key.bats +++ b/e2e/base-key.bats @@ -1,30 +1,30 @@ #!/usr/bin/env bats setup_file() { - echo -n '{"clientId":"opentdf","clientSecret":"secret"}' > creds.json + echo -n '{"clientId":"opentdf","clientSecret":"secret"}' >creds.json export WITH_CREDS='--with-client-creds-file ./creds.json' export HOST='--host http://localhost:8080' # Create a KAS registry entry for testing base keys export KAS_NAME_BASE_KEY_TEST="kas-registry-for-base-key-tests" export KAS_URI_BASE_KEY_TEST="https://test-kas-for-base-keys.com" - export KAS_REGISTRY_ID_BASE_KEY_TEST=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --name "${KAS_NAME_BASE_KEY_TEST}" --uri "${KAS_URI_BASE_KEY_TEST}" --public-key-remote "${KAS_URI_BASE_KEY_TEST}" --json | jq -r '.id') + export KAS_REGISTRY_ID_BASE_KEY_TEST=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --name "${KAS_NAME_BASE_KEY_TEST}" --uri "${KAS_URI_BASE_KEY_TEST}" --json | jq -r '.id') # Create a regular KAS key to be set as a base key # This key will be used by the 'set' command tests export REGULAR_KEY_ID_FOR_BASE_TEST="regular-key-for-base-$(date +%s)" export WRAPPING_KEY="gp6TcYb/ZrgkQOYPdiYFRj11jZwbevy+r2KFbAYM0GE=" - export KAS_KEY_SYSTEM_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kasId "${KAS_REGISTRY_ID_BASE_KEY_TEST}" --keyId "${REGULAR_KEY_ID_FOR_BASE_TEST}" --alg rsa:2048 --mode local --wrappingKey "${WRAPPING_KEY}" --wrappingKeyId "wrapping-key-id" --json | jq -r '.key.id') + export KAS_KEY_SYSTEM_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kas "${KAS_REGISTRY_ID_BASE_KEY_TEST}" --key-id "${REGULAR_KEY_ID_FOR_BASE_TEST}" --algorithm rsa:2048 --mode local --wrapping-key "${WRAPPING_KEY}" --wrapping-key-id "wrapping-key-id" --json | jq -r '.key.id') } setup() { - load "${BATS_LIB_PATH}/bats-support/load.bash" - load "${BATS_LIB_PATH}/bats-assert/load.bash" + load "${BATS_LIB_PATH}/bats-support/load.bash" + load "${BATS_LIB_PATH}/bats-assert/load.bash" - # invoke binary with credentials for base key commands - run_otdfctl_base_key () { - run sh -c "./otdfctl policy kas-registry key base $HOST $WITH_CREDS $*" - } + # invoke binary with credentials for base key commands + run_otdfctl_base_key() { + run sh -c "./otdfctl policy kas-registry key base $HOST $WITH_CREDS $*" + } } teardown_file() { @@ -36,7 +36,7 @@ teardown_file() { @test "base-key: get (initially no base key should be set for a new KAS)" { run_otdfctl_base_key get - assert_failure # Expecting failure or specific message indicating no base key + assert_failure # Expecting failure or specific message indicating no base key assert_output --partial "No base key found" # Or similar error message } @@ -52,13 +52,11 @@ teardown_file() { assert_not_equal "$(echo "$output" | jq -r .new_base_key.public_key.pem)" "null" assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.algorithm)" "rsa:2048" # Verify previous base key is null or not present if this is the first set - assert_equal "$(echo "$output" | jq -r .previous_base_key)" "null" + assert_equal "$(echo "$output" | jq -r .previous_base_key)" "null" } - - -@test "base-key: set by --keyId and --kasId" { - run_otdfctl_base_key set --keyId "${REGULAR_KEY_ID_FOR_BASE_TEST}" --kasId "${KAS_REGISTRY_ID_BASE_KEY_TEST}" --json +@test "base-key: set by --key(id) and --kas(id)" { + run_otdfctl_base_key set --key "${REGULAR_KEY_ID_FOR_BASE_TEST}" --kas "${KAS_REGISTRY_ID_BASE_KEY_TEST}" --json assert_success # Verify the new base key part of the response assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.kid)" "${REGULAR_KEY_ID_FOR_BASE_TEST}" @@ -81,8 +79,8 @@ teardown_file() { assert_equal "$(echo "$output" | jq -r .public_key.algorithm)" "rsa:2048" } -@test "base-key: set by --keyId and --kasName" { - run_otdfctl_base_key set --keyId "${REGULAR_KEY_ID_FOR_BASE_TEST}" --kasName "${KAS_NAME_BASE_KEY_TEST}" --json +@test "base-key: set by --key(id) and --kas(name)" { + run_otdfctl_base_key set --key "${REGULAR_KEY_ID_FOR_BASE_TEST}" --kasName "${KAS_NAME_BASE_KEY_TEST}" --json assert_success assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.kid)" "${REGULAR_KEY_ID_FOR_BASE_TEST}" assert_equal "$(echo "$output" | jq -r .new_base_key.kas_uri)" "${KAS_URI_BASE_KEY_TEST}" # KAS URI should remain the same for the KAS Name @@ -91,9 +89,9 @@ teardown_file() { assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.algorithm)" "rsa:2048" } -@test "base-key: set by --keyId and --kasUri" { +@test "base-key: set by --key(id) and --kas(uri)" { # This will set REGULAR_KEY_ID_FOR_BASE_TEST back as the base key - run_otdfctl_base_key set --keyId "${REGULAR_KEY_ID_FOR_BASE_TEST}" --kasUri "${KAS_URI_BASE_KEY_TEST}" --json + run_otdfctl_base_key set --key "${REGULAR_KEY_ID_FOR_BASE_TEST}" --kas "${KAS_URI_BASE_KEY_TEST}" --json assert_success # Verify the new base key assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.kid)" "${REGULAR_KEY_ID_FOR_BASE_TEST}" @@ -104,58 +102,55 @@ teardown_file() { } @test "base-key: set, get, and verify previous base key" { - run_otdfctl_base_key set --id "${KAS_KEY_SYSTEM_ID}" --json - assert_success - assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.kid)" "${REGULAR_KEY_ID_FOR_BASE_TEST}" - assert_equal "$(echo "$output" | jq -r .new_base_key.kas_uri)" "${KAS_URI_BASE_KEY_TEST}" - assert_not_equal "$(echo "$output" | jq -r .new_base_key.public_key.pem)" "" - assert_not_equal "$(echo "$output" | jq -r .new_base_key.public_key.pem)" "null" - assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.algorithm)" "rsa:2048" - - - run_otdfctl_base_key get --json - assert_success - assert_equal "$(echo "$output" | jq -r .public_key.kid)" "${REGULAR_KEY_ID_FOR_BASE_TEST}" - assert_equal "$(echo "$output" | jq -r .kas_uri)" "${KAS_URI_BASE_KEY_TEST}" - assert_not_equal "$(echo "$output" | jq -r .public_key.pem)" "" - assert_not_equal "$(echo "$output" | jq -r .public_key.pem)" "null" - assert_equal "$(echo "$output" | jq -r .public_key.algorithm)" "rsa:2048" - - - SECOND_KEY_ID_FOR_BASE_TEST="second-key-for-base-$(date +%s)" - SECOND_KAS_KEY_SYSTEM_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kasId "${KAS_REGISTRY_ID_BASE_KEY_TEST}" --keyId "${SECOND_KEY_ID_FOR_BASE_TEST}" --alg ec:secp256r1 --mode local --wrappingKey "${WRAPPING_KEY}" --wrappingKeyId "test-key" --json | jq -r '.key.id') - - run_otdfctl_base_key set --id "${SECOND_KAS_KEY_SYSTEM_ID}" --json - assert_success - assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.kid)" "${SECOND_KEY_ID_FOR_BASE_TEST}" - assert_equal "$(echo "$output" | jq -r .new_base_key.kas_uri)" "${KAS_URI_BASE_KEY_TEST}" - assert_not_equal "$(echo "$output" | jq -r .new_base_key.public_key.pem)" "" - assert_not_equal "$(echo "$output" | jq -r .new_base_key.public_key.pem)" "null" - assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.algorithm)" "ec:secp256r1" - # Verify previous base key - assert_equal "$(echo "$output" | jq -r .previous_base_key.public_key.kid)" "${REGULAR_KEY_ID_FOR_BASE_TEST}" - assert_equal "$(echo "$output" | jq -r .previous_base_key.kas_uri)" "${KAS_URI_BASE_KEY_TEST}" - assert_not_equal "$(echo "$output" | jq -r .new_base_key.public_key.pem)" "" - assert_not_equal "$(echo "$output" | jq -r .new_base_key.public_key.pem)" "null" - assert_equal "$(echo "$output" | jq -r .previous_base_key.public_key.algorithm)" "rsa:2048" -} + run_otdfctl_base_key set --key "${KAS_KEY_SYSTEM_ID}" --json + assert_success + assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.kid)" "${REGULAR_KEY_ID_FOR_BASE_TEST}" + assert_equal "$(echo "$output" | jq -r .new_base_key.kas_uri)" "${KAS_URI_BASE_KEY_TEST}" + assert_not_equal "$(echo "$output" | jq -r .new_base_key.public_key.pem)" "" + assert_not_equal "$(echo "$output" | jq -r .new_base_key.public_key.pem)" "null" + assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.algorithm)" "rsa:2048" + + run_otdfctl_base_key get --json + assert_success + assert_equal "$(echo "$output" | jq -r .public_key.kid)" "${REGULAR_KEY_ID_FOR_BASE_TEST}" + assert_equal "$(echo "$output" | jq -r .kas_uri)" "${KAS_URI_BASE_KEY_TEST}" + assert_not_equal "$(echo "$output" | jq -r .public_key.pem)" "" + assert_not_equal "$(echo "$output" | jq -r .public_key.pem)" "null" + assert_equal "$(echo "$output" | jq -r .public_key.algorithm)" "rsa:2048" + SECOND_KEY_ID_FOR_BASE_TEST="second-key-for-base-$(date +%s)" + SECOND_KAS_KEY_SYSTEM_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kasId "${KAS_REGISTRY_ID_BASE_KEY_TEST}" --keyId "${SECOND_KEY_ID_FOR_BASE_TEST}" --alg ec:secp256r1 --mode local --wrappingKey "${WRAPPING_KEY}" --wrappingKeyId "test-key" --json | jq -r '.key.id') + + run_otdfctl_base_key set --key "${SECOND_KAS_KEY_SYSTEM_ID}" --json + assert_success + assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.kid)" "${SECOND_KEY_ID_FOR_BASE_TEST}" + assert_equal "$(echo "$output" | jq -r .new_base_key.kas_uri)" "${KAS_URI_BASE_KEY_TEST}" + assert_not_equal "$(echo "$output" | jq -r .new_base_key.public_key.pem)" "" + assert_not_equal "$(echo "$output" | jq -r .new_base_key.public_key.pem)" "null" + assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.algorithm)" "ec:secp256r1" + # Verify previous base key + assert_equal "$(echo "$output" | jq -r .previous_base_key.public_key.kid)" "${REGULAR_KEY_ID_FOR_BASE_TEST}" + assert_equal "$(echo "$output" | jq -r .previous_base_key.kas_uri)" "${KAS_URI_BASE_KEY_TEST}" + assert_not_equal "$(echo "$output" | jq -r .new_base_key.public_key.pem)" "" + assert_not_equal "$(echo "$output" | jq -r .new_base_key.public_key.pem)" "null" + assert_equal "$(echo "$output" | jq -r .previous_base_key.public_key.algorithm)" "rsa:2048" +} @test "base-key: set (missing kas identifier: kasId, kasName, or kasUri)" { - run_otdfctl_base_key set --keyId "${REGULAR_KEY_ID_FOR_BASE_TEST}" + run_otdfctl_base_key set --key "${REGULAR_KEY_ID_FOR_BASE_TEST}" assert_failure assert_output --partial "at least one of 'kasId', 'kasName', or 'kasUri' must be provided with 'keyId'" } @test "base-key: set (missing key identifier: id or keyId)" { - run_otdfctl_base_key set --kasId "${KAS_REGISTRY_ID_BASE_KEY_TEST}" + run_otdfctl_base_key set --kas "${KAS_REGISTRY_ID_BASE_KEY_TEST}" assert_failure assert_output --partial "Error: at least one of the flags in the group [id keyId] is required" } @test "base-key: set (using non-existent keyId)" { NON_EXISTENT_KEY_ID="this-key-does-not-exist-12345" - run_otdfctl_base_key set --keyId "${NON_EXISTENT_KEY_ID}" --kasId "${KAS_REGISTRY_ID_BASE_KEY_TEST}" + run_otdfctl_base_key set --key "${NON_EXISTENT_KEY_ID}" --kas "${KAS_REGISTRY_ID_BASE_KEY_TEST}" assert_failure # The exact error message might depend on the backend implementation assert_output --partial "not_found" # Or a more specific "key not found" error @@ -163,8 +158,7 @@ teardown_file() { @test "base-key: set (using non-existent kasId)" { NON_EXISTENT_KAS_ID="a1b2c3d4-e5f6-7890-1234-567890abcdef" - run_otdfctl_base_key set --keyId "${REGULAR_KEY_ID_FOR_BASE_TEST}" --kasId "${NON_EXISTENT_KAS_ID}" + run_otdfctl_base_key set --key "${REGULAR_KEY_ID_FOR_BASE_TEST}" --kas "${NON_EXISTENT_KAS_ID}" assert_failure assert_output --partial "not_found" # Or a more specific "KAS not found" error } - diff --git a/e2e/kas-keys.bats b/e2e/kas-keys.bats index 91ba86d2..5dab3796 100644 --- a/e2e/kas-keys.bats +++ b/e2e/kas-keys.bats @@ -1,29 +1,28 @@ #!/usr/bin/env bats setup_file() { - echo -n '{"clientId":"opentdf","clientSecret":"secret"}' > creds.json + echo -n '{"clientId":"opentdf","clientSecret":"secret"}' >creds.json export WITH_CREDS='--with-client-creds-file ./creds.json' export HOST='--host http://localhost:8080' # This command is not a 'kas-registry key' subcommand, so it won't use run_otdfctl_key export KAS_URI="https://test-kas-with-keys.com" export KAS_NAME="kas-registry-for-keys-test" - export KAS_REGISTRY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --name $KAS_NAME --uri "$KAS_URI" --public-key-remote 'https://test-kas-with-keys.com' --json | jq -r '.id') + export KAS_REGISTRY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --name $KAS_NAME --uri "$KAS_URI" --json | jq -r '.id') export PC_ID=$(./otdfctl $HOST $WITH_CREDS keymanagement provider create --name "test-provider-config-kas-keys" --config '{}' --json | jq -r '.id') export WRAPPING_KEY="gp6TcYb/ZrgkQOYPdiYFRj11jZwbevy+r2KFbAYM0GE=" export PEM_B64=$(echo "pem" | base64) } setup() { - load "${BATS_LIB_PATH}/bats-support/load.bash" - load "${BATS_LIB_PATH}/bats-assert/load.bash" + load "${BATS_LIB_PATH}/bats-support/load.bash" + load "${BATS_LIB_PATH}/bats-assert/load.bash" - # invoke binary with credentials - run_otdfctl_key () { - run sh -c "./otdfctl policy kas-registry key $HOST $WITH_CREDS $*" - } + # invoke binary with credentials + run_otdfctl_key() { + run sh -c "./otdfctl policy kas-registry key $HOST $WITH_CREDS $*" + } } - teardown_file() { ./otdctl keymanagement provider "$HOST" "$WITH_CREDS" delete --id "$PC_ID" # Cannot cleanup KAS registry and keys, since keys cannot be deleted currently. @@ -39,7 +38,7 @@ generate_key_id() { echo "Error: /dev/urandom not found. Cannot generate random string." >&2 return 1 fi - key_id=$(LC_ALL=C < /dev/urandom tr -dc 'A-Za-z0-9' 2>/dev/null | head -c "${length}") + key_id=$(LC_ALL=C tr /dev/null | head -c "${length}") echo "$key_id" } @@ -51,7 +50,7 @@ generate_kas_name() { echo "Error: /dev/urandom not found. Cannot generate random string." >&2 return 1 fi - kas_name=$(LC_ALL=C < /dev/urandom tr -dc 'A-Za-z0-9' 2>/dev/null | head -c "${length}") + kas_name=$(LC_ALL=C tr /dev/null | head -c "${length}") echo "$kas_name" } @@ -65,13 +64,13 @@ format_kas_name_as_uri() { # For local mode, a public key is generated by otdfctl. # Its exact value cannot be known before running the command without replicating the key generation logic. # Thus, we assert its presence and that it\'s a non-empty base64 encoded string. This is the intended assertion. - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg rsa:2048 --mode local --wrappingKeyId wrapping-key-1 --wrappingKey "${WRAPPING_KEY}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithmorithm rsa:2048 --mode local --wrapping-key-id wrapping-key-1 --wrappingKey "${WRAPPING_KEY}" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "1" # local - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active (assuming default) + assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "1" # local + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active (assuming default) # Assert public_key_ctx.pem is present and not empty assert_not_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "null" assert_not_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "" @@ -88,13 +87,13 @@ format_kas_name_as_uri() { # For local mode, a public key is generated by otdfctl. # Its exact value cannot be known before running the command without replicating the key generation logic. # Thus, we assert its presence and that it\'s a non-empty base64 encoded string. This is the intended assertion. - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "ec:secp256r1" --mode "local" --wrappingKeyId "wrapping-key-1" --wrappingKey "${WRAPPING_KEY}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "ec:secp256r1" --mode "local" --wrapping-key-id "wrapping-key-1" --wrappingKey "${WRAPPING_KEY}" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "3" # ec:secp256r1 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "1" # local - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "3" # ec:secp256r1 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "1" # local + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_not_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "null" assert_not_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx.key_id)" "wrapping-key-1" @@ -106,13 +105,13 @@ format_kas_name_as_uri() { @test "kas-keys: create key (public_key mode)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" # Assert private_key_ctx is null or not present for public_key mode assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" @@ -122,16 +121,16 @@ format_kas_name_as_uri() { @test "kas-keys: create key (remote mode)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "remote" --pubPem "${PEM_B64}" --providerConfigId "${PC_ID}" --wrappingKeyId "wrapping-key-remote" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "remote" --public-key-pem "${PEM_B64}" --provider-config-id "${PC_ID}" --wrapping-key-id "wrapping-key-remote" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "3" # remote - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "3" # remote + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" # Assert private_key_ctx is not what it is for local mode, but check its key_id as per previous logic - # Based on kas-keys.go, remote mode sets privateKeyCtx.KeyId = wrappingKeyId + # Based on kas-keys.go, remote mode sets privateKeyCtx.key-id = wrapping-key-id assert_equal "$(echo "$output" | jq -r .key.private_key_ctx.key_id)" "wrapping-key-remote" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx.wrapped_key)" "null" # wrapped_key should not be set for remote assert_not_equal "$(echo "$output" | jq -r .key.metadata.created_at)" "null" @@ -141,13 +140,13 @@ format_kas_name_as_uri() { @test "kas-keys: create key (provider mode)" { KEY_ID=$(generate_key_id) WRAPPING_KEY_ID="wrapping-key-for-provider" - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "provider" --providerConfigId "${PC_ID}" --wrappingKeyId "${WRAPPING_KEY_ID}" --pubPem "${PEM_B64}" --privatePem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "provider" --provider-config-id "${PC_ID}" --wrapping-key-id "${WRAPPING_KEY_ID}" --public-key-pem "${PEM_B64}" --private-key-pem "${PEM_B64}" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "2" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "2" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx.wrapped_key)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx.key_id)" "${WRAPPING_KEY_ID}" @@ -157,13 +156,13 @@ format_kas_name_as_uri() { @test "kas-keys: create key with labels" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --label "env=dev" --label "owner=test" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --label "env=dev" --label "owner=test" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_equal "$(echo "$output" | jq -r '.key.metadata.labels."env"')" "dev" @@ -172,129 +171,129 @@ format_kas_name_as_uri() { assert_not_equal "$(echo "$output" | jq -r .key.metadata.updated_at)" "null" } -@test "kas-keys: create key (missing keyId)" { - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --alg "rsa:2048" --mode "local" --wrappingKeyId "wrapping-key-1" --wrappingKey "${WRAPPING_KEY}" +@test "kas-keys: create key (missing key-id)" { + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --algorithm "rsa:2048" --mode "local" --wrapping-key-id "wrapping-key-1" --wrappingKey "${WRAPPING_KEY}" assert_failure - assert_output --partial "Flag '--keyId' is required" + assert_output --partial "Flag '--key-id' is required" } -@test "kas-keys: create key (missing alg)" { +@test "kas-keys: create key (missing algorithm)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --mode "local" --wrappingKeyId "wrapping-key-1" --wrappingKey "${WRAPPING_KEY}" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --mode "local" --wrapping-key-id "wrapping-key-1" --wrappingKey "${WRAPPING_KEY}" assert_failure - assert_output --partial "Flag '--alg' is required" + assert_output --partial "Flag '--algorithm' is required" } @test "kas-keys: create key (missing mode)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --wrappingKeyId "wrapping-key-1" --wrappingKey "${WRAPPING_KEY}" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --wrapping-key-id "wrapping-key-1" --wrappingKey "${WRAPPING_KEY}" assert_failure assert_output --partial "Flag '--mode' is required" } -@test "kas-keys: create key (local mode, missing wrappingKeyId)" { +@test "kas-keys: create key (local mode, missing wrapping-key-id)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "local" --wrappingKey "${WRAPPING_KEY}" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "local" --wrappingKey "${WRAPPING_KEY}" assert_failure - assert_output --partial "wrappingKeyId is required for mode local" + assert_output --partial "wrapping-key-id is required for mode local" } @test "kas-keys: create key (local mode, missing wrappingKey)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "local" --wrappingKeyId "wrapping-key-1" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "local" --wrapping-key-id "wrapping-key-1" assert_failure assert_output --partial "Flag '--wrappingKey' is required" } @test "kas-keys: create key (public_key mode, missing pem)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "public_key" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "public_key" assert_failure - # The error message might vary based on how --pubPem is validated if missing. + # The error message might vary based on how --public-key-pem is validated if missing. # Assuming it's caught by the CLI framework or the command logic. - assert_output --partial "Flag '--pubPem' is required" + assert_output --partial "Flag '--public-key-pem' is required" } @test "kas-keys: create key (remote mode, missing pem)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "remote" --providerConfigId "pc-1" --wrappingKeyId "wk-1" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "remote" --provider-config-id "pc-1" --wrapping-key-id "wk-1" assert_failure - assert_output --partial "Flag '--pubPem' is required" + assert_output --partial "Flag '--public-key-pem' is required" } -@test "kas-keys: create key (remote mode, missing providerConfigId)" { +@test "kas-keys: create key (remote mode, missing provider-config-id)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "remote" --pubPem "${PEM_B64}" --wrappingKeyId "wk-1" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "remote" --public-key-pem "${PEM_B64}" --wrapping-key-id "wk-1" assert_failure - assert_output --partial "providerConfigId is required for mode remote" + assert_output --partial "provider-config-id is required for mode remote" } -@test "kas-keys: create key (remote mode, missing wrappingKeyId)" { +@test "kas-keys: create key (remote mode, missing wrapping-key-id)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "remote" --pubPem "${PEM_B64}" --providerConfigId "pc-1" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "remote" --public-key-pem "${PEM_B64}" --provider-config-id "pc-1" assert_failure - assert_output --partial "wrappingKeyId is required for mode remote" + assert_output --partial "wrapping-key-id is required for mode remote" } -@test "kas-keys: create key (provider mode, missing wrappingKeyId)" { +@test "kas-keys: create key (provider mode, missing wrapping-key-id)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "provider" --providerConfigId "pc-1" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "provider" --provider-config-id "pc-1" assert_failure - assert_output --partial "wrappingKeyId is required for mode provider" + assert_output --partial "wrapping-key-id is required for mode provider" } -@test "kas-keys: create key (provider mode, missing providerConfigId)" { +@test "kas-keys: create key (provider mode, missing provider-config-id)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "provider" --wrappingKeyId "wk-1" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "provider" --wrapping-key-id "wk-1" assert_failure - assert_output --partial "providerConfigId is required for mode provider" + assert_output --partial "provider-config-id is required for mode provider" } @test "kas-keys: create key (remote mode, pem not base64)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "remote" --pubPem "not-base64-value" --providerConfigId "pc-1" --wrappingKeyId "wk-1" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "remote" --public-key-pem "not-base64-value" --provider-config-id "pc-1" --wrapping-key-id "wk-1" assert_failure assert_output --partial "pem must be base64 encoded" } @test "kas-keys: create key (public_key mode, pem not base64)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "public_key" --pubPem "not-base64-value" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "not-base64-value" assert_failure assert_output --partial "pem must be base64 encoded" } -@test "kas-keys: create key (missing kas identifier - kasId, kasName, or kasUri)" { +@test "kas-keys: create key (missing kas identifier - kas, kas, or kas)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --keyId "${KEY_ID}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" + run_otdfctl_key create --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" assert_failure - assert_output --partial "Error: at least one of the flags in the group [kasId kasUri kasName] is required" + assert_output --partial "Error: at least one of the flags in the group [kas kas kas] is required" } -@test "kas-keys: create key (using kasName)" { +@test "kas-keys: create key (using kas)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasName "${KAS_NAME}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_NAME}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.created_at)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.updated_at)" "null" } -@test "kas-keys: create key (using kasUri)" { +@test "kas-keys: create key (using kas)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasUri "${KAS_URI}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_URI}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.created_at)" "null" @@ -303,28 +302,28 @@ format_kas_name_as_uri() { @test "kas-keys: create key (mutually exclusive KAS identifiers)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --kasName "some-other-kas" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --kas "some-other-kas" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_failure - assert_output --partial "Error: if any flags in the group [kasId kasUri kasName] are set none of the others can be; [kasId kasName] were all set" + assert_output --partial "Error: if any flags in the group [kas kas kas] are set none of the others can be; [kas kas] were all set" } -@test "kas-keys: create key (invalid algorithm value)" { +@test "kas-keys: create key (invalid algorithmorithm value)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "invalid-algorithm-value" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "invalid-algorithmorithm-value" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_failure - assert_output --partial "Invalid algorithm" + assert_output --partial "Invalid algorithmorithm" } @test "kas-keys: create key (invalid mode value)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID}" --alg "rsa:2048" --mode "invalid-mode-value" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "invalid-mode-value" --public-key-pem "${PEM_B64}" --json assert_failure assert_output --partial "Invalid mode" } @test "kas-keys: get key by system ID" { KEY_ID_GET=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID_GET}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID_GET}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success CREATED_KEY_SYSTEM_ID=$(echo "$output" | jq -r .key.id) @@ -333,92 +332,92 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.id)" "${CREATED_KEY_SYSTEM_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID_GET}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.created_at)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.updated_at)" "null" } -@test "kas-keys: get key by user keyId and kasId" { +@test "kas-keys: get key by user key-id and kas" { KEY_ID_GET_USER=$(generate_key_id) # Using ec:secp256r1 and public_key mode for variety - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID_GET_USER}" --alg "ec:secp256r1" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID_GET_USER}" --algorithm "ec:secp256r1" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success local created_key_system_id_for_get=$(echo "$output" | jq -r .key.id) - run_otdfctl_key get --keyId "${KEY_ID_GET_USER}" --kasId "${KAS_REGISTRY_ID}" --json + run_otdfctl_key get --key-id "${KEY_ID_GET_USER}" --kas "${KAS_REGISTRY_ID}" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.id)" "${created_key_system_id_for_get}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID_GET_USER}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "3" # ec:secp256r1 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "3" # ec:secp256r1 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.created_at)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.updated_at)" "null" } -@test "kas-keys: get key by user keyId and kasName" { - KEY_ID_GET_USER_KASNAME=$(generate_key_id) - run_otdfctl_key create --kasName "kas-registry-for-keys-test" --keyId "${KEY_ID_GET_USER_KASNAME}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json +@test "kas-keys: get key by user key-id and kas" { + KEY_ID_GET_USER_kas=$(generate_key_id) + run_otdfctl_key create --kas "kas-registry-for-keys-test" --key-id "${KEY_ID_GET_USER_kas}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success - local created_key_system_id_for_kasname_get=$(echo "$output" | jq -r .key.id) + local created_key_system_id_for_kas_get=$(echo "$output" | jq -r .key.id) - run_otdfctl_key get --keyId "${KEY_ID_GET_USER_KASNAME}" --kasName "kas-registry-for-keys-test" --json + run_otdfctl_key get --key-id "${KEY_ID_GET_USER_kas}" --kas "kas-registry-for-keys-test" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" - assert_equal "$(echo "$output" | jq -r .key.id)" "${created_key_system_id_for_kasname_get}" - assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID_GET_USER_KASNAME}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.id)" "${created_key_system_id_for_kas_get}" + assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID_GET_USER_kas}" + assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.created_at)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.updated_at)" "null" } -@test "kas-keys: get key by user keyId and kasUri" { - KEY_ID_GET_USER_KASURI=$(generate_key_id) - run_otdfctl_key create --kasUri "${KAS_URI}" --keyId "${KEY_ID_GET_USER_KASURI}" --alg "ec:secp256r1" --mode "public_key" --pubPem "${PEM_B64}" --json +@test "kas-keys: get key by user key-id and kas" { + KEY_ID_GET_USER_kas=$(generate_key_id) + run_otdfctl_key create --kas "${KAS_URI}" --key-id "${KEY_ID_GET_USER_kas}" --algorithm "ec:secp256r1" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success - local created_key_system_id_for_kasuri_get=$(echo "$output" | jq -r .key.id) + local created_key_system_id_for_kas_get=$(echo "$output" | jq -r .key.id) - run_otdfctl_key get --keyId "${KEY_ID_GET_USER_KASURI}" --kasUri "${KAS_URI}" --json + run_otdfctl_key get --key-id "${KEY_ID_GET_USER_kas}" --kas "${KAS_URI}" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" # Should resolve to the same KAS - assert_equal "$(echo "$output" | jq -r .key.id)" "${created_key_system_id_for_kasuri_get}" - assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID_GET_USER_KASURI}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "3" # ec:secp256r1 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.id)" "${created_key_system_id_for_kas_get}" + assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID_GET_USER_kas}" + assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "3" # ec:secp256r1 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.created_at)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.updated_at)" "null" } -@test "kas-keys: get key (failure: only keyId, missing KAS identifier)" { +@test "kas-keys: get key (failure: only key-id, missing KAS identifier)" { KEY_ID_FAIL_GET=$(generate_key_id) # Create a key first so it potentially exists, though the failure should be due to missing KAS context for the get - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID_FAIL_GET}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID_FAIL_GET}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success - run_otdfctl_key get --keyId "${KEY_ID_FAIL_GET}" --json + run_otdfctl_key get --key-id "${KEY_ID_FAIL_GET}" --json assert_failure # Error message might vary, but it should indicate an issue with resolving the key or missing parameters - assert_output --partial "at least one of 'kasId', 'kasName', or 'kasUri' must be provided with 'keyId'" # Or a more specific error about missing KAS identifier + assert_output --partial "at least one of 'kas', 'kas', or 'kas' must be provided with 'key-id'" # Or a more specific error about missing KAS identifier } -@test "kas-keys: get key (failure: only kasId, missing keyId or system id)" { - run_otdfctl_key get --kasId "${KAS_REGISTRY_ID}" --json +@test "kas-keys: get key (failure: only kas, missing key-id or system id)" { + run_otdfctl_key get --kas "${KAS_REGISTRY_ID}" --json assert_failure - assert_output --partial "at least one of the flags in the group [id keyId] is required" + assert_output --partial "at least one of the flags in the group [id key-id] is required" } @test "kas-keys: get key (not found by system ID)" { @@ -427,27 +426,27 @@ format_kas_name_as_uri() { assert_output --partial "Failed to get kas key" # Error should indicate not found or similar } -@test "kas-keys: get key (not found by user keyId and kasId)" { - run_otdfctl_key get --keyId "non-existent-key" --kasId "${KAS_REGISTRY_ID}" --json +@test "kas-keys: get key (not found by user key-id and kas)" { + run_otdfctl_key get --key-id "non-existent-key" --kas "${KAS_REGISTRY_ID}" --json assert_failure assert_output --partial "Failed to get kas key" # Error should indicate not found or similar } -@test "kas-keys: get key (mutually exclusive: id and keyId)" { - run_otdfctl_key get --id "some-system-id" --keyId "some-user-key-id" --kasId "${KAS_REGISTRY_ID}" --json +@test "kas-keys: get key (mutually exclusive: id and key-id)" { + run_otdfctl_key get --id "some-system-id" --key-id "some-user-key-id" --kas "${KAS_REGISTRY_ID}" --json assert_failure - assert_output --partial "Error: if any flags in the group [id keyId] are set none of the others can be" + assert_output --partial "Error: if any flags in the group [id key-id] are set none of the others can be" } -@test "kas-keys: get key (mutually exclusive: kasId and kasName with keyId)" { - run_otdfctl_key get --keyId "some-user-key-id" --kasId "${KAS_REGISTRY_ID}" --kasName "some-kas-name" --json +@test "kas-keys: get key (mutually exclusive: kas and kas with key-id)" { + run_otdfctl_key get --key-id "some-user-key-id" --kas "${KAS_REGISTRY_ID}" --kas "some-kas-name" --json assert_failure - assert_output --partial "Error: if any flags in the group [kasUri kasId kasName] are set none of the others can be; [kasId kasName] were all set" + assert_output --partial "Error: if any flags in the group [kas kas kas] are set none of the others can be; [kas kas] were all set" } @test "kas-keys: update key labels (add)" { KEY_ID_UPDATE_LABEL=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID_UPDATE_LABEL}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --label "initial=true" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID_UPDATE_LABEL}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --label "initial=true" --json assert_success UPDATE_KEY_LABEL_SYSTEM_ID=$(echo "$output" | jq -r .key.id) local initial_created_at_seconds=$(echo "$output" | jq -r .key.metadata.created_at.seconds) @@ -458,9 +457,9 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.id)" "${UPDATE_KEY_LABEL_SYSTEM_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID_UPDATE_LABEL}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active (should not change) + assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active (should not change) assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_equal "$(echo "$output" | jq -r '.key.metadata.labels."initial"')" "true" @@ -476,20 +475,19 @@ format_kas_name_as_uri() { @test "kas-keys: update key labels (replace)" { KEY_ID_UPDATE_LABEL_REPLACE=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID_UPDATE_LABEL_REPLACE}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --label "initial=true" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID_UPDATE_LABEL_REPLACE}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --label "initial=true" --json assert_success UPDATE_KEY_LABEL_REPLACE_SYSTEM_ID=$(echo "$output" | jq -r .key.id) local initial_created_at_replace_seconds=$(echo "$output" | jq -r .key.metadata.created_at.seconds) - run_otdfctl_key update --id "${UPDATE_KEY_LABEL_REPLACE_SYSTEM_ID}" --label "replaced=true" --force-replace-labels --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.id)" "${UPDATE_KEY_LABEL_REPLACE_SYSTEM_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID_UPDATE_LABEL_REPLACE}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r '.key.metadata.labels."replaced"')" "true" assert_equal "$(echo "$output" | jq -r '.key.metadata.labels."initial" // "null"')" "null" assert_equal "$(echo "$output" | jq -r .key.metadata.created_at.seconds)" "${initial_created_at_replace_seconds}" @@ -518,12 +516,12 @@ format_kas_name_as_uri() { # Create a few keys to ensure there\\'s something to list and to check structure KEY_ID_LIST_1=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID_LIST_1}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID_LIST_1}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success local key1_system_id=$(echo "$output" | jq -r .key.id) KEY_ID_LIST_2=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_REGISTRY_ID}" --keyId "${KEY_ID_LIST_2}" --alg "ec:secp256r1" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID_LIST_2}" --algorithm "ec:secp256r1" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success local key2_system_id=$(echo "$output" | jq -r .key.id) @@ -533,7 +531,7 @@ format_kas_name_as_uri() { # For key1: assert_equal "$(echo "$output" | jq -r --arg id "${key1_system_id}" '.[] | select(.key.id == $id) | .key.id')" "${key1_system_id}" assert_equal "$(echo "$output" | jq -r --arg id "${key1_system_id}" '.[] | select(.key.id == $id) | .key.key_id')" "${KEY_ID_LIST_1}" - assert_equal "$(echo "$output" | jq -r --arg id "${key1_system_id}" '.[] | select(.key.id == $id) | .key.key_algorithm')" "1" + assert_equal "$(echo "$output" | jq -r --arg id "${key1_system_id}" '.[] | select(.key.id == $id) | .key.key_algorithmorithm')" "1" assert_equal "$(echo "$output" | jq -r --arg id "${key1_system_id}" '.[] | select(.key.id == $id) | .key.key_mode')" "4" assert_equal "$(echo "$output" | jq -r --arg id "${key1_system_id}" '.[] | select(.key.id == $id) | .key.key_status')" "1" assert_equal "$(echo "$output" | jq -r --arg id "${key1_system_id}" '.[] | select(.key.id == $id) | .key.public_key_ctx.pem')" "${PEM_B64}" @@ -544,7 +542,7 @@ format_kas_name_as_uri() { # For key2: assert_equal "$(echo "$output" | jq -r --arg id "${key2_system_id}" '.[] | select(.key.id == $id) | .key.id')" "${key2_system_id}" assert_equal "$(echo "$output" | jq -r --arg id "${key2_system_id}" '.[] | select(.key.id == $id) | .key.key_id')" "${KEY_ID_LIST_2}" - assert_equal "$(echo "$output" | jq -r --arg id "${key2_system_id}" '.[] | select(.key.id == $id) | .key.key_algorithm')" "3" + assert_equal "$(echo "$output" | jq -r --arg id "${key2_system_id}" '.[] | select(.key.id == $id) | .key.key_algorithmorithm')" "3" assert_equal "$(echo "$output" | jq -r --arg id "${key2_system_id}" '.[] | select(.key.id == $id) | .key.key_mode')" "4" assert_equal "$(echo "$output" | jq -r --arg id "${key2_system_id}" '.[] | select(.key.id == $id) | .key.key_status')" "1" assert_equal "$(echo "$output" | jq -r --arg id "${key2_system_id}" '.[] | select(.key.id == $id) | .key.public_key_ctx.pem')" "${PEM_B64}" @@ -561,35 +559,34 @@ format_kas_name_as_uri() { # Create a known set of keys for pagination testing local key_p1_id=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_ID_LIST}" --keyId "${key_p1_id}" --alg "rsa:4096" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_ID_LIST}" --key-id "${key_p1_id}" --algorithm "rsa:4096" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success local key_p1_sys_id=$(echo "$output" | jq -r .key.id) local key_p2_id=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_ID_LIST}" --keyId "${key_p2_id}" --alg "ec:secp256r1" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_ID_LIST}" --key-id "${key_p2_id}" --algorithm "ec:secp256r1" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success local key_p2_sys_id=$(echo "$output" | jq -r .key.id) local key_p3_id=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_ID_LIST}" --keyId "${key_p3_id}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_ID_LIST}" --key-id "${key_p3_id}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success local key_p3_sys_id=$(echo "$output" | jq -r .key.id) # Test: limit 1, offset 0 - should get the first key (order dependent on server, so we check for one of them) - run_otdfctl_key list --kasId "${KAS_ID_LIST}" --limit 1 --offset 0 --json + run_otdfctl_key list --kas "${KAS_ID_LIST}" --limit 1 --offset 0 --json assert_success assert_equal "$(echo "$output" | jq '. | length')" "1" local found_id_limit1_offset0=$(echo "$output" | jq -r '.[0].key.id') # Test: limit 1, offset 1 - should get the second key - run_otdfctl_key list --kasId "${KAS_ID_LIST}" --limit 1 --offset 1 --json + run_otdfctl_key list --kas "${KAS_ID_LIST}" --limit 1 --offset 1 --json assert_success assert_equal "$(echo "$output" | jq '. | length')" "1" local found_id_limit1_offset1=$(echo "$output" | jq -r '.[0].key.id') assert_not_equal "${found_id_limit1_offset1}" "${found_id_limit1_offset0}" - - run_otdfctl_key list --kasId "${KAS_ID_LIST}" --limit 3 --offset 0 --json # Fetch up to 3 + run_otdfctl_key list --kas "${KAS_ID_LIST}" --limit 3 --offset 0 --json # Fetch up to 3 assert_success local count_limit3_offset0=$(echo "$output" | jq '. | length') assert_equal "${count_limit3_offset0}" 3 @@ -597,14 +594,13 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r --arg id "${key_p2_sys_id}" '.[] | select(.key.id == $id) | .key.id')" "${key_p2_sys_id}" assert_equal "$(echo "$output" | jq -r --arg id "${key_p3_sys_id}" '.[] | select(.key.id == $id) | .key.id')" "${key_p3_sys_id}" - # Test: limit 1, offset (large number, e.g., 100) - should get 0 keys - run_otdfctl_key list --kasId "${KAS_ID_LIST}" --limit 1 --offset 100 --json + run_otdfctl_key list --kas "${KAS_ID_LIST}" --limit 1 --offset 100 --json assert_success assert_equal "$(echo "$output" | jq '. | length')" "0" } -@test "kas-keys: list keys (filter by alg rsa:2048)" { +@test "kas-keys: list keys (filter by algorithm rsa:2048)" { KAS_NAME_LIST=$(generate_kas_name) KAS_URI_LIST=$(format_kas_name_as_uri "${KAS_NAME_LIST}") KAS_ID_LIST=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --name "$KAS_NAME_LIST" --uri "$KAS_URI_LIST" --public-key-remote 'https://test-kas-with-keys.com' --json | jq -r '.id') @@ -612,24 +608,23 @@ format_kas_name_as_uri() { # Ensure at least one rsa:2048 key exists for this KAS KEY_ID_LIST_RSA=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_ID_LIST}" --keyId "${KEY_ID_LIST_RSA}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_ID_LIST}" --key-id "${KEY_ID_LIST_RSA}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success local rsa_key_sys_id=$(echo "$output" | jq -r .key.id) # Ensure at least one non-rsa:2048 key exists for this KAS to test filtering KEY_ID_LIST_EC=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_ID_LIST}" --keyId "${KEY_ID_LIST_EC}" --alg "ec:secp256r1" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_ID_LIST}" --key-id "${KEY_ID_LIST_EC}" --algorithm "ec:secp256r1" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success local ec_key_sys_id=$(echo "$output" | jq -r .key.id) - - run_otdfctl_key list --kasId "${KAS_ID_LIST}" --alg "rsa:2048" --json + run_otdfctl_key list --kas "${KAS_ID_LIST}" --algorithm "rsa:2048" --json assert_success # Every key in the list should be rsa:2048 # And our specific RSA key should be present assert_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.id')" "${rsa_key_sys_id}" assert_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.key_id')" "${KEY_ID_LIST_RSA}" - assert_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.key_algorithm')" "1" + assert_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.key_algorithmorithm')" "1" assert_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.key_mode')" "4" assert_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.key_status')" "1" assert_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.public_key_ctx.pem')" "${PEM_B64}" @@ -637,29 +632,29 @@ format_kas_name_as_uri() { assert_not_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.metadata.created_at')" "null" assert_not_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.metadata.updated_at')" "null" - # Check that all listed keys have key_algorithm 1 (ALGORITHM_RSA_2048) - local count_non_rsa=$(echo "$output" | jq '[.[] | select(.key.key_algorithm != 1)] | length') + # Check that all listed keys have key_algorithmorithm 1 (algorithmORITHM_RSA_2048) + local count_non_rsa=$(echo "$output" | jq '[.[] | select(.key.key_algorithmorithm != 1)] | length') assert_equal "$count_non_rsa" "0" } -@test "kas-keys: list keys (filter by kasId)" { +@test "kas-keys: list keys (filter by kas)" { KAS_NAME_LIST=$(generate_kas_name) KAS_URI_LIST=$(format_kas_name_as_uri "${KAS_NAME_LIST}") KAS_ID_LIST=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --name "$KAS_NAME_LIST" --uri "$KAS_URI_LIST" --public-key-remote 'https://test-kas-with-keys.com' --json | jq -r '.id') assert_not_equal "$KAS_ID_LIST" "" KEY_ID_LIST_KAS_FILTER=$(generate_key_id) - run_otdfctl_key create --kasId "${KAS_ID_LIST}" --keyId "${KEY_ID_LIST_KAS_FILTER}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_ID_LIST}" --key-id "${KEY_ID_LIST_KAS_FILTER}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success local kas_filter_key_sys_id=$(echo "$output" | jq -r .key.id) # List keys for the new KAS - run_otdfctl_key list --kasId "${KAS_ID_LIST}" --json + run_otdfctl_key list --kas "${KAS_ID_LIST}" --json assert_success assert_equal "$(echo "$output" | jq -r '.[0].kas_id')" "${KAS_ID_LIST}" assert_equal "$(echo "$output" | jq -r '.[0].key.id')" "${kas_filter_key_sys_id}" assert_equal "$(echo "$output" | jq -r '.[0].key.key_id')" "${KEY_ID_LIST_KAS_FILTER}" - assert_equal "$(echo "$output" | jq -r '.[0].key.key_algorithm')" "1" + assert_equal "$(echo "$output" | jq -r '.[0].key.key_algorithmorithm')" "1" assert_equal "$(echo "$output" | jq -r '.[0].key.key_mode')" "4" assert_equal "$(echo "$output" | jq -r '.[0].key.key_status')" "1" assert_equal "$(echo "$output" | jq -r '.[0].key.public_key_ctx.pem')" "${PEM_B64}" @@ -668,14 +663,13 @@ format_kas_name_as_uri() { assert_not_equal "$(echo "$output" | jq -r '.[0].key.metadata.updated_at')" "null" assert_equal "$(echo "$output" | jq '. | length')" "1" - # List keys for the default KAS_REGISTRY_ID and ensure the new key is not present - run_otdfctl_key list --kasId "${KAS_REGISTRY_ID}" --json + run_otdfctl_key list --kas "${KAS_REGISTRY_ID}" --json assert_success assert_equal "$(echo "$output" | jq -r --arg id "${kas_filter_key_sys_id}" '[.[] | select(.key.id == $id)] | length')" "0" } -@test "kas-keys: list keys (filter by kasName)" { +@test "kas-keys: list keys (filter by kas)" { KAS_NAME_LIST=$(generate_kas_name) echo "DEBUG: KAS_NAME_LIST: ${KAS_NAME_LIST}" >&2 KAS_URI_LIST=$(format_kas_name_as_uri "${KAS_NAME_LIST}") @@ -684,16 +678,16 @@ format_kas_name_as_uri() { KEY_ID_LIST_KAS_NAME_FILTER=$(generate_key_id) local lower_kas_name=$(echo "${KAS_NAME_LIST}" | tr '[:upper:]' '[:lower:]') - run_otdfctl_key create --kasName "${lower_kas_name}" --keyId "${KEY_ID_LIST_KAS_NAME_FILTER}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${lower_kas_name}" --key-id "${KEY_ID_LIST_KAS_NAME_FILTER}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success local kas_name_filter_key_sys_id=$(echo "$output" | jq -r .key.id) - run_otdfctl_key list --kasName "${lower_kas_name}" --json + run_otdfctl_key list --kas "${lower_kas_name}" --json assert_success assert_equal "$(echo "$output" | jq -r '.[0].kas_id')" "${KAS_ID_LIST}" assert_equal "$(echo "$output" | jq -r '.[0].key.id')" "${kas_name_filter_key_sys_id}" assert_equal "$(echo "$output" | jq -r '.[0].key.key_id')" "${KEY_ID_LIST_KAS_NAME_FILTER}" - assert_equal "$(echo "$output" | jq -r '.[0].key.key_algorithm')" "1" + assert_equal "$(echo "$output" | jq -r '.[0].key.key_algorithmorithm')" "1" assert_equal "$(echo "$output" | jq -r '.[0].key.key_mode')" "4" assert_equal "$(echo "$output" | jq -r '.[0].key.key_status')" "1" assert_equal "$(echo "$output" | jq -r '.[0].key.public_key_ctx.pem')" "${PEM_B64}" @@ -702,7 +696,7 @@ format_kas_name_as_uri() { assert_not_equal "$(echo "$output" | jq -r '.[0].key.metadata.updated_at')" "null" } -@test "kas-keys: list keys (filter by kasUri)" { +@test "kas-keys: list keys (filter by kas)" { # This command is not a 'kas-registry key' subcommand, so it won't use run_otdfctl_key KAS_NAME_LIST=$(generate_kas_name) KAS_URI_LIST=$(format_kas_name_as_uri "${KAS_NAME_LIST}") @@ -710,29 +704,29 @@ format_kas_name_as_uri() { assert_not_equal "$KAS_ID_LIST" "" KEY_ID_LIST_KAS_URI_FILTER=$(generate_key_id) - run_otdfctl_key create --kasUri "${KAS_URI_LIST}" --keyId "${KEY_ID_LIST_KAS_URI_FILTER}" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_URI_LIST}" --key-id "${KEY_ID_LIST_KAS_URI_FILTER}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success local kas_uri_filter_key_sys_id=$(echo "$output" | jq -r .key.id) - run_otdfctl_key list --kasUri "${KAS_URI_LIST}" --json + run_otdfctl_key list --kas "${KAS_URI_LIST}" --json assert_success assert_equal "$(echo "$output" | jq -r '.[0].kas_id')" "${KAS_ID_LIST}" assert_equal "$(echo "$output" | jq -r '.[0].key.id')" "${kas_uri_filter_key_sys_id}" assert_equal "$(echo "$output" | jq -r '.[0].key.key_id')" "${KEY_ID_LIST_KAS_URI_FILTER}" - assert_equal "$(echo "$output" | jq -r '.[0].key.key_algorithm')" "1" + assert_equal "$(echo "$output" | jq -r '.[0].key.key_algorithmorithm')" "1" assert_equal "$(echo "$output" | jq -r '.[0].key.key_mode')" "4" assert_equal "$(echo "$output" | jq -r '.[0].key.key_status')" "1" assert_equal "$(echo "$output" | jq -r '.[0].key.public_key_ctx.pem')" "${PEM_B64}" } -@test "kas-keys: list keys (invalid alg)" { - run_otdfctl_key list --alg "invalid-alg" --json +@test "kas-keys: list keys (invalid algorithm)" { + run_otdfctl_key list --algorithm "invalid-algorithm" --json assert_failure - assert_output --partial "Invalid algorithm" + assert_output --partial "Invalid algorithmorithm" } -@test "kas-keys: list keys (mutually exclusive: kasId and kasName)" { - run_otdfctl_key list --kasId "${KAS_REGISTRY_ID}" --kasName "some-kas-name" --json +@test "kas-keys: list keys (mutually exclusive: kas and kas)" { + run_otdfctl_key list --kas "${KAS_REGISTRY_ID}" --kas "some-kas-name" --json assert_failure - assert_output --partial "Error: if any flags in the group [kasId kasName kasUri] are set none of the others can be" + assert_output --partial "Error: if any flags in the group [kas kas kas] are set none of the others can be" } diff --git a/pkg/utils/identifier.go b/pkg/utils/identifier.go new file mode 100644 index 00000000..a7e371bb --- /dev/null +++ b/pkg/utils/identifier.go @@ -0,0 +1,73 @@ +// pkg/utils/identifier.go +package utils + +import ( + "net/url" + "strings" + + "github.com/google/uuid" +) + +// IdentifierStringType defines the type of string identified. +type IdentifierStringType int + +const ( + // StringTypeUnknown indicates the string type could not be determined or is empty. + StringTypeUnknown IdentifierStringType = iota + // StringTypeUUID indicates the string is a valid UUID. + StringTypeUUID + // StringTypeURI indicates the string is a valid absolute URI. + StringTypeURI + // StringTypeGeneric indicates the string is not a UUID or URI, and can be treated as a generic identifier (e.g., a name). + StringTypeGeneric +) + +// String returns a string representation of the IdentifierStringType. +func (it IdentifierStringType) String() string { + switch it { + case StringTypeUUID: + return "UUID" + case StringTypeURI: + return "URI" + case StringTypeGeneric: + return "Generic" + case StringTypeUnknown: + fallthrough + default: + return "Unknown" + } +} + +// ClassifyString attempts to determine if the input string is a UUID, an absolute URI, or a generic string. +// It prioritizes UUID, then URI, then defaults to Generic. +func ClassifyString(input string) IdentifierStringType { + trimmedInput := strings.TrimSpace(input) + if trimmedInput == "" { + return StringTypeUnknown // Or StringTypeGeneric if empty strings should be treated as such + } + + // Check for UUID + // uuid.Parse is strict and will return an error if the string is not a valid UUID. + if _, err := uuid.Parse(trimmedInput); err == nil { + return StringTypeUUID + } + + // Check for an absolute URI + // url.ParseRequestURI requires the URL to be absolute. + // We also check for a scheme and host to ensure it's a usable network URI. + if parsedURL, err := url.ParseRequestURI(trimmedInput); err == nil { + if parsedURL.Scheme != "" && parsedURL.Host != "" { + return StringTypeURI + } + } + // A slightly more lenient check that also catches schemeless URLs if needed, + // but for KAS identifiers, absolute URIs are usually expected. + // if parsedURL, err := url.Parse(trimmedInput); err == nil { + // if parsedURL.Scheme != "" && parsedURL.Host != "" { + // return StringTypeURI + // } + // } + + // If not a UUID and not a well-formed absolute URI, treat as generic + return StringTypeGeneric +} diff --git a/pkg/utils/identifier_test.go b/pkg/utils/identifier_test.go new file mode 100644 index 00000000..532f2830 --- /dev/null +++ b/pkg/utils/identifier_test.go @@ -0,0 +1,92 @@ +package utils + +import ( + "testing" +) + +func TestClassifyString(t *testing.T) { + tests := []struct { + name string + input string + expected IdentifierStringType + }{ + { + name: "Valid UUID", + input: "123e4567-e89b-12d3-a456-426614174000", + expected: StringTypeUUID, + }, + { + name: "Valid UUID with spaces", + input: " 123e4567-e89b-12d3-a456-426614174000 ", + expected: StringTypeUUID, + }, + { + name: "Valid URI - https", + input: "https://example.com/path?query=value", + expected: StringTypeURI, + }, + { + name: "Valid URI - http", + input: "http://localhost:8080", + expected: StringTypeURI, + }, + { + name: "Valid URI with spaces", + input: " https://example.com/path ", + expected: StringTypeURI, + }, + { + name: "Generic string - name", + input: "my-kas-server", + expected: StringTypeGeneric, + }, + { + name: "Generic string - simple word", + input: "kas1", + expected: StringTypeGeneric, + }, + { + name: "Generic string with spaces", + input: " My KAS Name ", + expected: StringTypeGeneric, + }, + { + name: "Empty string", + input: "", + expected: StringTypeUnknown, + }, + { + name: "String with only spaces", + input: " ", + expected: StringTypeUnknown, + }, + { + name: "Invalid UUID - too short", + input: "123e4567-e89b-12d3-a456-42661417400", + expected: StringTypeGeneric, // Falls back to generic + }, + { + name: "Invalid URI - no scheme", + input: "example.com/path", + expected: StringTypeGeneric, // Falls back to generic + }, + { + name: "Invalid URI - no host", + input: "https:///path", + expected: StringTypeGeneric, // Falls back to generic + }, + { + name: "String that looks like URI but isn't absolute", + input: "/just/a/path", + expected: StringTypeGeneric, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := ClassifyString(tt.input); got != tt.expected { + t.Errorf("ClassifyString() = %v, want %v", got, tt.expected) + } + }) + } +} From 811f875334e77718119dd80d1b8f3a2f180249b1 Mon Sep 17 00:00:00 2001 From: Sean Trantalis <18211470+strantalis@users.noreply.github.com> Date: Mon, 2 Jun 2025 08:51:43 -0400 Subject: [PATCH 02/27] Update cmd/kas-keys.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- cmd/kas-keys.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/kas-keys.go b/cmd/kas-keys.go index 66f181d3..39fdd4e9 100644 --- a/cmd/kas-keys.go +++ b/cmd/kas-keys.go @@ -316,7 +316,7 @@ func policyCreateKasKey(cmd *cobra.Command, args []string) { } case policy.KeyMode_KEY_MODE_REMOTE: pem := c.Flags.GetRequiredString("public-key-pem") - providerConfigID = c.Flags.GetRequiredString("provider-config-pem") +providerConfigID = c.Flags.GetRequiredString("provider-config-id") _, err = base64.StdEncoding.DecodeString(pem) if err != nil { From 5b709a6404a95a11b61035f8855c1b9b0dd86c59 Mon Sep 17 00:00:00 2001 From: Sean Trantalis <18211470+strantalis@users.noreply.github.com> Date: Mon, 2 Jun 2025 08:51:54 -0400 Subject: [PATCH 03/27] Update cmd/kas-keys.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- cmd/kas-keys.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/kas-keys.go b/cmd/kas-keys.go index 39fdd4e9..75aac5bc 100644 --- a/cmd/kas-keys.go +++ b/cmd/kas-keys.go @@ -249,7 +249,7 @@ func policyCreateKasKey(cmd *cobra.Command, args []string) { kasIdentifier := c.Flags.GetRequiredString("kas") metadataLabels = c.Flags.GetStringSlice("label", metadataLabels, cli.FlagsStringSliceOptions{Min: 0}) - alg, err := algToEnum(c.Flags.GetRequiredString("alg")) +alg, err := algToEnum(c.Flags.GetRequiredString("algorithm")) if err != nil { cli.ExitWithError("Invalid algorithm", err) } From 28c30ababb65d4dd508eeac64642920bd31b1666 Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 08:54:26 -0400 Subject: [PATCH 04/27] fix e2e typo --- e2e/kas-keys.bats | 100 +++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/e2e/kas-keys.bats b/e2e/kas-keys.bats index 5dab3796..9ac7978f 100644 --- a/e2e/kas-keys.bats +++ b/e2e/kas-keys.bats @@ -68,9 +68,9 @@ format_kas_name_as_uri() { assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "1" # local - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active (assuming default) + assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "1" # local + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active (assuming default) # Assert public_key_ctx.pem is present and not empty assert_not_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "null" assert_not_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "" @@ -91,9 +91,9 @@ format_kas_name_as_uri() { assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "3" # ec:secp256r1 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "1" # local - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "3" # ec:secp256r1 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "1" # local + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_not_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "null" assert_not_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx.key_id)" "wrapping-key-1" @@ -109,9 +109,9 @@ format_kas_name_as_uri() { assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" # Assert private_key_ctx is null or not present for public_key mode assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" @@ -125,9 +125,9 @@ format_kas_name_as_uri() { assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "3" # remote - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "3" # remote + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" # Assert private_key_ctx is not what it is for local mode, but check its key_id as per previous logic # Based on kas-keys.go, remote mode sets privateKeyCtx.key-id = wrapping-key-id @@ -144,9 +144,9 @@ format_kas_name_as_uri() { assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "2" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "2" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx.wrapped_key)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx.key_id)" "${WRAPPING_KEY_ID}" @@ -160,9 +160,9 @@ format_kas_name_as_uri() { assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_equal "$(echo "$output" | jq -r '.key.metadata.labels."env"')" "dev" @@ -276,9 +276,9 @@ format_kas_name_as_uri() { assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.created_at)" "null" @@ -291,9 +291,9 @@ format_kas_name_as_uri() { assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.created_at)" "null" @@ -332,9 +332,9 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.id)" "${CREATED_KEY_SYSTEM_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID_GET}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.created_at)" "null" @@ -353,9 +353,9 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.id)" "${created_key_system_id_for_get}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID_GET_USER}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "3" # ec:secp256r1 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "3" # ec:secp256r1 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.created_at)" "null" @@ -373,9 +373,9 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.id)" "${created_key_system_id_for_kas_get}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID_GET_USER_kas}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.created_at)" "null" @@ -393,9 +393,9 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" # Should resolve to the same KAS assert_equal "$(echo "$output" | jq -r .key.id)" "${created_key_system_id_for_kas_get}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID_GET_USER_kas}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "3" # ec:secp256r1 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "3" # ec:secp256r1 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_not_equal "$(echo "$output" | jq -r .key.metadata.created_at)" "null" @@ -457,9 +457,9 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.id)" "${UPDATE_KEY_LABEL_SYSTEM_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID_UPDATE_LABEL}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active (should not change) + assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active (should not change) assert_equal "$(echo "$output" | jq -r .key.public_key_ctx.pem)" "${PEM_B64}" assert_equal "$(echo "$output" | jq -r .key.private_key_ctx)" "null" assert_equal "$(echo "$output" | jq -r '.key.metadata.labels."initial"')" "true" @@ -485,9 +485,9 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.id)" "${UPDATE_KEY_LABEL_REPLACE_SYSTEM_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID_UPDATE_LABEL_REPLACE}" - assert_equal "$(echo "$output" | jq -r .key.key_algorithmorithm)" "1" # rsa:2048 - assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key - assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active + assert_equal "$(echo "$output" | jq -r .key.key_algorithm)" "1" # rsa:2048 + assert_equal "$(echo "$output" | jq -r .key.key_mode)" "4" # public_key + assert_equal "$(echo "$output" | jq -r .key.key_status)" "1" # active assert_equal "$(echo "$output" | jq -r '.key.metadata.labels."replaced"')" "true" assert_equal "$(echo "$output" | jq -r '.key.metadata.labels."initial" // "null"')" "null" assert_equal "$(echo "$output" | jq -r .key.metadata.created_at.seconds)" "${initial_created_at_replace_seconds}" @@ -531,7 +531,7 @@ format_kas_name_as_uri() { # For key1: assert_equal "$(echo "$output" | jq -r --arg id "${key1_system_id}" '.[] | select(.key.id == $id) | .key.id')" "${key1_system_id}" assert_equal "$(echo "$output" | jq -r --arg id "${key1_system_id}" '.[] | select(.key.id == $id) | .key.key_id')" "${KEY_ID_LIST_1}" - assert_equal "$(echo "$output" | jq -r --arg id "${key1_system_id}" '.[] | select(.key.id == $id) | .key.key_algorithmorithm')" "1" + assert_equal "$(echo "$output" | jq -r --arg id "${key1_system_id}" '.[] | select(.key.id == $id) | .key.key_algorithm')" "1" assert_equal "$(echo "$output" | jq -r --arg id "${key1_system_id}" '.[] | select(.key.id == $id) | .key.key_mode')" "4" assert_equal "$(echo "$output" | jq -r --arg id "${key1_system_id}" '.[] | select(.key.id == $id) | .key.key_status')" "1" assert_equal "$(echo "$output" | jq -r --arg id "${key1_system_id}" '.[] | select(.key.id == $id) | .key.public_key_ctx.pem')" "${PEM_B64}" @@ -542,7 +542,7 @@ format_kas_name_as_uri() { # For key2: assert_equal "$(echo "$output" | jq -r --arg id "${key2_system_id}" '.[] | select(.key.id == $id) | .key.id')" "${key2_system_id}" assert_equal "$(echo "$output" | jq -r --arg id "${key2_system_id}" '.[] | select(.key.id == $id) | .key.key_id')" "${KEY_ID_LIST_2}" - assert_equal "$(echo "$output" | jq -r --arg id "${key2_system_id}" '.[] | select(.key.id == $id) | .key.key_algorithmorithm')" "3" + assert_equal "$(echo "$output" | jq -r --arg id "${key2_system_id}" '.[] | select(.key.id == $id) | .key.key_algorithm')" "3" assert_equal "$(echo "$output" | jq -r --arg id "${key2_system_id}" '.[] | select(.key.id == $id) | .key.key_mode')" "4" assert_equal "$(echo "$output" | jq -r --arg id "${key2_system_id}" '.[] | select(.key.id == $id) | .key.key_status')" "1" assert_equal "$(echo "$output" | jq -r --arg id "${key2_system_id}" '.[] | select(.key.id == $id) | .key.public_key_ctx.pem')" "${PEM_B64}" @@ -624,7 +624,7 @@ format_kas_name_as_uri() { # And our specific RSA key should be present assert_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.id')" "${rsa_key_sys_id}" assert_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.key_id')" "${KEY_ID_LIST_RSA}" - assert_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.key_algorithmorithm')" "1" + assert_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.key_algorithm')" "1" assert_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.key_mode')" "4" assert_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.key_status')" "1" assert_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.public_key_ctx.pem')" "${PEM_B64}" @@ -632,8 +632,8 @@ format_kas_name_as_uri() { assert_not_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.metadata.created_at')" "null" assert_not_equal "$(echo "$output" | jq -r --arg id "${rsa_key_sys_id}" '.[] | select(.key.id == $id) | .key.metadata.updated_at')" "null" - # Check that all listed keys have key_algorithmorithm 1 (algorithmORITHM_RSA_2048) - local count_non_rsa=$(echo "$output" | jq '[.[] | select(.key.key_algorithmorithm != 1)] | length') + # Check that all listed keys have key_algorithm 1 (algorithmORITHM_RSA_2048) + local count_non_rsa=$(echo "$output" | jq '[.[] | select(.key.key_algorithm != 1)] | length') assert_equal "$count_non_rsa" "0" } @@ -654,7 +654,7 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r '.[0].kas_id')" "${KAS_ID_LIST}" assert_equal "$(echo "$output" | jq -r '.[0].key.id')" "${kas_filter_key_sys_id}" assert_equal "$(echo "$output" | jq -r '.[0].key.key_id')" "${KEY_ID_LIST_KAS_FILTER}" - assert_equal "$(echo "$output" | jq -r '.[0].key.key_algorithmorithm')" "1" + assert_equal "$(echo "$output" | jq -r '.[0].key.key_algorithm')" "1" assert_equal "$(echo "$output" | jq -r '.[0].key.key_mode')" "4" assert_equal "$(echo "$output" | jq -r '.[0].key.key_status')" "1" assert_equal "$(echo "$output" | jq -r '.[0].key.public_key_ctx.pem')" "${PEM_B64}" @@ -687,7 +687,7 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r '.[0].kas_id')" "${KAS_ID_LIST}" assert_equal "$(echo "$output" | jq -r '.[0].key.id')" "${kas_name_filter_key_sys_id}" assert_equal "$(echo "$output" | jq -r '.[0].key.key_id')" "${KEY_ID_LIST_KAS_NAME_FILTER}" - assert_equal "$(echo "$output" | jq -r '.[0].key.key_algorithmorithm')" "1" + assert_equal "$(echo "$output" | jq -r '.[0].key.key_algorithm')" "1" assert_equal "$(echo "$output" | jq -r '.[0].key.key_mode')" "4" assert_equal "$(echo "$output" | jq -r '.[0].key.key_status')" "1" assert_equal "$(echo "$output" | jq -r '.[0].key.public_key_ctx.pem')" "${PEM_B64}" @@ -713,7 +713,7 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r '.[0].kas_id')" "${KAS_ID_LIST}" assert_equal "$(echo "$output" | jq -r '.[0].key.id')" "${kas_uri_filter_key_sys_id}" assert_equal "$(echo "$output" | jq -r '.[0].key.key_id')" "${KEY_ID_LIST_KAS_URI_FILTER}" - assert_equal "$(echo "$output" | jq -r '.[0].key.key_algorithmorithm')" "1" + assert_equal "$(echo "$output" | jq -r '.[0].key.key_algorithm')" "1" assert_equal "$(echo "$output" | jq -r '.[0].key.key_mode')" "4" assert_equal "$(echo "$output" | jq -r '.[0].key.key_status')" "1" assert_equal "$(echo "$output" | jq -r '.[0].key.public_key_ctx.pem')" "${PEM_B64}" From 764a1d2eb0038f03f69e2403351d5bbe48e38f50 Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 08:59:19 -0400 Subject: [PATCH 05/27] fix lint issues --- cmd/base-keys.go | 2 +- cmd/kas-keys.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/base-keys.go b/cmd/base-keys.go index 937a8591..c021425f 100644 --- a/cmd/base-keys.go +++ b/cmd/base-keys.go @@ -47,7 +47,7 @@ func getKasKeyIdentifier(c *cli.Cli) (*kasregistry.KasKeyIdentifier, error) { } kasInputType := utils.ClassifyString(kasIdentifierInput) - switch kasInputType { + switch kasInputType { // nolint:exhaustive // default catches unknown case utils.StringTypeUUID: identifier.Identifier = &kasregistry.KasKeyIdentifier_KasId{KasId: kasIdentifierInput} case utils.StringTypeURI: diff --git a/cmd/kas-keys.go b/cmd/kas-keys.go index 75aac5bc..47373cb7 100644 --- a/cmd/kas-keys.go +++ b/cmd/kas-keys.go @@ -249,7 +249,7 @@ func policyCreateKasKey(cmd *cobra.Command, args []string) { kasIdentifier := c.Flags.GetRequiredString("kas") metadataLabels = c.Flags.GetStringSlice("label", metadataLabels, cli.FlagsStringSliceOptions{Min: 0}) -alg, err := algToEnum(c.Flags.GetRequiredString("algorithm")) + alg, err := algToEnum(c.Flags.GetRequiredString("algorithm")) if err != nil { cli.ExitWithError("Invalid algorithm", err) } @@ -316,7 +316,7 @@ alg, err := algToEnum(c.Flags.GetRequiredString("algorithm")) } case policy.KeyMode_KEY_MODE_REMOTE: pem := c.Flags.GetRequiredString("public-key-pem") -providerConfigID = c.Flags.GetRequiredString("provider-config-id") + providerConfigID = c.Flags.GetRequiredString("provider-config-id") _, err = base64.StdEncoding.DecodeString(pem) if err != nil { @@ -529,7 +529,7 @@ func resolveKasIdentifier(ctx context.Context, ident string, h handlers.Handler) kasLookup := handlers.KasIdentifier{} kasInputType := utils.ClassifyString(ident) - switch kasInputType { + switch kasInputType { // nolint:exhaustive // default catches unknown case utils.StringTypeUUID: return ident, nil case utils.StringTypeURI: From cde52e52f55d44b001f9249d0ab511002b660598 Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 09:16:02 -0400 Subject: [PATCH 06/27] fix lint issue --- cmd/base-keys.go | 2 +- cmd/kas-keys.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/base-keys.go b/cmd/base-keys.go index c021425f..db320090 100644 --- a/cmd/base-keys.go +++ b/cmd/base-keys.go @@ -47,7 +47,7 @@ func getKasKeyIdentifier(c *cli.Cli) (*kasregistry.KasKeyIdentifier, error) { } kasInputType := utils.ClassifyString(kasIdentifierInput) - switch kasInputType { // nolint:exhaustive // default catches unknown + switch kasInputType { //nolint:exhaustive // default catches unknown case utils.StringTypeUUID: identifier.Identifier = &kasregistry.KasKeyIdentifier_KasId{KasId: kasIdentifierInput} case utils.StringTypeURI: diff --git a/cmd/kas-keys.go b/cmd/kas-keys.go index 47373cb7..f6915c4d 100644 --- a/cmd/kas-keys.go +++ b/cmd/kas-keys.go @@ -529,7 +529,7 @@ func resolveKasIdentifier(ctx context.Context, ident string, h handlers.Handler) kasLookup := handlers.KasIdentifier{} kasInputType := utils.ClassifyString(ident) - switch kasInputType { // nolint:exhaustive // default catches unknown + switch kasInputType { //nolint:exhaustive // default catches unknown case utils.StringTypeUUID: return ident, nil case utils.StringTypeURI: From 3c02dce2f1069156d14ea30ce2269ef1d3eb52d9 Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 09:37:12 -0400 Subject: [PATCH 07/27] fix base-key flags --- cmd/base-keys.go | 4 +--- pkg/handlers/base-keys.go | 17 ++++------------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/cmd/base-keys.go b/cmd/base-keys.go index db320090..805834db 100644 --- a/cmd/base-keys.go +++ b/cmd/base-keys.go @@ -115,13 +115,11 @@ func setBaseKey(cmd *cobra.Command, args []string) { h := NewHandler(c) defer h.Close() - id := c.Flags.GetOptionalID("id") - identifier, err := getKasKeyIdentifier(c) if err != nil { c.ExitWithError("Invalid key identifier", err) } - baseKey, err := h.SetBaseKey(c.Context(), id, identifier) + baseKey, err := h.SetBaseKey(c.Context(), identifier) if err != nil { cli.ExitWithError("Failed to set base key", err) } diff --git a/pkg/handlers/base-keys.go b/pkg/handlers/base-keys.go index 86f75c29..7db74a64 100644 --- a/pkg/handlers/base-keys.go +++ b/pkg/handlers/base-keys.go @@ -2,7 +2,6 @@ package handlers import ( "context" - "errors" "github.com/opentdf/platform/protocol/go/policy/kasregistry" ) @@ -18,19 +17,11 @@ func (h Handler) GetBaseKey(ctx context.Context) (*kasregistry.SimpleKasKey, err return resp.GetBaseKey(), nil } -func (h Handler) SetBaseKey(ctx context.Context, id string, key *kasregistry.KasKeyIdentifier) (*kasregistry.SetBaseKeyResponse, error) { +func (h Handler) SetBaseKey(ctx context.Context, key *kasregistry.KasKeyIdentifier) (*kasregistry.SetBaseKeyResponse, error) { req := kasregistry.SetBaseKeyRequest{} - switch { - case id != "": - req.ActiveKey = &kasregistry.SetBaseKeyRequest_Id{ - Id: id, - } - case key != nil: - req.ActiveKey = &kasregistry.SetBaseKeyRequest_Key{ - Key: key, - } - default: - return nil, errors.New("id or key must be provided") + + req.ActiveKey = &kasregistry.SetBaseKeyRequest_Key{ + Key: key, } return h.sdk.KeyAccessServerRegistry.SetBaseKey(ctx, &req) From cbb8015910f619a7d33d0752ea0d084d0106a172 Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 09:53:25 -0400 Subject: [PATCH 08/27] fix flags --- cmd/base-keys.go | 37 ++---- cmd/kas-keys.go | 145 ++++++++--------------- docs/man/policy/kas-registry/key/list.md | 2 +- 3 files changed, 57 insertions(+), 127 deletions(-) diff --git a/cmd/base-keys.go b/cmd/base-keys.go index 805834db..597b203b 100644 --- a/cmd/base-keys.go +++ b/cmd/base-keys.go @@ -152,38 +152,17 @@ func init() { man.WithRun(setBaseKey), ) setDoc.Flags().StringP( - setDoc.GetDocFlag("id").Name, - setDoc.GetDocFlag("id").Shorthand, - setDoc.GetDocFlag("id").Default, - setDoc.GetDocFlag("id").Description, + setDoc.GetDocFlag("key").Name, + setDoc.GetDocFlag("key").Shorthand, + setDoc.GetDocFlag("key").Default, + setDoc.GetDocFlag("key").Description, ) setDoc.Flags().StringP( - setDoc.GetDocFlag("keyId").Name, - setDoc.GetDocFlag("keyId").Shorthand, - setDoc.GetDocFlag("keyId").Default, - setDoc.GetDocFlag("keyId").Description, + setDoc.GetDocFlag("kas").Name, + setDoc.GetDocFlag("kas").Shorthand, + setDoc.GetDocFlag("kas").Default, + setDoc.GetDocFlag("kas").Description, ) - setDoc.Flags().StringP( - setDoc.GetDocFlag("kasUri").Name, - setDoc.GetDocFlag("kasUri").Shorthand, - setDoc.GetDocFlag("kasUri").Default, - setDoc.GetDocFlag("kasUri").Description, - ) - setDoc.Flags().StringP( - setDoc.GetDocFlag("kasId").Name, - setDoc.GetDocFlag("kasId").Shorthand, - setDoc.GetDocFlag("kasId").Default, - setDoc.GetDocFlag("kasId").Description, - ) - setDoc.Flags().StringP( - setDoc.GetDocFlag("kasName").Name, - setDoc.GetDocFlag("kasName").Shorthand, - setDoc.GetDocFlag("kasName").Default, - setDoc.GetDocFlag("kasName").Description, - ) - setDoc.MarkFlagsMutuallyExclusive("id", "keyId") - setDoc.MarkFlagsOneRequired("id", "keyId") - setDoc.MarkFlagsMutuallyExclusive("kasUri", "kasId", "kasName") doc := man.Docs.GetCommand("policy/kas-registry/key/base", man.WithSubcommands(getDoc, setDoc)) diff --git a/cmd/kas-keys.go b/cmd/kas-keys.go index f6915c4d..40aa8b00 100644 --- a/cmd/kas-keys.go +++ b/cmd/kas-keys.go @@ -556,16 +556,16 @@ func init() { man.WithRun(policyCreateKasKey), ) createDoc.Flags().StringP( - createDoc.GetDocFlag("keyId").Name, - createDoc.GetDocFlag("keyId").Shorthand, - createDoc.GetDocFlag("keyId").Default, - createDoc.GetDocFlag("keyId").Description, + createDoc.GetDocFlag("key-id").Name, + createDoc.GetDocFlag("key-id").Shorthand, + createDoc.GetDocFlag("key-id").Default, + createDoc.GetDocFlag("key-id").Description, ) createDoc.Flags().StringP( - createDoc.GetDocFlag("alg").Name, - createDoc.GetDocFlag("alg").Shorthand, - createDoc.GetDocFlag("alg").Default, - createDoc.GetDocFlag("alg").Description, + createDoc.GetDocFlag("algorithm").Name, + createDoc.GetDocFlag("algorithm").Shorthand, + createDoc.GetDocFlag("algorithm").Default, + createDoc.GetDocFlag("algorithm").Description, ) createDoc.Flags().StringP( createDoc.GetDocFlag("mode").Name, @@ -574,55 +574,41 @@ func init() { createDoc.GetDocFlag("mode").Description, ) createDoc.Flags().StringP( - createDoc.GetDocFlag("kasId").Name, - createDoc.GetDocFlag("kasId").Shorthand, - createDoc.GetDocFlag("kasId").Default, - createDoc.GetDocFlag("kasId").Description, + createDoc.GetDocFlag("kas").Name, + createDoc.GetDocFlag("kas").Shorthand, + createDoc.GetDocFlag("kas").Default, + createDoc.GetDocFlag("kas").Description, ) createDoc.Flags().StringP( - createDoc.GetDocFlag("kasUri").Name, - createDoc.GetDocFlag("kasUri").Shorthand, - createDoc.GetDocFlag("kasUri").Default, - createDoc.GetDocFlag("kasUri").Description, + createDoc.GetDocFlag("wrapping-key-id").Name, + createDoc.GetDocFlag("wrapping-key-id").Shorthand, + createDoc.GetDocFlag("wrapping-key-id").Default, + createDoc.GetDocFlag("wrapping-key-id").Description, ) createDoc.Flags().StringP( - createDoc.GetDocFlag("kasName").Name, - createDoc.GetDocFlag("kasName").Shorthand, - createDoc.GetDocFlag("kasName").Default, - createDoc.GetDocFlag("kasName").Description, + createDoc.GetDocFlag("wrapping-key").Name, + createDoc.GetDocFlag("wrapping-key").Shorthand, + createDoc.GetDocFlag("wrapping-key").Default, + createDoc.GetDocFlag("wrapping-key").Description, ) createDoc.Flags().StringP( - createDoc.GetDocFlag("wrappingKeyId").Name, - createDoc.GetDocFlag("wrappingKeyId").Shorthand, - createDoc.GetDocFlag("wrappingKeyId").Default, - createDoc.GetDocFlag("wrappingKeyId").Description, + createDoc.GetDocFlag("provider-config-id").Name, + createDoc.GetDocFlag("provider-config-id").Shorthand, + createDoc.GetDocFlag("provider-config-id").Default, + createDoc.GetDocFlag("provider-config-id").Description, ) createDoc.Flags().StringP( - createDoc.GetDocFlag("wrappingKey").Name, - createDoc.GetDocFlag("wrappingKey").Shorthand, - createDoc.GetDocFlag("wrappingKey").Default, - createDoc.GetDocFlag("wrappingKey").Description, + createDoc.GetDocFlag("public-key-pem").Name, + createDoc.GetDocFlag("public-key-pem").Shorthand, + createDoc.GetDocFlag("public-key-pem").Default, + createDoc.GetDocFlag("public-key-pem").Description, ) createDoc.Flags().StringP( - createDoc.GetDocFlag("providerConfigId").Name, - createDoc.GetDocFlag("providerConfigId").Shorthand, - createDoc.GetDocFlag("providerConfigId").Default, - createDoc.GetDocFlag("providerConfigId").Description, + createDoc.GetDocFlag("private-key-pem").Name, + createDoc.GetDocFlag("private-key-pem").Shorthand, + createDoc.GetDocFlag("private-key-pem").Default, + createDoc.GetDocFlag("private-key-pem").Description, ) - createDoc.Flags().StringP( - createDoc.GetDocFlag("pubPem").Name, - createDoc.GetDocFlag("pubPem").Shorthand, - createDoc.GetDocFlag("pubPem").Default, - createDoc.GetDocFlag("pubPem").Description, - ) - createDoc.Flags().StringP( - createDoc.GetDocFlag("privatePem").Name, - createDoc.GetDocFlag("privatePem").Shorthand, - createDoc.GetDocFlag("privatePem").Default, - createDoc.GetDocFlag("privatePem").Description, - ) - createDoc.MarkFlagsOneRequired("kasId", "kasUri", "kasName") - createDoc.MarkFlagsMutuallyExclusive("kasId", "kasUri", "kasName") injectLabelFlags(&createDoc.Command, false) // Get Kas Key @@ -630,39 +616,17 @@ func init() { man.WithRun(policyGetKasKey), ) getDoc.Flags().StringP( - getDoc.GetDocFlag("id").Name, - getDoc.GetDocFlag("id").Shorthand, - getDoc.GetDocFlag("id").Default, - getDoc.GetDocFlag("id").Description, - ) - getDoc.Flags().StringP( - getDoc.GetDocFlag("keyId").Name, - getDoc.GetDocFlag("keyId").Shorthand, - getDoc.GetDocFlag("keyId").Default, - getDoc.GetDocFlag("keyId").Description, - ) - getDoc.Flags().StringP( - getDoc.GetDocFlag("kasUri").Name, - getDoc.GetDocFlag("kasUri").Shorthand, - getDoc.GetDocFlag("kasUri").Default, - getDoc.GetDocFlag("kasUri").Description, + getDoc.GetDocFlag("key").Name, + getDoc.GetDocFlag("key").Shorthand, + getDoc.GetDocFlag("key").Default, + getDoc.GetDocFlag("key").Description, ) getDoc.Flags().StringP( - getDoc.GetDocFlag("kasId").Name, - getDoc.GetDocFlag("kasId").Shorthand, - getDoc.GetDocFlag("kasId").Default, - getDoc.GetDocFlag("kasId").Description, + getDoc.GetDocFlag("kas").Name, + getDoc.GetDocFlag("kas").Shorthand, + getDoc.GetDocFlag("kas").Default, + getDoc.GetDocFlag("kas").Description, ) - getDoc.Flags().StringP( - getDoc.GetDocFlag("kasName").Name, - getDoc.GetDocFlag("kasName").Shorthand, - getDoc.GetDocFlag("kasName").Default, - getDoc.GetDocFlag("kasName").Description, - ) - getDoc.MarkFlagsMutuallyExclusive("id", "keyId") - getDoc.MarkFlagsOneRequired("id", "keyId") - getDoc.MarkFlagsMutuallyExclusive("kasUri", "kasId", "kasName") - // Update Kas Key updateDoc := man.Docs.GetCommand("policy/kas-registry/key/update", man.WithRun(policyUpdateKasKey), @@ -680,31 +644,18 @@ func init() { man.WithRun(policyListKasKeys), ) listDoc.Flags().StringP( - listDoc.GetDocFlag("alg").Name, - listDoc.GetDocFlag("alg").Shorthand, - listDoc.GetDocFlag("alg").Default, - listDoc.GetDocFlag("alg").Description, - ) - listDoc.Flags().StringP( - listDoc.GetDocFlag("kasId").Name, - listDoc.GetDocFlag("kasId").Shorthand, - listDoc.GetDocFlag("kasId").Default, - listDoc.GetDocFlag("kasId").Description, - ) - listDoc.Flags().StringP( - listDoc.GetDocFlag("kasName").Name, - listDoc.GetDocFlag("kasName").Shorthand, - listDoc.GetDocFlag("kasName").Default, - listDoc.GetDocFlag("kasName").Description, + listDoc.GetDocFlag("algorithm").Name, + listDoc.GetDocFlag("algorithm").Shorthand, + listDoc.GetDocFlag("algorithm").Default, + listDoc.GetDocFlag("algorithm").Description, ) listDoc.Flags().StringP( - listDoc.GetDocFlag("kasUri").Name, - listDoc.GetDocFlag("kasUri").Shorthand, - listDoc.GetDocFlag("kasUri").Default, - listDoc.GetDocFlag("kasUri").Description, + listDoc.GetDocFlag("kas").Name, + listDoc.GetDocFlag("kas").Shorthand, + listDoc.GetDocFlag("kas").Default, + listDoc.GetDocFlag("kas").Description, ) injectListPaginationFlags(listDoc) - listDoc.MarkFlagsMutuallyExclusive("kasId", "kasName", "kasUri") policyKasRegistryKeysCmd.AddSubcommands(createDoc, getDoc, updateDoc, listDoc) policyKasRegCmd.AddCommand(&policyKasRegistryKeysCmd.Command) diff --git a/docs/man/policy/kas-registry/key/list.md b/docs/man/policy/kas-registry/key/list.md index 773fcb62..1baef4fb 100644 --- a/docs/man/policy/kas-registry/key/list.md +++ b/docs/man/policy/kas-registry/key/list.md @@ -13,7 +13,7 @@ command: shorthand: o description: Number of keys to skip before starting to return results required: true - - name: alg + - name: algorithm shorthand: a description: Key Algorithm to filter for - name: kas From 0c9bec99980bcf92c6bacbbbc0106a503fbbcdbf Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 10:28:16 -0400 Subject: [PATCH 09/27] fix duplicate kas name --- e2e/kas-keys.bats | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/e2e/kas-keys.bats b/e2e/kas-keys.bats index 9ac7978f..7a1e9f57 100644 --- a/e2e/kas-keys.bats +++ b/e2e/kas-keys.bats @@ -270,7 +270,7 @@ format_kas_name_as_uri() { assert_output --partial "Error: at least one of the flags in the group [kas kas kas] is required" } -@test "kas-keys: create key (using kas)" { +@test "kas-keys: create key (using kasName)" { KEY_ID=$(generate_key_id) run_otdfctl_key create --kas "${KAS_NAME}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success @@ -285,7 +285,7 @@ format_kas_name_as_uri() { assert_not_equal "$(echo "$output" | jq -r .key.metadata.updated_at)" "null" } -@test "kas-keys: create key (using kas)" { +@test "kas-keys: create key (using kasUri)" { KEY_ID=$(generate_key_id) run_otdfctl_key create --kas "${KAS_URI}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success @@ -341,7 +341,7 @@ format_kas_name_as_uri() { assert_not_equal "$(echo "$output" | jq -r .key.metadata.updated_at)" "null" } -@test "kas-keys: get key by user key-id and kas" { +@test "kas-keys: get key by user key-id and kasId" { KEY_ID_GET_USER=$(generate_key_id) # Using ec:secp256r1 and public_key mode for variety run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID_GET_USER}" --algorithm "ec:secp256r1" --mode "public_key" --public-key-pem "${PEM_B64}" --json @@ -362,7 +362,7 @@ format_kas_name_as_uri() { assert_not_equal "$(echo "$output" | jq -r .key.metadata.updated_at)" "null" } -@test "kas-keys: get key by user key-id and kas" { +@test "kas-keys: get key by user key-id and kasName" { KEY_ID_GET_USER_kas=$(generate_key_id) run_otdfctl_key create --kas "kas-registry-for-keys-test" --key-id "${KEY_ID_GET_USER_kas}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success @@ -382,7 +382,7 @@ format_kas_name_as_uri() { assert_not_equal "$(echo "$output" | jq -r .key.metadata.updated_at)" "null" } -@test "kas-keys: get key by user key-id and kas" { +@test "kas-keys: get key by user key-id and kasUri" { KEY_ID_GET_USER_kas=$(generate_key_id) run_otdfctl_key create --kas "${KAS_URI}" --key-id "${KEY_ID_GET_USER_kas}" --algorithm "ec:secp256r1" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success @@ -669,7 +669,7 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r --arg id "${kas_filter_key_sys_id}" '[.[] | select(.key.id == $id)] | length')" "0" } -@test "kas-keys: list keys (filter by kas)" { +@test "kas-keys: list keys (filter by kasName)" { KAS_NAME_LIST=$(generate_kas_name) echo "DEBUG: KAS_NAME_LIST: ${KAS_NAME_LIST}" >&2 KAS_URI_LIST=$(format_kas_name_as_uri "${KAS_NAME_LIST}") @@ -696,7 +696,7 @@ format_kas_name_as_uri() { assert_not_equal "$(echo "$output" | jq -r '.[0].key.metadata.updated_at')" "null" } -@test "kas-keys: list keys (filter by kas)" { +@test "kas-keys: list keys (filter by kasUri)" { # This command is not a 'kas-registry key' subcommand, so it won't use run_otdfctl_key KAS_NAME_LIST=$(generate_kas_name) KAS_URI_LIST=$(format_kas_name_as_uri "${KAS_NAME_LIST}") From 8f4d1781158132e4a7b19f976232f5fa67543631 Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 11:15:32 -0400 Subject: [PATCH 10/27] fix assign command flags --- cmd/policy-attributeNamespaces.go | 20 +++++++++---------- cmd/policy-attributeValues.go | 20 +++++++++---------- cmd/policy-attributes.go | 20 +++++++++---------- docs/man/policy/attributes/key/_index.md | 2 +- docs/man/policy/attributes/key/assign.md | 6 +++--- .../attributes/namespaces/key/_index.md | 2 +- .../attributes/namespaces/key/assign.md | 6 +++--- .../attributes/namespaces/key/remove.md | 6 +++--- .../policy/attributes/values/key/_index.md | 2 +- .../policy/attributes/values/key/assign.md | 6 +++--- .../policy/attributes/values/key/remove.md | 6 +++--- 11 files changed, 48 insertions(+), 48 deletions(-) diff --git a/cmd/policy-attributeNamespaces.go b/cmd/policy-attributeNamespaces.go index 5ebdba72..3bfafa26 100644 --- a/cmd/policy-attributeNamespaces.go +++ b/cmd/policy-attributeNamespaces.go @@ -285,7 +285,7 @@ func policyAssignKeyToNamespace(cmd *cobra.Command, args []string) { defer h.Close() namespace := c.Flags.GetRequiredString("namespace") - keyID := c.Flags.GetRequiredID("keyId") + keyID := c.Flags.GetRequiredID("key-id") // Get the attribute namespace to show meaningful information in case of error attrKey, err := h.AssignKeyToAttributeNamespace(c.Context(), namespace, keyID) @@ -309,7 +309,7 @@ func policyRemoveKeyFromNamespace(cmd *cobra.Command, args []string) { defer h.Close() namespace := c.Flags.GetRequiredString("namespace") - keyID := c.Flags.GetRequiredID("keyId") + keyID := c.Flags.GetRequiredID("key-id") err := h.RemoveKeyFromAttributeNamespace(c.Context(), namespace, keyID) if err != nil { @@ -441,10 +441,10 @@ func init() { assignKasKeyCmd.GetDocFlag("namespace").Description, ) assignKasKeyCmd.Flags().StringP( - assignKasKeyCmd.GetDocFlag("keyId").Name, - assignKasKeyCmd.GetDocFlag("keyId").Shorthand, - assignKasKeyCmd.GetDocFlag("keyId").Default, - assignKasKeyCmd.GetDocFlag("keyId").Description, + assignKasKeyCmd.GetDocFlag("key-id").Name, + assignKasKeyCmd.GetDocFlag("key-id").Shorthand, + assignKasKeyCmd.GetDocFlag("key-id").Default, + assignKasKeyCmd.GetDocFlag("key-id").Description, ) // Remove KAS key from attribute namespace @@ -458,10 +458,10 @@ func init() { removeKasKeyCmd.GetDocFlag("namespace").Description, ) removeKasKeyCmd.Flags().StringP( - removeKasKeyCmd.GetDocFlag("keyId").Name, - removeKasKeyCmd.GetDocFlag("keyId").Shorthand, - removeKasKeyCmd.GetDocFlag("keyId").Default, - removeKasKeyCmd.GetDocFlag("keyId").Description, + removeKasKeyCmd.GetDocFlag("key-id").Name, + removeKasKeyCmd.GetDocFlag("key-id").Shorthand, + removeKasKeyCmd.GetDocFlag("key-id").Default, + removeKasKeyCmd.GetDocFlag("key-id").Description, ) keyCmd.AddSubcommands(assignKasKeyCmd, removeKasKeyCmd) diff --git a/cmd/policy-attributeValues.go b/cmd/policy-attributeValues.go index 411da3d1..c24dfcc7 100644 --- a/cmd/policy-attributeValues.go +++ b/cmd/policy-attributeValues.go @@ -238,7 +238,7 @@ func policyAssignKeyToAttrValue(cmd *cobra.Command, args []string) { defer h.Close() value := c.Flags.GetRequiredString("value") - keyID := c.Flags.GetRequiredID("keyId") + keyID := c.Flags.GetRequiredID("key-id") attrKey, err := h.AssignKeyToAttributeValue(c.Context(), value, keyID) if err != nil { @@ -260,7 +260,7 @@ func policyRemoveKeyFromAttrValue(cmd *cobra.Command, args []string) { defer h.Close() value := c.Flags.GetRequiredString("value") - keyID := c.Flags.GetRequiredID("keyId") + keyID := c.Flags.GetRequiredID("key-id") err := h.RemoveKeyFromAttributeValue(c.Context(), value, keyID) if err != nil { @@ -355,10 +355,10 @@ func init() { assignKasKeyCmd.GetDocFlag("value").Description, ) assignKasKeyCmd.Flags().StringP( - assignKasKeyCmd.GetDocFlag("keyId").Name, - assignKasKeyCmd.GetDocFlag("keyId").Shorthand, - assignKasKeyCmd.GetDocFlag("keyId").Default, - assignKasKeyCmd.GetDocFlag("keyId").Description, + assignKasKeyCmd.GetDocFlag("key-id").Name, + assignKasKeyCmd.GetDocFlag("key-id").Shorthand, + assignKasKeyCmd.GetDocFlag("key-id").Default, + assignKasKeyCmd.GetDocFlag("key-id").Description, ) removeKasKeyCmd := man.Docs.GetCommand("policy/attributes/values/key/remove", @@ -371,10 +371,10 @@ func init() { removeKasKeyCmd.GetDocFlag("value").Description, ) removeKasKeyCmd.Flags().StringP( - removeKasKeyCmd.GetDocFlag("keyId").Name, - removeKasKeyCmd.GetDocFlag("keyId").Shorthand, - removeKasKeyCmd.GetDocFlag("keyId").Default, - removeKasKeyCmd.GetDocFlag("keyId").Description, + removeKasKeyCmd.GetDocFlag("key-id").Name, + removeKasKeyCmd.GetDocFlag("key-id").Shorthand, + removeKasKeyCmd.GetDocFlag("key-id").Default, + removeKasKeyCmd.GetDocFlag("key-id").Description, ) unsafeReactivateCmd := man.Docs.GetCommand("policy/attributes/values/unsafe/reactivate", diff --git a/cmd/policy-attributes.go b/cmd/policy-attributes.go index e86e5ce1..68c12ccf 100644 --- a/cmd/policy-attributes.go +++ b/cmd/policy-attributes.go @@ -311,7 +311,7 @@ func policyAssignKeyToAttribute(cmd *cobra.Command, args []string) { defer h.Close() attribute := c.Flags.GetRequiredString("attribute") - keyID := c.Flags.GetRequiredID("keyId") + keyID := c.Flags.GetRequiredID("key-id") // Get the attribute to show meaningful information in case of error attrKey, err := h.AssignKeyToAttribute(c.Context(), attribute, keyID) @@ -335,7 +335,7 @@ func policyRemoveKeyFromAttribute(cmd *cobra.Command, args []string) { defer h.Close() attribute := c.Flags.GetRequiredString("attribute") - keyID := c.Flags.GetRequiredID("keyId") + keyID := c.Flags.GetRequiredID("key-id") err := h.RemoveKeyFromAttribute(c.Context(), attribute, keyID) if err != nil { @@ -504,10 +504,10 @@ func init() { assignKasKeyCmd.GetDocFlag("attribute").Description, ) assignKasKeyCmd.Flags().StringP( - assignKasKeyCmd.GetDocFlag("keyId").Name, - assignKasKeyCmd.GetDocFlag("keyId").Shorthand, - assignKasKeyCmd.GetDocFlag("keyId").Default, - assignKasKeyCmd.GetDocFlag("keyId").Description, + assignKasKeyCmd.GetDocFlag("key-id").Name, + assignKasKeyCmd.GetDocFlag("key-id").Shorthand, + assignKasKeyCmd.GetDocFlag("key-id").Default, + assignKasKeyCmd.GetDocFlag("key-id").Description, ) removeKasKeyCmd := man.Docs.GetCommand("policy/attributes/key/remove", @@ -520,10 +520,10 @@ func init() { removeKasKeyCmd.GetDocFlag("attribute").Description, ) removeKasKeyCmd.Flags().StringP( - removeKasKeyCmd.GetDocFlag("keyId").Name, - removeKasKeyCmd.GetDocFlag("keyId").Shorthand, - removeKasKeyCmd.GetDocFlag("keyId").Default, - removeKasKeyCmd.GetDocFlag("keyId").Description, + removeKasKeyCmd.GetDocFlag("key-id").Name, + removeKasKeyCmd.GetDocFlag("key-id").Shorthand, + removeKasKeyCmd.GetDocFlag("key-id").Default, + removeKasKeyCmd.GetDocFlag("key-id").Description, ) keyCmd.AddSubcommands(assignKasKeyCmd, removeKasKeyCmd) diff --git a/docs/man/policy/attributes/key/_index.md b/docs/man/policy/attributes/key/_index.md index a01b7661..4d81d13b 100644 --- a/docs/man/policy/attributes/key/_index.md +++ b/docs/man/policy/attributes/key/_index.md @@ -5,4 +5,4 @@ command: name: key --- -Assigns a KAS key to an attribute definition. +Manages KAS key associations for attribute definitions. diff --git a/docs/man/policy/attributes/key/assign.md b/docs/man/policy/attributes/key/assign.md index 2042295b..036df643 100644 --- a/docs/man/policy/attributes/key/assign.md +++ b/docs/man/policy/attributes/key/assign.md @@ -7,7 +7,7 @@ command: shorthand: a description: URI or ID of the attribute definition required: true - - name: keyId + - name: key-id shorthand: k description: ID of the KAS key to assign required: true @@ -18,9 +18,9 @@ Assigns a KAS key to a policy attribute. This enables the attribute to be used w ## Example ```shell -otdfctl policy attributes key assign --attribute 3d25d33e-2469-4990-a9ed-fdd13ce74436 --keyId 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d +otdfctl policy attributes key assign --attribute 3d25d33e-2469-4990-a9ed-fdd13ce74436 --key-id 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d ``` ```shell -otdfctl policy attributes key assign --attribute "https://example.com/attr/example" --keyId 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d +otdfctl policy attributes key assign --attribute "https://example.com/attr/example" --key-id 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d ``` diff --git a/docs/man/policy/attributes/namespaces/key/_index.md b/docs/man/policy/attributes/namespaces/key/_index.md index 07a9c064..868fa998 100644 --- a/docs/man/policy/attributes/namespaces/key/_index.md +++ b/docs/man/policy/attributes/namespaces/key/_index.md @@ -5,4 +5,4 @@ command: name: key --- -Assigns a KAS key to an attribute namespace. +Manages KAS key associations for attribute namespaces. diff --git a/docs/man/policy/attributes/namespaces/key/assign.md b/docs/man/policy/attributes/namespaces/key/assign.md index 93fef9e1..f85f5b96 100644 --- a/docs/man/policy/attributes/namespaces/key/assign.md +++ b/docs/man/policy/attributes/namespaces/key/assign.md @@ -7,7 +7,7 @@ command: shorthand: n description: Can be URI or ID of namespace required: true - - name: keyId + - name: key-id shorthand: k description: ID of the KAS key to assign required: true @@ -18,9 +18,9 @@ Assigns a KAS key to a policy attribute namespace. This enables the attribute na ## Example ```shell -otdfctl policy attributes namespaces assign --namespace 3d25d33e-2469-4990-a9ed-fdd13ce74436 --keyId 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d +otdfctl policy attributes namespaces assign --namespace 3d25d33e-2469-4990-a9ed-fdd13ce74436 --key-id 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d ``` ```shell -otdfctl policy attributes namespaces remove --namespace "https://example.com" --keyId 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d +otdfctl policy attributes namespaces remove --namespace "https://example.com" --key-id 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d ``` diff --git a/docs/man/policy/attributes/namespaces/key/remove.md b/docs/man/policy/attributes/namespaces/key/remove.md index c08dfc34..a58d4eb4 100644 --- a/docs/man/policy/attributes/namespaces/key/remove.md +++ b/docs/man/policy/attributes/namespaces/key/remove.md @@ -7,7 +7,7 @@ command: shorthand: n description: Can be URI or ID of namespace required: true - - name: keyId + - name: key-id shorthand: k description: ID of the KAS key to remove required: true @@ -18,9 +18,9 @@ Removes a KAS key from a policy attribute namespace. After removing the key, the ## Example ```shell -otdfctl policy attributes namespaces remove --namespace 3d25d33e-2469-4990-a9ed-fdd13ce74436 --keyId 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d +otdfctl policy attributes namespaces remove --namespace 3d25d33e-2469-4990-a9ed-fdd13ce74436 --key-id 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d ``` ```shell -otdfctl policy attributes namespaces remove --namespace "https://example.com" --keyId 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d +otdfctl policy attributes namespaces remove --namespace "https://example.com" --key-id 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d ``` diff --git a/docs/man/policy/attributes/values/key/_index.md b/docs/man/policy/attributes/values/key/_index.md index e0e6e912..8bf6144d 100644 --- a/docs/man/policy/attributes/values/key/_index.md +++ b/docs/man/policy/attributes/values/key/_index.md @@ -5,4 +5,4 @@ command: name: key --- -Assigns a KAS key to an attribute value. +Manages KAS key associations for attribute values. diff --git a/docs/man/policy/attributes/values/key/assign.md b/docs/man/policy/attributes/values/key/assign.md index feeb130c..4932f2ea 100644 --- a/docs/man/policy/attributes/values/key/assign.md +++ b/docs/man/policy/attributes/values/key/assign.md @@ -7,7 +7,7 @@ command: shorthand: v description: URI or ID of attribute value required: true - - name: keyId + - name: key-id shorthand: k description: ID of the KAS key to assign required: true @@ -18,9 +18,9 @@ Assigns a KAS key to a policy attribute value. This enables the attribute value ## Example ```shell -otdfctl policy attributes values assign --value 3d25d33e-2469-4990-a9ed-fdd13ce74436 --keyId 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d +otdfctl policy attributes values assign --value 3d25d33e-2469-4990-a9ed-fdd13ce74436 --key-id 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d ``` ```shell -otdfctl policy attributes values assign --value "https://demo.com/attr/example/value/1" --keyId 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d +otdfctl policy attributes values assign --value "https://demo.com/attr/example/value/1" --key-id 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d ``` diff --git a/docs/man/policy/attributes/values/key/remove.md b/docs/man/policy/attributes/values/key/remove.md index 8c567535..995a70ab 100644 --- a/docs/man/policy/attributes/values/key/remove.md +++ b/docs/man/policy/attributes/values/key/remove.md @@ -7,7 +7,7 @@ command: shorthand: v description: URI or ID of attribute value required: true - - name: keyId + - name: key-id shorthand: k description: ID of the KAS key to remove required: true @@ -18,9 +18,9 @@ Removes a KAS key from a policy attribute value. After removing the key, the att ## Example ```shell -otdfctl policy attributes values remove --value 3d25d33e-2469-4990-a9ed-fdd13ce74436 --keyId 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d +otdfctl policy attributes values remove --value 3d25d33e-2469-4990-a9ed-fdd13ce74436 --key-id 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d ``` ```shell -otdfctl policy attributes values remove --value "https://example.com/attr/example/value/1" --keyId 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d +otdfctl policy attributes values remove --value "https://example.com/attr/example/value/1" --key-id 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d ``` From c2aa319f43c2db0925990e1b5293fc1d347ab810 Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 11:43:37 -0400 Subject: [PATCH 11/27] fix assign flag id --- docs/man/policy/attributes/key/remove.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/man/policy/attributes/key/remove.md b/docs/man/policy/attributes/key/remove.md index 613345f9..c79da0d4 100644 --- a/docs/man/policy/attributes/key/remove.md +++ b/docs/man/policy/attributes/key/remove.md @@ -7,7 +7,7 @@ command: shorthand: a description: URI or ID of attribute definition required: true - - name: keyId + - name: key-id shorthand: k description: ID of the KAS key to remove required: true @@ -18,9 +18,9 @@ Removes a KAS key association from a policy attribute. This will prevent the att ## Example ```shell -otdfctl policy attributes key remove --attribute 3d25d33e-2469-4990-a9ed-fdd13ce74436 --keyId 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d +otdfctl policy attributes key remove --attribute 3d25d33e-2469-4990-a9ed-fdd13ce74436 --key-id 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d ``` ```shell -otdfctl policy attributes key remove --attribute "https://example.com/attr/example" --keyId 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d +otdfctl policy attributes key remove --attribute "https://example.com/attr/example" --key-id 8f7e6d5c-4b3a-2d1e-9f8d-7c6b5a432f1d ``` From 77ffaf253a0cf18129b838232a00bb809210cb53 Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 12:05:54 -0400 Subject: [PATCH 12/27] fix bats test for assigning --- e2e/attributes.bats | 344 ++++++++++++++++++++++---------------------- e2e/namespaces.bats | 183 ++++++++++++----------- 2 files changed, 261 insertions(+), 266 deletions(-) diff --git a/e2e/attributes.bats b/e2e/attributes.bats index 70f7fada..9a2faeb3 100755 --- a/e2e/attributes.bats +++ b/e2e/attributes.bats @@ -3,38 +3,38 @@ # Tests for attributes setup_file() { - echo -n '{"clientId":"opentdf","clientSecret":"secret"}' > creds.json - export WITH_CREDS='--with-client-creds-file ./creds.json' - export HOST='--host http://localhost:8080' + echo -n '{"clientId":"opentdf","clientSecret":"secret"}' >creds.json + export WITH_CREDS='--with-client-creds-file ./creds.json' + export HOST='--host http://localhost:8080' - # Create the namespace to be used by other tests + # Create the namespace to be used by other tests - export NS_NAME="testing-attr.co" - export NS_ID=$(./otdfctl $HOST $WITH_CREDS policy attributes namespaces create -n "$NS_NAME" --json | jq -r '.id') + export NS_NAME="testing-attr.co" + export NS_ID=$(./otdfctl $HOST $WITH_CREDS policy attributes namespaces create -n "$NS_NAME" --json | jq -r '.id') - export KAS_URI="https://test-kas-for-attributes.com" - export KAS_REG_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --uri "$KAS_URI" --public-key-remote 'https://test-kas-for-attributes.com/pub_key' --json | jq -r '.id') - export PEM_B64=$(echo "pem" | base64) - export KAS_KEY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kasId "$KAS_REG_ID" --keyId "test-key-for-attr" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json | jq -r '.key.id') + export KAS_URI="https://test-kas-for-attributes.com" + export KAS_REG_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --uri "$KAS_URI" --public-key-remote 'https://test-kas-for-attributes.com/pub_key' --json | jq -r '.id') + export PEM_B64=$(echo "pem" | base64) + export KAS_KEY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kasId "$KAS_REG_ID" --key-id "test-key-for-attr" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json | jq -r '.key.id') } # always create a randomly named attribute setup() { - load "${BATS_LIB_PATH}/bats-support/load.bash" - load "${BATS_LIB_PATH}/bats-assert/load.bash" + load "${BATS_LIB_PATH}/bats-support/load.bash" + load "${BATS_LIB_PATH}/bats-assert/load.bash" - # invoke binary with credentials - run_otdfctl_attr () { - run sh -c "./otdfctl $HOST $WITH_CREDS policy attributes $*" - } + # invoke binary with credentials + run_otdfctl_attr() { + run sh -c "./otdfctl $HOST $WITH_CREDS policy attributes $*" + } - export ATTR_NAME_RANDOM=$(LC_ALL=C tr -dc 'a-zA-Z' < /dev/urandom | head -c 16) - export ATTR_ID=$(./otdfctl $HOST $WITH_CREDS policy attributes create --namespace "$NS_ID" --name "$ATTR_NAME_RANDOM" --rule ANY_OF -l key=value --json | jq -r '.id') + export ATTR_NAME_RANDOM=$(LC_ALL=C tr -dc 'a-zA-Z' creds.json - export WITH_CREDS='--with-client-creds-file ./creds.json' - export HOST='--host http://localhost:8080' + echo -n '{"clientId":"opentdf","clientSecret":"secret"}' >creds.json + export WITH_CREDS='--with-client-creds-file ./creds.json' + export HOST='--host http://localhost:8080' - # Create the namespace to be used by other tests + # Create the namespace to be used by other tests - export NS_NAME="creating-test-ns.net" - export NS_NAME_UPDATE="updated-test-ns.net" - export NS_ID=$(./otdfctl $HOST $WITH_CREDS policy attributes namespaces create -n "$NS_NAME" --json | jq -r '.id') - export NS_ID_FLAG="--id $NS_ID" + export NS_NAME="creating-test-ns.net" + export NS_NAME_UPDATE="updated-test-ns.net" + export NS_ID=$(./otdfctl $HOST $WITH_CREDS policy attributes namespaces create -n "$NS_NAME" --json | jq -r '.id') + export NS_ID_FLAG="--id $NS_ID" - export KAS_URI="https://test-kas-for-namespace.com" - export KAS_REG_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --uri "$KAS_URI" --public-key-remote 'https://test-kas-for-namespace.com/pub_key' --json | jq -r '.id') - export PEM_B64=$(echo "pem" | base64) - export KAS_KEY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kasId "$KAS_REG_ID" --keyId "test-key-for-namespace" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json | jq -r '.key.id') + export KAS_URI="https://test-kas-for-namespace.com" + export KAS_REG_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --uri "$KAS_URI" --public-key-remote 'https://test-kas-for-namespace.com/pub_key' --json | jq -r '.id') + export PEM_B64=$(echo "pem" | base64) + export KAS_KEY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kasId "$KAS_REG_ID" --key-id "test-key-for-namespace" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json | jq -r '.key.id') } setup() { - load "${BATS_LIB_PATH}/bats-support/load.bash" - load "${BATS_LIB_PATH}/bats-assert/load.bash" + load "${BATS_LIB_PATH}/bats-support/load.bash" + load "${BATS_LIB_PATH}/bats-assert/load.bash" - # invoke binary with credentials - run_otdfctl_ns () { - run sh -c "./otdfctl $HOST $WITH_CREDS policy attributes namespaces $*" - } + # invoke binary with credentials + run_otdfctl_ns() { + run sh -c "./otdfctl $HOST $WITH_CREDS policy attributes namespaces $*" + } } teardown_file() { @@ -54,22 +54,22 @@ teardown_file() { @test "Create a namespace - Bad" { # bad namespace names - run_otdfctl_ns create --name no_domain_extension - assert_failure - run_otdfctl_ns create --name -first-char-hyphen.co - assert_failure - run_otdfctl_ns create --name last-char-hyphen-.co - assert_failure + run_otdfctl_ns create --name no_domain_extension + assert_failure + run_otdfctl_ns create --name -first-char-hyphen.co + assert_failure + run_otdfctl_ns create --name last-char-hyphen-.co + assert_failure # missing flag - run_otdfctl_ns create - assert_failure - assert_output --partial "Flag '--name' is required" - + run_otdfctl_ns create + assert_failure + assert_output --partial "Flag '--name' is required" + # conflict - run_otdfctl_ns create -n "$NS_NAME" - assert_failure - assert_output --partial "already_exists" + run_otdfctl_ns create -n "$NS_NAME" + assert_failure + assert_output --partial "already_exists" } @test "Get a namespace - Good" { @@ -99,7 +99,7 @@ teardown_file() { } @test "List namespaces - when active" { - run_otdfctl_ns list --json + run_otdfctl_ns list --json echo $output | jq --arg id "$NS_ID" '.[] | select(.[]? | type == "object" and .id == $id)' run_otdfctl_ns list --state inactive --json @@ -109,7 +109,7 @@ teardown_file() { assert_output --partial "$NS_ID" assert_output --partial "Total" assert_line --regexp "Current Offset.*0" - + } @test "Update namespace - Safe" { @@ -140,76 +140,71 @@ teardown_file() { refute_output --regexp "Name.*$NS_NAME" } - @test "Assign/Remove KAS key from namespace - With Namespace ID" { - run_otdfctl_ns key assign --namespace "$NS_ID" --keyId "$KAS_KEY_ID" --json - assert_success - assert_equal "$(echo "$output" | jq -r '.namespace_id')" "$NS_ID" - assert_equal "$(echo "$output" | jq -r '.key_id')" "$KAS_KEY_ID" + run_otdfctl_ns key assign --namespace "$NS_ID" --key-id "$KAS_KEY_ID" --json + assert_success + assert_equal "$(echo "$output" | jq -r '.namespace_id')" "$NS_ID" + assert_equal "$(echo "$output" | jq -r '.key_id')" "$KAS_KEY_ID" run_otdfctl_ns get --id "$NS_ID" --json - echo "$output" >&2 - assert_success - assert_equal "$(echo "$output" | jq -r '.id')" "$NS_ID" - assert_equal "$(echo "$output" | jq -r '.kas_keys[0].key.id')" "$KAS_KEY_ID" - assert_equal "$(echo "$output" | jq -r '.kas_keys[0].key.private_key_ctx')" "null" - assert_equal "$(echo "$output" | jq -r '.kas_keys[0].key.public_key_ctx.pem')" "${PEM_B64}" - - - run_otdfctl_ns key remove --namespace "$NS_ID" --keyId "$KAS_KEY_ID" --json - assert_success - + echo "$output" >&2 + assert_success + assert_equal "$(echo "$output" | jq -r '.id')" "$NS_ID" + assert_equal "$(echo "$output" | jq -r '.kas_keys[0].key.id')" "$KAS_KEY_ID" + assert_equal "$(echo "$output" | jq -r '.kas_keys[0].key.private_key_ctx')" "null" + assert_equal "$(echo "$output" | jq -r '.kas_keys[0].key.public_key_ctx.pem')" "${PEM_B64}" + + run_otdfctl_ns key remove --namespace "$NS_ID" --key-id "$KAS_KEY_ID" --json + assert_success + run_otdfctl_ns get --id "$NS_ID" --json - assert_success - assert_equal "$(echo "$output" | jq -r '.id')" "$NS_ID" - assert_equal "$(echo "$output" | jq -r '.kas_keys | length')" 0 + assert_success + assert_equal "$(echo "$output" | jq -r '.id')" "$NS_ID" + assert_equal "$(echo "$output" | jq -r '.kas_keys | length')" 0 } @test "Assign/Remove KAS key from namespace - With Namespace FQN" { run_otdfctl_ns get --id "$NS_ID" --json - assert_success - assert_equal "$(echo "$output" | jq -r '.id')" "$NS_ID" - assert_equal "$(echo "$output" | jq -r '.kas_keys | length')" 0 - NS_FQN=$(echo "$output" | jq -r '.fqn') - + assert_success + assert_equal "$(echo "$output" | jq -r '.id')" "$NS_ID" + assert_equal "$(echo "$output" | jq -r '.kas_keys | length')" 0 + NS_FQN=$(echo "$output" | jq -r '.fqn') - run_otdfctl_ns key assign --namespace "$NS_FQN" --keyId "$KAS_KEY_ID" --json - assert_success - assert_equal "$(echo "$output" | jq -r '.namespace_id')" "$NS_ID" - assert_equal "$(echo "$output" | jq -r '.key_id')" "$KAS_KEY_ID" + run_otdfctl_ns key assign --namespace "$NS_FQN" --key-id "$KAS_KEY_ID" --json + assert_success + assert_equal "$(echo "$output" | jq -r '.namespace_id')" "$NS_ID" + assert_equal "$(echo "$output" | jq -r '.key_id')" "$KAS_KEY_ID" run_otdfctl_ns get --id "$NS_ID" --json - assert_success - assert_equal "$(echo "$output" | jq -r '.id')" "$NS_ID" - assert_equal "$(echo "$output" | jq -r '.kas_keys[0].key.id')" "$KAS_KEY_ID" - assert_equal "$(echo "$output" | jq -r '.kas_keys[0].key.private_key_ctx')" "null" - assert_equal "$(echo "$output" | jq -r '.kas_keys[0].key.public_key_ctx.pem')" "${PEM_B64}" - - - run_otdfctl_ns key remove --namespace "$NS_ID" --keyId "$KAS_KEY_ID" --json - assert_success - + assert_success + assert_equal "$(echo "$output" | jq -r '.id')" "$NS_ID" + assert_equal "$(echo "$output" | jq -r '.kas_keys[0].key.id')" "$KAS_KEY_ID" + assert_equal "$(echo "$output" | jq -r '.kas_keys[0].key.private_key_ctx')" "null" + assert_equal "$(echo "$output" | jq -r '.kas_keys[0].key.public_key_ctx.pem')" "${PEM_B64}" + + run_otdfctl_ns key remove --namespace "$NS_ID" --key-id "$KAS_KEY_ID" --json + assert_success + run_otdfctl_ns get --id "$NS_ID" --json - assert_success - assert_equal "$(echo "$output" | jq -r '.id')" "$NS_ID" - assert_equal "$(echo "$output" | jq -r '.kas_keys | length')" 0 + assert_success + assert_equal "$(echo "$output" | jq -r '.id')" "$NS_ID" + assert_equal "$(echo "$output" | jq -r '.kas_keys | length')" 0 } - @test "KAS key assignment error handling - namespace" { # Test with non-existent namespace ID - run_otdfctl_ns key assign --namespace "00000000-0000-0000-0000-000000000000" --keyId "$KAS_KEY_ID" - assert_failure - assert_output --partial "ERROR" + run_otdfctl_ns key assign --namespace "00000000-0000-0000-0000-000000000000" --key-id "$KAS_KEY_ID" + assert_failure + assert_output --partial "ERROR" # Test with missing required flags run_otdfctl_ns key assign --namespace "$NS_ID" - assert_failure - assert_output --partial "Flag '--keyId' is required" + assert_failure + assert_output --partial "Flag '--key-id' is required" - run_otdfctl_ns key assign --keyId "$KAS_KEY_ID" - assert_failure - assert_output --partial "Flag '--namespace' is required" + run_otdfctl_ns key assign --key-id "$KAS_KEY_ID" + assert_failure + assert_output --partial "Flag '--namespace' is required" } @test "Deactivate namespace" { @@ -220,21 +215,21 @@ teardown_file() { } @test "List namespaces - when inactive" { - run_otdfctl_ns list --json + run_otdfctl_ns list --json echo $output | jq --arg id "$NS_ID" '.[] | select(.[]? | type == "object" and .id == $id)' # json - run_otdfctl_ns list --state inactive --json - echo $output | assert_output --partial "$NS_ID" + run_otdfctl_ns list --state inactive --json + echo $output | assert_output --partial "$NS_ID" - run_otdfctl_ns list --state active --json - echo $output | refute_output --partial "$NS_ID" + run_otdfctl_ns list --state active --json + echo $output | refute_output --partial "$NS_ID" # table - run_otdfctl_ns list --state inactive - echo $output | assert_output --partial "$NS_ID" + run_otdfctl_ns list --state inactive + echo $output | assert_output --partial "$NS_ID" - run_otdfctl_ns list --state active - echo $output | refute_output --partial "$NS_ID" + run_otdfctl_ns list --state active + echo $output | refute_output --partial "$NS_ID" } @test "Unsafe reactivate namespace" { @@ -244,7 +239,7 @@ teardown_file() { } @test "List namespaces - when reactivated" { - run_otdfctl_ns list --json + run_otdfctl_ns list --json echo $output | jq --arg id "$NS_ID" '.[] | select(.[]? | type == "object" and .id == $id)' run_otdfctl_ns list --state inactive --json @@ -262,7 +257,7 @@ teardown_file() { } @test "List namespaces - when deleted" { - run_otdfctl_ns list --json + run_otdfctl_ns list --json echo $output | refute_output --partial "$NS_ID" run_otdfctl_ns list --state inactive --json From c779642b4653e0669d7e366adae0dedddbac2e35 Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 12:17:11 -0400 Subject: [PATCH 13/27] fix id flag on key get --- e2e/kas-keys.bats | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/e2e/kas-keys.bats b/e2e/kas-keys.bats index 7a1e9f57..195fb2fa 100644 --- a/e2e/kas-keys.bats +++ b/e2e/kas-keys.bats @@ -327,7 +327,7 @@ format_kas_name_as_uri() { assert_success CREATED_KEY_SYSTEM_ID=$(echo "$output" | jq -r .key.id) - run_otdfctl_key get --id "${CREATED_KEY_SYSTEM_ID}" --json + run_otdfctl_key get --key "${CREATED_KEY_SYSTEM_ID}" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.id)" "${CREATED_KEY_SYSTEM_ID}" @@ -421,7 +421,7 @@ format_kas_name_as_uri() { } @test "kas-keys: get key (not found by system ID)" { - run_otdfctl_key get --id "39af808f-6cac-403f-90d7-6b88e865860d" --json + run_otdfctl_key get --key "39af808f-6cac-403f-90d7-6b88e865860d" --json assert_failure assert_output --partial "Failed to get kas key" # Error should indicate not found or similar } @@ -433,7 +433,7 @@ format_kas_name_as_uri() { } @test "kas-keys: get key (mutually exclusive: id and key-id)" { - run_otdfctl_key get --id "some-system-id" --key-id "some-user-key-id" --kas "${KAS_REGISTRY_ID}" --json + run_otdfctl_key get --key "some-system-id" --key-id "some-user-key-id" --kas "${KAS_REGISTRY_ID}" --json assert_failure assert_output --partial "Error: if any flags in the group [id key-id] are set none of the others can be" } @@ -467,7 +467,7 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r .key.metadata.created_at.seconds)" "${initial_created_at_seconds}" # created_at should not change # Verify with a subsequent get - run_otdfctl_key get --id "${UPDATE_KEY_LABEL_SYSTEM_ID}" --json + run_otdfctl_key get --key "${UPDATE_KEY_LABEL_SYSTEM_ID}" --json assert_success assert_equal "$(echo "$output" | jq -r '.key.metadata.labels."initial"')" "true" assert_equal "$(echo "$output" | jq -r '.key.metadata.labels."added"')" "true" @@ -493,14 +493,14 @@ format_kas_name_as_uri() { assert_equal "$(echo "$output" | jq -r .key.metadata.created_at.seconds)" "${initial_created_at_replace_seconds}" # Verify with a subsequent get - run_otdfctl_key get --id "${UPDATE_KEY_LABEL_REPLACE_SYSTEM_ID}" --json + run_otdfctl_key get --key "${UPDATE_KEY_LABEL_REPLACE_SYSTEM_ID}" --json assert_success assert_equal "$(echo "$output" | jq -r '.key.metadata.labels."replaced"')" "true" assert_equal "$(echo "$output" | jq -r '.key.metadata.labels."initial" // "null"')" "null" } @test "kas-keys: update key (not found)" { - run_otdfctl_key update --id "39af808f-6cac-403f-90d7-6b88e865860d" --json + run_otdfctl_key update --key "39af808f-6cac-403f-90d7-6b88e865860d" --json assert_failure assert_output --partial "Failed to update kas key" } From 3265b1b35bd962bc73fc0058d32d6cfbc124fb81 Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 13:26:01 -0400 Subject: [PATCH 14/27] more test fixes --- cmd/base-keys.go | 16 ++++++++++++---- docs/man/policy/kas-registry/key/base/set.md | 4 +--- e2e/base-key.bats | 6 +++--- e2e/kas-keys.bats | 20 ++++---------------- pkg/handlers/base-keys.go | 12 +++++++++--- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/cmd/base-keys.go b/cmd/base-keys.go index 597b203b..b5a6d9c3 100644 --- a/cmd/base-keys.go +++ b/cmd/base-keys.go @@ -115,11 +115,19 @@ func setBaseKey(cmd *cobra.Command, args []string) { h := NewHandler(c) defer h.Close() - identifier, err := getKasKeyIdentifier(c) - if err != nil { - c.ExitWithError("Invalid key identifier", err) + var identifier *kasregistry.KasKeyIdentifier + var err error + + id := c.Flags.GetOptionalString("key") + fmt.Println("id: ", id) + if utils.ClassifyString(id) != utils.StringTypeUUID { + fmt.Println("calling getKasKeyIdentifier") + identifier, err = getKasKeyIdentifier(c) + if err != nil { + c.ExitWithError("Invalid key identifier", err) + } } - baseKey, err := h.SetBaseKey(c.Context(), identifier) + baseKey, err := h.SetBaseKey(c.Context(), id, identifier) if err != nil { cli.ExitWithError("Failed to set base key", err) } diff --git a/docs/man/policy/kas-registry/key/base/set.md b/docs/man/policy/kas-registry/key/base/set.md index aab90a55..d672b245 100644 --- a/docs/man/policy/kas-registry/key/base/set.md +++ b/docs/man/policy/kas-registry/key/base/set.md @@ -10,9 +10,7 @@ command: description: The KeyID (human-readable identifier) or the internal UUID of an existing key within the specified KAS. This key will be designated as the platform base key. The system will attempt to resolve the provided value as either a UUID or a KeyID. required: true - name: kas - description: Specify the Key Access Server (KAS) where the key (identified by `--key`) is registered. The KAS can be identified by its ID, URI, or Name. - required: true - + description: Specify the Key Access Server (KAS) where the key (identified by `--key`) is registered. The KAS can be identified by its ID, URI, or Name. --- Command for setting a base key to be used for encryption operations on data where no attributes are present or where no keys are present on found attributes. The key to be set as the base key must be identified using its KeyID or UUID via the `--key` flag, and the KAS it belongs to must be specified with the `--kas` flag. diff --git a/e2e/base-key.bats b/e2e/base-key.bats index 9ae5198e..732c4fe9 100644 --- a/e2e/base-key.bats +++ b/e2e/base-key.bats @@ -42,8 +42,8 @@ teardown_file() { # --- set base key tests --- -@test "base-key: set by --id" { - run_otdfctl_base_key set --id "${KAS_KEY_SYSTEM_ID}" --json +@test "base-key: set by --key (uuid)" { + run_otdfctl_base_key set --key "${KAS_KEY_SYSTEM_ID}" --json assert_success # Verify the new base key part of the response assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.kid)" "${REGULAR_KEY_ID_FOR_BASE_TEST}" @@ -67,7 +67,7 @@ teardown_file() { } @test "base-key: get (after setting a base key)" { - run_otdfctl_base_key set --id "${KAS_KEY_SYSTEM_ID}" --json + run_otdfctl_base_key set --key "${KAS_KEY_SYSTEM_ID}" --json assert_success run_otdfctl_base_key get --json diff --git a/e2e/kas-keys.bats b/e2e/kas-keys.bats index 195fb2fa..5ea8e2b7 100644 --- a/e2e/kas-keys.bats +++ b/e2e/kas-keys.bats @@ -64,7 +64,7 @@ format_kas_name_as_uri() { # For local mode, a public key is generated by otdfctl. # Its exact value cannot be known before running the command without replicating the key generation logic. # Thus, we assert its presence and that it\'s a non-empty base64 encoded string. This is the intended assertion. - run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithmorithm rsa:2048 --mode local --wrapping-key-id wrapping-key-1 --wrappingKey "${WRAPPING_KEY}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm rsa:2048 --mode local --wrapping-key-id wrapping-key-1 --wrappingKey "${WRAPPING_KEY}" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" @@ -263,7 +263,7 @@ format_kas_name_as_uri() { assert_output --partial "pem must be base64 encoded" } -@test "kas-keys: create key (missing kas identifier - kas, kas, or kas)" { +@test "kas-keys: create key (missing kas identifier)" { KEY_ID=$(generate_key_id) run_otdfctl_key create --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" assert_failure @@ -427,23 +427,11 @@ format_kas_name_as_uri() { } @test "kas-keys: get key (not found by user key-id and kas)" { - run_otdfctl_key get --key-id "non-existent-key" --kas "${KAS_REGISTRY_ID}" --json + run_otdfctl_key get --key "non-existent-key" --kas "${KAS_REGISTRY_ID}" --json assert_failure assert_output --partial "Failed to get kas key" # Error should indicate not found or similar } -@test "kas-keys: get key (mutually exclusive: id and key-id)" { - run_otdfctl_key get --key "some-system-id" --key-id "some-user-key-id" --kas "${KAS_REGISTRY_ID}" --json - assert_failure - assert_output --partial "Error: if any flags in the group [id key-id] are set none of the others can be" -} - -@test "kas-keys: get key (mutually exclusive: kas and kas with key-id)" { - run_otdfctl_key get --key-id "some-user-key-id" --kas "${KAS_REGISTRY_ID}" --kas "some-kas-name" --json - assert_failure - assert_output --partial "Error: if any flags in the group [kas kas kas] are set none of the others can be; [kas kas] were all set" -} - @test "kas-keys: update key labels (add)" { KEY_ID_UPDATE_LABEL=$(generate_key_id) run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID_UPDATE_LABEL}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --label "initial=true" --json @@ -722,7 +710,7 @@ format_kas_name_as_uri() { @test "kas-keys: list keys (invalid algorithm)" { run_otdfctl_key list --algorithm "invalid-algorithm" --json assert_failure - assert_output --partial "Invalid algorithmorithm" + assert_output --partial "Invalid algorithm" } @test "kas-keys: list keys (mutually exclusive: kas and kas)" { diff --git a/pkg/handlers/base-keys.go b/pkg/handlers/base-keys.go index 7db74a64..3656c139 100644 --- a/pkg/handlers/base-keys.go +++ b/pkg/handlers/base-keys.go @@ -17,11 +17,17 @@ func (h Handler) GetBaseKey(ctx context.Context) (*kasregistry.SimpleKasKey, err return resp.GetBaseKey(), nil } -func (h Handler) SetBaseKey(ctx context.Context, key *kasregistry.KasKeyIdentifier) (*kasregistry.SetBaseKeyResponse, error) { +func (h Handler) SetBaseKey(ctx context.Context, id string, key *kasregistry.KasKeyIdentifier) (*kasregistry.SetBaseKeyResponse, error) { req := kasregistry.SetBaseKeyRequest{} - req.ActiveKey = &kasregistry.SetBaseKeyRequest_Key{ - Key: key, + if id != "" { + req.ActiveKey = &kasregistry.SetBaseKeyRequest_Id{ + Id: id, + } + } else if key != nil { + req.ActiveKey = &kasregistry.SetBaseKeyRequest_Key{ + Key: key, + } } return h.sdk.KeyAccessServerRegistry.SetBaseKey(ctx, &req) From c1750ac82b7c67e490a06553ec1d7012f3c30daf Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 13:36:02 -0400 Subject: [PATCH 15/27] more test fixes --- cmd/kas-keys.go | 2 +- e2e/kas-keys.bats | 22 ++++++++-------------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/cmd/kas-keys.go b/cmd/kas-keys.go index 40aa8b00..5f8ec0ff 100644 --- a/cmd/kas-keys.go +++ b/cmd/kas-keys.go @@ -245,7 +245,7 @@ func policyCreateKasKey(cmd *cobra.Command, args []string) { h := NewHandler(c) defer h.Close() - keyIdentifier := c.Flags.GetRequiredString("key") + keyIdentifier := c.Flags.GetRequiredString("key-id") kasIdentifier := c.Flags.GetRequiredString("kas") metadataLabels = c.Flags.GetStringSlice("label", metadataLabels, cli.FlagsStringSliceOptions{Min: 0}) diff --git a/e2e/kas-keys.bats b/e2e/kas-keys.bats index 5ea8e2b7..5ec8d68d 100644 --- a/e2e/kas-keys.bats +++ b/e2e/kas-keys.bats @@ -64,7 +64,7 @@ format_kas_name_as_uri() { # For local mode, a public key is generated by otdfctl. # Its exact value cannot be known before running the command without replicating the key generation logic. # Thus, we assert its presence and that it\'s a non-empty base64 encoded string. This is the intended assertion. - run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm rsa:2048 --mode local --wrapping-key-id wrapping-key-1 --wrappingKey "${WRAPPING_KEY}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm rsa:2048 --mode local --wrapping-key-id wrapping-key-1 --wrapping-key "${WRAPPING_KEY}" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" @@ -87,7 +87,7 @@ format_kas_name_as_uri() { # For local mode, a public key is generated by otdfctl. # Its exact value cannot be known before running the command without replicating the key generation logic. # Thus, we assert its presence and that it\'s a non-empty base64 encoded string. This is the intended assertion. - run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "ec:secp256r1" --mode "local" --wrapping-key-id "wrapping-key-1" --wrappingKey "${WRAPPING_KEY}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "ec:secp256r1" --mode "local" --wrapping-key-id "wrapping-key-1" --wrapping-key "${WRAPPING_KEY}" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.key_id)" "${KEY_ID}" @@ -172,37 +172,37 @@ format_kas_name_as_uri() { } @test "kas-keys: create key (missing key-id)" { - run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --algorithm "rsa:2048" --mode "local" --wrapping-key-id "wrapping-key-1" --wrappingKey "${WRAPPING_KEY}" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --algorithm "rsa:2048" --mode "local" --wrapping-key-id "wrapping-key-1" --wrapping-key "${WRAPPING_KEY}" assert_failure assert_output --partial "Flag '--key-id' is required" } @test "kas-keys: create key (missing algorithm)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --mode "local" --wrapping-key-id "wrapping-key-1" --wrappingKey "${WRAPPING_KEY}" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --mode "local" --wrapping-key-id "wrapping-key-1" --wrapping-key "${WRAPPING_KEY}" assert_failure assert_output --partial "Flag '--algorithm' is required" } @test "kas-keys: create key (missing mode)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --wrapping-key-id "wrapping-key-1" --wrappingKey "${WRAPPING_KEY}" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --wrapping-key-id "wrapping-key-1" --wrapping-key "${WRAPPING_KEY}" assert_failure assert_output --partial "Flag '--mode' is required" } @test "kas-keys: create key (local mode, missing wrapping-key-id)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "local" --wrappingKey "${WRAPPING_KEY}" + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "local" --wrapping-key "${WRAPPING_KEY}" assert_failure assert_output --partial "wrapping-key-id is required for mode local" } -@test "kas-keys: create key (local mode, missing wrappingKey)" { +@test "kas-keys: create key (local mode, missing wrapping-key)" { KEY_ID=$(generate_key_id) run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "local" --wrapping-key-id "wrapping-key-1" assert_failure - assert_output --partial "Flag '--wrappingKey' is required" + assert_output --partial "Flag '--wrapping-key' is required" } @test "kas-keys: create key (public_key mode, missing pem)" { @@ -712,9 +712,3 @@ format_kas_name_as_uri() { assert_failure assert_output --partial "Invalid algorithm" } - -@test "kas-keys: list keys (mutually exclusive: kas and kas)" { - run_otdfctl_key list --kas "${KAS_REGISTRY_ID}" --kas "some-kas-name" --json - assert_failure - assert_output --partial "Error: if any flags in the group [kas kas kas] are set none of the others can be" -} From ec7f499916fa8867973ff22d0c294018d3c6002d Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 13:48:12 -0400 Subject: [PATCH 16/27] add kas key-remote info back --- cmd/base-keys.go | 2 -- e2e/base-key.bats | 2 +- e2e/kas-keys.bats | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/cmd/base-keys.go b/cmd/base-keys.go index b5a6d9c3..fd8ce7a5 100644 --- a/cmd/base-keys.go +++ b/cmd/base-keys.go @@ -119,9 +119,7 @@ func setBaseKey(cmd *cobra.Command, args []string) { var err error id := c.Flags.GetOptionalString("key") - fmt.Println("id: ", id) if utils.ClassifyString(id) != utils.StringTypeUUID { - fmt.Println("calling getKasKeyIdentifier") identifier, err = getKasKeyIdentifier(c) if err != nil { c.ExitWithError("Invalid key identifier", err) diff --git a/e2e/base-key.bats b/e2e/base-key.bats index 732c4fe9..d4917af7 100644 --- a/e2e/base-key.bats +++ b/e2e/base-key.bats @@ -8,7 +8,7 @@ setup_file() { # Create a KAS registry entry for testing base keys export KAS_NAME_BASE_KEY_TEST="kas-registry-for-base-key-tests" export KAS_URI_BASE_KEY_TEST="https://test-kas-for-base-keys.com" - export KAS_REGISTRY_ID_BASE_KEY_TEST=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --name "${KAS_NAME_BASE_KEY_TEST}" --uri "${KAS_URI_BASE_KEY_TEST}" --json | jq -r '.id') + export KAS_REGISTRY_ID_BASE_KEY_TEST=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --name "${KAS_NAME_BASE_KEY_TEST}" --uri "${KAS_URI_BASE_KEY_TEST}" --public-key-remote "${KAS_URI_BASE_KEY_TEST}" --json | jq -r '.id') # Create a regular KAS key to be set as a base key # This key will be used by the 'set' command tests diff --git a/e2e/kas-keys.bats b/e2e/kas-keys.bats index 5ec8d68d..70f8c451 100644 --- a/e2e/kas-keys.bats +++ b/e2e/kas-keys.bats @@ -7,7 +7,7 @@ setup_file() { # This command is not a 'kas-registry key' subcommand, so it won't use run_otdfctl_key export KAS_URI="https://test-kas-with-keys.com" export KAS_NAME="kas-registry-for-keys-test" - export KAS_REGISTRY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --name $KAS_NAME --uri "$KAS_URI" --json | jq -r '.id') + export KAS_REGISTRY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --name $KAS_NAME --uri "$KAS_URI" --public-key-remote 'https://test-kas-with-keys.com' --json | jq -r '.id') export PC_ID=$(./otdfctl $HOST $WITH_CREDS keymanagement provider create --name "test-provider-config-kas-keys" --config '{}' --json | jq -r '.id') export WRAPPING_KEY="gp6TcYb/ZrgkQOYPdiYFRj11jZwbevy+r2KFbAYM0GE=" export PEM_B64=$(echo "pem" | base64) From f7c60ca7ac419e8e989174b2f3d81ee863a2e06e Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 13:55:55 -0400 Subject: [PATCH 17/27] more fixes --- cmd/kas-keys.go | 14 ++++++++++---- e2e/kas-keys.bats | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/cmd/kas-keys.go b/cmd/kas-keys.go index 5f8ec0ff..93520bcd 100644 --- a/cmd/kas-keys.go +++ b/cmd/kas-keys.go @@ -14,6 +14,7 @@ import ( "github.com/opentdf/otdfctl/pkg/utils" "github.com/opentdf/platform/lib/ocrypto" "github.com/opentdf/platform/protocol/go/policy" + "github.com/opentdf/platform/protocol/go/policy/kasregistry" "github.com/spf13/cobra" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" @@ -377,11 +378,16 @@ func policyGetKasKey(cmd *cobra.Command, args []string) { h := NewHandler(c) defer h.Close() - id := c.Flags.GetOptionalID("id") + id := c.Flags.GetOptionalID("key") - identifier, err := getKasKeyIdentifier(c) - if err != nil { - cli.ExitWithError("Invalid key identifier", err) + var identifier *kasregistry.KasKeyIdentifier + var err error + + if utils.ClassifyString(id) != utils.StringTypeUUID { + identifier, err = getKasKeyIdentifier(c) + if err != nil { + cli.ExitWithError("Invalid key identifier", err) + } } kasKey, err := h.GetKasKey(c.Context(), id, identifier) if err != nil { diff --git a/e2e/kas-keys.bats b/e2e/kas-keys.bats index 70f8c451..be39c92d 100644 --- a/e2e/kas-keys.bats +++ b/e2e/kas-keys.bats @@ -488,7 +488,7 @@ format_kas_name_as_uri() { } @test "kas-keys: update key (not found)" { - run_otdfctl_key update --key "39af808f-6cac-403f-90d7-6b88e865860d" --json + run_otdfctl_key update --id "39af808f-6cac-403f-90d7-6b88e865860d" --json assert_failure assert_output --partial "Failed to update kas key" } From fcb608a05a89ba136b4760046304b3d776c7bce3 Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 14:22:10 -0400 Subject: [PATCH 18/27] more cleanup --- cmd/kas-keys.go | 4 ++-- e2e/kas-keys.bats | 25 +++++++++---------------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/cmd/kas-keys.go b/cmd/kas-keys.go index 93520bcd..578f0e38 100644 --- a/cmd/kas-keys.go +++ b/cmd/kas-keys.go @@ -378,7 +378,7 @@ func policyGetKasKey(cmd *cobra.Command, args []string) { h := NewHandler(c) defer h.Close() - id := c.Flags.GetOptionalID("key") + id := c.Flags.GetOptionalString("key") var identifier *kasregistry.KasKeyIdentifier var err error @@ -449,7 +449,7 @@ func policyListKasKeys(cmd *cobra.Command, args []string) { cli.ExitWithError("Invalid algorithm", err) } } - kasIdentifier := c.Flags.GetRequiredString("kas") + kasIdentifier := c.Flags.GetOptionalString("kas") kasIdentifier, err := resolveKasIdentifier(c.Context(), kasIdentifier, h) if err != nil { diff --git a/e2e/kas-keys.bats b/e2e/kas-keys.bats index be39c92d..67e80041 100644 --- a/e2e/kas-keys.bats +++ b/e2e/kas-keys.bats @@ -267,7 +267,7 @@ format_kas_name_as_uri() { KEY_ID=$(generate_key_id) run_otdfctl_key create --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" assert_failure - assert_output --partial "Error: at least one of the flags in the group [kas kas kas] is required" + assert_output --partial "Flag '--kas' is required" } @test "kas-keys: create key (using kasName)" { @@ -300,18 +300,11 @@ format_kas_name_as_uri() { assert_not_equal "$(echo "$output" | jq -r .key.metadata.updated_at)" "null" } -@test "kas-keys: create key (mutually exclusive KAS identifiers)" { +@test "kas-keys: create key (invalid algorithm value)" { KEY_ID=$(generate_key_id) - run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --kas "some-other-kas" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "invalid-algorithm-value" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_failure - assert_output --partial "Error: if any flags in the group [kas kas kas] are set none of the others can be; [kas kas] were all set" -} - -@test "kas-keys: create key (invalid algorithmorithm value)" { - KEY_ID=$(generate_key_id) - run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID}" --algorithm "invalid-algorithmorithm-value" --mode "public_key" --public-key-pem "${PEM_B64}" --json - assert_failure - assert_output --partial "Invalid algorithmorithm" + assert_output --partial "Invalid algorithm: invalid algorithm" } @test "kas-keys: create key (invalid mode value)" { @@ -348,7 +341,7 @@ format_kas_name_as_uri() { assert_success local created_key_system_id_for_get=$(echo "$output" | jq -r .key.id) - run_otdfctl_key get --key-id "${KEY_ID_GET_USER}" --kas "${KAS_REGISTRY_ID}" --json + run_otdfctl_key get --key "${KEY_ID_GET_USER}" --kas "${KAS_REGISTRY_ID}" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.id)" "${created_key_system_id_for_get}" @@ -368,7 +361,7 @@ format_kas_name_as_uri() { assert_success local created_key_system_id_for_kas_get=$(echo "$output" | jq -r .key.id) - run_otdfctl_key get --key-id "${KEY_ID_GET_USER_kas}" --kas "kas-registry-for-keys-test" --json + run_otdfctl_key get --key "${KEY_ID_GET_USER_kas}" --kas "kas-registry-for-keys-test" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" assert_equal "$(echo "$output" | jq -r .key.id)" "${created_key_system_id_for_kas_get}" @@ -388,7 +381,7 @@ format_kas_name_as_uri() { assert_success local created_key_system_id_for_kas_get=$(echo "$output" | jq -r .key.id) - run_otdfctl_key get --key-id "${KEY_ID_GET_USER_kas}" --kas "${KAS_URI}" --json + run_otdfctl_key get --key "${KEY_ID_GET_USER_kas}" --kas "${KAS_URI}" --json assert_success assert_equal "$(echo "$output" | jq -r .kas_id)" "${KAS_REGISTRY_ID}" # Should resolve to the same KAS assert_equal "$(echo "$output" | jq -r .key.id)" "${created_key_system_id_for_kas_get}" @@ -408,7 +401,7 @@ format_kas_name_as_uri() { run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID_FAIL_GET}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json assert_success - run_otdfctl_key get --key-id "${KEY_ID_FAIL_GET}" --json + run_otdfctl_key get --key "${KEY_ID_FAIL_GET}" --json assert_failure # Error message might vary, but it should indicate an issue with resolving the key or missing parameters assert_output --partial "at least one of 'kas', 'kas', or 'kas' must be provided with 'key-id'" # Or a more specific error about missing KAS identifier @@ -417,7 +410,7 @@ format_kas_name_as_uri() { @test "kas-keys: get key (failure: only kas, missing key-id or system id)" { run_otdfctl_key get --kas "${KAS_REGISTRY_ID}" --json assert_failure - assert_output --partial "at least one of the flags in the group [id key-id] is required" + assert_output --partial "Flag '--key' is required" } @test "kas-keys: get key (not found by system ID)" { From fc94ea96178b1e4560004e1f0d779a3b223b53de Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 14:37:55 -0400 Subject: [PATCH 19/27] more fixes --- e2e/base-key.bats | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/e2e/base-key.bats b/e2e/base-key.bats index d4917af7..65500a5b 100644 --- a/e2e/base-key.bats +++ b/e2e/base-key.bats @@ -80,7 +80,7 @@ teardown_file() { } @test "base-key: set by --key(id) and --kas(name)" { - run_otdfctl_base_key set --key "${REGULAR_KEY_ID_FOR_BASE_TEST}" --kasName "${KAS_NAME_BASE_KEY_TEST}" --json + run_otdfctl_base_key set --key "${REGULAR_KEY_ID_FOR_BASE_TEST}" --kas "${KAS_NAME_BASE_KEY_TEST}" --json assert_success assert_equal "$(echo "$output" | jq -r .new_base_key.public_key.kid)" "${REGULAR_KEY_ID_FOR_BASE_TEST}" assert_equal "$(echo "$output" | jq -r .new_base_key.kas_uri)" "${KAS_URI_BASE_KEY_TEST}" # KAS URI should remain the same for the KAS Name @@ -136,16 +136,16 @@ teardown_file() { assert_equal "$(echo "$output" | jq -r .previous_base_key.public_key.algorithm)" "rsa:2048" } -@test "base-key: set (missing kas identifier: kasId, kasName, or kasUri)" { +@test "base-key: set (missing kas identifier)" { run_otdfctl_base_key set --key "${REGULAR_KEY_ID_FOR_BASE_TEST}" assert_failure - assert_output --partial "at least one of 'kasId', 'kasName', or 'kasUri' must be provided with 'keyId'" + assert_output --partial "Flag '--kas' is required" } @test "base-key: set (missing key identifier: id or keyId)" { run_otdfctl_base_key set --kas "${KAS_REGISTRY_ID_BASE_KEY_TEST}" assert_failure - assert_output --partial "Error: at least one of the flags in the group [id keyId] is required" + assert_output --partial "Flag '--key' is required" } @test "base-key: set (using non-existent keyId)" { From 82fa65a7845b5a677b67cc46d696a1e55fa18a5f Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 15:24:20 -0400 Subject: [PATCH 20/27] more test fixes --- e2e/attributes.bats | 2 +- e2e/namespaces.bats | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/attributes.bats b/e2e/attributes.bats index 9a2faeb3..277762b7 100755 --- a/e2e/attributes.bats +++ b/e2e/attributes.bats @@ -15,7 +15,7 @@ setup_file() { export KAS_URI="https://test-kas-for-attributes.com" export KAS_REG_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --uri "$KAS_URI" --public-key-remote 'https://test-kas-for-attributes.com/pub_key' --json | jq -r '.id') export PEM_B64=$(echo "pem" | base64) - export KAS_KEY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kasId "$KAS_REG_ID" --key-id "test-key-for-attr" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json | jq -r '.key.id') + export KAS_KEY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kasId "$KAS_REG_ID" --key-id "test-key-for-attr" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json | jq -r '.key.id') } # always create a randomly named attribute diff --git a/e2e/namespaces.bats b/e2e/namespaces.bats index 09f0f546..6abab5fe 100755 --- a/e2e/namespaces.bats +++ b/e2e/namespaces.bats @@ -17,7 +17,7 @@ setup_file() { export KAS_URI="https://test-kas-for-namespace.com" export KAS_REG_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --uri "$KAS_URI" --public-key-remote 'https://test-kas-for-namespace.com/pub_key' --json | jq -r '.id') export PEM_B64=$(echo "pem" | base64) - export KAS_KEY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kasId "$KAS_REG_ID" --key-id "test-key-for-namespace" --alg "rsa:2048" --mode "public_key" --pubPem "${PEM_B64}" --json | jq -r '.key.id') + export KAS_KEY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kas "$KAS_REG_ID" --key-id "test-key-for-namespace" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json | jq -r '.key.id') } setup() { From ad39bbac2761ce4ef189c1be8f05f8b7366a747a Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 15:50:47 -0400 Subject: [PATCH 21/27] more test fixes --- e2e/base-key.bats | 2 +- e2e/kas-keys.bats | 2 +- pkg/handlers/base-keys.go | 2 +- pkg/handlers/kas-keys.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/e2e/base-key.bats b/e2e/base-key.bats index 65500a5b..86e9ee94 100644 --- a/e2e/base-key.bats +++ b/e2e/base-key.bats @@ -119,7 +119,7 @@ teardown_file() { assert_equal "$(echo "$output" | jq -r .public_key.algorithm)" "rsa:2048" SECOND_KEY_ID_FOR_BASE_TEST="second-key-for-base-$(date +%s)" - SECOND_KAS_KEY_SYSTEM_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kasId "${KAS_REGISTRY_ID_BASE_KEY_TEST}" --keyId "${SECOND_KEY_ID_FOR_BASE_TEST}" --alg ec:secp256r1 --mode local --wrappingKey "${WRAPPING_KEY}" --wrappingKeyId "test-key" --json | jq -r '.key.id') + SECOND_KAS_KEY_SYSTEM_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kas "${KAS_REGISTRY_ID_BASE_KEY_TEST}" --key-id "${SECOND_KEY_ID_FOR_BASE_TEST}" --algorithm ec:secp256r1 --mode local --wrapping-key "${WRAPPING_KEY}" --wrapping-key-id "test-key" --json | jq -r '.key.id') run_otdfctl_base_key set --key "${SECOND_KAS_KEY_SYSTEM_ID}" --json assert_success diff --git a/e2e/kas-keys.bats b/e2e/kas-keys.bats index 67e80041..fc538dab 100644 --- a/e2e/kas-keys.bats +++ b/e2e/kas-keys.bats @@ -404,7 +404,7 @@ format_kas_name_as_uri() { run_otdfctl_key get --key "${KEY_ID_FAIL_GET}" --json assert_failure # Error message might vary, but it should indicate an issue with resolving the key or missing parameters - assert_output --partial "at least one of 'kas', 'kas', or 'kas' must be provided with 'key-id'" # Or a more specific error about missing KAS identifier + assert_output --partial "Flag '--kas' is required" # Or a more specific error about missing KAS identifier } @test "kas-keys: get key (failure: only kas, missing key-id or system id)" { diff --git a/pkg/handlers/base-keys.go b/pkg/handlers/base-keys.go index 3656c139..11aac6c0 100644 --- a/pkg/handlers/base-keys.go +++ b/pkg/handlers/base-keys.go @@ -20,7 +20,7 @@ func (h Handler) GetBaseKey(ctx context.Context) (*kasregistry.SimpleKasKey, err func (h Handler) SetBaseKey(ctx context.Context, id string, key *kasregistry.KasKeyIdentifier) (*kasregistry.SetBaseKeyResponse, error) { req := kasregistry.SetBaseKeyRequest{} - if id != "" { + if id != "" && key == nil { req.ActiveKey = &kasregistry.SetBaseKeyRequest_Id{ Id: id, } diff --git a/pkg/handlers/kas-keys.go b/pkg/handlers/kas-keys.go index 6c239fd0..511bf773 100644 --- a/pkg/handlers/kas-keys.go +++ b/pkg/handlers/kas-keys.go @@ -42,7 +42,7 @@ func (h Handler) CreateKasKey( func (h Handler) GetKasKey(ctx context.Context, id string, key *kasregistry.KasKeyIdentifier) (*policy.KasKey, error) { req := kasregistry.GetKeyRequest{} switch { - case id != "": + case id != "" && key == nil: req.Identifier = &kasregistry.GetKeyRequest_Id{ Id: id, } From 57f753bd59def81379fd4220e236ab031ea4bb04 Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 15:57:09 -0400 Subject: [PATCH 22/27] fix attributes.bats --- e2e/attributes.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/attributes.bats b/e2e/attributes.bats index 277762b7..32bfaf31 100755 --- a/e2e/attributes.bats +++ b/e2e/attributes.bats @@ -15,7 +15,7 @@ setup_file() { export KAS_URI="https://test-kas-for-attributes.com" export KAS_REG_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --uri "$KAS_URI" --public-key-remote 'https://test-kas-for-attributes.com/pub_key' --json | jq -r '.id') export PEM_B64=$(echo "pem" | base64) - export KAS_KEY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kasId "$KAS_REG_ID" --key-id "test-key-for-attr" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json | jq -r '.key.id') + export KAS_KEY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry key create --kas "$KAS_REG_ID" --key-id "test-key-for-attr" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json | jq -r '.key.id') } # always create a randomly named attribute From e358355056225013c656a15ffd75c87aca61fdd5 Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 16:10:13 -0400 Subject: [PATCH 23/27] fix some minor issues --- cmd/kas-keys.go | 25 ++++++++----------------- pkg/handlers/kas-registry.go | 13 +++++++++++++ 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/cmd/kas-keys.go b/cmd/kas-keys.go index 578f0e38..8bfd4c86 100644 --- a/cmd/kas-keys.go +++ b/cmd/kas-keys.go @@ -345,14 +345,14 @@ func policyCreateKasKey(cmd *cobra.Command, args []string) { cli.ExitWithError("Invalid mode", nil) } - kasIdentifier, err = resolveKasIdentifier(c.Context(), kasIdentifier, h) + kasLookUp, err := resolveKasIdentifier(c.Context(), kasIdentifier, h) if err != nil { cli.ExitWithError("Invalid kas identifier", err) } kasKey, err := h.CreateKasKey( c.Context(), - kasIdentifier, + kasLookUp.GetIdentifierValue(), keyIdentifier, alg, mode, @@ -451,15 +451,13 @@ func policyListKasKeys(cmd *cobra.Command, args []string) { } kasIdentifier := c.Flags.GetOptionalString("kas") - kasIdentifier, err := resolveKasIdentifier(c.Context(), kasIdentifier, h) + kasLookup, err := resolveKasIdentifier(c.Context(), kasIdentifier, h) if err != nil { cli.ExitWithError("Invalid kas identifier", err) } // Get the list of keys. - keys, page, err := h.ListKasKeys(c.Context(), limit, offset, alg, handlers.KasIdentifier{ - ID: kasIdentifier, - }) + keys, page, err := h.ListKasKeys(c.Context(), limit, offset, alg, kasLookup) if err != nil { cli.ExitWithError("Failed to list kas keys", err) } @@ -530,30 +528,23 @@ func policyListKasKeys(cmd *cobra.Command, args []string) { HandleSuccess(cmd, "", t, keys) } -func resolveKasIdentifier(ctx context.Context, ident string, h handlers.Handler) (string, error) { +func resolveKasIdentifier(ctx context.Context, ident string, h handlers.Handler) (handlers.KasIdentifier, error) { // Use the ClassifyString helper to determine how to look up the KAS kasLookup := handlers.KasIdentifier{} kasInputType := utils.ClassifyString(ident) switch kasInputType { //nolint:exhaustive // default catches unknown case utils.StringTypeUUID: - return ident, nil + kasLookup.ID = ident case utils.StringTypeURI: kasLookup.URI = ident case utils.StringTypeGeneric: kasLookup.Name = ident default: - return "", errors.New("invalid kas identifier") + return kasLookup, errors.New("invalid kas identifier") } - if kasInputType != utils.StringTypeUUID { - resolvedKas, err := h.GetKasRegistryEntry(ctx, kasLookup) - if err != nil { - return "", errors.Join(errors.New("failed to get kas registry entry"), err) - } - return resolvedKas.GetId(), nil - } - return "", nil + return kasLookup, nil } func init() { diff --git a/pkg/handlers/kas-registry.go b/pkg/handlers/kas-registry.go index 13d702c6..68bd5b05 100644 --- a/pkg/handlers/kas-registry.go +++ b/pkg/handlers/kas-registry.go @@ -15,6 +15,19 @@ type KasIdentifier struct { URI string } +func (k KasIdentifier) GetIdentifierValue() string { + if k.ID != "" { + return k.ID + } + if k.Name != "" { + return k.Name + } + if k.URI != "" { + return k.URI + } + return "" +} + func (h Handler) GetKasRegistryEntry(ctx context.Context, identifer KasIdentifier) (*policy.KeyAccessServer, error) { req := &kasregistry.GetKeyAccessServerRequest{} switch { From 15cf59b3a45c8cb6c50ddf12f76807784c58aa56 Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 18:02:32 -0400 Subject: [PATCH 24/27] final test fixes --- cmd/kas-keys.go | 22 +++++++++++++-- e2e/kas-keys.bats | 54 +++++++++++++++++++++++++++++------- pkg/handlers/kas-registry.go | 13 --------- 3 files changed, 64 insertions(+), 25 deletions(-) diff --git a/cmd/kas-keys.go b/cmd/kas-keys.go index 8bfd4c86..9b1e1df7 100644 --- a/cmd/kas-keys.go +++ b/cmd/kas-keys.go @@ -345,14 +345,26 @@ func policyCreateKasKey(cmd *cobra.Command, args []string) { cli.ExitWithError("Invalid mode", nil) } - kasLookUp, err := resolveKasIdentifier(c.Context(), kasIdentifier, h) + kasLookup, err := resolveKasIdentifier(c.Context(), kasIdentifier, h) if err != nil { cli.ExitWithError("Invalid kas identifier", err) } + var resolvedKasID string + if kasLookup.ID != "" { + resolvedKasID = kasLookup.ID + } else { + // If not a UUID, resolve it to get the UUID + kasEntry, err := h.GetKasRegistryEntry(c.Context(), kasLookup) + if err != nil { + cli.ExitWithError(fmt.Sprintf("Failed to resolve KAS identifier '%s'", kasIdentifier), err) + } + resolvedKasID = kasEntry.GetId() + } + kasKey, err := h.CreateKasKey( c.Context(), - kasLookUp.GetIdentifierValue(), + resolvedKasID, keyIdentifier, alg, mode, @@ -529,6 +541,12 @@ func policyListKasKeys(cmd *cobra.Command, args []string) { } func resolveKasIdentifier(ctx context.Context, ident string, h handlers.Handler) (handlers.KasIdentifier, error) { + // If the identifier is empty, it means no KAS filter is applied. + // Return an empty KasIdentifier and no error. + if ident == "" { + return handlers.KasIdentifier{}, nil + } + // Use the ClassifyString helper to determine how to look up the KAS kasLookup := handlers.KasIdentifier{} kasInputType := utils.ClassifyString(ident) diff --git a/e2e/kas-keys.bats b/e2e/kas-keys.bats index fc538dab..d7f8119f 100644 --- a/e2e/kas-keys.bats +++ b/e2e/kas-keys.bats @@ -1,5 +1,21 @@ #!/usr/bin/env bats +load "${BATS_LIB_PATH}/bats-support/load.bash" +load "${BATS_LIB_PATH}/bats-assert/load.bash" + +# Helper functions for otdfctl commands +run_otdfctl_key() { + run sh -c "./otdfctl policy kas-registry key $HOST $WITH_CREDS $*" +} + +run_otdfctl_kas_registry_create() { + run sh -c "./otdfctl policy kas-registry create $HOST $WITH_CREDS $*" +} + +run_otdfctl_provider_create() { + run sh -c "./otdfctl keymanagement provider create $HOST $WITH_CREDS $*" +} + setup_file() { echo -n '{"clientId":"opentdf","clientSecret":"secret"}' >creds.json export WITH_CREDS='--with-client-creds-file ./creds.json' @@ -7,24 +23,25 @@ setup_file() { # This command is not a 'kas-registry key' subcommand, so it won't use run_otdfctl_key export KAS_URI="https://test-kas-with-keys.com" export KAS_NAME="kas-registry-for-keys-test" - export KAS_REGISTRY_ID=$(./otdfctl $HOST $WITH_CREDS policy kas-registry create --name $KAS_NAME --uri "$KAS_URI" --public-key-remote 'https://test-kas-with-keys.com' --json | jq -r '.id') - export PC_ID=$(./otdfctl $HOST $WITH_CREDS keymanagement provider create --name "test-provider-config-kas-keys" --config '{}' --json | jq -r '.id') + + run_otdfctl_kas_registry_create --name $KAS_NAME --uri "$KAS_URI" --public-key-remote 'https://test-kas-with-keys.com' --json + assert_success + export KAS_REGISTRY_ID=$(echo "$output" | jq -r '.id') + + run_otdfctl_provider_create --name "test-provider-config-kas-keys" --config '{}' --json + assert_success + export PC_ID=$(echo "$output" | jq -r '.id') export WRAPPING_KEY="gp6TcYb/ZrgkQOYPdiYFRj11jZwbevy+r2KFbAYM0GE=" export PEM_B64=$(echo "pem" | base64) } setup() { - load "${BATS_LIB_PATH}/bats-support/load.bash" - load "${BATS_LIB_PATH}/bats-assert/load.bash" - - # invoke binary with credentials - run_otdfctl_key() { - run sh -c "./otdfctl policy kas-registry key $HOST $WITH_CREDS $*" - } + # No setup specific to individual tests needed here currently + : # No-op } teardown_file() { - ./otdctl keymanagement provider "$HOST" "$WITH_CREDS" delete --id "$PC_ID" + ./otdfctl keymanagement provider "$HOST" "$WITH_CREDS" delete --id "$PC_ID" # Cannot cleanup KAS registry and keys, since keys cannot be deleted currently. unset HOST WITH_CREDS KAS_REGISTRY_ID KAS_NAME KAS_URI PEM_B64 WRAPPING_KEY PC_ID } @@ -314,6 +331,23 @@ format_kas_name_as_uri() { assert_output --partial "Invalid mode" } +@test "kas-keys: create key (duplicate key-id)" { + KEY_ID_DUPLICATE=$(generate_key_id) + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID_DUPLICATE}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json + assert_success + + run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID_DUPLICATE}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json + assert_failure + assert_output --partial "Failed to create kas key" +} + +@test "kas-keys: create key (invalid kas identifier)" { + KEY_ID=$(generate_key_id) + run_otdfctl_key create --kas "invalid-kas-id" --key-id "${KEY_ID}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json + assert_failure + assert_output --partial "Failed to resolve KAS identifier 'invalid-kas-id': not_found: resource not found" +} + @test "kas-keys: get key by system ID" { KEY_ID_GET=$(generate_key_id) run_otdfctl_key create --kas "${KAS_REGISTRY_ID}" --key-id "${KEY_ID_GET}" --algorithm "rsa:2048" --mode "public_key" --public-key-pem "${PEM_B64}" --json diff --git a/pkg/handlers/kas-registry.go b/pkg/handlers/kas-registry.go index 68bd5b05..13d702c6 100644 --- a/pkg/handlers/kas-registry.go +++ b/pkg/handlers/kas-registry.go @@ -15,19 +15,6 @@ type KasIdentifier struct { URI string } -func (k KasIdentifier) GetIdentifierValue() string { - if k.ID != "" { - return k.ID - } - if k.Name != "" { - return k.Name - } - if k.URI != "" { - return k.URI - } - return "" -} - func (h Handler) GetKasRegistryEntry(ctx context.Context, identifer KasIdentifier) (*policy.KeyAccessServer, error) { req := &kasregistry.GetKeyAccessServerRequest{} switch { From 63f034f63d3ccd7d1ca280c9873397720e7171ac Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 18:04:27 -0400 Subject: [PATCH 25/27] remove unused ctx --- cmd/kas-keys.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cmd/kas-keys.go b/cmd/kas-keys.go index 9b1e1df7..67b3d870 100644 --- a/cmd/kas-keys.go +++ b/cmd/kas-keys.go @@ -1,7 +1,6 @@ package cmd import ( - "context" "encoding/base64" "errors" "fmt" @@ -345,7 +344,7 @@ func policyCreateKasKey(cmd *cobra.Command, args []string) { cli.ExitWithError("Invalid mode", nil) } - kasLookup, err := resolveKasIdentifier(c.Context(), kasIdentifier, h) + kasLookup, err := resolveKasIdentifier(kasIdentifier, h) if err != nil { cli.ExitWithError("Invalid kas identifier", err) } @@ -463,7 +462,7 @@ func policyListKasKeys(cmd *cobra.Command, args []string) { } kasIdentifier := c.Flags.GetOptionalString("kas") - kasLookup, err := resolveKasIdentifier(c.Context(), kasIdentifier, h) + kasLookup, err := resolveKasIdentifier(kasIdentifier, h) if err != nil { cli.ExitWithError("Invalid kas identifier", err) } @@ -540,7 +539,7 @@ func policyListKasKeys(cmd *cobra.Command, args []string) { HandleSuccess(cmd, "", t, keys) } -func resolveKasIdentifier(ctx context.Context, ident string, h handlers.Handler) (handlers.KasIdentifier, error) { +func resolveKasIdentifier(ident string, h handlers.Handler) (handlers.KasIdentifier, error) { // If the identifier is empty, it means no KAS filter is applied. // Return an empty KasIdentifier and no error. if ident == "" { From 56f8ad2633e63d5aedc742898de7e528b3f3bb8e Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 18:06:49 -0400 Subject: [PATCH 26/27] fix lint issue --- cmd/kas-keys.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/kas-keys.go b/cmd/kas-keys.go index 67b3d870..2bb9a00a 100644 --- a/cmd/kas-keys.go +++ b/cmd/kas-keys.go @@ -344,7 +344,7 @@ func policyCreateKasKey(cmd *cobra.Command, args []string) { cli.ExitWithError("Invalid mode", nil) } - kasLookup, err := resolveKasIdentifier(kasIdentifier, h) + kasLookup, err := resolveKasIdentifier(kasIdentifier) if err != nil { cli.ExitWithError("Invalid kas identifier", err) } @@ -462,7 +462,7 @@ func policyListKasKeys(cmd *cobra.Command, args []string) { } kasIdentifier := c.Flags.GetOptionalString("kas") - kasLookup, err := resolveKasIdentifier(kasIdentifier, h) + kasLookup, err := resolveKasIdentifier(kasIdentifier) if err != nil { cli.ExitWithError("Invalid kas identifier", err) } @@ -539,7 +539,7 @@ func policyListKasKeys(cmd *cobra.Command, args []string) { HandleSuccess(cmd, "", t, keys) } -func resolveKasIdentifier(ident string, h handlers.Handler) (handlers.KasIdentifier, error) { +func resolveKasIdentifier(ident string) (handlers.KasIdentifier, error) { // If the identifier is empty, it means no KAS filter is applied. // Return an empty KasIdentifier and no error. if ident == "" { From d19899b0da17abe47ff27cfb06b8ad5e184feb1f Mon Sep 17 00:00:00 2001 From: strantalis Date: Mon, 2 Jun 2025 20:54:34 -0400 Subject: [PATCH 27/27] minor cleanup based on feedback --- cmd/base-keys.go | 27 ++++++------------- docs/man/policy/kas-registry/key/_index.md | 4 --- .../policy/kas-registry/key/base/_index.md | 4 --- 3 files changed, 8 insertions(+), 27 deletions(-) diff --git a/cmd/base-keys.go b/cmd/base-keys.go index fd8ce7a5..1bfcd9aa 100644 --- a/cmd/base-keys.go +++ b/cmd/base-keys.go @@ -1,7 +1,6 @@ package cmd import ( - "errors" "fmt" "github.com/evertras/bubble-table/table" @@ -29,33 +28,23 @@ const ( var policyKasRegistryBaseKeysCmd *cobra.Command func getKasKeyIdentifier(c *cli.Cli) (*kasregistry.KasKeyIdentifier, error) { - // This function is called when the user provides a human-readable key ID - // via the --key flag and identifies the KAS it belongs to via the --kas flag. - humanReadableKeyID := c.Flags.GetRequiredString("key") // Flag for the key's human-readable ID - kasIdentifierInput := c.Flags.GetRequiredString("kas") // Flag for KAS ID, URI, or Name - - // Basic validation, though GetRequiredString should handle empty inputs. - if humanReadableKeyID == "" { - return nil, errors.New("--key (human-readable key ID) cannot be empty") - } - if kasIdentifierInput == "" { - return nil, errors.New("--kas (KAS identifier) cannot be empty") - } + keyIdentifier := c.Flags.GetRequiredString("key") + kasIdentifier := c.Flags.GetRequiredString("kas") identifier := &kasregistry.KasKeyIdentifier{ - Kid: humanReadableKeyID, + Kid: keyIdentifier, } - kasInputType := utils.ClassifyString(kasIdentifierInput) + kasInputType := utils.ClassifyString(kasIdentifier) switch kasInputType { //nolint:exhaustive // default catches unknown case utils.StringTypeUUID: - identifier.Identifier = &kasregistry.KasKeyIdentifier_KasId{KasId: kasIdentifierInput} + identifier.Identifier = &kasregistry.KasKeyIdentifier_KasId{KasId: kasIdentifier} case utils.StringTypeURI: - identifier.Identifier = &kasregistry.KasKeyIdentifier_Uri{Uri: kasIdentifierInput} + identifier.Identifier = &kasregistry.KasKeyIdentifier_Uri{Uri: kasIdentifier} case utils.StringTypeGeneric: - identifier.Identifier = &kasregistry.KasKeyIdentifier_Name{Name: kasIdentifierInput} + identifier.Identifier = &kasregistry.KasKeyIdentifier_Name{Name: kasIdentifier} default: // Catches StringTypeUnknown and any other unexpected types - return nil, fmt.Errorf("invalid KAS identifier: '%s'. Must be a KAS UUID, URI, or Name", kasIdentifierInput) + return nil, fmt.Errorf("invalid KAS identifier: '%s'. Must be a KAS UUID, URI, or Name", kasIdentifier) } return identifier, nil } diff --git a/docs/man/policy/kas-registry/key/_index.md b/docs/man/policy/kas-registry/key/_index.md index f2b727cb..e79efaaf 100644 --- a/docs/man/policy/kas-registry/key/_index.md +++ b/docs/man/policy/kas-registry/key/_index.md @@ -6,10 +6,6 @@ command: hidden: true aliases: - k - flags: - - name: json - description: Output the result of a subcommand in JSON format (overrides configured output format). This is an inherited flag. - default: 'false' --- Provides a set of subcommands for managing cryptographic keys within the Key Access Server (KAS) registry. diff --git a/docs/man/policy/kas-registry/key/base/_index.md b/docs/man/policy/kas-registry/key/base/_index.md index 8be6308c..c900fca8 100644 --- a/docs/man/policy/kas-registry/key/base/_index.md +++ b/docs/man/policy/kas-registry/key/base/_index.md @@ -4,10 +4,6 @@ title: Platform Base Key Management command: name: base hidden: true - flags: - - name: json - description: Output the result of a subcommand in JSON format (overrides configured output format). This is an inherited flag. - default: 'false' --- Provides subcommands for managing the platform's base cryptographic key.