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 node identity #3125

Merged
merged 39 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
7caedf3
Remove code duplication
islamaliev Oct 8, 2024
a1ea081
Assign identity to a node
islamaliev Oct 8, 2024
f916707
WIP
islamaliev Oct 8, 2024
d916c33
Return RawIdentity, add test
islamaliev Oct 10, 2024
1238aba
Fix lint
islamaliev Oct 10, 2024
1b92c70
Update docs
islamaliev Oct 10, 2024
61c8fb0
Update mocks
islamaliev Oct 10, 2024
82dc3b2
Minor refactor
islamaliev Oct 10, 2024
30a028f
PR fixup
islamaliev Oct 12, 2024
2bd361a
Polish
islamaliev Oct 12, 2024
940177d
Update mocks
islamaliev Oct 12, 2024
55413a3
PR fixup
islamaliev Oct 15, 2024
5ecf6ab
Polish
islamaliev Oct 15, 2024
a32a1f4
PR fixup
islamaliev Oct 15, 2024
62e38c5
PR fixup
islamaliev Oct 15, 2024
ed20e57
PR fixup
islamaliev Oct 17, 2024
a3396bc
Update docs
islamaliev Oct 17, 2024
3f03aa5
Rename command to node-identity
islamaliev Oct 18, 2024
5b2f935
Add assign-node-identity command
islamaliev Oct 20, 2024
b9ebd23
Update docs
islamaliev Oct 20, 2024
d158f83
Lint fix
islamaliev Oct 20, 2024
ab5dc33
Update mocks
islamaliev Oct 20, 2024
4c73fb4
Create parent command node-identity
islamaliev Oct 20, 2024
5946638
PR fixup
islamaliev Oct 21, 2024
8e39ec3
Merge remote-tracking branch 'upstream/develop' into feat/node-identity
islamaliev Oct 21, 2024
0530ab7
Make identity token updatable
islamaliev Oct 22, 2024
ab3a9ea
Update docs
islamaliev Oct 22, 2024
0e0a252
Fix lint
islamaliev Oct 22, 2024
5b3a5c4
Merge remote-tracking branch 'upstream/develop' into feat/node-identity
islamaliev Oct 22, 2024
a0f173f
Turn 2d array of identities into 1d (WIP)
islamaliev Oct 12, 2024
b6d148b
Add clear distinction between user and node identity
islamaliev Oct 13, 2024
95fc645
Pass ctx explicitly
islamaliev Oct 22, 2024
b154dbe
Remove duration from node's identity
islamaliev Oct 23, 2024
af4e2f9
Remove node-identity assign command
islamaliev Oct 23, 2024
2869d87
Polish
islamaliev Oct 24, 2024
3210fbf
Merge remote-tracking branch 'upstream/develop' into feat/node-identity
islamaliev Oct 24, 2024
e4fc548
Make identityRef optional
islamaliev Oct 25, 2024
7fc8e3d
Rename UserIdentity to ClientIdentity
islamaliev Oct 25, 2024
f3ca301
Merge remote-tracking branch 'upstream/develop' into feat/node-identity
islamaliev Oct 25, 2024
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
64 changes: 27 additions & 37 deletions tests/integration/acp.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,9 @@ func addPolicyACP(
require.Fail(s.t, "Expected error should not have an expected policyID with it.", s.testCase.Description)
}

nodeIDs, nodes := getNodesWithIDs(action.NodeID, s.nodes)
for index, node := range nodes {
nodeID := nodeIDs[index]
ctx := identity.WithContext(s.ctx, getIdentity(s, nodeID, action.Identity))
_, nodes := getNodesWithIDs(action.NodeID, s.nodes)
for _, node := range nodes {
ctx := identity.WithContext(s.ctx, getIdentity(s, action.Identity))
policyResult, err := node.AddPolicy(ctx, action.Policy)

expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError)
Expand Down Expand Up @@ -189,14 +188,14 @@ func addDocActorRelationshipACP(
nodeID := nodeIDs[index]

collectionName, docID := getCollectionAndDocInfo(s, action.CollectionID, action.DocID, nodeID)
requestorIdentity := getRequestorIdentity(s, action.RequestorIdentity, nodeID)
requestorIdentity := getRequestorIdentity(s, action.RequestorIdentity)

exists, err := node.AddDocActorRelationship(
identity.WithContext(s.ctx, requestorIdentity),
collectionName,
docID,
action.Relation,
getTargetIdentity(s, action.TargetIdentity, nodeID),
getTargetIdentity(s, action.TargetIdentity),
)

expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError)
Expand Down Expand Up @@ -271,14 +270,14 @@ func deleteDocActorRelationshipACP(
nodeID := nodeIDs[index]

collectionName, docID := getCollectionAndDocInfo(s, action.CollectionID, action.DocID, nodeID)
requestorIdentity := getRequestorIdentity(s, action.RequestorIdentity, nodeID)
requestorIdentity := getRequestorIdentity(s, action.RequestorIdentity)

deleteDocActorRelationshipResult, err := node.DeleteDocActorRelationship(
identity.WithContext(s.ctx, requestorIdentity),
collectionName,
docID,
action.Relation,
getTargetIdentity(s, action.TargetIdentity, nodeID),
getTargetIdentity(s, action.TargetIdentity),
)

expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError)
Expand Down Expand Up @@ -314,9 +313,9 @@ func getCollectionAndDocInfo(s *state, collectionID, docInd, nodeID int) (string
return collectionName, docID
}

func getTargetIdentity(s *state, targetIdent, nodeID int) string {
func getTargetIdentity(s *state, targetIdent int) string {
if targetIdent != -1 {
optionalTargetIdentity := getIdentity(s, nodeID, immutable.Some(targetIdent))
optionalTargetIdentity := getIdentity(s, immutable.Some(targetIdent))
if !optionalTargetIdentity.HasValue() {
require.Fail(s.t, "Expected non-empty target identity, but it was empty.", s.testCase.Description)
}
Expand All @@ -325,9 +324,9 @@ func getTargetIdentity(s *state, targetIdent, nodeID int) string {
return ""
}

func getRequestorIdentity(s *state, requestorIdent, nodeID int) immutable.Option[acpIdentity.Identity] {
func getRequestorIdentity(s *state, requestorIdent int) immutable.Option[acpIdentity.Identity] {
if requestorIdent != -1 {
requestorIdentity := getIdentity(s, nodeID, immutable.Some(requestorIdent))
requestorIdentity := getIdentity(s, immutable.Some(requestorIdent))
if !requestorIdentity.HasValue() {
require.Fail(s.t, "Expected non-empty requestor identity, but it was empty.", s.testCase.Description)
}
Expand Down Expand Up @@ -612,11 +611,12 @@ func crossLock(port uint16) (func(), error) {
nil
}

func getNodeAudience(s *state, nodeIndex int) immutable.Option[string] {
if nodeIndex >= len(s.nodes) {
return immutable.None[string]()
}
switch client := s.nodes[nodeIndex].(type) {
func getNodeAudience(s *state) immutable.Option[string] {
//if nodeIndex >= len(s.nodes) {
//return immutable.None[string]()
//}
//switch client := s.nodes[nodeIndex].(type) {
switch client := s.nodes[0].(type) {
case *http.Wrapper:
return immutable.Some(strings.TrimPrefix(client.Host(), "http://"))
case *cli.Wrapper:
Expand Down Expand Up @@ -649,17 +649,12 @@ func generateIdentity(s *state, seedIndex int, audience immutable.Option[string]
return identity, err
}

func getIdentity(s *state, nodeIndex int, index immutable.Option[int]) immutable.Option[acpIdentity.Identity] {
func getIdentity(s *state, index immutable.Option[int]) immutable.Option[acpIdentity.Identity] {
if !index.HasValue() {
return immutable.None[acpIdentity.Identity]()
}

if len(s.identities) <= nodeIndex {
identities := make([][]acpIdentity.Identity, nodeIndex+1)
copy(identities, s.identities)
s.identities = identities
}
nodeIdentities := s.identities[nodeIndex]
nodeIdentities := s.identities

if len(nodeIdentities) <= index.Value() {
identities := make([]acpIdentity.Identity, index.Value()+1)
Expand All @@ -669,33 +664,28 @@ func getIdentity(s *state, nodeIndex int, index immutable.Option[int]) immutable
identities[i] = nodeIdentities[i]
continue
}
newIdentity, err := generateIdentity(s, i, getNodeAudience(s, nodeIndex))
newIdentity, err := generateIdentity(s, i, getNodeAudience(s))
require.NoError(s.t, err)
identities[i] = newIdentity
}
s.identities[nodeIndex] = identities
s.identities = identities
return immutable.Some(identities[index.Value()])
} else {
return immutable.Some(nodeIdentities[index.Value()])
}
}

func generateNodeIdentity(s *state, nodeIndex int) acpIdentity.Identity {
if len(s.identities) <= nodeIndex {
identities := make([][]acpIdentity.Identity, nodeIndex+1)
copy(identities, s.identities)
s.identities = identities
}

identity, err := generateIdentity(s, s.nextNodeIdentityGenSeed, getNodeAudience(s, nodeIndex))
func getNodeIdentity(s *state, nodeIndex int) acpIdentity.Identity {
// TODO: check if it makes sense to create a wrapper over the node to store client and identity
identity, err := generateIdentity(s, s.nextNodeIdentityGenSeed, immutable.None[string]())
require.NoError(s.t, err)

s.nextNodeIdentityGenSeed--

if len(s.identities[nodeIndex]) == 0 {
s.identities[nodeIndex] = append(s.identities[nodeIndex], identity)
if len(s.identities) == 0 {
s.identities = append(s.identities, identity)
} else {
s.identities[nodeIndex][0] = identity
s.identities[0] = identity
}

return identity
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ type state struct {
txns []datastore.Txn

// Identities by node index, by identity index.
identities [][]identity.Identity
identities []identity.Identity

// Identities by name.
// It is used in order to anchor the identity to a specific name as opposed to a identity's
Expand Down
30 changes: 15 additions & 15 deletions tests/integration/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ func startNodes(s *state, action Start) {
}
originalPath := databaseDir
databaseDir = s.dbPaths[nodeIndex]
node, _, err := setupNode(s, db.WithNodeIdentity(generateNodeIdentity(s, nodeIndex)))
node, _, err := setupNode(s, db.WithNodeIdentity(getNodeIdentity(s, nodeIndex)))
require.NoError(s.t, err)
databaseDir = originalPath

Expand Down Expand Up @@ -865,7 +865,7 @@ func configureNode(
for _, opt := range netNodeOpts {
nodeOpts = append(nodeOpts, opt)
}
nodeOpts = append(nodeOpts, db.WithNodeIdentity(generateNodeIdentity(s, len(s.nodes))))
nodeOpts = append(nodeOpts, db.WithNodeIdentity(getNodeIdentity(s, len(s.nodes))))

node, path, err := setupNode(s, nodeOpts...) //disable change detector, or allow it?
require.NoError(s.t, err)
Expand Down Expand Up @@ -1314,7 +1314,7 @@ func createDocViaColSave(
}

func makeContextForDocCreate(s *state, ctx context.Context, nodeIndex int, action *CreateDoc) context.Context {
ctx = identity.WithContext(ctx, getIdentity(s, nodeIndex, action.Identity))
ctx = identity.WithContext(ctx, getIdentity(s, action.Identity))
ctx = encryption.SetContextConfigFromParams(ctx, action.IsDocEncrypted, action.EncryptedFields)
return ctx
}
Expand Down Expand Up @@ -1393,7 +1393,7 @@ func createDocViaGQL(
req := fmt.Sprintf(`mutation { %s(%s) { _docID } }`, key, params)

txn := getTransaction(s, node, immutable.None[int](), action.ExpectedError)
ctx := identity.WithContext(db.SetContextTxn(s.ctx, txn), getIdentity(s, nodeIndex, action.Identity))
ctx := identity.WithContext(db.SetContextTxn(s.ctx, txn), getIdentity(s, action.Identity))

result := node.ExecRequest(ctx, req)
if len(result.GQL.Errors) > 0 {
Expand Down Expand Up @@ -1447,7 +1447,7 @@ func deleteDoc(
for index, node := range nodes {
nodeID := nodeIDs[index]
collection := s.collections[nodeID][action.CollectionID]
ctx := identity.WithContext(s.ctx, getIdentity(s, nodeID, action.Identity))
ctx := identity.WithContext(s.ctx, getIdentity(s, action.Identity))
err := withRetryOnNode(
node,
func() error {
Expand Down Expand Up @@ -1520,7 +1520,7 @@ func updateDocViaColSave(
nodeIndex int,
collection client.Collection,
) error {
ctx := identity.WithContext(s.ctx, getIdentity(s, nodeIndex, action.Identity))
ctx := identity.WithContext(s.ctx, getIdentity(s, action.Identity))

doc, err := collection.Get(ctx, s.docIDs[action.CollectionID][action.DocID], true)
if err != nil {
Expand All @@ -1540,7 +1540,7 @@ func updateDocViaColUpdate(
nodeIndex int,
collection client.Collection,
) error {
ctx := identity.WithContext(s.ctx, getIdentity(s, nodeIndex, action.Identity))
ctx := identity.WithContext(s.ctx, getIdentity(s, action.Identity))

doc, err := collection.Get(ctx, s.docIDs[action.CollectionID][action.DocID], true)
if err != nil {
Expand Down Expand Up @@ -1576,7 +1576,7 @@ func updateDocViaGQL(
input,
)

ctx := identity.WithContext(s.ctx, getIdentity(s, nodeIndex, action.Identity))
ctx := identity.WithContext(s.ctx, getIdentity(s, action.Identity))

result := node.ExecRequest(ctx, request)
if len(result.GQL.Errors) > 0 {
Expand All @@ -1594,7 +1594,7 @@ func updateWithFilter(s *state, action UpdateWithFilter) {
for index, node := range nodes {
nodeID := nodeIDs[index]
collection := s.collections[nodeID][action.CollectionID]
ctx := identity.WithContext(s.ctx, getIdentity(s, nodeID, action.Identity))
ctx := identity.WithContext(s.ctx, getIdentity(s, action.Identity))
err := withRetryOnNode(
node,
func() error {
Expand Down Expand Up @@ -1836,7 +1836,7 @@ func executeRequest(
txn := getTransaction(s, node, action.TransactionID, action.ExpectedError)

ctx := db.SetContextTxn(s.ctx, txn)
ctx = identity.WithContext(ctx, getIdentity(s, nodeID, action.Identity))
ctx = identity.WithContext(ctx, getIdentity(s, action.Identity))

var options []client.RequestOption
if action.OperationName.HasValue() {
Expand Down Expand Up @@ -2337,13 +2337,13 @@ func skipIfACPTypeUnsupported(t testing.TB, supportedACPTypes immutable.Option[[
func skipIfDatabaseTypeUnsupported(
t testing.TB,
databases []DatabaseType,
supporteDatabaseTypes immutable.Option[[]DatabaseType],
supportedDatabaseTypes immutable.Option[[]DatabaseType],
) []DatabaseType {
if !supporteDatabaseTypes.HasValue() {
if !supportedDatabaseTypes.HasValue() {
return databases
}
filteredDatabases := []DatabaseType{}
for _, supportedType := range supporteDatabaseTypes.Value() {
for _, supportedType := range supportedDatabaseTypes.Value() {
for _, database := range databases {
if supportedType == database {
filteredDatabases = append(filteredDatabases, database)
Expand Down Expand Up @@ -2436,7 +2436,7 @@ func performGetNodeIdentityAction(s *state, action GetNodeIdentity) {
actualIdent, err := s.nodes[action.NodeID].GetNodeIdentity(s.ctx)
require.NoError(s.t, err, s.testCase.Description)

expectedIdent := getIdentity(s, action.NodeID, immutable.Some(0)).Value()
expectedIdent := getIdentity(s, immutable.Some(0)).Value()
expectedRawIdent := immutable.Some(expectedIdent.IntoRawIdentity().Public())
require.Equal(s.t, expectedRawIdent, actualIdent, "identity at %d mismatch", action.NodeID)

Expand All @@ -2461,7 +2461,7 @@ func performAssignNodeIdentityAction(s *state, action AssignNodeIdentity) {
s.t.Fatalf("identity name not provided")
}

ident := generateNodeIdentity(s, action.NodeID)
ident := getNodeIdentity(s, action.NodeID)
s.identitiesByName[action.Name] = ident

err := s.nodes[action.NodeID].AssignNodeIdentity(s.ctx, ident)
Expand Down