Secure your API with these 16 practices

A few months ago, I stumbled upon this list of 16 practices for securing your API:

  1. Certification: Verifies the identity of users accessing APIs.
  2. Authorization: Specifies the permissions of authenticated users.
  3. Data editing: Hides sensitive data for protection.
  4. Encryption: It encodes data so that only authorized parties can decode it.
  5. Troubleshooting: Manages responses when things go wrong, avoiding disclosure of sensitive information.
  6. Data entry validation and correction: It checks the input data and removes harmful parts.
  7. Intrusion detection systems: Monitor networks for suspicious activity.
  8. List of allowed IP addresses: Allows API access only from trusted IP addresses.
  9. Recording and monitoring: Keeps detailed logs and regularly monitors APIs.
  10. Speed ​​limit: Limits user requests to prevent overload.
  11. Safe dependencies: It ensures that there are no third-party vulnerabilities.
  12. Security headers: Improves website security against types of attacks such as XSS.
  13. Token Expiration: Regularly expiring and renewing tokens prevent unauthorized access.
  14. Using security standards and frameworks: It guides your API security strategy.
  15. Web application firewall: Protects your site from HTTP-specific attacks.
  16. API versions: It maintains different versions of your API for seamless updates.

Although it is debatable whether some points refer to safety, for example versions, 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 APISIX (or not).

Certification

Authentication is about identifying yourself with the system. Proof is needed.

Apache APISIX provides two types of authentication: internal, with APISIX to verify credentials, and external, when delegated to a third party. All authentication mechanisms work through plugins. Here is the current list of available authentication plugins.

Type Name Description
Internal key-auth Authentication via HTTP headers
basic-auth It relies on a browser callback
jwt-auth It uses a JWT token for authentication
External authz-keycloak Delegates to Keycloak
authz-casdoor Delegates at Casdoor
wolf-rbac Delegates pull
openid-connect It delegates to a third party that is compatible with OpenID Connect
cas-auth Delegates to a CAS compliant third party
hmac-auth Delegates to an HMAC compliant third party
authz-casbin It delegates to a third party that is compatible with Lua Casbin
ldap-auth Delegates to LDAP
opa Delegates the Open Policy Agent endpoint
forward-auth Forwards authentication to a third-party endpoint

APISIX grants authenticated calls a consumer. For example, we can create a consumer authenticated with key-auth include:

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

Any request that contains a header apikey with a key mykey will be assigned to the consumer john.

Authorization

Authentication alone is not enough. Once the URL request has been validated, we need to decide if it is allowed to continue. That is the role of authority.

Authorization […] is the function of determining the rights/privileges of access to resources, which refers to general information security and computer security, and in particular to access control. More formally, “authorize” means to define an access policy.

— Authorization on Wikipedia

Apache APISIX enforces authorization mainly through the consumer restriction plugin. Here is the simplest use consumer-restriction include:

consumers:
  - username: johndoe                     #1
    plugins:
      keyauth:
        key: mykey

routes:
  - upstream_id: 1                        #2
    plugins:
      keyauth: ~
      consumer-restriction:
        whitelist:                        #3
          - johndoe               

  1. Define the consumer
  2. Referencing a pre-existing upstream
  3. It allows only defined consumers to access the route

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

consumer_groups:
  - id: accountants                      #1

consumers:
  - username: johndoe
    group_id: accountants                #2
    plugins:
      keyauth:
        key: mykey

routes:
  - upstream_id: 1
    plugins:
      keyauth: ~
      consumer-restriction:
        type: consumer_group_id          #3
        whitelist:
          - accountants

  1. Define the consumer group
  2. Assign the consumer to a previously defined group of consumers
  3. Restrict access to members of a defined group of consumers, i.e, accountants

Input validation

With Apache APISIX, you can define a set of JSON schemas and validate a request against any of them. My colleague Navendu wrote a comprehensive blog post on the topic: Your API requests should be validated.

I don’t think API Gateway is responsible for processing requests. Each upstream has specific logic, and moving the responsibility for validation from the upstream to the Gateway binds the latter to logic with no real benefit.

Either way, the checkbox is checked.

List of allowed IP addresses

Apache APISIX implements IP whitelisting via the ip-limit plugin. You can define common IP addresses or CIDR blocks.

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

Logging and tracking

Logging and monitoring fall into the broader Noticeability category, which also includes Tracing. Apache APISIX offers a wide range of monitoring plugins in each category.

Type Name Description
Tracing zipkin Collect and send traces according to the Zipkin specification
skywalking Integrate with the Apache SkyWalking project
opentelemetry Report data according to the OpenTelemetry specification
Metrics prometheus Expose metrics in Prometheus format
node-status Expose metrics in JSON format
datadog Integrate with Datadog
Cutting wood file-logger Push log streams to a local file
syslog Push logs to Syslog server
http-logger Push JSON encoded logs to HTTP server
tcp-logger Push JSON encoded logs to TCP server
udp-logger Push JSON encoded logs to UDP server
kafka-logger Push JSON encoded logs to Kafka cluster
rocketmq-logger Push JSON-encoded records to the RocketMQ cluster
loki-logger Push JSON-encoded logs to a Loki instance
splunk-hec-logging Push logs to a Splunk instance
loggly Push logs to a Loggly instance
elasticsearch-logger Push the logs to the Elasticsearch instance
sls-logger Push logs to Alibaba Cloud Log Service
google-cloud-logging Push access logs to Google Cloud Logging Service
tencent-cloud-cls Push access logs to Tencent Cloud CLS

Rate limit

Rate limiting protects upstream channels from Distributed Denial of Services attacks, aka DDoS. This is one of the main features of reverse proxies and API gateways. APISIX 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
  • A capping plugin limits the number of requests to your service to a specific number at a time. Supplement uses Fixed window algorithm

Let’s take advantage limit-count for example:

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

The above configuration snippet protects the upstream from more than ten requests per second. It is applied to every IP address due to the default configuration. The complete snippet would look like this:

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

When working with APIs, chances are you want to differentiate your customers. Some might get a better price for different reasons: they paid a premium offer, are considered strategic, are internal clients, etc. The same consumer can also use different IP addresses because they are running on different machines with different APIs. It would be unfair to allow the same user to make multiple calls because they are executing their requests on a distributed infrastructure.

As it stands, IP is not a good way to assign restrictions; we prefer to use a named consumer or, even better, a group of consumers. With APISIX this is perfectly possible:

consumer_groups:
  - id: basic
    plugins:
      limit-count:
        count: 1
        time_window: 1
        rejected_code: 429
  - id: premium
    plugins:
      limit-count:
        count: 10
        time_window: 1
        rejected_code: 429

consumers:
  - username: johndoe
    group_id: basic
    plugins:
      keyauth:
        key: mykey1
  - username: janedoe
    group_id: premium
    plugins:
      keyauth:
        key: mykey2

routes:
  - upstream_id: 1
    plugins:
      key-auth: ~

Now, johndoe it can only send a request every second, because it is a part basic to plan while janedoe can claim ten times more as part of a premium plan.

Conclusion

We’ve seen how to configure Apache APISIX to protect your APIs from 7 of the 16 rules in the original list. The remaining rules may be less easy to implement; we’ll cover them in another installment.

Source link

Leave a Reply

Your email address will not be published. Required fields are marked *