From a918e1201bb366d0cc18d7fd047f2c0854558e9e Mon Sep 17 00:00:00 2001 From: Ryan Schumacher Date: Wed, 26 Jun 2024 14:48:59 -0500 Subject: [PATCH] feat: add mimetypes to ztdf on encrypt (#209) --- cmd/tdf-decrypt.go | 9 ++++---- cmd/tdf-encrypt.go | 45 +++++++++++++++++++++++++++++++++----- docs/man/encrypt/_index.md | 2 ++ go.mod | 3 ++- go.sum | 4 ++++ pkg/handlers/tdf.go | 9 ++++---- 6 files changed, 56 insertions(+), 16 deletions(-) diff --git a/cmd/tdf-decrypt.go b/cmd/tdf-decrypt.go index 899173f7..65a6da08 100644 --- a/cmd/tdf-decrypt.go +++ b/cmd/tdf-decrypt.go @@ -26,16 +26,17 @@ func dev_tdfDecryptCmd(cmd *cobra.Command, args []string) { piped := readPipedStdin() // Prefer file argument over piped input over default filename - var bytesToDecrypt []byte + bytesToDecrypt := piped var tdfFile string if len(args) > 0 { tdfFile = args[0] bytesToDecrypt = readBytesFromFile(tdfFile) - } else if len(piped) > 0 { - bytesToDecrypt = piped - } else { + } + + if len(bytesToDecrypt) == 0 { 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 if tdfType == TDF3 { diff --git a/cmd/tdf-encrypt.go b/cmd/tdf-encrypt.go index 0250beea..3da594e9 100644 --- a/cmd/tdf-encrypt.go +++ b/cmd/tdf-encrypt.go @@ -4,9 +4,12 @@ import ( "bytes" "fmt" "io" + "log/slog" "os" + "path/filepath" "strings" + "github.com/gabriel-vasile/mimetype" "github.com/opentdf/otdfctl/pkg/cli" "github.com/opentdf/otdfctl/pkg/man" "github.com/spf13/cobra" @@ -23,10 +26,14 @@ func dev_tdfEncryptCmd(cmd *cobra.Command, args []string) { flagHelper := cli.NewFlagHelper(cmd) var filePath string + var fileExt string if len(args) > 0 { filePath = args[0] + fileExt = strings.ToLower(strings.TrimPrefix(filepath.Ext(filePath), ".")) } + out := flagHelper.GetOptionalString("out") + fileMimeType := flagHelper.GetOptionalString("mime-type") values := flagHelper.GetStringSlice("attr", attrValues, cli.FlagHelperStringSliceOptions{Min: 0}) tdfType := flagHelper.GetOptionalString("tdf-type") if tdfType == "" { @@ -43,25 +50,46 @@ func dev_tdfEncryptCmd(cmd *cobra.Command, args []string) { inputCount++ } + cliExit := func(s string) { + cli.ExitWithError("Must provide "+s+" of the following to encrypt: [file argument, stdin input]", nil) + } if inputCount == 0 { - cli.ExitWithError("Must provide ONE of the following to encrypt: [file argument, stdin input]", nil) + cliExit("ONE") } else if inputCount > 1 { - cli.ExitWithError("Must provide ONLY ONE of the following to encrypt: [file argument, stdin input]", nil) + cliExit("ONLY ONE") } // prefer filepath argument over stdin input - var bytesSlice []byte + bytesSlice := piped if filePath != "" { bytesSlice = readBytesFromFile(filePath) - } else { - bytesSlice = piped } + // auto-detect mime type if not provided + if fileMimeType == "" { + slog.Debug("Detecting mime type of file") + // get the mime type of the file + mimetype.SetLimit(1024 * 1024) // limit to 1MB + m := mimetype.Detect(bytesSlice) + // default to application/octet-stream if no mime type is detected + fileMimeType = m.String() + + if fileMimeType == "application/octet-stream" { + if fileExt != "" { + fileMimeType = mimetype.Lookup(fileExt).String() + } + } + } + slog.Debug("Encrypting file", + slog.Int("file-len", len(bytesSlice)), + slog.String("mime-type", fileMimeType), + ) + // Do the encryption var encrypted *bytes.Buffer var err error if tdfType == TDF3 { - encrypted, err = h.EncryptBytes(bytesSlice, values) + encrypted, err = h.EncryptBytes(bytesSlice, values, fileMimeType) } else if tdfType == NANO { encrypted, err = h.EncryptNanoBytes(bytesSlice, values) } else { @@ -111,6 +139,11 @@ func init() { []string{}, encryptCmd.GetDocFlag("attr").Description, ) + encryptCmd.Flags().String( + encryptCmd.GetDocFlag("mime-type").Name, + encryptCmd.GetDocFlag("mime-type").Default, + encryptCmd.GetDocFlag("mime-type").Description, + ) encryptCmd.Flags().StringP( encryptCmd.GetDocFlag("tdf-type").Name, encryptCmd.GetDocFlag("tdf-type").Shorthand, diff --git a/docs/man/encrypt/_index.md b/docs/man/encrypt/_index.md index 35b8e8fe..db3fc89c 100644 --- a/docs/man/encrypt/_index.md +++ b/docs/man/encrypt/_index.md @@ -10,6 +10,8 @@ command: - name: attr shorthand: a description: Attribute value Fully Qualified Names (FQNs, i.e. 'https://example.com/attr/attr1/value/value1') to apply to the encrypted data. + - name: mime-type + 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 diff --git a/go.mod b/go.mod index 8d8dd41b..d37d4dd3 100644 --- a/go.mod +++ b/go.mod @@ -45,6 +45,7 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.4 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/google/uuid v1.6.0 // indirect @@ -91,7 +92,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.23.0 // indirect golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect - golang.org/x/net v0.24.0 // indirect + golang.org/x/net v0.25.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/text v0.15.0 // indirect diff --git a/go.sum b/go.sum index 2a529b95..60474290 100644 --- a/go.sum +++ b/go.sum @@ -93,6 +93,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I= +github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -299,6 +301,8 @@ golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/pkg/handlers/tdf.go b/pkg/handlers/tdf.go index 682f3fd2..aad0bb34 100644 --- a/pkg/handlers/tdf.go +++ b/pkg/handlers/tdf.go @@ -7,7 +7,7 @@ import ( "github.com/opentdf/platform/sdk" ) -func (h Handler) EncryptBytes(b []byte, values []string) (*bytes.Buffer, error) { +func (h Handler) EncryptBytes(b []byte, values []string, mimeType string) (*bytes.Buffer, error) { var encrypted []byte enc := bytes.NewBuffer(encrypted) @@ -15,10 +15,9 @@ func (h Handler) EncryptBytes(b []byte, values []string) (*bytes.Buffer, error) _, err := h.sdk.CreateTDF(enc, bytes.NewReader(b), sdk.WithDataAttributes(values...), sdk.WithKasInformation(sdk.KASInfo{ - URL: h.platformEndpoint, - PublicKey: "", - }, - ), + URL: h.platformEndpoint, + }), + sdk.WithMimeType(mimeType), ) if err != nil { return nil, err