def test_decode_caveat_v1_from_go(self): tp_key = macaroonbakery.PrivateKey( nacl.public.PrivateKey( base64.b64decode( 'TSpvLpQkRj+T3JXnsW2n43n5zP/0X4zn0RvDiWC3IJ0='))) fp_key = macaroonbakery.PrivateKey( nacl.public.PrivateKey( base64.b64decode( 'KXpsoJ9ujZYi/O2Cca6kaWh65MSawzy79LWkrjOfzcs='))) root_key = base64.b64decode('vDxEmWZEkgiNEFlJ+8ruXe3qDSLf1H+o') # This caveat has been generated from the go code # to check the compatibilty encrypted_cav = six.b( 'eyJUaGlyZFBhcnR5UHVibGljS2V5IjoiOFA3R1ZZc3BlWlN4c' '3hFdmJsSVFFSTFqdTBTSWl0WlIrRFdhWE40cmxocz0iLCJGaX' 'JzdFBhcnR5UHVibGljS2V5IjoiSDlqSFJqSUxidXppa1VKd2o' '5VGtDWk9qeW5oVmtTdHVsaUFRT2d6Y0NoZz0iLCJOb25jZSI6' 'Ii9lWTRTTWR6TGFxbDlsRFc3bHUyZTZuSzJnVG9veVl0IiwiS' 'WQiOiJra0ZuOGJEaEt4RUxtUjd0NkJxTU0vdHhMMFVqaEZjR1' 'BORldUUExGdjVla1dWUjA4Uk1sbGJhc3c4VGdFbkhzM0laeVo' '0V2lEOHhRUWdjU3ljOHY4eUt4dEhxejVEczJOYmh1ZDJhUFdt' 'UTVMcVlNWitmZ2FNaTAxdE9DIn0=') cav = macaroonbakery.decode_caveat(tp_key, encrypted_cav) self.assertEquals( cav, macaroonbakery.ThirdPartyCaveatInfo( condition='caveat condition', first_party_public_key=fp_key.public_key, third_party_key_pair=tp_key, root_key=root_key, caveat=encrypted_cav, version=macaroonbakery.BAKERY_V1, namespace=macaroonbakery.legacy_namespace()))
def test_decode_caveat_v3_from_go(self): tp_key = macaroonbakery.PrivateKey( nacl.public.PrivateKey( base64.b64decode( 'TSpvLpQkRj+T3JXnsW2n43n5zP/0X4zn0RvDiWC3IJ0='))) fp_key = macaroonbakery.PrivateKey( nacl.public.PrivateKey( base64.b64decode( 'KXpsoJ9ujZYi/O2Cca6kaWh65MSawzy79LWkrjOfzcs='))) root_key = base64.b64decode(b'oqOXI3/Mz/pKjCuFOt2eYxb7ndLq66GY') # This caveat has been generated from the go code # to check the compatibilty encrypted_cav = base64.urlsafe_b64decode( utils.add_base64_padding( six. b('A_D-xlUf2MdGMgtu7OKRQnCP1OQJk6PKeFWRK26WIBA6DNwKGNLeFSkD2M-8A' 'EYvmgVH95GWu7T7caKxKhhOQFcEKgnXKJvYXxz1zin4cZc4Q6C7gVqA-J4_j3' '1LX4VKxymqG62UGPo78wOv0_fKjr3OI6PPJOYOQgBMclemlRF2'))) cav = macaroonbakery.decode_caveat(tp_key, encrypted_cav) self.assertEquals( cav, macaroonbakery.ThirdPartyCaveatInfo( condition='third party condition', first_party_public_key=fp_key.public_key, third_party_key_pair=tp_key, root_key=root_key, caveat=encrypted_cav, version=macaroonbakery.BAKERY_V3, namespace=macaroonbakery.legacy_namespace()))
def test_decode_caveat_v1_from_go(self): tp_key = bakery.PrivateKey( nacl.public.PrivateKey(base64.b64decode( 'TSpvLpQkRj+T3JXnsW2n43n5zP/0X4zn0RvDiWC3IJ0='))) fp_key = bakery.PrivateKey( nacl.public.PrivateKey(base64.b64decode( 'KXpsoJ9ujZYi/O2Cca6kaWh65MSawzy79LWkrjOfzcs='))) root_key = base64.b64decode('vDxEmWZEkgiNEFlJ+8ruXe3qDSLf1H+o') # This caveat has been generated from the go code # to check the compatibilty encrypted_cav = six.b( 'eyJUaGlyZFBhcnR5UHVibGljS2V5IjoiOFA3R1ZZc3BlWlN4c' '3hFdmJsSVFFSTFqdTBTSWl0WlIrRFdhWE40cmxocz0iLCJGaX' 'JzdFBhcnR5UHVibGljS2V5IjoiSDlqSFJqSUxidXppa1VKd2o' '5VGtDWk9qeW5oVmtTdHVsaUFRT2d6Y0NoZz0iLCJOb25jZSI6' 'Ii9lWTRTTWR6TGFxbDlsRFc3bHUyZTZuSzJnVG9veVl0IiwiS' 'WQiOiJra0ZuOGJEaEt4RUxtUjd0NkJxTU0vdHhMMFVqaEZjR1' 'BORldUUExGdjVla1dWUjA4Uk1sbGJhc3c4VGdFbkhzM0laeVo' '0V2lEOHhRUWdjU3ljOHY4eUt4dEhxejVEczJOYmh1ZDJhUFdt' 'UTVMcVlNWitmZ2FNaTAxdE9DIn0=') cav = bakery.decode_caveat(tp_key, encrypted_cav) self.assertEquals(cav, bakery.ThirdPartyCaveatInfo( condition='caveat condition', first_party_public_key=fp_key.public_key, third_party_key_pair=tp_key, root_key=root_key, caveat=encrypted_cav, version=bakery.VERSION_1, id=None, namespace=bakery.legacy_namespace() ))
def test_decode_caveat_v2_from_go(self): tp_key = macaroonbakery.PrivateKey( nacl.public.PrivateKey( base64.b64decode( 'TSpvLpQkRj+T3JXnsW2n43n5zP/0X4zn0RvDiWC3IJ0='))) fp_key = macaroonbakery.PrivateKey( nacl.public.PrivateKey( base64.b64decode( 'KXpsoJ9ujZYi/O2Cca6kaWh65MSawzy79LWkrjOfzcs='))) root_key = base64.b64decode('wh0HSM65wWHOIxoGjgJJOFvQKn2jJFhC') # This caveat has been generated from the go code # to check the compatibilty encrypted_cav = base64.urlsafe_b64decode( utils.add_base64_padding( six. b('AvD-xlUf2MdGMgtu7OKRQnCP1OQJk6PKeFWRK26WIBA6DNwKGIHq9xGcHS9IZ' 'Lh0cL6D9qpeKI0mXmCPfnwRQDuVYC8y5gVWd-oCGZaj5TGtk3byp2Vnw6ojmt' 'sULDhY59YA_J_Y0ATkERO5T9ajoRWBxU2OXBoX6bImXA'))) cav = macaroonbakery.decode_caveat(tp_key, encrypted_cav) self.assertEqual( cav, macaroonbakery.ThirdPartyCaveatInfo( condition='third party condition', first_party_public_key=fp_key.public_key, third_party_key_pair=tp_key, root_key=root_key, caveat=encrypted_cav, version=macaroonbakery.BAKERY_V2, namespace=macaroonbakery.legacy_namespace()))
def test_decode_caveat_v3_from_go(self): tp_key = bakery.PrivateKey( nacl.public.PrivateKey(base64.b64decode( 'TSpvLpQkRj+T3JXnsW2n43n5zP/0X4zn0RvDiWC3IJ0='))) fp_key = bakery.PrivateKey(nacl.public.PrivateKey( base64.b64decode( 'KXpsoJ9ujZYi/O2Cca6kaWh65MSawzy79LWkrjOfzcs='))) root_key = base64.b64decode(b'oqOXI3/Mz/pKjCuFOt2eYxb7ndLq66GY') # This caveat has been generated from the go code # to check the compatibilty encrypted_cav = bakery.b64decode( 'A_D-xlUf2MdGMgtu7OKRQnCP1OQJk6PKeFWRK26WIBA6DNwKGNLeFSkD2M-8A' 'EYvmgVH95GWu7T7caKxKhhOQFcEKgnXKJvYXxz1zin4cZc4Q6C7gVqA-J4_j3' '1LX4VKxymqG62UGPo78wOv0_fKjr3OI6PPJOYOQgBMclemlRF2', ) cav = bakery.decode_caveat(tp_key, encrypted_cav) self.assertEquals(cav, bakery.ThirdPartyCaveatInfo( condition='third party condition', first_party_public_key=fp_key.public_key, third_party_key_pair=tp_key, root_key=root_key, caveat=encrypted_cav, version=bakery.VERSION_3, id=None, namespace=bakery.legacy_namespace() ))
def test_decode_caveat_v2_from_go(self): tp_key = bakery.PrivateKey(nacl.public.PrivateKey( base64.b64decode( 'TSpvLpQkRj+T3JXnsW2n43n5zP/0X4zn0RvDiWC3IJ0='))) fp_key = bakery.PrivateKey( nacl.public.PrivateKey(base64.b64decode( 'KXpsoJ9ujZYi/O2Cca6kaWh65MSawzy79LWkrjOfzcs='))) root_key = base64.b64decode('wh0HSM65wWHOIxoGjgJJOFvQKn2jJFhC') # This caveat has been generated from the go code # to check the compatibilty encrypted_cav = bakery.b64decode( 'AvD-xlUf2MdGMgtu7OKRQnCP1OQJk6PKeFWRK26WIBA6DNwKGIHq9xGcHS9IZ' 'Lh0cL6D9qpeKI0mXmCPfnwRQDuVYC8y5gVWd-oCGZaj5TGtk3byp2Vnw6ojmt' 'sULDhY59YA_J_Y0ATkERO5T9ajoRWBxU2OXBoX6bImXA', ) cav = bakery.decode_caveat(tp_key, encrypted_cav) self.assertEqual(cav, bakery.ThirdPartyCaveatInfo( condition='third party condition', first_party_public_key=fp_key.public_key, third_party_key_pair=tp_key, root_key=root_key, caveat=encrypted_cav, version=bakery.VERSION_2, id=None, namespace=bakery.legacy_namespace() ))
def discharge(ctx, id, caveat, key, checker, locator): ''' Creates a macaroon to discharge a third party caveat. The given parameters specify the caveat and how it should be checked. The condition implicit in the caveat is checked for validity using checker. If it is valid, a new macaroon is returned which discharges the caveat. The macaroon is created with a version derived from the version that was used to encode the id. :param id: (bytes) holds the id to give to the discharge macaroon. If Caveat is empty, then the id also holds the encrypted third party caveat. :param caveat: (bytes) holds the encrypted third party caveat. If this is None, id will be used. :param key: holds the key to use to decrypt the third party caveat information and to encrypt any additional third party caveats returned by the caveat checker. :param checker: used to check the third party caveat, and may also return further caveats to be added to the discharge macaroon. :param locator: used to information on third parties referred to by third party caveats returned by the Checker. ''' caveat_id_prefix = [] if caveat is None: # The caveat information is encoded in the id itself. caveat = id else: # We've been given an explicit id, so when extra third party # caveats are added, use that id as the prefix # for any more ids. caveat_id_prefix = id cav_info = macaroonbakery.decode_caveat(key, caveat) # Note that we don't check the error - we allow the # third party checker to see even caveats that we can't # understand. try: cond, arg = checkers.parse_caveat(cav_info.condition) except ValueError as exc: raise macaroonbakery.VerificationError(exc.args[0]) if cond == checkers.COND_NEED_DECLARED: cav_info = cav_info._replace(condition=arg.encode('utf-8')) caveats = _check_need_declared(ctx, cav_info, checker) else: caveats = checker.check_third_party_caveat(ctx, cav_info) # Note that the discharge macaroon does not need to # be stored persistently. Indeed, it would be a problem if # we did, because then the macaroon could potentially be used # for normal authorization with the third party. m = macaroonbakery.Macaroon(cav_info.root_key, id, '', cav_info.version, cav_info.namespace) m._caveat_id_prefix = caveat_id_prefix if caveats is not None: for cav in caveats: m.add_caveat(cav, key, locator) return m
def test_v2_round_trip(self): tp_info = bakery.ThirdPartyInfo(version=bakery.VERSION_2, public_key=self.tp_key.public_key) cid = bakery.encode_caveat('is-authenticated-user', b'a random string', tp_info, self.fp_key, None) res = bakery.decode_caveat(self.tp_key, cid) self.assertEquals( res, bakery.ThirdPartyCaveatInfo( first_party_public_key=self.fp_key.public_key, root_key=b'a random string', condition='is-authenticated-user', caveat=cid, third_party_key_pair=self.tp_key, version=bakery.VERSION_2, id=None, namespace=bakery.legacy_namespace()))
def test_v3_round_trip(self): tp_info = bakery.ThirdPartyInfo(version=bakery.VERSION_3, public_key=self.tp_key.public_key) ns = checkers.Namespace() ns.register('testns', 'x') cid = bakery.encode_caveat('is-authenticated-user', b'a random string', tp_info, self.fp_key, ns) res = bakery.decode_caveat(self.tp_key, cid) self.assertEquals( res, bakery.ThirdPartyCaveatInfo( first_party_public_key=self.fp_key.public_key, root_key=b'a random string', condition='is-authenticated-user', caveat=cid, third_party_key_pair=self.tp_key, version=bakery.VERSION_3, id=None, namespace=ns))
def test_v2_round_trip(self): tp_info = bakery.ThirdPartyInfo( version=bakery.VERSION_2, public_key=self.tp_key.public_key) cid = bakery.encode_caveat( 'is-authenticated-user', b'a random string', tp_info, self.fp_key, None) res = bakery.decode_caveat(self.tp_key, cid) self.assertEquals(res, bakery.ThirdPartyCaveatInfo( first_party_public_key=self.fp_key.public_key, root_key=b'a random string', condition='is-authenticated-user', caveat=cid, third_party_key_pair=self.tp_key, version=bakery.VERSION_2, id=None, namespace=bakery.legacy_namespace() ))
def test_v3_round_trip(self): tp_info = bakery.ThirdPartyInfo( version=bakery.VERSION_3, public_key=self.tp_key.public_key) ns = checkers.Namespace() ns.register('testns', 'x') cid = bakery.encode_caveat( 'is-authenticated-user', b'a random string', tp_info, self.fp_key, ns) res = bakery.decode_caveat(self.tp_key, cid) self.assertEquals(res, bakery.ThirdPartyCaveatInfo( first_party_public_key=self.fp_key.public_key, root_key=b'a random string', condition='is-authenticated-user', caveat=cid, third_party_key_pair=self.tp_key, version=bakery.VERSION_3, id=None, namespace=ns ))
def discharge(ctx, id, caveat, key, checker, locator): ''' Creates a macaroon to discharge a third party caveat. The given parameters specify the caveat and how it should be checked. The condition implicit in the caveat is checked for validity using checker. If it is valid, a new macaroon is returned which discharges the caveat. The macaroon is created with a version derived from the version that was used to encode the id. :param id: (bytes) holds the id to give to the discharge macaroon. If Caveat is empty, then the id also holds the encrypted third party caveat. :param caveat: (bytes) holds the encrypted third party caveat. If this is None, id will be used. :param key: holds the key to use to decrypt the third party caveat information and to encrypt any additional third party caveats returned by the caveat checker. :param checker: used to check the third party caveat, and may also return further caveats to be added to the discharge macaroon. :param locator: used to information on third parties referred to by third party caveats returned by the Checker. ''' caveat_id_prefix = [] if caveat is None: # The caveat information is encoded in the id itself. caveat = id else: # We've been given an explicit id, so when extra third party # caveats are added, use that id as the prefix # for any more ids. caveat_id_prefix = id cav_info = bakery.decode_caveat(key, caveat) cav_info = bakery.ThirdPartyCaveatInfo( condition=cav_info.condition, first_party_public_key=cav_info.first_party_public_key, third_party_key_pair=cav_info.third_party_key_pair, root_key=cav_info.root_key, caveat=cav_info.caveat, version=cav_info.version, id=id, namespace=cav_info.namespace ) # Note that we don't check the error - we allow the # third party checker to see even caveats that we can't # understand. try: cond, arg = checkers.parse_caveat(cav_info.condition) except ValueError as exc: raise bakery.VerificationError(exc.args[0]) if cond == checkers.COND_NEED_DECLARED: cav_info = cav_info._replace(condition=arg.encode('utf-8')) caveats = _check_need_declared(ctx, cav_info, checker) else: caveats = checker.check_third_party_caveat(ctx, cav_info) # Note that the discharge macaroon does not need to # be stored persistently. Indeed, it would be a problem if # we did, because then the macaroon could potentially be used # for normal authorization with the third party. m = bakery.Macaroon( cav_info.root_key, id, '', cav_info.version, cav_info.namespace, ) m._caveat_id_prefix = caveat_id_prefix if caveats is not None: for cav in caveats: m.add_caveat(cav, key, locator) return m
def test_empty_caveat_id(self): with self.assertRaises(macaroonbakery.VerificationError) as context: macaroonbakery.decode_caveat(self.tp_key, b'') self.assertTrue('empty third party caveat' in str(context.exception))
def test_empty_caveat_id(self): with self.assertRaises(bakery.VerificationError) as context: bakery.decode_caveat(self.tp_key, b'') self.assertTrue('empty third party caveat' in str(context.exception))