Can nginx's njs (or Lua?) be used to replace a header with that header's SHA-512?

2 min read 30-08-2024
Can nginx's njs (or Lua?) be used to replace a header with that header's SHA-512?


Hashing Log Fields in Nginx with njs: A Practical Guide

Security is paramount, and often involves obfuscating sensitive data. This article explores how to use Nginx's JavaScript engine (njs) to hash log fields, particularly the http_authorization header, for enhanced security.

The Problem: Nginx's js_set directive requires synchronous code, while njs's crypto.subtle.digest for SHA-512 hashing is asynchronous. This creates a conflict, making it challenging to replace a log field with its hash.

Solution: While directly using js_set with asynchronous functions isn't feasible, we can leverage the power of asynchronous programming to achieve the desired result.

Here's a breakdown of the solution, based on insights from Stack Overflow:

  1. Embrace Asynchronous Nature: We can wrap the asynchronous hashing operation within a Promise, ensuring the code flow continues while the hashing process completes in the background.

  2. Nginx Configuration: Modify your nginx.conf to utilize the asynchronous function. The following snippet demonstrates this:

    js_import obfuscate.js;
    log_format main escape=json '{'
    '"http_authorization":"$obfuscated_token",'
    '}';
    
    location / {
        js_set $obfuscated_token obfuscate.get_obfuscated_token($http_authorization);
        access_log /var/log/nginx/access.log main;
    }
    
  3. JavaScript Code: Implement the SHA-512 hashing in your obfuscate.js file. The provided code below handles the hashing and returns the hexadecimal representation of the hash:

    async function get_obfuscated_token(token) {
        const encoder = new TextEncoder();
        const msgUint8 = encoder.encode(token);
        const digest = await crypto.subtle.digest("SHA-512", msgUint8);
        const hashArray = Array.from(new Uint8Array(digest));
        const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
        return hashHex;
    }
    

Explanation:

  • The get_obfuscated_token function accepts the http_authorization header as input.
  • It converts the header string to a Uint8Array using TextEncoder.
  • The crypto.subtle.digest function performs the SHA-512 hashing asynchronously, returning a Promise.
  • The Promise resolves with the hash digest, which is then converted to a hexadecimal representation.
  • The hexadecimal hash is returned, replacing the original http_authorization value.

Additional Considerations:

  • Performance: While the asynchronous approach is elegant, it may impact performance slightly. Consider profiling your application to assess any potential bottlenecks.
  • Error Handling: Implement robust error handling within your get_obfuscated_token function to catch potential failures during hashing.

Conclusion: By harnessing the power of asynchronous programming and njs, you can effectively hash sensitive log fields like http_authorization in your Nginx configurations. This solution improves security while maintaining the desired functionality, demonstrating the flexibility and power of njs for customizing your web server.

Attribution: