Skip to content
144 changes: 144 additions & 0 deletions cmd/kas-grants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package cmd

import (
"strings"

"github.com/opentdf/tructl/pkg/cli"
"github.com/spf13/cobra"
)

var (
kasGrants_crudCommands = []string{
kasGrantsUpdateCmd.Use,
kasGrantsDeleteCmd.Use,
}

// KasGrantsCmd is the command for managing KAS grants
kasGrantsCmd = &cobra.Command{
Use: "kas-grants",
Short: "Manage Key Access Server grants [" + strings.Join(kasGrants_crudCommands, ", ") + "]",
}

// Update one KAS registry entry
kasGrantsUpdateCmd = &cobra.Command{
Use: "update",
Short: "Update a KAS grant",
Run: func(cmd *cobra.Command, args []string) {
h := cli.NewHandler(cmd)
defer h.Close()

flagHelper := cli.NewFlagHelper(cmd)

attr := flagHelper.GetOptionalString("attribute")
val := flagHelper.GetOptionalString("value")
kas := flagHelper.GetRequiredString("kas")

if kas == "" || (attr == "" && val == "") {
cli.ExitWithError("Specify a key access server and an attribute id or attribute value if to update.", nil)
}
var (
id string
header string
updated map[string]interface{}
)

updated["kas_id"] = kas

if attr != "" {
_, err := h.UpdateKasGrantForAttribute(attr, kas)
if err != nil {
cli.ExitWithError("Could not update KAS grant for attribute", err)
}
id = attr
header = "Attribute ID"
updated["attribute_id"] = attr
} else {
_, err := h.UpdateKasGrantForValue(val, kas)
if err != nil {
cli.ExitWithError("Could not update KAS grant for attribute value", err)
}
id = val
header = "Value ID"
updated["value_id"] = val
}

t := cli.NewTabular().
Rows([][]string{
{header, id},
{"KAS ID", kas},
}...)
HandleSuccess(cmd, id, t, updated)
},
}

kasGrantsDeleteCmd = &cobra.Command{
Use: "delete",
Short: "Delete a KAS grant",
Run: func(cmd *cobra.Command, args []string) {
h := cli.NewHandler(cmd)
defer h.Close()

flagHelper := cli.NewFlagHelper(cmd)
attr := flagHelper.GetOptionalString("attribute")
val := flagHelper.GetOptionalString("value")
kas := flagHelper.GetRequiredString("kas")

if kas == "" || (attr == "" && val == "") {
cli.ExitWithError("Specify a key access server and an attribute id or attribute value if to update.", nil)
}
var (
id string
header string
deleted map[string]interface{}
)

cli.ConfirmDelete("KAS ID: ", kas)

deleted["kas_id"] = kas

if attr != "" {
_, err := h.DeleteKasGrantFromAttribute(attr, kas)
if err != nil {
cli.ExitWithError("Could not update KAS grant for attribute", err)
}
id = attr
header = "Attribute ID"
deleted["attribute_id"] = attr
} else {
_, err := h.DeleteKasGrantFromValue(val, kas)
if err != nil {
cli.ExitWithError("Could not update KAS grant for attribute value", err)
}
id = val
header = "Value ID"
deleted["value_id"] = val
}

t := cli.NewTabular().
Rows([][]string{
{header, id},
{"KAS ID", kas},
}...)
HandleSuccess(cmd, id, t, deleted)
},
}
)

func init() {
policyCmd.AddCommand(kasGrantsCmd)

kasGrantsCmd.AddCommand(kasGrantsUpdateCmd)
kasGrantsUpdateCmd.Flags().StringP("attribute", "a", "", "Attribute ID")
kasGrantsUpdateCmd.Flags().StringP("value", "v", "", "Attribute Value ID")
kasGrantsUpdateCmd.Flags().StringP("kas", "k", "", "KAS ID")
injectLabelFlags(kasGrantsUpdateCmd, true)

kasGrantsCmd.AddCommand(kasGrantsDeleteCmd)
kasGrantsDeleteCmd.Flags().StringP("attribute", "a", "", "Attribute ID")
kasGrantsDeleteCmd.Flags().StringP("value", "v", "", "Attribute Value ID")
kasGrantsDeleteCmd.Flags().StringP("kas", "k", "", "KAS ID")
}

func init() {
rootCmd.AddCommand(kasGrantsCmd)
}
65 changes: 65 additions & 0 deletions pkg/handlers/kas-grants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package handlers

import (
"github.com/opentdf/platform/protocol/go/policy/attributes"
)

func (h Handler) UpdateKasGrantForAttribute(attr_id string, kas_id string) (*attributes.AttributeKeyAccessServer, error) {
kas := &attributes.AttributeKeyAccessServer{
AttributeId: attr_id,
KeyAccessServerId: kas_id,
}
resp, err := h.sdk.Attributes.AssignKeyAccessServerToAttribute(h.ctx, &attributes.AssignKeyAccessServerToAttributeRequest{
AttributeKeyAccessServer: kas,
})
if err != nil {
return nil, err
}

return resp.AttributeKeyAccessServer, nil
}

func (h Handler) DeleteKasGrantFromAttribute(attr_id string, kas_id string) (*attributes.AttributeKeyAccessServer, error) {
kas := &attributes.AttributeKeyAccessServer{
AttributeId: attr_id,
KeyAccessServerId: kas_id,
}
resp, err := h.sdk.Attributes.RemoveKeyAccessServerFromAttribute(h.ctx, &attributes.RemoveKeyAccessServerFromAttributeRequest{
AttributeKeyAccessServer: kas,
})
if err != nil {
return nil, err
}

return resp.AttributeKeyAccessServer, nil
}

func (h Handler) UpdateKasGrantForValue(val_id string, kas_id string) (*attributes.ValueKeyAccessServer, error) {
kas := &attributes.ValueKeyAccessServer{
ValueId: val_id,
KeyAccessServerId: kas_id,
}
resp, err := h.sdk.Attributes.AssignKeyAccessServerToValue(h.ctx, &attributes.AssignKeyAccessServerToValueRequest{
ValueKeyAccessServer: kas,
})
if err != nil {
return nil, err
}

return resp.ValueKeyAccessServer, nil
}

func (h Handler) DeleteKasGrantFromValue(val_id string, kas_id string) (*attributes.ValueKeyAccessServer, error) {
kas := &attributes.ValueKeyAccessServer{
ValueId: val_id,
KeyAccessServerId: kas_id,
}
resp, err := h.sdk.Attributes.RemoveKeyAccessServerFromValue(h.ctx, &attributes.RemoveKeyAccessServerFromValueRequest{
ValueKeyAccessServer: kas,
})
if err != nil {
return nil, err
}

return resp.ValueKeyAccessServer, nil
}