Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2a18062
feat(core): support kas grants to namespaces
jakedoublev Aug 20, 2024
71c7407
bats
jakedoublev Aug 20, 2024
9d112f3
bump platform deps
jakedoublev Aug 20, 2024
5849423
namespace flag requirement fix and more tests
jakedoublev Aug 20, 2024
0f0a423
actually run BATS tests
jakedoublev Aug 20, 2024
35a0c17
make bats test executable
jakedoublev Aug 20, 2024
846128d
variables in tests
jakedoublev Aug 20, 2024
949223b
fix tests
jakedoublev Aug 20, 2024
e0e5ce2
fix jq
jakedoublev Aug 20, 2024
a3b8545
working tests
jakedoublev Aug 20, 2024
b31dd73
provision test fixtures before e2e run and add teardown
jakedoublev Aug 21, 2024
2fa684d
fix setup/teardown
jakedoublev Aug 21, 2024
ae40e64
fix if conditional
jakedoublev Aug 21, 2024
af990e1
fix setup
jakedoublev Aug 21, 2024
6d4067b
fix setup
jakedoublev Aug 21, 2024
8018485
speed up
jakedoublev Aug 21, 2024
c09a6c6
try to find assert_output dependency
jakedoublev Aug 21, 2024
e1d7f4f
syntax
jakedoublev Aug 21, 2024
ae14f9a
syntax
jakedoublev Aug 21, 2024
04cc7b9
glob matching
jakedoublev Aug 21, 2024
d67d3dc
allow force to override confirm
jakedoublev Aug 21, 2024
0fc2851
fix bug found by test suite
jakedoublev Aug 21, 2024
1455f77
add status check for expected failures
jakedoublev Aug 21, 2024
1797fc4
implement try catch to avoid failure on expected error
jakedoublev Aug 21, 2024
4216b6f
comments and test fix
jakedoublev Aug 21, 2024
2edb1cd
improve try/catch
jakedoublev Aug 21, 2024
3c16d69
Merge branch 'main' into feat/ns-grants
jakedoublev Aug 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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