PingIntelligence

Configuring NGINX Plus for PingIntelligence

Configure the nginx.conf to setup NGINX Plus and PingIntelligence sideband integration.

About this task

To configure NGINX Plus for PingIntelligence:

Steps

  1. Create a modules directory in NGINX Plus:

    # mkdir /etc/nginx/modules
  2. Download the NGINX Plus - PingIntelligence policy modules from the API Intelligence Downloads site.

  3. Untar the downloaded file:

    # tar -xvzf pi-api-nginx-plus-policy-4.3.tar.gz
  4. Copy the three PingIntelligence modules files for RHEL to the modules directory of NGINX Plus and pi-pf.conf file to /usr/local/nginx/conf/ directory.

    The pi-pf.conf file has the OAuth policy details. The three PingIntelligence modules are:

    • ngx_ase_integration_module.so

    • ngx_http_ase_integration_request_module.so

    • ngx_http_ase_integration_response_module.so

      # cp ngx_ase_integration_module.so /etc/nginx/modules
      # cp ngx_http_ase_integration_request_module.so /etc/nginx/modules
      # cp ngx_http_ase_integration_response_module.so /etc/nginx/modules
      # cp pi-pf.conf /usr/local/nginx/conf/
  5. Change to root user:

    # sudo su
  6. Export client credentials as environment variables.

    Here PF_ID and PF_SECRET are PingFederate client ID and secret.

    # export PF_ID=<ID>
    # export PF_SECRET=<SECRET>
  7. Edit the nginx.conf file to load the PingIntelligence modules.

    Example:

    The following is a snippet of the nginx.conf file showing the loaded PingIntelligence modules:

    worker_processes  4;
    
    error_log  /usr/local/nginx/logs/error.log debug;
    worker_rlimit_core  500M;
    working_directory  /usr/local/nginx;
    
    pid        /usr/local/nginx/pid/nginx.pid;
    env PF_ID;
    env PF_SECRET;
    
    load_module modules/ngx_ase_integration_module.so; load_module modules/ngx_http_ase_integration_request_module.so; load_module modules/ngx_http_ase_integration_response_module.so; load_module modules/ndk_http_module.so; load_module modules/ngx_http_lua_module.so;
    
    events {
        worker_connections  1024;
    }
     truncated nginx.conf file
  8. Configure ASE primary and secondary node IP address by replacing IP:PORT in the nginx.conf file snippet below:

    http {
    
        keepalive_timeout  65;
        upstream ase.pi {
           server  IP:PORT  max_fails=1 max_conns=100 fail_timeout=10;
           server  IP:PORT  max_fails=1 max_conns=100 fail_timeout=10 backup;
           keepalive 32;
           #keepalive_timeout 3600s; # NOT allowed < 1.15.3
       }
    
    truncated nginx.conf file
  9. Configure introspect server IP address by replacing IP:PORT in the nginx.conf file snippet show below:

    upstream introspect_server {
            server  IP:PORT  max_fails=1 max_conns=100 fail_timeout=10;
            server  IP:PORT  max_fails=1 max_conns=100 fail_timeout=10 backup;
            keepalive 32;
        }
    
    truncated nginx.conf file
  10. Configure the username and client ID keys in nginx.conf.

    These are the keys for username and client ID that you have configured in PingFederate.

    set $oauth_username_key  Username;
    set $oauth_client_id_key  ClientID;
    
    truncated nginx.conf file
  11. Configure the token parameter name after $arg_ and in ase/request:

    # Set the token parameter name below after $arg_ and inside /ase/request.
        set $oauth_key_param $arg_access_token;
        set $oauth_token_param $arg_access_token;
    
    	#ASE Request Proxy Configuration
           location = /ase/request {
           internal;
           ase_integration https://test.ase.pi;
           ase_integration_method "POST";
           ase_integration_http_version 1.1;
           ase_integration_ase_token $ase_token;
           ase_integration_correlation_id $correlationid;
           ase_integration_host $ase_host;
           # set token key here.
           ase_integration_token_key  access_token;
           ase_integration_ssl_trusted_certificate $certificate;
           ase_integration_ssl_verify    off;
           ase_integration_ssl_verify_depth 1;
           ase_integration_ssl_server_name off;
           ase_integration_ssl_name $ase_ssl_host;
           ase_integration_next_upstream error timeout non_idempotent;
        }
    
    truncated nginx.conf file
  12. Configure the URL of the introspection server:

    # Set introspection URL
        set $oauth_url https://introspect_server/as/introspect.oauth2;
    
    truncated nginx.conf file
  13. Configure the ASE sideband token:

    The sideband authentication token was created in step 4 in Preparing to deploy the PingIntelligence policy.

    Example:

    The following is a snippet showing sideband authentication token:

     #ASE Token for sideband authentication
        set $ase_token <ASE_TOKEN>;
  14. Configure the ASE request and response API endpoints in nginx.conf.

    The following snippet from nginx.conf shows ASE request and response:

     #ASE Request Proxy Configuration
        location = /ase/request {
           internal;
           ase_integration https://test.ase.pi;
           ase_integration_method "POST";
           ase_integration_http_version 1.1;
           ase_integration_ase_token $ase_token;
           ase_integration_correlation_id $correlationid;
           ase_integration_host $ase_host;
           # set token key here.
           ase_integration_token_key access_token;
           ase_integration_ssl_trusted_certificate $certificate;
           ase_integration_ssl_verify    off;
           ase_integration_ssl_verify_depth 1;
           ase_integration_ssl_server_name off;
           ase_integration_ssl_name $ase_ssl_host;
           ase_integration_next_upstream error timeout non_idempotent;
        }
        #ASE Response Proxy Configuration
        location = /ase/response {
           internal;
           ase_integration https://test.ase.pi;
           ase_integration_method "POST";
           ase_integration_http_version 1.1;
           ase_integration_ase_token $ase_token;
           ase_integration_correlation_id $correlationid;
           ase_integration_host $ase_host;
           ase_integration_ssl_trusted_certificate $certificate;
           ase_integration_ssl_verify    off;
           ase_integration_ssl_verify_depth 1;
           ase_integration_ssl_server_name off;
           ase_integration_ssl_name $ase_ssl_host;
           ase_integration_next_upstream error timeout non_idempotent;
        }
    
    truncated nginx.conf file
  15. Apply the PingIntelligence policy at the global level (for all the APIs in your environment) or for an individual API.

    If the authorization header in the request has multiple tokens, the PingIntelligence policy extracts only the first valid bearer token from the authorization header.

    Choose from:

    • To apply the PingIntelligence policy globally, add ase_integration_request and ase_integration_response in the server section of nginx.conf:

      server {
          listen              4443 ssl bind;
          server_name         localhost;
          ssl_certificate     /usr/local/nginx/ssl/cert.pem;
          ssl_certificate_key /usr/local/nginx/ssl/key.pem;
          ssl_password_file   /usr/local/nginx/ssl/password_file;
          ssl_protocols       TLSv1.2;
          ssl_ciphers         HIGH:!aNULL:!MD5;
          resolver 8.8.8.8 ipv6=off;
           ase_integration_request; ase_integration_response;
      
          # Set OAuth Client details
       truncated nginx.conf file
    • To apply the PingIntelligence policy for a specific API, configure location in nginx.conf.

      ase_integration_request should be the first, and an ase_integration_response should be the last.

      Comment-out ase_integration_request and ase_integration_response that was configured to apply PingIntelligence policy globally.

      location / {
             include /usr/local/nginx/conf/pi-pf.conf;
             ase_integration_request;
             proxy_pass http://localhost:8080/;
             ase_integration_response;
      }
      
      truncated nginx.conf file
  16. Verify the syntactical correctness of nginx.conf by running the following command:

    # /usr/local/nginx/sbin/nginx -t
    nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
    nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
  17. Configure the PingIntelligence policy for NGINX Plus:

    1. Restart NGINX by entering the following command:

      # /usr/local/nginx/sbin/nginx -s stop
      # /usr/local/nginx/sbin/nginx
    2. Run the following command to verify if --with-compat and --with-http_ssl_module is in the list of flags under configured arguments:

      # sudo /usr/local/nginx/sbin/nginx -V
      nginx version: nginx/1.15.2 (nginx-plus-r16)
      built by gcc 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)
      built with OpenSSL 1.0.2g  1 Mar 2016
      TLS SNI support enabled
      configure arguments: --with-compat --with-http_ssl_module
    3. Verify that NGINX has restarted by entering the following command:

      # netstat -tulpn | grep 4443

      Example:

      The following is a sample nginx.conf file. Make sure that the PingIntelligence module and other configurations are added at the correct place in nginx.conf as shown in the sample file.

      worker_processes  4;
      
      error_log  /usr/local/nginx/logs/error.log debug;
      worker_rlimit_core  500M;
      working_directory  /usr/local/nginx;
      
      pid        /usr/local/nginx/pid/nginx.pid;
      env PF_ID;
      env PF_SECRET;
      
      load_module modules/ngx_ase_integration_module.so;
      load_module modules/ngx_http_ase_integration_request_module.so;
      load_module modules/ngx_http_ase_integration_response_module.so;
      load_module modules/ndk_http_module.so;
      load_module modules/ngx_http_lua_module.so;
      
      events {
          worker_connections  1024;
      }
      
      http {
      
          keepalive_timeout  65;
          upstream test.ase.pi {
             server IP:PORT max_fails=1 max_conns=100 fail_timeout=10;
             server IP:PORT max_fails=1 max_conns=100 fail_timeout=10 backup;
             keepalive 32;
      #      keepalive_timeout 3600s; # NOT allowed < 1.15.3
         }
      
          upstream introspect_server {
              server IP:PORT max_fails=1 max_conns=100 fail_timeout=10;
              server IP:PORT max_fails=1 max_conns=100 fail_timeout=10 backup;
              keepalive 32;
          }
      
          lua_shared_dict cache_dict 128m;
      
      server {
          listen              4443 ssl bind;
          server_name         localhost;
          ssl_certificate     /usr/local/nginx/ssl/cert.pem;
          ssl_certificate_key /usr/local/nginx/ssl/key.pem;
          ssl_password_file   /usr/local/nginx/ssl/password_file;
          ssl_protocols       TLSv1.2;
          ssl_ciphers         HIGH:!aNULL:!MD5;
          resolver 8.8.8.8 ipv6=off;
          ase_integration_request;
          ase_integration_response;
      
          # Set OAuth Client details
      
          # Set env variable PF_ID &PF_SECRET
          set_by_lua $client_id 'return os.getenv("PF_ID")';
          set_by_lua $client_secret 'return os.getenv("PF_SECRET")';
      
          # Uncomment next 2 lines to set client credentials here.
          # set $client_id nginx_client;
          # set $client_secret nginx_secret;
      
          set $oauth_username_key Username;
          set $oauth_client_id_key ClientID;
      
          # Set the token parameter name below after $arg_ and inside /ase/request.
          set $oauth_key_param $arg_access_token;
          set $oauth_token_param $arg_access_token;
          # Set cache lifetime, default is 120s.
          set $oauth_cache_timeout 120;
      
          # Set introspection URL
          set $oauth_url https://introspect_server/as/introspect.oauth2;
      
          location /introspect {
              internal;
              proxy_method    POST;
              if ($arg_auth_token) {
                  set $auth_token $arg_auth_token;
              }
               if ($http_authorization ~* .*?(bearer)(\s+)([-a-zA-Z0-9._~+/]+)(,|\s|$)) {
                  set $auth_token $3;
              }
              proxy_set_header  Content-Type "application/x-www-form-urlencoded";
              proxy_set_body  "client_id=${client_id}&client_secret=${client_secret}&token=${auth_token}";
              proxy_pass_request_body off;
              proxy_http_version 1.1;
              proxy_set_header Connection "";
              proxy_pass      $oauth_url;
          }
      
          location /shop {
             include /usr/local/nginx/conf/pi-pf.conf;
             proxy_pass http://18.209.173.37:4100/shop;
      
          }
          #DO NOT EDIT BELOW VARIABLE
          set $correlationid $pid-$request_id-$server_addr-$remote_addr-$remote_port-$request_length-$connection;
          #Certificate location of ASE
          set $certificate /usr/local/nginx/ssl/test.ase.pi;
          #ASE Token for sideband authentication
          set $ase_token <ASE_TOKEN>;
          #Host header which should be send to ASE
          set $ase_host test.ase.pi;
          #SNI value to use for ASE
          set $ase_ssl_host test.ase.pi;
          #ASE Request Proxy Configuration
          location = /ase/request {
             internal;
             ase_integration https://test.ase.pi;
             ase_integration_method "POST";
             ase_integration_http_version 1.1;
             ase_integration_ase_token $ase_token;
             ase_integration_correlation_id $correlationid;
             ase_integration_host $ase_host;
             # set token key here.
             ase_integration_token_key access_token;
             ase_integration_ssl_trusted_certificate $certificate;
             ase_integration_ssl_verify    off;
             ase_integration_ssl_verify_depth 1;
             ase_integration_ssl_server_name off;
             ase_integration_ssl_name $ase_ssl_host;
             ase_integration_next_upstream error timeout non_idempotent;
          }
          #ASE Response Proxy Configuration
          location = /ase/response {
             internal;
             ase_integration https://test.ase.pi;
             ase_integration_method "POST";
             ase_integration_http_version 1.1;
             ase_integration_ase_token $ase_token;
             ase_integration_correlation_id $correlationid;
             ase_integration_host $ase_host;
             ase_integration_ssl_trusted_certificate $certificate;
             ase_integration_ssl_verify    off;
             ase_integration_ssl_verify_depth 1;
             ase_integration_ssl_server_name off;
             ase_integration_ssl_name $ase_ssl_host;
             ase_integration_next_upstream error timeout non_idempotent;
          }
      }
      
      }