HAProxy Enterprise Documentation 1.9r1

SAML Quick Start on Azure

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

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.

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.

Create a sample local application

  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.

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.

  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.

Create 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 name>"' >> ~/.bashrc
    $ echo 'idp_app_id="<Your Azure application ID>"' >> ~/.bashrc
    https://cdn.haproxy.com/documentation/hapee/1-9r1/assets/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

Set up the SAML parameters

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

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

    https://cdn.haproxy.com/documentation/hapee/1-9r1/assets/azure-select-a-single-sign-on-method-9b9540c62bfc9702572250959a720970e392c28cf07d5d146323af2bca52accf.png

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

    https://cdn.haproxy.com/documentation/hapee/1-9r1/assets/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.

    https://app.example.local/saml/reply

    Logout Url

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

    https://app.example.local/saml/logout

    https://cdn.haproxy.com/documentation/hapee/1-9r1/assets/azure-create-app-variables-saml-4fcd89ac6a53f2f50f6f42bd25e2c869becd96c13f97944593d36a32afcfd9da.png

Export 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.

    https://cdn.haproxy.com/documentation/hapee/1-9r1/assets/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
    https://cdn.haproxy.com/documentation/hapee/1-9r1/assets/azure-create-app-variables-tenant-id-90cec4af1f62a5839f0ca82275c21b1ba04012a0afbab1b10b957e3d1ef214f7.png

Install HAProxy Enterprise with SAML components

  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

  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://www.haproxy.com/static/install_haproxy_enterprise.sh | sudo bash /dev/stdin 1.9r1 $hapeekey
$ sudo apt install hapee-extras-spoa-saml -y

Manage the 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

Configure HAProxy Enterprise and the HAProxy Enterprise SAML Component

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):

https://cdn.haproxy.com/documentation/hapee/1-9r1/assets/saml-hapee-lb-cfg-391593f58440f7bf864f3131d872115d9f48893c0e451b2118af248989a8653d.svg

Create 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):

https://cdn.haproxy.com/documentation/hapee/1-9r1/assets/samlini-66781428fd254f20a85af8bfd0a6bb492532bf78ce14b4705c710dc55f03ddd2.svg

Start HAProxy Enterprise and the 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

Connect 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.

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

    The NGINX instance's welcome page displays.

Allow or block usernames

You can allow or block 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
    $ 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:

    frontend ft-saml
      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 an allowed username, then with another username.


Next up

SAML configuration options