def __init__(self, name, auth, idm, locator):
     self._name = name
     self._store = _MacaroonStore(macaroonbakery.generate_key(), locator)
     self._checker = macaroonbakery.Checker(checker=test_checker(),
                                            authorizer=auth,
                                            identity_client=idm,
                                            macaroon_opstore=self._store)
    def test_fallback(self):
        key = macaroonbakery.generate_key()

        @urlmatch(path='.*/discharge/info')
        def discharge_info(url, request):
            return {
                'status_code': 404,
            }

        @urlmatch(path='.*/publickey')
        def public_key(url, request):
            return {
                'status_code': 200,
                'content': {
                    'PublicKey': key.public_key.encode().decode('utf-8')
                }
            }

        expectInfo = macaroonbakery.ThirdPartyInfo(
            public_key=key.public_key, version=macaroonbakery.BAKERY_V1)
        kr = httpbakery.ThirdPartyLocator(allow_insecure=True)
        with HTTMock(discharge_info):
            with HTTMock(public_key):
                info = kr.third_party_info('http://0.1.2.3/')
        self.assertEqual(info, expectInfo)
 def __init__(self, name, auth, idm, locator):
     self._name = name
     self._store = _MacaroonStore(bakery.generate_key(), locator)
     self._checker = bakery.Checker(
         checker=test_checker(),
         authorizer=auth,
         identity_client=idm,
         macaroon_opstore=self._store)
 def test_discharge_all_local_discharge_version1(self):
     oc = common.new_bakery('ts', None)
     client_key = bakery.generate_key()
     m = oc.oven.macaroon(bakery.VERSION_1, common.ages, [
         bakery.local_third_party_caveat(client_key.public_key,
                                         bakery.VERSION_1)
     ], [bakery.LOGIN_OP])
     ms = bakery.discharge_all(m, no_discharge(self), client_key)
     oc.checker.auth([ms]).allow(common.test_context, [bakery.LOGIN_OP])
 def test_discharge_all_local_discharge_version1(self):
     oc = common.new_bakery('ts', None)
     client_key = bakery.generate_key()
     m = oc.oven.macaroon(bakery.VERSION_1, common.ages, [
         bakery.local_third_party_caveat(
             client_key.public_key, bakery.VERSION_1)
     ], [bakery.LOGIN_OP])
     ms = bakery.discharge_all(m, no_discharge(self), client_key)
     oc.checker.auth([ms]).allow(common.test_context,
                                 [bakery.LOGIN_OP])
 def test_discharge_all_local_discharge(self):
     oc = common.new_bakery('ts', None)
     client_key = macaroonbakery.generate_key()
     m = oc.oven.macaroon(macaroonbakery.LATEST_BAKERY_VERSION, common.ages,
                          [
                              macaroonbakery.local_third_party_caveat(
                                  client_key.public_key,
                                  macaroonbakery.LATEST_BAKERY_VERSION)
                          ], [macaroonbakery.LOGIN_OP])
     ms = macaroonbakery.discharge_all(common.test_context, m,
                                       no_discharge(self), client_key)
     oc.checker.auth([ms]).allow(common.test_context,
                                 [macaroonbakery.LOGIN_OP])
예제 #7
0
def new_bakery(location, locator=None):
    # Returns a new Bakery instance using a new
    # key pair, and registers the key with the given locator if provided.
    #
    # It uses test_checker to check first party caveats.
    key = bakery.generate_key()
    if locator is not None:
        locator.add_info(location,
                         bakery.ThirdPartyInfo(
                             public_key=key.public_key,
                             version=bakery.LATEST_VERSION))
    return bakery.Bakery(
        key=key,
        checker=test_checker(),
        location=location,
        identity_client=OneIdentity(),
        locator=locator,
    )
예제 #8
0
def new_bakery(location, locator=None):
    # Returns a new Bakery instance using a new
    # key pair, and registers the key with the given locator if provided.
    #
    # It uses test_checker to check first party caveats.
    key = bakery.generate_key()
    if locator is not None:
        locator.add_info(
            location,
            bakery.ThirdPartyInfo(public_key=key.public_key,
                                  version=bakery.LATEST_VERSION))
    return bakery.Bakery(
        key=key,
        checker=test_checker(),
        location=location,
        identity_client=OneIdentity(),
        locator=locator,
    )
예제 #9
0
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 test_auth_with_third_party_caveats(self):
        locator = _DischargerLocator()
        ids = _IdService('ids', locator, self)

        # We make an authorizer that requires a third party discharge
        # when authorizing.
        def authorize_with_tp_discharge(ctx, id, op):
            if (id is not None and id.id() == 'bob'
                    and op == macaroonbakery.Op(entity='something',
                                                action='read')):
                return True, [
                    checkers.Caveat(condition='question',
                                    location='other third party')
                ]
            return False, None

        auth = macaroonbakery.AuthorizerFunc(authorize_with_tp_discharge)
        ts = _Service('myservice', auth, ids, locator)

        class _LocalDischargeChecker(macaroonbakery.ThirdPartyCaveatChecker):
            def check_third_party_caveat(_, ctx, info):
                if info.condition != 'question':
                    raise ValueError('third party condition not recognized')
                self._discharges.append(
                    _DischargeRecord(location='other third party',
                                     user=ctx.get(_DISCHARGE_USER_KEY)))
                return []

        locator['other third party'] = _Discharger(
            key=macaroonbakery.generate_key(),
            checker=_LocalDischargeChecker(),
            locator=locator,
        )
        client = _Client(locator)
        ctx = test_context.with_value(_DISCHARGE_USER_KEY, 'bob')
        client.do(ctx, ts,
                  [macaroonbakery.Op(entity='something', action='read')])
        self.assertEqual(self._discharges, [
            _DischargeRecord(location='ids', user='******'),
            _DischargeRecord(location='other third party', user='******')
        ])
    def test_auth_with_third_party_caveats(self):
        locator = _DischargerLocator()
        ids = _IdService('ids', locator, self)

        # We make an authorizer that requires a third party discharge
        # when authorizing.
        def authorize_with_tp_discharge(ctx, id, op):
            if (id is not None and id.id() == 'bob' and
                    op == bakery.Op(entity='something', action='read')):
                return True, [checkers.Caveat(condition='question',
                                              location='other third party')]
            return False, None

        auth = bakery.AuthorizerFunc(authorize_with_tp_discharge)
        ts = _Service('myservice', auth, ids, locator)

        class _LocalDischargeChecker(bakery.ThirdPartyCaveatChecker):
            def check_third_party_caveat(_, ctx, info):
                if info.condition != 'question':
                    raise ValueError('third party condition not recognized')
                self._discharges.append(_DischargeRecord(
                    location='other third party',
                    user=ctx.get(_DISCHARGE_USER_KEY)
                ))
                return []

        locator['other third party'] = _Discharger(
            key=bakery.generate_key(),
            checker=_LocalDischargeChecker(),
            locator=locator,
        )
        client = _Client(locator)
        ctx = test_context.with_value(_DISCHARGE_USER_KEY, 'bob')
        client.do(ctx, ts, [bakery.Op(entity='something', action='read')])
        self.assertEqual(self._discharges, [
            _DischargeRecord(location='ids', user='******'),
            _DischargeRecord(location='other third party', user='******')
        ])
 def __init__(self, dischargers):
     self._key = bakery.generate_key()
     self._macaroons = {}
     self._dischargers = dischargers
예제 #13
0
 def setUp(self):
     self.fp_key = bakery.generate_key()
     self.tp_key = bakery.generate_key()
 def __init__(self, location, locator, test_class):
     self._location = location
     self._test = test_class
     key = bakery.generate_key()
     self._discharger = _Discharger(key=key, checker=self, locator=locator)
     locator[location] = self._discharger
예제 #15
0
    def test_agent_login(self):
        discharge_key = bakery.generate_key()

        class _DischargerLocator(bakery.ThirdPartyLocator):
            def third_party_info(self, loc):
                if loc == 'http://0.3.2.1':
                    return bakery.ThirdPartyInfo(
                        public_key=discharge_key.public_key,
                        version=bakery.LATEST_VERSION,
                    )

        d = _DischargerLocator()
        server_key = bakery.generate_key()
        server_bakery = bakery.Bakery(key=server_key, locator=d)

        @urlmatch(path='.*/here')
        def server_get(url, request):
            ctx = checkers.AuthContext()
            test_ops = [bakery.Op(entity='test-op', action='read')]
            auth_checker = server_bakery.checker.auth(
                httpbakery.extract_macaroons(request.headers))
            try:
                auth_checker.allow(ctx, test_ops)
                resp = response(status_code=200, content='done')
            except bakery.PermissionDenied:
                caveats = [
                    checkers.Caveat(location='http://0.3.2.1',
                                    condition='is-ok')
                ]
                m = server_bakery.oven.macaroon(version=bakery.LATEST_VERSION,
                                                expiry=datetime.utcnow() +
                                                timedelta(days=1),
                                                caveats=caveats,
                                                ops=test_ops)
                content, headers = httpbakery.discharge_required_response(
                    m, '/', 'test', 'message')
                resp = response(status_code=401,
                                content=content,
                                headers=headers)
            return request.hooks['response'][0](resp)

        @urlmatch(path='.*/discharge')
        def discharge(url, request):
            qs = parse_qs(request.body)
            if qs.get('token64') is None:
                return response(status_code=401,
                                content={
                                    'Code':
                                    httpbakery.ERR_INTERACTION_REQUIRED,
                                    'Message': 'interaction required',
                                    'Info': {
                                        'InteractionMethods': {
                                            'agent': {
                                                'login-url': '/login'
                                            },
                                        },
                                    },
                                },
                                headers={'Content-Type': 'application/json'})
            else:
                qs = parse_qs(request.body)
                content = {q: qs[q][0] for q in qs}
                m = httpbakery.discharge(checkers.AuthContext(), content,
                                         discharge_key, None, alwaysOK3rd)
                return {
                    'status_code': 200,
                    'content': {
                        'Macaroon': m.serialize_json()
                    }
                }

        key = bakery.generate_key()

        @urlmatch(path='.*/login')
        def login(url, request):
            b = bakery.Bakery(key=discharge_key)
            m = b.oven.macaroon(
                version=bakery.LATEST_VERSION,
                expiry=datetime.utcnow() + timedelta(days=1),
                caveats=[
                    bakery.local_third_party_caveat(
                        key.public_key,
                        version=httpbakery.request_version(request.headers))
                ],
                ops=[bakery.Op(entity='agent', action='login')])
            return {'status_code': 200, 'content': {'macaroon': m.to_dict()}}

        with HTTMock(server_get), \
                HTTMock(discharge), \
                HTTMock(login):
            client = httpbakery.Client(interaction_methods=[
                agent.AgentInteractor(
                    agent.AuthInfo(
                        key=key,
                        agents=[
                            agent.Agent(username='******',
                                        url=u'http://0.3.2.1')
                        ],
                    ), ),
            ])
            resp = requests.get('http://0.1.2.3/here',
                                cookies=client.cookies,
                                auth=client.auth())
        self.assertEquals(resp.content, b'done')
예제 #16
0
    def test_agent_legacy(self):
        discharge_key = bakery.generate_key()

        class _DischargerLocator(bakery.ThirdPartyLocator):
            def third_party_info(self, loc):
                if loc == 'http://0.3.2.1':
                    return bakery.ThirdPartyInfo(
                        public_key=discharge_key.public_key,
                        version=bakery.LATEST_VERSION,
                    )

        d = _DischargerLocator()
        server_key = bakery.generate_key()
        server_bakery = bakery.Bakery(key=server_key, locator=d)

        @urlmatch(path='.*/here')
        def server_get(url, request):
            ctx = checkers.AuthContext()
            test_ops = [bakery.Op(entity='test-op', action='read')]
            auth_checker = server_bakery.checker.auth(
                httpbakery.extract_macaroons(request.headers))
            try:
                auth_checker.allow(ctx, test_ops)
                resp = response(status_code=200, content='done')
            except bakery.PermissionDenied:
                caveats = [
                    checkers.Caveat(location='http://0.3.2.1',
                                    condition='is-ok')
                ]
                m = server_bakery.oven.macaroon(version=bakery.LATEST_VERSION,
                                                expiry=datetime.utcnow() +
                                                timedelta(days=1),
                                                caveats=caveats,
                                                ops=test_ops)
                content, headers = httpbakery.discharge_required_response(
                    m, '/', 'test', 'message')
                resp = response(
                    status_code=401,
                    content=content,
                    headers=headers,
                )
            return request.hooks['response'][0](resp)

        class InfoStorage:
            info = None

        @urlmatch(path='.*/discharge')
        def discharge(url, request):
            qs = parse_qs(request.body)
            if qs.get('caveat64') is not None:
                content = {q: qs[q][0] for q in qs}

                class InteractionRequiredError(Exception):
                    def __init__(self, error):
                        self.error = error

                class CheckerInError(bakery.ThirdPartyCaveatChecker):
                    def check_third_party_caveat(self, ctx, info):
                        InfoStorage.info = info
                        raise InteractionRequiredError(
                            httpbakery.Error(
                                code=httpbakery.ERR_INTERACTION_REQUIRED,
                                version=httpbakery.request_version(
                                    request.headers),
                                message='interaction required',
                                info=httpbakery.ErrorInfo(
                                    wait_url='http://0.3.2.1/wait?'
                                    'dischargeid=1',
                                    visit_url='http://0.3.2.1/visit?'
                                    'dischargeid=1'),
                            ), )

                try:
                    httpbakery.discharge(checkers.AuthContext(), content,
                                         discharge_key, None, CheckerInError())
                except InteractionRequiredError as exc:
                    return response(
                        status_code=401,
                        content={
                            'Code': exc.error.code,
                            'Message': exc.error.message,
                            'Info': {
                                'WaitURL': exc.error.info.wait_url,
                                'VisitURL': exc.error.info.visit_url,
                            },
                        },
                        headers={'Content-Type': 'application/json'})

        key = bakery.generate_key()

        @urlmatch(path='.*/visit?$')
        def visit(url, request):
            if request.headers.get('Accept') == 'application/json':
                return {'status_code': 200, 'content': {'agent': request.url}}
            cs = SimpleCookie()
            cookies = request.headers.get('Cookie')
            if cookies is not None:
                cs.load(str(cookies))
            public_key = None
            for c in cs:
                if c == 'agent-login':
                    json_cookie = json.loads(
                        base64.b64decode(cs[c].value).decode('utf-8'))
                    public_key = bakery.PublicKey.deserialize(
                        json_cookie.get('public_key'))
            ms = httpbakery.extract_macaroons(request.headers)
            if len(ms) == 0:
                b = bakery.Bakery(key=discharge_key)
                m = b.oven.macaroon(
                    version=bakery.LATEST_VERSION,
                    expiry=datetime.utcnow() + timedelta(days=1),
                    caveats=[
                        bakery.local_third_party_caveat(
                            public_key,
                            version=httpbakery.request_version(
                                request.headers))
                    ],
                    ops=[bakery.Op(entity='agent', action='login')])
                content, headers = httpbakery.discharge_required_response(
                    m, '/', 'test', 'message')
                resp = response(status_code=401,
                                content=content,
                                headers=headers)
                return request.hooks['response'][0](resp)

            return {'status_code': 200, 'content': {'agent-login': True}}

        @urlmatch(path='.*/wait?$')
        def wait(url, request):
            class EmptyChecker(bakery.ThirdPartyCaveatChecker):
                def check_third_party_caveat(self, ctx, info):
                    return []

            if InfoStorage.info is None:
                self.fail('visit url has not been visited')
            m = bakery.discharge(
                checkers.AuthContext(),
                InfoStorage.info.id,
                InfoStorage.info.caveat,
                discharge_key,
                EmptyChecker(),
                _DischargerLocator(),
            )
            return {'status_code': 200, 'content': {'Macaroon': m.to_dict()}}

        with HTTMock(server_get), \
                HTTMock(discharge), \
                HTTMock(visit), \
                HTTMock(wait):
            client = httpbakery.Client(interaction_methods=[
                agent.AgentInteractor(
                    agent.AuthInfo(
                        key=key,
                        agents=[
                            agent.Agent(username='******',
                                        url=u'http://0.3.2.1')
                        ],
                    ), ),
            ])
            resp = requests.get(
                'http://0.1.2.3/here',
                cookies=client.cookies,
                auth=client.auth(),
            )
        self.assertEquals(resp.content, b'done')
 def __init__(self, dischargers):
     self._key = macaroonbakery.generate_key()
     self._macaroons = {}
     self._dischargers = dischargers
예제 #18
0
 def setUp(self):
     self.fp_key = bakery.generate_key()
     self.tp_key = bakery.generate_key()
 def __init__(self, location, locator, test_class):
     self._location = location
     self._test = test_class
     key = macaroonbakery.generate_key()
     self._discharger = _Discharger(key=key, checker=self, locator=locator)
     locator[location] = self._discharger
예제 #20
0
 def __init__(self):
     self.key = bakery.generate_key()
예제 #21
0
 def setUp(self):
     self.fp_key = macaroonbakery.generate_key()
     self.tp_key = macaroonbakery.generate_key()