def includeme(config): # Register our login service config.register_service_factory(database_login_factory, IUserService) # Register our token services config.register_service_factory(TokenServiceFactory(name="password"), ITokenService, name="password") config.register_service_factory(TokenServiceFactory(name="email"), ITokenService, name="email") # Register our password breach detection service. config.register_service_factory(hibp_password_breach_factory, IPasswordBreachedService) # Register our authentication and authorization policies config.set_authentication_policy( MultiAuthenticationPolicy([ SessionAuthenticationPolicy(callback=_authenticate), BasicAuthAuthenticationPolicy(check=_login_via_basic_auth), ])) config.set_authorization_policy(ACLAuthorizationPolicy()) # Add a request method which will allow people to access the user object. config.add_request_method(_user, name="user", reify=True) # Register the rate limits that we're going to be using for our login # attempts config.register_service_factory(RateLimit("10 per 5 minutes"), IRateLimiter, name="user.login") config.register_service_factory(RateLimit("1000 per 5 minutes"), IRateLimiter, name="global.login")
def test_eq(self): assert RateLimit("1 per 5 minutes", identifiers=["foo"]) == RateLimit("1 per 5 minutes", identifiers=["foo"]) assert RateLimit("1 per 5 minutes", identifiers=["foo"]) != RateLimit( "1 per 5 minutes", identifiers=["bar"]) assert RateLimit("1 per 5 minutes", identifiers=["foo"]) != object()
def test_includeme(monkeypatch): macaroon_authn_obj = pretend.stub() macaroon_authn_cls = pretend.call_recorder(lambda callback: macaroon_authn_obj) basic_authn_obj = pretend.stub() basic_authn_cls = pretend.call_recorder(lambda check: basic_authn_obj) session_authn_obj = pretend.stub() session_authn_cls = pretend.call_recorder(lambda callback: session_authn_obj) authn_obj = pretend.stub() authn_cls = pretend.call_recorder(lambda *a: authn_obj) authz_obj = pretend.stub() authz_cls = pretend.call_recorder(lambda *a, **kw: authz_obj) monkeypatch.setattr(accounts, "BasicAuthAuthenticationPolicy", basic_authn_cls) monkeypatch.setattr(accounts, "SessionAuthenticationPolicy", session_authn_cls) monkeypatch.setattr(accounts, "MacaroonAuthenticationPolicy", macaroon_authn_cls) monkeypatch.setattr(accounts, "MultiAuthenticationPolicy", authn_cls) monkeypatch.setattr(accounts, "ACLAuthorizationPolicy", authz_cls) monkeypatch.setattr(accounts, "MacaroonAuthorizationPolicy", authz_cls) config = pretend.stub( registry=pretend.stub(settings={}), register_service_factory=pretend.call_recorder( lambda factory, iface, name=None: None ), add_request_method=pretend.call_recorder(lambda f, name, reify: None), set_authentication_policy=pretend.call_recorder(lambda p: None), set_authorization_policy=pretend.call_recorder(lambda p: None), maybe_dotted=pretend.call_recorder(lambda path: path), ) accounts.includeme(config) assert config.register_service_factory.calls == [ pretend.call(database_login_factory, IUserService), pretend.call( TokenServiceFactory(name="password"), ITokenService, name="password" ), pretend.call(TokenServiceFactory(name="email"), ITokenService, name="email"), pretend.call( TokenServiceFactory(name="two_factor"), ITokenService, name="two_factor" ), pretend.call( HaveIBeenPwnedPasswordBreachedService.create_service, IPasswordBreachedService, ), pretend.call(RateLimit("10 per 5 minutes"), IRateLimiter, name="user.login"), pretend.call( RateLimit("1000 per 5 minutes"), IRateLimiter, name="global.login" ), ] assert config.add_request_method.calls == [ pretend.call(accounts._user, name="user", reify=True) ] assert config.set_authentication_policy.calls == [pretend.call(authn_obj)] assert config.set_authorization_policy.calls == [pretend.call(authz_obj)] assert basic_authn_cls.calls == [pretend.call(check=accounts._basic_auth_login)] assert session_authn_cls.calls == [pretend.call(callback=accounts._authenticate)] assert authn_cls.calls == [ pretend.call([session_authn_obj, basic_authn_obj, macaroon_authn_obj]) ] assert authz_cls.calls == [pretend.call(), pretend.call(policy=authz_obj)]
def includeme(config): # Register our login service config.register_service_factory(database_login_factory, IUserService) config.register_service_factory(user_token_factory, IUserTokenService) # Register our authentication and authorization policies config.set_authentication_policy( MultiAuthenticationPolicy([ SessionAuthenticationPolicy(callback=_authenticate), BasicAuthAuthenticationPolicy(check=_login), ]), ) config.set_authorization_policy(ACLAuthorizationPolicy()) # Add a request method which will allow people to access the user object. config.add_request_method(_user, name="user", reify=True) # Register the rate limits that we're going to be using for our login # attempts config.register_service_factory( RateLimit("10 per 5 minutes"), IRateLimiter, name="user.login", ) config.register_service_factory( RateLimit("1000 per 5 minutes"), IRateLimiter, name="global.login", )
def includeme(config): # Register our login service config.register_service_factory(database_login_factory, IUserService) # Register our token services config.register_service_factory( TokenServiceFactory(name="password"), ITokenService, name="password" ) config.register_service_factory( TokenServiceFactory(name="email"), ITokenService, name="email" ) config.register_service_factory( TokenServiceFactory(name="two_factor"), ITokenService, name="two_factor" ) # Register our password breach detection service. breached_pw_class = config.maybe_dotted( config.registry.settings.get( "breached_passwords.backend", HaveIBeenPwnedPasswordBreachedService ) ) config.register_service_factory( breached_pw_class.create_service, IPasswordBreachedService ) # Register our authentication and authorization policies config.set_authentication_policy( MultiAuthenticationPolicy( [ SessionAuthenticationPolicy(callback=_authenticate), BasicAuthAuthenticationPolicy(check=_basic_auth_login), MacaroonAuthenticationPolicy(callback=_authenticate), ] ) ) config.set_authorization_policy( MacaroonAuthorizationPolicy(policy=ACLAuthorizationPolicy()) ) # Add a request method which will allow people to access the user object. config.add_request_method(_user, name="user", reify=True) # Register the rate limits that we're going to be using for our login # attempts config.register_service_factory( RateLimit("10 per 5 minutes"), IRateLimiter, name="user.login" ) config.register_service_factory( RateLimit("1000 per 5 minutes"), IRateLimiter, name="global.login" )
def includeme(config): ratelimit_string = config.registry.settings.get( "warehouse.xmlrpc.client.ratelimit_string" ) config.register_service_factory( RateLimit(ratelimit_string), IRateLimiter, name="xmlrpc.client" )
def includeme(config): config.add_view_deriver(reauth_view, over="rendered_view", under="decorated_view") user_oidc_registration_ratelimit_string = config.registry.settings.get( "warehouse.manage.oidc.user_registration_ratelimit_string" ) config.register_service_factory( RateLimit(user_oidc_registration_ratelimit_string), IRateLimiter, name="user_oidc.provider.register", ) ip_oidc_registration_ratelimit_string = config.registry.settings.get( "warehouse.manage.oidc.ip_registration_ratelimit_string" ) config.register_service_factory( RateLimit(ip_oidc_registration_ratelimit_string), IRateLimiter, name="ip_oidc.provider.register", )
def test_basic(self): limiter_obj = pretend.stub() limiter_class = pretend.call_recorder(lambda *a, **kw: limiter_obj) context = pretend.stub() request = pretend.stub(registry={"ratelimiter.storage": pretend.stub()}) result = RateLimit( "1 per 5 minutes", identifiers=["foo"], limiter_class=limiter_class )(context, request) assert result is limiter_obj assert limiter_class.calls == [ pretend.call( request.registry["ratelimiter.storage"], limit="1 per 5 minutes", identifiers=["foo"], ) ]
def test_basic(self, pyramid_request, metrics): limiter_obj = pretend.stub() limiter_class = pretend.call_recorder(lambda *a, **kw: limiter_obj) context = pretend.stub() pyramid_request.registry["ratelimiter.storage"] = pretend.stub() result = RateLimit("1 per 5 minutes", identifiers=["foo"], limiter_class=limiter_class)(context, pyramid_request) assert result is limiter_obj assert limiter_class.calls == [ pretend.call( pyramid_request.registry["ratelimiter.storage"], limit="1 per 5 minutes", identifiers=["foo"], metrics=metrics, ) ]
def includeme(config): # Register our login service config.register_service_factory(database_login_factory, IUserService) # Register our token services config.register_service_factory(TokenServiceFactory(name="password"), ITokenService, name="password") config.register_service_factory(TokenServiceFactory(name="email"), ITokenService, name="email") config.register_service_factory(TokenServiceFactory(name="two_factor"), ITokenService, name="two_factor") # Register our password breach detection service. breached_pw_class = config.maybe_dotted( config.registry.settings.get("breached_passwords.backend", HaveIBeenPwnedPasswordBreachedService)) config.register_service_factory(breached_pw_class.create_service, IPasswordBreachedService) # Register our security policies (AuthN + AuthZ) authz_policy = TwoFactorAuthorizationPolicy( policy=MacaroonAuthorizationPolicy(policy=ACLAuthorizationPolicy())) config.set_security_policy( MultiSecurityPolicy( [ SessionSecurityPolicy(), BasicAuthSecurityPolicy(), MacaroonSecurityPolicy(), ], authz_policy, )) # Add a request method which will allow people to access the user object. config.add_request_method(_user, name="user", reify=True) # Register the rate limits that we're going to be using for our login # attempts and account creation user_login_ratelimit_string = config.registry.settings.get( "warehouse.account.user_login_ratelimit_string") config.register_service_factory(RateLimit(user_login_ratelimit_string), IRateLimiter, name="user.login") ip_login_ratelimit_string = config.registry.settings.get( "warehouse.account.ip_login_ratelimit_string") config.register_service_factory(RateLimit(ip_login_ratelimit_string), IRateLimiter, name="ip.login") global_login_ratelimit_string = config.registry.settings.get( "warehouse.account.global_login_ratelimit_string") config.register_service_factory(RateLimit(global_login_ratelimit_string), IRateLimiter, name="global.login") email_add_ratelimit_string = config.registry.settings.get( "warehouse.account.email_add_ratelimit_string") config.register_service_factory(RateLimit(email_add_ratelimit_string), IRateLimiter, name="email.add") password_reset_ratelimit_string = config.registry.settings.get( "warehouse.account.password_reset_ratelimit_string") config.register_service_factory(RateLimit(password_reset_ratelimit_string), IRateLimiter, name="password.reset")
def test_includeme(monkeypatch): authz_obj = pretend.stub() authz_cls = pretend.call_recorder(lambda *a, **kw: authz_obj) monkeypatch.setattr(accounts, "ACLAuthorizationPolicy", authz_cls) monkeypatch.setattr(accounts, "MacaroonAuthorizationPolicy", authz_cls) monkeypatch.setattr(accounts, "TwoFactorAuthorizationPolicy", authz_cls) multi_policy_obj = pretend.stub() multi_policy_cls = pretend.call_recorder( lambda ps, authz: multi_policy_obj) monkeypatch.setattr(accounts, "MultiSecurityPolicy", multi_policy_cls) session_policy_obj = pretend.stub() session_policy_cls = pretend.call_recorder(lambda: session_policy_obj) monkeypatch.setattr(accounts, "SessionSecurityPolicy", session_policy_cls) basic_policy_obj = pretend.stub() basic_policy_cls = pretend.call_recorder(lambda: basic_policy_obj) monkeypatch.setattr(accounts, "BasicAuthSecurityPolicy", basic_policy_cls) macaroon_policy_obj = pretend.stub() macaroon_policy_cls = pretend.call_recorder(lambda: macaroon_policy_obj) monkeypatch.setattr(accounts, "MacaroonSecurityPolicy", macaroon_policy_cls) config = pretend.stub( registry=pretend.stub( settings={ "warehouse.account.user_login_ratelimit_string": "10 per 5 minutes", "warehouse.account.ip_login_ratelimit_string": "10 per 5 minutes", "warehouse.account.global_login_ratelimit_string": "1000 per 5 minutes", "warehouse.account.email_add_ratelimit_string": "2 per day", "warehouse.account.password_reset_ratelimit_string": "5 per day", }), register_service_factory=pretend.call_recorder( lambda factory, iface, name=None: None), add_request_method=pretend.call_recorder(lambda f, name, reify: None), set_security_policy=pretend.call_recorder(lambda p: None), maybe_dotted=pretend.call_recorder(lambda path: path), add_route_predicate=pretend.call_recorder(lambda name, cls: None), ) accounts.includeme(config) assert config.register_service_factory.calls == [ pretend.call(database_login_factory, IUserService), pretend.call(TokenServiceFactory(name="password"), ITokenService, name="password"), pretend.call(TokenServiceFactory(name="email"), ITokenService, name="email"), pretend.call(TokenServiceFactory(name="two_factor"), ITokenService, name="two_factor"), pretend.call( HaveIBeenPwnedPasswordBreachedService.create_service, IPasswordBreachedService, ), pretend.call(RateLimit("10 per 5 minutes"), IRateLimiter, name="user.login"), pretend.call(RateLimit("10 per 5 minutes"), IRateLimiter, name="ip.login"), pretend.call(RateLimit("1000 per 5 minutes"), IRateLimiter, name="global.login"), pretend.call(RateLimit("2 per day"), IRateLimiter, name="email.add"), pretend.call(RateLimit("5 per day"), IRateLimiter, name="password.reset"), ] assert config.add_request_method.calls == [ pretend.call(accounts._user, name="user", reify=True) ] assert config.set_security_policy.calls == [pretend.call(multi_policy_obj)] assert multi_policy_cls.calls == [ pretend.call( [session_policy_obj, basic_policy_obj, macaroon_policy_obj], authz_obj) ]