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: Add authentication for ACP #2649

Merged
merged 19 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
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
20 changes: 10 additions & 10 deletions acp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ resources:

CLI Command:
```sh
defradb client acp policy add -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j -f examples/dpi_policy/user_dpi_policy.yml
defradb client acp policy add -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f -f examples/dpi_policy/user_dpi_policy.yml

```

Expand Down Expand Up @@ -242,7 +242,7 @@ Result:

CLI Command:
```sh
defradb client collection create -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j --name Users '[{ "name": "SecretShahzad" }, { "name": "SecretLone" }]'
defradb client collection create -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f --name Users '[{ "name": "SecretShahzad" }, { "name": "SecretLone" }]'
```

### Create public documents (without identity)
Expand All @@ -255,7 +255,7 @@ defradb client collection create --name Users '[{ "name": "PublicShahzad" }, {
### Get all docIDs without an identity (shows only public):
CLI Command:
```sh
defradb client collection docIDs -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j
defradb client collection docIDs -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f
```

Result:
Expand All @@ -273,7 +273,7 @@ Result:

### Get all docIDs with an identity (shows public and owned documents):
```sh
defradb client collection docIDs -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j
defradb client collection docIDs -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f
```

Result:
Expand All @@ -300,7 +300,7 @@ Result:
### Access the private document (including field names):
CLI Command:
```sh
defradb client collection get -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j --name Users "bae-a5830219-b8e7-5791-9836-2e494816fc0a"
defradb client collection get -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f --name Users "bae-a5830219-b8e7-5791-9836-2e494816fc0a"
```

Result:
Expand All @@ -325,7 +325,7 @@ Error:
### Accessing the private document with wrong identity:
CLI Command:
```sh
defradb client collection get -i cosmos1x25hhksxhu86r45hqwk28dd70qzux3262hdrll --name Users "bae-a5830219-b8e7-5791-9836-2e494816fc0a"
defradb client collection get -i 4d092126012ebaf56161716018a71630d99443d9d5217e9d8502bb5c5456f2c5 --name Users "bae-a5830219-b8e7-5791-9836-2e494816fc0a"
```

Error:
Expand All @@ -336,7 +336,7 @@ Error:
### Update private document:
CLI Command:
```sh
defradb client collection update -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j --name Users --docID "bae-a5830219-b8e7-5791-9836-2e494816fc0a" --updater '{ "name": "SecretUpdatedShahzad" }'
defradb client collection update -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f --name Users --docID "bae-a5830219-b8e7-5791-9836-2e494816fc0a" --updater '{ "name": "SecretUpdatedShahzad" }'
```

Result:
Expand All @@ -352,7 +352,7 @@ Result:
#### Check if it actually got updated:
CLI Command:
```sh
defradb client collection get -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j --name Users "bae-a5830219-b8e7-5791-9836-2e494816fc0a"
defradb client collection get -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f --name Users "bae-a5830219-b8e7-5791-9836-2e494816fc0a"
```

Result:
Expand All @@ -368,7 +368,7 @@ Result:
### Delete private document:
CLI Command:
```sh
defradb client collection delete -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j --name Users --docID "bae-a5830219-b8e7-5791-9836-2e494816fc0a"
defradb client collection delete -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f --name Users --docID "bae-a5830219-b8e7-5791-9836-2e494816fc0a"
```

Result:
Expand All @@ -384,7 +384,7 @@ Result:
#### Check if it actually got deleted:
CLI Command:
```sh
defradb client collection get -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j --name Users "bae-a5830219-b8e7-5791-9836-2e494816fc0a"
defradb client collection get -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f --name Users "bae-a5830219-b8e7-5791-9836-2e494816fc0a"
```

Error:
Expand Down
60 changes: 37 additions & 23 deletions acp/identity/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,48 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

/*
Package identity provides defradb identity.
*/

package identity

import "github.com/sourcenetwork/immutable"
import (
cosmosSecp256k1 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/types"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/sourcenetwork/immutable"
)

// Identity is the unique identifier for an actor.
type Identity string
// None specifies an anonymous actor.
var None = immutable.None[Identity]()

var (
// None is an empty identity.
None = immutable.None[Identity]()
)
type Identity struct {
// PublicKey is the identity public key.
PublicKey *secp256k1.PublicKey
// PrivateKey is the identity private key.
PrivateKey *secp256k1.PrivateKey
// Address is the identity address.
Address string
}

// FromPrivateKey returns a new identity using the given private key.
func FromPrivateKey(privateKey *secp256k1.PrivateKey) immutable.Option[Identity] {
pubKey := privateKey.PubKey()
return immutable.Some(Identity{
Address: AddressFromPublicKey(pubKey),
PublicKey: pubKey,
PrivateKey: privateKey,
})
}

// New makes a new identity if the input is not empty otherwise, returns None.
func New(identity string) immutable.Option[Identity] {
// TODO-ACP: There will be more validation once sourcehub gets some utilities.
// Then a validation function would do the validation, will likely do outside this function.
// https://github.com/sourcenetwork/defradb/issues/2358
if identity == "" {
return None
}
return immutable.Some(Identity(identity))
// FromPublicKey returns a new identity using the given public key.
func FromPublicKey(publicKey *secp256k1.PublicKey) immutable.Option[Identity] {
return immutable.Some(Identity{
Address: AddressFromPublicKey(publicKey),
PublicKey: publicKey,
})
}

// String returns the string representation of the identity.
func (i Identity) String() string {
return string(i)
// AddressFromPublicKey returns the unique address of the given public key.
func AddressFromPublicKey(publicKey *secp256k1.PublicKey) string {
pub := cosmosSecp256k1.PubKey{Key: publicKey.SerializeCompressed()}
// conversion from well known types should never cause a panic
return types.MustBech32ifyAddressBytes("cosmos", pub.Address().Bytes())
}
7 changes: 4 additions & 3 deletions cli/acp_policy_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func MakeACPPolicyAddCommand() *cobra.Command {
var cmd = &cobra.Command{
Use: "add [-i --identity] [policy]",
Short: "Add new policy",
//nolint:lll
Long: `Add new policy

Notes:
Expand All @@ -37,7 +38,7 @@ Notes:
- Learn more about [ACP & DPI Rules](/acp/README.md)

Example: add from an argument string:
defradb client acp policy add -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j '
defradb client acp policy add -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f '
description: A Valid DefraDB Policy Interface

actor:
Expand All @@ -61,10 +62,10 @@ resources:
'

Example: add from file:
defradb client acp policy add -i cosmos17r39df0hdcrgnmmw4mvu7qgk5nu888c7uvv37y -f policy.yml
defradb client acp policy add -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f -f policy.yml

Example: add from file, verbose flags:
defradb client acp policy add --identity cosmos1kpw734v54g0t0d8tcye8ee5jc3gld0tcr2q473 --file policy.yml
defradb client acp policy add --identity 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f --file policy.yml

Example: add from stdin:
cat policy.yml | defradb client acp policy add -
Expand Down
3 changes: 2 additions & 1 deletion cli/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ Execute queries, add schema types, obtain node info, etc.`,
return setContextDB(cmd)
},
}
cmd.PersistentFlags().StringVarP(&identity, "identity", "i", "", "ACP Identity")
cmd.PersistentFlags().StringVarP(&identity, "identity", "i", "",
"Hex formatted private key used to authenticate with ACP")
cmd.PersistentFlags().Uint64Var(&txID, "tx", 0, "Transaction ID")
return cmd
}
3 changes: 2 additions & 1 deletion cli/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ func MakeCollectionCommand() *cobra.Command {
},
}
cmd.PersistentFlags().Uint64Var(&txID, "tx", 0, "Transaction ID")
cmd.PersistentFlags().StringVarP(&identity, "identity", "i", "", "ACP Identity")
cmd.PersistentFlags().StringVarP(&identity, "identity", "i", "",
"Hex formatted private key used to authenticate with ACP")
cmd.PersistentFlags().StringVar(&name, "name", "", "Collection name")
cmd.PersistentFlags().StringVar(&schemaRoot, "schema", "", "Collection schema Root")
cmd.PersistentFlags().StringVar(&versionID, "version", "", "Collection version ID")
Expand Down
3 changes: 2 additions & 1 deletion cli/collection_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ func MakeCollectionCreateCommand() *cobra.Command {
var cmd = &cobra.Command{
Use: "create [-i --identity] <document>",
Short: "Create a new document.",
//nolint:lll
Long: `Create a new document.

Example: create from string:
defradb client collection create --name User '{ "name": "Bob" }'

Example: create from string, with identity:
defradb client collection create -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j --name User '{ "name": "Bob" }'
defradb client collection create -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f --name User '{ "name": "Bob" }'

Example: create multiple from string:
defradb client collection create --name User '[{ "name": "Alice" }, { "name": "Bob" }]'
Expand Down
3 changes: 2 additions & 1 deletion cli/collection_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ func MakeCollectionDeleteCommand() *cobra.Command {
var cmd = &cobra.Command{
Use: "delete [-i --identity] [--filter <filter> --docID <docID>]",
Short: "Delete documents by docID or filter.",
//nolint:lll
Long: `Delete documents by docID or filter and lists the number of documents deleted.

Example: delete by docID:
defradb client collection delete --name User --docID bae-123

Example: delete by docID with identity:
defradb client collection delete -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j --name User --docID bae-123
defradb client collection delete -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f --name User --docID bae-123

Example: delete by filter:
defradb client collection delete --name User --filter '{ "_gte": { "points": 100 } }'
Expand Down
2 changes: 1 addition & 1 deletion cli/collection_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Example:
defradb client collection get --name User bae-123

Example to get a private document we must use an identity:
defradb client collection get -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j --name User bae-123
defradb client collection get -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f --name User bae-123
`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down
2 changes: 1 addition & 1 deletion cli/collection_list_doc_ids.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Example: list all docID(s):
defradb client collection docIDs --name User

Example: list all docID(s), with an identity:
defradb client collection docIDs -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j --name User
defradb client collection docIDs -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f --name User
`,
RunE: func(cmd *cobra.Command, args []string) error {
col, ok := tryGetContextCollection(cmd)
Expand Down
2 changes: 1 addition & 1 deletion cli/collection_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Example: update by docID:
--docID bae-123 --updater '{ "verified": true }'

Example: update private docID, with identity:
defradb client collection update -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j --name User \
defradb client collection update -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f --name User \
--docID bae-123 --updater '{ "verified": true }'
`,
Args: cobra.RangeArgs(0, 1),
Expand Down
2 changes: 1 addition & 1 deletion cli/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Do a query request from a file by using the '-f' flag. Example command:
defradb client query -f request.graphql

Do a query request from a file and with an identity. Example command:
defradb client query -i cosmos1f2djr7dl9vhrk3twt3xwqp09nhtzec9mdkf70j -f request.graphql
defradb client query -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f -f request.graphql

Or it can be sent via stdin by using the '-' special syntax. Example command:
cat request.graphql | defradb client query -
Expand Down
14 changes: 10 additions & 4 deletions cli/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ package cli

import (
"context"
"encoding/hex"
"encoding/json"
"os"
"path/filepath"
"syscall"

"github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"golang.org/x/term"
Expand Down Expand Up @@ -139,12 +141,16 @@ func setContextTransaction(cmd *cobra.Command, txId uint64) error {
}

// setContextIdentity sets the identity for the current command context.
func setContextIdentity(cmd *cobra.Command, identity string) error {
// TODO-ACP: `https://github.com/sourcenetwork/defradb/issues/2358` do the validation here.
if identity == "" {
func setContextIdentity(cmd *cobra.Command, privateKeyHex string) error {
if privateKeyHex == "" {
return nil
}
ctx := db.SetContextIdentity(cmd.Context(), acpIdentity.New(identity))
data, err := hex.DecodeString(privateKeyHex)
if err != nil {
return err
}
privKey := secp256k1.PrivKeyFromBytes(data)
ctx := db.SetContextIdentity(cmd.Context(), acpIdentity.FromPrivateKey(privKey))
cmd.SetContext(ctx)
return nil
}
Expand Down
18 changes: 15 additions & 3 deletions crypto/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,29 @@ package crypto
import (
"crypto/ed25519"
"crypto/rand"

"github.com/decred/dcrd/dcrec/secp256k1/v4"
)

// GenerateSecp256k1 generates a new secp256k1 private key.
func GenerateSecp256k1() (*secp256k1.PrivateKey, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: You only need this for testing right? not for any production code?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'm planning on adding a way to generate and store them in the keyring as well.

return secp256k1.GeneratePrivateKey()
}

// GenerateAES256 generates a new random AES-256 bit key.
func GenerateAES256() ([]byte, error) {
data := make([]byte, 32)
_, err := rand.Read(data)
return data, err
return RandomBytes(32)
}

// GenerateEd25519 generates a new random Ed25519 private key.
func GenerateEd25519() (ed25519.PrivateKey, error) {
_, priv, err := ed25519.GenerateKey(rand.Reader)
return priv, err
}

// RandomBytes returns a random slice of bytes of the given size.
func RandomBytes(size int) ([]byte, error) {
data := make([]byte, size)
_, err := rand.Read(data)
return data, err
}
2 changes: 1 addition & 1 deletion docs/website/references/cli/defradb_client.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Execute queries, add schema types, obtain node info, etc.

```
-h, --help help for client
-i, --identity string ACP Identity
-i, --identity string Hex formatted private key used to authenticate with ACP
--tx uint Transaction ID
```

Expand Down
2 changes: 1 addition & 1 deletion docs/website/references/cli/defradb_client_acp.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Learn more about [ACP](/acp/README.md)
### Options inherited from parent commands

```
-i, --identity string ACP Identity
-i, --identity string Hex formatted private key used to authenticate with ACP
--keyring-backend string Keyring backend to use. Options are file or system (default "file")
--keyring-namespace string Service name to use when using the system backend (default "defradb")
--keyring-path string Path to store encrypted keys when using the file backend (default "keys")
Expand Down
2 changes: 1 addition & 1 deletion docs/website/references/cli/defradb_client_acp_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Interact with the acp policy features of DefraDB instance
### Options inherited from parent commands

```
-i, --identity string ACP Identity
-i, --identity string Hex formatted private key used to authenticate with ACP
--keyring-backend string Keyring backend to use. Options are file or system (default "file")
--keyring-namespace string Service name to use when using the system backend (default "defradb")
--keyring-path string Path to store encrypted keys when using the file backend (default "keys")
Expand Down
Loading
Loading