def test_tracing_interceptor_auth_cookies(db): user, token = generate_user() account = Account() rpc_def = { "rpc": account.GetAccountInfo, "service_name": "org.couchers.api.account.Account", "method_name": "GetAccountInfo", "interceptors": [TracingInterceptor(), AuthValidatorInterceptor()], "request_type": empty_pb2.Empty, "response_type": account_pb2.GetAccountInfoRes, } # with cookies with interceptor_dummy_api(**rpc_def, creds=grpc.local_channel_credentials()) as call_rpc: res1 = call_rpc(empty_pb2.Empty(), metadata=(("cookie", f"couchers-sesh={token}"),)) assert res1.username == user.username with session_scope() as session: trace = session.execute(select(APICall)).scalar_one() assert trace.method == "/org.couchers.api.account.Account/GetAccountInfo" assert not trace.status_code assert trace.user_id == user.id assert not trace.is_api_key assert len(trace.request) == 0 assert not trace.traceback
def test_tracing_interceptor_auth_api_key(db): super_user, super_token = generate_user(is_superuser=True) user, token = generate_user() with real_admin_session(super_token) as api: api.CreateApiKey(admin_pb2.CreateApiKeyReq(user=user.username)) with session_scope() as session: api_session = session.execute(select(UserSession).where(UserSession.is_api_key == True)).scalar_one() api_key = api_session.token account = Account() rpc_def = { "rpc": account.GetAccountInfo, "service_name": "org.couchers.api.account.Account", "method_name": "GetAccountInfo", "interceptors": [TracingInterceptor(), AuthValidatorInterceptor()], "request_type": empty_pb2.Empty, "response_type": account_pb2.GetAccountInfoRes, } # with api key with interceptor_dummy_api(**rpc_def, creds=grpc.local_channel_credentials()) as call_rpc: res1 = call_rpc(empty_pb2.Empty(), metadata=(("authorization", f"Bearer {api_key}"),)) assert res1.username == user.username with session_scope() as session: trace = session.execute(select(APICall)).scalar_one() assert trace.method == "/org.couchers.api.account.Account/GetAccountInfo" assert not trace.status_code assert trace.user_id == user.id assert trace.is_api_key assert len(trace.request) == 0 assert not trace.traceback
def account_session(token): """ Create a Account API for testing, uses the token for auth """ channel = fake_channel(token) account_pb2_grpc.add_AccountServicer_to_server(Account(), channel) yield account_pb2_grpc.AccountStub(channel)
def account_session(db, token): """ Create a Account API for testing, uses the token for auth """ auth_interceptor = Auth(db).get_auth_interceptor(allow_jailed=False) user_id, jailed = Auth(db).get_session_for_token(token) channel = FakeChannel(user_id=user_id) account_pb2_grpc.add_AccountServicer_to_server(Account(db), channel) yield account_pb2_grpc.AccountStub(channel)
def create_main_server(port): server = grpc.server( futures.ThreadPoolExecutor(SERVER_THREADS), interceptors=[ ErrorSanitizationInterceptor(), TracingInterceptor(), AuthValidatorInterceptor(), ], ) server.add_insecure_port(f"[::]:{port}") account_pb2_grpc.add_AccountServicer_to_server(Account(), server) admin_pb2_grpc.add_AdminServicer_to_server(Admin(), server) api_pb2_grpc.add_APIServicer_to_server(API(), server) auth_pb2_grpc.add_AuthServicer_to_server(Auth(), server) blocking_pb2_grpc.add_BlockingServicer_to_server(Blocking(), server) bugs_pb2_grpc.add_BugsServicer_to_server(Bugs(), server) communities_pb2_grpc.add_CommunitiesServicer_to_server( Communities(), server) conversations_pb2_grpc.add_ConversationsServicer_to_server( Conversations(), server) discussions_pb2_grpc.add_DiscussionsServicer_to_server( Discussions(), server) donations_pb2_grpc.add_DonationsServicer_to_server(Donations(), server) events_pb2_grpc.add_EventsServicer_to_server(Events(), server) gis_pb2_grpc.add_GISServicer_to_server(GIS(), server) groups_pb2_grpc.add_GroupsServicer_to_server(Groups(), server) jail_pb2_grpc.add_JailServicer_to_server(Jail(), server) notifications_pb2_grpc.add_NotificationsServicer_to_server( Notifications(), server) pages_pb2_grpc.add_PagesServicer_to_server(Pages(), server) references_pb2_grpc.add_ReferencesServicer_to_server(References(), server) reporting_pb2_grpc.add_ReportingServicer_to_server(Reporting(), server) requests_pb2_grpc.add_RequestsServicer_to_server(Requests(), server) resources_pb2_grpc.add_ResourcesServicer_to_server(Resources(), server) search_pb2_grpc.add_SearchServicer_to_server(Search(), server) stripe_pb2_grpc.add_StripeServicer_to_server(Stripe(), server) threads_pb2_grpc.add_ThreadsServicer_to_server(Threads(), server) return server
def test_auth_interceptor(db): super_user, super_token = generate_user(is_superuser=True) user, token = generate_user() with real_admin_session(super_token) as api: api.CreateApiKey(admin_pb2.CreateApiKeyReq(user=user.username)) with session_scope() as session: api_session = session.execute(select(UserSession).where(UserSession.is_api_key == True)).scalar_one() api_key = api_session.token account = Account() rpc_def = { "rpc": account.GetAccountInfo, "service_name": "org.couchers.api.account.Account", "method_name": "GetAccountInfo", "interceptors": [AuthValidatorInterceptor()], "request_type": empty_pb2.Empty, "response_type": account_pb2.GetAccountInfoRes, } # no creds, no go for secure APIs with interceptor_dummy_api(**rpc_def, creds=grpc.local_channel_credentials()) as call_rpc: with pytest.raises(grpc.RpcError) as e: call_rpc(empty_pb2.Empty()) assert e.value.code() == grpc.StatusCode.UNAUTHENTICATED assert e.value.details() == "Unauthorized" # can auth with cookie with interceptor_dummy_api(**rpc_def, creds=grpc.local_channel_credentials()) as call_rpc: res1 = call_rpc(empty_pb2.Empty(), metadata=(("cookie", f"couchers-sesh={token}"),)) assert res1.username == user.username # can't auth with wrong cookie with interceptor_dummy_api(**rpc_def, creds=grpc.local_channel_credentials()) as call_rpc: with pytest.raises(grpc.RpcError) as e: call_rpc(empty_pb2.Empty(), metadata=(("cookie", f"couchers-sesh={random_hex(32)}"),)) assert e.value.code() == grpc.StatusCode.UNAUTHENTICATED assert e.value.details() == "Unauthorized" # can auth with api key with interceptor_dummy_api(**rpc_def, creds=grpc.local_channel_credentials()) as call_rpc: res2 = call_rpc(empty_pb2.Empty(), metadata=(("authorization", f"Bearer {api_key}"),)) assert res2.username == user.username # can't auth with wrong api key with interceptor_dummy_api(**rpc_def, creds=grpc.local_channel_credentials()) as call_rpc: with pytest.raises(grpc.RpcError) as e: call_rpc(empty_pb2.Empty(), metadata=(("authorization", f"Bearer {random_hex(32)}"),)) assert e.value.code() == grpc.StatusCode.UNAUTHENTICATED assert e.value.details() == "Unauthorized" # can auth with grpc helper (they do the same as above) comp_creds = grpc.composite_channel_credentials( grpc.local_channel_credentials(), grpc.access_token_call_credentials(api_key) ) with interceptor_dummy_api(**rpc_def, creds=comp_creds) as call_rpc: res3 = call_rpc(empty_pb2.Empty()) assert res3.username == user.username # can't auth with both with interceptor_dummy_api(**rpc_def, creds=grpc.local_channel_credentials()) as call_rpc: with pytest.raises(grpc.RpcError) as e: call_rpc( empty_pb2.Empty(), metadata=( ("cookie", f"couchers-sesh={token}"), ("authorization", f"Bearer {api_key}"), ), ) assert e.value.code() == grpc.StatusCode.UNAUTHENTICATED assert e.value.details() == 'Both "cookie" and "authorization" in request' # malformed bearer with interceptor_dummy_api(**rpc_def, creds=grpc.local_channel_credentials()) as call_rpc: with pytest.raises(grpc.RpcError) as e: call_rpc(empty_pb2.Empty(), metadata=(("authorization", f"bearer {api_key}"),)) assert e.value.code() == grpc.StatusCode.UNAUTHENTICATED assert e.value.details() == "Unauthorized"
jailed_server.add_insecure_port("[::]:1754") jail_pb2_grpc.add_JailServicer_to_server(Jail(), jailed_server) jailed_server.start() servicer = API() server = grpc.server( futures.ThreadPoolExecutor(2), interceptors=[ ErrorSanitizationInterceptor(), LoggingInterceptor(), auth.get_auth_interceptor(allow_jailed=False), ], ) server.add_insecure_port("[::]:1751") account_pb2_grpc.add_AccountServicer_to_server(Account(), server) api_pb2_grpc.add_APIServicer_to_server(servicer, server) communities_pb2_grpc.add_CommunitiesServicer_to_server( Communities(), server) conversations_pb2_grpc.add_ConversationsServicer_to_server( Conversations(), server) discussions_pb2_grpc.add_DiscussionsServicer_to_server( Discussions(), server) gis_pb2_grpc.add_GISServicer_to_server(GIS(), server) groups_pb2_grpc.add_GroupsServicer_to_server(Groups(), server) pages_pb2_grpc.add_PagesServicer_to_server(Pages(), server) references_pb2_grpc.add_ReferencesServicer_to_server(References(), server) requests_pb2_grpc.add_RequestsServicer_to_server(Requests(), server) search_pb2_grpc.add_SearchServicer_to_server(Search(), server) threads_pb2_grpc.add_ThreadsServicer_to_server(Threads(), server)