diff --git a/.gitignore b/.gitignore index 16ecfd88..9d626514 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ bin/.DS_Store .DS_Store target/ .vscode/launch.json +tructl.yaml \ No newline at end of file diff --git a/README.md b/README.md index 8145d4f9..83a1be5c 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,10 @@ The main goals are to: ## Usage +The CLI is configured via the `tructl.yaml`. There is an example provided in `example-tructl.yaml`. + +Run `cp example-tructl.yaml tructl.yaml` to copy the example config when running the CLI. + ## Development ### CLI diff --git a/cmd/dev.go b/cmd/dev.go index e4264ff9..490d79fa 100644 --- a/cmd/dev.go +++ b/cmd/dev.go @@ -78,8 +78,8 @@ func unMarshalMetadata(m string) *common.MetadataMutable { return nil } -func getMetadata(labels []string) *common.MetadataMutable { - var metadata *common.MetadataMutable +func getMetadataMutable(labels []string) *common.MetadataMutable { + metadata := common.MetadataMutable{} if len(labels) > 0 { metadata.Labels = map[string]string{} for _, label := range labels { @@ -89,7 +89,7 @@ func getMetadata(labels []string) *common.MetadataMutable { } metadata.Labels[kv[0]] = kv[1] } - return metadata + return &metadata } return nil } @@ -114,6 +114,14 @@ func HandleSuccess(command *cobra.Command, id string, t *table.Table, policyObje cli.PrintSuccessTable(command, id, t) } +// Adds reusable create/update label flags to a Policy command and the optional force-replace-labels flag for updates only +func injectLabelFlags(cmd *cobra.Command, isUpdate bool) { + cmd.Flags().StringSliceVarP(&metadataLabels, "label", "l", []string{}, "Optional metadata 'labels' in the format: key=value") + if isUpdate { + cmd.Flags().BoolVar(&forceReplaceMetadataLabels, "force-replace-labels", false, "Destructively replace entire set of existing metadata 'labels' with any provided to this command.") + } +} + func init() { rootCmd.AddCommand(devCmd) devCmd.AddCommand(designCmd) diff --git a/cmd/kas-registry.go b/cmd/kas-registry.go new file mode 100644 index 00000000..ba3a3231 --- /dev/null +++ b/cmd/kas-registry.go @@ -0,0 +1,270 @@ +package cmd + +import ( + "fmt" + "strings" + + "github.com/opentdf/platform/protocol/go/kasregistry" + "github.com/opentdf/tructl/pkg/cli" + "github.com/spf13/cobra" +) + +var ( + kasRegistry_crudCommands = []string{ + kasRegistrysCreateCmd.Use, + kasRegistryGetCmd.Use, + kasRegistrysListCmd.Use, + kasRegistryUpdateCmd.Use, + kasRegistryDeleteCmd.Use, + } + + // KasRegistryCmd is the command for managing KAS registrations + kasRegistryCmd = &cobra.Command{ + Use: "kas-registry", + Short: "Manage Key Access Server registrations [" + strings.Join(kasRegistry_crudCommands, ", ") + "]", + Long: ` + Manage Key Access Server registrations within the platform. + + The Key Access Server (KAS) registry is a record of servers granting and maintaining public keys. The registry contains critical + information like each server's uri, its public key (which can be either local or at a remote uri), and any metadata about the server. + Key Access Servers grant keys for specified Attributes and their Values via Attribute Key Access Grants and Attribute Value + Key Access Grants. + `, + } + + kasRegistryGetCmd = &cobra.Command{ + Use: "get", + Short: "Get a registered Key Access Server by id", + Run: func(cmd *cobra.Command, args []string) { + h := cli.NewHandler(cmd) + defer h.Close() + + flagHelper := cli.NewFlagHelper(cmd) + id := flagHelper.GetRequiredString("id") + + kas, err := h.GetKasRegistryEntry(id) + if err != nil { + errMsg := fmt.Sprintf("Could not find KAS registry entry (%s)", id) + cli.ExitWithNotFoundError(errMsg, err) + } + + keyType := "Local" + key := kas.PublicKey.GetLocal() + if kas.PublicKey.GetRemote() != "" { + keyType = "Remote" + key = kas.PublicKey.GetRemote() + } + + t := cli.NewTabular(). + Rows([][]string{ + {"Id", kas.Id}, + // TODO: render labels [https://github.com/opentdf/tructl/issues/73] + {"URI", kas.Uri}, + {"PublicKey Type", keyType}, + {"PublicKey", key}, + }...) + HandleSuccess(cmd, kas.Id, t, kas) + }, + } + + kasRegistrysListCmd = &cobra.Command{ + Use: "list", + Short: "List KAS registry entries", + Run: func(cmd *cobra.Command, args []string) { + h := cli.NewHandler(cmd) + defer h.Close() + + list, err := h.ListKasRegistryEntries() + if err != nil { + cli.ExitWithError("Could not get KAS registry entries", err) + } + + t := cli.NewTable() + t.Headers("Id", "URI", "PublicKey Location", "PublicKey") + for _, kas := range list { + keyType := "Local" + key := kas.PublicKey.GetLocal() + if kas.PublicKey.GetRemote() != "" { + keyType = "Remote" + key = kas.PublicKey.GetRemote() + } + + t.Row( + kas.Id, + kas.Uri, + keyType, + key, + // TODO: render labels [https://github.com/opentdf/tructl/issues/73] + ) + } + HandleSuccess(cmd, "", t, list) + }, + } + + kasRegistrysCreateCmd = &cobra.Command{ + Use: "create", + Short: "Create a new KAS registry entry, i.e. 'https://example.com'", + Run: func(cmd *cobra.Command, args []string) { + h := cli.NewHandler(cmd) + defer h.Close() + + flagHelper := cli.NewFlagHelper(cmd) + uri := flagHelper.GetRequiredString("uri") + local := flagHelper.GetOptionalString("public-key-local") + remote := flagHelper.GetOptionalString("public-key-remote") + metadataLabels := flagHelper.GetStringSlice("label", metadataLabels, cli.FlagHelperStringSliceOptions{Min: 0}) + + if local == "" && remote == "" { + e := fmt.Errorf("A public key is required. Please pass either a local or remote public key") + cli.ExitWithError("Issue with create flags 'public-key-local' and 'public-key-remote': ", e) + } + + key := &kasregistry.PublicKey{} + keyType := "Local" + if local != "" { + if remote != "" { + e := fmt.Errorf("Only one public key is allowed. Please pass either a local or remote public key but not both") + cli.ExitWithError("Issue with create flags 'public-key-local' and 'public-key-remote': ", e) + } + key.PublicKey = &kasregistry.PublicKey_Local{Local: local} + } else { + keyType = "Remote" + key.PublicKey = &kasregistry.PublicKey_Remote{Remote: remote} + } + + created, err := h.CreateKasRegistryEntry( + uri, + key, + getMetadataMutable(metadataLabels), + ) + if err != nil { + cli.ExitWithError("Could not create KAS registry entry", err) + } + + t := cli.NewTabular(). + Rows([][]string{ + {"Id", created.Id}, + {"URI", created.Uri}, + {"PublicKey Type", keyType}, + {"PublicKey", local}, + // TODO: render labels [https://github.com/opentdf/tructl/issues/73] + }...) + + HandleSuccess(cmd, created.Id, t, created) + }, + } + + // Update one KAS registry entry + kasRegistryUpdateCmd = &cobra.Command{ + Use: "update", + Short: "Update a KAS registry entry", + Run: func(cmd *cobra.Command, args []string) { + h := cli.NewHandler(cmd) + defer h.Close() + + flagHelper := cli.NewFlagHelper(cmd) + + id := flagHelper.GetRequiredString("id") + uri := flagHelper.GetOptionalString("uri") + local := flagHelper.GetOptionalString("public-key-local") + remote := flagHelper.GetOptionalString("public-key-remote") + labels := flagHelper.GetStringSlice("label", metadataLabels, cli.FlagHelperStringSliceOptions{Min: 0}) + + if local == "" && remote == "" && len(labels) == 0 && uri == "" { + cli.ExitWithError("No values were passed to update. Please pass at least one value to update (E.G. 'uri', 'public-key-local', 'public-key-remote', 'label')", nil) + } + + // TODO: should update of a type of key be a dangerous mutation or cause a need for confirmation in the CLI? + var pubKey *kasregistry.PublicKey + if local != "" && remote != "" { + e := fmt.Errorf("Only one public key is allowed. Please pass either a local or remote public key but not both") + cli.ExitWithError("Issue with update flags 'public-key-local' and 'public-key-remote': ", e) + } else if local != "" { + pubKey = &kasregistry.PublicKey{PublicKey: &kasregistry.PublicKey_Local{Local: local}} + } else if remote != "" { + pubKey = &kasregistry.PublicKey{PublicKey: &kasregistry.PublicKey_Remote{Remote: remote}} + } + + updated, err := h.UpdateKasRegistryEntry( + id, + uri, + pubKey, + getMetadataMutable(labels), + getMetadataUpdateBehavior(), + ) + if err != nil { + cli.ExitWithError("Could not update KAS registry entry", err) + } + t := cli.NewTabular(). + Rows([][]string{ + {"Id", id}, + {"URI", uri}, + // TODO: render labels [https://github.com/opentdf/tructl/issues/73] + }...) + HandleSuccess(cmd, id, t, updated) + }, + } + + kasRegistryDeleteCmd = &cobra.Command{ + Use: "delete", + Short: "Delete a KAS registry entry by id", + Run: func(cmd *cobra.Command, args []string) { + h := cli.NewHandler(cmd) + defer h.Close() + + flagHelper := cli.NewFlagHelper(cmd) + id := flagHelper.GetRequiredString("id") + + kas, err := h.GetKasRegistryEntry(id) + if err != nil { + errMsg := fmt.Sprintf("Could not find KAS registry entry (%s)", id) + cli.ExitWithNotFoundError(errMsg, err) + } + + cli.ConfirmDelete("KAS Registry Entry: ", id) + + if err := h.DeleteKasRegistryEntry(id); err != nil { + errMsg := fmt.Sprintf("Could not delete KAS registry entry (%s)", id) + cli.ExitWithError(errMsg, err) + } + + t := cli.NewTabular(). + Rows([][]string{ + {"Id", kas.Id}, + {"URI", kas.Uri}, + }...) + + HandleSuccess(cmd, kas.Id, t, kas) + }, + } +) + +func init() { + policyCmd.AddCommand(kasRegistryCmd) + + kasRegistryCmd.AddCommand(kasRegistryGetCmd) + kasRegistryGetCmd.Flags().StringP("id", "i", "", "Id of the KAS registry entry") + + kasRegistryCmd.AddCommand(kasRegistrysListCmd) + // TODO: active, inactive, any state querying [https://github.com/opentdf/tructl/issues/68] + + kasRegistryCmd.AddCommand(kasRegistrysCreateCmd) + kasRegistrysCreateCmd.Flags().StringP("uri", "u", "", "The URI of the KAS registry entry") + kasRegistrysCreateCmd.Flags().StringP("public-key-local", "p", "", "A local public key for the registered Key Access Server (KAS)") + kasRegistrysCreateCmd.Flags().StringP("public-key-remote", "r", "", "A remote endpoint that provides a public key for the registered Key Access Server (KAS)") + injectLabelFlags(kasRegistrysCreateCmd, false) + + kasRegistryCmd.AddCommand(kasRegistryUpdateCmd) + kasRegistryUpdateCmd.Flags().StringP("id", "i", "", "Id of the KAS registry entry") + kasRegistryUpdateCmd.Flags().StringP("uri", "u", "", "The URI of the KAS registry entry") + kasRegistryUpdateCmd.Flags().StringP("public-key-local", "p", "", "A local public key for the registered Key Access Server (KAS)") + kasRegistryUpdateCmd.Flags().StringP("public-key-remote", "r", "", "A remote endpoint that serves a public key for the registered Key Access Server (KAS)") + injectLabelFlags(kasRegistryUpdateCmd, true) + + kasRegistryCmd.AddCommand(kasRegistryDeleteCmd) + kasRegistryDeleteCmd.Flags().StringP("id", "i", "", "Id of the KAS registry entry") +} + +func init() { + rootCmd.AddCommand(kasRegistryCmd) +} diff --git a/cmd/policy-attributes.go b/cmd/policy-attributes.go index c271d901..df16187e 100644 --- a/cmd/policy-attributes.go +++ b/cmd/policy-attributes.go @@ -50,7 +50,7 @@ used to define the access controls based on subject encodings and entity entitle namespace := flagHelper.GetRequiredString("namespace") metadataLabels := flagHelper.GetStringSlice("label", metadataLabels, cli.FlagHelperStringSliceOptions{Min: 0}) - attr, err := h.CreateAttribute(name, rule, namespace, getMetadata(metadataLabels)) + attr, err := h.CreateAttribute(name, rule, namespace, getMetadataMutable(metadataLabels)) if err != nil { cli.ExitWithError("Could not create attribute", err) } @@ -106,7 +106,6 @@ used to define the access controls based on subject encodings and entity entitle if err != nil { errMsg := fmt.Sprintf("Could not find attribute (%s)", id) cli.ExitWithNotFoundError(errMsg, err) - cli.ExitWithError(errMsg, err) } a := cli.GetSimpleAttribute(attr) @@ -118,7 +117,7 @@ used to define the access controls based on subject encodings and entity entitle {"Values", cli.CommaSeparated(a.Values)}, {"Namespace", a.Namespace}, }...) - HandleSuccess(cmd, a.Id, t, a) + HandleSuccess(cmd, a.Id, t, attr) }, } @@ -165,7 +164,6 @@ used to define the access controls based on subject encodings and entity entitle if err != nil { errMsg := fmt.Sprintf("Could not find attribute (%s)", id) cli.ExitWithNotFoundError(errMsg, err) - cli.ExitWithError(errMsg, err) } cli.ConfirmDelete("attribute", attr.Name) @@ -174,7 +172,6 @@ used to define the access controls based on subject encodings and entity entitle if err != nil { errMsg := fmt.Sprintf("Could not deactivate attribute (%s)", id) cli.ExitWithNotFoundError(errMsg, err) - cli.ExitWithError(errMsg, err) } a := cli.GetSimpleAttribute(attr) @@ -201,7 +198,7 @@ used to define the access controls based on subject encodings and entity entitle id := flagHelper.GetRequiredString("id") labels := flagHelper.GetStringSlice("label", metadataLabels, cli.FlagHelperStringSliceOptions{Min: 0}) - if a, err := h.UpdateAttribute(id, getMetadata(labels), getMetadataUpdateBehavior()); err != nil { + if a, err := h.UpdateAttribute(id, getMetadataMutable(labels), getMetadataUpdateBehavior()); err != nil { cli.ExitWithError("Could not update attribute", err) } else { HandleSuccess(cmd, id, nil, a) @@ -220,7 +217,7 @@ func init() { policy_attributesCreateCmd.Flags().StringSliceVarP(&attrValues, "values", "v", []string{}, "Values of the attribute") policy_attributesCreateCmd.Flags().StringP("namespace", "s", "", "Namespace of the attribute") policy_attributesCreateCmd.Flags().StringP("description", "d", "", "Description of the attribute") - policy_attributesCreateCmd.Flags().StringSliceVarP(&metadataLabels, "label", "l", []string{}, "Labels for the attribute") + injectLabelFlags(policy_attributesCreateCmd, false) // Get an attribute policy_attributesCmd.AddCommand(policy_attributeGetCmd) @@ -232,8 +229,7 @@ func init() { // Update an attribute policy_attributesCmd.AddCommand(policy_attributeUpdateCmd) policy_attributeUpdateCmd.Flags().StringP("id", "i", "", "Id of the attribute") - policy_attributeUpdateCmd.Flags().StringSliceVarP(&metadataLabels, "label", "l", []string{}, "Optional new metadata 'labels' in the format: key=value") - policy_attributeUpdateCmd.Flags().BoolVar(&forceReplaceMetadataLabels, "force-replace-labels", false, "Destructively replace entire set of existing metadata 'labels' with any provided to this command.") + injectLabelFlags(policy_attributeUpdateCmd, true) // Delete an attribute policy_attributesCmd.AddCommand(policy_attributesDeleteCmd) diff --git a/cmd/policy-namespaces.go b/cmd/policy-namespaces.go index bd9abafa..a7d6e59a 100644 --- a/cmd/policy-namespaces.go +++ b/cmd/policy-namespaces.go @@ -45,7 +45,6 @@ or different attributes tied to each. if err != nil { errMsg := fmt.Sprintf("Could not find namespace (%s)", id) cli.ExitWithNotFoundError(errMsg, err) - cli.ExitWithError(errMsg, err) } t := cli.NewTabular(). @@ -92,7 +91,7 @@ or different attributes tied to each. name := flagHelper.GetRequiredString("name") metadataLabels := flagHelper.GetStringSlice("label", metadataLabels, cli.FlagHelperStringSliceOptions{Min: 0}) - created, err := h.CreateNamespace(name, getMetadata(metadataLabels)) + created, err := h.CreateNamespace(name, getMetadataMutable(metadataLabels)) if err != nil { cli.ExitWithError("Could not create namespace", err) } @@ -119,7 +118,6 @@ or different attributes tied to each. if err != nil { errMsg := fmt.Sprintf("Could not find namespace (%s)", id) cli.ExitWithNotFoundError(errMsg, err) - cli.ExitWithError(errMsg, err) } cli.ConfirmDelete("namespace", ns.Name) @@ -127,7 +125,6 @@ or different attributes tied to each. if err := h.DeactivateNamespace(id); err != nil { errMsg := fmt.Sprintf("Could not deactivate namespace (%s)", id) cli.ExitWithNotFoundError(errMsg, err) - cli.ExitWithError(errMsg, err) } t := cli.NewTabular(). @@ -153,7 +150,7 @@ or different attributes tied to each. ns, err := h.UpdateNamespace( id, - getMetadata(labels), + getMetadataMutable(labels), getMetadataUpdateBehavior(), ) if err != nil { @@ -179,12 +176,11 @@ func init() { policy_namespacesCmd.AddCommand(policy_namespacesCreateCmd) policy_namespacesCreateCmd.Flags().StringP("name", "n", "", "Name value of the namespace") - policy_namespacesCreateCmd.Flags().StringSliceVarP(&metadataLabels, "label", "l", []string{}, "Optional metadata 'labels' in the format: key=value") + injectLabelFlags(policy_namespacesCreateCmd, false) policy_namespacesCmd.AddCommand(policy_namespaceUpdateCmd) policy_namespaceUpdateCmd.Flags().StringP("id", "i", "", "Id of the namespace") - policy_namespaceUpdateCmd.Flags().StringSliceVarP(&metadataLabels, "label", "l", []string{}, "Optional new metadata 'labels' in the format: key=value") - policy_namespaceUpdateCmd.Flags().BoolVar(&forceReplaceMetadataLabels, "force-replace-labels", false, "Destructively replace entire set of existing metadata 'labels' with any provided to this command.") + injectLabelFlags(policy_namespaceUpdateCmd, true) policy_namespacesCmd.AddCommand(policy_namespaceDeleteCmd) policy_namespaceDeleteCmd.Flags().StringP("id", "i", "", "Id of the namespace") diff --git a/cmd/policy-resource_mappings.go b/cmd/policy-resource_mappings.go index 8fe9bc68..01ad5f34 100644 --- a/cmd/policy-resource_mappings.go +++ b/cmd/policy-resource_mappings.go @@ -41,7 +41,7 @@ var ( }) metadataLabels := flagHelper.GetStringSlice("label", metadataLabels, cli.FlagHelperStringSliceOptions{Min: 0}) - resourceMapping, err := h.CreateResourceMapping(attrId, terms, getMetadata(metadataLabels)) + resourceMapping, err := h.CreateResourceMapping(attrId, terms, getMetadataMutable(metadataLabels)) if err != nil { cli.ExitWithError("Failed to create resource mapping", err) } @@ -115,7 +115,7 @@ var ( terms := flagHelper.GetStringSlice("terms", policy_resource_mappingsTerms, cli.FlagHelperStringSliceOptions{}) labels := flagHelper.GetStringSlice("label", metadataLabels, cli.FlagHelperStringSliceOptions{Min: 0}) - resourceMapping, err := h.UpdateResourceMapping(id, attrValueId, terms, getMetadata(labels), getMetadataUpdateBehavior()) + resourceMapping, err := h.UpdateResourceMapping(id, attrValueId, terms, getMetadataMutable(labels), getMetadataUpdateBehavior()) if err != nil { cli.ExitWithError("Failed to update resource mapping", err) } @@ -164,7 +164,7 @@ func init() { policy_resource_mappingsCmd.AddCommand(policy_resource_mappingsCreateCmd) policy_resource_mappingsCreateCmd.Flags().String("attribute-value-id", "", "Attribute Value ID") policy_resource_mappingsCreateCmd.Flags().StringSliceVar(&policy_resource_mappingsTerms, "terms", []string{}, "Synonym terms") - policy_resource_mappingsCreateCmd.Flags().StringSliceVarP(&metadataLabels, "label", "l", []string{}, "Optional metadata 'labels' in the format: key=value") + injectLabelFlags(policy_resource_mappingsCreateCmd, false) policy_resource_mappingsCmd.AddCommand(policy_resource_mappingsGetCmd) policy_resource_mappingsGetCmd.Flags().String("id", "", "Resource Mapping ID") @@ -175,8 +175,7 @@ func init() { policy_resource_mappingsUpdateCmd.Flags().String("id", "", "Resource Mapping ID") policy_resource_mappingsUpdateCmd.Flags().String("attribute-value-id", "", "Attribute Value ID") policy_resource_mappingsUpdateCmd.Flags().StringSliceVar(&policy_resource_mappingsTerms, "terms", []string{}, "Synonym terms") - policy_resource_mappingsUpdateCmd.Flags().StringSliceVarP(&metadataLabels, "label", "l", []string{}, "Optional metadata 'labels' in the format: key=value") - policy_resource_mappingsUpdateCmd.Flags().BoolVar(&forceReplaceMetadataLabels, "force-replace-labels", false, "Destructively replace entire set of existing metadata 'labels' with any provided to this command.") + injectLabelFlags(policy_resource_mappingsUpdateCmd, true) policy_resource_mappingsCmd.AddCommand(policy_resource_mappingsDeleteCmd) policy_resource_mappingsDeleteCmd.Flags().String("id", "", "Resource Mapping ID") diff --git a/cmd/policy-subject_mappings.go b/cmd/policy-subject_mappings.go index ac9077ae..26de4bb0 100644 --- a/cmd/policy-subject_mappings.go +++ b/cmd/policy-subject_mappings.go @@ -61,7 +61,6 @@ Note: SubjectConditionSets are reusable among SubjectMappings and are available if err != nil { errMsg := fmt.Sprintf("Could not find subject mapping (%s)", id) cli.ExitWithNotFoundError(errMsg, err) - cli.ExitWithError(errMsg, err) } var actionsJSON []byte @@ -161,7 +160,7 @@ Note: SubjectConditionSets are reusable among SubjectMappings and are available } actions := getFullActionsList(standardActions, customActions) - mapping, err := h.CreateNewSubjectMapping(attrValueId, actions, existingSCSId, nil, getMetadata(metadataLabels)) + mapping, err := h.CreateNewSubjectMapping(attrValueId, actions, existingSCSId, nil, getMetadataMutable(metadataLabels)) if err != nil { cli.ExitWithError("Could not create subject mapping", err) } @@ -208,7 +207,6 @@ Note: SubjectConditionSets are reusable among SubjectMappings and are available if err != nil { errMsg := fmt.Sprintf("Could not find subject mapping (%s)", id) cli.ExitWithNotFoundError(errMsg, err) - cli.ExitWithError(errMsg, err) } cli.ConfirmDelete("subject mapping", sm.Id) @@ -217,7 +215,6 @@ Note: SubjectConditionSets are reusable among SubjectMappings and are available if err != nil { errMsg := fmt.Sprintf("Could not delete subject mapping (%s)", id) cli.ExitWithNotFoundError(errMsg, err) - cli.ExitWithError(errMsg, err) } HandleSuccess(cmd, id, nil, deleted) }, @@ -255,7 +252,7 @@ full set of actions on update. `, id, scsId, actions, - getMetadata(labels), + getMetadataMutable(labels), getMetadataUpdateBehavior(), ) if err != nil { @@ -312,15 +309,14 @@ func init() { policy_subject_mappingCreateCmd.Flags().String("subject-condition-set-id", "", "Pre-existing Subject Condition Set Id") // TODO: do we need to support creating a SM & SCS simultaneously? If so, it gets more complex. // policy_subject_mappingCreateCmd.Flags().StringP("new-subject-condition-set", "scs", "", "New Subject Condition Set (optional)") - policy_subject_mappingCreateCmd.Flags().StringSliceVarP(&metadataLabels, "label", "l", []string{}, "Optional metadata 'labels' in the format: key=value") + injectLabelFlags(policy_subject_mappingCreateCmd, false) policy_subject_mappingsCmd.AddCommand(policy_subject_mappingUpdateCmd) policy_subject_mappingUpdateCmd.Flags().StringP("id", "i", "", "Id of the subject mapping") policy_subject_mappingUpdateCmd.Flags().StringSliceVarP(&standardActions, "action-standard", "s", []string{}, "Standard Action: [DECRYPT, TRANSMIT]. Note: destructively replaces existing Actions.") policy_subject_mappingUpdateCmd.Flags().StringSliceVarP(&customActions, "action-custom", "c", []string{}, "Custom Action. Note: destructively replaces existing Actions.") policy_subject_mappingUpdateCmd.Flags().String("subject-condition-set-id", "", "Updated Subject Condition Set Id") - policy_subject_mappingUpdateCmd.Flags().StringSliceVarP(&metadataLabels, "label", "l", []string{}, "Optional new metadata 'labels' in the format: key=value") - policy_subject_mappingUpdateCmd.Flags().BoolVar(&forceReplaceMetadataLabels, "force-replace-labels", false, "Destructively replace entire set of existing metadata 'labels' with any provided to this command.") + injectLabelFlags(policy_subject_mappingUpdateCmd, true) policy_subject_mappingsCmd.AddCommand(policy_subject_mappingDeleteCmd) policy_subject_mappingDeleteCmd.Flags().StringP("id", "i", "", "Id of the subject mapping") diff --git a/example-tructl.yaml b/example-tructl.yaml new file mode 100644 index 00000000..bc036821 --- /dev/null +++ b/example-tructl.yaml @@ -0,0 +1,3 @@ +output: + # acceptable formats: json or styled + format: styled diff --git a/pkg/handlers/kas-registry.go b/pkg/handlers/kas-registry.go index 07416006..4bd02a7b 100644 --- a/pkg/handlers/kas-registry.go +++ b/pkg/handlers/kas-registry.go @@ -1,7 +1,7 @@ package handlers import ( - common "github.com/opentdf/platform/protocol/go/common" + "github.com/opentdf/platform/protocol/go/common" "github.com/opentdf/platform/protocol/go/kasregistry" ) @@ -17,9 +17,7 @@ func (h Handler) GetKasRegistryEntry(id string) (*kasregistry.KeyAccessServer, e } func (h Handler) ListKasRegistryEntries() ([]*kasregistry.KeyAccessServer, error) { - req := &kasregistry.ListKeyAccessServersRequest{} - - resp, err := h.sdk.KeyAccessServerRegistry.ListKeyAccessServers(h.ctx, req) + resp, err := h.sdk.KeyAccessServerRegistry.ListKeyAccessServers(h.ctx, &kasregistry.ListKeyAccessServersRequest{}) if err != nil { return nil, err } @@ -42,9 +40,14 @@ func (h Handler) CreateKasRegistryEntry(uri string, publicKey *kasregistry.Publi return resp.KeyAccessServer, nil } -// TODO: verify updation behavior -func (h Handler) UpdateKasRegistryEntry(id string, kasUpdateReq *kasregistry.UpdateKeyAccessServerRequest) (*kasregistry.KeyAccessServer, error) { - resp, err := h.sdk.KeyAccessServerRegistry.UpdateKeyAccessServer(h.ctx, kasUpdateReq) +func (h Handler) UpdateKasRegistryEntry(id string, uri string, publickey *kasregistry.PublicKey, metadata *common.MetadataMutable, behavior common.MetadataUpdateEnum) (*kasregistry.KeyAccessServer, error) { + resp, err := h.sdk.KeyAccessServerRegistry.UpdateKeyAccessServer(h.ctx, &kasregistry.UpdateKeyAccessServerRequest{ + Id: id, + Uri: uri, + PublicKey: publickey, + Metadata: metadata, + MetadataUpdateBehavior: behavior, + }) if err != nil { return nil, err } diff --git a/tructl.yaml b/tructl.yaml deleted file mode 100644 index 5dedadc4..00000000 --- a/tructl.yaml +++ /dev/null @@ -1,2 +0,0 @@ -output: - format: styled