{"id":18048056,"url":"https://github.com/ivangfr/springboot-kong-plugins","last_synced_at":"2025-10-08T16:23:17.651Z","repository":{"id":111328645,"uuid":"135820743","full_name":"ivangfr/springboot-kong-plugins","owner":"ivangfr","description":"The goal of this project is to create a simple Spring Boot REST API and securing it with Kong using the LDAP Authentication and Basic Authentication plugins. Besides, we will explore more plugins that Kong offers like: Rate Limiting and Prometheus plugins.","archived":false,"fork":false,"pushed_at":"2024-11-15T07:44:59.000Z","size":1793,"stargazers_count":16,"open_issues_count":0,"forks_count":15,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-12T21:54:51.977Z","etag":null,"topics":["basic-authentication","docker","java","kong","kong-plugin","ldap","ldap-authentication","openldap","phpldapadmin","postgresql","prometheus","rate-limiting","spring-boot","spring-web-mvc"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ivangfr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"ivangfr"}},"created_at":"2018-06-02T13:39:23.000Z","updated_at":"2025-04-09T10:12:59.000Z","dependencies_parsed_at":"2024-04-13T21:40:59.010Z","dependency_job_id":"29c56af4-3f8a-4413-840f-a423a836b679","html_url":"https://github.com/ivangfr/springboot-kong-plugins","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ivangfr/springboot-kong-plugins","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivangfr%2Fspringboot-kong-plugins","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivangfr%2Fspringboot-kong-plugins/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivangfr%2Fspringboot-kong-plugins/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivangfr%2Fspringboot-kong-plugins/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ivangfr","download_url":"https://codeload.github.com/ivangfr/springboot-kong-plugins/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivangfr%2Fspringboot-kong-plugins/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278975125,"owners_count":26078562,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-08T02:00:06.501Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["basic-authentication","docker","java","kong","kong-plugin","ldap","ldap-authentication","openldap","phpldapadmin","postgresql","prometheus","rate-limiting","spring-boot","spring-web-mvc"],"created_at":"2024-10-30T20:11:06.723Z","updated_at":"2025-10-08T16:23:17.621Z","avatar_url":"https://github.com/ivangfr.png","language":"Shell","funding_links":["https://github.com/sponsors/ivangfr"],"categories":[],"sub_categories":[],"readme":"# springboot-kong-plugins\n\nThe goal of this project is to create a simple [`Spring Boot`](https://docs.spring.io/spring-boot/index.html) REST API and securing it with [`Kong`](https://konghq.com/kong/) using the `LDAP Authentication` and `Basic Authentication` plugins. Besides, we will explore more plugins that `Kong` offers like: `Rate Limiting` and `Prometheus` plugins.\n\n## Proof-of-Concepts \u0026 Articles\n\nOn [ivangfr.github.io](https://ivangfr.github.io), I have compiled my Proof-of-Concepts (PoCs) and articles. You can easily search for the technology you are interested in by using the filter. Who knows, perhaps I have already implemented a PoC or written an article about what you are looking for.\n\n## Additional Readings\n\n- \\[**Medium**\\] [**Using Kong to secure a Simple Spring Boot REST API with Basic Authentication plugin**](https://medium.com/@ivangfr/using-kong-to-secure-a-simple-spring-boot-rest-api-with-basic-authentication-plugin-90f3529043f3)\n- \\[**Medium**\\] [**Using Kong to secure a Simple Spring Boot REST API with LDAP Authentication plugin**](https://medium.com/@ivangfr/using-kong-to-secure-a-simple-spring-boot-rest-api-with-ldap-authentication-plugin-3a499e01382a)\n- \\[**Medium**\\] [**Using Kong to configure Rate Limiting to a Simple Spring Boot REST API**](https://medium.com/@ivangfr/using-kong-to-configure-rate-limiting-to-a-simple-spring-boot-rest-api-33b1899077d)\n- \\[**Medium**\\] [**Using Kong to secure a Simple Spring Boot REST API with Kong OIDC plugin and Keycloak**](https://medium.com/@ivangfr/using-kong-to-secure-a-simple-spring-boot-rest-api-with-kong-oidc-plugin-and-keycloak-c8fa8de32e6e)\n\n## Project Diagram\n\n![project-diagram](documentation/project-diagram.jpeg)\n\n## Application\n\n- ### simple-service\n\n  `Spring Boot` Java Web application that exposes two endpoints:\n   - `/api/public`: that can be access by anyone, it is not secured;\n   - `/api/private`: that must be accessed only by authenticated users.\n\n## Prerequisites\n\n- [`Java 21+`](https://www.oracle.com/java/technologies/downloads/#java21)\n- [`Docker`](https://www.docker.com/)\n\n## Run application during development using Maven\n\n- Open a terminal and navigate to `springboot-kong-plugins` root folder\n\n- Run the command below to start\n  ```\n  ./mvnw clean spring-boot:run --projects simple-service\n  ```\n\n- Open another terminal and call application endpoints\n  ```\n  curl -i localhost:8080/api/public\n  curl -i localhost:8080/api/private\n  curl -i localhost:8080/actuator/beans\n  curl -i localhost:8080/actuator/health\n  ```\n\n- To stop, go to the terminal where the application is running and press `Ctrl+C`\n\n## Build application Docker Image\n\n- In a terminal, make sure you are in `springboot-kong-plugins` root folder\n\n- Build Docker Image\n  - JVM\n    ```\n    ./docker-build.sh\n    ```\n  - Native\n    ```\n    ./docker-build.sh native\n    ```\n    \n## Test application Docker Image\n\n- In a terminal, run the following command\n  ```\n  docker run --rm -p 8080:8080 --name simple-service ivanfranchin/simple-service:1.0.0\n  ```\n\n- Open another terminal and call application endpoints\n  ```\n  curl -i localhost:8080/api/public\n  curl -i localhost:8080/api/private\n  curl -i localhost:8080/actuator/beans\n  curl -i localhost:8080/actuator/health\n  ```\n\n- To stop, go to the terminal where the application is running and press `Ctrl+C`\n\n## Initialize Environment\n\n- In a terminal, make use you are in `springboot-kong-plugins` root folder\n\n- Run the following script\n  ```\n  ./init-environment.sh\n  ```\n  \u003e **Note**: `simple-service` application is running as a Docker container. The container does not expose any port to HOST machine. So, it cannot be accessed directly, forcing the caller to use `Kong` as gateway server in order to access it.\n\n## Import OpenLDAP Users\n\nThe `LDIF` file that we will use, `ldap/ldap-mycompany-com.ldif`, has already a pre-defined structure for `mycompany.com`. Basically, it has 2 groups (`developers` and `admin`) and 4 users (`Bill Gates`, `Steve Jobs`, `Mark Cuban` and `Ivan Franchin`). Besides, it's defined that `Bill Gates`, `Steve Jobs` and `Mark Cuban` belong to `developers` group and `Ivan Franchin` belongs to `admin` group.\n```\nBill Gates \u003e username: bgates, password: 123\nSteve Jobs \u003e username: sjobs, password: 123\nMark Cuban \u003e username: mcuban, password: 123\nIvan Franchin \u003e username: ifranchin, password: 123\n```\n\nThere are two ways to import those users: by running a script or using `phpldapadmin`\n\n### Import users running a script\n\n- In another terminal, make use you are in `springboot-kong-plugins` root folder\n\n- Run the following script\n  ```\n  ./import-openldap-users.sh\n  ```\n  \n- Check users imported using [`ldapsearch`](https://linux.die.net/man/1/ldapsearch)\n  ```\n  ldapsearch -x -D \"cn=admin,dc=mycompany,dc=com\" \\\n    -w admin -H ldap://localhost:389 \\\n    -b \"ou=users,dc=mycompany,dc=com\" \\\n    -s sub \"(uid=*)\"\n  ```\n\n### Import users using phpldapadmin\n\n- Access https://localhost:6443\n\n- Login with the credentials\n  ```\n  Login DN: cn=admin,dc=mycompany,dc=com\n  Password: admin\n  ```\n\n- Import the file `ldap/ldap-mycompany-com.ldif`\n\n- You should see something like\n\n  ![openldap](documentation/openldap.jpeg)\n\n## Kong\n\nIn a terminal, follow the steps below to configure `Kong`\n\n### Check Status\n\n- Before starting, check if `Kong` admin API is accessible\n  ```\n  curl -I http://localhost:8001\n  ```\n\n  It should return\n  ```\n  HTTP/1.1 200 OK\n  ```\n\n### Add Service\n\n1. The following call will add the `simple-service` service\n   ```\n   curl -i -X POST http://localhost:8001/services/ \\\n     -d \"name=simple-service\" \\\n     -d \"protocol=http\" \\\n     -d \"host=simple-service\" \\\n     -d \"port=8080\"\n   ```\n\n2. \\[Optional\\] To list all services run\n   ```\n   curl -i http://localhost:8001/services\n   ```\n\n### Add routes\n\n1. One default route for the service, no specific `path` included\n   ```\n   curl -i -X POST http://localhost:8001/services/simple-service/routes/ \\\n     -d \"name=simple-service-default\" \\\n     -d \"protocols[]=http\" \\\n     -d \"hosts[]=simple-service\"\n   ```\n\n2. Another route specifically for `/api/private` endpoint (it will be secured and only accessible by LDAP users)\n   ```\n   curl -i -X POST http://localhost:8001/services/simple-service/routes/ \\\n     -d \"name=simple-service-api-private\" \\\n     -d \"protocols[]=http\" \\\n     -d \"hosts[]=simple-service\" \\\n     -d \"paths[]=/api/private\" \\\n     -d \"strip_path=false\"\n   ```\n\n3. Finally, one route for `/actuator/beans` endpoint (it will be secured and only accessible by pre-defined users)\n   ```\n   curl -i -X POST http://localhost:8001/services/simple-service/routes/ \\\n     -d \"name=simple-service-actuator-beans\" \\\n     -d \"protocols[]=http\" \\\n     -d \"hosts[]=simple-service\" \\\n     -d \"paths[]=/actuator/beans\" \\\n     -d \"strip_path=false\"\n   ```\n\n4. \\[Optional\\] To list all `simple-service` routes run\n   ```\n   curl -i http://localhost:8001/services/simple-service/routes\n   ```\n\n### Call endpoints\n\n1. Call `/api/public` endpoint\n   ```\n   curl -i http://localhost:8000/api/public -H 'Host: simple-service'\n   ```\n\n   It should return\n   ```\n   HTTP/1.1 200\n   It is public.\n   ```\n\n2. Call `/api/private` endpoint\n   ```\n   curl -i http://localhost:8000/api/private -H 'Host: simple-service'\n   ```\n\n   It should return\n   ```\n   HTTP/1.1 200\n   null, it is private.\n   ```\n\n   \u003e **Note**: This endpoint is not secured by the application, that is why the response is returned. The idea is to use `Kong` to secure it. It will be done on the next steps.\n\n3. Call `/actuator/beans` endpoint\n   ```\n   curl -i http://localhost:8000/actuator/beans -H 'Host: simple-service'\n   ```\n\n   It should return\n   ```\n   HTTP/1.1 200\n   {\"contexts\":{\"simple-service\":{\"beans\":...\n   ```\n\n   \u003e **Note**: As happened previously with `/api/private`, `/actuator/beans` endpoint is not secured by the application. We will use `Kong` to secure it on the next steps.\n\n## Plugins\n\nIn this project, we are going to add these plugins: `LDAP Authentication`, `Basic Authentication`, `Rate Limiting` and `Prometheus`. Please refer to https://konghq.com/plugins for more.\n\n### Add LDAP Authentication plugin\n\nThe `LDAP Authentication` plugin will be used to secure the `/api/private` endpoint.\n\n1. Add plugin to route `simple-service-api-private`\n   ```\n   curl -i -X POST http://localhost:8001/routes/simple-service-api-private/plugins \\\n     -d \"name=ldap-auth\" \\\n     -d \"config.hide_credentials=true\" \\\n     -d \"config.ldap_host=openldap\" \\\n     -d \"config.ldap_port=389\" \\\n     -d \"config.start_tls=false\" \\\n     -d \"config.base_dn=ou=users,dc=mycompany,dc=com\" \\\n     -d \"config.verify_ldap_host=false\" \\\n     -d \"config.attribute=cn\" \\\n     -d \"config.cache_ttl=60\" \\\n     -d \"config.header_type=ldap\"\n   ```\n\n2. Try to call `/api/private` endpoint without credentials\n   ```\n   curl -i http://localhost:8000/api/private -H 'Host: simple-service'\n   ```\n\n   It should return\n   ```\n   HTTP/1.1 401 Unauthorized\n   {\"message\":\"Unauthorized\"}\n   ```\n\n3. Call `/api/private` endpoint using Bill Gates base64 encode credentials\n   ```\n   curl -i http://localhost:8000/api/private \\\n     -H \"Authorization:ldap $(echo -n 'Bill Gates':123 | base64)\" \\\n     -H 'Host: simple-service'\n   ```\n\n   It should return\n   ```\n   HTTP/1.1 200\n   Bill Gates, it is private.\n   ```\n\n### Add Basic Authentication plugin\n\nThe `Basic Authentication` plugin will be used to secure the `/actuator/beans` endpoint\n\n1. Add plugin to route `simple-service-actuator-beans`\n   ```\n   curl -i -X POST http://localhost:8001/routes/simple-service-actuator-beans/plugins \\\n     -d \"name=basic-auth\" \\\n     -d \"config.hide_credentials=true\"\n   ```\n\n2. Try to call `/actuator/beans` endpoint without credentials.\n   ```\n   curl -i http://localhost:8000/actuator/beans -H 'Host: simple-service'\n   ```\n\n   It should return\n   ```\n   HTTP/1.1 401 Unauthorized\n   {\"message\":\"Unauthorized\"}\n   ```\n\n3. Create a consumer\n   ```\n   curl -i -X POST http://localhost:8001/consumers -d \"username=ivanfranchin\"\n   ```\n\n4. Create a credential for consumer\n   ```\n   curl -i -X POST http://localhost:8001/consumers/ivanfranchin/basic-auth \\\n     -d \"username=ivan.franchin\" \\\n     -d \"password=123\"\n   ```\n\n5. Call `/api/private` endpoint using `ivan.franchin` credential\n   ```\n   curl -i -u ivan.franchin:123 http://localhost:8000/actuator/beans -H 'Host: simple-service'\n   ```\n\n   It should return\n   ```\n   HTTP/1.1 200\n   {\"contentDescriptor\":{\"providerVersion\":...\n   ```\n\n6. Let's create another consumer just for testing purpose\n   ```\n   curl -i -X POST http://localhost:8001/consumers -d \"username=administrator\"\n   \n   curl -i -X POST http://localhost:8001/consumers/administrator/basic-auth \\\n     -d \"username=administrator\" \\\n     -d \"password=123\"\n   ```\n\n### Add Rate Limiting plugin\n\nWe are going to add the following rate limitings:\n- `/api/public` and `/actuator/health`: one request per second\n- `/api/private`: 5 requests a minute\n- `/actuator/beans`: 2 requests a minute or 100 requests an hour\n\n1. Add plugin to route `simple-service-default`\n   ```\n   curl -i -X POST http://localhost:8001/routes/simple-service-default/plugins \\\n     -d \"name=rate-limiting\" \\\n     -d \"config.second=1\"\n   ```\n\n2. Add plugin to route `simple-service-api-private`\n   ```\n   curl -i -X POST http://localhost:8001/routes/simple-service-api-private/plugins \\\n     -d \"name=rate-limiting\" \\\n     -d \"config.minute=5\"\n   ```\n\n3. Add plugin to route `simple-service-actuator-beans`\n   ```\n   curl -i -X POST http://localhost:8001/routes/simple-service-actuator-beans/plugins \\\n     -d \"name=rate-limiting\" \\\n     -d \"config.minute=2\" \\\n     -d \"config.hour=100\"\n   ```\n\n4. Make some calls to these endpoints\n\n   - Test `/api/public`\n     ```\n     curl -i http://localhost:8000/api/public -H 'Host: simple-service'\n     curl -i http://localhost:8000/actuator/health -H 'Host: simple-service'\n     ```\n\n   - Test `/actuator/beans`\n     ```\n     curl -i -u ivan.franchin:123 http://localhost:8000/actuator/beans -H 'Host: simple-service'\n     curl -i -u administrator:123 http://localhost:8000/actuator/beans -H 'Host: simple-service'\n     ```\n\n   - Test `/api/private`\n     ```\n     curl -i http://localhost:8000/api/private \\\n       -H \"Authorization:ldap $(echo -n 'Bill Gates':123 | base64)\" \\\n       -H 'Host: simple-service'\n     \n     curl -i http://localhost:8000/api/private \\\n       -H \"Authorization:ldap $(echo -n 'Mark Cuban':123 | base64)\" \\\n       -H 'Host: simple-service'\n     ```\n\n5. After exceeding some calls in a minute, you should see\n   ```\n   HTTP/1.1 429 Too Many Requests\n   {\"message\":\"API rate limit exceeded\"}\n   ```\n\n### Add Prometheus plugin\n\n1. Add plugin to `simple-service`\n   ```\n   curl -i -X POST http://localhost:8001/services/simple-service/plugins -d \"name=prometheus\"\n   ```\n\n2. Make some requests to `simple-service` endpoints\n\n3. You can see some metrics\n   ```\n   curl -i http://localhost:8001/metrics\n   ```\n\n## Shutdown\n\nIn a terminal and, inside `springboot-kong-plugins` root folder, run the following script\n```\n./shutdown-environment.sh\n```\n\n## Cleanup\n\nTo remove the Docker image created by this project, go to a terminal and, inside `springboot-kong-plugins` root folder, run the script below\n```\n./remove-docker-images.sh\n```\n\n## Issues\n\nWhen upgrading postgres to a version above `13.x` (using current kong version), there is an error while running `kong-database migration`\n```\nRunning kong-database migration\n-------------------------------\nError: module 'openssl.rand' not found:No LuaRocks module found for openssl.rand\n\tno field package.preload['openssl.rand']\n\tno file './openssl/rand.lua'\n\tno file './openssl/rand/init.lua'\n\tno file './openssl/rand.lua'\n\tno file './openssl/rand/init.lua'\n\tno file '/usr/local/openresty/site/lualib/openssl/rand.ljbc'\n\tno file '/usr/local/openresty/site/lualib/openssl/rand/init.ljbc'\n\tno file '/usr/local/openresty/lualib/openssl/rand.ljbc'\n\tno file '/usr/local/openresty/lualib/openssl/rand/init.ljbc'\n\tno file '/usr/local/openresty/site/lualib/openssl/rand.lua'\n\tno file '/usr/local/openresty/site/lualib/openssl/rand/init.lua'\n\tno file '/usr/local/openresty/lualib/openssl/rand.lua'\n\tno file '/usr/local/openresty/lualib/openssl/rand/init.lua'\n\tno file './openssl/rand.lua'\n\tno file '/usr/local/openresty/luajit/share/luajit-2.1.0-beta3/openssl/rand.lua'\n\tno file '/usr/local/share/lua/5.1/openssl/rand.lua'\n\tno file '/usr/local/share/lua/5.1/openssl/rand/init.lua'\n\tno file '/usr/local/openresty/luajit/share/lua/5.1/openssl/rand.lua'\n\tno file '/usr/local/openresty/luajit/share/lua/5.1/openssl/rand/init.lua'\n\tno file '/home/kong/.luarocks/share/lua/5.1/openssl/rand.lua'\n\tno file '/home/kong/.luarocks/share/lua/5.1/openssl/rand/init.lua'\n\tno file '/usr/local/openresty/site/lualib/openssl/rand.so'\n\tno file '/usr/local/openresty/lualib/openssl/rand.so'\n\tno file './openssl/rand.so'\n\tno file '/usr/local/lib/lua/5.1/openssl/rand.so'\n\tno file '/usr/local/openresty/luajit/lib/lua/5.1/openssl/rand.so'\n\tno file '/usr/local/lib/lua/5.1/loadall.so'\n\tno file '/home/kong/.luarocks/lib/lua/5.1/openssl/rand.so'\n\tno file '/usr/local/openresty/site/lualib/openssl.so'\n\tno file '/usr/local/openresty/lualib/openssl.so'\n\tno file './openssl.so'\n\tno file '/usr/local/lib/lua/5.1/openssl.so'\n\tno file '/usr/local/openresty/luajit/lib/lua/5.1/openssl.so'\n\tno file '/usr/local/lib/lua/5.1/loadall.so'\n\tno file '/home/kong/.luarocks/lib/lua/5.1/openssl.so'\n\n  Run with --v (verbose) or --vv (debug) for more details\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivangfr%2Fspringboot-kong-plugins","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivangfr%2Fspringboot-kong-plugins","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivangfr%2Fspringboot-kong-plugins/lists"}