コード例 #1
0
ファイル: test_keyring.py プロジェクト: aminba90/PythonCourse
    def test_fallback(self):
        key = bakery.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': str(key.public_key),
                }
            }

        expectInfo = bakery.ThirdPartyInfo(public_key=key.public_key,
                                           version=bakery.VERSION_1)
        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)
コード例 #2
0
    def test_fallback(self):
        key = bakery.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': str(key.public_key),
                }
            }

        expectInfo = bakery.ThirdPartyInfo(
            public_key=key.public_key,
            version=bakery.VERSION_1
        )
        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)
コード例 #3
0
ファイル: test_checker.py プロジェクト: aminba90/PythonCourse
 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)
コード例 #4
0
 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)
コード例 #5
0
 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])
コード例 #6
0
def _get_macaroon_oven_key():
    """Return a private key to use for macaroon caveats signing.

    The key is read from the Config if found, otherwise a new one is created
    and saved.

    """
    material = Config.objects.get_config("macaroon_private_key")
    if material:
        return bakery.PrivateKey.deserialize(material)

    key = bakery.generate_key()
    Config.objects.set_config("macaroon_private_key",
                              key.serialize().decode("ascii"))
    return key
コード例 #7
0
ファイル: auth.py プロジェクト: steverydz/ubuntu.com
    def is_authorized(*args, **kwargs):
        macaroon_bakery = bakery.Bakery(
            location="ubuntu.com/security",
            locator=httpbakery.ThirdPartyLocator(),
            identity_client=IdentityClient(),
            key=bakery.generate_key(),
            root_key_store=bakery.MemoryKeyStore(
                flask.current_app.config["SECRET_KEY"]),
        )
        macaroons = httpbakery.extract_macaroons(flask.request.headers)
        auth_checker = macaroon_bakery.checker.auth(macaroons)
        launchpad = Launchpad.login_anonymously("ubuntu.com/security",
                                                "production",
                                                version="devel")

        try:
            auth_info = auth_checker.allow(checkers.AuthContext(),
                                           [bakery.LOGIN_OP])
        except bakery._error.DischargeRequiredError:
            macaroon = macaroon_bakery.oven.macaroon(
                version=bakery.VERSION_2,
                expiry=datetime.utcnow() + timedelta(days=1),
                caveats=IDENTITY_CAVEATS,
                ops=[bakery.LOGIN_OP],
            )

            content, headers = httpbakery.discharge_required_response(
                macaroon, "/", "cookie-suffix")
            return content, 401, headers

        username = auth_info.identity.username()
        lp_user = launchpad.people(username)
        authorized = False

        for team in AUTHORIZED_TEAMS:
            if lp_user in launchpad.people(team).members:
                authorized = True
                break

        if not authorized:
            return (
                f"{username} is not in any of the authorized teams: "
                f"{str(AUTHORIZED_TEAMS)}",
                401,
            )

        # Validate authentication token
        return func(*args, **kwargs)
コード例 #8
0
    def __init__(self, locator=None):
        locator = httpbakery.ThirdPartyLocator()

        # generate a new keypair for encrypting third party caveats
        # it's safe to use a new keypair every time the server starts
        # as it's used only for encrypting the third party caveats
        # for sending them to be discharged. The private key doesn't need
        # to survive across restarts.
        key = bakery.generate_key()

        location = 'localhost:8000'
        root_key = 'private-key'

        self._bakery = bakery.Bakery(
            location=location, locator=locator,
            identity_client=IdentityClient(), key=key,
            root_key_store=bakery.MemoryKeyStore(root_key))
コード例 #9
0
    def test_third_party_discharge_macaroon_wrong_root_key_and_third_party_caveat(
            self):

        root_keys = bakery.MemoryKeyStore()
        ts = bakery.Bakery(
            key=bakery.generate_key(),
            checker=common.test_checker(),
            root_key_store=root_keys,
            identity_client=common.OneIdentity(),
        )
        locator = bakery.ThirdPartyStore()
        bs = common.new_bakery('bs-loc', locator)

        # ts creates a macaroon with a third party caveat addressed to bs.
        ts_macaroon = ts.oven.macaroon(bakery.LATEST_VERSION, common.ages,
                                       None, [bakery.LOGIN_OP])
        ts_macaroon.add_caveat(
            checkers.Caveat(location='bs-loc', condition='true'),
            ts.oven.key,
            locator,
        )

        def get_discharge(cav, payload):
            return bakery.discharge(
                common.test_context,
                cav.caveat_id_bytes,
                payload,
                bs.oven.key,
                common.ThirdPartyStrcmpChecker('true'),
                bs.oven.locator,
            )

        d = bakery.discharge_all(ts_macaroon, get_discharge)

        # The authorization should succeed at first.
        ts.checker.auth([d]).allow(common.test_context, [bakery.LOGIN_OP])
        # Corrupt the root key and try again.
        # We should get a DischargeRequiredError because the verification has failed.
        root_keys._key = os.urandom(24)
        with self.assertRaises(bakery.PermissionDenied) as err:
            ts.checker.auth([d]).allow(common.test_context, [bakery.LOGIN_OP])
        self.assertEqual(
            str(err.exception),
            'verification failed: Decryption failed. Ciphertext failed verification'
        )
コード例 #10
0
ファイル: common.py プロジェクト: johnsca/py-macaroon-bakery
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,
    )
コード例 #11
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,
    )
コード例 #12
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,
    )
コード例 #13
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,
    )
コード例 #14
0
    def test_third_party_discharge_macaroon_wrong_root_key_and_third_party_caveat(self):

        root_keys = bakery.MemoryKeyStore()
        ts = bakery.Bakery(
            key=bakery.generate_key(),
            checker=common.test_checker(),
            root_key_store=root_keys,
            identity_client=common.OneIdentity(),
        )
        locator = bakery.ThirdPartyStore()
        bs = common.new_bakery('bs-loc', locator)

        # ts creates a macaroon with a third party caveat addressed to bs.
        ts_macaroon = ts.oven.macaroon(bakery.LATEST_VERSION,
                                       common.ages,
                                       None, [bakery.LOGIN_OP])
        ts_macaroon.add_caveat(
            checkers.Caveat(location='bs-loc', condition='true'),
            ts.oven.key, locator,
        )

        def get_discharge(cav, payload):
            return bakery.discharge(
                common.test_context,
                cav.caveat_id_bytes,
                payload,
                bs.oven.key,
                common.ThirdPartyStrcmpChecker('true'),
                bs.oven.locator,
            )

        d = bakery.discharge_all(ts_macaroon, get_discharge)

        # The authorization should succeed at first.
        ts.checker.auth([d]).allow(common.test_context, [bakery.LOGIN_OP])
        # Corrupt the root key and try again.
        # We should get a DischargeRequiredError because the verification has failed.
        root_keys._key = os.urandom(24)
        with self.assertRaises(bakery.PermissionDenied) as err:
            ts.checker.auth([d]).allow(common.test_context, [bakery.LOGIN_OP])
        self.assertEqual(str(err.exception), 'verification failed: Decryption failed. Ciphertext failed verification')
コード例 #15
0
ファイル: test_checker.py プロジェクト: aminba90/PythonCourse
    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='******')
        ])
コード例 #16
0
    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='******')
        ])
コード例 #17
0
async def test_macaroon_auth_with_bad_key(event_loop):
    auth_info, username = agent_auth_info()
    # Use a random key rather than the correct key.
    auth_info = auth_info._replace(key=bakery.generate_key())
    # Create a bakery client can do agent authentication.
    client = httpbakery.Client(
        key=auth_info.key,
        interaction_methods=[agent.AgentInteractor(auth_info)],
    )

    async with base.CleanModel(bakery_client=client) as m:
        async with await m.get_controller() as c:
            await c.grant_model(username, m.info.uuid, 'admin')
        try:
            async with Model(
                jujudata=NoAccountsJujuData(m._connector.jujudata),
                bakery_client=client,
            ):
                pytest.fail('Should not be able to connect with invalid key')
        except httpbakery.BakeryException:
            # We're expecting this because we're using the
            # wrong key.
            pass
コード例 #18
0
async def test_macaroon_auth_with_bad_key(event_loop):
    auth_info, username = agent_auth_info()
    # Use a random key rather than the correct key.
    auth_info = auth_info._replace(key=bakery.generate_key())
    # Create a bakery client can do agent authentication.
    client = httpbakery.Client(
        key=auth_info.key,
        interaction_methods=[agent.AgentInteractor(auth_info)],
    )

    async with base.CleanModel(bakery_client=client) as m:
        async with await m.get_controller() as c:
            await c.grant_model(username, m.info.uuid, 'admin')
        try:
            async with Model(
                    jujudata=NoAccountsJujuData(m._connector.jujudata),
                    bakery_client=client,
            ):
                pytest.fail('Should not be able to connect with invalid key')
        except httpbakery.BakeryException:
            # We're expecting this because we're using the
            # wrong key.
            pass
コード例 #19
0
ファイル: configauth.py プロジェクト: tjjh89017/maas
def _register_service(client, service, auth_details):
    key = generate_key()
    response = client.register_service(service['$uri'], str(key.public_key))
    auth_details.url = response['url']
    auth_details.user = response['username']
    auth_details.key = str(key)
コード例 #20
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.to_dict()
                    }
                }

        auth_info = agent.load_auth_info(self.agent_filename)

        @urlmatch(path='.*/login')
        def login(url, request):
            qs = parse_qs(urlparse(request.url).query)
            self.assertEqual(request.method, 'GET')
            self.assertEqual(
                qs, {'username': ['test-user'], 'public-key': [PUBLIC_KEY]})
            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')])
            return {
                'status_code': 200,
                'content': {
                    'macaroon': m.to_dict()
                }
            }

        with HTTMock(server_get), \
                HTTMock(discharge), \
                HTTMock(login):
            client = httpbakery.Client(interaction_methods=[
                agent.AgentInteractor(auth_info),
            ])
            resp = requests.get(
                'http://0.1.2.3/here',
                cookies=client.cookies,
                auth=client.auth())
        self.assertEqual(resp.content, b'done')
コード例 #21
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': '/agent-visit',
                    }
                }
            raise Exception('unexpected call to visit without Accept header')

        @urlmatch(path='.*/agent-visit')
        def agent_visit(url, request):
            if request.method != "POST":
                raise Exception('unexpected method')
            log.info('agent_visit url {}'.format(url))
            body = json.loads(request.body.decode('utf-8'))
            if body['username'] != 'test-user':
                raise Exception('unexpected username in body {!r}'.format(request.body))
            public_key = bakery.PublicKey.deserialize(body['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), \
                HTTMock(agent_visit):
            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.assertEqual(resp.content, b'done')
コード例 #22
0
 def __init__(self):
     self.key = bakery.generate_key()
コード例 #23
0
 def __init__(self, dischargers):
     self._key = bakery.generate_key()
     self._macaroons = {}
     self._dischargers = dischargers
コード例 #24
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.to_dict()
                    }
                }

        auth_info = agent.load_auth_info(self.agent_filename)

        @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(
                        auth_info.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(auth_info),
            ])
            resp = requests.get('http://0.1.2.3/here',
                                cookies=client.cookies,
                                auth=client.auth())
        self.assertEquals(resp.content, b'done')
コード例 #25
0
 def setUp(self):
     self.fp_key = bakery.generate_key()
     self.tp_key = bakery.generate_key()
コード例 #26
0
ファイル: test_checker.py プロジェクト: aminba90/PythonCourse
 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
コード例 #27
0
 def setUp(self):
     self.fp_key = bakery.generate_key()
     self.tp_key = bakery.generate_key()
コード例 #28
0
ファイル: test_checker.py プロジェクト: aminba90/PythonCourse
 def __init__(self, dischargers):
     self._key = bakery.generate_key()
     self._macaroons = {}
     self._dischargers = dischargers
コード例 #29
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': '/agent-visit',
                    }
                }
            raise Exception('unexpected call to visit without Accept header')

        @urlmatch(path='.*/agent-visit')
        def agent_visit(url, request):
            if request.method != "POST":
                raise Exception('unexpected method')
            log.info('agent_visit url {}'.format(url))
            body = json.loads(request.body.decode('utf-8'))
            if body['username'] != 'test-user':
                raise Exception('unexpected username in body {!r}'.format(
                    request.body))
            public_key = bakery.PublicKey.deserialize(body['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), \
                HTTMock(agent_visit):
            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')
コード例 #30
0
 def __init__(self):
     self.key = bakery.generate_key()
コード例 #31
0
 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