Example #1
0
 def test_operations_checker(self):
     tests = [
         ('all allowed', checkers.allow_caveat(['op1', 'op2', 'op4', 'op3'
                                                ]), ['op1', 'op3',
                                                     'op2'], None),
         ('none denied', checkers.deny_caveat(['op1',
                                               'op2']), ['op3',
                                                         'op4'], None),
         ('one not allowed', checkers.allow_caveat(['op1',
                                                    'op2']), ['op1', 'op3'],
          'caveat "allow op1 op2" not satisfied: op3 not allowed'),
         ('one not denied', checkers.deny_caveat(['op1', 'op2']),
          ['op4', 'op5',
           'op2'], 'caveat "deny op1 op2" not satisfied: op2 not allowed'),
         ('no operations, allow caveat', checkers.allow_caveat(['op1']), [],
          'caveat "allow op1" not satisfied: op1 not allowed'),
         ('no operations, deny caveat', checkers.deny_caveat(['op1']), [],
          None),
         ('no operations, empty allow caveat',
          checkers.Caveat(condition=checkers.COND_ALLOW), [],
          'caveat "allow" not satisfied: no operations allowed'),
     ]
     checker = checkers.Checker()
     for test in tests:
         print(test[0])
         ctx = checkers.context_with_operations(checkers.AuthContext(),
                                                test[2])
         err = checker.check_first_party_caveat(ctx, test[1].condition)
         if test[3] is None:
             self.assertIsNone(err)
             continue
         self.assertEqual(err, test[3])
Example #2
0
    def __init__(self,
                 location=None,
                 locator=None,
                 ops_store=None,
                 key=None,
                 identity_client=None,
                 checker=None,
                 root_key_store=None,
                 authorizer=ClosedAuthorizer()):
        '''Returns a new Bakery instance which combines an Oven with a
        Checker for the convenience of callers that wish to use both
        together.
        @param checker holds the checker used to check first party caveats.
        If this is None, it will use checkers.Checker(None).
        @param root_key_store holds the root key store to use.
        If you need to use a different root key store for different operations,
        you'll need to pass a root_key_store_for_ops value to Oven directly.
        @param root_key_store If this is None, it will use MemoryKeyStore().
        Note that that is almost certain insufficient for production services
        that are spread across multiple instances or that need
        to persist keys across restarts.
        @param locator is used to find out information on third parties when
        adding third party caveats. If this is None, no non-local third
        party caveats can be added.
        @param key holds the private key of the oven. If this is None,
        no third party caveats may be added.
        @param identity_client holds the identity implementation to use for
        authentication. If this is None, no authentication will be possible.
        @param authorizer is used to check whether an authenticated user is
        allowed to perform operations. If it is None, it will use
        a ClosedAuthorizer.
        The identity parameter passed to authorizer.allow will
        always have been obtained from a call to
        IdentityClient.declared_identity.
        @param ops_store used to persistently store the association of
        multi-op entities with their associated operations
        when oven.macaroon is called with multiple operations.
        @param location holds the location to use when creating new macaroons.
        '''

        if checker is None:
            checker = checkers.Checker()
        root_keystore_for_ops = None
        if root_key_store is not None:

            def root_keystore_for_ops(ops):
                return root_key_store

        oven = Oven(key=key,
                    location=location,
                    locator=locator,
                    namespace=checker.namespace(),
                    root_keystore_for_ops=root_keystore_for_ops,
                    ops_store=ops_store)
        self._oven = oven

        self._checker = Checker(checker=checker,
                                authorizer=authorizer,
                                identity_client=identity_client,
                                macaroon_opstore=oven)
Example #3
0
 def __init__(self, key=None, location=None, locator=None, namespace=None,
              root_keystore_for_ops=None, ops_store=None):
     '''
     @param namespace holds the namespace to use when adding first party
     caveats.
     @param root_keystore_for_ops a function that will give the macaroon
     storage to be used for root keys associated with macaroons created
     with macaroon.
     @param ops_store object is used to persistently store the association
     of multi-op entities with their associated operations when macaroon is
     called with multiple operations.
     When this is in use, operation entities with the prefix "multi-" are
     reserved - a "multi-"-prefixed entity represents a set of operations
     stored in the OpsStore.
     @param key holds the private nacl key pair used to encrypt third party
     caveats. If it is None, no third party caveats can be created.
     @param location string holds the location that will be associated with
     new macaroons (as returned by Macaroon.Location).
     @param locator is used to find out information on third parties when
     adding third party caveats. If this is None, no non-local third
     party caveats can be added.
     '''
     self.key = key
     self.location = location
     self.locator = locator
     if namespace is None:
         namespace = checkers.Checker().namespace()
     self.namespace = namespace
     self.ops_store = ops_store
     self.root_keystore_for_ops = root_keystore_for_ops
     if root_keystore_for_ops is None:
         my_store = MemoryKeyStore()
         self.root_keystore_for_ops = lambda x: my_store
Example #4
0
 def test_register_no_registered_ns_exception(self):
     checker = checkers.Checker()
     with self.assertRaises(checkers.RegisterError) as ctx:
         checker.register('x', 'testns', lambda x: None)
     self.assertEqual(
         ctx.exception.args[0],
         'no prefix registered for namespace testns when '
         'registering condition x')
Example #5
0
 def test_register_none_func_raise_exception(self):
     checker = checkers.Checker()
     with self.assertRaises(checkers.RegisterError) as ctx:
         checker.register('x', checkers.STD_NAMESPACE, None)
     self.assertEqual(
         ctx.exception.args[0],
         'no check function registered for namespace std when '
         'registering condition x')
Example #6
0
 def test_register_empty_prefix_condition_with_colon(self):
     checker = checkers.Checker()
     checker.namespace().register('testns', '')
     with self.assertRaises(checkers.RegisterError) as ctx:
         checker.register('x:y', 'testns', lambda x: None)
     self.assertEqual(
         ctx.exception.args[0],
         'caveat condition x:y in namespace testns contains a '
         'colon but its prefix is empty')
Example #7
0
 def test_register_twice_same_namespace(self):
     checker = checkers.Checker()
     checker.namespace().register('testns', '')
     checker.register('x', 'testns', lambda x: None)
     with self.assertRaises(checkers.RegisterError) as ctx:
         checker.register('x', 'testns', lambda x: None)
     self.assertEqual(
         ctx.exception.args[0],
         'checker for x (namespace testns) already registered'
         ' in namespace testns')
Example #8
0
    def test_checker_info(self):
        checker = checkers.Checker(include_std_checkers=False)
        checker.namespace().register('one', 't')
        checker.namespace().register('two', 't')
        checker.namespace().register('three', '')
        checker.namespace().register('four', 's')

        class Called(object):
            val = ''

        def register(name, ns):
            def func(ctx, cond, arg):
                Called.val = name + ' ' + ns
                return None

            checker.register(name, ns, func)

        register('x', 'one')
        register('y', 'one')
        register('z', 'two')
        register('a', 'two')
        register('something', 'three')
        register('other', 'three')
        register('xxx', 'four')

        expect = [
            checkers.CheckerInfo(ns='four', name='xxx', prefix='s'),
            checkers.CheckerInfo(ns='one', name='x', prefix='t'),
            checkers.CheckerInfo(ns='one', name='y', prefix='t'),
            checkers.CheckerInfo(ns='three', name='other', prefix=''),
            checkers.CheckerInfo(ns='three', name='something', prefix=''),
            checkers.CheckerInfo(ns='two', name='a', prefix='t'),
            checkers.CheckerInfo(ns='two', name='z', prefix='t'),
        ]
        infos = checker.info()
        self.assertEqual(len(infos), len(expect))
        new_infos = []
        for i, info in enumerate(infos):
            Called.val = ''
            info.check(None, '', '')
            self.assertEqual(Called.val, expect[i].name + ' ' + expect[i].ns)
            new_infos.append(
                checkers.CheckerInfo(ns=info.ns,
                                     name=info.name,
                                     prefix=info.prefix))
        self.assertEqual(new_infos, expect)
def new_bakery(location, locator, checker):
    '''Return a new bakery instance.
    @param location Location of the bakery {str}.
    @param locator Locator for third parties {ThirdPartyLocator or None}
    @param checker Caveat checker {FirstPartyCaveatChecker or None}
    @return {Bakery}
    '''
    if checker is None:
        c = checkers.Checker()
        c.namespace().register('testns', '')
        c.register('is', 'testns', check_is_something)
        checker = c
    key = bakery.generate_key()
    return bakery.Bakery(
        location=location,
        locator=locator,
        key=key,
        checker=checker,
    )
 def __init__(self, checker=checkers.Checker(),
              authorizer=macaroonbakery.ClosedAuthorizer(),
              identity_client=None,
              macaroon_opstore=None):
     '''
     :param checker: a first party checker implementing a
     :param authorizer (Authorizer): used to check whether an authenticated
     user is allowed to perform operations.
     The identity parameter passed to authorizer.allow will always have been
     obtained from a call to identity_client.declared_identity.
     :param identity_client (IdentityClient) used for interactions with the
     external identity service used for authentication.
     If this is None, no authentication will be possible.
     :param macaroon_opstore (object with new_macaroon and macaroon_ops
     method): used to retrieve macaroon root keys and other associated
     information.
     '''
     self._first_party_caveat_checker = checker
     self._authorizer = authorizer
     if identity_client is None:
         identity_client = macaroonbakery.NoIdentities()
     self._identity_client = identity_client
     self._macaroon_opstore = macaroon_opstore
Example #11
0
def test_checker():
    c = checkers.Checker()
    c.namespace().register('testns', '')
    c.register('str', 'testns', str_check)
    c.register('true', 'testns', true_check)
    return c
Example #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)