def test_anonymous_caller(network, args): if args.package == "liblogging": primary, _ = network.find_primary() # Create a new user but do not record its identity network.create_user("user5", args.participants_curve, record=False) log_id = 101 msg = "This message is anonymous" with primary.client("user5") as c: r = c.post("/app/log/private/anonymous", {"id": log_id, "msg": msg}) assert r.body.json() == True r = c.get(f"/app/log/private?id={log_id}") assert r.status_code == http.HTTPStatus.UNAUTHORIZED.value, r with primary.client("user0") as c: r = c.get(f"/app/log/private?id={log_id}") assert msg in r.body.json()["msg"], r else: LOG.warning( f"Skipping {inspect.currentframe().f_code.co_name} as application is not C++" ) return network
def test_user(network, args, verify=True): # Note: This test should not be chained in the test suite as it creates # a new user and uses its own LoggingTxs primary, _ = network.find_nodes() new_user_local_id = "user3" new_user = network.create_user(new_user_local_id, args.participants_curve) user_data = {"lifetime": "temporary"} network.consortium.add_user(primary, new_user.local_id, user_data) txs = app.LoggingTxs(user_id=new_user.local_id) txs.issue( network=network, number_txs=1, ) if verify: txs.verify() network.consortium.remove_user(primary, new_user.service_id) with primary.client(new_user_local_id) as c: r = c.get("/app/log/private") assert r.status_code == http.HTTPStatus.UNAUTHORIZED.value return network
def test_jinja_templates(network, args, verify=True): primary, _ = network.find_primary() new_user_local_id = "bob" new_user = network.create_user(new_user_local_id, args.participants_curve) with primary.client(new_user_local_id) as c: r = c.post("/app/log/private", {"id": 42, "msg": "New user test"}) assert r.status_code == http.HTTPStatus.UNAUTHORIZED.value template_loader = jinja2.ChoiceLoader( [ jinja2.FileSystemLoader(args.jinja_templates_path), jinja2.FileSystemLoader(os.path.dirname(new_user.cert_path)), ] ) template_env = jinja2.Environment( loader=template_loader, undefined=jinja2.StrictUndefined ) proposal_template = template_env.get_template("set_user_proposal.json.jinja") proposal_body = proposal_template.render(cert=os.path.basename(new_user.cert_path)) proposal = network.consortium.get_any_active_member().propose( primary, proposal_body ) ballot_template = template_env.get_template("ballot.json.jinja") ballot_body = ballot_template.render(**json.loads(proposal_body)) network.consortium.vote_using_majority(primary, proposal, ballot_body) with primary.client(new_user_local_id) as c: r = c.post("/app/log/private", {"id": 42, "msg": "New user test"}) assert r.status_code == http.HTTPStatus.OK.value network.consortium.remove_user(primary, new_user.service_id) with primary.client(new_user_local_id) as c: r = c.get("/app/log/private") assert r.status_code == http.HTTPStatus.UNAUTHORIZED.value return network
def test_actions(network, args): node = network.find_random_node() with node.client(None, "member0") as c: valid_set_member_data = proposal( action( "set_member_data", member_id= f"{network.consortium.get_member_by_local_id('member0').service_id}", member_data={"is_admin": True}, )) r = c.post("/gov/proposals.js", valid_set_member_data) assert r.status_code == 200, r.body.text() valid_rekey_ledger = proposal(action("rekey_ledger")) r = c.post("/gov/proposals.js", valid_rekey_ledger) assert r.status_code == 200, r.body.text() valid_service_open = proposal(action("transition_service_to_open")) r = c.post("/gov/proposals.js", valid_service_open) assert r.status_code == 200, r.body.text() new_user_local_id = "js_user" new_user = network.create_user(new_user_local_id, args.participants_curve) LOG.info(f"Adding new user {new_user.service_id}") with open( os.path.join(network.common_dir, f"{new_user_local_id}_cert.pem"), "r") as cert: valid_new_user = proposal( action("set_user", cert=cert.read(), user_data={"is_admin": True})) r = c.post("/gov/proposals.js", valid_new_user) assert r.status_code == 200, r.body.text() return network
def test_multi_auth(network, args): primary, _ = network.find_primary() user = network.users[0] member = network.consortium.members[0] with primary.client(user.local_id) as c: response = c.get("/app/api") supported_methods = response.body.json()["paths"] if "/multi_auth" in supported_methods.keys(): response_bodies = set() def require_new_response(r): assert r.status_code == http.HTTPStatus.OK.value, r.status_code r_body = r.body.text() assert r_body not in response_bodies, r_body response_bodies.add(r_body) LOG.info("Anonymous, no auth") with primary.client() as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a user, via TLS cert") with primary.client(user.local_id) as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as same user, now with user data") network.consortium.set_user_data( primary, user.service_id, {"some": ["interesting", "data", 42]} ) with primary.client(user.local_id) as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a different user, via TLS cert") with primary.client("user1") as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a member, via TLS cert") with primary.client(member.local_id) as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as same member, now with user data") network.consortium.set_member_data( primary, member.service_id, {"distinct": {"arbitrary": ["data"]}} ) with primary.client(member.local_id) as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a different member, via TLS cert") with primary.client("member1") as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a user, via HTTP signature") with primary.client(None, user.local_id) as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a member, via HTTP signature") with primary.client(None, member.local_id) as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as user2 but sign as user1") with primary.client("user2", "user1") as c: r = c.get("/app/multi_auth") require_new_response(r) network.create_user("user5", args.participants_curve, record=False) LOG.info("Authenticate as invalid user5 but sign as valid user3") with primary.client("user5", "user3") as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate via JWT token") jwt_key_priv_pem, _ = infra.crypto.generate_rsa_keypair(2048) jwt_cert_pem = infra.crypto.generate_cert(jwt_key_priv_pem) jwt_kid = "my_key_id" jwt_issuer = "https://example.issuer" # Add JWT issuer with tempfile.NamedTemporaryFile(prefix="ccf", mode="w+") as metadata_fp: jwt_cert_der = infra.crypto.cert_pem_to_der(jwt_cert_pem) der_b64 = base64.b64encode(jwt_cert_der).decode("ascii") data = { "issuer": jwt_issuer, "jwks": { "keys": [{"kty": "RSA", "kid": jwt_kid, "x5c": [der_b64]}] }, } json.dump(data, metadata_fp) metadata_fp.flush() network.consortium.set_jwt_issuer(primary, metadata_fp.name) with primary.client() as c: jwt = infra.crypto.create_jwt({}, jwt_key_priv_pem, jwt_kid) r = c.get("/app/multi_auth", headers={"authorization": "Bearer " + jwt}) require_new_response(r) else: LOG.warning( f"Skipping {inspect.currentframe().f_code.co_name} as application does not implement '/multi_auth'" ) return network
def test_actions(network, args): node = network.find_random_node() # Rekey ledger network.consortium.trigger_ledger_rekey(node) # Add new user twice (with and without user data) new_user_local_id = "js_user" new_user = network.create_user(new_user_local_id, args.participants_curve) LOG.info(f"Adding new user {new_user.service_id}") user_data = None network.consortium.add_user(node, new_user.local_id, user_data) user_data = {"foo": "bar"} network.consortium.add_user(node, new_user.local_id, user_data) with node.client(new_user.local_id) as c: r = c.post("/app/log/private", {"id": 0, "msg": "JS"}) assert r.status_code == 200, r.body.text() # Set user data network.consortium.set_user_data(node, new_user.service_id, user_data={"user": "******"}) network.consortium.set_user_data(node, new_user.service_id, user_data=None) # Remove user network.consortium.remove_user(node, new_user.service_id) with node.client(new_user.local_id) as c: r = c.get("/app/log/private") assert r.status_code == 401, r.body.text() # Set member data network.consortium.set_member_data( node, network.consortium.get_member_by_local_id("member0").service_id, member_data={ "is_operator": True, "is_admin": True }, ) # Set recovery threshold try: network.consortium.set_recovery_threshold(node, recovery_threshold=0) assert False, "Recovery threshold cannot be set to zero" except infra.proposal.ProposalNotCreated as e: assert (e.response.status_code == 400 and e.response.body.json()["error"]["code"] == "ProposalFailedToValidate"), e.response.body.text() try: network.consortium.set_recovery_threshold(node, recovery_threshold=256) assert False, "Recovery threshold cannot be set to > 255" except infra.proposal.ProposalNotCreated as e: assert (e.response.status_code == 400 and e.response.body.json()["error"]["code"] == "ProposalFailedToValidate"), e.response.body.text() try: network.consortium.set_recovery_threshold(node, recovery_threshold=None) assert False, "Recovery threshold value must be passed as proposal argument" except infra.proposal.ProposalNotCreated as e: assert (e.response.status_code == 400 and e.response.body.json()["error"]["code"] == "ProposalFailedToValidate"), e.response.body.text() try: network.consortium.set_recovery_threshold( node, recovery_threshold=len( network.consortium.get_active_recovery_members()) + 1, ) assert ( False ), "Recovery threshold cannot be greater than the number of active recovery members" except infra.proposal.ProposalNotAccepted: pass network.consortium.set_recovery_threshold( node, recovery_threshold=network.consortium.recovery_threshold - 1) # Refresh recovery shares network.consortium.trigger_recovery_shares_refresh(node) # Set member new_member = network.consortium.generate_and_add_new_member( node, args.participants_curve) member_data = {"foo": "bar"} new_member = network.consortium.generate_and_add_new_member( node, args.participants_curve, member_data=member_data) # Remove member network.consortium.remove_member(node, new_member) network.consortium.remove_member(node, new_member) return network
def test_multi_auth(network, args): if args.package == "liblogging": primary, _ = network.find_primary() response_bodies = set() def require_new_response(r): assert r.status_code == http.HTTPStatus.OK.value, r.status_code r_body = r.body.text() assert r_body not in response_bodies, r_body response_bodies.add(r_body) LOG.info("Anonymous, no auth") with primary.client() as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a user, via TLS cert") with primary.client("user0") as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a different user, via TLS cert") with primary.client("user1") as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a member, via TLS cert") with primary.client("member0") as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a different member, via TLS cert") with primary.client("member1") as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a user, via HTTP signature") with primary.client(None, "user0") as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a member, via HTTP signature") with primary.client(None, "member0") as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as user2 but sign as user1") with primary.client("user2", "user1") as c: r = c.get("/app/multi_auth") require_new_response(r) network.create_user(5, args.participants_curve, record=False) LOG.info("Authenticate as invalid user5 but sign as valid user3") with primary.client("user5", "user3") as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate via JWT token") jwt_key_priv_pem, _ = infra.crypto.generate_rsa_keypair(2048) jwt_cert_pem = infra.crypto.generate_cert(jwt_key_priv_pem) jwt_kid = "my_key_id" jwt_issuer = "https://example.issuer" # Add JWT issuer with tempfile.NamedTemporaryFile(prefix="ccf", mode="w+") as metadata_fp: jwt_cert_der = infra.crypto.cert_pem_to_der(jwt_cert_pem) der_b64 = base64.b64encode(jwt_cert_der).decode("ascii") data = { "issuer": jwt_issuer, "jwks": { "keys": [{ "kty": "RSA", "kid": jwt_kid, "x5c": [der_b64] }] }, } json.dump(data, metadata_fp) metadata_fp.flush() network.consortium.set_jwt_issuer(primary, metadata_fp.name) with primary.client() as c: jwt = infra.crypto.create_jwt({}, jwt_key_priv_pem, jwt_kid) r = c.get("/app/multi_auth", headers={"authorization": "Bearer " + jwt}) require_new_response(r) return network
def test_multi_auth(network, args): primary, _ = network.find_primary() user = network.users[0] member = network.consortium.members[0] with primary.client(user.local_id) as c: response = c.get("/app/api") supported_methods = response.body.json()["paths"] if "/multi_auth" in supported_methods.keys(): response_bodies = set() def require_new_response(r): assert r.status_code == http.HTTPStatus.OK.value, r.status_code r_body = r.body.text() assert r_body not in response_bodies, r_body response_bodies.add(r_body) LOG.info("Anonymous, no auth") with primary.client() as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a user, via TLS cert") with primary.client(user.local_id) as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as same user, now with user data") network.consortium.set_user_data( primary, user.service_id, {"some": ["interesting", "data", 42]} ) with primary.client(user.local_id) as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a different user, via TLS cert") with primary.client("user1") as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a member, via TLS cert") with primary.client(member.local_id) as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as same member, now with user data") network.consortium.set_member_data( primary, member.service_id, {"distinct": {"arbitrary": ["data"]}} ) with primary.client(member.local_id) as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a different member, via TLS cert") with primary.client("member1") as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a user, via HTTP signature") with primary.client(None, user.local_id) as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as a member, via HTTP signature") with primary.client(None, member.local_id) as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate as user2 but sign as user1") with primary.client("user2", "user1") as c: r = c.get("/app/multi_auth") require_new_response(r) network.create_user("user5", args.participants_curve, record=False) LOG.info("Authenticate as invalid user5 but sign as valid user3") with primary.client("user5", "user3") as c: r = c.get("/app/multi_auth") require_new_response(r) LOG.info("Authenticate via JWT token") jwt_issuer = infra.jwt_issuer.JwtIssuer() jwt_issuer.register(network) jwt = jwt_issuer.issue_jwt(claims={"user": "******"}) with primary.client() as c: r = c.get("/app/multi_auth", headers={"authorization": "Bearer " + jwt}) require_new_response(r) LOG.info("Authenticate via second JWT token") jwt2 = jwt_issuer.issue_jwt(claims={"user": "******"}) with primary.client( common_headers={"authorization": "Bearer " + jwt2} ) as c: r = c.get("/app/multi_auth") require_new_response(r) else: LOG.warning( f"Skipping {inspect.currentframe().f_code.co_name} as application does not implement '/multi_auth'" ) return network