-
Notifications
You must be signed in to change notification settings - Fork 16
1. Development
A C compiler must be installed that meets the ISO C Standard (C99), such as gcc.
On macOS, the C compiler installed by XCode works fine.
Also ensure that a Docker engine and the jq tool are installed.
This project can be developed in a basic manner with Visual Studio Code and the C/C++ Extension Pack.
Alternatively, a more specialist compiler such as CLion can be used, with better debugging features.
First run the base configure script, and accept the default NGINX version, which defaults to that of the latest NGINX Plus release (1.27.4). If you prefer, enter an nginx open source version instead:
make clean
export NGINX_VERSION='1.27.4'
./configureSelect the following options when getting started. The first enables debugging of the C code, while the second enables Perl tests to run:
Do you want to enable debug featured? --> Yes
Do you want to create a dynamic module? --> No
The configure script will download the NGINX source code if it is not already local. If it is, the location may be provided when prompted. By default, version 1.27.4 will be downloaded; a different version can be fetched by setting NGINX_VERSION before running the configure script. Any additional parameters (e.g., --prefix) that NGINX's configure script supports can also be provided. When this module's configure script is run, it will pass along --with-compat to NGINX's script. It asks if a dynamic module should be created (thus passing along --add-dynamic-module) or if the module should be compiled into the NGINX binary (thus passing --add-module); by default, it created a dynamically-linked module. It will also ask if debug flags should be enabled; if so, --with-debug and certain GCC flags will be passed on to NGINX's configure script to make debugging easier.
WARNING If --without-pcre, --without-http_gzip_module and potentially other flags are provided to the configure script and a module is created, it will not be compatible with NGINX Plus or the pre-compiled open source NGINX binaries; if you include such flags (when building the module), you will only be able to load it into a custom build of NGINX that also excludes the same functionality. If the configure script exits with an error about a missing dependency, like PCRE and zlib, install those instead of excluding them if compatibility with pre-build NGINX binaries is desired.
The code can be imported into CLion 2020.2 or newer as a Makefile project. To do this though, you need to run the configure script without running make or make all. Also, CLion will not work if the clean target it set since this target deletes the Makefile, which is generated by the configure script. If this process is followed, the project will import easily and all the smart IDE features will work.
Whenever the code in the module changes, run this command to rebuild NGINX, which will delegate to NGINX's Makefile:
makePre-creating the nginx folder for development is recommended.
This enables nginx to be run as your own user account, which works better later when debugging:
sudo mkdir /usr/local/nginx
sudo chown yourusername /usr/local/nginxWhenever you want to update the local system after building code, do a make install.
This deploys an entire NGINX system under the /usr/local/nginx folder:
make installFinally deploy the nginx.conf development configuration and start NGINX locally:
cp ./testing/localhost/nginx.conf /usr/local/nginx/conf/nginx.conf
/usr/local/nginx/sbin/nginxYou can run curl requests against the nginx system in the same manner as a web or mobile client:
ACCESS_TOKEN='xxx'
curl -i -X GET http://localhost:8080/api \
-H "Authorization: Bearer $ACCESS_TOKEN"This will result in a 500 error, since the plugin cannot connect to an introspection endpoint yet:
{
"code": "server_error",
"message": "Problem encountered processing the request"
}Run a local instance in Docker using the following command.
Then login to http://localhost:6749/admin with credentials admin / Password1.
Then complete the initial setup wizard and accept all defaults:
docker run -it -e PASSWORD=Password1 -p 6749:6749 -p 8443:8443 curity.azurecr.io/curity/idsvrThen save this XML to a clients.xml file, and upload / merge it via the Changes / Upload option:
<config>
<profiles xmlns="https://curity.se/ns/conf/base">
<profile>
<id>token-service</id>
<type xmlns:as="https://curity.se/ns/conf/profile/oauth">as:oauth-service</type>
<expose-detailed-error-messages/>
<settings>
<authorization-server xmlns="https://curity.se/ns/conf/profile/oauth">
<client-store>
<config-backed>
<client>
<id>test-client</id>
<secret>secret1</secret>
<capabilities>
<client-credentials/>
</capabilities>
</client>
<client>
<id>test-nginx</id>
<secret>secret2</secret>
<capabilities>
<introspection/>
</capabilities>
</client>
</config-backed>
</client-store>
</authorization-server>
</settings>
</profile>
</profiles>
</config>Next run this command to get an opaque access token:
OPAQUE_ACCESS_TOKEN=$(curl -s -X POST http://localhost:8443/oauth/v2/oauth-token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=test-client" \
-d "client_secret=secret1" \
-d "grant_type=client_credentials" | jq -r .access_token)
echo $OPAQUE_ACCESS_TOKENSend the opaque token to the stub API with this command, which will result in the plugin introspecting it:
curl -s -X GET 'http://localhost:8080/api' -H "Authorization: Bearer $OPAQUE_ACCESS_TOKEN"The introspection request made from nginx can, if required, be executed locally, for debugging purposes:
JWT_ACCESS_TOKEN=$(curl -s -X POST http://localhost:8443/oauth/v2/oauth-introspect \
-H "Accept: application/jwt" \
-d "client_id=test-nginx" \
-d "client_secret=secret2" \
-d "token=$OPAQUE_ACCESS_TOKEN")
echo $JWT_ACCESS_TOKENThe stub API simply echoes back the JWT access token:
{
"message": "API was called successfully with eyJraWQiOiI5MTc5OTY5NTAiLCJ4NXQiOiJqeU1UMUgwb3B6MWdYWTZPY3JsaUg0dTU0amciLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiJjNWNjN2M5NS02MjczLTQwYjAtYThkNy0zNzZjZjA5ZTU0MWIiLCJkZWxlZ2F0aW9uSWQiOiIwOTNjYTZiYi1hYTkyLTRhZTMtOTY5NS04MGI2NzE5M2M5ZjAiLCJleHAiOjE2Njc0MTkwMjIsIm5iZiI6MTY2NzQxODcyMiwic2NvcGUiOiIiLCJpc3MiOiJodHRwOi8vMTQ3ZTRiNjhiMmQ0Ojg0NDMvb2F1dGgvdjIvb2F1dGgtYW5vbnltb3VzIiwic3ViIjoidGVzdC1jbGllbnQiLCJhdWQiOiJ0ZXN0LWNsaWVudCIsImlhdCI6MTY2NzQxODcyMiwicHVycG9zZSI6ImFjY2Vzc190b2tlbiJ9.j5qS61HbBuyT-igAhuSxjvYVQc4PWEX5fO5ugOTdaE5Y41oZ8HrywzaTYY-cj-bOZoXsKEbtMXftc-jW5qehiBZd0fvebICpEMUrZ81pVhwoPFmZb3tO5gBaGbzsV1M_s8s_N0n9rd26X3fMmiiIDkwBIdwZhd1fb2LeXtpglYOPlV-nBSCjXsIK5nrlpbbQkTv0NIUQx4ZZG4R9dckkzhYimxT7lwOYDwJIH-GSoPUiCT9N0l8BZiSQ6kl-JP2QcxRisiEfglkZfsmxhMZl3vQIM2HaVsJbuf6A3mKcnkvSiDAA90fGQIL3WnEAjlSaE-EkswMfzOHS4pHnUx1SWQ"
}To perform printf debugging you can add ngx_log_error statements to the C code and then look at NGINX output.
Once nginx is running, select Run / Attach to Process in CLion, then choose the nginx worker process.
Then set breakpoints, after which you can step through code to check variable state carefully.
You can consult the following sources of information for further details on NGINX module development: