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.

/de/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:

/de/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 local 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:

  1. Create a local virtual machine to host your sample application.

  2. Create a sample local application.

  3. Create a SAML enabled Azure Active Directory enterprise application.

  4. Set up the Azure Active Directory enterprise application's SAML parameters.

  5. Manage HAProxy Enterprise SAML Component and Microsoft Azure certificates.

  6. Install required packages.

  7. Configure HAProxy Enterprise and HAProxy Enterprise SAML Component.

  8. Start HAProxy Enterprise and HAProxy Enterprise SAML Component.

  9. Connect to your sample local application.

  10. Whitelist or blacklist usernames.

Conventions

The procedures below use the following icons:

azure-logo

Perform the step in Microsoft Azure.

terminal

Perform the step in a Bash terminal.

browser

Perform the step in a browser.

Creating a local virtual machine

  1. Create a new Ubuntu Desktop 20.04 LTS local virtual machine.

  2. Log in to your new local virtual machine.

The procedures below will all take place on the local virtual machine.

Creating a sample local application

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

Note

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

  1. Launch a terminal.

  2. terminal Install NGINX:

    ~$ sudo apt install nginx -y
  3. terminal Make the NGINX instance listen on port 3200:

    ~$ sudo sed -i 's/80/3200/' /etc/nginx/sites-enabled/default
    ~$ sudo systemctl restart nginx
  4. browser Connect to 127.0.0.1:3200 via a web browser.

    The NGINX instance's welcome page displays.

    You cannot access it via 127.0.0.1:80. We will give access to the sample local application on port 80 later on via HAProxy Enterprise SAML Component.

    Note

    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.

Creating an Azure Active Directory enterprise application

  1. browser 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. azure-logo In Microsoft Azure, create a new non-gallery enterprise application in Azure Active Directory.

  3. terminal Add the following variables to your .bashrc file:

    ~$ echo 'myazureapp="<Your Azure application's name>"' >> ~/.bashrc
    ~$ echo 'idp_app_id="<Your Azure application ID>"' >> ~/.bashrc
    /de/documentation/hapee/1-8r2/assets/images/azure-create-app-variables-8b05385db611acdd0863f4e09443ff4aa991c86c35cfab7c18d76b3a43718a4d.png

    We will use these variables later on to configure HAProxy Enterprise and HAProxy Enterprise SAML Component.

  4. azure-logo 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

Setting up the Azure Active Directory enterprise application's SAML parameters

Setting up the basic SAML configuration

  1. terminal Add a variable for your sample local application's FQDN to your .bashrc file:

    ~$ echo 'myappfqdn="<Your sample local application's FQDN>"' >> ~/.bashrc
    ~$ echo 'myappfqdn="app.example.local"' >> ~/.bashrc
  2. azure-logo Select Sign-on, then click SAML.

    /de/documentation/hapee/1-8r2/assets/images/azure-select-a-single-sign-on-method-9b9540c62bfc9702572250959a720970e392c28cf07d5d146323af2bca52accf.png

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

    /de/documentation/hapee/1-8r2/assets/images/azure-set-up-single-sign-on-with-saml-af07839c912841d9e3b443de87bf8efeb4f22d84f28cffdc540f2e0aeef792ce.png
  3. azure-logo 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, which corresponds to the value of the $myazureapp variable.

    samlappjuly1

    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.

    /de/documentation/hapee/1-8r2/assets/images/azure-create-app-variables-saml-4fcd89ac6a53f2f50f6f42bd25e2c869becd96c13f97944593d36a32afcfd9da.png

Exporting the certificate and the tenant ID

  1. azure-logo Click the pencil in the SAML Signing Certificate area, then select Sign SAML response and assertion in the Signing option drop-down.

  2. azure-logo Download the Azure Openssl PEM format Base64 Azure Active Directory enterprise application' certificate.

    For instance samlappjuly1.cer.

    /de/documentation/hapee/1-8r2/assets/images/azure-certificate-22169403957be28fd8776f7f862a67d7284cc468737ce3bece55bd0b48280a59.png
  3. azure-logo Navigate to Azure Active Directory, then copy your tenant ID.

  4. terminal Add a variable for your tenant ID to your .bashrc file:

    ~$ echo 'idp_tenant_id="<Your Azure Active Directory tenant ID>"' >> ~/.bashrc
    /de/documentation/hapee/1-8r2/assets/images/azure-create-app-variables-tenant-id-90cec4af1f62a5839f0ca82275c21b1ba04012a0afbab1b10b957e3d1ef214f7.png

Installing required packages

  1. terminal Add the following variables to your .bashrc file:

    ~$ echo 'hapeekey="<HAProxy Enterprise Key>"' >> ~/.bashrc
    ~$ echo 'hapeeversion="<HAProxy Enterprise version>"' >> ~/.bashrc
    ~$ echo 'samlapp="<Internal name for your sample local application>"' >> ~/.bashrc

    Variable

    Value

    Example

    hapeekey

    HAProxy Enterprise key you received when you registered.

    xxxxxxxx-xxxxxxxx

    hapeeversion

    HAProxy Enterprise version number.

    2.1

    samlapp

    Application configured in the HAProxy Enterprise SAML Component saml.ini initialization file

    You can create several sections. Each section corresponds to an application.

    MySAMLApp

    Note

    The internal name for your sample local application can only contain alphanumeric characters and underscores (_).

  2. Reload your .bashrc file to take into account the variables you've created:

    ~$ . .bashrc
  3. terminal Install cURL, OpenSSL, HAProxy Enterprise, and HAProxy Enterprise SAML Component:

    This step uses the following variable:

    $hapeekey

    HAProxy Enterprise key you received when you registered

~$ sudo apt install curl openssl -y
~$ curl -s https://cdn.haproxy.com/static/install_haproxy_enterprise.sh | sudo bash /dev/stdin 2.1r1 $hapeekey
~$ sudo apt install hapee-extras-spoa-saml -y

Managing HAProxy Enterprise SAML Component and Microsoft Azure certificates

  1. terminal Create a self-signed SSL certificate to allow connecting via HTTPS, then copy the certificate and the key to the right directory, with the right ownership:

    This step uses the following variables:

    $hapeeversion

    HAProxy Enterprise version used in paths

    $myappfqdn

    Your sample local application's FQDN, used in the certificate Common Name.

    The certificate is valid only if the request hostname matches the common name.

    ~$ sudo 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"
    ~$ sudo cat key.pem cert.pem | sudo tee -a /etc/hapee-$hapeeversion/certs/mycert.pem
    ~$ sudo cp key.pem /etc/hapee-extras/
    ~$ sudo chmod 744 /etc/hapee-extras/key.pem
  2. terminal Copy your Azure Active Directory enterprise application certificate to /etc/hapee-extras/, then make the current user the owner of the certificate:

    ~$ sudo cp ~/Download/$myazureapp.cer /etc/hapee-extras/
    ~$ sudo chmod 744 /etc/hapee-extras/$myazureapp.cer

Configuring HAProxy Enterprise and HAProxy Enterprise SAML Component

Creating the HAProxy Enterprise configuration file

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

The following variable values will be implemented in the file:

$hapeeversion

HAProxy Enterprise version

$myappfqdn

Your sample local application's FQDN

$samlapp

Application configured in the HAProxy Enterprise SAML Component saml.ini initialization file

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

~$ cat <<EOF | sudo tee /etc/hapee-$hapeeversion/hapee-lb.cfg
global
    crt-base /etc/hapee-$hapeeversion/certs

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($samlapp) if { hdr(host) -i $myappfqdn }
    filter spoe engine spoe-saml config /etc/hapee-extras/hapee-saml-spoe.cfg
    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 app1 127.0.0.1:3200
    timeout connect 30s
    timeout server 1m
EOF

Your HAProxy Enterprise hapee-lb.cfg configuration file should contain values such as these (the corresponding variables are specified as comments):

/de/documentation/hapee/1-8r2/assets/images/saml-hapee-lb-cfg-391593f58440f7bf864f3131d872115d9f48893c0e451b2118af248989a8653d.svg

Creating the HAProxy Enterprise SAML Component initialization file

The following variable values will be implemented in the file:

$idp_app_id

Your Azure application ID

$idp_tenant_id

Your Azure Active Directory tenant ID

$myappfqdn

Your sample local application's FQDN

$myazureapp

Your Azure application's name

$samlapp

Application configured in the HAProxy Enterprise SAML Component saml.ini initialization file

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

    ~$ sudo cp /etc/hapee-extras/saml_examples/azure/*.xml /etc/hapee-extras/
  2. terminal Create the HAProxy Enterprise SAML Component saml.ini initialization file:

    ~$ 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}}
    
    signing_algo=rsa-sha1
    signing_key=/etc/hapee-extras/key.pem
    sign_authn_requests=1
    sign_logout_requests=1
    verify_signature=0
    
    app_login_url = {{APP_LOGIN_URL}}
    app_logout_url = {{APP_LOGOUT_URL}}
    
    idp_public_cert = $myazureapp.cer
    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

Your HAProxy Enterprise SAML Component saml.ini initialization file should contain values such as these (the corresponding variables are specified as comments):

/de/documentation/hapee/1-8r2/assets/images/samlini-66781428fd254f20a85af8bfd0a6bb492532bf78ce14b4705c710dc55f03ddd2.svg

Starting HAProxy Enterprise and HAProxy Enterprise SAML Component

terminal Start HAProxy Enterprise and HAProxy Enterprise SAML Component:

This step uses the following variable:

$hapeeversion

HAProxy Enterprise version used in paths and binary files names

~$ sudo systemctl enable hapee-extras-spoa-saml
~$ sudo systemctl start hapee-extras-spoa-saml
~$ sudo systemctl enable hapee-$hapeeversion-lb
~$ sudo systemctl start hapee-$hapeeversion-lb

Connecting to your sample local application

  1. terminal Redirect your NGNIX instance's Fully Qualified Domain Name to 127.0.0.1 in the /etc/hosts file:

    This step uses the following variable:

    $myappfqdn

    Your sample local application's FQDN

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

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

    Note

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

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

    The NGINX instance's welcome page displays.

    Note

    You can safely ignore the security warning that displays because we use a self-signed certificate.

    Tip

    If an error occurs, start HAProxy Enterprise SAML Component in debug mode:

    ~$ /opt/hapee-extras/bin/hapee-saml -C /etc/hapee-extras -f /etc/hapee-extras/saml.ini --debug-all -F

Whitelisting or blacklisting usernames

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

  1. azure-logo Copy the first name of one or several users who have access to your Azure Active Directory enterprise application from their user profiles.

  2. terminal Add a variable for the list of authorized user's first names to your .bashrc file:

    ~$ echo 'samlappusers="<Space delimited list of users' first names>"' >> ~/.bashrc

    Tip

    You can escape spaces with the backslash character \. When creating the Bash variable, escape the backslash character itself with another one \\.

    ~$ echo 'samlappusers="'Elena John Mary\\ Lou'"' >> ~/.bashrc
  3. Reload your .bashrc file to take into account the variables you've created:

    ~$ . .bashrc
  4. terminal 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()' /etc/hapee-extras/saml.ini
  5. terminal 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 }" /etc/hapee-$hapeeversion/hapee-lb.cfg
  6. terminal Restart HAProxy Enterprise and HAProxy Enterprise SAML Component:

    ~$ sudo systemctl reload hapee-$hapeeversion-lb
    ~$ sudo systemctl stop hapee-extras-spoa-saml
    ~$ /opt/hapee-extras/bin/hapee-saml -C /etc/hapee-extras -f /etc/hapee-extras/saml.ini
  7. browser 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 hapee-lb.cfg 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 /etc/hapee-extras/hapee-saml-spoe.cfg
    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
frontend ft-saml

Declare a SAML frontend to redirect user requests to HAProxy Enterprise SAML Component.

    bind :80

Listen to incoming traffic over HTTP and HTTPS.

    bind :443 ssl crt mycert.pem

Listen to incoming traffic over HTTPS and enable SSL termination. 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.

    option http-buffer-request

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

    tcp-request inspect-delay 10s

Set the maximum time to wait for data during content inspection to 10 seconds.

    http-request set-var(sess.saml_app) str(MySAMLApp) if { hdr(host) -i app.example.local }

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.

    filter spoe engine spoe-saml config /etc/hapee-extras/hapee-saml-spoe.cfg

Declare the spoe-saml SPOE filter and its /etc/hapee-extras/hapee-saml-spoe.cfg configuration file, to forward streaming data to HAProxy Enterprise SAML Component.

    http-request send-spoe-group spoe-saml spoe-group-req

Send messages to HAProxy Enterprise SAML Component. Define the spoe-group-req group of messages to send via a spoe-group section in the /etc/hapee-extras/hapee-saml-spoe.cfg SPOE configuration file.

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

Redirect the user to the value of variable txn.saml.redirect_to.

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.

/de/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.

/etc/hapee-extras/saml.ini example
config_version = 1.0.0

[MySAMLApp]
{{ID_APP_NAME}} = xxx  #  the name of your application in Azure AD
{{IDP_APP_ID}} = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
{{IDP_TENANT_ID}} = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
{{CLAIM_PREFIX}} = http://schemas.xmlsoap.org/ws/2005/05/identity/claims
{{APP_FQDN}} = xxx  #  ex: app1.example.local
{{APP_LOGIN_URL}} = https://{{APP_FQDN}}/saml/reply    # ACS url, depending on your application
{{APP_LOGOUT_URL}} = https://{{APP_FQDN}}/saml/logout  # logout url, depending on your application
{{APP_BACKEND}} = bk-{{APP_NAME}}                      # 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 = {{APP_FQDN}}
authn_request_template_filename = authn_request.xml
logout_request_template_filename = logout_request.xml
saml_app_backend = {{APP_BACKEND}}

idp_login_url = https://login.microsoftonline.com/{{IDP_TENANT_ID}}/saml2
idp_logout_url = https://login.microsoftonline.com/{{IDP_TENANT_ID}}/saml2
app_login_url = {{APP_LOGIN_URL}}
app_logout_url = {{APP_LOGOUT_URL}}
idp_referer_url = https://login.microsoftonline.com/

on_saml_response check_schema
; idp_public_cert = azure_pub_cert.pem  # in Azure, chose Certificate (Base64) to download a .cer file
; verify_signature=1
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

on_logout_request check_attr destination {{APP_LOGOUT_URL}} required
on_logout_request check_attr issuer https://sts.windows.net/{{IDP_APP_ID}}/ required

on_saml_response check_attr optional set_var_cnt set_var=givenname xpath=/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name="{{CLAIM_PREFIX}}/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">
  <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>
</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>
~$ /opt/hapee-extras/bin/hapee-saml -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.