1package approle 2 3import ( 4 "context" 5 "testing" 6 "time" 7 8 "github.com/hashicorp/vault/sdk/logical" 9) 10 11func TestAppRole_BoundCIDRLogin(t *testing.T) { 12 var resp *logical.Response 13 var err error 14 b, s := createBackendWithStorage(t) 15 16 // Create a role with secret ID binding disabled and only bound cidr list 17 // enabled 18 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 19 Path: "role/testrole", 20 Operation: logical.CreateOperation, 21 Data: map[string]interface{}{ 22 "bind_secret_id": false, 23 "bound_cidr_list": []string{"127.0.0.1/8"}, 24 "token_bound_cidrs": []string{"10.0.0.0/8"}, 25 }, 26 Storage: s, 27 }) 28 if err != nil || (resp != nil && resp.IsError()) { 29 t.Fatalf("err:%v resp:%#v", err, resp) 30 } 31 32 // Read the role ID 33 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 34 Path: "role/testrole/role-id", 35 Operation: logical.ReadOperation, 36 Storage: s, 37 }) 38 if err != nil || (resp != nil && resp.IsError()) { 39 t.Fatalf("err:%v resp:%#v", err, resp) 40 } 41 42 roleID := resp.Data["role_id"] 43 44 // Fill in the connection information and login with just the role ID 45 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 46 Path: "login", 47 Operation: logical.UpdateOperation, 48 Data: map[string]interface{}{ 49 "role_id": roleID, 50 }, 51 Storage: s, 52 Connection: &logical.Connection{RemoteAddr: "127.0.0.1"}, 53 }) 54 if err != nil || (resp != nil && resp.IsError()) { 55 t.Fatalf("err:%v resp:%#v", err, resp) 56 } 57 if resp.Auth == nil { 58 t.Fatal("expected login to succeed") 59 } 60 if len(resp.Auth.BoundCIDRs) != 1 { 61 t.Fatal("bad token bound cidrs") 62 } 63 if resp.Auth.BoundCIDRs[0].String() != "10.0.0.0/8" { 64 t.Fatalf("bad: %s", resp.Auth.BoundCIDRs[0].String()) 65 } 66 67 // Override with a secret-id value, verify it doesn't pass 68 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 69 Path: "role/testrole", 70 Operation: logical.UpdateOperation, 71 Data: map[string]interface{}{ 72 "bind_secret_id": true, 73 }, 74 Storage: s, 75 }) 76 if err != nil || (resp != nil && resp.IsError()) { 77 t.Fatalf("err:%v resp:%#v", err, resp) 78 } 79 80 roleSecretIDReq := &logical.Request{ 81 Operation: logical.UpdateOperation, 82 Path: "role/testrole/secret-id", 83 Storage: s, 84 Data: map[string]interface{}{ 85 "token_bound_cidrs": []string{"11.0.0.0/24"}, 86 }, 87 } 88 resp, err = b.HandleRequest(context.Background(), roleSecretIDReq) 89 if err == nil { 90 t.Fatal("expected error due to mismatching subnet relationship") 91 } 92 93 roleSecretIDReq.Data["token_bound_cidrs"] = "10.0.0.0/24" 94 resp, err = b.HandleRequest(context.Background(), roleSecretIDReq) 95 if err != nil || (resp != nil && resp.IsError()) { 96 t.Fatalf("err:%v resp:%#v", err, resp) 97 } 98 secretID := resp.Data["secret_id"] 99 100 resp, err = b.HandleRequest(context.Background(), &logical.Request{ 101 Path: "login", 102 Operation: logical.UpdateOperation, 103 Data: map[string]interface{}{ 104 "role_id": roleID, 105 "secret_id": secretID, 106 }, 107 Storage: s, 108 Connection: &logical.Connection{RemoteAddr: "127.0.0.1"}, 109 }) 110 if err != nil || (resp != nil && resp.IsError()) { 111 t.Fatalf("err:%v resp:%#v", err, resp) 112 } 113 if resp.Auth == nil { 114 t.Fatal("expected login to succeed") 115 } 116 if len(resp.Auth.BoundCIDRs) != 1 { 117 t.Fatal("bad token bound cidrs") 118 } 119 if resp.Auth.BoundCIDRs[0].String() != "10.0.0.0/24" { 120 t.Fatalf("bad: %s", resp.Auth.BoundCIDRs[0].String()) 121 } 122} 123 124func TestAppRole_RoleLogin(t *testing.T) { 125 var resp *logical.Response 126 var err error 127 b, storage := createBackendWithStorage(t) 128 129 createRole(t, b, storage, "role1", "a,b,c") 130 roleRoleIDReq := &logical.Request{ 131 Operation: logical.ReadOperation, 132 Path: "role/role1/role-id", 133 Storage: storage, 134 } 135 resp, err = b.HandleRequest(context.Background(), roleRoleIDReq) 136 if err != nil || (resp != nil && resp.IsError()) { 137 t.Fatalf("err:%v resp:%#v", err, resp) 138 } 139 roleID := resp.Data["role_id"] 140 141 roleSecretIDReq := &logical.Request{ 142 Operation: logical.UpdateOperation, 143 Path: "role/role1/secret-id", 144 Storage: storage, 145 } 146 resp, err = b.HandleRequest(context.Background(), roleSecretIDReq) 147 if err != nil || (resp != nil && resp.IsError()) { 148 t.Fatalf("err:%v resp:%#v", err, resp) 149 } 150 secretID := resp.Data["secret_id"] 151 152 loginData := map[string]interface{}{ 153 "role_id": roleID, 154 "secret_id": secretID, 155 } 156 loginReq := &logical.Request{ 157 Operation: logical.UpdateOperation, 158 Path: "login", 159 Storage: storage, 160 Data: loginData, 161 Connection: &logical.Connection{ 162 RemoteAddr: "127.0.0.1", 163 }, 164 } 165 loginResp, err := b.HandleRequest(context.Background(), loginReq) 166 if err != nil || (loginResp != nil && loginResp.IsError()) { 167 t.Fatalf("err:%v resp:%#v", err, loginResp) 168 } 169 170 if loginResp.Auth == nil { 171 t.Fatalf("expected a non-nil auth object in the response") 172 } 173 174 if loginResp.Auth.Metadata == nil { 175 t.Fatalf("expected a non-nil metadata object in the response") 176 } 177 178 if val := loginResp.Auth.Metadata["role_name"]; val != "role1" { 179 t.Fatalf("expected metadata.role_name to equal 'role1', got: %v", val) 180 } 181 182 if loginResp.Auth.Alias.Metadata == nil { 183 t.Fatalf("expected a non-nil alias metadata object in the response") 184 } 185 186 if val := loginResp.Auth.Alias.Metadata["role_name"]; val != "role1" { 187 t.Fatalf("expected metadata.alias.role_name to equal 'role1', got: %v", val) 188 } 189 190 // Test renewal 191 renewReq := generateRenewRequest(storage, loginResp.Auth) 192 193 resp, err = b.HandleRequest(context.Background(), renewReq) 194 if err != nil || (resp != nil && resp.IsError()) { 195 t.Fatalf("err:%v resp:%#v", err, resp) 196 } 197 198 if resp.Auth.TTL != 400*time.Second { 199 t.Fatalf("expected period value from response to be 400s, got: %s", resp.Auth.TTL) 200 } 201 202 /// 203 // Test renewal with period 204 /// 205 206 // Create role 207 period := 600 * time.Second 208 roleData := map[string]interface{}{ 209 "policies": "a,b,c", 210 "period": period.String(), 211 } 212 roleReq := &logical.Request{ 213 Operation: logical.CreateOperation, 214 Path: "role/" + "role-period", 215 Storage: storage, 216 Data: roleData, 217 } 218 resp, err = b.HandleRequest(context.Background(), roleReq) 219 if err != nil || (resp != nil && resp.IsError()) { 220 t.Fatalf("err:%v resp:%#v", err, resp) 221 } 222 223 roleRoleIDReq = &logical.Request{ 224 Operation: logical.ReadOperation, 225 Path: "role/role-period/role-id", 226 Storage: storage, 227 } 228 resp, err = b.HandleRequest(context.Background(), roleRoleIDReq) 229 if err != nil || (resp != nil && resp.IsError()) { 230 t.Fatalf("err:%v resp:%#v", err, resp) 231 } 232 roleID = resp.Data["role_id"] 233 234 roleSecretIDReq = &logical.Request{ 235 Operation: logical.UpdateOperation, 236 Path: "role/role-period/secret-id", 237 Storage: storage, 238 } 239 resp, err = b.HandleRequest(context.Background(), roleSecretIDReq) 240 if err != nil || (resp != nil && resp.IsError()) { 241 t.Fatalf("err:%v resp:%#v", err, resp) 242 } 243 secretID = resp.Data["secret_id"] 244 245 loginData["role_id"] = roleID 246 loginData["secret_id"] = secretID 247 248 loginResp, err = b.HandleRequest(context.Background(), loginReq) 249 if err != nil || (loginResp != nil && loginResp.IsError()) { 250 t.Fatalf("err:%v resp:%#v", err, loginResp) 251 } 252 253 if loginResp.Auth == nil { 254 t.Fatalf("expected a non-nil auth object in the response") 255 } 256 257 renewReq = generateRenewRequest(storage, loginResp.Auth) 258 259 resp, err = b.HandleRequest(context.Background(), renewReq) 260 if err != nil || (resp != nil && resp.IsError()) { 261 t.Fatalf("err:%v resp:%#v", err, resp) 262 } 263 264 if resp.Auth.Period != period { 265 t.Fatalf("expected period value of %d in the response, got: %s", period, resp.Auth.Period) 266 } 267} 268 269func generateRenewRequest(s logical.Storage, auth *logical.Auth) *logical.Request { 270 renewReq := &logical.Request{ 271 Operation: logical.RenewOperation, 272 Storage: s, 273 Auth: &logical.Auth{}, 274 } 275 renewReq.Auth.InternalData = auth.InternalData 276 renewReq.Auth.Metadata = auth.Metadata 277 renewReq.Auth.LeaseOptions = auth.LeaseOptions 278 renewReq.Auth.Policies = auth.Policies 279 renewReq.Auth.Period = auth.Period 280 281 return renewReq 282} 283