Exemplo n.º 1
0
    def macaroon(self, version, expiry, caveats, ops):
        ''' Takes a macaroon with the given version from the oven,
        associates it with the given operations and attaches the given caveats.
        There must be at least one operation specified.
        The macaroon will expire at the given time - a time_before first party
        caveat will be added with that time.

        @return: a new Macaroon object.
        '''
        if len(ops) == 0:
            raise ValueError('cannot mint a macaroon associated '
                             'with no operations')

        ops = canonical_ops(ops)
        root_key, storage_id = self.root_keystore_for_ops(ops).root_key()

        id = self._new_macaroon_id(storage_id, expiry, ops)

        id_bytes = six.int2byte(macaroonbakery.LATEST_BAKERY_VERSION) + \
            id.SerializeToString()

        if macaroonbakery.macaroon_version(version) < MACAROON_V2:
            # The old macaroon format required valid text for the macaroon id,
            # so base64-encode it.
            id_bytes = utils.raw_urlsafe_b64encode(id_bytes)

        m = macaroonbakery.Macaroon(root_key, id_bytes, self.location, version,
                                    self.namespace)
        m.add_caveat(checkers.time_before_caveat(expiry), self.key,
                     self.locator)
        m.add_caveats(caveats, self.key, self.locator)
        return m
Exemplo n.º 2
0
 def test_expire_time(self):
     ExpireTest = namedtuple('ExpireTest', 'about caveats expectTime')
     tests = [
         ExpireTest(
             about='no caveats',
             caveats=[],
             expectTime=None,
         ),
         ExpireTest(
             about='single time-before caveat',
             caveats=[
                 fpcaveat(checkers.time_before_caveat(t1).condition),
             ],
             expectTime=t1,
         ),
         ExpireTest(
             about='multiple time-before caveat',
             caveats=[
                 fpcaveat(checkers.time_before_caveat(t2).condition),
                 fpcaveat(checkers.time_before_caveat(t1).condition),
             ],
             expectTime=t1,
         ),
         ExpireTest(
             about='mixed caveats',
             caveats=[
                 fpcaveat(checkers.time_before_caveat(t1).condition),
                 fpcaveat('allow bar'),
                 fpcaveat(checkers.time_before_caveat(t2).condition),
                 fpcaveat('deny foo'),
             ],
             expectTime=t1,
         ),
         ExpireTest(
             about='mixed caveats',
             caveats=[
                 fpcaveat(checkers.COND_TIME_BEFORE + ' tomorrow'),
             ],
             expectTime=None,
         ),
     ]
     for test in tests:
         print('test ', test.about)
         t = checkers.expiry_time(checkers.Namespace(), test.caveats)
         self.assertEqual(t, test.expectTime)
Exemplo n.º 3
0
 def test_expire_time(self):
     ExpireTest = namedtuple('ExpireTest', 'about caveats expectTime')
     tests = [
         ExpireTest(
             about='no caveats',
             caveats=[],
             expectTime=None,
         ),
         ExpireTest(
             about='single time-before caveat',
             caveats=[
                 fpcaveat(checkers.time_before_caveat(t1).condition),
             ],
             expectTime=t1,
         ),
         ExpireTest(
             about='multiple time-before caveat',
             caveats=[
                 fpcaveat(checkers.time_before_caveat(t2).condition),
                 fpcaveat(checkers.time_before_caveat(t1).condition),
             ],
             expectTime=t1,
         ),
         ExpireTest(
             about='mixed caveats',
             caveats=[
                 fpcaveat(checkers.time_before_caveat(t1).condition),
                 fpcaveat('allow bar'),
                 fpcaveat(checkers.time_before_caveat(t2).condition),
                 fpcaveat('deny foo'),
             ],
             expectTime=t1,
         ),
         ExpireTest(
             about='mixed caveats',
             caveats=[
                 fpcaveat(checkers.COND_TIME_BEFORE + ' tomorrow'),
             ],
             expectTime=None,
         ),
     ]
     for test in tests:
         print('test ', test.about)
         t = checkers.expiry_time(checkers.Namespace(), test.caveats)
         self.assertEqual(t, test.expectTime)
Exemplo n.º 4
0
 def test_macaroons_expire_time(self):
     ExpireTest = namedtuple('ExpireTest', 'about macaroons expectTime')
     tests = [
         ExpireTest(
             about='no macaroons',
             macaroons=[newMacaroon()],
             expectTime=None,
         ),
         ExpireTest(
             about='single macaroon without caveats',
             macaroons=[newMacaroon()],
             expectTime=None,
         ),
         ExpireTest(
             about='multiple macaroon without caveats',
             macaroons=[newMacaroon()],
             expectTime=None,
         ),
         ExpireTest(
             about='single macaroon with time-before caveat',
             macaroons=[
                 newMacaroon([checkers.time_before_caveat(t1).condition]),
             ],
             expectTime=t1,
         ),
         ExpireTest(
             about='single macaroon with multiple time-before caveats',
             macaroons=[
                 newMacaroon([
                     checkers.time_before_caveat(t2).condition,
                     checkers.time_before_caveat(t1).condition,
                 ]),
             ],
             expectTime=t1,
         ),
         ExpireTest(
             about='multiple macaroons with multiple time-before caveats',
             macaroons=[
                 newMacaroon([
                     checkers.time_before_caveat(t3).condition,
                     checkers.time_before_caveat(t1).condition,
                 ]),
                 newMacaroon([
                     checkers.time_before_caveat(t3).condition,
                     checkers.time_before_caveat(t1).condition,
                 ]),
             ],
             expectTime=t1,
         ),
     ]
     for test in tests:
         print('test ', test.about)
         t = checkers.macaroons_expiry_time(checkers.Namespace(),
                                            test.macaroons)
         self.assertEqual(t, test.expectTime)
Exemplo n.º 5
0
 def test_macaroons_expire_time(self):
     ExpireTest = namedtuple('ExpireTest', 'about macaroons expectTime')
     tests = [
         ExpireTest(
             about='no macaroons',
             macaroons=[newMacaroon()],
             expectTime=None,
         ),
         ExpireTest(
             about='single macaroon without caveats',
             macaroons=[newMacaroon()],
             expectTime=None,
         ),
         ExpireTest(
             about='multiple macaroon without caveats',
             macaroons=[newMacaroon()],
             expectTime=None,
         ),
         ExpireTest(
             about='single macaroon with time-before caveat',
             macaroons=[
                 newMacaroon([checkers.time_before_caveat(t1).condition]),
             ],
             expectTime=t1,
         ),
         ExpireTest(
             about='single macaroon with multiple time-before caveats',
             macaroons=[
                 newMacaroon([
                     checkers.time_before_caveat(t2).condition,
                     checkers.time_before_caveat(t1).condition,
                 ]),
             ],
             expectTime=t1,
         ),
         ExpireTest(
             about='multiple macaroons with multiple time-before caveats',
             macaroons=[
                 newMacaroon([
                     checkers.time_before_caveat(t3).condition,
                     checkers.time_before_caveat(t1).condition,
                 ]),
                 newMacaroon([
                     checkers.time_before_caveat(t3).condition,
                     checkers.time_before_caveat(t1).condition,
                 ]),
             ],
             expectTime=t1,
         ),
     ]
     for test in tests:
         print('test ', test.about)
         t = checkers.macaroons_expiry_time(checkers.Namespace(),
                                            test.macaroons)
         self.assertEqual(t, test.expectTime)
Exemplo n.º 6
0
    def macaroon(self, version, expiry, caveats, ops):
        ''' Takes a macaroon with the given version from the oven,
        associates it with the given operations and attaches the given caveats.
        There must be at least one operation specified.
        The macaroon will expire at the given time - a time_before first party
        caveat will be added with that time.

        @return: a new Macaroon object.
        '''
        if len(ops) == 0:
            raise ValueError('cannot mint a macaroon associated '
                             'with no operations')

        ops = canonical_ops(ops)
        root_key, storage_id = self.root_keystore_for_ops(ops).root_key()

        id = self._new_macaroon_id(storage_id, expiry, ops)

        id_bytes = six.int2byte(bakery.LATEST_VERSION) + \
            id.SerializeToString()

        if bakery.macaroon_version(version) < MACAROON_V2:
            # The old macaroon format required valid text for the macaroon id,
            # so base64-encode it.
            id_bytes = utils.raw_urlsafe_b64encode(id_bytes)

        m = bakery.Macaroon(
            root_key,
            id_bytes,
            self.location,
            version,
            self.namespace,
        )
        m.add_caveat(checkers.time_before_caveat(expiry), self.key,
                     self.locator)
        m.add_caveats(caveats, self.key, self.locator)
        return m
 def final(self):
     if self._expiry is not None:
         self._conds.append(
             checkers.time_before_caveat(self._expiry).condition)
     # Make deterministic and eliminate duplicates.
     return sorted(set(self._conds))
 def final(self):
     if self._expiry is not None:
         self._conds.append(
             checkers.time_before_caveat(self._expiry).condition)
     # Make deterministic and eliminate duplicates.
     return sorted(set(self._conds))
    def test_first_party_caveat_squashing(self):
        locator = _DischargerLocator()
        ids = _IdService('ids', locator, self)
        auth = _OpAuthorizer({
            bakery.Op(entity='e1', action='read'): {'alice'},
            bakery.Op(entity='e2', action='read'): {'alice'},
        })
        ts = _Service('myservice', auth, ids, locator)
        tests = [
            ('duplicates removed', [
                checkers.Caveat(condition='true 1', namespace='testns'),
                checkers.Caveat(condition='true 2', namespace='testns'),
                checkers.Caveat(condition='true 1', namespace='testns'),
                checkers.Caveat(condition='true 1', namespace='testns'),
                checkers.Caveat(condition='true 3', namespace='testns'),
            ], [
                checkers.Caveat(condition='true 1', namespace='testns'),
                checkers.Caveat(condition='true 2', namespace='testns'),
                checkers.Caveat(condition='true 3', namespace='testns'),
            ]), ('earliest time before', [
                checkers.time_before_caveat(epoch + timedelta(days=1)),
                checkers.Caveat(condition='true 1', namespace='testns'),
                checkers.time_before_caveat(
                    epoch + timedelta(days=0, hours=1)),
                checkers.time_before_caveat(epoch + timedelta(
                    days=0, hours=0, minutes=5)),
            ], [
                checkers.time_before_caveat(epoch + timedelta(
                    days=0, hours=0, minutes=5)),
                checkers.Caveat(condition='true 1', namespace='testns'),
            ]), ('operations and declared caveats removed', [
                checkers.deny_caveat(['foo']),
                checkers.allow_caveat(['read', 'write']),
                checkers.declared_caveat('username', 'bob'),
                checkers.Caveat(condition='true 1', namespace='testns'),
            ], [
                checkers.Caveat(condition='true 1', namespace='testns'),
            ])
        ]
        for test in tests:
            print(test[0])

            # Make a first macaroon with all the required first party caveats.
            ctx = test_context.with_value(_DISCHARGE_USER_KEY, 'alice')
            m1 = _Client(locator).capability(
                ctx, ts, [bakery.Op(entity='e1', action='read')])
            m1.add_caveats(test[1], None, None)

            # Make a second macaroon that's not used to check that it's
            # caveats are not added.
            m2 = _Client(locator).capability(
                ctx, ts, [bakery.Op(entity='e1', action='read')])
            m2.add_caveat(checkers.Caveat(
                condition='true notused', namespace='testns'), None, None)
            client = _Client(locator)
            client.add_macaroon(ts, 'authz1', [m1.macaroon])
            client.add_macaroon(ts, 'authz2', [m2.macaroon])

            m3 = client.capability(
                test_context, ts, [bakery.Op(entity='e1', action='read')])
            self.assertEqual(
                _macaroon_conditions(m3.macaroon.caveats, False),
                _resolve_caveats(m3.namespace, test[2]))
    def test_first_party_caveat_squashing(self):
        locator = _DischargerLocator()
        ids = _IdService('ids', locator, self)
        auth = _OpAuthorizer({
            macaroonbakery.Op(entity='e1', action='read'): {'alice'},
            macaroonbakery.Op(entity='e2', action='read'): {'alice'},
        })
        ts = _Service('myservice', auth, ids, locator)
        tests = [('duplicates removed', [
            checkers.Caveat(condition='true 1', namespace='testns'),
            checkers.Caveat(condition='true 2', namespace='testns'),
            checkers.Caveat(condition='true 1', namespace='testns'),
            checkers.Caveat(condition='true 1', namespace='testns'),
            checkers.Caveat(condition='true 3', namespace='testns'),
        ], [
            checkers.Caveat(condition='true 1', namespace='testns'),
            checkers.Caveat(condition='true 2', namespace='testns'),
            checkers.Caveat(condition='true 3', namespace='testns'),
        ]),
                 ('earliest time before', [
                     checkers.time_before_caveat(epoch + timedelta(days=1)),
                     checkers.Caveat(condition='true 1', namespace='testns'),
                     checkers.time_before_caveat(epoch +
                                                 timedelta(days=0, hours=1)),
                     checkers.time_before_caveat(
                         epoch + timedelta(days=0, hours=0, minutes=5)),
                 ], [
                     checkers.time_before_caveat(
                         epoch + timedelta(days=0, hours=0, minutes=5)),
                     checkers.Caveat(condition='true 1', namespace='testns'),
                 ]),
                 ('operations and declared caveats removed', [
                     checkers.deny_caveat(['foo']),
                     checkers.allow_caveat(['read', 'write']),
                     checkers.declared_caveat('username', 'bob'),
                     checkers.Caveat(condition='true 1', namespace='testns'),
                 ], [
                     checkers.Caveat(condition='true 1', namespace='testns'),
                 ])]
        for test in tests:
            print(test[0])

            # Make a first macaroon with all the required first party caveats.
            ctx = test_context.with_value(_DISCHARGE_USER_KEY, 'alice')
            m1 = _Client(locator).capability(
                ctx, ts, [macaroonbakery.Op(entity='e1', action='read')])
            m1.add_caveats(test[1], None, None)

            # Make a second macaroon that's not used to check that it's
            # caveats are not added.
            m2 = _Client(locator).capability(
                ctx, ts, [macaroonbakery.Op(entity='e1', action='read')])
            m2.add_caveat(
                checkers.Caveat(condition='true notused', namespace='testns'),
                None, None)
            client = _Client(locator)
            client.add_macaroon(ts, 'authz1', [m1.macaroon])
            client.add_macaroon(ts, 'authz2', [m2.macaroon])

            m3 = client.capability(
                test_context, ts,
                [macaroonbakery.Op(entity='e1', action='read')])
            self.assertEqual(_macaroon_conditions(m3.macaroon.caveats, False),
                             _resolve_caveats(m3.namespace, test[2]))
    def test_checkers(self):

        tests = [
            ('nothing in context, no extra checkers', [
                ('something',
                 'caveat "something" not satisfied: caveat not recognized'),
                ('', 'cannot parse caveat "": empty caveat'),
                (' hello', 'cannot parse caveat " hello": caveat starts with'
                           ' space character'),
            ], None),
            ('one failed caveat', [
                ('t:a aval', None),
                ('t:b bval', None),
                ('t:a wrong', 'caveat "t:a wrong" not satisfied: wrong arg'),
            ], None),
            ('time from clock', [
                (checkers.time_before_caveat(
                    datetime.utcnow() +
                    timedelta(0, 1)).condition,
                 None),
                (checkers.time_before_caveat(NOW).condition,
                 'caveat "time-before 2006-01-02T15:04:05.000123Z" '
                 'not satisfied: macaroon has expired'),
                (checkers.time_before_caveat(NOW - timedelta(0, 1)).condition,
                 'caveat "time-before 2006-01-02T15:04:04.000123Z" '
                 'not satisfied: macaroon has expired'),
                ('time-before bad-date',
                 'caveat "time-before bad-date" not satisfied: '
                 'cannot parse "bad-date" as RFC 3339'),
                (checkers.time_before_caveat(NOW).condition + " ",
                 'caveat "time-before 2006-01-02T15:04:05.000123Z " '
                 'not satisfied: '
                 'cannot parse "2006-01-02T15:04:05.000123Z " as RFC 3339'),
            ], lambda x: checkers.context_with_clock(ctx, TestClock())),
            ('real time', [
                (checkers.time_before_caveat(datetime(
                    year=2010, month=1, day=1)).condition,
                 'caveat "time-before 2010-01-01T00:00:00.000000Z" not '
                 'satisfied: macaroon has expired'),
                (checkers.time_before_caveat(datetime(
                    year=3000, month=1, day=1)).condition, None),
            ], None),
            ('declared, no entries', [
                (checkers.declared_caveat('a', 'aval').condition,
                 'caveat "declared a aval" not satisfied: got a=null, '
                 'expected "aval"'),
                (checkers.COND_DECLARED, 'caveat "declared" not satisfied: '
                                         'declared caveat has no value'),
            ], None),
            ('declared, some entries', [
                (checkers.declared_caveat('a', 'aval').condition, None),
                (checkers.declared_caveat('b', 'bval').condition, None),
                (checkers.declared_caveat('spc', ' a b').condition, None),
                (checkers.declared_caveat('a', 'bval').condition,
                 'caveat "declared a bval" not satisfied: '
                 'got a="aval", expected "bval"'),
                (checkers.declared_caveat('a', ' aval').condition,
                 'caveat "declared a  aval" not satisfied: '
                 'got a="aval", expected " aval"'),
                (checkers.declared_caveat('spc', 'a b').condition,
                 'caveat "declared spc a b" not satisfied: '
                 'got spc=" a b", expected "a b"'),
                (checkers.declared_caveat('', 'a b').condition,
                 'caveat "error invalid caveat \'declared\' key """ '
                 'not satisfied: bad caveat'),
                (checkers.declared_caveat('a b', 'a b').condition,
                 'caveat "error invalid caveat \'declared\' key "a b"" '
                 'not satisfied: bad caveat'),
            ], lambda x: checkers.context_with_declared(x, {
                'a': 'aval',
                'b': 'bval',
                'spc': ' a b'})),
        ]
        checker = checkers.Checker()
        checker.namespace().register('testns', 't')
        checker.register('a', 'testns', arg_checker(self, 't:a', 'aval'))
        checker.register('b', 'testns', arg_checker(self, 't:b', 'bval'))
        ctx = checkers.AuthContext()
        for test in tests:
            print(test[0])
            if test[2] is not None:
                ctx1 = test[2](ctx)
            else:
                ctx1 = ctx
            for check in test[1]:
                err = checker.check_first_party_caveat(ctx1, check[0])
                if check[1] is not None:
                    self.assertEqual(err, check[1])
                else:
                    self.assertIsNone(err)
Exemplo n.º 12
0
    def test_checkers(self):

        tests = [
            ('nothing in context, no extra checkers', [
                ('something',
                 'caveat "something" not satisfied: caveat not recognized'),
                ('', 'cannot parse caveat "": empty caveat'),
                (' hello', 'cannot parse caveat " hello": caveat starts with'
                 ' space character'),
            ], None),
            ('one failed caveat', [
                ('t:a aval', None),
                ('t:b bval', None),
                ('t:a wrong', 'caveat "t:a wrong" not satisfied: wrong arg'),
            ], None),
            ('time from clock', [
                (checkers.time_before_caveat(datetime.utcnow() +
                                             timedelta(0, 1)).condition, None),
                (checkers.time_before_caveat(NOW).condition,
                 'caveat "time-before 2006-01-02T15:04:05.000123Z" '
                 'not satisfied: macaroon has expired'),
                (checkers.time_before_caveat(NOW - timedelta(0, 1)).condition,
                 'caveat "time-before 2006-01-02T15:04:04.000123Z" '
                 'not satisfied: macaroon has expired'),
                ('time-before bad-date',
                 'caveat "time-before bad-date" not satisfied: '
                 'cannot parse "bad-date" as RFC 3339'),
                (checkers.time_before_caveat(NOW).condition + " ",
                 'caveat "time-before 2006-01-02T15:04:05.000123Z " '
                 'not satisfied: '
                 'cannot parse "2006-01-02T15:04:05.000123Z " as RFC 3339'),
            ], lambda x: checkers.context_with_clock(ctx, TestClock())),
            ('real time', [
                (checkers.time_before_caveat(
                    datetime(year=2010, month=1, day=1)).condition,
                 'caveat "time-before 2010-01-01T00:00:00.000000Z" not '
                 'satisfied: macaroon has expired'),
                (checkers.time_before_caveat(
                    datetime(year=3000, month=1, day=1)).condition, None),
            ], None),
            ('declared, no entries', [
                (checkers.declared_caveat('a', 'aval').condition,
                 'caveat "declared a aval" not satisfied: got a=null, '
                 'expected "aval"'),
                (checkers.COND_DECLARED, 'caveat "declared" not satisfied: '
                 'declared caveat has no value'),
            ], None),
            ('declared, some entries', [
                (checkers.declared_caveat('a', 'aval').condition, None),
                (checkers.declared_caveat('b', 'bval').condition, None),
                (checkers.declared_caveat('spc', ' a b').condition, None),
                (checkers.declared_caveat('a', 'bval').condition,
                 'caveat "declared a bval" not satisfied: '
                 'got a="aval", expected "bval"'),
                (checkers.declared_caveat('a', ' aval').condition,
                 'caveat "declared a  aval" not satisfied: '
                 'got a="aval", expected " aval"'),
                (checkers.declared_caveat('spc', 'a b').condition,
                 'caveat "declared spc a b" not satisfied: '
                 'got spc=" a b", expected "a b"'),
                (checkers.declared_caveat('', 'a b').condition,
                 'caveat "error invalid caveat \'declared\' key """ '
                 'not satisfied: bad caveat'),
                (checkers.declared_caveat('a b', 'a b').condition,
                 'caveat "error invalid caveat \'declared\' key "a b"" '
                 'not satisfied: bad caveat'),
            ],
             lambda x: checkers.context_with_declared(x, {
                 'a': 'aval',
                 'b': 'bval',
                 'spc': ' a b'
             })),
        ]
        checker = checkers.Checker()
        checker.namespace().register('testns', 't')
        checker.register('a', 'testns', arg_checker(self, 't:a', 'aval'))
        checker.register('b', 'testns', arg_checker(self, 't:b', 'bval'))
        ctx = checkers.AuthContext()
        for test in tests:
            print(test[0])
            if test[2] is not None:
                ctx1 = test[2](ctx)
            else:
                ctx1 = ctx
            for check in test[1]:
                err = checker.check_first_party_caveat(ctx1, check[0])
                if check[1] is not None:
                    self.assertEqual(err, check[1])
                else:
                    self.assertIsNone(err)
Exemplo n.º 13
0
 def test_macaroons_expire_time_skips_third_party(self):
     m1 = newMacaroon([checkers.time_before_caveat(t1).condition])
     m2 = newMacaroon()
     m2.add_third_party_caveat('https://example.com', 'a-key', '123')
     t = checkers.macaroons_expiry_time(checkers.Namespace(), [m1, m2])
     self.assertEqual(t1, t)
Exemplo n.º 14
0
 def test_macaroons_expire_time_skips_third_party(self):
     m1 = newMacaroon([checkers.time_before_caveat(t1).condition])
     m2 = newMacaroon()
     m2.add_third_party_caveat('https://example.com', 'a-key', '123')
     t = checkers.macaroons_expiry_time(checkers.Namespace(), [m1, m2])
     self.assertEqual(t1, t)