kubernetessitecoreidentityserver4nginx-ingress

Sitecore 10 K8S Deployment - Invalid redirect_uri and Keyset Missing Errors


I am working on a k8s (AKS) Sitecore 10 XM1 deployment, and am seeing two (potentially related) issues in the k8s environment which do not occur with the same container images in Docker for windows. My assumption is that they are probably caused by the ingress controller config, TLS certificates or environment variables since these are the only real differences. I'm having difficulty diagnosing the cause as I'm fairly new to containers, the newish Sitecore identity server and k8s.

I've replaced the actual domain name with 'mydomain', and we have valid TLS certs for the actual domain deployed using certmanager.

The first issue is related to our CD pipeline not being able to login non-interactively (per https://doc.sitecore.com/developers/100/developer-tools/en/configure-a-non-interactive-client-login.html) in order to perform content serialization commands. When my deployment pipeline executes dotnet sitecore login --client-credentials true --authority ${{ parameters.idServerUrl }} --cm ${{ parameters.cmServerUrl }} --allow-write true --client-id "Pipeline_Automation" --client-secret "$(sitecore-identitysecret-pipeline)", I receive the error Keyset is missing. The necessary config files are deployed to our cm and id instances via COPY commands in the environment Dockerfiles (which I can see inside the running containers), and I am able to login via client credentials when the solution is running locally in Docker.

The second issue is that we see Invalid redirect_uri: "https://author.qa.mydomain.com/identity/signin" errors in the id pod logs when attempting to hit https://author.qa.mydomain.com/sitecore at the point where we should be redirected to the sign-in page. I've read that this is typically caused by the actual redirect URL not matching that configured by Sitecore_Sitecore__IdentityServer__Clients__DefaultClient__AllowedCorsOrigins__AllowedCorsOriginsGroup1 environment variable of the k8s spec for the id environment, however the logs indicate that they're identical:

id logs

[13:12:36] IdentityServer4.Validation.AuthorizeRequestValidator [Error] Invalid redirect_uri: "https://author.qa.mydomain.com/identity/signin"

AuthorizeRequestValidationLog {ClientId="Sitecore", ClientName="Sitecore", RedirectUri=null, AllowedRedirectUris=["{AllowedCorsOrigin}/identity/signin", "{AllowedCorsOrigin}/signin-oidc"], SubjectId="anonymous", ResponseType=null, ResponseMode=null, GrantType=null, RequestedScopes="", State=null, UiLocales=null, Nonce=null, AuthenticationContextReferenceClasses=null, DisplayMode=null, PromptMode=null, MaxAge=null, LoginHint=null, SessionId=null, Raw={["client_id"]="Sitecore", ["response_type"]="code id_token token", ["scope"]="openid sitecore.profile", ["state"]="OpenIdConnect.AuthenticationProperties=gradGeDSd71cNE43mbnFr-GuWj0q03FGaBiqGgyhXJW0-7qYt4xi5D5C360rNowTwT0PC9hZCut484hMo7WFSRsHmkseOJ5ud99RUhtxQwHrXuATCqErmKQE0m3UtPBsBhpySWkcs3J1EwkuPeELzplf_uMU7F6lyh77sUfyrQuTZf1bn05wJ2ZnEpGDXmAcSe5nCRQOt5D9hemDBZ4WzA", ["response_mode"]="form_post", ["nonce"]="637527067565470343.M2MwMDkxNGMtNzM0NC00OThkLWI0YmMtZTBiZmJhZDM2OWRmODM4YjViODgtOTdmOC00Nzc5LThhZWMtZjU2MmE2MzY5M2Mz", ["redirect_uri"]="https://author.qa.mydomain.com/identity/signin", ["sc_account_prefix"]="sitecore\\", ["x-client-SKU"]="ID_NET461", ["x-client-ver"]="5.3.0.0"}} 

[13:12:36] IdentityServer4.Endpoints.AuthorizeEndpoint [Error] Request validation failed

nginx logs

XXX.XX.XXX.XX - - [31/Mar/2021:12:10:16 +0000] "POST /identity/externallogin?authenticationType=SitecoreIdentityServer&ReturnUrl=%2fidentity%2fexternallogincallback%3fReturnUrl%3d%26sc_site%3dshell%26authenticationSource%3dDefault&sc_site=shell HTTP/2.0" 302 0 "https://author.qa.mydomain.com/identity/login/shell/SitecoreIdentityServer" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0" 597 0.013 [default-cm-80] [] 10.240.0.83:80 0 0.012 302 435fbe68699d547286aef26f15f4d33f
XXX.XX.XXX.XX - - [31/Mar/2021:12:10:16 +0000] "GET /connect/authorize?client_id=Sitecore&response_type=code%20id_token%20token&scope=openid%20sitecore.profile&state=OpenIdConnect.AuthenticationProperties%3DD9AWnwdC9UV0fjOTg3giJdWs0rdIRftadzkgUYO7c9sGu6nsBnyVCcrXNFJw1EhiXT2bDmJrdpqy3Gf8sMX5UXU1yJmz0u2Rpud_OUTd9YMot-1_OFzTCjPZS7-lrUxBlwkHhJP-eJN5wgDPBKCohsyHpHqmI9KaETYn2p7pnfnsQMh-7nvI9_iy3KFifcHiMYo4zyMkch-FZm7SW_pWsA&response_mode=form_post&nonce=637527894166260277.ZjdmNWIyNjUtZTk2NS00NzhmLTk4MDctMjFlNmU3ZjRjNjE4MjNhMDAwYmEtNGRmYS00YTcxLThmYTYtNTIwNzkzN2M3NGYy&redirect_uri=https%3A%2F%2Fauthor.qa.mydomain.com%2Fidentity%2Fsignin&sc_account_prefix=sitecore%5C&x-client-SKU=ID_NET461&x-client-ver=5.3.0.0 HTTP/2.0" 302 0 "https://author.qa.mydomain.com/identity/login/shell/SitecoreIdentityServer" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0" 564 0.007 [default-id-80] [] 10.240.0.73:80 0 0.008 302 354a57aea9818b47ce853edc6abee662
XXX.XX.XXX.XX - - [31/Mar/2021:12:10:16 +0000] "GET /home/error?errorId=CfDJ8B12A-SlGFlFuiZCVhQvJ8LQrI1XT9zDZiDk__KCVmMZULmTqb8K9QN9a-lqnM_gl9hxJC3CqPMCOITToOp5QKRb3nP8A8IuiY9Z0v7ofXpvYlzYiMnbe1V03MJs7t_nHh6CS8RkfqlwK1Z1R2V31JcDb7FEXn2Ek6mwWxAonA9LuGcGQe9yhxcy3zmF60DqQkun71_fWMtrgIdIeFHo4Zn1aCYSYYQpuLY84lOB-aiFNdxgS48gV1lASfUshgdBrVTD3y6KuMMdUylKsoOG4JXQRUh5aT67f6J2WCWWwzYiDQ5sos1N7Lxp_Pq7iZq5KQ HTTP/2.0" 404 0 "https://author.qa.mydomain.com/identity/login/shell/SitecoreIdentityServer" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0" 295 0.003 [default-id-80] [] 10.240.0.73:80 0 0.000 404 fd27666878ee5cf4affb008674edc693

I believe the issues are related as the identity server behaves normally when the solution runs locally behind its traefik ingress. I am able to login, do not experience the redirect error and can login non-interactively.

I'd like to try using a cli browser such as lynx running in a pod within the cluster to see if I can reproduce the redirect error in order to narrow the cause to the ingress controller, but have not found an easy way to do this.

If anyone could provide some diagnostic advice, I'd be most grateful.

id.yaml k8s spec

apiVersion: v1
kind: Service
metadata:
  name: id
spec:
  selector:
    app: id
  ports:
  - protocol: TCP
    port: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: id
  labels:
    app: id
spec:
  replicas: 1
  selector:
    matchLabels:
      app: id
  template:
    metadata:
      labels:
        app: id
    spec:
      nodeSelector:
        kubernetes.io/os: windows
      containers:
      - name: sitecore-xm1-id
        image: mydomain.azurecr.io/cms/mydomain-id:latest
        ports:
        - containerPort: 80
        imagePullPolicy: Always
        env:
        - name: Database_Server
          valueFrom:
            secretKeyRef:
              name: sitecore-database
              key: sitecore-databaseservername.txt
        - name: Core_Database_Username
          valueFrom:
            secretKeyRef:
              name: sitecore-database
              key: sitecore-core-database-username.txt
        - name: Core_Database_Password
          valueFrom:
            secretKeyRef:
              name: sitecore-database
              key: sitecore-core-database-password.txt
        - name: Sitecore_Sitecore__IdentityServer__Clients__PasswordClient__ClientSecrets__ClientSecret1
          valueFrom:
            secretKeyRef:
              name: sitecore-identity
              key: sitecore-identitysecret.txt
        - name: Sitecore_Sitecore__IdentityServer__CertificateRawData
          valueFrom:
            secretKeyRef:
              name: sitecore-identitycertificate
              key: sitecore-identitycertificate.txt
        - name: Sitecore_Sitecore__IdentityServer__CertificateRawDataPassword
          valueFrom:
            secretKeyRef:
              name: sitecore-identitycertificate
              key: sitecore-identitycertificatepassword.txt
        - name: Sitecore_License
          valueFrom:
            secretKeyRef:
              name: sitecore-license
              key: sitecore-license.txt
        - name: Sitecore_Sitecore__IdentityServer__Clients__CliServerClient__ClientSecrets__ClientSecret1
          valueFrom:
            secretKeyRef:
              name: sitecore-identity
              key: sitecore-identitysecret-pipeline.txt
        - name: Sitecore_Sitecore__IdentityServer__SitecoreMemberShipOptions__ConnectionString
          value: Data Source=$(Database_Server);Initial Catalog=Sitecore.Core;User ID=$(Core_Database_Username);Password=$(Core_Database_Password);
        - name: Sitecore_Sitecore__IdentityServer__AccountOptions__PasswordRecoveryUrl
          value: https://author.qa.mydomain.com/sitecore/login?rc=1
        - name: Sitecore_Sitecore__IdentityServer__Clients__DefaultClient__AllowedCorsOrigins__AllowedCorsOriginsGroup1
          value: https://author.qa.mydomain.com
        - name: Sitecore_Sitecore__IdentityServer__PublicOrigin
          value: https://id.qa.mydomain.com
        livenessProbe:
          httpGet:
            path: /healthz/live
            port: 80
            httpHeaders:
            - name: X-Kubernetes-Probe
              value: Liveness
          timeoutSeconds: 300
          periodSeconds: 30
          failureThreshold: 3
        startupProbe:
          httpGet:
            path: /healthz/ready
            port: 80
            httpHeaders:
            - name: X-Kubernetes-Probe
              value: Startup
          timeoutSeconds: 300
          periodSeconds: 30
          failureThreshold: 10
      imagePullSecrets:
      - name: acr-secret

cd.yaml k8s spec

apiVersion: v1
kind: Service
metadata:
  name: cm
spec:
  selector:
    app: cm
  ports:
  - protocol: TCP
    port: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cm
  labels:
    app: cm
spec:
  replicas: 1
  selector:
    matchLabels:
      app: cm
  template:
    metadata:
      labels:
        app: cm
    spec:
      nodeSelector:
        kubernetes.io/os: windows
      containers:
      - name: sitecore-xm1-cm
        image: mydomain.azurecr.io/cms/mydomain-xm1-cm:latest
        ports:
        - containerPort: 80
        imagePullPolicy: Always
        env:
        - name: Sitecore_InstanceName
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: Database_Server
          valueFrom:
            secretKeyRef:
              name: sitecore-database
              key: sitecore-databaseservername.txt
        - name: Master_Database_Username
          valueFrom:
            secretKeyRef:
              name: sitecore-database
              key: sitecore-master-database-username.txt
        - name: Master_Database_Password
          valueFrom:
            secretKeyRef:
              name: sitecore-database
              key: sitecore-master-database-password.txt
        - name: Core_Database_Username
          valueFrom:
            secretKeyRef:
              name: sitecore-database
              key: sitecore-core-database-username.txt
        - name: Core_Database_Password
          valueFrom:
            secretKeyRef:
              name: sitecore-database
              key: sitecore-core-database-password.txt
        - name: Web_Database_Username
          valueFrom:
            secretKeyRef:
              name: sitecore-database
              key: sitecore-web-database-username.txt
        - name: Web_Database_Password
          valueFrom:
            secretKeyRef:
              name: sitecore-database
              key: sitecore-web-database-password.txt
        - name: Forms_Database_Username
          valueFrom:
            secretKeyRef:
              name: sitecore-database
              key: sitecore-forms-database-username.txt
        - name: Forms_Database_Password
          valueFrom:
            secretKeyRef:
              name: sitecore-database
              key: sitecore-forms-database-password.txt
        - name: Sitecore_ConnectionStrings_Sitecoreidentity.secret
          valueFrom:
            secretKeyRef:
              name: sitecore-identity
              key: sitecore-identitysecret.txt
        - name: Sitecore_AppSettings_Telerik.AsyncUpload.ConfigurationEncryptionKey
          valueFrom:
            secretKeyRef:
              name: sitecore-telerik
              key: sitecore-telerikencryptionkey.txt
        - name: Sitecore_AppSettings_Telerik.Upload.ConfigurationHashKey
          valueFrom:
            secretKeyRef:
              name: sitecore-telerik
              key: sitecore-telerikencryptionkey.txt
        - name: Sitecore_AppSettings_Telerik.Web.UI.DialogParametersEncryptionKey
          valueFrom:
            secretKeyRef:
              name: sitecore-telerik
              key: sitecore-telerikencryptionkey.txt
        - name: Sitecore_License
          valueFrom:
            secretKeyRef:
              name: sitecore-license
              key: sitecore-license.txt
        - name: Sitecore_ConnectionStrings_Core
          value: Data Source=$(Database_Server);Initial Catalog=Sitecore.Core;User ID=$(Core_Database_Username);Password=$(Core_Database_Password);
        - name: Sitecore_ConnectionStrings_Security
          value: Data Source=$(Database_Server);Initial Catalog=Sitecore.Core;User ID=$(Core_Database_Username);Password=$(Core_Database_Password);
        - name: Sitecore_ConnectionStrings_Master
          value: Data Source=$(Database_Server);Initial Catalog=Sitecore.Master;User ID=$(Master_Database_Username);Password=$(Master_Database_Password);
        - name: Sitecore_ConnectionStrings_Web
          value: Data Source=$(Database_Server);Initial Catalog=Sitecore.Web;User ID=$(Web_Database_Username);Password=$(Web_Database_Password);
        - name: Sitecore_ConnectionStrings_ExperienceForms
          value: Data Source=$(Database_Server);Initial Catalog=Sitecore.ExperienceForms;User ID=$(Forms_Database_Username);Password=$(Forms_Database_Password);
        - name: Sitecore_ConnectionStrings_Solr.Search
          valueFrom:
            secretKeyRef:
              name: sitecore-solr
              key: sitecore-solr-connection-string.txt
        - name: Sitecore_Identity_Server_Authority
          value: https://id.qa.mydomain.com
        - name: Sitecore_Identity_Server_CallbackAuthority
          value: https://author.qa.mydomain.com
        - name: Sitecore_Identity_Server_InternalAuthority
          value: http://id
        - name: Sitecore_Identity_Server_Require_Https
          value: "false"
        - name: SOLR_CORE_PREFIX_NAME
          valueFrom:
            secretKeyRef:
              name: sitecore-solr
              key: sitecore-solr-core-prefix-name.txt
        livenessProbe:
          httpGet:
            path: /healthz/live
            port: 80
            httpHeaders:
            - name: X-Kubernetes-Probe
              value: Liveness
          timeoutSeconds: 300
          periodSeconds: 30
          failureThreshold: 3
        startupProbe:
          httpGet:
            path: /healthz/ready
            port: 80
            httpHeaders:
            - name: X-Kubernetes-Probe
              value: Startup
          timeoutSeconds: 300
          periodSeconds: 30
          failureThreshold: 10
      imagePullSecrets:
      - name: acr-secret

Solution

  • We resolved this by changing the version of sitecore cli we were using in our deployment pipeline. The powershell script which allows for login and serialization/publishing is:

    # Add nuget source & install Sitecore CLI
    Write-Host "Installing Sitecore CLI"
    dotnet nuget add source ${{ parameters.sitecoreNugetFeed }} --name "Sitecore-Public-Nuget-Feed"
    dotnet tool install --version 2.0.0 Sitecore.CLI
       
    # Login to ID Server
    Write-Host "Logging into ID Server ${{ parameters.idServerUrl }} for environment ${{ parameters.cmServerUrl }}"
    dotnet sitecore login --client-credentials true --authority ${{ parameters.idServerUrl }} --cm ${{ parameters.cmServerUrl }} --allow-write true --client-id "Pipeline_Automation" --client-secret "$(sitecore-identitysecret-pipeline)"
      
    # Deserialize Content
    Write-Host "Push Content"
    dotnet sitecore ser push
        
    # Publish Database
    Write-Host "Publish Database"
    dotnet sitecore publish