Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: refactor encrypt and decrypt + CLI examples #418

Merged
merged 15 commits into from
Nov 8, 2024
6 changes: 5 additions & 1 deletion .github/spellcheck.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ NPM
Namespace
namespace's
Nano
NanoTDF
OIDC
OpenTDF
OpenID
Expand Down Expand Up @@ -108,8 +109,11 @@ uri
with-client-creds
with-client-creds-file
yaml
ZTDF
ztdf
tdo
appliesToState
stanag
nato
ocl
ocl
cryptographically
19 changes: 3 additions & 16 deletions cmd/tdf-decrypt.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cmd

import (
"bytes"
"errors"
"fmt"
"os"
Expand All @@ -14,16 +13,12 @@ import (
var TDF = "tdf"

func dev_tdfDecryptCmd(cmd *cobra.Command, args []string) {
c := cli.New(cmd, args)
c := cli.New(cmd, args, cli.WithPrintJson())
h := NewHandler(c)
defer h.Close()

output := c.Flags.GetOptionalString("out")
tdfType := c.Flags.GetOptionalString("tdf-type")
disableAssertionVerification := c.Flags.GetOptionalBool("no-verify-assertions")
if tdfType == "" {
tdfType = TDF3
}

// check for piped input
piped := readPipedStdin()
Expand All @@ -40,16 +35,7 @@ func dev_tdfDecryptCmd(cmd *cobra.Command, args []string) {
cli.ExitWithError("Must provide ONE of the following to decrypt: [file argument, stdin input]", errors.New("no input provided"))
}

var decrypted *bytes.Buffer
var err error
switch tdfType {
case TDF3:
decrypted, err = h.DecryptTDF(bytesToDecrypt, disableAssertionVerification)
case NANO:
decrypted, err = h.DecryptNanoTDF(bytesToDecrypt)
default:
cli.ExitWithError("Failed to decrypt", fmt.Errorf("unrecognized tdf-type: %s", tdfType))
}
decrypted, err := h.DecryptBytes(bytesToDecrypt, disableAssertionVerification)
if err != nil {
cli.ExitWithError("Failed to decrypt file", err)
}
Expand Down Expand Up @@ -81,6 +67,7 @@ func init() {
decryptCmd.GetDocFlag("out").Default,
decryptCmd.GetDocFlag("out").Description,
)
// deprecated flag
decryptCmd.Flags().StringP(
decryptCmd.GetDocFlag("tdf-type").Name,
decryptCmd.GetDocFlag("tdf-type").Shorthand,
Expand Down
25 changes: 6 additions & 19 deletions cmd/tdf-encrypt.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cmd

import (
"bytes"
"fmt"
"io"
"log/slog"
Expand All @@ -16,16 +15,17 @@ import (
)

const (
TDF3 = "tdf3"
NANO = "nano"
Size_1MB = 1024 * 1024
TDFTYPE_ZTDF = "ztdf"
TDF3 = "tdf3"
NANO = "nano"
Size_1MB = 1024 * 1024
)

var attrValues []string
var assertions string

func dev_tdfEncryptCmd(cmd *cobra.Command, args []string) {
c := cli.New(cmd, args)
c := cli.New(cmd, args, cli.WithPrintJson())
h := NewHandler(c)
defer h.Close()

Expand All @@ -40,9 +40,6 @@ func dev_tdfEncryptCmd(cmd *cobra.Command, args []string) {
fileMimeType := c.Flags.GetOptionalString("mime-type")
attrValues = c.Flags.GetStringSlice("attr", attrValues, cli.FlagsStringSliceOptions{Min: 0})
tdfType := c.Flags.GetOptionalString("tdf-type")
if tdfType == "" {
tdfType = TDF3
}
kasURLPath := c.Flags.GetOptionalString("kas-url-path")

piped := readPipedStdin()
Expand Down Expand Up @@ -91,17 +88,7 @@ func dev_tdfEncryptCmd(cmd *cobra.Command, args []string) {
)

// Do the encryption
var encrypted *bytes.Buffer
var err error
switch tdfType {
case TDF3:
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)
default:
cli.ExitWithError("Failed to encrypt", fmt.Errorf("unrecognized tdf-type: %s", tdfType))
}
encrypted, err := h.EncryptBytes(tdfType, bytesSlice, attrValues, fileMimeType, kasURLPath, c.Flags.GetOptionalBool("ecdsa-binding"), assertions)
if err != nil {
cli.ExitWithError("Failed to encrypt", err)
}
Expand Down
6 changes: 5 additions & 1 deletion docs/man/auth/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ command:
name: auth
---

This command will allow you to manage your local authentication session with the OpenTDF platform.
> [!NOTE]
> Requires experimental profiles feature. (Linux not yet supported. Windows is brittle.)

The auth commands facilitate the process of authenticating the user with the system using profiles to store the
credentials.
3 changes: 2 additions & 1 deletion docs/man/auth/clear-client-credentials.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ command:
default: false
---

This command has been deprecated. Use the `profile` subcommand to manage profiles and credentials.
> [!WARNING]
> Deprecated. Use the `profile` subcommand to manage profiles and credentials.
23 changes: 23 additions & 0 deletions docs/man/auth/client-credentials.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,28 @@ command:
- client-secret
---

> [!NOTE]
> Requires experimental profiles feature.
>
> | OS | Keychain | State |
> | --- | --- | --- |
> | MacOS | Keychain | Stable |
> | Windows | Credential Manager | Alpha |
> | Linux | Secret Service | Not yet supported |

Allows the user to login in via Client Credentials flow. The client credentials will be stored safely
in the OS keyring for future use.

## Examples

Authenticate with client credentials (secret provided interactively)

```shell
opentdf auth client-credentials --client-id <client-id>
```

Authenticate with client credentials (secret provided as argument)

```shell
opentdf auth client-credentials --client-id <client-id> --client-secret <client-secret>
```
9 changes: 9 additions & 0 deletions docs/man/auth/login.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ command:
required: false
---

> [!NOTE]
> Requires experimental profiles feature.
>
> | OS | Keychain | State |
> | --- | --- | --- |
> | MacOS | Keychain | Stable |
> | Windows | Credential Manager | Alpha |
> | Linux | Secret Service | Not yet supported |

Authenticate for use of the OpenTDF Platform through a browser (required).

Provide a specific public 'client-id' known to support the Auth Code PKCE flow and recognized
Expand Down
10 changes: 10 additions & 0 deletions docs/man/auth/logout.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,15 @@ command:
name: logout
---


> [!NOTE]
> Requires experimental profiles feature.
>
> | OS | Keychain | State |
> | --- | --- | --- |
> | MacOS | Keychain | Stable |
> | Windows | Credential Manager | Alpha |
> | Linux | Secret Service | Not yet supported |

Removes any auth credentials (Client Credentials or an Access Token from a login)
from the current profile.
11 changes: 10 additions & 1 deletion docs/man/auth/print-access-token.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,13 @@ command:
default: false
---

Retrieves a new OIDC Access Token using the client credentials from the OS-specific keychain and prints to stdout if found.
> [!NOTE]
> Requires experimental profiles feature.
>
> | OS | Keychain | State |
> | --- | --- | --- |
> | MacOS | Keychain | Stable |
> | Windows | Credential Manager | Alpha |
> | Linux | Secret Service | Not yet supported |

Retrieves a new OIDC Access Token using the client credentials and prints to stdout if found.
32 changes: 19 additions & 13 deletions docs/man/decrypt/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@ command:
default: ''
- name: tdf-type
shorthand: t
description: The type of tdf to decrypt as
enum:
- tdf3
- nano
default: tdf3
description: Deprecated. TDF type is now auto-detected.
- name: no-verify-assertions
description: disable verification of assertions
default: false
Expand All @@ -23,14 +19,24 @@ Decrypt a Trusted Data Format (TDF) file and output the contents to stdout or a

The first argument is the TDF file with path from the current working directory being decrypted.

## Examples:
## Examples

```bash
# specify the TDF to decrypt then output decrypted contents
otdfctl decrypt hello.txt.tdf # write to stdout
otdfctl decrypt hello.txt.tdf > hello.txt # consume stdout to write to hello.txt file
otdfctl decrypt hello.txt.tdf -o hello.txt # write to hello.txt file instead of stdout
Various ways to decrypt a TDF file

# pipe the TDF to decrypt
cat hello.txt.tdf | otdfctl decrypt > hello.txt
```shell
# decrypt file and write to standard output
otdfctl decrypt hello.txt.tdf

# decrypt file and write to hello.txt file
otdfctl decrypt hello.txt.tdf -o hello.txt

# decrypt piped TDF content and write to hello.txt file
cat hello.txt.tdf | otdfctl decrypt -o hello.txt
```

Advanced piping is supported

```shell
$ echo "hello world" | otdfctl encrypt | otdfctl decrypt | cat
hello world
```
74 changes: 62 additions & 12 deletions docs/man/encrypt/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,84 @@ command:
description: The MIME type of the input data. If not provided, the MIME type is inferred from the input data.
- name: tdf-type
shorthand: t
description: The type of tdf to encrypt as. TDF3 supports structured manifests and larger payloads. Nano has a smaller footprint and more performant, but does not support structured manifests or large payloads.
description: The type of tdf to encrypt as. ZTDF supports structured manifests and larger payloads. NanoTDF has a smaller footprint and more performant, but does not support structured manifests or large payloads. (tdf3 is an alias for ztdf)
enum:
- ztdf
- tdf3
- nano
default: tdf3
default: ztdf
- name: ecdsa-binding
description: For nano type containers only, enables ECDSA policy binding
- 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\"}"}}]'
EXPERIMENTAL: JSON string of assertions to bind metadata to the TDF. See examples for more information.
---

Build a Trusted Data Format (TDF) with encrypted content from a specified file or input from stdin utilizing OpenTDF platform.

## Examples:
## Examples

```bash
Various ways to encrypt a file

```shell
# output to stdout
echo "some text" | otdfctl encrypt
otdfctl encrypt hello.txt
# pipe stdout to a bucket
echo "my secret" | otdfctl encrypt | aws s3 cp - s3://my-bucket/secret.txt.tdf

# output hello.txt.tdf in root directory
echo "hello world" | otdfctl encrypt -o hello.txt
cat hello.txt | otdfctl encrypt -o hello.txt
cat hello.txt | otdfctl encrypt -o hello.txt.tdf #.tdf extension is only added once
# output to hello.txt.tdf
otdfctl encrypt hello.txt --out hello.txt.tdf

# encrypt piped content and write to hello.txt.tdf
cat hello.txt | otdfctl encrypt --out hello.txt.tdf
```

Automatically append .tdf to the output file name

```shell
$ cat hello.txt | otdfctl encrypt --out hello.txt; ls
hello.txt hello.txt.tdf

$ cat hello.txt | otdfctl encrypt --out hello.txt.tdf; ls
hello.txt hello.txt.tdf
```

Advanced piping is supported

```shell
$ echo "hello world" | otdfctl encrypt | otdfctl decrypt | cat
hello world
```

## Attributes

Attributes can be added to the encrypted data. The attribute value is a Fully Qualified Name (FQN) that is used to
restrict access to the data based on entity entitlements.

```shell
# output to hello.txt.tdf with attribute
otdfctl encrypt hello.txt --out hello.txt.tdf --attr https://example.com/attr/attr1/value/value1
```

## NanoTDF

NanoTDF is a lightweight TDF format that is more performant and has a smaller footprint than TDF3. NanoTDF does not
jrschumacher marked this conversation as resolved.
Show resolved Hide resolved
support structured manifests or large payloads.

```shell
# output to nano.tdf
otdfctl encrypt hello.txt --tdf-type nano --out hello.txt.tdf
```

## ZTDF Assertions (experimental)

Assertions are a way to bind metadata to the TDF data object in a cryptographically secure way.

### STANAG 5636

The following example demonstrates how to bind a STANAG 5636 metadata assertion to the TDF data object.

```shell
otdfctl encrypt hello.txt --out hello.txt.tdf --with-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\"}"}}]'
```
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ require (
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/google/uuid v1.6.0
github.com/opentdf/platform/lib/flattening v0.1.1
github.com/opentdf/platform/protocol/go v0.2.18
github.com/opentdf/platform/sdk v0.3.17
github.com/opentdf/platform/protocol/go v0.2.20
github.com/opentdf/platform/sdk v0.3.18
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.9.0
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,12 @@ github.com/opentdf/platform/lib/ocrypto v0.1.6 h1:rd4ctCZOE/c3qDJORtkSK9tw6dEXb+
github.com/opentdf/platform/lib/ocrypto v0.1.6/go.mod h1:ne+l8Q922OdzA0xesK3XJmfECBnn5vLSGYU3/3OhiHM=
github.com/opentdf/platform/protocol/go v0.2.18 h1:s+TVZkOPGCzy7WyObtJWJNaFeOGDUTuSmAsq3omvugY=
github.com/opentdf/platform/protocol/go v0.2.18/go.mod h1:WqDcnFQJb0v8ivRQPidbehcL8ils5ZSZYXkuv0nyvsI=
github.com/opentdf/platform/protocol/go v0.2.20 h1:FPU1ZcXvPm/QeE2nqgbD/HMTOCICQSD0DoncQbAZ1ws=
github.com/opentdf/platform/protocol/go v0.2.20/go.mod h1:TWIuf387VeR3q0TL4nAMKQTWEqqID+8Yjao76EX9Dto=
github.com/opentdf/platform/sdk v0.3.17 h1:Uo/kTMneB18i0gZNfTRtvw34bGLFUc8BEnA/BMK0VVs=
github.com/opentdf/platform/sdk v0.3.17/go.mod h1:c2+nrsRLvLf2OOryXnNy0iGZN/TScc21Pul7uqKVXIs=
github.com/opentdf/platform/sdk v0.3.18 h1:IY6fNrOfQD9lF/hZp9ewZsH0PMuLe17HlSE1A5kyIWc=
github.com/opentdf/platform/sdk v0.3.18/go.mod h1:u+XZhVRsMq5blukCFCHcjk6HLCp4Y5mmIQu7GhtKQ3E=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
Expand Down
Loading
Loading