HAProxy Enterprise SAML Component Version 1.2

Before you begin

About SAML 2.0

The XML-based Security Assertion Markup Language (SAML) 2.0 open-standard transfers identity data (assertions) between an Identity Provider and a Service Provider.

Identity Provider

Performs authentication on the Service Provider's behalf.

Service Provider

Authorizes users to access the requested resource once they are authenticated by a trusted Identity Provider.

About HAProxy Enterprise SAML Component

HAProxy Enterprise SAML Component acts as a SAML Service Provider. It provides SP-initiated cross-domain web single-sign-on (SSO) to any web application located behind an HAProxy Enterprise server. You thus don't have to implement SAML directly in your application.

In an SP-initiated SSO flow, the Service Provider creates an Authentication Request (AuthnRequest) and redirects the user to the Identity Provider.

HAProxy Enterprise SAML Component checks user credentials against an Identity Provider such as Azure Active Directory, either on-premises or in the cloud.

/fr/documentation/hapee/1-8r2/assets/images/saml-overview-3c32cb525507e9bcd2b58c3477de2a2e54cc5435d4689f85ab21051424dab3fd.png

HAProxy Enterprise SAML Component then grants or denies access to web applications based on SAML assertions sent by the Identity Provider.

Features

  • Implement SSO seamlessly, even for legacy web applications

  • Configure logging and grant access thanks to the HAProxy Enterprise ACL syntax

  • Check SAML assertions or attributes with XPath

  • Retrieve SAML assertions and use them as HAProxy Enterprise variables. For example, you can then:

    • Grant access to a group of users

    • Enhance logs

    • Pass user information to the application via HTTP headers

Architecture

HAProxy Enterprise SAML Component expands the functionalities of HAProxy Enterprise thanks to the Stream Processing Offload Engine.

HAProxy Enterprise SAML Component is a Stream Processing Offload Agent. It communicates with HAProxy Enterprise using the Stream Processing Offload Protocol.

Concepts and workflows

Single sign-on using SAML in a Web browser

The SSO workflow using a Web browser is as follows:

/fr/documentation/hapee/1-8r2/assets/images/saml-workflow-specs-6ab92713b502502e266dda6f9cbd5bf00e523ee8cbdc244938b3ab010a26da99.png
User does not have an authentication session at the Identity Provider
  1. A user visits a web application (a SAML Service Provider).

  2. The web application redirects the user's browser to the SAML Identity Provider via HAProxy Enterprise SAML Component.

  3. HAProxy Enterprise SAML Component and the web application establish a trust relationship by exchanging certificates over HTTPS.

  4. The user signs on, and the Identity Provider validates credentials.

  5. HAProxy Enterprise SAML Component redirects the user's browser back to the web application with a SAML response containing a SAML authentication assertion. The response is sent to the web application's Assertion Consumer Service URL.

Authentication

When a user wants to access a web application:

  1. HAProxy Enterprise SAML Component checks that the user has sent a valid SAML cookie.

  2. The user has sent a valid SAML cookie

    HAProxy Enterprise SAML Component grants access to the web application.

    The user has not sent a valid SAML cookie
    1. The user sends, through their browsers, a SAML AuthnRequest (Authentication Request) to the Identity Provider.

      The AuthnRequest format is specific to the Identity Provider.

    2. The Identity Provider asks the user to authenticate via an authentication portal or any other way (e.g., tokens or 2-factor authentication).

    3. Once the user has successfully authenticated, the Identity Provider sends a SAML Response to the Service Provider via the user's browser.

      The SAML Response is sent in a POST HTTP request.

      It contains authorization and authentication information about the user, such as the user name, the user's email address, or any custom XML attribute, depending on the Service Provider configuration.

    4. HAProxy Enterprise SAML Component analyzes this SAML Response and allows administrators to make specific checks or actions on XML attributes present in the SAML Response, and to take decisions based on the results.

Using web applications

As long as their browsers send a valid, non-expired, SAML cookie (called saml_cookie), users are granted access to web applications.

Every action requested in the on_saml_response category is executed on each subsequent HTTP response unless set_var_once is specified.

Single Logout

When a user wants to log out:

  1. HAProxy Enterprise SAML Component asks the Identity Provider to log out from any application where the user has previously logged in, by sending a LogoutRequest.

    You can customize the Logout Request sent to the Identity Provider via the logout_request_template_filename configuration directive.

  2. The Identity Provider replies to every application and asks them to log the user out, using a Logout Response.

Prerequisites

To use HAProxy Enterprise SAML Component, you must have access to a SAML Identity Provider such as Azure Active Directory, Okta, or Ping, on-premises, or in the cloud.

Installing HAProxy Enterprise SAML Component

Install HAProxy Enterprise SAML Component via your package manager.

To install the HAProxy Enterprise SAML Component on Ubuntu 20.04, run:

$ sudo apt install hapee-extras-spoa-saml

See also

Installing HAProxy Enterprise 1.8r1

HAProxy Enterprise SAML Component Azure Quick Start Guide

This Quick Start Guide will guide you through setting up a sandbox HAProxy Enterprise SAML Component implementation in a Ubuntu 20.04 LTS virtual machine

Warning

This setup is meant for test purposes only. Do not use it in a production environment.

We will enable single sign-on to a local NGINX instance. We will use Azure Active Directory as the Identity Provider. HAProxy Enterprise SAML Component will be the Service Provider.

In this quick start guide, you will:

  • Configure an Azure application

  • Configure an Ubuntu virtual machine

  • Start HAProxy Enterprise and HAProxy Enterprise SAML Component

  • Install HAProxy Enterprise and HAProxy Enterprise SAML Component on the virtual machine

  • Connect to your sample local application by providing Azure credentials

Conventions

The procedures below use the following icons:

azure-logo20

Perform the step in Microsoft Azure.

ubuntu20

Perform the procedure in the Ubuntu VM.

Configuring an Azure application

  1. Define your sample local application's FQDN.

    app.example.local

Creating an Azure Active Directory enterprise application

azure-logo40 Perform the steps below on the Azure portal.

  1. Launch a web browser, then sign in to the Microsoft Azure portal as a cloud application administrator, or as an application administrator for your Azure Active Directory tenant.

  2. In Microsoft Azure, create a new non-gallery enterprise application in Azure Active Directory.

  3. Click Assign users and groups, and grant access to the Azure Active Directory enterprise application to one or several users.

See also

Add an unlisted (non-gallery) application to your Azure AD organization

Exporting the tenant ID and usernames

azure-logo40 Perform the steps below on the Azure portal.

  1. Navigate to Azure Active Directory, then write down your tenant ID.

  2. Write down the first name of one or several users who have access to your Azure Active Directory enterprise application from their user profiles.

    We will whitelist users later on.

Setting up the basic SAML configuration

azure-logo40 Perform the steps below on the Azure portal.

  1. Select Sign-on, then click SAML.

    ../../_assets/images/azure-select-a-single-sign-on-method.png

    The Set up Single Sign-On with SAML page appears.

    ../../_assets/images/azure-set-up-single-sign-on-with-saml.png
  2. Edit the Basic SAML Configuration:

    Identifier (Entity ID)

    Enter a SAML ID for your application. For the sake of simplicity, enter your Azure Active Directory enterprise application's name.

    This ID can only contain alphanumeric characters and underscores (_).

    samlappaugust11

    Reply URL (Assertion Consumer Service URL)

    Enter https://<Your sample local application's FQDN>/saml/reply.

    Logout Url

    Enter https://<Your sample local application's FQDN>/saml/logout.

Configuring the Ubuntu VM

  1. Launch a new Ubuntu Desktop 20.04 LTS virtual machine.

    Select the Bridged Network mode.

    ../../_assets/images/saml-bridge-vm.png
  2. Connect to your VM via SSH or PuTTY.

    ../../_assets/images/saml-putty-0.png ../../_assets/images/saml-putty-1.png ../../_assets/images/saml-putty-2.png

Creating a sample local application

ubuntu40 Perform the steps below on the Ubuntu VM.

We will set up an NGINX instance on the virtual machine as a sample application. It will listen on localhost on port 3200 and will not be SAML-enabled on its own.

Warning

In a production environment, your application would be hosted on a cluster of dedicated servers, on a private network.

Though the security level provided by this implementation is very poor, it is enough to show the basics of setting up HAProxy Enterprise SAML Component.

  1. Install NGINX:

    ubuntu@vm:~$ sudo apt install nginx -y
  2. Customize the NGINX welcome page:

    ubuntu@vm:~$ sudo sed -i 's/Welcome to nginx/My SAML application/' \
    /var/www/html/index.nginx-debian.html
  3. Make the NGINX instance listen on port 3200:

    ubuntu@vm:~$ sudo sed -i 's/80/3200/' /etc/nginx/sites-enabled/default
    ubuntu@vm:~$ sudo systemctl restart nginx

Creating variables

ubuntu40 Perform the steps below on the Ubuntu VM.

  1. Add the following variables to a new variables.txt file:

    export myazureapp=<Your Azure application's name>
    export idp_app_id=<Your Azure application ID>
    export idp_tenant_id=<Your Azure Active Directory tenant ID>
    export myappfqdn=<Your sample local application's FQDN>
    export myappsocketpadress=<Your sample local application's IP:port>
    export samlapp=<Internal name for your sample local application>
    export samlappusers=<Space delimited list of users' first names>
    export lbipaddress=<HAProxy Enterprise's IP address>
    export hapeeversion=<HAProxy Enterprise Major Version Number>
    export hapeekey=<HAProxy Enterprise Key>
    ubuntu@vm:~$ cat <<EOF > variables.txt
    export myazureapp=samlappaugust11
    export idp_app_id=0000b000-00a0-0000-00c0-0000c000a0c0
    export idp_tenant_id=0fbb0000-0000-00ad-b00e-f00000000000
    export myappfqdn=app.example.local
    export myappsocketpadress=192.168.1.10:3200
    export samlapp="\$myazureapp"
    export samlappusers='Elena John Mary\\ Lou'
    export lbipaddress=127.0.0.1
    export hapeeversion=1.8
    export hapeekey=xxxxxxxx-xxxxxxxx
    EOF

Installing required packages

ubuntu40 Perform the steps below on the Ubuntu VM.

  1. Install cURL, HAProxy Enterprise, and HAProxy Enterprise SAML Component:

    ubuntu@vm:~$ source variables.txt
    ubuntu@vm:~$ sudo apt install curl -y
    ubuntu@vm:~$ curl -s https://cdn.haproxy.com/static/install_haproxy_enterprise.sh |
    sudo bash /dev/stdin 1.8r2 $hapeekey
    ubuntu@vm:~$ sudo apt install hapee-extras-spoa-saml -y

Creating a self-signed SSL certificate

ubuntu40 Perform the steps below on the Ubuntu VM.

  1. Create a self-signed SSL certificate to allow connecting via HTTPS:

    ubuntu@vm:~$ source variables.txt
    ubuntu@vm:~$ openssl req -keyout key.pem \
    -out cert.pem -x509 -sha256 -nodes -days 365 -newkey rsa:2048 \
    -subj "/C=FR/ST=IdF/L=Paris/O=HAProxy Technologies/OU=IT/CN=$myappfqdn"

    Your sample local application's FQDN is used in the certificate Common Name. The certificate is valid only if the request hostname matches the common name.

  2. Concatenate the key and the certificate into a new certificate:

    ubuntu@vm:~$ cat key.pem cert.pem |
    sudo tee /etc/hapee-$hapeeversion/certs/$samlapp.pem

Creating the HAProxy Enterprise configuration file

ubuntu40 Perform the steps below on the Ubuntu VM.

The HAProxy Enterprise hapee-lb.cfg configuration file will contain:

  • A SAML frontend to redirect user requests to HAProxy Enterprise SAML Component

  • The three following backends:

    • A backend for the Stream Processing Offload Engine

    • A default backend to manage errors

    • A backend for your sample local application

  1. Create the HAProxy Enterprise hapee-lb.cfg configuration file:

    The bind :443 ssl directive performs SSL termination on HAProxy Enterprise. You can then leverage HAProxy Enterprise to implement SSL in all your applications, whatever the underlying technologies.

    ubuntu@vm:~$ source variables.txt
    ubuntu@vm:~$
    frontend ft-saml
        bind :80
        bind :443 ssl crt $samlapp.pem
        mode http
        option http-buffer-request
        tcp-request inspect-delay 10s
        timeout client 1m
        http-request set-var(sess.saml_app) str($samlapp)                            if { hdr(host) -i $myappfqdn }
        filter spoe engine spoe-saml config
        http-request send-spoe-group spoe-saml spoe-group-req
        http-request redirect location                %[var(txn.saml.redirect_to)] code 302 if   { var(txn.saml.redirect_to) -m found }
        http-request deny                                                                   if ! { var(txn.saml.saml_auth_ok) -m bool } ! { var(txn.saml.saml_logout_ok) -m bool }
    
        http-request set-header givenname             %[var(txn.saml.givenname)]
        http-request set-header display_name          %[var(txn.saml.display_name)]
        http-request set-header all_attributes_names  %[var(txn.saml.all_attributes_names)]
        http-request set-header all_attributes_values %[var(txn.saml.all_attributes_values)]
        http-request set-header AuthnInstant          %[var(txn.saml.AuthnInstant)]
        http-request set-header AuthnInstant_ts       %[var(txn.saml.AuthnInstant_ts)]
        http-response set-header Set-Cookie           %[var(txn.saml.set_cookie)]           if { var(txn.saml.set_cookie) -m found }
        http-response set-header saml-auth-error-text %[var(txn.saml.saml_auth_error_text)] if { var(txn.saml.saml_auth_error_text) -m found }
        http-response set-header location             %[var(txn.saml.redirect_after_auth)]              if { var(txn.saml.redirect_after_auth)  -m found }
        http-response set-status 303                                                        if { var(txn.saml.redirect_after_auth)  -m found }
    
        default_backend bk-err
        use_backend                                   %[var(txn.saml.saml_app_backend)]     if { var(txn.saml.saml_app_backend) -m found }
    
    backend bk-spoe
        mode tcp
        timeout connect 5s
        timeout server  30s
        server auth-server-spoe 127.0.0.1:12345
    
    backend bk-err
        mode http
    
    backend bk-$samlapp
        option forwardfor
        mode http
        server $samlapp $myappsocketpadress
        timeout connect 30s
        timeout server 1m
    EOF

Creating the HAProxy Enterprise SAML Component initialization file

ubuntu40 Perform the steps below on the Ubuntu VM.

  1. Create the HAProxy Enterprise SAML Component saml.ini initialization file:

    ubuntu@vm:~$ source variables.txt
    ubuntu@vm:~$ cat <<EOF | sudo tee /etc/hapee-extras/saml.ini
    config_version = 1.0.0
    
    [$samlapp]
    {{IDP_APP_NAME}} = $myazureapp
    {{IDP_APP_ID}} = $idp_app_id
    {{IDP_TENANT_ID}} = $idp_tenant_id
    {{CLAIM_PREFIX}} = http://schemas.xmlsoap.org/ws/2005/05/identity/claims
    
    {{APP_FQDN}} = $myappfqdn
    {{APP_LOGIN_URL}} = https://{{APP_FQDN}}/saml/reply
    {{APP_LOGOUT_URL}} = https://{{APP_FQDN}}/saml/logout
    {{APP_BACKEND}} = bk-{{APP_NAME}}
    
    saml_cookie_secure = 0
    saml_cookie_samesite = Lax
    saml_cookie_httponly = 0
    saml_cookie_lifetime = 3600
    saml_cookie_time_offset = 0
    saml_cookie_domain = {{APP_FQDN}}
    authn_request_template_filename = authn_request.xml
    logout_request_template_filename = logout_request.xml
    saml_app_backend = {{APP_BACKEND}}
    
    sign_authn_requests=0
    sign_logout_requests=0
    verify_signature=0
    
    app_login_url = {{APP_LOGIN_URL}}
    app_logout_url = {{APP_LOGOUT_URL}}
    
    idp_login_url = https://login.microsoftonline.com/{{IDP_TENANT_ID}}/saml2
    idp_logout_url = https://login.microsoftonline.com/logout.srf
    
    ; this field is also used to detect redirect loops between the IDp and our app
    idp_referer_url = https://login.microsoftonline.com/
    on_saml_response check_schema
    on_saml_response check_attr entity_id spn:{{IDP_APP_ID}}
    on_saml_response check_attr version
    on_saml_response check_attr status_code
    on_saml_response check_attr issuer https://sts.windows.net/{{IDP_TENANT_ID}}/
    on_saml_response check_attr issue_instant
    on_saml_response check_attr destination {{APP_LOGIN_URL}}
    on_saml_response check_attr assertion required_count=1
    on_saml_response check_conditions required_count=1
    on_saml_response check_subject_confirmation_data required_count=1
    
    ; Get all the SAML attributes names
    on_saml_response check_attr set_var=all_attributes_names  set_var_sep=| xpath=/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute/@Name
    
    ; Get all the SAML attributes values
    on_saml_response check_attr set_var=all_attributes_values set_var_sep=| xpath=/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute/saml:AttributeValue/text()
    
    ; Get the User Display Name provided in SAML Responses or Logout Requests
    on_saml_response check_attr set_var=display_name xpath=/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name='http://schemas.microsoft.com/identity/claims/displayname']/@Name
    
    on_saml_response check_attr set_var=AuthnInstant_ts xpath=/samlp:Response/saml:Assertion/saml:AuthnStatement/@AuthnInstant set_var_as_timestamp
    on_saml_response check_attr set_var=AuthnInstant    xpath=/samlp:Response/saml:Assertion/saml:AuthnStatement/@AuthnInstant
    
    on_logout_request check_attr set_var=display_name xpath=/samlp:LogoutRequest/saml:NameID/text()
    on_logout_request check_attr destination {{APP_LOGOUT_URL}} required
    on_logout_request check_attr issuer https://sts.windows.net/{{IDP_TENANT_ID}}/ required
    EOF

Creating the Microsoft Azure templates

ubuntu40 Perform the steps below on the Ubuntu VM.

  1. Copy the Microsoft Azure example authentication request and logout request templates to the HAProxy Enterprise configuration directory:

    ubuntu@vm:~$ sudo cp  \
    ubuntu@vm:~$ sudo cp  \

Starting HAProxy Enterprise and HAProxy Enterprise SAML Component

ubuntu40 Perform the steps below on the Ubuntu VM.

  1. Start HAProxy Enterprise and HAProxy Enterprise SAML Component:

    :~$ sudo systemctl enable hapee-extras-spoa-saml
    Synchronizing state of hapee-extras-spoa-saml.service with SysV service script with /lib/systemd/systemd-sysv-install.
    Executing: /lib/systemd/systemd-sysv-install enable hapee-extras-spoa-saml
    Created symlink /etc/systemd/system/multi-user.target.wants/hapee-extras-spoa-saml.service → /lib/systemd/system/hapee-extras-spoa-saml.service.
    :~$ sudo systemctl start hapee-extras-spoa-saml
    :~$ sudo systemctl enable hapee-1.8-lb
    Synchronizing state of hapee-2.1-lb.service with SysV service script with /lib/systemd/systemd-sysv-install.
    Executing: /lib/systemd/systemd-sysv-install enable hapee-2.1-lb
    Created symlink /etc/systemd/system/multi-user.target.wants/hapee-2.1-lb.service → /lib/systemd/system/hapee-2.1-lb.service.
    :~$ sudo systemctl start hapee-1.8-lb

Connecting to your sample local application

ubuntu40 Perform the steps below on the Ubuntu VM.

  1. Redirect your NGNIX instance's Fully Qualified Domain Name to the IP address your HAProxy Enterprise instance is listening on in the /etc/hosts file:

    :~$ echo "127.0.0.1 $myappfqdn" | sudo tee -a /etc/hosts
  2. Connect to your sample local application's Fully Qualified Domain Name via a web browser.

    Connect to http://app.example.local.

    Note

    Your NGINX instance listens on port 3200. You are then actually connecting to HAProxy Enterprise.

  3. Sign on to the Microsoft Azure portal with your Microsoft Azure credentials.

    ../../_assets/images/saml-sign-in-to-microsoft-azure.png

    You can safely ignore the warning message since we use a self-signed certificate.

    ../../_assets/images/saml-warning.png

    The NGINX instance's welcome page displays.

    ../../_assets/images/saml-success.png

Troubleshooting

ubuntu40 Perform the steps below on the Ubuntu VM.

If an error occurs:

  1. Stop HAProxy Enterprise SAML Component:

    :~$ sudo service saml stop
    # Stopping spoa-saml (pid 8831 according to /var/run/saml.pid) ...
      Waiting..
       --> removing stale pid file ...
      ==> stop spoa-saml Done.
  2. Start HAProxy Enterprise SAML Component in debug mode:

    :~$  -C  \
    -f  --debug-all -F >> /tmp/log_file 2>&1
  3. Repeat the steps that led to the error, then analyze the /tmp/log_file file.

Whitelisting or blacklisting usernames

ubuntu40 Perform the steps below on the Ubuntu VM.

You can whitelist or blacklist users at the Service Provider level, whatever the Identity Provider.

  1. Insert the following directive in the HAProxy Enterprise SAML Component saml.ini initialization file:

    on_saml_response check_subject_confirmation_data/a on_saml_response check_attr optional set_var_cnt set_var=givenname xpath=/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"]/saml:AttributeValue/text()'
    :~$ sudo sed -i '/on_saml_response check_subject_confirmation_data/a on_saml_response check_attr optional set_var_cnt set_var=givenname xpath=/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"]/saml:AttributeValue/text()'
  2. Insert the following directive in the HAProxy Enterprise hapee-lb.cfg configuration file's frontend ft-saml section:

    http-request deny if ! { var(txn.saml.<Internal name for your sample local application>.givenname) <Space delimited list of users' first names> }"

    http-request deny if ! { var(txn.saml.MySAMLApp.givenname) Elena John Mary\ Lou }"

    :~$ sudo sed -i "/http-request deny/a        \    http-request deny if !        { var(txn.saml.$samlapp.givenname) $samlappusers }"
  3. Restart HAProxy Enterprise and HAProxy Enterprise SAML Component:

    :~$ sudo systemctl reload hapee-1.8-lb
    :~$ sudo systemctl stop hapee-extras-spoa-saml
    :~$ sudo  -C  -f
  4. Sign on to your sample local application with a whitelisted username, then with another username.

Tip

To blacklist users, remove the ! sign before the condition.

Reference guide

HAProxy Enterprise configuration file sections

Frontend

frontend ft-saml
 bind :80
 bind :443 ssl crt mycert.pem
 mode http
 option http-buffer-request
 tcp-request inspect-delay 10s
 timeout client 1m
 http-request set-var(sess.saml_app) str(MySAMLApp) if { hdr(host) -i app.example.local }
 filter spoe engine spoe-saml config
 http-request send-spoe-group spoe-saml spoe-group-req
 http-request redirect location %[var(txn.saml.redirect_to)] code 302 if   { var(txn.saml.redirect_to) -m found }
 http-request deny                                                    if ! { var(txn.saml.saml_auth_ok) -m bool } ! { var(txn.saml.saml_logout_ok) -m bool }

 http-request set-header givenname             %[var(txn.saml.givenname)]
 http-request set-header displayname           %[var(txn.saml.displayname)]
 http-request set-header all_attributes_names  %[var(txn.saml.all_attributes_names)]
 http-request set-header all_attributes_values %[var(txn.saml.all_attributes_values)]
 http-request set-header AuthnInstant          %[var(txn.saml.AuthnInstant)]
 http-request set-header AuthnInstant_ts       %[var(txn.saml.AuthnInstant_ts)]
 http-response set-header Set-Cookie %[var(txn.saml.set_cookie)]                     if { var(txn.saml.set_cookie) -m found }
 http-response set-header saml-auth-error-text %[var(txn.saml.saml_auth_error_text)] if { var(txn.saml.saml_auth_error_text) -m found }
Key directives
  • Declare a SAML frontend to redirect user requests to HAProxy Enterprise SAML Component:

    frontend ft-saml
  • Listen to incoming traffic over HTTP and HTTPS:

    bind :80
  • Listen to incoming traffic over HTTPS and enable SSL termination:

    bind :443 ssl crt mycert.pem

    Note

    The CRT parameter identifies the PEM-formatted SSL certificate location. This certificate should contain both the HAProxy Enterprise server's public certificate and private key.

  • Wait for the whole HTTP request body before forwarding it to HAProxy Enterprise SAML Component :

    option http-buffer-request
  • Set the maximum time to wait for data during content inspection to 10 seconds:

    tcp-request inspect-delay 10s
  • Set variable sess.saml_app to MySAMLApp if the HTTP request's host header field matches app.example.local, ignoring case:

    Note

    Replace app.example.local by the section header of your HAProxy Enterprise SAML Component saml.ini initialization file, and edit the ACL as needed. See SAML application backend.

    http-request set-var(sess.saml_app) str(MySAMLApp) if { hdr(host) -i app.example.local }
  • Declare the spoe-saml SPOE filter and its hapee-saml-spoe.cfg configuration file, to forward streaming data to HAProxy Enterprise SAML Component:

    filter spoe engine spoe-saml config
  • Send messages to HAProxy Enterprise SAML Component; define the spoe-group-req group of messages to send via a spoe-group section in the hapee-saml-spoe.cfg SPOE configuration file:

    http-request send-spoe-group spoe-saml spoe-group-req
  • Redirect the user to the value of variable txn.saml.redirect_to:

    http-request redirect location %[var(txn.saml.redirect_to)] code 302 if   { var(txn.saml.redirect_to) -m found }

See also

Configuring HAProxy Enterprise for Transport Layer Security (TLS)

Stream Processing Offload Engine (SPOE)

Backends

Add the following backend sections:

Stream Processing Offload Engine backend:
backend bk-spoe
 mode tcp
 timeout connect 5s
 timeout server  30s
 server auth-server-spoe 127.0.0.1:12345

Change the socket address on the server line to match your setup.

You can use the spoa-saml -A and -P options to change the IP address and the port.

Default backend to manage errors
backend bk-err
 mode http

Make it the default backend in the frontend section:

default_backend bk-err

If no target backend has been set, the fallback backend is bk-err. The user is not granted access and receives a 502 error.

SAML application backend
backend bk-MySAMLApp
 option forwardfor
 mode http
 server app1 127.0.0.1:3200
 timeout connect 30s
 timeout server 1m

Warning

Before sending the HAProxy Enterprise requests to the Stream Processing Offload Agent, you must set the sess.saml_app variable to the name of the application.

This application must have a dedicated section in the HAProxy Enterprise SAML Component saml.ini initialization file.

See also

sess.saml_app

HAProxy Enterprise SAML Component saml.ini initialization file

You can configure several applications in the HAProxy Enterprise SAML Component saml.ini initialization file, one per section.

To configure an application called MySAMLApp, use [MySAMLApp] as the section header.

Configuration options

config_version

Version of the configuration file. For upward compatibility.

Type

string

idp_login_url

URL of the Identity Provider's web authentication portal.

Type

string

Example

On Microsoft Azure, https://login.microsoftonline.com/{{IDP_APP_ID}}/saml2.

idp_logout_url

Single Logout URL. Endpoint which will initiate the SAML Logout for all applications.

Type

string

Example

On Microsoft Azure, https://login.microsoftonline.com/logout.srf

idp_referer_url

HTTP Referer value to check when receiving HTTP data from the Identity Provider.

Type

string

Example

On Microsoft Azure, https://login.microsoftonline.com/.

app_login_url

URL where the application expects to receive the SAML Response from the Identity Provider. The reply URL is also referred to as the Assertion Consumer Service.

Type

string

app_logout_url

When the users browse this URL, a LogoutRequest is sent to the Identity Provider.

Type

string

signing_algo

Cryptographic algorithm used to sign sent requests.

Type

string

idp_public_cert

Identity Provider's X509 public certificate of the (in base64 .pem format). Used to verify SAML Responses' "Response" and "Assertion" attributes.

Type

string

verify_signature

Verify the signature of incoming SAML requests.

Type

boolean

Default value

0

require_signed_response

Fail if the XML response is not signed.

Type

boolean

Default value

0

require_signed_assertion

Fail if the XML assertion is not signed.

Type

boolean

Default value

0

signing_key

Private key used to sign sent requests.

Type

string

sign_authn_requests

Set to 1 to sign Authn Requests.

Type

boolean

Default value

0

sign_logout_requests

Set to 1 to sign Logout Requests.

Type

boolean

Default value

0

saml_app_backend

Backend name for this application.

Type

string

Default value

bk-{{APP_NAME}}

Actions

on_saml_response check_attr

Check any attribute in a SAML Response. You can use XPath=<xpath_expression> set_var=<my_var_name> to set it in an HAProxy variable.

By default, the SAML Response validation fails if you do not specify an attribute. Use the 'optional' flag to make the SAML Response validation succeed even if no attribute is specified.

on_saml_response check_schema

Validate the SAML response against the SAML 2.0 XSD schema.

on_saml_response check_conditions

Check the <SubjectConfirmationData> XML attribute, including NotBefore and NotOnOrAfter values.

on_saml_response check_subject_confirmation_data

Check the <Condition> XML attribute, including NotBefore and NotOnOrAfter values.

on_saml_response check_attr entity_id

Check that the audience <AudienceRestriction><Audience> attribute exists.

Optional

Specific entity_id value to check.

on_saml_response check_attr version

Check that the SAML protocol version is 2.0.

on_saml_response check_attr status_code

Check the SALMResponse status code.

Optional

Status to match. Otherwise compare to "urn:oasis:names:tc:SAML:2.0:status:Success".

on_saml_response check_attr destination

Check that the SAMLResponse Destination value matches this item.

Mandatory

Destination to match. You can use '<APP_LOGIN_URL>' to match the configured app_login_url. On Microsoft Azure, it must match the URL Assertion Consumer Service (ACS).

on_saml_response check_attr issuer

Check the Issuer attribute of the SAMLResponse.

Optional

Specific value to check.

on_saml_response check_attr issue_instant

Check that the IssueInstant attribute exists. It can be set in a variable by using 'set_var' and set in the for of a timestamp, using 'set_var_as_timestamp'.

on_saml_response check_attr assertion

Check that the Assertion attribute exists.

on_logout_request check_attr

Check any attribute in a Logout Request. You can use XPath=<xpath_expression> set_var=<my_var_name> to set it in an HAProxy variable.

on_logout_request check_attr issuer

Check the issuer attribute of the LogoutRequest.

Optional

Specific value to check.

on_logout_request check_attr name_id

Check that the nameId attribute exists in LogoutRequest.

on_logout_request check_attr destination

Check that the LogoutRequest destination value matches this item.

Mandatory

Destination to match.

Note

You can use {{APP_LOGOUT_URL}} to match the configured app_logout_url.

Microsoft Azure HAProxy Enterprise SAML Component saml.ini initialization file example

This example is intended to be used with Microsoft Azure. To use HAProxy Enterprise SAML Component with other Identity Providers, this configuration file needs some adjustments.

Variables
{{ID_APP_NAME}}

Name of your application in Azure Active Directory.

{{IDP_APP_ID}}

Application ID provided by the Identity Provider (Azure Active Directory).

For instance: aa0aaaaa-0aa0-000a-a0a0-aa0000a0000a.

/fr/documentation/hapee/1-8r2/assets/images/azure-application-id-362e3f0f656ad91cf7e4beb21c7f9ddb195bd4b8d0e689e3d976c5cc427e6058.png
{{IDP_TENANT_ID}}

aaa000a0-0000-0a00-0000-000a00a00a0

{{CLAIM_PREFIX}}

http://schemas.xmlsoap.org/ws/2005/05/identity/claims

{{APP_FQDN}}

Fully Qualified Domain Name of the Identity Provider (Azure Active Directory).

dkorunichaproxy.onmicrosoft.com

{{APP_LOGIN_URL}}

Assertion Consumer Service URL, depending on your application. Value of app_login_url for this application.

{{APP_LOGIN_URL}} is automatically replaced if you specify it in the HAProxy Enterprise SAML Component saml.ini initialization file.

{{APP_LOGOUT_URL}}

Value of app_logout_url for this application.

Logout URL, depending on your application.

https://{{APP_FQDN}}/saml/logout

{{APP_BACKEND}}

Backend on which the application is available.

bk-{{APP_NAME}}: {{APP_NAME}} will be replaced with the section name.

If the section header is [MySAMLApp], the backend is called bk-MySAMLApp.

saml.ini example

config_version = 1.0.0

[MySAMLApp]
 = xxx  #  the name of your application in Azure AD
 = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
 = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
 = http://schemas.xmlsoap.org/ws/2005/05/identity/claims
 = xxx  #  ex: app1.example.local
 = https:///saml/reply    # ACS url, depending on your application
 = https:///saml/logout  # logout url, depending on your application
 = bk-                      # APP_NAME will be replaced with the section name

saml_cookie_secure = 0
saml_cookie_httponly = 1
saml_cookie_lifetime = 3600
saml_cookie_time_offset = 0
saml_cookie_domain =
authn_request_template_filename = authn_request.xml
logout_request_template_filename = logout_request.xml
saml_app_backend =

idp_login_url = https://login.microsoftonline.com//saml2
idp_logout_url = https://login.microsoftonline.com//saml2
app_login_url =
app_logout_url =
idp_referer_url = https://login.microsoftonline.com/

on_saml_response check_schema
verify_signature=0
on_saml_response check_attr entity_id spn:
on_saml_response check_attr version
on_saml_response check_attr status_code
on_saml_response check_attr issuer https://sts.windows.net/
on_saml_response check_attr issue_instant
on_saml_response check_attr destination
on_saml_response check_attr assertion required_count=1
on_saml_response check_conditions required_count=1
on_saml_response check_subject_confirmation_data required_count=1

on_logout_request check_attr destination  required
on_logout_request check_attr issuer https://sts.windows.net// required

on_saml_response check_attr optional set_var_cnt set_var=givenname xpath=/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name="/givenname"]/saml:AttributeValue/text()

Note

You can use retrieved XML attributes in HTTP rules in the HAProxy Enterprise hapee-lb.cfg configuration file:

  • To restrict acess:

    For instance:

    http-request deny if ! \{ var(txn.givenname) user1 user2 user3 }
  • To set HTTP headers:

    For instance:

    set-header myname %[var(txn.givenname)]

AuthnRequest template

Here is an example of an Authentication Request template. You can send generated AuthnRequests to Microsoft Azure:

authn_request.xml
<samlp:AuthnRequest
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
ID="id%%RANDOM_ID_HEX_32%%"
Version="2.0" IssueInstant="%%NOW_WITH_MS%%"
ForceAuthn="false"
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">{{IDP_APP_ID}}</Issuer>
</samlp:AuthnRequest>

You can specify templates via the authn_request_template_filename configuration directive. The path is relative to the configuration directory. You can specify a custom directory via the -C command-line option.

The following patterns are automatically replaced:

%%NOW%%

Current time in ISO 8601 format.

2020-01-28T15:25:14Z

%%NOW_WITH_MS%%

Current time in ISO 8601 format, including milliseconds.

2020-01-28T15:25:14.884Z

%%RANDOM_ID_HEX_32%%

32-char random ID, comprising the following characters: 0123456789abcdef.

%%ISSUER%%

Replace manually by the value expected by your Identity Provider. On Microsoft Azure, you can replace it with:

  • Your Microsoft Azure Application ID

    The entity_id received in the SAML Response is spn:<Application ID>.

    ae7edebf-2db4-476f-b1a9-bf5782b1799a5b25e637

  • The name of your application in Microsoft Azure

    The entity_id received in the SAML Response is this very issuer.

If your application name in this configuration file is the same as the one in Microsoft Azure, you can use {{APP_NAME}}.

ForceAuthn="false"

If set to True, users have to reauthenticate, even if they already have a valid session.

LogoutRequest template

You can use a similar template for Logout Requests:

logout_request.xml
<samlp:LogoutRequest
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
ID="id%%RANDOM_ID_HEX_32%%" Version="2.0" IssueInstant="%%NOW_WITH_MS%%" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<<<<<<< HEAD
  <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">{{IDP_APP_ID}}</Issuer>
  <NameID xmlns="urn:oasis:names:tc:SAML:2.0:assertion">%%NAME_ID%%</NameID>
=======
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">{{IDP_APP_ID}}</Issuer>
<NameID xmlns="urn:oasis:names:tc:SAML:2.0:assertion">%%NAME_ID%%</NameID>
>>>>>>> SAML-COMMON
</samlp:LogoutRequest>

The following patterns are automatically replaced:

%%ISSUER%%

Value from the SAML Response.

In Microsoft Azure, the following template applies:

https://sts.windows.net/<MS application ID>/

%%NameID%%

Value from the SAML Response, usually the user's email address.

Actions

on_saml_response check_attr

Check any attribute in a SAML Response. You can use XPath=<xpath_expression> set_var=<my_var_name> to set it in an HAProxy variable.

By default, the SAML Response validation fails if you do not specify an attribute. Use the 'optional' flag to make the SAML Response validation succeed even if no attribute is specified.

on_saml_response check_schema

Validate the SAML response against the SAML 2.0 XSD schema.

on_saml_response check_conditions

Check the <SubjectConfirmationData> XML attribute, including NotBefore and NotOnOrAfter values.

on_saml_response check_subject_confirmation_data

Check the <Condition> XML attribute, including NotBefore and NotOnOrAfter values.

on_saml_response check_attr entity_id

Check that the audience <AudienceRestriction><Audience> attribute exists.

Optional

Specific entity_id value to check.

on_saml_response check_attr version

Check that the SAML protocol version is 2.0.

on_saml_response check_attr status_code

Check the SALMResponse status code.

Optional

Status to match. Otherwise compare to "urn:oasis:names:tc:SAML:2.0:status:Success".

on_saml_response check_attr destination

Check that the SAMLResponse Destination value matches this item.

Mandatory

Destination to match. You can use '<APP_LOGIN_URL>' to match the configured app_login_url. On Microsoft Azure, it must match the URL Assertion Consumer Service (ACS).

on_saml_response check_attr issuer

Check the Issuer attribute of the SAMLResponse.

Optional

Specific value to check.

on_saml_response check_attr issue_instant

Check that the IssueInstant attribute exists. It can be set in a variable by using 'set_var' and set in the for of a timestamp, using 'set_var_as_timestamp'.

on_saml_response check_attr assertion

Check that the Assertion attribute exists.

on_logout_request check_attr

Check any attribute in a Logout Request. You can use XPath=<xpath_expression> set_var=<my_var_name> to set it in an HAProxy variable.

on_logout_request check_attr issuer

Check the issuer attribute of the LogoutRequest.

Optional

Specific value to check.

on_logout_request check_attr name_id

Check that the nameId attribute exists in LogoutRequest.

on_logout_request check_attr destination

Check that the LogoutRequest destination value matches this item.

Mandatory

Destination to match.

Note

You can use {{APP_LOGOUT_URL}} to match the configured app_logout_url.

Action flags
optional

This argument is not required.

required

This argument is mandatory.

nofail

For testing purposes. This action never fails, even if it returns an error.

required_count=<count>

Fails if the number of searched elements is different from <count>.

xpath=<XPath expression>

XPath expression to look for. Use with check_attr actions.

expected=<expected_value>

Fails if the XPath result is different from this expression.

set_var=<var_name>

If one or more XPath results are found, store their values in this variable. The variable name is then prefixed with the application name followed by a dot.

If you set set_var=myvar, the value is available in the HAProxy Enterprise hapee-lb.cfg configuration file via %[var(txn.saml.MySAMLApp.myvar)].

set_var_once

The variable is set only after the POST request from the SAML Identity Provider. Otherwise, it is set each time the SAML cookie is found.

set_var_cnt

The number of XPath results is stored into variable <APP_NAME>.<VAR_NAME>_cnt.

set_var_as_timestamp

If used with a value in ISO 8601 date and time format, the variable is converted to a timestamp.

2020-01-28T15:25:14.884Z

set_var_sep=<separator>

If multiple results are returned from the XPath query, separate them with this character.

set_var_default=<default_value>

Default value used if the XPath expression does not match.

sign_auth_requests

Set to 1 to sign authentication requests.

sign_logout_requests

Set to 1 to sign logout requests.

signing_algo

Cryptographic algorithm used to sign outbound requests.

signing_key

Private key used to sign outbound requests.

verify_signature

Verify the signature of incoming SAML requests.

Running HAProxy Enterprise SAML Component

To run HAProxy Enterprise SAML Component, run the following command:

~$ /opt/hapee-extras/bin/hapee-saml -C <config_dir> -f <SAML configuration file>
~$  -C spoa-saml/examples -f /etc/hapee-extras/saml.ini
Usage

hapee-saml [OPTION]...

-h

Print this message.

-f config_file

.ini file containing the SAML configuration.

-C config_dir

Directory containing the configuration file and the SAML templates.

-l --licenses

Print software licenses.

-v --version

Print product version.

--debug-spoe -d

Debug Stream Processing Offload Engine.

--debug-spoe-variables

Debug Stream Processing Offload Engine variables.

--debug-saml

Debug SAML actions.

--debug-xml

Debug XML parsing.

--debug-config

Debug configuration parsing.

--debug-all

Debug all, except the configuration parsing.

--print-cfg

Display configuration during startup.

--check-cfg -c

Check configuration, then exit.

--gid

Run in the specified group.

--uid

Run as the specified user.

-F

Disable syslog output, and run in the foreground.

-s

Use syslog.

-p <pidfile>

Write the server PID to the specified file.

-A <address>

Listen on this address.

-P <port>

Specify the port to listen on.

Default value: 12345

-n <num-workers>

Specify the number of workers.

-b <conn-backlog>

Specify the connection backlog value.

Default value: 10

Troubleshooting

Debug mode

If requests are denied or authentication fails, you can start the program with --debug-all -F to get more verbose output.

~$ hapee-saml -f /etc/hapee-extras/saml.ini --debug-all -F
  1586529662.886993 [00] Config version supported: 1.0.0
  1586529662.887347 [00] Config version 1.0.0
  1586529662.889158 [00] add namespace 0: samlp->urn:oasis:names:tc:SAML:2.0:protocol
  1586529662.889413 [00] add namespace 1: saml->urn:oasis:names:tc:SAML:2.0:assertion
  [...]

Testing XPath expressions

  1. Run HAProxy Enterprise SAML Component in debug mode.

  2. Save the SAML Response to a text file.

  3. Use the xmllint command-line XML tool to test XPath expressions.

    The xmllint command is provided in the libxml2 package.

$ hapee-saml -f /etc/hapee-extras/saml.ini --debug-all -F >> log_file 2>&1

$ xmllint --shell SAMLResponse.xml

setns saml=urn:oasis:names:tc:SAML:2.0:assertion
setns samlp=urn:oasis:names:tc:SAML:2.0:protocol

xpath /samlp:Response/@Destination

Various online XPath test tools are available online. Be careful not to send confidential information.

Infinite loop

If an infinite loop between your application and the Identity Provider occurs when trying to access a resource, check your cookie_secure setting. If set to 1, your browser will only use the cookie for HTTPS, not for plain HTTP.

Before you go into production

  1. Set saml_cookie_secure to 1.

  2. Enable XML signatures if supported by your Identity Provider and your setup.

  3. Depending on how your Identity Provider handles logouts, ensure that the LogoutRequest is sent to your application along with a cookie.

  4. Some Identity Providers' cookies (for example, Azure's) are regarded as third-party (these Identity Providers use an iframe to send the LogoutRequest to your application).

    These cookies might be blocked by your browser, depending on its configuration and the value of the SameSite cookie attribute.

    Set the SameSite to 0 or 1 via the saml_cookie_samesite configuration item.

  5. To test logout, check that the LogoutRequest returns a 200 code and is received by your application.

    Successful LogoutRequests also set the txn.saml.saml_logout_ok HAProxy Enterprise variable to 1.