Skip to content

Commit

Permalink
feat(core): adds assertions to encrypt subcommand (#408)
Browse files Browse the repository at this point in the history
Co-authored-by: Jake Van Vorhis <[email protected]>
Co-authored-by: Ryan Schumacher <[email protected]>
  • Loading branch information
3 people authored Nov 6, 2024
1 parent 57966ff commit 8f0e906
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 3 deletions.
7 changes: 6 additions & 1 deletion .github/spellcheck.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,9 @@ upsert
uri
with-client-creds
with-client-creds-file
yaml
yaml
tdo
appliesToState
stanag
nato
ocl
10 changes: 9 additions & 1 deletion cmd/tdf-encrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const (
)

var attrValues []string
var assertions string

func dev_tdfEncryptCmd(cmd *cobra.Command, args []string) {
c := cli.New(cmd, args)
Expand Down Expand Up @@ -94,7 +95,7 @@ func dev_tdfEncryptCmd(cmd *cobra.Command, args []string) {
var err error
switch tdfType {
case TDF3:
encrypted, err = h.EncryptBytes(bytesSlice, attrValues, fileMimeType, kasURLPath)
encrypted, err = h.EncryptBytes(bytesSlice, attrValues, fileMimeType, kasURLPath, assertions)
case NANO:
ecdsaBinding := c.Flags.GetOptionalBool("ecdsa-binding")
encrypted, err = h.EncryptNanoBytes(bytesSlice, attrValues, kasURLPath, ecdsaBinding)
Expand Down Expand Up @@ -145,6 +146,13 @@ func init() {
[]string{},
encryptCmd.GetDocFlag("attr").Description,
)
encryptCmd.Flags().StringVarP(
&assertions,
encryptCmd.GetDocFlag("with-assertions").Name,
encryptCmd.GetDocFlag("with-assertions").Shorthand,
"",
encryptCmd.GetDocFlag("with-assertions").Description,
)
encryptCmd.Flags().String(
encryptCmd.GetDocFlag("mime-type").Name,
encryptCmd.GetDocFlag("mime-type").Default,
Expand Down
3 changes: 3 additions & 0 deletions docs/man/encrypt/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ command:
- name: kas-url-path
description: URL path to the KAS service at the platform endpoint domain. Leading slash is required if needed.
default: /kas
- name: with-assertions
description: >
EXPERIMENTAL: JSON string containing list of assertions to be applied during encryption. example - '[{"id":"assertion1","type":"handling","scope":"tdo","appliesToState":"encrypted","statement":{"format":"json+stanag5636","schema":"urn:nato:stanag:5636:A:1:elements:json","value":"{\"ocl\":\"2024-10-21T20:47:36Z\"}"}}]'
---

Build a Trusted Data Format (TDF) with encrypted content from a specified file or input from stdin utilizing OpenTDF platform.
Expand Down
6 changes: 6 additions & 0 deletions e2e/encrypt-decrypt.bats
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ setup_file() {
VAL_ID=$(./otdfctl --host $HOST $WITH_CREDS $DEBUG_LEVEL policy attributes values create --attribute-id "$ATTR_ID" -v value1 --json | jq -r '.id')
# entitles opentdf client id for client credentials CLI user
SCS='[{"condition_groups":[{"conditions":[{"operator":1,"subject_external_values":["opentdf"],"subject_external_selector_value":".clientId"}],"boolean_operator":2}]}]'
ASSERTIONS='[{"id":"assertion1","type":"handling","scope":"tdo","appliesToState":"encrypted","statement":{"format":"json+stanag5636","schema":"urn:nato:stanag:5636:A:1:elements:json","value":"{\"ocl\":\"2024-10-21T20:47:36Z\"}"}}]'
SM=$(./otdfctl --host $HOST $WITH_CREDS $DEBUG_LEVEL policy subject-mappings create --action-standard DECRYPT -a "$VAL_ID" --subject-condition-set-new "$SCS")
export FQN="https://testing-enc-dec.io/attr/attr1/value/value1"
export MIXED_CASE_FQN="https://Testing-Enc-Dec.io/attr/Attr1/value/VALUE1"
Expand Down Expand Up @@ -51,6 +52,11 @@ teardown_file(){
./otdfctl decrypt --host $HOST --tls-no-verify $DEBUG_LEVEL $WITH_CREDS $OUTFILE_TXT | grep "$SECRET_TEXT"
}

@test "roundtrip TDF3, assertions, stdin" {
echo $SECRET_TEXT | ./otdfctl encrypt -o $OUT_TXT --host $HOST --tls-no-verify $DEBUG_LEVEL $WITH_CREDS -a $FQN --with-assertions "$ASSERTIONS"
./otdfctl decrypt --host $HOST --tls-no-verify $DEBUG_LEVEL $WITH_CREDS $OUTFILE_TXT | grep "$SECRET_TEXT"
}

@test "roundtrip NANO, no attributes, file" {
./otdfctl encrypt -o $OUTFILE_GO_MOD --host $HOST --tls-no-verify $DEBUG_LEVEL $WITH_CREDS --tdf-type nano $INFILE_GO_MOD
./otdfctl decrypt -o $RESULTFILE_GO_MOD --host $HOST --tls-no-verify $DEBUG_LEVEL $WITH_CREDS --tdf-type nano $OUTFILE_GO_MOD
Expand Down
13 changes: 12 additions & 1 deletion pkg/handlers/tdf.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package handlers

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
Expand All @@ -15,19 +16,29 @@ var (
ErrTDFInspectFailNotInspectable = errors.New("file or input is not inspectable")
ErrTDFUnableToReadAttributes = errors.New("unable to read attributes from TDF")
ErrTDFUnableToReadUnencryptedMetadata = errors.New("unable to read unencrypted metadata from TDF")
ErrTDFUnableToReadAssertions = errors.New("unable to read assertions")
minBytesLength = 3
)

func (h Handler) EncryptBytes(b []byte, values []string, mimeType string, kasUrlPath string) (*bytes.Buffer, error) {
func (h Handler) EncryptBytes(b []byte, values []string, mimeType string, kasUrlPath string, assertions string) (*bytes.Buffer, error) {
var encrypted []byte
enc := bytes.NewBuffer(encrypted)

var assertionConfigs []sdk.AssertionConfig
if assertions != "" {
err := json.Unmarshal([]byte(assertions), &assertionConfigs)
if err != nil {
return nil, errors.Join(ErrTDFUnableToReadAssertions, err)
}
}

// TODO: validate values are FQNs or return an error [https://github.com/opentdf/platform/issues/515]
_, err := h.sdk.CreateTDF(enc, bytes.NewReader(b),
sdk.WithDataAttributes(values...),
sdk.WithKasInformation(sdk.KASInfo{
URL: h.platformEndpoint + kasUrlPath,
}),
sdk.WithAssertions(assertionConfigs...),
sdk.WithMimeType(mimeType),
)
if err != nil {
Expand Down

0 comments on commit 8f0e906

Please sign in to comment.