Git Product home page Git Product logo

wallarm / api-firewall Goto Github PK

View Code? Open in Web Editor NEW
556.0 23.0 52.0 1.38 MB

Fast and light-weight API proxy firewall for request and response validation by OpenAPI specs.

Home Page: https://wallarm.github.io/api-firewall/

License: Mozilla Public License 2.0

Smarty 0.51% Go 91.02% Makefile 0.17% Dockerfile 0.15% Shell 0.04% CSS 1.82% JavaScript 6.29%
proxy firewall waf api-gateway apigateway api-wrapper security-tools security api-security api

api-firewall's People

Contributors

afr1ka avatar alexeypetrov13 avatar anastasiatww avatar bonakodo-eric avatar cspf-founder avatar d0znpp avatar maximbashurov avatar mreccowallarm avatar stepan-3 avatar svkirillov avatar xdmitriev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

api-firewall's Issues

Bypass Upstream Certificate Checking

Is there a configuration parameter to bypass the certificate validity checking for upstream / proxied APIs?

This is the error I am getting
{"level":"error","msg":"#0000000100000001 : error while proxying request: x509: certificate is valid for abc.xyz.net not abc","time":"2021-11-17T10:44:07Z"}

This would be helpful for self signed certificates and networks that are not directly internet accessible.

The error "method or path not found in the OpenAPI" occurs when handling requests with the OPTIONS method

Typically, the OPTIONS method is not described in specifications. I suggest allowing OPTIONS requests to be skipped, even if they are not present in the specification.

Message example:
"level":"error","method":"OPTIONS","msg":"method or path not found in the OpenAPI specification","path":"/v1/some/path","request_id":"cf75d489-7ac2-490e-8587-4dbebeaa9f7c","response_length":"0","status_code":200

If you adhere to the belief that OPTIONS requests should be filtered, I suggest introducing a variable to control this behavior.
For example:

Normal mode - OPTIONS requests are ignored (default behavior)
Strict mode - OPTIONS requests must be described in the specification

File upload api being blocked

File upload api is being blocked when it should be allowed. Can you please suggest what can be changed in order to allow this upload?
The spec has it defined as { "/document/upload": { "post": { "tags": [ "document-controller" ], "operationId": "Document_1", "parameters": [ { "name": "id", "in": "query", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "multipart/form-data": { "schema": { "required": [ "file" ], "type": "object", "properties": { "file": { "type": "string", "format": "binary" } } } } } }, "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "string" } } } } } } } }

The error when uploading a docx is api-firewall | time=2021-12-04T17:32:18Z level=error msg=#0000000900000001 : request validation error: request body has an error: failed to decode request body: path file: unsupported content type "application/vnd.openxmlformats-officedocument.wordprocessingml.document"

The content type passed in request header is Content-Type multipart/form-data; boundary=---------------------------162567064334244515552744535554
Request itself is
`-----------------------------162567064334244515552744535554
Content-Disposition: form-data; name="file"; filename="mydoc.docx"
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document

TEST-doc

-----------------------------162567064334244515552744535554--
`

Support for DNS load balancers

There are several methods of load balancing traffic using DNS:

  • Round robin DNS
  • Returning the IP address of a live host in response to a DNS query
  • etc.

Currently, API-Firewall cannot work with such load balancers and performs DNS resolution only at startup.
During operation, DNS may point to a different A record, but API-Firewall will continue trying to send requests to the old IP address.

Please add support for DNS load balancers so that DNS resolution occurs periodically and connects to the new IP (transparently to the end user, without service degradation).

Pass API schema via URL

In some cases API schema is available on URL.
Please add a feature with passing an URL instead of mounting a file.

Unable to parse response data with http compression

The http request sent from api-firewall to the server contains this http header: Accept-Encoding: gzip, deflate, br, which means it accepts compressed data.
When the server response is compressed with http header, e.g. content-encoding: gzip, it's unable to parse the response without decompression.

nginx configuration for tests

Does fasthttp accidentally keep connected connections, if so, it would be more appropriate to use this configuration:

worker_processes 8; # equal to number of CPU cores on our machine
...
upstream backend {
    server 127.0.0.1:9090;
    keepalive 8;
}
...
client_body_buffer_size 128K; # greater than our JSON file size
... 
       location / {
                proxy_pass http://backend;
                proxy_http_version 1.1;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header Connection "";
        }

Published 386 musl binary appears to be amd64

Hi! Building https://github.com/wallarm/api-firewall-docker/blob/5cd07f115f16d10095a385a73568a4e60caf278b/0.6.7/Dockerfile on i386 (docker build --platform linux/386) fails with /bin/sh: api-firewall: not found.

When downloading https://github.com/wallarm/api-firewall/releases/download/v0.6.7/api-firewall-386-musl.tar.gz in an amd64 container instead, I can successfully ldd (and run!) the binary:

$ docker run -it --rm alpine:3.15
/ # wget https://github.com/wallarm/api-firewall/releases/download/v0.6.7/api-firewall-386-musl.tar.gz
Connecting to github.com (192.30.255.113:443)
Connecting to objects.githubusercontent.com (185.199.111.133:443)
saving to 'api-firewall-386-musl.tar.gz'
api-firewall-386-mus 100% |********************************| 3589k  0:00:00 ETA
'api-firewall-386-musl.tar.gz' saved
/ # tar -xvf api-firewall-386-musl.tar.gz
./
./api-firewall
./LICENSE
/ # ldd api-firewall
	/lib/ld-musl-x86_64.so.1 (0x7f2461ac7000)
	libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f2461ac7000)
/ # ./api-firewall -v
Version: 0.6.7
Wallarm API-Firewall

I'm not 100% certain I'm looking in the right place, but it seems like

is maybe missing the same case block to set GOARCH=386 as build-x86: has?
case "${{ matrix.arch }}" in
"386")
export GOARCH=386
export GOHOSTARCH=amd64
export GOHOSTOS=linux
export GOOS=linux
;;
esac

Honestly, it should be pretty safe to just set GOARCH unilaterally -- if you're on amd64 and explicitly set GOARCH=amd64, it doesn't do anything (since that's the default detected value for that case). ๐Ÿ˜…

(Also, setting GOHOSTARCH and GOHOSTOS explicitly like that shouldn't be necessary.)

Individual operation mode for each endpoint

In most cases, it is not possible to immediately launch API-Firewall in BLOCK mode; we have to start in monitoring mode, analyze logs, and make changes to the OAS, which takes quite a lot of time.
Moreover, it is inconvenient to roll out API updates in BLOCK mode.

Is it possible to implement individual management of the operation mode for each endpoint?

Examples:
We launched API-Firewall in LOG_ONLY mode, identified endpoints without errors, and enabled BLOCK for them, thus gradually transitioning the entire API to BLOCK mode.

With such a configuration, it is also possible to safely deploy new API endpoints (they will be in LOG_ONLY) and switch them to BLOCK when ready.

It is preferable for the operation mode to be set not in the specification but, for example, through an additional config.

The use of line breaks in log formatting in the TEXT format.

The use of line breaks significantly complicates parsing with popular log collection tools (such as OpenObserve, Filebeat, Logstash, Fluentd, Vector, etc).

Some events, for example, "request validation error", are split into multiple lines, making it difficult to parse logs properly and work with them.

I request a change in formatting to avoid using \r\n as a separator within a single event.

OpenAPI Base Path

Hi, in OpenAPI 2 there was a top-level property called basePath which (if set) defined the base path before all API endpoints, like /api/v1. In OpenAPI 3 this was removed, but the Swagger OpenAPI 3.0 docs and the spec itself suggest putting the base path in the server URL like this:

servers:
- url: "https://api.my-service.com/api/v1"
- url: "https://staging-api.my-service.com/api/v1"

Without support for a base path, all of my API endpoints are rejected because they are missing the /api/v1 portion (my base path).

Four ways to solve this problem come to mind:

  1. Change all my endpoint paths to include the base path (this doesn't seem ideal since the docs suggest I use a base path in the server URL).
  2. Run my OpenAPI spec through a preprocessor that prepends the base path to each endpoint before you read it.
  3. You can infer the base path from the servers by capturing the path of the first server URL (if present). This is what the AWS API Gateway does.
  4. You can provide an environment variable / CLI argument to set the base path like APIFW_API_BASE_PATH.

I would be happy to contribute this enhancement but I don't see the source code anywhere. Also, you might want to clarify the license of this product.

Response validation failed with empty content type

I set APIFW_RESPONSE_VALIDATION=BLOCK and got the following error:
level=error msg=response validation error error=response header Content-Type has unexpected value: "" request_id=#0000000100000001

I suspect it's due to this code in cmd/api-firewall/internal/handlers/openapi.go

	// Prepare http response headers
	respHeader := http.Header{}
	ctx.Request.Header.VisitAll(func(k, v []byte) {
		sk := string(k)
		sv := string(v)

		respHeader.Set(sk, sv)
	})

It seems to obtain the http headers from request rather than response. Should ctx.Request be changed to ctx.Response?

The ability to update OAS in API Firewall without restarting the binary/Docker in PROXY mode

Currently, it is necessary to restart the API Firewall to use the new version of the specification, which causes connection disruptions. This setup complicates integration into the infrastructure and ensures the uninterrupted operation of the protected service.

Is it possible to implement background loading of the new OAS version, its validation, and updating without restarting the API-FW?

This is needed both for a file and for loading the specification via URL.

The lack of necessary information in the logs, JSON format.

Information about the "path" is missing for the following events:

"request body has an error: doesn't match schema"
"value is required but missing"
"Shadow API: undefined parameters found"

This makes it extremely inconvenient to monitor the API Firewall's request processing, especially when multiple containers are running and a log aggregator like Open Observe is being used.

Please add output information about the "path".

helm chart can't be rendered if APIspec are mounted as extraVolumes

Hi team,
it turned out, that APISpec values is required for testing api-firewall. I changed my values.yaml by providing api spec as a separate file (mounted to the pod), but it looks like now I'm getting an error with render:

$ helm upgrade --install apifw . -n apifw
Error: UPGRADE FAILED: YAML parse error on api-firewall/templates/deployment.yaml: error converting YAML to JSON: yaml: line 58: did not find expected key

my values.yaml is very close to the default one:

manifest:
  enabled: false

## API Firewall chart
## https://docs.wallarm.com/api-firewall/overview/
##
apiFirewall:
  ## Chart name to use instead of the automatically generated name
  nameOverride: ""

  ## Docker image of API Firewall
  ## https://kubernetes.io/docs/concepts/containers/images/
  ##
  image:
    pullPolicy: IfNotPresent
    registry: ""
    name: "wallarm/api-firewall"
    ### You can set a specific version or set it automaticaly from appVersion
    ###
    tag: ""

  ## Array of private container registry credentials
  ## (If you forked the official API Firewall image and pushed it to a private registry)
  ## https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
  ##
  imagePullSecrets: []
  # - name: secretName

  ## Main settings of API Firewall
  config:
    mode: proxy
    listenAddress: 0.0.0.0
    listenPort: 8080
    maxConnsPerHost: 512
    timeouts:
      dial: "200ms"
      readFromBackend: "5s"
      writeToBackend: "5s"
    validationMode:
      request: block
      response: block
    shadowAPI:
      excludeList: "404"
      unknownParametersDetection: true
    passOptions: false

  ## Number of deployment replicas for the API Firewall container
  ## https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#deploymentspec-v1-apps
  ##
  replicaCount: 3

  ## Settings for automated rolling updates of the API Firewall container
  ## https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#deploymentstrategy-v1-apps
  ##
  updateStrategy: {}
  #  type: RollingUpdate
  #  rollingUpdate:
  #    maxUnavailable: 1
  #    maxSurge: 25%

  ## Minimum number of seconds for which a newly created pod should be ready without the API Firewall container crashing
  ## https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#deploymentspec-v1-apps
  ##
  minReadySeconds: 0

  ## The number of old ReplicaSets to retain to allow rollback
  ## https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#deploymentspec-v1-apps
  ##
  revisionHistoryLimit: 10

  ## Labels to add to the Pod with the API Firewall container
  ##
  podLabels: {}
  # key: value

  ## Annotations to add to the Pod with the API Firewall container
  ##
  podAnnotations: {}
  # key: value

  ## Additional command line arguments to pass to API Firewall
  ## These arguments override environment variables values passed to the Docker container
  ##
  extraArgs:
    log-level: DEBUG
  extraEnvs:
    - name: APIFW_API_SPECS
      value: /etc/api-firewall/manifests/openapi-manifest.yaml
    - name: APIFW_SERVER_INSECURE_CONNECTION
      value: "true"
    - name: APIFW_LOG_FORMAT
      value: JSON
    - name: APIFW_RESPONSE_VALIDATION
      value: DISABLE
    - name: APIFW_PASS_OPTIONS
      value: "true"
  extraVolumeMounts:
    - name: openapi-manifest
      mountPath: /etc/api-firewall/manifests
  extraVolumes:
    - name: openapi-manifest
      configMap:
        name: api-firewall-manifest
  # tls-certs-path: certs
  # tls-cert-file: localhost.crt
  # tls-cert-key: localhost.key
  # server-read-timeout: 5s
  # server-write-timeout: 5s
  # log-level: DEBUG
  # api-specs: swagger.json

  ## Additional environment variables to pass to the API Firewall container
  ## (If you forked and customize the official API Firewall image)
  ##
  # - name: FOO
  #   value: FOO
  # - name: BAR
  #   valueFrom:
  #     secretKeyRef:
  #       key: BAR
  #       name: bar-secret

  ## Setting to allow this Pod to schedule onto nodes with matching taints
  ## https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/
  ##
  tolerations: []
  # - key: "key"
  #   operator: "Equal|Exists"
  #   value: "value"
  #   effect: "NoSchedule|PreferNoSchedule"

  ## Affinity and anti-affinity settings of this Pod
  ## https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
  ##
  ## Prefered podAntiAffinity will be applied if no one affinity configured
  ##
  affinity: {}
  # podAntiAffinity:
  #   preferredDuringSchedulingIgnoredDuringExecution:
  #   - weight: 100
  #     podAffinityTerm:
  #       labelSelector:
  #         matchExpressions:
  #         - key: component
  #           operator: In
  #           values:
  #           - api-firewall
  #         - key: app
  #           operator: In
  #           values:
  #           - api-firewall
  #       topologyKey: kubernetes.io/hostname
  # podAntiAffinity:
  #   requiredDuringSchedulingIgnoredDuringExecution:
  #   - labelSelector:
  #       matchExpressions:
  #       - key: component
  #         operator: In
  #         values:
  #         - api-firewall
  #       - key: app
  #         operator: In
  #         values:
  #         - api-firewall
  #     topologyKey: "kubernetes.io/hostname"

  ## Lables of the node this Pod should be assigned to
  ## https://kubernetes.io/docs/user-guide/node-selection/
  ##
  nodeSelector: {}

  ## Settings for the API Firewall container lifecycle hooks
  ## https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/
  ##
  lifecycle: {}

  ## Liveness and readiness probe values for the API Firewall container
  ## https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes
  ##
  livenessProbe:
   httpGet:
     path: /v1/liveness
     port: 9667
     scheme: HTTP
   failureThreshold: 3
   initialDelaySeconds: 10
   periodSeconds: 10
   successThreshold: 1
   timeoutSeconds: 1
  readinessProbe:
   httpGet:
     path: /v1/readiness
     port: 9667
     scheme: HTTP
   failureThreshold: 3
   initialDelaySeconds: 10
   periodSeconds: 10
   successThreshold: 1
   timeoutSeconds: 1

  ## Grace period for this Pod termination in seconds
  ##
  terminationGracePeriodSeconds: 60

  ## One of the PriorityClass names applied to this Pod
  ## This setting indicates the importance of the Pod relative to other Pods
  ## https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/
  ##
  priorityClassName: ""

  ## One of the RuntimeClass names applied to this Pod
  ## This setting selects the API Firewall container runtime configuration
  ## https://kubernetes.io/docs/concepts/containers/runtime-class/
  ##
  runtimeClassName: ""

  ## privilege and access control settings for the API Firewall container
  ## https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
  ## https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#securitycontext-v1-core
  ##
  securityContext: {}

  ## The number of resources required for the API Firewall container
  ## https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
  ##
  resources: {}
  # limits:
  #   cpu: 1000m
  #   memory: 400Mi
  # requests:
  #   cpu: 700m
  #   memory: 250Mi

  ## Additional containers to be added to this Pod
  ##
  extraContainers: []
  # - name: some-container
  #   image: some/image:latest
  #   env:
  #   - name: FOO
  #     value: "123"
  #   volumeMounts:
  #   - name: bar-volume
  #     mountPath: /mnt

  ## Containers that should be started before the API Firewall container start
  ##
  extraInitContainers: []
  # - name: init
  #   image: busybox
  #   command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']

  ## Volumes that should be mounted to the API Firewall container
  ##
  # - name: something
  #   mountPath: /mnt/something

  ## Volumes that should be mounted to this pod
  ##
  # - name: something
  #   emptyDir: {}

  ## Target backend configuration
  ##
  target:
    ## Type of a target backend Service
    ## API Firewall will protect this Service and proxy requests to this Service
    ##   "service"   - use an existing Service or static IP of a load balacer
    ##   "endpoints" - create a Service with specified endpoints
    ##
    type: "service"

    ## A name of an existing Service or a Service that should be created
    ##
    name: "backend"

    ## Destination port of a backend Service
    ## If a Service type is "service", this setting will not be applied
    ##
    port: 80

    ## Endpoints to be attached to the created Service
    ## If a Service type is "service", this setting will not be applied
    ##
    ## https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#endpointaddress-v1-core
    ##
    endpoints: []
    # - hostname: some.hostname.example-1.tld
    # - hostname: some.hostname.example-2.tld
    # - ip: 1.1.1.1
    # - ip: 2.2.2.2

    ## Annotations for the created backend Service
    ## If a Service type is "service", this setting will not be applied
    ##
    annotations: {}

    ## Cluster IP for the created Service
    ## If a Service type is "service", this setting will not be applied
    ##
    clusterIP: ""

  service:
    ## Service type
    ## https://kubernetes.io/docs/concepts/services-networking/service/
    ## https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#service-v1-core
    ##
    type: ClusterIP

    ## Service port
    ##
    port: 80

    ## Service node port (if the service type if "NodePort")
    ##
    nodePort: 0

    ## Load balancer IP address
    ## https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer
    ##
    loadBalancerIP: ""

    ## Load balancer source ranges
    ## https://kubernetes.io/docs/concepts/services-networking/service/#aws-nlb-support
    ##
    loadBalancerSourceRanges: []
    # - "192.168.0.0/16"
    # - "10.0.0.0/8"
    # - "172.16.0.0/12"

    ## Kubernetes external traffic policy
    ## https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/
    ##
    externalTrafficPolicy: ""

    ## Annotations for this Service
    ##
    annotations: {}

    ## IP address of this Service cluster
    ##
    clusterIP: ""

  ingress:
    enabled: false

    ## Ingress class name used to expose this Service
    ## https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class
    ##
    ingressClass: ""

    ## Ingress hosts
    ##
    hosts: []
    # - my.example-1.tld
    # - my.example-2.tld

    ## Ingress route
    ##
    path: /

    ## TLS configuration
    ##
    tls: []
    # - hosts:
    #   - my.example-1.tld
    #   - my.example-2.tld
    #   secretName: my-example-1-tld-tls-secret

    ## Annotations for the Ingress resource
    ##
    annotations: {}

  ## Pod Security Policy settings
  ## https://kubernetes.io/docs/concepts/policy/pod-security-policy/
  ##
  podSecurityPolicy:
    enabled: false
    allowedCapabilities: []
    privileged: false
    allowPrivilegeEscalation: false
    volumes:
    - 'configMap'
    - 'emptyDir'
    - 'downwardAPI'
    - 'secret'
    hostNetwork: false
    hostIPC: false
    hostPID: false
    runAsUser:
      rule: 'MustRunAsNonRoot'
    supplementalGroups:
      rule: 'MustRunAs'
      ranges:
      - min: 1000
        max: 65535
    fsGroup:
      rule: 'MustRunAs'
      ranges:
      - min: 1000
        max: 65535
    seLinux:
      rule: RunAsAny
    
    ## Just for additional entries in ".spec" if PodSecurityPolicy
    ##
    additionalRestrictions: {}
    # requiredDropCapabilities:
    #   - ALL
    # readOnlyRootFilesystem: false

  ## Pod Disturion Budget settings
  ## https://kubernetes.io/docs/tasks/run-application/configure-pdb/
  ##
  podDisruptionBudget:
    enabled: false
    maxUnavailable: 1

  ## Pod autoscaling policy
  ## https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
  ##
  autoscaling:
    enabled: false
    minReplicas: 3
    maxReplicas: 11
    targetCPUUtilizationPercentage: 70
    targetMemoryUtilizationPercentage: 70

  ## Service Account for this Pod
  ## https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
  ##
  serviceAccount:
    ## Name of the existing Service Account
    ## If not specified, new Service Account will be created
    ##
    name: ""
    ## Annotations for the created Service Account
    ##
    annotations: {}

error: header Content-Type has unexpected value "application/x-www-form-urlencoded"

Hi team,

propably (most likely) not an error: I receive this error message and wonder, what is the correct Content-type header in a request?

api-firewall          | time=2023-12-13T20:56:35Z level=error msg=request validation error error=request body has an error: header Content-Type has unexpected value "application/x-www-form-urlencoded" request_id=#0000000100000001

Many thanks for your reply.

More detailed information in the logs for the event 'Shadow API: undefined parameters found'

The current logs lack sufficient detail to identify which parameters are undefined, where they are passed, and what data type they contain. This lack of information makes it inconvenient to work with such events.

I'll improve the information output as per your request. I suggest specifying:

  • Request method
  • Parameter name
  • Data type
  • Indication of where this parameter is passed (e.g., query, body)

This will provide more clarity and make it easier to work with such events.

Examples of current entries:

message:{"errors":[{"Input":null,"Parameters":["user_data"],"RequestBody":null,"Err":}}],
"host":"api.example.com","level":"error",
"msg":"Shadow API: undefined parameters found","path":"/v1/foo/bar",
"request_id":"c07ab637-158c-4fc8-ad2d-eb45a9459514","time":"2024-03-14T13:01:31Z"},

message:{"errors":[{"Input":null,"Parameters":["limit","no_wait","exclude_expired"],"RequestBody":null,"Err":{}}],
"host":"api.example.com","level":"error",
"msg":"Shadow API: undefined parameters found","path":"/v4/rules/export/events",
"request_id":"7f0eefdb-0f59-4b3d-b754-77fa2dcb7619","time":"2024-03-14T13:00:39Z"},

Non-unique request_id.

It has been noticed that the request_id is incremental, leading to issues when running multiple API-Firewall containers and using log collection systems (such as OpenObserve). Consequently, unrelated events may be assigned the same request_id.

I request to implement the generation of unique request_id values.

Enforce OAuth Access Token Scope requirements

Ideally, when I design an endpoint, I should be able to say how each method is authorized. In OAuth, we use scopes to determine the extent of access granted for an access_token ("AT"). The AT may be a value token: a JWT requiring signature validation (and auto-fetching of the current keys). The AT may also be a reference token: a guess-resistent identifier requiring OAuth token introspection. In either case, the AT should contain the scope claim, which is a space-delimited list of scopes (normally in URI format).

In the example below, the swagger doc is saying that to do a GET on the persistence endpoint, you need to present a token with either the properties.read OR properties.write scope

/jans-config-api/api/v1/jans-auth-server/config/persistence:
    get:
      summary: Returns persistence type configured for Jans authorization server.
      description: Returns persistence type configured for Jans authorization server.
      operationId: get-properties-persistence
      security:
        - oauth2: [properties.read, properties.write]

For extra credit, you can consider how the scopes are combined. Can you use AND instead of OR for a given endpoint? For more complex booleans, you could support JSONLogic syntax.

Feature Suggestion - x509 key pair authentication

This application is a really nice tool and I can imagine numerous applications for this model. What I would like to suggest is an additional module that would allow for zero trust via x509 key pair. This would allow users to deploy unconfigured versions on their applications and the said application could just auth with a key pair, request what it needs to request for an initial configuration download.

Private key verification could be integrated into cloud-based key storage like Google KMS, an intermediate CA, or even stored locally on the host machine's file system or k8s secrets.

Question about settings

Hello, team Wallarm.
I have studied your documentation, i have a question.
Tell me if it is possible to change the http response code in the blocking mode through variables. By default, as I understand it, it is 403.
But sometimes it is more convenient to be able to set your own response code, for accurate diagnostics by logs, or for introducing a custom page when blocking the api by a firewall.

More flexible Proxy configuration in API-Firewall

Currently, proxying is configured only through --server-url.
If --server-url contains a DNS name, it is resolved to an IP, a connection is established with this IP, and the DNS name is written to header_host.
If an IP address is specified, the connection is made to it, and it is also placed in the header_host of the HTTP request.

This approach is not flexible enough.
Please add an additional launch key where an arbitrary header_host can be specified.
This will significantly simplify the integration of API-Firewall into the infrastructure.

helm chart templates use outdated API [PodDisruptionBudget]

Hi team, please check the following issue with helm chart installation:

Steps to reproduce:

  1. $ git clone https://github.com/wallarm/api-firewall.git
  2. $ cd api-firewall/helm/api-firewall
  3. $ kubectl create ns apif
  4. $ helm upgrade --install apifw . -n apifw
    Release "apifw" does not exist. Installing it now.
    Error: unable to build kubernetes objects from release manifest: resource mapping not found for name: "apifw-api-firewall" namespace: "" from "": no matches for kind "PodDisruptionBudget" in version "extensions/v1beta1"
    ensure CRDs are installed first
  5. $ kubectl version
    Client Version: v1.30.1
    Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
    Server Version: v1.30.0

The same on kubernetes v1.25 and above.
The issue can be fixed by disabling podDisruptionBudget (set enabled to false).

My guess is PDB templates are built on removed API:
https://kubernetes.io/docs/reference/using-api/deprecation-guide/

Integer field in JSON request body is validated as null instead of its value

When configuring request body schema with an integer type field and sending a valid request, it produces a validation error with the value considered as null.

Minimal example built by adjusting the docker-compose demo in this repo:
int-example.json instead of httpbin.json:

{
  "openapi": "3.0.1",
  "info": {
    "title": "Minimal integer field example",
    "version": "0.0.1"
  },
  "paths": {
    "/integer-field": {
      "post": {
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "count": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success"
          }
        }
      }
    }
  }
}

Add these env vars to the original docker-compose demo:

APIFW_API_SPECS: "/opt/resources/int-example.json"
APIFW_LOG_LEVEL: "DEBUG"
APIFW_ADD_VALIDATION_STATUS_HEADER: "true"

Request (curl):

curl -X POST http://localhost:8080/integer-field \
   -H 'Content-Type: application/json' \
   -d '{"count":1}'

Error in log:

time=2022-12-12T11:51:11Z level=error msg=request validation error error=request body has an error: doesn't match the schema: Error at "/count": Value is not nullable
Schema:
  {
    "type": "integer"
  }

Value:
  null
 request_id=#0000000400000001

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.