Skip to content

Commit

Permalink
Morgabra/add decrypt (#108)
Browse files Browse the repository at this point in the history
* Add baton-sdk dep.

* stash

* regen go sdk

* Update dependencies. Use latest baton-sdk. Use branch of conductorone-sdk-go.

* Get CONE_API_ENDPOINT env var working with ports.

* Fetch all encrypted credentials and try to decrypt them.

* Cone Decrypt app id argument (#102)

* Implemented argument to check a specific app instead of all apps, which will still be checked if no args are passed

* Updated validating command arguments and return message

* Swapped fmt.printf to pterm.printf

* Update cmd/cone/decrypt.go

Co-authored-by: Logan Saso <[email protected]>

* Update cmd/cone/decrypt.go

Co-authored-by: Logan Saso <[email protected]>

---------

Co-authored-by: Logan Saso <[email protected]>

* Push broken build - needs dev version of SDK to work

* Updating SDK with dev version

* Skip credentials we cannot decode

* Print output more prettily and give more context

* Remove comments
Add nil check

---------

Co-authored-by: Brad Morgan <[email protected]>
Co-authored-by: Geoff Greer <[email protected]>
Co-authored-by: Grant Kopczenski <[email protected]>
Co-authored-by: Logan Saso <[email protected]>
Co-authored-by: Logan Saso <[email protected]>
Co-authored-by: Phoebe Yu <[email protected]>
  • Loading branch information
7 people authored Oct 31, 2024
1 parent d1f7996 commit 4c4a5b4
Show file tree
Hide file tree
Showing 449 changed files with 93,479 additions and 4,711 deletions.
146 changes: 146 additions & 0 deletions cmd/cone/decrypt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package main

import (
"context"
"crypto"
"encoding/base64"
"encoding/hex"
"fmt"

v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2"
"github.com/conductorone/baton-sdk/pkg/crypto/providers"
"github.com/conductorone/baton-sdk/pkg/crypto/providers/jwk"
"github.com/conductorone/conductorone-sdk-go/pkg/models/shared"
"github.com/pterm/pterm"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"gopkg.in/square/go-jose.v2"

"github.com/conductorone/cone/pkg/client"
)

func decryptCredentialCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "decrypt-credential [app-id]",
Short: "Attempts to decrypt a credential",
RunE: decryptCredentialRun,
}

return cmd
}

func thumbprint(jwk jose.JSONWebKey) string {
tp, err := jwk.Thumbprint(crypto.SHA256)
if err != nil {
panic(fmt.Errorf("failed to compute key id: %w", err))
}
return hex.EncodeToString(tp)
}

func decodeCredential(ctx context.Context, v *viper.Viper, cred shared.AppUserCredential) (*v2.PlaintextData, error) {
// so, we store the ciphertext as []byte, but json serialization of this will be base64 encoded, so let's just require that as our input.
credentialDec, err := base64.StdEncoding.DecodeString(*cred.EncryptedData.EncryptedBytes)
if err != nil {
return nil, fmt.Errorf("failed to base64 decode credential: %w", err)
}

provider, err := providers.GetEncryptionProvider(jwk.EncryptionProviderJwk)
if err != nil {
return nil, fmt.Errorf("failed to get encryption provider: %w", err)
}

// FIXME(morgabra): This is a hack for testing.
ciphertext := &v2.EncryptedData{
Provider: jwk.EncryptionProviderJwk,
EncryptedBytes: credentialDec,
}

// Get our secret key and dig out the private jwk, this is silly.
_, clientSecret, err := getCredentials(v)
if err != nil {
return nil, fmt.Errorf("failed to get credentials: %w", err)
}
privateJWK, err := client.ParseSecret([]byte(clientSecret))
if err != nil {
return nil, fmt.Errorf("failed to parse secret: %w", err)
}
privateKeyBytes, err := privateJWK.MarshalJSON()
if err != nil {
return nil, fmt.Errorf("failed to marshal private jwk: %w", err)
}

plaintext, err := provider.Decrypt(ctx, ciphertext, privateKeyBytes)
if err != nil {
return nil, fmt.Errorf("failed to decrypt credential: %w", err)
}

pterm.Printf("Thumbprint: %s\n", thumbprint(privateJWK.Public()))
return plaintext, nil
}

func decryptCredentialRun(cmd *cobra.Command, args []string) error {
ctx, c, v, err := cmdContext(cmd)
if err != nil {
return err
}

if validateArgLenth(0, args, cmd) != nil && validateArgLenth(1, args, cmd) != nil {
return fmt.Errorf("expected 0 or 1 arguments, got %d\n%s", len(args), cmd.UsageString())
}

appMap := make(map[string]shared.App)
var apps []shared.App
if len(args) > 0 {
app, err := c.GetApp(ctx, args[0])
if err != nil {
return err
}
apps = append(apps, *app)
appMap[*app.ID] = shared.App{ID: &args[0]}
} else {
apps, err = c.ListApps(ctx)
if err != nil {
return err
}
}

allCreds := make([]shared.AppUserCredential, 0)

for _, app := range apps {
if app.ID == nil {
continue
}
appUsers, err := c.ListAppUsers(ctx, *app.ID)
if err != nil {
return err
}
for _, appUser := range appUsers {
creds, err := c.ListAppUserCredentials(ctx, *app.ID, *appUser.ID)
if err != nil {
return err
}
allCreds = append(allCreds, creds...)
appMap[*app.ID] = app
}
}

pterm.Printf("Found %d credentials\n", len(allCreds))
pterm.Printf("========================================\n")
for i, cred := range allCreds {
pterm.Printf("========================================\n")
pterm.Printf("Credential #%d\n", i+1)
pterm.Printf("App Display Name: %s\n", *appMap[*cred.AppID].DisplayName)
pterm.Printf("App ID: %s\n", *cred.AppID)
pterm.Printf("App User ID: %s\n", *cred.AppUserID)
plaintext, err := decodeCredential(ctx, v, cred)
if err != nil {
pterm.Printf("Failed to decode credential: %s\n", err.Error())
pterm.Printf("========================================\n")
continue
}
pterm.Printf("Decrypted Credential: %s\n", plaintext.Bytes)
pterm.Printf("========================================\n")
}

return nil
}
4 changes: 3 additions & 1 deletion cmd/cone/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import (
"os/signal"
"syscall"

"github.com/conductorone/cone/pkg/client"
"github.com/spf13/cobra"

"github.com/conductorone/cone/pkg/client"
)

var version = "dev"
Expand Down Expand Up @@ -70,6 +71,7 @@ func runCli(ctx context.Context) int {
cliCmd.AddCommand(hasCmd())
cliCmd.AddCommand(tokenCmd())
cliCmd.AddCommand(terraformCmd())
cliCmd.AddCommand(decryptCredentialCmd())

err = cliCmd.ExecuteContext(ctx)
if err != nil {
Expand Down
40 changes: 23 additions & 17 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ go 1.21

require (
go.uber.org/zap v1.27.0
golang.org/x/net v0.29.0
golang.org/x/net v0.30.0
google.golang.org/grpc v1.67.1
google.golang.org/protobuf v1.34.2
google.golang.org/protobuf v1.35.1
)

require (
github.com/conductorone/conductorone-sdk-go v1.21.0
github.com/conductorone/baton-sdk v0.2.35
github.com/conductorone/conductorone-sdk-go v1.21.1-0.20241009214436-e388bb33c02f
github.com/pterm/pterm v0.12.62
github.com/toqueteos/webbrowser v1.2.0
github.com/xhit/go-str2duration/v2 v2.1.0
Expand All @@ -21,41 +22,46 @@ require (
atomicgo.dev/cursor v0.1.1 // indirect
atomicgo.dev/keyboard v0.2.9 // indirect
atomicgo.dev/schedule v0.0.2 // indirect
filippo.io/age v1.1.1 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/containerd/console v1.0.3 // indirect
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
github.com/ericlagergren/decimal v0.0.0-20240411145413-00de7ca16731 // indirect
github.com/go-jose/go-jose/v3 v3.0.3 // indirect
github.com/gookit/color v1.5.3 // indirect
github.com/lithammer/fuzzysearch v1.1.8 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/term v0.24.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect
golang.org/x/crypto v0.28.0 // indirect
golang.org/x/term v0.25.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect
)

require (
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pquerna/xjwt v0.2.0
github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/cobra v1.7.0
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.15.0
github.com/subosito/gotenv v1.4.2 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
github.com/spf13/viper v1.18.2
github.com/subosito/gotenv v1.6.0 // indirect
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
golang.org/x/oauth2 v0.23.0
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/text v0.19.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/square/go-jose.v2 v2.6.0
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
Loading

0 comments on commit 4c4a5b4

Please sign in to comment.