TykTechnologies / tyk

Tyk Open Source API Gateway written in Go, supporting REST, GraphQL, TCP and gRPC protocols
Other
9.55k stars 1.07k forks source link

[TT-2367] - Disabling API Rate-Limiter should not disable policy limits #2716

Open asoorm opened 4 years ago

asoorm commented 4 years ago

Branch/Environment/Version

all

Describe the bug

The purpose of API rate-limits are to protect the upstream services of becoming overloaded. If we do not wish to protect the upstreams, we can disable the API rate-limiter.

Despite the above, we should still be able to apply policy rate-limits. As they are two different limiters.

Screenshot 2019-12-05 at 22 44 33

As an aside - the above-mentioned dashboard messaging is particularly confusing.

Further, it is specified in the documentation:

Note: Disabling the rate limiter at the global level does not disable the rate limiting at the key level. Tyk will enforce the rate limit at the key level regardless of this setting.

https://tyk.io/docs/control-limit-traffic/rate-limiting/#can-i-disable-the-rate-limiter

Screenshot 2019-12-05 at 22 47 17

Reproduction steps

  1. Add api, apply authentication and disable rate-limits.
  2. Create a policy, granting access rights to this api, with a rate-limit. e.g. 5 requests per 60s
API Definition

```json { "api_model": {}, "api_definition": { "api_id": "f2c27e790c9d4b2776752ad3e7ba0ea3", "jwt_issued_at_validation_skew": 0, "upstream_certificates": {}, "use_keyless": false, "enable_coprocess_auth": false, "base_identity_provided_by": "", "custom_middleware": { "pre": [], "post": [], "post_key_auth": [], "auth_check": { "name": "", "path": "", "require_session": false, "raw_body_only": false }, "response": [], "driver": "", "id_extractor": { "extract_from": "", "extract_with": "", "extractor_config": {} } }, "disable_quota": false, "custom_middleware_bundle": "", "cache_options": { "cache_timeout": 60, "enable_cache": true, "cache_all_safe_requests": false, "cache_response_codes": [], "enable_upstream_cache_control": false, "cache_control_ttl_header": "" }, "enable_ip_blacklisting": false, "tag_headers": [], "jwt_scope_to_policy_mapping": {}, "pinned_public_keys": {}, "expire_analytics_after": 0, "domain": "", "openid_options": { "providers": [], "segregate_by_client": false }, "jwt_policy_field_name": "", "enable_proxy_protocol": false, "jwt_default_policies": [], "active": true, "jwt_expires_at_validation_skew": 0, "config_data": {}, "notifications": { "shared_secret": "", "oauth_on_keychange_url": "" }, "jwt_client_base_field": "", "auth": { "use_param": false, "param_name": "", "use_cookie": false, "cookie_name": "", "auth_header_name": "Authorization", "use_certificate": false, "validate_signature": false, "signature": { "algorithm": "", "header": "", "secret": "", "allowed_clock_skew": 0, "error_code": 0, "error_message": "" } }, "check_host_against_uptime_tests": false, "auth_provider": { "name": "", "storage_engine": "", "meta": {} }, "blacklisted_ips": [], "hmac_allowed_clock_skew": -1, "dont_set_quota_on_create": false, "uptime_tests": { "check_list": [], "config": { "expire_utime_after": 0, "service_discovery": { "use_discovery_service": false, "query_endpoint": "", "use_nested_query": false, "parent_data_path": "", "data_path": "", "cache_timeout": 60 }, "recheck_wait": 0 } }, "enable_jwt": false, "do_not_track": false, "name": "rl-test", "slug": "rl-test", "oauth_meta": { "allowed_access_types": [], "allowed_authorize_types": [], "auth_login_redirect": "" }, "CORS": { "enable": false, "max_age": 24, "allow_credentials": false, "exposed_headers": [], "allowed_headers": [], "options_passthrough": false, "debug": false, "allowed_origins": [], "allowed_methods": [] }, "event_handlers": { "events": {} }, "proxy": { "target_url": "http://httpbin.org/", "service_discovery": { "endpoint_returns_list": false, "cache_timeout": 0, "parent_data_path": "", "query_endpoint": "", "use_discovery_service": false, "_sd_show_port_path": false, "target_path": "", "use_target_list": false, "use_nested_query": false, "data_path": "", "port_data_path": "" }, "check_host_against_uptime_tests": false, "transport": { "ssl_insecure_skip_verify": false, "ssl_ciphers": [], "ssl_min_version": 0, "proxy_url": "" }, "target_list": [], "preserve_host_header": false, "strip_listen_path": true, "enable_load_balancing": false, "listen_path": "/rl-test/", "disable_strip_slash": false }, "client_certificates": [], "use_basic_auth": false, "version_data": { "not_versioned": true, "default_version": "", "versions": { "Default": { "name": "Default", "expires": "", "paths": { "ignored": [], "white_list": [], "black_list": [] }, "use_extended_paths": true, "extended_paths": { "ignored": [], "white_list": [], "black_list": [], "transform": [], "transform_response": [], "transform_jq": [], "transform_jq_response": [], "transform_headers": [], "transform_response_headers": [], "hard_timeouts": [], "circuit_breakers": [], "url_rewrites": [], "virtual": [], "size_limits": [], "method_transforms": [], "track_endpoints": [], "do_not_track_endpoints": [], "validate_json": [], "internal": [] }, "global_headers": {}, "global_headers_remove": [], "global_size_limit": 0, "override_target": "" } } }, "jwt_scope_claim_name": "", "use_standard_auth": true, "session_lifetime": 0, "hmac_allowed_algorithms": [], "disable_rate_limit": true, "definition": { "location": "header", "key": "x-api-version", "strip_path": false }, "use_oauth2": false, "jwt_source": "", "jwt_signing_method": "", "jwt_not_before_validation_skew": 0, "use_go_plugin_auth": false, "jwt_identity_base_field": "", "allowed_ips": [], "request_signing": { "is_enabled": false, "secret": "", "key_id": "", "algorithm": "", "header_list": [], "certificate_id": "" }, "org_id": "5d67b96d767e02015ea84a6f", "enable_ip_whitelisting": false, "global_rate_limit": { "rate": 0, "per": 0 }, "protocol": "", "enable_context_vars": false, "tags": [], "basic_auth": { "disable_caching": false, "cache_ttl": 0, "extract_from_body": false, "body_user_regexp": "", "body_password_regexp": "" }, "listen_port": 0, "session_provider": { "name": "", "storage_engine": "", "meta": {} }, "auth_configs": {}, "strip_auth_data": false, "id": "5de8f007767e0271d0246620", "certificates": [], "enable_signature_checking": false, "use_openid": false, "internal": false, "jwt_skip_kid": false, "enable_batch_request_support": false, "response_processors": [], "use_mutual_tls_auth": false }, "hook_references": [], "is_site": false, "sort_by": 0, "user_group_owners": [], "user_owners": [] } ```

Policy

```json { "_id" : ObjectId("5de8f01b767e0271d0246621"), "org_id" : "5d67b96d767e02015ea84a6f", "rate" : 5.0, "per" : 60.0, "throttle_interval" : -1.0, "throttle_retry_limit" : -1, "quota_max" : NumberLong(-1), "quota_renewal_rate" : NumberLong(3600), "access_rights" : { "f2c27e790c9d4b2776752ad3e7ba0ea3" : { "apiname" : "rl-test", "apiid" : "f2c27e790c9d4b2776752ad3e7ba0ea3", "versions" : [ "Default" ], "allowed_urls" : [], "limit" : null, "allowance_scope" : "" } }, "hmac_enabled" : false, "active" : true, "name" : "rl-test", "is_inactive" : false, "date_created" : ISODate("2019-12-05T11:55:07.795Z"), "tags" : [], "key_expires_in" : NumberLong(0), "partitions" : { "quota" : false, "rate_limit" : false, "acl" : false, "per_api" : false }, "last_updated" : "1575546907" } ```

Create and test Key

```bash $ for i in {0..6}; do curl -Is localhost:8080/rl-test/get -H 'Authorization: 5d67b96d767e02015ea84a6f7016fd73c0504a1a9c937426d8751911'| grep HTTP; done HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK ```

Actual behavior

You can send unlimited requests because the policy rate-limiter has also been erroneously disabled.

Expected behavior

The key should still be restricted as defined by the rules in the policy.

cc:

@ilijabojanovic

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs, please add comments to this ticket if you would like it to stay open. Thank you for your contributions.

asoorm commented 4 years ago

not stale

ghost commented 4 years ago

I reproduced this by creating an API with "disable_rate_limit": true and a Key that has a rate limit configuration:

{
    "access_rights": {
        "api-mock": {
            "api_id": "api-mock",
            "api_name": "Test - api-mock",
            "versions": ["Default"]
        }
    },
    "rate": 5,
    "per": 1
}

It works as expected only if the API is defined this way:

"disable_rate_limit": false,
"global_rate_limit": {
    "rate": 1,
    "per": -1
}