def add_caveat(self, cav, key=None, loc=None): '''Add a caveat to the macaroon. It encrypts it using the given key pair and by looking up the location using the given locator. As a special case, if the caveat's Location field has the prefix "local " the caveat is added as a client self-discharge caveat using the public key base64-encoded in the rest of the location. In this case, the Condition field must be empty. The resulting third-party caveat will encode the condition "true" encrypted with that public key. @param cav the checkers.Caveat to be added. @param key the public key to encrypt third party caveat. @param loc locator to find information on third parties when adding third party caveats. It is expected to have a third_party_info method that will be called with a location string and should return a ThirdPartyInfo instance holding the requested information. ''' if cav.location is None: self._macaroon.add_first_party_caveat( self.namespace.resolve_caveat(cav).condition) return if key is None: raise ValueError('no private key to encrypt third party caveat') local_info = _parse_local_location(cav.location) if local_info is not None: info = local_info if cav.condition is not '': raise ValueError('cannot specify caveat condition in ' 'local third-party caveat') cav = checkers.Caveat(location='local', condition='true') else: if loc is None: raise ValueError('no locator when adding third party caveat') info = loc.third_party_info(cav.location) root_key = os.urandom(24) # Use the least supported version to encode the caveat. if self._version < info.version: info = bakery.ThirdPartyInfo( version=self._version, public_key=info.public_key, ) caveat_info = bakery.encode_caveat(cav.condition, root_key, info, key, self._namespace) if info.version < bakery.VERSION_3: # We're encoding for an earlier client or third party which does # not understand bundled caveat info, so use the encoded # caveat information as the caveat id. id = caveat_info else: id = self._new_caveat_id(self._caveat_id_prefix) self._caveat_data[id] = caveat_info self._macaroon.add_third_party_caveat(cav.location, root_key, id)
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 add_caveat(self, cav, key=None, loc=None): '''Add a caveat to the macaroon. It encrypts it using the given key pair and by looking up the location using the given locator. As a special case, if the caveat's Location field has the prefix "local " the caveat is added as a client self-discharge caveat using the public key base64-encoded in the rest of the location. In this case, the Condition field must be empty. The resulting third-party caveat will encode the condition "true" encrypted with that public key. @param cav the checkers.Caveat to be added. @param key the public key to encrypt third party caveat. @param loc locator to find information on third parties when adding third party caveats. It is expected to have a third_party_info method that will be called with a location string and should return a ThirdPartyInfo instance holding the requested information. ''' if cav.location is None: self._macaroon.add_first_party_caveat( self.namespace.resolve_caveat(cav).condition) return if key is None: raise ValueError( 'no private key to encrypt third party caveat') local_info = _parse_local_location(cav.location) if local_info is not None: info = local_info if cav.condition is not '': raise ValueError( 'cannot specify caveat condition in ' 'local third-party caveat') cav = checkers.Caveat(location='local', condition='true') else: if loc is None: raise ValueError( 'no locator when adding third party caveat') info = loc.third_party_info(cav.location) root_key = os.urandom(24) # Use the least supported version to encode the caveat. if self._version < info.version: info = bakery.ThirdPartyInfo( version=self._version, public_key=info.public_key, ) caveat_info = bakery.encode_caveat( cav.condition, root_key, info, key, self._namespace) if info.version < bakery.VERSION_3: # We're encoding for an earlier client or third party which does # not understand bundled caveat info, so use the encoded # caveat information as the caveat id. id = caveat_info else: id = self._new_caveat_id(self._caveat_id_prefix) self._caveat_data[id] = caveat_info self._macaroon.add_third_party_caveat(cav.location, root_key, id)