1package http 2 3import ( 4 "encoding/hex" 5 "encoding/json" 6 "fmt" 7 "net/http" 8 "reflect" 9 "testing" 10 11 "github.com/go-test/deep" 12 "github.com/hashicorp/vault/vault" 13) 14 15// Test to check if the API errors out when wrong number of PGP keys are 16// supplied for rekey 17func TestSysRekey_Init_pgpKeysEntriesForRekey(t *testing.T) { 18 core, _, token := vault.TestCoreUnsealed(t) 19 ln, addr := TestServer(t, core) 20 defer ln.Close() 21 TestServerAuth(t, addr, token) 22 23 resp := testHttpPut(t, token, addr+"/v1/sys/rekey/init", map[string]interface{}{ 24 "secret_shares": 5, 25 "secret_threshold": 3, 26 "pgp_keys": []string{"pgpkey1"}, 27 }) 28 testResponseStatus(t, resp, 400) 29} 30 31func TestSysRekey_Init_Status(t *testing.T) { 32 t.Run("status-barrier-default", func(t *testing.T) { 33 core, _, token := vault.TestCoreUnsealed(t) 34 ln, addr := TestServer(t, core) 35 defer ln.Close() 36 TestServerAuth(t, addr, token) 37 38 resp, err := http.Get(addr + "/v1/sys/rekey/init") 39 if err != nil { 40 t.Fatalf("err: %s", err) 41 } 42 43 var actual map[string]interface{} 44 expected := map[string]interface{}{ 45 "started": false, 46 "t": json.Number("0"), 47 "n": json.Number("0"), 48 "progress": json.Number("0"), 49 "required": json.Number("3"), 50 "pgp_fingerprints": interface{}(nil), 51 "backup": false, 52 "nonce": "", 53 "verification_required": false, 54 } 55 testResponseStatus(t, resp, 200) 56 testResponseBody(t, resp, &actual) 57 if !reflect.DeepEqual(actual, expected) { 58 t.Fatalf("\nexpected: %#v\nactual: %#v", expected, actual) 59 } 60 }) 61} 62 63func TestSysRekey_Init_Setup(t *testing.T) { 64 t.Run("init-barrier-barrier-key", func(t *testing.T) { 65 core, _, token := vault.TestCoreUnsealed(t) 66 ln, addr := TestServer(t, core) 67 defer ln.Close() 68 TestServerAuth(t, addr, token) 69 70 // Start rekey 71 resp := testHttpPut(t, token, addr+"/v1/sys/rekey/init", map[string]interface{}{ 72 "secret_shares": 5, 73 "secret_threshold": 3, 74 }) 75 testResponseStatus(t, resp, 200) 76 77 var actual map[string]interface{} 78 expected := map[string]interface{}{ 79 "started": true, 80 "t": json.Number("3"), 81 "n": json.Number("5"), 82 "progress": json.Number("0"), 83 "required": json.Number("3"), 84 "pgp_fingerprints": interface{}(nil), 85 "backup": false, 86 "verification_required": false, 87 } 88 testResponseStatus(t, resp, 200) 89 testResponseBody(t, resp, &actual) 90 if actual["nonce"].(string) == "" { 91 t.Fatalf("nonce was empty") 92 } 93 expected["nonce"] = actual["nonce"] 94 if diff := deep.Equal(actual, expected); diff != nil { 95 t.Fatal(diff) 96 } 97 98 // Get rekey status 99 resp = testHttpGet(t, token, addr+"/v1/sys/rekey/init") 100 101 actual = map[string]interface{}{} 102 expected = map[string]interface{}{ 103 "started": true, 104 "t": json.Number("3"), 105 "n": json.Number("5"), 106 "progress": json.Number("0"), 107 "required": json.Number("3"), 108 "pgp_fingerprints": interface{}(nil), 109 "backup": false, 110 "verification_required": false, 111 } 112 testResponseStatus(t, resp, 200) 113 testResponseBody(t, resp, &actual) 114 if actual["nonce"].(string) == "" { 115 t.Fatalf("nonce was empty") 116 } 117 if actual["nonce"].(string) == "" { 118 t.Fatalf("nonce was empty") 119 } 120 expected["nonce"] = actual["nonce"] 121 if !reflect.DeepEqual(actual, expected) { 122 t.Fatalf("\nexpected: %#v\nactual: %#v", expected, actual) 123 } 124 }) 125} 126 127func TestSysRekey_Init_Cancel(t *testing.T) { 128 t.Run("cancel-barrier-barrier-key", func(t *testing.T) { 129 core, _, token := vault.TestCoreUnsealed(t) 130 ln, addr := TestServer(t, core) 131 defer ln.Close() 132 TestServerAuth(t, addr, token) 133 134 resp := testHttpPut(t, token, addr+"/v1/sys/rekey/init", map[string]interface{}{ 135 "secret_shares": 5, 136 "secret_threshold": 3, 137 }) 138 testResponseStatus(t, resp, 200) 139 140 resp = testHttpDelete(t, token, addr+"/v1/sys/rekey/init") 141 testResponseStatus(t, resp, 204) 142 143 resp, err := http.Get(addr + "/v1/sys/rekey/init") 144 if err != nil { 145 t.Fatalf("err: %s", err) 146 } 147 148 var actual map[string]interface{} 149 expected := map[string]interface{}{ 150 "started": false, 151 "t": json.Number("0"), 152 "n": json.Number("0"), 153 "progress": json.Number("0"), 154 "required": json.Number("3"), 155 "pgp_fingerprints": interface{}(nil), 156 "backup": false, 157 "nonce": "", 158 "verification_required": false, 159 } 160 testResponseStatus(t, resp, 200) 161 testResponseBody(t, resp, &actual) 162 if !reflect.DeepEqual(actual, expected) { 163 t.Fatalf("\nexpected: %#v\nactual: %#v", expected, actual) 164 } 165 }) 166} 167 168func TestSysRekey_badKey(t *testing.T) { 169 core, _, token := vault.TestCoreUnsealed(t) 170 ln, addr := TestServer(t, core) 171 defer ln.Close() 172 TestServerAuth(t, addr, token) 173 174 resp := testHttpPut(t, token, addr+"/v1/sys/rekey/update", map[string]interface{}{ 175 "key": "0123", 176 }) 177 testResponseStatus(t, resp, 400) 178} 179 180func TestSysRekey_Update(t *testing.T) { 181 t.Run("rekey-barrier-barrier-key", func(t *testing.T) { 182 core, keys, token := vault.TestCoreUnsealed(t) 183 ln, addr := TestServer(t, core) 184 defer ln.Close() 185 TestServerAuth(t, addr, token) 186 187 resp := testHttpPut(t, token, addr+"/v1/sys/rekey/init", map[string]interface{}{ 188 "secret_shares": 5, 189 "secret_threshold": 3, 190 }) 191 var rekeyStatus map[string]interface{} 192 testResponseStatus(t, resp, 200) 193 testResponseBody(t, resp, &rekeyStatus) 194 195 var actual map[string]interface{} 196 var expected map[string]interface{} 197 198 for i, key := range keys { 199 resp = testHttpPut(t, token, addr+"/v1/sys/rekey/update", map[string]interface{}{ 200 "nonce": rekeyStatus["nonce"].(string), 201 "key": hex.EncodeToString(key), 202 }) 203 204 actual = map[string]interface{}{} 205 expected = map[string]interface{}{ 206 "started": true, 207 "nonce": rekeyStatus["nonce"].(string), 208 "backup": false, 209 "pgp_fingerprints": interface{}(nil), 210 "required": json.Number("3"), 211 "t": json.Number("3"), 212 "n": json.Number("5"), 213 "progress": json.Number(fmt.Sprintf("%d", i+1)), 214 "verification_required": false, 215 } 216 testResponseStatus(t, resp, 200) 217 testResponseBody(t, resp, &actual) 218 219 if i+1 == len(keys) { 220 delete(expected, "started") 221 delete(expected, "required") 222 delete(expected, "t") 223 delete(expected, "n") 224 delete(expected, "progress") 225 expected["complete"] = true 226 expected["keys"] = actual["keys"] 227 expected["keys_base64"] = actual["keys_base64"] 228 } 229 230 if i+1 < len(keys) && (actual["nonce"] == nil || actual["nonce"].(string) == "") { 231 t.Fatalf("expected a nonce, i is %d, actual is %#v", i, actual) 232 } 233 234 if !reflect.DeepEqual(actual, expected) { 235 t.Fatalf("\nexpected: \n%#v\nactual: \n%#v", expected, actual) 236 } 237 } 238 239 retKeys := actual["keys"].([]interface{}) 240 if len(retKeys) != 5 { 241 t.Fatalf("bad: %#v", retKeys) 242 } 243 keysB64 := actual["keys_base64"].([]interface{}) 244 if len(keysB64) != 5 { 245 t.Fatalf("bad: %#v", keysB64) 246 } 247 }) 248} 249 250func TestSysRekey_ReInitUpdate(t *testing.T) { 251 core, keys, token := vault.TestCoreUnsealed(t) 252 ln, addr := TestServer(t, core) 253 defer ln.Close() 254 TestServerAuth(t, addr, token) 255 256 resp := testHttpPut(t, token, addr+"/v1/sys/rekey/init", map[string]interface{}{ 257 "secret_shares": 5, 258 "secret_threshold": 3, 259 }) 260 testResponseStatus(t, resp, 200) 261 262 resp = testHttpDelete(t, token, addr+"/v1/sys/rekey/init") 263 testResponseStatus(t, resp, 204) 264 265 resp = testHttpPut(t, token, addr+"/v1/sys/rekey/init", map[string]interface{}{ 266 "secret_shares": 5, 267 "secret_threshold": 3, 268 }) 269 testResponseStatus(t, resp, 200) 270 271 resp = testHttpPut(t, token, addr+"/v1/sys/rekey/update", map[string]interface{}{ 272 "key": hex.EncodeToString(keys[0]), 273 }) 274 275 testResponseStatus(t, resp, 400) 276} 277