Jeremy Davis
Jeremy Davis
Sitecore, C# and web development
Jeremy Davis
Jeremy Davis
Sitecore, C# and web development

Using ItemService in containers

Published 13 September 2021

I was asked to enable Sitecore's ItemService endpoints on a containerised instance of Sitecore recently, and my first pass through this didn't work. Turns out there's a key bit of documentation that seems to be missing for this scenario. Hence a quick post to help get info into Google. So if you need to do this, read on:

The issue

Out-of-the-box, the ItemService endpoints aren't available to external requests. The project I was working on needed this to be available to other apps from the CM role, to allow for some other work that was going on. So based on the existing documentation for this, I added a config patch to the solution:

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/">
    <sitecore>
        <settings>
            <setting name="Sitecore.Services.SecurityPolicy" role:require="ContentManagement">
                <patch:attribute name="value">Sitecore.Services.Infrastructure.Web.Http.Security.ServicesOnPolicy, Sitecore.Services.Infrastructure</patch:attribute>
            </setting>
        </settings>
    </sitecore>
</configuration>

For most IaaS or PaaS deployments, that should be enough. But when you do that in a containerised deployment it doesn't work. If you make a call to the ItemService endpoint you'll get an error back when you try to authenicate. The key part of the response is the body:

HTTPS is required

So what's missing?

The solution

The reason for the error is that when Sitecore runs in the suggested container setup, HTTPS requests have their SSL terminated at the Ingress Controller. (Which is going to be Traefik or Nginx if you're following the defaults) So when your API request to the ItemService arrives at its controller it's using HTTP not and HTTPS.

The root cause of the error above comes from this bit of code in the Sitecore.Services.Infrastructure.Web.Http.Filters namespace. It's a filter applied to all the endpoints for ItemService:

public class RequireHttpsFilter : AuthorizationFilterAttribute
{
	public override void OnAuthorization(HttpActionContext actionContext)
	{
		Assert.ArgumentNotNull(actionContext, "actionContext");
		HttpRequestMessage request = actionContext.get_Request();
		if (!(request.get_RequestUri().Scheme == Uri.UriSchemeHttps) && !_configurationSettings.get_AllowToLoginWithHttp())
		{
			if (request.get_Method().get_Method() == "GET")
			{
				actionContext.set_Response(HttpRequestMessageExtensions.CreateResponse(request, HttpStatusCode.Found));
				actionContext.get_Response().set_Content((HttpContent)new StringContent("HTTPS is required", Encoding.UTF8, "text/html"));
				UriBuilder uriBuilder = new UriBuilder(request.get_RequestUri())
				{
					Scheme = Uri.UriSchemeHttps,
					Port = 443
				};
				actionContext.get_Response().get_Headers().set_Location(uriBuilder.Uri);
			}
			else
			{
				actionContext.set_Response(HttpRequestMessageExtensions.CreateResponse(request, HttpStatusCode.NotFound));
				actionContext.get_Response().set_Content((HttpContent)new StringContent("HTTPS is required", Encoding.UTF8, "text/html"));
			}
		}
	}
}

And the answer to fixing this is hiding there in the highlighted line. There's a config setting you can supply to disable this "require HTTPS" behaviour.

Doing a bit of a search, it turns out that setting has its default set in the Sitecore.Services.Client.config file. So a second bit of config patching will make all this work happily in the containers:

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/">
    <sitecore>
        <settings>
            <setting name="Sitecore.Services.AllowToLoginWithHttp" role:require="ContentManagement">
                <patch:attribute name="value">true</patch:attribute>
            </setting>
        </settings>
    </sitecore>
</configuration>

Problem solved.