github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/nomad/state/state_store_acl_binding_rule_test.go (about)

     1  package state
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/hashicorp/go-memdb"
     7  	"github.com/hashicorp/nomad/ci"
     8  	"github.com/hashicorp/nomad/helper/uuid"
     9  	"github.com/hashicorp/nomad/nomad/mock"
    10  	"github.com/hashicorp/nomad/nomad/structs"
    11  	"github.com/shoenig/test/must"
    12  )
    13  
    14  func TestStateStore_UpsertACLBindingRules(t *testing.T) {
    15  	ci.Parallel(t)
    16  	testState := testStateStore(t)
    17  
    18  	// Generate a mocked ACL binding rule for testing and attempt to upsert
    19  	// this straight into state. It should fail because the auth method does
    20  	// not exist.
    21  	mockedACLBindingRules := []*structs.ACLBindingRule{mock.ACLBindingRule()}
    22  	err := testState.UpsertACLBindingRules(10, mockedACLBindingRules, false)
    23  	must.EqError(t, err, "ACL binding rule insert failed: ACL auth method not found")
    24  
    25  	// Create an auth method and ensure the binding rule is updated, so it is
    26  	// related to it.
    27  	authMethod := mock.ACLAuthMethod()
    28  	mockedACLBindingRules[0].AuthMethod = authMethod.Name
    29  
    30  	must.NoError(t, testState.UpsertACLAuthMethods(10, []*structs.ACLAuthMethod{authMethod}))
    31  	must.NoError(t, testState.UpsertACLBindingRules(20, mockedACLBindingRules, false))
    32  
    33  	// Check that the index for the table was modified as expected.
    34  	initialIndex, err := testState.Index(TableACLBindingRules)
    35  	must.NoError(t, err)
    36  	must.Eq(t, 20, initialIndex)
    37  
    38  	// List all the ACL binding rules in the table, so we can perform a number
    39  	// of tests on the return array.
    40  	ws := memdb.NewWatchSet()
    41  	iter, err := testState.GetACLBindingRules(ws)
    42  	must.NoError(t, err)
    43  
    44  	// Count how many table entries we have, to ensure it is the expected
    45  	// number.
    46  	var count int
    47  
    48  	for raw := iter.Next(); raw != nil; raw = iter.Next() {
    49  		count++
    50  
    51  		// Ensure the create and modify indexes are populated correctly.
    52  		aclRole := raw.(*structs.ACLBindingRule)
    53  		must.Eq(t, 20, aclRole.CreateIndex)
    54  		must.Eq(t, 20, aclRole.ModifyIndex)
    55  	}
    56  	must.Eq(t, 1, count)
    57  
    58  	// Try writing the same ACL binding rule to state which should not result
    59  	// in an update to the table index.
    60  	must.NoError(t, testState.UpsertACLBindingRules(20, mockedACLBindingRules, false))
    61  	reInsertActualIndex, err := testState.Index(TableACLBindingRules)
    62  	must.NoError(t, err)
    63  	must.Eq(t, 20, reInsertActualIndex)
    64  
    65  	// Make a change to the binding rule and ensure this update is accepted and
    66  	// the table index is updated.
    67  	updatedMockedACLBindingRule := mockedACLBindingRules[0].Copy()
    68  	updatedMockedACLBindingRule.BindType = "role-name"
    69  	updatedMockedACLBindingRule.SetHash()
    70  	must.NoError(t, testState.UpsertACLBindingRules(
    71  		30, []*structs.ACLBindingRule{updatedMockedACLBindingRule}, false))
    72  
    73  	// Check that the index for the table was modified as expected.
    74  	updatedIndex, err := testState.Index(TableACLBindingRules)
    75  	must.NoError(t, err)
    76  	must.Eq(t, 30, updatedIndex)
    77  
    78  	// List the ACL roles in state.
    79  	iter, err = testState.GetACLBindingRules(ws)
    80  	must.NoError(t, err)
    81  
    82  	// Count how many table entries we have, to ensure it is the expected
    83  	// number.
    84  	count = 0
    85  
    86  	for raw := iter.Next(); raw != nil; raw = iter.Next() {
    87  		count++
    88  
    89  		// Ensure the create and modify indexes are populated correctly.
    90  		aclRole := raw.(*structs.ACLBindingRule)
    91  		must.Eq(t, 20, aclRole.CreateIndex)
    92  		must.Eq(t, 30, aclRole.ModifyIndex)
    93  	}
    94  	must.Eq(t, 1, count)
    95  
    96  	// Now try inserting an ACL binding rule using the missing auth methods
    97  	// argument to simulate replication.
    98  	replicatedACLBindingRule := []*structs.ACLBindingRule{mock.ACLBindingRule()}
    99  	must.NoError(t, testState.UpsertACLBindingRules(40, replicatedACLBindingRule, true))
   100  
   101  	replicatedACLBindingRuleResp, err := testState.GetACLBindingRule(ws, replicatedACLBindingRule[0].ID)
   102  	must.NoError(t, err)
   103  	must.Eq(t, replicatedACLBindingRule[0].Hash, replicatedACLBindingRuleResp.Hash)
   104  }
   105  
   106  func TestStateStore_DeleteACLBindingRules(t *testing.T) {
   107  	ci.Parallel(t)
   108  	testState := testStateStore(t)
   109  
   110  	// Generate a some mocked ACL binding rules for testing and upsert these
   111  	// straight into state.
   112  	mockedACLBindingRoles := []*structs.ACLBindingRule{mock.ACLBindingRule(), mock.ACLBindingRule()}
   113  	must.NoError(t, testState.UpsertACLBindingRules(10, mockedACLBindingRoles, true))
   114  
   115  	// Try and delete a binding rule using an ID that doesn't exist. This
   116  	// should return an error and not change the index for the table.
   117  	err := testState.DeleteACLBindingRules(20, []string{uuid.Generate()})
   118  	must.EqError(t, err, "ACL binding rule not found")
   119  
   120  	tableIndex, err := testState.Index(TableACLBindingRules)
   121  	must.NoError(t, err)
   122  	must.Eq(t, 10, tableIndex)
   123  
   124  	// Delete one of the previously upserted ACL binding rules. This should
   125  	// succeed and modify the table index.
   126  	must.NoError(t, testState.DeleteACLBindingRules(20, []string{mockedACLBindingRoles[0].ID}))
   127  
   128  	tableIndex, err = testState.Index(TableACLBindingRules)
   129  	must.NoError(t, err)
   130  	must.Eq(t, 20, tableIndex)
   131  
   132  	// List the ACL binding rules and ensure we now only have one present and
   133  	// that it is the one we expect.
   134  	ws := memdb.NewWatchSet()
   135  	iter, err := testState.GetACLBindingRules(ws)
   136  	must.NoError(t, err)
   137  
   138  	var aclBindingRules []*structs.ACLBindingRule
   139  
   140  	for raw := iter.Next(); raw != nil; raw = iter.Next() {
   141  		aclBindingRules = append(aclBindingRules, raw.(*structs.ACLBindingRule))
   142  	}
   143  
   144  	must.Len(t, 1, aclBindingRules)
   145  	must.True(t, aclBindingRules[0].Equal(mockedACLBindingRoles[1]))
   146  
   147  	// Delete the final remaining ACL binding rule. This should succeed and
   148  	// modify the table index.
   149  	must.NoError(t, testState.DeleteACLBindingRules(30, []string{mockedACLBindingRoles[1].ID}))
   150  
   151  	tableIndex, err = testState.Index(TableACLBindingRules)
   152  	must.NoError(t, err)
   153  	must.Eq(t, 30, tableIndex)
   154  
   155  	// List the ACL binding rules and ensure we have zero entries.
   156  	iter, err = testState.GetACLBindingRules(ws)
   157  	must.NoError(t, err)
   158  
   159  	aclBindingRules = make([]*structs.ACLBindingRule, 0)
   160  
   161  	for raw := iter.Next(); raw != nil; raw = iter.Next() {
   162  		aclBindingRules = append(aclBindingRules, raw.(*structs.ACLBindingRule))
   163  	}
   164  	must.Len(t, 0, aclBindingRules)
   165  }
   166  
   167  func TestStateStore_GetACLBindingRules(t *testing.T) {
   168  	ci.Parallel(t)
   169  	testState := testStateStore(t)
   170  
   171  	// Generate a some mocked ACL binding rules for testing and upsert these
   172  	// straight into state.
   173  	mockedACLBindingRoles := []*structs.ACLBindingRule{mock.ACLBindingRule(), mock.ACLBindingRule()}
   174  	must.NoError(t, testState.UpsertACLBindingRules(10, mockedACLBindingRoles, true))
   175  
   176  	// List the ACL binding rules and ensure they are exactly as we expect.
   177  	ws := memdb.NewWatchSet()
   178  	iter, err := testState.GetACLBindingRules(ws)
   179  	must.NoError(t, err)
   180  
   181  	var aclBindingRules []*structs.ACLBindingRule
   182  
   183  	for raw := iter.Next(); raw != nil; raw = iter.Next() {
   184  		aclBindingRules = append(aclBindingRules, raw.(*structs.ACLBindingRule))
   185  	}
   186  
   187  	expected := mockedACLBindingRoles
   188  	for i := range expected {
   189  		expected[i].CreateIndex = 10
   190  		expected[i].ModifyIndex = 10
   191  	}
   192  
   193  	must.Eq(t, aclBindingRules, expected)
   194  }
   195  
   196  func TestStateStore_GetACLBindingRule(t *testing.T) {
   197  	ci.Parallel(t)
   198  	testState := testStateStore(t)
   199  
   200  	// Generate a some mocked ACL binding rules for testing and upsert these
   201  	// straight into state.
   202  	mockedACLBindingRoles := []*structs.ACLBindingRule{mock.ACLBindingRule(), mock.ACLBindingRule()}
   203  	must.NoError(t, testState.UpsertACLBindingRules(10, mockedACLBindingRoles, true))
   204  
   205  	ws := memdb.NewWatchSet()
   206  
   207  	// Try reading an ACL binding rule that does not exist.
   208  	aclBindingRule, err := testState.GetACLBindingRule(ws, uuid.Generate())
   209  	must.NoError(t, err)
   210  	must.Nil(t, aclBindingRule)
   211  
   212  	// Read the two ACL binding rules that we should find.
   213  	aclBindingRule, err = testState.GetACLBindingRule(ws, mockedACLBindingRoles[0].ID)
   214  	must.NoError(t, err)
   215  	must.Eq(t, mockedACLBindingRoles[0], aclBindingRule)
   216  
   217  	aclBindingRule, err = testState.GetACLBindingRule(ws, mockedACLBindingRoles[1].ID)
   218  	must.NoError(t, err)
   219  	must.Eq(t, mockedACLBindingRoles[1], aclBindingRule)
   220  }
   221  
   222  func TestStateStore_GetACLBindingRulesByAuthMethod(t *testing.T) {
   223  	ci.Parallel(t)
   224  	testState := testStateStore(t)
   225  
   226  	// Generate a some mocked ACL binding rules for testing and upsert these
   227  	// straight into state.
   228  	mockedACLBindingRoles := []*structs.ACLBindingRule{mock.ACLBindingRule(), mock.ACLBindingRule()}
   229  	must.NoError(t, testState.UpsertACLBindingRules(10, mockedACLBindingRoles, true))
   230  
   231  	ws := memdb.NewWatchSet()
   232  
   233  	// Lookup ACL binding rules using an auth method that is not referenced. We
   234  	// should not get any results within the iterator.
   235  	iter, err := testState.GetACLBindingRulesByAuthMethod(ws, "not-an-auth-method")
   236  	must.NoError(t, err)
   237  
   238  	var aclBindingRules []*structs.ACLBindingRule
   239  
   240  	for raw := iter.Next(); raw != nil; raw = iter.Next() {
   241  		aclBindingRules = append(aclBindingRules, raw.(*structs.ACLBindingRule))
   242  	}
   243  	must.Len(t, 0, aclBindingRules)
   244  
   245  	// Lookup ACL binding rules using an auth method that is referenced by both
   246  	// mocked rules. Ensure the results are as expected.
   247  	iter, err = testState.GetACLBindingRulesByAuthMethod(ws, mockedACLBindingRoles[0].AuthMethod)
   248  	must.NoError(t, err)
   249  
   250  	aclBindingRules = make([]*structs.ACLBindingRule, 0)
   251  
   252  	for raw := iter.Next(); raw != nil; raw = iter.Next() {
   253  		aclBindingRules = append(aclBindingRules, raw.(*structs.ACLBindingRule))
   254  	}
   255  	must.Len(t, 2, aclBindingRules)
   256  }