diff --git a/examples/pki/cms/auth_token_revoked.pkiz b/examples/pki/cms/auth_token_revoked.pkiz new file mode 100644 index 00000000..9fbe8ea2 --- /dev/null +++ b/examples/pki/cms/auth_token_revoked.pkiz @@ -0,0 +1 @@ +PKIZ_eJylVtly4jgUfddXzHuqK9jGED_Mgze8BInYeEF-8wJeBYTF29ePbEh3p9OZycxQRZUtS_eee87Rlb59oz9J1Qz0hwzXw8s3AA1DZxpsPh8CI6tjJFqxfKBjnSLL0pMli5bayo6oS6l7UlIoawUd31qavH7V1kbEAcVSdTGkg4mrpunG3nZmhllUxRzMV7k0N_b0eR8cMespeGNnkSbsjeKQ-tw5j8jiAoK1MTNkk43Ylol8N1_KYh74fBlrwjHa2_3bZOzbl9DnPbdsaGAxD3V7EiuHGix7tUPdtFkW4hU6hynqY3bJ4XbZ4wkuAgLZIMcsZGBv9ch3p9jBTUAQWSlVjgvMAugkmZE3qbE3q4Ct6igfEXWBnxwjln-JyA0VzT4JNuYV--07FGCA8X9QgAHGDxQSg0l7xIy3duQRySHR7WaVP9XQMbgxgTxtV0XKoR7XSaHWABV2jgjuA2IWuHd7pEAmcLIMFRLBLJ6ufDNHBW4Rq-Y7b3KmQSfbjVQN5Br7oAaR7l2oEsOHKiJ2E7HVNdHRLtKqa3iTMtps6EL9JttdtX2kLa6YdXPwb2X7hS8ewKLsBsL-qxLgs8jvA39OLnjPbtmtHGNg9yNhpLpgP6nGgMS7BrpUD4hAzAhn-nCKOxp5cUl26yal-4HCZO4L-Toh6qcWB18kazDXZDQX1f5n6cE_aT9kjom3D33hetP-TnQpXAf5Aa1zgFTFhM-ixVccaA0cXeH6iUWawYKgoGAIKpADJ7D3qpWmslALiqBIeUwMFhUqh29GaxLfpHyhL22m39b7u3LB33qdoDraSEyifWw0G7Y9RuTSg1EOhhGWMm1fAw-0K43wWI-PObt-c-FndgdfkLCn_DCoE1iYT5tfLT-osP5q9_ldcPAx-lebittARaxBUhh0wBQ262GxzcfanQPfrmi9x0QvPyVw4AIMBN4X15S40W10L1RbXTpSB46TjMJoYJ9eoKJeoJO5sFBn0LFmUElCcINNs5HFNRkg085Ds2W0jCoY3-0u8d1B3h8b7G3-QriCYRDenFYGG1TEpGoS7d5UNJ6JtGb4dgxufEyG4LSMXehbrbGf3PbC_WND-1wR-FkdaXRv5KYw1J5s6NGW35DFRDjTJO_6JaCa0gXuW0sbnjujmvwC2awSIpwC396NAW-GG9fcA3j9zwfmvfN29Lyk5ZkfXDoicYzR-kMJTMx63c8Lg00wKFJuOK-_Geo7T2_lfp8D7pPupDDCztFkMT40aaprYqpK0NBK-t9C69DIIlY8y1qojcpA69zIFlYAHdDUxvTcXl1CsdRExlVlCcrWRG3VQrSkFHmSGDuyh5iI8HxCFhS-uoaSOM4FcgZNh5OqqEIT7KMTtNVGacZMS7XJlsGm6hONti9HraAMv99M6MXEFG3sgx_b1hOjIdD-FmhJhC7oVRdKxphJbOHSZb1zkEtO6CfXwKfXH5oMSA1ePDdTRcwOjWL9fFdSJckS6bVHFfF1IvDP-CWbCmXy9NpVu_BpqcRivc16oLGr4hK_vmoz1BDkvSxetosqVk-l6J5X-elhpsFty70GHNfuNX6VQnbGwedWP0pnp9wFMTBTn1wV_hryDJ7He69j2piEh31eh4yyeDTnVnOUqwekOJskWmXPiGm6R-UlY4xz-ZjMe0C6bus-TBfLy45cLuHM19gyW1Df1s5JbjUu1XU3FphSW7XS6UnvrDYL42XW7YvwyD-fOhBCxpuHZbEsrSeTeY6cR3W5TY66RQ4MmmvZUYXRflFI5uuWEecPjMA9If-BMIFQZVOb04E_O0ai7my7iTy3iyjLPXa6O678kDwyBSTepGIrln2AO_U4mzlzS-TU7WP1_DJr_vwTjHdVFSk_7q1_AfJ_mjc= \ No newline at end of file diff --git a/examples/pki/cms/auth_token_scoped.pkiz b/examples/pki/cms/auth_token_scoped.pkiz new file mode 100644 index 00000000..34d7706e --- /dev/null +++ b/examples/pki/cms/auth_token_scoped.pkiz @@ -0,0 +1 @@ +PKIZ_eJylVst2ozgU3OsrZp_Tx4CNY5biaRFLGMx7ZyDGYMBObJ5fPwInpyedzkxmhhUIqVS36t4r_fhBH1HREPlDwrvx4wfACK1bM9CfziE6NjGBZiyd6dg1lyRxuZCgqXSSDddi6rzKKZa0cTxeaNLuRduhaA5kU1nDPR2MVkqaeo_PvX4MOFLEc5wZmfiIKvpehZeAc-XAt46RJlQoP6fe_JpFpXoD4Q4tkaRzEdexkedkGwlmocefYk24RJU1vE8OPOu293jXObUUGGb7tcXE8rkBm0HpSb9oNzmssX1ekCHmNvOg2wwBE-RhibkwCzjM4sEciOcsAjtow5KUhlxkQR5wANvJEWVtiiq9CLmiibKJUR96ySXi-G1U3lnR3ZnQ1-vA6z6wACON_8MCjDR-shDZoOwuAevubGlick7WVmtkqwbbaD5tIC06I0_nZAiaJFcaQHIrI2UwhKWeB4MzEBmzoX08klwsAy5YGJ6ekTzoCKdkB5e5UlDm2ReLUVxUhQ2I1u6NOjH-KKLSaiOuqJM1OURaUe_vVka-Txeu77a9uVZFmloHnJOBf2vbL3rxAOenfhTsvzoBvkL-CPy1uOCjuqfesNGo7mfByuIWeEkxAZZuHa7FZmQEYla40pfXuKfI6i057NqU1gOlyb4t5JukVL5McfBNscbkYqbkot7_1XrwT96PO8elW-09ob57_yb0SahH-wGNc6RUxCV_jNTvZKA5alTj3YojGuJAmFMyJcmJjRk8uIWhKRzWwjzMUz4oEUdyZR7cE61NPJ3qRb5VTL-N93fhgr_N9ZI0kS-yifa50fhcd4nK2wAmO1hW2Ei0fY060K400eNcPp5bzXsWfpXu4BsWDlQflvQCh7NF-2vKjy7svtt9fgcOPqN_t6k4LZZhA5Ic0QFd8HfjYouPtTcNPKug8V6S9elLAUctwCjg2-KGCjdlG62F4nktXmgGTpNQjlo8pDcsKzdsHx2cK0tsm0ssJ3twp013K9U6GSnTzkN3O9IwinD6tvrEc0Z7fxbY-3xVqME4iO-Zdgp9ksdl0SbaW1PReDbS2vHfJbzrwYzgNIzD3jM7VDH3Wnj72dI-l4fesYk0WhuZLoyxJz492rI7s7gUrnSTD_0SUE_pAue9pY3vPSqYXyi7A7X1MDVV-71CRzCcgRHlQwN5B6w-deKenp8Fzt4dm0DvGny1C41zsnQKoxAuoUzrxWcFHCCxp8c8jAMJ0PO_Tfdmm4aLTsohElPiitCxoe100gD1-3dgw8K1sXltJTOQXdNESqvLpq3sABahBllHETusO3O3jqqCoylcYAu1CpwmPyltsY01t3bmFr07XDvFhts78NUGknIrnn3C0Fqgdjotav96WzmJ6jF8Df1iSDTawhyxGYHiO1AdzfUKYMtslXTaSVbamx16XYlUcgkpYEgjUj5cbyAR09PL8ZRpQsuINHwVQLij9yBp74o5-3C9beMjRm4RGubu5K2F9HGJocPh_HJ7OM-zk36Nb-eHw2sxnGZ74rvrAqi2wSpx1jJyNWd7CHM1LftoqJiSh-nGUy32Js_OzhI1jmuXPJJmF9hh5aytDpquHbdgGGbIvIVPr71BcFdDy7fk2ZFJ92m33szIIMlu-IIEf-UzJFJOwolZRZ1hz-ONETD7_AwstzFmO7fpltxy63KH5wd0qXbBIt7HrOs-YWgF-_PT7CF9KnouPykraZg9YN1WOdW_7O0ckPm5UMNs268OL8QpD24qFNvu8eHFEjtI2uct79Qmn3P8cWWacap2kXw1ZCHP4Gzj16QE2-r1YrVQqwweOk_ybmMdDF83-GVNIJjuogqRf95L_wRcTpJ3 \ No newline at end of file diff --git a/examples/pki/cms/auth_token_scoped_expired.pkiz b/examples/pki/cms/auth_token_scoped_expired.pkiz new file mode 100644 index 00000000..766b4cdd --- /dev/null +++ b/examples/pki/cms/auth_token_scoped_expired.pkiz @@ -0,0 +1 @@ +PKIZ_eJylVtlyozgUfddXzHuqK2xOzCObMdiSzW7pzUCMwchLbNavH4GT6kmnM5OZcZWrQEhH555z75V-_GA_1TAt9IcGveHlB4CWNW8cbC9OxNrXCVKcRDuxsWuhaeqTpCmO0Wq-Mlez4FXPoGYO44lkat7F9KxYBLpjzJUtG4ynRpZFzy-dvccCKhMR5qtcfbaO7PlIzlgIdbxx97EpH63ilEXiNY_p7AaIZz1Zmi3EQsvHUZAvNSUn0eSQmPI5Prr9-2QcubdtNAmDQ8OAlXw7d7lEP9Vg2Rsd6qRmWSgV9E8S6hNhKeJ22WMOF4RCgeRYgDzsnR5FgYR93BCK6Eovc1xgAUA_3Vt5k1lHuyRCWcf5yKgjUXqOhck6pndWbHeObOwKR-0HFmCg8X9YgIHGTxYqj2l7xnzo-drI5JTO3WaVT2voW-K4gSa1qyITUY_rtDBqgAo3RxT3hNoF7oMe6ZAn_n6PCpViAUuryM5RgVskGPku5K4MlHvZqOUgrnUkNYjn4Y05MXwoY-o2sVBW6RztYrOstncr482GLZzfbXtz7RibswoLQQ7-rW2_6DUBsDh0g2D_1QnwFfJH4K_FBR_VPXQr3xrU_SwYLW84SssRkIYVmav1wAgkvHxlD69Jx5Bnt3TnNRmrB0aTf1s4qVNqfJni4JtiDcnFjcnFvP-r9eCfvB92Tmh43EZydff-TeiDXA32AxbnQKlM6GQfz76Tgc6gUQW9qYBMSwCkYGQoKpAPOdiH5co0BGiSghTZBFNLQIUh4nuiNWlkM73Qt4rpt_H-Llzwt7lOUR1vVD41PzeajdCeY3rrwWgHz8tLjbWvQQfWlUZ6QjhJRLd-z8Kv0h18w8Ke6cOjThZgLjW_pvzggvfd7vM7cPAZ_btNJWigrtQgLSw2YMsbb1jsThLzTYPILVm853R--FLAQQswCPi2uGbCjdnGaqF8matnloHjJKuwGugrN6hj9rcD6DtPSE-eYO9uwZ02243OqnSgzDoP223PwijJ-O52aRQM9v4ssPf5M7kCwyC8Z9qBbFCR0LJJzbemYk742GyGb2dy14MbwFkYu23ktNaRu9fC28eG9bmCRPs6Nllt5LY8xJ5u2NGW35klVL6yTT70S8A8ZQuC95Y2PHdWyf1COeyZrbuxqfrvFTqAwRwMKB8ayDvg8VMn7tj5WcL83bER9K7BV7uwOEdLxzBK-Ux0Vi8bXobYUjt2zCsJ1gA7_5ts6zQZkVqtUCw1Q6GqBL7iB63WK_b9HftKGfrQuTaag_XQcSyjsXXHNzwAVcVU-MBQW2gHYljFx1JgKVxC12oMZZy8MJpynZhhFYguuztcW8NX1nfgqw8041a-bBDHaoHZGTRW89fbykGd7ckr2ZR9arIWFqj1AJTcgapYtI8Auk5jZONOutHcfBK11JqhM2GAhEVkfLjeKEjNDpf9ITflhlNZ-DOgKB67B2niTXTXpH1IYeWIT09VZWNhm5pu_7LFotenk40hKN5tMWmeLuGz5F_p9Lw8CZct2Exj5Vhc1ig3oPTgy6G0cGOnnYclRPPLjp6a5elZauAxWJk7U3pep74japd2cbW6ykoJIP5aWuX7hwdztjNlszcnrfuwmnC8LJSzZ11Osktpha621jm0Jdw6epycXy3yWK5odqWiC66rXBCk-CJeBffxOaJazV2mNJhOt4l2eFXI3o0Wt2oBV3SWRiePSlr56B_UY9dRTz2YEvCb9bK-zFdQrRHO5cuZqx5fIiHT1CZ3-SQq7Cpz7MNRvjxORbSpQnmy7B7YRZI_16hsr-B6Pb2IF9vVHjxzkSbJLjhEi9h4DOIVBeNd1ED6z3vpnxbOkgI= \ No newline at end of file diff --git a/examples/pki/cms/auth_token_unscoped.pem b/examples/pki/cms/auth_token_unscoped.pem index 6c93452d..4ef7a783 100644 --- a/examples/pki/cms/auth_token_unscoped.pem +++ b/examples/pki/cms/auth_token_unscoped.pem @@ -5,15 +5,15 @@ MTItMDgtMTdUMTU6MzU6MzRaIiwgImlkIjogIjAxZTAzMmM5OTZlZjQ0MDZiMTQ0 MzM1OTE1YTQxZTc5In0sICJzZXJ2aWNlQ2F0YWxvZyI6IHt9LCAidXNlciI6IHsi dXNlcm5hbWUiOiAidXNlcl9uYW1lMSIsICJyb2xlc19saW5rcyI6IFtdLCAiaWQi OiAiYzljODllM2JlM2VlNDUzZmJmMDBjNzk2NmY2ZDNmYmQiLCAicm9sZXMiOiBb -eyduYW1lJzogJ3JvbGUxJ30seyduYW1lJzogJ3JvbGUyJ30sXSwgIm5hbWUiOiAi +eyJuYW1lIjogInJvbGUxIn0sIHsibmFtZSI6ICJyb2xlMiJ9XSwgIm5hbWUiOiAi dXNlcl9uYW1lMSJ9fX0xggHKMIIBxgIBATCBpDCBnjEKMAgGA1UEBRMBNTELMAkG A1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTdW5ueXZhbGUxEjAQBgNV BAoTCU9wZW5TdGFjazERMA8GA1UECxMIS2V5c3RvbmUxJTAjBgkqhkiG9w0BCQEW FmtleXN0b25lQG9wZW5zdGFjay5vcmcxFDASBgNVBAMTC1NlbGYgU2lnbmVkAgER -MAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBAFq4JvODBIaoHiYG6KMCnBEhDjWS -CuW0gq3kbi3j8kOzb4Mr7Muq0XvGMRwDrZlkfSpzIyuri/Fzf2pW58hnjWfDHQ1S -laAWLs6csh2u80hgWpMngCN5ZVFtIIbWlE0ZuLZh8p7E0IJZnNvYmlOVrmIkRo+J -1vMr71HZr5/kFcJzFVgi8QI4XU5iBPsUWOdJJV+0jXkMHVqOX3H297CYCePaotLD -azuquE74N8KMyl8j8jE9wi9O1gVBqO4L66ePjt5zI/TrjbjKwdseqoZR1dDGlp5V -awRwRYCjsKF+asAbuASOwdSgP8V6VgTOUrZh2D8KHtclwS+URoTdVl4ypQA= +MAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBAFvooB0VQsp6sBW+xbnGmfDKlLWS +XHA1kqS5GuI1wu+rqSGarUR4WNCuBCp4bNzfgM+mXSArL/tTCiAMhs/Lh6GOYC7w +ZOFh8GSIIcLFYThCPZa+uV/39ZaLTguMmjYPZq1EUco+NErajY6mbVGpshlb8Y5l +F6cNkrMhPbskcARi6BUWu/eObjfeb9uw13wVIyWKQIEKA1UGA0yeyi+I6kmYpyBw +U4fWKdvcvOiXiGSWZuToc/xZQV0NooQeEZI87n2AF+dGLe/7YJi7MdP7klI5u0Ue +VP1YdeRzH4a2wyNRvGjD/b8+ZNqF+WDulfWSQ+spKqz2Y4FEO6z8ZuvI4wM= -----END CMS----- diff --git a/examples/pki/cms/auth_token_unscoped.pkiz b/examples/pki/cms/auth_token_unscoped.pkiz new file mode 100644 index 00000000..13c5e40c --- /dev/null +++ b/examples/pki/cms/auth_token_unscoped.pkiz @@ -0,0 +1 @@ +PKIZ_eJx9VMmSozgQvfMVfa-oMAbbVRzmIAlZCFvQGLHewAs72MaY5esHuzt65tSKUEiZkS_z5RL5-TkfiAk1fiBmv4RPgVGq7kCg75qQps-jAawjamYd4QiBwUHAwgPiQIOJc1cThkg-67lDkH0jNo1lQbWwBqJZaQc4SXB2HvU0kIzyKLPMzOAXred_HV4DyVUD_5DGRKlp3iRnWWwp0kUhlh5lnNEN1dos9NM-8vXyOM4yoiPjeNxzsNpzLLsqXpo5e13Ry-gLfA0R3QizYc88p2eTnpu8kEIvEA0VSEGO55dNBi8Gw8PibCObtq7sEchO_szqd1DhWClt6BuXmJRd9It27Nt9Qqt1GnvOLP8GlEoXeMuS2e_oYywNb6YC3T6-_m_8dshxdpmdzPV4g14501p_xsQZab08_WEx44S_RHnnOL-56bGV6TlTUDlT6DmiwY0qqIKeESYLJg-kMA8LJoVZiHTl4otDkmi7ub1wSCgEHMGrimCd4x0DCQFLB8MDgwbHewYKIrwVKUOuywY0AR0mhgtBwkFhQHagPQaB6lqWhvuSn7x1d_bDuZXOgHNgvWwFCBqOHKUPvTU_kW0eTfjAwPc7EhoYtSV3fZQPz7hyBp2DHCbFLS0yovQiRBb2hG31KM--IcbSurTI29H0djSun8fqOGxVYP9ixThaGmVMgsSRyjqu3AIk-CAwcCTQbk3Q04gB8c-IzhMKgeUAONcCbO8atS73i3mAGF0iWEaZWKcHN11FAj1_r8a1F5ZGKDWGyD468ZlOstqwRb1jnp5-5fK-M-cJvXSTbE6Vxqs4Sg9dUQdNcSuE_Cfc3JzH-fqxLruP-wpoqpNGV9iP8lMuzsmGtUkY1PCeUyJHQ7Nl2vfJslSkKOoJWpOw21fD1JDztsjbyx27Hw95icVWut-JOC6a_SUK-k1AmpUrNtpjm3T5osNNEn608g1lsSOgZBVvppgUhx2vm-5ate56rZynjSgam_tr6J7awn9y4n5Lth48bJRdy6Wx8m52ju7IE1Z-G92-ldZegIXrbm6gHJuBT63Ss1g3be9i5-ZTVotYxMm5WNrPXaB2_PpzsPt_hPdKwYb633r5FzKfcIU= \ No newline at end of file diff --git a/examples/pki/cms/auth_v3_token_revoked.json b/examples/pki/cms/auth_v3_token_revoked.json index c1680c18..63410f15 100644 --- a/examples/pki/cms/auth_v3_token_revoked.json +++ b/examples/pki/cms/auth_v3_token_revoked.json @@ -7,6 +7,6 @@ "project": {"enabled": true, "description": null, "name": "tenant_name1", "id": "tenant_id1", "domain": {"id": "domain_id1", "name": "domain_name1"}}, "user": {"name": "revoked_username1", "id": "revoked_user_id1", "domain": {"id": "domain_id1", "name": "domain_name1"}}, "roles": [{"name": "role1"}, {"name": "role2"}], - "methods": ["password"], + "methods": ["password"] } } diff --git a/examples/pki/cms/auth_v3_token_revoked.pem b/examples/pki/cms/auth_v3_token_revoked.pem index 9b0b1e2f..c908533d 100644 --- a/examples/pki/cms/auth_v3_token_revoked.pem +++ b/examples/pki/cms/auth_v3_token_revoked.pem @@ -1,6 +1,6 @@ -----BEGIN CMS----- -MIIIVgYJKoZIhvcNAQcCoIIIRzCCCEMCAQExCTAHBgUrDgMCGjCCBmMGCSqGSIb3 -DQEHAaCCBlQEggZQeyJ0b2tlbiI6DQogICAgeyJjYXRhbG9nIjogW3siZW5kcG9p +MIIIVQYJKoZIhvcNAQcCoIIIRjCCCEICAQExCTAHBgUrDgMCGjCCBmIGCSqGSIb3 +DQEHAaCCBlMEggZPeyJ0b2tlbiI6DQogICAgeyJjYXRhbG9nIjogW3siZW5kcG9p bnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc2L3YxLzY0 YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwgInJlZ2lvbiI6ICJyZWdp b25PbmUiLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc2L3Yx @@ -33,15 +33,15 @@ bl9uYW1lMSJ9fSwNCiAgICAgInVzZXIiOiB7Im5hbWUiOiAicmV2b2tlZF91c2Vy bmFtZTEiLCAiaWQiOiAicmV2b2tlZF91c2VyX2lkMSIsICJkb21haW4iOiB7Imlk IjogImRvbWFpbl9pZDEiLCAibmFtZSI6ICJkb21haW5fbmFtZTEifX0sDQogICAg ICJyb2xlcyI6IFt7Im5hbWUiOiAicm9sZTEifSwgeyJuYW1lIjogInJvbGUyIn1d -LA0KICAgICAibWV0aG9kcyI6IFsicGFzc3dvcmQiXSwNCiAgICB9DQp9DQoxggHK -MIIBxgIBATCBpDCBnjEKMAgGA1UEBRMBNTELMAkGA1UEBhMCVVMxCzAJBgNVBAgT -AkNBMRIwEAYDVQQHEwlTdW5ueXZhbGUxEjAQBgNVBAoTCU9wZW5TdGFjazERMA8G -A1UECxMIS2V5c3RvbmUxJTAjBgkqhkiG9w0BCQEWFmtleXN0b25lQG9wZW5zdGFj -ay5vcmcxFDASBgNVBAMTC1NlbGYgU2lnbmVkAgERMAcGBSsOAwIaMA0GCSqGSIb3 -DQEBAQUABIIBAI9qvSGYlIHoI0gWTZ55POWwj5Gjyr/SQ4q2e13m5bSnmvawGw6Z -Xa500UvvnUPHe/Nf4ExS0/hO2zn80hjLC+uEDwESlMMDTc29+TbafHTQOp+Zz742 -KdO+2Zv3UevStJK+wg+D0cKUmhmghyzzIsD44OmzLaGe+3mCqLkWFv8i7KX9rrb5 -Jqv8kbLm9bY7wlWqmYcaJyXy5SdJMKi1/aWm9nn5AOaujHTfV/bygQd8ZY9t4+6k -OwKPZlt5x1KA3IxGdJUFvIHj7am6j0auQ2TMx8x2vzPzy5+mBzB0u0XaENJsb9Jz -z+aVgXOQ81PbwwZmStONrwEVpjQeyEXY4pM= +LA0KICAgICAibWV0aG9kcyI6IFsicGFzc3dvcmQiXQ0KICAgIH0NCn0NCjGCAcow +ggHGAgEBMIGkMIGeMQowCAYDVQQFEwE1MQswCQYDVQQGEwJVUzELMAkGA1UECBMC +Q0ExEjAQBgNVBAcTCVN1bm55dmFsZTESMBAGA1UEChMJT3BlblN0YWNrMREwDwYD +VQQLEwhLZXlzdG9uZTElMCMGCSqGSIb3DQEJARYWa2V5c3RvbmVAb3BlbnN0YWNr +Lm9yZzEUMBIGA1UEAxMLU2VsZiBTaWduZWQCAREwBwYFKw4DAhowDQYJKoZIhvcN +AQEBBQAEggEAmG4yoCylqeL51u3yAOI5hGOlOZrBT53W7GGLpTqa2NZxXJOhVhPa +UBn8idQtVOPHk66XOrGdExSy0QSvTz/Q9iFQ5Tj7NsYj3vCOIHF7UqZo1SfRJ6Ss +iE18JPYMDCt9kChcPyiNpdPpqUyHuX2Oe83yVZtfljf9u+WNv2kaNys2gwdrMKIb +rKC3/JFoEEn6ISqkRqs3+aEbe++Z0YykrFctuYvctJPARqFewmBvkvrnOXuaeIsN +kT70Zgthd/JUHp/fC2vbRtIXiskl9zVegAtu10nlHV9ff3B2YHZi1MGcwJAnwxyY +eRuWwQ5bndCczoncOpb13FbC1eeOBgrXNQ== -----END CMS----- diff --git a/examples/pki/cms/auth_v3_token_revoked.pkiz b/examples/pki/cms/auth_v3_token_revoked.pkiz new file mode 100644 index 00000000..67823fd3 --- /dev/null +++ b/examples/pki/cms/auth_v3_token_revoked.pkiz @@ -0,0 +1 @@ +PKIZ_eJylVsmSozgQvesr5l7R0Symyhz6wG5oS5jFgLixtDEY7PLC-vUjYXd31Sw1PTOOcNgIZerle7no0yfykTXDRL8p0KMPnwA0zdWywNbXU2zuuwxJTqacyNpiUhRZXCqSow2KL63kYntRC6gYFVnfLQ3FOxuemfJAdbSVlNBFSSuK6PpttJiUu9VpaT6bq2uZrawuaYIqV-7PcSjscTPU8fzsjiAPt1dTsQ4px-6TcFHapfxiNsI-Dbfkv1TGhnjDYd1G3Lw2mGVfmE19MKsT-XU7kIb6a1qLr7GqlTuPvvxpnBtBi0OBeW_s1hmHxiSSmSQUW0A9pcfgmipvPB_dOm30NtffOkb73NCvKZdRlCkJlThna3A3iLt0Fdxiz6ThEGO3T7m6zVfw--Z9bLAEaeD5NHbFOuUrt7fLZQegb_LrSmqhshjsquDRhLu80jpUuSVq8BQ3VoWn7YRUyMb-fo8qucEcXtihVaIKDwBxWrlWpDJrgiON6Y7IqmOu7tKD2D5QvaYkrIzyo79HASiM_4MCUBg_UKyCMjXqKggseJdpz-Qr6Xk9LgdYZfSAfl1pz7aa8agUOegtOYAMk4srck6DKuRDBk5BbRsaB424iqtCwI3JoUrjsWeJEVXj6AqZ8ZC5Ea8kkdj6rm_Qxiu5S4juGSteye8lG0ms-i2nMn6X7Y4sv5L8qCg_4N_K9p6vwwhs36SE_WclwN95fuf4A3LBO3Z9U4Azu38mLAnZfcxtZ4ekIg-ZIVJEE4i44TVtbhP1HLKsuFbeV2PaiBz-IMXBr5FFk8uhIbVU-7fSg4-1n08e4zB_TbnFjOg70T4nzPIDUsItqfuRlO_1lzJQoRwthvWEGVzFDYBcXGIOsnByJhRuF9jHfdygxlbrElfkjZ_v50Q7yixpZa-Y_aVi-ut4_ypc8FGuY068kRxg_txo0I7kRZvwsARUjihirrTjEh5oV6LwLnFUT7nxIwv_Nt3BP0tI-dnyax5Pdy4eKV7ONh64SyRs0uaeZbQa44hW3hBsD_09C1cuk6mnbj1pIxqpIsS5f5oIJyxAI5FlnGH2eWiRMkb_ZMhCVepnREc2B_TUfFX3j9hfYzILcqNmvn1A3J03Nqe2ZLAETGKIh3vzIKPM0KeMz7usccpZlSZYZEY9xhHa4ciZkcFKmmyF6aHHDMDWnZHAGpB66hF7evQF8RpH8N0AefSILjXIhDr-VA08oI8pN9Sw_J4LwRRH5mNOut08_h7D9o3U8zwFhPXdvOhrDxWcPwzV-kD7A333xpiEFHcJFxxAxNPT7jDho3XFyvtNjz074pzAZ8WdbyhSduqLYmUAqdBkaBoH8v0GnVOvSFgNHEfXeo2FzrVXnPnZ0Hor2E7aGkoHQ2K3miJDxWG0AWiV5MgFCmQp85UAsWkjCDkpbRKSB2XpvnkPLZ-X67RGDA7RBbpar_az4zXQ-v36R977Wg0V-OP6Qm4vluTikIQhZDwhswmklDo63h2tG3EE8aRtoWzOJ0kDXG-54BqXsp-EeRuHjiKR0-Qe61_7hSrtT73qvL1PaTKQHXo30qTi8A1d3G3mrSX5pubCKREZlaxEeZF0qnqe3Gq0mmcvvB763tW0W69v-s-RDqpRgZnLY1x4BMViY3G8gDiW3cTRsolW2uc0MOVLyz_fal5dtTiSq7TstR2f2eNmoWKwQVmIxW25t-zzywnrqrEbO_VsuJd1bWtQ1vTyKWg3ngtbQfl80c8Xd0wydeAbqJRPVxcMHty3SBcuQd0vfX_h9ofRwuYUcmWwGJJ8SL7mJRwCzcebvLt5SqHwT_LGzgaxZ3aFBBzm5Ww_7faNib7K_nR4sXH7ujkdrPPlZSva8pNYtf1zPY0o6XtJv52T6LwNfIlbdkJvSQxA-XNVOzJ7Vlipvh6Dk_2UC0vmcxS3tiN9-QLmC62G1J-X298BCSOhiw== \ No newline at end of file diff --git a/examples/pki/cms/auth_v3_token_scoped.pkiz b/examples/pki/cms/auth_v3_token_scoped.pkiz new file mode 100644 index 00000000..d687c03b --- /dev/null +++ b/examples/pki/cms/auth_v3_token_scoped.pkiz @@ -0,0 +1 @@ +PKIZ_eJy9V8lyo0gQvddXzN3RYUCgNoc-FItYTCGBEEvdWCwWscjWwvL1UyDJ3W577J6YiFGEDlUFmS_zvcxKvn0jP0FWNPMvEa3HxTeANE1X2kB_bLCWnWMTWrHYkD1JEkXRSkVoyZ3oQFVINy9SikSlEEWhTxVx_aystWgGJEtWYUg2u52cprH71OtUxBzLKNfmmnrIY1U_h5VbJOJljRX-GHjlSSualDx7AoFHl-NCq-xz5C32Ucmfxj201g6aqO_x-KKo7yKGzkKP24ae1Wk1NZ6VUbXIQaS4u9FAouo0XrfEEJdF3iZf5jBPFJcY4yifmfY6LR_P7TJmzD70BSr0-BMYX45q9xCJ42E5GdNqe7R-Shb8Hktyvh0N1_qZOBvGc292yMn5Ea-1OSBQ-ojpCGSdN0Th-68I4oo_YEfLt-4E-Yh9u4kY-2Kk19vANweQMHyPRT0xRJhjP2tDXy9jms-mpIlajyTEGg7sDEdmXUnrloVMLQs48_IpRwUIfDuLFL7-HRo5ZAgyekQzGfe4Xazw-6i2X8NIfP0ALgxkVKLCudE_dKiIT0hkW6OQ50spnpk5z6D1A2MqGoMLswoqszAdRKHBLZeKzACk4AIXKRdUGmMW8iy40kc8lXGFs4C55CPw7GPosROauHLrkYHROSDZLTFTnqMdf8K3RNZuH134bxLVbpf5wxk52swo4IiO5CGdmUNwTgr5DMzCzgmwAVd6EQybwZQQjZ0sMwuhCpiAXXp6bhZBZzLy5J2IicK-XgWeWV4QVOWJCKYnyTtMQrkhyicEPfaSfcRwq6jaTHog8qXjqp3CClWbArHUnI1B7s1-TByB6DSsOcSMMQs6YwiooMAVYnAeMIhGgzWY3oYNnKDFlVktpTIHQUGOnCS7yPSCBleL4kplm3j6IfTQu-TdkIJb8vxJrjYXK9c6ICpMxkIbC0d9o486UhankZ3RKPgngXyqD0fj0KQP7QD-DecfUQ6-5nzXE48j5_8fjRwiXkca_4QZ8FmMvzMTenSGmVckU-u7ViN3Tir507L9J1bAa9mKIy3sH6nvV_GBD2LMsELvo0vHuSaRvba4S7gOw70KDHwpmi_Qgc_gfYDuKjrSeMULQvAVxK8Qgv-SwBEh-Lfl-7tGwE0kAcMfY9Wl8AcXTMi4XDwjd2f1vsWDPy1hNPZLJyZFhd4UFbhVlVYtdtF4bb8vqPVnBQXGivqgoIg3RJs9SW7_8T1xRTDOB-37hJV_fleAn41j0yIJvovxNcRaoIOq2wf9W4mDEc7mjYDo6aZO1LK9qQ-TQSNRSurplT53wL5GQhlb2m20uc5Ev3Tf17Fm2nNuLc2acnCblYDPlLvLcAF_fZmOGbd_O9rcppfRu36dlWgebB1FhHHTpqmqwFQWkKbsyP8JWU0rwkByLWshtzKNrEMrWtNakVvd3QyygeBOAZDeyKKARIuSO7mAlpCargBjR3RNOqo4LiHNlsBfIwEq07MZ0p2ZUEalSZEEvwBky63UTpYNuc0M7JdDohD6HLlEInodKMk8qUM78H7K2oURMQSi-mLJqMisNMgbJGiTJ9ghY8O4B5wLTuglJ-xZIiTOhDZYPLasBLOmlaxABz9HXFkQLEimVRnmJ3OlLmcvbKSdqMYrmzCrm95WXJ12CpbiH4Ln1O5ZzC2aZ6DndyU-zU7DXS1QL_Ndjdd-JsAIqbs9v3To5N5fB9zLshOf-uql6beRHX3H4Xy_hxWW6AqsHh-d7_NktVXtxxXTR2yhoe3cWAcs_bxqnxTBqRUha-onmROWuZpIXC05Em0v1vaB1bI50P2ZKjyrfXi33B4XFO47K4lXsKyFx7vW2Id3ZyKK9OUQMH7ztHPNY-vcQ38ZZliW5ORlDQYlpPYnVmg1NNNgWvIzt33g7oXy0LVwkMU8rNSu3g6ORWFa9GAxHL1NWqSxkdqqeL4HK0GEBs73RVma-_uGClnlMehWZR49Gdvvq8UiiqvZ1jZ0-OMHmD4xZFP6-bnxN6RCLsw= \ No newline at end of file diff --git a/examples/pki/cms/revocation_list.der b/examples/pki/cms/revocation_list.der new file mode 100644 index 00000000..e69de29b diff --git a/examples/pki/cms/revocation_list.json b/examples/pki/cms/revocation_list.json index c3401b0f..f8e734d5 100644 --- a/examples/pki/cms/revocation_list.json +++ b/examples/pki/cms/revocation_list.json @@ -1 +1 @@ -{"revoked":[{"id":"7acfcfdaf6a14aebe97c61c5947bc4d3","expires":"2012-08-14T17:58:48Z"}]} +{"revoked": [{"expires": "2112-08-14T17:58:48Z", "id": "dc57ea171d2f93e4ff5fa01fe5711f2a"}, {"expires": "2112-08-14T17:58:48Z", "id": "4948fb46f88c41af90b65213a48baef7"}, {"expires": "2112-08-14T17:58:48Z", "id": "dc57ea171d2f93e4ff5fa01fe5711f2a"}, {"expires": "2112-08-14T17:58:48Z", "id": "4948fb46f88c41af90b65213a48baef7"}]} \ No newline at end of file diff --git a/examples/pki/cms/revocation_list.pem b/examples/pki/cms/revocation_list.pem index 4c6233ec..d96cd5c5 100644 --- a/examples/pki/cms/revocation_list.pem +++ b/examples/pki/cms/revocation_list.pem @@ -1,15 +1,20 @@ -----BEGIN CMS----- -MIICWgYJKoZIhvcNAQcCoIICSzCCAkcCAQExCTAHBgUrDgMCGjBpBgkqhkiG9w0B -BwGgXARaeyJyZXZva2VkIjpbeyJpZCI6IjdhY2ZjZmRhZjZhMTRhZWJlOTdjNjFj -NTk0N2JjNGQzIiwiZXhwaXJlcyI6IjIwMTItMDgtMTRUMTc6NTg6NDhaIn1dfQ0K -MYIByjCCAcYCAQEwgaQwgZ4xCjAIBgNVBAUTATUxCzAJBgNVBAYTAlVTMQswCQYD -VQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3RhY2sx -ETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBvcGVu -c3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZAIBETAHBgUrDgMCGjANBgkq -hkiG9w0BAQEFAASCAQB8CHeQzIDFNy4RcWb+RRwwZ3JZ8Vw7OnFZhWXdbQ7a5KZr -CrB/cGpkvMgnOtCNfpwSv7H97UEmOhQEarFJ6YFNNjA2FdXgt+2MCPmodG6tGyXl -F+sh/g7qE8ONTiIJn2634kCj7fAyrVUlRxDLu6Llk9KWv7pAxtJKjqirHr8i8tYM -/QV8pX/QP0u+vJvzZBXb/UlViQpaJnY9SWKF0ETXGypFTtExfiXG9qz96JWvC/jK -gOF68N0FsoCNhzRys86rrAk7jZugajzjk3y/buInZiv4npQcEMC3lHKBXtA2uiRf -ILgnF0qOttONx8GNE72eJqWBkiJf52239PxgxWNg +MIIDTwYJKoZIhvcNAQcCoIIDQDCCAzwCAQExCTAHBgUrDgMCGjCCAVwGCSqGSIb3 +DQEHAaCCAU0EggFJeyJyZXZva2VkIjogW3siZXhwaXJlcyI6ICIyMTEyLTA4LTE0 +VDE3OjU4OjQ4WiIsICJpZCI6ICJkYzU3ZWExNzFkMmY5M2U0ZmY1ZmEwMWZlNTcx +MWYyYSJ9LCB7ImV4cGlyZXMiOiAiMjExMi0wOC0xNFQxNzo1ODo0OFoiLCAiaWQi +OiAiNDk0OGZiNDZmODhjNDFhZjkwYjY1MjEzYTQ4YmFlZjcifSwgeyJleHBpcmVz +IjogIjIxMTItMDgtMTRUMTc6NTg6NDhaIiwgImlkIjogImRjNTdlYTE3MWQyZjkz +ZTRmZjVmYTAxZmU1NzExZjJhIn0sIHsiZXhwaXJlcyI6ICIyMTEyLTA4LTE0VDE3 +OjU4OjQ4WiIsICJpZCI6ICI0OTQ4ZmI0NmY4OGM0MWFmOTBiNjUyMTNhNDhiYWVm +NyJ9XX0xggHKMIIBxgIBATCBpDCBnjEKMAgGA1UEBRMBNTELMAkGA1UEBhMCVVMx +CzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTdW5ueXZhbGUxEjAQBgNVBAoTCU9wZW5T +dGFjazERMA8GA1UECxMIS2V5c3RvbmUxJTAjBgkqhkiG9w0BCQEWFmtleXN0b25l +QG9wZW5zdGFjay5vcmcxFDASBgNVBAMTC1NlbGYgU2lnbmVkAgERMAcGBSsOAwIa +MA0GCSqGSIb3DQEBAQUABIIBAI2tvOIhjQTThmRwK4wp+KeZOU6hKk2A5j5c+XNZ +DxwLlvuX+YZxm5OpLdInKTjMvjMi6guciwH3VUAo2Iqq9yMhH/Xh5t8QJS+zPF7i ++GOqwZpBc6QKNihIok09L4jtaUjf4/f7EZQNh/jMkftuA3hhtuLalnkYW7yEA2sF +ne7PRVUV6i8i+q7gC5L9iXk4Qy3p2AzgPGfhF6PM/0pzyjJtk6v8PBCkMBNexrkq +RS4WjsYMR3mev1jL3dJ0wTgCgnqCcR3bQtDL/MHpU6q6Ce6Q3DGE6hkQOIRHenE/ +NoPZqDY/M34NHbjsMqi4zJkO4HMrcgAiYa/zX/yBwzvEurI= -----END CMS----- diff --git a/examples/pki/cms/revocation_list.pkiz b/examples/pki/cms/revocation_list.pkiz new file mode 100644 index 00000000..600fce02 --- /dev/null +++ b/examples/pki/cms/revocation_list.pkiz @@ -0,0 +1 @@ +PKIZ_eJx9VEuPszgQvPMr9h6NQgIhk8N3MMaACTaBmJdvCZMxGMhjkgmPX79kRtq9rNYXq0ul6u7qVr-9Tc9EDqZ_QbJ_BW8KwdhiXe5tLxyXz4KCsICXCQstCMHYQRCiHjLgmiL-sgSBjpzwpHPg_ubs8VFTrBC54DCBsYqEsL3T4A0848_DMqmxvIhUu1c8K7tD5jXFgA0M8UAYGnwGdJ8hVUkspAUy1gMZ6mmF7xh6Vw5fRK_Ox1jjKerpaNekzVdkGau8zRe8RR1JeUNZ0SskzYd87218aK5xm-iF00wVkCqoQEUk6kmldgFUe2qHk9BlEVgXNbAvlQ9BdUjDSnkRqVWrgcOnn7eBVUpq2SWXdZfLfDGJjDkL9by1Gy6L6nPfianN5uSa16JNRuXVJ5a4Jww_iCUehEUxYYVBmTCoVR5w1QncNj9-4DaSlH00OUMaScNhSjIqnEUtl0mbM9DzNl7QEfVceiU-q3fs_r-BL_-U_zYQq8FUNm-xSttcDxyiktRuA2ZWVMaTCC2n6qo8TVqFDt4my9ReCHc77YTZC2wCBs2rBc2zRFsChAMWMTIjYlKGfALq37gkMElIr8AReKagiQkEAzU1SYQ7BHIrCUMXdQ37SFffp4yXRyfukQThL_fCYLzpeLpiyodjy8OIIgLef5RhT_B-mawKLXoe27j3GJCmqG9lXTmbTjVhiKZmHs0po-pxuWqU0PlRGn-EhtWzaIvetsD-NxNhcEGbo5OLeNmcj21SA_FKVjjm_h6ADh8UAtR_9npaaxOEMTAnLwBePp4BLmXIWNlG3VbvrrPtiQexUW7rJVjJVTHLKFesvvOb53c2y3nfroKr_4HPWybJU5LKEN9F1blaEoPLEt9um4GU7jwrV4_30NvPxp29rpSZE9w6fjULI9zSqsSXWt34unwcYvmpzz_XiIe0nEtSfz6-gVaWj2__0JzrPF0PCCzvtnI-rXdREidG9V7NbmsBV_6mymo9HLTrEoxi53yWtrEjc_U6DtJ71MbzfWfCehrqqf-qb0q011N5z0mktafnQvrah6d2TEBxvsEi0o7hw_LnxL3Gxs2AJyPULAcZZR0GOHJPZzRX6GXHb1Y-J5pO3aO8k1ulj14d6C75KgSo8sN8zOaD2Y1P9P2F_yg_dwhR69-b9Dc2l4GQ \ No newline at end of file diff --git a/examples/pki/gen_cmsz.py b/examples/pki/gen_cmsz.py new file mode 100644 index 00000000..6840c08e --- /dev/null +++ b/examples/pki/gen_cmsz.py @@ -0,0 +1,117 @@ +#!/usr/bin/python + +# Licensed 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. + +import json +import os + +from keystoneclient.common import cms +from keystoneclient import utils + +CURRENT_DIR = os.path.abspath(os.path.dirname(__file__)) + + +def make_filename(*args): + return os.path.join(CURRENT_DIR, *args) + + +def generate_revocation_list(): + REVOKED_TOKENS = ['auth_token_revoked', 'auth_v3_token_revoked'] + revoked_list = [] + for token in REVOKED_TOKENS: + with open(make_filename('cms', '%s.pkiz' % name), 'r') as f: + token_data = f.read() + id = utils.hash_signed_token(token_data.encode('utf-8')) + revoked_list.append({ + 'id': id, + "expires": "2112-08-14T17:58:48Z" + }) + with open(make_filename('cms', '%s.pem' % name), 'r') as f: + pem_data = f.read() + token_data = cms.cms_to_token(pem_data).encode('utf-8') + id = utils.hash_signed_token(token_data) + revoked_list.append({ + 'id': id, + "expires": "2112-08-14T17:58:48Z" + }) + revoked_json = json.dumps({"revoked": revoked_list}) + with open(make_filename('cms', 'revocation_list.json'), 'w') as f: + f.write(revoked_json) + encoded = cms.pkiz_sign(revoked_json, + SIGNING_CERT_FILE_NAME, + SIGNING_KEY_FILE_NAME) + with open(make_filename('cms', 'revocation_list.pkiz'), 'w') as f: + f.write(encoded) + + encoded = cms.cms_sign_data(revoked_json, + SIGNING_CERT_FILE_NAME, + SIGNING_KEY_FILE_NAME) + with open(make_filename('cms', 'revocation_list.pem'), 'w') as f: + f.write(encoded) + + +CA_CERT_FILE_NAME = make_filename('certs', 'cacert.pem') +SIGNING_CERT_FILE_NAME = make_filename('certs', 'signing_cert.pem') +SIGNING_KEY_FILE_NAME = make_filename('private', 'signing_key.pem') +EXAMPLE_TOKENS = ['auth_token_revoked', + 'auth_token_unscoped', + 'auth_token_scoped', + 'auth_token_scoped_expired', + 'auth_v3_token_scoped', + 'auth_v3_token_revoked'] + + +# Helper script to generate the sample data for testing +# the signed tokens using the existing JSON data for the +# MII-prefixed tokens. Uses the keys and certificates +# generated in gen_pki.sh. +def generate_der_form(name): + derfile = make_filename('cms', '%s.der' % name) + with open(derfile, 'w') as f: + derform = cms.cms_sign_data(text, + SIGNING_CERT_FILE_NAME, + SIGNING_KEY_FILE_NAME, cms.PKIZ_CMS_FORM) + f.write(derform) + +for name in EXAMPLE_TOKENS: + json_file = make_filename('cms', name + '.json') + pkiz_file = make_filename('cms', name + '.pkiz') + with open(json_file, 'r') as f: + string_data = f.read() + + # validate the JSON + try: + token_data = json.loads(string_data) + except ValueError as v: + raise SystemExit('%s while processing token data from %s: %s' % + (v, json_file, string_data)) + + text = json.dumps(token_data).encode('utf-8') + + # Uncomment to record the token uncompressed, + # useful for debugging + # generate_der_form(name) + + encoded = cms.pkiz_sign(text, + SIGNING_CERT_FILE_NAME, + SIGNING_KEY_FILE_NAME) + + # verify before writing + cms.pkiz_verify(encoded, + SIGNING_CERT_FILE_NAME, + CA_CERT_FILE_NAME) + + with open(pkiz_file, 'w') as f: + f.write(encoded) + + generate_revocation_list() diff --git a/keystoneclient/common/cms.py b/keystoneclient/common/cms.py index 96f8b61f..156b1a14 100644 --- a/keystoneclient/common/cms.py +++ b/keystoneclient/common/cms.py @@ -19,9 +19,12 @@ If set_subprocess() is not called, this module will pick Python's subprocess or eventlet.green.subprocess based on if os module is patched by eventlet. """ +import base64 import errno import hashlib import logging +import zlib + import six from keystoneclient import exceptions @@ -30,6 +33,9 @@ from keystoneclient import exceptions subprocess = None LOG = logging.getLogger(__name__) PKI_ASN1_PREFIX = 'MII' +PKIZ_PREFIX = 'PKIZ_' +PKIZ_CMS_FORM = 'DER' +PKI_ASN1_FORM = 'PEM' def _ensure_subprocess(): @@ -99,14 +105,30 @@ def _process_communicate_handle_oserror(process, data, files): return output, err, retcode -def cms_verify(formatted, signing_cert_file_name, ca_file_name): +def _encoding_for_form(inform): + if inform == PKI_ASN1_FORM: + encoding = 'UTF-8' + elif inform == PKIZ_CMS_FORM: + encoding = 'hex' + else: + raise ValueError('"inform" must be either %s or %s' % + (PKI_ASN1_FORM, PKIZ_CMS_FORM)) + + return encoding + + +def cms_verify(formatted, signing_cert_file_name, ca_file_name, + inform=PKI_ASN1_FORM): """Verifies the signature of the contents IAW CMS syntax. :raises: subprocess.CalledProcessError :raises: CertificateConfigError if certificate is not configured properly. """ _ensure_subprocess() - data = bytearray(formatted, encoding='utf-8') + if isinstance(formatted, six.string_types): + data = bytearray(formatted, _encoding_for_form(inform)) + else: + data = formatted process = subprocess.Popen(['openssl', 'cms', '-verify', '-certfile', signing_cert_file_name, '-CAfile', ca_file_name, @@ -133,7 +155,10 @@ def cms_verify(formatted, signing_cert_file_name, ca_file_name): # Error opening certificate file not_exist_file # if retcode == 2: - raise exceptions.CertificateConfigError(err) + if err.startswith('Error reading S/MIME message'): + raise exceptions.CMSError(err) + else: + raise exceptions.CertificateConfigError(err) elif retcode: # NOTE(dmllr): Python 2.6 compatibility: # CalledProcessError did not have output keyword argument @@ -143,6 +168,45 @@ def cms_verify(formatted, signing_cert_file_name, ca_file_name): return output +def is_pkiz(token_text): + """Determine if a token a cmsz token + + Checks if the string has the prefix that indicates it is a + Crypto Message Syntax, Z compressed token. + """ + return token_text.startswith(PKIZ_PREFIX) + + +def pkiz_sign(text, + signing_cert_file_name, + signing_key_file_name, + compression_level=6): + signed = cms_sign_data(text, + signing_cert_file_name, + signing_key_file_name, + PKIZ_CMS_FORM) + + compressed = zlib.compress(signed, compression_level) + encoded = PKIZ_PREFIX + base64.urlsafe_b64encode( + compressed).decode('utf-8') + return encoded + + +def pkiz_uncompress(signed_text): + text = signed_text[len(PKIZ_PREFIX):].encode('utf-8') + unencoded = base64.urlsafe_b64decode(text) + uncompressed = zlib.decompress(unencoded) + return uncompressed + + +def pkiz_verify(signed_text, signing_cert_file_name, ca_file_name): + uncompressed = pkiz_uncompress(signed_text) + return cms_verify(uncompressed, signing_cert_file_name, ca_file_name, + inform=PKIZ_CMS_FORM) + + +# This function is deprecated and will be removed once the ASN1 token format +# is no longer required. It is only here to be used for testing. def token_to_cms(signed_text): copy_of_text = signed_text.replace('-', '/') @@ -225,14 +289,33 @@ def is_ans1_token(token): return is_asn1_token(token) -def cms_sign_text(text, signing_cert_file_name, signing_key_file_name): +def cms_sign_text(data_to_sign, signing_cert_file_name, signing_key_file_name): + return cms_sign_data(data_to_sign, signing_cert_file_name, + signing_key_file_name) + + +def cms_sign_data(data_to_sign, signing_cert_file_name, signing_key_file_name, + outform=PKI_ASN1_FORM): """Uses OpenSSL to sign a document. Produces a Base64 encoding of a DER formatted CMS Document http://en.wikipedia.org/wiki/Cryptographic_Message_Syntax + + :param data_to_sign: data to sign + :param signing_cert_file_name: path to the X509 certificate containing + the public key associated with the private key used to sign the data + :param signing_key_file_name: path to the private key used to sign + the data + :param outform: Format for the signed document PKIZ_CMS_FORM or + PKI_ASN1_FORM + + """ _ensure_subprocess() - data = bytearray(text, encoding='utf-8') + if isinstance(data_to_sign, six.string_types): + data = bytearray(data_to_sign, encoding='utf-8') + else: + data = data_to_sign process = subprocess.Popen(['openssl', 'cms', '-sign', '-signer', signing_cert_file_name, '-inkey', signing_key_file_name, @@ -248,12 +331,21 @@ def cms_sign_text(text, signing_cert_file_name, signing_key_file_name): if retcode or ('Error' in err): LOG.error('Signing error: %s' % err) + if retcode == 3: + LOG.error('Signing error: Unable to load certificate - ' + 'ensure you have configured PKI with ' + '"keystone-manage pki_setup"') + else: + LOG.error('Signing error: %s', err) raise subprocess.CalledProcessError(retcode, 'openssl') - return output.decode('utf-8') + if outform == PKI_ASN1_FORM: + return output.decode('utf-8') + else: + return output def cms_sign_token(text, signing_cert_file_name, signing_key_file_name): - output = cms_sign_text(text, signing_cert_file_name, signing_key_file_name) + output = cms_sign_data(text, signing_cert_file_name, signing_key_file_name) return cms_to_token(output) @@ -273,12 +365,12 @@ def cms_to_token(cms_text): def cms_hash_token(token_id, mode='md5'): """Hash PKI tokens. - return: for asn1_token, returns the hash of the passed in token + return: for asn1 or pkiz tokens, returns the hash of the passed in token otherwise, returns what it was passed in. """ if token_id is None: return None - if is_asn1_token(token_id): + if is_asn1_token(token_id) or is_pkiz(token_id): hasher = hashlib.new(mode) if isinstance(token_id, six.text_type): token_id = token_id.encode('utf-8') diff --git a/keystoneclient/exceptions.py b/keystoneclient/exceptions.py index 4572af92..31f25cb7 100644 --- a/keystoneclient/exceptions.py +++ b/keystoneclient/exceptions.py @@ -37,6 +37,14 @@ class CertificateConfigError(Exception): super(CertificateConfigError, self).__init__(msg) +class CMSError(Exception): + """Error reading the certificate""" + def __init__(self, output): + self.output = output + msg = ("Unable to sign or verify data.") + super(CMSError, self).__init__(msg) + + class EmptyCatalog(EndpointNotFound): """The service catalog is empty.""" pass diff --git a/keystoneclient/middleware/auth_token.py b/keystoneclient/middleware/auth_token.py index 637b3b26..f11a2602 100644 --- a/keystoneclient/middleware/auth_token.py +++ b/keystoneclient/middleware/auth_token.py @@ -875,7 +875,9 @@ class AuthProtocol(object): 'Token is marked as having been revoked') raise InvalidUserToken( 'Token authorization failed') - + elif cms.is_pkiz(user_token): + verified = self.verify_pkiz_token(user_token) + data = jsonutils.loads(verified) elif cms.is_asn1_token(user_token): verified = self.verify_signed_token(user_token) data = jsonutils.loads(verified) @@ -1228,7 +1230,7 @@ class AuthProtocol(object): revoked_ids = (x['id'] for x in revoked_tokens) return token_id in revoked_ids - def cms_verify(self, data): + def cms_verify(self, data, inform=cms.PKI_ASN1_FORM): """Verifies the signature of the provided data's IAW CMS syntax. If either of the certificate files might be missing, fetch them and @@ -1236,9 +1238,9 @@ class AuthProtocol(object): """ def verify(): try: - return cms.cms_verify( - data, self.signing_cert_file_name, - self.signing_ca_file_name).decode('utf-8') + return cms.cms_verify(data, self.signing_cert_file_name, + self.signing_ca_file_name, + inform=inform).decode('utf-8') except cms.subprocess.CalledProcessError as err: self.LOG.warning('Verify error: %s', err) raise @@ -1265,7 +1267,19 @@ class AuthProtocol(object): raise InvalidUserToken('Token has been revoked') formatted = cms.token_to_cms(signed_text) - return self.cms_verify(formatted) + verified = self.cms_verify(formatted) + return verified + + def verify_pkiz_token(self, signed_text): + if self.is_signed_token_revoked(signed_text): + raise InvalidUserToken('Token has been revoked') + try: + uncompressed = cms.pkiz_uncompress(signed_text) + verified = self.cms_verify(uncompressed, inform=cms.PKIZ_CMS_FORM) + return verified + # TypeError If the signed_text is not zlib compressed + except TypeError: + raise InvalidUserToken(signed_text) def verify_signing_dir(self): if os.path.exists(self.signing_dirname): diff --git a/keystoneclient/tests/client_fixtures.py b/keystoneclient/tests/client_fixtures.py index 6aabd99b..f090db04 100644 --- a/keystoneclient/tests/client_fixtures.py +++ b/keystoneclient/tests/client_fixtures.py @@ -53,6 +53,8 @@ class Examples(fixtures.Fixture): # files in the signing subdirectory. In order to keep the values # consistent between the tests and the signed documents, we read them # in for use in the tests. + with open(os.path.join(CMSDIR, 'auth_token_scoped.json')) as f: + self.TOKEN_SCOPED_DATA = cms.cms_to_token(f.read()) with open(os.path.join(CMSDIR, 'auth_token_scoped.pem')) as f: self.SIGNED_TOKEN_SCOPED = cms.cms_to_token(f.read()) @@ -66,6 +68,19 @@ class Examples(fixtures.Fixture): self.SIGNED_TOKEN_SCOPED_EXPIRED = cms.cms_to_token(f.read()) with open(os.path.join(CMSDIR, 'auth_v3_token_revoked.pem')) as f: self.REVOKED_v3_TOKEN = cms.cms_to_token(f.read()) + with open(os.path.join(CMSDIR, 'auth_token_scoped.pkiz')) as f: + self.SIGNED_TOKEN_SCOPED_PKIZ = cms.cms_to_token(f.read()) + with open(os.path.join(CMSDIR, 'auth_token_unscoped.pkiz')) as f: + self.SIGNED_TOKEN_UNSCOPED_PKIZ = cms.cms_to_token(f.read()) + with open(os.path.join(CMSDIR, 'auth_v3_token_scoped.pkiz')) as f: + self.SIGNED_v3_TOKEN_SCOPED_PKIZ = cms.cms_to_token(f.read()) + with open(os.path.join(CMSDIR, 'auth_token_revoked.pkiz')) as f: + self.REVOKED_TOKEN_PKIZ = cms.cms_to_token(f.read()) + with open(os.path.join(CMSDIR, + 'auth_token_scoped_expired.pkiz')) as f: + self.SIGNED_TOKEN_SCOPED_EXPIRED_PKIZ = cms.cms_to_token(f.read()) + with open(os.path.join(CMSDIR, 'auth_v3_token_revoked.pkiz')) as f: + self.REVOKED_v3_TOKEN_PKIZ = cms.cms_to_token(f.read()) with open(os.path.join(CMSDIR, 'revocation_list.json')) as f: self.REVOCATION_LIST = jsonutils.loads(f.read()) with open(os.path.join(CMSDIR, 'revocation_list.pem')) as f: @@ -116,6 +131,26 @@ class Examples(fixtures.Fixture): self.REVOKED_v3_TOKEN_LIST_JSON = jsonutils.dumps( self.REVOKED_v3_TOKEN_LIST) + revoked_token_pkiz = self.REVOKED_TOKEN_PKIZ + if isinstance(revoked_token_pkiz, six.text_type): + revoked_token_pkiz = revoked_token_pkiz.encode('utf-8') + self.REVOKED_TOKEN_PKIZ_HASH = utils.hash_signed_token( + revoked_token_pkiz) + revoked_v3_token_pkiz = self.REVOKED_v3_TOKEN_PKIZ + if isinstance(revoked_v3_token_pkiz, six.text_type): + revoked_v3_token_pkiz = revoked_v3_token_pkiz.encode('utf-8') + self.REVOKED_v3_PKIZ_TOKEN_HASH = utils.hash_signed_token( + revoked_v3_token_pkiz) + + self.REVOKED_TOKEN_PKIZ_LIST = ( + {'revoked': [{'id': self.REVOKED_TOKEN_PKIZ_HASH, + 'expires': timeutils.utcnow()}, + {'id': self.REVOKED_v3_PKIZ_TOKEN_HASH, + 'expires': timeutils.utcnow()}, + ]}) + self.REVOKED_TOKEN_PKIZ_LIST_JSON = jsonutils.dumps( + self.REVOKED_TOKEN_PKIZ_LIST) + self.SIGNED_TOKEN_SCOPED_KEY = cms.cms_hash_token( self.SIGNED_TOKEN_SCOPED) self.SIGNED_TOKEN_UNSCOPED_KEY = cms.cms_hash_token( @@ -123,6 +158,13 @@ class Examples(fixtures.Fixture): self.SIGNED_v3_TOKEN_SCOPED_KEY = cms.cms_hash_token( self.SIGNED_v3_TOKEN_SCOPED) + self.SIGNED_TOKEN_SCOPED_PKIZ_KEY = cms.cms_hash_token( + self.SIGNED_TOKEN_SCOPED_PKIZ) + self.SIGNED_TOKEN_UNSCOPED_PKIZ_KEY = cms.cms_hash_token( + self.SIGNED_TOKEN_UNSCOPED_PKIZ) + self.SIGNED_v3_TOKEN_SCOPED_PKIZ_KEY = cms.cms_hash_token( + self.SIGNED_v3_TOKEN_SCOPED_PKIZ) + self.INVALID_SIGNED_TOKEN = ( "MIIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" @@ -142,6 +184,25 @@ class Examples(fixtures.Fixture): "9999999999999999999999999999999999999999999999999999999999999999" "0000000000000000000000000000000000000000000000000000000000000000") + self.INVALID_SIGNED_PKIZ_TOKEN = ( + "PKIZ_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" + "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" + "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD" + "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "0000000000000000000000000000000000000000000000000000000000000000" + "1111111111111111111111111111111111111111111111111111111111111111" + "2222222222222222222222222222222222222222222222222222222222222222" + "3333333333333333333333333333333333333333333333333333333333333333" + "4444444444444444444444444444444444444444444444444444444444444444" + "5555555555555555555555555555555555555555555555555555555555555555" + "6666666666666666666666666666666666666666666666666666666666666666" + "7777777777777777777777777777777777777777777777777777777777777777" + "8888888888888888888888888888888888888888888888888888888888888888" + "9999999999999999999999999999999999999999999999999999999999999999" + "0000000000000000000000000000000000000000000000000000000000000000") + # JSON responses keyed by token ID self.TOKEN_RESPONSES = { self.UUID_TOKEN_DEFAULT: { @@ -444,6 +505,12 @@ class Examples(fixtures.Fixture): } }, } + self.TOKEN_RESPONSES[self.SIGNED_TOKEN_SCOPED_PKIZ_KEY] = ( + self.TOKEN_RESPONSES[self.SIGNED_TOKEN_SCOPED_KEY]) + self.TOKEN_RESPONSES[self.SIGNED_TOKEN_UNSCOPED_PKIZ_KEY] = ( + self.TOKEN_RESPONSES[self.SIGNED_TOKEN_UNSCOPED_KEY]) + self.TOKEN_RESPONSES[self.SIGNED_v3_TOKEN_SCOPED_PKIZ_KEY] = ( + self.TOKEN_RESPONSES[self.SIGNED_v3_TOKEN_SCOPED_KEY]) self.JSON_TOKEN_RESPONSES = dict([(k, jsonutils.dumps(v)) for k, v in six.iteritems(self.TOKEN_RESPONSES)]) diff --git a/keystoneclient/tests/test_auth_token_middleware.py b/keystoneclient/tests/test_auth_token_middleware.py index b14917d0..6b81f236 100644 --- a/keystoneclient/tests/test_auth_token_middleware.py +++ b/keystoneclient/tests/test_auth_token_middleware.py @@ -14,6 +14,7 @@ import calendar import datetime +import json import os import shutil import stat @@ -532,6 +533,12 @@ class CommonAuthTokenMiddlewareTest(object): #ensure that signed requests do not generate HTTP traffic self.assertLastPath(None) + def test_valid_signed_compressed_request(self): + self.assert_valid_request_200( + self.token_dict['signed_token_scoped_pkiz']) + # ensure that signed requests do not generate HTTP traffic + self.assertLastPath(None) + def test_revoked_token_receives_401(self): self.middleware.token_revocation_list = self.get_revocation_list_json() req = webob.Request.blank('/') @@ -572,10 +579,27 @@ class CommonAuthTokenMiddlewareTest(object): self.middleware.verify_signed_token, self.token_dict['revoked_token']) + def test_verify_signed_token_raises_exception_for_revoked_pkiz_token(self): + self.middleware.token_revocation_list = ( + self.examples.REVOKED_TOKEN_PKIZ_LIST_JSON) + self.assertRaises(auth_token.InvalidUserToken, + self.middleware.verify_pkiz_token, + self.token_dict['revoked_token_pkiz']) + + def assertIsValidJSON(self, text): + json.loads(text) + def test_verify_signed_token_succeeds_for_unrevoked_token(self): self.middleware.token_revocation_list = self.get_revocation_list_json() - self.middleware.verify_signed_token( + text = self.middleware.verify_signed_token( self.token_dict['signed_token_scoped']) + self.assertIsValidJSON(text) + + def test_verify_signed_compressed_token_succeeds_for_unrevoked_token(self): + self.middleware.token_revocation_list = self.get_revocation_list_json() + text = self.middleware.verify_pkiz_token( + self.token_dict['signed_token_scoped_pkiz']) + self.assertIsValidJSON(text) def test_verify_signing_dir_create_while_missing(self): tmp_name = uuid.uuid4().hex @@ -671,9 +695,17 @@ class CommonAuthTokenMiddlewareTest(object): req = webob.Request.blank('/') req.headers['X-Auth-Token'] = self.examples.INVALID_SIGNED_TOKEN self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 401) - self.assertEqual(self.response_headers['WWW-Authenticate'], - "Keystone uri='https://keystone.example.com:1234'") + self.assertEqual(401, self.response_status) + self.assertEqual("Keystone uri='https://keystone.example.com:1234'", + self.response_headers['WWW-Authenticate']) + + def test_request_invalid_signed_pkiz_token(self): + req = webob.Request.blank('/') + req.headers['X-Auth-Token'] = self.examples.INVALID_SIGNED_PKIZ_TOKEN + self.middleware(req.environ, self.start_fake_response) + self.assertEqual(401, self.response_status) + self.assertEqual("Keystone uri='https://keystone.example.com:1234'", + self.response_headers['WWW-Authenticate']) def test_request_no_token(self): req = webob.Request.blank('/') @@ -1293,9 +1325,11 @@ class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest, 'uuid_token_bind': self.examples.UUID_TOKEN_BIND, 'uuid_token_unknown_bind': self.examples.UUID_TOKEN_UNKNOWN_BIND, 'signed_token_scoped': self.examples.SIGNED_TOKEN_SCOPED, + 'signed_token_scoped_pkiz': self.examples.SIGNED_TOKEN_SCOPED_PKIZ, 'signed_token_scoped_expired': self.examples.SIGNED_TOKEN_SCOPED_EXPIRED, 'revoked_token': self.examples.REVOKED_TOKEN, + 'revoked_token_pkiz': self.examples.REVOKED_TOKEN_PKIZ, 'revoked_token_hash': self.examples.REVOKED_TOKEN_HASH } @@ -1475,9 +1509,12 @@ class v3AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest, 'uuid_token_unknown_bind': self.examples.v3_UUID_TOKEN_UNKNOWN_BIND, 'signed_token_scoped': self.examples.SIGNED_v3_TOKEN_SCOPED, + 'signed_token_scoped_pkiz': + self.examples.SIGNED_v3_TOKEN_SCOPED_PKIZ, 'signed_token_scoped_expired': self.examples.SIGNED_TOKEN_SCOPED_EXPIRED, 'revoked_token': self.examples.REVOKED_v3_TOKEN, + 'revoked_token_pkiz': self.examples.REVOKED_v3_TOKEN_PKIZ, 'revoked_token_hash': self.examples.REVOKED_v3_TOKEN_HASH } diff --git a/keystoneclient/tests/test_cms.py b/keystoneclient/tests/test_cms.py index 2f00522d..43eba2b9 100644 --- a/keystoneclient/tests/test_cms.py +++ b/keystoneclient/tests/test_cms.py @@ -36,7 +36,7 @@ class CMSTest(utils.TestCase, testresources.ResourcedTestCase): 'no_exist_cert_file', 'no_exist_ca_file') - def test_token_to_cms_to_token(self): + def test_token_tocms_to_token(self): with open(os.path.join(client_fixtures.CMSDIR, 'auth_token_scoped.pem')) as f: AUTH_TOKEN_SCOPED_CMS = f.read() @@ -55,14 +55,20 @@ class CMSTest(utils.TestCase, testresources.ResourcedTestCase): def test_cms_sign_token_no_files(self): self.assertRaises(subprocess.CalledProcessError, cms.cms_sign_token, - self.examples.SIGNED_TOKEN_SCOPED, + self.examples.TOKEN_SCOPED_DATA, + '/no/such/file', '/no/such/key') + + def test_cms_sign_token_no_files_pkiz(self): + self.assertRaises(subprocess.CalledProcessError, + cms.pkiz_sign, + self.examples.TOKEN_SCOPED_DATA, '/no/such/file', '/no/such/key') def test_cms_sign_token_success(self): self.assertTrue( - cms.cms_sign_token(self.examples.SIGNED_TOKEN_SCOPED, - self.examples.SIGNING_CERT_FILE, - self.examples.SIGNING_KEY_FILE)) + cms.pkiz_sign(self.examples.TOKEN_SCOPED_DATA, + self.examples.SIGNING_CERT_FILE, + self.examples.SIGNING_KEY_FILE)) def test_cms_verify_token_no_files(self): self.assertRaises(exceptions.CertificateConfigError,