1package approle 2 3import ( 4 "context" 5 "fmt" 6 "sync" 7 "testing" 8 "time" 9 10 "github.com/hashicorp/vault/sdk/logical" 11) 12 13func TestAppRole_TidyDanglingAccessors_Normal(t *testing.T) { 14 var resp *logical.Response 15 var err error 16 b, storage := createBackendWithStorage(t) 17 18 // Create a role 19 createRole(t, b, storage, "role1", "a,b,c") 20 21 // Create a secret-id 22 roleSecretIDReq := &logical.Request{ 23 Operation: logical.UpdateOperation, 24 Path: "role/role1/secret-id", 25 Storage: storage, 26 } 27 resp, err = b.HandleRequest(context.Background(), roleSecretIDReq) 28 if err != nil || (resp != nil && resp.IsError()) { 29 t.Fatalf("err:%v resp:%#v", err, resp) 30 } 31 32 accessorHashes, err := storage.List(context.Background(), "accessor/") 33 if err != nil { 34 t.Fatal(err) 35 } 36 if len(accessorHashes) != 1 { 37 t.Fatalf("bad: len(accessorHashes); expect 1, got %d", len(accessorHashes)) 38 } 39 40 entry1, err := logical.StorageEntryJSON( 41 "accessor/invalid1", 42 &secretIDAccessorStorageEntry{ 43 SecretIDHMAC: "samplesecretidhmac", 44 }, 45 ) 46 err = storage.Put(context.Background(), entry1) 47 if err != nil { 48 t.Fatal(err) 49 } 50 51 entry2, err := logical.StorageEntryJSON( 52 "accessor/invalid2", 53 &secretIDAccessorStorageEntry{ 54 SecretIDHMAC: "samplesecretidhmac2", 55 }, 56 ) 57 err = storage.Put(context.Background(), entry2) 58 if err != nil { 59 t.Fatal(err) 60 } 61 62 accessorHashes, err = storage.List(context.Background(), "accessor/") 63 if err != nil { 64 t.Fatal(err) 65 } 66 if len(accessorHashes) != 3 { 67 t.Fatalf("bad: len(accessorHashes); expect 3, got %d", len(accessorHashes)) 68 } 69 70 _, err = b.tidySecretID(context.Background(), &logical.Request{ 71 Storage: storage, 72 }) 73 if err != nil { 74 t.Fatal(err) 75 } 76 77 // It runs async so we give it a bit of time to run 78 time.Sleep(10 * time.Second) 79 80 accessorHashes, err = storage.List(context.Background(), "accessor/") 81 if err != nil { 82 t.Fatal(err) 83 } 84 if len(accessorHashes) != 1 { 85 t.Fatalf("bad: len(accessorHashes); expect 1, got %d", len(accessorHashes)) 86 } 87} 88 89func TestAppRole_TidyDanglingAccessors_RaceTest(t *testing.T) { 90 var resp *logical.Response 91 var err error 92 b, storage := createBackendWithStorage(t) 93 94 b.testTidyDelay = 300 * time.Millisecond 95 96 // Create a role 97 createRole(t, b, storage, "role1", "a,b,c") 98 99 // Create an initial entry 100 roleSecretIDReq := &logical.Request{ 101 Operation: logical.UpdateOperation, 102 Path: "role/role1/secret-id", 103 Storage: storage, 104 } 105 resp, err = b.HandleRequest(context.Background(), roleSecretIDReq) 106 if err != nil || (resp != nil && resp.IsError()) { 107 t.Fatalf("err:%v resp:%#v", err, resp) 108 } 109 count := 1 110 111 wg := &sync.WaitGroup{} 112 now := time.Now() 113 started := false 114 for { 115 if time.Now().Sub(now) > 700*time.Millisecond { 116 break 117 } 118 if time.Now().Sub(now) > 100*time.Millisecond && !started { 119 started = true 120 _, err = b.tidySecretID(context.Background(), &logical.Request{ 121 Storage: storage, 122 }) 123 if err != nil { 124 t.Fatal(err) 125 } 126 } 127 wg.Add(1) 128 go func() { 129 defer wg.Done() 130 roleSecretIDReq := &logical.Request{ 131 Operation: logical.UpdateOperation, 132 Path: "role/role1/secret-id", 133 Storage: storage, 134 } 135 resp, err := b.HandleRequest(context.Background(), roleSecretIDReq) 136 if err != nil || (resp != nil && resp.IsError()) { 137 t.Fatalf("err:%v resp:%#v", err, resp) 138 } 139 }() 140 count++ 141 } 142 143 t.Logf("wrote %d entries", count) 144 145 wg.Wait() 146 // Let tidy finish 147 time.Sleep(1 * time.Second) 148 149 // Run tidy again 150 _, err = b.tidySecretID(context.Background(), &logical.Request{ 151 Storage: storage, 152 }) 153 if err != nil { 154 t.Fatal(err) 155 } 156 time.Sleep(2 * time.Second) 157 158 accessorHashes, err := storage.List(context.Background(), "accessor/") 159 if err != nil { 160 t.Fatal(err) 161 } 162 if len(accessorHashes) != count { 163 t.Fatalf("bad: len(accessorHashes); expect %d, got %d", count, len(accessorHashes)) 164 } 165 166 roleHMACs, err := storage.List(context.Background(), secretIDPrefix) 167 if err != nil { 168 t.Fatal(err) 169 } 170 secretIDs, err := storage.List(context.Background(), fmt.Sprintf("%s%s", secretIDPrefix, roleHMACs[0])) 171 if err != nil { 172 t.Fatal(err) 173 } 174 if len(secretIDs) != count { 175 t.Fatalf("bad: len(secretIDs); expect %d, got %d", count, len(secretIDs)) 176 } 177} 178