You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2018/01/04 00:50:14 UTC

[1/7] jclouds-labs git commit: Add Azure KeyVault support

Repository: jclouds-labs
Updated Branches:
  refs/heads/master 5a3b59916 -> fa63f6b1f


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultsamplesecret.txt
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultsamplesecret.txt b/azurecompute-arm/src/test/resources/vaultsamplesecret.txt
new file mode 100644
index 0000000..d0d159e
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultsamplesecret.txt
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAvZiOgV6b4EmGiasBskXYnTaRyWzBHBGnWB11BzFN3FGigfWx
+VvjI7Ox1SHTx+vGsnjbqQPvIP4JnPEsNcWLyHa6tNAcnj/M7BuyIwdD5+Hvs6kOe
+PuSOJUf8dRjPMUpr6rcUcBmmOwTnKOH4rdpb6jXNnuCIHP+lgXCeRWveZ62TjEB+
+9aB8W8UHH854FGebiUd/aY0tpCFC7wkWz3KbgmjmY2vSe2U98Yj4+l/IWydIZ7ON
+LicteEEIGbNM0o2QSYhQBCJSw5RixDpPlrUUB094qgqUOyW0k8PvjibGxxTh0LYy
+WqWydPF0XaqFRQ6v36UvEiVGwzVsLwsJL/QVtQIDAQABAoIBAEJ6790lE3s9zNMR
+B3M/UoktzUjXvY7eEdOv4I05GJgcd+MiB6D7c1jAQQ+7Ee5wN5rynolSwBCk5RYb
+KweLLmKCEXGg4Jp1K0luPzXW1Q/wRE6Qjzh2Y/FmoHtey6f49IZE1AHKvKMNQRDw
+y4YKfxhM7WC8Un34lkwg9R5aiI3JkOG9/yNkOGrJfQnGUKt+AOAdu6fNYsRLWAPo
+G3vWSNIgwaG5WL5cKd1gacbGBlc6tLB7+LrZuNrqln5ibTtN6QJvRF9KfOrMSvxy
+L/xiHRpyzec/jrxJxAIIwFHiw2jbLdxNqDaVPFA6X1Cks4fvY40KymOS8Ecmkgx4
+C6/ZqLECgYEA38rL8zmbJRRWgrxSoROucaN/9DyvE8Hd97s1zf3I0LIF+GI3JdcN
+DV5O5VDIgQ7QZ55lOaTqJ0f2fOQZF1UbTU1gBUHVF6j1nv6Xic3OV+ZmhTMbt0Op
+WxPaKup6dkNEAe/Xg0p308r8xw/psh4/gjL1ICHwycjUlz9FQz8FLGsCgYEA2OHc
+/F4vAdK04U4w6AyivuJdIsDAks1ikl+3TqgzyesPg+DpKVNSy6DhraDFKdRqWhbK
+DqigTud8TVk9kmyF3WIb1BDf4IrxlTK08s6Jf25QA/lBlwIst3rejqWwRBY2fJp4
+O8hU31xNLd8nZq8tKYaP+yvyI6fSC+9ZIgyATl8CgYBtTlYzZG2cvMRMcsNBHaXU
+p3E1z/YLhmNuPqhXBp/xHyK/YOliuBkN8IREiSKFtsCf+8OhViVwLjv8YETJGq6N
+IT/HEZKNTd86W0uU6UrhsA1e/cmJx6iObbHfyEssPEqZT5ZJ8DN65Oh2KhWRBCks
+5MrJeQps5ITBowunfr5+JQKBgBln09goPD9tbEzcOPRlzoanw5s3kxdfQcW9up5X
+K8HibC3ZodZ6cT9zOBx7sbzlqhOlicPP0v+LNE9nPcQyPDgjrvjXhTIrdIMyrmmm
+8gpgZLUidKF42r4fgYSaOhyvsXBFNAJkxDRp/ox6EIaBzLuJjMIycqnklcFaJ0nK
+xxjnAoGAU/3jRok74Yn0MY183UCXICf/WxVYzwEi3cyRWVh6gAo2ExNye97rau/B
+Y2woAcVxEN9h1HNirq8Z2AwrZKd/BcBnvulZqECeH5zBQ0W56ADX72r+lzOAxTJa
+U1AIlNCIkfsQ5CpIoYsVoNEM8P+GyS8B9kaEmk/FVKldRTKJqkI=
+-----END RSA PRIVATE KEY-----
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultsecretbackup.txt
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultsecretbackup.txt b/azurecompute-arm/src/test/resources/vaultsecretbackup.txt
new file mode 100644
index 0000000..877d28c
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultsecretbackup.txt
@@ -0,0 +1 @@
+KUF6dXJlS2V5VmF1bHRTZWNyZXRCYWNrdXBWMS5taWNyb3NvZnQuY29tZXlKcmFXUWlPaUppTTJJd1pqZ3dZeTB5Wkdaa0xUUmlPVGt0T0RVeE1TMWpZVGRrTTJKbFlURTVNMkVpTENKaGJHY2lPaUpTVTBFdFQwRkZVQ0lzSW1WdVl5STZJa0V4TWpoRFFrTXRTRk15TlRZaWZRLlFLelA2anZVR0Y5X1M3UU8tRkZDTHIyNGp0RXJuandkQThNZUtsSGE1MmhvS01rNjdiOHQyckZhNTJ6dGR2and1d1I3VWh4RldRLUpuOHk3YlJiNlYtcTlUYl9iV3E5clplUlhpUy1jdUhPak9ONHB1bHd1cVVmQkJOU2V3NlJGUXpOUzRrQks3RmxQSGZpQVRRaUUtLTc1cnZIM0dMTEdDd25KTkxIUDNTR0FtWlR1dXo0bTN6X1owR3RsZUU5XzFZT3pqczU1UmJFNEdOTC0tWDhDWnlRWmVFNGdGRXZ2WmFrYkRXTk5hOWd6SnBUNlNOTm5tcGtpMFZocGxaNGdzWmNmR29xQktZNF8wTS1WTmpIbkZ5QUlySXdsSTNjZkIzWUVCbHJ3X1A1QXhQVFFvNDJNa1pETmNKYjFwaGh0c1phaTNLcWRxT0E0ZEVWNVZWQ1VNZy5fTkN5eTNJSS1VV1VtWDB4UXhTVnNRLjJkbEFpUEpSa3NlenNVTEZocTE3ZmdCWm11XzBBaU5GUWkyTU8zMnlVanpEMjMxQlY0bHhwU21ZMmI1bGdsTXlYQzNtYy1PT2VmcVNseXdqMlcwTllOYzJKOUg4MzFHc0VCdXZ1SS1BWEQ3dzdocGRNTG5VaG5DQ0RUQTJYY0ZTZ2lXTWMzMFFISHUzRi1KcDh2VGU1QUk5R1ljelEzSFVPRjJOREpjRERoLU9CNFFJRlZWMS0zWEJkeS1uOWR5MjlSY0FwNEo4WHRPMjZxN2dJa3BDT1JxMTVuOXZHd3ViV
 lZhdGhfMlZwM3p1ZEJPX3k5SlFTVVYxMW1jZFVIQXNCVGxFMU5xYkZaU0lfX093NTl6ZktGRTVTMnZrYWl6a1RFbXFVQi1EcTVnMnMxQ05PcUdUNk1wQWNiSEtUNTNSajNZN2RlOFlBckZIMlNSZF9udUV6Q09PMnAxeFpFUjh4c2RIRjlDM1Nnc3ZRQzIzX3BfeDBIR1RfbWY5V3B4amZOWF9Bd1E5NWNLZ0JOdU1ENEZ1TTdWTmpKc1JaSGtvM2tNTlJ5N3BybkhhaVd5aHRiVV9ic0w3X3FRa1JGNEl3eGFzUlh6M3RtZzYyT2tCWl82MEMyRE11Q0pIZWtqSnI5SGJDeGp6Z1lGMjVmRDhDTk00YmNaRV9ma1Z4Y2lVVklWU2lvemREX3owTFBMY09paVp6dTNIWGIxekplZkJsVXduc1NBT0RZa2lWbjJPMjFOMHpkRGwwMjNPSnJTdWQycWo1UkEtVTlsVWRxU0w1QUltN1ZaMTFSVzh5clpkWXc4NFJTejVySldRSm1sVW54RzJHb3lMMTFaQkJacXY5bEJ5Wnd3SDN6ZGNDZWFRQWM0LVZJWjQ5NzBfTC1tT2paNUFwdXI4UERHVDIydkNKdEw1cVVaNGJabThBeXQ0NDFEX2o2cG16NzRUWWlIU210ZnlJcnNvRTMzbG9QM0xGdTFKMklXLXJTdk9HUElveEx1ai1ZMkNKMENYTk1lR0UyQVNhOEY5RmY3enhVLVRkbVZneWpfYi1EY05XUmVJZUMyTEF4OV9EWDY0QlRJV0pNSFc3a2plbjRkem9kajMzbjM1aFU0UUVmRVM0a2pmUUtMVENrYnRlWXliVUlQWmhaa3BDRzRpTVBQSVpTRVdqU2RMckl6NlRYN3FJZHFHcE1UYk9zeld3eWc2dzI1WTd4aDFvelY2RjJEOFpKR3FiZjhQZTVDRWtIcE5LeC1kNExUTzNsOWZlZVd6RFRwTzRnTWpBZ1RNdHBqdX
 RqT2xhSEYyN1JLaVNGWU82eFNQY0ZVb3JGMlZKRERlQUxZSk9Pb0JOMkhpalJ1Y0R5bWR3NUtzNHBZTmZvV3dCeHVnbjBPenJoNVFIS2Q3dWpoUll1XzhkLWd2RVNKQzNJY3JZWFI1aFhxaUp5WGVNMGtULWlnRUFQRFVmSXE0cjJiRW5iZ0RhdUZrN2syekZzXzZzeGZ4Ty1TNEp0alp2UkJia0lnZm1WdVB5OXZTQy02QUl0aEctMW5OUE9PNG1oak9ON2EzVUdzQVpvREg0T1RFczA3ajJMQ092VGdqX05PN1pJcEt6LWhyU0daSXdCdjlRdHJ5NjY4US1kTUpRZzAzRi1UXzZlX1htc1BWRWt1RWdaSzdnS092STNzdjk4Y0VVODFiVEZfNjQ3cmE5bjN6NHdnbmZwVE1lWEhMQ1JWeGpKbHJURmxJcW9wbkdZeHlQdm5iVXBzb3A2NktHbVAtTEpTeERjNlJJckpuQ2drbjN1OGN0c25NZWxuWHZSeGZFdFRsNnkyendUV3ZSdnVEcVR1UFphQXdNVmllbTdaaXZqNTdMYjNHT3RUcjBxQXNrMC15dHN2TkpmY19tYTEydVlUWll1b2RCM2ZoVFBITjFaclFoQzdiWDVHdXFDUFFDQXFuenJjT0lESDIweTFlZHAxam1ZdTFyZThPaG9yMDRiVWhLa2stcUVVdEVsZTFqYzFTckNuWkEyMlRZMFNVYkxkVm1hb2dyaUJfckpackVaM0tneGFaSjNnZ3FQd2NhSW0wNUVoMDQwYUpUa20xOWdzRzVCNEExQ2dDWHRMOGhUMFl4TmNneW9tT0dnRzd2Q2FzdW43WGhtdjJZLWROWVNrZzRZbzlfdkktWWlmZEp2MnhJVWY3eGFvS1RRRzY4NkNzaE0zTkVubFRWb1FjaWxjaXllaHc3RkpiMnYyTDFNV0tlamRWM2dPNjIyVjZ3QXV4MW9GdXJhdWZORzh2cnkyS2NwczF
 OUzBWeFJObU9mNDFkbFRhSkljUmFJM2tSbUg5UkpTakJZcnA1Y1ZzZWh5WGVaQXpnU2JzUlg0eGp6LURJSGVPa1dRS05HMlZvTnloZ3BZS05FVnlNN2dkdFBWTUo3TmlkVE9PM3BaYTBMeV9GaUhHLXc0dkUwTTR0X1ZpOFhvRzBFbWhJcjBWdmRvN0RGUXVUbmdoblRGVnpreEtyRlJSZzRMWkhCNzR2Z1BycTVTNGxTV2hlZGRfekRad2JVeUxJY1NXWmk3QzlpWDctczNHeGp2UjNGekxJT3NuSXUxVHpaQ3B4a0d4ZGkzU1VyS1c0NGlTaDM3eGNmaEpsNDVDcTQ5N1pQQmo1eVA0UmYwazVTS3djM1JvOUJoUXN0aUdzVk5qMlIzcmpHTHZfOEwtUHNxOG1IYTZKZHVvaEtRbEVQT1hYNzZ5aDdab05KUUZhemRNRWV3eVJNOGQ3eUZIcFc0M3RTZTA4Mi1BUmRjcW55OXFZRmJLMFJfV3dNTDlOQkFpNWxjQldUSms2ZHJXN1RPRmJ2eDFyZ0p5cUcza2w4TEdwRExheFNfaFhXZVRxSy1YS3pVRk9zNjA4WEp6U2NhVE1xay1QTVZIdkN5c3Vjci1mOFN3SF9wdks0bTNQYWprcGVOMjl3dmVZdUp1X1ZKZHlPNE9yY043cnRYVXR3VWNSblBzNUNXYWF0N1RfUWhnZ1VTdHBZczBJTlVuNXU2Rm5oNGVsUUxTTEhvdWZDdE9RekpDV0VVd3N2TWdkdkc2cEUzU2FZU244OFd6YzdMbGctZEVMeERLQXE1dmI1bXFleXAyem9hZFhJa20wWks5amlwdnBZdmQyRlFnNE50NF9nOUo3WTRoeVp3TjFWdXlqQ2YyUkFpMzJXZlNid1B4ZmdVdjhVVkktcUlKWjc5TjNQOTFnWnB4X2xxdF9aNFB0bzIwTTZqamw0MGkwUXRwMUdaRU5hbHoxN00zbFRBUl81WkY5Ql81
 dTIwN1FGbGh3UDYzbFRNMF8td1lCOVBzV2VtdGJUTEZYZmJFU0t6VGVzckVzQWwzQkVDMFotSndhMno3cEc3VHhvQWhON21hWDdKajVjbWtzdmJjVk05MENSNTVwbmtwOUM0Tm1BRWM2amw1dXRBSGlGOEdaV1A1V2lGVFFwVTBpYktXLUVycEMyblVvRVBmbFRPbVowM2lzaFNLbnZTSUFUQjBMSW95S1lhYm9tcU5NWkZhWDV5OWVjTGtFdmlmYS04dW8zRzNYSWFhQWk3TE5YRXpqQm9iZWlVSzBFeGJxaGd0VzNvbE85V1o1MGxqOWw5UXpGV3FWOGRiUThOeTdkdzRnT2wzNl93ZVNrbHJ3b19VVDA0Sm9Oc0IzOWFrUnJaWkdzaXJuamR1T0F4RWZaaXRLdHdTdkpZSzRtV0huSk5uRENMVlo2cVpzVG50NThjVjQ2cFY3T1FxckNpVnlQREU3Y1N0RW5neXhEbzRZdlpibDNrNndkaGxYOXAwZXNaOUdXbHNxcXlGVUJCc19QbVN2UUd6djZ3bDlWSnk4WnNKYmpIdlkwclZOUFJnN2FYTjlNOElsVWpia3B6RmdqY0VPZVVrZ1M5UFp5RURLYUw5U2NjeFJFbjI1OUR3MDFJZFJPS2U5Mnp3U1hSQUJlbVhBcVRaSGZPd1Z2VDBUS2JnWkwxcE5vb242NWRMR0hKZ2dYWmt6SjVHT3dvbFRkYkEwczVkaXRQZllxU3ZwQmpmVHpfQTZhTWl3bmFnamlET0QzT2doeTQxc1Q2UDdTWTFxanpfWkxjZ1puc1djWDlkOWc4TkpzZ1had184d2dUY3hRdW1TM3oxVTYxX2dlbndBNzNPaEs5MWl5YW90Z2ZySWNzOWxodm1taEcwRC1KX3lkQUxfdXNROWc0dHRlN1ptN0hMZDZOb1pCYnJFTkZ0ODRmejdJbjJxMXItM1lsYk9kMm1xRXIxZUdZMmtCTlh1eFc0XzlVZ
 VFOZER5UHZPRFR0Ni1mR3FuMF9sd2dYOXJldUxsRzY1UjFKY29yMnczWmZBLWU3SEN3Y2tCTTBEcmhjZmwxdmhtcVY4WXpMcHBxUUhPa1F2YUpMNHE2ZG1ZS0thZmhGbXcxVk1qSnp5UWswUVNzazFWUGdzUmpta3l0YmpjZjRoenJNdVRMU0VQTGZVWGVPOEYzbEdLNE03bWlhblRPQ0xXSmRNWnc5dFlKSHVTQ0g3SjhZOUVwNS1XWTRBeUZlaFJfaDVSNHVYdlBPUmUzSzZQcWJibHlaMEJuclpCcDZnTUNvNVcwZkd5ZEdiQ1N6dzUzVndsY3FEWnJlb0p0Rk5pZFNzdTBtLUFub1g0SWxsSFFnYVB4SnlLYWRPSWpvalNKMnZTTTZCYXRkci1pR3VTbDJSZmswLXkyX3FFeDZRakNOQWFXaWNvM2RsS3VIY0h6TU13YzVXT1J4bzdweXdWYmtOUmpoOUVPZlkxSW51Tk11SjdfYWt2T0V5MGpMVXlCc04zR0hrTzlEUExFLTk2bVlIMWd6R19IbGQ5aVRpOWcxZTB5WjdBVkNEQzBoaVRZMXB5V0pVanpGVE91clJaYW5qOWl5MWdjcFdpeFVPN2xiWjl2aHFhdHg0VUh4VFRneS1IbUcydmRTYjhJbGl2bHNqLXVpM3dxUjBYeVNXRDFVYmVJUFVIZk15bTR2bXkzdkIyWEJKMEJnTF80bkx2VWQ2MEpFdXI1Z0ZOSUUtR0RSY0JwSkdPZXN4b1lyQktYU1I2QUd1UG84b2ptemFudUFIaF83OTI5OWg2aDdtN3JRZ0NxYzJ0Wjg1dU9YVHNzZzRYSW1kVjdCN3ZrcHRlUmt5WjZEQ1RFYW5GRmNvWEJzSThYMVFZeFFDRzgtdzltYlppTHNiRGN6bVV5Z3RiRkNQUXludjByclNiRzFUUWtmZnk4UGVfT0tRYkxSdWJNNG55dmZxWG81X21FcXA0T1dzMlJSMDhiSE
 9YTWpDU0FlYUwyaC1RRjg2MmRrLUNpV05ZSVVuUHhTYWkyWTEzeGVqVklwYkI1YkZzaVUzTWJmY2pyNnduRUVuMmhzWGx1aGpWVXFtUzNIOEZwZDFkS0pSa1lzM2NWZWRHTEhaRFZRM0hTWHlBWk1FbXNzX01kTUlGMFZhUjU0WTU3QXhhcnR5QUFmZy1OWWtkNVhtVkxPQWJnRFdCMzdrbEVPVEZCYXV4SGg4dXJjVk9neVF6Z1RNcTIwTWpEUzhzaDlZLUNHNUxSRHJiYVlRU2ZoR0VSYVFYcFpuVEdWX20tcDFpWU1zMEMzRFBJanMxSWIxZVR4X0lJbTFPRlBGOWcwWVJsbXFCdkx2bGtGeExqM0t2SGxQVEUwaUYyZ1JaMmN4NUMtckJGZ0dXaU1hRUQzdjcxTW0xQlFJeklaY1lfUUI5V3FsWEVaSmJWZHNZc0FmNm93eW9XckpVQUszTEswclRPaEdNS2VaUzlzUGxvZWU4T0x2OTluc2wxRUM0Z3F2MHJqdk9JQ0pVR0kwb1R1dXV5enhSbU41cHJtX2VycHNLbkM3QmRXV3VaLXRab0g0c2ZDeExiYVppeW8tQU1xdVRhMzB0ckFOV21rSUtuTHFubFRvcXJXZ1JiQjF3Q0hlVjA4WXR1ak9sQUdKc0dHRTRLVjc0X2QwSXZ2NXA3RUxQZlJJcU51cGVLdlpTZ0pxU19tQmU0eG5wTFZsWDhmaHRIOE9aSUxKQ25ZQUt5VHZyNGFoZG9jd0NrOE9JX0xVOG5wQ1Rpc1VFdEo1MXpON2dqUEs2eGhCazZ1YnNNeE9oalhNSjhUd01sWHZvMjcwSXdYV08wVm1lN3pGbnp2S3dnWjV0UlB4c1hwTjlySDBlLUxIZU9uNHIzWWtHeHlpRDFrMkUyM0s4ay02RmxhM2JwMV9DQktfdkM0VUhBU3NqQnJjd21kOHVvYzdJTDRsQmRfeldQbEtyUXp6bmxyZVlMV2w3S1R
 mdG5ELXF0STlLMlFpWm9Ib3E4anZSYUJTTjZqUTk3RXhEb0E5dUk1LVRFc21UYlpCV3pGemdoOS1mbXBKZmQ1R3VNUXVhblJDN2VPbzh4bkJrVnI2UVVnZjVhYzV6Um0zc1ZBaktBVDJ5djc0dTNyOEJjUEJMcTBsc1gwTUpza3FlNEZhN193NXB5Q0Y4dS1RbVFkN2dmeUdPSW1OdTgySGJPSk5yMHg4Vm9NZU9uUExsVUhyY2cxNk43czY5ekU3SEM2UExpcHJobHdmY2JvMXlaZDZYVUxYNGI5MXJ4ME5SU0VpYURISGV1QS1LNWFQb1F6VVZiSFJ0cExvdHpwTEFTZkhwMWFhSEoyakRQUElfcVllbzkwWjVrR3RiV2plSTBYVDlzMy1TMk5pcW16Z2Q5WEMxNEJaUTM0UWpNdksyNUpJYXpqWW5FdGQzYUFYRWFZNU9CdGZ5R2NIcV96UmRaZlVQdDdDNk1LTFdRbnpzTXNWZHJ4cnpCcWRMMVV0NzlIQnZ5M3RlWDZ0RmJuYjR2ZkgxY3NZUl82a041T205VndHelRZYWNGM1dDTkNuOHljMk13N1Y4b25ZOXFLU0VLS1hRYk5KYlB1cEJsT29qLV9tV1drTkdmSy1TUHJoRmFGNF9LaDFTd25TelBydHRVVU9WMXg4ejNmUVFXZml5eVllcGd0VHVGSEZheHE0YXNCUjRQVndfUnBJN3c4QTNiSGR5ODQteWprZU0wU0k4WE5CdkRmVThRXzA2aVZjWkg1UWhwU2VENVpZNWotcDNzN3c4X2MtRXo3RHRZaHgyQzducWU2OFNVYmt3dmd4d2RUOFhaYzcySTJwSUFwYklPTzN0SEFIVmpvVHdVX3dsSHctSVZKbzZfSlBvRE5JbEdZcHdDZ21oMV9rb2FCLXFvMGdQd0UyeG1sRmdNeVVCd3lfWHNEdVRUcVJfT3pYVHBQbWdhTWNZMXJldEgzVjBDZ3BHaTBqYVZo
 N2NJSUpoVWNRcXRIVHl6S1hDTWVMRVBXYzJuVV9oXzB5U0tTanJMUmR1cHpkMTZ6V2sxdTRzdDRDak9CR1AxbloxVU14X3lGQ3ZsVVlESGY5OHhBelJNbUg0c1YxMnVMYmlCS2l0eTEwSG83X2N6T0htQ09LeE1oaFlhRmVrS19veUU3X3pWbTRjUzhHbEJiMUo2UVZMeHpGMXlORnlqeHdITEtnNURXUzN1T0JfSGpNdHlMOHh4WXhNR2FjNTh1X2g5ZEM5QThtVGJ5bEF6Wll6eTUtU3pvSVJYZHhVOGtBN1c0QzFWYmI1VGgyVHZmemF1Vk1mNVg0SWc1WTU4NzMtd3oxNVpHZW5xU3JreFVqU0tVUWVlZkI2eEg1aGtKeWs1cDZWY1JJNzF6SkVEVEU2LWZHSGsxTlNRd2QtS2tTaWlwMjI2d0JCOHZSVWdGQ1VZcy1EZC10TXF1aDdKZjlaRTU5amNzR0ZkTDJhamFRcjc4Z21VZEFVYS1HRHpQeHp3YkM0b1FKS29ObkNEZGc5WV94S3NHeEtDWnRVT1VjM0Z4MlptZFpfM292ZGExaHdyVDZpYVJLM0MxZnh0ZVpheE9IWkNvdW5MeU8wZUkzZ1Nnd2dkVERxODZ3TzY2U3pHdGRxYmo0bGZrT3NkRUYtUDNhQU1yOGNuclh3b2NOdGVpaVJ0YnVqLXhfNlVQUk5hWHJCV0lHRk1Mc2x3b1VlRXE1ZUpuOUhSYmdvd25vU3psOUdDWWdtdnRsb1ZIVHFVLXpNWk9TcmxPejA2aU1ZZjBjakliUDJtdHUyWHlDS3dkRnFsZHJqUWs3VmNUUEJkczluRjR2Z3lmOU1nSFVTeVpHTHFubHNtdG5ER1p4VTN0UmR1eXZfTFRLcDgxYVVQVVprb0EtTkMzdEFncHdQbUtodzVnY3M4U19aSC16VVNFd1BjLVR6NGtJSzhrSFVxQ2ZFY0pfMmhpX2RTWHRKbFB3TG9EeU95R
 1hTWkp5ZGIzb2hjblk3Z3RneGpQaU82Vmlwd1NZMXRVVUV1YmFKbHkzTGFwRjN0cXlEZXBBdHMxc2JDdzNSSm1HcE92WjlfaTk5SXZ6WjY1WDZPSDB1YUpDTWl6bFpzdGQwZ1FRMXl2ZTNQRDRaVHZPdzlMMm9Na0ZDQlFvQzBUalU5b0tPTHNpdlAzbTZOWjROLVpiaWFaNTIxbWU1ZjBWV1loRkN3RENxajRyUDZ5WmloOXVPTW5rWnNhZ3BtS0RlaVV6d1RpaENKdlRkZnBfbG1GQ3cyc0Jyd0lIVWJfdkxWY1RWNDd4NVNwSnhuS2dpWHpZUG8weElnYnY1bmZGWTJvM1NBWkZpSlNlNEJQbmFsX2FQLUFnNDdWM2h5NmNzT0xCM3l0VlNCRDdlNjFpU1VGWVhBUmZJVEVXa0VRaHBIWWJyRTlvemdldzdOLU5HaXdtWndOUy04SUFSbmRFS0tXSXRXb01fMllXVmYxS1ZoME8xQ2wwR0ZDV2NCNzFDLWxMazVJbkpKUm5Wd2dPQ1M2YUFKaEM2T2pIVVYydTR3TTdndFI1c1Y2Snk1NUxQcjFUbVpZQXAyVFNSMG0zUWMyN0ZKRnhxaFU2R20tZGtVNXZKbGtnSjUwY2xTUVVGcVl4Z0pDX1hSdWVpOXNzdkNmbnZVOW1ZSEFQZTU2Q2dXNWFiVGhSOEJCcTc2aTlxUjBlRVV4eFVWUUtCemFhVlB3TmVqaFRVYnpWcHZnNGlqSFRocFBlRzdDZ3hwQ00zT0pCaHFnS2k3RzVTeHFHYjdNVEhoclp2Q3I2WHZtZGdFc3NxWW9RdUQyYUQ4TlhjdVU0Mm1NVGwyZS1sY2pwU1E5R29hdlRHSjFCeFp2YWlYZzRNS1FGUjBjRDQzYkxsaXo2Y2NCeEEwZnJTU2dqbUhRNERxdHhjYkFiNFlPTDFlYkFQNFNSQnJwa3hGQW5fc1l6ci1aR0F0R0l3R1JfUHRRbjVLQ05yaX
 BueDRITVBmS2UtTHg4MzBIWFNxVGV5c0hRbGtuRlRSeFdwLXdNcUxPMlFhTHJnMlUzdnBDekloRmh4dG1tWnpPSE8zZmY2YTAySk9BaDVDek9GcG9oTDFXakl5a1RMd0dNMDZMQ25uNmhGeDVOZEhmVTlqaTdKNGZuT2RkcVh2ZnZ4TDhSN0wtM1d6SThIUVI4TkRHRzl6ZGtHZDUyQVlkNTBqUTZPN29qNUdkZldGMDdQTVY3WWFETjhGc1YwT19wZDM5bFpiUnM0SlV1Y0xWMzBXNGpqVGdselZGeXBaZEFxQXU0d2pWTVd5T1I0X1RSMnh6YW0wemx0ZXc1bm01TUk4NTlZYVhCVE95bkV5T18yRndDR2hzdmxQR2t5SHZuc050NFVya3pjRGswX0JaYUlYYWFNbUhxMUJQUWdiR0d6bUxNV0FXcFY0OUszdnBkN250WHFBZEVyN25VUnVpS2RSckVTYnpEUnAxclh2NExOMUdGNXRnRUFCZFhwYTVQVG9nVDM3cHUwb1BNNW5FZXFDeklRbmtjemMzUVk5SEZwY1J6bWFmbV9fSngxRFd0ak5qR1J0cVM4aHVUcVNKOG5ORl90ZXZsV2dwOU5uZU9KSUZwZkVMMnhYMTc2dnkyQ1FONTBFRzZZWmM4dXZreHFNUmk3OFNjdENEeXQ0WS5Sc3FFM1dad19XclIxRmtQc1RtWW1B
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultsetcertificatecontacts.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultsetcertificatecontacts.json b/azurecompute-arm/src/test/resources/vaultsetcertificatecontacts.json
new file mode 100644
index 0000000..ca89576
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultsetcertificatecontacts.json
@@ -0,0 +1,8 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/contacts",
+	"contacts": [{
+		"email": "foo@bar.com",
+		"name": "Foo bar",
+		"phone": "867-5309"
+	}]
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultsetcertificatecontactsrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultsetcertificatecontactsrequestbody.json b/azurecompute-arm/src/test/resources/vaultsetcertificatecontactsrequestbody.json
new file mode 100644
index 0000000..eefa904
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultsetcertificatecontactsrequestbody.json
@@ -0,0 +1,7 @@
+{
+	"contacts": [{
+		"email": "foo@bar.com",
+		"name": "Foo bar",
+		"phone": "867-5309"
+	}]
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultsetcertificateissuer.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultsetcertificateissuer.json b/azurecompute-arm/src/test/resources/vaultsetcertificateissuer.json
new file mode 100644
index 0000000..dd08fe9
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultsetcertificateissuer.json
@@ -0,0 +1,21 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/issuers/globalsign01",
+	"provider": "GlobalSign",
+	"credentials": {
+		"account_id": "imauser"
+	},
+	"org_details": {
+		"zip": 0,
+		"admin_details": [{
+			"first_name": "Admin",
+			"last_name": "Guy",
+			"email": "adminguy@certsforme.com",
+			"phone": "867-5309"
+		}]
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509346474,
+		"updated": 1509346474
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultsetcertificateissuerrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultsetcertificateissuerrequestbody.json b/azurecompute-arm/src/test/resources/vaultsetcertificateissuerrequestbody.json
new file mode 100644
index 0000000..4d2d25a
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultsetcertificateissuerrequestbody.json
@@ -0,0 +1,15 @@
+{
+	"credentials": {
+		"account_id": "imauser",
+		"pwd": "This1sMyPa55wurD!"
+	},
+	"org_details": {
+		"admin_details": [{
+			"email": "adminguy@certsforme.com",
+			"first_name": "Admin",
+			"last_name": "Guy",
+			"phone": "867-5309"
+		}]
+	},
+	"provider": "GlobalSign"
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultsetsecret.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultsetsecret.json b/azurecompute-arm/src/test/resources/vaultsetsecret.json
new file mode 100644
index 0000000..9f1e929
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultsetsecret.json
@@ -0,0 +1,11 @@
+{
+	"value": "-----BEGIN RSA PRIVATE KEY-----\\nMIIEogIBAAKCAQEAvZiOgV6b4EmGiasBskXYnTaRyWzBHBGnWB11BzFN3FGigfWx\\nVvjI7Ox1SHTx+vGsnjbqQPvIP4JnPEsNcWLyHa6tNAcnj/M7BuyIwdD5+Hvs6kOe\\nPuSOJUf8dRjPMUpr6rcUcBmmOwTnKOH4rdpb6jXNnuCIHP+lgXCeRWveZ62TjEB+\\n9aB8W8UHH854FGebiUd/aY0tpCFC7wkWz3KbgmjmY2vSe2U98Yj4+l/IWydIZ7ON\\nLicteEEIGbNM0o2QSYhQBCJSw5RixDpPlrUUB094qgqUOyW0k8PvjibGxxTh0LYy\\nWqWydPF0XaqFRQ6v36UvEiVGwzVsLwsJL/QVtQIDAQABAoIBAEJ6790lE3s9zNMR\\nB3M/UoktzUjXvY7eEdOv4I05GJgcd+MiB6D7c1jAQQ+7Ee5wN5rynolSwBCk5RYb\\nKweLLmKCEXGg4Jp1K0luPzXW1Q/wRE6Qjzh2Y/FmoHtey6f49IZE1AHKvKMNQRDw\\ny4YKfxhM7WC8Un34lkwg9R5aiI3JkOG9/yNkOGrJfQnGUKt+AOAdu6fNYsRLWAPo\\nG3vWSNIgwaG5WL5cKd1gacbGBlc6tLB7+LrZuNrqln5ibTtN6QJvRF9KfOrMSvxy\\nL/xiHRpyzec/jrxJxAIIwFHiw2jbLdxNqDaVPFA6X1Cks4fvY40KymOS8Ecmkgx4\\nC6/ZqLECgYEA38rL8zmbJRRWgrxSoROucaN/9DyvE8Hd97s1zf3I0LIF+GI3JdcN\\nDV5O5VDIgQ7QZ55lOaTqJ0f2fOQZF1UbTU1gBUHVF6j1nv6Xic3OV+ZmhTMbt0Op\\nWxPaKup6dkNEAe/Xg0p308r8xw/psh4/gjL1ICHwycjUlz9FQz8FLGsCgYEA2OHc\\n/F4vAdK04U4w6A
 yivuJdIsDAks1ikl+3TqgzyesPg+DpKVNSy6DhraDFKdRqWhbK\\nDqigTud8TVk9kmyF3WIb1BDf4IrxlTK08s6Jf25QA/lBlwIst3rejqWwRBY2fJp4\\nO8hU31xNLd8nZq8tKYaP+yvyI6fSC+9ZIgyATl8CgYBtTlYzZG2cvMRMcsNBHaXU\\np3E1z/YLhmNuPqhXBp/xHyK/YOliuBkN8IREiSKFtsCf+8OhViVwLjv8YETJGq6N\\nIT/HEZKNTd86W0uU6UrhsA1e/cmJx6iObbHfyEssPEqZT5ZJ8DN65Oh2KhWRBCks\\n5MrJeQps5ITBowunfr5+JQKBgBln09goPD9tbEzcOPRlzoanw5s3kxdfQcW9up5X\\nK8HibC3ZodZ6cT9zOBx7sbzlqhOlicPP0v+LNE9nPcQyPDgjrvjXhTIrdIMyrmmm\\n8gpgZLUidKF42r4fgYSaOhyvsXBFNAJkxDRp/ox6EIaBzLuJjMIycqnklcFaJ0nK\\nxxjnAoGAU/3jRok74Yn0MY183UCXICf/WxVYzwEi3cyRWVh6gAo2ExNye97rau/B\\nY2woAcVxEN9h1HNirq8Z2AwrZKd/BcBnvulZqECeH5zBQ0W56ADX72r+lzOAxTJa\\nU1AIlNCIkfsQ5CpIoYsVoNEM8P+GyS8B9kaEmk/FVKldRTKJqkI=\\n-----END RSA PRIVATE KEY-----\\n",
+	"contentType": "testSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/b936ececbc674f3bb1367ae50d28ada0",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335932,
+		"updated": 1509335932,
+		"recoveryLevel": "Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultsetsecretrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultsetsecretrequestbody.json b/azurecompute-arm/src/test/resources/vaultsetsecretrequestbody.json
new file mode 100644
index 0000000..52dc431
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultsetsecretrequestbody.json
@@ -0,0 +1,7 @@
+{
+	"attributes": {
+		"enabled": true
+	},
+	"contentType": "testSecretKey",
+	"value": "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAvZiOgV6b4EmGiasBskXYnTaRyWzBHBGnWB11BzFN3FGigfWx\nVvjI7Ox1SHTx+vGsnjbqQPvIP4JnPEsNcWLyHa6tNAcnj/M7BuyIwdD5+Hvs6kOe\nPuSOJUf8dRjPMUpr6rcUcBmmOwTnKOH4rdpb6jXNnuCIHP+lgXCeRWveZ62TjEB+\n9aB8W8UHH854FGebiUd/aY0tpCFC7wkWz3KbgmjmY2vSe2U98Yj4+l/IWydIZ7ON\nLicteEEIGbNM0o2QSYhQBCJSw5RixDpPlrUUB094qgqUOyW0k8PvjibGxxTh0LYy\nWqWydPF0XaqFRQ6v36UvEiVGwzVsLwsJL/QVtQIDAQABAoIBAEJ6790lE3s9zNMR\nB3M/UoktzUjXvY7eEdOv4I05GJgcd+MiB6D7c1jAQQ+7Ee5wN5rynolSwBCk5RYb\nKweLLmKCEXGg4Jp1K0luPzXW1Q/wRE6Qjzh2Y/FmoHtey6f49IZE1AHKvKMNQRDw\ny4YKfxhM7WC8Un34lkwg9R5aiI3JkOG9/yNkOGrJfQnGUKt+AOAdu6fNYsRLWAPo\nG3vWSNIgwaG5WL5cKd1gacbGBlc6tLB7+LrZuNrqln5ibTtN6QJvRF9KfOrMSvxy\nL/xiHRpyzec/jrxJxAIIwFHiw2jbLdxNqDaVPFA6X1Cks4fvY40KymOS8Ecmkgx4\nC6/ZqLECgYEA38rL8zmbJRRWgrxSoROucaN/9DyvE8Hd97s1zf3I0LIF+GI3JdcN\nDV5O5VDIgQ7QZ55lOaTqJ0f2fOQZF1UbTU1gBUHVF6j1nv6Xic3OV+ZmhTMbt0Op\nWxPaKup6dkNEAe/Xg0p308r8xw/psh4/gjL1ICHwycjUlz9FQz8FLGsCgYEA2OHc\n/F4vAdK04U4w6AyivuJdIsDAks1ik
 l+3TqgzyesPg+DpKVNSy6DhraDFKdRqWhbK\nDqigTud8TVk9kmyF3WIb1BDf4IrxlTK08s6Jf25QA/lBlwIst3rejqWwRBY2fJp4\nO8hU31xNLd8nZq8tKYaP+yvyI6fSC+9ZIgyATl8CgYBtTlYzZG2cvMRMcsNBHaXU\np3E1z/YLhmNuPqhXBp/xHyK/YOliuBkN8IREiSKFtsCf+8OhViVwLjv8YETJGq6N\nIT/HEZKNTd86W0uU6UrhsA1e/cmJx6iObbHfyEssPEqZT5ZJ8DN65Oh2KhWRBCks\n5MrJeQps5ITBowunfr5+JQKBgBln09goPD9tbEzcOPRlzoanw5s3kxdfQcW9up5X\nK8HibC3ZodZ6cT9zOBx7sbzlqhOlicPP0v+LNE9nPcQyPDgjrvjXhTIrdIMyrmmm\n8gpgZLUidKF42r4fgYSaOhyvsXBFNAJkxDRp/ox6EIaBzLuJjMIycqnklcFaJ0nK\nxxjnAoGAU/3jRok74Yn0MY183UCXICf/WxVYzwEi3cyRWVh6gAo2ExNye97rau/B\nY2woAcVxEN9h1HNirq8Z2AwrZKd/BcBnvulZqECeH5zBQ0W56ADX72r+lzOAxTJa\nU1AIlNCIkfsQ5CpIoYsVoNEM8P+GyS8B9kaEmk/FVKldRTKJqkI\u003d\n-----END RSA PRIVATE KEY-----"
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatecertificate.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatecertificate.json b/azurecompute-arm/src/test/resources/vaultupdatecertificate.json
new file mode 100644
index 0000000..4998d29
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatecertificate.json
@@ -0,0 +1,58 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"sid": "https://kvvaultapilivetest.vault.azure.net/secrets/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"x5t": "K7HXO6YIK6xwCX8W1InUKsJV9Rk",
+	"cer": "MIIDTDCCAjSgAwIBAgIQVA+XomvgS56ybBWv2MnacjANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDExhteWNlcnRpZmljYXRlLmZvb2Jhci5jb20wHhcNMTcxMDMwMDY0NDI3WhcNMTgxMDMwMDY1NDI3WjAjMSEwHwYDVQQDExhteWNlcnRpZmljYXRlLmZvb2Jhci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCusjC1A7rQEjW9SRL9XHRNDl0EuNYEV9AVQcAEmgpcJ6WgusdataeFrHKPmO8RUZgXk4sE14d3o9HjduYcqfOre+FBdQDWwoFHEAlq9Iz1r4woGk3f1oq9KepE12cRMTyTA214iluYNUx7XxSca3KFFswqonvcekbLJF2IPydNL0XrlIJFCUoAs3PRWLfPnYuijqRGhk8B9xGQMBtuDsnEi4wQRxusFHR1JxHSbY65xi1Hc9Ds9RAxdKwvBmYYC7V78q6qNM0LpenFGlZJMd/eRLVDguM1d17yyTX/lei/Oj8yVVDsva23ilUrv1mR549sv1lIqxNzdOGLsb6jykJ7AgMBAAGjfDB6MA4GA1UdDwEB/wQEAwIFoDAJBgNVHRMEAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAfBgNVHSMEGDAWgBRnlX51KtyJ/m/V8I/3il4cAW/HOzAdBgNVHQ4EFgQUZ5V+dSrcif5v1fCP94peHAFvxzswDQYJKoZIhvcNAQELBQADggEBAAbSFuMRMbXyH80iA/jU7vuUCYe0Ra/wTTB1qVHTBuqQ/W8RI01mdqI9+GAPOTyN94XPPYVpSz9ZQ3P0/dhgcsahW5bZQkC0CcUSE5R7JUOKI5Up6n8zZM/unHlC6ZcEpNA/scObPKhQXdZayxgf2/p30bii4CiyS7ADEH92xMnzo1Eu9Dckxh1MRDypfxMY9YIzggks
 iY78BxoNsRDyxNjeRHVUxAIJ3n9TUv+WG31r7rMOIs6ZPsWc96AzUHHAZREVTEh2kiKKIenbMXn1tCpF6/GJKGfp7rt5ObUoQAlnn7kgAceteKZHEMgRZ4c4EQq+yqBw3hJrz4dOabJcmcU=",
+	"attributes": {
+		"enabled": true,
+		"nbf": 1509345867,
+		"exp": 1540882467,
+		"created": 1509346467,
+		"updated": 1509346472,
+		"recoveryLevel": "Purgeable"
+	},
+	"tags": {
+		"selfsigned": "true"
+	},
+	"policy": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/policy",
+		"key_props": {
+			"exportable": false,
+			"kty": "RSA",
+			"key_size": 2048,
+			"reuse_key": false
+		},
+		"secret_props": {
+			"contentType": "application/x-pkcs12"
+		},
+		"x509_props": {
+			"subject": "CN=mycertificate.foobar.com",
+			"ekus": ["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"],
+			"key_usage": ["digitalSignature", "keyEncipherment"],
+			"validity_months": 12,
+			"basic_constraints": {
+				"ca": false
+			}
+		},
+		"lifetime_actions": [{
+			"trigger": {
+				"lifetime_percentage": 80
+			},
+			"action": {
+				"action_type": "AutoRenew"
+			}
+		}],
+		"issuer": {
+			"name": "Self"
+		},
+		"attributes": {
+			"enabled": true,
+			"created": 1509346452,
+			"updated": 1509346472
+		}
+	},
+	"pending": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/pending"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatecertificateissuer.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatecertificateissuer.json b/azurecompute-arm/src/test/resources/vaultupdatecertificateissuer.json
new file mode 100644
index 0000000..4960ce5
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatecertificateissuer.json
@@ -0,0 +1,21 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/issuers/globalsign01",
+	"provider": "GlobalSign",
+	"credentials": {
+		"account_id": "imauser"
+	},
+	"org_details": {
+		"zip": 0,
+		"admin_details": [{
+			"first_name": "Admin",
+			"last_name": "Guy",
+			"email": "adminguy@certsforme.com",
+			"phone": "867-5309"
+		}]
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509346474,
+		"updated": 1509346654
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatecertificateissuerrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatecertificateissuerrequestbody.json b/azurecompute-arm/src/test/resources/vaultupdatecertificateissuerrequestbody.json
new file mode 100644
index 0000000..658610e
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatecertificateissuerrequestbody.json
@@ -0,0 +1,15 @@
+{
+	"credentials": {
+		"account_id": "imauser",
+		"pwd": "CanHa5P455wuRd!"
+	},
+	"org_details": {
+		"admin_details": [{
+			"email": "adminguy@certsforme.com",
+			"first_name": "Admin",
+			"last_name": "Guy",
+			"phone": "867-5309"
+		}]
+	},
+	"provider": "GlobalSign"
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatecertificateoperation.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatecertificateoperation.json b/azurecompute-arm/src/test/resources/vaultupdatecertificateoperation.json
new file mode 100644
index 0000000..800f399
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatecertificateoperation.json
@@ -0,0 +1,11 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myTempCertificate/pending",
+	"issuer": {
+		"name": "Self"
+	},
+	"csr": "MIIEtzCCAp8CAQAwJzElMCMGA1UEAxMcbXl0ZW1wY2VydGlmaWNhdGUuZm9vYmFyLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMmt2TbL1ndbSggTwx2l3k/ZUzt0IGO/FMB/oqpmc5izy2KGi0/uSoEdFA9cSqfctL3FGx2J1cFVTz287cvLB8HB3A4svAoPnKsZmKpXuYbF4fK2wQGXm/iNk+JVq1KL0lfoqW2g52lHDM85XURMn8YCkAGIKeTlOVyEn7EMBuBumcJbszj0g56Ij+VKmxoua/Ja4ONmIGsKdyZRBEuvFQ1GTnJUvCWHwyo1pT0M5EY/VL9ikc283DSvpQcfvNelQgQfWCpTRX1Q7nTUHk14DD4d/Y6OdbjcVuqE0Jdqdw6MXfU2zrkPo/nZBf5GHsUChiaxzVeEafPjWKvqVDzhEYXpmMB5SDAELaQtV6PoX+kxcjAO4K//BQtwneHHVF/Sh+7ke3nNUlSf4Mjn541wS7LdkBDOlTnKdYu+DhfbdkRD4E9LPiDduWDWHZs051uFBecR93JaZmX2b376RORQygDkBRga/MNENoEEnsz4zmoMYCGspZhRXEC9Uts1hzYEtwM1hyLqJlfadX/sct20N4JkhDkM8NG2V43R8jcnKFmzjfv6Yc1tuiQ1GQpYNFPJWh+fakAZkt7IwYsvy1CQg92Yvi3ne9zRTBn00enDpBTWaGCZ84gYYaT7Yfyo7/WRTjinYt6R0+u8l0AmZb0xkgxEACIQoyrg+oWQZI4YrneRAgMBAAGgSzBJBgkqhkiG9w0BCQ4xPDA6MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAgEAr8RMKLLpGG31Mq4Dor6Tf11AoiHCLH33MUqblF1VfDiw0++qBZ1dgm0D
 +uzQph/bZ6jKe/PUWpS1bErfaOt3iaVNOHom8jP/U3kZiYWvc/YHetU03prm1Qb+izNZA97NNeZRsuCXMAkNAHQnXa/rz/zG6BmGXFigh55wglX6aB8PnfKZb7N6RCct8BsKSV8uPpxXzRWPKrv7TA2RKfMifUD/Dzt7FSDuYJ8FGkvQNX012RXb2DqHp8tbZgUSj7iXdoZMZ1jfwlh6P61yhfItbF4SYvtBd9PTWIxP6SkCfDjJ7f0/ofwoV2DvAiwfH7URdQIMC+B8dPCqbjya3Ku+B2fWXXhdG7gJqa1zRY066QTIsHwfwd3WbeLQxCcBUEQUG0u23gj9fDX81fvKsgHtN9Nod5wXsdLtjjpHpJQJlDanII4H3fvDxAOlqSnxxEhjL9uA3YXUERMGGjExXA5kCOqKrdfGT5x4yosuNutylvF8YYn8r+mvMgegtVl8XmKnyP+uESSE2krVVmnSM2gveq7ILxBvanq70LmQVeYQB4AlLtUsxPUPIPiOryDI39KrlqWKdl3/oC7Gx+WbVzXxs37NEwt/tx8E+r1Nq/jRFxP0QlyyUdjpiPXjUpuCdn4y6erpCuahbMP+CZNCNgeEh1v2pNljuaGCIB+VA2Fz/oU=",
+	"cancellation_requested": true,
+	"status": "inProgress",
+	"status_details": "Pending certificate created. Certificate request is in progress. This may take some time based on the issuer provider. Please check again later.",
+	"request_id": "32051e4e4ac947c5b9ad1b6737bee7c0"
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatecertificateoperationrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatecertificateoperationrequestbody.json b/azurecompute-arm/src/test/resources/vaultupdatecertificateoperationrequestbody.json
new file mode 100644
index 0000000..5d370b3
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatecertificateoperationrequestbody.json
@@ -0,0 +1,3 @@
+{
+    "cancellation_requested": true
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicy.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicy.json b/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicy.json
new file mode 100644
index 0000000..97e126a
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicy.json
@@ -0,0 +1,37 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/policy",
+	"key_props": {
+		"exportable": false,
+		"kty": "RSA",
+		"key_size": 2048,
+		"reuse_key": false
+	},
+	"secret_props": {
+		"contentType": "application/x-pkcs12"
+	},
+	"x509_props": {
+		"subject": "CN=mycertificate.foobar.com",
+		"ekus": ["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"],
+		"key_usage": ["digitalSignature", "keyEncipherment"],
+		"validity_months": 12,
+		"basic_constraints": {
+			"ca": false
+		}
+	},
+	"lifetime_actions": [{
+		"trigger": {
+			"lifetime_percentage": 80
+		},
+		"action": {
+			"action_type": "AutoRenew"
+		}
+	}],
+	"issuer": {
+		"name": "Self"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509346452,
+		"updated": 1509346452
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicyrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicyrequestbody.json b/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicyrequestbody.json
new file mode 100644
index 0000000..4424614
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatecertificatepolicyrequestbody.json
@@ -0,0 +1,8 @@
+{
+	"key_props": {
+		"exportable": true,
+		"key_size": 3072,
+		"kty": "RSA",
+		"reuse_key": false
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatecertificaterequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatecertificaterequestbody.json b/azurecompute-arm/src/test/resources/vaultupdatecertificaterequestbody.json
new file mode 100644
index 0000000..747f02f
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatecertificaterequestbody.json
@@ -0,0 +1 @@
+{"policy":{"id":"myCertificate","issuer":{"name":"Self"},"key_props":{"exportable":false,"key_size":2048,"kty":"RSA","reuse_key":false},"lifetime_actions":[],"x509_props":{"ekus":[],"key_usage":[],"subject":"CN=mycertificate.foobar.com","validity_months":12}},"tags":{"selfsigned":"true"}}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatekey.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatekey.json b/azurecompute-arm/src/test/resources/vaultupdatekey.json
new file mode 100644
index 0000000..cd208a1
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatekey.json
@@ -0,0 +1,18 @@
+{
+	"key": {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/bd6566ec707e4ad89f4ab9577d9d0bef",
+		"kty": "RSA",
+		"key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+		"n": "2ZWsir4hwVxFTQXfWN7Vy1zA33jg1kxUMHmkmEFtVjGDByzmMfEXpnPziNCtYppBtpNT4AJEVQ60aIgSLNrUYBMoeiI2HCf2NM0NTdwYp7wq5tImtbGDASdDXQ1v3Bv3hXGh3CVmN2VLRf0OmoXnZUG_2UZZ05iPXOY6lNFfq8L81v0ZCMiXwFvNVhZ_fzppzhnwuHQf-X6Lnvrd1ocFqF8IFjV3663eumAfZmBLPP6tmiAZYW3G68_G0I2CHLtTPFX05aN51Jn42RITgcs63HFMT_iVW5556YR0BwtqkCXIUgTD714Fipz7EKGqhHsqND7YUSKpiRVQhfoZEckAkQ",
+		"e": "AQAB"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509335902,
+		"updated": 1509335923,
+		"recoveryLevel": "Purgeable"
+	},
+	"tags": {
+		"purpose": "testing"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatekeyrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatekeyrequestbody.json b/azurecompute-arm/src/test/resources/vaultupdatekeyrequestbody.json
new file mode 100644
index 0000000..9ce289f
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatekeyrequestbody.json
@@ -0,0 +1,5 @@
+{
+  "tags": {
+    "purpose": "testing"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatekeywithversion.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatekeywithversion.json b/azurecompute-arm/src/test/resources/vaultupdatekeywithversion.json
new file mode 100644
index 0000000..337b33b
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatekeywithversion.json
@@ -0,0 +1,18 @@
+{
+	"key": {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/bd6566ec707e4ad89f4ab9577d9d0bef",
+		"kty": "RSA",
+		"key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+		"n": "2ZWsir4hwVxFTQXfWN7Vy1zA33jg1kxUMHmkmEFtVjGDByzmMfEXpnPziNCtYppBtpNT4AJEVQ60aIgSLNrUYBMoeiI2HCf2NM0NTdwYp7wq5tImtbGDASdDXQ1v3Bv3hXGh3CVmN2VLRf0OmoXnZUG_2UZZ05iPXOY6lNFfq8L81v0ZCMiXwFvNVhZ_fzppzhnwuHQf-X6Lnvrd1ocFqF8IFjV3663eumAfZmBLPP6tmiAZYW3G68_G0I2CHLtTPFX05aN51Jn42RITgcs63HFMT_iVW5556YR0BwtqkCXIUgTD714Fipz7EKGqhHsqND7YUSKpiRVQhfoZEckAkQ",
+		"e": "AQAB"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509335902,
+		"updated": 1509335927,
+		"recoveryLevel": "Purgeable"
+	},
+	"tags": {
+		"purpose": "testing again"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatesecret.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatesecret.json b/azurecompute-arm/src/test/resources/vaultupdatesecret.json
new file mode 100644
index 0000000..3f96107
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatesecret.json
@@ -0,0 +1,13 @@
+{
+	"contentType": "testSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/b936ececbc674f3bb1367ae50d28ada0",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335932,
+		"updated": 1509335934,
+		"recoveryLevel": "Purgeable"
+	},
+	"tags": {
+		"purpose": "testing"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatesecretrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatesecretrequestbody.json b/azurecompute-arm/src/test/resources/vaultupdatesecretrequestbody.json
new file mode 100644
index 0000000..06c614f
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatesecretrequestbody.json
@@ -0,0 +1,5 @@
+{
+	"tags": {
+		"purpose": "testing"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatesecretwithversion.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatesecretwithversion.json b/azurecompute-arm/src/test/resources/vaultupdatesecretwithversion.json
new file mode 100644
index 0000000..e6d8f46
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatesecretwithversion.json
@@ -0,0 +1,13 @@
+{
+	"contentType": "testSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/b936ececbc674f3bb1367ae50d28ada0",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335932,
+		"updated": 1509335946,
+		"recoveryLevel": "Purgeable"
+	},
+	"tags": {
+		"purpose": "testing again"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultupdatesecretwithversionrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultupdatesecretwithversionrequestbody.json b/azurecompute-arm/src/test/resources/vaultupdatesecretwithversionrequestbody.json
new file mode 100644
index 0000000..a9c6db9
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultupdatesecretwithversionrequestbody.json
@@ -0,0 +1,5 @@
+{
+	"tags": {
+		"purpose": "testing again"
+	}
+}


[5/7] jclouds-labs git commit: Add Azure KeyVault support

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiLiveTest.java
new file mode 100644
index 0000000..026aa28
--- /dev/null
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiLiveTest.java
@@ -0,0 +1,1057 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.features;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import org.jclouds.azurecompute.arm.domain.Certificate;
+import org.jclouds.azurecompute.arm.domain.Certificate.Contact;
+import org.jclouds.azurecompute.arm.domain.Certificate.Contacts;
+import org.jclouds.azurecompute.arm.domain.Certificate.AdministrationDetails;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateIssuer;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateOperation;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificatePolicy;
+import org.jclouds.azurecompute.arm.domain.Certificate.DeletedCertificate;
+import org.jclouds.azurecompute.arm.domain.Certificate.DeletedCertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.OrganizationDetails;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerCredentials;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerParameters;
+import org.jclouds.azurecompute.arm.domain.Certificate.KeyProperties;
+import org.jclouds.azurecompute.arm.domain.Certificate.SecretProperties;
+import org.jclouds.azurecompute.arm.domain.Certificate.X509CertificateProperties;
+import org.jclouds.azurecompute.arm.domain.Secret;
+import org.jclouds.azurecompute.arm.domain.Secret.SecretBundle;
+import org.jclouds.azurecompute.arm.domain.Secret.SecretAttributes;
+import org.jclouds.azurecompute.arm.domain.Secret.DeletedSecretBundle;
+import org.jclouds.azurecompute.arm.domain.Key;
+import org.jclouds.azurecompute.arm.domain.Key.JsonWebKey;
+import org.jclouds.azurecompute.arm.domain.Key.KeyBundle;
+import org.jclouds.azurecompute.arm.domain.Key.KeyAttributes;
+import org.jclouds.azurecompute.arm.domain.Key.DeletedKeyBundle;
+import org.jclouds.azurecompute.arm.domain.Key.KeyOperationResult;
+import org.jclouds.azurecompute.arm.domain.SKU;
+import org.jclouds.azurecompute.arm.domain.Vault;
+import org.jclouds.azurecompute.arm.domain.Vault.DeletedVault;
+import org.jclouds.azurecompute.arm.domain.VaultProperties;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
+import org.testng.SkipException;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+import static com.google.common.base.Preconditions.checkState;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
+
+@Test(groups = "live", testName = "VaultApiLiveTest")
+public class VaultApiLiveTest extends BaseAzureComputeApiLiveTest {
+   private String vaultName;
+   private URI vaultUri = null;
+   private static String KEY_NAME = "myKey";
+   private static String IMPORT_KEY_NAME = "myImportKey";
+   private static String RECOVERABLE_KEY_NAME = "myRecoverableKey";
+   private static String SECRET_NAME = "mySecret";
+   private static String RECOVERABLE_SECRET_NAME = "myRecoverableSecret";
+   private static String CERTIFICATE_NAME = "myCertificate";
+   private static String TEMP_CERTIFICATE_NAME = "myTempCertificate";
+   private static String RECOVERABLE_CERTIFICATE_NAME = "myRecoverableCertificate";
+   private static String IMPORTABLE_CERTIFICATE_NAME = "myImportableCertificate";
+   private String importableCertificatePem = stringFromResource("/vaultimportablecert.txt");
+   private String sampleSecret = stringFromResource("/vaultsamplesecret.txt");
+   private static String cryptoText = "R29sZCUyNTIxJTJCR29sZCUyNTIxJTJCR2" +
+           "9sZCUyQmZyb20lMkJ0aGUlMkJBbWVyaWNhbiUyQlJpdmVyJTI1MjE";
+   private static String cryptoAlgorithm = "RSA-OAEP";
+   private static String hashToSign = "FvabKT6qGwpml59iHUJ72DZ4XyJcJ8bgpgFA4_8JFmM";
+   private static String signatureAlgorithm = "RS256";
+   private static String contentEncryptionKey = "YxzoHR65aFwD2_IOiZ5rD08jMSALA1y7b_yYW0G3hyI";
+
+   @BeforeClass
+   @Override
+   public void setup() {
+      super.setup();
+      createTestResourceGroup();
+      vaultName = String.format("kv%s", this.getClass().getSimpleName().toLowerCase());
+   }
+
+   @AfterClass(alwaysRun = true)
+   public void forceVaultRemoval() {
+      // see if the vault has been deleted or not
+      Vault vault = api().getVault(vaultName);
+      if (vault != null) {
+         if ((vault.properties().enableSoftDelete() != null) && vault.properties().enableSoftDelete()) {
+            api().deleteVault(vaultName);
+            checkState(deletedVaultStatus.create(resourceGroupName, true).apply(vaultName),
+                    "vault was not deleted before timeout");
+         } else {
+            return;
+         }
+      }
+
+      DeletedVault deletedVault = api().getDeletedVault(LOCATION, vaultName);
+      if (deletedVault != null) {
+         api().purgeVault(LOCATION, vaultName);
+         checkState(deletedVaultStatus.create(resourceGroupName, false).apply(vaultName),
+                 "vault was not purged before timeout");
+      }
+   }
+
+   @Test
+   public void testCreate() {
+      String objectId = api.getServicePrincipal().get().objectId();
+      Vault vault = api().createOrUpdateVault(vaultName, LOCATION, VaultProperties.builder()
+              .tenantId(tenantId)
+              .sku(SKU.create(LOCATION, "standard", null, "A"))
+              .accessPolicies(ImmutableList.of(VaultProperties.AccessPolicyEntry.create(null, objectId, tenantId,
+                      VaultProperties.Permissions.create(
+                              ImmutableList.of( // certificates
+                                      "Get",
+                                      "List",
+                                      "Update",
+                                      "Create",
+                                      "Import",
+                                      "Delete",
+                                      "ManageContacts",
+                                      "ManageIssuers",
+                                      "GetIssuers",
+                                      "ListIssuers",
+                                      "SetIssuers",
+                                      "DeleteIssuers",
+                                      "Purge",
+                                      "Recover"
+                              ),
+                              ImmutableList.of( // keys
+                                      "Get",
+                                      "List",
+                                      "Update",
+                                      "Create",
+                                      "Import",
+                                      "Delete",
+                                      "Recover",
+                                      "Backup",
+                                      "Restore",
+                                      "Purge",
+                                      "Encrypt",
+                                      "Decrypt",
+                                      "Sign",
+                                      "Verify",
+                                      "WrapKey",
+                                      "UnwrapKey"
+                              ),
+                              ImmutableList.of( // secrets
+                                      "Get",
+                                      "List",
+                                      "Set",
+                                      "Delete",
+                                      "Recover",
+                                      "Backup",
+                                      "Restore",
+                                      "Purge"
+                              ),
+                              ImmutableList.<String>of()
+                      ))))
+              .build(),
+              null);
+      vaultUri = vault.properties().vaultUri();
+      assertTrue(!vault.name().isEmpty());
+   }
+
+   @Test(dependsOnMethods = "testCreate")
+   public void testGet() {
+      Vault vaultFound = api().getVault(vaultName);
+      assertNotNull(vaultFound);
+   }
+
+   @Test(dependsOnMethods = "testCreate")
+   public void testList() {
+      for (Vault vault : api().listVaults()) {
+         assertTrue(!vault.name().isEmpty());
+      }
+   }
+
+   @Test(dependsOnMethods = {"testDeleteKey", "testDeleteSecret"})
+   public void testUpdateVaultToSoftDelete() {
+      Vault v = api().getVault(vaultName);
+      assertNotNull(v);
+      VaultProperties newProps = VaultProperties.create(v.properties().tenantId(),
+              v.properties().vaultUri(),
+              v.properties().enabledForDeployment(),
+              v.properties().enabledForTemplateDeployment(),
+              true,
+              v.properties().createMode(),
+              v.properties().sku(),
+              v.properties().accessPolicies());
+      Vault updatedVault = api().createOrUpdateVault(vaultName, LOCATION, newProps, null);
+      assertNotNull(updatedVault);
+      updatedVault = api().getVault(vaultName);
+      assertTrue(updatedVault.properties().enableSoftDelete());
+   }
+
+   @Test(dependsOnMethods = {"testPurgeDeletedKey", "testPurgeDeletedSecret"})
+   public void testDelete() {
+      boolean result =  api().deleteVault(vaultName);
+      assertTrue(result);
+      checkState(deletedVaultStatus.create(resourceGroupName, true).apply(vaultName),
+              "vault was not deleted before timeout");
+   }
+
+   @Test(dependsOnMethods = "testDelete")
+   public void testGetDeleted() {
+      DeletedVault dv = api().getDeletedVault(LOCATION, vaultName);
+      assertNotNull(dv);
+   }
+
+   @Test(dependsOnMethods = "testDelete")
+   public void testListDeleted() {
+      for (DeletedVault vault : api().listDeletedVaults()) {
+         assertNotNull(vault.name());
+      }
+   }
+
+   @Test(dependsOnMethods = {"testGetDeleted", "testListDeleted"})
+   public void testPurgeDeletedVault() {
+      api().purgeVault(LOCATION, vaultName);
+      checkState(deletedVaultStatus.create(resourceGroupName, true).apply(vaultName),
+              "vault was not purged before timeout");
+
+   }
+
+   @Test(dependsOnMethods = "testGet")
+   public void testCreateKey() {
+      KeyAttributes keyAttr = KeyAttributes.create(true, 0, null, null, null, null);
+      KeyBundle keyBundle = api().createKey(vaultUri,
+              KEY_NAME,
+              keyAttr,
+              null,
+              null,
+              2048,
+              "RSA",
+              null
+      );
+      assertNotNull(keyBundle);
+   }
+
+   @Test(dependsOnMethods = "testCreateKey")
+   public void testImportKey() {
+      KeyAttributes keyAttr = KeyAttributes.create(true, null, null, null, null, null);
+      List<String> keyOps = new ArrayList<String>();
+      keyOps.add("encrypt");
+      JsonWebKey keyInfo = JsonWebKey.create(
+              null,
+              "DjU54mYvHpICXHjc5-JiFqiH8NkUgOG8LL4kwt3DeBp9bP0-5hSJH8vmzwJkeGG9L79EWG4b_bfxgYdeNX7cFFagmW" +
+                      "PRFrlxbd64VRYFawZHRJt-2cbzMVI6DL8EK4bu5Ux5qTiV44Jw19hoD9nDzCTfPzSTSGrKD3iLPdnREYaIGDVxcjB" +
+                      "v3Tx6rrv3Z2lhHHKhEHb0RRjATcjAVKV9NZhMajJ4l9pqJ3A4IQrCBl95ux6Xm1oXP0i6aR78cjchsCpcMXdP3WMs" +
+                      "vHgTlsZT0RZLFHrvkiNHlPiil4G2_eHkwvT__CrcbO6SmI_zCtMmypuHJqcr-Xb7GPJoa64WoQ",
+              "DB9nGuHplY_7Xv5a5UCs5YgxkWPtJFfbIZ1Zr-XHCCY09JIWReOGQG226OhjwixKtOK_OqmAKtMKM9OmKviJRHNbD" +
+                      "hbTxumN3u7cL8dftjXpSryiEQlPmWyW94MneI2WNIrvh4wruQuDt8EztgOiDFxwcnUgey8iend7WmZnE7E",
+              "O-bSTUQ4N_UuQezgkF3TDrnBraO67leDGwRbfiE_U0ghQvqh5DA0QSPVzlWDZc9KUitvj8vxsR9o1PW9GS0an17GJ" +
+                      "EYuetLnkShKK3NWOhBBX6d1yP9rVdH6JhgIJEy_g0Suz7TAFiFc8i7JF8u4QJ05C8bZAMhOLotqftQeVOM",
+              "AQAB",
+              null,
+              null,
+              keyOps,
+              null,
+              "RSA",
+              "33TqqLR3eeUmDtHS89qF3p4MP7Wfqt2Zjj3lZjLjjCGDvwr9cJNlNDiuKboODgUiT4ZdPWbOiMAfDcDzlOxA04DDnEF" +
+                      "GAf-kDQiNSe2ZtqC7bnIc8-KSG_qOGQIVaay4Ucr6ovDkykO5Hxn7OU7sJp9TP9H0JH8zMQA6YzijYH9LsupTerrY" +
+                      "3U6zyihVEDXXOv08vBHk50BMFJbE9iwFwnxCsU5-UZUZYw87Uu0n4LPFS9BT8tUIvAfnRXIEWCha3KbFWmdZQZlyr" +
+                      "Fw0buUEf0YN3_Q0auBkdbDR_ES2PbgKTJdkjc_rEeM0TxvOUf7HuUNOhrtAVEN1D5uuxE1WSw",
+              "8K33pX90XX6PZGiv26wZm7tfvqlqWFT03nUMvOAytqdxhO2HysiPn4W58OaJd1tY4372Qpiv6enmUeI4MidCie-s-d0" +
+                      "_B6A0xfhU5EeeaDN0xDOOl8yN-kaaVj9b4HDR3c91OAwKpDJQIeJVZtxoijxl-SRx3u7Vs_7meeSpOfE",
+              "7a5KnUs1pTo72A-JquJvIz4Eu794Yh3ftTk_Et-83aE_FVc6Nk-EhfnwYSNpVmM6UKdrAoy5gsCvZPxrq-eR9pEwU8M" +
+                      "5UOlki03vWY_nqDBpJSIqwPvGHUB16zvggsPQUyQBfnN3N8XlDi12n88ltvWwEhn1LQOwMUALEfka9_s",
+              "InfGmkb2jNkPGuNiZ-mU0-ZrOgLza_fLL9ErZ35jUPhGFzdGxJNobklvsNoTd-E2GAU41YkJh24bncMLvJVYxHHA5iF" +
+                      "7FBWx1SvpEyKVhhnIcuXGD7N5PbNZzEdmr9C6I7cPVkWO-sUV7zfFukexIcANmsd_oBBGKRoYzP5Tti4",
+              null,
+              null
+      );
+      KeyBundle importedKey = api().importKey(vaultUri, IMPORT_KEY_NAME, false, keyAttr, keyInfo, null);
+      assertNotNull(importedKey);
+   }
+
+   @Test(dependsOnMethods = "testCreateKey")
+   public void testListKeys() {
+      for (Key key : api().listKeys(vaultUri)) {
+         assertNotNull(key);   
+      }
+   }
+
+   @Test(dependsOnMethods = "testListKeys")
+   public void testGetKey() {
+      KeyBundle keyBundle = api().getKey(vaultUri, KEY_NAME);
+      assertNotNull(keyBundle);
+   }
+
+   @Test(dependsOnMethods = "testGetKey")
+   public void testUpdateKey() {
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing");
+      KeyBundle updatedKey = api().updateKey(vaultUri, KEY_NAME, "", null, null, tags);
+      assertNotNull(updatedKey.tags());
+      assertEquals(updatedKey.tags().size(), 1);
+   }
+
+   @Test(dependsOnMethods = "testUpdateKey")
+   public void testListKeyVersions() {
+      // Create a second version of the key
+      KeyAttributes keyAttr = KeyAttributes.create(true, null, null, null, null, null);
+      KeyBundle keyBundle = api().createKey(vaultUri,
+              KEY_NAME,
+              keyAttr,
+              null,
+              null,
+              3072,
+              "RSA",
+              null);
+
+      // List key versions
+      List<Key> keys = api().getKeyVersions(vaultUri, KEY_NAME);
+      assertNotNull(keys);
+      assertTrue(keys.size() > 1);
+   }
+
+   @Test(dependsOnMethods = "testListKeyVersions")
+   public void testUpdateKeyWithVersion() {
+      List<Key> keys = api().getKeyVersions(vaultUri, KEY_NAME);
+      assertNotNull(keys);
+      assertTrue(keys.size() > 1);
+
+      // get key version to operate on
+      Key key = keys.get(1);
+      assertNotNull(key);
+      final String version = key.kid().substring(key.kid().lastIndexOf("/") + 1).trim();
+
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing again");
+      KeyBundle updatedKey = api().updateKey(vaultUri, KEY_NAME, version, null, null, tags);
+      assertNotNull(updatedKey);
+
+      FluentIterable<Key> iKeys = FluentIterable.from(api().getKeyVersions(vaultUri, KEY_NAME));
+      assertTrue(iKeys.anyMatch(new Predicate<Key>() {
+         @Override public boolean apply(Key input) {
+            return input.kid().contains(version);
+         }
+      }));
+
+      assertEquals(tags, updatedKey.tags());
+   }
+
+   @Test(dependsOnMethods = "testUpdateKeyWithVersion")
+   public void testBackupRestoreKey() {
+      KeyBundle originalKey = api().getKey(vaultUri, KEY_NAME);
+      assertNotNull(originalKey);
+
+      String backupKey = api().backupKey(vaultUri, KEY_NAME);
+      assertNotNull(backupKey);
+
+      DeletedKeyBundle dkb = api().deleteKey(vaultUri, KEY_NAME);
+      assertNotNull(dkb);
+
+      KeyBundle restoredKey = api().restoreKey(vaultUri, backupKey);
+      assertNotNull(restoredKey);
+
+      KeyBundle verifyKey = api().getKey(vaultUri, KEY_NAME);
+      assertNotNull(verifyKey);
+
+      assertEquals(verifyKey, originalKey);
+   }
+
+   @Test(dependsOnMethods = "testBackupRestoreKey")
+   public void testDeleteKey() {
+      DeletedKeyBundle dkb = api().deleteKey(vaultUri, KEY_NAME);
+      assertNotNull(dkb);
+   }
+
+   @Test(dependsOnMethods = "testUpdateVaultToSoftDelete")
+   public void testCreateRecoverableKey() {
+      KeyAttributes keyAttr = KeyAttributes.create(true, null, null, null, null, null);
+      KeyBundle keyBundle = api().createKey(vaultUri, RECOVERABLE_KEY_NAME,
+              keyAttr,
+              null,
+              null,
+              2048,
+              "RSA",
+              null
+      );
+      assertNotNull(keyBundle);
+      checkState(recoverableKeyStatus.create(resourceGroupName, vaultUri, false).apply(RECOVERABLE_KEY_NAME),
+              "key was not created before timeout");
+   }
+
+   @Test(dependsOnMethods = "testCreateRecoverableKey")
+   public void testDeleteRecoverableKey() {
+      DeletedKeyBundle dkb = api().deleteKey(vaultUri, RECOVERABLE_KEY_NAME);
+      assertNotNull(dkb.deletedDate());
+      assertNotNull(dkb.recoveryId());
+      checkState(deletedKeyStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_KEY_NAME),
+              "key was not deleted before timeout");
+   }
+
+   @Test(dependsOnMethods = "testDeleteRecoverableKey")
+   public void testListDeletedKeys() {
+      for (DeletedKeyBundle key : api().listDeletedKeys(vaultUri)) {
+         assertNotNull(key.deletedDate());
+      }
+   }
+
+   @Test(dependsOnMethods = "testListDeletedKeys")
+   public void testGetDeletedKey() {
+      DeletedKeyBundle key = api().getDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+      assertNotNull(key.deletedDate());
+   }
+
+   @Test(dependsOnMethods = {"testDeleteRecoverableKey", "testGetDeletedKey"})
+   public void testRecoverDeletedKey() {
+      KeyBundle key = api().recoverDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+      checkState(recoverableKeyStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_KEY_NAME),
+              "key was not recovered before timeout");
+   }
+
+   @Test(dependsOnMethods = "testRecoverDeletedKey")
+   public void testPurgeDeletedKey() {
+      // delete the key
+      DeletedKeyBundle dkb = api().deleteKey(vaultUri, RECOVERABLE_KEY_NAME);
+      checkState(deletedKeyStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_KEY_NAME),
+              "key was not deleted before timeout");
+
+      // purge the key and verify that it is no longer listed as deleted
+      api().purgeDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+      checkState(deletedKeyStatus.create(resourceGroupName, vaultUri, false).apply(RECOVERABLE_KEY_NAME),
+              "key was not purged before timeout");
+   }
+
+   @Test(dependsOnMethods = "testCreateKey")
+   public void testEncryptDecrypt() {
+      // Encrypt some text
+      KeyOperationResult encryptResult = api().encrypt(vaultUri,
+              KEY_NAME,
+              "",
+              cryptoAlgorithm,
+              cryptoText
+      );
+      assertNotNull(encryptResult);
+      assertTrue(encryptResult.value().length() > cryptoText.length());
+
+      // Decrypt the encrypted text
+      KeyOperationResult decryptResult = api().decrypt(vaultUri,
+              KEY_NAME,
+              "",
+              cryptoAlgorithm,
+              encryptResult.value()
+      );
+      assertNotNull(decryptResult);
+      assertTrue(decryptResult.value().equals(cryptoText));
+   }
+
+   @Test(dependsOnMethods = "testCreateKey")
+   public void testSignVerify() {
+      // Sign a hash
+      KeyOperationResult signResult = api().sign(vaultUri,
+              KEY_NAME,
+              "",
+              signatureAlgorithm,
+              hashToSign
+      );
+      assertNotNull(signResult);
+      assertTrue(!signResult.value().isEmpty());
+
+      // Verify the signature
+      boolean verifyResult = api().verify(vaultUri,
+              KEY_NAME,
+              "",
+              signatureAlgorithm,
+              hashToSign,
+              signResult.value()
+      );
+      assertTrue(verifyResult);
+   }
+
+   @Test(dependsOnMethods = "testCreateKey")
+   public void testWrapUnwrapKey() {
+      // Wrap a 256bit symmetric key
+      KeyOperationResult wrapResult = api().wrap(vaultUri,
+              KEY_NAME,
+              "",
+              cryptoAlgorithm,
+              contentEncryptionKey
+      );
+      assertNotNull(wrapResult);
+      assertTrue(!wrapResult.value().isEmpty());
+
+      // Unwrap symmetric key
+      KeyOperationResult unwrapResult = api().unwrap(vaultUri,
+              KEY_NAME,
+              "",
+              cryptoAlgorithm,
+              wrapResult.value()
+      );
+      assertNotNull(unwrapResult);
+      assertTrue(unwrapResult.value().equals(contentEncryptionKey));
+   }
+
+   @Test(dependsOnMethods = "testBackupRestoreKey")
+   public void testSetSecret() {
+      SecretAttributes attributes = SecretAttributes.create(true, null, null, null, null, null);
+      SecretBundle secretBundle = api().setSecret(vaultUri,
+              SECRET_NAME,
+              attributes,
+              "testSecretKey",
+              null,
+              sampleSecret
+      );
+      assertNotNull(secretBundle);
+   }
+
+   @Test(dependsOnMethods = "testSetSecret")
+   public void testGetSecret() {
+      SecretBundle secret = api().getSecret(vaultUri, SECRET_NAME, null);
+      assertNotNull(secret);
+   }
+
+   @Test(dependsOnMethods = "testSetSecret")
+   public void testGetSecrets() {
+      for (Secret secret : api().listSecrets(vaultUri)) {
+         assertNotNull(secret);
+      }
+   }
+
+   @Test(dependsOnMethods = {"testBackupRestoreSecret"})
+   public void testDeleteSecret() {
+      DeletedSecretBundle dsb = api().deleteSecret(vaultUri, SECRET_NAME);
+      assertNotNull(dsb);
+   }
+
+   @Test(dependsOnMethods = "testGetSecret")
+   public void testUpdateSecret() {
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing");
+      SecretBundle updatedSecret = api().updateSecret(vaultUri, SECRET_NAME, "", null, null, tags);
+      assertNotNull(updatedSecret.tags());
+      assertEquals(updatedSecret.tags().size(), 1);
+   }
+
+   @Test(dependsOnMethods = "testUpdateSecret")
+   public void testListSecretVersions() {
+      // Create a second version of the secret
+      SecretAttributes attributes = SecretAttributes.create(true, null, null, null, null, null);
+      SecretBundle secretBundle = api().setSecret(vaultUri,
+              SECRET_NAME,
+              attributes,
+              "aNewSecretKey",
+              null,
+              "-----BEGIN DSA PRIVATE KEY-----\n" +
+                      "MIIBvAIBAAKBgQDvgcVEyeU5gfw69xY2n1zHWGp/Z8O573SiWIcy29rW382W6jvn\n" +
+                      "X5rF/LX8AscwRhf2pUTEy64ECkd08eRgEjRIKdGSaTZpBXxM25TPb2fF9k1/ObXd\n" +
+                      "SkNOQNlwoCHdyQlvwdkVRohJoBX9u371owXObwLiBR1V597p3PdGNYD3DQIVAPtD\n" +
+                      "dHQQaHCYMxAIXRsaCmOZfsjdAoGBANVOovY4XqS48hvi/RzcCMbRbuHMFBXh/lEM\n" +
+                      "FmBdZ5sczpi1S3KpEjnBPQfOTzspTlEm5y6cHbkQjh1qT1tMdPAAr5aHYVLCTR+v\n" +
+                      "CSSALXP48YiZrJcgdyfhbyr5h/Su2QuwX2DvYrR9d88fYHU4O0njEyMd8UFwQ6Uy\n" +
+                      "qez/catgAoGAJ2AbSklFUXYvehmCVO6XVo3bgO++C3GMycJY3HHTTFQNAb3LJkeO\n" +
+                      "fa2ZCSqWbd85M00Lt0VEkqlb0EkjDvAgL0R78IJUmvb3FH1RiUofP/yK3g1/3I/l\n" +
+                      "jUa1fXXn2jSFYcyzGaDnC2U/B55g9G7hXsXJuldwATfDnLtqCdNPoWcCFQDx5K/k\n" +
+                      "Ub4xHF/4Tau8wDAkxHeJiw==\n" +
+                      "-----END DSA PRIVATE KEY-----"
+      );
+
+      // List secret versions
+      List<Secret> secrets = api().getSecretVersions(vaultUri, SECRET_NAME);
+      assertNotNull(secrets);
+      assertEquals(secrets.size(), 2);
+   }
+
+   @Test(dependsOnMethods = "testListSecretVersions")
+   public void testUpdateSecretWithVersion() {
+      List<Secret> secrets = api().getSecretVersions(vaultUri, SECRET_NAME);
+      assertNotNull(secrets);
+      assertEquals(secrets.size(), 2);
+
+      // get secret version to operate on
+      Secret secret = secrets.get(1);
+      assertNotNull(secret);
+      String version = secret.id().substring(secret.id().lastIndexOf("/") + 1).trim();
+
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing again");
+      SecretBundle updatedSecret = api().updateSecret(vaultUri, SECRET_NAME, version, null, null, tags);
+      assertNotNull(updatedSecret);
+
+      secrets = api().getSecretVersions(vaultUri, SECRET_NAME);
+      assertNotNull(secrets);
+      boolean found = false;
+      for (Secret s : secrets) {
+         if (s.id().contains(version)) {
+            secret = s;
+            found = true;
+            break;
+         }
+      }
+      assertTrue(found);
+      assertEquals(tags, secret.tags());
+   }
+
+   @Test(dependsOnMethods = "testUpdateSecretWithVersion")
+   public void testBackupRestoreSecret() {
+      SecretBundle originalSecret = api().getSecret(vaultUri, SECRET_NAME, null);
+      assertNotNull(originalSecret);
+
+      String backupSecret = api().backupSecret(vaultUri, SECRET_NAME);
+      assertNotNull(backupSecret);
+
+      DeletedSecretBundle dsb = api().deleteSecret(vaultUri, SECRET_NAME);
+      assertNotNull(dsb);
+
+      SecretBundle restoredSecret = api().restoreSecret(vaultUri, backupSecret);
+      assertNotNull(restoredSecret);
+
+      SecretBundle verifySecret = api().getSecret(vaultUri, SECRET_NAME, null);
+      assertNotNull(verifySecret);
+
+      assertEquals(verifySecret, originalSecret);
+   }
+
+   @Test(dependsOnMethods = "testUpdateVaultToSoftDelete")
+   public void testCreateRecoverableSecret() {
+      SecretAttributes attributes = SecretAttributes.create(true, null, null, null, null, null);
+      SecretBundle secretBundle = api().setSecret(vaultUri,
+              RECOVERABLE_SECRET_NAME,
+              attributes,
+              "aNewSecretKey",
+              null,
+              "-----BEGIN DSA PRIVATE KEY-----\n" +
+                      "MIIBvAIBAAKBgQDvgcVEyeU5gfw69xY2n1zHWGp/Z8O573SiWIcy29rW382W6jvn\n" +
+                      "X5rF/LX8AscwRhf2pUTEy64ECkd08eRgEjRIKdGSaTZpBXxM25TPb2fF9k1/ObXd\n" +
+                      "SkNOQNlwoCHdyQlvwdkVRohJoBX9u371owXObwLiBR1V597p3PdGNYD3DQIVAPtD\n" +
+                      "dHQQaHCYMxAIXRsaCmOZfsjdAoGBANVOovY4XqS48hvi/RzcCMbRbuHMFBXh/lEM\n" +
+                      "FmBdZ5sczpi1S3KpEjnBPQfOTzspTlEm5y6cHbkQjh1qT1tMdPAAr5aHYVLCTR+v\n" +
+                      "CSSALXP48YiZrJcgdyfhbyr5h/Su2QuwX2DvYrR9d88fYHU4O0njEyMd8UFwQ6Uy\n" +
+                      "qez/catgAoGAJ2AbSklFUXYvehmCVO6XVo3bgO++C3GMycJY3HHTTFQNAb3LJkeO\n" +
+                      "fa2ZCSqWbd85M00Lt0VEkqlb0EkjDvAgL0R78IJUmvb3FH1RiUofP/yK3g1/3I/l\n" +
+                      "jUa1fXXn2jSFYcyzGaDnC2U/B55g9G7hXsXJuldwATfDnLtqCdNPoWcCFQDx5K/k\n" +
+                      "Ub4xHF/4Tau8wDAkxHeJiw==\n" +
+                      "-----END DSA PRIVATE KEY-----"
+      );
+      assertNotNull(secretBundle);
+      checkState(recoverableSecretStatus.create(resourceGroupName, vaultUri, false).apply(RECOVERABLE_SECRET_NAME),
+              "secret was not created before timeout");
+   }
+
+   @Test(dependsOnMethods = "testCreateRecoverableSecret")
+   public void testDeleteRecoverableSecret() {
+      DeletedSecretBundle dsb = api().deleteSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+      assertNotNull(dsb.deletedDate());
+      assertNotNull(dsb.recoveryId());
+      checkState(deletedSecretStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_SECRET_NAME),
+              "secret was not deleted before timeout");
+   }
+
+   @Test(dependsOnMethods = "testDeleteRecoverableSecret")
+   public void testListDeletedSecrets() {
+      for (DeletedSecretBundle secret : api().listDeletedSecrets(vaultUri)) {
+         assertNotNull(secret.deletedDate());
+      }
+   }
+
+   @Test(dependsOnMethods = "testListDeletedSecrets")
+   public void testGetDeletedSecret() {
+      DeletedSecretBundle dsb = api().getDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+      assertNotNull(dsb.deletedDate());
+   }
+
+   @Test(dependsOnMethods = {"testDeleteRecoverableSecret", "testGetDeletedSecret"})
+   public void testRecoverDeletedSecret() {
+      SecretBundle secret = api().recoverDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+      checkState(recoverableSecretStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_SECRET_NAME),
+              "secret was not created before timeout");
+   }
+
+   @Test(dependsOnMethods = "testRecoverDeletedSecret")
+   public void testPurgeDeletedSecret() {
+      // delete the secret
+      DeletedSecretBundle dsb = api().deleteSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+      checkState(deletedSecretStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_SECRET_NAME),
+              "secret was not deleted before timeout");
+
+      // purge the secret and verify that it is no longer listed as deleted
+      api().purgeDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+      checkState(deletedSecretStatus.create(resourceGroupName, vaultUri, false).apply(RECOVERABLE_SECRET_NAME),
+              "secret was not purged before timeout");
+   }
+
+   @Test(dependsOnMethods = "testGet")
+   public void testCreateCertificate() {
+      CertificatePolicy policy = Certificate.CertificatePolicy.create(null,
+              CERTIFICATE_NAME,
+              IssuerParameters.create(null, "Self"),
+              KeyProperties.create(false, 2048, "RSA", false),
+              null,
+              null,
+              X509CertificateProperties.create(null, null, null, "CN=mycertificate.foobar.com", 12)
+      );
+      assertNotNull(policy);
+
+      CertificateOperation certOp = api().createCertificate(vaultUri,
+              CERTIFICATE_NAME,
+              null,
+              policy,
+              null
+      );
+      assertNotNull(certOp);
+   }
+
+   @Test(dependsOnMethods = "testCreateCertificate")
+   public void testImportCertificate() {
+      String certPem = importableCertificatePem;
+      CertificateBundle certBundle = api().importCertificate(
+              vaultUri,
+              IMPORTABLE_CERTIFICATE_NAME,
+              null,
+              CertificatePolicy.create(
+                      null,
+                      null,
+                      null,
+                      null,
+                      null,
+                      SecretProperties.create("application/x-pem-file"),
+                      null
+              ),
+              null,
+              null,
+              certPem);
+      assertNotNull(certBundle);
+   }
+
+   @Test(dependsOnMethods = "testImportCertificate")
+   public void testMergeCertificate() {
+      /* XXX - Merging certificates is used in the case where a CSR is generated
+       * within the Azure Key Vault and then signed by an external entity.
+       * Since this requires an offline process outside the scope of automated
+       * tests, this test is currently not implemented.
+       */
+      throw new SkipException("merging certificates requires an external entity, skipping");
+   }
+
+   @Test(dependsOnMethods = "testGetCertificateOperation")
+   public void testGetCertificate() {
+      CertificateBundle certBundle = api().getCertificate(vaultUri, "myCertificate", null);
+      assertNotNull(certBundle);
+   }
+
+   @Test(dependsOnMethods = "testGetCertificateOperation")
+   public void testListCertificates() {
+      List<Certificate> certs = api().getCertificates(vaultUri);
+      assertTrue(!certs.isEmpty());
+      for (Certificate cert : certs) {
+         assertNotNull(cert.id());
+      }
+   }
+
+   @Test(dependsOnMethods = "testGetCertificateOperation")
+   public void testListCertificateVersions() {
+      List<Certificate> certs = api().getCertificateVersions(vaultUri, CERTIFICATE_NAME);
+      assertNotNull(certs);
+      assertEquals(certs.size(), 1);
+   }
+
+   @Test(dependsOnMethods = "testGetCertificatePolicy")
+   public void testUpdateCertificate() {
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("selfsigned", "true");
+      CertificatePolicy policy = api().getCertificatePolicy(
+              vaultUri,
+              CERTIFICATE_NAME
+      );
+      assertNotNull(policy);
+      CertificateBundle certBundle = api().updateCertificate(
+              vaultUri,
+              CERTIFICATE_NAME,
+              "",
+              null,
+              policy,
+              tags
+      );
+      assertNotNull(certBundle);
+      assertEquals(certBundle.tags().size(), 1);
+   }
+
+   @Test(dependsOnMethods = "testUpdateCertificate")
+   public void testUpdateCertificateVersion() {
+      // create a new version of the certificate
+      /*
+       * XXX -- update using version complains about needing policy (required input), yet
+       * passing in the same policy results in the error:
+       *
+       * Policy cannot be updated with a specific version of a certificate
+       *
+       * Will uncomment/fix once this issue is resolved.
+       *
+       */
+      throw new SkipException("bug in requirements for function");
+   }
+
+   @Test(dependsOnMethods = {"testDeleteCertificateOperation", "testDeleteCertificateIssuer",
+                             "testDeleteCertificateContacts", "testUpdateCertificatePolicy"})
+   public void testDeleteCertificate() {
+      DeletedCertificateBundle dcb = api().deleteCertificate(
+              vaultUri,
+              CERTIFICATE_NAME
+      );
+      assertNotNull(dcb);
+   }
+
+   @Test(dependsOnMethods = "testCreateCertificate")
+   public void testGetCertificateOperation() {
+      CertificateOperation certOp = api().getCertificateOperation(vaultUri, CERTIFICATE_NAME);
+      assertNotNull(certOp);
+      checkState(certificateOperationStatus.create(resourceGroupName, vaultUri, true).apply(CERTIFICATE_NAME),
+              "certificate was not created before timeout");
+   }
+
+   @Test(dependsOnMethods = "testDeleteCertificateContacts")
+   public void testUpdateCertificateOperation() {
+      CertificatePolicy policy = Certificate.CertificatePolicy.create(null,
+              TEMP_CERTIFICATE_NAME,
+              IssuerParameters.create(null, "Self"),
+              KeyProperties.create(false, 4096, "RSA", false),
+              null,
+              null,
+              X509CertificateProperties.create(null, null, null, "CN=mytempcertificate.foobar.com", 12)
+      );
+      assertNotNull(policy);
+      CertificateOperation certOp = api().createCertificate(vaultUri,
+              TEMP_CERTIFICATE_NAME,
+              null,
+              policy,
+              null
+      );
+      assertNotNull(certOp);
+
+      certOp = api().updateCertificateOperation(vaultUri, TEMP_CERTIFICATE_NAME, true);
+      assertNotNull(certOp);
+      assertTrue(certOp.cancellationRequested());
+   }
+
+   @Test(dependsOnMethods = "testUpdateCertificateOperation")
+   public void testDeleteCertificateOperation() {
+      CertificateOperation certOp = api().deleteCertificateOperation(vaultUri, TEMP_CERTIFICATE_NAME);
+      assertNotNull(certOp);
+      checkState(certificateOperationStatus.create(resourceGroupName, vaultUri, false).apply(TEMP_CERTIFICATE_NAME),
+              "certificate was not deleted before timeout");
+   }
+
+   @Test(dependsOnMethods = "testGetCertificate")
+   public void testSetCertificateIssuer() {
+      AdministrationDetails adminDetail = AdministrationDetails.create(
+              "adminguy@certsforme.com",
+              "Admin",
+              "Guy",
+              "867-5309"
+      );
+      List<AdministrationDetails> adminDetails = new ArrayList<AdministrationDetails>();
+      adminDetails.add(adminDetail);
+      OrganizationDetails orgDetails = OrganizationDetails.create(
+              adminDetails,
+              null
+      );
+      IssuerBundle issuer = api().setCertificateIssuer(
+              vaultUri,
+              "globalsign01",
+              null,
+              IssuerCredentials.create("imauser", "This1sMyPa55wurD!"),
+              orgDetails,
+              "GlobalSign"
+      );
+      assertNotNull(issuer);
+   }
+
+   @Test(dependsOnMethods = "testSetCertificateIssuer")
+   public void testGetCertificateIssuers() {
+      List<CertificateIssuer> issuers = api().getCertificateIssuers(vaultUri);
+      assertNotNull(issuers);
+      assertTrue(issuers.size() > 0);
+   }
+
+   @Test(dependsOnMethods = "testSetCertificateIssuer")
+   public void testGetCertificateIssuer() {
+      IssuerBundle issuer = api().getCertificateIssuer(vaultUri, "globalsign01");
+      assertNotNull(issuer);
+      assertEquals(issuer.provider(), "GlobalSign");
+   }
+
+   @Test(dependsOnMethods = "testGetCertificateIssuer")
+   public void testUpdateCertificateIssuer() {
+      AdministrationDetails adminDetail = AdministrationDetails.create(
+              "adminguy@certsforme.com",
+              "Admin",
+              "Guy",
+              "867-5309"
+      );
+      List<AdministrationDetails> adminDetails = new ArrayList<AdministrationDetails>();
+      adminDetails.add(adminDetail);
+      OrganizationDetails orgDetails = OrganizationDetails.create(
+              adminDetails,
+              null
+      );
+      IssuerBundle issuer = api().updateCertificateIssuer(
+              vaultUri,
+              "globalsign01",
+              null,
+              IssuerCredentials.create("imauser", "CanHa5P455wuRd!"),
+              orgDetails,
+              "GlobalSign"
+      );
+      assertNotNull(issuer);
+   }
+
+   @Test(dependsOnMethods = "testUpdateCertificateIssuer")
+   public void testDeleteCertificateIssuer() {
+      IssuerBundle issuer = api().deleteCertificateIssuer(vaultUri, "globalsign01");
+      assertNotNull(issuer);
+
+      issuer = api().getCertificateIssuer(vaultUri, "globalsign01");
+      assertEquals(issuer, null);
+   }
+
+   @Test(dependsOnMethods = "testDeleteCertificateIssuer")
+   public void testSetCertificateContacts() {
+      List<Contact> contactsIn = new ArrayList<Contact>();
+      contactsIn.add(Contact.create("foo@bar.com", "Foo bar", "867-5309"));
+      Contacts contacts = api().setCertificateContacts(vaultUri, contactsIn);
+      assertNotNull(contacts);
+   }
+   @Test(dependsOnMethods = "testSetCertificateContacts")
+   public void testGetCertificateContacts() {
+      Contacts contacts = api().getCertificateContacts(vaultUri);
+      assertNotNull(contacts.id());
+      assertEquals(contacts.contacts().size(), 1);
+   }
+
+   @Test(dependsOnMethods = "testGetCertificateContacts")
+   public void testDeleteCertificateContacts() {
+      Contacts contacts = api().deleteCertificateContacts(vaultUri);
+      assertNotNull(contacts.id());
+
+      contacts = api().getCertificateContacts(vaultUri);
+      assertNull(contacts);
+   }
+
+   @Test(dependsOnMethods = "testCreateCertificate")
+   public void testGetCertificatePolicy() {
+      CertificatePolicy policy = api().getCertificatePolicy(vaultUri, CERTIFICATE_NAME);
+      assertNotNull(policy);
+   }
+
+   @Test(dependsOnMethods = "testUpdateCertificate")
+   public void testUpdateCertificatePolicy() {
+      CertificatePolicy policy = api().updateCertificatePolicy(
+              vaultUri,
+              CERTIFICATE_NAME,
+              null,
+              null,
+              KeyProperties.create(true, 3072, "RSA", false),
+              null,
+              null,
+              null
+      );
+      assertNotNull(policy);
+      assertTrue(policy.keyProps().exportable());
+   }
+
+   @Test(dependsOnMethods = "testUpdateVaultToSoftDelete")
+   public void testImportRecoverableCertificate() {
+      String certPem = importableCertificatePem;
+      CertificateBundle certBundle = api().importCertificate(
+              vaultUri,
+              RECOVERABLE_CERTIFICATE_NAME,
+              null,
+              CertificatePolicy.create(
+                      null,
+                      null,
+                      null,
+                      null,
+                      null,
+                      SecretProperties.create("application/x-pem-file"),
+                      null
+              ),
+              null,
+              null,
+              certPem);
+      checkState(recoverableCertificateStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_CERTIFICATE_NAME),
+              "certificate was not imported before timeout");
+
+      certBundle = api().getCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME, null);
+      assertNotNull(certBundle);
+      assertTrue(certBundle.attributes().recoveryLevel().contains("Recoverable"));
+   }
+
+   @Test(dependsOnMethods = "testImportRecoverableCertificate")
+   public void testDeleteRecoverableCertificate() {
+      DeletedCertificateBundle dcb = api().deleteCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+      assertNotNull(dcb.deletedDate());
+      assertNotNull(dcb.recoveryId());
+      checkState(deletedCertificateStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_CERTIFICATE_NAME),
+              "certificate was not deleted before timeout");
+   }
+
+   @Test(dependsOnMethods = "testDeleteRecoverableCertificate")
+   public void testListDeletedCertificates() {
+      for (DeletedCertificate dc : api().getDeletedCertificates(vaultUri)) {
+         assertNotNull(dc.deletedDate());
+      }
+   }
+
+   @Test(dependsOnMethods = "testListDeletedCertificates")
+   public void testGetDeletedCertificate() {
+      DeletedCertificateBundle dcb = api().getDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+      assertNotNull(dcb.deletedDate());
+   }
+
+   @Test(dependsOnMethods = "testGetDeletedCertificate")
+   public void testRecoverDeletedCertificate() {
+      CertificateBundle dcb = api().recoverDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+      assertNotNull(dcb);
+      checkState(recoverableCertificateStatus.create(resourceGroupName, vaultUri, false).apply(RECOVERABLE_CERTIFICATE_NAME),
+              "certificate was not recovered before timeout");
+   }
+
+   @Test(dependsOnMethods = "testRecoverDeletedCertificate")
+   public void testPurgeDeletedCertificate() {
+      // delete the certificate
+      DeletedCertificateBundle dcb = api().deleteCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+      checkState(deletedCertificateStatus.create(resourceGroupName, vaultUri, true).apply(RECOVERABLE_CERTIFICATE_NAME),
+              "certificate was not deleted before timeout");
+
+      // purge the certificate and verify that it is no longer listed as deleted
+      api().purgeDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+      checkState(deletedCertificateStatus.create(resourceGroupName, vaultUri, false).apply(RECOVERABLE_CERTIFICATE_NAME),
+              "certificate was not purged before timeout");
+   }
+
+   private VaultApi api() {
+      return api.getVaultApi(resourceGroupName);
+   }
+}


[6/7] jclouds-labs git commit: Add Azure KeyVault support

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Certificate.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Certificate.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Certificate.java
new file mode 100644
index 0000000..65de40c
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Certificate.java
@@ -0,0 +1,638 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.domain;
+
+import java.util.Map;
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+
+@AutoValue
+public abstract class Certificate {
+   @AutoValue
+   public abstract static class CertificateAttributes {
+      @Nullable
+      public abstract Integer created();
+
+      public abstract boolean enabled();
+
+      @Nullable
+      public abstract Integer expiry();
+
+      @Nullable
+      public abstract Integer notBefore();
+
+      @Nullable
+      public abstract String recoveryLevel();
+
+      @Nullable
+      public abstract Integer updated();
+
+      @SerializedNames({"created", "enabled", "exp", "nbf", "recoveryLevel", "updated"})
+      public static CertificateAttributes create(final Integer created,
+                                                 final boolean enabled,
+                                                 final Integer expiry,
+                                                 final Integer notBefore,
+                                                 final String recoveryLevel,
+                                                 final Integer updated) {
+         return new AutoValue_Certificate_CertificateAttributes(created, enabled, expiry, notBefore, recoveryLevel, updated);
+      }
+   }
+
+   @AutoValue
+   public abstract static class IssuerParameters {
+      @Nullable
+      public abstract String certType();
+
+      @Nullable
+      public abstract String name();
+
+      @SerializedNames({"cty", "name"})
+      public static IssuerParameters create(final String certType,
+                                            final String name) {
+         return new AutoValue_Certificate_IssuerParameters(certType, name);
+      }
+   }
+
+   @AutoValue
+   public abstract static class KeyProperties {
+      @Nullable
+      public abstract Boolean exportable();
+
+      @Nullable
+      public abstract Integer keySize();
+
+      @Nullable
+      public abstract String keyType();
+
+      @Nullable
+      public abstract Boolean reuseKey();
+
+      @SerializedNames({"exportable", "key_size", "kty", "reuse_key"})
+      public static KeyProperties create(final boolean exportable,
+                                         final Integer keySize,
+                                         final String keyType,
+                                         final boolean reuseKey) {
+         return new AutoValue_Certificate_KeyProperties(exportable, keySize, keyType, reuseKey);
+      }
+   }
+
+   @AutoValue
+   public abstract static class LifetimeActionTrigger {
+      @Nullable
+      public abstract Integer daysBeforeExpiry();
+
+      @Nullable
+      public abstract Integer lifetimePercentage();
+
+      @SerializedNames({"days_before_expiry", "lifetime_percentage"})
+      public static LifetimeActionTrigger create(final Integer daysBeforeExpiry,
+                                                 final Integer lifetimePercentage) {
+         return new AutoValue_Certificate_LifetimeActionTrigger(daysBeforeExpiry, lifetimePercentage);
+      }
+   }
+
+   @AutoValue
+   public abstract static class LifetimeActionAction {
+      public abstract String actionType();
+
+      @SerializedNames({"action_type"})
+      public static LifetimeActionAction create(final String actionType) {
+         return new AutoValue_Certificate_LifetimeActionAction(actionType);
+      }
+   }
+
+   @AutoValue
+   public abstract static class LifetimeAction {
+      public abstract LifetimeActionAction action();
+
+      public abstract LifetimeActionTrigger trigger();
+
+      @SerializedNames({"action", "trigger"})
+      public static LifetimeAction create(final LifetimeActionAction action,
+                                          final LifetimeActionTrigger trigger) {
+         return new AutoValue_Certificate_LifetimeAction(action, trigger);
+      }
+   }
+
+   @AutoValue
+   public abstract static class SecretProperties {
+      public abstract String contentType();
+
+      @SerializedNames({"contentType"})
+      public static SecretProperties create(final String contentType) {
+         return new AutoValue_Certificate_SecretProperties(contentType);
+      }
+   }
+
+   @AutoValue
+   public abstract static class SubjectAlternativeNames {
+      public abstract List<String> dnsNames();
+
+      public abstract List<String> emails();
+
+      public abstract List<String> upns();
+
+      @SerializedNames({"dns_names", "emails", "upns"})
+      public static SubjectAlternativeNames create(final List<String> dnsNames,
+                                                   final List<String> emails,
+                                                   final List<String> upns) {
+         return new AutoValue_Certificate_SubjectAlternativeNames(
+                 dnsNames != null ? ImmutableList.copyOf(dnsNames) : ImmutableList.<String> of(),
+                 emails != null ? ImmutableList.copyOf(emails) : ImmutableList.<String> of(),
+                 upns != null ? ImmutableList.copyOf(upns) : ImmutableList.<String> of()
+         );
+      }
+   }
+
+   @AutoValue
+   public abstract static class X509CertificateProperties {
+      public abstract List<String> enhancedKeyUsage();
+
+      public abstract List<String> keyUsage();
+
+      @Nullable
+      public abstract SubjectAlternativeNames subjectAltNames();
+
+      @Nullable
+      public abstract String subject();
+
+      @Nullable
+      public abstract Integer validityMonths();
+
+      @SerializedNames({"ekus", "key_usage", "sans", "subject", "validity_months"})
+      public static X509CertificateProperties create(final List<String> enhancedKeyUsage,
+                                                     final List<String> keyUsage,
+                                                     final SubjectAlternativeNames subjectAltNames,
+                                                     final String subject,
+                                                     final Integer validityMonths) {
+         return new AutoValue_Certificate_X509CertificateProperties(
+                 enhancedKeyUsage != null ? ImmutableList.copyOf(enhancedKeyUsage) : ImmutableList.<String> of(),
+                 keyUsage != null ? ImmutableList.copyOf(keyUsage) : ImmutableList.<String> of(),
+                 subjectAltNames,
+                 subject,
+                 validityMonths
+         );
+      }
+   }
+
+   @AutoValue
+   public abstract static class CertificatePolicy {
+      @Nullable
+      public abstract CertificateAttributes attributes();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract IssuerParameters issuer();
+
+      @Nullable
+      public abstract KeyProperties keyProps();
+
+      public abstract List<LifetimeAction> lifetimeActions();
+
+      @Nullable
+      public abstract SecretProperties secretProps();
+
+      @Nullable
+      public abstract X509CertificateProperties x509props();
+
+      @SerializedNames({"attributes", "id", "issuer", "key_props", "lifetime_actions", "secret_props", "x509_props"})
+      public static CertificatePolicy create(final CertificateAttributes attributes,
+                                             final String id,
+                                             final IssuerParameters issuer,
+                                             final KeyProperties keyProps,
+                                             final List<LifetimeAction> lifetimeActions,
+                                             final SecretProperties secretProperties,
+                                             final X509CertificateProperties x509Props) {
+         return new AutoValue_Certificate_CertificatePolicy(
+                 attributes,
+                 id,
+                 issuer,
+                 keyProps,
+                 lifetimeActions != null ? ImmutableList.copyOf(lifetimeActions) : ImmutableList.<LifetimeAction>of(),
+                 secretProperties,
+                 x509Props
+         );
+      }
+   }
+
+   @AutoValue
+   public abstract static class CertificateError {
+      @Nullable
+      public abstract String code();
+
+      @Nullable
+      public abstract String message();
+
+      @SerializedNames({"code", "message"})
+      public static CertificateError create(final String code,
+                                            final String message) {
+         return new AutoValue_Certificate_CertificateError(code, message);
+      }
+   }
+
+   @AutoValue
+   public abstract static class CertificateOperation {
+      @Nullable
+      public abstract Boolean cancellationRequested();
+
+      @Nullable
+      public abstract String csr();
+
+      @Nullable
+      public abstract CertificateError error();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract IssuerParameters issuer();
+
+      @Nullable
+      public abstract String requestId();
+
+      @Nullable
+      public abstract String status();
+
+      @Nullable
+      public abstract String statusDetails();
+
+      @Nullable
+      public abstract String target();
+
+      @SerializedNames({"cancellation_requested", "csr", "error", "id", "issuer", "request_id", "status", "status_details", "target"})
+      public static CertificateOperation create(final boolean cancellationRequested,
+                                                final String csr,
+                                                final CertificateError error,
+                                                final String id,
+                                                final IssuerParameters issuer,
+                                                final String requestId,
+                                                final String status,
+                                                final String statusDetails,
+                                                final String target) {
+         return new AutoValue_Certificate_CertificateOperation(
+                 cancellationRequested,
+                 csr,
+                 error,
+                 id,
+                 issuer,
+                 requestId,
+                 status,
+                 statusDetails,
+                 target);
+      }
+   }
+
+   @AutoValue
+   public abstract static class CertificateBundle {
+      @Nullable
+      public abstract CertificateAttributes attributes();
+
+      @Nullable
+      public abstract String certificate();
+
+      @Nullable
+      public abstract String contentType();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract String keyId();
+
+      @Nullable
+      public abstract CertificatePolicy policy();
+
+      @Nullable
+      public abstract String secretId();
+
+      @Nullable
+      public abstract Map<String, String> tags();
+
+      @Nullable
+      public abstract String thumbprint();
+
+      @SerializedNames({"attributes", "cer", "contentType", "id", "kid", "policy", "sid", "tags", "x5t"})
+      public static CertificateBundle create(final CertificateAttributes attributes,
+                                             final String certificate,
+                                             final String contentType,
+                                             final String id,
+                                             final String keyId,
+                                             final CertificatePolicy policy,
+                                             final String secretId,
+                                             final Map<String, String> tags,
+                                             final String thumbprint) {
+         return new AutoValue_Certificate_CertificateBundle(attributes,
+                 certificate,
+                 contentType,
+                 id,
+                 keyId,
+                 policy,
+                 secretId,
+                 tags != null ? ImmutableMap.copyOf(tags) : null,
+                 thumbprint
+         );
+      }
+   }
+
+   @AutoValue
+   public abstract static class CertificateIssuer {
+      public abstract String id();
+
+      public abstract String provider();
+
+      @SerializedNames({"id", "provider"})
+      public static CertificateIssuer create(final String id,
+                                             final String provider) {
+         return new AutoValue_Certificate_CertificateIssuer(id, provider);
+      }
+   }
+
+   @AutoValue
+   public abstract static class IssuerAttributes {
+      @Nullable
+      public abstract Integer created();
+
+      @Nullable
+      public abstract Boolean enabled();
+
+      @Nullable
+      public abstract Integer updated();
+
+      @SerializedNames({"created", "enabled", "updated"})
+      public static IssuerAttributes create(final Integer created,
+                                            final Boolean enabled,
+                                            final Integer updated) {
+         return new AutoValue_Certificate_IssuerAttributes(created, enabled, updated);
+      }
+   }
+
+   @AutoValue
+   public abstract static class IssuerCredentials {
+      @Nullable
+      public abstract String accountId();
+
+      @Nullable
+      public abstract String password();
+
+      @SerializedNames({"account_id", "pwd"})
+      public static IssuerCredentials create(final String accountId,
+                                             final String password) {
+         return new AutoValue_Certificate_IssuerCredentials(accountId, password);
+      }
+   }
+
+   @AutoValue
+   public abstract static class OrganizationDetails {
+      public abstract List<AdministrationDetails> adminDetails();
+
+      @Nullable
+      public abstract String id();
+
+      @SerializedNames({"admin_details", "id"})
+      public static OrganizationDetails create(final List<AdministrationDetails> adminDetails,
+                                               final String id) {
+         return new AutoValue_Certificate_OrganizationDetails(
+                 adminDetails != null ? ImmutableList.copyOf(adminDetails) : ImmutableList.<AdministrationDetails> of(),
+                 id
+         );
+      }
+   }
+
+   @AutoValue
+   public abstract static class AdministrationDetails {
+      @Nullable
+      public abstract String email();
+
+      @Nullable
+      public abstract String firstName();
+
+      @Nullable
+      public abstract String lastName();
+
+      @Nullable
+      public abstract String phoneNumber();
+
+      @SerializedNames({"email", "first_name", "last_name", "phone"})
+      public static AdministrationDetails create(final String email,
+                                                 final String firstName,
+                                                 final String lastName,
+                                                 final String phoneNumber) {
+         return new AutoValue_Certificate_AdministrationDetails(email, firstName, lastName, phoneNumber);
+      }
+   }
+
+   @AutoValue
+   public abstract static class IssuerBundle {
+      @Nullable
+      public abstract IssuerAttributes attributes();
+
+      @Nullable
+      public abstract IssuerCredentials credentials();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract OrganizationDetails organizationDetails();
+
+      @Nullable
+      public abstract String provider();
+
+      @SerializedNames({"attributes", "credentials", "id", "org_details", "provider"})
+      public static IssuerBundle create(final IssuerAttributes attributes,
+                                        final IssuerCredentials credentials,
+                                        final String id,
+                                        final OrganizationDetails orgDetails,
+                                        final String provider) {
+         return new AutoValue_Certificate_IssuerBundle(attributes, credentials, id, orgDetails, provider);
+      }
+   }
+
+   @AutoValue
+   public abstract static class Contact {
+      @Nullable
+      public abstract String email();
+
+      @Nullable
+      public abstract String name();
+
+      @Nullable
+      public abstract String phone();
+
+      @SerializedNames({"email", "name", "phone"})
+      public static Contact create(final String email,
+                                   final String name,
+                                   final String phone) {
+         return new AutoValue_Certificate_Contact(email, name, phone);
+      }
+   }
+
+   @AutoValue
+   public abstract static class Contacts {
+      public abstract List<Contact> contacts();
+
+      @Nullable
+      public abstract String id();
+
+      @SerializedNames({"contacts", "id"})
+      public static Contacts create(final List<Contact> contacts,
+                                    final String id) {
+         return new AutoValue_Certificate_Contacts(
+                 contacts != null ? ImmutableList.copyOf(contacts) : ImmutableList.<Contact> of(),
+                 id
+         );
+      }
+   }
+
+   @AutoValue
+   public abstract static class DeletedCertificateBundle {
+      @Nullable
+      public abstract CertificateAttributes attributes();
+
+      @Nullable
+      public abstract String bytes();
+
+      @Nullable
+      public abstract Integer deletedDate();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract String keyId();
+
+      @Nullable
+      public abstract String recoveryId();
+
+      @Nullable
+      public abstract Integer scheduledPurgeDate();
+
+      @Nullable
+      public abstract String secredId();
+
+      @Nullable
+      public abstract Map<String, String> tags();
+
+      @Nullable
+      public abstract String thumbprint();
+
+      @SerializedNames({"attributes", "cer", "deletedDate", "id", "kid", "recoveryId", "scheduledPurgeDate", "sid", "tags", "x5t"})
+      public static DeletedCertificateBundle create(final CertificateAttributes attributes,
+                                                    final String bytes,
+                                                    final Integer deletedDate,
+                                                    final String id,
+                                                    final String keyId,
+                                                    final String recoveryId,
+                                                    final Integer scheduledPurgeDate,
+                                                    final String secretId,
+                                                    final Map<String, String> tags,
+                                                    final String thumbprint) {
+         return new AutoValue_Certificate_DeletedCertificateBundle(
+                 attributes,
+                 bytes,
+                 deletedDate,
+                 id,
+                 keyId,
+                 recoveryId,
+                 scheduledPurgeDate,
+                 secretId,
+                 tags != null ? ImmutableMap.copyOf(tags) : null,
+                 thumbprint
+         );
+      }
+   }
+
+   @AutoValue
+   public abstract static class DeletedCertificate {
+      @Nullable
+      public abstract CertificateAttributes attributes();
+
+      @Nullable
+      public abstract Integer deletedDate();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract String recoveryId();
+
+      @Nullable
+      public abstract Integer scheduledPurgeDate();
+
+      @Nullable
+      public abstract Map<String, String> tags();
+
+      @Nullable
+      public abstract String thumbprint();
+
+      @SerializedNames({"attributes", "deletedDate", "id", "recoveryId", "scheduledPurgeDate", "tags", "x5t"})
+      public static DeletedCertificate create(final CertificateAttributes attributes,
+                                              final Integer deletedDate,
+                                              final String id,
+                                              final String recoveryId,
+                                              final Integer scheduledPurgeDate,
+                                              final Map<String, String> tags,
+                                              final String thumbprint) {
+         return new AutoValue_Certificate_DeletedCertificate(
+                 attributes,
+                 deletedDate,
+                 id,
+                 recoveryId,
+                 scheduledPurgeDate,
+                 tags != null ? ImmutableMap.copyOf(tags) : null,
+                 thumbprint
+         );
+      }
+   }
+
+   @Nullable
+   public abstract CertificateAttributes attributes();
+
+   @Nullable
+   public abstract String id();
+
+   @Nullable
+   public abstract Map<String, String> tags();
+
+   @Nullable
+   public abstract String thumbprint();
+
+   @SerializedNames({"attributes", "id", "tags", "x5t"})
+   public static Certificate create(final CertificateAttributes attributes,
+                                    final String id,
+                                    final Map<String, String> tags,
+                                    final String thumbprint) {
+      return new AutoValue_Certificate(
+              attributes,
+              id,
+              tags != null ? ImmutableMap.copyOf(tags) : null,
+              thumbprint
+      );
+   }
+
+   Certificate() {
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Key.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Key.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Key.java
new file mode 100644
index 0000000..ed9b778
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Key.java
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.domain;
+
+import java.util.Map;
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Key {
+    @AutoValue
+    public abstract static class JsonWebKey {
+        @Nullable
+        public abstract String crv();
+
+        @Nullable
+        public abstract String d();
+
+        @Nullable
+        public abstract String dp();
+
+        @Nullable
+        public abstract String dq();
+
+        @Nullable
+        public abstract String e();
+
+        @Nullable
+        public abstract String k();
+
+        @Nullable
+        public abstract String keyHsm();
+
+        public abstract List<String> keyOps();
+
+        @Nullable
+        public abstract String kid();
+
+        @Nullable
+        public abstract String kty();
+
+        @Nullable
+        public abstract String n();
+
+        @Nullable
+        public abstract String p();
+
+        @Nullable
+        public abstract String q();
+
+        @Nullable
+        public abstract String qi();
+
+        @Nullable
+        public abstract String x();
+
+        @Nullable
+        public abstract String y();
+
+        @SerializedNames({"crv", "d", "dp", "dq", "e", "k", "key_hsm", "key_ops", "kid", "kty", "n", "p", "q", "qi", "x", "y"})
+        public static JsonWebKey create(final String crv, final String d, final String dp, final String dq,
+                                        final String e, final String k, final String keyHsm, final List<String> keyOps,
+                                        final String kid, final String kty, final String n, final String p,
+                                        final String q, final String qi, final String x, final String y) {
+            return new AutoValue_Key_JsonWebKey(
+                    crv, d, dp, dq, e, k, keyHsm,
+                    keyOps != null ? ImmutableList.copyOf(keyOps) : ImmutableList.<String> of(),
+                    kid, kty, n, p, q, qi, x, y);
+        }
+    }
+
+    @AutoValue
+    public abstract static class KeyAttributes {
+        @Nullable
+        public abstract Boolean enabled();
+
+        @Nullable
+        public abstract Integer created();
+
+        @Nullable
+        public abstract Integer expires();
+
+        @Nullable
+        public abstract Integer notBefore();
+
+        @Nullable
+        public abstract String recoveryLevel();
+
+        @Nullable
+        public abstract Integer updated();
+
+        @SerializedNames({"enabled", "created", "expires", "notBefore", "recoveryLevel", "updated"})
+        public static KeyAttributes create(final Boolean enabled,
+                                           final Integer created,
+                                           final Integer expires,
+                                           final Integer notBefore,
+                                           final String recoveryLevel,
+                                           final Integer updated) {
+            return new AutoValue_Key_KeyAttributes(enabled, created, expires, notBefore, recoveryLevel, updated);
+        }
+
+        KeyAttributes() {
+        }
+    }
+
+    @AutoValue
+    public abstract static class KeyBundle {
+        @Nullable
+        public abstract KeyAttributes attributes();
+
+        @Nullable
+        public abstract JsonWebKey key();
+
+        @Nullable
+        public abstract Boolean managed();
+
+        @Nullable
+        public abstract Map<String, String> tags();
+
+        @SerializedNames({"attributes", "key", "managed", "tags"})
+        public static KeyBundle create(final KeyAttributes attributes, final JsonWebKey key, final boolean managed, final Map<String, String> tags) {
+            return new AutoValue_Key_KeyBundle(
+                    attributes,
+                    key,
+                    managed,
+                    tags != null ? ImmutableMap.copyOf(tags) : null
+            );
+        }
+    }
+
+    @AutoValue
+    public abstract static class DeletedKeyBundle {
+        @Nullable
+        public abstract KeyAttributes attributes();
+
+        @Nullable
+        public abstract String deletedDate();
+
+        @Nullable
+        public abstract JsonWebKey key();
+
+        @Nullable
+        public abstract Boolean managed();
+
+        @Nullable
+        public abstract String recoveryId();
+
+        @Nullable
+        public abstract String scheduledPurgeDate();
+
+        @Nullable
+        public abstract Map<String, String> tags();
+
+        @SerializedNames({"attributes", "deletedDate", "key", "managed", "recoveryId", "scheduledPurgeDate", "tags"})
+        public static DeletedKeyBundle create(final KeyAttributes attributes, final String deletedDate, final JsonWebKey key, final boolean managed, final String recoveryId, final String scheduledPurgeDate, final Map<String, String> tags) {
+            return new AutoValue_Key_DeletedKeyBundle(
+                    attributes,
+                    deletedDate,
+                    key,
+                    managed,
+                    recoveryId,
+                    scheduledPurgeDate,
+                    tags != null ? ImmutableMap.copyOf(tags) : null
+
+            );
+        }
+    }
+
+    @AutoValue
+    public abstract static class KeyOperationResult {
+        @Nullable
+        public abstract String keyId();
+
+        @Nullable
+        public abstract String value();
+
+        @SerializedNames({"kid", "value"})
+        public static KeyOperationResult create(final String keyId, final String value) {
+            return new AutoValue_Key_KeyOperationResult(
+                    keyId,
+                    value
+            );
+        }
+    }
+
+    @Nullable
+    public abstract String kid();
+
+    public abstract KeyAttributes attributes();
+
+    @Nullable
+    public abstract Boolean managed();
+
+    @Nullable
+    public abstract Map<String, String> tags();
+
+    @SerializedNames({"kid", "attributes", "managed", "tags"})
+    public static Key create(final String kid, final KeyAttributes attributes, final boolean managed, final Map<String, String> tags) {
+        return new AutoValue_Key(
+                kid,
+                attributes,
+                managed,
+                tags != null ? ImmutableMap.copyOf(tags) : null
+        );
+    }
+
+    Key() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/SKU.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/SKU.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/SKU.java
index 4c414e5..6af4406 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/SKU.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/SKU.java
@@ -16,36 +16,25 @@
  */
 package org.jclouds.azurecompute.arm.domain;
 
-import com.google.auto.value.AutoValue;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
-/**
- * SKU
- */
+import com.google.auto.value.AutoValue;
+
 @AutoValue
 public abstract class SKU {
-   /**
-    * The location of the SKU
-    */
    @Nullable
    public abstract String location();
-
-   /**
-    * The name of the SKU
-    */
    @Nullable
    public abstract String name();
-
-   /**
-    * The id of the SKU
-    */
    @Nullable
    public abstract String id();
+   @Nullable
+   public abstract String family();
+   
+   @SerializedNames({"location", "name", "id", "family"})
+   public static SKU create(final String location, final String name, final String id, final String family) {
 
-   @SerializedNames({"location", "name", "id"})
-   public static SKU create(final String location, final String name, final String id) {
-
-      return new AutoValue_SKU(location, name, id);
+      return new AutoValue_SKU(location, name, id, family);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secret.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secret.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secret.java
new file mode 100644
index 0000000..789a71c
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Secret.java
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.domain;
+
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import java.util.Map;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Secret {
+
+   @AutoValue
+   public abstract static class SecretAttributes {
+      @Nullable
+      public abstract Boolean enabled();
+
+      @Nullable
+      public abstract Integer created();
+
+      @Nullable
+      public abstract Integer expires();
+
+      @Nullable
+      public abstract Integer notBefore();
+
+      @Nullable
+      public abstract String recoveryLevel();
+
+      @Nullable
+      public abstract Integer updated();
+
+      @SerializedNames({"enabled", "created", "expires", "notBefore", "recoveryLevel", "updated"})
+      public static SecretAttributes create(final Boolean enabled,
+                                            final Integer created,
+                                            final Integer expires,
+                                            final Integer notBefore,
+                                            final String recoveryLevel,
+                                            final Integer updated) {
+         return new AutoValue_Secret_SecretAttributes(enabled, created, expires, notBefore, recoveryLevel, updated);
+      }
+
+      SecretAttributes() {
+      }
+   }
+
+   @AutoValue
+   public abstract static class DeletedSecretBundle {
+      @Nullable
+      public abstract SecretAttributes attributes();
+
+      @Nullable
+      public abstract String contentType();
+
+      @Nullable
+      public abstract String deletedDate();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract String kid();
+
+      @Nullable
+      public abstract Boolean managed();
+
+      @Nullable
+      public abstract String recoveryId();
+
+      @Nullable
+      public abstract String scheduledPurgeDate();
+
+      @Nullable
+      public abstract Map<String, String> tags();
+
+      @Nullable
+      public abstract String value();
+
+      @SerializedNames({"attributes", "contentType", "deletedDate", "id", "kid", "managed", "recoveryId", "scheduledPurgeDate", "tags", "value"})
+      public static DeletedSecretBundle create(final SecretAttributes attributes,
+                                               final String contentType,
+                                               final String deletedDate,
+                                               final String id,
+                                               final String kid,
+                                               final Boolean managed,
+                                               final String recoveryId,
+                                               final String scheduledPurgeDate,
+                                               final Map<String, String> tags,
+                                               String value) {
+         return new AutoValue_Secret_DeletedSecretBundle(
+                 attributes, contentType, deletedDate,
+                 id, kid, managed, recoveryId, scheduledPurgeDate,
+                 tags != null ? ImmutableMap.copyOf(tags) : null,
+                 value);
+      }
+   }
+
+   @AutoValue
+   public abstract static class SecretBundle {
+      @Nullable
+      public abstract SecretAttributes attributes();
+
+      @Nullable
+      public abstract String contentType();
+
+      @Nullable
+      public abstract String id();
+
+      @Nullable
+      public abstract String kid();
+
+      @Nullable
+      public abstract Boolean managed();
+
+      @Nullable
+      public abstract Map<String, String> tags();
+
+      @Nullable
+      public abstract String value();
+
+      @SerializedNames({"attributes", "contentType", "id", "kid", "managed", "tags", "value"})
+      public static SecretBundle create(final SecretAttributes attributes,
+                                        final String contentType,
+                                        final String id,
+                                        final String kid,
+                                        final Boolean managed,
+                                        final Map<String, String> tags,
+                                        String value) {
+         return new AutoValue_Secret_SecretBundle(
+                 attributes, contentType, id,
+                 kid, managed,
+                 tags != null ? ImmutableMap.copyOf(tags) : null,
+                 value);
+      }
+   }
+
+   @Nullable
+   public abstract SecretAttributes attributes();
+
+   @Nullable
+   public abstract String contentType();
+
+   @Nullable
+   public abstract String id();
+
+   @Nullable
+   public abstract Boolean managed();
+
+   @Nullable
+   public abstract Map<String, String> tags();
+
+   @SerializedNames({"attributes", "contentType", "id", "managed", "tags"})
+   public static Secret create(final SecretAttributes attributes,
+                               final String contentType,
+                               final String id,
+                               final Boolean managed,
+                               final Map<String, String> tags) {
+      return new AutoValue_Secret(
+              attributes,
+              contentType,
+              id,
+              managed,
+              tags != null ? ImmutableMap.copyOf(tags) : null
+      );
+   }
+
+   Secret() {
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Vault.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Vault.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Vault.java
new file mode 100644
index 0000000..3683df6
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Vault.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.domain;
+
+import java.util.Date;
+import java.util.Map;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableMap;
+
+@AutoValue
+public abstract class Vault {
+
+   @AutoValue
+   public abstract static class DeletedVault {
+      @Nullable public abstract String id();
+      @Nullable public abstract String name();
+      @Nullable public abstract String type();
+      @Nullable public abstract DeletedVaultProperties properties();
+
+      @SerializedNames({"id", "name", "type", "properties"})
+      public static DeletedVault create(final String id, final String name,
+                                        final String type, final DeletedVaultProperties properties) {
+         return new AutoValue_Vault_DeletedVault(id, name, type, properties);
+      }
+   }
+
+   @AutoValue
+   public abstract static class DeletedVaultProperties {
+      @Nullable public abstract Date deletionDate();
+      @Nullable public abstract String location();
+      @Nullable public abstract Date scheduledPurgeDate();
+      @Nullable public abstract Map<String, String> tags();
+      @Nullable public abstract String vaultId();
+
+      @SerializedNames({"deletionDate", "location", "scheduledPurgeDate", "tags", "vaultId"})
+      public static DeletedVaultProperties create (final Date deletionDate, final String location,
+                                           final Date scheduledPurgeDate, final Map<String, String> tags,
+                                           final String vaultId) {
+         return new AutoValue_Vault_DeletedVaultProperties(
+                 deletionDate,
+                 location,
+                 scheduledPurgeDate,
+                 tags != null ? ImmutableMap.copyOf(tags) : null,
+                 vaultId
+         );
+      }
+   }
+
+   @Nullable public abstract String id();
+   @Nullable public abstract String type();
+   public abstract String location();
+   @Nullable public abstract Map<String, String> tags();
+   @Nullable public abstract String name();
+   public abstract VaultProperties properties();
+
+   @SerializedNames({"id", "name", "type", "location", "properties", "tags"})
+   public static Vault create(final String id, final String name, final String type,
+                              final String location,
+                              final VaultProperties properties, final Map<String, String> tags) {
+      return builder()
+              .id(id)
+              .name(name)
+              .type(type)
+              .location(location)
+              .properties(properties)
+              .tags(tags != null ? ImmutableMap.copyOf(tags) : null)
+              .build();
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_Vault.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder id(String id);
+      public abstract Builder name(String name);
+      public abstract Builder type(String type);
+      public abstract Builder location(String location);
+      public abstract Builder properties(VaultProperties properties);
+      public abstract Builder tags(Map<String, String> tags);
+
+      abstract Map<String, String> tags();
+      abstract Vault autoBuild();
+
+      public Vault build() {
+         tags(tags() != null ? ImmutableMap.copyOf(tags()) : null);
+         return autoBuild();
+      }
+      
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultProperties.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultProperties.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultProperties.java
new file mode 100644
index 0000000..5e97cf3
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VaultProperties.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.domain;
+
+import java.net.URI;
+import java.util.List;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+
+@AutoValue
+public abstract class VaultProperties {
+
+   @AutoValue
+   public abstract static class Permissions {
+
+      public abstract List<String> certificates();
+      public abstract List<String> keys();
+      public abstract List<String> secrets();
+      public abstract List<String> storage();
+
+      @SerializedNames({ "certificates", "keys", "secrets", "storage"})
+      public static Permissions create(final List<String> certificates, final List<String> keys, final List<String> secrets, final List<String> storage) {
+         return new AutoValue_VaultProperties_Permissions(
+                 certificates != null ? ImmutableList.copyOf(certificates) : ImmutableList.<String> of(),
+                 keys != null ? ImmutableList.copyOf(keys) : ImmutableList.<String> of(),
+                 secrets != null ? ImmutableList.copyOf(secrets) : ImmutableList.<String> of(),
+                 storage != null ? ImmutableList.copyOf(storage) : ImmutableList.<String> of()
+         );
+      }
+
+      Permissions() {
+
+      }
+   }
+   
+   @AutoValue
+   public abstract static class AccessPolicyEntry {
+
+      @Nullable public abstract String applicationId();
+      public abstract String objectId();
+      public abstract String tenantId();
+      @Nullable public abstract Permissions permissions();
+
+      @SerializedNames({"applicationId", "objectId", "tenantId", "permissions"})
+      public static AccessPolicyEntry create(final String applicationId, final String objectId, final String tenantId, final Permissions permissions) {
+         return new AutoValue_VaultProperties_AccessPolicyEntry(applicationId, objectId, tenantId, permissions);
+      }
+
+      AccessPolicyEntry() {
+
+      }
+   }
+   
+   @Nullable
+   public abstract String tenantId();
+   @Nullable
+   public abstract URI vaultUri();
+   @Nullable
+   public abstract Boolean enabledForDeployment();
+   @Nullable
+   public abstract Boolean enabledForTemplateDeployment();
+   @Nullable
+   public abstract Boolean enableSoftDelete();
+   @Nullable
+   public abstract String createMode();
+   @Nullable
+   public abstract SKU sku();
+   @Nullable
+   public abstract List<AccessPolicyEntry> accessPolicies();
+
+   @SerializedNames({"tenantId", "vaultUri", "enabledForDeployment", "enabledForTemplateDeployment", "enableSoftDelete", "createMode", "sku", "accessPolicies" })
+   public static VaultProperties create(final String tenantId, final URI vaultUri, final Boolean enabledForDeployment, final Boolean enabledForTemplateDeployment, final Boolean enableSoftDelete, final String createMode,
+                                        final SKU sku, final List<AccessPolicyEntry> accessPolicies) {
+      return builder()
+              .tenantId(tenantId)
+              .vaultUri(vaultUri)
+              .enabledForDeployment(enabledForDeployment)
+              .enabledForTemplateDeployment(enabledForTemplateDeployment)
+              .enableSoftDelete(enableSoftDelete)
+              .createMode(createMode)
+              .sku(sku)
+              .accessPolicies(accessPolicies)
+              .build();
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_VaultProperties.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder tenantId(String tenantId);
+      public abstract Builder vaultUri(URI vaultUri);
+      public abstract Builder enabledForDeployment(Boolean enabledForDeployment);
+      public abstract Builder enabledForTemplateDeployment(Boolean enabledForTemplateDeployment);
+      public abstract Builder enableSoftDelete(Boolean enableSoftDelete);
+      public abstract Builder createMode(String createMode);
+      public abstract Builder sku(SKU sku);
+      public abstract Builder accessPolicies(List<AccessPolicyEntry> accessPolicies);
+      
+      abstract List<AccessPolicyEntry> accessPolicies();
+
+      abstract VaultProperties autoBuild();
+
+      public VaultProperties build() {
+         return accessPolicies(accessPolicies() != null ? ImmutableList.copyOf(accessPolicies()) : ImmutableList.<AccessPolicyEntry>of())
+                 .autoBuild();
+      }
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VaultApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VaultApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VaultApi.java
new file mode 100644
index 0000000..5ae39ba
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VaultApi.java
@@ -0,0 +1,635 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.features;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import com.google.common.base.Function;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.azurecompute.arm.config.OAuthResource;
+import org.jclouds.azurecompute.arm.domain.Certificate;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateAttributes;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateIssuer;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateOperation;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificatePolicy;
+import org.jclouds.azurecompute.arm.domain.Certificate.Contact;
+import org.jclouds.azurecompute.arm.domain.Certificate.Contacts;
+import org.jclouds.azurecompute.arm.domain.Certificate.DeletedCertificate;
+import org.jclouds.azurecompute.arm.domain.Certificate.DeletedCertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerAttributes;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerCredentials;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerParameters;
+import org.jclouds.azurecompute.arm.domain.Certificate.KeyProperties;
+import org.jclouds.azurecompute.arm.domain.Certificate.LifetimeAction;
+import org.jclouds.azurecompute.arm.domain.Certificate.OrganizationDetails;
+import org.jclouds.azurecompute.arm.domain.Certificate.SecretProperties;
+import org.jclouds.azurecompute.arm.domain.Certificate.X509CertificateProperties;
+import org.jclouds.azurecompute.arm.domain.Key;
+import org.jclouds.azurecompute.arm.domain.Key.DeletedKeyBundle;
+import org.jclouds.azurecompute.arm.domain.Key.JsonWebKey;
+import org.jclouds.azurecompute.arm.domain.Key.KeyAttributes;
+import org.jclouds.azurecompute.arm.domain.Key.KeyBundle;
+import org.jclouds.azurecompute.arm.domain.Key.KeyOperationResult;
+import org.jclouds.azurecompute.arm.domain.Secret;
+import org.jclouds.azurecompute.arm.domain.Secret.DeletedSecretBundle;
+import org.jclouds.azurecompute.arm.domain.Secret.SecretAttributes;
+import org.jclouds.azurecompute.arm.domain.Secret.SecretBundle;
+import org.jclouds.azurecompute.arm.domain.Vault;
+import org.jclouds.azurecompute.arm.domain.Vault.DeletedVault;
+import org.jclouds.azurecompute.arm.domain.VaultProperties;
+import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.oauth.v2.filters.OAuthFilter;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PATCH;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.binders.BindToJsonPayload;
+import org.jclouds.rest.annotations.ParamParser;
+
+@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
+@Consumes(MediaType.APPLICATION_JSON)
+public interface VaultApi {
+   static class PrependSlashOrEmptyString implements Function<Object, String> {
+      public String apply(Object from) {
+         if ((from == null) || (from.toString().length() == 0)) {
+            return "";
+         } else {
+            return "/" + from.toString();
+         }
+      }
+   }
+
+   // Vault operations
+   @Named("vault:list")
+   @SelectJson("value")
+   @GET
+   @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.KeyVault/vaults")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<Vault> listVaults();
+
+   @Named("vault:create_or_update")
+   @PUT
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.KeyVault/vaults/{vaultName}")
+   Vault createOrUpdateVault(@PathParam("vaultName") String vaultName, @PayloadParam("location") String location,
+         @PayloadParam("properties") VaultProperties properties, @Nullable @PayloadParam("tags") Map<String, String> tags);
+
+   @Named("vault:get")
+   @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.KeyVault/vaults/{vaultName}")
+   @GET
+   @Fallback(NullOnNotFoundOr404.class)
+   Vault getVault(@PathParam("vaultName") String vaultName);
+
+   @Named("vault:delete")
+   @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.KeyVault/vaults/{vaultName}")
+   @DELETE
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean deleteVault(@PathParam("vaultName") String vaultName);
+
+   @Named("vault:list_deleted_vaults")
+   @Path("/providers/Microsoft.KeyVault/deletedVaults")
+   @GET
+   @SelectJson("value")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<DeletedVault> listDeletedVaults();
+
+   @Named("vault:get_deleted")
+   @GET
+   @Path("/providers/Microsoft.KeyVault/locations/{location}/deletedVaults/{vaultName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   DeletedVault getDeletedVault(@PathParam("location") String location, @PathParam("vaultName") String vaultName);
+
+   @Named("vault:purge")
+   @POST
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Path("/providers/Microsoft.KeyVault/locations/{location}/deletedVaults/{vaultName}/purge")
+   boolean purgeVault(@PathParam("location") String location, @PathParam("vaultName") String vaultName);
+
+   // Key operations
+   @Named("key:list")
+   @SelectJson("value")
+   @GET
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @Path("/keys")
+   @OAuthResource("https://vault.azure.net")
+   List<Key> listKeys(@EndpointParam URI keyVaultUri);
+
+   @Named("key:create")
+   @POST
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/keys/{keyName}/create")
+   @OAuthResource("https://vault.azure.net")
+   KeyBundle createKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName,
+         @Nullable @PayloadParam("attributes") KeyAttributes attributes,
+         @Nullable @PayloadParam("crv") String curveName, @Nullable @PayloadParam("key_ops") List<String> keyOps,
+         @PayloadParam("key_size") int keySize, @PayloadParam("kty") String keyType,
+         @Nullable @PayloadParam("tags") Map<String, String> tags);
+
+   @Named("key:import")
+   @PUT
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/keys/{keyName}")
+   @OAuthResource("https://vault.azure.net")
+   KeyBundle importKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName,
+         @PayloadParam("Hsm") boolean hsm, @Nullable @PayloadParam("attributes") KeyAttributes attributes,
+         @Nullable @PayloadParam("key") JsonWebKey key, @Nullable @PayloadParam("tags") Map<String, String> tags);
+
+   @Named("key:get")
+   @GET
+   @Path("/keys/{keyName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   KeyBundle getKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
+
+   @Named("key:delete")
+   @DELETE
+   @Path("/keys/{keyName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   DeletedKeyBundle deleteKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
+
+   @Named("key:get_versions")
+   @GET
+   @SelectJson("value")
+   @Path("/keys/{keyName}/versions")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<Key> getKeyVersions(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
+
+   @Named("key:update")
+   @PATCH
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/keys/{keyName}{keyVersion}")
+   @OAuthResource("https://vault.azure.net")
+   KeyBundle updateKey(@EndpointParam URI vaultBaseUrl,
+                       @PathParam("keyName") String keyName,
+                       @Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
+                       @Nullable @PayloadParam("attributes") KeyAttributes attributes,
+                       @Nullable @PayloadParam("key_ops") List<String> keyOps,
+                       @Nullable @PayloadParam("tags") Map<String, String> tags);
+
+   @Named("key:backup")
+   @POST
+   @SelectJson("value")
+   @Path("/keys/{keyName}/backup")
+   @OAuthResource("https://vault.azure.net")
+   String backupKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
+
+   @Named("key:restore")
+   @POST
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/keys/restore")
+   @OAuthResource("https://vault.azure.net")
+   KeyBundle restoreKey(@EndpointParam URI vaultBaseUrl, @PayloadParam("value") String keyInfo);
+
+   // Soft-delete key operations
+   @Named("key:list_deleted")
+   @GET
+   @SelectJson("value")
+   @Path("/deletedkeys")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<DeletedKeyBundle> listDeletedKeys(@EndpointParam URI vaultBaseUrl);
+
+   @Named("key:get_deleted")
+   @GET
+   @Path("/deletedkeys/{keyName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   DeletedKeyBundle getDeletedKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
+
+   @Named("key:recover_deleted")
+   @POST
+   @Path("/deletedkeys/{keyName}/recover")
+   @OAuthResource("https://vault.azure.net")
+   KeyBundle recoverDeletedKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
+
+   @Named("key:purge_deleted")
+   @DELETE
+   @Path("/deletedkeys/{keyName}")
+   @Fallback(FalseOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   boolean purgeDeletedKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
+
+   // Key cryptographic operations
+   @Named("key:crypto_encrypt")
+   @POST
+   @Path("/keys/{keyName}{keyVersion}/encrypt")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   KeyOperationResult encrypt(@EndpointParam URI vaultBaseUrl,
+                              @PathParam("keyName") String keyName,
+                              @Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
+                              @PayloadParam("alg") String algorithm,
+                              @PayloadParam("value") String value);
+
+   @Named("key:crypto_decrypt")
+   @POST
+   @Path("/keys/{keyName}{keyVersion}/decrypt")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   KeyOperationResult decrypt(@EndpointParam URI vaultBaseUrl,
+                              @PathParam("keyName") String keyName,
+                              @Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
+                              @PayloadParam("alg") String algorithm,
+                              @PayloadParam("value") String value);
+
+   @Named("key:crypto_sign")
+   @POST
+   @Path("/keys/{keyName}{keyVersion}/sign")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   KeyOperationResult sign(@EndpointParam URI vaultBaseUrl,
+                           @PathParam("keyName") String keyName,
+                           @Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
+                           @PayloadParam("alg") String algorithm,
+                           @PayloadParam("value") String value);
+
+   @Named("key:crypto_verify")
+   @POST
+   @Path("/keys/{keyName}{keyVersion}/verify")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   boolean verify(@EndpointParam URI vaultBaseUrl,
+                  @PathParam("keyName") String keyName,
+                  @Nullable @PathParam("keyVersion")  @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
+                  @PayloadParam("alg") String algorithm,
+                  @PayloadParam("digest") String digest,
+                  @PayloadParam("value") String value);
+
+   @Named("key:crypto_wrap")
+   @POST
+   @Path("/keys/{keyName}{keyVersion}/wrapkey")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   KeyOperationResult wrap(@EndpointParam URI vaultBaseUrl,
+                           @PathParam("keyName") String keyName,
+                           @Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
+                           @PayloadParam("alg") String algorithm,
+                           @PayloadParam("value") String value);
+
+   @Named("key:crypto_unwrap")
+   @POST
+   @Path("/keys/{keyName}{keyVersion}/unwrapkey")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   KeyOperationResult unwrap(@EndpointParam URI vaultBaseUrl,
+                             @PathParam("keyName") String keyName,
+                             @Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
+                             @PayloadParam("alg") String algorithm,
+                             @PayloadParam("value") String value);
+
+   // Secret operations
+   @Named("secret:list")
+   @SelectJson("value")
+   @GET
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @Path("/secrets")
+   @OAuthResource("https://vault.azure.net")
+   List<Secret> listSecrets(@EndpointParam URI keyVaultUri);
+
+   @Named("secret:set")
+   @PUT
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/secrets/{secretName}")
+   @OAuthResource("https://vault.azure.net")
+   SecretBundle setSecret(@EndpointParam URI keyVaultUri, @PathParam("secretName") String secretName,
+         @Nullable @PayloadParam("attributes") SecretAttributes attributes,
+         @Nullable @PayloadParam("contentType") String contentType,
+         @Nullable @PayloadParam("tags") Map<String, String> tags, @PayloadParam("value") String value);
+
+   @Named("secret:get")
+   @GET
+   @Path("/secrets/{secretName}{secretVersion}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   SecretBundle getSecret(@EndpointParam URI vaultBaseUrl,
+                          @PathParam("secretName") String secretName,
+                          @Nullable @PathParam("secretVersion") @ParamParser(PrependSlashOrEmptyString.class) String secretVersion);
+
+   @Named("secret:delete")
+   @DELETE
+   @Path("/secrets/{secretName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   DeletedSecretBundle deleteSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
+
+   @Named("secret:get_versions")
+   @GET
+   @SelectJson("value")
+   @Path("/secrets/{secretName}/versions")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<Secret> getSecretVersions(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
+
+   @Named("secret:update")
+   @PATCH
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/secrets/{secretName}{secretVersion}")
+   @OAuthResource("https://vault.azure.net")
+   SecretBundle updateSecret(@EndpointParam URI vaultBaseUrl,
+                             @PathParam("secretName") String secretName,
+                             @Nullable @PathParam("secretVersion") @ParamParser(PrependSlashOrEmptyString.class) String secretVersion,
+                             @Nullable @PayloadParam("attributes") SecretAttributes attributes,
+                             @Nullable @PayloadParam("contentType") String contentType,
+                             @Nullable @PayloadParam("tags") Map<String, String> tags);
+
+   @Named("secret:backup")
+   @POST
+   @SelectJson("value")
+   @Path("/secrets/{secretName}/backup")
+   @OAuthResource("https://vault.azure.net")
+   String backupSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
+
+   @Named("secret:restore")
+   @POST
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/secrets/restore")
+   @OAuthResource("https://vault.azure.net")
+   SecretBundle restoreSecret(@EndpointParam URI vaultBaseUrl, @PayloadParam("value") String secretInfo);
+
+   // Soft-delete secret operations
+   @Named("secret:list_deleted")
+   @GET
+   @SelectJson("value")
+   @Path("/deletedsecrets")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<DeletedSecretBundle> listDeletedSecrets(@EndpointParam URI vaultBaseUrl);
+
+   @Named("secret:get_deleted")
+   @GET
+   @Path("/deletedsecrets/{secretName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   DeletedSecretBundle getDeletedSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
+
+   @Named("secret:recover_deleted")
+   @POST
+   @Path("/deletedsecrets/{secretName}/recover")
+   @OAuthResource("https://vault.azure.net")
+   SecretBundle recoverDeletedSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
+
+   @Named("secret:purge_deleted")
+   @DELETE
+   @Path("/deletedsecrets/{secretName}")
+   @Fallback(FalseOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   boolean purgeDeletedSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
+
+   // Certificate operations
+   @Named("certificate:create")
+   @POST
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/certificates/{certificateName}/create")
+   @OAuthResource("https://vault.azure.net")
+   CertificateOperation createCertificate(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName,
+         @Nullable @PayloadParam("attributes") CertificateAttributes attributes,
+         @Nullable @PayloadParam("policy") CertificatePolicy policy,
+         @Nullable @PayloadParam("tags") Map<String, String> tags);
+
+   @Named("certificate:get")
+   @GET
+   @Path("/certificates/{certificateName}{certificateVersion}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   CertificateBundle getCertificate(@EndpointParam URI vaultBaseUrl,
+                                    @PathParam("certificateName") String certificateName,
+                                    @Nullable @PathParam("certificateVersion") @ParamParser(PrependSlashOrEmptyString.class) String certificateVersion);
+
+   @Named("certificate:delete")
+   @DELETE
+   @Path("/certificates/{certificateName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   DeletedCertificateBundle deleteCertificate(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:list")
+   @GET
+   @SelectJson("value")
+   @Path("/certificates")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<Certificate> getCertificates(@EndpointParam URI vaultBaseUrl);
+
+   @Named("certificate:list_deleted")
+   @GET
+   @SelectJson("value")
+   @Path("/deletedcertificates")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<DeletedCertificate> getDeletedCertificates(@EndpointParam URI vaultBaseUrl);
+
+   @Named("certificate:get_deleted")
+   @GET
+   @Path("/deletedcertificates/{certificateName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   DeletedCertificateBundle getDeletedCertificate(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:recover_deleted")
+   @POST
+   @Path("/deletedcertificates/{certificateName}/recover")
+   @OAuthResource("https://vault.azure.net")
+   CertificateBundle recoverDeletedCertificate(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:purge_deleted")
+   @DELETE
+   @Path("/deletedcertificates/{certificateName}")
+   @Fallback(FalseOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   boolean purgeDeletedCertificate(@EndpointParam URI vaultBaseUrl, @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:get_versions")
+   @GET
+   @SelectJson("value")
+   @Path("/certificates/{certificateName}/versions")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<Certificate> getCertificateVersions(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:update")
+   @PATCH
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/certificates/{certificateName}{certificateVersion}")
+   @OAuthResource("https://vault.azure.net")
+   CertificateBundle updateCertificate(@EndpointParam URI vaultBaseUrl,
+                                       @PathParam("certificateName") String certificateName,
+                                       @Nullable @PathParam("certificateVersion") @ParamParser(PrependSlashOrEmptyString.class) String certificateVersion,
+                                       @Nullable @PayloadParam("attributes") CertificateAttributes attributes,
+                                       @Nullable @PayloadParam("policy") CertificatePolicy policy,
+                                       @Nullable @PayloadParam("tags") Map<String, String> tags);
+
+   @Named("certificate:import")
+   @POST
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/certificates/{certificateName}/import")
+   @OAuthResource("https://vault.azure.net")
+   CertificateBundle importCertificate(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName,
+         @Nullable @PayloadParam("attributes") CertificateAttributes attributes,
+         @Nullable @PayloadParam("policy") CertificatePolicy policy, @Nullable @PayloadParam("pwd") String password,
+         @Nullable @PayloadParam("tags") Map<String, String> tags, @PayloadParam("value") String value);
+
+   @Named("certificate:merge")
+   @POST
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/certificates/{certificateName}/pending/merge")
+   @OAuthResource("https://vault.azure.net")
+   CertificateBundle mergeCertificate(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName,
+         @Nullable @PayloadParam("attributes") CertificateAttributes attributes,
+         @Nullable @PayloadParam("tags") Map<String, String> tags, @PayloadParam("x5c") List<String> value);
+
+   @Named("certificate:get_operation")
+   @GET
+   @Path("/certificates/{certificateName}/pending")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   CertificateOperation getCertificateOperation(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:update_operation")
+   @PATCH
+   @Path("/certificates/{certificateName}/pending")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   CertificateOperation updateCertificateOperation(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName,
+         @PayloadParam("cancellation_requested") boolean cancellationRequested);
+
+   @Named("certificate:delete_operation")
+   @DELETE
+   @Path("/certificates/{certificateName}/pending")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   CertificateOperation deleteCertificateOperation(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:set_issuer")
+   @PUT
+   @Path("/certificates/issuers/{issuerName}")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   IssuerBundle setCertificateIssuer(@EndpointParam URI vaultBaseUrl, @PathParam("issuerName") String issuerName,
+         @Nullable @PayloadParam("attributes") IssuerAttributes attributes,
+         @Nullable @PayloadParam("credentials") IssuerCredentials credentials,
+         @Nullable @PayloadParam("org_details") OrganizationDetails orgDetails,
+         @PayloadParam("provider") String provider);
+
+   @Named("certificate:get_issuers")
+   @GET
+   @SelectJson("value")
+   @Path("/certificates/issuers")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   List<CertificateIssuer> getCertificateIssuers(@EndpointParam URI vaultBaseUrl);
+
+   @Named("certificate:get_issuer")
+   @GET
+   @Path("/certificates/issuers/{issuerName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   IssuerBundle getCertificateIssuer(@EndpointParam URI vaultBaseUrl, @PathParam("issuerName") String issuerName);
+
+   @Named("certificate:update_issuer")
+   @PATCH
+   @Path("/certificates/issuers/{issuerName}")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   IssuerBundle updateCertificateIssuer(@EndpointParam URI vaultBaseUrl, @PathParam("issuerName") String issuerName,
+         @Nullable @PayloadParam("attributes") IssuerAttributes attributes,
+         @Nullable @PayloadParam("credentials") IssuerCredentials credentials,
+         @Nullable @PayloadParam("org_details") OrganizationDetails orgDetails,
+         @PayloadParam("provider") String provider);
+
+   @Named("certificate:delete_issuer")
+   @DELETE
+   @Path("/certificates/issuers/{issuerName}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   IssuerBundle deleteCertificateIssuer(@EndpointParam URI vaultBaseUrl, @PathParam("issuerName") String issuerName);
+
+   @Named("certificate:get_contacts")
+   @GET
+   @Path("/certificates/contacts")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   Contacts getCertificateContacts(@EndpointParam URI vaultBaseUrl);
+
+   @Named("certificate:set_contacts")
+   @PUT
+   @Path("/certificates/contacts")
+   @MapBinder(BindToJsonPayload.class)
+   @OAuthResource("https://vault.azure.net")
+   Contacts setCertificateContacts(@EndpointParam URI vaultBaseUrl, @PayloadParam("contacts") List<Contact> contacts);
+
+   @Named("certificate:delete_contacts")
+   @DELETE
+   @Path("/certificates/contacts")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   Contacts deleteCertificateContacts(@EndpointParam URI vaultBaseUrl);
+
+   @Named("certificate:get_policy")
+   @GET
+   @Path("/certificates/{certificateName}/policy")
+   @Fallback(NullOnNotFoundOr404.class)
+   @OAuthResource("https://vault.azure.net")
+   CertificatePolicy getCertificatePolicy(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName);
+
+   @Named("certificate:update_policy")
+   @PATCH
+   @MapBinder(BindToJsonPayload.class)
+   @Path("/certificates/{certificateName}/policy")
+   @OAuthResource("https://vault.azure.net")
+   CertificatePolicy updateCertificatePolicy(@EndpointParam URI vaultBaseUrl,
+         @PathParam("certificateName") String certificateName,
+         @Nullable @PayloadParam("attributes") CertificateAttributes attributes,
+         @Nullable @PayloadParam("issuer") IssuerParameters issuer,
+         @Nullable @PayloadParam("key_props") KeyProperties keyProps,
+         @Nullable @PayloadParam("lifetime_actions") List<LifetimeAction> lifetimeActions,
+         @Nullable @PayloadParam("secret_props") SecretProperties secretProps,
+         @Nullable @PayloadParam("x509_props") X509CertificateProperties x509Props);
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
index 5cf4239..adcde2b 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
@@ -39,7 +39,7 @@ import java.util.Properties;
 import java.util.Set;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.PublicIpAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetProperties;


[4/7] jclouds-labs git commit: Add Azure KeyVault support

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiMockTest.java
new file mode 100644
index 0000000..7459f48
--- /dev/null
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VaultApiMockTest.java
@@ -0,0 +1,1619 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.features;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Arrays;
+import java.util.ArrayList;
+
+import org.jclouds.azurecompute.arm.domain.Certificate;
+import org.jclouds.azurecompute.arm.domain.Certificate.AdministrationDetails;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateAttributes;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateIssuer;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateOperation;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificatePolicy;
+import org.jclouds.azurecompute.arm.domain.Certificate.Contact;
+import org.jclouds.azurecompute.arm.domain.Certificate.Contacts;
+import org.jclouds.azurecompute.arm.domain.Certificate.DeletedCertificate;
+import org.jclouds.azurecompute.arm.domain.Certificate.DeletedCertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerCredentials;
+import org.jclouds.azurecompute.arm.domain.Certificate.IssuerParameters;
+import org.jclouds.azurecompute.arm.domain.Certificate.KeyProperties;
+import org.jclouds.azurecompute.arm.domain.Certificate.OrganizationDetails;
+import org.jclouds.azurecompute.arm.domain.Certificate.SecretProperties;
+import org.jclouds.azurecompute.arm.domain.Certificate.X509CertificateProperties;
+import org.jclouds.azurecompute.arm.domain.Key;
+import org.jclouds.azurecompute.arm.domain.Key.DeletedKeyBundle;
+import org.jclouds.azurecompute.arm.domain.Key.JsonWebKey;
+import org.jclouds.azurecompute.arm.domain.Key.KeyAttributes;
+import org.jclouds.azurecompute.arm.domain.Key.KeyBundle;
+import org.jclouds.azurecompute.arm.domain.Key.KeyOperationResult;
+import org.jclouds.azurecompute.arm.domain.SKU;
+import org.jclouds.azurecompute.arm.domain.Secret;
+import org.jclouds.azurecompute.arm.domain.Secret.DeletedSecretBundle;
+import org.jclouds.azurecompute.arm.domain.Secret.SecretAttributes;
+import org.jclouds.azurecompute.arm.domain.Secret.SecretBundle;
+import org.jclouds.azurecompute.arm.domain.Vault;
+import org.jclouds.azurecompute.arm.domain.Vault.DeletedVault;
+import org.jclouds.azurecompute.arm.domain.VaultProperties;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
+import org.jclouds.rest.ResourceNotFoundException;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+
+@Test(groups = "unit", testName = "VaultApiMockTest", singleThreaded = true)
+public class VaultApiMockTest extends BaseAzureComputeApiMockTest {
+   private final String subscriptionId = "SUBSCRIPTIONID";
+   private final String resourceGroup = "myresourcegroup";
+   private final String tenantId = "myTenantId";
+   private final String identityObjId = "myIdentityObjectId";
+   private final String vaultName = "kvvaultapimocktest";
+   private final String apiVersion = "api-version=2016-10-01";
+   private final String location = "westeurope";
+   private URI vaultUri;
+
+   private static String KEY_NAME = "myKey";
+   private static String TEMP_KEY_NAME = "myTempKey";
+   private static String IMPORT_KEY_NAME = "myImportKey";
+   private static String RECOVERABLE_KEY_NAME = "myRecoverableKey";
+   private static String SECRET_NAME = "mySecret";
+   private static String RECOVERABLE_SECRET_NAME = "myRecoverableSecret";
+   private static String CERTIFICATE_NAME = "myCertificate";
+   private static String TEMP_CERTIFICATE_NAME = "myTempCertificate";
+   private static String RECOVERABLE_CERTIFICATE_NAME = "myRecoverableCertificate";
+   private static String IMPORTABLE_CERTIFICATE_NAME = "myImportableCertificate";
+   private static String CERTIFICATE_ISSUER_NAME = "globalsign01";
+   private String IMPORTABLE_CERTIFICATE_PEM = stringFromResource("/vaultimportablecert.txt");
+   private String sampleSecret = stringFromResource("/vaultsamplesecret.txt");
+   private String keyBackup = stringFromResource("/vaultkeybackup.txt");
+   private String secretBackup = stringFromResource("/vaultsecretbackup.txt");
+   private String[] mergeX5C = {
+           stringFromResource("/vaultmergex5c-1.txt"),
+           stringFromResource("/vaultmergex5c-2.txt"),
+           stringFromResource("/vaultmergex5c-3.txt")
+   };
+   private static String cryptoText = "R29sZCUyNTIxJTJCR29sZCUyNTIxJTJCR2" +
+           "9sZCUyQmZyb20lMkJ0aGUlMkJBbWVyaWNhbiUyQlJpdmVyJTI1MjE";
+   private static String cryptoAlgorithm = "RSA-OAEP";
+   private static String hashToSign = "FvabKT6qGwpml59iHUJ72DZ4XyJcJ8bgpgFA4_8JFmM";
+   private static String signatureAlgorithm = "RS256";
+   private static String contentEncryptionKey = "YxzoHR65aFwD2_IOiZ5rD08jMSALA1y7b_yYW0G3hyI";
+   private static String keyDecryptData = "0_S8pyjjnGRlcbDa-Lt0jYjMXpXrf9Fat3elx-fSO" +
+           "g3dj6mYgEEs6kt79OMD4MFmVyOt6umeWAfdDIkNVnqb5fgyWceveh9wN-37jc5CFgG2PF3XI" +
+           "A6RII-HF2BkBcVa9KcAX3_di4KQE70PXgHf-dlz_RgLOJILeG50wzFeBFCLsjEEPp3itmoai" +
+           "E6vfDidCRm5At8Vjka0G-N_afwkIijfQZLT0VaXvL39cIJE2QN3HJPZM8YPUlkFlYnY4GIRy" +
+           "RWSBpK_KYuVufzUGtDi6Sh8pUa67ppa7DHVZlixlmnVqI3Oeg6XUvMqbFFqVSrcNbRQDwVGL" +
+           "3cUtK-KB1PfKg";
+   private static String keySignedData = "uO0r4P1cB-fKsDZ8cj5ahiNw8Tdsudt5zLCeEKOt29" +
+           "LAlPDpeGx9Q1SOFNaR7JlRYVelxsohdzvydwX8ao6MLnqlpdEj0Xt5Aadp-kN84AXW238gab" +
+           "S1AUyiWILCmdsBFeRU4wTRSxz2qGS_0ztHkaNln32P_9GJC72ZRlgZoVA4C_fowZolUoCWGj" +
+           "4V7fAzcSoiNYipWP0HkFe3xmuz-cSQg3CCAs-MclHHfMeSagLJZZQ9bpl5LIr-Ik89bNtqEq" +
+           "yP7Jb_fCgHajAx2lUFcRZhSIKuCfrLPMl6wzejQ2rQXX-ixEkDa73dYaPIrVW4IL3iC0Ufxn" +
+           "fxYffHJ7QCRw";
+   private static String keyWrappedData = "1jcTlu3KJNDBYydhaH9POWOo0tAPGkpsZVizCkHpC" +
+           "3g_9Kg91Q3HKK-rfZynn5W5nVPM-SVFHA3JTankcXX8gx8GycwUh4pMoyil_DV35m2QjyuiT" +
+           "ln83OJXw-nMvRXyKdVfF7nyRcs256kW7gthAOsYUVBrfFS7DFFxsXqLNREsA8j85IqIXIm8p" +
+           "AB3C9uvl1I7SQhLvrwZZXXqjeCWMfseVJwWgsQFyyqH2P0f3-xnngV7cvik2k3Elrk3G_2Cu" +
+           "JCozIIrANg9zG9Z8DrwSNNm9YooxWkSu0ZeDLOJ0bMdhcPGGm5OvKz3oZqX-39yv5klNlCRb" +
+           "r0q7gqmI0x25w";
+
+   @BeforeMethod
+   public void start() throws IOException, URISyntaxException {
+      super.start();
+      vaultUri = server.getUrl("").toURI();
+   }
+
+   public void createVault() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultcreate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Vault vault = vaultApi.createOrUpdateVault(vaultName, location, VaultProperties.builder()
+              .tenantId(this.tenantId)
+              .sku(SKU.create(location, "standard", null, "A"))
+              .accessPolicies(ImmutableList.of(VaultProperties.AccessPolicyEntry.create(null, this.identityObjId, this.tenantId,
+                      VaultProperties.Permissions.create(
+                              ImmutableList.of( // certificates
+                                      "Get",
+                                      "List",
+                                      "Update",
+                                      "Create",
+                                      "Import",
+                                      "Delete",
+                                      "ManageContacts",
+                                      "ManageIssuers",
+                                      "GetIssuers",
+                                      "ListIssuers",
+                                      "SetIssuers",
+                                      "DeleteIssuers",
+                                      "Purge",
+                                      "Recover"
+                              ),
+                              ImmutableList.of( // keys
+                                      "Get",
+                                      "List",
+                                      "Update",
+                                      "Create",
+                                      "Import",
+                                      "Delete",
+                                      "Recover",
+                                      "Backup",
+                                      "Restore",
+                                      "Purge",
+                                      "Encrypt",
+                                      "Decrypt",
+                                      "Sign",
+                                      "Verify",
+                                      "WrapKey",
+                                      "UnwrapKey"
+                              ),
+                              ImmutableList.of( // secrets
+                                      "Get",
+                                      "List",
+                                      "Set",
+                                      "Delete",
+                                      "Recover",
+                                      "Backup",
+                                      "Restore",
+                                      "Purge"
+                              ),
+                              ImmutableList.<String>of()
+                      ))))
+              .build(),
+              null);
+
+      String path = String.format(
+              "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.KeyVault/vaults/%s?%s",
+              subscriptionId, resourceGroup, vaultName, apiVersion
+      );
+      assertSent(server, "PUT", path, stringFromResource("/vaultcreaterequestbody.json"));
+
+      assertNotNull(vault);
+      assertNotNull(vault.properties().vaultUri());
+      assertTrue(!vault.name().isEmpty());
+   }
+
+   public void listVaults() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlist.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Vault> vaults = vaultApi.listVaults();
+
+      String path = String.format(
+              "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.KeyVault/vaults?%s",
+              subscriptionId, resourceGroup, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertNotNull(vaults);
+      assertTrue(vaults.size() > 0);
+      assertTrue(!vaults.get(0).name().isEmpty());
+   }
+
+   public void listVaultsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Vault> vaults = vaultApi.listVaults();
+
+      String path = String.format(
+              "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.KeyVault/vaults?%s",
+              subscriptionId, resourceGroup, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertTrue(vaults.isEmpty());
+   }
+
+   public void getVault() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultget.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Vault vault = vaultApi.getVault(vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.KeyVault/vaults/%s?%s",
+              subscriptionId, resourceGroup, vaultName, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertNotNull(vault);
+      assertTrue(!vault.name().isEmpty());
+   }
+
+   public void getVaultReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Vault vault = vaultApi.getVault(vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.KeyVault/vaults/%s?%s",
+              subscriptionId, resourceGroup, vaultName, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertNull(vault);
+   }
+
+   public void deleteVault() throws InterruptedException {
+      server.enqueue(response200());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.deleteVault(vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.KeyVault/vaults/%s?%s",
+              subscriptionId, resourceGroup, vaultName, apiVersion
+      );
+      assertSent(server, "DELETE", path);
+
+      assertTrue(status);
+   }
+
+   public void deleteVaultReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.deleteVault(vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.KeyVault/vaults/%s?%s",
+              subscriptionId, resourceGroup, vaultName, apiVersion
+      );
+      assertSent(server, "DELETE", path);
+
+      assertFalse(status);
+   }
+
+   public void purgeDeletedVault() throws InterruptedException {
+      server.enqueue(response200());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeVault(location, vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/providers/Microsoft.KeyVault/locations/%s/deletedVaults/%s/purge?%s",
+              subscriptionId, location, vaultName, apiVersion
+      );
+      assertSent(server, "POST", path);
+
+      assertTrue(status);
+   }
+
+   public void purgeDeletedVaultReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeVault(location, vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/providers/Microsoft.KeyVault/locations/%s/deletedVaults/%s/purge?%s",
+              subscriptionId, location, vaultName, apiVersion
+      );
+      assertSent(server, "POST", path);
+
+      assertFalse(status);
+   }
+
+   public void listDeletedVaults() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistdeleted.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedVault> vaults = vaultApi.listDeletedVaults();
+
+      String path = String.format(
+              "/subscriptions/%s/providers/Microsoft.KeyVault/deletedVaults?%s",
+              subscriptionId, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertNotNull(vaults);
+      assertTrue(vaults.size() > 0);
+   }
+
+   public void listDeletedVaultsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedVault> vaults = vaultApi.listDeletedVaults();
+
+      String path = String.format(
+              "/subscriptions/%s/providers/Microsoft.KeyVault/deletedVaults?%s",
+              subscriptionId, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertTrue(vaults.isEmpty());
+   }
+
+   public void getDeletedVault() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetdeleted.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedVault vault = vaultApi.getDeletedVault(location, vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/providers/Microsoft.KeyVault/locations/%s/deletedVaults/%s?%s",
+              subscriptionId, location, vaultName, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertNotNull(vault);
+      assertTrue(!vault.name().isEmpty());
+      assertTrue(!vault.properties().deletionDate().toString().isEmpty());
+   }
+
+   public void getDeletedVaultReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedVault vault = vaultApi.getDeletedVault(location, vaultName);
+
+      String path = String.format(
+              "/subscriptions/%s/providers/Microsoft.KeyVault/locations/%s/deletedVaults/%s?%s",
+              subscriptionId, location, vaultName, apiVersion
+      );
+      assertSent(server, "GET", path);
+
+      assertNull(vault);
+   }
+
+
+   // Key mock tests
+   public void listKeys() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistkeys.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Key> keys = vaultApi.listKeys(vaultUri);
+
+      String path = String.format("/keys?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(keys);
+      assertTrue(keys.size() > 0);
+   }
+
+   public void listKeysReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Key> keys = vaultApi.listKeys(vaultUri);
+
+      String path = String.format("/keys?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(keys.isEmpty());
+   }
+
+   public void createKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultcreatekey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyAttributes keyAttr = KeyAttributes.create(true, null, null, null, null, null);
+      KeyBundle keyBundle = vaultApi.createKey(vaultUri,
+              KEY_NAME,
+              keyAttr,
+              null,
+              null,
+              2048,
+              "RSA",
+              null
+      );
+
+      String path = String.format("/keys/%s/create?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultcreatekeyrequestbody.json"));
+
+      assertNotNull(keyBundle);
+      assertNotNull(keyBundle.attributes().created());
+   }
+
+   public void importKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultcreatekey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyAttributes keyAttr = KeyAttributes.create(true, null, null, null, null, null);
+      List<String> keyOps = new ArrayList<String>();
+      keyOps.add("encrypt");
+      JsonWebKey keyInfo = JsonWebKey.create(
+              null,
+              "DjU54mYvHpICXHjc5-JiFqiH8NkUgOG8LL4kwt3DeBp9bP0-5hSJH8vmzwJkeGG9L79EWG4b_bfxgYdeNX7cFFagmW" +
+                      "PRFrlxbd64VRYFawZHRJt-2cbzMVI6DL8EK4bu5Ux5qTiV44Jw19hoD9nDzCTfPzSTSGrKD3iLPdnREYaIGDVxcjB" +
+                      "v3Tx6rrv3Z2lhHHKhEHb0RRjATcjAVKV9NZhMajJ4l9pqJ3A4IQrCBl95ux6Xm1oXP0i6aR78cjchsCpcMXdP3WMs" +
+                      "vHgTlsZT0RZLFHrvkiNHlPiil4G2_eHkwvT__CrcbO6SmI_zCtMmypuHJqcr-Xb7GPJoa64WoQ",
+              "DB9nGuHplY_7Xv5a5UCs5YgxkWPtJFfbIZ1Zr-XHCCY09JIWReOGQG226OhjwixKtOK_OqmAKtMKM9OmKviJRHNbD" +
+                      "hbTxumN3u7cL8dftjXpSryiEQlPmWyW94MneI2WNIrvh4wruQuDt8EztgOiDFxwcnUgey8iend7WmZnE7E",
+              "O-bSTUQ4N_UuQezgkF3TDrnBraO67leDGwRbfiE_U0ghQvqh5DA0QSPVzlWDZc9KUitvj8vxsR9o1PW9GS0an17GJ" +
+                      "EYuetLnkShKK3NWOhBBX6d1yP9rVdH6JhgIJEy_g0Suz7TAFiFc8i7JF8u4QJ05C8bZAMhOLotqftQeVOM",
+              "AQAB",
+              null,
+              null,
+              keyOps,
+              null,
+              "RSA",
+              "33TqqLR3eeUmDtHS89qF3p4MP7Wfqt2Zjj3lZjLjjCGDvwr9cJNlNDiuKboODgUiT4ZdPWbOiMAfDcDzlOxA04DDnEF" +
+                      "GAf-kDQiNSe2ZtqC7bnIc8-KSG_qOGQIVaay4Ucr6ovDkykO5Hxn7OU7sJp9TP9H0JH8zMQA6YzijYH9LsupTerrY" +
+                      "3U6zyihVEDXXOv08vBHk50BMFJbE9iwFwnxCsU5-UZUZYw87Uu0n4LPFS9BT8tUIvAfnRXIEWCha3KbFWmdZQZlyr" +
+                      "Fw0buUEf0YN3_Q0auBkdbDR_ES2PbgKTJdkjc_rEeM0TxvOUf7HuUNOhrtAVEN1D5uuxE1WSw",
+              "8K33pX90XX6PZGiv26wZm7tfvqlqWFT03nUMvOAytqdxhO2HysiPn4W58OaJd1tY4372Qpiv6enmUeI4MidCie-s-d0" +
+                      "_B6A0xfhU5EeeaDN0xDOOl8yN-kaaVj9b4HDR3c91OAwKpDJQIeJVZtxoijxl-SRx3u7Vs_7meeSpOfE",
+              "7a5KnUs1pTo72A-JquJvIz4Eu794Yh3ftTk_Et-83aE_FVc6Nk-EhfnwYSNpVmM6UKdrAoy5gsCvZPxrq-eR9pEwU8M" +
+                      "5UOlki03vWY_nqDBpJSIqwPvGHUB16zvggsPQUyQBfnN3N8XlDi12n88ltvWwEhn1LQOwMUALEfka9_s",
+              "InfGmkb2jNkPGuNiZ-mU0-ZrOgLza_fLL9ErZ35jUPhGFzdGxJNobklvsNoTd-E2GAU41YkJh24bncMLvJVYxHHA5iF" +
+                      "7FBWx1SvpEyKVhhnIcuXGD7N5PbNZzEdmr9C6I7cPVkWO-sUV7zfFukexIcANmsd_oBBGKRoYzP5Tti4",
+              null,
+              null
+      );
+      KeyBundle importedKey = vaultApi.importKey(vaultUri, IMPORT_KEY_NAME, false, keyAttr, keyInfo, null);
+
+      String path = String.format("/keys/%s?%s", IMPORT_KEY_NAME, apiVersion);
+      assertSent(server, "PUT", path, stringFromResource("/vaultimportkeyrequestbody.json"));
+
+      assertNotNull(importedKey);
+      assertNotNull(importedKey.attributes().created());
+   }
+
+   public void getKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetkey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyBundle key = vaultApi.getKey(vaultUri, KEY_NAME);
+
+      String path = String.format("/keys/%s?%s", KEY_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(key);
+      assertNotNull(key.attributes().created());
+   }
+
+   public void getKeyReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyBundle key = vaultApi.getKey(vaultUri, KEY_NAME);
+
+      String path = String.format("/keys/%s?%s", KEY_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(key);
+   }
+
+   public void deleteKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultdeletekey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedKeyBundle key = vaultApi.deleteKey(vaultUri, KEY_NAME);
+
+      String path = String.format("/keys/%s?%s", KEY_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNotNull(key);
+      assertNotNull(key.attributes().created());
+   }
+
+   public void deleteKeyReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedKeyBundle key = vaultApi.deleteKey(vaultUri, KEY_NAME);
+
+      String path = String.format("/keys/%s?%s", KEY_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNull(key);
+   }
+
+   public void getKeyVersions() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetkeyversions.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Key> keys = vaultApi.getKeyVersions(vaultUri, KEY_NAME);
+
+      String path = String.format("/keys/%s/versions?%s", KEY_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(keys);
+      assertTrue(keys.size() > 0);
+      assertNotNull(keys.get(0).attributes().created());
+   }
+
+   public void getKeyVersionsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Key> keys = vaultApi.getKeyVersions(vaultUri, KEY_NAME);
+
+      String path = String.format("/keys/%s/versions?%s", KEY_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(keys.isEmpty());
+   }
+
+   public void updateKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatekey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing");
+      KeyBundle updatedKey = vaultApi.updateKey(vaultUri, KEY_NAME, null, null, null, tags);
+
+      String path = String.format("/keys/%s?%s", KEY_NAME, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatekeyrequestbody.json"));
+
+      assertNotNull(updatedKey);
+      assertNotNull(updatedKey.attributes().created());
+   }
+
+   public void updateKeyWithVersion() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatekeywithversion.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      String keyVersion = "bd6566ec707e4ad89f4ab9577d9d0bef";
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing");
+      KeyBundle updatedKey = vaultApi.updateKey(vaultUri, KEY_NAME, keyVersion, null, null, tags);
+
+      String path = String.format("/keys/%s/%s?%s", KEY_NAME, keyVersion, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatekeyrequestbody.json"));
+
+      assertNotNull(updatedKey);
+      assertNotNull(updatedKey.attributes().created());
+   }
+
+   public void backupKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultbackupkey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      String keyBackup = vaultApi.backupKey(vaultUri, KEY_NAME);
+
+      String path = String.format("/keys/%s/backup?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path);
+
+      assertNotNull(keyBackup);
+      assertTrue(keyBackup.length() > 0);
+   }
+
+   public void restoreKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultrestorekey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyBundle restoredKey = vaultApi.restoreKey(vaultUri, keyBackup);
+
+      String path = String.format("/keys/restore?%s", apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultrestorekeyrequestbody.json"));
+
+      assertNotNull(restoredKey);
+      assertNotNull(restoredKey.attributes().created());
+   }
+
+   public void listDeletedKeys() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistdeletedkeys.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedKeyBundle> keys = vaultApi.listDeletedKeys(vaultUri);
+
+      String path = String.format("/deletedkeys?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(keys);
+      assertTrue(keys.size() > 0);
+   }
+
+   public void listDeletedKeysReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedKeyBundle> keys = vaultApi.listDeletedKeys(vaultUri);
+
+      String path = String.format("/deletedkeys?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(keys.isEmpty());
+   }
+
+   public void getDeletedKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetdeletedkey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedKeyBundle key = vaultApi.getDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+
+      String path = String.format("/deletedkeys/%s?%s", RECOVERABLE_KEY_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(key);
+      assertTrue(!key.deletedDate().isEmpty());
+   }
+
+   public void getDeletedKeyReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedKeyBundle key = vaultApi.getDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+
+      String path = String.format("/deletedkeys/%s?%s", RECOVERABLE_KEY_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(key);
+   }
+
+   public void recoverDeletedKey() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultrecoverdeletedkey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyBundle key = vaultApi.recoverDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+
+      String path = String.format("/deletedkeys/%s/recover?%s", RECOVERABLE_KEY_NAME, apiVersion);
+      assertSent(server, "POST", path);
+
+      assertNotNull(key);
+      assertNotNull(key.attributes().created());
+   }
+
+   public void purgeDeletedKey() throws InterruptedException {
+      server.enqueue(response200());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+
+      String path = String.format("/deletedkeys/%s?%s", RECOVERABLE_KEY_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertTrue(status);
+   }
+
+   public void purgeDeletedKeyReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeDeletedKey(vaultUri, RECOVERABLE_KEY_NAME);
+
+      String path = String.format("/deletedkeys/%s?%s", RECOVERABLE_KEY_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertFalse(status);
+   }
+
+   public void encrypt() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultkeyencrypt.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyOperationResult encryptResult = vaultApi.encrypt(vaultUri,
+              KEY_NAME,
+              null,
+              cryptoAlgorithm,
+              cryptoText
+      );
+
+      String path = String.format("/keys/%s/encrypt?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultkeyencryptrequestbody.json"));
+
+      assertNotNull(encryptResult);
+      assertTrue(!encryptResult.value().isEmpty());
+   }
+
+   public void decrypt() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultkeydecrypt.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyOperationResult decryptResult = vaultApi.decrypt(vaultUri,
+              KEY_NAME,
+              null,
+              cryptoAlgorithm,
+              keyDecryptData
+      );
+
+      String path = String.format("/keys/%s/decrypt?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultkeydecryptrequestbody.json"));
+
+      assertNotNull(decryptResult);
+      assertTrue(!decryptResult.value().isEmpty());
+   }
+
+   public void sign() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultkeysign.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyOperationResult signResult = vaultApi.sign(vaultUri,
+              KEY_NAME,
+              null,
+              signatureAlgorithm,
+              hashToSign
+      );
+
+      String path = String.format("/keys/%s/sign?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultkeysignrequestbody.json"));
+
+      assertNotNull(signResult);
+      assertTrue(!signResult.value().isEmpty());
+   }
+
+   public void verify() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultkeyverify.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean verifyResult = vaultApi.verify(vaultUri,
+              KEY_NAME,
+              null,
+              signatureAlgorithm,
+              hashToSign,
+              keySignedData
+      );
+
+      String path = String.format("/keys/%s/verify?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultkeyverifyrequestbody.json"));
+
+      assertTrue(verifyResult);
+   }
+
+   public void wrap() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultkeywrap.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyOperationResult wrapResult = vaultApi.wrap(vaultUri,
+              KEY_NAME,
+              null,
+              cryptoAlgorithm,
+              contentEncryptionKey
+      );
+
+      String path = String.format("/keys/%s/wrapkey?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultkeywraprequestbody.json"));
+
+      assertNotNull(wrapResult);
+      assertTrue(!wrapResult.value().isEmpty());
+   }
+
+   public void unwrap() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultkeyunwrap.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      KeyOperationResult unwrapResult = vaultApi.unwrap(vaultUri,
+              KEY_NAME,
+              null,
+              cryptoAlgorithm,
+              keyWrappedData
+      );
+
+      String path = String.format("/keys/%s/unwrapkey?%s", KEY_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultkeyunwraprequestbody.json"));
+
+      assertNotNull(unwrapResult);
+      assertTrue(!unwrapResult.value().isEmpty());
+   }
+
+   // Secret mock tests
+   public void listSecrets() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistsecrets.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Secret> secrets = vaultApi.listSecrets(vaultUri);
+
+      String path = String.format("/secrets?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(secrets);
+      assertTrue(secrets.size() > 0);
+   }
+
+   public void listSecretsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Secret> secrets = vaultApi.listSecrets(vaultUri);
+
+      String path = String.format("/secrets?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(secrets.isEmpty());
+   }
+
+   public void setSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultsetsecret.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      SecretAttributes attributes = SecretAttributes.create(true, null, null, null, null, null);
+      SecretBundle secretBundle = vaultApi.setSecret(vaultUri,
+              SECRET_NAME,
+              attributes,
+              "testSecretKey",
+              null,
+              sampleSecret
+      );
+
+      String path = String.format("/secrets/%s?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "PUT", path, stringFromResource("/vaultsetsecretrequestbody.json"));
+
+      assertNotNull(secretBundle);
+      assertTrue(!secretBundle.id().isEmpty());
+   }
+
+   public void getSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetsecret.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      SecretBundle secret = vaultApi.getSecret(vaultUri, SECRET_NAME, null);
+
+      String path = String.format("/secrets/%s?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(secret);
+      assertNotNull(secret.attributes().created());
+   }
+
+   public void getSecretReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      SecretBundle secret = vaultApi.getSecret(vaultUri, SECRET_NAME, null);
+
+      String path = String.format("/secrets/%s?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(secret);
+   }
+
+   public void deleteSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultdeletesecret.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedSecretBundle secret = vaultApi.deleteSecret(vaultUri, SECRET_NAME);
+
+      String path = String.format("/secrets/%s?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNotNull(secret);
+      assertNotNull(secret.attributes().created());
+   }
+
+   public void deleteSecretReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedSecretBundle secret = vaultApi.deleteSecret(vaultUri, SECRET_NAME);
+
+      String path = String.format("/secrets/%s?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNull(secret);
+   }
+
+   public void getSecretVersions() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetsecretversions.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Secret> secrets = vaultApi.getSecretVersions(vaultUri, SECRET_NAME);
+
+      String path = String.format("/secrets/%s/versions?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(secrets);
+      assertTrue(secrets.size() > 0);
+      assertNotNull(secrets.get(0).attributes().created());
+   }
+
+   public void getSecretVersionsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Secret> secrets = vaultApi.getSecretVersions(vaultUri, SECRET_NAME);
+
+      String path = String.format("/secrets/%s/versions?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(secrets.isEmpty());
+   }
+
+   public void updateSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatekey.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing");
+      SecretBundle updatedSecret = vaultApi.updateSecret(vaultUri, SECRET_NAME, null, null, null, tags);
+
+      String path = String.format("/secrets/%s?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatesecretrequestbody.json"));
+
+      assertNotNull(updatedSecret);
+      assertNotNull(updatedSecret.attributes().created());
+   }
+
+   public void updateSecretWithVersion() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatesecretwithversion.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      String secretVersion = "b936ececbc674f3bb1367ae50d28ada0";
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("purpose", "testing again");
+      SecretBundle updatedSecret = vaultApi.updateSecret(vaultUri, SECRET_NAME,  secretVersion, null, null, tags);
+
+      String path = String.format("/secrets/%s/%s?%s", SECRET_NAME, secretVersion, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatesecretwithversionrequestbody.json"));
+
+      assertNotNull(updatedSecret);
+      assertNotNull(updatedSecret.attributes().created());
+   }
+
+   public void backupSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultbackupsecret.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      String secretBackup = vaultApi.backupSecret(vaultUri, SECRET_NAME);
+
+      String path = String.format("/secrets/%s/backup?%s", SECRET_NAME, apiVersion);
+      assertSent(server, "POST", path);
+
+      assertNotNull(secretBackup);
+      assertTrue(secretBackup.length() > 0);
+   }
+
+   public void restoreSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultrestoresecret.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      SecretBundle restoredSecret = vaultApi.restoreSecret(vaultUri, secretBackup);
+
+      String path = String.format("/secrets/restore?%s", apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultrestoresecretrequestbody.json"));
+
+      assertNotNull(restoredSecret);
+      assertNotNull(restoredSecret.attributes().created());
+   }
+
+   public void listDeletedSecrets() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistdeletedsecrets.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedSecretBundle> secrets = vaultApi.listDeletedSecrets(vaultUri);
+
+      String path = String.format("/deletedsecrets?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(secrets);
+      assertTrue(secrets.size() > 0);
+   }
+
+   public void listDeletedSecretsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedSecretBundle> secrets = vaultApi.listDeletedSecrets(vaultUri);
+
+      String path = String.format("/deletedsecrets?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(secrets.isEmpty());
+   }
+
+   public void getDeletedSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetdeletedsecret.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedSecretBundle secret = vaultApi.getDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+
+      String path = String.format("/deletedsecrets/%s?%s", RECOVERABLE_SECRET_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(secret);
+      assertTrue(!secret.deletedDate().isEmpty());
+   }
+
+   public void getDeletedSecretReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedSecretBundle secret = vaultApi.getDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+
+      String path = String.format("/deletedsecrets/%s?%s", RECOVERABLE_SECRET_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(secret);
+   }
+
+   public void recoverDeletedSecret() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultrecoverdeletedsecret.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      SecretBundle secret = vaultApi.recoverDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+
+      String path = String.format("/deletedsecrets/%s/recover?%s", RECOVERABLE_SECRET_NAME, apiVersion);
+      assertSent(server, "POST", path);
+
+      assertNotNull(secret);
+      assertNotNull(secret.attributes().created());
+   }
+
+   public void purgeDeletedSecret() throws InterruptedException {
+      server.enqueue(response200());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+
+      String path = String.format("/deletedsecrets/%s?%s", RECOVERABLE_SECRET_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertTrue(status);
+   }
+
+   public void purgeDeletedSecretReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeDeletedSecret(vaultUri, RECOVERABLE_SECRET_NAME);
+
+      String path = String.format("/deletedsecrets/%s?%s", RECOVERABLE_SECRET_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertFalse(status);
+   }
+
+   public void createCertificate() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultcreatecertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificatePolicy policy = CertificatePolicy.create(null,
+              CERTIFICATE_NAME,
+              IssuerParameters.create(null, "Self"),
+              KeyProperties.create(false, 2048, "RSA", false),
+              null,
+              null,
+              X509CertificateProperties.create(null, null, null, "CN=mycertificate.foobar.com", 12)
+      );
+      CertificateOperation certOp = vaultApi.createCertificate(vaultUri,
+              CERTIFICATE_NAME,
+              null,
+              policy,
+              null
+      );
+
+      String path = String.format("/certificates/%s/create?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultcreatecertificaterequestbody.json"));
+
+      assertNotNull(certOp);
+      assertTrue(!certOp.id().isEmpty());
+   }
+
+   public void getCertificate() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetcertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateBundle cert = vaultApi.getCertificate(vaultUri, CERTIFICATE_NAME, null);
+
+      String path = String.format("/certificates/%s?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(cert);
+      assertTrue(!cert.id().isEmpty());
+   }
+
+   public void getCertificateReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateBundle cert = vaultApi.getCertificate(vaultUri, CERTIFICATE_NAME, null);
+
+      String path = String.format("/certificates/%s?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(cert);
+   }
+
+   public void deleteCertificate() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultdeletecertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedCertificateBundle cert = vaultApi.deleteCertificate(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNotNull(cert);
+      assertTrue(!cert.id().isEmpty());
+   }
+
+   public void deleteCertificateReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedCertificateBundle cert = vaultApi.deleteCertificate(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNull(cert);
+   }
+
+   public void listCertificates() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistcertificates.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Certificate> certs = vaultApi.getCertificates(vaultUri);
+
+      String path = String.format("/certificates?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(certs);
+      assertTrue(certs.size() > 0);
+   }
+
+   public void listCertificatesReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Certificate> certs = vaultApi.getCertificates(vaultUri);
+
+      String path = String.format("/certificates?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(certs.isEmpty());
+   }
+
+   public void listDeletedCertificates() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistdeletedcertificates.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedCertificate> certs = vaultApi.getDeletedCertificates(vaultUri);
+
+      String path = String.format("/deletedcertificates?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(certs);
+      assertTrue(certs.size() > 0);
+   }
+
+   public void listDeletedCertificatesReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<DeletedCertificate> certs = vaultApi.getDeletedCertificates(vaultUri);
+
+      String path = String.format("/deletedcertificates?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(certs.isEmpty());
+   }
+
+   public void getDeletedCertificate() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetdeletedcertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedCertificateBundle cert = vaultApi.getDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+
+      String path = String.format("/deletedcertificates/%s?%s", RECOVERABLE_CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(cert);
+      assertTrue(!cert.id().isEmpty());
+   }
+
+   public void getDeletedCertificateReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      DeletedCertificateBundle cert = vaultApi.getDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+
+      String path = String.format("/deletedcertificates/%s?%s", RECOVERABLE_CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(cert);
+   }
+
+   public void recoverDeletedCertificate() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultrecoverdeletedcertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateBundle cert = vaultApi.recoverDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+
+      String path = String.format("/deletedcertificates/%s/recover?%s", RECOVERABLE_CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "POST", path);
+
+      assertNotNull(cert);
+      assertTrue(!cert.id().isEmpty());
+   }
+
+   public void purgeDeletedCertificate() throws InterruptedException {
+      server.enqueue(response200());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+
+      String path = String.format("/deletedcertificates/%s?%s", RECOVERABLE_CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertTrue(status);
+   }
+
+   public void purgeDeletedCertificateReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      boolean status = vaultApi.purgeDeletedCertificate(vaultUri, RECOVERABLE_CERTIFICATE_NAME);
+
+      String path = String.format("/deletedcertificates/%s?%s", RECOVERABLE_CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertFalse(status);
+   }
+
+   public void listCertificateVersions() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistcertificateversions.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Certificate> certs = vaultApi.getCertificateVersions(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/versions?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(certs);
+      assertTrue(certs.size() > 0);
+   }
+
+   public void listCertificateVersionsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Certificate> certs = vaultApi.getCertificateVersions(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/versions?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(certs.isEmpty());
+   }
+
+   public void updateCertificate() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatecertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Map<String, String> tags = new HashMap<String, String>();
+      tags.put("selfsigned", "true");
+      CertificatePolicy policy = CertificatePolicy.create(null,
+              CERTIFICATE_NAME,
+              IssuerParameters.create(null, "Self"),
+              KeyProperties.create(false, 2048, "RSA", false),
+              null,
+              null,
+              X509CertificateProperties.create(null, null, null, "CN=mycertificate.foobar.com", 12)
+      );
+      CertificateBundle certBundle = vaultApi.updateCertificate(
+              vaultUri,
+              CERTIFICATE_NAME,
+              null,
+              null,
+              policy,
+              tags
+      );
+
+      String path = String.format("/certificates/%s?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatecertificaterequestbody.json"));
+
+      assertNotNull(certBundle);
+      assertTrue(!certBundle.id().isEmpty());
+   }
+
+   public void updateCertificateVersion() {
+      // Update the specific version of a certificate
+
+        /*
+         * XXX -- update using version complains about needing policy (required input), yet
+         * passing in the same policy results in the error:
+         *
+         * Policy cannot be updated with a specific version of a certificate
+         *
+         * Will uncomment/fix once this issue is resolved.
+         *
+         */
+      throw new SkipException("azure bug - update using version complains about needing policy");
+   }
+
+   public void importCertificate() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultimportcertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      String certPem = IMPORTABLE_CERTIFICATE_PEM;
+      CertificateBundle certBundle = null;
+      try {
+         certBundle = vaultApi.importCertificate(
+                 vaultUri,
+                 RECOVERABLE_CERTIFICATE_NAME,
+                 null,
+                 CertificatePolicy.create(
+                         null,
+                         null,
+                         null,
+                         null,
+                         null,
+                         SecretProperties.create("application/x-pem-file"),
+                         null
+                 ),
+                 null,
+                 null,
+                 certPem);
+      } catch (ResourceNotFoundException rnf) {
+         assertNotNull(rnf);
+      }
+
+      String path = String.format("/certificates/%s/import?%s", RECOVERABLE_CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultimportcertificaterequestbody.json"));
+
+      assertNotNull(certBundle);
+      assertTrue(!certBundle.id().isEmpty());
+   }
+
+   public void mergeCertificate() throws InterruptedException {
+      // Merging a certificate is for when a CSR is signed by an external CA
+      server.enqueue(jsonResponse("/vaultmergecertificate.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateAttributes attributes = CertificateAttributes.create(null, true, null, null, null, null);
+      CertificateBundle certBundle = vaultApi.mergeCertificate(
+              vaultUri,
+              CERTIFICATE_NAME,
+              attributes,
+              null,
+              Arrays.asList(mergeX5C)
+      );
+
+      String path = String.format("/certificates/%s/pending/merge?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "POST", path, stringFromResource("/vaultmergecertificaterequestbody.json"));
+
+      assertNotNull(certBundle);
+      assertTrue(!certBundle.attributes().created().toString().isEmpty());
+   }
+
+   public void getCertificateOperation() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetcertificateoperation.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateOperation certOp = vaultApi.getCertificateOperation(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/pending?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(certOp);
+      assertTrue(!certOp.id().isEmpty());
+   }
+
+   public void getCertificateOperationReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateOperation certOp = vaultApi.getCertificateOperation(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/pending?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(certOp);
+   }
+
+   public void updateCertificateOperation() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatecertificateoperation.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateOperation certOp = vaultApi.updateCertificateOperation(vaultUri, CERTIFICATE_NAME, true);
+
+      String path = String.format("/certificates/%s/pending?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatecertificateoperationrequestbody.json"));
+
+      assertNotNull(certOp);
+      assertTrue(!certOp.id().isEmpty());
+   }
+
+   public void deleteCertificateOperation() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultdeletecertificateoperation.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateOperation certOp = vaultApi.deleteCertificateOperation(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/pending?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNotNull(certOp);
+      assertTrue(!certOp.id().isEmpty());
+   }
+
+   public void deleteCertificateOperationReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificateOperation certOp = vaultApi.deleteCertificateOperation(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/pending?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNull(certOp);
+   }
+
+   public void setCertificateIssuer() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultsetcertificateissuer.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      AdministrationDetails adminDetail = AdministrationDetails.create(
+              "adminguy@certsforme.com",
+              "Admin",
+              "Guy",
+              "867-5309"
+      );
+      List<AdministrationDetails> adminDetails = new ArrayList<AdministrationDetails>();
+      adminDetails.add(adminDetail);
+      OrganizationDetails orgDetails = OrganizationDetails.create(
+              adminDetails,
+              null
+      );
+      IssuerBundle issuer = null;
+      try {
+         issuer = vaultApi.setCertificateIssuer(
+                 vaultUri,
+                 CERTIFICATE_ISSUER_NAME,
+                 null,
+                 IssuerCredentials.create("imauser", "This1sMyPa55wurD!"),
+                 orgDetails,
+                 "GlobalSign"
+         );
+      } catch (ResourceNotFoundException rnf) {
+         assertNotNull(rnf);
+      }
+
+      String path = String.format("/certificates/issuers/%s?%s", CERTIFICATE_ISSUER_NAME, apiVersion);
+      assertSent(server, "PUT", path, stringFromResource("/vaultsetcertificateissuerrequestbody.json"));
+
+      assertNotNull(issuer);
+      assertTrue(!issuer.id().isEmpty());
+   }
+
+   public void listCertificateIssuers() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultlistcertificateissuers.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<CertificateIssuer> issuers = vaultApi.getCertificateIssuers(vaultUri);
+
+      String path = String.format("/certificates/issuers?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(issuers);
+      assertTrue(issuers.size() > 0);
+   }
+
+   public void listCertificateIssuersReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<CertificateIssuer> issuers = vaultApi.getCertificateIssuers(vaultUri);
+
+      String path = String.format("/certificates/issuers?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertTrue(issuers.isEmpty());
+   }
+
+   public void getCertificateIssuer() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetcertificateissuer.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      IssuerBundle issuer = vaultApi.getCertificateIssuer(vaultUri, CERTIFICATE_ISSUER_NAME);
+
+      String path = String.format("/certificates/issuers/%s?%s", CERTIFICATE_ISSUER_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(issuer);
+      assertTrue(!issuer.id().isEmpty());
+   }
+
+   public void getCertificateIssuerReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      IssuerBundle issuer = vaultApi.getCertificateIssuer(vaultUri, CERTIFICATE_ISSUER_NAME);
+
+      String path = String.format("/certificates/issuers/%s?%s", CERTIFICATE_ISSUER_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(issuer);
+   }
+
+   public void updateCertificateIssuer() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatecertificateissuer.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      AdministrationDetails adminDetail = AdministrationDetails.create(
+              "adminguy@certsforme.com",
+              "Admin",
+              "Guy",
+              "867-5309"
+      );
+      List<AdministrationDetails> adminDetails = new ArrayList<AdministrationDetails>();
+      adminDetails.add(adminDetail);
+      OrganizationDetails orgDetails = OrganizationDetails.create(
+              adminDetails,
+              null
+      );
+      IssuerBundle issuer = vaultApi.updateCertificateIssuer(
+              vaultUri,
+              "globalsign01",
+              null,
+              IssuerCredentials.create("imauser", "CanHa5P455wuRd!"),
+              orgDetails,
+              "GlobalSign"
+      );
+
+      String path = String.format("/certificates/issuers/%s?%s", CERTIFICATE_ISSUER_NAME, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatecertificateissuerrequestbody.json"));
+
+      assertNotNull(issuer);
+      assertTrue(!issuer.id().isEmpty());
+   }
+
+   public void deleteCertificateIssuer() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultdeletecertificateissuer.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      IssuerBundle issuer = vaultApi.deleteCertificateIssuer(vaultUri, CERTIFICATE_ISSUER_NAME);
+
+      String path = String.format("/certificates/issuers/%s?%s", CERTIFICATE_ISSUER_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNotNull(issuer);
+      assertTrue(!issuer.id().isEmpty());
+   }
+
+   public void deleteCertificateIssuerReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      IssuerBundle issuer = vaultApi.deleteCertificateIssuer(vaultUri, CERTIFICATE_ISSUER_NAME);
+
+      String path = String.format("/certificates/issuers/%s?%s", CERTIFICATE_ISSUER_NAME, apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNull(issuer);
+   }
+
+   public void getCertificateContacts() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetcertificatecontacts.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Contacts contacts = vaultApi.getCertificateContacts(vaultUri);
+
+      String path = String.format("/certificates/contacts?%s", apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(contacts);
+      assertTrue(!contacts.id().isEmpty());
+      assertTrue(contacts.contacts().size() > 0);
+   }
+
+   public void getCertificateContactsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      IssuerBundle issuer = null;
+      try {
+         issuer = vaultApi.getCertificateIssuer(vaultUri, CERTIFICATE_ISSUER_NAME);
+      } catch (ResourceNotFoundException rnf) {
+         assertNotNull(rnf);
+      }
+
+      String path = String.format("/certificates/issuers/%s?%s", CERTIFICATE_ISSUER_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(issuer);
+   }
+
+   public void setCertificateContacts() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultsetcertificatecontacts.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      List<Contact> contactsIn = new ArrayList<Contact>();
+      contactsIn.add(Contact.create("foo@bar.com", "Foo bar", "867-5309"));
+      Contacts contacts = vaultApi.setCertificateContacts(vaultUri, contactsIn);
+
+      String path = String.format("/certificates/contacts?%s", apiVersion);
+      assertSent(server, "PUT", path, stringFromResource("/vaultsetcertificatecontactsrequestbody.json"));
+
+      assertNotNull(contacts);
+      assertTrue(!contacts.id().isEmpty());
+      assertTrue(contacts.contacts().size() > 0);
+   }
+
+   public void deleteCertificateContacts() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultdeletecertificatecontacts.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Contacts contacts = vaultApi.deleteCertificateContacts(vaultUri);
+
+      String path = String.format("/certificates/contacts?%s", apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNotNull(contacts);
+      assertTrue(!contacts.id().isEmpty());
+      assertTrue(contacts.contacts().size() > 0);
+   }
+
+   public void deleteCertificateContactsReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      Contacts contacts = vaultApi.deleteCertificateContacts(vaultUri);
+
+      String path = String.format("/certificates/contacts?%s", apiVersion);
+      assertSent(server, "DELETE", path);
+
+      assertNull(contacts);
+   }
+
+   public void getCertificatePolicy() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultgetcertificatepolicy.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificatePolicy policy = vaultApi.getCertificatePolicy(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/policy?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNotNull(policy);
+      assertTrue(!policy.id().isEmpty());
+   }
+
+   public void getCertificatePolicyReturns404() throws InterruptedException {
+      server.enqueue(response404());
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificatePolicy policy = vaultApi.getCertificatePolicy(vaultUri, CERTIFICATE_NAME);
+
+      String path = String.format("/certificates/%s/policy?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "GET", path);
+
+      assertNull(policy);
+   }
+
+   public void updateCertificatePolicy() throws InterruptedException {
+      server.enqueue(jsonResponse("/vaultupdatecertificatepolicy.json").setResponseCode(200));
+      final VaultApi vaultApi = api.getVaultApi(resourceGroup);
+      CertificatePolicy policy = vaultApi.updateCertificatePolicy(
+              vaultUri,
+              CERTIFICATE_NAME,
+              null,
+              null,
+              KeyProperties.create(true, 3072, "RSA", false),
+              null,
+              null,
+              null
+      );
+
+      String path = String.format("/certificates/%s/policy?%s", CERTIFICATE_NAME, apiVersion);
+      assertSent(server, "PATCH", path, stringFromResource("/vaultupdatecertificatepolicyrequestbody.json"));
+
+      assertNotNull(policy);
+      assertTrue(!policy.id().isEmpty());
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
index f439315..78d5425 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
@@ -17,21 +17,42 @@
 package org.jclouds.azurecompute.arm.internal;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
 import static org.jclouds.util.Predicates2.retry;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
-
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_DELETE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_SECRET_DELETE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_SECRET_RECOVERABLE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_KEY_DELETED_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_KEY_RECOVERABLE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_CERTIFICATE_DELETE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_CERTIFICATE_RECOVERABLE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_CERTIFICATE_OPERATION_STATUS;
+
+import java.io.IOException;
 import java.net.URI;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Properties;
 import java.util.Random;
 
+import com.google.common.base.Charsets;
+import com.google.common.base.Throwables;
+import com.google.common.io.Resources;
 import org.jclouds.apis.BaseApiLiveTest;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.config.Tenant;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultPredicates.DeletedVaultStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultKeyPredicates.DeletedKeyStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultKeyPredicates.RecoverableKeyStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultSecretPredicates.DeletedSecretStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultSecretPredicates.RecoverableSecretStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultCertificatePredicates.CertificateOperationStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultCertificatePredicates.DeletedCertificateStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VaultCertificatePredicates.RecoverableCertificateStatusPredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.PublicIpAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
@@ -47,11 +68,11 @@ import com.google.common.base.Predicate;
 import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
+import com.google.inject.name.Names;
 import com.google.inject.Injector;
-import com.google.inject.Key;
 import com.google.inject.Module;
+import com.google.inject.Key;
 import com.google.inject.TypeLiteral;
-import com.google.inject.name.Names;
 
 public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi> {
 
@@ -64,12 +85,22 @@ public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi
    protected Predicate<URI> resourceDeleted;
    protected PublicIpAvailablePredicateFactory publicIpAvailable;
    protected Predicate<Supplier<Provisionable>> resourceAvailable;
-   
+   protected DeletedVaultStatusPredicateFactory deletedVaultStatus;
+   protected DeletedKeyStatusPredicateFactory deletedKeyStatus;
+   protected RecoverableKeyStatusPredicateFactory recoverableKeyStatus;
+   protected DeletedSecretStatusPredicateFactory deletedSecretStatus;
+   protected RecoverableSecretStatusPredicateFactory recoverableSecretStatus;
+   protected DeletedCertificateStatusPredicateFactory deletedCertificateStatus;
+   protected RecoverableCertificateStatusPredicateFactory recoverableCertificateStatus;
+   protected CertificateOperationStatusPredicateFactory certificateOperationStatus;
+
+
    protected String resourceGroupName;
    
    protected String vaultResourceGroup;
    protected String vaultName;
    protected String vaultCertificateUrl;
+   protected String tenantId;
 
    public BaseAzureComputeApiLiveTest() {
       provider = "azurecompute-arm";
@@ -110,6 +141,16 @@ public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi
       publicIpAvailable = injector.getInstance(PublicIpAvailablePredicateFactory.class);
       resourceAvailable = injector.getInstance(Key.get(new TypeLiteral<Predicate<Supplier<Provisionable>>>() {
       }));
+      deletedVaultStatus = injector.getInstance(Key.get(DeletedVaultStatusPredicateFactory.class, Names.named(VAULT_DELETE_STATUS)));
+      deletedKeyStatus = injector.getInstance(Key.get(DeletedKeyStatusPredicateFactory.class, Names.named(VAULT_KEY_DELETED_STATUS)));
+      recoverableKeyStatus = injector.getInstance(Key.get(RecoverableKeyStatusPredicateFactory.class, Names.named(VAULT_KEY_RECOVERABLE_STATUS)));
+      deletedSecretStatus = injector.getInstance(Key.get(DeletedSecretStatusPredicateFactory.class, Names.named(VAULT_SECRET_DELETE_STATUS)));
+      recoverableSecretStatus = injector.getInstance(Key.get(RecoverableSecretStatusPredicateFactory.class, Names.named(VAULT_SECRET_RECOVERABLE_STATUS)));
+      deletedCertificateStatus = injector.getInstance(Key.get(DeletedCertificateStatusPredicateFactory.class, Names.named(VAULT_CERTIFICATE_DELETE_STATUS)));
+      recoverableCertificateStatus = injector.getInstance(Key.get(RecoverableCertificateStatusPredicateFactory.class, Names.named(VAULT_CERTIFICATE_RECOVERABLE_STATUS)));
+      certificateOperationStatus = injector.getInstance(Key.get(CertificateOperationStatusPredicateFactory.class, Names.named(VAULT_CERTIFICATE_OPERATION_STATUS)));
+
+      tenantId = injector.getInstance(Key.get(String.class, Tenant.class));
       return injector.getInstance(AzureComputeApi.class);
    }
 
@@ -198,4 +239,11 @@ public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi
       return subscriptionId;
    }
 
+   protected String stringFromResource(String resourceName) {
+      try {
+         return Resources.toString(getClass().getResource(resourceName), Charsets.UTF_8);
+      } catch (IOException e) {
+         throw Throwables.propagate(e);
+      }
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
index 9d5eab0..8a0efd4 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiMockTest.java
@@ -26,6 +26,7 @@ import static org.testng.Assert.assertEquals;
 
 import java.io.IOException;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.Properties;
 import java.util.Set;
 
@@ -71,7 +72,7 @@ public class BaseAzureComputeApiMockTest {
    private final JsonParser parser = new JsonParser();
 
    @BeforeMethod
-   public void start() throws IOException {
+   public void start() throws IOException, URISyntaxException {
       server = new MockWebServer();
       server.play();
       
@@ -148,10 +149,19 @@ public class BaseAzureComputeApiMockTest {
                   "https://management.azure.com/subscriptions/SUBSCRIPTIONID/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1SVEVTVC1DRU5UUkFMVVMiLCJqb2JMb2NhdGlvbiI6ImNlbnRyYWx1cyJ9?api-version=2014-04-01");
    }
 
+   protected MockResponse response200WithHeader() {
+      return new MockResponse()
+              .setStatus("HTTP/1.1 200 O")
+              .addHeader("Location", "https://management.azure.com/subscriptions/SUBSCRIPTIONID/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1SVEVTVC1DRU5UUkFMVVMiLCJqb2JMb2NhdGlvbiI6ImNlbnRyYWx1cyJ9?api-version=2014-04-01");
+   }
+
    protected String stringFromResource(String resourceName) {
       try {
-         return Resources.toString(getClass().getResource(resourceName), Charsets.UTF_8).replace(DEFAULT_ENDPOINT,
-               url(""));
+         String rsrc = Resources.toString(getClass().getResource(resourceName), Charsets.UTF_8);
+         if (rsrc.contains(DEFAULT_ENDPOINT)) {
+            rsrc = rsrc.replace(DEFAULT_ENDPOINT, url(""));
+         }
+         return rsrc;
       } catch (IOException e) {
          throw Throwables.propagate(e);
       }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/getvault.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/getvault.json b/azurecompute-arm/src/test/resources/getvault.json
new file mode 100644
index 0000000..53bee7d
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/getvault.json
@@ -0,0 +1,60 @@
+{
+  "id": "/subscriptions/012e832d-7b27-4c30-9f21-22cdd9159d12/resourceGroups/rg-vaultapilivetest-andrea/providers/Microsoft.KeyVault/vaults/vaultapilivetest-andrea",
+  "name": "vaultapilivetest-andrea",
+  "type": "Microsoft.KeyVault/vaults",
+  "location": "westeurope",
+  "tags": {},
+  "properties": {
+    "sku": {
+      "family": "A",
+      "name": "Standard"
+    },
+    "tenantId": "ba85e8cd-8c83-486e-a7e3-0d7666169d34",
+    "accessPolicies": [
+      {
+        "tenantId": "ba85e8cd-8c83-486e-a7e3-0d7666169d34",
+        "objectId": "b025a8c0-d7fa-42fd-8e62-d988a3f12791",
+        "permissions": {
+          "keys": [
+            "Get",
+            "List",
+            "Update",
+            "Create",
+            "Import",
+            "Delete",
+            "Recover",
+            "Backup",
+            "Restore"
+          ],
+          "secrets": [
+            "Get",
+            "List",
+            "Set",
+            "Delete",
+            "Recover",
+            "Backup",
+            "Restore"
+          ],
+          "certificates": [
+            "Get",
+            "List",
+            "Update",
+            "Create",
+            "Import",
+            "Delete",
+            "ManageContacts",
+            "ManageIssuers",
+            "GetIssuers",
+            "ListIssuers",
+            "SetIssuers",
+            "DeleteIssuers"
+          ]
+        }
+      }
+    ],
+    "enabledForDeployment": false,
+    "enabledForDiskEncryption": false,
+    "enabledForTemplateDeployment": false,
+    "vaultUri": "https://vaultapilivetest-andrea.vault.azure.net/"
+  }
+}


[3/7] jclouds-labs git commit: Add Azure KeyVault support

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultbackupkey.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultbackupkey.json b/azurecompute-arm/src/test/resources/vaultbackupkey.json
new file mode 100644
index 0000000..05a469f
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultbackupkey.json
@@ -0,0 +1,3 @@
+{
+	"value": "JkF6dXJlS2V5VmF1bHRLZXlCYWNrdXBWMS5taWNyb3NvZnQuY29tZXlKcmFXUWlPaUppTTJJd1pqZ3dZeTB5Wkdaa0xUUmlPVGt0T0RVeE1TMWpZVGRrTTJKbFlURTVNMkVpTENKaGJHY2lPaUpTVTBFdFQwRkZVQ0lzSW1WdVl5STZJa0V4TWpoRFFrTXRTRk15TlRZaWZRLnVWeGFLX3g3V1kyMzhLTEY0TDNVOXJEYUlWdnpwaEt6ckY3WGtqcVhkOGwzaVMwMXdfdncwLUFpS3JocEVoY3NGaHVkMHREaFV2eXBNS2cyN1UxZlZNRkZoRExxVmxwUk5vdTZnSVZKVThSa3N6anZmU3phaS1hYS0zSzFacHU3eENBazJXTW1iZzJMSXB5bWI0T29HZ3B0NXA3dk16RW9fN1ZjRTRKTXhUckVQV0xOY1plQXRKUkxlVFkza3YyUHZCTHQ4cGN3MmhNWUYtQ1hpd1UtcGt3R0s5QUMxUVFwZzBFWEZXZnpGZkNwVkg0UUpZQ1dyckd5MXhUMlpWbERPdGZHcG9zSkZ2cDBfSWR0X2ZnY2lxeVZ4Ym1Ccnk4eGJ4blRXcVdySm1KOExmMldzRXdMcXNvZ3pQUzZlRFJqU29YRlBCd1lqal9ENFVhcDNqTGlCQS5DOEV1cFF1aUNSOU12YVBabGVKSTN3LkQwT01pTHBHd1pVVW5GdDI0OFJYUjNycS1KcVFqeTJSUzZnTFBUMkM1SVFyOHVTZmpoaUI1cTRoQV9TN2NMQTVnWXo4VVZpWTRRNEQ3eTdSU2JxemhRTUNPa1QxclBNUkxtZjYzbC03ckNBaHhHNWNwVzFCZVlma2FBaTFMUGxwZ1RnYi1EN2h2NjFNQzhCcXMtU0t1eTEyN2tfSXV5d0hMelFtXzQ5WTNBQ0xJSGlDQlhYZTlSTWJKSEhuY21nMTc1WGlGY2RuRlhKTnRKb1B6MWZWZWlrRFBkb2
 x2Z3pYSkFHYTROcDI2SDhJVGRTanRpOWUtWVNUTllTUEs0ZXlwRFRNcFlYcTJZNUJIYjNTNnYzMHZCNWhCdHkxdy1jXy1iQ3pUQ3VHNzA4WnZneHB5V3VXU3prZ2g1VVF4Y0F5djdaUk5fZk1VVEVQdXMxTmRKaEt1N1Vna3FxdWU1c0ZPVm1mS3ZTaXdlN21QZldUajA2N1JpTXVWY29JLTU0eUhLU3NRTXcyZjRteTR4eDk1QlloUmlXOE9HMS1ISzdkN2Z0TGRYbHRKMDR2WjFDUmFOTjlQdldUOWhNR25DUlFRYTMwamlWNDd1Mm9oTnZGRDJNLUlQT25pb1ZYbWNPeGQ2eXluaUpxQzBodWNuMWo3ZnRlTFpNbVlLMDJEOTZNZzZ1aEZnU2ZWVDFDRDdVeUtISk9tamIwX3FtNXBLZ24xWGkxZVhlSWsxMnNpeTBqMDlBNkJDTW9JM3NIdEZaeWxaTmY1SDlTMmRzcEhZN0JvTWt5eUZqOWJjMEFWY1F4Umpjc2YyMEE1cHd4TWlLZ2tRSUlIT3RkbEpGUHQxWUVrQ0Yxc182LTlSenpGbVI2OW5LaUZJdVYwS1BWRjVOT05RYmc1Vm5qcnhhNFEweFhVcE1Ecmsxa2ZQZ0lSRG5LQ1dUMEtlbWkzSVctdS1EMzBHNXJUZ1RvYjdDNkdLd3NYeHpCXy1scWdEb2RqUk9LdVhISFdjMzZlZ3ZwbWNRdDNRaHFkYUt5UEVRTWNUbHdSWGw1VE9yangwWHloZENpZ2hWSk95XzVMVGxLUkpXdVh6dHZ0Z3lIaGhGVi1CdS02UFBKeDFSSTF6NmV0Q2xSNGd3WnlYU3p4c0cwem9tSjlKVTJqczBrQVBmWlFVc1FQZ0FZZFlvTEFkTV93a0l1eXVrNks1RmVTZ2FQbFJiRXEtNmZzdnhCVXM1STRwcm9BYnZDR0c2RXc1YXRDVU8ycTh2V3VrcFBZNG5DVzdseDkxZWI2QVV
 QRjdhMFUyQzh2SjRJU3VuSGdpaURvX19YaDlTZDk3ZDNZNnFUemZhd1A5eUIwTERKZDZIeDQ4QWNWd1ZYQWdNeVo1Vm1YWWtVTjgxTFVxNzNLY21lRGV6R2hlelpBVmp3cEVXQzZKdzdRMUJfM2luMlA0SzB2bGVXa3ROWjFaV2ltd20yRDNkTjNYdWc2Rkh3MWdjZ0RyaEc1OXd4ZEVTVU40eXFwY2hZQWZSZnlLc0R0NkdpOFRZWThiSGI4eXFCWUxITEpQd2p4UzY3dTc1QVRZTGNKU2lTQXk1cEtPSzRSUGhDMzRVWjR4Wi1mZEFVUGdHNmJIcHd1eHdOWVhYM3dnZzR4LUN4X0s1bERGWTJfenhUdG91c0tGSXZ3N3BDNkRkT215N0JPQkRyRzhUMkVKYmJHQW41QzJxZXNCRHNQMlh0U3RwZno2MXF5QWlpeVFzWVF1UWR0Ums2MWVfaWlDZldaYlBhVTZPYnRYemJrblVCM3lwcHpybnZiQlB3S2RuY2RVVHU2Q2hldzduc1gzRkR3TGdPSnNld0xjb1BwSndSWGl2QnY1Z1pNT2NFLVB3VUc4WmVLWjQzUDMweW9UenJWWnkzUmgtQW80ZVVyR3k0QXFja0UwbUx1ald0d1JUQnpEbFBwWE9aWHV4dTkwTENOdVJXQ0RBYnRfajdKd1hCbkZjSlVTYTJVUkM5VHdWaTNZWW01aURrSnRZR2s4ZkFILVU4b0xIT2dRb2Itb0o1eTdwQjNrM3pnNmpLWC04T0wtbWlLWkw3a1JPYUlOVzNtWEZHSmhIdmR0cHNaaFNVV29FaU9ZbkdNT1NwSFpSdkJtYVRlVDRHNTFLWlB5bHV3aEx2bXNNVTFjZlpYVzE0SnlXZlpYbUk3YWRrQ1cyRTBDZGE4Si0tbGtLQ0pxVUVtdW5WZmhndVRaakRxVF8xSy14ZF9ldkk3TV9mZVNfX3ppZFJncDFiV2NrTl9EZ0NZSjkyNHpS
 V3h4bVE1MU5NSF9pcVZiS2FFOXhSOXZ5cFNRLS0xV0tONWZFWHh2NFdYa29sbkRTYUp2VWhaYmE1bGFSbXUzT19sQnZMU2VRbEM3eDQ5MWJTbGhmdXpWV2gxOUpzdGRtYkF6Y0dZQk1ZYXpwMDRMclc0cW5ZTVNYWHFQU2VJcWpWMVBzTHg1WTUzR2JxbnY0TktRMEJubnhjRVZHZzVPZGl5ZlB6UTRMZUlPZzZhTzBxUy05eUVqTHFZdGY3dDVWRnZaN1RDWTRDWlI4dlRoT0Z0cURvSHYyVWo0eUJaODFuYU41OFF1aXMtb01iampETTM1OV9WMy1OUWhvTk9vSllpZXFiYW9fSTRlUzVNclAxZXNEYzNvck5BWEptV1M4MDB3SG9maGRjUE9vYmt6dzNjUmhQN19wYjduZGtWZjEwUmVJZEktcnAwTjJiOGk4bEppRG1Xb1otR291bkdkbGZoSVlqdUpROUczRHhMNXcyRWIxRDlXMlBnTlZON3FSRk1fM29Dc045MWs1YnJjNWJUUWdBMTZ4TTg4NlNXb0ttaGViYjdEb2ZSU3NQV1RTRno2Y1JjTzcyTUZNSkQxUDY2T2otcVlfUGU3cElhZ3IyVl9QVFNQclBsb2MyYjBlRmt6bTZROGhlRUdpZVlZcnd0SGFTUVVoWmlyN1N4aW5IVmxTblBYVkpDUzZmcWRKbnBaeHhOdzVaZ2JiWGJobDRwU0tLOGY5b0FDdTNvTk1XUGdWaVRpVjRSS09WalM0QXF1bjB5T2ljRkRoVzVOZEExZWItakhfN2V2RGxaNmNnemZ5bkNfdjFpbzFucDAyTEs2WG9jNURIZEhUMzlqZDkzQUdvZmtkT1c1LWx0clUycW0wMzYxVDA3WTAtSG5ZeHNDQW96VGs1M25zQmdTMkRQWklYaWpiRVpIVHc2OWJINTZPX2J1R0ZBYUdNMUNySV9RLUJoWW9QWHpINHFuMXMyZ3RlcUNaOUtKM
 GZlMy1lVnE1ZGZkNVRmR2pfUzNCWl9QZnlPYUtIR1pBdk1mcS12cTdhdU52UjN2YnRMTjJkZHhLVTZoQkNpRkcwbmtWZ3JMNVVBbzZ2em5fTXZBdC0zYktaRXhXSDB3WGtjM05rc1U2YnBpMkQyVnFVeV9RUE9TVUlsTktRUDVwX3ExMERheXFleWdwdlZYNWJsMGVwWDd4ZGxURmN3Z3lZUGxpc2h4VnlZX2ZydTV0QlRCX3hjZWgzMXFTeEZjTUNMYnFLMUpIZm5LVjltUVJZNUZDRURibllwQVNTeDBJVkxRVFpqNjBSN3MyVTVqTk0tZzFzXzc2RlNSSDlZS2VEc1FXcUpZNkVxNjJxaHBUNjBDOTFhMGhRRGdIdW5xTU5lSl96azFDbGZZZmJwSWdDaHZFd01YX3VOS1FMRmNDdWVjWG1mS0Fxb1ZfczRLTXJlbVJqMDMzNDQwWUZxS2FiZWhjVDVpYWhDSnRkZnZxSXUwc3pDRnNmY09INGtyRndYTmlXYV9VY09aY3FHc0Fxbjh6eWFfZVRSV3BUanNFelYzY0tjU3F1aHBtQUU2SWpnQ1NFTGw3SmxsZVdteFdzM214NnFJYmJlakhNLV9ndUZ4QmQxc2FJMUZVWFlQYWJsMXFybzJNZDhPSWtGeUR0WmJad3Zla1JoTU9lWFBJWFNKRGFuVkR1S0h3akRCbEktSWgxd2R4TndqN2tBVW5fSm5rM1BZQzVKM2MxTm80Q3hxdW9ocm1nZGJTUEdqNXBzZWNWRDRGaFh2VDVvNUxtRDdVcEVVT3lFemtjVFJNeHNQTTMxVFprRVlnOHktX3V0VTFJLVQxN3NLOGo3dGxnVTFfTm9kQW1TUHM4WmdHaFRhRXA1SVRRZXNFNXN4NFl4TnZBVXpHTklPUGNzSExfTi15WnA4OGN5dlhyV1g4TXdBZEhwYTFNX19Xd09DOS1KempvRVYyejJ3YWNyTk83bUxiQWNydVFoSz
 BQMXBrRmpsbENzUHdqSkdwWGN4dldtaEdrMDE0cjA1dWtjRkp0LS05bGw1WFFvQkdwWU1GWGY1Q0l1SG9HaUF0cGJvRDlRd2NhN0ZiNkU5MFRqSVhUMkJ4cmhKR1lXY0dWajAzNlFja2I2WVJpOVZiRWxweXBmbkxscEdvWDcxVndVTWJnY1RvMHlORElWLTNtMEM2VlVndmtxS0ljT2RnYi1SX0VPdkVSVHNhODQzVHA0Z3JlM1pnRzlTNVI3UE1GdE40ZUY3NkJZbzdFYm5IcGttdTJkdlg1aDdQdnF0R216cnp0QVozZ1ZWUUcyNFVVNHRDN0VmaHdkLXR1MkNWcU5QTVRROFhSaUxlM3JKMjJuRktEdFNXSXVHcFRoV0hqNGJ1Uy0xRFlkNHBxV1hNUjBtUDNLNkYxbFJ2SUlUSnhlNEhjeVhvaVJtaktJQjVvbFJFZEFsR2ZhY0taY1FmcDhvVUlmM0liNEJnSDVQU1VHSGFMWFhjSDZaN3RPU1pERzZCVmJsZTVvT1VMdkd1SzVUaUQtaVh1bWFSMjk3TFB3SHl0dEZDQ1BjN0txdGZhbEJPTy15dUJacmRtRlVtN3ljMkdpRWtnWnNuVlFzcHl3NHZmU2hWb3VCTGdsbHJuU05NN1l1NWoxM2hTOEFkblBmWGNOQ0xsVkFleTVVeVVuTWlpcmR5ek90Yk9TekI1dHRGcDFpR1AtaElfSmtvUHdvT0RIZUJlbzQ0cXhkekZvUVBWbUFGNS10RzN4QWFqU0FUNGVyNXNLVlZ3dmsxWmZUQlJxYXhQWTdHd3RaWmxpa3hYcThpTC0wdm5mNEtINktnT09uUGtoajM2VmhCeXp1c1BrNkYyUUdQdjNXdlRxX3VMalgxV2V4UWVmS0JjYUtrOTF4R1Nxakl0YXVZQTZGWWpNd3Jmc0NPelNwOGV0VjNQc0NhWEt4dHJyWGxHd1dEOV9EeFhKVmprNDMyc3UyR0pEaVk3aVN
 fOGl6XzBlQWQxakxOQ09YcFN4SzlFYjdvY2RjS3pTX05JVktqMTZFYWxDa1Z1MGI3OXZfLU0tY055NUwyc0lUZHpGRmZEOVZDdjVRdk5hbFFzTU1Fc2VoRm5JXzAtMW1fRXFNMUtFdTVlWGtZa3JwMThoWXU3RFpCbXg4dDZhTXY0Q0tpVk9kVDhhUVFmeXhwZ3BSSS1jUGdBNHVxVzk0U2dRZ0RURWhmeGVxbzg5WEd1MXBaOTRndHliOXEzVHd3VDZTeWNYRW5vSlExck9EaEhqV0gzRUJyUjZRSVR3d1VqRUFjRHdDZmFPREJ0OWlUeHJjZk0tem5mekx3elZkUjVBakVNd3RSTVZUOEpzd3JYeHI5bXlWMU52cGtZeFdFUlpvbTItcW1DWm1vRWZWdG13d1Axa2g2d1U0a1VGNWo4Q1psOWdUck5NVk9Ra1pzbkxuWDRKVnhpc2k5WENBVWRkLXE3NlZpemNFNGpFYzVmamd6ZzdsdF9IZldWUXpIVWZaR1NXVUg5OGZEd0k3N0otSmh2dlJMMF9uQkpvZDZlYUxVNjRpODgzSDFrODdpTXFXcTl6ZVNrcFpmRGhpZVhvb1Brc1YyRUROZG5pSkt4dHZvcU8zLU53bTdoVTNDZXNEMjZ0STB3dHhEZk1MdkQ3Y2VZMTVRZXNOdTJqSmRTdGE1bmNtZVNMMmNVVWZkUmJyWmhRYmV3VFFtMTh6UWlXSTN5d09jWXhadm9SNXpXc3ctQmIwT29XRWVwbFJQNzR1S3RXTVZVQUlpYTdHcVN0aGxFT2tXcllFMUNLT2ExajB5dU85Q0czTk1jSmdHYnlOMXJUYmR5azBfQXlEUV9JT1NEQUp3TVg0UkZadkNSdjRNWU01U1hPYVhWWVRwa0t0bEdFWXlUaEQyT3liU2ZLNjJhTnNTQUJDc29MWm1Pb1pYeWlwT2swT0F1Rkw1djh6S0hzMkJENVBkTGNRc3B0d0pyUlFPZ3Nt
 S3JRU1dJNFJrTDJwVzJ4VEtfdkJibC1LcnpEcGdJUHZwaUFENUJYS2FEbzlvU3BKRWZQbEw4VTBLX1k4Z00taGtqUmYyZzBzRFdJeVUxYV9raUdzY21UYl9oNlRiYTg5aVQ3cjg3RVhUTlhwMmI2TnNmdDI3QlMxdy1qc0RPSVZtdlNfNThTbVVDXzAwdmxjVENBcUhaM1ItWnE0dFdHdkY4UkE3UnVabDBDYXVvY3hXTFNBV0NEbkVCUXM0X2wyUmowek04NFBXeVhRN0loZlRDVU12X1gzZmwwYVJJN18wYTd2c1BYLXRILThBSTBPRzVRb2tUZm1scXhFWTNhSjRxUTlOTERJN0t1TExpWGE1clZ0WjFVelJLNHRWTUNKaUJPQzRGZ3BiRDRkT1VEWFRQWVUyenRMN3F2dy1pbGxYNTc1WlNyUzVCMGVQSXFUdFl6NWZoX2pXeUtiR2x2U1RlbHpSNFdueVBxa01CaUNWQmd0dkZGS09nZV9vclpEM25CNVVuVHBTd0NGWVFkLTZwVDRKeEdNTDF4RWloWk9tTTdSV1BaaHpFNWVfRGczdzZ5UVlSbUhabV9hb3lrNGh5Tld6OW01Q3hleVlIRjc0N2c5a3NpOHpJN3hycTVLWHVHeFhxMXNIWEtvV21jNTVySV9LeGpTb3Y1bTlLYkVNNGZOMW4tMFVORmF3cDM2Vkk2WGQ3enAwa2pZeXVJY2J1TTZqMkdNUEJIeXZWbmFEYzIzMkVwWWVTdnhOUUJZUW1NR1hDNUNoWm1KQzN5T0ZXV09OQy11SkZjbVY4eENuXzE2LTkzS3JCT1U1eVVYaUZRQlV3M0hzTU5BRnNrdllwWjBncTNwZ1dWNTBOMXRRcDZjclFTTXBNNFppOTdVUU10TlhZLWNPZHpsNHl2Q05mM1ExN013U2Z5MFlrN2F6bVpIalNhclZaajZHbTdadjdFRHRpT0lYNTlDNEJRVGpkTDZONUZJLXROZ
 ElxOVlJODB6N3pvRXZpOHE4czY0UmsxZm5TY3NWbkpNOEFKTVVHV1Vkay12REYyTzR0QjNQQllKZXdheUkyNjRHSWJRSElJeDB2Z0pkVkhLYnFmZE56bzZwQnVHaldCUWVkczhWakJxdnA5b3BERnRhamx5X2lkY0p5ZGFtbFNfN0RCekdGaS1SLUNYSmxqVTgtdllvekVJM3h2SkxzamViN3ZtRFNpNml0a3BEaVZwX0hDSUhzQTM5MkhhZzZjN0VSbWJ3cEk0MkZaOUVUYzVReVRoc2ExZkVYaEw3aG5mR2N4b0RpdlJSc2dFdXdndEZTb2N4T0U0Y0o5UjUzeFNTYWRYcUFqSS1NSWdGWDNXRGhjcWlNemRBRm1SQVRnLW9tc1NMN0ZoZ2NmNk5WUUtpaVZVMEJZRUNPQjh2YTVFZVlnd0gwOGZfeTdNUF9Fb0xOZHBQN2IxMWFoSkR3cDRsN3FhaXNWcDZzX0ZoMi03OVN2a3o4RGU5azVNT25WVjQzOEVVUzJGUGMwb2RfQkpxWng2bVNaSFE1MFdpSTYwV2hSTnEtMy1DQWJ3ODVrSVBPTXlCdjlvNXNIVEVVU1EyQjVFSm1HOV9rZFVxTkF6aXE5cWNWbGJ4RHFHc0hsaFJ5QmlZdi1jQjd6NlVack1ZaWNwT3VaYzVNbUFseGxoY0t3cHl2R2RuX0hkRS1RT0dvekNHdUF1M3UwbjU5Um5qWDRCWm1hdTFWeXhJeWkxdkYydXNKUFZub3RoU0NxUlY0U1RNTWljZDhrNm9zU1BIWTZLUmRrRVN1SnRoZjlxWWctVFQ0MVp0M3RYVUE4bUhfWWxNTEU1NnVpWWlJMlZCT2FNbFktMlQ4My1MUHcwTEpnQ2k3RElvZ3BOTnFWRE14ZVVDTWdpX2pKMnotMEYta0pWdUtNMTJMT0YwSENWQmJUeWJ0cFlGVHB2eXFVSU02d1dzanp1WjNGdUh3c3hyVnRqWWZFUHJfaV
 htM2FQazBHSEdFVUFLMG1YTUozN3Y1Zm1GZmhwcTJ6aFRyLXJYR29sYVU1NHlBVkZrV2pLbkJYTWdxb0pCLWZMbHh0WFlvMllHbzdHUDFDMkFVRkUzTWFiOW5zSTlacmhGYV8yN0RXMHVDeTBsV09QQ2JCNTRPRUpIdTR2MGdSaTZCeERDUU5NUS1NNFZQUGdfQUVyOWV2aEFnQlRseUZtbFdDX1A0Vm1ONzJmYV9sdjBnSldsZERGQWdpOHFaaGhRUHdoamdUekRvR2ZqNzRDOFZiZE5KbXgyMm5DSW5fQVhiUi1PV0hsM200TnVVeEdZblVZcDNKczRoTF84UVFqNFJlWHppajVnSWJVYXhTTWx4UTFhRmVLLVVJaXFuQVJDcC12TW1TNm16V3N6TGJRUzVEN0RXSnl5N2JuRmtFLVljblYzTlJCTEFaei1ndU5DX1Z1bkpwVGxuSVJ5bzIzaERIZkNQeDROM0lLVWMyTWlxUDdTNW1vT09HMjZUb0Y3LUJBZktzT2ttMl84UGNudU51VWhmRWpxYzN3VUlZU2c1TmlyZzlUSVlOQks1YVNhSEFjS1AwcXdENW0tMkt0T2lEMkJ0RmhrelJPdm9fUnF6SnAtR21kajFwdFRyQlIwcy1KdU9rY1lud3VJcW9RRFBhVy16WDJXTzRjX3pDMDR2YlZjcDRGdXFoZzhaTVNiQWFkQldQWFZlNENGU1A1R2RfVkJvVFU5V3RLRkdEOXViLVNLQkNfbXRZcVVfRDN6SUpxTFJmUm5mT1JoT2RoemdJNVFpMlAxTVlISjdFenF6NHhNSzlzZVU5OEdtZkM5cUwteEZhRW9RTlVCajBUaHp1dVUwNkxUbENYZXh0OWNtVXRhYnVFZGwzQXE5RnhQVXJwRWxwWGhoLTQ1N2gzQk1Bal94Nmk1a0RBUV85X1EzZVEtay05Y3dPQmRrRUcwNk5xX0NhNFFyNUFTRTZvcXVEazBVMHBjcER
 Ha2ltTUM1MVZ5N1lzNWlqQk42cTFKVzNzYU8yN1ZUV19LSC01YWFQQUw1ZmVBZ2lXeW56T0l5V3pEX1BwWm40SHNGaFNwU1RKcVViYXI3amZIRERNaUN6bUhybFVJQWF3QW10blhsS0drWF9RMDhjeEN0Ni1YMDlCd0poQk5JMDJkTXpWZDFPQzhPVUo1VFEtX28zTzgwZmNIeml6UDhENk1GS1R1SDFfcjgwczlBX1IybVRObGdFaTY4T19fdFVqZUdQNWZqd0JlbWJjSGc1aEREdDBDaVBMZmZMUm1iQ1dtT2JJR0xMNFlLazNrWEh3ejQ3MlpjZFRCZndGT0dDT1BzUXcyc1hMcDhtNE5TeWpIeTlTSzN6a2tNdHE2cVJ5YWQ0dHpnaTVoTmJJLWpYRUdLWmZGWWFDSkxXQUJGbzljSU5hb2VhU2lFbTdXeDNkWEV3R0QtNmZQU0JVRzVLVl84QTZmU1R2WVVkMU5QSmRuSkgyY1lUOTFIekk2cjAwQUpOcFg4NWtfbG8yZlJKVkNSUE1UVkVZb1JqSWtBUURQVDdDMlI1Y1pxcDhneURod2JGc1pzUlhTWGp3RkgxOU1Kd2lsaHFNNnQzNW1FU3o2Zy1aeldMQzJrNDZBSkd2eTUzajJwYzQwbTVXRGpxdVBzQjh6RUt6bGlobHpFbWtTdzlIT2VJNjJPM050RDFBQTVSTnFNYkdVeVhUN09KWEFIRWZrOV8wOHRkOUJoMkhQaUVxOVVZSERsWW10WjdUbjkxV3NpelZYNEZxeFpzMjR4OE9XQ2VJTm9PZFRDZHFocGNxRVQ4aldYYmZvX0Z2Mkl0UEljMndSSWVqekZ4X2h2bjBVbVc3UTRFSWRTdnNJelI1ZnQ4ZHJzUUZHN3ZQZTRfQlhCOEw0cmtQY2JGUGVWU29XejdvcnhxWWc5bGJlWEVRR2s3dzN3OG9FTU1rZ0VPVnk1eVdvREFQY2xldTk3VmVKdFJlRUkz
 clBKNE9jUFh2bnRVUG4zSDFsSjBnUzQxT1dwckVMRWFWTl9ocVpsaXdkRUpJTXAtNTdydGN5SVk4N19McU1rUEFDVkJtX2dtZ2V4MVZkTlhkYzU1OUlvWVljd0NDUlBERWVpRXVSLWcxMWtTRHFJZ3lRaHE1OWRDSmpRN2JCSTV5andfMG5PNkpYRjU5eWRWcURfU1ZEb2xkazNpa09VcEYwUTRrZkZKYlYxY29wQl9DRFJKM3pXRE5ScENhVEZxbEVGc3dMWEtRSFliTUwyOThKR3dIWW5FX0N0dWtrU1Q0YU9kbnBkcGVfTGhhLWJvUVQwQ2RKMUhhZHJOb21uWlhER3VxckZQcWVBRGkyOTJHZzRLZGxEV2MwVkh1RGtrSGREYkRtaWd2RXhhVjVEQlFhd05zcFJxaUhIa0R0cDFZRmVlT2FwdTRFM3o2WkhkYzFNUWpFRWlGYjczSmNNQVVTMGlwS1VLV0NhS1B3ZE51dU95ZUF0Q0o0dnpicmczTFdSaWJaVjRzc0pqZElRYjZneFpMOHZteTUtMUFiZ0czekpJSUNvSElJM3ZqWWxEVXk1UVRqMkhoaEp3TnFYR1hxTmNaM1ptMGRoMlRzSTJseHZEVDVVRlBzeG9ab2F6dXZIUW1uSjR0ZXlma1hNalNFMEgyRGF0YVhiS1pndGJTaEY3Q0tpYjRwdXN1SHpyMFllOTI1MDdPaHk5Rzg2WENSUWxkb2xlVkhVMEczWUVhQ1AxeWhjRG9qbmg4ZVBFSlFwdFhpRGxBU3hXSFFiY1FNOUE5dWs3ZmNRVEFLZ1hsYTdjR3JFamwwODJENWtWWmhROTV2dVpXTEtDN2lqZlE3dGVnX09WOHNzel9pSGxlSHpiV1o3SGhWaGM2YmZLMW9GUGdCS0dESmlmTk1fZ040QkVQRjFSaTR0ajh3cGdLbzIyaWpieG5faXhac2pUUDU4TTRmSXEyWmFweWFSVkpoQ3NKTkRWWlFab
 nRKTGVsVVNVWmxrZktPOURfdjNXcVZwZ2RhbngxVHZ5M1BCUWhlU1RzVXE3Yk0xdXJhMEdEbXN4dFZVdnBncW5HTWtuNHRoZUlNRm1ndWJoTmlXUFd2ZlJNNUpDM2hBVjJXb28zRGpvS1lISkVrMFA1MnBqOUVuVEVXZWlTcWZHcklqUndjZml2RXFRNHk2ZkRfSFZaSUx2RzhxMl9IemoyWXVPVHN1dWFPNExnZkZCeUNXN29kemZNejJDeDVVeHdXUEZPYm9LcF9INVdUUTFfRTFDQjB4bHIxRGVFSElwS0ZLUVowakZIQ0IwWGtsLUc0OE9tYTRXS1dZcW5JSV9LaGdBRkY5Y0NUQ1dQZlNwTUtGWS1MRXN3R18xN2hxOEswYXNoTzZZbFR1TkNNczlpZEdCRnZyZEd6THhoUGVldDI1bVlPSDRLZUs3WkZPeUh5RnY3YWVSVmlESkQ2dW8zbHV4TXM5UV9NTkF4WnZ5SUZhMG4yQ0V3eUwxVTlQcGhhNm9UMW4zZHFsbDhSVFVLaGZDZXRQZWtaQVJfT20ybDhRMWFVY0tHV2RaN3d2Xzd5SXVCWEpHbTdieDgwVnpxTDYxMVN3OE5FdFh1cVprLUVkRGlvMEx0SU1kNDZ3MWpTQ0l6QTFueUdtSklrTjktZWF3czlkNy1Uc3FUcHpQQTV5WS1KRkl3c2NXcEozcE5ma1d5RDFKaDV2cldvcEE4THRJaWJNdHlEU2ZnZ1FZckNvQWNWSmdGcmRzUWJ4Z2x5UXpablVNVEZKV2IwYjZnWnRqNHh4cndlb3lEV25zMmRlMWVqMDV5QUl1c3E4MVZXTU5fc0pDZG5NOGpOUWxSMzhPcnhXaVU3SDBVT3N2ejZPTG1WMmUwSzN6RmRKbUItWVk0eDdmd3hGaDVMREQ2Y2VteDA3UndQSzhxSzJGem5VNmx1eEVrTkpIRHNKSDZmdENxb19BaGgxQ2I2a0tmUGhkc1BYSTZxUl
 JIM2psOGJKMkVDRkhiVHpDTHUtM2RVQTJjQXo0amd3Ynpfd2ZQZWItNG9wR0xTVHpMVU5RYVhibkFaLTkwZnpNTmM2SUY5MFNVeHRXY190bFFPUzhxclBvcFVRSF9ObV9wR0sxT0VmRkg0U2J3SVFVY2xrQnZQUXh1VEs2TS1QZFh2QVFpQUZTWlEyTVVlSmZkRk56LXNyaTJUWV9yY01KQU02cTVOVEdPMS1INEV4SEZVTmRZYUt5RWkyNEJ2Z1pRTEtBREtBLV9uRElqNE93ME4zOGFnZ0ZFX0VIUDZ3bXNPWXFXQ09VLVlSb2dyT2VXREhlenBwaGIxeklPVVF0SmxHdHhlREZEdTRmNjc2bVUtM2hhcmlBRzNtV2ZYUUJ3RDB3dzhnc2ZZWXNkdUduUWpEdUgwZjlYRGZlVHhHbi02T0RxVG9mcHFGMl82ZVZOM0pUR3hieXFLMkpWVGo3YU04Mi1WMVJ3RG1iZV85N05uM0lfSzZGbmpCclJzZEowNklJcF9vdW5aUVVVT1pEbXdyRXZKN0dxWXRYYktubnlYTVdYcHI4UmRaUjItVWphWXBFNDZjRmRFM0ZhTTk0ZnRDS3Ezd1BTMXZFbU1KVnUzLUZSTVMtc3VKZDZCTlFPWUEzTjU4VHF6c1NIWEk4Nm1FOXA4dW5zazZMSHN1OXFxMHVMS1UwS2xDTTZWZFd1b0pfMy1yMk1ELVZHc2VoWFZ0VzdwTmE3SzF4bWVDcjVnNEFXX0tWaGJLMy1nWUY1RWNQd3JLR2ttNktYMkx0emZOSWZtcEhHN2djaFFGbm9KeEZwclZQejR2b1lwbDRTUTlKaHhCOXFJbUhWVll6WTI1dm1UdnpZd3FDRnUxYnZDN0VrTE9fNzZTemc2OUdLeHc5QThlSmFucHBydDVjMzE0YjB5Z1FVSUtXdWV2YVJXcFVhTEI0Ml9wSXJBcWQxV1VZSk5idy04MzZoM1QxZkdhR1pqUDduX1B
 HRDlpVzB5TUlXMHBGdmdfTXVoajN1N1ZHUTZ2aEEzZEo2MHB2ZEZIOWUzVmNMdktFcC1hYXl3ZUdlaHBKTVJiUkc1amhOaC1DODdOMzZNUzBaWVIwX1F2YjQ0ZnVyekVoRXdRcUN0M1k2a2xSb05tS2x5LW9rZmtRTWgxWG9xc1dLMUJxSTEyZjl4N1ZOSnFPV0VxWkRNYlNPcmlCb1g4a3prY0VaWHh0YUpDeEVFZkhxZWZkcldiN3RLWldvaXFiei1mSUVCazk2N0s4OHJSQ3V5TnhRR1BXcnNuTEtrTnNVdnhKOWhzckdNZFVoendUX2d2OV9iUllGVXN6ZXdweHA2QXdJNEpac041Z1RScWRvRkhaZnVUb3FIZ1NlODQ4TFUtelRJV245Y3ROWUtWb1Z4VWNEdzBiZHdSdXRUdmk0R2RvY0JiMTlqRXRzeWR5Y1VyclZWVXY1UTc3UjVRVi1tSFFtSTZ1VmRGR0JHUUdiM0Nkakw2YUNRTG5GVEl3U25LalN0N0pSLXAtb3Q4WFFvNDVRR1dGZEJSMkZXT2FmZGZkSkJ4Qno5MExmZjJrczZ4bXhfVmx2b3ptV0JFMi1zV2hLbXFONVRrZ1JnMXNNWFhZTWpBUEsxMENoR2doanVLLWxydndvOWYuYVFLYzIzRDR0TUlkZUhoVklVQ3FqZw"
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultbackupsecret.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultbackupsecret.json b/azurecompute-arm/src/test/resources/vaultbackupsecret.json
new file mode 100644
index 0000000..ac51969
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultbackupsecret.json
@@ -0,0 +1,3 @@
+{
+	"value": "KUF6dXJlS2V5VmF1bHRTZWNyZXRCYWNrdXBWMS5taWNyb3NvZnQuY29tZXlKcmFXUWlPaUppTTJJd1pqZ3dZeTB5Wkdaa0xUUmlPVGt0T0RVeE1TMWpZVGRrTTJKbFlURTVNMkVpTENKaGJHY2lPaUpTVTBFdFQwRkZVQ0lzSW1WdVl5STZJa0V4TWpoRFFrTXRTRk15TlRZaWZRLlFLelA2anZVR0Y5X1M3UU8tRkZDTHIyNGp0RXJuandkQThNZUtsSGE1MmhvS01rNjdiOHQyckZhNTJ6dGR2and1d1I3VWh4RldRLUpuOHk3YlJiNlYtcTlUYl9iV3E5clplUlhpUy1jdUhPak9ONHB1bHd1cVVmQkJOU2V3NlJGUXpOUzRrQks3RmxQSGZpQVRRaUUtLTc1cnZIM0dMTEdDd25KTkxIUDNTR0FtWlR1dXo0bTN6X1owR3RsZUU5XzFZT3pqczU1UmJFNEdOTC0tWDhDWnlRWmVFNGdGRXZ2WmFrYkRXTk5hOWd6SnBUNlNOTm5tcGtpMFZocGxaNGdzWmNmR29xQktZNF8wTS1WTmpIbkZ5QUlySXdsSTNjZkIzWUVCbHJ3X1A1QXhQVFFvNDJNa1pETmNKYjFwaGh0c1phaTNLcWRxT0E0ZEVWNVZWQ1VNZy5fTkN5eTNJSS1VV1VtWDB4UXhTVnNRLjJkbEFpUEpSa3NlenNVTEZocTE3ZmdCWm11XzBBaU5GUWkyTU8zMnlVanpEMjMxQlY0bHhwU21ZMmI1bGdsTXlYQzNtYy1PT2VmcVNseXdqMlcwTllOYzJKOUg4MzFHc0VCdXZ1SS1BWEQ3dzdocGRNTG5VaG5DQ0RUQTJYY0ZTZ2lXTWMzMFFISHUzRi1KcDh2VGU1QUk5R1ljelEzSFVPRjJOREpjRERoLU9CNFFJRlZWMS0zWEJkeS1uOWR5MjlSY0FwNEo4WHRPMjZxN2dJa3BDT1JxMT
 VuOXZHd3ViVlZhdGhfMlZwM3p1ZEJPX3k5SlFTVVYxMW1jZFVIQXNCVGxFMU5xYkZaU0lfX093NTl6ZktGRTVTMnZrYWl6a1RFbXFVQi1EcTVnMnMxQ05PcUdUNk1wQWNiSEtUNTNSajNZN2RlOFlBckZIMlNSZF9udUV6Q09PMnAxeFpFUjh4c2RIRjlDM1Nnc3ZRQzIzX3BfeDBIR1RfbWY5V3B4amZOWF9Bd1E5NWNLZ0JOdU1ENEZ1TTdWTmpKc1JaSGtvM2tNTlJ5N3BybkhhaVd5aHRiVV9ic0w3X3FRa1JGNEl3eGFzUlh6M3RtZzYyT2tCWl82MEMyRE11Q0pIZWtqSnI5SGJDeGp6Z1lGMjVmRDhDTk00YmNaRV9ma1Z4Y2lVVklWU2lvemREX3owTFBMY09paVp6dTNIWGIxekplZkJsVXduc1NBT0RZa2lWbjJPMjFOMHpkRGwwMjNPSnJTdWQycWo1UkEtVTlsVWRxU0w1QUltN1ZaMTFSVzh5clpkWXc4NFJTejVySldRSm1sVW54RzJHb3lMMTFaQkJacXY5bEJ5Wnd3SDN6ZGNDZWFRQWM0LVZJWjQ5NzBfTC1tT2paNUFwdXI4UERHVDIydkNKdEw1cVVaNGJabThBeXQ0NDFEX2o2cG16NzRUWWlIU210ZnlJcnNvRTMzbG9QM0xGdTFKMklXLXJTdk9HUElveEx1ai1ZMkNKMENYTk1lR0UyQVNhOEY5RmY3enhVLVRkbVZneWpfYi1EY05XUmVJZUMyTEF4OV9EWDY0QlRJV0pNSFc3a2plbjRkem9kajMzbjM1aFU0UUVmRVM0a2pmUUtMVENrYnRlWXliVUlQWmhaa3BDRzRpTVBQSVpTRVdqU2RMckl6NlRYN3FJZHFHcE1UYk9zeld3eWc2dzI1WTd4aDFvelY2RjJEOFpKR3FiZjhQZTVDRWtIcE5LeC1kNExUTzNsOWZlZVd6RFRwTzRnTWp
 BZ1RNdHBqdXRqT2xhSEYyN1JLaVNGWU82eFNQY0ZVb3JGMlZKRERlQUxZSk9Pb0JOMkhpalJ1Y0R5bWR3NUtzNHBZTmZvV3dCeHVnbjBPenJoNVFIS2Q3dWpoUll1XzhkLWd2RVNKQzNJY3JZWFI1aFhxaUp5WGVNMGtULWlnRUFQRFVmSXE0cjJiRW5iZ0RhdUZrN2syekZzXzZzeGZ4Ty1TNEp0alp2UkJia0lnZm1WdVB5OXZTQy02QUl0aEctMW5OUE9PNG1oak9ON2EzVUdzQVpvREg0T1RFczA3ajJMQ092VGdqX05PN1pJcEt6LWhyU0daSXdCdjlRdHJ5NjY4US1kTUpRZzAzRi1UXzZlX1htc1BWRWt1RWdaSzdnS092STNzdjk4Y0VVODFiVEZfNjQ3cmE5bjN6NHdnbmZwVE1lWEhMQ1JWeGpKbHJURmxJcW9wbkdZeHlQdm5iVXBzb3A2NktHbVAtTEpTeERjNlJJckpuQ2drbjN1OGN0c25NZWxuWHZSeGZFdFRsNnkyendUV3ZSdnVEcVR1UFphQXdNVmllbTdaaXZqNTdMYjNHT3RUcjBxQXNrMC15dHN2TkpmY19tYTEydVlUWll1b2RCM2ZoVFBITjFaclFoQzdiWDVHdXFDUFFDQXFuenJjT0lESDIweTFlZHAxam1ZdTFyZThPaG9yMDRiVWhLa2stcUVVdEVsZTFqYzFTckNuWkEyMlRZMFNVYkxkVm1hb2dyaUJfckpackVaM0tneGFaSjNnZ3FQd2NhSW0wNUVoMDQwYUpUa20xOWdzRzVCNEExQ2dDWHRMOGhUMFl4TmNneW9tT0dnRzd2Q2FzdW43WGhtdjJZLWROWVNrZzRZbzlfdkktWWlmZEp2MnhJVWY3eGFvS1RRRzY4NkNzaE0zTkVubFRWb1FjaWxjaXllaHc3RkpiMnYyTDFNV0tlamRWM2dPNjIyVjZ3QXV4MW9GdXJhdWZORzh2
 cnkyS2NwczFOUzBWeFJObU9mNDFkbFRhSkljUmFJM2tSbUg5UkpTakJZcnA1Y1ZzZWh5WGVaQXpnU2JzUlg0eGp6LURJSGVPa1dRS05HMlZvTnloZ3BZS05FVnlNN2dkdFBWTUo3TmlkVE9PM3BaYTBMeV9GaUhHLXc0dkUwTTR0X1ZpOFhvRzBFbWhJcjBWdmRvN0RGUXVUbmdoblRGVnpreEtyRlJSZzRMWkhCNzR2Z1BycTVTNGxTV2hlZGRfekRad2JVeUxJY1NXWmk3QzlpWDctczNHeGp2UjNGekxJT3NuSXUxVHpaQ3B4a0d4ZGkzU1VyS1c0NGlTaDM3eGNmaEpsNDVDcTQ5N1pQQmo1eVA0UmYwazVTS3djM1JvOUJoUXN0aUdzVk5qMlIzcmpHTHZfOEwtUHNxOG1IYTZKZHVvaEtRbEVQT1hYNzZ5aDdab05KUUZhemRNRWV3eVJNOGQ3eUZIcFc0M3RTZTA4Mi1BUmRjcW55OXFZRmJLMFJfV3dNTDlOQkFpNWxjQldUSms2ZHJXN1RPRmJ2eDFyZ0p5cUcza2w4TEdwRExheFNfaFhXZVRxSy1YS3pVRk9zNjA4WEp6U2NhVE1xay1QTVZIdkN5c3Vjci1mOFN3SF9wdks0bTNQYWprcGVOMjl3dmVZdUp1X1ZKZHlPNE9yY043cnRYVXR3VWNSblBzNUNXYWF0N1RfUWhnZ1VTdHBZczBJTlVuNXU2Rm5oNGVsUUxTTEhvdWZDdE9RekpDV0VVd3N2TWdkdkc2cEUzU2FZU244OFd6YzdMbGctZEVMeERLQXE1dmI1bXFleXAyem9hZFhJa20wWks5amlwdnBZdmQyRlFnNE50NF9nOUo3WTRoeVp3TjFWdXlqQ2YyUkFpMzJXZlNid1B4ZmdVdjhVVkktcUlKWjc5TjNQOTFnWnB4X2xxdF9aNFB0bzIwTTZqamw0MGkwUXRwMUdaRU5hbHoxN00zbFRBU
 l81WkY5Ql81dTIwN1FGbGh3UDYzbFRNMF8td1lCOVBzV2VtdGJUTEZYZmJFU0t6VGVzckVzQWwzQkVDMFotSndhMno3cEc3VHhvQWhON21hWDdKajVjbWtzdmJjVk05MENSNTVwbmtwOUM0Tm1BRWM2amw1dXRBSGlGOEdaV1A1V2lGVFFwVTBpYktXLUVycEMyblVvRVBmbFRPbVowM2lzaFNLbnZTSUFUQjBMSW95S1lhYm9tcU5NWkZhWDV5OWVjTGtFdmlmYS04dW8zRzNYSWFhQWk3TE5YRXpqQm9iZWlVSzBFeGJxaGd0VzNvbE85V1o1MGxqOWw5UXpGV3FWOGRiUThOeTdkdzRnT2wzNl93ZVNrbHJ3b19VVDA0Sm9Oc0IzOWFrUnJaWkdzaXJuamR1T0F4RWZaaXRLdHdTdkpZSzRtV0huSk5uRENMVlo2cVpzVG50NThjVjQ2cFY3T1FxckNpVnlQREU3Y1N0RW5neXhEbzRZdlpibDNrNndkaGxYOXAwZXNaOUdXbHNxcXlGVUJCc19QbVN2UUd6djZ3bDlWSnk4WnNKYmpIdlkwclZOUFJnN2FYTjlNOElsVWpia3B6RmdqY0VPZVVrZ1M5UFp5RURLYUw5U2NjeFJFbjI1OUR3MDFJZFJPS2U5Mnp3U1hSQUJlbVhBcVRaSGZPd1Z2VDBUS2JnWkwxcE5vb242NWRMR0hKZ2dYWmt6SjVHT3dvbFRkYkEwczVkaXRQZllxU3ZwQmpmVHpfQTZhTWl3bmFnamlET0QzT2doeTQxc1Q2UDdTWTFxanpfWkxjZ1puc1djWDlkOWc4TkpzZ1had184d2dUY3hRdW1TM3oxVTYxX2dlbndBNzNPaEs5MWl5YW90Z2ZySWNzOWxodm1taEcwRC1KX3lkQUxfdXNROWc0dHRlN1ptN0hMZDZOb1pCYnJFTkZ0ODRmejdJbjJxMXItM1lsYk9kMm1xRXIxZUdZMmtCTl
 h1eFc0XzlVZVFOZER5UHZPRFR0Ni1mR3FuMF9sd2dYOXJldUxsRzY1UjFKY29yMnczWmZBLWU3SEN3Y2tCTTBEcmhjZmwxdmhtcVY4WXpMcHBxUUhPa1F2YUpMNHE2ZG1ZS0thZmhGbXcxVk1qSnp5UWswUVNzazFWUGdzUmpta3l0YmpjZjRoenJNdVRMU0VQTGZVWGVPOEYzbEdLNE03bWlhblRPQ0xXSmRNWnc5dFlKSHVTQ0g3SjhZOUVwNS1XWTRBeUZlaFJfaDVSNHVYdlBPUmUzSzZQcWJibHlaMEJuclpCcDZnTUNvNVcwZkd5ZEdiQ1N6dzUzVndsY3FEWnJlb0p0Rk5pZFNzdTBtLUFub1g0SWxsSFFnYVB4SnlLYWRPSWpvalNKMnZTTTZCYXRkci1pR3VTbDJSZmswLXkyX3FFeDZRakNOQWFXaWNvM2RsS3VIY0h6TU13YzVXT1J4bzdweXdWYmtOUmpoOUVPZlkxSW51Tk11SjdfYWt2T0V5MGpMVXlCc04zR0hrTzlEUExFLTk2bVlIMWd6R19IbGQ5aVRpOWcxZTB5WjdBVkNEQzBoaVRZMXB5V0pVanpGVE91clJaYW5qOWl5MWdjcFdpeFVPN2xiWjl2aHFhdHg0VUh4VFRneS1IbUcydmRTYjhJbGl2bHNqLXVpM3dxUjBYeVNXRDFVYmVJUFVIZk15bTR2bXkzdkIyWEJKMEJnTF80bkx2VWQ2MEpFdXI1Z0ZOSUUtR0RSY0JwSkdPZXN4b1lyQktYU1I2QUd1UG84b2ptemFudUFIaF83OTI5OWg2aDdtN3JRZ0NxYzJ0Wjg1dU9YVHNzZzRYSW1kVjdCN3ZrcHRlUmt5WjZEQ1RFYW5GRmNvWEJzSThYMVFZeFFDRzgtdzltYlppTHNiRGN6bVV5Z3RiRkNQUXludjByclNiRzFUUWtmZnk4UGVfT0tRYkxSdWJNNG55dmZxWG81X21FcXA0T1d
 zMlJSMDhiSE9YTWpDU0FlYUwyaC1RRjg2MmRrLUNpV05ZSVVuUHhTYWkyWTEzeGVqVklwYkI1YkZzaVUzTWJmY2pyNnduRUVuMmhzWGx1aGpWVXFtUzNIOEZwZDFkS0pSa1lzM2NWZWRHTEhaRFZRM0hTWHlBWk1FbXNzX01kTUlGMFZhUjU0WTU3QXhhcnR5QUFmZy1OWWtkNVhtVkxPQWJnRFdCMzdrbEVPVEZCYXV4SGg4dXJjVk9neVF6Z1RNcTIwTWpEUzhzaDlZLUNHNUxSRHJiYVlRU2ZoR0VSYVFYcFpuVEdWX20tcDFpWU1zMEMzRFBJanMxSWIxZVR4X0lJbTFPRlBGOWcwWVJsbXFCdkx2bGtGeExqM0t2SGxQVEUwaUYyZ1JaMmN4NUMtckJGZ0dXaU1hRUQzdjcxTW0xQlFJeklaY1lfUUI5V3FsWEVaSmJWZHNZc0FmNm93eW9XckpVQUszTEswclRPaEdNS2VaUzlzUGxvZWU4T0x2OTluc2wxRUM0Z3F2MHJqdk9JQ0pVR0kwb1R1dXV5enhSbU41cHJtX2VycHNLbkM3QmRXV3VaLXRab0g0c2ZDeExiYVppeW8tQU1xdVRhMzB0ckFOV21rSUtuTHFubFRvcXJXZ1JiQjF3Q0hlVjA4WXR1ak9sQUdKc0dHRTRLVjc0X2QwSXZ2NXA3RUxQZlJJcU51cGVLdlpTZ0pxU19tQmU0eG5wTFZsWDhmaHRIOE9aSUxKQ25ZQUt5VHZyNGFoZG9jd0NrOE9JX0xVOG5wQ1Rpc1VFdEo1MXpON2dqUEs2eGhCazZ1YnNNeE9oalhNSjhUd01sWHZvMjcwSXdYV08wVm1lN3pGbnp2S3dnWjV0UlB4c1hwTjlySDBlLUxIZU9uNHIzWWtHeHlpRDFrMkUyM0s4ay02RmxhM2JwMV9DQktfdkM0VUhBU3NqQnJjd21kOHVvYzdJTDRsQmRfeldQbEtyUXp6bmxy
 ZVlMV2w3S1RmdG5ELXF0STlLMlFpWm9Ib3E4anZSYUJTTjZqUTk3RXhEb0E5dUk1LVRFc21UYlpCV3pGemdoOS1mbXBKZmQ1R3VNUXVhblJDN2VPbzh4bkJrVnI2UVVnZjVhYzV6Um0zc1ZBaktBVDJ5djc0dTNyOEJjUEJMcTBsc1gwTUpza3FlNEZhN193NXB5Q0Y4dS1RbVFkN2dmeUdPSW1OdTgySGJPSk5yMHg4Vm9NZU9uUExsVUhyY2cxNk43czY5ekU3SEM2UExpcHJobHdmY2JvMXlaZDZYVUxYNGI5MXJ4ME5SU0VpYURISGV1QS1LNWFQb1F6VVZiSFJ0cExvdHpwTEFTZkhwMWFhSEoyakRQUElfcVllbzkwWjVrR3RiV2plSTBYVDlzMy1TMk5pcW16Z2Q5WEMxNEJaUTM0UWpNdksyNUpJYXpqWW5FdGQzYUFYRWFZNU9CdGZ5R2NIcV96UmRaZlVQdDdDNk1LTFdRbnpzTXNWZHJ4cnpCcWRMMVV0NzlIQnZ5M3RlWDZ0RmJuYjR2ZkgxY3NZUl82a041T205VndHelRZYWNGM1dDTkNuOHljMk13N1Y4b25ZOXFLU0VLS1hRYk5KYlB1cEJsT29qLV9tV1drTkdmSy1TUHJoRmFGNF9LaDFTd25TelBydHRVVU9WMXg4ejNmUVFXZml5eVllcGd0VHVGSEZheHE0YXNCUjRQVndfUnBJN3c4QTNiSGR5ODQteWprZU0wU0k4WE5CdkRmVThRXzA2aVZjWkg1UWhwU2VENVpZNWotcDNzN3c4X2MtRXo3RHRZaHgyQzducWU2OFNVYmt3dmd4d2RUOFhaYzcySTJwSUFwYklPTzN0SEFIVmpvVHdVX3dsSHctSVZKbzZfSlBvRE5JbEdZcHdDZ21oMV9rb2FCLXFvMGdQd0UyeG1sRmdNeVVCd3lfWHNEdVRUcVJfT3pYVHBQbWdhTWNZMXJldEgzVjBDZ
 3BHaTBqYVZoN2NJSUpoVWNRcXRIVHl6S1hDTWVMRVBXYzJuVV9oXzB5U0tTanJMUmR1cHpkMTZ6V2sxdTRzdDRDak9CR1AxbloxVU14X3lGQ3ZsVVlESGY5OHhBelJNbUg0c1YxMnVMYmlCS2l0eTEwSG83X2N6T0htQ09LeE1oaFlhRmVrS19veUU3X3pWbTRjUzhHbEJiMUo2UVZMeHpGMXlORnlqeHdITEtnNURXUzN1T0JfSGpNdHlMOHh4WXhNR2FjNTh1X2g5ZEM5QThtVGJ5bEF6Wll6eTUtU3pvSVJYZHhVOGtBN1c0QzFWYmI1VGgyVHZmemF1Vk1mNVg0SWc1WTU4NzMtd3oxNVpHZW5xU3JreFVqU0tVUWVlZkI2eEg1aGtKeWs1cDZWY1JJNzF6SkVEVEU2LWZHSGsxTlNRd2QtS2tTaWlwMjI2d0JCOHZSVWdGQ1VZcy1EZC10TXF1aDdKZjlaRTU5amNzR0ZkTDJhamFRcjc4Z21VZEFVYS1HRHpQeHp3YkM0b1FKS29ObkNEZGc5WV94S3NHeEtDWnRVT1VjM0Z4MlptZFpfM292ZGExaHdyVDZpYVJLM0MxZnh0ZVpheE9IWkNvdW5MeU8wZUkzZ1Nnd2dkVERxODZ3TzY2U3pHdGRxYmo0bGZrT3NkRUYtUDNhQU1yOGNuclh3b2NOdGVpaVJ0YnVqLXhfNlVQUk5hWHJCV0lHRk1Mc2x3b1VlRXE1ZUpuOUhSYmdvd25vU3psOUdDWWdtdnRsb1ZIVHFVLXpNWk9TcmxPejA2aU1ZZjBjakliUDJtdHUyWHlDS3dkRnFsZHJqUWs3VmNUUEJkczluRjR2Z3lmOU1nSFVTeVpHTHFubHNtdG5ER1p4VTN0UmR1eXZfTFRLcDgxYVVQVVprb0EtTkMzdEFncHdQbUtodzVnY3M4U19aSC16VVNFd1BjLVR6NGtJSzhrSFVxQ2ZFY0pfMmhpX2RTWHRKbF
 B3TG9EeU95R1hTWkp5ZGIzb2hjblk3Z3RneGpQaU82Vmlwd1NZMXRVVUV1YmFKbHkzTGFwRjN0cXlEZXBBdHMxc2JDdzNSSm1HcE92WjlfaTk5SXZ6WjY1WDZPSDB1YUpDTWl6bFpzdGQwZ1FRMXl2ZTNQRDRaVHZPdzlMMm9Na0ZDQlFvQzBUalU5b0tPTHNpdlAzbTZOWjROLVpiaWFaNTIxbWU1ZjBWV1loRkN3RENxajRyUDZ5WmloOXVPTW5rWnNhZ3BtS0RlaVV6d1RpaENKdlRkZnBfbG1GQ3cyc0Jyd0lIVWJfdkxWY1RWNDd4NVNwSnhuS2dpWHpZUG8weElnYnY1bmZGWTJvM1NBWkZpSlNlNEJQbmFsX2FQLUFnNDdWM2h5NmNzT0xCM3l0VlNCRDdlNjFpU1VGWVhBUmZJVEVXa0VRaHBIWWJyRTlvemdldzdOLU5HaXdtWndOUy04SUFSbmRFS0tXSXRXb01fMllXVmYxS1ZoME8xQ2wwR0ZDV2NCNzFDLWxMazVJbkpKUm5Wd2dPQ1M2YUFKaEM2T2pIVVYydTR3TTdndFI1c1Y2Snk1NUxQcjFUbVpZQXAyVFNSMG0zUWMyN0ZKRnhxaFU2R20tZGtVNXZKbGtnSjUwY2xTUVVGcVl4Z0pDX1hSdWVpOXNzdkNmbnZVOW1ZSEFQZTU2Q2dXNWFiVGhSOEJCcTc2aTlxUjBlRVV4eFVWUUtCemFhVlB3TmVqaFRVYnpWcHZnNGlqSFRocFBlRzdDZ3hwQ00zT0pCaHFnS2k3RzVTeHFHYjdNVEhoclp2Q3I2WHZtZGdFc3NxWW9RdUQyYUQ4TlhjdVU0Mm1NVGwyZS1sY2pwU1E5R29hdlRHSjFCeFp2YWlYZzRNS1FGUjBjRDQzYkxsaXo2Y2NCeEEwZnJTU2dqbUhRNERxdHhjYkFiNFlPTDFlYkFQNFNSQnJwa3hGQW5fc1l6ci1aR0F0R0l3R1JfUHR
 RbjVLQ05yaXBueDRITVBmS2UtTHg4MzBIWFNxVGV5c0hRbGtuRlRSeFdwLXdNcUxPMlFhTHJnMlUzdnBDekloRmh4dG1tWnpPSE8zZmY2YTAySk9BaDVDek9GcG9oTDFXakl5a1RMd0dNMDZMQ25uNmhGeDVOZEhmVTlqaTdKNGZuT2RkcVh2ZnZ4TDhSN0wtM1d6SThIUVI4TkRHRzl6ZGtHZDUyQVlkNTBqUTZPN29qNUdkZldGMDdQTVY3WWFETjhGc1YwT19wZDM5bFpiUnM0SlV1Y0xWMzBXNGpqVGdselZGeXBaZEFxQXU0d2pWTVd5T1I0X1RSMnh6YW0wemx0ZXc1bm01TUk4NTlZYVhCVE95bkV5T18yRndDR2hzdmxQR2t5SHZuc050NFVya3pjRGswX0JaYUlYYWFNbUhxMUJQUWdiR0d6bUxNV0FXcFY0OUszdnBkN250WHFBZEVyN25VUnVpS2RSckVTYnpEUnAxclh2NExOMUdGNXRnRUFCZFhwYTVQVG9nVDM3cHUwb1BNNW5FZXFDeklRbmtjemMzUVk5SEZwY1J6bWFmbV9fSngxRFd0ak5qR1J0cVM4aHVUcVNKOG5ORl90ZXZsV2dwOU5uZU9KSUZwZkVMMnhYMTc2dnkyQ1FONTBFRzZZWmM4dXZreHFNUmk3OFNjdENEeXQ0WS5Sc3FFM1dad19XclIxRmtQc1RtWW1B"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultcreate.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultcreate.json b/azurecompute-arm/src/test/resources/vaultcreate.json
new file mode 100644
index 0000000..604810e
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultcreate.json
@@ -0,0 +1,26 @@
+{
+  "id": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourceGroups/rg-vaultapilivetest-jims/providers/Microsoft.KeyVault/vaults/kvvaultapilivetest",
+  "name": "kvvaultapilivetest",
+  "type": "Microsoft.KeyVault/vaults",
+  "location": "westeurope",
+  "tags": {},
+  "properties": {
+    "sku": {
+      "family": "A",
+      "name": "standard"
+    },
+    "tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
+    "accessPolicies": [{
+      "tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
+      "objectId": "5a7f4cb9-ce9d-4b31-87ce-f61083c4b0ea",
+      "permissions": {
+        "certificates": ["Get", "List", "Update", "Create", "Import", "Delete", "ManageContacts", "ManageIssuers", "GetIssuers", "ListIssuers", "SetIssuers", "DeleteIssuers", "Purge", "Recover"],
+        "keys": ["Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore", "Purge"],
+        "secrets": ["Get", "List", "Set", "Delete", "Recover", "Backup", "Restore", "Purge"],
+        "storage": []
+      }
+    }],
+    "enabledForDeployment": false,
+    "vaultUri": "https://kvvaultapilivetest.vault.azure.net"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultcreatecertificate.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultcreatecertificate.json b/azurecompute-arm/src/test/resources/vaultcreatecertificate.json
new file mode 100644
index 0000000..15b7aa6
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultcreatecertificate.json
@@ -0,0 +1,11 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/pending",
+	"issuer": {
+		"name": "Self"
+	},
+	"csr": "MIICszCCAZsCAQAwIzEhMB8GA1UEAxMYbXljZXJ0aWZpY2F0ZS5mb29iYXIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArrIwtQO60BI1vUkS/Vx0TQ5dBLjWBFfQFUHABJoKXCeloLrHWrWnhaxyj5jvEVGYF5OLBNeHd6PR43bmHKnzq3vhQXUA1sKBRxAJavSM9a+MKBpN39aKvSnqRNdnETE8kwNteIpbmDVMe18UnGtyhRbMKqJ73HpGyyRdiD8nTS9F65SCRQlKALNz0Vi3z52Loo6kRoZPAfcRkDAbbg7JxIuMEEcbrBR0dScR0m2OucYtR3PQ7PUQMXSsLwZmGAu1e/KuqjTNC6XpxRpWSTHf3kS1Q4LjNXde8sk1/5Xovzo/MlVQ7L2tt4pVK79ZkeePbL9ZSKsTc3Thi7G+o8pCewIDAQABoEswSQYJKoZIhvcNAQkOMTwwOjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBABoDgWVU0DqfhKsujIa4gUHyZKvRWhms0reqb4Ld9GkF4O6TV+TxibBUZRW3SSVvA+po8G7aX+E+si0BfQiwM1PutcK0f5WuYMiEkQ6xaiDhIblrouCYRCTiYmmt2+8iuKAtDNqgqMJjViGXUKcGQgz7UTEJY/LLlgxW2kDyfEJOhGls40AT7tuXAjZ6QPLT9vAdQ8B0L0JNzJ6lJcDe7KattWonjQ4cLZ7xvY0SwUyvabui1UkOFze/EEkLwnJjigvfWkzhoJS7j0Cp3nI08c5zd/rQGq1XNVb9plnjtQP0kwNVQdHVeTug9rqZCyuS3jqwa1prrXkZJyufMmuNSV0=",
+	"cancellation_requested": false,
+	"status": "inProgress",
+	"status_details": "Pending certificate created. Certificate request is in progress. This may take some time based on the issuer provider. Please check again later.",
+	"request_id": "550fcfd2c33440aea6cd354658f91ddb"
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultcreatecertificaterequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultcreatecertificaterequestbody.json b/azurecompute-arm/src/test/resources/vaultcreatecertificaterequestbody.json
new file mode 100644
index 0000000..c85aeb1
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultcreatecertificaterequestbody.json
@@ -0,0 +1,21 @@
+{
+	"policy": {
+		"id": "myCertificate",
+		"issuer": {
+			"name": "Self"
+		},
+		"key_props": {
+			"exportable": false,
+			"key_size": 2048,
+			"kty": "RSA",
+			"reuse_key": false
+		},
+		"lifetime_actions": [],
+		"x509_props": {
+			"ekus": [],
+			"key_usage": [],
+			"subject": "CN\u003dmycertificate.foobar.com",
+			"validity_months": 12
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultcreatekey.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultcreatekey.json b/azurecompute-arm/src/test/resources/vaultcreatekey.json
new file mode 100644
index 0000000..470007a
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultcreatekey.json
@@ -0,0 +1,15 @@
+{
+  "key": {
+    "kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/f5cfaa4b90a34710a646af83636a5c1b",
+    "kty": "RSA",
+    "key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+    "n": "zattdXaoaTAnEDPv38dpgkLSuVp56_7TNczuyBGy3GOF62LgLEId1i7You5R4SGAXJDVDWBVAFIcbw3ppgbn-DgCf4QbAWWREQUOvPNhFvm78Ey6tewofP5jyrCDeSBkjlXC5lRgd8XtVXv0JvNtOU_GbTLMVAGOwPE-0nZWXaD__nkO90AS_2D1tDywcZ7vKix9WjkjYTmY1CEw06-vsQJSYSaaL2M5MmE-S21sgoGZUv7a0jHxDR2rEX3okFoW0sjynz6yxCZtYUmUyDMpWdTIaqKu9ZhfxZPtb6T9E8yAStvma0M5xc70gfOj1LJRK8mMhLmB4lh0POj-2a4fBw",
+    "e": "AQAB"
+  },
+  "attributes": {
+    "enabled": true,
+    "created": 1509314506,
+    "updated": 1509314506,
+    "recoveryLevel": "Purgeable"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultcreatekeyrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultcreatekeyrequestbody.json b/azurecompute-arm/src/test/resources/vaultcreatekeyrequestbody.json
new file mode 100644
index 0000000..bfb19a2
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultcreatekeyrequestbody.json
@@ -0,0 +1,7 @@
+{
+  "attributes": {
+    "enabled": true
+  },
+  "key_size": 2048,
+  "kty": "RSA"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultcreaterequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultcreaterequestbody.json b/azurecompute-arm/src/test/resources/vaultcreaterequestbody.json
new file mode 100644
index 0000000..0b0742d
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultcreaterequestbody.json
@@ -0,0 +1,21 @@
+{
+  "location": "westeurope",
+  "properties": {
+    "tenantId": "myTenantId",
+    "sku": {
+      "location": "westeurope",
+      "name": "standard",
+      "family": "A"
+    },
+    "accessPolicies": [{
+      "objectId": "myIdentityObjectId",
+      "tenantId": "myTenantId",
+      "permissions": {
+        "certificates": ["Get", "List", "Update", "Create", "Import", "Delete", "ManageContacts", "ManageIssuers", "GetIssuers", "ListIssuers", "SetIssuers", "DeleteIssuers", "Purge", "Recover"],
+        "keys": ["Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore", "Purge", "Encrypt", "Decrypt", "Sign", "Verify", "WrapKey", "UnwrapKey"],
+        "secrets": ["Get", "List", "Set", "Delete", "Recover", "Backup", "Restore", "Purge"],
+        "storage": []
+      }
+    }]
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultdeletecertificate.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultdeletecertificate.json b/azurecompute-arm/src/test/resources/vaultdeletecertificate.json
new file mode 100644
index 0000000..eba51a6
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultdeletecertificate.json
@@ -0,0 +1,58 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"sid": "https://kvvaultapilivetest.vault.azure.net/secrets/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"x5t": "K7HXO6YIK6xwCX8W1InUKsJV9Rk",
+	"cer": "MIIDTDCCAjSgAwIBAgIQVA+XomvgS56ybBWv2MnacjANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDExhteWNlcnRpZmljYXRlLmZvb2Jhci5jb20wHhcNMTcxMDMwMDY0NDI3WhcNMTgxMDMwMDY1NDI3WjAjMSEwHwYDVQQDExhteWNlcnRpZmljYXRlLmZvb2Jhci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCusjC1A7rQEjW9SRL9XHRNDl0EuNYEV9AVQcAEmgpcJ6WgusdataeFrHKPmO8RUZgXk4sE14d3o9HjduYcqfOre+FBdQDWwoFHEAlq9Iz1r4woGk3f1oq9KepE12cRMTyTA214iluYNUx7XxSca3KFFswqonvcekbLJF2IPydNL0XrlIJFCUoAs3PRWLfPnYuijqRGhk8B9xGQMBtuDsnEi4wQRxusFHR1JxHSbY65xi1Hc9Ds9RAxdKwvBmYYC7V78q6qNM0LpenFGlZJMd/eRLVDguM1d17yyTX/lei/Oj8yVVDsva23ilUrv1mR549sv1lIqxNzdOGLsb6jykJ7AgMBAAGjfDB6MA4GA1UdDwEB/wQEAwIFoDAJBgNVHRMEAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAfBgNVHSMEGDAWgBRnlX51KtyJ/m/V8I/3il4cAW/HOzAdBgNVHQ4EFgQUZ5V+dSrcif5v1fCP94peHAFvxzswDQYJKoZIhvcNAQELBQADggEBAAbSFuMRMbXyH80iA/jU7vuUCYe0Ra/wTTB1qVHTBuqQ/W8RI01mdqI9+GAPOTyN94XPPYVpSz9ZQ3P0/dhgcsahW5bZQkC0CcUSE5R7JUOKI5Up6n8zZM/unHlC6ZcEpNA/scObPKhQXdZayxgf2/p30bii4CiyS7ADEH92xMnzo1Eu9Dckxh1MRDypfxMY9YIzggks
 iY78BxoNsRDyxNjeRHVUxAIJ3n9TUv+WG31r7rMOIs6ZPsWc96AzUHHAZREVTEh2kiKKIenbMXn1tCpF6/GJKGfp7rt5ObUoQAlnn7kgAceteKZHEMgRZ4c4EQq+yqBw3hJrz4dOabJcmcU=",
+	"attributes": {
+		"enabled": true,
+		"nbf": 1509345867,
+		"exp": 1540882467,
+		"created": 1509346467,
+		"updated": 1509346472,
+		"recoveryLevel": "Purgeable"
+	},
+	"tags": {
+		"selfsigned": "true"
+	},
+	"policy": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/policy",
+		"key_props": {
+			"exportable": true,
+			"kty": "RSA",
+			"key_size": 3072,
+			"reuse_key": false
+		},
+		"secret_props": {
+			"contentType": "application/x-pkcs12"
+		},
+		"x509_props": {
+			"subject": "CN=mycertificate.foobar.com",
+			"ekus": ["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"],
+			"key_usage": ["digitalSignature", "keyEncipherment"],
+			"validity_months": 12,
+			"basic_constraints": {
+				"ca": false
+			}
+		},
+		"lifetime_actions": [{
+			"trigger": {
+				"lifetime_percentage": 80
+			},
+			"action": {
+				"action_type": "AutoRenew"
+			}
+		}],
+		"issuer": {
+			"name": "Self"
+		},
+		"attributes": {
+			"enabled": true,
+			"created": 1509346452,
+			"updated": 1509346474
+		}
+	},
+	"pending": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/pending"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultdeletecertificatecontacts.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultdeletecertificatecontacts.json b/azurecompute-arm/src/test/resources/vaultdeletecertificatecontacts.json
new file mode 100644
index 0000000..ca89576
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultdeletecertificatecontacts.json
@@ -0,0 +1,8 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/contacts",
+	"contacts": [{
+		"email": "foo@bar.com",
+		"name": "Foo bar",
+		"phone": "867-5309"
+	}]
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultdeletecertificateissuer.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultdeletecertificateissuer.json b/azurecompute-arm/src/test/resources/vaultdeletecertificateissuer.json
new file mode 100644
index 0000000..73421fe
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultdeletecertificateissuer.json
@@ -0,0 +1,21 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/issuers/globalsign01",
+	"provider": "GlobalSign",
+	"credentials": {
+		"account_id": "imauser"
+	},
+	"org_details": {
+		"zip": 0,
+		"admin_details": [{
+			"first_name": "Admin",
+			"last_name": "Guy",
+			"email": "adminguy@certsforme.com",
+			"phone": "867-5309"
+		}]
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509346474,
+		"updated": 1509346479
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultdeletecertificateoperation.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultdeletecertificateoperation.json b/azurecompute-arm/src/test/resources/vaultdeletecertificateoperation.json
new file mode 100644
index 0000000..800f399
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultdeletecertificateoperation.json
@@ -0,0 +1,11 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myTempCertificate/pending",
+	"issuer": {
+		"name": "Self"
+	},
+	"csr": "MIIEtzCCAp8CAQAwJzElMCMGA1UEAxMcbXl0ZW1wY2VydGlmaWNhdGUuZm9vYmFyLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMmt2TbL1ndbSggTwx2l3k/ZUzt0IGO/FMB/oqpmc5izy2KGi0/uSoEdFA9cSqfctL3FGx2J1cFVTz287cvLB8HB3A4svAoPnKsZmKpXuYbF4fK2wQGXm/iNk+JVq1KL0lfoqW2g52lHDM85XURMn8YCkAGIKeTlOVyEn7EMBuBumcJbszj0g56Ij+VKmxoua/Ja4ONmIGsKdyZRBEuvFQ1GTnJUvCWHwyo1pT0M5EY/VL9ikc283DSvpQcfvNelQgQfWCpTRX1Q7nTUHk14DD4d/Y6OdbjcVuqE0Jdqdw6MXfU2zrkPo/nZBf5GHsUChiaxzVeEafPjWKvqVDzhEYXpmMB5SDAELaQtV6PoX+kxcjAO4K//BQtwneHHVF/Sh+7ke3nNUlSf4Mjn541wS7LdkBDOlTnKdYu+DhfbdkRD4E9LPiDduWDWHZs051uFBecR93JaZmX2b376RORQygDkBRga/MNENoEEnsz4zmoMYCGspZhRXEC9Uts1hzYEtwM1hyLqJlfadX/sct20N4JkhDkM8NG2V43R8jcnKFmzjfv6Yc1tuiQ1GQpYNFPJWh+fakAZkt7IwYsvy1CQg92Yvi3ne9zRTBn00enDpBTWaGCZ84gYYaT7Yfyo7/WRTjinYt6R0+u8l0AmZb0xkgxEACIQoyrg+oWQZI4YrneRAgMBAAGgSzBJBgkqhkiG9w0BCQ4xPDA6MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAgEAr8RMKLLpGG31Mq4Dor6Tf11AoiHCLH33MUqblF1VfDiw0++qBZ1dgm0D
 +uzQph/bZ6jKe/PUWpS1bErfaOt3iaVNOHom8jP/U3kZiYWvc/YHetU03prm1Qb+izNZA97NNeZRsuCXMAkNAHQnXa/rz/zG6BmGXFigh55wglX6aB8PnfKZb7N6RCct8BsKSV8uPpxXzRWPKrv7TA2RKfMifUD/Dzt7FSDuYJ8FGkvQNX012RXb2DqHp8tbZgUSj7iXdoZMZ1jfwlh6P61yhfItbF4SYvtBd9PTWIxP6SkCfDjJ7f0/ofwoV2DvAiwfH7URdQIMC+B8dPCqbjya3Ku+B2fWXXhdG7gJqa1zRY066QTIsHwfwd3WbeLQxCcBUEQUG0u23gj9fDX81fvKsgHtN9Nod5wXsdLtjjpHpJQJlDanII4H3fvDxAOlqSnxxEhjL9uA3YXUERMGGjExXA5kCOqKrdfGT5x4yosuNutylvF8YYn8r+mvMgegtVl8XmKnyP+uESSE2krVVmnSM2gveq7ILxBvanq70LmQVeYQB4AlLtUsxPUPIPiOryDI39KrlqWKdl3/oC7Gx+WbVzXxs37NEwt/tx8E+r1Nq/jRFxP0QlyyUdjpiPXjUpuCdn4y6erpCuahbMP+CZNCNgeEh1v2pNljuaGCIB+VA2Fz/oU=",
+	"cancellation_requested": true,
+	"status": "inProgress",
+	"status_details": "Pending certificate created. Certificate request is in progress. This may take some time based on the issuer provider. Please check again later.",
+	"request_id": "32051e4e4ac947c5b9ad1b6737bee7c0"
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultdeletekey.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultdeletekey.json b/azurecompute-arm/src/test/resources/vaultdeletekey.json
new file mode 100644
index 0000000..9ca672e
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultdeletekey.json
@@ -0,0 +1,15 @@
+{
+	"key": {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/1374543b3de34500a97d075991ee3893",
+		"kty": "RSA",
+		"key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+		"n": "tY2pzXPfU7NFYCWvZB1gJNAetkgJ7Qi75lTVOzVns9KjFFo6e_F9GSETZbAYl5oMwfLtdqQqT5fxzWDk0sYlz09HXvCCoYmbzobd3gJ6-WLAqhtCbBikr5HAIlCzy_UqKT--WhEw8AT_EJFBPIY9xNktqnaNZuRBmjmXinzT02qUmBZRsAdJmaYfG9IZSmToOkb54OytI5TreWN0JvceoQ3GSeFLMC5PUmXP6HmZliOzBBHWnXNq3H7a3qfWV3rxT2QpbrIuz18ZqOVp7o5868kN8knKytVcqEzmdiQUdabkqbrwuh-z_IEre9AqTfw6OjUUmLjs4lyKcpWLYFh8KJuML1ub-8u0VgNGwczUZ7aAld1iwGMsoMmQfMRDOnv-9pqtY-y40ZWpBGXpzFV-IvtKHnqQk_vWqowpE8xwx7yZ74z9XNgS9TmkVpcC-ONbEfNE1sez0Zf-RZ9eOm_7WSxxH6OJYtJI7wotBXYoy1bJaqo7mgHs1IUOFhSE-Evj",
+		"e": "AQAB"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509335925,
+		"updated": 1509335925,
+		"recoveryLevel": "Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultdeletesecret.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultdeletesecret.json b/azurecompute-arm/src/test/resources/vaultdeletesecret.json
new file mode 100644
index 0000000..bff4c9d
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultdeletesecret.json
@@ -0,0 +1,10 @@
+{
+	"contentType": "aNewSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/8c418537cbc948539ea2ac12c0bfcfb4",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335944,
+		"updated": 1509335944,
+		"recoveryLevel": "Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultget.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultget.json b/azurecompute-arm/src/test/resources/vaultget.json
new file mode 100644
index 0000000..46de8b9
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultget.json
@@ -0,0 +1,26 @@
+{
+  "id": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourceGroups/rg-vaultapilivetest-jims/providers/Microsoft.KeyVault/vaults/kvvaultapilivetest",
+  "name": "kvvaultapilivetest",
+  "type": "Microsoft.KeyVault/vaults",
+  "location": "westeurope",
+  "tags": {},
+  "properties": {
+    "sku": {
+      "family": "A",
+      "name": "standard"
+    },
+    "tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
+    "accessPolicies": [{
+      "tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
+      "objectId": "5a7f4cb9-ce9d-4b31-87ce-f61083c4b0ea",
+      "permissions": {
+        "certificates": ["Get", "List", "Update", "Create", "Import", "Delete", "ManageContacts", "ManageIssuers", "GetIssuers", "ListIssuers", "SetIssuers", "DeleteIssuers", "Purge", "Recover"],
+        "keys": ["Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore", "Purge"],
+        "secrets": ["Get", "List", "Set", "Delete", "Recover", "Backup", "Restore", "Purge"],
+        "storage": []
+      }
+    }],
+    "enabledForDeployment": false,
+    "vaultUri": "https://kvvaultapilivetest.vault.azure.net/"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultgetcertificate.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultgetcertificate.json b/azurecompute-arm/src/test/resources/vaultgetcertificate.json
new file mode 100644
index 0000000..31e982f
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultgetcertificate.json
@@ -0,0 +1,55 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"sid": "https://kvvaultapilivetest.vault.azure.net/secrets/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+	"x5t": "K7HXO6YIK6xwCX8W1InUKsJV9Rk",
+	"cer": "MIIDTDCCAjSgAwIBAgIQVA+XomvgS56ybBWv2MnacjANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDExhteWNlcnRpZmljYXRlLmZvb2Jhci5jb20wHhcNMTcxMDMwMDY0NDI3WhcNMTgxMDMwMDY1NDI3WjAjMSEwHwYDVQQDExhteWNlcnRpZmljYXRlLmZvb2Jhci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCusjC1A7rQEjW9SRL9XHRNDl0EuNYEV9AVQcAEmgpcJ6WgusdataeFrHKPmO8RUZgXk4sE14d3o9HjduYcqfOre+FBdQDWwoFHEAlq9Iz1r4woGk3f1oq9KepE12cRMTyTA214iluYNUx7XxSca3KFFswqonvcekbLJF2IPydNL0XrlIJFCUoAs3PRWLfPnYuijqRGhk8B9xGQMBtuDsnEi4wQRxusFHR1JxHSbY65xi1Hc9Ds9RAxdKwvBmYYC7V78q6qNM0LpenFGlZJMd/eRLVDguM1d17yyTX/lei/Oj8yVVDsva23ilUrv1mR549sv1lIqxNzdOGLsb6jykJ7AgMBAAGjfDB6MA4GA1UdDwEB/wQEAwIFoDAJBgNVHRMEAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAfBgNVHSMEGDAWgBRnlX51KtyJ/m/V8I/3il4cAW/HOzAdBgNVHQ4EFgQUZ5V+dSrcif5v1fCP94peHAFvxzswDQYJKoZIhvcNAQELBQADggEBAAbSFuMRMbXyH80iA/jU7vuUCYe0Ra/wTTB1qVHTBuqQ/W8RI01mdqI9+GAPOTyN94XPPYVpSz9ZQ3P0/dhgcsahW5bZQkC0CcUSE5R7JUOKI5Up6n8zZM/unHlC6ZcEpNA/scObPKhQXdZayxgf2/p30bii4CiyS7ADEH92xMnzo1Eu9Dckxh1MRDypfxMY9YIzggks
 iY78BxoNsRDyxNjeRHVUxAIJ3n9TUv+WG31r7rMOIs6ZPsWc96AzUHHAZREVTEh2kiKKIenbMXn1tCpF6/GJKGfp7rt5ObUoQAlnn7kgAceteKZHEMgRZ4c4EQq+yqBw3hJrz4dOabJcmcU=",
+	"attributes": {
+		"enabled": true,
+		"nbf": 1509345867,
+		"exp": 1540882467,
+		"created": 1509346467,
+		"updated": 1509346467,
+		"recoveryLevel": "Purgeable"
+	},
+	"policy": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/policy",
+		"key_props": {
+			"exportable": false,
+			"kty": "RSA",
+			"key_size": 2048,
+			"reuse_key": false
+		},
+		"secret_props": {
+			"contentType": "application/x-pkcs12"
+		},
+		"x509_props": {
+			"subject": "CN=mycertificate.foobar.com",
+			"ekus": ["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"],
+			"key_usage": ["digitalSignature", "keyEncipherment"],
+			"validity_months": 12,
+			"basic_constraints": {
+				"ca": false
+			}
+		},
+		"lifetime_actions": [{
+			"trigger": {
+				"lifetime_percentage": 80
+			},
+			"action": {
+				"action_type": "AutoRenew"
+			}
+		}],
+		"issuer": {
+			"name": "Self"
+		},
+		"attributes": {
+			"enabled": true,
+			"created": 1509346452,
+			"updated": 1509346452
+		}
+	},
+	"pending": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/pending"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultgetcertificatecontacts.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultgetcertificatecontacts.json b/azurecompute-arm/src/test/resources/vaultgetcertificatecontacts.json
new file mode 100644
index 0000000..ca89576
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultgetcertificatecontacts.json
@@ -0,0 +1,8 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/contacts",
+	"contacts": [{
+		"email": "foo@bar.com",
+		"name": "Foo bar",
+		"phone": "867-5309"
+	}]
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultgetcertificateissuer.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultgetcertificateissuer.json b/azurecompute-arm/src/test/resources/vaultgetcertificateissuer.json
new file mode 100644
index 0000000..dd08fe9
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultgetcertificateissuer.json
@@ -0,0 +1,21 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/issuers/globalsign01",
+	"provider": "GlobalSign",
+	"credentials": {
+		"account_id": "imauser"
+	},
+	"org_details": {
+		"zip": 0,
+		"admin_details": [{
+			"first_name": "Admin",
+			"last_name": "Guy",
+			"email": "adminguy@certsforme.com",
+			"phone": "867-5309"
+		}]
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509346474,
+		"updated": 1509346474
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultgetcertificateoperation.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultgetcertificateoperation.json b/azurecompute-arm/src/test/resources/vaultgetcertificateoperation.json
new file mode 100644
index 0000000..15b7aa6
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultgetcertificateoperation.json
@@ -0,0 +1,11 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/pending",
+	"issuer": {
+		"name": "Self"
+	},
+	"csr": "MIICszCCAZsCAQAwIzEhMB8GA1UEAxMYbXljZXJ0aWZpY2F0ZS5mb29iYXIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArrIwtQO60BI1vUkS/Vx0TQ5dBLjWBFfQFUHABJoKXCeloLrHWrWnhaxyj5jvEVGYF5OLBNeHd6PR43bmHKnzq3vhQXUA1sKBRxAJavSM9a+MKBpN39aKvSnqRNdnETE8kwNteIpbmDVMe18UnGtyhRbMKqJ73HpGyyRdiD8nTS9F65SCRQlKALNz0Vi3z52Loo6kRoZPAfcRkDAbbg7JxIuMEEcbrBR0dScR0m2OucYtR3PQ7PUQMXSsLwZmGAu1e/KuqjTNC6XpxRpWSTHf3kS1Q4LjNXde8sk1/5Xovzo/MlVQ7L2tt4pVK79ZkeePbL9ZSKsTc3Thi7G+o8pCewIDAQABoEswSQYJKoZIhvcNAQkOMTwwOjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBABoDgWVU0DqfhKsujIa4gUHyZKvRWhms0reqb4Ld9GkF4O6TV+TxibBUZRW3SSVvA+po8G7aX+E+si0BfQiwM1PutcK0f5WuYMiEkQ6xaiDhIblrouCYRCTiYmmt2+8iuKAtDNqgqMJjViGXUKcGQgz7UTEJY/LLlgxW2kDyfEJOhGls40AT7tuXAjZ6QPLT9vAdQ8B0L0JNzJ6lJcDe7KattWonjQ4cLZ7xvY0SwUyvabui1UkOFze/EEkLwnJjigvfWkzhoJS7j0Cp3nI08c5zd/rQGq1XNVb9plnjtQP0kwNVQdHVeTug9rqZCyuS3jqwa1prrXkZJyufMmuNSV0=",
+	"cancellation_requested": false,
+	"status": "inProgress",
+	"status_details": "Pending certificate created. Certificate request is in progress. This may take some time based on the issuer provider. Please check again later.",
+	"request_id": "550fcfd2c33440aea6cd354658f91ddb"
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultgetcertificatepolicy.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultgetcertificatepolicy.json b/azurecompute-arm/src/test/resources/vaultgetcertificatepolicy.json
new file mode 100644
index 0000000..97e126a
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultgetcertificatepolicy.json
@@ -0,0 +1,37 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/policy",
+	"key_props": {
+		"exportable": false,
+		"kty": "RSA",
+		"key_size": 2048,
+		"reuse_key": false
+	},
+	"secret_props": {
+		"contentType": "application/x-pkcs12"
+	},
+	"x509_props": {
+		"subject": "CN=mycertificate.foobar.com",
+		"ekus": ["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"],
+		"key_usage": ["digitalSignature", "keyEncipherment"],
+		"validity_months": 12,
+		"basic_constraints": {
+			"ca": false
+		}
+	},
+	"lifetime_actions": [{
+		"trigger": {
+			"lifetime_percentage": 80
+		},
+		"action": {
+			"action_type": "AutoRenew"
+		}
+	}],
+	"issuer": {
+		"name": "Self"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509346452,
+		"updated": 1509346452
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultgetdeleted.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultgetdeleted.json b/azurecompute-arm/src/test/resources/vaultgetdeleted.json
new file mode 100644
index 0000000..bb3bb2c
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultgetdeleted.json
@@ -0,0 +1,12 @@
+{
+  "id": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/providers/Microsoft.KeyVault/locations/westeurope/deletedVaults/kvvaultapilivetest",
+  "name": "kvvaultapilivetest",
+  "type": "Microsoft.KeyVault/deletedVaults",
+  "properties": {
+    "vaultId": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourceGroups/rg-vaultapilivetest-jims/providers/Microsoft.KeyVault/vaults/kvvaultapilivetest",
+    "location": "westeurope",
+    "tags": {},
+    "deletionDate": "2017-10-29T22:06:02Z",
+    "scheduledPurgeDate": "2018-01-27T22:06:02Z"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultgetdeletedcertificate.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultgetdeletedcertificate.json b/azurecompute-arm/src/test/resources/vaultgetdeletedcertificate.json
new file mode 100644
index 0000000..73635de
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultgetdeletedcertificate.json
@@ -0,0 +1,55 @@
+{
+	"recoveryId": "https://kvvaultapilivetest.vault.azure.net/deletedcertificates/myRecoverableCertificate",
+	"deletedDate": 1509346545,
+	"scheduledPurgeDate": 1517122545,
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myRecoverableCertificate/42f1b607074a4531b4f14fb4447d4346",
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myRecoverableCertificate/42f1b607074a4531b4f14fb4447d4346",
+	"sid": "https://kvvaultapilivetest.vault.azure.net/secrets/myRecoverableCertificate/42f1b607074a4531b4f14fb4447d4346",
+	"x5t": "-qEnW6P9TdfOOXzbNQNS5ZKveRo",
+	"cer": "MIIFNDCCAxygAwIBAgICQ0MwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEhMB8GA1UEAwwYRm9vYmFyIEludGVybWVkaWF0ZSBDQSAxMB4XDTE3MTAyODIyNTIxNFoXDTE4MTEwNzIyNTIxNFowUTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEcMBoGA1UEAwwTdGVzdHNpdGUuZm9vYmFyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKlPGmdiqKloSbUri9gvo2lyS0x2axSpeTfgIxI4Qnqhq8wMkih+SuO8+2rzIUd3S9nYqVww6yy+qHiJLXi3DKVYM/jgJnF+PlUoXxulD1abN8kX+TCKuHeAfTSIjM6WSgimGqW3hoB6bYHsaUFaAIg5FYbg5/IpbEMnD2yjU4M/nHVbxRwPqHGYdYfSqGDeHYjDb8GdA/+N0JDEoMVflTQKrDzq9R0lwOg+kICem1D+kww9ajyTu/7QdE8oOhAzuqFIVkCyZwpkrs576ng34mP04vpGcBs8YiKODydtFl2p5labXr5la0LVpLJL6rUkM3EhWOhQ0s+fCGtfrlmFRMCAwEAAaOCAQ8wggELMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFNPsyKBhnCjL7pVBLRYK3jaoZ8PfMHIGA1UdIwRrMGmAFAf9rGqvLeJheBNJOHBKTG3Oz32PoU2kSzBJMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEPMA0GA1UECgwGRm9vYmFy
 MRQwEgYDVQQDDAtGb29iYXIgUm9vdIICQkIwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQA4sFKv4JDZ0+CVjcHL9bkTpk5I2L45xXk3d7GrhBpGveyy8vlb/g7P0qyAVo0UnB+eRTtwk6GTsJdzz4FBem+FDq8ZO/N51Rn4ZJQbDg24eGErK4rpbOo5OQgKKhTKjjBYwsAsIOkJ1TKQDQ3++Kqw3cWh/vlCWoxGPSMOeU/Iro34IWzSeEREMamYo5kIYq2ERCcVSoTcYB87cTYMU+ORyQSEx/OncDuAKm45ub92By5NpeFVMk+8ibifgzbNJHVnaZUVg8ScdM1A4Db6WAL0SUsYIawrnQ+TENs+6Ekls+wu8G5FAmbtOEV0WOafGvdcnELn5IPXlkvLbiRx5EChG+nF3XrLgn3dBQwP2cGrI/IPRm1XfaaBAkMSkf6St5TX3C40g1CGcNSVoKBYBB2Di+hPXwTHImGggR1JF34ljHCokMoPxmr7lP9pam0dhP/SSpIwxfsvDJylBgUEqTr3tsVDIDfMtJjudK7A7H1HMoqEiqlzRvJIEZ1koOxANFcQ1f9am2PPUNFvfK9IbLQlV8d4k1w6xBAeOVke79lJI9pTTCSVb+PTDniEL79JXjmjQUoKE4zo1u41d+wLu3dEGM27GI7BdLYt6bRsolZvrbey7Nn4c0t4ug4B4GTd1SLLVJns/IRLBrNr1anBJ7u9WFruBUEWwtdxAwSoXdtIIQ==",
+	"attributes": {
+		"enabled": true,
+		"nbf": 1509231134,
+		"exp": 1541631134,
+		"created": 1509346510,
+		"updated": 1509346510,
+		"recoveryLevel": "Recoverable+Purgeable"
+	},
+	"policy": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myRecoverableCertificate/policy",
+		"key_props": {
+			"exportable": true,
+			"kty": "RSA",
+			"key_size": 2048,
+			"reuse_key": false
+		},
+		"secret_props": {
+			"contentType": "application/x-pem-file"
+		},
+		"x509_props": {
+			"subject": "CN=testsite.foobar.com, O=Foobar, S=California, C=US",
+			"ekus": ["1.3.6.1.5.5.7.3.1"],
+			"key_usage": ["digitalSignature", "keyEncipherment"],
+			"validity_months": 13,
+			"basic_constraints": {
+				"ca": false
+			}
+		},
+		"lifetime_actions": [{
+			"trigger": {
+				"lifetime_percentage": 80
+			},
+			"action": {
+				"action_type": "EmailContacts"
+			}
+		}],
+		"issuer": {
+			"name": "Unknown"
+		},
+		"attributes": {
+			"enabled": true,
+			"created": 1509346510,
+			"updated": 1509346510
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultgetdeletedkey.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultgetdeletedkey.json b/azurecompute-arm/src/test/resources/vaultgetdeletedkey.json
new file mode 100644
index 0000000..687a1cc
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultgetdeletedkey.json
@@ -0,0 +1,18 @@
+{
+	"recoveryId": "https://kvvaultapilivetest.vault.azure.net/deletedkeys/myRecoverableKey",
+	"deletedDate": 1509335960,
+	"scheduledPurgeDate": 1517111960,
+	"key": {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myRecoverableKey/274f6c69b94b41359a5932226425eb43",
+		"kty": "RSA",
+		"key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+		"n": "urhKlXbEGvYetOSH-GLytvSJ5djS0-5SKBtFOlJ2885PE0s_ZbnkRURDm2fImv_RV763HKSUQbEolQNs8I99N-3uCkrDStVZ6MPii9-0U6lrEkX7LrMRNYCfPAaSSZhSjCbsyqX9Y-N_A5Jz9uHNuXvpjQ9N7ojUK7fqqhnJKcJ6l6YsGOhGCD3uei4SL5GzbSAn2auIK51lj77UXjBZaudnNWTiKaCbTAmSmEe13DOJkg82_7Y1eWea3NJn4T2nY8WqRJCp4hzBsPBmFXjE1lgFWcSjm_afiSb0mCUP7v7tSOLR3xUBv9WgMO7p4_ce_--A9ZWP418Uqq0COcHAWQ",
+		"e": "AQAB"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509335950,
+		"updated": 1509335950,
+		"recoveryLevel": "Recoverable+Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultgetdeletedsecret.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultgetdeletedsecret.json b/azurecompute-arm/src/test/resources/vaultgetdeletedsecret.json
new file mode 100644
index 0000000..cd57373
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultgetdeletedsecret.json
@@ -0,0 +1,13 @@
+{
+	"recoveryId": "https://kvvaultapilivetest.vault.azure.net/deletedsecrets/myRecoverableSecret",
+	"deletedDate": 1509335980,
+	"scheduledPurgeDate": 1517111980,
+	"contentType": "aNewSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/myRecoverableSecret/d7194ca6b0214d0ba382353109cd7e58",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335958,
+		"updated": 1509335958,
+		"recoveryLevel": "Recoverable+Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultgetkey.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultgetkey.json b/azurecompute-arm/src/test/resources/vaultgetkey.json
new file mode 100644
index 0000000..66fcf42
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultgetkey.json
@@ -0,0 +1,15 @@
+{
+	"key": {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/bd6566ec707e4ad89f4ab9577d9d0bef",
+		"kty": "RSA",
+		"key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+		"n": "2ZWsir4hwVxFTQXfWN7Vy1zA33jg1kxUMHmkmEFtVjGDByzmMfEXpnPziNCtYppBtpNT4AJEVQ60aIgSLNrUYBMoeiI2HCf2NM0NTdwYp7wq5tImtbGDASdDXQ1v3Bv3hXGh3CVmN2VLRf0OmoXnZUG_2UZZ05iPXOY6lNFfq8L81v0ZCMiXwFvNVhZ_fzppzhnwuHQf-X6Lnvrd1ocFqF8IFjV3663eumAfZmBLPP6tmiAZYW3G68_G0I2CHLtTPFX05aN51Jn42RITgcs63HFMT_iVW5556YR0BwtqkCXIUgTD714Fipz7EKGqhHsqND7YUSKpiRVQhfoZEckAkQ",
+		"e": "AQAB"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509335902,
+		"updated": 1509335902,
+		"recoveryLevel": "Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultgetkeyversions.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultgetkeyversions.json b/azurecompute-arm/src/test/resources/vaultgetkeyversions.json
new file mode 100644
index 0000000..c534f8f
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultgetkeyversions.json
@@ -0,0 +1,23 @@
+{
+	"value": [{
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/1374543b3de34500a97d075991ee3893",
+		"attributes": {
+			"enabled": true,
+			"created": 1509335925,
+			"updated": 1509335925,
+			"recoveryLevel": "Purgeable"
+		}
+	}, {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/bd6566ec707e4ad89f4ab9577d9d0bef",
+		"attributes": {
+			"enabled": true,
+			"created": 1509335902,
+			"updated": 1509335923,
+			"recoveryLevel": "Purgeable"
+		},
+		"tags": {
+			"purpose": "testing"
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultgetsecret.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultgetsecret.json b/azurecompute-arm/src/test/resources/vaultgetsecret.json
new file mode 100644
index 0000000..9f1e929
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultgetsecret.json
@@ -0,0 +1,11 @@
+{
+	"value": "-----BEGIN RSA PRIVATE KEY-----\\nMIIEogIBAAKCAQEAvZiOgV6b4EmGiasBskXYnTaRyWzBHBGnWB11BzFN3FGigfWx\\nVvjI7Ox1SHTx+vGsnjbqQPvIP4JnPEsNcWLyHa6tNAcnj/M7BuyIwdD5+Hvs6kOe\\nPuSOJUf8dRjPMUpr6rcUcBmmOwTnKOH4rdpb6jXNnuCIHP+lgXCeRWveZ62TjEB+\\n9aB8W8UHH854FGebiUd/aY0tpCFC7wkWz3KbgmjmY2vSe2U98Yj4+l/IWydIZ7ON\\nLicteEEIGbNM0o2QSYhQBCJSw5RixDpPlrUUB094qgqUOyW0k8PvjibGxxTh0LYy\\nWqWydPF0XaqFRQ6v36UvEiVGwzVsLwsJL/QVtQIDAQABAoIBAEJ6790lE3s9zNMR\\nB3M/UoktzUjXvY7eEdOv4I05GJgcd+MiB6D7c1jAQQ+7Ee5wN5rynolSwBCk5RYb\\nKweLLmKCEXGg4Jp1K0luPzXW1Q/wRE6Qjzh2Y/FmoHtey6f49IZE1AHKvKMNQRDw\\ny4YKfxhM7WC8Un34lkwg9R5aiI3JkOG9/yNkOGrJfQnGUKt+AOAdu6fNYsRLWAPo\\nG3vWSNIgwaG5WL5cKd1gacbGBlc6tLB7+LrZuNrqln5ibTtN6QJvRF9KfOrMSvxy\\nL/xiHRpyzec/jrxJxAIIwFHiw2jbLdxNqDaVPFA6X1Cks4fvY40KymOS8Ecmkgx4\\nC6/ZqLECgYEA38rL8zmbJRRWgrxSoROucaN/9DyvE8Hd97s1zf3I0LIF+GI3JdcN\\nDV5O5VDIgQ7QZ55lOaTqJ0f2fOQZF1UbTU1gBUHVF6j1nv6Xic3OV+ZmhTMbt0Op\\nWxPaKup6dkNEAe/Xg0p308r8xw/psh4/gjL1ICHwycjUlz9FQz8FLGsCgYEA2OHc\\n/F4vAdK04U4w6A
 yivuJdIsDAks1ikl+3TqgzyesPg+DpKVNSy6DhraDFKdRqWhbK\\nDqigTud8TVk9kmyF3WIb1BDf4IrxlTK08s6Jf25QA/lBlwIst3rejqWwRBY2fJp4\\nO8hU31xNLd8nZq8tKYaP+yvyI6fSC+9ZIgyATl8CgYBtTlYzZG2cvMRMcsNBHaXU\\np3E1z/YLhmNuPqhXBp/xHyK/YOliuBkN8IREiSKFtsCf+8OhViVwLjv8YETJGq6N\\nIT/HEZKNTd86W0uU6UrhsA1e/cmJx6iObbHfyEssPEqZT5ZJ8DN65Oh2KhWRBCks\\n5MrJeQps5ITBowunfr5+JQKBgBln09goPD9tbEzcOPRlzoanw5s3kxdfQcW9up5X\\nK8HibC3ZodZ6cT9zOBx7sbzlqhOlicPP0v+LNE9nPcQyPDgjrvjXhTIrdIMyrmmm\\n8gpgZLUidKF42r4fgYSaOhyvsXBFNAJkxDRp/ox6EIaBzLuJjMIycqnklcFaJ0nK\\nxxjnAoGAU/3jRok74Yn0MY183UCXICf/WxVYzwEi3cyRWVh6gAo2ExNye97rau/B\\nY2woAcVxEN9h1HNirq8Z2AwrZKd/BcBnvulZqECeH5zBQ0W56ADX72r+lzOAxTJa\\nU1AIlNCIkfsQ5CpIoYsVoNEM8P+GyS8B9kaEmk/FVKldRTKJqkI=\\n-----END RSA PRIVATE KEY-----\\n",
+	"contentType": "testSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/b936ececbc674f3bb1367ae50d28ada0",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335932,
+		"updated": 1509335932,
+		"recoveryLevel": "Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultgetsecretversions.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultgetsecretversions.json b/azurecompute-arm/src/test/resources/vaultgetsecretversions.json
new file mode 100644
index 0000000..c09ca45
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultgetsecretversions.json
@@ -0,0 +1,25 @@
+{
+	"value": [{
+		"contentType": "aNewSecretKey",
+		"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/8c418537cbc948539ea2ac12c0bfcfb4",
+		"attributes": {
+			"enabled": true,
+			"created": 1509335944,
+			"updated": 1509335944,
+			"recoveryLevel": "Purgeable"
+		}
+	}, {
+		"contentType": "testSecretKey",
+		"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/b936ececbc674f3bb1367ae50d28ada0",
+		"attributes": {
+			"enabled": true,
+			"created": 1509335932,
+			"updated": 1509335934,
+			"recoveryLevel": "Purgeable"
+		},
+		"tags": {
+			"purpose": "testing"
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultimportablecert.txt
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultimportablecert.txt b/azurecompute-arm/src/test/resources/vaultimportablecert.txt
new file mode 100644
index 0000000..f364c85
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultimportablecert.txt
@@ -0,0 +1,58 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCipTxpnYqipaEm
+1K4vYL6NpcktMdmsUqXk34CMSOEJ6oavMDJIofkrjvPtq8yFHd0vZ2KlcMOssvqh
+4iS14twylWDP44CZxfj5VKF8bpQ9WmzfJF/kwirh3gH00iIzOlkoIphqlt4aAem2
+B7GlBWgCIORWG4OfyKWxDJw9so1ODP5x1W8UcD6hxmHWH0qhg3h2Iw2/BnQP/jdC
+QxKDFX5U0Cqw86vUdJcDoPpCAnptQ/pMMPWo8k7v+0HRPKDoQM7qhSFZAsmcKZK7
+Oe+p4N+Jj9OL6RnAbPGIijg8nbRZdqeZWm16+ZWtC1aSyS+q1JDNxIVjoUNLPnwh
+rX65ZhUTAgMBAAECggEAQWLiXadbM7YYik7YU+21zaZHsWaoFtIHJXMA7+Tgq6bg
+TI+4t2B+lpda00LM7vspj8QlcVNbJxOxFOGgVosEcUWCbTEN40Qmqr3uSeL+r4ep
+2y95abLxoGorKSxNWYDslOkLk1Zhpdz9AxQmw6vfu3NTuJZJHTSCACKMsXUVv7lv
+gMzyaZQ5JC+NFjLv/AK1moq4AqkjwQYzwXou2jbzJ9aoSS+hGSijGwmJbYBe1tev
+3PZVa708PTUF/U0Iw2FaEIg7BrkUxILic6THRBE/Lak+nBG7dlmQhL/3gEukTojr
+iMMtYhCEv0mhKGa7AycIGk31ySbAtV7/KXMEvgMROQKBgQDOrv9f9skNdanV5YyU
+OoOzfc8LOFUlTMyDS5Ioh5PWD0YqzELcBbcbsMmVwRBlChDiJcwDG7Ro4DCSLG9I
+G4vo0JHDxyKJpWLq07E8MRzL3804K0XKKP/AFS4u0P8LMVAny7OK2c58NvFXmDqu
+RV+k3S65AVQNaie0uUZ7IoXfvwKBgQDJdDm6hOJtKuZiZP7k23k1rcBGc0mPkd0w
+8yUooWNZGBjPpwzX7ELqYFnK+6Wy8qOJSEYVjzov7ArSmbmhq09bej9uLP0fWYcm
+O6C7FMw++Gkz+MF5s7EGcUQI36wGWIlGuNyHTVNqOgBhCYBulhtQVj0CImuV5XHg
+HMv3YppfrQKBgB3jNnClGjvFCRMyR5rjv0nEZp1DvyROr8BIvFD6EgnBWa80rHJu
+rSTm8q+iJIHH69sYBiFo7zS/PqbUoB74RMoc5wc9k6P984jrpdSDcZuVuHJn54at
+WRZoua3xcQAoWGP40/S/PFnABDRbghjTVVpc1bXRGFt8P1Ol+ygxPNS3AoGACRbq
+Z+UJBl3yKSxfZ9oTPP3K+CLJheXR8hx2Z7/oaKOysuPZq4BogIS6aHM0Rb+260HM
+j7p3qKPg1SHEg2vkV79LT2BOR3TVqT71gJtun8S7knG94QzfhufjZvcYnuytvPgo
+Ux6FDfzx+W7hUZwKPXS2qfr9mbTRj4gdF9tmFb0CgYBTT/j/J4pHnUUVTMROhHTb
+4HlyZLvfaT5TSHa+W+WyqtYNvsR1yUrQ+bErjBiSg8lFZjVUiGlUeWtysMBUttdr
+uulnqRnPp3QFmwNdu+6gIfJmz0R8QZfkBc57X/9wDLmEb6nN8PnysQ8zvRDTE1ga
+8MCiq3A3u1HM0+JN+v0c2g==
+-----END PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIFNDCCAxygAwIBAgICQ0MwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEhMB8GA1UEAwwY
+Rm9vYmFyIEludGVybWVkaWF0ZSBDQSAxMB4XDTE3MTAyODIyNTIxNFoXDTE4MTEw
+NzIyNTIxNFowUTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzAN
+BgNVBAoMBkZvb2JhcjEcMBoGA1UEAwwTdGVzdHNpdGUuZm9vYmFyLmNvbTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKlPGmdiqKloSbUri9gvo2lyS0x
+2axSpeTfgIxI4Qnqhq8wMkih+SuO8+2rzIUd3S9nYqVww6yy+qHiJLXi3DKVYM/j
+gJnF+PlUoXxulD1abN8kX+TCKuHeAfTSIjM6WSgimGqW3hoB6bYHsaUFaAIg5FYb
+g5/IpbEMnD2yjU4M/nHVbxRwPqHGYdYfSqGDeHYjDb8GdA/+N0JDEoMVflTQKrDz
+q9R0lwOg+kICem1D+kww9ajyTu/7QdE8oOhAzuqFIVkCyZwpkrs576ng34mP04vp
+GcBs8YiKODydtFl2p5labXr5la0LVpLJL6rUkM3EhWOhQ0s+fCGtfrlmFRMCAwEA
+AaOCAQ8wggELMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG
++EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYD
+VR0OBBYEFNPsyKBhnCjL7pVBLRYK3jaoZ8PfMHIGA1UdIwRrMGmAFAf9rGqvLeJh
+eBNJOHBKTG3Oz32PoU2kSzBJMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZv
+cm5pYTEPMA0GA1UECgwGRm9vYmFyMRQwEgYDVQQDDAtGb29iYXIgUm9vdIICQkIw
+DgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEB
+CwUAA4ICAQA4sFKv4JDZ0+CVjcHL9bkTpk5I2L45xXk3d7GrhBpGveyy8vlb/g7P
+0qyAVo0UnB+eRTtwk6GTsJdzz4FBem+FDq8ZO/N51Rn4ZJQbDg24eGErK4rpbOo5
+OQgKKhTKjjBYwsAsIOkJ1TKQDQ3++Kqw3cWh/vlCWoxGPSMOeU/Iro34IWzSeERE
+MamYo5kIYq2ERCcVSoTcYB87cTYMU+ORyQSEx/OncDuAKm45ub92By5NpeFVMk+8
+ibifgzbNJHVnaZUVg8ScdM1A4Db6WAL0SUsYIawrnQ+TENs+6Ekls+wu8G5FAmbt
+OEV0WOafGvdcnELn5IPXlkvLbiRx5EChG+nF3XrLgn3dBQwP2cGrI/IPRm1XfaaB
+AkMSkf6St5TX3C40g1CGcNSVoKBYBB2Di+hPXwTHImGggR1JF34ljHCokMoPxmr7
+lP9pam0dhP/SSpIwxfsvDJylBgUEqTr3tsVDIDfMtJjudK7A7H1HMoqEiqlzRvJI
+EZ1koOxANFcQ1f9am2PPUNFvfK9IbLQlV8d4k1w6xBAeOVke79lJI9pTTCSVb+PT
+DniEL79JXjmjQUoKE4zo1u41d+wLu3dEGM27GI7BdLYt6bRsolZvrbey7Nn4c0t4
+ug4B4GTd1SLLVJns/IRLBrNr1anBJ7u9WFruBUEWwtdxAwSoXdtIIQ==
+-----END CERTIFICATE-----
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultimportcertificate.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultimportcertificate.json b/azurecompute-arm/src/test/resources/vaultimportcertificate.json
new file mode 100644
index 0000000..d431070
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultimportcertificate.json
@@ -0,0 +1,52 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myImportableCertificate/f69168f2963e4ac7b68622b2bb2f80d3",
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myImportableCertificate/f69168f2963e4ac7b68622b2bb2f80d3",
+	"sid": "https://kvvaultapilivetest.vault.azure.net/secrets/myImportableCertificate/f69168f2963e4ac7b68622b2bb2f80d3",
+	"x5t": "-qEnW6P9TdfOOXzbNQNS5ZKveRo",
+	"cer": "MIIFNDCCAxygAwIBAgICQ0MwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEhMB8GA1UEAwwYRm9vYmFyIEludGVybWVkaWF0ZSBDQSAxMB4XDTE3MTAyODIyNTIxNFoXDTE4MTEwNzIyNTIxNFowUTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEcMBoGA1UEAwwTdGVzdHNpdGUuZm9vYmFyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKlPGmdiqKloSbUri9gvo2lyS0x2axSpeTfgIxI4Qnqhq8wMkih+SuO8+2rzIUd3S9nYqVww6yy+qHiJLXi3DKVYM/jgJnF+PlUoXxulD1abN8kX+TCKuHeAfTSIjM6WSgimGqW3hoB6bYHsaUFaAIg5FYbg5/IpbEMnD2yjU4M/nHVbxRwPqHGYdYfSqGDeHYjDb8GdA/+N0JDEoMVflTQKrDzq9R0lwOg+kICem1D+kww9ajyTu/7QdE8oOhAzuqFIVkCyZwpkrs576ng34mP04vpGcBs8YiKODydtFl2p5labXr5la0LVpLJL6rUkM3EhWOhQ0s+fCGtfrlmFRMCAwEAAaOCAQ8wggELMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFNPsyKBhnCjL7pVBLRYK3jaoZ8PfMHIGA1UdIwRrMGmAFAf9rGqvLeJheBNJOHBKTG3Oz32PoU2kSzBJMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEPMA0GA1UECgwGRm9vYmFy
 MRQwEgYDVQQDDAtGb29iYXIgUm9vdIICQkIwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQA4sFKv4JDZ0+CVjcHL9bkTpk5I2L45xXk3d7GrhBpGveyy8vlb/g7P0qyAVo0UnB+eRTtwk6GTsJdzz4FBem+FDq8ZO/N51Rn4ZJQbDg24eGErK4rpbOo5OQgKKhTKjjBYwsAsIOkJ1TKQDQ3++Kqw3cWh/vlCWoxGPSMOeU/Iro34IWzSeEREMamYo5kIYq2ERCcVSoTcYB87cTYMU+ORyQSEx/OncDuAKm45ub92By5NpeFVMk+8ibifgzbNJHVnaZUVg8ScdM1A4Db6WAL0SUsYIawrnQ+TENs+6Ekls+wu8G5FAmbtOEV0WOafGvdcnELn5IPXlkvLbiRx5EChG+nF3XrLgn3dBQwP2cGrI/IPRm1XfaaBAkMSkf6St5TX3C40g1CGcNSVoKBYBB2Di+hPXwTHImGggR1JF34ljHCokMoPxmr7lP9pam0dhP/SSpIwxfsvDJylBgUEqTr3tsVDIDfMtJjudK7A7H1HMoqEiqlzRvJIEZ1koOxANFcQ1f9am2PPUNFvfK9IbLQlV8d4k1w6xBAeOVke79lJI9pTTCSVb+PTDniEL79JXjmjQUoKE4zo1u41d+wLu3dEGM27GI7BdLYt6bRsolZvrbey7Nn4c0t4ug4B4GTd1SLLVJns/IRLBrNr1anBJ7u9WFruBUEWwtdxAwSoXdtIIQ==",
+	"attributes": {
+		"enabled": true,
+		"nbf": 1509231134,
+		"exp": 1541631134,
+		"created": 1509346469,
+		"updated": 1509346469,
+		"recoveryLevel": "Purgeable"
+	},
+	"policy": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myImportableCertificate/policy",
+		"key_props": {
+			"exportable": true,
+			"kty": "RSA",
+			"key_size": 2048,
+			"reuse_key": false
+		},
+		"secret_props": {
+			"contentType": "application/x-pem-file"
+		},
+		"x509_props": {
+			"subject": "CN=testsite.foobar.com, O=Foobar, S=California, C=US",
+			"ekus": ["1.3.6.1.5.5.7.3.1"],
+			"key_usage": ["digitalSignature", "keyEncipherment"],
+			"validity_months": 13,
+			"basic_constraints": {
+				"ca": false
+			}
+		},
+		"lifetime_actions": [{
+			"trigger": {
+				"lifetime_percentage": 80
+			},
+			"action": {
+				"action_type": "EmailContacts"
+			}
+		}],
+		"issuer": {
+			"name": "Unknown"
+		},
+		"attributes": {
+			"enabled": true,
+			"created": 1509346469,
+			"updated": 1509346469
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultimportcertificaterequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultimportcertificaterequestbody.json b/azurecompute-arm/src/test/resources/vaultimportcertificaterequestbody.json
new file mode 100644
index 0000000..2ca39cb
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultimportcertificaterequestbody.json
@@ -0,0 +1,9 @@
+{
+	"policy": {
+		"lifetime_actions": [],
+		"secret_props": {
+			"contentType": "application/x-pem-file"
+		}
+	},
+	"value": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCipTxpnYqipaEm\n1K4vYL6NpcktMdmsUqXk34CMSOEJ6oavMDJIofkrjvPtq8yFHd0vZ2KlcMOssvqh\n4iS14twylWDP44CZxfj5VKF8bpQ9WmzfJF/kwirh3gH00iIzOlkoIphqlt4aAem2\nB7GlBWgCIORWG4OfyKWxDJw9so1ODP5x1W8UcD6hxmHWH0qhg3h2Iw2/BnQP/jdC\nQxKDFX5U0Cqw86vUdJcDoPpCAnptQ/pMMPWo8k7v+0HRPKDoQM7qhSFZAsmcKZK7\nOe+p4N+Jj9OL6RnAbPGIijg8nbRZdqeZWm16+ZWtC1aSyS+q1JDNxIVjoUNLPnwh\nrX65ZhUTAgMBAAECggEAQWLiXadbM7YYik7YU+21zaZHsWaoFtIHJXMA7+Tgq6bg\nTI+4t2B+lpda00LM7vspj8QlcVNbJxOxFOGgVosEcUWCbTEN40Qmqr3uSeL+r4ep\n2y95abLxoGorKSxNWYDslOkLk1Zhpdz9AxQmw6vfu3NTuJZJHTSCACKMsXUVv7lv\ngMzyaZQ5JC+NFjLv/AK1moq4AqkjwQYzwXou2jbzJ9aoSS+hGSijGwmJbYBe1tev\n3PZVa708PTUF/U0Iw2FaEIg7BrkUxILic6THRBE/Lak+nBG7dlmQhL/3gEukTojr\niMMtYhCEv0mhKGa7AycIGk31ySbAtV7/KXMEvgMROQKBgQDOrv9f9skNdanV5YyU\nOoOzfc8LOFUlTMyDS5Ioh5PWD0YqzELcBbcbsMmVwRBlChDiJcwDG7Ro4DCSLG9I\nG4vo0JHDxyKJpWLq07E8MRzL3804K0XKKP/AFS4u0P8LMVAny7OK2c58NvFXmDqu\nRV+k3S65AVQNaie0uUZ7IoXfvwKBgQDJd
 Dm6hOJtKuZiZP7k23k1rcBGc0mPkd0w\n8yUooWNZGBjPpwzX7ELqYFnK+6Wy8qOJSEYVjzov7ArSmbmhq09bej9uLP0fWYcm\nO6C7FMw++Gkz+MF5s7EGcUQI36wGWIlGuNyHTVNqOgBhCYBulhtQVj0CImuV5XHg\nHMv3YppfrQKBgB3jNnClGjvFCRMyR5rjv0nEZp1DvyROr8BIvFD6EgnBWa80rHJu\nrSTm8q+iJIHH69sYBiFo7zS/PqbUoB74RMoc5wc9k6P984jrpdSDcZuVuHJn54at\nWRZoua3xcQAoWGP40/S/PFnABDRbghjTVVpc1bXRGFt8P1Ol+ygxPNS3AoGACRbq\nZ+UJBl3yKSxfZ9oTPP3K+CLJheXR8hx2Z7/oaKOysuPZq4BogIS6aHM0Rb+260HM\nj7p3qKPg1SHEg2vkV79LT2BOR3TVqT71gJtun8S7knG94QzfhufjZvcYnuytvPgo\nUx6FDfzx+W7hUZwKPXS2qfr9mbTRj4gdF9tmFb0CgYBTT/j/J4pHnUUVTMROhHTb\n4HlyZLvfaT5TSHa+W+WyqtYNvsR1yUrQ+bErjBiSg8lFZjVUiGlUeWtysMBUttdr\nuulnqRnPp3QFmwNdu+6gIfJmz0R8QZfkBc57X/9wDLmEb6nN8PnysQ8zvRDTE1ga\n8MCiq3A3u1HM0+JN+v0c2g\u003d\u003d\n-----END PRIVATE KEY-----\n-----BEGIN CERTIFICATE-----\nMIIFNDCCAxygAwIBAgICQ0MwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx\nEzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEhMB8GA1UEAwwY\nRm9vYmFyIEludGVybWVkaWF0ZSBDQSAxMB4XDTE3MTAyODIyNTIxNFoXDTE4MTEw\nNzIyNTIxNFowUT
 ELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzAN\nBgNVBAoMBkZvb2JhcjEcMBoGA1UEAwwTdGVzdHNpdGUuZm9vYmFyLmNvbTCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKlPGmdiqKloSbUri9gvo2lyS0x\n2axSpeTfgIxI4Qnqhq8wMkih+SuO8+2rzIUd3S9nYqVww6yy+qHiJLXi3DKVYM/j\ngJnF+PlUoXxulD1abN8kX+TCKuHeAfTSIjM6WSgimGqW3hoB6bYHsaUFaAIg5FYb\ng5/IpbEMnD2yjU4M/nHVbxRwPqHGYdYfSqGDeHYjDb8GdA/+N0JDEoMVflTQKrDz\nq9R0lwOg+kICem1D+kww9ajyTu/7QdE8oOhAzuqFIVkCyZwpkrs576ng34mP04vp\nGcBs8YiKODydtFl2p5labXr5la0LVpLJL6rUkM3EhWOhQ0s+fCGtfrlmFRMCAwEA\nAaOCAQ8wggELMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG\n+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYD\nVR0OBBYEFNPsyKBhnCjL7pVBLRYK3jaoZ8PfMHIGA1UdIwRrMGmAFAf9rGqvLeJh\neBNJOHBKTG3Oz32PoU2kSzBJMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZv\ncm5pYTEPMA0GA1UECgwGRm9vYmFyMRQwEgYDVQQDDAtGb29iYXIgUm9vdIICQkIw\nDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEB\nCwUAA4ICAQA4sFKv4JDZ0+CVjcHL9bkTpk5I2L45xXk3d7GrhBpGveyy8vlb/g7P\n0qyAVo0UnB+eRTtwk6GTs
 Jdzz4FBem+FDq8ZO/N51Rn4ZJQbDg24eGErK4rpbOo5\nOQgKKhTKjjBYwsAsIOkJ1TKQDQ3++Kqw3cWh/vlCWoxGPSMOeU/Iro34IWzSeERE\nMamYo5kIYq2ERCcVSoTcYB87cTYMU+ORyQSEx/OncDuAKm45ub92By5NpeFVMk+8\nibifgzbNJHVnaZUVg8ScdM1A4Db6WAL0SUsYIawrnQ+TENs+6Ekls+wu8G5FAmbt\nOEV0WOafGvdcnELn5IPXlkvLbiRx5EChG+nF3XrLgn3dBQwP2cGrI/IPRm1XfaaB\nAkMSkf6St5TX3C40g1CGcNSVoKBYBB2Di+hPXwTHImGggR1JF34ljHCokMoPxmr7\nlP9pam0dhP/SSpIwxfsvDJylBgUEqTr3tsVDIDfMtJjudK7A7H1HMoqEiqlzRvJI\nEZ1koOxANFcQ1f9am2PPUNFvfK9IbLQlV8d4k1w6xBAeOVke79lJI9pTTCSVb+PT\nDniEL79JXjmjQUoKE4zo1u41d+wLu3dEGM27GI7BdLYt6bRsolZvrbey7Nn4c0t4\nug4B4GTd1SLLVJns/IRLBrNr1anBJ7u9WFruBUEWwtdxAwSoXdtIIQ\u003d\u003d\n-----END CERTIFICATE-----"
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultimportkeyrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultimportkeyrequestbody.json b/azurecompute-arm/src/test/resources/vaultimportkeyrequestbody.json
new file mode 100644
index 0000000..fe9312e
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultimportkeyrequestbody.json
@@ -0,0 +1,18 @@
+{
+  "Hsm": false,
+  "attributes": {
+    "enabled": true
+  },
+  "key": {
+    "d": "DjU54mYvHpICXHjc5-JiFqiH8NkUgOG8LL4kwt3DeBp9bP0-5hSJH8vmzwJkeGG9L79EWG4b_bfxgYdeNX7cFFagmWPRFrlxbd64VRYFawZHRJt-2cbzMVI6DL8EK4bu5Ux5qTiV44Jw19hoD9nDzCTfPzSTSGrKD3iLPdnREYaIGDVxcjBv3Tx6rrv3Z2lhHHKhEHb0RRjATcjAVKV9NZhMajJ4l9pqJ3A4IQrCBl95ux6Xm1oXP0i6aR78cjchsCpcMXdP3WMsvHgTlsZT0RZLFHrvkiNHlPiil4G2_eHkwvT__CrcbO6SmI_zCtMmypuHJqcr-Xb7GPJoa64WoQ",
+    "dp": "DB9nGuHplY_7Xv5a5UCs5YgxkWPtJFfbIZ1Zr-XHCCY09JIWReOGQG226OhjwixKtOK_OqmAKtMKM9OmKviJRHNbDhbTxumN3u7cL8dftjXpSryiEQlPmWyW94MneI2WNIrvh4wruQuDt8EztgOiDFxwcnUgey8iend7WmZnE7E",
+    "dq": "O-bSTUQ4N_UuQezgkF3TDrnBraO67leDGwRbfiE_U0ghQvqh5DA0QSPVzlWDZc9KUitvj8vxsR9o1PW9GS0an17GJEYuetLnkShKK3NWOhBBX6d1yP9rVdH6JhgIJEy_g0Suz7TAFiFc8i7JF8u4QJ05C8bZAMhOLotqftQeVOM",
+    "e": "AQAB",
+    "key_ops": ["encrypt"],
+    "kty": "RSA",
+    "n": "33TqqLR3eeUmDtHS89qF3p4MP7Wfqt2Zjj3lZjLjjCGDvwr9cJNlNDiuKboODgUiT4ZdPWbOiMAfDcDzlOxA04DDnEFGAf-kDQiNSe2ZtqC7bnIc8-KSG_qOGQIVaay4Ucr6ovDkykO5Hxn7OU7sJp9TP9H0JH8zMQA6YzijYH9LsupTerrY3U6zyihVEDXXOv08vBHk50BMFJbE9iwFwnxCsU5-UZUZYw87Uu0n4LPFS9BT8tUIvAfnRXIEWCha3KbFWmdZQZlyrFw0buUEf0YN3_Q0auBkdbDR_ES2PbgKTJdkjc_rEeM0TxvOUf7HuUNOhrtAVEN1D5uuxE1WSw",
+    "p": "8K33pX90XX6PZGiv26wZm7tfvqlqWFT03nUMvOAytqdxhO2HysiPn4W58OaJd1tY4372Qpiv6enmUeI4MidCie-s-d0_B6A0xfhU5EeeaDN0xDOOl8yN-kaaVj9b4HDR3c91OAwKpDJQIeJVZtxoijxl-SRx3u7Vs_7meeSpOfE",
+    "q": "7a5KnUs1pTo72A-JquJvIz4Eu794Yh3ftTk_Et-83aE_FVc6Nk-EhfnwYSNpVmM6UKdrAoy5gsCvZPxrq-eR9pEwU8M5UOlki03vWY_nqDBpJSIqwPvGHUB16zvggsPQUyQBfnN3N8XlDi12n88ltvWwEhn1LQOwMUALEfka9_s",
+    "qi": "InfGmkb2jNkPGuNiZ-mU0-ZrOgLza_fLL9ErZ35jUPhGFzdGxJNobklvsNoTd-E2GAU41YkJh24bncMLvJVYxHHA5iF7FBWx1SvpEyKVhhnIcuXGD7N5PbNZzEdmr9C6I7cPVkWO-sUV7zfFukexIcANmsd_oBBGKRoYzP5Tti4"
+  }
+}
\ No newline at end of file


[2/7] jclouds-labs git commit: Add Azure KeyVault support

Posted by na...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultkeybackup.txt
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultkeybackup.txt b/azurecompute-arm/src/test/resources/vaultkeybackup.txt
new file mode 100644
index 0000000..7c68c54
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultkeybackup.txt
@@ -0,0 +1 @@
+JkF6dXJlS2V5VmF1bHRLZXlCYWNrdXBWMS5taWNyb3NvZnQuY29tZXlKcmFXUWlPaUppTTJJd1pqZ3dZeTB5Wkdaa0xUUmlPVGt0T0RVeE1TMWpZVGRrTTJKbFlURTVNMkVpTENKaGJHY2lPaUpTVTBFdFQwRkZVQ0lzSW1WdVl5STZJa0V4TWpoRFFrTXRTRk15TlRZaWZRLk9tXzl6QnhwTEw5a3NCVmNfR1JLUHR5akZ6R1JGV3BBWFVvVm91dmdNQXNEcFo2UUp1QUloRzZJWFB4ZHBOUDNlbEZFc19Ld3RpMlBhRXNEQWM4TEVQVHZvVzlSRmlROHZTY3JiWHlKcFNROXJSS1V5NlQ2SWo3UEpDV3Z6alp5ZlNYbklPNjRYMUtzRThFZWNKRDdudDRhN2tfZkpiSkw4a3paWnhXWFZLZnZwZEQ4c3dobFdOLVhMU0RsWDFORmlYQk5ILVRoU1BDbkNMOHc4RjlpV0o0LWFxeXozc0ozRDAzb3JzTHdKczFBTF9LN1c4eUlUNlprb3Azc20zeGlBb2pYZl92WDdOLXhQMUtKMU1tRlFnQVpaMmNpQWdJc2UzVDdoWFhsa0RaNGJqSXpYa2ZocGg1YlNuUEkzQU5kbDRUaXZkdVlxM0lCdlZrQ0hpWnY0US5pLXNxb3lQVVNHdlM2SVdUdld0MzBRLkR5N0U0cE9vanU3bzlMQ2dkcVYwd1c2MGxkOWRaU0tPN0wxWXhid1RMQzd3Z0piSmhlNno5b3VWN0FFMnBMLXFFMUhLclI3Nk9TVTJ3c1FBMFZuTDhlR1RnVFk0TWJOaklzSERraGFSUWN4bGRjOHpGWEVxNzNOWlhPWE5vaWJ2QVhUcm9oX3JnS0plNVFYWE1MSFJ6T2lVWEtqVEU3ak11Qm0zejNMRm1mQ1pQb0xWTnpNT09mdmFwQTh5XzNEUFk1OUdxOUFzWlZsakNpTWoxUlVrQV9QQTBwREUwRU8xd25pV
 0dIb0t1R3h2N2hLb18wcFVMMWRPalZrNFA1ZmRWRmtGOENVemVvSDNja29xbUxMRmktQ0Nra2E5Q1JZcUE5ekZFckJsZGYzQTlIOVNuazdiUkNhb3c5Tk0tdXFBbkF1OWF6U3JBbnZZZ1NUT0VFUjFvX01Yc1Bqc1loTHp0NFZoTGx4RjlQNDROSU1ZTjEwWVZBYlVIQ0FaREZZejl5d3l2YWJPSXF1bjUzc25DZTBYVjBaWndabFNmSktJUkNsMk9zU29vVEt2OWx6U2kwOVFlUTRxb1NCMFdXSThobjFGd1pYV0RhdHNSNFFxOTB4RXB1bFVyWV9mOWI3cnNSem9jYmF6c0cxek50a0t5bjNVY29fR00yRjJDclFybi1uRVlXMkZRcVpkMlpHT2Nnbk52NFVyWmMxRjB5MUpTdXgxS29qdHBkZDgzR2JPd2s5dmVlSGs2NXlCdmtMTUYtcGtUWGdFS0lZeVN5ZUM4ekdndVZJOHhrX2VndXhQVlhCVVBMWk0xTHJ3U1VDc2JhaGR3WnRZZDN0R1dZVjZsSzhyT1UtQjhlWllvRTd0QUF2RkZxNEJ1R0U1TXRsdHFSRVpkcHlkOWFkTDRVRkttZ05YcTlvNWVqdWJuSmV2RWhRQmhVRXpRLUdCZ3RudVgtSlNTYjBDVllxV3p0NVU2dzJpcVNwZzBNMnQ4WG5OQXN5WTlvYXVBbVhuUGhMZ3lYYWpaSE1TS2FqNjIwOHdrZVA5ME1CSkt1anBfSFhJaEttSW1TOXVwLVY1NXBHRXdMQnhfYlU3TFpwYnhIcm14R3VOTE9pNXhJUGt3QkpTdXFZRlNSMWdaUU5lb1ZHUncwTW5TQW5HYnJ3eE92NFVjVlpUUjhkVTI1Y0NTOHpENjNwQ0ZUdm5CNllyN0pwcGhYekd3SFZYeTM2TkJPdWVuQ2NYQUR2QXNXS2M5a1RQeTlEalVFRFVQd0QydUpZQmhqaV9RR2taYjhfQnNwdU
 RUbWM1Z0Y3TkdsV2NPRTBqZmFwUi1CSlJhUXJENFhxeU95NTRsTUxCZlNSTFBIN0w4VnMyUTVvc0FfVHlPYUoxa3B6dG5iLUhyNTdSQ1E4UWNsRnd5eVRfakpLaXFQRFEyWFlrZ2NjMmdkZlAtS29GNHFHSl9HRERMN3NVaThKeWRnOFNBdDBoRGdUOTh4Zk1URTlQc0twTU9FQUkwWF9KRWdsRTFwRmNxbVFkT2NOU2Z0VUxRaEFPVWd6Qlgxb1UtYTdiX2gtX0l5RVgyb0htZDdaNUJJRV80b0ZEYWVMaXh6ck9BWFdTTzVFZ3B4U0pYUXZ2ZEVZUV9mNHhPVFU3SExmUWkyNEthdGNUTWJJczlBVU1UY1NvVUhIY0RLWVhZbTl3SWR0RXR3MG5mbFp5YVJMYkx4cVJNTzd0X1ZLbnJ6OGVOZ2dJWENBVno4dmJmXzk1VWdVNGJUTzZDLU9BbHJqbUZNbVNzaEpwY0VhRjAwaGx3MnZud2s2QWlCRTlWUzdOYmJFb0JVZmtuaWJFeVJ5NHp2MmZtMWxhRkJnYmUzWV9QVEtHQTlVOGJlNGJsb2lkQmlVOGwxUS1qT3oxeFRNVFUybkpnYkJ6b0xzWEtadEw0d0ZDTnlNVFN3N1pyX3c0aDJjUzU4UHZsVWlYalRhcGpNdTJzYWJtdVJnVXROTjFlWVdxZjBRSEVFdGoydE5nd25TaHNBOHBRWkZKaXp6Rlc2VXpKRXdPbnN4S25tcjFEQktnZ1hsZFFtdmlxWHU5aE00MzdWcUJIeVA2SFZ1dUdiOEUtTlM5WlBPekJWMEFrcTM2QXVJcWNIMXUwTm1NT0laaXR1WVhFNXp3UGlVczJxSmMzQ1BHbVdZQ3d6THNibF9YRkx1dU5udXlIa2VGN1cwOGtxNjhBU2FBMTVic3BQMDU1a2UyMlRVbzNqVl9PeHRUY205OUdBcktGOE82elBjTlQyQ0xNdjkwZ3I1SEx0MVg1WjF
 4WFNTTVczZ0NRVEs0TmFtNUsyTzFUNXdoTWtPdnhYYmdkb3Jwc245amhGb25aaC00VG5RczJiUmMxVTM1Q1BudmRVM0s1dUVOTzNxZGVxV28zR20xeFRMaUdJSUhsNkdpX0dFdnlqWjdEQzRjeVhlYkI5enRiMklLQXZLVFhyQkF0aXd2bWF4U2FzNFRXVUc5Qy1RYUxLZnpRdDZwVm82NU8wLUZHQ3VLSU1Fc1I4bm9lM19jVVVJNzRiYl9sTVFWdnNyOW9KamJtS1RrWVBhREViQWZCd0FLdGw2dzdWUER4bGt6UmFZVTdPVENsdmFhMTVZQ1hJSzQ2V2hkd2QxMDNoR0x5UjltWlFSdmcyLWhfN0tESzNSVWRzcjNtTlBEYmpCcU16U202MldDNnZTclBVdENKTks2UG1ZWjhfT3A4bXp0U0xUbDBLWlN4dWt5U3d1Y2hfQXZLcGdqa3ktQmVfS0JXNTdka05TT2JlWmZKZElRT0xkSVcwZExqd1BWeTdENEhPS3FyWE1JRGdIdkRIR25zWFBZb0VRZG9wX05BOFZfTW03bWp1blhtZWoxVDI4cTN5VTcxRDEzVUxhdXNwVnNQVHBTcEVDX19mS2ZVSUF2dnI3RmszN19uSFU2QXowSndhNklSU19mTUZHamRuSDI5RXBUcTZGRDdaY1hPZzMxSGdNMHNtNUZlUnkxaHFqUUdIOTRwd2JpUktfWXhQaWVzZHd3cUh2TE1MZE02SU1CU0tuZlVfdTV0bkJISEV6NzZvQ0dHSEJmM0ZnTzFkX1hZZGhtVDZIR2FRUmZhV0s5QTVRNkpUbHBaWUpkOHc2eVlLSDVvNktFR01TWXRKbDFhM29KQ1A2Q0o5Wmh0R0ZWcHlQYlk3M1BkenozR2xvdFlqOE8zYzgtT3BxTm0xaEc2MU1IeEFnNkJYZHgxeFBqZ1RuTVRHbUtTYUplV0d6OWdHc2JDWm52RmlwSExjbHJQVHczVVR0
 NThOdmpkcGJtOGV1VVdxUDM3RVZzMFFoVHZkNzdmc1duZTgzZlpsYkh5SHF1Y3gwWEtBRmNlMURZNlM5Vlc1Ulp4akU4bHJHemxpVXplTGtsS19wVG91d191MXBVWktLV25jTzJ5RzlrZ3dOT0pkazZiWVlPb1dCRGhVNHU3TFVZR2tETENFaVJrSGRIeVBQbjJBeGNXTGhQYml5cUZ2RWRtNUNMMzMtaHN0OHFRNC1QYldfQV85QVFLZ2hoLXJfUUE2Wjlzd3F4QWJFeWI5R294TUFPenAzMlBoaVhpOHRxTC1qQ1ZqSEFnRTdqYm1jRVBVQVh4QlZFUXNLRGd0MFFRM2RscG0xSUd0OU9fMzNwWEIwUmt1bUxYT3pnWjYzYzNGNVp4ZlRyTGtZZ2MxM0p5dXdjb0Nxa0VxS2RxY0F1N3RFODUtSnkxZnpNTHQzLW9wXzBOWUdqallIZTQxU2drdDZjWjdnQXRFeHlDek5YRjBZcG10WFlralI2UTF0dnFIczhRWU9GaTF4RFZBb01pUjBMczFjRGFRcm5WMEhVZ05QeFJSdUlaYld3dWc1OE9QYnNvUDZYdHRhVGo5RU9yRlJEbUR3OVhiSjhxWEV6YkQ5ZXcxUjVsWGVPZWZZcjVnQVlIU1k0X2lTMXR2Qzg0QkY3RGtYUjVDVUxWZXNkTDBwckh6RFA5MHZfRC1oemJSUDVBNFJMM0RLNmFGN3Z6dFktRlRJSnM0bTNKZ3NyVUp4WkV4NjFMQjRIdGJKM2RTMUYxTjJ2YTJPc2VBSWZ0dkhESWFyV21tbjhBZy12T1JhTW1kWC1pT2YtajI2dWlYV3VvTkNPV085NnM3ZWsyUzRoQ1psN0lPNzVzQThkZGprbDNtaFhrSmEtaVBZZk9Nb3pKWDV5WEREX1E2WDg2YzNvZThLZEdVODJCbGluNXRycjRUdlVXcHBEYVZoYzJ6MENyclN4dko2ZjBIb2ZrYVVNTW9seVlpW
 W1rSEdpVWNzdmRNbDhMS1MxVEZoWVZiVW9xNUVyYWhKdW0yTjlqdk9DOGd0Ty0yempNR2NjbkEwUzhqbTR2SFVTRDV4MGtkWFotY0NrZ01HSWM2LW1LaHU1YVRpTTFWX01mN3dteTlrdHZITVRqVUM1d0kwU3JMU1F2RnNWZUZHamthLW1qajlsUEkzMFhORmRLajRTR3A5T2pmclRyYnhfeV91emZ5b3NudGVvRHF0RURmVmFSSFhVOF9pQncwWEdZUDBIaGloR3VlczdrdTZJVlE5aTVjVTBNSTRKR01vR0xJRUJKUG1NckxmamJMdkdVWTgzOWUwc0s5NFNBVHJseXo1YzYyeUloTC1xdEdIeTJBMmxxRUhnVnNvQjF0M0J5bDhwME1OSWJId1ZaUlkxcFBDdFBJVmctYWJCZ1ZVSGZneC1FSDVhVlR3QUZGekw5YjBhVUF5eEhnam1XVTlkYjJTMGJ2S3lKaTh2UXJuOWVnYkt4QWM4OEw1NDNsY1dUU1BIOUQ2Zmk5Z19hY0JUUXF5VUt6S3JxYmJUUGxMNWxQdGdfazFhd3ZLNmhNUDZfR0FLUi15a3JzTlcwVUZHaFI0WDNkTE5DNnFUdGdNaXFnYThKN1dVSjdMZUtaRTV1dzlzQlVRemJSdUxjUDFSMnEwQ29DSHdRYWJIRGhPUkdNMkFyMF9HbmIxZVotRXNNSXJHcWcxQkY5T2FMMTdZWE9RWXRhZXBhUEZGcXI5TS1FTHpEWEtYWlBFU1RVZGZqU1g0RllvMFk5cXNTUGdnTjlhajNnMWxfYVNoclA2SVdxZjJrRWoxTjNIMWVaZVUzQjZrWHBCUFV4VXV0LXk3MkU4Q3l6czJtUDgyQjRvNW9GOUVncldIZXF6WGw5XzQyVDFYNlB0Y0l2TGZ2d2hzd2FTVzlGamxVbC1hczVQbUtxSlRtUzl3bE9CdHZybDh1YWdIT1psMW1zZ3Ezd0hWTGVxMmRQclc4Um
 RjZXJwSTNySGVDZGVzZGJUb3pnS3FuTVhSSVNmZWtvQThLRTkzWFRDOXl1SkM2NmdMcTNJbkJnZ2NUMFp3X0pmWldvN2tmb2dyd2dMRTYwTm9uamxvMERGWFlCRDlKcDd6VGFDRGFGLUZRbHZ5MFdGb1YzRlh2dDllMDdJajBTN0c3THZ0OXVOaW1sbnYyazZOUUJxemlLT01zSjVRQ0pYOEFsbnMwNk9rZG9aVmIzV3Q5MjRQcFM4U0N5R3JnYWVPb24xTHhiMXp2QkIyZDQ5cGJ4a1ZMQnZjcnpFZkYzbExSOU9NdThGNERjS1VHcnBiMjUtNHFQQXVIZXJCcEVEWVBDY3p1RWJaQktZakZQSlozejhKNk45S2l6MktaQTQ0Z3ZKVE42QW5rcThnXzRJMWRBNzRtME9QMEcxd3dtd1pQQU10VXJqYmJ2TVNtbHVjb0FibXhSbDNPd2hFbGRoVFVwdi1iQ3d6ZHVqYnNPMVBsYWI5am1LQUZZaFloU0RZR0FoOTRRRVJ1dkd2VTJnQzlzRmYxTGFTM0Zaa24tRXIxWmgyallpc3BwMlFFd1FBdFlDcmMwaUptMlYwOF95RTVheEVJSnlpZzBhVnFZQ1FiN05GS2diX19LRF9uMi1yN2YwX2RIOFgxeUdJcXpiNzNGbHRCU05RRG1oUU1TdVlVYjlMbHFlREhuNVFtZ3JpQW02d3kwR25QMmE2X2k2TGZWejhMckUxVm94d253V1h4SDlSeDVuTUdpREFvRGxaVlIzVzd1cW1BZ0lMaGFvNldXb0xuYVZSU0pRUTFybTY2R2dCTENUa1QwcE9kS0Vpelc4TlpwXy00Q0tWSHB4ZUpRVFBodXo1cXBmalM4Xzh2M3Nkb0lHNko5RkxwMUludnlmTnFIM0djZ0sxbWZZbWZPUW42cXUybU4yckpiMDg2Y3U2cU5VZnpRcXJqQVpwckdpQ2pCU3Z5T3JwdnZCdGQxVHBQTXFMZEZ
 xbmtGeC1GSTdYWDJocUtoRGFyX2R6QldTWXFPSE9adG50d0hocGNWVExLeXdqQTl0MmxGWTFuNFJtR1l1SHlKdlhVeFZvc05BU19nd1EzM015U25lTk40am5aTWFCNFMyM2lNV0Y0UktSaUlSXzAtTV9Nc1kwbDZmbUxOekZFbFJrUE1LcWFsOHFmbUo3VDkxU2IxdkJFQl9WX052dGxlVzd2VnlaSXBpbV8xUHJ3MC1oMXBMcXVXVDFodll4SWNtbHllSldIUy1NQURnaVdWbnlFOVJBOHpXWFI3TWR2V2s0U2MtaGV0U29LUk1YbmxCM0F2cFc1bEVYN2g0aTJEcVNfLTI0RGdMS09iNWlfVTMwZHNxcWJCdTFMUkNiX2p5dHJhUUlwMEJOczhEMFFXQmFzYlZDbTdNTkM2WlpESlZLMFlBQWkyZnktM3RPSjA3dFF2OFRQelNiaHZETDh6UHdqTmVCSURMWjlvTmdlZFNJYk5sRWdZS3RKZHh6emJEOVp2UmNKSzNYUTBYVHY5bGc0V19HVGJYSUx1bF9fa1owcGZ2RjV6N1Rlc21obV9hRFY2MzNYTEJzWG1wNHJqWUdKUE4tdWxkNW11YkZoWnFWRjJaRHpOTFI5czNKSXNkeHZubnl5QVpiR3dfVjI3eFVKQ19WbktXTzN4bVhGdW5lV0dVSkNFZFpWR2FyZkQ3MHgzc1JIeHJzM29jSEQyQ1JhcnFpM19SOHlndWM4NzlveEJuU29FbXJJTkd5dWkxbXkyRHdnOFYyaGNrcVZKSjhBakxONjNJaGZBR0FTNEU4QWpQODdBczlPX0ZUcnVESWhtOHBEOGpFbUpQTFlTV0hNbkl5WDV6VXEwa3p0NE1QMkNpdzF0Z1pXMGtvRGtHVFhMX1hTV2JCX2ZmVG1lWDN0cDVYU0M0YUh3X3BzUV9oNE44Y2NkS3ItWE1jYXo2aTJ0U3k0Ymh6U2lwWXdqcGx6S3hTYU5wdVpm
 cURWUHlEVXpfSE9OSHVvV0ZVSEw5alhpTEVuR2JFYW5HZ2VlRXN0cEFDcGMyS2JNN0NhSWpDdUtubmpxVy1EZWoxWGNMY3Y5LU1EVFVraGZwTGhMV3ZOWUZKV19UZ1F3eHhEbllTdEwxYTNZVGRfMjJuQ3dJUm5SekY1Y19YTU5KM0JleDh5c3F6ZTJyN1Q4b1hUcFhvY2ozQ2sxaGgzdEh0dHhCOEIyYUh0UlRUanIzRFltamc1RllTOENLNl9mOThkX1QyS2FHYkViZFd4eDhyTDdEZ3JKTGdqeC1Ba05ma0pCR3prY1JaRnBFX1VHVnNhMW1nZlNwOC00QTVaM1Bfdzhuc1RsdzhsaUZ1MUpxcTR2S2ZyQmNUWTI2UEptdEdkZWQ5N21KQnN1aFhyWW5uZW5qamg5bEZYZ3g1TmYyOFFKNHdoV2w5eTFnSS0wNHF5ZEdfem5CbVJ0MkY1Q0FNbXdMQ0hpZV83LUNZVzNDTkJNWlRPcV80VUpaWndxcTUzNkJYdWtmNHZNZ2ZJSENnT1JfczcxUTRleGRmWWZ2ZTU5ZEp3WEc4ZHRMa2xxdXM5SlM4dlgzSnFHdHpLOUhWYjhlVkdmVWpNNXVnU3J6RWJCRFQ2SE1vLWhqVFpNbzBrbjAtY2hTV0hpVV81X2xRanlmdDZMYkxWZFZEbkxlLXFhczlhUi05YXZDZGk2Wmt1SmxuNVJPbXI1XzVpam54Y0haam1ZU3ZXdU9xX0tZT1JxLTMwRXhMdldTM29YbjNQc0lzOTNWTGktU1hHSEpXamJ6YXVlWDFySWlsMGZFLVY4ektpMU5aLXVVWjJJQnVHdjllVWtYeXJyVl9EWmZxUE94RlpMT1NqYWZuWWxSNEt0dE9WMHJVeURaUExob2h6bkZHdG9jRjAwV29xOVB6b1dCT3VJNjNjeE1YNVZGSnpmYTdTdTZ4Vk1FRExLVEZZRzh0bGVDdUpLSHpTV2hpR0FaY1djU3NvL
 U1VNnQ3LUJMVEQwWHEzVklNZU5qQzdQcmU2TjU3YkZheWpqaVVTdTBrOEh1SjBhWGZnNDlOZ2M5S1AxWHp5bjA3M3p4NWd4dEVQYTFhSFVFVEROMkVWakc2SDZMdE50VnNqNGVWRVVzTzZ1VTZTWk1hOHhfX1ZPUEM0WEgzVGRYVFMwTl9KZUw4OENyWmZSMmt3VDh2RWdSUHNVLUc1MU9fQnBXcnVzRndXMElRWXBZTnUwLVVmUjB3VDBlUUFsdHpCbDQ5VkZ6SkVMeHhsTXlKc3ByVUNmMHp1cUNUaVg4d0VUNEc5YWtZZzZKWlV5SVptSUk2RmNycy1sWTBPWlVYSW5IS3pqY0w0WnRVbHhZTTFFUENXVXBibWw4SXN2SlpBN1FELUtWOEJVeFdTXzdUOHRLOWtfbUpGT2pTdVhZUTNjTFVDVktyVkRwU3RZZ3JUREdiUlR5bk9EX3QxU2dwbHczMFFUS01mTXNyZkJweWQ1VEpkSGg2eVdSNFFwUlJnWnVaWGR6STRfWVFUMXIzT3NnWDBWM1NaMUZQN2hSNF9NQnFQSkVTenpZc2pQWVdkTzdzaE55Tl8yaXJDLVNxbG81UkJaNVZvZ2VNZDNaVmhhZEQzcnF0UjJmVHZNZm1aYUtuN0piT2FoUUFJYjY3a3NVUHZHQU9rRC1kNS1VRDV0N2JTU0xkd2xXel9aUjFLakxES0xaTE1WSEtTRk40ejhOUGhIcjc3d21GSDZ0ZEw4X0dEaWh3YnVGTEdmbHl3VmRuWi1uenFQcXNhaTU5MGU4SnBfOVQ3dGtMczZQUHBwclFGSGFVRnFtSTAyYUNvaFJDMGRhTEZDY0JrTXA4blkxeFRlamJyZm1yLVpNcmNLMGQtUmM3bWtpVTY3bUpBRTJSQ3BFZ0Y1dUNiT0xoTlNxMXh5SEZHa0llUE92RkFYMWFGQjNwa1VCN0Q4OWxoUkF1ZGd1bW9JWkRCd0dzdVBSRGZPUlR1T3
 hZakZhaWozZzVyenZHdEVlanB0SVJDbVhNZXhhMVFnYlpQOWJabWh4a0k1SXdHNHJDS0pvZ3NBWnFhYmZUSmUwY18xQTdLYjIzNkEzSHRSMFhJMWRIbVotM2c4cXBwVG9Eb0JPYTZ2RW5vU3NkOFNsX1g1Z0JlZFdmWXZwYzd3X1pfdXJGUXlac3BBbDJrS0N5N2w2U19BUkZqR0dvSnVNWVFicElIbjZGbkJCcjhsTGlyMExZUDVTQlJfM3NaSHNyb3UwamxyLWNMejRZSlpUYzBZcnBGNnRETHA3NFJ0bWM3cDk5aHhNRVE1UG40S1VGNlZJcWt2R2JocjJjdlgzb1d1bk52S0tOcmdXaDYtYzBONFNDTjBkMklveVZfbktzNG4wR2tQcmtDS1ExSGJMbUg1N2ZSTGdqSzFFaEtydGp1SUx3dXFRM0pCeUhISlpOdEdsbV9nZkt5bzZsQ2IyQ2xacElxR2Y0X3ozcVVyMmZVQXhMdWxtRFRMZzh6Z0RlTEViVVdUTXYxTWRUc0pSb0NTZGJiS1NvQ3k2UE1YZUwycllBR2tHT1VYMnVPaDVnRlVkZkdzRVg3enVHamtadnhra2J3VHpTSFlibkMxNHlaRXZsbS1qRkhWS0JjUFdJemJKSnFoUl8zdFVNZ2xRc0xrZzQ2WHFlLUREblVTYUMxbzZ0NnNXOE5CbGR3aGdnOU9JUXhlT2NacVhTanY4TW84SkdrUWlBMnp2WUVWNmJpa09MS3BTbXQyRnNWVE5BSVBQNm1nazE2NG5JaVZXSTN3dlljZ0pCb1ZxeEpCdXJVY2NVNksyVmc1MkU1cnVQc09rNVZwTlphR0ZCb3NYNnU1bjhBM2RfR0laV3VhTUxsZnZnVkdxN21nbFowaFBlM3F3WHI5QndCNm5VV1lJdU1ycFVxUDFQanBmck9OZ3BSOHprQlJ1T0R5R040XzJzRHloMDFWUWRxOGF6OUY4a1gwRU9RaHZ2ZUJ
 KcmtqTTRENGJ5dFVSeVR5RHJRX0hYTExFYUw4UjBPMm9MOGNPeUtSa3F6b1ZGc0NjUC1jMzB1UHFnV2E0T0NzYXhnYUxkTUJveTFKdkFENVF3SWp5dHd2QzR6THNpSXljd3JqeEZaZnVlUnBNRVZLOTR4WVRvNkhlWGQxX0VweFBYMkhiMFFBb0VVVS1zWkFCQVBFZG1OQi1XMEtoUnNpMmJSZi12b3JVZzhJbS1remxCZmxaQ19zUU1RckcwZjR0VE9qTlR0QnlHWUt2dXRqQWJuTjhMQlFSN2JmT0tzM1BvQktQc3pTWDNWMUhtTTUyNnd0X1ZmcDk4d1lFZUNOc3RwcTl1YTRKUlcxRWNGTTRJNnY2aXBXQ3Q5b1V3dVVsTkhUOHNhR2NaUVptRzdZTTRUTDNYVVJITHdaZnNzeUFma2dHejZ0Qm84RWp2MlhNVlZta0ZlRGQ4REl5QXNSUEVHRzZFYUowXzdYajRxNWttR2lUOEJBNE9jMm5pS0M3eVJCVE5CNnhMSldPaXRHcHM0a3ZSX3JfVTl2VUQwMTZ6U19PVlgzLTBqLWNwNzYyWjRicHhNeUswbmNzbFc0M1diUFhRajh2N1libjR1bmtPOU5lc0ZkMC1YWlRvU0J0ZlBTeDk2dGVMM0t4YXEwOFBzV1U5NzhDTVdrUlZHXzZnZWtWWGI0SDdrQUo1M0RoTlpFTW1yM0hSM0lsampIM1YySDRvVGlmeW82ZWdiMHZQX1VEQVNFZGVCUkNYT3JuLUJhTUxzaWhGZE8wVjFxNmNwS2FLVlBkTHgtOTRlelRSRWdtcEpjYjNvSXZoa21RRzJhZ3pZejFEMy1lX0FRU3ladE03TUx6NmY3Ni1HYkkyMy05S0JtVnBVQjJOTnU1aS1xZl8tN3ExQ3JVTFNxNE04aGJsN2E2OUt1UW1RZ0xtQUJZVzlwX3J0ZGFGUzJTRTNGZ0ZPWk1GYnB3MEo3SzRDbXd1VURXb0ty
 ejlGZXAwRDktdkR5NEtpQmdnZWlZTHY3ZFJPVEMwblV2WWlMX00ydXlHbXZtMGJDc29ZMXB3VFNjcDl0aUJZVTZuYW9Ub21ua09qWXZ3T0ZHN3h5R1ZSMF9yT2o3aHpWbzlfbDY3ZE4xaHRFcXZud1BTRno0dXNEcE5UOEFnR3VDVXlMVW5NVVc3ZjNDUFVlOGlqWk5PTm14NEpBT2ZZY1E4dXh3SVRPaExqSEU2alFJOVVFSGNnRmJsMUtrVFJJSDFveGhNSDI3ajJTaUNkS2VrUWVZX3J6cllHTWNmTWF0NTFrdXVzT2pMWDZvbnZWVzBEc1ZXS1FnaUt1OVI1QW8tQkFUTXhxMGJUMWl1X2FaZGNLNkxlZHVwTnVqRXJzSHpNTzF3eGRRcWtMcDVvN2M0ajlQLU5xTTJWWGpnQm93OWJrUmxYdWd2a3Z4WV9tNU1fMm1oeWF1amdtdHg1bXNPR0pIUl9OckY1djZiUGk2aWZkU2o5emhuWGV4MDFEb1B1VmRHeXJkaGN3N25FRjZrczV2N1pOT2ZvRFZuemxCbUpsQVA1eHFjX21SQjI0ZmdWQW5JTzNXMTFSX0V2ZF9UbWxXd085a1cyemFxbi1OeURLUGxtOWp0aXdSSExYRmR1Snc2d2MtdVhJYXdxZFNkZVJkSUV2TWhYX2ExSFhNTG9RYk5VZnpHYk0xSi1aUVBNNWRfbkJPMGN3S0xyRUhlX1ZiT1R4UmZuUU1UVEw1ZnlrcmJGZkgwWUdPYl90aVlqWGJ3QWRsUmtFcFVuSmRWemtCY0tPZUxHMF9ydkRXdmJKX3E4QTFkeFpONm9PSlFvOHRjV0IyVTIyMFNmWjNoNmhUdC12dVBPelltdG1WMDZQb1ZSQTQ5c0JxRWJhNUVKU0pRSGRkVEQyZERDVnRBSV9XNFFFNF9QRGFhQ2kyZFVsN09pZnZJS09TMnJVeVRRckJ2eG1LSnN2Rm9yM2hjOEQ1a3UxMEFQc
 nlUQmdtOFFTbXJma0xlZGNHUEk0YzlxLW53QnRPM1l0cXExTmhnaHU1WFBxc3h4RXZiMkpOekdXME1DeFJGSGI1bzZLbFg4cExjLWZzUFV1V05lWlV0MnQ3R3ppd1dDc2QtTno2VW1Hb1JicU52SmNKeE56VjUtdnotNWJpUzN5UWkwVlJSczl4elhmN05jYURrQlR1N090Q28wVDFUYWQ3bVE1WTVVREN6UXJGVkR4YS05Q1JubDczLUFvZXp2SUtSWUtYWDZLam5RUjZpNmRJOWNBN2pKRFFFT0thMGY3UHFXcU5tYktMalhSY25ocXZJNW56UU5pYUh5bkUzTXpMb3VOMzEwQ2wtM2d5VFloci1ya3c1UE15VHY4enZpYWtMbER5Vm93dTF4OHMzcmdlSDFUbFp5U0JRUDRIcDBBWFYxelZQQUhNbFU0R1dZdXNOSk0tWk1uSGxBdW5RSVd1WF9pRmxVbmFqMWhyR3pfUFJ3dzRVajF5aVZOLW1UR2laSUdadXRDQXRYeGZUd1hwOE5Lc1pwNThYU2QyeTNfTE4xc2QwZDMydEI3Z20xRE1ybHpqQmFybkdBQ3pEQVo4LXpwUDhhVzh5cXFDQ25GdHdiU1hGOUtiNkVEZzRPckNqZmlpTlZXQTZHSFE2TDlPTnZvemozOXpvaU1nOTdDc2dLY2tZTnUxTXo3NWhtSG14NjdudzZLdFBrcnBBRTFmVDBzeDlYdUtWczhUWEdlUFdvVHREMGRDOUVTRjRsV3RPMnpoV3NsTzhHaWVkQnhjTDVUOTNmWGFwR05sbG12d2lIVWx3S29TSFVnS2JwVWp6MU9WenBGM0l0TGNzVnpoRXlRQXJKakp4THoyNkFGSzVaTE5NUGc0Z2V4ZlRtMmI3YTNkX0g0LUhvMlY0THE4WDVMN1ZBZzh2b1dXY0tfZnBfbERHLWp2STduQzFOYzd0UmkyWnkwU05zY2FKbVQyeE1pZ1ZZM1ZYaG
 JyRG9iQXJvbjZBZkJlZjRibE9PMHNVTFdWMVRobzVMMmc3TEs1alc1am41bjRYSDkzNEYydTNPazhwT211T25HOWwzZDVySy1zWVpYQ3g3NENqVDJmN3BjZ3FiQ2F3cExBMmx2T1VqOVFublRiaVpkQzc5LXF4YVpZWXRUOVc4dEFVQllpQllJTUY3UFl4ME1KaFVWUFBWM1NMR0syTkJURTF2bWM2c1RFZ2l3ODltcTRPakJLZ3hUTTNNa2paRGJzMm1OVktqUjhHODBYYjlKX3VMOWYzRzI1c1RBemdVcDB5ZEItaHR3OGFwRDlmRkhSZzhYSEdDZTVmSHNGTDNpejJvb0d0RTRkeHZSQ1ZDLW5lY3FtRG1KMS1jMEZkVDE4djRWX2ZZcGc3QXpNQzNYT2xQLXNiOE5KS2d6RUZOZldseUtHWXhaRkt6R0RhZnBBYjdEYUloWVpmU2Faa3Ftbnh4eHpDbGVrSTk2T2ZnZElsbkgtUEd6dW5Nb2FvcElxN0lPek1rZGVPazBpUFF6VmtDUGxxc0M0LXZ1enFJODZvLTQxbHZGVmhpU20yeEozRHJWQzBXbGpVUjlPVVZ0R2JoNEF3Zm8tb3hMdVFLMW1Ma2pqLW1yNkQ3d3ktNDBrcmdOV1ZLeEpET0Z4UEhnOVBQc09xQlBvbWpwUXpkNUowYWg1RmdvNk9uODJlVmVRZzdHRzkwUjZZbVBSR2dFVFVQUWl0XzRHZGE0U0xnTVZDSktZdGZvZHY2WWQwZ2pSZzJEVW5qZUtOVUp3c1RjSEhyYWs3MXNRaVNfVmRtekZsSm1CNjVhYjFlSE9VQ2I4SmtYalF1XzR3UmZXdnhuc1VmcExWd1VMMGNmNi1YWmp1RVpIUF9PaGlGWDlzWldTSjBLS1RfVFI4RzFTbWpFcTZUbXhKa1E1RHRnV014OWNwTjJSRlNwcWFyU1V0STJtUWNIM191U0tERjNuY1lhWDl0Vk55ZGpEOFl
 oUkdwWHVQdk4wWHZyejBKTklHLVBWeVlqUUJPdXNvOF9GeV9yX0ctSmVhdVNxMFRpVUhEUVM0Yl96ZDlfQWxMM2wySzZJdzAyQkVhWEhwb2Jpd3pFeEdFeU4weWFVMDRVNjliUEl5TGxIcy1sVVpnMTl5Z3hOR2pzdkxDaktqQ2gzdlhxdDRsMnlZZmFnY0RHSzdWcXpUYzhDWG5wZ1p1bnR3LnRTWm9BN2tNdGItRVJtRWs3d2MyT2c
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultkeydecrypt.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultkeydecrypt.json b/azurecompute-arm/src/test/resources/vaultkeydecrypt.json
new file mode 100644
index 0000000..279b0d5
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultkeydecrypt.json
@@ -0,0 +1,4 @@
+{
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/003a927b194f4f6a9070ebdbdce57c59",
+	"value": "R29sZCUyNTIxJTJCR29sZCUyNTIxJTJCR29sZCUyQmZyb20lMkJ0aGUlMkJBbWVyaWNhbiUyQlJpdmVyJTI1MjE"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultkeydecryptrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultkeydecryptrequestbody.json b/azurecompute-arm/src/test/resources/vaultkeydecryptrequestbody.json
new file mode 100644
index 0000000..9ac39e3
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultkeydecryptrequestbody.json
@@ -0,0 +1,4 @@
+{
+	"alg": "RSA-OAEP",
+	"value": "0_S8pyjjnGRlcbDa-Lt0jYjMXpXrf9Fat3elx-fSOg3dj6mYgEEs6kt79OMD4MFmVyOt6umeWAfdDIkNVnqb5fgyWceveh9wN-37jc5CFgG2PF3XIA6RII-HF2BkBcVa9KcAX3_di4KQE70PXgHf-dlz_RgLOJILeG50wzFeBFCLsjEEPp3itmoaiE6vfDidCRm5At8Vjka0G-N_afwkIijfQZLT0VaXvL39cIJE2QN3HJPZM8YPUlkFlYnY4GIRyRWSBpK_KYuVufzUGtDi6Sh8pUa67ppa7DHVZlixlmnVqI3Oeg6XUvMqbFFqVSrcNbRQDwVGL3cUtK-KB1PfKg"
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultkeyencrypt.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultkeyencrypt.json b/azurecompute-arm/src/test/resources/vaultkeyencrypt.json
new file mode 100644
index 0000000..53adb40
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultkeyencrypt.json
@@ -0,0 +1,4 @@
+{
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/003a927b194f4f6a9070ebdbdce57c59",
+	"value": "0_S8pyjjnGRlcbDa-Lt0jYjMXpXrf9Fat3elx-fSOg3dj6mYgEEs6kt79OMD4MFmVyOt6umeWAfdDIkNVnqb5fgyWceveh9wN-37jc5CFgG2PF3XIA6RII-HF2BkBcVa9KcAX3_di4KQE70PXgHf-dlz_RgLOJILeG50wzFeBFCLsjEEPp3itmoaiE6vfDidCRm5At8Vjka0G-N_afwkIijfQZLT0VaXvL39cIJE2QN3HJPZM8YPUlkFlYnY4GIRyRWSBpK_KYuVufzUGtDi6Sh8pUa67ppa7DHVZlixlmnVqI3Oeg6XUvMqbFFqVSrcNbRQDwVGL3cUtK-KB1PfKg"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultkeyencryptrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultkeyencryptrequestbody.json b/azurecompute-arm/src/test/resources/vaultkeyencryptrequestbody.json
new file mode 100644
index 0000000..f246914
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultkeyencryptrequestbody.json
@@ -0,0 +1,4 @@
+{
+	"alg": "RSA-OAEP",
+	"value": "R29sZCUyNTIxJTJCR29sZCUyNTIxJTJCR29sZCUyQmZyb20lMkJ0aGUlMkJBbWVyaWNhbiUyQlJpdmVyJTI1MjE"
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultkeysign.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultkeysign.json b/azurecompute-arm/src/test/resources/vaultkeysign.json
new file mode 100644
index 0000000..b64e05a
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultkeysign.json
@@ -0,0 +1,4 @@
+{
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/003a927b194f4f6a9070ebdbdce57c59",
+	"value": "uO0r4P1cB-fKsDZ8cj5ahiNw8Tdsudt5zLCeEKOt29LAlPDpeGx9Q1SOFNaR7JlRYVelxsohdzvydwX8ao6MLnqlpdEj0Xt5Aadp-kN84AXW238gabS1AUyiWILCmdsBFeRU4wTRSxz2qGS_0ztHkaNln32P_9GJC72ZRlgZoVA4C_fowZolUoCWGj4V7fAzcSoiNYipWP0HkFe3xmuz-cSQg3CCAs-MclHHfMeSagLJZZQ9bpl5LIr-Ik89bNtqEqyP7Jb_fCgHajAx2lUFcRZhSIKuCfrLPMl6wzejQ2rQXX-ixEkDa73dYaPIrVW4IL3iC0UfxnfxYffHJ7QCRw"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultkeysignrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultkeysignrequestbody.json b/azurecompute-arm/src/test/resources/vaultkeysignrequestbody.json
new file mode 100644
index 0000000..ea66595
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultkeysignrequestbody.json
@@ -0,0 +1,4 @@
+{
+	"alg": "RS256",
+	"value": "FvabKT6qGwpml59iHUJ72DZ4XyJcJ8bgpgFA4_8JFmM"
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultkeyunwrap.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultkeyunwrap.json b/azurecompute-arm/src/test/resources/vaultkeyunwrap.json
new file mode 100644
index 0000000..03b6740
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultkeyunwrap.json
@@ -0,0 +1,4 @@
+{
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/003a927b194f4f6a9070ebdbdce57c59",
+	"value": "YxzoHR65aFwD2_IOiZ5rD08jMSALA1y7b_yYW0G3hyI"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultkeyunwraprequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultkeyunwraprequestbody.json b/azurecompute-arm/src/test/resources/vaultkeyunwraprequestbody.json
new file mode 100644
index 0000000..b3f4efc
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultkeyunwraprequestbody.json
@@ -0,0 +1,4 @@
+{
+	"alg": "RSA-OAEP",
+	"value": "1jcTlu3KJNDBYydhaH9POWOo0tAPGkpsZVizCkHpC3g_9Kg91Q3HKK-rfZynn5W5nVPM-SVFHA3JTankcXX8gx8GycwUh4pMoyil_DV35m2QjyuiTln83OJXw-nMvRXyKdVfF7nyRcs256kW7gthAOsYUVBrfFS7DFFxsXqLNREsA8j85IqIXIm8pAB3C9uvl1I7SQhLvrwZZXXqjeCWMfseVJwWgsQFyyqH2P0f3-xnngV7cvik2k3Elrk3G_2CuJCozIIrANg9zG9Z8DrwSNNm9YooxWkSu0ZeDLOJ0bMdhcPGGm5OvKz3oZqX-39yv5klNlCRbr0q7gqmI0x25w"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultkeyverify.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultkeyverify.json b/azurecompute-arm/src/test/resources/vaultkeyverify.json
new file mode 100644
index 0000000..ceca009
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultkeyverify.json
@@ -0,0 +1,3 @@
+{
+	"value": true
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultkeyverifyrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultkeyverifyrequestbody.json b/azurecompute-arm/src/test/resources/vaultkeyverifyrequestbody.json
new file mode 100644
index 0000000..a34a45d
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultkeyverifyrequestbody.json
@@ -0,0 +1,5 @@
+{
+	"alg": "RS256",
+	"digest": "FvabKT6qGwpml59iHUJ72DZ4XyJcJ8bgpgFA4_8JFmM",
+	"value": "FvabKT6qGwpml59iHUJ72DZ4XyJcJ8bgpgFA4_8JFmM","value":"uO0r4P1cB-fKsDZ8cj5ahiNw8Tdsudt5zLCeEKOt29LAlPDpeGx9Q1SOFNaR7JlRYVelxsohdzvydwX8ao6MLnqlpdEj0Xt5Aadp-kN84AXW238gabS1AUyiWILCmdsBFeRU4wTRSxz2qGS_0ztHkaNln32P_9GJC72ZRlgZoVA4C_fowZolUoCWGj4V7fAzcSoiNYipWP0HkFe3xmuz-cSQg3CCAs-MclHHfMeSagLJZZQ9bpl5LIr-Ik89bNtqEqyP7Jb_fCgHajAx2lUFcRZhSIKuCfrLPMl6wzejQ2rQXX-ixEkDa73dYaPIrVW4IL3iC0UfxnfxYffHJ7QCRw"
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultkeywrap.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultkeywrap.json b/azurecompute-arm/src/test/resources/vaultkeywrap.json
new file mode 100644
index 0000000..bb30400
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultkeywrap.json
@@ -0,0 +1,4 @@
+{
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/003a927b194f4f6a9070ebdbdce57c59",
+	"value": "1jcTlu3KJNDBYydhaH9POWOo0tAPGkpsZVizCkHpC3g_9Kg91Q3HKK-rfZynn5W5nVPM-SVFHA3JTankcXX8gx8GycwUh4pMoyil_DV35m2QjyuiTln83OJXw-nMvRXyKdVfF7nyRcs256kW7gthAOsYUVBrfFS7DFFxsXqLNREsA8j85IqIXIm8pAB3C9uvl1I7SQhLvrwZZXXqjeCWMfseVJwWgsQFyyqH2P0f3-xnngV7cvik2k3Elrk3G_2CuJCozIIrANg9zG9Z8DrwSNNm9YooxWkSu0ZeDLOJ0bMdhcPGGm5OvKz3oZqX-39yv5klNlCRbr0q7gqmI0x25w"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultkeywraprequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultkeywraprequestbody.json b/azurecompute-arm/src/test/resources/vaultkeywraprequestbody.json
new file mode 100644
index 0000000..634f37b
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultkeywraprequestbody.json
@@ -0,0 +1,4 @@
+{
+	"alg": "RSA-OAEP",
+	"value": "YxzoHR65aFwD2_IOiZ5rD08jMSALA1y7b_yYW0G3hyI"
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultlist.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultlist.json b/azurecompute-arm/src/test/resources/vaultlist.json
new file mode 100644
index 0000000..d8c1421
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultlist.json
@@ -0,0 +1,29 @@
+{
+  "value": [{
+    "id": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourceGroups/rg-vaultapilivetest-jims/providers/Microsoft.KeyVault/vaults/kvvaultapilivetest",
+    "name": "kvvaultapilivetest",
+    "type": "Microsoft.KeyVault/vaults",
+    "location": "westeurope",
+    "tags": {},
+    "properties": {
+      "sku": {
+        "family": "A",
+        "name": "standard"
+      },
+      "tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
+      "accessPolicies": [{
+        "tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
+        "objectId": "5a7f4cb9-ce9d-4b31-87ce-f61083c4b0ea",
+        "permissions": {
+          "certificates": ["Get", "List", "Update", "Create", "Import", "Delete", "ManageContacts", "ManageIssuers", "GetIssuers", "ListIssuers", "SetIssuers", "DeleteIssuers", "Purge", "Recover"],
+          "keys": ["Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore", "Purge"],
+          "secrets": ["Get", "List", "Set", "Delete", "Recover", "Backup", "Restore", "Purge"],
+          "storage": []
+        }
+      }],
+      "enabledForDeployment": false,
+      "vaultUri": "https://kvvaultapilivetest.vault.azure.net/"
+    }
+  }],
+  "nextLink": "https://management.azure.com/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourcegroups/rg-vaultapilivetest-jims/providers/Microsoft.KeyVault/vaults?api-version=2016-10-01&$skiptoken=a3Z2YXVsdGFwaWxpdmV0ZXN0"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultlistcertificateissuers.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultlistcertificateissuers.json b/azurecompute-arm/src/test/resources/vaultlistcertificateissuers.json
new file mode 100644
index 0000000..0342427
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultlistcertificateissuers.json
@@ -0,0 +1,7 @@
+{
+	"value": [{
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/issuers/globalsign01",
+		"provider": "GlobalSign"
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultlistcertificates.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultlistcertificates.json b/azurecompute-arm/src/test/resources/vaultlistcertificates.json
new file mode 100644
index 0000000..99e714d
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultlistcertificates.json
@@ -0,0 +1,27 @@
+{
+	"value": [{
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate",
+		"x5t": "K7HXO6YIK6xwCX8W1InUKsJV9Rk",
+		"attributes": {
+			"enabled": true,
+			"nbf": 1509345867,
+			"exp": 1540882467,
+			"created": 1509346467,
+			"updated": 1509346472
+		},
+		"tags": {
+			"selfsigned": "true"
+		}
+	}, {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myImportableCertificate",
+		"x5t": "-qEnW6P9TdfOOXzbNQNS5ZKveRo",
+		"attributes": {
+			"enabled": true,
+			"nbf": 1509231134,
+			"exp": 1541631134,
+			"created": 1509346469,
+			"updated": 1509346469
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultlistcertificateversions.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultlistcertificateversions.json b/azurecompute-arm/src/test/resources/vaultlistcertificateversions.json
new file mode 100644
index 0000000..0480f2e
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultlistcertificateversions.json
@@ -0,0 +1,17 @@
+{
+	"value": [{
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myCertificate/b73ba4610dc24dca946f76933f6590dd",
+		"x5t": "K7HXO6YIK6xwCX8W1InUKsJV9Rk",
+		"attributes": {
+			"enabled": true,
+			"nbf": 1509345867,
+			"exp": 1540882467,
+			"created": 1509346467,
+			"updated": 1509346472
+		},
+		"tags": {
+			"selfsigned": "true"
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultlistdeleted.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultlistdeleted.json b/azurecompute-arm/src/test/resources/vaultlistdeleted.json
new file mode 100644
index 0000000..332785a
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultlistdeleted.json
@@ -0,0 +1,15 @@
+{
+	"value": [{
+		"id": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/providers/Microsoft.KeyVault/locations/westeurope/deletedVaults/kvvaultapilivetest",
+		"name": "kvvaultapilivetest",
+		"type": "Microsoft.KeyVault/deletedVaults",
+		"properties": {
+			"vaultId": "/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/resourceGroups/rg-vaultapilivetest-jims/providers/Microsoft.KeyVault/vaults/kvvaultapilivetest",
+			"location": "westeurope",
+			"tags": {},
+			"deletionDate": "2017-10-29T22:06:02Z",
+			"scheduledPurgeDate": "2018-01-27T22:06:02Z"
+		}
+	}],
+	"nextLink": "https://management.azure.com/subscriptions/3fee811e-11bf-4b5c-9c62-a2f28b517724/providers/Microsoft.KeyVault/deletedVaults?api-version=2016-10-01&%24skiptoken=HY1db4IwGEb%2fS7PsrpQyUCQxiwts0QkMbDHxjo8Xh%2bUrtLgN438f8fJJzjnPDbXwq%2fZVKyRybujoHZjH4%2fDLQw76VqqXDiFN2qZnaKBVWjqNA2h51xA5ZjIfql5VXSvJSwlgUwqY0qzEZmbleJUvDJwapWFnFl0uDZP0Q3etChgk8at86GRXKu0T%2fpJ0rBUpoAYFxWPI17Sv8HUm5%2fja0OkCUx3r9PlJivmxE9CuuUiOcbJjMY%2ffmZfwA1%2bFe17z0t1Sn50t%2fyLM4LKZgknogZubPkvsQOzeQrdwQ49PMRNT4J3cSN9akfCNaDp9%2bOzh%2fERsg%2b73fw%3d%3d"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultlistdeletedcertificates.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultlistdeletedcertificates.json b/azurecompute-arm/src/test/resources/vaultlistdeletedcertificates.json
new file mode 100644
index 0000000..4ac53b0
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultlistdeletedcertificates.json
@@ -0,0 +1,18 @@
+{
+	"value": [{
+		"recoveryId": "https://kvvaultapilivetest.vault.azure.net/deletedcertificates/myRecoverableCertificate",
+		"deletedDate": 1509346545,
+		"scheduledPurgeDate": 1517122545,
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myRecoverableCertificate",
+		"x5t": "-qEnW6P9TdfOOXzbNQNS5ZKveRo",
+		"attributes": {
+			"enabled": true,
+			"nbf": 1509231134,
+			"exp": 1541631134,
+			"created": 1509346510,
+			"updated": 1509346510,
+			"recoveryLevel": "Recoverable+Purgeable"
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultlistdeletedkeys.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultlistdeletedkeys.json b/azurecompute-arm/src/test/resources/vaultlistdeletedkeys.json
new file mode 100644
index 0000000..08dde30
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultlistdeletedkeys.json
@@ -0,0 +1,15 @@
+{
+	"value": [{
+		"recoveryId": "https://kvvaultapilivetest.vault.azure.net/deletedkeys/myRecoverableKey",
+		"deletedDate": 1509335960,
+		"scheduledPurgeDate": 1517111960,
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myRecoverableKey",
+		"attributes": {
+			"enabled": true,
+			"created": 1509335950,
+			"updated": 1509335950,
+			"recoveryLevel": "Recoverable+Purgeable"
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultlistdeletedsecrets.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultlistdeletedsecrets.json b/azurecompute-arm/src/test/resources/vaultlistdeletedsecrets.json
new file mode 100644
index 0000000..1719798
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultlistdeletedsecrets.json
@@ -0,0 +1,16 @@
+{
+	"value": [{
+		"recoveryId": "https://kvvaultapilivetest.vault.azure.net/deletedsecrets/myRecoverableSecret",
+		"deletedDate": 1509335980,
+		"scheduledPurgeDate": 1517111980,
+		"contentType": "aNewSecretKey",
+		"id": "https://kvvaultapilivetest.vault.azure.net/secrets/myRecoverableSecret",
+		"attributes": {
+			"enabled": true,
+			"created": 1509335958,
+			"updated": 1509335958,
+			"recoveryLevel": "Recoverable+Purgeable"
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultlistkeys.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultlistkeys.json b/azurecompute-arm/src/test/resources/vaultlistkeys.json
new file mode 100644
index 0000000..313dae2
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultlistkeys.json
@@ -0,0 +1,42 @@
+{
+  "value": [{
+    "kid": "https://kvvaultapilivetest.vault.azure.net/keys/myCertificate",
+    "attributes": {
+      "enabled": true,
+      "nbf": 1509313915,
+      "exp": 1540850515,
+      "created": 1509314515,
+      "updated": 1509314515,
+      "recoveryLevel": "Purgeable"
+    },
+    "managed": true
+  }, {
+    "kid": "https://kvvaultapilivetest.vault.azure.net/keys/myImportableCertificate",
+    "attributes": {
+      "enabled": true,
+      "nbf": 1509231134,
+      "exp": 1541631134,
+      "created": 1509314521,
+      "updated": 1509314521,
+      "recoveryLevel": "Purgeable"
+    },
+    "managed": true
+  }, {
+    "kid": "https://kvvaultapilivetest.vault.azure.net/keys/myImportKey",
+    "attributes": {
+      "enabled": true,
+      "created": 1509314522,
+      "updated": 1509314522,
+      "recoveryLevel": "Purgeable"
+    }
+  }, {
+    "kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey",
+    "attributes": {
+      "enabled": true,
+      "created": 1509314506,
+      "updated": 1509314506,
+      "recoveryLevel": "Purgeable"
+    }
+  }],
+  "nextLink": null
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultlistsecrets.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultlistsecrets.json b/azurecompute-arm/src/test/resources/vaultlistsecrets.json
new file mode 100644
index 0000000..73063d1
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultlistsecrets.json
@@ -0,0 +1,40 @@
+{
+	"value": [{
+		"contentType": "application/x-pkcs12",
+		"id": "https://kvvaultapilivetest.vault.azure.net/secrets/myCertificate",
+		"managed": true,
+		"attributes": {
+			"enabled": true,
+			"nbf": 1509335314,
+			"exp": 1540871914,
+			"created": 1509335914,
+			"updated": 1509335920,
+			"recoveryLevel": "Purgeable"
+		},
+		"tags": {
+			"selfsigned": "true"
+		}
+	}, {
+		"contentType": "application/x-pem-file",
+		"id": "https://kvvaultapilivetest.vault.azure.net/secrets/myImportableCertificate",
+		"managed": true,
+		"attributes": {
+			"enabled": true,
+			"nbf": 1509231134,
+			"exp": 1541631134,
+			"created": 1509335917,
+			"updated": 1509335917,
+			"recoveryLevel": "Purgeable"
+		}
+	}, {
+		"contentType": "testSecretKey",
+		"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret",
+		"attributes": {
+			"enabled": true,
+			"created": 1509335932,
+			"updated": 1509335932,
+			"recoveryLevel": "Purgeable"
+		}
+	}],
+	"nextLink": null
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultmergecertificate.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultmergecertificate.json b/azurecompute-arm/src/test/resources/vaultmergecertificate.json
new file mode 100644
index 0000000..4511b2b
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultmergecertificate.json
@@ -0,0 +1,62 @@
+{
+  "id": "https://jimskv1.vault.azure.net/certificates/jmskv1cert6/d8f385d3741b4b1cba9c002299e892dd",
+  "kid": "https://jimskv1.vault.azure.net/keys/jmskv1cert6/d8f385d3741b4b1cba9c002299e892dd",
+  "sid": "https://jimskv1.vault.azure.net/secrets/jmskv1cert6/d8f385d3741b4b1cba9c002299e892dd",
+  "x5t": "SQix1jyV9XeF2Q8MCecpUr0etk4",
+  "cer": "MIIEQTCCAikCAhABMA0GCSqGSIb3DQEBCwUAMF4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQKDA1BQ01FIFRlc3QgTHRkMSIwIAYDVQQDDBlBQ01FIFRlc3QgSW50ZXJtZWRpYXRlIENBMB4XDTE3MTEyODIzMDkxMVoXDTE4MTIwODIzMDkxMVowbjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlBbGxlZ2hhbnkxDTALBgNVBAoTBEFDTUUxFDASBgNVBAsTC0VuZ2luZWVyaW5nMRkwFwYDVQQDExBBQ01FIEZvb2JhciBDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwE0Gu/rJlbkqL0ynSbkCdrM+XP4dis/QNPz819ybXXpIX8HfkmAxrpLmfWh36KlflFYgpuV/J5lnJKlRmPWWOFjizAhq0dBijJUdLf6+QuImDjijd/nkO5SeQApZ4D50imTJL81vs2vwAfcCLwdlf7MNrMIfBsyjRSJh/Phjqib6kcYWcz6I6yTfkcsXcUB1JgR8KnQdVy0gYDu1MacHu2VYuS35HpPcQyXRqR1Ky9qh16+OhheRJw03ghEiPMcKbWS5NRgw/l/itoST2Qd6BzJTHUkJaXHNSO9fNF/fAccqECp0ZfaCSrfZs47EcjCv+N7bvrqfFl4BhB77tb7ZAQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCbpjL5XGC3T6gWU8sxCbS0VBmgamyvSHA8jLkWUXQfPirGFwgdGN7394mYViVU0qe6ZqmnhlhqZ1h6VbkBMVwzp3KlRhuoz/fXlW+TFvEC8Q3F+7oUdHn8w3EMyjKA5EbLzRIYXBizdbfEn8eJynjyWEdOaJpMmy9au/oFSqpmZDcxWW2SKq4j+Pqjhr+Ig4BmTVvwR6iEERPYQI4pv0O
 xRa7xA6Hb8NF02TyDzV7k02kN9PL/QO2dh9f3U0YY5XlV1HQzQ/BmavudPT1MiuH0CVSlCHE/JetXdJdWZA4HRiwXJn+5K8MgE5i1hjjXN/dLuaY8vItJzyrgxGRtRZoJA8t7B3QJjDECmey2m0K0qjYu7l1jAVFBWaqDdJQLmnKxViuz0MF4uFqgveW6CZEMcdqwZQ2cmZPlmcjneT0veBBh5qCdFNFM9pYDn0wqt5ruK+vqHkqJdMToBPNaBfGX10ADlB8rKW24eve+2c0iVmorJuTPdOqm2L9NKGpf2scvZZU4n/khkGKihrSOLygeLZ6SQc74cRL35FmzJqqKKpZtG9/a91dkJDz2XUiTO5TialaOU9+A1+Xrzj8LGG9JnB0KizF5dOd5mbZTROr3VCexRxyTrtZLpeJK+lYQLkDQ5ixWnd2sikym4hy3+NZ1g6nE+GQpqSALB4YnsFgUdg==",
+  "attributes": {
+    "enabled": true,
+    "nbf": 1511910551,
+    "exp": 1544310551,
+    "created": 1511911458,
+    "updated": 1511911458,
+    "recoveryLevel": "Purgeable"
+  },
+  "policy": {
+    "id": "https://jimskv1.vault.azure.net/certificates/jmskv1cert6/policy",
+    "key_props": {
+      "exportable": true,
+      "kty": "RSA",
+      "key_size": 2048,
+      "reuse_key": true
+    },
+    "secret_props": {
+      "contentType": "application/x-pem-file"
+    },
+    "x509_props": {
+      "subject": "C=US, ST=CA, L=Alleghany, O=ACME, OU=Engineering, CN=ACME Foobar Cert",
+      "sans": {
+        "emails": [],
+        "dns_names": [],
+        "upns": []
+      },
+      "ekus": [
+        "1.3.6.1.5.5.7.3.1"
+      ],
+      "key_usage": [
+        "cRLSign",
+        "dataEncipherment",
+        "digitalSignature",
+        "keyAgreement",
+        "keyCertSign",
+        "keyEncipherment"
+      ],
+      "validity_months": 24,
+      "basic_constraints": {
+        "ca": false
+      }
+    },
+    "lifetime_actions": [],
+    "issuer": {
+      "name": "Unknown"
+    },
+    "attributes": {
+      "enabled": true,
+      "created": 1511910301,
+      "updated": 1511910301
+    }
+  },
+  "pending": {
+    "id": "https://jimskv1.vault.azure.net/certificates/jmskv1cert6/pending"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultmergecertificaterequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultmergecertificaterequestbody.json b/azurecompute-arm/src/test/resources/vaultmergecertificaterequestbody.json
new file mode 100644
index 0000000..045b0c3
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultmergecertificaterequestbody.json
@@ -0,0 +1,10 @@
+{
+    "attributes": {
+        "enabled": true
+    },
+    "x5c": [
+        "MIIFljCCA36gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAoMDUFDTUUgVGVzdCBMdGQxGjAYBgNVBAMMEUFDTUUgVGVzdCBSb290IENBMB4XDTE3MTEyODIwMDA1NVoXDTI3MTEyNjIwMDA1NVowXjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAoMDUFDTUUgVGVzdCBMdGQxIjAgBgNVBAMMGUFDTUUgVGVzdCBJbnRlcm1lZGlhdGUgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDU1CRXpOEOzNxom8xwA3kYb4kmc3JX8cSuWZKoaPm8KvhsgYOkH+1z4dt2OC/FtSaWJuMZrSTJs/lFmdyE1yuyRBhyqwCK3ZnFxCG10NXiHgj+uHK8ajNJQDitFuz4yLwgp6R91UhuCPPMAKL3eDwC/PPqnT6/D/EPG7eotlokUrpNrhTdz5YYH4VhXwM3VKkIdtSkPQTMftZ0Rbzd0u4sJlsF+RtXVY7/zzg2st0d2vEddpaOENFQfYT7D8C9VsKqo13sClQGoKoPa20a1Yvh65bK2P0SDzhbIu2xQCeis+wC/h0ZZrwCW5/ivCFo4DILk9269LaN4xqpnwJz9QrNFxwglktZm2j7gm4K9BH5a437E6xMvo7WXYwt+0305lLN4khL2ZhagFrvEYG6SLgJwZRWTAE8IsOC9Oyrq0CgpX+KpGkGMpokrgH8aWVCSgQxsUCPJYaBwMgAWepuf3Rx54cUV66vYb7z2NlSvV7JNvtNdXFFjddOfdoQC0QIVOJM1sOgUN/9negFRUtspudB397h+ncvnLnlrg+QaTZNjfCvP4YV+t0eMmlyhBpxIKxPnP0vQCVH9JfpJeZxpY9hFwbxfKcsNLhYHC/2
 2ntbr1UMiIV1HDN8o1gQb6KwyPnS4SVggnf+WPqO4xhXCtwqSDQSAuVe9t03xAs1SGvt8wIDAQABo2YwZDAdBgNVHQ4EFgQURR0ZtFNyLfu1x57+yYiybG149JQwHwYDVR0jBBgwFoAUSCW8FQ+iFqE5L3zx0+2Onc3d1vYwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAMo/VnCd/ndvOfBrI29QhBcwaHEgiC9QUA9u63EhAFGHaThtSd8dFnJLhOQaS2+rYC1nUhkZa03ImceTQpWsGpXOm/sFIAWojzgxqTEopCP5OUxVu6FuJMOGaUvaupGLIJSrUpzpn31NJxThOANEtd0sbMK5fk7sYXLlLNeCOfLu/dytit5jfDsUERJQGTi2YmzIYgFli0ECdswgxAb3b1klKvqOcXZI4K6WkCl5L/wjEP5XygnfyXJ6nMTSLpxuD7dRpqyitmauavfscGpLwYMArx+5gn2jwlq4TIDWdaKi86Oz8VAg+X0C5qBcAdx6k8pFUSjeD2kvykNbEdxBtkD4dgUn5UDmqB2IfW5UiL04cDBaxijDLbsYvjOE+wiXbESxnZf9bQXdeFSemARIWmE6to0uOmdp+snetB88Nw8EQ6faL9aKGBYPI3+KDy1IdMtyU50dMj7BSogZeBHh+6B/1qqlp3VGm5/PBaoyZJLRgx7VQNYFcPjUk0iLaBK7bqJ1CFkr5YX3/Ypjty4u1BD1LxEG2u60Q6PpLgBGGxqXDH6KpNkH2Z9mdagLL+HfZDf73m+J2PD0puLzVVcvzwPRf3nJyyh7ALnG9gd5gl8ksy6uHBizAOmzO0Ize7B8/1he1dSxZQ7wnHIuZ9HSvTvVHv8ST2l7XkKGaB0+BBHR",
+        "MIIFkjCCA3qgAwIBAgIJANPuNc8d4n46MA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQKDA1BQ01FIFRlc3QgTHRkMRowGAYDVQQDDBFBQ01FIFRlc3QgUm9vdCBDQTAeFw0xNzExMjgxOTU3MDJaFw0zNzExMjMxOTU3MDJaMFYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQKDA1BQ01FIFRlc3QgTHRkMRowGAYDVQQDDBFBQ01FIFRlc3QgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOP2me/TzHq4fGve9X2fdDXQFayCq4XZ/mijLkerAPoka3T7lNfO4FI0jvnPNbrf6KZ2YolwiQ04OnFekder5WoVuoQFKZMLCFulHK/+GpyJPdE0fRRrbIsnSRiTvX7fvarHilQKu1B5vKyn6SLzNbvA8+zKJuCiA+ghIxiIKTI3wenzp/uuaWS9+qUXISINJnitgNxD9FnV3CSvAbuzTWfoWDNjS4q7BqUsY6sHCLCmds8kd2ah/CLOmraC7diwA5okE6CCSNzMI7fSzAztRx4BmYW9EgZjwacoWPUp+lGM9ZxRhPcD/euk91Qks10h04EkUXV2HpSVwtNYoSuFBADlNYw7mmn+UpzvG7wBUusDbjhDWG22i5IyOBRuuiUGYgDzleo7v7b9W8ocn5/q4cgEryed7LRxspP7wa614DcHz/6Rmg7CD1dH7zo96EyDl4tlyFB37XQzDtdvs0tU9ahQxFMVj+wcNEnVf7IBv93ukv5YA0sgcfmanLu5fiRBT+hw2ADb4OWNFhR+ZnuTpAtsc27bbjrJ6h6cwYnUFLdYiOVTTFYZjVKLlIhfpB1gNhzZFeiYwZBeU8bvmhD3xASApNyJL93PqTJYHxVY
 v9rfW5hcGkAJz+0gEBXSDEuKekm0vEujdMDMo9Atkv6HR3oeQttd3mRL81PfcxAqQbC1AgMBAAGjYzBhMB0GA1UdDgQWBBRIJbwVD6IWoTkvfPHT7Y6dzd3W9jAfBgNVHSMEGDAWgBRIJbwVD6IWoTkvfPHT7Y6dzd3W9jAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAlLFwOq4VgtDEJ6vpWn21GfweuB2Saz8DYoDBrvcXLGImArfp9n0baeXqa9qqR8Tu12ZF2dEkvQsFnZ6gzobmctw3k4c+Oz0pJ5/iFUTotkqhFf8/RcZCwEk0pcEyAqlQ2LehMyB5UvFhSg54uucj4Ofp1CSjQ59GSe7u9LvHO0cEOdN7jQS9OaAnP03WYktDFTupxD+7xyQsIKePilCKVYgOAlJPKMAaaYcSGMGljUOizLVNYPLaFermcOzdaoyHz6btjq56febLQ2c0VSrL1C2+qOaVbJz0oQSEwt6meADvO8rcP/ZNK9T0kmDxbQzqpKZ31bt/d0iRBygGaFy2vYgybwo3iPGqPTInv2FaTRvWnHP/NlbdNKFwd876hMM+8m9PcNRcIeM+yFwD0aCJtfqorxdN2nNEioP5X08yVnexO9ywkDcAXQTj4RV9TyGlzZRc+1JM1LkhIgLvI6OAOxmrnXnHW08Vzo3yhK72NtnDukU4UcCAHOao6Vq+MJu2Ngb11WBlZulObcEoccxhpx929xIeOj67ZSLOEopP7z+fesjgABc4HQVQQ0v37eiYvVT3Bzz+TklfL/gEVLAk6AqLcFizs9vND2bTrGDgE8AWEX77lBsLGg92ofPXeXZsHsh43m2fRjAnroXQVsziQ0zJgHcA7OmLlB8mkb8fl3E=",
+        "MIIEQTCCAikCAhABMA0GCSqGSIb3DQEBCwUAMF4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQKDA1BQ01FIFRlc3QgTHRkMSIwIAYDVQQDDBlBQ01FIFRlc3QgSW50ZXJtZWRpYXRlIENBMB4XDTE3MTEyODIzMDkxMVoXDTE4MTIwODIzMDkxMVowbjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlBbGxlZ2hhbnkxDTALBgNVBAoTBEFDTUUxFDASBgNVBAsTC0VuZ2luZWVyaW5nMRkwFwYDVQQDExBBQ01FIEZvb2JhciBDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwE0Gu/rJlbkqL0ynSbkCdrM+XP4dis/QNPz819ybXXpIX8HfkmAxrpLmfWh36KlflFYgpuV/J5lnJKlRmPWWOFjizAhq0dBijJUdLf6+QuImDjijd/nkO5SeQApZ4D50imTJL81vs2vwAfcCLwdlf7MNrMIfBsyjRSJh/Phjqib6kcYWcz6I6yTfkcsXcUB1JgR8KnQdVy0gYDu1MacHu2VYuS35HpPcQyXRqR1Ky9qh16+OhheRJw03ghEiPMcKbWS5NRgw/l/itoST2Qd6BzJTHUkJaXHNSO9fNF/fAccqECp0ZfaCSrfZs47EcjCv+N7bvrqfFl4BhB77tb7ZAQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCbpjL5XGC3T6gWU8sxCbS0VBmgamyvSHA8jLkWUXQfPirGFwgdGN7394mYViVU0qe6ZqmnhlhqZ1h6VbkBMVwzp3KlRhuoz/fXlW+TFvEC8Q3F+7oUdHn8w3EMyjKA5EbLzRIYXBizdbfEn8eJynjyWEdOaJpMmy9au/oFSqpmZDcxWW2SKq4j+Pqjhr+Ig4BmTVvwR6iEERPYQI4pv0Ox
 Ra7xA6Hb8NF02TyDzV7k02kN9PL/QO2dh9f3U0YY5XlV1HQzQ/BmavudPT1MiuH0CVSlCHE/JetXdJdWZA4HRiwXJn+5K8MgE5i1hjjXN/dLuaY8vItJzyrgxGRtRZoJA8t7B3QJjDECmey2m0K0qjYu7l1jAVFBWaqDdJQLmnKxViuz0MF4uFqgveW6CZEMcdqwZQ2cmZPlmcjneT0veBBh5qCdFNFM9pYDn0wqt5ruK+vqHkqJdMToBPNaBfGX10ADlB8rKW24eve+2c0iVmorJuTPdOqm2L9NKGpf2scvZZU4n/khkGKihrSOLygeLZ6SQc74cRL35FmzJqqKKpZtG9/a91dkJDz2XUiTO5TialaOU9+A1+Xrzj8LGG9JnB0KizF5dOd5mbZTROr3VCexRxyTrtZLpeJK+lYQLkDQ5ixWnd2sikym4hy3+NZ1g6nE+GQpqSALB4YnsFgUdg=="
+    ]
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultmergex5c-1.txt
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultmergex5c-1.txt b/azurecompute-arm/src/test/resources/vaultmergex5c-1.txt
new file mode 100644
index 0000000..d8ff78d
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultmergex5c-1.txt
@@ -0,0 +1 @@
+MIIFljCCA36gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAoMDUFDTUUgVGVzdCBMdGQxGjAYBgNVBAMMEUFDTUUgVGVzdCBSb290IENBMB4XDTE3MTEyODIwMDA1NVoXDTI3MTEyNjIwMDA1NVowXjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAoMDUFDTUUgVGVzdCBMdGQxIjAgBgNVBAMMGUFDTUUgVGVzdCBJbnRlcm1lZGlhdGUgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDU1CRXpOEOzNxom8xwA3kYb4kmc3JX8cSuWZKoaPm8KvhsgYOkH+1z4dt2OC/FtSaWJuMZrSTJs/lFmdyE1yuyRBhyqwCK3ZnFxCG10NXiHgj+uHK8ajNJQDitFuz4yLwgp6R91UhuCPPMAKL3eDwC/PPqnT6/D/EPG7eotlokUrpNrhTdz5YYH4VhXwM3VKkIdtSkPQTMftZ0Rbzd0u4sJlsF+RtXVY7/zzg2st0d2vEddpaOENFQfYT7D8C9VsKqo13sClQGoKoPa20a1Yvh65bK2P0SDzhbIu2xQCeis+wC/h0ZZrwCW5/ivCFo4DILk9269LaN4xqpnwJz9QrNFxwglktZm2j7gm4K9BH5a437E6xMvo7WXYwt+0305lLN4khL2ZhagFrvEYG6SLgJwZRWTAE8IsOC9Oyrq0CgpX+KpGkGMpokrgH8aWVCSgQxsUCPJYaBwMgAWepuf3Rx54cUV66vYb7z2NlSvV7JNvtNdXFFjddOfdoQC0QIVOJM1sOgUN/9negFRUtspudB397h+ncvnLnlrg+QaTZNjfCvP4YV+t0eMmlyhBpxIKxPnP0vQCVH9JfpJeZxpY9hFwbxfKcsNLhYHC/22ntbr1UMi
 IV1HDN8o1gQb6KwyPnS4SVggnf+WPqO4xhXCtwqSDQSAuVe9t03xAs1SGvt8wIDAQABo2YwZDAdBgNVHQ4EFgQURR0ZtFNyLfu1x57+yYiybG149JQwHwYDVR0jBBgwFoAUSCW8FQ+iFqE5L3zx0+2Onc3d1vYwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAMo/VnCd/ndvOfBrI29QhBcwaHEgiC9QUA9u63EhAFGHaThtSd8dFnJLhOQaS2+rYC1nUhkZa03ImceTQpWsGpXOm/sFIAWojzgxqTEopCP5OUxVu6FuJMOGaUvaupGLIJSrUpzpn31NJxThOANEtd0sbMK5fk7sYXLlLNeCOfLu/dytit5jfDsUERJQGTi2YmzIYgFli0ECdswgxAb3b1klKvqOcXZI4K6WkCl5L/wjEP5XygnfyXJ6nMTSLpxuD7dRpqyitmauavfscGpLwYMArx+5gn2jwlq4TIDWdaKi86Oz8VAg+X0C5qBcAdx6k8pFUSjeD2kvykNbEdxBtkD4dgUn5UDmqB2IfW5UiL04cDBaxijDLbsYvjOE+wiXbESxnZf9bQXdeFSemARIWmE6to0uOmdp+snetB88Nw8EQ6faL9aKGBYPI3+KDy1IdMtyU50dMj7BSogZeBHh+6B/1qqlp3VGm5/PBaoyZJLRgx7VQNYFcPjUk0iLaBK7bqJ1CFkr5YX3/Ypjty4u1BD1LxEG2u60Q6PpLgBGGxqXDH6KpNkH2Z9mdagLL+HfZDf73m+J2PD0puLzVVcvzwPRf3nJyyh7ALnG9gd5gl8ksy6uHBizAOmzO0Ize7B8/1he1dSxZQ7wnHIuZ9HSvTvVHv8ST2l7XkKGaB0+BBHR
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultmergex5c-2.txt
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultmergex5c-2.txt b/azurecompute-arm/src/test/resources/vaultmergex5c-2.txt
new file mode 100644
index 0000000..c1f842d
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultmergex5c-2.txt
@@ -0,0 +1 @@
+MIIFkjCCA3qgAwIBAgIJANPuNc8d4n46MA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQKDA1BQ01FIFRlc3QgTHRkMRowGAYDVQQDDBFBQ01FIFRlc3QgUm9vdCBDQTAeFw0xNzExMjgxOTU3MDJaFw0zNzExMjMxOTU3MDJaMFYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQKDA1BQ01FIFRlc3QgTHRkMRowGAYDVQQDDBFBQ01FIFRlc3QgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOP2me/TzHq4fGve9X2fdDXQFayCq4XZ/mijLkerAPoka3T7lNfO4FI0jvnPNbrf6KZ2YolwiQ04OnFekder5WoVuoQFKZMLCFulHK/+GpyJPdE0fRRrbIsnSRiTvX7fvarHilQKu1B5vKyn6SLzNbvA8+zKJuCiA+ghIxiIKTI3wenzp/uuaWS9+qUXISINJnitgNxD9FnV3CSvAbuzTWfoWDNjS4q7BqUsY6sHCLCmds8kd2ah/CLOmraC7diwA5okE6CCSNzMI7fSzAztRx4BmYW9EgZjwacoWPUp+lGM9ZxRhPcD/euk91Qks10h04EkUXV2HpSVwtNYoSuFBADlNYw7mmn+UpzvG7wBUusDbjhDWG22i5IyOBRuuiUGYgDzleo7v7b9W8ocn5/q4cgEryed7LRxspP7wa614DcHz/6Rmg7CD1dH7zo96EyDl4tlyFB37XQzDtdvs0tU9ahQxFMVj+wcNEnVf7IBv93ukv5YA0sgcfmanLu5fiRBT+hw2ADb4OWNFhR+ZnuTpAtsc27bbjrJ6h6cwYnUFLdYiOVTTFYZjVKLlIhfpB1gNhzZFeiYwZBeU8bvmhD3xASApNyJL93PqTJYHxVYv9rfW5hcG
 kAJz+0gEBXSDEuKekm0vEujdMDMo9Atkv6HR3oeQttd3mRL81PfcxAqQbC1AgMBAAGjYzBhMB0GA1UdDgQWBBRIJbwVD6IWoTkvfPHT7Y6dzd3W9jAfBgNVHSMEGDAWgBRIJbwVD6IWoTkvfPHT7Y6dzd3W9jAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAlLFwOq4VgtDEJ6vpWn21GfweuB2Saz8DYoDBrvcXLGImArfp9n0baeXqa9qqR8Tu12ZF2dEkvQsFnZ6gzobmctw3k4c+Oz0pJ5/iFUTotkqhFf8/RcZCwEk0pcEyAqlQ2LehMyB5UvFhSg54uucj4Ofp1CSjQ59GSe7u9LvHO0cEOdN7jQS9OaAnP03WYktDFTupxD+7xyQsIKePilCKVYgOAlJPKMAaaYcSGMGljUOizLVNYPLaFermcOzdaoyHz6btjq56febLQ2c0VSrL1C2+qOaVbJz0oQSEwt6meADvO8rcP/ZNK9T0kmDxbQzqpKZ31bt/d0iRBygGaFy2vYgybwo3iPGqPTInv2FaTRvWnHP/NlbdNKFwd876hMM+8m9PcNRcIeM+yFwD0aCJtfqorxdN2nNEioP5X08yVnexO9ywkDcAXQTj4RV9TyGlzZRc+1JM1LkhIgLvI6OAOxmrnXnHW08Vzo3yhK72NtnDukU4UcCAHOao6Vq+MJu2Ngb11WBlZulObcEoccxhpx929xIeOj67ZSLOEopP7z+fesjgABc4HQVQQ0v37eiYvVT3Bzz+TklfL/gEVLAk6AqLcFizs9vND2bTrGDgE8AWEX77lBsLGg92ofPXeXZsHsh43m2fRjAnroXQVsziQ0zJgHcA7OmLlB8mkb8fl3E=
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultmergex5c-3.txt
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultmergex5c-3.txt b/azurecompute-arm/src/test/resources/vaultmergex5c-3.txt
new file mode 100644
index 0000000..5ac2516
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultmergex5c-3.txt
@@ -0,0 +1 @@
+MIIEQTCCAikCAhABMA0GCSqGSIb3DQEBCwUAMF4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQKDA1BQ01FIFRlc3QgTHRkMSIwIAYDVQQDDBlBQ01FIFRlc3QgSW50ZXJtZWRpYXRlIENBMB4XDTE3MTEyODIzMDkxMVoXDTE4MTIwODIzMDkxMVowbjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlBbGxlZ2hhbnkxDTALBgNVBAoTBEFDTUUxFDASBgNVBAsTC0VuZ2luZWVyaW5nMRkwFwYDVQQDExBBQ01FIEZvb2JhciBDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwE0Gu/rJlbkqL0ynSbkCdrM+XP4dis/QNPz819ybXXpIX8HfkmAxrpLmfWh36KlflFYgpuV/J5lnJKlRmPWWOFjizAhq0dBijJUdLf6+QuImDjijd/nkO5SeQApZ4D50imTJL81vs2vwAfcCLwdlf7MNrMIfBsyjRSJh/Phjqib6kcYWcz6I6yTfkcsXcUB1JgR8KnQdVy0gYDu1MacHu2VYuS35HpPcQyXRqR1Ky9qh16+OhheRJw03ghEiPMcKbWS5NRgw/l/itoST2Qd6BzJTHUkJaXHNSO9fNF/fAccqECp0ZfaCSrfZs47EcjCv+N7bvrqfFl4BhB77tb7ZAQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCbpjL5XGC3T6gWU8sxCbS0VBmgamyvSHA8jLkWUXQfPirGFwgdGN7394mYViVU0qe6ZqmnhlhqZ1h6VbkBMVwzp3KlRhuoz/fXlW+TFvEC8Q3F+7oUdHn8w3EMyjKA5EbLzRIYXBizdbfEn8eJynjyWEdOaJpMmy9au/oFSqpmZDcxWW2SKq4j+Pqjhr+Ig4BmTVvwR6iEERPYQI4pv0OxRa7xA6Hb8
 NF02TyDzV7k02kN9PL/QO2dh9f3U0YY5XlV1HQzQ/BmavudPT1MiuH0CVSlCHE/JetXdJdWZA4HRiwXJn+5K8MgE5i1hjjXN/dLuaY8vItJzyrgxGRtRZoJA8t7B3QJjDECmey2m0K0qjYu7l1jAVFBWaqDdJQLmnKxViuz0MF4uFqgveW6CZEMcdqwZQ2cmZPlmcjneT0veBBh5qCdFNFM9pYDn0wqt5ruK+vqHkqJdMToBPNaBfGX10ADlB8rKW24eve+2c0iVmorJuTPdOqm2L9NKGpf2scvZZU4n/khkGKihrSOLygeLZ6SQc74cRL35FmzJqqKKpZtG9/a91dkJDz2XUiTO5TialaOU9+A1+Xrzj8LGG9JnB0KizF5dOd5mbZTROr3VCexRxyTrtZLpeJK+lYQLkDQ5ixWnd2sikym4hy3+NZ1g6nE+GQpqSALB4YnsFgUdg==
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultrecoverdeletedcertificate.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultrecoverdeletedcertificate.json b/azurecompute-arm/src/test/resources/vaultrecoverdeletedcertificate.json
new file mode 100644
index 0000000..d75a38a
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultrecoverdeletedcertificate.json
@@ -0,0 +1,52 @@
+{
+	"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myRecoverableCertificate/42f1b607074a4531b4f14fb4447d4346",
+	"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myRecoverableCertificate/42f1b607074a4531b4f14fb4447d4346",
+	"sid": "https://kvvaultapilivetest.vault.azure.net/secrets/myRecoverableCertificate/42f1b607074a4531b4f14fb4447d4346",
+	"x5t": "-qEnW6P9TdfOOXzbNQNS5ZKveRo",
+	"cer": "MIIFNDCCAxygAwIBAgICQ0MwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEhMB8GA1UEAwwYRm9vYmFyIEludGVybWVkaWF0ZSBDQSAxMB4XDTE3MTAyODIyNTIxNFoXDTE4MTEwNzIyNTIxNFowUTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExDzANBgNVBAoMBkZvb2JhcjEcMBoGA1UEAwwTdGVzdHNpdGUuZm9vYmFyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKlPGmdiqKloSbUri9gvo2lyS0x2axSpeTfgIxI4Qnqhq8wMkih+SuO8+2rzIUd3S9nYqVww6yy+qHiJLXi3DKVYM/jgJnF+PlUoXxulD1abN8kX+TCKuHeAfTSIjM6WSgimGqW3hoB6bYHsaUFaAIg5FYbg5/IpbEMnD2yjU4M/nHVbxRwPqHGYdYfSqGDeHYjDb8GdA/+N0JDEoMVflTQKrDzq9R0lwOg+kICem1D+kww9ajyTu/7QdE8oOhAzuqFIVkCyZwpkrs576ng34mP04vpGcBs8YiKODydtFl2p5labXr5la0LVpLJL6rUkM3EhWOhQ0s+fCGtfrlmFRMCAwEAAaOCAQ8wggELMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFNPsyKBhnCjL7pVBLRYK3jaoZ8PfMHIGA1UdIwRrMGmAFAf9rGqvLeJheBNJOHBKTG3Oz32PoU2kSzBJMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEPMA0GA1UECgwGRm9vYmFy
 MRQwEgYDVQQDDAtGb29iYXIgUm9vdIICQkIwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQA4sFKv4JDZ0+CVjcHL9bkTpk5I2L45xXk3d7GrhBpGveyy8vlb/g7P0qyAVo0UnB+eRTtwk6GTsJdzz4FBem+FDq8ZO/N51Rn4ZJQbDg24eGErK4rpbOo5OQgKKhTKjjBYwsAsIOkJ1TKQDQ3++Kqw3cWh/vlCWoxGPSMOeU/Iro34IWzSeEREMamYo5kIYq2ERCcVSoTcYB87cTYMU+ORyQSEx/OncDuAKm45ub92By5NpeFVMk+8ibifgzbNJHVnaZUVg8ScdM1A4Db6WAL0SUsYIawrnQ+TENs+6Ekls+wu8G5FAmbtOEV0WOafGvdcnELn5IPXlkvLbiRx5EChG+nF3XrLgn3dBQwP2cGrI/IPRm1XfaaBAkMSkf6St5TX3C40g1CGcNSVoKBYBB2Di+hPXwTHImGggR1JF34ljHCokMoPxmr7lP9pam0dhP/SSpIwxfsvDJylBgUEqTr3tsVDIDfMtJjudK7A7H1HMoqEiqlzRvJIEZ1koOxANFcQ1f9am2PPUNFvfK9IbLQlV8d4k1w6xBAeOVke79lJI9pTTCSVb+PTDniEL79JXjmjQUoKE4zo1u41d+wLu3dEGM27GI7BdLYt6bRsolZvrbey7Nn4c0t4ug4B4GTd1SLLVJns/IRLBrNr1anBJ7u9WFruBUEWwtdxAwSoXdtIIQ==",
+	"attributes": {
+		"enabled": true,
+		"nbf": 1509231134,
+		"exp": 1541631134,
+		"created": 1509346510,
+		"updated": 1509346510,
+		"recoveryLevel": "Recoverable+Purgeable"
+	},
+	"policy": {
+		"id": "https://kvvaultapilivetest.vault.azure.net/certificates/myRecoverableCertificate/policy",
+		"key_props": {
+			"exportable": true,
+			"kty": "RSA",
+			"key_size": 2048,
+			"reuse_key": false
+		},
+		"secret_props": {
+			"contentType": "application/x-pem-file"
+		},
+		"x509_props": {
+			"subject": "CN=testsite.foobar.com, O=Foobar, S=California, C=US",
+			"ekus": ["1.3.6.1.5.5.7.3.1"],
+			"key_usage": ["digitalSignature", "keyEncipherment"],
+			"validity_months": 13,
+			"basic_constraints": {
+				"ca": false
+			}
+		},
+		"lifetime_actions": [{
+			"trigger": {
+				"lifetime_percentage": 80
+			},
+			"action": {
+				"action_type": "EmailContacts"
+			}
+		}],
+		"issuer": {
+			"name": "Unknown"
+		},
+		"attributes": {
+			"enabled": true,
+			"created": 1509346510,
+			"updated": 1509346510
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultrecoverdeletedkey.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultrecoverdeletedkey.json b/azurecompute-arm/src/test/resources/vaultrecoverdeletedkey.json
new file mode 100644
index 0000000..f9c45a0
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultrecoverdeletedkey.json
@@ -0,0 +1,15 @@
+{
+	"key": {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myRecoverableKey/274f6c69b94b41359a5932226425eb43",
+		"kty": "RSA",
+		"key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+		"n": "urhKlXbEGvYetOSH-GLytvSJ5djS0-5SKBtFOlJ2885PE0s_ZbnkRURDm2fImv_RV763HKSUQbEolQNs8I99N-3uCkrDStVZ6MPii9-0U6lrEkX7LrMRNYCfPAaSSZhSjCbsyqX9Y-N_A5Jz9uHNuXvpjQ9N7ojUK7fqqhnJKcJ6l6YsGOhGCD3uei4SL5GzbSAn2auIK51lj77UXjBZaudnNWTiKaCbTAmSmEe13DOJkg82_7Y1eWea3NJn4T2nY8WqRJCp4hzBsPBmFXjE1lgFWcSjm_afiSb0mCUP7v7tSOLR3xUBv9WgMO7p4_ce_--A9ZWP418Uqq0COcHAWQ",
+		"e": "AQAB"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509335950,
+		"updated": 1509335950,
+		"recoveryLevel": "Recoverable+Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultrecoverdeletedsecret.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultrecoverdeletedsecret.json b/azurecompute-arm/src/test/resources/vaultrecoverdeletedsecret.json
new file mode 100644
index 0000000..e36c591
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultrecoverdeletedsecret.json
@@ -0,0 +1,10 @@
+{
+	"contentType": "aNewSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/myRecoverableSecret/d7194ca6b0214d0ba382353109cd7e58",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335958,
+		"updated": 1509335958,
+		"recoveryLevel": "Recoverable+Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultrestorekey.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultrestorekey.json b/azurecompute-arm/src/test/resources/vaultrestorekey.json
new file mode 100644
index 0000000..9ca672e
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultrestorekey.json
@@ -0,0 +1,15 @@
+{
+	"key": {
+		"kid": "https://kvvaultapilivetest.vault.azure.net/keys/myKey/1374543b3de34500a97d075991ee3893",
+		"kty": "RSA",
+		"key_ops": ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"],
+		"n": "tY2pzXPfU7NFYCWvZB1gJNAetkgJ7Qi75lTVOzVns9KjFFo6e_F9GSETZbAYl5oMwfLtdqQqT5fxzWDk0sYlz09HXvCCoYmbzobd3gJ6-WLAqhtCbBikr5HAIlCzy_UqKT--WhEw8AT_EJFBPIY9xNktqnaNZuRBmjmXinzT02qUmBZRsAdJmaYfG9IZSmToOkb54OytI5TreWN0JvceoQ3GSeFLMC5PUmXP6HmZliOzBBHWnXNq3H7a3qfWV3rxT2QpbrIuz18ZqOVp7o5868kN8knKytVcqEzmdiQUdabkqbrwuh-z_IEre9AqTfw6OjUUmLjs4lyKcpWLYFh8KJuML1ub-8u0VgNGwczUZ7aAld1iwGMsoMmQfMRDOnv-9pqtY-y40ZWpBGXpzFV-IvtKHnqQk_vWqowpE8xwx7yZ74z9XNgS9TmkVpcC-ONbEfNE1sez0Zf-RZ9eOm_7WSxxH6OJYtJI7wotBXYoy1bJaqo7mgHs1IUOFhSE-Evj",
+		"e": "AQAB"
+	},
+	"attributes": {
+		"enabled": true,
+		"created": 1509335925,
+		"updated": 1509335925,
+		"recoveryLevel": "Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultrestorekeyrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultrestorekeyrequestbody.json b/azurecompute-arm/src/test/resources/vaultrestorekeyrequestbody.json
new file mode 100644
index 0000000..4fd7296
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultrestorekeyrequestbody.json
@@ -0,0 +1,3 @@
+{
+  "value": "JkF6dXJlS2V5VmF1bHRLZXlCYWNrdXBWMS5taWNyb3NvZnQuY29tZXlKcmFXUWlPaUppTTJJd1pqZ3dZeTB5Wkdaa0xUUmlPVGt0T0RVeE1TMWpZVGRrTTJKbFlURTVNMkVpTENKaGJHY2lPaUpTVTBFdFQwRkZVQ0lzSW1WdVl5STZJa0V4TWpoRFFrTXRTRk15TlRZaWZRLk9tXzl6QnhwTEw5a3NCVmNfR1JLUHR5akZ6R1JGV3BBWFVvVm91dmdNQXNEcFo2UUp1QUloRzZJWFB4ZHBOUDNlbEZFc19Ld3RpMlBhRXNEQWM4TEVQVHZvVzlSRmlROHZTY3JiWHlKcFNROXJSS1V5NlQ2SWo3UEpDV3Z6alp5ZlNYbklPNjRYMUtzRThFZWNKRDdudDRhN2tfZkpiSkw4a3paWnhXWFZLZnZwZEQ4c3dobFdOLVhMU0RsWDFORmlYQk5ILVRoU1BDbkNMOHc4RjlpV0o0LWFxeXozc0ozRDAzb3JzTHdKczFBTF9LN1c4eUlUNlprb3Azc20zeGlBb2pYZl92WDdOLXhQMUtKMU1tRlFnQVpaMmNpQWdJc2UzVDdoWFhsa0RaNGJqSXpYa2ZocGg1YlNuUEkzQU5kbDRUaXZkdVlxM0lCdlZrQ0hpWnY0US5pLXNxb3lQVVNHdlM2SVdUdld0MzBRLkR5N0U0cE9vanU3bzlMQ2dkcVYwd1c2MGxkOWRaU0tPN0wxWXhid1RMQzd3Z0piSmhlNno5b3VWN0FFMnBMLXFFMUhLclI3Nk9TVTJ3c1FBMFZuTDhlR1RnVFk0TWJOaklzSERraGFSUWN4bGRjOHpGWEVxNzNOWlhPWE5vaWJ2QVhUcm9oX3JnS0plNVFYWE1MSFJ6T2lVWEtqVEU3ak11Qm0zejNMRm1mQ1pQb0xWTnpNT09mdmFwQTh5XzNEUFk1OUdxOUFzWlZsakNpTWoxUlVrQV9QQTBwR
 EUwRU8xd25pV0dIb0t1R3h2N2hLb18wcFVMMWRPalZrNFA1ZmRWRmtGOENVemVvSDNja29xbUxMRmktQ0Nra2E5Q1JZcUE5ekZFckJsZGYzQTlIOVNuazdiUkNhb3c5Tk0tdXFBbkF1OWF6U3JBbnZZZ1NUT0VFUjFvX01Yc1Bqc1loTHp0NFZoTGx4RjlQNDROSU1ZTjEwWVZBYlVIQ0FaREZZejl5d3l2YWJPSXF1bjUzc25DZTBYVjBaWndabFNmSktJUkNsMk9zU29vVEt2OWx6U2kwOVFlUTRxb1NCMFdXSThobjFGd1pYV0RhdHNSNFFxOTB4RXB1bFVyWV9mOWI3cnNSem9jYmF6c0cxek50a0t5bjNVY29fR00yRjJDclFybi1uRVlXMkZRcVpkMlpHT2Nnbk52NFVyWmMxRjB5MUpTdXgxS29qdHBkZDgzR2JPd2s5dmVlSGs2NXlCdmtMTUYtcGtUWGdFS0lZeVN5ZUM4ekdndVZJOHhrX2VndXhQVlhCVVBMWk0xTHJ3U1VDc2JhaGR3WnRZZDN0R1dZVjZsSzhyT1UtQjhlWllvRTd0QUF2RkZxNEJ1R0U1TXRsdHFSRVpkcHlkOWFkTDRVRkttZ05YcTlvNWVqdWJuSmV2RWhRQmhVRXpRLUdCZ3RudVgtSlNTYjBDVllxV3p0NVU2dzJpcVNwZzBNMnQ4WG5OQXN5WTlvYXVBbVhuUGhMZ3lYYWpaSE1TS2FqNjIwOHdrZVA5ME1CSkt1anBfSFhJaEttSW1TOXVwLVY1NXBHRXdMQnhfYlU3TFpwYnhIcm14R3VOTE9pNXhJUGt3QkpTdXFZRlNSMWdaUU5lb1ZHUncwTW5TQW5HYnJ3eE92NFVjVlpUUjhkVTI1Y0NTOHpENjNwQ0ZUdm5CNllyN0pwcGhYekd3SFZYeTM2TkJPdWVuQ2NYQUR2QXNXS2M5a1RQeTlEalVFRFVQd0QydUpZQmhqaV9RR2
 taYjhfQnNwdURUbWM1Z0Y3TkdsV2NPRTBqZmFwUi1CSlJhUXJENFhxeU95NTRsTUxCZlNSTFBIN0w4VnMyUTVvc0FfVHlPYUoxa3B6dG5iLUhyNTdSQ1E4UWNsRnd5eVRfakpLaXFQRFEyWFlrZ2NjMmdkZlAtS29GNHFHSl9HRERMN3NVaThKeWRnOFNBdDBoRGdUOTh4Zk1URTlQc0twTU9FQUkwWF9KRWdsRTFwRmNxbVFkT2NOU2Z0VUxRaEFPVWd6Qlgxb1UtYTdiX2gtX0l5RVgyb0htZDdaNUJJRV80b0ZEYWVMaXh6ck9BWFdTTzVFZ3B4U0pYUXZ2ZEVZUV9mNHhPVFU3SExmUWkyNEthdGNUTWJJczlBVU1UY1NvVUhIY0RLWVhZbTl3SWR0RXR3MG5mbFp5YVJMYkx4cVJNTzd0X1ZLbnJ6OGVOZ2dJWENBVno4dmJmXzk1VWdVNGJUTzZDLU9BbHJqbUZNbVNzaEpwY0VhRjAwaGx3MnZud2s2QWlCRTlWUzdOYmJFb0JVZmtuaWJFeVJ5NHp2MmZtMWxhRkJnYmUzWV9QVEtHQTlVOGJlNGJsb2lkQmlVOGwxUS1qT3oxeFRNVFUybkpnYkJ6b0xzWEtadEw0d0ZDTnlNVFN3N1pyX3c0aDJjUzU4UHZsVWlYalRhcGpNdTJzYWJtdVJnVXROTjFlWVdxZjBRSEVFdGoydE5nd25TaHNBOHBRWkZKaXp6Rlc2VXpKRXdPbnN4S25tcjFEQktnZ1hsZFFtdmlxWHU5aE00MzdWcUJIeVA2SFZ1dUdiOEUtTlM5WlBPekJWMEFrcTM2QXVJcWNIMXUwTm1NT0laaXR1WVhFNXp3UGlVczJxSmMzQ1BHbVdZQ3d6THNibF9YRkx1dU5udXlIa2VGN1cwOGtxNjhBU2FBMTVic3BQMDU1a2UyMlRVbzNqVl9PeHRUY205OUdBcktGOE82elBjTlQyQ0xNdjkwZ3I
 1SEx0MVg1WjF4WFNTTVczZ0NRVEs0TmFtNUsyTzFUNXdoTWtPdnhYYmdkb3Jwc245amhGb25aaC00VG5RczJiUmMxVTM1Q1BudmRVM0s1dUVOTzNxZGVxV28zR20xeFRMaUdJSUhsNkdpX0dFdnlqWjdEQzRjeVhlYkI5enRiMklLQXZLVFhyQkF0aXd2bWF4U2FzNFRXVUc5Qy1RYUxLZnpRdDZwVm82NU8wLUZHQ3VLSU1Fc1I4bm9lM19jVVVJNzRiYl9sTVFWdnNyOW9KamJtS1RrWVBhREViQWZCd0FLdGw2dzdWUER4bGt6UmFZVTdPVENsdmFhMTVZQ1hJSzQ2V2hkd2QxMDNoR0x5UjltWlFSdmcyLWhfN0tESzNSVWRzcjNtTlBEYmpCcU16U202MldDNnZTclBVdENKTks2UG1ZWjhfT3A4bXp0U0xUbDBLWlN4dWt5U3d1Y2hfQXZLcGdqa3ktQmVfS0JXNTdka05TT2JlWmZKZElRT0xkSVcwZExqd1BWeTdENEhPS3FyWE1JRGdIdkRIR25zWFBZb0VRZG9wX05BOFZfTW03bWp1blhtZWoxVDI4cTN5VTcxRDEzVUxhdXNwVnNQVHBTcEVDX19mS2ZVSUF2dnI3RmszN19uSFU2QXowSndhNklSU19mTUZHamRuSDI5RXBUcTZGRDdaY1hPZzMxSGdNMHNtNUZlUnkxaHFqUUdIOTRwd2JpUktfWXhQaWVzZHd3cUh2TE1MZE02SU1CU0tuZlVfdTV0bkJISEV6NzZvQ0dHSEJmM0ZnTzFkX1hZZGhtVDZIR2FRUmZhV0s5QTVRNkpUbHBaWUpkOHc2eVlLSDVvNktFR01TWXRKbDFhM29KQ1A2Q0o5Wmh0R0ZWcHlQYlk3M1BkenozR2xvdFlqOE8zYzgtT3BxTm0xaEc2MU1IeEFnNkJYZHgxeFBqZ1RuTVRHbUtTYUplV0d6OWdHc2JDWm52RmlwSExj
 bHJQVHczVVR0NThOdmpkcGJtOGV1VVdxUDM3RVZzMFFoVHZkNzdmc1duZTgzZlpsYkh5SHF1Y3gwWEtBRmNlMURZNlM5Vlc1Ulp4akU4bHJHemxpVXplTGtsS19wVG91d191MXBVWktLV25jTzJ5RzlrZ3dOT0pkazZiWVlPb1dCRGhVNHU3TFVZR2tETENFaVJrSGRIeVBQbjJBeGNXTGhQYml5cUZ2RWRtNUNMMzMtaHN0OHFRNC1QYldfQV85QVFLZ2hoLXJfUUE2Wjlzd3F4QWJFeWI5R294TUFPenAzMlBoaVhpOHRxTC1qQ1ZqSEFnRTdqYm1jRVBVQVh4QlZFUXNLRGd0MFFRM2RscG0xSUd0OU9fMzNwWEIwUmt1bUxYT3pnWjYzYzNGNVp4ZlRyTGtZZ2MxM0p5dXdjb0Nxa0VxS2RxY0F1N3RFODUtSnkxZnpNTHQzLW9wXzBOWUdqallIZTQxU2drdDZjWjdnQXRFeHlDek5YRjBZcG10WFlralI2UTF0dnFIczhRWU9GaTF4RFZBb01pUjBMczFjRGFRcm5WMEhVZ05QeFJSdUlaYld3dWc1OE9QYnNvUDZYdHRhVGo5RU9yRlJEbUR3OVhiSjhxWEV6YkQ5ZXcxUjVsWGVPZWZZcjVnQVlIU1k0X2lTMXR2Qzg0QkY3RGtYUjVDVUxWZXNkTDBwckh6RFA5MHZfRC1oemJSUDVBNFJMM0RLNmFGN3Z6dFktRlRJSnM0bTNKZ3NyVUp4WkV4NjFMQjRIdGJKM2RTMUYxTjJ2YTJPc2VBSWZ0dkhESWFyV21tbjhBZy12T1JhTW1kWC1pT2YtajI2dWlYV3VvTkNPV085NnM3ZWsyUzRoQ1psN0lPNzVzQThkZGprbDNtaFhrSmEtaVBZZk9Nb3pKWDV5WEREX1E2WDg2YzNvZThLZEdVODJCbGluNXRycjRUdlVXcHBEYVZoYzJ6MENyclN4dko2ZjBIb2ZrY
 VVNTW9seVlpWW1rSEdpVWNzdmRNbDhMS1MxVEZoWVZiVW9xNUVyYWhKdW0yTjlqdk9DOGd0Ty0yempNR2NjbkEwUzhqbTR2SFVTRDV4MGtkWFotY0NrZ01HSWM2LW1LaHU1YVRpTTFWX01mN3dteTlrdHZITVRqVUM1d0kwU3JMU1F2RnNWZUZHamthLW1qajlsUEkzMFhORmRLajRTR3A5T2pmclRyYnhfeV91emZ5b3NudGVvRHF0RURmVmFSSFhVOF9pQncwWEdZUDBIaGloR3VlczdrdTZJVlE5aTVjVTBNSTRKR01vR0xJRUJKUG1NckxmamJMdkdVWTgzOWUwc0s5NFNBVHJseXo1YzYyeUloTC1xdEdIeTJBMmxxRUhnVnNvQjF0M0J5bDhwME1OSWJId1ZaUlkxcFBDdFBJVmctYWJCZ1ZVSGZneC1FSDVhVlR3QUZGekw5YjBhVUF5eEhnam1XVTlkYjJTMGJ2S3lKaTh2UXJuOWVnYkt4QWM4OEw1NDNsY1dUU1BIOUQ2Zmk5Z19hY0JUUXF5VUt6S3JxYmJUUGxMNWxQdGdfazFhd3ZLNmhNUDZfR0FLUi15a3JzTlcwVUZHaFI0WDNkTE5DNnFUdGdNaXFnYThKN1dVSjdMZUtaRTV1dzlzQlVRemJSdUxjUDFSMnEwQ29DSHdRYWJIRGhPUkdNMkFyMF9HbmIxZVotRXNNSXJHcWcxQkY5T2FMMTdZWE9RWXRhZXBhUEZGcXI5TS1FTHpEWEtYWlBFU1RVZGZqU1g0RllvMFk5cXNTUGdnTjlhajNnMWxfYVNoclA2SVdxZjJrRWoxTjNIMWVaZVUzQjZrWHBCUFV4VXV0LXk3MkU4Q3l6czJtUDgyQjRvNW9GOUVncldIZXF6WGw5XzQyVDFYNlB0Y0l2TGZ2d2hzd2FTVzlGamxVbC1hczVQbUtxSlRtUzl3bE9CdHZybDh1YWdIT1psMW1zZ3Ezd0hWTG
 VxMmRQclc4UmRjZXJwSTNySGVDZGVzZGJUb3pnS3FuTVhSSVNmZWtvQThLRTkzWFRDOXl1SkM2NmdMcTNJbkJnZ2NUMFp3X0pmWldvN2tmb2dyd2dMRTYwTm9uamxvMERGWFlCRDlKcDd6VGFDRGFGLUZRbHZ5MFdGb1YzRlh2dDllMDdJajBTN0c3THZ0OXVOaW1sbnYyazZOUUJxemlLT01zSjVRQ0pYOEFsbnMwNk9rZG9aVmIzV3Q5MjRQcFM4U0N5R3JnYWVPb24xTHhiMXp2QkIyZDQ5cGJ4a1ZMQnZjcnpFZkYzbExSOU9NdThGNERjS1VHcnBiMjUtNHFQQXVIZXJCcEVEWVBDY3p1RWJaQktZakZQSlozejhKNk45S2l6MktaQTQ0Z3ZKVE42QW5rcThnXzRJMWRBNzRtME9QMEcxd3dtd1pQQU10VXJqYmJ2TVNtbHVjb0FibXhSbDNPd2hFbGRoVFVwdi1iQ3d6ZHVqYnNPMVBsYWI5am1LQUZZaFloU0RZR0FoOTRRRVJ1dkd2VTJnQzlzRmYxTGFTM0Zaa24tRXIxWmgyallpc3BwMlFFd1FBdFlDcmMwaUptMlYwOF95RTVheEVJSnlpZzBhVnFZQ1FiN05GS2diX19LRF9uMi1yN2YwX2RIOFgxeUdJcXpiNzNGbHRCU05RRG1oUU1TdVlVYjlMbHFlREhuNVFtZ3JpQW02d3kwR25QMmE2X2k2TGZWejhMckUxVm94d253V1h4SDlSeDVuTUdpREFvRGxaVlIzVzd1cW1BZ0lMaGFvNldXb0xuYVZSU0pRUTFybTY2R2dCTENUa1QwcE9kS0Vpelc4TlpwXy00Q0tWSHB4ZUpRVFBodXo1cXBmalM4Xzh2M3Nkb0lHNko5RkxwMUludnlmTnFIM0djZ0sxbWZZbWZPUW42cXUybU4yckpiMDg2Y3U2cU5VZnpRcXJqQVpwckdpQ2pCU3Z5T3JwdnZCdGQ
 xVHBQTXFMZEZxbmtGeC1GSTdYWDJocUtoRGFyX2R6QldTWXFPSE9adG50d0hocGNWVExLeXdqQTl0MmxGWTFuNFJtR1l1SHlKdlhVeFZvc05BU19nd1EzM015U25lTk40am5aTWFCNFMyM2lNV0Y0UktSaUlSXzAtTV9Nc1kwbDZmbUxOekZFbFJrUE1LcWFsOHFmbUo3VDkxU2IxdkJFQl9WX052dGxlVzd2VnlaSXBpbV8xUHJ3MC1oMXBMcXVXVDFodll4SWNtbHllSldIUy1NQURnaVdWbnlFOVJBOHpXWFI3TWR2V2s0U2MtaGV0U29LUk1YbmxCM0F2cFc1bEVYN2g0aTJEcVNfLTI0RGdMS09iNWlfVTMwZHNxcWJCdTFMUkNiX2p5dHJhUUlwMEJOczhEMFFXQmFzYlZDbTdNTkM2WlpESlZLMFlBQWkyZnktM3RPSjA3dFF2OFRQelNiaHZETDh6UHdqTmVCSURMWjlvTmdlZFNJYk5sRWdZS3RKZHh6emJEOVp2UmNKSzNYUTBYVHY5bGc0V19HVGJYSUx1bF9fa1owcGZ2RjV6N1Rlc21obV9hRFY2MzNYTEJzWG1wNHJqWUdKUE4tdWxkNW11YkZoWnFWRjJaRHpOTFI5czNKSXNkeHZubnl5QVpiR3dfVjI3eFVKQ19WbktXTzN4bVhGdW5lV0dVSkNFZFpWR2FyZkQ3MHgzc1JIeHJzM29jSEQyQ1JhcnFpM19SOHlndWM4NzlveEJuU29FbXJJTkd5dWkxbXkyRHdnOFYyaGNrcVZKSjhBakxONjNJaGZBR0FTNEU4QWpQODdBczlPX0ZUcnVESWhtOHBEOGpFbUpQTFlTV0hNbkl5WDV6VXEwa3p0NE1QMkNpdzF0Z1pXMGtvRGtHVFhMX1hTV2JCX2ZmVG1lWDN0cDVYU0M0YUh3X3BzUV9oNE44Y2NkS3ItWE1jYXo2aTJ0U3k0Ymh6U2lwWXdqcGx6
 S3hTYU5wdVpmcURWUHlEVXpfSE9OSHVvV0ZVSEw5alhpTEVuR2JFYW5HZ2VlRXN0cEFDcGMyS2JNN0NhSWpDdUtubmpxVy1EZWoxWGNMY3Y5LU1EVFVraGZwTGhMV3ZOWUZKV19UZ1F3eHhEbllTdEwxYTNZVGRfMjJuQ3dJUm5SekY1Y19YTU5KM0JleDh5c3F6ZTJyN1Q4b1hUcFhvY2ozQ2sxaGgzdEh0dHhCOEIyYUh0UlRUanIzRFltamc1RllTOENLNl9mOThkX1QyS2FHYkViZFd4eDhyTDdEZ3JKTGdqeC1Ba05ma0pCR3prY1JaRnBFX1VHVnNhMW1nZlNwOC00QTVaM1Bfdzhuc1RsdzhsaUZ1MUpxcTR2S2ZyQmNUWTI2UEptdEdkZWQ5N21KQnN1aFhyWW5uZW5qamg5bEZYZ3g1TmYyOFFKNHdoV2w5eTFnSS0wNHF5ZEdfem5CbVJ0MkY1Q0FNbXdMQ0hpZV83LUNZVzNDTkJNWlRPcV80VUpaWndxcTUzNkJYdWtmNHZNZ2ZJSENnT1JfczcxUTRleGRmWWZ2ZTU5ZEp3WEc4ZHRMa2xxdXM5SlM4dlgzSnFHdHpLOUhWYjhlVkdmVWpNNXVnU3J6RWJCRFQ2SE1vLWhqVFpNbzBrbjAtY2hTV0hpVV81X2xRanlmdDZMYkxWZFZEbkxlLXFhczlhUi05YXZDZGk2Wmt1SmxuNVJPbXI1XzVpam54Y0haam1ZU3ZXdU9xX0tZT1JxLTMwRXhMdldTM29YbjNQc0lzOTNWTGktU1hHSEpXamJ6YXVlWDFySWlsMGZFLVY4ektpMU5aLXVVWjJJQnVHdjllVWtYeXJyVl9EWmZxUE94RlpMT1NqYWZuWWxSNEt0dE9WMHJVeURaUExob2h6bkZHdG9jRjAwV29xOVB6b1dCT3VJNjNjeE1YNVZGSnpmYTdTdTZ4Vk1FRExLVEZZRzh0bGVDdUpLSHpTV2hpR
 0FaY1djU3NvLU1VNnQ3LUJMVEQwWHEzVklNZU5qQzdQcmU2TjU3YkZheWpqaVVTdTBrOEh1SjBhWGZnNDlOZ2M5S1AxWHp5bjA3M3p4NWd4dEVQYTFhSFVFVEROMkVWakc2SDZMdE50VnNqNGVWRVVzTzZ1VTZTWk1hOHhfX1ZPUEM0WEgzVGRYVFMwTl9KZUw4OENyWmZSMmt3VDh2RWdSUHNVLUc1MU9fQnBXcnVzRndXMElRWXBZTnUwLVVmUjB3VDBlUUFsdHpCbDQ5VkZ6SkVMeHhsTXlKc3ByVUNmMHp1cUNUaVg4d0VUNEc5YWtZZzZKWlV5SVptSUk2RmNycy1sWTBPWlVYSW5IS3pqY0w0WnRVbHhZTTFFUENXVXBibWw4SXN2SlpBN1FELUtWOEJVeFdTXzdUOHRLOWtfbUpGT2pTdVhZUTNjTFVDVktyVkRwU3RZZ3JUREdiUlR5bk9EX3QxU2dwbHczMFFUS01mTXNyZkJweWQ1VEpkSGg2eVdSNFFwUlJnWnVaWGR6STRfWVFUMXIzT3NnWDBWM1NaMUZQN2hSNF9NQnFQSkVTenpZc2pQWVdkTzdzaE55Tl8yaXJDLVNxbG81UkJaNVZvZ2VNZDNaVmhhZEQzcnF0UjJmVHZNZm1aYUtuN0piT2FoUUFJYjY3a3NVUHZHQU9rRC1kNS1VRDV0N2JTU0xkd2xXel9aUjFLakxES0xaTE1WSEtTRk40ejhOUGhIcjc3d21GSDZ0ZEw4X0dEaWh3YnVGTEdmbHl3VmRuWi1uenFQcXNhaTU5MGU4SnBfOVQ3dGtMczZQUHBwclFGSGFVRnFtSTAyYUNvaFJDMGRhTEZDY0JrTXA4blkxeFRlamJyZm1yLVpNcmNLMGQtUmM3bWtpVTY3bUpBRTJSQ3BFZ0Y1dUNiT0xoTlNxMXh5SEZHa0llUE92RkFYMWFGQjNwa1VCN0Q4OWxoUkF1ZGd1bW9JWkRCd0dzdV
 BSRGZPUlR1T3hZakZhaWozZzVyenZHdEVlanB0SVJDbVhNZXhhMVFnYlpQOWJabWh4a0k1SXdHNHJDS0pvZ3NBWnFhYmZUSmUwY18xQTdLYjIzNkEzSHRSMFhJMWRIbVotM2c4cXBwVG9Eb0JPYTZ2RW5vU3NkOFNsX1g1Z0JlZFdmWXZwYzd3X1pfdXJGUXlac3BBbDJrS0N5N2w2U19BUkZqR0dvSnVNWVFicElIbjZGbkJCcjhsTGlyMExZUDVTQlJfM3NaSHNyb3UwamxyLWNMejRZSlpUYzBZcnBGNnRETHA3NFJ0bWM3cDk5aHhNRVE1UG40S1VGNlZJcWt2R2JocjJjdlgzb1d1bk52S0tOcmdXaDYtYzBONFNDTjBkMklveVZfbktzNG4wR2tQcmtDS1ExSGJMbUg1N2ZSTGdqSzFFaEtydGp1SUx3dXFRM0pCeUhISlpOdEdsbV9nZkt5bzZsQ2IyQ2xacElxR2Y0X3ozcVVyMmZVQXhMdWxtRFRMZzh6Z0RlTEViVVdUTXYxTWRUc0pSb0NTZGJiS1NvQ3k2UE1YZUwycllBR2tHT1VYMnVPaDVnRlVkZkdzRVg3enVHamtadnhra2J3VHpTSFlibkMxNHlaRXZsbS1qRkhWS0JjUFdJemJKSnFoUl8zdFVNZ2xRc0xrZzQ2WHFlLUREblVTYUMxbzZ0NnNXOE5CbGR3aGdnOU9JUXhlT2NacVhTanY4TW84SkdrUWlBMnp2WUVWNmJpa09MS3BTbXQyRnNWVE5BSVBQNm1nazE2NG5JaVZXSTN3dlljZ0pCb1ZxeEpCdXJVY2NVNksyVmc1MkU1cnVQc09rNVZwTlphR0ZCb3NYNnU1bjhBM2RfR0laV3VhTUxsZnZnVkdxN21nbFowaFBlM3F3WHI5QndCNm5VV1lJdU1ycFVxUDFQanBmck9OZ3BSOHprQlJ1T0R5R040XzJzRHloMDFWUWRxOGF6OUY4a1g
 wRU9RaHZ2ZUJKcmtqTTRENGJ5dFVSeVR5RHJRX0hYTExFYUw4UjBPMm9MOGNPeUtSa3F6b1ZGc0NjUC1jMzB1UHFnV2E0T0NzYXhnYUxkTUJveTFKdkFENVF3SWp5dHd2QzR6THNpSXljd3JqeEZaZnVlUnBNRVZLOTR4WVRvNkhlWGQxX0VweFBYMkhiMFFBb0VVVS1zWkFCQVBFZG1OQi1XMEtoUnNpMmJSZi12b3JVZzhJbS1remxCZmxaQ19zUU1RckcwZjR0VE9qTlR0QnlHWUt2dXRqQWJuTjhMQlFSN2JmT0tzM1BvQktQc3pTWDNWMUhtTTUyNnd0X1ZmcDk4d1lFZUNOc3RwcTl1YTRKUlcxRWNGTTRJNnY2aXBXQ3Q5b1V3dVVsTkhUOHNhR2NaUVptRzdZTTRUTDNYVVJITHdaZnNzeUFma2dHejZ0Qm84RWp2MlhNVlZta0ZlRGQ4REl5QXNSUEVHRzZFYUowXzdYajRxNWttR2lUOEJBNE9jMm5pS0M3eVJCVE5CNnhMSldPaXRHcHM0a3ZSX3JfVTl2VUQwMTZ6U19PVlgzLTBqLWNwNzYyWjRicHhNeUswbmNzbFc0M1diUFhRajh2N1libjR1bmtPOU5lc0ZkMC1YWlRvU0J0ZlBTeDk2dGVMM0t4YXEwOFBzV1U5NzhDTVdrUlZHXzZnZWtWWGI0SDdrQUo1M0RoTlpFTW1yM0hSM0lsampIM1YySDRvVGlmeW82ZWdiMHZQX1VEQVNFZGVCUkNYT3JuLUJhTUxzaWhGZE8wVjFxNmNwS2FLVlBkTHgtOTRlelRSRWdtcEpjYjNvSXZoa21RRzJhZ3pZejFEMy1lX0FRU3ladE03TUx6NmY3Ni1HYkkyMy05S0JtVnBVQjJOTnU1aS1xZl8tN3ExQ3JVTFNxNE04aGJsN2E2OUt1UW1RZ0xtQUJZVzlwX3J0ZGFGUzJTRTNGZ0ZPWk1GYnB3MEo3SzRD
 bXd1VURXb0tyejlGZXAwRDktdkR5NEtpQmdnZWlZTHY3ZFJPVEMwblV2WWlMX00ydXlHbXZtMGJDc29ZMXB3VFNjcDl0aUJZVTZuYW9Ub21ua09qWXZ3T0ZHN3h5R1ZSMF9yT2o3aHpWbzlfbDY3ZE4xaHRFcXZud1BTRno0dXNEcE5UOEFnR3VDVXlMVW5NVVc3ZjNDUFVlOGlqWk5PTm14NEpBT2ZZY1E4dXh3SVRPaExqSEU2alFJOVVFSGNnRmJsMUtrVFJJSDFveGhNSDI3ajJTaUNkS2VrUWVZX3J6cllHTWNmTWF0NTFrdXVzT2pMWDZvbnZWVzBEc1ZXS1FnaUt1OVI1QW8tQkFUTXhxMGJUMWl1X2FaZGNLNkxlZHVwTnVqRXJzSHpNTzF3eGRRcWtMcDVvN2M0ajlQLU5xTTJWWGpnQm93OWJrUmxYdWd2a3Z4WV9tNU1fMm1oeWF1amdtdHg1bXNPR0pIUl9OckY1djZiUGk2aWZkU2o5emhuWGV4MDFEb1B1VmRHeXJkaGN3N25FRjZrczV2N1pOT2ZvRFZuemxCbUpsQVA1eHFjX21SQjI0ZmdWQW5JTzNXMTFSX0V2ZF9UbWxXd085a1cyemFxbi1OeURLUGxtOWp0aXdSSExYRmR1Snc2d2MtdVhJYXdxZFNkZVJkSUV2TWhYX2ExSFhNTG9RYk5VZnpHYk0xSi1aUVBNNWRfbkJPMGN3S0xyRUhlX1ZiT1R4UmZuUU1UVEw1ZnlrcmJGZkgwWUdPYl90aVlqWGJ3QWRsUmtFcFVuSmRWemtCY0tPZUxHMF9ydkRXdmJKX3E4QTFkeFpONm9PSlFvOHRjV0IyVTIyMFNmWjNoNmhUdC12dVBPelltdG1WMDZQb1ZSQTQ5c0JxRWJhNUVKU0pRSGRkVEQyZERDVnRBSV9XNFFFNF9QRGFhQ2kyZFVsN09pZnZJS09TMnJVeVRRckJ2eG1LSnN2Rm9yM2hjO
 EQ1a3UxMEFQcnlUQmdtOFFTbXJma0xlZGNHUEk0YzlxLW53QnRPM1l0cXExTmhnaHU1WFBxc3h4RXZiMkpOekdXME1DeFJGSGI1bzZLbFg4cExjLWZzUFV1V05lWlV0MnQ3R3ppd1dDc2QtTno2VW1Hb1JicU52SmNKeE56VjUtdnotNWJpUzN5UWkwVlJSczl4elhmN05jYURrQlR1N090Q28wVDFUYWQ3bVE1WTVVREN6UXJGVkR4YS05Q1JubDczLUFvZXp2SUtSWUtYWDZLam5RUjZpNmRJOWNBN2pKRFFFT0thMGY3UHFXcU5tYktMalhSY25ocXZJNW56UU5pYUh5bkUzTXpMb3VOMzEwQ2wtM2d5VFloci1ya3c1UE15VHY4enZpYWtMbER5Vm93dTF4OHMzcmdlSDFUbFp5U0JRUDRIcDBBWFYxelZQQUhNbFU0R1dZdXNOSk0tWk1uSGxBdW5RSVd1WF9pRmxVbmFqMWhyR3pfUFJ3dzRVajF5aVZOLW1UR2laSUdadXRDQXRYeGZUd1hwOE5Lc1pwNThYU2QyeTNfTE4xc2QwZDMydEI3Z20xRE1ybHpqQmFybkdBQ3pEQVo4LXpwUDhhVzh5cXFDQ25GdHdiU1hGOUtiNkVEZzRPckNqZmlpTlZXQTZHSFE2TDlPTnZvemozOXpvaU1nOTdDc2dLY2tZTnUxTXo3NWhtSG14NjdudzZLdFBrcnBBRTFmVDBzeDlYdUtWczhUWEdlUFdvVHREMGRDOUVTRjRsV3RPMnpoV3NsTzhHaWVkQnhjTDVUOTNmWGFwR05sbG12d2lIVWx3S29TSFVnS2JwVWp6MU9WenBGM0l0TGNzVnpoRXlRQXJKakp4THoyNkFGSzVaTE5NUGc0Z2V4ZlRtMmI3YTNkX0g0LUhvMlY0THE4WDVMN1ZBZzh2b1dXY0tfZnBfbERHLWp2STduQzFOYzd0UmkyWnkwU05zY2FKbVQyeE
 1pZ1ZZM1ZYaGJyRG9iQXJvbjZBZkJlZjRibE9PMHNVTFdWMVRobzVMMmc3TEs1alc1am41bjRYSDkzNEYydTNPazhwT211T25HOWwzZDVySy1zWVpYQ3g3NENqVDJmN3BjZ3FiQ2F3cExBMmx2T1VqOVFublRiaVpkQzc5LXF4YVpZWXRUOVc4dEFVQllpQllJTUY3UFl4ME1KaFVWUFBWM1NMR0syTkJURTF2bWM2c1RFZ2l3ODltcTRPakJLZ3hUTTNNa2paRGJzMm1OVktqUjhHODBYYjlKX3VMOWYzRzI1c1RBemdVcDB5ZEItaHR3OGFwRDlmRkhSZzhYSEdDZTVmSHNGTDNpejJvb0d0RTRkeHZSQ1ZDLW5lY3FtRG1KMS1jMEZkVDE4djRWX2ZZcGc3QXpNQzNYT2xQLXNiOE5KS2d6RUZOZldseUtHWXhaRkt6R0RhZnBBYjdEYUloWVpmU2Faa3Ftbnh4eHpDbGVrSTk2T2ZnZElsbkgtUEd6dW5Nb2FvcElxN0lPek1rZGVPazBpUFF6VmtDUGxxc0M0LXZ1enFJODZvLTQxbHZGVmhpU20yeEozRHJWQzBXbGpVUjlPVVZ0R2JoNEF3Zm8tb3hMdVFLMW1Ma2pqLW1yNkQ3d3ktNDBrcmdOV1ZLeEpET0Z4UEhnOVBQc09xQlBvbWpwUXpkNUowYWg1RmdvNk9uODJlVmVRZzdHRzkwUjZZbVBSR2dFVFVQUWl0XzRHZGE0U0xnTVZDSktZdGZvZHY2WWQwZ2pSZzJEVW5qZUtOVUp3c1RjSEhyYWs3MXNRaVNfVmRtekZsSm1CNjVhYjFlSE9VQ2I4SmtYalF1XzR3UmZXdnhuc1VmcExWd1VMMGNmNi1YWmp1RVpIUF9PaGlGWDlzWldTSjBLS1RfVFI4RzFTbWpFcTZUbXhKa1E1RHRnV014OWNwTjJSRlNwcWFyU1V0STJtUWNIM191U0tERjNuY1lhWDl
 0Vk55ZGpEOFloUkdwWHVQdk4wWHZyejBKTklHLVBWeVlqUUJPdXNvOF9GeV9yX0ctSmVhdVNxMFRpVUhEUVM0Yl96ZDlfQWxMM2wySzZJdzAyQkVhWEhwb2Jpd3pFeEdFeU4weWFVMDRVNjliUEl5TGxIcy1sVVpnMTl5Z3hOR2pzdkxDaktqQ2gzdlhxdDRsMnlZZmFnY0RHSzdWcXpUYzhDWG5wZ1p1bnR3LnRTWm9BN2tNdGItRVJtRWs3d2MyT2c"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultrestoresecret.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultrestoresecret.json b/azurecompute-arm/src/test/resources/vaultrestoresecret.json
new file mode 100644
index 0000000..bff4c9d
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultrestoresecret.json
@@ -0,0 +1,10 @@
+{
+	"contentType": "aNewSecretKey",
+	"id": "https://kvvaultapilivetest.vault.azure.net/secrets/mySecret/8c418537cbc948539ea2ac12c0bfcfb4",
+	"attributes": {
+		"enabled": true,
+		"created": 1509335944,
+		"updated": 1509335944,
+		"recoveryLevel": "Purgeable"
+	}
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/test/resources/vaultrestoresecretrequestbody.json
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/test/resources/vaultrestoresecretrequestbody.json b/azurecompute-arm/src/test/resources/vaultrestoresecretrequestbody.json
new file mode 100644
index 0000000..d57bc99
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/vaultrestoresecretrequestbody.json
@@ -0,0 +1,3 @@
+{
+    "value": "KUF6dXJlS2V5VmF1bHRTZWNyZXRCYWNrdXBWMS5taWNyb3NvZnQuY29tZXlKcmFXUWlPaUppTTJJd1pqZ3dZeTB5Wkdaa0xUUmlPVGt0T0RVeE1TMWpZVGRrTTJKbFlURTVNMkVpTENKaGJHY2lPaUpTVTBFdFQwRkZVQ0lzSW1WdVl5STZJa0V4TWpoRFFrTXRTRk15TlRZaWZRLlFLelA2anZVR0Y5X1M3UU8tRkZDTHIyNGp0RXJuandkQThNZUtsSGE1MmhvS01rNjdiOHQyckZhNTJ6dGR2and1d1I3VWh4RldRLUpuOHk3YlJiNlYtcTlUYl9iV3E5clplUlhpUy1jdUhPak9ONHB1bHd1cVVmQkJOU2V3NlJGUXpOUzRrQks3RmxQSGZpQVRRaUUtLTc1cnZIM0dMTEdDd25KTkxIUDNTR0FtWlR1dXo0bTN6X1owR3RsZUU5XzFZT3pqczU1UmJFNEdOTC0tWDhDWnlRWmVFNGdGRXZ2WmFrYkRXTk5hOWd6SnBUNlNOTm5tcGtpMFZocGxaNGdzWmNmR29xQktZNF8wTS1WTmpIbkZ5QUlySXdsSTNjZkIzWUVCbHJ3X1A1QXhQVFFvNDJNa1pETmNKYjFwaGh0c1phaTNLcWRxT0E0ZEVWNVZWQ1VNZy5fTkN5eTNJSS1VV1VtWDB4UXhTVnNRLjJkbEFpUEpSa3NlenNVTEZocTE3ZmdCWm11XzBBaU5GUWkyTU8zMnlVanpEMjMxQlY0bHhwU21ZMmI1bGdsTXlYQzNtYy1PT2VmcVNseXdqMlcwTllOYzJKOUg4MzFHc0VCdXZ1SS1BWEQ3dzdocGRNTG5VaG5DQ0RUQTJYY0ZTZ2lXTWMzMFFISHUzRi1KcDh2VGU1QUk5R1ljelEzSFVPRjJOREpjRERoLU9CNFFJRlZWMS0zWEJkeS1uOWR5MjlSY0FwNEo4WHRPMjZxN2dJa3BDT1J
 xMTVuOXZHd3ViVlZhdGhfMlZwM3p1ZEJPX3k5SlFTVVYxMW1jZFVIQXNCVGxFMU5xYkZaU0lfX093NTl6ZktGRTVTMnZrYWl6a1RFbXFVQi1EcTVnMnMxQ05PcUdUNk1wQWNiSEtUNTNSajNZN2RlOFlBckZIMlNSZF9udUV6Q09PMnAxeFpFUjh4c2RIRjlDM1Nnc3ZRQzIzX3BfeDBIR1RfbWY5V3B4amZOWF9Bd1E5NWNLZ0JOdU1ENEZ1TTdWTmpKc1JaSGtvM2tNTlJ5N3BybkhhaVd5aHRiVV9ic0w3X3FRa1JGNEl3eGFzUlh6M3RtZzYyT2tCWl82MEMyRE11Q0pIZWtqSnI5SGJDeGp6Z1lGMjVmRDhDTk00YmNaRV9ma1Z4Y2lVVklWU2lvemREX3owTFBMY09paVp6dTNIWGIxekplZkJsVXduc1NBT0RZa2lWbjJPMjFOMHpkRGwwMjNPSnJTdWQycWo1UkEtVTlsVWRxU0w1QUltN1ZaMTFSVzh5clpkWXc4NFJTejVySldRSm1sVW54RzJHb3lMMTFaQkJacXY5bEJ5Wnd3SDN6ZGNDZWFRQWM0LVZJWjQ5NzBfTC1tT2paNUFwdXI4UERHVDIydkNKdEw1cVVaNGJabThBeXQ0NDFEX2o2cG16NzRUWWlIU210ZnlJcnNvRTMzbG9QM0xGdTFKMklXLXJTdk9HUElveEx1ai1ZMkNKMENYTk1lR0UyQVNhOEY5RmY3enhVLVRkbVZneWpfYi1EY05XUmVJZUMyTEF4OV9EWDY0QlRJV0pNSFc3a2plbjRkem9kajMzbjM1aFU0UUVmRVM0a2pmUUtMVENrYnRlWXliVUlQWmhaa3BDRzRpTVBQSVpTRVdqU2RMckl6NlRYN3FJZHFHcE1UYk9zeld3eWc2dzI1WTd4aDFvelY2RjJEOFpKR3FiZjhQZTVDRWtIcE5LeC1kNExUTzNsOWZlZVd6RFRwTzRn
 TWpBZ1RNdHBqdXRqT2xhSEYyN1JLaVNGWU82eFNQY0ZVb3JGMlZKRERlQUxZSk9Pb0JOMkhpalJ1Y0R5bWR3NUtzNHBZTmZvV3dCeHVnbjBPenJoNVFIS2Q3dWpoUll1XzhkLWd2RVNKQzNJY3JZWFI1aFhxaUp5WGVNMGtULWlnRUFQRFVmSXE0cjJiRW5iZ0RhdUZrN2syekZzXzZzeGZ4Ty1TNEp0alp2UkJia0lnZm1WdVB5OXZTQy02QUl0aEctMW5OUE9PNG1oak9ON2EzVUdzQVpvREg0T1RFczA3ajJMQ092VGdqX05PN1pJcEt6LWhyU0daSXdCdjlRdHJ5NjY4US1kTUpRZzAzRi1UXzZlX1htc1BWRWt1RWdaSzdnS092STNzdjk4Y0VVODFiVEZfNjQ3cmE5bjN6NHdnbmZwVE1lWEhMQ1JWeGpKbHJURmxJcW9wbkdZeHlQdm5iVXBzb3A2NktHbVAtTEpTeERjNlJJckpuQ2drbjN1OGN0c25NZWxuWHZSeGZFdFRsNnkyendUV3ZSdnVEcVR1UFphQXdNVmllbTdaaXZqNTdMYjNHT3RUcjBxQXNrMC15dHN2TkpmY19tYTEydVlUWll1b2RCM2ZoVFBITjFaclFoQzdiWDVHdXFDUFFDQXFuenJjT0lESDIweTFlZHAxam1ZdTFyZThPaG9yMDRiVWhLa2stcUVVdEVsZTFqYzFTckNuWkEyMlRZMFNVYkxkVm1hb2dyaUJfckpackVaM0tneGFaSjNnZ3FQd2NhSW0wNUVoMDQwYUpUa20xOWdzRzVCNEExQ2dDWHRMOGhUMFl4TmNneW9tT0dnRzd2Q2FzdW43WGhtdjJZLWROWVNrZzRZbzlfdkktWWlmZEp2MnhJVWY3eGFvS1RRRzY4NkNzaE0zTkVubFRWb1FjaWxjaXllaHc3RkpiMnYyTDFNV0tlamRWM2dPNjIyVjZ3QXV4MW9GdXJhdWZOR
 zh2cnkyS2NwczFOUzBWeFJObU9mNDFkbFRhSkljUmFJM2tSbUg5UkpTakJZcnA1Y1ZzZWh5WGVaQXpnU2JzUlg0eGp6LURJSGVPa1dRS05HMlZvTnloZ3BZS05FVnlNN2dkdFBWTUo3TmlkVE9PM3BaYTBMeV9GaUhHLXc0dkUwTTR0X1ZpOFhvRzBFbWhJcjBWdmRvN0RGUXVUbmdoblRGVnpreEtyRlJSZzRMWkhCNzR2Z1BycTVTNGxTV2hlZGRfekRad2JVeUxJY1NXWmk3QzlpWDctczNHeGp2UjNGekxJT3NuSXUxVHpaQ3B4a0d4ZGkzU1VyS1c0NGlTaDM3eGNmaEpsNDVDcTQ5N1pQQmo1eVA0UmYwazVTS3djM1JvOUJoUXN0aUdzVk5qMlIzcmpHTHZfOEwtUHNxOG1IYTZKZHVvaEtRbEVQT1hYNzZ5aDdab05KUUZhemRNRWV3eVJNOGQ3eUZIcFc0M3RTZTA4Mi1BUmRjcW55OXFZRmJLMFJfV3dNTDlOQkFpNWxjQldUSms2ZHJXN1RPRmJ2eDFyZ0p5cUcza2w4TEdwRExheFNfaFhXZVRxSy1YS3pVRk9zNjA4WEp6U2NhVE1xay1QTVZIdkN5c3Vjci1mOFN3SF9wdks0bTNQYWprcGVOMjl3dmVZdUp1X1ZKZHlPNE9yY043cnRYVXR3VWNSblBzNUNXYWF0N1RfUWhnZ1VTdHBZczBJTlVuNXU2Rm5oNGVsUUxTTEhvdWZDdE9RekpDV0VVd3N2TWdkdkc2cEUzU2FZU244OFd6YzdMbGctZEVMeERLQXE1dmI1bXFleXAyem9hZFhJa20wWks5amlwdnBZdmQyRlFnNE50NF9nOUo3WTRoeVp3TjFWdXlqQ2YyUkFpMzJXZlNid1B4ZmdVdjhVVkktcUlKWjc5TjNQOTFnWnB4X2xxdF9aNFB0bzIwTTZqamw0MGkwUXRwMUdaRU5hbHoxN00zbF
 RBUl81WkY5Ql81dTIwN1FGbGh3UDYzbFRNMF8td1lCOVBzV2VtdGJUTEZYZmJFU0t6VGVzckVzQWwzQkVDMFotSndhMno3cEc3VHhvQWhON21hWDdKajVjbWtzdmJjVk05MENSNTVwbmtwOUM0Tm1BRWM2amw1dXRBSGlGOEdaV1A1V2lGVFFwVTBpYktXLUVycEMyblVvRVBmbFRPbVowM2lzaFNLbnZTSUFUQjBMSW95S1lhYm9tcU5NWkZhWDV5OWVjTGtFdmlmYS04dW8zRzNYSWFhQWk3TE5YRXpqQm9iZWlVSzBFeGJxaGd0VzNvbE85V1o1MGxqOWw5UXpGV3FWOGRiUThOeTdkdzRnT2wzNl93ZVNrbHJ3b19VVDA0Sm9Oc0IzOWFrUnJaWkdzaXJuamR1T0F4RWZaaXRLdHdTdkpZSzRtV0huSk5uRENMVlo2cVpzVG50NThjVjQ2cFY3T1FxckNpVnlQREU3Y1N0RW5neXhEbzRZdlpibDNrNndkaGxYOXAwZXNaOUdXbHNxcXlGVUJCc19QbVN2UUd6djZ3bDlWSnk4WnNKYmpIdlkwclZOUFJnN2FYTjlNOElsVWpia3B6RmdqY0VPZVVrZ1M5UFp5RURLYUw5U2NjeFJFbjI1OUR3MDFJZFJPS2U5Mnp3U1hSQUJlbVhBcVRaSGZPd1Z2VDBUS2JnWkwxcE5vb242NWRMR0hKZ2dYWmt6SjVHT3dvbFRkYkEwczVkaXRQZllxU3ZwQmpmVHpfQTZhTWl3bmFnamlET0QzT2doeTQxc1Q2UDdTWTFxanpfWkxjZ1puc1djWDlkOWc4TkpzZ1had184d2dUY3hRdW1TM3oxVTYxX2dlbndBNzNPaEs5MWl5YW90Z2ZySWNzOWxodm1taEcwRC1KX3lkQUxfdXNROWc0dHRlN1ptN0hMZDZOb1pCYnJFTkZ0ODRmejdJbjJxMXItM1lsYk9kMm1xRXIxZUdZMmt
 CTlh1eFc0XzlVZVFOZER5UHZPRFR0Ni1mR3FuMF9sd2dYOXJldUxsRzY1UjFKY29yMnczWmZBLWU3SEN3Y2tCTTBEcmhjZmwxdmhtcVY4WXpMcHBxUUhPa1F2YUpMNHE2ZG1ZS0thZmhGbXcxVk1qSnp5UWswUVNzazFWUGdzUmpta3l0YmpjZjRoenJNdVRMU0VQTGZVWGVPOEYzbEdLNE03bWlhblRPQ0xXSmRNWnc5dFlKSHVTQ0g3SjhZOUVwNS1XWTRBeUZlaFJfaDVSNHVYdlBPUmUzSzZQcWJibHlaMEJuclpCcDZnTUNvNVcwZkd5ZEdiQ1N6dzUzVndsY3FEWnJlb0p0Rk5pZFNzdTBtLUFub1g0SWxsSFFnYVB4SnlLYWRPSWpvalNKMnZTTTZCYXRkci1pR3VTbDJSZmswLXkyX3FFeDZRakNOQWFXaWNvM2RsS3VIY0h6TU13YzVXT1J4bzdweXdWYmtOUmpoOUVPZlkxSW51Tk11SjdfYWt2T0V5MGpMVXlCc04zR0hrTzlEUExFLTk2bVlIMWd6R19IbGQ5aVRpOWcxZTB5WjdBVkNEQzBoaVRZMXB5V0pVanpGVE91clJaYW5qOWl5MWdjcFdpeFVPN2xiWjl2aHFhdHg0VUh4VFRneS1IbUcydmRTYjhJbGl2bHNqLXVpM3dxUjBYeVNXRDFVYmVJUFVIZk15bTR2bXkzdkIyWEJKMEJnTF80bkx2VWQ2MEpFdXI1Z0ZOSUUtR0RSY0JwSkdPZXN4b1lyQktYU1I2QUd1UG84b2ptemFudUFIaF83OTI5OWg2aDdtN3JRZ0NxYzJ0Wjg1dU9YVHNzZzRYSW1kVjdCN3ZrcHRlUmt5WjZEQ1RFYW5GRmNvWEJzSThYMVFZeFFDRzgtdzltYlppTHNiRGN6bVV5Z3RiRkNQUXludjByclNiRzFUUWtmZnk4UGVfT0tRYkxSdWJNNG55dmZxWG81X21FcXA0
 T1dzMlJSMDhiSE9YTWpDU0FlYUwyaC1RRjg2MmRrLUNpV05ZSVVuUHhTYWkyWTEzeGVqVklwYkI1YkZzaVUzTWJmY2pyNnduRUVuMmhzWGx1aGpWVXFtUzNIOEZwZDFkS0pSa1lzM2NWZWRHTEhaRFZRM0hTWHlBWk1FbXNzX01kTUlGMFZhUjU0WTU3QXhhcnR5QUFmZy1OWWtkNVhtVkxPQWJnRFdCMzdrbEVPVEZCYXV4SGg4dXJjVk9neVF6Z1RNcTIwTWpEUzhzaDlZLUNHNUxSRHJiYVlRU2ZoR0VSYVFYcFpuVEdWX20tcDFpWU1zMEMzRFBJanMxSWIxZVR4X0lJbTFPRlBGOWcwWVJsbXFCdkx2bGtGeExqM0t2SGxQVEUwaUYyZ1JaMmN4NUMtckJGZ0dXaU1hRUQzdjcxTW0xQlFJeklaY1lfUUI5V3FsWEVaSmJWZHNZc0FmNm93eW9XckpVQUszTEswclRPaEdNS2VaUzlzUGxvZWU4T0x2OTluc2wxRUM0Z3F2MHJqdk9JQ0pVR0kwb1R1dXV5enhSbU41cHJtX2VycHNLbkM3QmRXV3VaLXRab0g0c2ZDeExiYVppeW8tQU1xdVRhMzB0ckFOV21rSUtuTHFubFRvcXJXZ1JiQjF3Q0hlVjA4WXR1ak9sQUdKc0dHRTRLVjc0X2QwSXZ2NXA3RUxQZlJJcU51cGVLdlpTZ0pxU19tQmU0eG5wTFZsWDhmaHRIOE9aSUxKQ25ZQUt5VHZyNGFoZG9jd0NrOE9JX0xVOG5wQ1Rpc1VFdEo1MXpON2dqUEs2eGhCazZ1YnNNeE9oalhNSjhUd01sWHZvMjcwSXdYV08wVm1lN3pGbnp2S3dnWjV0UlB4c1hwTjlySDBlLUxIZU9uNHIzWWtHeHlpRDFrMkUyM0s4ay02RmxhM2JwMV9DQktfdkM0VUhBU3NqQnJjd21kOHVvYzdJTDRsQmRfeldQbEtyUXp6b
 mxyZVlMV2w3S1RmdG5ELXF0STlLMlFpWm9Ib3E4anZSYUJTTjZqUTk3RXhEb0E5dUk1LVRFc21UYlpCV3pGemdoOS1mbXBKZmQ1R3VNUXVhblJDN2VPbzh4bkJrVnI2UVVnZjVhYzV6Um0zc1ZBaktBVDJ5djc0dTNyOEJjUEJMcTBsc1gwTUpza3FlNEZhN193NXB5Q0Y4dS1RbVFkN2dmeUdPSW1OdTgySGJPSk5yMHg4Vm9NZU9uUExsVUhyY2cxNk43czY5ekU3SEM2UExpcHJobHdmY2JvMXlaZDZYVUxYNGI5MXJ4ME5SU0VpYURISGV1QS1LNWFQb1F6VVZiSFJ0cExvdHpwTEFTZkhwMWFhSEoyakRQUElfcVllbzkwWjVrR3RiV2plSTBYVDlzMy1TMk5pcW16Z2Q5WEMxNEJaUTM0UWpNdksyNUpJYXpqWW5FdGQzYUFYRWFZNU9CdGZ5R2NIcV96UmRaZlVQdDdDNk1LTFdRbnpzTXNWZHJ4cnpCcWRMMVV0NzlIQnZ5M3RlWDZ0RmJuYjR2ZkgxY3NZUl82a041T205VndHelRZYWNGM1dDTkNuOHljMk13N1Y4b25ZOXFLU0VLS1hRYk5KYlB1cEJsT29qLV9tV1drTkdmSy1TUHJoRmFGNF9LaDFTd25TelBydHRVVU9WMXg4ejNmUVFXZml5eVllcGd0VHVGSEZheHE0YXNCUjRQVndfUnBJN3c4QTNiSGR5ODQteWprZU0wU0k4WE5CdkRmVThRXzA2aVZjWkg1UWhwU2VENVpZNWotcDNzN3c4X2MtRXo3RHRZaHgyQzducWU2OFNVYmt3dmd4d2RUOFhaYzcySTJwSUFwYklPTzN0SEFIVmpvVHdVX3dsSHctSVZKbzZfSlBvRE5JbEdZcHdDZ21oMV9rb2FCLXFvMGdQd0UyeG1sRmdNeVVCd3lfWHNEdVRUcVJfT3pYVHBQbWdhTWNZMXJldEgzVj
 BDZ3BHaTBqYVZoN2NJSUpoVWNRcXRIVHl6S1hDTWVMRVBXYzJuVV9oXzB5U0tTanJMUmR1cHpkMTZ6V2sxdTRzdDRDak9CR1AxbloxVU14X3lGQ3ZsVVlESGY5OHhBelJNbUg0c1YxMnVMYmlCS2l0eTEwSG83X2N6T0htQ09LeE1oaFlhRmVrS19veUU3X3pWbTRjUzhHbEJiMUo2UVZMeHpGMXlORnlqeHdITEtnNURXUzN1T0JfSGpNdHlMOHh4WXhNR2FjNTh1X2g5ZEM5QThtVGJ5bEF6Wll6eTUtU3pvSVJYZHhVOGtBN1c0QzFWYmI1VGgyVHZmemF1Vk1mNVg0SWc1WTU4NzMtd3oxNVpHZW5xU3JreFVqU0tVUWVlZkI2eEg1aGtKeWs1cDZWY1JJNzF6SkVEVEU2LWZHSGsxTlNRd2QtS2tTaWlwMjI2d0JCOHZSVWdGQ1VZcy1EZC10TXF1aDdKZjlaRTU5amNzR0ZkTDJhamFRcjc4Z21VZEFVYS1HRHpQeHp3YkM0b1FKS29ObkNEZGc5WV94S3NHeEtDWnRVT1VjM0Z4MlptZFpfM292ZGExaHdyVDZpYVJLM0MxZnh0ZVpheE9IWkNvdW5MeU8wZUkzZ1Nnd2dkVERxODZ3TzY2U3pHdGRxYmo0bGZrT3NkRUYtUDNhQU1yOGNuclh3b2NOdGVpaVJ0YnVqLXhfNlVQUk5hWHJCV0lHRk1Mc2x3b1VlRXE1ZUpuOUhSYmdvd25vU3psOUdDWWdtdnRsb1ZIVHFVLXpNWk9TcmxPejA2aU1ZZjBjakliUDJtdHUyWHlDS3dkRnFsZHJqUWs3VmNUUEJkczluRjR2Z3lmOU1nSFVTeVpHTHFubHNtdG5ER1p4VTN0UmR1eXZfTFRLcDgxYVVQVVprb0EtTkMzdEFncHdQbUtodzVnY3M4U19aSC16VVNFd1BjLVR6NGtJSzhrSFVxQ2ZFY0pfMmhpX2RTWHR
 KbFB3TG9EeU95R1hTWkp5ZGIzb2hjblk3Z3RneGpQaU82Vmlwd1NZMXRVVUV1YmFKbHkzTGFwRjN0cXlEZXBBdHMxc2JDdzNSSm1HcE92WjlfaTk5SXZ6WjY1WDZPSDB1YUpDTWl6bFpzdGQwZ1FRMXl2ZTNQRDRaVHZPdzlMMm9Na0ZDQlFvQzBUalU5b0tPTHNpdlAzbTZOWjROLVpiaWFaNTIxbWU1ZjBWV1loRkN3RENxajRyUDZ5WmloOXVPTW5rWnNhZ3BtS0RlaVV6d1RpaENKdlRkZnBfbG1GQ3cyc0Jyd0lIVWJfdkxWY1RWNDd4NVNwSnhuS2dpWHpZUG8weElnYnY1bmZGWTJvM1NBWkZpSlNlNEJQbmFsX2FQLUFnNDdWM2h5NmNzT0xCM3l0VlNCRDdlNjFpU1VGWVhBUmZJVEVXa0VRaHBIWWJyRTlvemdldzdOLU5HaXdtWndOUy04SUFSbmRFS0tXSXRXb01fMllXVmYxS1ZoME8xQ2wwR0ZDV2NCNzFDLWxMazVJbkpKUm5Wd2dPQ1M2YUFKaEM2T2pIVVYydTR3TTdndFI1c1Y2Snk1NUxQcjFUbVpZQXAyVFNSMG0zUWMyN0ZKRnhxaFU2R20tZGtVNXZKbGtnSjUwY2xTUVVGcVl4Z0pDX1hSdWVpOXNzdkNmbnZVOW1ZSEFQZTU2Q2dXNWFiVGhSOEJCcTc2aTlxUjBlRVV4eFVWUUtCemFhVlB3TmVqaFRVYnpWcHZnNGlqSFRocFBlRzdDZ3hwQ00zT0pCaHFnS2k3RzVTeHFHYjdNVEhoclp2Q3I2WHZtZGdFc3NxWW9RdUQyYUQ4TlhjdVU0Mm1NVGwyZS1sY2pwU1E5R29hdlRHSjFCeFp2YWlYZzRNS1FGUjBjRDQzYkxsaXo2Y2NCeEEwZnJTU2dqbUhRNERxdHhjYkFiNFlPTDFlYkFQNFNSQnJwa3hGQW5fc1l6ci1aR0F0R0l3R1Jf
 UHRRbjVLQ05yaXBueDRITVBmS2UtTHg4MzBIWFNxVGV5c0hRbGtuRlRSeFdwLXdNcUxPMlFhTHJnMlUzdnBDekloRmh4dG1tWnpPSE8zZmY2YTAySk9BaDVDek9GcG9oTDFXakl5a1RMd0dNMDZMQ25uNmhGeDVOZEhmVTlqaTdKNGZuT2RkcVh2ZnZ4TDhSN0wtM1d6SThIUVI4TkRHRzl6ZGtHZDUyQVlkNTBqUTZPN29qNUdkZldGMDdQTVY3WWFETjhGc1YwT19wZDM5bFpiUnM0SlV1Y0xWMzBXNGpqVGdselZGeXBaZEFxQXU0d2pWTVd5T1I0X1RSMnh6YW0wemx0ZXc1bm01TUk4NTlZYVhCVE95bkV5T18yRndDR2hzdmxQR2t5SHZuc050NFVya3pjRGswX0JaYUlYYWFNbUhxMUJQUWdiR0d6bUxNV0FXcFY0OUszdnBkN250WHFBZEVyN25VUnVpS2RSckVTYnpEUnAxclh2NExOMUdGNXRnRUFCZFhwYTVQVG9nVDM3cHUwb1BNNW5FZXFDeklRbmtjemMzUVk5SEZwY1J6bWFmbV9fSngxRFd0ak5qR1J0cVM4aHVUcVNKOG5ORl90ZXZsV2dwOU5uZU9KSUZwZkVMMnhYMTc2dnkyQ1FONTBFRzZZWmM4dXZreHFNUmk3OFNjdENEeXQ0WS5Sc3FFM1dad19XclIxRmtQc1RtWW1B"
+}
\ No newline at end of file


[7/7] jclouds-labs git commit: Add Azure KeyVault support

Posted by na...@apache.org.
Add Azure KeyVault support


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/fa63f6b1
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/fa63f6b1
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/fa63f6b1

Branch: refs/heads/master
Commit: fa63f6b1ff7b48417389a88d6ebae798e6fb6e90
Parents: 5a3b599
Author: Jim Spring <jm...@gmail.com>
Authored: Fri Dec 22 18:37:08 2017 -0800
Committer: Ignasi Barrera <na...@apache.org>
Committed: Thu Jan 4 01:44:48 2018 +0100

----------------------------------------------------------------------
 .../azurecompute/arm/AzureComputeApi.java       |   12 +-
 .../arm/AzureComputeProviderMetadata.java       |    2 +
 .../arm/AzureManagementApiMetadata.java         |    2 +
 .../arm/compute/AzureComputeServiceAdapter.java |    2 +-
 .../AzureComputeServiceContextModule.java       |  269 ---
 .../compute/config/AzurePredicatesModule.java   |  602 +++++++
 .../ResourceGroupAndNameAndIngressRules.java    |    5 +-
 .../extensions/AzureComputeImageExtension.java  |    4 +-
 .../AzureComputeSecurityGroupExtension.java     |    2 +-
 .../loaders/CreateSecurityGroupIfNeeded.java    |    2 +-
 .../arm/config/AzureComputeProperties.java      |    9 +
 .../azurecompute/arm/domain/Certificate.java    |  638 +++++++
 .../jclouds/azurecompute/arm/domain/Key.java    |  229 +++
 .../jclouds/azurecompute/arm/domain/SKU.java    |   27 +-
 .../jclouds/azurecompute/arm/domain/Secret.java |  186 ++
 .../jclouds/azurecompute/arm/domain/Vault.java  |  112 ++
 .../arm/domain/VaultProperties.java             |  131 ++
 .../azurecompute/arm/features/VaultApi.java     |  635 +++++++
 .../arm/features/LoadBalancerApiLiveTest.java   |    2 +-
 .../arm/features/VaultApiLiveTest.java          | 1057 ++++++++++++
 .../arm/features/VaultApiMockTest.java          | 1619 ++++++++++++++++++
 .../internal/BaseAzureComputeApiLiveTest.java   |   60 +-
 .../internal/BaseAzureComputeApiMockTest.java   |   16 +-
 .../src/test/resources/getvault.json            |   60 +
 .../src/test/resources/vaultbackupkey.json      |    3 +
 .../src/test/resources/vaultbackupsecret.json   |    3 +
 .../src/test/resources/vaultcreate.json         |   26 +
 .../test/resources/vaultcreatecertificate.json  |   11 +
 .../vaultcreatecertificaterequestbody.json      |   21 +
 .../src/test/resources/vaultcreatekey.json      |   15 +
 .../resources/vaultcreatekeyrequestbody.json    |    7 +
 .../test/resources/vaultcreaterequestbody.json  |   21 +
 .../test/resources/vaultdeletecertificate.json  |   58 +
 .../vaultdeletecertificatecontacts.json         |    8 +
 .../resources/vaultdeletecertificateissuer.json |   21 +
 .../vaultdeletecertificateoperation.json        |   11 +
 .../src/test/resources/vaultdeletekey.json      |   15 +
 .../src/test/resources/vaultdeletesecret.json   |   10 +
 .../src/test/resources/vaultget.json            |   26 +
 .../src/test/resources/vaultgetcertificate.json |   55 +
 .../resources/vaultgetcertificatecontacts.json  |    8 +
 .../resources/vaultgetcertificateissuer.json    |   21 +
 .../resources/vaultgetcertificateoperation.json |   11 +
 .../resources/vaultgetcertificatepolicy.json    |   37 +
 .../src/test/resources/vaultgetdeleted.json     |   12 +
 .../resources/vaultgetdeletedcertificate.json   |   55 +
 .../src/test/resources/vaultgetdeletedkey.json  |   18 +
 .../test/resources/vaultgetdeletedsecret.json   |   13 +
 .../src/test/resources/vaultgetkey.json         |   15 +
 .../src/test/resources/vaultgetkeyversions.json |   23 +
 .../src/test/resources/vaultgetsecret.json      |   11 +
 .../test/resources/vaultgetsecretversions.json  |   25 +
 .../src/test/resources/vaultimportablecert.txt  |   58 +
 .../test/resources/vaultimportcertificate.json  |   52 +
 .../vaultimportcertificaterequestbody.json      |    9 +
 .../resources/vaultimportkeyrequestbody.json    |   18 +
 .../src/test/resources/vaultkeybackup.txt       |    1 +
 .../src/test/resources/vaultkeydecrypt.json     |    4 +
 .../resources/vaultkeydecryptrequestbody.json   |    4 +
 .../src/test/resources/vaultkeyencrypt.json     |    4 +
 .../resources/vaultkeyencryptrequestbody.json   |    4 +
 .../src/test/resources/vaultkeysign.json        |    4 +
 .../test/resources/vaultkeysignrequestbody.json |    4 +
 .../src/test/resources/vaultkeyunwrap.json      |    4 +
 .../resources/vaultkeyunwraprequestbody.json    |    4 +
 .../src/test/resources/vaultkeyverify.json      |    3 +
 .../resources/vaultkeyverifyrequestbody.json    |    5 +
 .../src/test/resources/vaultkeywrap.json        |    4 +
 .../test/resources/vaultkeywraprequestbody.json |    4 +
 .../src/test/resources/vaultlist.json           |   29 +
 .../resources/vaultlistcertificateissuers.json  |    7 +
 .../test/resources/vaultlistcertificates.json   |   27 +
 .../resources/vaultlistcertificateversions.json |   17 +
 .../src/test/resources/vaultlistdeleted.json    |   15 +
 .../resources/vaultlistdeletedcertificates.json |   18 +
 .../test/resources/vaultlistdeletedkeys.json    |   15 +
 .../test/resources/vaultlistdeletedsecrets.json |   16 +
 .../src/test/resources/vaultlistkeys.json       |   42 +
 .../src/test/resources/vaultlistsecrets.json    |   40 +
 .../test/resources/vaultmergecertificate.json   |   62 +
 .../vaultmergecertificaterequestbody.json       |   10 +
 .../src/test/resources/vaultmergex5c-1.txt      |    1 +
 .../src/test/resources/vaultmergex5c-2.txt      |    1 +
 .../src/test/resources/vaultmergex5c-3.txt      |    1 +
 .../vaultrecoverdeletedcertificate.json         |   52 +
 .../test/resources/vaultrecoverdeletedkey.json  |   15 +
 .../resources/vaultrecoverdeletedsecret.json    |   10 +
 .../src/test/resources/vaultrestorekey.json     |   15 +
 .../resources/vaultrestorekeyrequestbody.json   |    3 +
 .../src/test/resources/vaultrestoresecret.json  |   10 +
 .../vaultrestoresecretrequestbody.json          |    3 +
 .../src/test/resources/vaultsamplesecret.txt    |   27 +
 .../src/test/resources/vaultsecretbackup.txt    |    1 +
 .../resources/vaultsetcertificatecontacts.json  |    8 +
 .../vaultsetcertificatecontactsrequestbody.json |    7 +
 .../resources/vaultsetcertificateissuer.json    |   21 +
 .../vaultsetcertificateissuerrequestbody.json   |   15 +
 .../src/test/resources/vaultsetsecret.json      |   11 +
 .../resources/vaultsetsecretrequestbody.json    |    7 +
 .../test/resources/vaultupdatecertificate.json  |   58 +
 .../resources/vaultupdatecertificateissuer.json |   21 +
 ...vaultupdatecertificateissuerrequestbody.json |   15 +
 .../vaultupdatecertificateoperation.json        |   11 +
 ...ltupdatecertificateoperationrequestbody.json |    3 +
 .../resources/vaultupdatecertificatepolicy.json |   37 +
 ...vaultupdatecertificatepolicyrequestbody.json |    8 +
 .../vaultupdatecertificaterequestbody.json      |    1 +
 .../src/test/resources/vaultupdatekey.json      |   18 +
 .../resources/vaultupdatekeyrequestbody.json    |    5 +
 .../resources/vaultupdatekeywithversion.json    |   18 +
 .../src/test/resources/vaultupdatesecret.json   |   13 +
 .../resources/vaultupdatesecretrequestbody.json |    5 +
 .../resources/vaultupdatesecretwithversion.json |   13 +
 ...vaultupdatesecretwithversionrequestbody.json |    5 +
 114 files changed, 6861 insertions(+), 305 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
index 1f6b726..d62a5b7 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
@@ -41,6 +41,7 @@ import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
 import org.jclouds.azurecompute.arm.features.StorageAccountApi;
 import org.jclouds.azurecompute.arm.features.SubnetApi;
 import org.jclouds.azurecompute.arm.features.VMSizeApi;
+import org.jclouds.azurecompute.arm.features.VaultApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineScaleSetApi;
 import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
@@ -242,7 +243,7 @@ public interface AzureComputeApi extends Closeable {
     */
    @Delegate
    MetricDefinitionsApi getMetricsDefinitionsApi(@PathParam("resourceid") String resourceid);
-   
+
    /**
     * The Azure Active Directory Graph API provides programmatic access to Azure
     * AD through REST API endpoints.
@@ -253,6 +254,15 @@ public interface AzureComputeApi extends Closeable {
    GraphRBACApi getGraphRBACApi();
    
    /**
+    * Managing your key vaults as well as the keys, secrets, and certificates within your key vaults can be 
+    * accomplished through a REST interface.
+    *
+    * @see <a href="https://docs.microsoft.com/en-us/rest/api/keyvault/">docs</a>
+    */
+   @Delegate
+   VaultApi getVaultApi(@PathParam("resourcegroup") String resourcegroup);
+   
+   /**
     * Returns the information about the current service principal.
     */
    @Provides

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index 335de98..c85beb9 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
@@ -57,6 +57,7 @@ import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
 import org.jclouds.azurecompute.arm.features.StorageAccountApi;
 import org.jclouds.azurecompute.arm.features.SubnetApi;
 import org.jclouds.azurecompute.arm.features.VMSizeApi;
+import org.jclouds.azurecompute.arm.features.VaultApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
 import org.jclouds.azurecompute.arm.features.VirtualMachineScaleSetApi;
 import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
@@ -126,6 +127,7 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.put(API_VERSION_PREFIX + MetricsApi.class.getSimpleName(), "2016-09-01");
       properties.put(API_VERSION_PREFIX + VirtualMachineScaleSetApi.class.getSimpleName(), "2017-03-30");
       properties.put(API_VERSION_PREFIX + GraphRBACApi.class.getSimpleName(), "1.6");
+      properties.put(API_VERSION_PREFIX + VaultApi.class.getSimpleName(), "2016-10-01");
       
       return properties;
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java
index 9c73e99..56cb788 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureManagementApiMetadata.java
@@ -23,6 +23,7 @@ import java.util.Properties;
 
 import org.jclouds.apis.ApiMetadata;
 import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule;
 import org.jclouds.azurecompute.arm.config.AzureComputeHttpApiModule;
 import org.jclouds.azurecompute.arm.config.AzureComputeParserModule;
 import org.jclouds.azurecompute.arm.config.AzureComputeRateLimitModule;
@@ -80,6 +81,7 @@ public class AzureManagementApiMetadata extends BaseHttpApiMetadata<AzureCompute
                          .add(AzureComputeParserModule.class)
                          .add(AzureComputeHttpApiModule.class)
                          .add(AzureComputeServiceContextModule.class)
+                         .add(AzurePredicatesModule.class)
                          .add(AzureComputeRateLimitModule.class)
                          .build());
       }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index 37585e2..cd5e0e9 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -45,7 +45,7 @@ import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.PublicIpAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
index 11d3ab1..de33fdf 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
@@ -16,22 +16,8 @@
  */
 package org.jclouds.azurecompute.arm.compute.config;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
-import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
-import static org.jclouds.util.Predicates2.retry;
-
-import java.net.URI;
-import java.util.List;
-
-import javax.inject.Named;
 import javax.inject.Singleton;
 
-import org.jclouds.azurecompute.arm.AzureComputeApi;
 import org.jclouds.azurecompute.arm.compute.AzureComputeService;
 import org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndNameAndIngressRules;
@@ -47,20 +33,13 @@ import org.jclouds.azurecompute.arm.compute.loaders.CreateSecurityGroupIfNeeded;
 import org.jclouds.azurecompute.arm.compute.loaders.DefaultResourceGroup;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.compute.strategy.CreateResourcesThenCreateNodes;
-import org.jclouds.azurecompute.arm.domain.Image;
 import org.jclouds.azurecompute.arm.domain.Location;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
-import org.jclouds.azurecompute.arm.domain.Provisionable;
-import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
-import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.VMHardware;
 import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
-import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
-import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.PowerState;
-import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
 import org.jclouds.compute.ComputeService;
 import org.jclouds.compute.ComputeServiceAdapter;
 import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
@@ -72,15 +51,10 @@ import org.jclouds.compute.extensions.SecurityGroupExtension;
 import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatement;
 import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatementWithoutPublicKey;
 import org.jclouds.compute.options.TemplateOptions;
-import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
-import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
 import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
 import org.jclouds.net.domain.IpPermission;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
@@ -141,247 +115,4 @@ public class AzureComputeServiceContextModule extends
    protected final LoadingCache<String, ResourceGroup> defaultResourceGroup(CacheLoader<String, ResourceGroup> in) {
       return CacheBuilder.newBuilder().build(in);
    }
-
-   @Provides
-   @Named(TIMEOUT_NODE_RUNNING)
-   protected VirtualMachineInStatePredicateFactory provideVirtualMachineRunningPredicate(final AzureComputeApi api,
-         final Timeouts timeouts, final PollPeriod pollPeriod) {
-      return new VirtualMachineInStatePredicateFactory(api, PowerState.RUNNING, timeouts.nodeRunning,
-            pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
-   }
-
-   @Provides
-   @Named(TIMEOUT_NODE_TERMINATED)
-   protected Predicate<URI> provideNodeTerminatedPredicate(final AzureComputeApi api, final Timeouts timeouts,
-         final PollPeriod pollPeriod) {
-      return retry(new ActionDonePredicate(api), timeouts.nodeTerminated, pollPeriod.pollInitialPeriod,
-            pollPeriod.pollMaxPeriod);
-   }
-
-   @Provides
-   @Named(TIMEOUT_IMAGE_AVAILABLE)
-   protected Predicate<URI> provideImageCapturedPredicate(final AzureComputeApi api, final Timeouts timeouts,
-         final PollPeriod pollPeriod) {
-      return retry(new ImageCapturedPredicate(api), timeouts.imageAvailable, pollPeriod.pollInitialPeriod,
-            pollPeriod.pollMaxPeriod);
-   }
-
-   @Provides
-   @Named(TIMEOUT_RESOURCE_DELETED)
-   protected Predicate<URI> provideResourceDeletedPredicate(final AzureComputeApi api, final Timeouts timeouts,
-         final PollPeriod pollPeriod) {
-      return retry(new ActionDonePredicate(api), timeouts.nodeTerminated, pollPeriod.pollInitialPeriod,
-            pollPeriod.pollMaxPeriod);
-   }
-
-   @Provides
-   @Named(TIMEOUT_NODE_SUSPENDED)
-   protected VirtualMachineInStatePredicateFactory provideNodeSuspendedPredicate(final AzureComputeApi api,
-         final Timeouts timeouts, final PollPeriod pollPeriod) {
-      return new VirtualMachineInStatePredicateFactory(api, PowerState.STOPPED, timeouts.nodeTerminated,
-            pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
-   }
-
-   @Provides
-   protected PublicIpAvailablePredicateFactory providePublicIpAvailablePredicate(final AzureComputeApi api,
-         Predicate<Supplier<Provisionable>> resourceAvailable) {
-      return new PublicIpAvailablePredicateFactory(api, resourceAvailable);
-   }
-
-   @Provides
-   protected SecurityGroupAvailablePredicateFactory provideSecurityGroupAvailablePredicate(final AzureComputeApi api,
-         Predicate<Supplier<Provisionable>> resourceAvailable) {
-      return new SecurityGroupAvailablePredicateFactory(api, resourceAvailable);
-   }
-   
-   @Provides
-   protected ImageAvailablePredicateFactory provideImageAvailablePredicate(final AzureComputeApi api,
-         Predicate<Supplier<Provisionable>> resourceAvailable, final Timeouts timeouts, final PollPeriod pollPeriod) {
-      return new ImageAvailablePredicateFactory(api, retry(new ResourceInStatusPredicate("Succeeded"),
-            timeouts.imageAvailable, pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod));
-   }
-
-   @Provides
-   protected Predicate<Supplier<Provisionable>> provideResourceAvailablePredicate(final AzureComputeApi api,
-         @Named(OPERATION_TIMEOUT) Integer operationTimeout, PollPeriod pollPeriod) {
-      return retry(new ResourceInStatusPredicate("Succeeded"), operationTimeout, pollPeriod.pollInitialPeriod,
-            pollPeriod.pollMaxPeriod);
-   }
-
-   @Provides
-   @Named("STORAGE")
-   protected Predicate<URI> provideStorageAccountAvailablePredicate(final AzureComputeApi api,
-         @Named(OPERATION_TIMEOUT) Integer operationTimeout, PollPeriod pollPeriod) {
-      return retry(new ActionDonePredicate(api), operationTimeout, pollPeriod.pollInitialPeriod,
-            pollPeriod.pollMaxPeriod);
-   }
-
-   @VisibleForTesting
-   static class ActionDonePredicate implements Predicate<URI> {
-
-      private final AzureComputeApi api;
-
-      public ActionDonePredicate(final AzureComputeApi api) {
-         this.api = checkNotNull(api, "api must not be null");
-      }
-
-      @Override
-      public boolean apply(final URI uri) {
-         checkNotNull(uri, "uri cannot be null");
-         return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri)
-               || ParseJobStatus.JobStatus.NO_CONTENT == api.getJobApi().jobStatus(uri);
-      }
-
-   }
-
-   @VisibleForTesting
-   static class ImageCapturedPredicate implements Predicate<URI> {
-
-      private final AzureComputeApi api;
-
-      public ImageCapturedPredicate(final AzureComputeApi api) {
-         this.api = checkNotNull(api, "api must not be null");
-      }
-
-      @Override
-      public boolean apply(final URI uri) {
-         checkNotNull(uri, "uri cannot be null");
-         if (api.getJobApi().jobStatus(uri) != ParseJobStatus.JobStatus.DONE) {
-            return false;
-         }
-         List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
-         return definitions != null;
-      }
-   }
-
-   public static class VirtualMachineInStatePredicateFactory {
-
-      private final AzureComputeApi api;
-      private final PowerState powerState;
-      private final long timeout;
-      private final long period;
-      private final long maxPeriod;
-
-      VirtualMachineInStatePredicateFactory(final AzureComputeApi api, final PowerState powerState, final long timeout,
-            final long period, final long maxPeriod) {
-         this.api = checkNotNull(api, "api cannot be null");
-         this.powerState = checkNotNull(powerState, "powerState cannot be null");
-         this.timeout = timeout;
-         this.period = period;
-         this.maxPeriod = maxPeriod;
-      }
-
-      public Predicate<String> create(final String azureGroup) {
-         return retry(new Predicate<String>() {
-            @Override
-            public boolean apply(final String name) {
-               checkNotNull(name, "name cannot be null");
-               VirtualMachineInstance vmInstance = api.getVirtualMachineApi(azureGroup).getInstanceDetails(name);
-               if (vmInstance == null) {
-                  return false;
-               }
-               return powerState == vmInstance.powerState();
-            }
-         }, timeout, period, maxPeriod);
-      }
-   }
-   
-   public static class ResourceInStatusPredicate implements Predicate<Supplier<Provisionable>> {
-      private final String expectedStatus;
-
-      ResourceInStatusPredicate(String expectedStatus) {
-         this.expectedStatus = checkNotNull(expectedStatus, "expectedStatus cannot be null");
-      }
-
-      @Override
-      public boolean apply(Supplier<Provisionable> provisionableSupplier) {
-         checkNotNull(provisionableSupplier, "provisionableSupplier supplier cannot be null");
-         Provisionable provisionable = provisionableSupplier.get();
-         return provisionable != null && provisionable.provisioningState().equalsIgnoreCase(expectedStatus);
-      }
-   }
-
-   public static class PublicIpAvailablePredicateFactory {
-      private final AzureComputeApi api;
-      private final Predicate<Supplier<Provisionable>> resourceAvailable;
-
-      PublicIpAvailablePredicateFactory(final AzureComputeApi api, Predicate<Supplier<Provisionable>> resourceAvailable) {
-         this.api = checkNotNull(api, "api cannot be null");
-         this.resourceAvailable = resourceAvailable;
-      }
-
-      public Predicate<String> create(final String azureGroup) {
-         checkNotNull(azureGroup, "azureGroup cannot be null");
-         return new Predicate<String>() {
-            @Override
-            public boolean apply(final String name) {
-               checkNotNull(name, "name cannot be null");
-               return resourceAvailable.apply(new Supplier<Provisionable>() {
-                  @Override
-                  public Provisionable get() {
-                     PublicIPAddress publicIp = api.getPublicIPAddressApi(azureGroup).get(name);
-                     return publicIp == null ? null : publicIp.properties();
-                  }
-               });
-            }
-         };
-      }
-   }
-
-   public static class SecurityGroupAvailablePredicateFactory {
-      private final AzureComputeApi api;
-      private final Predicate<Supplier<Provisionable>> resourceAvailable;
-
-      SecurityGroupAvailablePredicateFactory(final AzureComputeApi api,
-            Predicate<Supplier<Provisionable>> resourceAvailable) {
-         this.api = checkNotNull(api, "api cannot be null");
-         this.resourceAvailable = resourceAvailable;
-      }
-
-      public Predicate<String> create(final String resourceGroup) {
-         checkNotNull(resourceGroup, "resourceGroup cannot be null");
-         return new Predicate<String>() {
-            @Override
-            public boolean apply(final String name) {
-               checkNotNull(name, "name cannot be null");
-               return resourceAvailable.apply(new Supplier<Provisionable>() {
-                  @Override
-                  public Provisionable get() {
-                     NetworkSecurityGroup sg = api.getNetworkSecurityGroupApi(resourceGroup).get(name);
-                     return sg == null ? null : sg.properties();
-                  }
-               });
-            }
-         };
-      }
-   }
-   
-   public static class ImageAvailablePredicateFactory {
-      private final AzureComputeApi api;
-      private final Predicate<Supplier<Provisionable>> resourceAvailable;
-      
-      ImageAvailablePredicateFactory(final AzureComputeApi api,
-            Predicate<Supplier<Provisionable>> resourceAvailable) {
-         this.api = checkNotNull(api, "api cannot be null");
-         this.resourceAvailable = resourceAvailable;
-      }
-
-      public Predicate<String> create(final String resourceGroup) {
-         checkNotNull(resourceGroup, "resourceGroup cannot be null");
-         return new Predicate<String>() {
-            @Override
-            public boolean apply(final String name) {
-               checkNotNull(name, "name cannot be null");
-               return resourceAvailable.apply(new Supplier<Provisionable>() {
-                  @Override
-                  public Provisionable get() {
-                     Image img = api.getVirtualMachineImageApi(resourceGroup).get(name);
-                     return img == null ? null : img.properties();
-                  }
-               });
-            }
-         };
-      }
-   }
-
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzurePredicatesModule.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzurePredicatesModule.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzurePredicatesModule.java
new file mode 100644
index 0000000..c8dfd6e
--- /dev/null
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzurePredicatesModule.java
@@ -0,0 +1,602 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.compute.config;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.google.inject.name.Named;
+
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
+
+import org.jclouds.azurecompute.arm.domain.Image;
+import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
+import org.jclouds.azurecompute.arm.domain.Provisionable;
+import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
+import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
+import org.jclouds.azurecompute.arm.domain.Vault;
+import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
+import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
+import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.domain.Key.DeletedKeyBundle;
+import org.jclouds.azurecompute.arm.domain.Key.KeyBundle;
+import org.jclouds.azurecompute.arm.domain.Secret.DeletedSecretBundle;
+import org.jclouds.azurecompute.arm.domain.Secret.SecretBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.DeletedCertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateBundle;
+import org.jclouds.azurecompute.arm.domain.Certificate.CertificateOperation;
+
+import java.net.URI;
+import java.util.List;
+
+import static org.jclouds.util.Predicates2.retry;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_DELETE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_KEY_DELETED_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_KEY_RECOVERABLE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_SECRET_DELETE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_SECRET_RECOVERABLE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_CERTIFICATE_DELETE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_CERTIFICATE_RECOVERABLE_STATUS;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_CERTIFICATE_OPERATION_STATUS;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class AzurePredicatesModule extends AbstractModule {
+    protected void configure() {
+    }
+
+    @Provides
+    @Named(TIMEOUT_NODE_RUNNING)
+    protected VirtualMachineInStatePredicateFactory provideVirtualMachineRunningPredicate(final AzureComputeApi api,
+                                                                                          final ComputeServiceConstants.Timeouts timeouts, final PollPeriod pollPeriod) {
+        return new VirtualMachineInStatePredicateFactory(api, VirtualMachineInstance.PowerState.RUNNING, timeouts.nodeRunning,
+                pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(TIMEOUT_NODE_TERMINATED)
+    protected Predicate<URI> provideNodeTerminatedPredicate(final AzureComputeApi api, final ComputeServiceConstants.Timeouts timeouts,
+                                                            final PollPeriod pollPeriod) {
+        return retry(new ActionDonePredicate(api), timeouts.nodeTerminated, pollPeriod.pollInitialPeriod,
+                pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(TIMEOUT_IMAGE_AVAILABLE)
+    protected Predicate<URI> provideImageCapturedPredicate(final AzureComputeApi api, final ComputeServiceConstants.Timeouts timeouts,
+                                                           final PollPeriod pollPeriod) {
+        return retry(new ImageCapturedPredicate(api), timeouts.imageAvailable, pollPeriod.pollInitialPeriod,
+                pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(TIMEOUT_RESOURCE_DELETED)
+    protected Predicate<URI> provideResourceDeletedPredicate(final AzureComputeApi api, final ComputeServiceConstants.Timeouts timeouts,
+                                                             final PollPeriod pollPeriod) {
+        return retry(new ActionDonePredicate(api), timeouts.nodeTerminated, pollPeriod.pollInitialPeriod,
+                pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(TIMEOUT_NODE_SUSPENDED)
+    protected VirtualMachineInStatePredicateFactory provideNodeSuspendedPredicate(final AzureComputeApi api,
+                                                                                  final ComputeServiceConstants.Timeouts timeouts, final PollPeriod pollPeriod) {
+        return new VirtualMachineInStatePredicateFactory(api, VirtualMachineInstance.PowerState.STOPPED, timeouts.nodeTerminated,
+                pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    protected PublicIpAvailablePredicateFactory providePublicIpAvailablePredicate(final AzureComputeApi api,
+                                                                                  Predicate<Supplier<Provisionable>> resourceAvailable) {
+        return new PublicIpAvailablePredicateFactory(api, resourceAvailable);
+    }
+
+    @Provides
+    protected SecurityGroupAvailablePredicateFactory provideSecurityGroupAvailablePredicate(final AzureComputeApi api,
+                                                                                            Predicate<Supplier<Provisionable>> resourceAvailable) {
+        return new SecurityGroupAvailablePredicateFactory(api, resourceAvailable);
+    }
+
+    @Provides
+    protected ImageAvailablePredicateFactory provideImageAvailablePredicate(final AzureComputeApi api,
+                                                                            Predicate<Supplier<Provisionable>> resourceAvailable, final ComputeServiceConstants.Timeouts timeouts, final PollPeriod pollPeriod) {
+        return new ImageAvailablePredicateFactory(api, retry(new ResourceInStatusPredicate("Succeeded"),
+                timeouts.imageAvailable, pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod));
+    }
+
+    @Provides
+    protected Predicate<Supplier<Provisionable>> provideResourceAvailablePredicate(final AzureComputeApi api,
+                                                                                   @Named(OPERATION_TIMEOUT) Integer operationTimeout, PollPeriod pollPeriod) {
+        return retry(new ResourceInStatusPredicate("Succeeded"), operationTimeout, pollPeriod.pollInitialPeriod,
+                pollPeriod.pollMaxPeriod);
+    }
+
+    @VisibleForTesting
+    static class ActionDonePredicate implements Predicate<URI> {
+
+        private final AzureComputeApi api;
+
+        public ActionDonePredicate(final AzureComputeApi api) {
+            this.api = checkNotNull(api, "api must not be null");
+        }
+
+        @Override
+        public boolean apply(final URI uri) {
+            checkNotNull(uri, "uri cannot be null");
+            return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri)
+                    || ParseJobStatus.JobStatus.NO_CONTENT == api.getJobApi().jobStatus(uri);
+        }
+    }
+
+    @VisibleForTesting
+    static class ImageCapturedPredicate implements Predicate<URI> {
+
+        private final AzureComputeApi api;
+
+        public ImageCapturedPredicate(final AzureComputeApi api) {
+            this.api = checkNotNull(api, "api must not be null");
+        }
+
+        @Override
+        public boolean apply(final URI uri) {
+            checkNotNull(uri, "uri cannot be null");
+            if (api.getJobApi().jobStatus(uri) != ParseJobStatus.JobStatus.DONE) {
+                return false;
+            }
+            List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
+            return definitions != null;
+        }
+    }
+
+    public static class VirtualMachineInStatePredicateFactory {
+
+        private final AzureComputeApi api;
+        private final VirtualMachineInstance.PowerState powerState;
+        private final long timeout;
+        private final long period;
+        private final long maxPeriod;
+
+        VirtualMachineInStatePredicateFactory(final AzureComputeApi api, final VirtualMachineInstance.PowerState powerState, final long timeout,
+                                              final long period, final long maxPeriod) {
+            this.api = checkNotNull(api, "api cannot be null");
+            this.powerState = checkNotNull(powerState, "powerState cannot be null");
+            this.timeout = timeout;
+            this.period = period;
+            this.maxPeriod = maxPeriod;
+        }
+
+        public Predicate<String> create(final String azureGroup) {
+            return retry(new Predicate<String>() {
+                @Override
+                public boolean apply(final String name) {
+                    checkNotNull(name, "name cannot be null");
+                    VirtualMachineInstance vmInstance = api.getVirtualMachineApi(azureGroup).getInstanceDetails(name);
+                    if (vmInstance == null) {
+                        return false;
+                    }
+                    return powerState == vmInstance.powerState();
+                }
+            }, timeout, period, maxPeriod);
+        }
+    }
+
+    public static class ResourceInStatusPredicate implements Predicate<Supplier<Provisionable>> {
+        private final String expectedStatus;
+
+        ResourceInStatusPredicate(String expectedStatus) {
+            this.expectedStatus = checkNotNull(expectedStatus, "expectedStatus cannot be null");
+        }
+
+        @Override
+        public boolean apply(Supplier<Provisionable> provisionableSupplier) {
+            checkNotNull(provisionableSupplier, "provisionableSupplier supplier cannot be null");
+            Provisionable provisionable = provisionableSupplier.get();
+            return provisionable != null && provisionable.provisioningState().equalsIgnoreCase(expectedStatus);
+        }
+    }
+
+    public static class PublicIpAvailablePredicateFactory {
+        private final AzureComputeApi api;
+        private final Predicate<Supplier<Provisionable>> resourceAvailable;
+
+        PublicIpAvailablePredicateFactory(final AzureComputeApi api, Predicate<Supplier<Provisionable>> resourceAvailable) {
+            this.api = checkNotNull(api, "api cannot be null");
+            this.resourceAvailable = resourceAvailable;
+        }
+
+        public Predicate<String> create(final String azureGroup) {
+            checkNotNull(azureGroup, "azureGroup cannot be null");
+            return new Predicate<String>() {
+                @Override
+                public boolean apply(final String name) {
+                    checkNotNull(name, "name cannot be null");
+                    return resourceAvailable.apply(new Supplier<Provisionable>() {
+                        @Override
+                        public Provisionable get() {
+                            PublicIPAddress publicIp = api.getPublicIPAddressApi(azureGroup).get(name);
+                            return publicIp == null ? null : publicIp.properties();
+                        }
+                    });
+                }
+            };
+        }
+    }
+
+    public static class SecurityGroupAvailablePredicateFactory {
+        private final AzureComputeApi api;
+        private final Predicate<Supplier<Provisionable>> resourceAvailable;
+
+        SecurityGroupAvailablePredicateFactory(final AzureComputeApi api,
+                                               Predicate<Supplier<Provisionable>> resourceAvailable) {
+            this.api = checkNotNull(api, "api cannot be null");
+            this.resourceAvailable = resourceAvailable;
+        }
+
+        public Predicate<String> create(final String resourceGroup) {
+            checkNotNull(resourceGroup, "resourceGroup cannot be null");
+            return new Predicate<String>() {
+                @Override
+                public boolean apply(final String name) {
+                    checkNotNull(name, "name cannot be null");
+                    return resourceAvailable.apply(new Supplier<Provisionable>() {
+                        @Override
+                        public Provisionable get() {
+                            NetworkSecurityGroup sg = api.getNetworkSecurityGroupApi(resourceGroup).get(name);
+                            return sg == null ? null : sg.properties();
+                        }
+                    });
+                }
+            };
+        }
+    }
+
+    public static class ImageAvailablePredicateFactory {
+        private final AzureComputeApi api;
+        private final Predicate<Supplier<Provisionable>> resourceAvailable;
+
+        ImageAvailablePredicateFactory(final AzureComputeApi api,
+                                       Predicate<Supplier<Provisionable>> resourceAvailable) {
+            this.api = checkNotNull(api, "api cannot be null");
+            this.resourceAvailable = resourceAvailable;
+        }
+
+        public Predicate<String> create(final String resourceGroup) {
+            checkNotNull(resourceGroup, "resourceGroup cannot be null");
+            return new Predicate<String>() {
+                @Override
+                public boolean apply(final String name) {
+                    checkNotNull(name, "name cannot be null");
+                    return resourceAvailable.apply(new Supplier<Provisionable>() {
+                        @Override
+                        public Provisionable get() {
+                            Image img = api.getVirtualMachineImageApi(resourceGroup).get(name);
+                            return img == null ? null : img.properties();
+                        }
+                    });
+                }
+            };
+        }
+    }
+
+    @Provides
+    @Named(VAULT_DELETE_STATUS)
+    protected VaultPredicates.DeletedVaultStatusPredicateFactory provideDeletedVaultStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                           @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                           final PollPeriod pollPeriod) {
+        return new VaultPredicates.DeletedVaultStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    public static class VaultPredicates {
+        public static class DeletedVaultStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            DeletedVaultStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final boolean shouldBePresent) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        checkNotNull(name, "name cannot be null");
+                        boolean present = false;
+                        List<Vault.DeletedVault> vaults = api.getVaultApi(resourceGroup).listDeletedVaults();
+                        return shouldBePresent == Iterables.any(vaults, new Predicate<Vault.DeletedVault>() {
+                            @Override public boolean apply(Vault.DeletedVault input) {
+                                return input.name().equals(name);
+                            }
+                        });
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+    }
+
+    @Provides
+    @Named(VAULT_KEY_DELETED_STATUS)
+    protected VaultKeyPredicates.DeletedKeyStatusPredicateFactory provideDeletedKeyStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                          @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                          final PollPeriod pollPeriod) {
+        return new VaultKeyPredicates.DeletedKeyStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(VAULT_KEY_RECOVERABLE_STATUS)
+    protected VaultKeyPredicates.RecoverableKeyStatusPredicateFactory provideRecoverableKeyStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                                  @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                                  final PollPeriod pollPeriod) {
+        return new VaultKeyPredicates.RecoverableKeyStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    public static class VaultKeyPredicates {
+        public static class DeletedKeyStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            DeletedKeyStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final URI vaultUri, final boolean shouldBePresent) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                checkNotNull(vaultUri, "vaultUri cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        checkNotNull(name, "name cannot be null");
+                        boolean present = false;
+                        DeletedKeyBundle key = api.getVaultApi(resourceGroup).getDeletedKey(vaultUri, name);
+                        return shouldBePresent == (key != null);
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+
+        public static class RecoverableKeyStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            RecoverableKeyStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final URI vaultUri, final boolean isRecovered) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                checkNotNull(vaultUri, "vaultUri cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        checkNotNull(name, "name cannot be null");
+                        boolean result = false;
+                        KeyBundle key = api.getVaultApi(resourceGroup).getKey(vaultUri, name);
+                        return key != null ? (isRecovered ? true : key.attributes().recoveryLevel().contains("Recoverable")) : false;
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+    }
+
+    @Provides
+    @Named(VAULT_SECRET_DELETE_STATUS)
+    protected VaultSecretPredicates.DeletedSecretStatusPredicateFactory provideDeletedSecretStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                                   @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                                   final PollPeriod pollPeriod) {
+        return new VaultSecretPredicates.DeletedSecretStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(VAULT_SECRET_RECOVERABLE_STATUS)
+    protected VaultSecretPredicates.RecoverableSecretStatusPredicateFactory provideRecoverableSecretStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                                           @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                                           final PollPeriod pollPeriod) {
+        return new VaultSecretPredicates.RecoverableSecretStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    public static class VaultSecretPredicates {
+        public static class DeletedSecretStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            DeletedSecretStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final URI vaultUri, final boolean shouldBePresent) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                checkNotNull(vaultUri, "vaultUri cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        boolean present = false;
+                        checkNotNull(name, "name cannot be null");
+                        DeletedSecretBundle secret = api.getVaultApi(resourceGroup).getDeletedSecret(vaultUri, name);
+                        return shouldBePresent == (secret != null);
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+
+        public static class RecoverableSecretStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            RecoverableSecretStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final URI vaultUri, final boolean isRecovered) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                checkNotNull(vaultUri, "vaultUri cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        checkNotNull(name, "name cannot be null");
+                        SecretBundle secret = api.getVaultApi(resourceGroup).getSecret(vaultUri, name, null);
+                        return secret != null ? (isRecovered ? true : secret.attributes().recoveryLevel().contains("Recoverable")) : false;
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+    }
+
+    @Provides
+    @Named(VAULT_CERTIFICATE_DELETE_STATUS)
+    protected VaultCertificatePredicates.DeletedCertificateStatusPredicateFactory provideDeletedCertificateStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                                                  @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                                                  final PollPeriod pollPeriod) {
+        return new VaultCertificatePredicates.DeletedCertificateStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(VAULT_CERTIFICATE_RECOVERABLE_STATUS)
+    protected VaultCertificatePredicates.RecoverableCertificateStatusPredicateFactory provideRecoverableCertificateStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                                                          @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                                                          final PollPeriod pollPeriod) {
+        return new VaultCertificatePredicates.RecoverableCertificateStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    @Provides
+    @Named(VAULT_CERTIFICATE_OPERATION_STATUS)
+    protected VaultCertificatePredicates.CertificateOperationStatusPredicateFactory provideCertificateOperationStatusPredicateFactory(final AzureComputeApi api,
+                                                                                                                                      @Named(OPERATION_TIMEOUT) Integer operationTimeout,
+                                                                                                                                      final PollPeriod pollPeriod) {
+        return new VaultCertificatePredicates.CertificateOperationStatusPredicateFactory(api, operationTimeout.longValue(), pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+    }
+
+    public static class VaultCertificatePredicates {
+        public static class DeletedCertificateStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            DeletedCertificateStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final URI vaultUri, final boolean shouldBePresent) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                checkNotNull(vaultUri, "vaultUri cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        boolean present = false;
+                        checkNotNull(name, "name cannot be null");
+                        DeletedCertificateBundle cert = api.getVaultApi(resourceGroup).getDeletedCertificate(vaultUri, name);
+                        return shouldBePresent == (cert != null);
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+
+        public static class RecoverableCertificateStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            RecoverableCertificateStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final URI vaultUri, final boolean isImport) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                checkNotNull(vaultUri, "vaultUri cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        checkNotNull(name, "name cannot be null");
+                        CertificateBundle cert = api.getVaultApi(resourceGroup).getCertificate(vaultUri, name, null);
+                        return cert != null ? (isImport ? true : cert.attributes().recoveryLevel().contains("Recoverable")) : false;
+
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+
+        public static class CertificateOperationStatusPredicateFactory {
+            private final AzureComputeApi api;
+            private final long operationTimeout;
+            private final long initialPeriod;
+            private final long maxPeriod;
+
+            CertificateOperationStatusPredicateFactory(final AzureComputeApi api, final long operationTimeout, final long initialPeriod, final long maxPeriod) {
+                this.api = checkNotNull(api, "api cannot be null");
+                this.operationTimeout = operationTimeout;
+                this.initialPeriod = initialPeriod;
+                this.maxPeriod = maxPeriod;
+            }
+
+            public Predicate<String> create(final String resourceGroup, final URI vaultUri, final boolean isCreate) {
+                checkNotNull(resourceGroup, "resourceGroup cannot be null");
+                checkNotNull(vaultUri, "vaultUri cannot be null");
+                return retry(new Predicate<String>() {
+                    @Override
+                    public boolean apply(final String name) {
+                        checkNotNull(name, "name cannot be null");
+                        boolean result = false;
+                        CertificateOperation certOp = api.getVaultApi(resourceGroup).getCertificateOperation(vaultUri, name);
+                        return isCreate ? ((certOp != null) ? !certOp.status().equals("inProgress") : false) : (certOp == null);
+                    }
+                }, operationTimeout, initialPeriod, maxPeriod);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java
index 2b07406..7c11642 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/domain/ResourceGroupAndNameAndIngressRules.java
@@ -18,6 +18,8 @@ package org.jclouds.azurecompute.arm.compute.domain;
 
 import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
 
+import java.util.Arrays;
+
 import com.google.auto.value.AutoValue;
 import com.google.common.base.Objects;
 
@@ -28,6 +30,7 @@ public abstract class ResourceGroupAndNameAndIngressRules {
    
    public abstract String location();
 
+   @SuppressWarnings("mutable")
    public abstract int[] inboundPorts();
 
    ResourceGroupAndNameAndIngressRules() {
@@ -37,7 +40,7 @@ public abstract class ResourceGroupAndNameAndIngressRules {
    public static ResourceGroupAndNameAndIngressRules create(String resourceGroup, String location, String name,
          int[] inboundPorts) {
       return new AutoValue_ResourceGroupAndNameAndIngressRules(fromResourceGroupAndName(resourceGroup, name), location,
-            inboundPorts);
+            Arrays.copyOf(inboundPorts, inboundPorts.length));
    }
 
    public String name() {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
index d826a51..6cba2c4 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
@@ -30,8 +30,8 @@ import javax.annotation.Resource;
 
 import org.jclouds.Constants;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.ImageAvailablePredicateFactory;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.VirtualMachineInStatePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.ImageAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.VirtualMachineInStatePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage;
 import org.jclouds.azurecompute.arm.domain.IdReference;

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
index eaf820c..b31e2a0 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java
@@ -36,7 +36,7 @@ import javax.inject.Inject;
 import javax.inject.Named;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.SecurityGroupAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.SecurityGroupAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
 import org.jclouds.azurecompute.arm.domain.NetworkProfile.NetworkInterface;

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
index 98732d2..baba6f9 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java
@@ -29,7 +29,7 @@ import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.SecurityGroupAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.config.AzurePredicatesModule.SecurityGroupAvailablePredicateFactory;
 import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndNameAndIngressRules;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fa63f6b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
----------------------------------------------------------------------
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
index 4ac5eaa..abe057d 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
@@ -34,4 +34,13 @@ public class AzureComputeProperties {
 
    public static final String API_VERSION_PREFIX = "jclouds.azurecompute.arm.apiversion.";
 
+   // Predicate constants
+   public static final String VAULT_DELETE_STATUS = "jclouds.azurecompute.arm.vault.delete_status";
+   public static final String VAULT_KEY_DELETED_STATUS = "jclouds.azurecompute.arm.vault.key.delete_status";
+   public static final String VAULT_KEY_RECOVERABLE_STATUS = "jclouds.azurecompute.arm.vault.key.recoverable_status";
+   public static final String VAULT_SECRET_DELETE_STATUS = "jclouds.azurecompute.arm.vault.secret.delete_status";
+   public static final String VAULT_SECRET_RECOVERABLE_STATUS = "jclouds.azurecompute.arm.vault.secret.recoverable_status";
+   public static final String VAULT_CERTIFICATE_DELETE_STATUS = "jclouds.azurecompute.arm.vault.certificate.delete_status";
+   public static final String VAULT_CERTIFICATE_RECOVERABLE_STATUS = "jclouds.azurecompute.arm.vault.certificate.recoverable_status";
+   public static final String VAULT_CERTIFICATE_OPERATION_STATUS = "jclouds.azurecompute.arm.vault.certificate.operation_status";
 }