def test_verify_failing_first_party_general_caveats(self): m = Macaroon( location='http://mybank/', identifier='we used our secret key', key='this is our super secret key; only we should know it') m.add_first_party_caveat('general caveat') v = Verifier() v.satisfy_general(lambda _: False) with assert_raises(MacaroonInvalidSignatureException) as cm: v.verify(m, 'this is our super secret key; only we should know it')
def _verify_macaroon(mac): v = Verifier() #verify the role is valid v.satisfy_general(_role_verification) #verify username is valid, only checks to make sure it only contains ascii, could be improved. v.satisfy_general(_user_verification) f = open("/var/EMR/secret_key", "r") if f.mode == 'r': secret_key = f.read() return v.verify(mac, secret_key) return None
def macaroon_ops(self, macaroons): ''' This method makes the oven satisfy the MacaroonOpStore protocol required by the Checker class. For macaroons minted with previous bakery versions, it always returns a single LoginOp operation. :param macaroons: :return: ''' if len(macaroons) == 0: raise ValueError('no macaroons provided') storage_id, ops = _decode_macaroon_id(macaroons[0].identifier_bytes) root_key = self.root_keystore_for_ops(ops).get(storage_id) if root_key is None: raise VerificationError( 'macaroon key not found in storage') v = Verifier() conditions = [] def validator(condition): # Verify the macaroon's signature only. Don't check any of the # caveats yet but save them so that we can return them. conditions.append(condition) return True v.satisfy_general(validator) try: v.verify(macaroons[0], root_key, macaroons[1:]) except Exception as exc: # Unfortunately pymacaroons doesn't control # the set of exceptions that can be raised here. # Possible candidates are: # pymacaroons.exceptions.MacaroonUnmetCaveatException # pymacaroons.exceptions.MacaroonInvalidSignatureException # ValueError # nacl.exceptions.CryptoError # # There may be others too, so just catch everything. raise six.raise_from( VerificationError('verification failed: {}'.format(str(exc))), exc, ) if (self.ops_store is not None and len(ops) == 1 and ops[0].entity.startswith('multi-')): # It's a multi-op entity, so retrieve the actual operations # it's associated with. ops = self.ops_store.get_ops(ops[0].entity) return ops, conditions
def verify(self, session, discharge): session_macaroon = Macaroon.from_binary(session) discharge_macaroon = Macaroon.from_binary(discharge) self.logger.debug('Root Macaroon:\n' + session_macaroon.inspect()) self.logger.debug('Discharge Macaroon:\n' + discharge_macaroon.inspect()) verifier = Verifier() verifier.satisfy_general(verify_time) verified = verifier.verify(session_macaroon, self.redis.get(session_macaroon.identifier), discharge_macaroons=[discharge_macaroon]) return verified
def test_verify_first_party_general_caveats(self): m = Macaroon( location='http://mybank/', identifier='we used our secret key', key='this is our super secret key; only we should know it') m.add_first_party_caveat('general caveat') def general_caveat_validator(predicate): return predicate == 'general caveat' v = Verifier() v.satisfy_general(general_caveat_validator) verified = v.verify( m, 'this is our super secret key; only we should know it') assert_true(verified)
def test_verify_failing_first_party_general_caveats(self): m = Macaroon( location='http://mybank/', identifier='we used our secret key', key='this is our super secret key; only we should know it' ) m.add_first_party_caveat('general caveat') v = Verifier() v.satisfy_general(lambda _: False) with assert_raises(MacaroonInvalidSignatureException) as cm: v.verify( m, 'this is our super secret key; only we should know it' )
def test_verify_first_party_general_caveats(self): m = Macaroon( location='http://mybank/', identifier='we used our secret key', key='this is our super secret key; only we should know it' ) m.add_first_party_caveat('general caveat') def general_caveat_validator(predicate): return predicate == 'general caveat' v = Verifier() v.satisfy_general(general_caveat_validator) verified = v.verify( m, 'this is our super secret key; only we should know it' ) assert_true(verified)
def macaroon_ops(self, macaroons): ''' This method makes the oven satisfy the MacaroonOpStore protocol required by the Checker class. For macaroons minted with previous bakery versions, it always returns a single LoginOp operation. :param macaroons: :return: ''' if len(macaroons) == 0: raise ValueError('no macaroons provided') storage_id, ops = _decode_macaroon_id(macaroons[0].identifier_bytes) root_key = self.root_keystore_for_ops(ops).get(storage_id) if root_key is None: raise bakery.VerificationError( 'macaroon key not found in storage') v = Verifier() conditions = [] def validator(condition): # Verify the macaroon's signature only. Don't check any of the # caveats yet but save them so that we can return them. conditions.append(condition) return True v.satisfy_general(validator) try: v.verify(macaroons[0], root_key, macaroons[1:]) except (MacaroonUnmetCaveatException, MacaroonInvalidSignatureException) as exc: raise bakery.VerificationError( 'verification failed: {}'.format(exc.args[0])) if (self.ops_store is not None and len(ops) == 1 and ops[0].entity.startswith('multi-')): # It's a multi-op entity, so retrieve the actual operations # it's associated with. ops = self.ops_store.get_ops(ops[0].entity) return ops, conditions
def gallery_token(token, image_name): if token: #Decode token n = Macaroon.deserialize(token) v = Verifier() form = forms.VerifyEmail() #On valid for submission if form.validate_on_submit(): #Verify Macaroon is valid v.satisfy_exact('email = {}'.format(form.email.data)) v.satisfy_exact('image_name = {}'.format(image_name)) v.satisfy_general(check_expiry) try: verified = v.verify(n, keys[n.identifier]) return send_from_directory(app.config['UPLOADED_IMAGES_DEST'], filename=image_name, as_attachment=False) except: flash("Unable to access") return render_template('validate_email.html', form=form, token=token, image_name=image_name) return render_template('validate_email.html', form=form, token=token, image_name=image_name) else: flash("Unable to access") return render_template('validate_email.html', form=form, token=token, image_name=image_name)
def macaroon_ops(self, macaroons): ''' This method makes the oven satisfy the MacaroonOpStore protocol required by the Checker class. For macaroons minted with previous bakery versions, it always returns a single LoginOp operation. :param macaroons: :return: ''' if len(macaroons) == 0: raise ValueError('no macaroons provided') storage_id, ops = _decode_macaroon_id(macaroons[0].identifier_bytes) root_key = self.root_keystore_for_ops(ops).get(storage_id) if root_key is None: raise bakery.VerificationError('macaroon key not found in storage') v = Verifier() conditions = [] def validator(condition): # Verify the macaroon's signature only. Don't check any of the # caveats yet but save them so that we can return them. conditions.append(condition) return True v.satisfy_general(validator) try: v.verify(macaroons[0], root_key, macaroons[1:]) except (MacaroonUnmetCaveatException, MacaroonInvalidSignatureException) as exc: raise bakery.VerificationError('verification failed: {}'.format( exc.args[0])) if (self.ops_store is not None and len(ops) == 1 and ops[0].entity.startswith('multi-')): # It's a multi-op entity, so retrieve the actual operations # it's associated with. ops = self.ops_store.get_ops(ops[0].entity) return ops, conditions
def satisfy_expiry(v: pymacaroons.Verifier, get_time_ms: Callable[[], int]) -> None: """Make a macaroon verifier which accepts 'time' caveats Builds a caveat verifier which will accept unexpired 'time' caveats, and adds it to the given macaroon verifier. Args: v: the macaroon verifier get_time_ms: a callable which will return the timestamp after which the caveat should be considered expired. Normally the current time. """ def verify_expiry_caveat(caveat: str) -> bool: time_msec = get_time_ms() prefix = "time < " if not caveat.startswith(prefix): return False expiry = int(caveat[len(prefix):]) return time_msec < expiry v.satisfy_general(verify_expiry_caveat)
def verify( macaroon: Macaroon, key: bytes, roles: List[str], caveats: List[str], used: int, req: Request, ) -> bool: assert macaroon v_obj = Verifier() v_obj.satisfy_exact(f"user = {macaroon.identifier}") for role in roles: v_obj.satisfy_exact(f"role = {role}") # satisfy specific actions in the API for caveat in caveats: v_obj.satisfy_exact(f"action = {caveat}") # satify same origin restrictions v_obj.satisfy_exact(f"origin = {req.headers['origin']}") # satisfy macaroon with time expiry v_obj.satisfy_general(lambda x: x.split(" = ")[0] == "expiry" and int( x.split(" = ")[1]) > time()) # satisfy macaroon with limited uses v_obj.satisfy_general(lambda x: x.split(" = ")[0] == "uses" and int( x.split(" = ")[1]) > used) # satisfy any with 'amount' caveat. Currently only included so macaroon user can tell amount v_obj.satisfy_general(lambda x: x.split(" = ")[0] == "amount") return bool(v_obj.verify(macaroon, key))
def verifyMacaroon(self, macaroon, context, require_context=True, errors=None, **kwargs): """See `IMacaroonIssuer`.""" if macaroon.location != config.vhost.mainsite.hostname: if errors is not None: errors.append("Macaroon has unknown location '%s'." % macaroon.location) return None if require_context and context is None: if errors is not None: errors.append( "Expected macaroon verification context but got None.") return None if context is not None: try: context = self.checkVerificationContext(context) except BadMacaroonContext as e: if errors is not None: errors.append(str(e)) return None seen = set() verified = MacaroonVerificationResult(self.identifier) def verify(caveat): try: caveat_name, caveat_value = caveat.split(" ", 1) except ValueError: if errors is not None: errors.append("Cannot parse caveat '%s'." % caveat) return False if caveat_name not in self.allow_multiple and caveat_name in seen: if errors is not None: errors.append("Multiple '%s' caveats are not allowed." % caveat_name) return False seen.add(caveat_name) if caveat_name == self._primary_caveat_name: checker = self.verifyPrimaryCaveat else: checker = self.checkers.get(caveat_name) if checker is None: if errors is not None: errors.append("Unhandled caveat name '%s'." % caveat_name) return False if not checker(caveat_value, context, **kwargs): if errors is not None: errors.append("Caveat check for '%s' failed." % caveat) return False return True try: verifier = Verifier() verifier.satisfy_general(verify) if verifier.verify(macaroon, self._root_secret): return verified else: return None # XXX cjwatson 2019-04-24: This can currently raise a number of # other exceptions in the presence of non-well-formed input data, # but most of them are too broad to reasonably catch so we let them # turn into OOPSes for now. Revisit this once # https://github.com/ecordell/pymacaroons/issues/51 is fixed. except MacaroonVerificationFailedException as e: if errors is not None and not errors: errors.append(str(e)) return None