Skip to content

Commit

Permalink
feat(core): support kas grants to namespaces (#292)
Browse files Browse the repository at this point in the history
Closes #269
  • Loading branch information
jakedoublev authored Aug 21, 2024
1 parent 0f533c7 commit f2c6689
Show file tree
Hide file tree
Showing 16 changed files with 275 additions and 45 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ jobs:
working-directory: platform
- run: go run ./service provision keycloak
working-directory: platform
- run: go run ./service provision fixtures
working-directory: platform
- uses: JarvusInnovations/background-action@2428e7b970a846423095c79d43f759abf979a635
name: start server in background
with:
Expand All @@ -85,4 +87,4 @@ jobs:
- name: Setup Bats and bats libs
uses: bats-core/[email protected]
- run: tests/encrypt-decrypt.bats

- run: tests/kas-grants.bats
101 changes: 79 additions & 22 deletions cmd/kas-grants.go
Original file line number Diff line number Diff line change
@@ -1,54 +1,70 @@
package cmd

import (
"errors"
"fmt"

"github.com/opentdf/otdfctl/pkg/cli"
"github.com/opentdf/otdfctl/pkg/man"
"github.com/spf13/cobra"
)

var forceFlagValue = false

func policy_assignKasGrant(cmd *cobra.Command, args []string) {
h := NewHandler(cmd)
defer h.Close()

flagHelper := cli.NewFlagHelper(cmd)

nsID := flagHelper.GetOptionalString("namespace-id")
attrID := flagHelper.GetOptionalString("attribute-id")
valID := flagHelper.GetOptionalString("value-id")
kasID := flagHelper.GetRequiredString("kas-id")
if attrID == "" && valID == "" {
cli.ExitWithError("Must specify and Attribute Definition ID or Value ID to assign a KAS Grant.", nil)

count := 0
for _, v := range []string{nsID, attrID, valID} {
if v != "" {
count++
}
}
if count != 1 {
cli.ExitWithError("Must specify exactly one Attribute Namespace ID, Definition ID, or Value ID to assign", errors.New("invalid flag values"))
}

var (
id string
header string
res interface{}
err error
id string
res interface{}
err error
rowID []string
)

kas, err := h.GetKasRegistryEntry(kasID)
if err != nil || kas == nil {
cli.ExitWithError("Failed to get registered KAS", err)
}

if attrID != "" {
res, err = h.UpdateKasGrantForAttribute(attrID, kasID)
ctx := cmd.Context()
if nsID != "" {
res, err = h.AssignKasGrantToNamespace(ctx, nsID, kasID)
if err != nil {
cli.ExitWithError("Failed to assign KAS Grant for Namespace", err)
}
rowID = []string{"Namespace ID", nsID}
} else if attrID != "" {
res, err = h.AssignKasGrantToAttribute(ctx, attrID, kasID)
if err != nil {
cli.ExitWithError("Failed to assign KAS Grant for Attribute Definition", err)
}
id = attrID
header = "Attribute ID"
rowID = []string{"Attribute ID", attrID}
} else {
res, err = h.UpdateKasGrantForValue(valID, kasID)
res, err = h.AssignKasGrantToValue(ctx, valID, kasID)
if err != nil {
cli.ExitWithError("Failed to assign KAS Grant for Attribute Value", err)
}
id = attrID
header = "Value ID"
rowID = []string{"Value ID", valID}
}

t := cli.NewTabular([]string{header, id}, []string{"KAS ID", kasID}, []string{"Granted KAS URI", kas.GetUri()})
t := cli.NewTabular(rowID, []string{"KAS ID", kasID}, []string{"Granted KAS URI", kas.GetUri()})
HandleSuccess(cmd, id, t, res)
}

Expand All @@ -57,12 +73,20 @@ func policy_unassignKasGrant(cmd *cobra.Command, args []string) {
defer h.Close()

flagHelper := cli.NewFlagHelper(cmd)
nsID := flagHelper.GetOptionalString("namespace-id")
attrID := flagHelper.GetOptionalString("attribute-id")
valID := flagHelper.GetOptionalString("value-id")
kasID := flagHelper.GetRequiredString("kas-id")
force := flagHelper.GetOptionalBool("force")

if attrID == "" && valID == "" {
cli.ExitWithError("Must specify an Attribute Definition ID or Value ID to unassign.", nil)
count := 0
for _, v := range []string{nsID, attrID, valID} {
if v != "" {
count++
}
}
if count != 1 {
cli.ExitWithError("Must specify exactly one Attribute Namespace ID, Definition ID, or Value ID to unassign", errors.New("invalid flag values"))
}
var (
res interface{}
Expand All @@ -78,14 +102,29 @@ func policy_unassignKasGrant(cmd *cobra.Command, args []string) {
}
kasURI := kas.GetUri()

if attrID != "" {
ctx := cmd.Context()
if nsID != "" {
ns, err := h.GetNamespace(nsID)
if err != nil || ns == nil {
cli.ExitWithError("Failed to get namespace definition", err)
}
confirm = fmt.Sprintf("the grant to namespace FQN (%s) of KAS URI", ns.GetFqn())
cli.ConfirmAction(cli.ActionDelete, confirm, kasURI, force)
res, err = h.DeleteKasGrantFromNamespace(ctx, nsID, kasID)
if err != nil {
cli.ExitWithError("Failed to update KAS grant for namespace", err)
}

rowID = []string{"Namespace ID", nsID}
rowFQN = []string{"Namespace FQN", ns.GetFqn()}
} else if attrID != "" {
attr, err := h.GetAttribute(attrID)
if err != nil || attr == nil {
cli.ExitWithError("Failed to get attribute definition", err)
}
confirm = fmt.Sprintf("the grant to attribute FQN (%s) of KAS URI", attr.GetFqn())
cli.ConfirmAction(cli.ActionDelete, confirm, kasURI)
res, err = h.DeleteKasGrantFromAttribute(attrID, kasID)
cli.ConfirmAction(cli.ActionDelete, confirm, kasURI, force)
res, err = h.DeleteKasGrantFromAttribute(ctx, attrID, kasID)
if err != nil {
cli.ExitWithError("Failed to update KAS grant for attribute", err)
}
Expand All @@ -98,8 +137,8 @@ func policy_unassignKasGrant(cmd *cobra.Command, args []string) {
cli.ExitWithError("Failed to get attribute value", err)
}
confirm = fmt.Sprintf("the grant to attribute value FQN (%s) of KAS URI", val.GetFqn())
cli.ConfirmAction(cli.ActionDelete, confirm, kasURI)
_, err = h.DeleteKasGrantFromValue(valID, kasID)
cli.ConfirmAction(cli.ActionDelete, confirm, kasURI, force)
_, err = h.DeleteKasGrantFromValue(ctx, valID, kasID)
if err != nil {
cli.ExitWithError("Failed to update KAS grant for attribute value", err)
}
Expand All @@ -118,6 +157,12 @@ func init() {
assignCmd := man.Docs.GetCommand("policy/kas-grants/assign",
man.WithRun(policy_assignKasGrant),
)
assignCmd.Flags().StringP(
assignCmd.GetDocFlag("namespace-id").Name,
assignCmd.GetDocFlag("namespace-id").Shorthand,
assignCmd.GetDocFlag("namespace-id").Default,
assignCmd.GetDocFlag("namespace-id").Description,
)
assignCmd.Flags().StringP(
assignCmd.GetDocFlag("attribute-id").Name,
assignCmd.GetDocFlag("attribute-id").Shorthand,
Expand All @@ -141,6 +186,12 @@ func init() {
unassignCmd := man.Docs.GetCommand("policy/kas-grants/unassign",
man.WithRun(policy_unassignKasGrant),
)
unassignCmd.Flags().StringP(
unassignCmd.GetDocFlag("namespace-id").Name,
unassignCmd.GetDocFlag("namespace-id").Shorthand,
unassignCmd.GetDocFlag("namespace-id").Default,
unassignCmd.GetDocFlag("namespace-id").Description,
)
unassignCmd.Flags().StringP(
unassignCmd.GetDocFlag("attribute-id").Name,
unassignCmd.GetDocFlag("attribute-id").Shorthand,
Expand All @@ -159,6 +210,12 @@ func init() {
unassignCmd.GetDocFlag("kas-id").Default,
unassignCmd.GetDocFlag("kas-id").Description,
)
unassignCmd.Flags().BoolVar(
&forceFlagValue,
unassignCmd.GetDocFlag("force").Name,
false,
unassignCmd.GetDocFlag("force").Description,
)

cmd := man.Docs.GetCommand("policy/kas-grants",
man.WithSubcommands(assignCmd, unassignCmd),
Expand Down
2 changes: 1 addition & 1 deletion cmd/kas-registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ func policy_deleteKeyAccessRegistry(cmd *cobra.Command, args []string) {
cli.ExitWithError(errMsg, err)
}

cli.ConfirmAction(cli.ActionDelete, "KAS Registry Entry: ", id)
cli.ConfirmAction(cli.ActionDelete, "KAS Registry Entry: ", id, false)

if _, err := h.DeleteKasRegistryEntry(id); err != nil {
errMsg := fmt.Sprintf("Failed to delete KAS registry entry (%s)", id)
Expand Down
2 changes: 1 addition & 1 deletion cmd/policy-attributeNamespaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func policy_deactivateAttributeNamespace(cmd *cobra.Command, args []string) {
cli.ExitWithError(errMsg, err)
}

cli.ConfirmAction(cli.ActionDeactivate, "namespace", ns.Name)
cli.ConfirmAction(cli.ActionDeactivate, "namespace", ns.Name, false)

d, err := h.DeactivateNamespace(id)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cmd/policy-attributeValues.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func policy_deactivateAttributeValue(cmd *cobra.Command, args []string) {
cli.ExitWithError(fmt.Sprintf("Failed to get attribute value (%s)", id), err)
}

cli.ConfirmAction(cli.ActionDeactivate, "attribute value", value.Value)
cli.ConfirmAction(cli.ActionDeactivate, "attribute value", value.Value, false)

deactivated, err := h.DeactivateAttributeValue(id)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cmd/policy-attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func policy_deactivateAttribute(cmd *cobra.Command, args []string) {
cli.ExitWithError(errMsg, err)
}

cli.ConfirmAction(cli.ActionDeactivate, "attribute", attr.Name)
cli.ConfirmAction(cli.ActionDeactivate, "attribute", attr.Name, false)

attr, err = h.DeactivateAttribute(id)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cmd/policy-resourceMappings.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func policy_deleteResourceMapping(cmd *cobra.Command, args []string) {
flagHelper := cli.NewFlagHelper(cmd)
id := flagHelper.GetRequiredString("id")

cli.ConfirmAction(cli.ActionDelete, "resource-mapping", id)
cli.ConfirmAction(cli.ActionDelete, "resource-mapping", id, false)

resourceMapping, err := h.DeleteResourceMapping(id)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cmd/policy-subjectConditionSets.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ func policy_deleteSubjectConditionSet(cmd *cobra.Command, args []string) {
cli.ExitWithError(fmt.Sprintf("Subject Condition Set with id %s not found", id), err)
}

cli.ConfirmAction(cli.ActionDelete, "Subject Condition Set", id)
cli.ConfirmAction(cli.ActionDelete, "Subject Condition Set", id, false)

if err := h.DeleteSubjectConditionSet(id); err != nil {
cli.ExitWithError(fmt.Sprintf("Subject Condition Set with id %s not found", id), err)
Expand Down
2 changes: 1 addition & 1 deletion cmd/policy-subject_mappings.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ func policy_deleteSubjectMapping(cmd *cobra.Command, args []string) {
cli.ExitWithError(errMsg, err)
}

cli.ConfirmAction(cli.ActionDelete, "subject mapping", sm.Id)
cli.ConfirmAction(cli.ActionDelete, "subject mapping", sm.Id, false)

deleted, err := h.DeleteSubjectMapping(id)
if err != nil {
Expand Down
9 changes: 6 additions & 3 deletions docs/man/policy/kas-grants/assign.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@ command:
- upsert
description: Assign a grant of a KAS to an Attribute Definition or Value
flags:
- name: namespace-id
shorthand: n
description: The ID of the Namespace being assigned a KAS Grant
- name: attribute-id
shorthand: a
description: The ID of the attribute definition being assigned a KAS Grant
description: The ID of the Attribute Definition being assigned a KAS Grant
required: true
- name: value-id
shorthand: v
description: The ID of the attribute value being assigned a KAS Grant
description: The ID of the Value being assigned a KAS Grant
required: true
- name: kas-id
shorthand: k
Expand All @@ -33,6 +36,6 @@ command:
default: false
---

Assign a registered Key Access Server (KAS) to an attribute definition or value.
Assign a registered Key Access Server (KAS) to an attribute namespace, definition, or value.

For more information, see `kas-registry` and `kas-grants` manuals.
5 changes: 5 additions & 0 deletions docs/man/policy/kas-grants/unassign.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ command:
- remove
description: Remove a grant assignment of a KAS to an Attribute Definition or Value
flags:
- name: namespace-id
shorthand: n
description: The ID of the Namespace being unassigned a KAS Grant
- name: attribute-id
shorthand: a
description: The ID of the Attribute Definition being unassigned the KAS grant
Expand All @@ -20,6 +23,8 @@ command:
shorthand: k
description: The Key Access Server (KAS) ID being unassigned a grant
required: true
- name: force
description: Force the unassignment with no confirmation
---

Unassign a registered Key Access Server (KAS) to an attribute definition or value.
Expand Down
2 changes: 1 addition & 1 deletion docs/man/policy/kas-registry/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ command:
The Key Access Server (KAS) registry is a record of KASs safeguarding access 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
for specified Namespaces, Attributes, and their Values via Attribute Key Access Grants and Attribute Value Key
Access Grants.

For more information about grants and how KASs are utilized once registered, see the manual for the
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,6 @@ github.com/opentdf/platform/lib/ocrypto v0.1.5 h1:Gv5dAmZEVQeD9w1Fg9fix8gdZIsPDH
github.com/opentdf/platform/lib/ocrypto v0.1.5/go.mod h1:ne+l8Q922OdzA0xesK3XJmfECBnn5vLSGYU3/3OhiHM=
github.com/opentdf/platform/protocol/go v0.2.14 h1:0wqKDVTpuPICyH37ecKxR2+tZNsgXV8TfdzlbQ3ovrA=
github.com/opentdf/platform/protocol/go v0.2.14/go.mod h1:WqDcnFQJb0v8ivRQPidbehcL8ils5ZSZYXkuv0nyvsI=
github.com/opentdf/platform/sdk v0.3.9 h1:sNXGjt5kWnmMCx43GcBc5+sE1YqPNyqxrMSHF3/SRk8=
github.com/opentdf/platform/sdk v0.3.9/go.mod h1:XqFivuo4tcqxGwJF9ORnLB3S5bjrgJwiaj6BAJUXJXg=
github.com/opentdf/platform/sdk v0.3.10 h1:WoPtM6IcwwDIEqCcLq2jb6pd15bFXmEDaju9MKd6JtM=
github.com/opentdf/platform/sdk v0.3.10/go.mod h1:XqFivuo4tcqxGwJF9ORnLB3S5bjrgJwiaj6BAJUXJXg=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
Expand Down
5 changes: 4 additions & 1 deletion pkg/cli/confirm.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ const (
InputNameFQNUpdated = "deprecated fully qualified name (FQN) being altered"
)

func ConfirmAction(action, resource, id string) {
func ConfirmAction(action, resource, id string, force bool) {
if force {
return
}
var confirm bool
err := huh.NewConfirm().
Title(fmt.Sprintf("Are you sure you want to %s %s:\n\n\t%s", action, resource, id)).
Expand Down
Loading

0 comments on commit f2c6689

Please sign in to comment.