//Cloudogu EcoSystem Docs

CAS-OIDC-Anbindung

Bei dem Upgrade zu Confluence 8 wurde versucht CAS mit OIDC anzubinden. Da Confluence leider noch keine Unterstützung für den BackChannel-Logout hat, werden hier alle geleisteten Implementierungen festgehalten. Diese können bei einer möglichen Unterstützung verwendet werden.

Allgemeine Aufgabe für die OIDC-Anbindung

  • Entfernen der CAS-Filter in resource/opt/atlassian/confluence/confluence/WEB-INF/web.xml.tpl
  • Verwendung des regulären ConfluenceAuthenticator in resource/opt/atlassian/confluence/confluence/WEB-INF/classes/seraph-config.xml-tpl
  • Im initialen Setup muss OIDC konfiguriert werden (zum Beispiel nach der LDAP-Konfiguration):
# Create ldap configuration
  postRequest "confluence/plugins/servlet/embedded-crowd/configure/ldap" "$(getLdapParameter)" "FALSE"

  # Add permissions to admin group
  postRequest "confluence/admin/permissions/doeditglobalpermissions.action" "$(getGlobalPermissionParameter)" "FALSE"

  # Add cas oidc instead of using the apereo java cas client because the confluence integration is deprecated.
  httpRequest "POST" "confluence/rest/authconfig/1.0/idps" "$(getCasOidcPayload)"

  # Disable basic auth for the login form so that confluence redirects to cas on login.
  disableBasicAuthLoginForm
function getCasOidcPayload() {
  local payload fqdn clientID clientSecret
  fqdn=$(doguctl config --global fqdn)
  clientID=$(doguctl config -e "sa-cas/oidc_client_id")
  clientSecret=$(doguctl config -e "sa-cas/oidc_client_secret")

  payload+='{"name":"CAS-OIDC",'
  payload+='"sso-type":"OIDC",'
  payload+='"issuer-url":"https://'"${fqdn}"'/cas/oidc",'
  payload+='"client-id":"'"${clientID}"'",'
  payload+='"client-secret":"'"${clientSecret}"'",'
  # shellcheck disable=SC2016
  payload+='"username-claim":"${preferred_username}",'
  payload+='"additional-scopes":[],'
  payload+='"discovery-enabled":false,'
  payload+='"enable-remember-me":true,'
  payload+='"enabled":true,'
  payload+='"button-text":"Login with CAS",'
  payload+='"authorization-endpoint":"https://'"${fqdn}"'/cas/oidc/authorize",'
  payload+='"token-endpoint":"https://'"${fqdn}"'/cas/oidc/accessToken",'
  payload+='"userinfo-endpoint":"https://'"${fqdn}"'/cas/oidc/profile",'
  payload+='"jit-configuration":{"user-provisioning-enabled":false}}'

  echo "${payload}"
}
function disableBasicAuthLoginForm() {
  echo "execute patch request to disable basic auth login form"
  httpRequest "PATCH" "confluence/rest/authconfig/1.0/sso" '{"show-login-form":false}'
}
  • Bei einem nicht initialen Start muss OIDC aktualisiert werden (zum Beispiel nach der FQDN-Aktualisierung):

    function subsequentStart() {
    echo "Confluence subsequent start detected."
    
    if [[ "${CREATE_CONFLUENCE_USERS_GROUP}" == "true" ]]; then
    echo "Updating users group..."
    update_users_group
    fi
    
    update_admin_group
    updateLdapSyncInterval
    updateFqdn
    updateOIDC
    
    doguctl state "starting"
    }
function updateOIDC() {
  # activate OIDC
  local fqdn clientID clientSecret oidcConfigID insertOrUpdateOIDC
  fqdn="$( doguctl config --global fqdn )"
  clientID="$( doguctl config -e "sa-cas/oidc_client_id" )"
  clientSecret="$( doguctl config -e "sa-cas/oidc_client_secret" )"
  oidcConfigID="$( execute_db_command_with_result "SELECT COALESCE((SELECT \"ID\" FROM \"AO_ED669C_IDP_CONFIG\" WHERE \"NAME\"='CAS-OIDC'), 1 /* default */)" )"
  read -r -d ';' insertOrUpdateOIDC<<EOM
    INSERT INTO "AO_ED669C_IDP_CONFIG" VALUES (
      '[]' /* ADDITIONAL_JIT_SCOPES */,
      '[]'/* ADDITIONAL_SCOPES */,
      'https://${fqdn}/cas/oidc/authorize' /* AUTHORIZATION_ENDPOINT */,
      'Login with CAS' /* BUTTON_TEXT */,
      '${clientID}' /* CLIENT_ID */,
      '${clientSecret}' /* CLIENT_SECRET */,
      true /* ENABLED */,
      true /* ENABLE_REMEMBER_ME */,
      '${oidcConfigID}' /* ID */,
      false /* INCLUDE_CUSTOMER_LOGINS */,
      'https://${fqdn}/cas/oidc' /* ISSUER */,
      NOW()::TIMESTAMP /* LAST_UPDATED */,
      '' /* MAPPING_DISPLAYNAME */,
      '' /* MAPPING_EMAIL */,
      '' /* MAPPING_GROUPS */,
      'CAS-OIDC' /* NAME */,
      NULL /* SAML_IDP_TYPE */,
      NULL /* SIGNING_CERT */,
      'OIDC' /* SSO_TYPE */,
      NULL /* SSO_URL */,
      'https://${fqdn}/cas/oidc/accessToken' /* TOKEN_ENDPOINT */,
      NULL /* USERNAME_ATTRIBUTE */,
      '\${preferred_username}' /* USERNAME_CLAIM */,
      'https://${fqdn}/cas/oidc/profile' /* USER_INFO_ENDPOINT */,
      false /* USER_PROVISIONING_ENABLED */,
      false /* USE_DISCOVERY */
    ) ON CONFLICT ("ID")
    DO UPDATE SET
      "ADDITIONAL_JIT_SCOPES" = '[]',
      "ADDITIONAL_SCOPES" = '[]',
      "AUTHORIZATION_ENDPOINT" = 'https://${fqdn}/cas/oidc/authorize',
      "BUTTON_TEXT" = 'Login with CAS',
      "CLIENT_ID" = '${clientID}',
      "CLIENT_SECRET" = '${clientSecret}',
      "ENABLED" = true,
      "ENABLE_REMEMBER_ME" = true,
      "INCLUDE_CUSTOMER_LOGINS" = false,
      "ISSUER" = 'https://${fqdn}/cas/oidc',
      "LAST_UPDATED" = NOW()::TIMESTAMP,
      "MAPPING_DISPLAYNAME" = '',
      "MAPPING_EMAIL" = '',
      "MAPPING_GROUPS" = '',
      "NAME" = 'CAS-OIDC',
      "SAML_IDP_TYPE" = NULL,
      "SIGNING_CERT" = NULL,
      "SSO_TYPE" = 'OIDC',
      "SSO_URL" = NULL,
      "TOKEN_ENDPOINT" = 'https://${fqdn}/cas/oidc/accessToken',
      "USERNAME_ATTRIBUTE" = NULL,
      "USERNAME_CLAIM" = '\${preferred_username}',
      "USER_INFO_ENDPOINT" = 'https://${fqdn}/cas/oidc/profile',
      "USER_PROVISIONING_ENABLED" = false,
      "USE_DISCOVERY" = false
    ;
EOM
  execute_db_command "${insertOrUpdateOIDC}"

  # deactivate confluence login form
  local loginFormKey jsmLoginFormKey authFallbackKey
  loginFormKey="com.atlassian.plugins.authentication.sso.config.show-login-form"
  jsmLoginFormKey="com.atlassian.plugins.authentication.sso.config.show-login-form-for-jsm"
  authFallbackKey="com.atlassian.plugins.authentication.sso.config.enable-authentication-fallback"
  upsertBandanaValue '_GLOBAL' "${loginFormKey}" '<string>false</string>'
  upsertBandanaValue '_GLOBAL' "${jsmLoginFormKey}" '<string>false</string>'
  upsertBandanaValue '_GLOBAL' "${authFallbackKey}" '<string>false</string>'
}