def test_mem_store(self): st = bakery.MemoryKeyStore() key, id = st.root_key() self.assertEqual(len(key), 24) self.assertEqual(id.decode('utf-8'), '0') key1, id1 = st.root_key() self.assertEqual(key1, key) self.assertEqual(id1, id) key2 = st.get(id) self.assertEqual(key2, key)
def test_version1_macaroon_id(self): # In the version 1 bakery, macaroon ids were hex-encoded with a # hyphenated UUID suffix. root_key_store = bakery.MemoryKeyStore() b = bakery.Bakery( root_key_store=root_key_store, identity_client=common.OneIdentity(), ) key, id = root_key_store.root_key() root_key_store.get(id) m = Macaroon(key=key, version=MACAROON_V1, location='', identifier=id + b'-deadl00f') b.checker.auth([[m]]).allow(common.test_context, [bakery.LOGIN_OP])
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_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' )
def __init__(self, key, locator): self._root_key_store = bakery.MemoryKeyStore() self._key = key self._locator = locator