Secure your API with these 16 Practices with Apache - part 1

admin 2 2025-01-13 编辑

Secure your API with these 16 Practices with Apache  - part 1

A couple of months ago, I stumbled upon this list of Secure your API with these 16 practices to secure your API:

While it's debatable whether some points relate to security, e.g.,, versioning, the list is a good starting point anyway. In this two-post series, I'd like to describe how we can implement each point with Apache APISXI (or not).

Authentication​

Authentication is about identifying yourself with a system. It requires a proof.

Apache provides two kinds of authentications: internal, with checking credentials, and external, when delegated to a third party. All authentication mechanisms work via plugins. Here's the current list of available authentication plugins.

TypeNameDescription
Internalkey-authAuthenticate via an HTTP Header
basic-authRelies on a browser callback
jwt-authUses a JWT token to authenticate
Externalauthz-keycloakDelegates to Keycloak
authz-casdoorDelegates to Casdoor
wolf-rbacDelegates to wolf
openid-connectDelegates to an OpenID Connect-compliant third-party
cas-authDelegates to a CAS-compliant third-party
hmac-authDelegates to an HMAC-compliant third-party
authz-casbinDelegates to a Lua Casbin-compliant third-party
ldap-authDelegates to an LDAP
opaDelegates to an Open Policy Agent endpoint
forward-authForwards the authentication to a third-party endpoint

assigns authenticated calls to a consumer. For example, we can create a consumer authenticated with the key-auth plugin:

consumers:  - username: john    plugins:      key-auth:        key: mykey

Every request containing the header apikey with the key mykey will be assigned to the consumer john.

Authorization​

Authentication alone isn't enough. Once a request to a URL has been authenticated, we need to decide whether it's allowed to proceed further. That's the role of authorization.

Authorization [...] is the function of specifying access rights/privileges to resources, which is related to general information security and computer security, and to access control in particular. More formally, "to authorize" is to define an access policy.

-- Authorization on Wikipedia

Apache implements authorization mainly via the consumer-restriction plugin. Here's the most straightforward usage of the consumer-restriction plugin:

consumers:  - username: johndoe                     #1    plugins:      keyauth:        key: mykeyroutes:  - upstream_id: 1                        #2    plugins:      keyauth: ~      consumer-restriction:        whitelist:                        #3          - johndoe
  1. Define a consumer
  2. Reference an already existing upstream
  3. Only allows defined consumers to access the route

Most real-world authorization models avoid binding an identity directly to a permission. They generally bind a group (and even a role) so that it becomes easier to manage many identities. Apache provides the consumer group abstraction for this.

consumer_groups:  - id: accountants                      #1consumers:  - username: johndoe    group_id: accountants                #2    plugins:      keyauth:        key: mykeyroutes:  - upstream_id: 1    plugins:      keyauth: ~      consumer-restriction:        type: consumer_group_id          #3        whitelist:          - accountants
  1. Define a consumer group
  2. Assign the consumer to the previously defined consumer group
  3. Restrict the access to members of the defined consumer group, i.e., accountants

Input validation​

With Apache , you can define a set of JSON schemas and validate a request against any of them. My colleague Navendu has written an exhaustive blog post on the subject: Your API Requests Should Be Validated.

I think it's not the API Gateway's responsibility to handle request validation. Each upstream has specific logic, and moving the validation responsibility from the upstream to the Gateway ties the latter to the logic for no actual benefit.

In any case, the checkbox is ticked.

IP Whitelisting​

Apache implements IP Whitelisting via the ip-restriction plugin. You can define either regular IPs or CIDR blocks.

routes:  - upstream_id: 1    plugins:      ip-restriction:        whitelist:          - 127.0.0.1          - 13.74.26.106/24

Logging and Monitoring​

Logging and Monitoring fall into the broader Observability category, also encompassing Tracing. Apache offers a broad range of Observability plugins in each category.

TypeNameDescription
TracingzipkinCollect and send traces according to the Zipkin specification
skywalkingIntegrate with the Apache SkyWalking project
opentelemetryReport data according to the OpenTelemetry specification
MetricsprometheusExpose metrics in the Prometheus format
node-statusExpose metrics in JSON format
datadogIntegrate with Datadog
Loggingfile-loggerPush log streams to a local file
syslogPush logs to a Syslog server
http-loggerPush JSON-encoded logs to an HTTP server
tcp-loggerPush JSON-encoded logs to a TCP server
udp-loggerPush JSON-encoded logs to a UDP server
kafka-loggerPush JSON-encoded logs to a Kafka cluster
rocketmq-loggerPush JSON-encoded logs to a RocketMQ cluster
loki-loggerPush JSON-encoded logs to a Loki instance
splunk-hec-loggingPush logs to a Splunk instance
logglyPush logs to a Loggly instance
elasticsearch-loggerPush logs to an Elasticsearch instance
sls-loggerPush logs to Alibaba Cloud Log Service
google-cloud-loggingPush access logs to Google Cloud Logging Service
tencent-cloud-clsPush access logs to Tencent Cloud CLS

Rate Limiting​

Rate Limiting protects upstreams from Distributed Denial of Services attacks, a.k.a DDoS. It's one of the main features of reverse proxies and API Gateways. implements rate limiting through three different plugins:

  • The limit-conn Plugin limits the number of concurrent requests to your services
  • The limit-req Plugin limits the number of requests to your service using the leaky bucket algorithm
  • The limit-count Plugin limits the number of requests to your service by a given count per time. The plugin is using Fixed Window algorithm

Let's use limit-count for the sake of example:

routes:  - upstream_id: 1    plugins:      limit-count:        count: 10        time_window: 1        rejected_code: 429

The above configuration snippet protects the upstream from being hit by more than ten requests per second. It applies to every IP address because of the default configuration. The complete snippet would look like the following:

routes:  - upstream_id: 1    plugins:      limit-count:        count: 10        time_window: 1        rejected_code: 429        key_type: var        key: remote_addr

When dealing with APIs, there's a considerable chance you want to differentiate between your clients. Some might get a better rate for different reasons: they paid a premium offer; they are considered strategic; they are internal clients, etc. The same consumer could also use different IP addresses because they run on various machines with other APIs. Allowing the same consumer more calls because they execute their requests on a distributed infrastructure would be unfair.

As it stands, the IP is not a great way to assign the limit; we prefer to use a named consumer or, even better, a consumer group. It's perfectly possible with :

consumer_groups:  - id: basic    plugins:      limit-count:        count: 1        time_window: 1        <span class="token key atrule" style="color: rgb(0, 164, 

Secure your API with these 16 Practices with Apache - part 1

上一篇: Understanding the Significance of 3.4 as a Root in Mathematics
下一篇: integrate with Kafka for real-time log monitoring
相关文章