Пример #1
0
    def test_discharge_two_need_declared(self):
        locator = bakery.ThirdPartyStore()
        first_party = common.new_bakery('first', locator)
        third_party = common.new_bakery('third', locator)

        # first_party mints a macaroon with two third party caveats
        # with overlapping attributes.
        m = first_party.oven.macaroon(
            bakery.LATEST_VERSION,
            common.ages, [
                checkers.need_declared_caveat(
                    checkers.Caveat(location='third', condition='x'),
                    ['foo', 'bar']),
                checkers.need_declared_caveat(
                    checkers.Caveat(location='third', condition='y'),
                    ['bar', 'baz']),
            ], [bakery.LOGIN_OP])

        # The client asks for a discharge macaroon for each third party caveat.
        # Since no declarations are added by the discharger,

        def get_discharge(cav, payload):
            return bakery.discharge(
                common.test_context,
                cav.caveat_id_bytes,
                payload,
                third_party.oven.key,
                common.ThirdPartyCaveatCheckerEmpty(),
                third_party.oven.locator,
            )

        d = bakery.discharge_all(m, get_discharge)
        declared = checkers.infer_declared(d, first_party.checker.namespace())
        self.assertEqual(declared, {
            'foo': '',
            'bar': '',
            'baz': '',
        })
        ctx = checkers.context_with_declared(common.test_context, declared)
        first_party.checker.auth([d]).allow(ctx, [bakery.LOGIN_OP])

        # If they return conflicting values, the discharge fails.
        # The client asks for a discharge macaroon for each third party caveat.
        # Since no declarations are added by the discharger,
        class ThirdPartyCaveatCheckerF(bakery.ThirdPartyCaveatChecker):
            def check_third_party_caveat(self, ctx, cav_info):
                if cav_info.condition == b'x':
                    return [checkers.declared_caveat('foo', 'fooval1')]
                if cav_info.condition == b'y':
                    return [
                        checkers.declared_caveat('foo', 'fooval2'),
                        checkers.declared_caveat('baz', 'bazval')
                    ]
                raise common.ThirdPartyCaveatCheckFailed('not matched')

        def get_discharge(cav, payload):
            return bakery.discharge(
                common.test_context,
                cav.caveat_id_bytes,
                payload,
                third_party.oven.key,
                ThirdPartyCaveatCheckerF(),
                third_party.oven.locator,
            )

        d = bakery.discharge_all(m, get_discharge)

        declared = checkers.infer_declared(d, first_party.checker.namespace())
        self.assertEqual(declared, {
            'bar': '',
            'baz': 'bazval',
        })
        with self.assertRaises(bakery.AuthInitError) as exc:
            first_party.checker.auth([d]).allow(common.test_context,
                                                bakery.LOGIN_OP)
        self.assertEqual('cannot authorize login macaroon: caveat "declared '
                         'foo fooval1" not satisfied: got foo=null, expected '
                         '"fooval1"', exc.exception.args[0])
 def test_infer_declared(self):
     tests = [
         ('no macaroons', [], {}, None),
         ('single macaroon with one declaration', [
             [checkers.Caveat(condition='declared foo bar')]
         ], {'foo': 'bar'}, None),
         ('only one argument to declared', [
             [checkers.Caveat(condition='declared foo')]
         ], {}, None),
         ('spaces in value', [
             [checkers.Caveat(condition='declared foo bar bloggs')]
         ], {'foo': 'bar bloggs'}, None),
         ('attribute with declared prefix', [
             [checkers.Caveat(condition='declaredccf foo')]
         ], {}, None),
         ('several macaroons with different declares', [
             [
                 checkers.declared_caveat('a', 'aval'),
                 checkers.declared_caveat('b', 'bval')
             ], [
                 checkers.declared_caveat('c', 'cval'),
                 checkers.declared_caveat('d', 'dval')
             ]
         ], {'a': 'aval', 'b': 'bval', 'c': 'cval', 'd': 'dval'}, None),
         ('duplicate values', [
             [
                 checkers.declared_caveat('a', 'aval'),
                 checkers.declared_caveat('a', 'aval'),
                 checkers.declared_caveat('b', 'bval')
             ], [
                 checkers.declared_caveat('a', 'aval'),
                 checkers.declared_caveat('b', 'bval'),
                 checkers.declared_caveat('c', 'cval'),
                 checkers.declared_caveat('d', 'dval')
             ]
         ], {'a': 'aval', 'b': 'bval', 'c': 'cval', 'd': 'dval'}, None),
         ('conflicting values', [
             [
                 checkers.declared_caveat('a', 'aval'),
                 checkers.declared_caveat('a', 'conflict'),
                 checkers.declared_caveat('b', 'bval')
             ], [
                 checkers.declared_caveat('a', 'conflict'),
                 checkers.declared_caveat('b', 'another conflict'),
                 checkers.declared_caveat('c', 'cval'),
                 checkers.declared_caveat('d', 'dval')
             ]
         ], {'c': 'cval', 'd': 'dval'}, None),
         ('third party caveats ignored', [
             [checkers.Caveat(condition='declared a no conflict',
                              location='location')],
             [checkers.declared_caveat('a', 'aval')]
         ], {'a': 'aval'}, None),
         ('unparseable caveats ignored', [
             [checkers.Caveat(condition=' bad')],
             [checkers.declared_caveat('a', 'aval')]
         ], {'a': 'aval'}, None),
         ('infer with namespace', [
             [
                 checkers.declared_caveat('a', 'aval'),
                 caveat_with_ns(checkers.declared_caveat('a', 'aval'),
                                'testns'),
             ]
         ], {'a': 'aval'}, None),
     ]
     for test in tests:
         uri_to_prefix = test[3]
         if uri_to_prefix is None:
             uri_to_prefix = {checkers.STD_NAMESPACE: ''}
         ns = checkers.Namespace(uri_to_prefix)
         print(test[0])
         ms = []
         for i, caveats in enumerate(test[1]):
             m = Macaroon(key=None, identifier=six.int2byte(i), location='',
                          version=MACAROON_V2)
             for cav in caveats:
                 cav = ns.resolve_caveat(cav)
                 if cav.location == '':
                     m.add_first_party_caveat(cav.condition)
                 else:
                     m.add_third_party_caveat(cav.location, None,
                                              cav.condition)
             ms.append(m)
         self.assertEqual(checkers.infer_declared(ms), test[2])
Пример #3
0
    def test_need_declared(self):
        locator = bakery.ThirdPartyStore()
        first_party = common.new_bakery('first', locator)
        third_party = common.new_bakery('third', locator)

        # firstParty mints a macaroon with a third-party caveat addressed
        # to thirdParty with a need-declared caveat.
        m = first_party.oven.macaroon(
            bakery.LATEST_VERSION, common.ages, [
                checkers.need_declared_caveat(
                    checkers.Caveat(location='third', condition='something'),
                    ['foo', 'bar']
                )
            ], [bakery.LOGIN_OP])

        # The client asks for a discharge macaroon for each third party caveat.
        def get_discharge(cav, payload):
            return bakery.discharge(
                common.test_context,
                cav.caveat_id_bytes,
                payload,
                third_party.oven.key,
                common.ThirdPartyStrcmpChecker('something'),
                third_party.oven.locator,
            )

        d = bakery.discharge_all(m, get_discharge)

        # The required declared attributes should have been added
        # to the discharge macaroons.
        declared = checkers.infer_declared(d, first_party.checker.namespace())
        self.assertEqual(declared, {
            'foo': '',
            'bar': '',
        })

        # Make sure the macaroons actually check out correctly
        # when provided with the declared checker.
        ctx = checkers.context_with_declared(common.test_context, declared)
        first_party.checker.auth([d]).allow(ctx, [bakery.LOGIN_OP])

        # Try again when the third party does add a required declaration.

        # The client asks for a discharge macaroon for each third party caveat.
        def get_discharge(cav, payload):
            checker = common.ThirdPartyCheckerWithCaveats([
                checkers.declared_caveat('foo', 'a'),
                checkers.declared_caveat('arble', 'b')
            ])
            return bakery.discharge(
                common.test_context,
                cav.caveat_id_bytes,
                payload,
                third_party.oven.key,
                checker,
                third_party.oven.locator,
            )

        d = bakery.discharge_all(m, get_discharge)

        # One attribute should have been added, the other was already there.
        declared = checkers.infer_declared(d, first_party.checker.namespace())
        self.assertEqual(declared, {
            'foo': 'a',
            'bar': '',
            'arble': 'b',
        })

        ctx = checkers.context_with_declared(common.test_context, declared)
        first_party.checker.auth([d]).allow(ctx, [bakery.LOGIN_OP])

        # Try again, but this time pretend a client is sneakily trying
        # to add another 'declared' attribute to alter the declarations.

        def get_discharge(cav, payload):
            checker = common.ThirdPartyCheckerWithCaveats([
                checkers.declared_caveat('foo', 'a'),
                checkers.declared_caveat('arble', 'b'),
            ])

            # Sneaky client adds a first party caveat.
            m = bakery.discharge(
                common.test_context, cav.caveat_id_bytes,
                payload,
                third_party.oven.key, checker,
                third_party.oven.locator,
            )
            m.add_caveat(checkers.declared_caveat('foo', 'c'), None, None)
            return m

        d = bakery.discharge_all(m, get_discharge)

        declared = checkers.infer_declared(d, first_party.checker.namespace())
        self.assertEqual(declared, {
            'bar': '',
            'arble': 'b',
        })

        with self.assertRaises(bakery.AuthInitError) as exc:
            first_party.checker.auth([d]).allow(common.test_context,
                                                bakery.LOGIN_OP)
        self.assertEqual('cannot authorize login macaroon: caveat '
                         '"declared foo a" not satisfied: got foo=null, '
                         'expected "a"', exc.exception.args[0])
Пример #4
0
 def test_infer_declared(self):
     tests = [
         ('no macaroons', [], {}, None),
         ('single macaroon with one declaration',
          [[checkers.Caveat(condition='declared foo bar')]], {
              'foo': 'bar'
          }, None),
         ('only one argument to declared',
          [[checkers.Caveat(condition='declared foo')]], {}, None),
         ('spaces in value',
          [[checkers.Caveat(condition='declared foo bar bloggs')]], {
              'foo': 'bar bloggs'
          }, None),
         ('attribute with declared prefix',
          [[checkers.Caveat(condition='declaredccf foo')]], {}, None),
         ('several macaroons with different declares',
          [[
              checkers.declared_caveat('a', 'aval'),
              checkers.declared_caveat('b', 'bval')
          ],
           [
               checkers.declared_caveat('c', 'cval'),
               checkers.declared_caveat('d', 'dval')
           ]], {
               'a': 'aval',
               'b': 'bval',
               'c': 'cval',
               'd': 'dval'
           }, None),
         ('duplicate values', [[
             checkers.declared_caveat('a', 'aval'),
             checkers.declared_caveat('a', 'aval'),
             checkers.declared_caveat('b', 'bval')
         ],
                               [
                                   checkers.declared_caveat('a', 'aval'),
                                   checkers.declared_caveat('b', 'bval'),
                                   checkers.declared_caveat('c', 'cval'),
                                   checkers.declared_caveat('d', 'dval')
                               ]], {
                                   'a': 'aval',
                                   'b': 'bval',
                                   'c': 'cval',
                                   'd': 'dval'
                               }, None),
         ('conflicting values',
          [[
              checkers.declared_caveat('a', 'aval'),
              checkers.declared_caveat('a', 'conflict'),
              checkers.declared_caveat('b', 'bval')
          ],
           [
               checkers.declared_caveat('a', 'conflict'),
               checkers.declared_caveat('b', 'another conflict'),
               checkers.declared_caveat('c', 'cval'),
               checkers.declared_caveat('d', 'dval')
           ]], {
               'c': 'cval',
               'd': 'dval'
           }, None),
         ('third party caveats ignored', [[
             checkers.Caveat(condition='declared a no conflict',
                             location='location')
         ], [checkers.declared_caveat('a', 'aval')]], {
             'a': 'aval'
         }, None),
         ('unparseable caveats ignored',
          [[checkers.Caveat(condition=' bad')],
           [checkers.declared_caveat('a', 'aval')]], {
               'a': 'aval'
           }, None),
         ('infer with namespace', [[
             checkers.declared_caveat('a', 'aval'),
             caveat_with_ns(checkers.declared_caveat('a', 'aval'),
                            'testns'),
         ]], {
             'a': 'aval'
         }, None),
     ]
     for test in tests:
         uri_to_prefix = test[3]
         if uri_to_prefix is None:
             uri_to_prefix = {checkers.STD_NAMESPACE: ''}
         ns = checkers.Namespace(uri_to_prefix)
         print(test[0])
         ms = []
         for i, caveats in enumerate(test[1]):
             m = Macaroon(key=None,
                          identifier=six.int2byte(i),
                          location='',
                          version=MACAROON_V2)
             for cav in caveats:
                 cav = ns.resolve_caveat(cav)
                 if cav.location == '':
                     m.add_first_party_caveat(cav.condition)
                 else:
                     m.add_third_party_caveat(cav.location, None,
                                              cav.condition)
             ms.append(m)
         self.assertEqual(checkers.infer_declared(ms), test[2])