HAProxy community

Health Check on page with no text


#1

I’m trying to configure a health check on my Jamf servers. I can successfully health check a 200 status but Jamf will return a 200 status prior to being ready to process client requests. During this time period the Jamf webpage shows a progress bar and then switches to a login page. I’m trying to do a string validation but I’ve been unable to match the content on the page.

Here’s a return from a curl request:
`





<!-- 508 -->

<head id="login">
  <meta http-equiv="Pragma" content="no-cache">
  <meta http-equiv="expires" content="0">
  <meta HTTP-EQUIV="content-type" CONTENT="text/html;charset=utf-8">
  <meta charset="utf-8" />
  <meta name="description" content="" />
  <meta name="author" content="JAMF Software" />
  <meta name="apple-mobile-web-app-title" content="Jamf Pro">
  <meta name="version" content="10.7.1-t1536934276">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <title>Jamf Pro Login - Jamf Pro v10.7.1-t1536934276</title>

  




<base href="&#x2f;">

<script type="text/javascript" id="setBaseHrefScript">

    var a = document.createElement('a');
    a.href = top.location + '';

    var path = a.pathname; // defaults to '/' if not set in top.location

    // Except in the case of IE, it may need '/' to be prepended.
    if (path.slice(0, 1) !== '/') {
        path = '/' + path;
    }
    var components = path.split('/');
    var context = '/';

    if (components.length > 1 && components[1] && components[1] !== 'view' && components[1] !== 'saml' && ! components[1].match(/^(.*\.html)|enroll?/)) {
        context += components[1] + '/';
    }

    var base = document.getElementsByTagName('base')[0];

    if (base) {
        var serverBaseHref = base.getAttribute('href');

        if (serverBaseHref !== context) {
            base.setAttribute('href', context);
        }
    } else {
        base = document.createElement('base');
        base.setAttribute('href', context);
        var script = document.getElementById('setBaseHrefScript');
        script.parentNode.insertBefore(base, script);
    }

</script>


  <!-- For non-Retina iPhone, iPod Touch, and Android 2.1+ devices: --><link rel="apple-touch-icon-precomposed" href="ui/images/touchicons/touch-icon-iphone.png"><!-- For first- and second-generation iPad: --><link rel="apple-touch-icon-precomposed" sizes="72x72" href="ui/images/touchicons/touch-icon-ipad.png"><!-- For iPhone with high-resolution Retina display: --><link rel="apple-touch-icon-precomposed" sizes="114x114" href="ui/images/touchicons/touch-icon-iphone-retina.png"><!-- For third-generation iPad with high-resolution Retina display: --><link rel="apple-touch-icon-precomposed" sizes="144x144" href="ui/images/touchicons/touch-icon-ipad-retina.png"><link rel="mask-icon" color="#8DC63F" href="ui/images/touchicons/JSS_pinned.svg"><link rel="icon" href="ui/images/jamf-32-32-favicon.ico">

<!--[if lt IE 9]>
  <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->

<!-- C:&#x2a; -->
  <!-- inject:css --><link rel="stylesheet" type="text/css" id="main-stylesheet-link" href="ui/styles/main.css?v=1536937816933"><!-- endinject --><!-- inject:js --><script src="ui/jamf.js?v=1536937816933"></script><!-- endinject --><!-- systemjs:js --><script src="ui/systemjs.config.js?v=1536937816933"></script><!-- endinject --><script>var isLogin = document.head.id === 'login';
    var isSetupAssistant = document.head.id === 'setupAssistant';
    var isStartup = document.head.id === 'startup' || document.head.id == 'activation';
    var config = 'ui/ui';

    if (isLogin) {
        config = 'ui/auth/loginApp';
    } else if (isSetupAssistant) {
        config = 'ui/setupAssistant/setupAssistant';
    } else if (isStartup) {
        config = 'ui/startup/startup';
    }

    var errorLogger = function (error) {
        console.error(error);
    };

    SystemJS.set('cache-buster', SystemJS.newModule({ 
        locate: function(load) {
            return load.address + '?v=1536937816933';
        }
    }));
    SystemJS.config({
        packages: {
            '.': {
                meta: { '*.js': { loader: 'cache-buster' } }
            }
        }
    });

    SystemJS.import(config).catch(errorLogger);</script><!-- non-npm:js --><script src="ui/jamf-non-npm.js?v=1536937816933"></script><!-- endinject -->
</head>

<body class="login-page">

  <div id="main-login-wrapper" class="unselectable " ng-controller="loginController as lc">
    <div id="login-wrapper" ng-class="lc.language">
      <div class="login-box">
        <div id="jamf-logo-login">
          <img src="ui/images/svg/logos/jamf-pro-color.svg" />
        </div>
        <form class="login-form" method="POST" name="f">
          <div id="login-panel">

            <div id="login-fields" ng-cloak>

              <span class="label" translate='INPUT_USERNAME' translate-default='Username'>&nbsp;</span>
              <input name="username" id="username" class="input" value="" autocapitalize="off" autocorrect="off"
                   ng-bind="lc.username" placeholder="ex. admin" />

              <div class="login-separator"></div>

              <span class="label" translate='INPUT_PASSWORD' translate-default='Password'>&nbsp;</span>
              <input name="password" id="password" class="input" type="password" autocomplete="off"
                   ng-bind="lc.password" placeholder="&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;" />

              <button id="jssLoginButton" class="submit-button icon-arrow-1-circle-right button" type="submit" value="{{'LOG_IN' | translate}}"></button>

            </div> 

            <div id="reset-fields">

              <div class="reset-fields-lead">
                <p class="reset-header" translate='RESET_PASSWORD' translate-default='Reset Password'>&nbsp;</p>
                <p class="reset-body" translate="RESET_PASSWORD_INFO">&nbsp;</p>
              </div>
              <div class="login-separator"></div>

              <span class="label" translate='INPUT_USERNAME' translate-default='Username'>&nbsp;</span>

              <input name="resetUsername" id="resetUsername" class="input" value=""
                     autocapitalize="off" autocorrect="off" placeholder="ex. admin" />
              <input type="hidden" disabled="disabled" name="reset" value="reset" />

              <button class="submit-button icon-arrow-1-circle-right button"
                      type="button" value="{{'RESET_PASSWORD' | translate}}" id="reset" onclick="sendResetPassword()"></button>

            </div> 

            <div id="reset-sent-fields">
              <p class="reset-sent-header" translate='RESET_EMAIL_SENT' translate-default='Reset Email Sent'>&nbsp;</p>
              <p class="reset-sent-body" translate='CONTACT_JSS_ADMIN_MISSING_EMAIL' translate-default='Contact your Jamf Pro administrator if you do not receive it.'>&nbsp;</p>
              <i class="submit-button icon-check-circle" onclick="hideResetPassword()"></i>

              <div class="login-separator"></div>

              <span class="label" translate='INPUT_USERNAME' translate-default='Username'>&nbsp;</span>
              <input class="input" value=""
                     autocapitalize="off" autocorrect="off" placeholder="ex. admin" />
              <input type="hidden" disabled="disabled" name="reset" value="reset"/>
            </div> 

          </div> 
        </form>
      </div>
      <div class="reset-links-wrapper">
        <jamf-copyright></jamf-copyright>
        <div id="show-reset-link" class="reset-links" onclick="showResetPassword()">
          <a translate='RESET_PASSWORD' translate-default='Reset Password'>&nbsp;</a><i class="submit-button icon-arrow-2-circle-right"></i>
        </div>
        <div id="show-login-link" class="reset-links" onclick="hideResetPassword()">
          <i class="submit-button icon-arrow-2-circle-left"></i><a translate='LOGIN' translate-default='Login'>&nbsp;</a>
        </div>
      </div>
    </div>

  </div> 

  <script>

    function setDefaultField(){
        document.addEventListener("angularReady", function() {
            
            document.getElementById('username').focus();
            
        });
    }

    function showResetPassword(){
      document.getElementById("login-wrapper").className="show-reset-fields";
      document.getElementsByName("reset")[0].removeAttribute("disabled");
    }

    function hideResetPassword(){
      document.getElementById("login-wrapper").className="show-login-fields";
      document.getElementsByName("reset")[0].setAttribute("disabled", "true");
    }

    document.getElementById("reset").onclick = function() {
        document.forms['f'].submit();
    };
  </script>

</body>
</html>

I’ve also discovered this url that actually does have some content but it doesn’t seem to work when I try to match the string “Powered” or “Jamf” either:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html>
    	<head>
    		<meta http-equiv="cache-control" content="max-age=0" />
    		<meta http-equiv="cache-control" content="no-cache" />
    		<meta http-equiv="expires" content="0" />
    		<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
    		<meta http-equiv="pragma" content="no-cache" />
    		<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
    		
    		
    			<link href="../stylesheets/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
    			<link type="text/css" rel="stylesheet" href="../stylesheets/enrollment.css" />
    		
    		<link type="text/css" rel="stylesheet" href="../stylesheets/enrollmentBase.css" />
    		
    		<meta content="minimum-scale=1.0, width=device-width, maximum-scale=0.6667, user-scalable=no" name="viewport" />
    		<script type="text/javascript" src="../javascripts/jquery/jquery.js"></script>
    		<script type="text/javascript" src="../javascripts/enrollment.js"></script>
    		<script type="text/javascript" src="../javascripts/jamf-ajaxTimeout.js"></script>
    		<script type="text/javascript" src="../javascripts/jamf-enrollment-monitor.js"></script>
    		<script type="text/javascript" src="../javascripts/jamf-enrollment-device.js"></script>
    		<title>Enroll Your Device</title>
    	
    		
    	</head>
    	
    	
    	<body>
    	
    	
    		<div class="container">
    			<div class="row">
    				<div class="col-md-3">
    				</div>
    				<div class="col-md-6">
    					<div class="jumbotron">
    						<form method="post" target="" name="f">
    							<input type="hidden" name="lastPage" value="unhandled.jsp" />
    							<input type="hidden" name="payload" id="payload" value="" />
    				
    							



    <style>
    .form-control-feedback{
    	top: 6px;
    }
    </style>

    <script>
    function toggleType(v){
    	document.getElementById("deviceType").value=v;
    	document.f.submit()
    }

    </script>

    	<input type="hidden" name="deviceType" id="deviceType" value="">
    	
    	<div class="form-group has-feedback">
    		<button class="btn btn-lg btn-default btn-block" type="button" onclick="javascript:toggleType('osx')">macOS</button>
    		<span id="osx-check" class="glyphicon glyphicon-ok form-control-feedback" style="display:none"></span>
    	</div>

    	<div class="form-group has-feedback">
    		<button class="btn btn-lg btn-default btn-block" type="button" onclick="javascript:toggleType('ios')">iOS</button>
    		<span id="ios-check" class="glyphicon glyphicon-ok form-control-feedback" style="display:none"></span>
    	</div>

    	<div class="form-group has-feedback">
    		<button class="btn btn-lg btn-default btn-block" type="button" onclick="javascript:toggleType('android')">Android</button>
    		<span id="android-check" class="glyphicon glyphicon-ok form-control-feedback" style="display:none"></span>
    	</div>

    	
    	
    						
    						</form>
    					</div>
    				</div>
    			</div>
    		</div>
    		
    		<footer class="footer">
    			Powered by <a href="https://www.jamf.com/" target="_blank">Jamf</a>
    		</footer>
    	
    	</body>`

Any ideas?

edit: having trouble getting the formatting to work. Hopefully you’ll be able to understand.


#2

What’s the health check configuration? Did you read http-check expect in its entirety?


#3

I’ve tried many combinations of http-check expect string "Jamf" or http-check expect string "Powered" (with and without quotes). I’m using expect string on another backend service hosted on the same HAProxy server and it’s working properly (the page loads with only “It Works!” on it and I’m using http-check expect string "It works!").


#4

Does the size of this response exceed tune.chksize?


#5

I increased the tune.chksize to 307200 (300KB) and no success. I then increased it to 307200000 for fun and no success.