<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>kubernetes &amp;mdash; Stijn De Vos | Sitecore blog</title>
    <link>https://stijndevos.net/tag:kubernetes</link>
    <description>Lead expert consultant @ delaware. Working with Sitecore, Azure, Kubernetes.</description>
    <pubDate>Tue, 14 Apr 2026 22:35:15 +0000</pubDate>
    <item>
      <title>Integrating Sitecore Identity with Azure AD on Kubernetes</title>
      <link>https://stijndevos.net/integrating-sitecore-identity-with-azure-ad-kubernetes-style?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[Sitecore Identity (SI), introduced in Sitecore 9.1, is the single sign-on mechanism for any Sitecore instance (XM, XP, XC, …) that requires authentication.&#xA;&#xA;As it was provided in a web deploy package (WDP), making small config changes like integrating with Azure AD was straightforward. With Sitecore moving to containers, and SI thus being provided as container image, making these same config changes becomes more complex… unless you’re willing to throw some Kubernetes features at it.&#xA;&#xA;!--more--&#xA;&#xA;Sitecore Identity is an OpenID Connect compliant security token service (STS), based on IdentityServer4. Its default setup is an OAuth wrapper around good old Sitecore Membership:&#xA;&#xA;As an unauthenticated user that tries to access Sitecore CM, you are redirected to SI.&#xA;On SI you can authenticate with your Sitecore credentials (username and password, stored in the security database).&#xA;On successful authentication, SI redirects you back to Sitecore CM with a security token.&#xA;With this security token, you can now access Sitecore CM (and potential other applications behind Sitecore security).&#xA;&#xA;Because it’s based on IdentityServer4, you can use SI as a gateway to one or more external identity providers (or subproviders, sometimes also called inner providers). For example, Azure AD:&#xA;&#xA;As an unauthenticated user that tries to access Sitecore CM, you are redirected to SI.&#xA;Instead of using Sitecore Membership, SI now offloads authentication to Azure AD: you are redirected to Azure, where you authenticate with your Azure AD account.&#xA;On successful authentication, SI redirects you back to Sitecore CM with a security token, now based on information from your Azure AD account.&#xA;With this security token, you can now access Sitecore CM (and potential other applications behind Sitecore security).&#xA;&#xA;This allows business users to log into Sitecore CM using their corporate (Azure AD) account.&#xA;&#xA;Configuring SI to integrate with Azure AD is supported out-of-the-box. You need to&#xA;&#xA;Register Sitecore as an Application in your Azure AD tenant&#xA;&#xA;Create groups in your Azure AD for the users you want to give access to the Sitecore back-end&#xA;&#xA;Configure SI to connect to that Azure AD application and add a user mapping that specifies the role (e.g. Sitecore\\admin) for a specified Azure AD group&#xA;&#xA;You find the official documentation on Use the Sitecore Identity server as a federation gateway, but I recommend Setting Up Azure Active Directory Integration with Sitecore Identity Server / Sitecore 9.1 (derekc.net) for a more detailed walkthrough of this setup.&#xA;&#xA;Deploying SI with a Web Deploy Package&#xA;&#xA;Before containers, changing the configuration was straightforward: SI is provided by Sitecore as a WDP (web deploy package — see Sitecore Downloads: Sitecore Identity 600). A structured folder containing DLLs, config XML files, … that you can deploy to IIS (virtual machine, Azure App Service, …) using Web Deploy.&#xA;&#xA;Change the config files, deploy the updated package and you’re done.&#xA;&#xA;Deploying SI with a container image&#xA;&#xA;Next to WDP, SI is also provided as a container image. For example, scr.sitecore.com/sxp/sitecore-id:10.2-ltsc2019&#xA;&#xA;Compared to changing a WDP zip file, creating a custom container image requires more skills and infrastructure:&#xA;&#xA;you need to create a DockerFile that takes an official Sitecore ID image as a base image and specify which custom files (the modified config files) you will patch over it to create your own custom Sitecore ID&#xA;you need to build the image (build server?) and push it to a container registry (acr?)&#xA;you need to change your deployment (k8s specs) to use the modified image&#xA;&#xA;None of this is rocket science, but it’s quite some work to change a simple config file.&#xA;&#xA;Configuring SI with Kubernetes ConfigMap&#xA;&#xA;With the custom container image approach, you first copy modified files over an original image. Then these modifications are baked into a new image that you deploy to Kubernetes. Kubernetes uses an abstraction to run this image on actual hardware.&#xA;&#xA;Thanks to the abstraction layer, it’s possible for Kubernetes to hijack the files an image tries to access while it’s running: in the id.yaml k8s spec file provided by Sitecore, you add a volumeMount, which tells the runtime that when image wants a file from /Identity/sitecore/Sitecore.Plugin.IdentityProvider.AzureAd/Config/ it should first be search in a volume called config. The config volume forwards this to a configMap called sitecore-id-azuread-config (an alternative would be an actual storage).&#xA;&#xA;A Configmaps is an API object in Kubernetes used to store data in:&#xA;&#xA;  A ConfigMap allows you to decouple environment-specific configuration from your container images, so that your applications are easily portable.&#xA;&#xA;In our case, we can simply put the whole custom configuration file in it:&#xA;&#xA;With this setup it’s possible to run Sitecore’s official SI image with a custom Identity/sitecore/Sitecore.Plugin.IdentityProvider.AzureAd/Config/Sitecore.Plugin.IdentityProvider.AzureAd.xml_ file, containing your project specific Azure AD configuration. No need to create a custom image for it!&#xA;&#xA;Tags: #kubernetes, #sitecoreidentity]]&gt;</description>
      <content:encoded><![CDATA[<p>Sitecore Identity (SI), introduced in Sitecore 9.1, is the single sign-on mechanism for any Sitecore instance (XM, XP, XC, …) that requires authentication.</p>

<p>As it was provided in a web deploy package (WDP), making small config changes like integrating with Azure AD was straightforward. With Sitecore moving to containers, and SI thus being provided as container image, making these same config changes becomes more complex… unless you’re willing to throw some Kubernetes features at it.</p>



<p>Sitecore Identity is an OpenID Connect compliant security token service (STS), based on <a href="https://github.com/IdentityServer/IdentityServer4">IdentityServer4</a>. Its default setup is an OAuth wrapper around good old Sitecore Membership:</p>
<ul><li>As an unauthenticated user that tries to access Sitecore CM, you are redirected to SI.</li>
<li>On SI you can authenticate with your Sitecore credentials (username and password, stored in the <em>security</em> database).</li>
<li>On successful authentication, SI redirects you back to Sitecore CM with a security token.</li>
<li>With this security token, you can now access Sitecore CM (and potential other applications behind Sitecore security).</li></ul>

<p>Because it’s based on IdentityServer4, you can use SI as a gateway to one or more external identity providers (or subproviders, sometimes also called <em>inner providers</em>). For example, Azure AD:</p>
<ul><li><em>As an unauthenticated user that tries to access Sitecore CM, you are redirected to SI.</em></li>
<li>Instead of using Sitecore Membership, SI now offloads authentication to Azure AD: you are redirected to Azure, where you authenticate with your Azure AD account.</li>
<li>On successful authentication, SI redirects you back to Sitecore CM with a security token, now based on information from your Azure AD account.</li>
<li><em>With this security token, you can now access Sitecore CM (and potential other applications behind Sitecore security).</em></li></ul>

<p>This allows business users to log into Sitecore CM using their corporate (Azure AD) account.</p>

<p>Configuring SI to integrate with Azure AD is supported out-of-the-box. You need to</p>
<ol><li><p>Register Sitecore as an Application in your Azure AD tenant</p></li>

<li><p>Create groups in your Azure AD for the users you want to give access to the Sitecore back-end</p></li>

<li><p>Configure SI to connect to that Azure AD application and add a user mapping that specifies the role (e.g. Sitecore\admin) for a specified Azure AD group</p></li></ol>

<p>You find the official documentation on <a href="https://doc.sitecore.com/xp/en/developers/102/sitecore-experience-manager/use-the-sitecore-identity-server-as-a-federation-gateway.html">Use the Sitecore Identity server as a federation gateway</a>, but I recommend <a href="https://sitecore.derekc.net/setting-up-azure-active-directory-integration-with-sitecore-identity-server-sitecore-9-1/">Setting Up Azure Active Directory Integration with Sitecore Identity Server / Sitecore 9.1 (derekc.net)</a> for a more detailed walkthrough of this setup.</p>

<h1 id="deploying-si-with-a-web-deploy-package" id="deploying-si-with-a-web-deploy-package">Deploying SI with a Web Deploy Package</h1>

<p>Before containers, changing the configuration was straightforward: SI is provided by Sitecore as a WDP (web deploy package — see <a href="https://dev.sitecore.net/Downloads/Sitecore_Identity/6x/Sitecore_Identity_600.aspx">Sitecore Downloads: Sitecore Identity 600</a>). A structured folder containing DLLs, config XML files, … that you can deploy to IIS (virtual machine, Azure App Service, …) using Web Deploy.</p>

<p>Change the config files, deploy the updated package and you’re done.</p>

<h1 id="deploying-si-with-a-container-image" id="deploying-si-with-a-container-image">Deploying SI with a container image</h1>

<p>Next to WDP, SI is also provided as a container image. For example, <em>scr.sitecore.com/sxp/sitecore-id:10.2-ltsc2019</em></p>

<p>Compared to changing a WDP zip file, creating a custom container image requires more skills and infrastructure:</p>
<ul><li>you need to create a DockerFile that takes an official Sitecore ID image as a base image and specify which custom files (the modified config files) you will patch over it to create your own custom Sitecore ID</li>
<li>you need to build the image (build server?) and push it to a container registry (acr?)</li>
<li>you need to change your deployment (k8s specs) to use the modified image</li></ul>

<p>None of this is rocket science, but it’s quite some work to change a simple config file.</p>

<h1 id="configuring-si-with-kubernetes-configmap" id="configuring-si-with-kubernetes-configmap">Configuring SI with Kubernetes ConfigMap</h1>

<p>With the custom container image approach, you first copy modified files over an original image. Then these modifications are baked into a new image that you deploy to Kubernetes. Kubernetes uses an abstraction to run this image on actual hardware.</p>

<p>Thanks to the abstraction layer, it’s possible for Kubernetes to hijack the files an image tries to access while it’s running: in the <strong>id.yaml</strong> k8s spec file provided by Sitecore, you add a <strong>volumeMount</strong>, which tells the runtime that when image wants a file from <em>/Identity/sitecore/Sitecore.Plugin.IdentityProvider.AzureAd/Config/</em> it should first be search in a volume called <strong>config</strong>. The <strong>config</strong> volume forwards this to a <strong>configMap</strong> called <em>sitecore-id-azuread-config</em> (an alternative would be an actual storage).</p>

<p><img src="https://i.snap.as/5pcfXL5E.png" alt=""/></p>

<p>A <a href="https://kubernetes.io/docs/concepts/configuration/configmap/">Configmaps</a> is an API object in Kubernetes used to store data in:</p>

<blockquote><p>A ConfigMap allows you to decouple environment-specific configuration from your container images, so that your applications are easily portable.</p></blockquote>

<p>In our case, we can simply put the whole custom configuration file in it:</p>

<p><img src="https://i.snap.as/PooulMR2.png" alt=""/></p>

<p>With this setup it’s possible to run Sitecore’s official SI image with a custom <em>Identity/sitecore/Sitecore.Plugin.IdentityProvider.AzureAd/Config/Sitecore.Plugin.IdentityProvider.AzureAd.xml</em> file, containing your project specific Azure AD configuration. No need to create a custom image for it!</p>

<p>Tags: <a href="https://stijndevos.net/tag:kubernetes" class="hashtag"><span>#</span><span class="p-category">kubernetes</span></a>, <a href="https://stijndevos.net/tag:sitecoreidentity" class="hashtag"><span>#</span><span class="p-category">sitecoreidentity</span></a></p>
]]></content:encoded>
      <guid>https://stijndevos.net/integrating-sitecore-identity-with-azure-ad-kubernetes-style</guid>
      <pubDate>Fri, 14 Jan 2022 15:38:20 +0000</pubDate>
    </item>
    <item>
      <title>Sitecore ingress gives 404 (AKS / K8s   = 1.19)</title>
      <link>https://stijndevos.net/sitecore-ingress-gives-404-on-aks-k8s-1-19?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[Recently, I was refactoring my Azure DevOps CI/CD scripts that setup and deploy Sitecore 10.1 on a newly created AKS. Deployment went smooth, until I tried to browse to the deployed environments. Nginx, configured with sitecore-ingress provided by Sitecore, returned a 404 Not Found. What gives?&#xA;&#xA;!--more--&#xA;&#xA;Where’s the error?&#xA;&#xA;The logical thing to do is start looking for errors. Unfortunately, the nginx-ingress-ingress-nginx-controller pods did not show any (they did not show anything at all). Perhaps running them in debug mode could have told me more, but my experience with nginx is limited (close to none actually :)), so I postponed figuring out how to do that.&#xA;&#xA;The only pointer I had was my browser. The HTTP response did not show anything special, but the insecure https indication was odd. I used a self-signed certificate that worked in the past without any issues. Inspecting the details shows a strange issuer: Kubernetes Ingress Controller Fake Certificate. That can’t be right.&#xA;&#xA;After a quick google, I landed on a Microsoft documentation site (Use your TLS certificates for ingress - Azure Kubernetes Service | Microsoft Docs), telling me the certificate and configured ingress route are not compatible in a way.&#xA;&#xA;But, as said, I was simply using the ingress configuration provided by Sitecore.&#xA;&#xA;What changed in my scripts?&#xA;&#xA;The scripts I used had been working before, so it had to be in the details. One thing I explicitly changed in my script was setting AKS to a more recent version of Kubernetes.&#xA;&#xA;Sitecore’s Installation Guide for Production Environment with Kubernetes (Sitecore 10.1) does not specify an upper bound of the version, so this is an acceptable change:&#xA;&#xA;  An AKS cluster configured with the latest stable release of Kubernetes – version 1.16.x or later.&#xA;    For startup probes to check whether the Sitecore software container has started successfully, Kubernetes version 1.18.x or later is required.&#xA;&#xA;The most popular GitHub examples, which I based myself on for previous -working- setups, use an older version:&#xA;&#xA;Sitecore-Symposium-2020-Containers-AKS/2.CreateAKS.ps1 at main · bplasmeijer/Sitecore-Symposium-2020-Containers-AKS (github.com)&#xA;paas-to-aks/create-aks.ps1 at main · robhabraken/paas-to-aks (github.com)&#xA;&#xA;One thing that always bothered during previous setups was the warning / usage of ingress beta:&#xA;&#xA;  Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress&#xA;&#xA;According to the mentioned versions, it should still work. But with experienced 404 / certificate issues, I thought I try to upgrade it and see what happens.&#xA;&#xA;Upgrading ingress to solve the issue (sort of)&#xA;&#xA;Upgrading is rather straightforward (see end of post for full spec).&#xA;&#xA;First you change the apiVersion from extensions/v1beta1 to  networking.k8s.io/v1.&#xA;&#xA;And make the specs a bit more structured / verbose.&#xA;&#xA;spec:&#xA;  rules:&#xA;  - host: cd.globalhost&#xA;    http:&#xA;      paths:&#xA;      - path: /&#xA;        backend:&#xA;          serviceName: cd&#xA;          servicePort: 80&#xA;&#xA;becomes&#xA;&#xA;spec:&#xA;  rules:&#xA;  - host: cd.globalhost&#xA;    http:&#xA;      paths:&#xA;      - path: /&#xA;        pathType: Prefix&#xA;        backend:&#xA;          service:&#xA;            name: cd&#xA;            port: &#xA;              number: 80&#xA;&#xA;And, the most crucial part of all, you need to add ingressClassName: nginx to the spec (e.g. right below rules).&#xA;&#xA;See Basic usage - NGINX Ingress Controller (kubernetes.github.io) for full details.&#xA;&#xA;After making the changes, Sitecore URLs resolve as expected.&#xA;&#xA;Conclusion&#xA;&#xA;The ingressClassName: nginx change turned out to be the root cause of my problem. According to its documentation, it’s required for K8s   = 1.19, which is exactly the change I made.&#xA;&#xA;Note that adding this to Sitecore’s ingress spec (apiVersion extensions/v1beta1) fixes the issue as well. So the warning unavailable in v1.22+ is correct, but there are extra versioning dependencies to take into account.&#xA;&#xA;Tags: #aks, #kubernetes, #ngnix.&#xA;&#xA;Full spec&#xA;&#xA;For those interested, this is updated ingress-nginx/ingress.yaml&#xA;&#xA;apiVersion: networking.k8s.io/v1&#xA;kind: Ingress&#xA;metadata:&#xA;  name: sitecore-ingress&#xA;  annotations:&#xA;    nginx.ingress.kubernetes.io/proxy-buffer-size: &#34;32k&#34;&#xA;    nginx.ingress.kubernetes.io/affinity: &#34;cookie&#34;&#xA;    nginx.ingress.kubernetes.io/rewrite-target: /&#xA;    nginx.ingress.kubernetes.io/proxy-connect-timeout: &#34;600&#34;&#xA;    nginx.ingress.kubernetes.io/proxy-read-timeout: &#34;600&#34;&#xA;    nginx.ingress.kubernetes.io/proxy-send-timeout: &#34;600&#34;&#xA;    nginx.ingress.kubernetes.io/proxy-body-size: &#34;512m&#34;&#xA;spec:&#xA;  rules:&#xA;  host: cd.globalhost&#xA;    http:&#xA;      paths:&#xA;      path: /&#xA;        pathType: Prefix&#xA;        backend:&#xA;          service:&#xA;            name: cd&#xA;            port: &#xA;              number: 80&#xA;  host: cm.globalhost&#xA;    http:&#xA;      paths:&#xA;      path: /&#xA;        pathType: Prefix&#xA;        backend:&#xA;          service:&#xA;            name: cm&#xA;            port:&#xA;              number: 80&#xA;  host: id.globalhost&#xA;    http:&#xA;      paths:&#xA;      path: /&#xA;        pathType: Prefix&#xA;        backend:&#xA;          service:&#xA;            name: id&#xA;            port:&#xA;              number: 80&#xA;  ingressClassName: nginx&#xA;  tls:&#xA;  secretName: global-cd-tls&#xA;    hosts:&#xA;    cd.globalhost&#xA;  secretName: global-cm-tls&#xA;    hosts:&#xA;    cm.globalhost&#xA;  secretName: global-id-tls&#xA;    hosts:&#xA;    id.globalhost&#xA;`]]&gt;</description>
      <content:encoded><![CDATA[<p>Recently, I was refactoring my Azure DevOps CI/CD scripts that setup and deploy Sitecore 10.1 on a newly created AKS. Deployment went smooth, until I tried to browse to the deployed environments. Nginx, configured with sitecore-ingress provided by Sitecore, returned a 404 Not Found. What gives?</p>

<p><img src="https://i.snap.as/lrLlpFTe.png" alt=""/></p>



<h1 id="where-s-the-error" id="where-s-the-error">Where’s the error?</h1>

<p>The logical thing to do is start looking for errors. Unfortunately, the <em>nginx-ingress-ingress-nginx-controller</em> pods did not show any (they did not show anything at all). Perhaps running them in debug mode could have told me more, but my experience with nginx is limited (close to none actually :)), so I postponed figuring out how to do that.</p>

<p>The only pointer I had was my browser. The HTTP response did not show anything special, but the <em>insecure https</em> indication was odd. I used a self-signed certificate that worked in the past without any issues. Inspecting the details shows a strange issuer: <strong>Kubernetes Ingress Controller Fake Certificate</strong>. That can’t be right.</p>

<p><img src="https://i.snap.as/p15Xl2TF.png" alt=""/></p>

<p>After a quick google, I landed on a Microsoft documentation site (<a href="https://docs.microsoft.com/en-us/azure/aks/ingress-own-tls">Use your TLS certificates for ingress – Azure Kubernetes Service | Microsoft Docs</a>), telling me the certificate and configured ingress route are not compatible in a way.</p>

<p><img src="https://i.snap.as/Pd4leRbo.png" alt=""/></p>

<p>But, as said, I was simply using the ingress configuration provided by Sitecore.</p>

<h1 id="what-changed-in-my-scripts" id="what-changed-in-my-scripts">What changed in my scripts?</h1>

<p>The scripts I used had been working before, so it had to be in the details. One thing I explicitly changed in my script was setting AKS to a more recent version of Kubernetes.</p>

<p>Sitecore’s <a href="https://sitecoredev.azureedge.net/~/media/AF34449136CD4AA79921EB6F7BEEFFF7.ashx?date=20210920T195203">Installation Guide for Production Environment with Kubernetes (Sitecore 10.1)</a> does not specify an upper bound of the version, so this is an acceptable change:</p>

<blockquote><p>An AKS cluster configured with the latest stable release of Kubernetes – version 1.16.x or later.</p>

<p>For startup probes to check whether the Sitecore software container has started successfully, Kubernetes version 1.18.x or later is required.</p></blockquote>

<p>The most popular GitHub examples, which I based myself on for previous -working- setups, use an older version:</p>
<ul><li><a href="https://github.com/bplasmeijer/Sitecore-Symposium-2020-Containers-AKS/blob/main/2.CreateAKS.ps1">Sitecore-Symposium-2020-Containers-AKS/2.CreateAKS.ps1 at main · bplasmeijer/Sitecore-Symposium-2020-Containers-AKS (github.com)</a></li>
<li><a href="https://github.com/robhabraken/paas-to-aks/blob/main/azure/scripts/create-aks.ps1">paas-to-aks/create-aks.ps1 at main · robhabraken/paas-to-aks (github.com)</a></li></ul>

<p>One thing that always bothered during previous setups was the warning / usage of ingress beta:</p>

<blockquote><p>Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress</p></blockquote>

<p>According to the mentioned versions, it should still work. But with experienced 404 / certificate issues, I thought I try to upgrade it and see what happens.</p>

<h1 id="upgrading-ingress-to-solve-the-issue-sort-of" id="upgrading-ingress-to-solve-the-issue-sort-of">Upgrading ingress to solve the issue (sort of)</h1>

<p>Upgrading is rather straightforward (see end of post for full spec).</p>

<p>First you change the apiVersion from <code>extensions/v1beta1</code>to  <code>networking.k8s.io/v1.</code></p>

<p>And make the specs a bit more structured / verbose.</p>

<pre><code>spec:
  rules:
  - host: cd.globalhost
    http:
      paths:
      - path: /
        backend:
          serviceName: cd
          servicePort: 80
</code></pre>

<p>becomes</p>

<pre><code>spec:
  rules:
  - host: cd.globalhost
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: cd
            port: 
              number: 80
</code></pre>

<p>And, the most crucial part of all, you need to add <strong>ingressClassName: nginx</strong> to the spec (e.g. right below <em>rules)</em>.</p>

<p>See <a href="https://kubernetes.github.io/ingress-nginx/user-guide/basic-usage/">Basic usage – NGINX Ingress Controller (kubernetes.github.io)</a> for full details.</p>

<p>After making the changes, Sitecore URLs resolve as expected.</p>

<p><img src="https://i.snap.as/J3jED8FZ.png" alt=""/></p>

<h1 id="conclusion" id="conclusion">Conclusion</h1>

<p>The <strong>ingressClassName: nginx</strong> change turned out to be the root cause of my problem. According to its <a href="https://kubernetes.github.io/ingress-nginx/user-guide/basic-usage/">documentation</a>, it’s required for K8s &gt;= 1.19, which is exactly the change I made.</p>

<p>Note that adding this to Sitecore’s ingress spec (apiVersion <code>extensions/v1beta1</code>) fixes the issue as well. So the warning <em>unavailable in v1.22+</em> is correct, but there are extra versioning dependencies to take into account.</p>

<p>Tags: <a href="https://stijndevos.net/tag:aks"><a href="https://stijndevos.net/tag:aks" class="hashtag"><span>#</span><span class="p-category">aks</span></a></a>, <a href="https://stijndevos.net/tag:kubernetes"><a href="https://stijndevos.net/tag:kubernetes" class="hashtag"><span>#</span><span class="p-category">kubernetes</span></a></a>, <a href="https://stijndevos.net/tag:ngnix"><a href="https://stijndevos.net/tag:ngnix" class="hashtag"><span>#</span><span class="p-category">ngnix</span></a></a>.</p>

<h1 id="full-spec" id="full-spec">Full spec</h1>

<p>For those interested, this is updated <em>ingress-nginx/ingress.yaml</em></p>

<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: sitecore-ingress
  annotations:
    nginx.ingress.kubernetes.io/proxy-buffer-size: &#34;32k&#34;
    nginx.ingress.kubernetes.io/affinity: &#34;cookie&#34;
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/proxy-connect-timeout: &#34;600&#34;
    nginx.ingress.kubernetes.io/proxy-read-timeout: &#34;600&#34;
    nginx.ingress.kubernetes.io/proxy-send-timeout: &#34;600&#34;
    nginx.ingress.kubernetes.io/proxy-body-size: &#34;512m&#34;
spec:
  rules:
  - host: cd.globalhost
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: cd
            port: 
              number: 80
  - host: cm.globalhost
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: cm
            port:
              number: 80
  - host: id.globalhost
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: id
            port:
              number: 80
  ingressClassName: nginx
  tls:
  - secretName: global-cd-tls
    hosts:
    - cd.globalhost
  - secretName: global-cm-tls
    hosts:
    - cm.globalhost
  - secretName: global-id-tls
    hosts:
    - id.globalhost
</code></pre>
]]></content:encoded>
      <guid>https://stijndevos.net/sitecore-ingress-gives-404-on-aks-k8s-1-19</guid>
      <pubDate>Mon, 27 Sep 2021 08:48:17 +0000</pubDate>
    </item>
    <item>
      <title>Tags</title>
      <link>https://stijndevos.net/tags?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[#aks #docker #istio #kubernetes #ngnix #ordercloud]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://stijndevos.net/tag:aks" class="hashtag"><span>#</span><span class="p-category">aks</span></a> <a href="https://stijndevos.net/tag:docker" class="hashtag"><span>#</span><span class="p-category">docker</span></a> <a href="https://stijndevos.net/tag:istio" class="hashtag"><span>#</span><span class="p-category">istio</span></a> <a href="https://stijndevos.net/tag:kubernetes" class="hashtag"><span>#</span><span class="p-category">kubernetes</span></a> <a href="https://stijndevos.net/tag:ngnix" class="hashtag"><span>#</span><span class="p-category">ngnix</span></a> <a href="https://stijndevos.net/tag:ordercloud" class="hashtag"><span>#</span><span class="p-category">ordercloud</span></a></p>
]]></content:encoded>
      <guid>https://stijndevos.net/tags</guid>
      <pubDate>Mon, 30 Aug 2021 10:26:01 +0000</pubDate>
    </item>
    <item>
      <title>How browser security fixes Sitecore login</title>
      <link>https://stijndevos.net/how-browser-security-fixes-sitecore-login?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[I was contacted by a client to help them roll out Sitecore Kubernetes deployment (hooray for clients willing to invest in technology updates). Of course I came in prepared: I tried out Installation Guide for Production Environment with Kubernetes (on Azure AKS with my own subscription), and had a shiny new Sitecore 10.x up and running on https://globalhost.cd in no time.&#xA;&#xA;When repeating the setup on the client’s subscription, deployment went well but we failed to log in into Sitecore:&#xA;&#xA;!--more--&#xA;&#xA;We try to access /sitecore.&#xA;Since we’re not logged in, Sitecore CM redirects us to Sitecore ID.&#xA;On Sitecore ID, we enter our credentials.&#xA;Everything seems fine and we are redirected back to Sitecore CM.&#xA;We see the browser redirecting, but the page failed to load: the browser fails with a timeout (IIRC).&#xA;&#xA;A quick look at the log files did not reveal any errors or failures.&#xA;&#xA;In my setup, everything worked as expected, so what’s different for our client? Since this is a real project setup, of course the URLs (and TLS) are going to be customer specific (so not globalhost). Typo’s are easily made, but not this time: double checking the config did not reveal any mistakes.&#xA;&#xA;With no traces in the logs we had to dig a little bit deeper. Since single-sign on is all about redirection and passing along the required information in the process, taking a closer look at the network traffic made sense.&#xA;&#xA;(see Virtual Developer Day 2020 - Getting to Know Sitecore Identity - George Chang for a good introduction on Sitecore ID)&#xA;&#xA;Security best practices for the win&#xA;&#xA;A useful tool to do this is fiddler (fiddler classic in my case): a web debugging proxy to successfully log, inspect, and alter HTTP(s) network requests and server responses.&#xA;&#xA;I was already thinking bad tokens, encryption issues, claim mismatches, … Luckily the issue was not as complex as I feared. Comparing network traffic from my (working) setup with traffic from the client setup revealed they had one HTTP header missing: Strict-Transport-Security, also known as HSTS.&#xA;&#xA;  If a website accepts a connection through HTTP and redirects to HTTPS, visitors may initially communicate with the non-encrypted version of the site before being redirected, if, for example, the visitor types http://www.foo.com/ or even just foo.com. This creates an opportunity for a man-in-the-middle attack. The redirect could be exploited to direct visitors to a malicious site instead of the secure version of the original site.&#xA;    The HTTP Strict Transport Security header informs the browser that it should never load a site using HTTP and should automatically convert all attempts to access the site using HTTP to HTTPS requests instead.&#xA;&#xA;https://developer.mozilla.org/en-US/docs/Glossary/HSTS&#xA;&#xA;This is exactly what happens in my fiddler trace: even though the server tells my browser to go to HTTP (using the Location: header), my browser ignores this and connects over HTTPS directly (line 52).&#xA;&#xA;Why would Sitecore redirect us to HTTP? No idea. As far as I can tell all our config is set correctly. I can only assume this is leftover code from a time where local development was often done on HTTP. With Sitecore on containers, development setup is a lot closer to production setup, including running on HTTPS.&#xA;&#xA;Ingress&#xA;&#xA;So why did I did not face this issue on my setup? An important part of a Kubernetes setup is managing how external traffic can access the services in your cluster (HTTP, HTTPS, TLS, …). This is done with the Ingress API object. Out of the box, Sitecore suggests you to use the NGINX Ingress controller for this.&#xA;&#xA;NGINX is a fine default, but my client has a track record in Kubernetes (not on Azure) and for their networking requirements they standardize on Istio, a service mesh. To use it, we had to switch NGINX with Istio Ingress.&#xA;&#xA;Turns out HSTS is enabled by default in NGINX (see https://kubernetes.github.io/ingress-nginx/user-guide/tls/#http-strict-transport-security), but not in Istio. Enabling it is quite easy though (in case you might be interested): https://www.wagner-dev.com/istio-configure-strict-transport-security-hsts.html&#xA;&#xA;In a development setup, network traffic is typically handled with traefik. Sitecore provides you with docker-compose files that force this behavior.&#xA;&#xA;So why didn’t we spot this right away? The browser we were using (it’s name starts with a ‘C’) doesn’t show the protocol in the URL bar, so we simply didn’t spot it. That we had to test this through a screen share session probably didn’t help neither (but that’s a different story).&#xA;&#xA;In summary&#xA;&#xA;Sitecore login depends on HSTS.&#xA;HSTS is enabled by default for NGNIX ingress, but that might not be the case for other ingress controllers (e.g. Isitio).&#xA;You can’t see what you can’t see.&#xA;&#xA;Tags: #aks, #kubernetes, #ngnix, #istio.]]&gt;</description>
      <content:encoded><![CDATA[<p>I was contacted by a client to help them roll out Sitecore Kubernetes deployment (hooray for clients willing to invest in technology updates). Of course I came in prepared: I tried out <a href="https://sitecoredev.azureedge.net/~/media/8DCE36C9C62B49A59DA398F2C9387892.ashx?date=20210714T144106">Installation Guide for Production Environment with Kubernetes</a> (on Azure AKS with my own subscription), and had a shiny new Sitecore 10.x up and running on <a href="https://globalhost.cd">https://globalhost.cd</a> in no time.</p>

<p>When repeating the setup on the client’s subscription, deployment went well but we failed to log in into Sitecore:</p>


<ul><li>We try to access <em>/sitecore</em>.</li>
<li>Since we’re not logged in, Sitecore CM redirects us to Sitecore ID.</li>
<li>On Sitecore ID, we enter our credentials.</li>
<li>Everything seems fine and we are redirected back to Sitecore CM.</li>
<li>We see the browser redirecting, but the page failed to load: the browser fails with a timeout (IIRC).</li></ul>

<p>A quick look at the log files did not reveal any errors or failures.</p>

<p>In my setup, everything worked as expected, so what’s different for our client? Since this is a real project setup, of course the URLs (and TLS) are going to be customer specific (so not <em>globalhost)</em>. Typo’s are easily made, but not this time: double checking the config did not reveal any mistakes.</p>

<p>With no traces in the logs we had to dig a little bit deeper. Since single-sign on is all about redirection and passing along the required information in the process, taking a closer look at the network traffic made sense.</p>

<p><img src="https://i.snap.as/5D6RVSjC.png" alt=""/></p>

<p><em>(see <a href="https://www.youtube.com/watch?v=J1_4v0u2aic">Virtual Developer Day 2020 – Getting to Know Sitecore Identity – George Chang</a> for a good introduction on Sitecore ID)</em></p>

<h2 id="security-best-practices-for-the-win" id="security-best-practices-for-the-win">Security best practices for the win</h2>

<p>A useful tool to do this is fiddler (<a href="https://www.telerik.com/fiddler/fiddler-classic" title="Fiddler Classic">fiddler classic</a> in my case): a web debugging proxy to <em>successfully log, inspect, and alter HTTP(s) network requests and server responses</em>.</p>

<p>I was already thinking bad tokens, encryption issues, claim mismatches, … Luckily the issue was not as complex as I feared. Comparing network traffic from my (working) setup with traffic from the client setup revealed they had one HTTP header missing: <strong>Strict-Transport-Security</strong>, also known as <strong>HSTS</strong>.</p>

<blockquote><p>If a website accepts a connection through HTTP and redirects to HTTPS, visitors may initially communicate with the non-encrypted version of the site before being redirected, if, for example, the visitor types <a href="http://www.foo.com/">http://www.foo.com/</a> or even just foo.com. This creates an opportunity for a man-in-the-middle attack. The redirect could be exploited to direct visitors to a malicious site instead of the secure version of the original site.</p>

<p>The HTTP Strict Transport Security header informs the browser that it should never load a site using HTTP and should automatically convert all attempts to access the site using HTTP to HTTPS requests instead.</p></blockquote>

<p><em><a href="https://developer.mozilla.org/en-US/docs/Glossary/HSTS">https://developer.mozilla.org/en-US/docs/Glossary/HSTS</a></em></p>

<p>This is exactly what happens in my fiddler trace: even though the server tells my browser to go to HTTP (using the <em>Location:</em> header), my browser ignores this and connects over HTTPS directly (line 52).</p>

<p><img src="https://i.snap.as/gEP8hH9P.png" alt=""/></p>

<p>Why would Sitecore redirect us to HTTP? No idea. As far as I can tell all our config is set correctly. I can only assume this is leftover code from a time where local development was often done on HTTP. With Sitecore on containers, development setup is a lot closer to production setup, including running on HTTPS.</p>

<h2 id="ingress" id="ingress">Ingress</h2>

<p>So why did I did not face this issue on my setup? An important part of a Kubernetes setup is managing how external traffic can access the services in your cluster (HTTP, HTTPS, TLS, …). This is done with the <a href="https://kubernetes.io/docs/concepts/services-networking/ingress/">Ingress API object</a>. Out of the box, Sitecore suggests you to use the <em>NGINX Ingress controller</em> for this.</p>

<p>NGINX is a fine default, but my client has a track record in Kubernetes (not on Azure) and for their networking requirements they standardize on <a href="https://istio.io/">Istio</a>, a service mesh. To use it, we had to switch NGINX with Istio Ingress.</p>

<p>Turns out HSTS is enabled by default in NGINX (see <a href="https://kubernetes.github.io/ingress-nginx/user-guide/tls/#http-strict-transport-security">https://kubernetes.github.io/ingress-nginx/user-guide/tls/#http-strict-transport-security</a>), but not in Istio. Enabling it is quite easy though (in case you might be interested): <a href="https://www.wagner-dev.com/istio-configure-strict-transport-security-hsts.html">https://www.wagner-dev.com/istio-configure-strict-transport-security-hsts.html</a></p>

<p>In a development setup, network traffic is typically handled with <a href="https://doc.traefik.io/traefik/">traefik</a>. Sitecore provides you with docker-compose files that force this behavior.</p>

<p><img src="https://i.snap.as/QIrF5Ncv.png" alt=""/></p>

<p>So why didn’t we spot this right away? The browser we were using (it’s name starts with a ‘C’) doesn’t show the protocol in the URL bar, so we simply didn’t spot it. That we had to test this through a screen share session probably didn’t help neither (but that’s a different story).</p>

<h2 id="in-summary" id="in-summary">In summary</h2>
<ul><li>Sitecore login depends on HSTS.</li>
<li>HSTS is enabled by default for NGNIX ingress, but that might not be the case for other ingress controllers (e.g. Isitio).</li>
<li>You can’t see what you can’t see.</li></ul>

<p>Tags: <a href="https://stijndevos.net/tag:aks" class="hashtag"><span>#</span><span class="p-category">aks</span></a>, <a href="https://stijndevos.net/tag:kubernetes" class="hashtag"><span>#</span><span class="p-category">kubernetes</span></a>, <a href="https://stijndevos.net/tag:ngnix" class="hashtag"><span>#</span><span class="p-category">ngnix</span></a>, <a href="https://stijndevos.net/tag:istio" class="hashtag"><span>#</span><span class="p-category">istio</span></a>.</p>
]]></content:encoded>
      <guid>https://stijndevos.net/how-browser-security-fixes-sitecore-login</guid>
      <pubDate>Mon, 26 Jul 2021 12:22:39 +0000</pubDate>
    </item>
  </channel>
</rss>