1package approle 2 3import ( 4 "context" 5 "strings" 6 "testing" 7 8 "github.com/hashicorp/vault/sdk/logical" 9) 10 11func createBackendWithStorage(t *testing.T) (*backend, logical.Storage) { 12 config := logical.TestBackendConfig() 13 config.StorageView = &logical.InmemStorage{} 14 15 b, err := Backend(config) 16 if err != nil { 17 t.Fatal(err) 18 } 19 if b == nil { 20 t.Fatalf("failed to create backend") 21 } 22 err = b.Backend.Setup(context.Background(), config) 23 if err != nil { 24 t.Fatal(err) 25 } 26 return b, config.StorageView 27} 28 29func TestAppRole_RoleNameCaseSensitivity(t *testing.T) { 30 testFunc := func(t *testing.T, roleName string) { 31 var resp *logical.Response 32 var err error 33 b, s := createBackendWithStorage(t) 34 35 // Create the role 36 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 37 Path: "role/" + roleName, 38 Operation: logical.CreateOperation, 39 Storage: s, 40 }) 41 if err != nil || (resp != nil && resp.IsError()) { 42 t.Fatalf("bad: resp: %#v\nerr:%v", resp, err) 43 } 44 45 // Get the role-id 46 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 47 Path: "role/" + roleName + "/role-id", 48 Operation: logical.ReadOperation, 49 Storage: s, 50 }) 51 if err != nil || (resp != nil && resp.IsError()) { 52 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 53 } 54 roleID := resp.Data["role_id"] 55 56 // Create a secret-id 57 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 58 Path: "role/" + roleName + "/secret-id", 59 Operation: logical.UpdateOperation, 60 Storage: s, 61 }) 62 if err != nil || (resp != nil && resp.IsError()) { 63 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 64 } 65 secretID := resp.Data["secret_id"] 66 secretIDAccessor := resp.Data["secret_id_accessor"] 67 68 // Ensure login works 69 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 70 Path: "login", 71 Operation: logical.UpdateOperation, 72 Data: map[string]interface{}{ 73 "role_id": roleID, 74 "secret_id": secretID, 75 }, 76 Storage: s, 77 }) 78 if err != nil || (resp != nil && resp.IsError()) { 79 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 80 } 81 if resp.Auth == nil { 82 t.Fatalf("failed to perform login") 83 } 84 85 // Destroy secret ID accessor 86 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 87 Path: "role/" + roleName + "/secret-id-accessor/destroy", 88 Operation: logical.UpdateOperation, 89 Storage: s, 90 Data: map[string]interface{}{ 91 "secret_id_accessor": secretIDAccessor, 92 }, 93 }) 94 if err != nil || (resp != nil && resp.IsError()) { 95 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 96 } 97 98 // Login again using the accessor's corresponding secret ID should fail 99 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 100 Path: "login", 101 Operation: logical.UpdateOperation, 102 Data: map[string]interface{}{ 103 "role_id": roleID, 104 "secret_id": secretID, 105 }, 106 Storage: s, 107 }) 108 if err != nil { 109 t.Fatal(err) 110 } 111 if resp == nil || !resp.IsError() { 112 t.Fatalf("expected error due to invalid secret ID") 113 } 114 115 // Generate another secret ID 116 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 117 Path: "role/" + roleName + "/secret-id", 118 Operation: logical.UpdateOperation, 119 Storage: s, 120 }) 121 if err != nil || (resp != nil && resp.IsError()) { 122 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 123 } 124 secretID = resp.Data["secret_id"] 125 secretIDAccessor = resp.Data["secret_id_accessor"] 126 127 // Ensure login works 128 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 129 Path: "login", 130 Operation: logical.UpdateOperation, 131 Data: map[string]interface{}{ 132 "role_id": roleID, 133 "secret_id": secretID, 134 }, 135 Storage: s, 136 }) 137 if err != nil || (resp != nil && resp.IsError()) { 138 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 139 } 140 if resp.Auth == nil { 141 t.Fatalf("failed to perform login") 142 } 143 144 // Destroy the secret ID 145 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 146 Path: "role/" + roleName + "/secret-id/destroy", 147 Operation: logical.UpdateOperation, 148 Storage: s, 149 Data: map[string]interface{}{ 150 "secret_id": secretID, 151 }, 152 }) 153 if err != nil || (resp != nil && resp.IsError()) { 154 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 155 } 156 157 // Login again using the same secret ID should fail 158 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 159 Path: "login", 160 Operation: logical.UpdateOperation, 161 Data: map[string]interface{}{ 162 "role_id": roleID, 163 "secret_id": secretID, 164 }, 165 Storage: s, 166 }) 167 if err != nil { 168 t.Fatal(err) 169 } 170 if resp == nil || !resp.IsError() { 171 t.Fatalf("expected error due to invalid secret ID") 172 } 173 174 // Generate another secret ID 175 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 176 Path: "role/" + roleName + "/secret-id", 177 Operation: logical.UpdateOperation, 178 Storage: s, 179 }) 180 if err != nil || (resp != nil && resp.IsError()) { 181 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 182 } 183 secretID = resp.Data["secret_id"] 184 secretIDAccessor = resp.Data["secret_id_accessor"] 185 186 // Ensure login works 187 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 188 Path: "login", 189 Operation: logical.UpdateOperation, 190 Data: map[string]interface{}{ 191 "role_id": roleID, 192 "secret_id": secretID, 193 }, 194 Storage: s, 195 }) 196 if err != nil || (resp != nil && resp.IsError()) { 197 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 198 } 199 if resp.Auth == nil { 200 t.Fatalf("failed to perform login") 201 } 202 203 // Destroy the secret ID using lower cased role name 204 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 205 Path: "role/" + strings.ToLower(roleName) + "/secret-id/destroy", 206 Operation: logical.UpdateOperation, 207 Storage: s, 208 Data: map[string]interface{}{ 209 "secret_id": secretID, 210 }, 211 }) 212 if err != nil || (resp != nil && resp.IsError()) { 213 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 214 } 215 216 // Login again using the same secret ID should fail 217 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 218 Path: "login", 219 Operation: logical.UpdateOperation, 220 Data: map[string]interface{}{ 221 "role_id": roleID, 222 "secret_id": secretID, 223 }, 224 Storage: s, 225 }) 226 if err != nil { 227 t.Fatal(err) 228 } 229 if resp == nil || !resp.IsError() { 230 t.Fatalf("expected error due to invalid secret ID") 231 } 232 233 // Generate another secret ID 234 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 235 Path: "role/" + roleName + "/secret-id", 236 Operation: logical.UpdateOperation, 237 Storage: s, 238 }) 239 if err != nil || (resp != nil && resp.IsError()) { 240 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 241 } 242 secretID = resp.Data["secret_id"] 243 secretIDAccessor = resp.Data["secret_id_accessor"] 244 245 // Ensure login works 246 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 247 Path: "login", 248 Operation: logical.UpdateOperation, 249 Data: map[string]interface{}{ 250 "role_id": roleID, 251 "secret_id": secretID, 252 }, 253 Storage: s, 254 }) 255 if err != nil || (resp != nil && resp.IsError()) { 256 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 257 } 258 if resp.Auth == nil { 259 t.Fatalf("failed to perform login") 260 } 261 262 // Destroy the secret ID using upper cased role name 263 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 264 Path: "role/" + strings.ToUpper(roleName) + "/secret-id/destroy", 265 Operation: logical.UpdateOperation, 266 Storage: s, 267 Data: map[string]interface{}{ 268 "secret_id": secretID, 269 }, 270 }) 271 if err != nil || (resp != nil && resp.IsError()) { 272 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 273 } 274 275 // Login again using the same secret ID should fail 276 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 277 Path: "login", 278 Operation: logical.UpdateOperation, 279 Data: map[string]interface{}{ 280 "role_id": roleID, 281 "secret_id": secretID, 282 }, 283 Storage: s, 284 }) 285 if err != nil { 286 t.Fatal(err) 287 } 288 if resp == nil || !resp.IsError() { 289 t.Fatalf("expected error due to invalid secret ID") 290 } 291 292 // Generate another secret ID 293 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 294 Path: "role/" + roleName + "/secret-id", 295 Operation: logical.UpdateOperation, 296 Storage: s, 297 }) 298 if err != nil || (resp != nil && resp.IsError()) { 299 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 300 } 301 secretID = resp.Data["secret_id"] 302 secretIDAccessor = resp.Data["secret_id_accessor"] 303 304 // Ensure login works 305 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 306 Path: "login", 307 Operation: logical.UpdateOperation, 308 Data: map[string]interface{}{ 309 "role_id": roleID, 310 "secret_id": secretID, 311 }, 312 Storage: s, 313 }) 314 if err != nil || (resp != nil && resp.IsError()) { 315 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 316 } 317 if resp.Auth == nil { 318 t.Fatalf("failed to perform login") 319 } 320 321 // Destroy the secret ID using mixed case name 322 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 323 Path: "role/saMpleRolEnaMe/secret-id/destroy", 324 Operation: logical.UpdateOperation, 325 Storage: s, 326 Data: map[string]interface{}{ 327 "secret_id": secretID, 328 }, 329 }) 330 if err != nil || (resp != nil && resp.IsError()) { 331 t.Fatalf("bad: resp: %#v\nerr: %v", resp, err) 332 } 333 334 // Login again using the same secret ID should fail 335 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 336 Path: "login", 337 Operation: logical.UpdateOperation, 338 Data: map[string]interface{}{ 339 "role_id": roleID, 340 "secret_id": secretID, 341 }, 342 Storage: s, 343 }) 344 if err != nil { 345 t.Fatal(err) 346 } 347 if resp == nil || !resp.IsError() { 348 t.Fatalf("expected error due to invalid secret ID") 349 } 350 } 351 352 // Lower case role name 353 testFunc(t, "samplerolename") 354 // Upper case role name 355 testFunc(t, "SAMPLEROLENAME") 356 // Mixed case role name 357 testFunc(t, "SampleRoleName") 358} 359