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 _setup_bakery(self, auth_endpoint, request): return bakery.Bakery( key=_get_macaroon_oven_key(), root_key_store=KeyStore(MACAROON_LIFESPAN), location=request.build_absolute_uri('/'), locator=httpbakery.ThirdPartyLocator( allow_insecure=not auth_endpoint.startswith('https:')), identity_client=IDClient(auth_endpoint), authorizer=bakery.ACLAuthorizer( get_acl=lambda ctx, op: [bakery.EVERYONE]))
def _get_bakery(request): auth_endpoint = request.external_auth_info.url auth_domain = request.external_auth_info.domain return bakery.Bakery( key=_get_macaroon_oven_key(), root_key_store=KeyStore(MACAROON_LIFESPAN), location=request.build_absolute_uri("/"), locator=httpbakery.ThirdPartyLocator( allow_insecure=not auth_endpoint.startswith("https:")), identity_client=_IDClient(auth_endpoint, auth_domain=auth_domain), authorizer=bakery.ACLAuthorizer( get_acl=lambda ctx, op: [bakery.EVERYONE]), )
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)
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))
def test_cache_fetch_no_version(self): key = bakery.generate_key() @urlmatch(path='.*/discharge/info') def discharge_info(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): info = kr.third_party_info('http://0.1.2.3/') self.assertEqual(info, expectInfo)
def test_allow_insecure(self): kr = httpbakery.ThirdPartyLocator() with self.assertRaises(macaroonbakery.error.ThirdPartyInfoNotFound): kr.third_party_info('http://0.1.2.3/')