def after_login(resp): try: root = Macaroon.deserialize(flask.session.pop("macaroon_root")) except KeyError: return ( flask.render_template("templates/_error_login.html", ), 400, ) bound = root.prepare_for_request( Macaroon.deserialize(resp.extensions["macaroon"].discharge)) flask.session["authentication_token"] = binary_serialize_macaroons( [root, bound]).decode("utf-8") if not resp.nickname: return flask.redirect(flask.current_app.config["CANONICAL_LOGIN_URL"]) flask.session["openid"] = { "identity_url": resp.identity_url, "nickname": resp.nickname, "fullname": resp.fullname, "image": resp.image, "email": resp.email, } return flask.redirect(open_id.get_next_url())
def discharge_macaroon_raw(self): root_macaroon = Macaroon.deserialize(self.root_macaroon_raw) unbound_discharge_macaroon = Macaroon.deserialize( self.unbound_discharge_macaroon_raw) discharge_macaroon = root_macaroon.prepare_for_request( unbound_discharge_macaroon) return discharge_macaroon.serialize()
def alice_server_access_service(): macaroon_cookie = request.cookies.get('macaroonCookie') discharge_cookie = request.cookies.get('macaroonDischargeCookie') if macaroon_cookie is not None and macaroon_cookie != "" and discharge_cookie is not None and discharge_cookie != "": m = Macaroon.deserialize(macaroon_cookie) dm = Macaroon.deserialize(discharge_cookie) # Should be done on the client pm = m.prepare_for_request(dm) v = Verifier() try: verified = v.verify(m, alice_server_keys[m.identifier], [pm]) except MacaroonInvalidSignatureException: verified = False if verified: resp = make_response( render_template("auth_demo.html", result="Successful Authentication")) else: resp = make_response( render_template("auth_demo.html", result="Auth failed")) return resp else: resp = make_response( render_template( "auth_demo.html", result="Couldn't get necessary macaroons from cookies")) return resp
def get_authorization_header(root, discharge): """ Bind root and discharge macaroons and return the authorization header. """ bound = Macaroon.deserialize(root).prepare_for_request( Macaroon.deserialize(discharge)) return "Macaroon root={}, discharge={}".format(root, bound.serialize())
def get_authorization_header(root, discharge): """ Bind root and discharge macaroons and return the authorization header. """ bound = Macaroon.deserialize(root).prepare_for_request( Macaroon.deserialize(discharge) ) return "Macaroon root={}, discharge={}".format(root, bound.serialize())
def _get_authorization_header(self, session): """ Bind root and discharge macaroons and return the authorization header. """ root = session["macaroon_root"] discharge = session["macaroon_discharge"] bound = (Macaroon.deserialize(root).prepare_for_request( Macaroon.deserialize(discharge)).serialize()) return {"Authorization": f"Macaroon root={root}, discharge={bound}"}
def match(self, macaroons): mismatch = Contains("root").match(macaroons) if mismatch is not None: return mismatch root_macaroon = Macaroon.deserialize(macaroons["root"]) if "discharge" in macaroons: discharge_macaroons = [ Macaroon.deserialize(macaroons["discharge"])] else: discharge_macaroons = [] try: Verifier().verify(root_macaroon, self.key, discharge_macaroons) except Exception as e: return Mismatch("Macaroons do not verify: %s" % e)
def discharge_macaroon(self, macaroon, token): # Deserialize the macaroon with pymacaroons macaroon = Macaroon.deserialize(macaroon, JsonSerializer()) # Extract the caveat we are interested in caveat = self._extract_caveat_to_discharge(macaroon) data = {"id64": caveat, "token64": token, "token-kind": "macaroon"} response = self._request(method="POST", url=f"{CANDID_API_URL}discharge", data=data) return Macaroon.deserialize(json.dumps(response.json()["Macaroon"]), JsonSerializer())
def _prepare_request(method, path, data=None, session=None): request = Request(method=method, url=f"{API_URL}{path}") if session: root = Macaroon.deserialize(session["macaroon_root"]) discharge = Macaroon.deserialize(session["macaroon_discharge"]) bound = root.prepare_for_request(discharge) token = binary_serialize_macaroons([root, bound]).decode("utf-8") request.headers["Authorization"] = f"Macaroon {token}" if data is not None: request.json = data return request.prepare()
def validate_pypi_token(token: str) -> Tuple[bool, str]: """ Returns whether the PyPI token *appears* to be valid. :param token: """ # TODO: perhaps use the pypitokens library? if not token.startswith("pypi-"): return False, "The token should start with 'pypi-'." b64string = token[5:] try: macaroon = Macaroon.deserialize(b64string) except Exception: return False, "Could not decode token." if macaroon.location != "pypi.org": return False, "The token is not for PyPI." caveats: List[Caveat] = macaroon.caveats if not macaroon.caveats: return False, "The decoded output does not have the expected format." try: permissions_dict = json.loads(caveats[0].caveat_id) except Exception: return False, "The decoded output does not have the expected format." # TODO: check the token has the required permissions. return True, ''
def attenuate(macaroon: str, caveats: List[str]) -> str: m_obj = Macaroon.deserialize(macaroon) for caveat in caveats: m_obj.add_first_party_caveat(caveat) return str(m_obj.serialize())
def _create_snap_recipe( snap, version, track, owner, tag, repo, dry_run, snap_recipe_email, snap_recipe_password, ): """ Creates an new snap recipe in Launchpad snap: Name of snap to create the recipe for (ie, kubectl) version: snap version channel apply this too (ie, Current patch is 1.13.3 but we want that to go in 1.13 snap channel) track: snap store version/risk/branch to publish to (ie, 1.13/edge/hotfix-LP123456) owner: launchpad owner of the snap recipe (ie, k8s-jenkaas-admins) tag: launchpad git tag to pull snapcraft instructions from (ie, git.launchpad.net/snap-kubectl) repo: launchpad git repo (git+ssh://[email protected]/snap-kubectl) # Note: this account would need access granted to the snaps it want's to publish from the snapstore dashboard snap_recipe_email: snapstore email for being able to publish snap recipe from launchpad to snap store snap_recipe_password: snapstore password for account being able to publish snap recipe from launchpad to snap store Usage: snaps-source.py builder --snap kubectl --version 1.13 --tag v1.13.2 \ --track 1.13/edge/hotfix-LP123456 \ --repo git+ssh://[email protected]/snap-kubectl \ --owner k8s-jenkaas-admins \ --snap-recipe-email [email protected] \ --snap-recipe-password aabbccddee """ _client = lp.Client(stage="production") _client.login() params = { "name": snap, "owner": owner, "version": version, "branch": tag, "repo": repo, "track": [track], } click.echo(f" > creating recipe for {params}") if dry_run: click.echo("dry-run only, exiting.") sys.exit(0) snap_recipe = _client.create_or_update_snap_recipe(**params) caveat_id = snap_recipe.beginAuthorization() cip = idm.CanonicalIdentityProvider(email=snap_recipe_email, password=snap_recipe_password) discharge_macaroon = cip.get_discharge(caveat_id).json() discharge_macaroon = Macaroon.deserialize( discharge_macaroon["discharge_macaroon"]) snap_recipe.completeAuthorization( discharge_macaroon=discharge_macaroon.serialize()) snap_recipe.requestBuilds(archive=_client.archive(), pocket="Updates")
def login_handler(): is_test_backend = flask.request.args.get("test_backend", False) api_url = flask.current_app.config["CONTRACTS_LIVE_API_URL"] if is_test_backend: api_url = flask.current_app.config["CONTRACTS_TEST_API_URL"] if user_info(flask.session): return flask.redirect(open_id.get_next_url()) response = session.request(method="get", url=f"{api_url}/v1/canonical-sso-macaroon") flask.session["macaroon_root"] = response.json()["macaroon"] for caveat in Macaroon.deserialize( flask.session["macaroon_root"]).third_party_caveats(): if caveat.location == "login.ubuntu.com": openid_macaroon = MacaroonRequest(caveat_id=caveat.caveat_id) break return open_id.try_login( flask.current_app.config["CANONICAL_LOGIN_URL"], ask_for=["email", "nickname", "image"], ask_for_optional=["fullname"], extensions=[openid_macaroon], )
def get_login_url(self, macaroon, callback_url, state): """ To initiate the login redirect the user's browser to the URL specified in the LoginURL parameter. The redirect must be a GET request and must include a "return_to" query parameter which must be whitelisted in the candid server. The redirect should also specify a "state" query parameter. This is an opaque value that will be sent back to the relaying party in the callback. This can be useful to verify that a login attempt was started by the relaying party and can help guard against CSRF attacks. """ # Deserialize the macaroon with pymacaroons macaroon = Macaroon.deserialize(macaroon, JsonSerializer()) # Extract the caveat we are interested in caveat = self._extract_caveat_to_discharge(macaroon) response = self._request( method="POST", url=f"{CANDID_API_URL}discharge", data={"id64": caveat}, ) data = response.json( )["Info"]["InteractionMethods"]["browser-redirect"] return f"{data['LoginURL']}?return_to={callback_url}&state={state}"
def test_serializing_deserializing_macaroon(self, key_id, loc, key): assume(key_id and loc and key) macaroon = Macaroon(location=loc, identifier=key_id, key=key) deserialized = Macaroon.deserialize(macaroon.serialize()) assert_equal(macaroon.identifier, deserialized.identifier) assert_equal(macaroon.location, deserialized.location) assert_equal(macaroon.signature, deserialized.signature)
def deserialize(json_macaroon): '''Deserialize a JSON macaroon into a macaroon object from pymacaroons. @param the JSON macaroon to deserialize as a dict. @return the deserialized macaroon object. ''' return Macaroon.deserialize(json.dumps(json_macaroon), json_serializer.JsonSerializer())
def test_deserializing_json_v2(self): m = Macaroon.deserialize( '{"l": "http://mybank/", "i": "we used our secret key", "s": ' '"197bac7a044af33332"' ', "c": [{"l": null, "i": "test = caveat", "v": null}]}', serializer=JsonSerializer()) assert_equal(m.signature_bytes, binascii.hexlify(b'197bac7a044af33332'))
def test_deserializing_accepts_padding(self): m = Macaroon.deserialize( ('MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVz' 'ZWQgb3VyIHNlY3JldCBrZXkKMDAxN2NpZCB0ZXN0ID0gYWNhdmVhdAowMDJmc2ln' 'bmF0dXJlIJRJ_V3WNJQnqlVq5eez7spnltwU_AXs8NIRY739sHooCg==')) assert_equal( m.signature, '9449fd5dd6349427aa556ae5e7b3eeca6796dc14fc05ecf0d21163bdfdb07a28')
def test_serializing_deserializing_json(self): m = Macaroon(location='http://test/', identifier='first', key='secret_key_1') m.add_first_party_caveat('test = caveat') n = Macaroon.deserialize(m.serialize(serializer=JsonSerializer()), serializer=JsonSerializer()) assert_equal(m.signature, n.signature)
def test_deserializing(self): m = Macaroon.deserialize( 'MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaW\ VyIHdlIHVzZWQgb3VyIHNlY3JldCBrZXkKMDAxNmNpZCB0ZXN0ID0gY2F2ZWF0CjAwMmZzaWduYXR1\ cmUgGXusegRK8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWcK') assert_equal( m.signature, '197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67')
def test_from_go_macaroon_json_v2(self): # The following macaroon have been generated with # https://github.com/go-macaroon/macaroon # to test the deserialization. json_v1 = '{"caveats":[{"cid":"fp caveat"},{"cid":"tp caveat",' \ '"vid":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp_MgxHrfLnfvNuYDo' \ 'zNKWTlRPPx6VemasWnPpJdAWE6FWmOuFX4sB4-a1oAURDp",' \ '"cl":"tp location"}],"location":"my location",' \ '"identifier":"my identifier",' \ '"signature":"483b3881c9990e5099cb6695da3164daa64da60417b' \ 'caf9e9dc4c0a9968f6636"}' json_v1_discharge = '{"caveats":[],"location":"tp location",' \ '"identifier":"tp caveat",' \ '"signature":"8506007f69ae3e6a654e0b9769f20dd9da5' \ 'd2af7860070d6776c15989fb7dea6"}' m = Macaroon.deserialize(json_v1, serializer=JsonSerializer()) discharge = Macaroon.deserialize(json_v1_discharge, serializer=JsonSerializer()) assert_macaroon(m, discharge, MACAROON_V1) binary_v1 = 'MDAxOWxvY2F0aW9uIG15IGxvY2F0aW9uCjAwMWRpZGVudGlmaWVyIG1' \ '5IGlkZW50aWZpZXIKMDAxMmNpZCBmcCBjYXZlYXQKMDAxMmNpZCB0cC' \ 'BjYXZlYXQKMDA1MXZpZCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACn' \ '8yDEet8ud+825gOjM0pZOVE8/HpV6Zqxac+kl0BYToVaY64VfiwHj5r' \ 'WgBREOkKMDAxM2NsIHRwIGxvY2F0aW9uCjAwMmZzaWduYXR1cmUgSDs' \ '4gcmZDlCZy2aV2jFk2qZNpgQXvK+encTAqZaPZjYK' binary_v1_discharge = 'MDAxOWxvY2F0aW9uIHRwIGxvY2F0aW9uCjAwMTlpZGVud' \ 'GlmaWVyIHRwIGNhdmVhdAowMDJmc2lnbmF0dXJlIIUGAH' \ '9prj5qZU4Ll2nyDdnaXSr3hgBw1ndsFZift96mCg' m = Macaroon.deserialize(binary_v1) discharge = Macaroon.deserialize(binary_v1_discharge) assert_macaroon(m, discharge, MACAROON_V1) json_v2 = '{"c":[{"i":"fp caveat"},{"i":"tp caveat",' \ '"v64":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp_MgxHrfLnfvNuYDoz' \ 'NKWTlRPPx6VemasWnPpJdAWE6FWmOuFX4sB4-a1oAURDp",' \ '"l":"tp location"}],"l":"my location","i":"my identifier",' \ '"s64":"SDs4gcmZDlCZy2aV2jFk2qZNpgQXvK-encTAqZaPZjY"}' json_v2_discharge = '{"l":"tp location","i":"tp caveat","s64":"hQYAf2' \ 'muPmplTguXafIN2dpdKveGAHDWd2wVmJ-33qY"}' m = Macaroon.deserialize(json_v2, serializer=JsonSerializer()) discharge = Macaroon.deserialize(json_v2_discharge, serializer=JsonSerializer()) assert_macaroon(m, discharge, MACAROON_V2) binary_v2 = 'AgELbXkgbG9jYXRpb24CDW15IGlkZW50aWZpZXIAAglmcCBjYXZlYXQ' \ 'AAQt0cCBsb2NhdGlvbgIJdHAgY2F2ZWF0BEgAAAAAAAAAAAAAAAAAAA' \ 'AAAAAAAAAAAAACn8yDEet8ud+825gOjM0pZOVE8/HpV6Zqxac+kl0BY' \ 'ToVaY64VfiwHj5rWgBREOkAAAYgSDs4gcmZDlCZy2aV2jFk2qZNpgQX' \ 'vK+encTAqZaPZjY' binary_v2_discharge = 'AgELdHAgbG9jYXRpb24CCXRwIGNhdmVhdAAABiCFBgB/a' \ 'a4+amVOC5dp8g3Z2l0q94YAcNZ3bBWYn7fepg' m = Macaroon.deserialize(binary_v2) discharge = Macaroon.deserialize(binary_v2_discharge) assert_macaroon(m, discharge, MACAROON_V2)
def macaroon_from_dict(json_macaroon): '''Return a pymacaroons.Macaroon object from the given JSON-deserialized dict. @param JSON-encoded macaroon as dict @return the deserialized macaroon object. ''' return Macaroon.deserialize(json.dumps(json_macaroon), json_serializer.JsonSerializer())
def test_deserializing_json(self): m = Macaroon.deserialize( '{"location": "http://mybank/", "identifier": "we used our secret \ key", "signature": "197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c2\ 3dbd67", "caveats": [{"cl": null, "cid": "test = caveat", "vid": null}]}', serializer=JsonSerializer()) assert_equal( m.signature, '197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67')
def get_store_authorization( email, permissions=None, channels=None, store_env=None, allowed_stores=None, snaps=None): """Return the serialised root and discharge macaroon. Get a permissions macaroon from SCA and discharge it in SSO. """ headers = DEFAULT_HEADERS.copy() # Request a SCA root macaroon with hard expiration in 180 days. sca_data = { 'permissions': permissions or ['package_access'], 'expires': ( datetime.date.today() + datetime.timedelta(days=180) ).strftime('%Y-%m-%d 00:00:00') } if channels: sca_data['channels'] = channels if allowed_stores: sca_data['store_ids'] = allowed_stores if snaps: sca_data['packages'] = [{'name': snap} for snap in snaps] response = requests.request( url='{}/dev/api/acl/'.format(CONSTANTS[store_env]['sca_base_url']), method='POST', json=sca_data, headers=headers) if response.status_code != 200: error = response.json()['title'] raise CliError("Error {}: {}".format(response.status_code, error)) root = response.json()['macaroon'] caveat, = [ c for c in Macaroon.deserialize(root).third_party_caveats() if c.location == CONSTANTS[store_env]['sso_location'] ] # Request a SSO discharge macaroon. sso_data = { 'email': email, 'password': getpass.getpass('Password for {}: '.format(email)), 'caveat_id': caveat.caveat_id, } response = requests.request( url='{}/api/v2/tokens/discharge'.format( CONSTANTS[store_env]['sso_base_url']), method='POST', json=sso_data, headers=headers) # OTP/2FA is optional. if (response.status_code == 401 and response.json().get('code') == 'TWOFACTOR_REQUIRED'): sys.stderr.write('Second-factor auth for {}: '.format(store_env)) sso_data.update({'otp': input()}) response = requests.request( url='{}/api/v2/tokens/discharge'.format( CONSTANTS[store_env]['sso_base_url']), method='POST', json=sso_data, headers=headers) discharge = response.json()['discharge_macaroon'] return root, discharge
def test_deserializing_accepts_padding(self): m = Macaroon.deserialize( ('MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVz' 'ZWQgb3VyIHNlY3JldCBrZXkKMDAxN2NpZCB0ZXN0ID0gYWNhdmVhdAowMDJmc2ln' 'bmF0dXJlIJRJ_V3WNJQnqlVq5eez7spnltwU_AXs8NIRY739sHooCg==') ) assert_equal( m.signature, '9449fd5dd6349427aa556ae5e7b3eeca6796dc14fc05ecf0d21163bdfdb07a28' )
def test_deserializing(self): m = Macaroon.deserialize( 'MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaW\ VyIHdlIHVzZWQgb3VyIHNlY3JldCBrZXkKMDAxNmNpZCB0ZXN0ID0gY2F2ZWF0CjAwMmZzaWduYXR1\ cmUgGXusegRK8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWcK' ) assert_equal( m.signature, '197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67' )
def login_device(macaroon, manufacturer, channel_id): m = Macaroon(location='localhost', identifier=manufacturer, key=keys[manufacturer]) m1 = Macaroon.deserialize(macaroon) channels = [] for caveat in m1.caveats: m.add_first_party_caveat(caveat.to_dict()['cid']) channels.append(caveat.to_dict()['cid']) return m1.signature == m.signature and channel_id in channels[2:]
def r_feed_item(obj, info, *_): m = Macaroon.deserialize( info.context["request"].headers["Authorization"].replace( "Bearer ", "")) if isinstance(obj, Invoice): if m.identifier == obj.payee: return "UserInvoice" if m.identifier == obj.payer: return "PaidInvoice" return "Deposit"
def get_caveat_id(root): """ Returns the caveat_id generated by the SSO """ caveat, = [ c for c in Macaroon.deserialize(root).third_party_caveats() if c.location == 'login.ubuntu.com' ] return caveat.caveat_id
def test_serializing_v2(self): m = Macaroon( location='http://mybank/', identifier='we used our secret key', key='this is our super secret key; only we should know it', version=MACAROON_V2) m.add_first_party_caveat('test = caveat') n = Macaroon.deserialize(m.serialize()) assert_equal(m.identifier_bytes, n.identifier_bytes) assert_equal(m.version, n.version)
async def check_auth(self, info) -> Union[User, Tuple[LSAT, Macaroon], Error]: """Function to check authentication of user""" # check if auth header is present serial_macaroon, preimage = self.get_auth(info) if not serial_macaroon: return Error("NoCredentials", "No token sent. You are not logged in") # attempt to deserialize macaroon try: macaroon = Macaroon.deserialize(serial_macaroon) except MacaroonDeserializationException: return Error("AuthenticationError", "Invalid token sent") # define types needed macaroon_key: bytes payload: Union[User, Tuple[LSAT, Macaroon]] # times token has been used. Only important with lsats used = 0 # determine if auth is an lsat if "LSAT" in self.args.get("kind"): lsat: Optional[LSAT] = await LSAT.get(macaroon.identifier) if not lsat: return Error("AuthenticationError", "Could not find lsat") self.logger.critical(f"comparing {preimage} with {lsat.preimage}") if not preimage or preimage != lsat.preimage: return Error("AuthenticationError", "Invalid preimage") used = lsat.used macaroon_key = lsat.key payload = lsat # auth is standard macaroon else: # lookup user by identifier db_user: Optional[User] = await User.get(macaroon.identifier) if not db_user: return Error("AuthenticationError", "Could not find user") macaroon_key = db_user.key payload = db_user # verify macaroon against directive arguments try: verify( macaroon=macaroon, key=macaroon_key, roles=self.args.get("roles"), caveats=self.args.get("caveats"), used=used, req=info.context["request"], ) except MacaroonInvalidSignatureException: return Error("AuthenticationError", "Macaroon caveats not satisfied") return payload
def test_deserializing_json_v2(self): m = Macaroon.deserialize( '{"l": "http://mybank/", "i": "we used our secret key", "s": ' '"197bac7a044af33332"' ', "c": [{"l": null, "i": "test = caveat", "v": null}]}', serializer=JsonSerializer() ) assert_equal( m.signature_bytes, binascii.hexlify(b'197bac7a044af33332') )
def test_serializing_v2(self): m = Macaroon( location='http://mybank/', identifier='we used our secret key', key='this is our super secret key; only we should know it', version=MACAROON_V2 ) m.add_first_party_caveat('test = caveat') n = Macaroon.deserialize(m.serialize()) assert_equal(m.identifier_bytes, n.identifier_bytes) assert_equal(m.version, n.version)
def get_store_authorization(session: Session, email: str, password: str, environment: str, permissions: Optional[List[str]] = None, channels: Optional[List[str]] = None): """Return the serialised root and discharge macaroon. Get a permissions macaroon from SCA and discharge it in SSO. """ headers = DEFAULT_HEADERS.copy() # Request a SCA root macaroon with hard expiration in 180 days. sca_data = { 'permissions': permissions or ['package_access'], 'expires': (datetime.date.today() + datetime.timedelta(days=180)).strftime('%Y-%m-%d 00:00:00') } if channels: sca_data.update({'channels': channels}) response = session.request(url='{}/dev/api/acl/'.format( CONSTANTS[environment]['sca_base_url']), method='POST', json=sca_data, headers=headers) root = response.json()['macaroon'] caveat, = [ c for c in Macaroon.deserialize(root).third_party_caveats() if c.location == CONSTANTS[environment]['sso_location'] ] # Request a SSO discharge macaroon. sso_data = { 'email': email, 'password': password, 'caveat_id': caveat.caveat_id, } response = session.request(url='{}/api/v2/tokens/discharge'.format( CONSTANTS[environment]['sso_base_url']), method='POST', json=sso_data, headers=headers) # OTP/2FA is optional. if (response.status_code == 401 and response.json().get('code') == 'TWOFACTOR_REQUIRED'): sys.stderr.write('Second-factor auth for {}: '.format(environment)) sso_data.update({'otp': input()}) response = session.request(url='{}/api/v2/tokens/discharge'.format( CONSTANTS[environment]['sso_base_url']), method='POST', json=sso_data, headers=headers) discharge = response.json()['discharge_macaroon'] return root, discharge
def test_deserializing_json(self): m = Macaroon.deserialize( '{"location": "http://mybank/", "identifier": "we used our secret \ key", "signature": "197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c2\ 3dbd67", "caveats": [{"cl": null, "cid": "test = caveat", "vid": null}]}', serializer=JsonSerializer() ) assert_equal( m.signature, '197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67' )
def main(): #---- Read arguments-------------------------------------------------------- args = parse_args() url = args.source if not "https" in url: print("ERROR: URL has to start with https") sys.exit(1) #--------------------------------------------------------------------------- #----- Config -------------------------------------------------------------- # Set the logging level if args.verbose: logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s - %(message)s', datefmt='%Y%m%d %H:%M:%S') else: logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s - %(message)s', datefmt='%Y%m%d %H:%M:%S') # Check that the configuration file exists if os.path.isfile(".config"): configParser = configparser.RawConfigParser() configParser.read(".config") curl_debug = configParser.getint('all', 'curl_debug') proxy = configParser.get('all', 'proxy') timeout = configParser.getint('all', 'timeout') else: # If the .config file doesn't exist, set the defaults curl_debug = 1 proxy = "/tmp/x509up_u0" timeout = 120 #--------------------------------------------------------------------------- tpc_util = TPC_util(log, timeout, curl_debug, proxy) caveats = "UPLOAD,DOWNLOAD,LIST,READ_METADATA" #caveats="DOWNLOAD,LIST" if args.ipv4: macaroon = tpc_util.request_macaroon(url, caveats, "-4") elif args.ipv6: macaroon = tpc_util.request_macaroon(url, caveats, "-6") else: macaroon = tpc_util.request_macaroon(url, caveats) if macaroon: log.info("Macaroon:\n" + macaroon) try: n = Macaroon.deserialize(macaroon) log.info("Macaroon deserialized:\n" + n.inspect()) except: log.info("Cannot deserialize the macaroon") else: log.error("Cannot get the macaroon")
def get_caveat_id(root): """ Returns the caveat_id generated by the SSO """ location = urlparse(LOGIN_URL).hostname (caveat, ) = [ c for c in Macaroon.deserialize(root).third_party_caveats() if c.location == location ] return caveat.caveat_id
def test_serializing_deserializing_macaroon(self, key_id, loc, key): assume(key_id and loc and key) macaroon = Macaroon( location=loc, identifier=key_id, key=key ) deserialized = Macaroon.deserialize(macaroon.serialize()) assert_equal(macaroon.identifier, deserialized.identifier) assert_equal(macaroon.location, deserialized.location) assert_equal(macaroon.signature, deserialized.signature)
def get_caveat_id(root): """ Returns the caveat_id generated by the SSO """ location = urlparse(LOGIN_URL).hostname caveat, = [ c for c in Macaroon.deserialize(root).third_party_caveats() if c.location == location ] return caveat.caveat_id
def test_serializing_with_binary_v2(self): identifier = base64.b64decode('AK2o+q0Aq9+bONkXw7ky7HAuhCLO9hhaMMc==') m = Macaroon( location='http://mybank/', identifier=identifier, key='this is our super secret key; only we should know it', version=MACAROON_V2 ) m.add_first_party_caveat('test = caveat') n = Macaroon.deserialize(m.serialize()) assert_equal(m.identifier_bytes, n.identifier_bytes) assert_equal(m.version, n.version)
def test_serializing_deserializing_json(self): m = Macaroon( location='http://test/', identifier='first', key='secret_key_1' ) m.add_first_party_caveat('test = caveat') n = Macaroon.deserialize( m.serialize(serializer=JsonSerializer()), serializer=JsonSerializer() ) assert_equal(m.signature, n.signature)
def test_serializing_json_v2_with_binary(self): id = base64.b64decode('AK2o+q0Aq9+bONkXw7ky7HAuhCLO9hhaMMc==') m = Macaroon( location='http://mybank/', identifier=id, key='this is our super secret key; only we should know it', version=MACAROON_V2 ) assert_equal( json.loads(m.serialize(serializer=JsonSerializer()))['i64'], "AK2o-q0Aq9-bONkXw7ky7HAuhCLO9hhaMMc" ) n = Macaroon.deserialize( m.serialize(serializer=JsonSerializer()), serializer=JsonSerializer() ) assert_equal(m.identifier_bytes, n.identifier_bytes)
def test_serializing_macaroon_with_first_and_third_caveats(self): m = Macaroon( location='http://mybank/', identifier='we used our other secret key', key='this is a different super-secret key; \ never use the same secret twice' ) m.add_first_party_caveat('account = 3735928559') caveat_key = '4; guaranteed random by a fair toss of the dice' identifier = 'this was how we remind auth of key/pred' m.add_third_party_caveat('http://auth.mybank/', caveat_key, identifier) n = Macaroon.deserialize(m.serialize()) assert_equal( m.signature, n.signature )
def test_deserializing_invalid(self): with assert_raises(MacaroonDeserializationException) as cm: Macaroon.deserialize("QA")