teamatldocker / confluence

Dockerized Atlassian Confluence
https://hub.docker.com/r/teamatldocker/confluence/
MIT License
301 stars 147 forks source link

xmlstarlet for Crowd SSO causing mangled seraph-config.xml ? #46

Closed dragon788 closed 6 years ago

dragon788 commented 6 years ago

I'm not sure if it is the mangled seraph-config.xml shown below or something else with the Crowd_enable_SSO flag, but there is something fishy going on.

I'm attempting to simulate an environment with all the Atlassian apps communicating with each other via a "composed" docker-compose and I've ironed out most of the kinks (and will hopefully PR a few changes to your repos soon), but every time I enable Crowd authentication if I also have Crowd SSO turned on for the Confluence container it completely prevents logging in. There is a known issue with Crowd in Confluence preventing local logins from working, but this is actually preventing valid Crowd logins from working either, I end up having to tear down the instance and set it up again. I've also run into issues with the Jira container and Crowd SSO so I've turned it off on those for now, though Bitbucket doesn't seem to mind whether it is on or off.

<security-config
  >
    <parameters
    >
        <init-param
      >
            <param-name
        >login.url</param-name
      >
            <param-value
        >/login.action?os_destination=${originalurl}&amp;permissionViolation=true</param-value
      >
        </init-param
    >
        <init-param
      >
            <param-name
        >link.login.url</param-name
      >
            <param-value
        >/login.action</param-value
      >
        </init-param
    >
        <init-param
      >
            <param-name
        >cookie.encoding</param-name
      >
            <param-value
        >cNf</param-value
      >
        </init-param
    >
        <init-param
      >
            <param-name
        >login.cookie.key</param-name
      >
            <param-value
        >seraph.confluence</param-value
      >
        </init-param
    >

        <!--only basic authentication available-->
        <init-param
      >
            <param-name
        >authentication.type</param-name
      >
            <param-value
        >os_authType</param-value
      >
        </init-param
    >

        <!-- Invalidate session on login to prevent session fixation attack -->
         <init-param
      >
            <param-name
        >invalidate.session.on.login</param-name
      >
            <param-value
        >true</param-value
      >
        </init-param
    >
        <!-- Add names for session attributes that must not be copied to a new session when the old one gets invalidated.
          Currently it is empty (i.e. all attributes will be copied). -->
        <init-param
      >
            <param-name
        >invalidate.session.exclude.list</param-name
      >
            <param-value
      />
        </init-param
    >
    </parameters
  >

    <rolemapper
      class="com.atlassian.confluence.security.ConfluenceRoleMapper"
  />
    <controller
      class="com.atlassian.confluence.setup.seraph.ConfluenceSecurityController"
  />

    <!-- Default Confluence authenticator, which uses the configured user management for authentication. -->

    <!-- Custom authenticators appear below. To enable one of them, comment out the default authenticator above and uncomment the one below. -->

    <!-- Authenticator with support for Crowd single-sign on (SSO). -->
    <!-- <authenticator class="com.atlassian.confluence.user.ConfluenceCrowdSSOAuthenticator"/> -->

    <!-- Specialised version of the default authenticator which adds authenticated users to confluence-users if they aren't already a member. -->

    <services
    >
        <service
        class="com.atlassian.seraph.service.PathService"
      >
            <init-param
        >
                <param-name
          >config.file</param-name
        >
                <param-value
          >seraph-paths.xml</param-value
        >
            </init-param
      >
        </service
    >
    </services
  >

    <elevatedsecurityguard
      class="com.atlassian.confluence.security.seraph.ConfluenceElevatedSecurityGuard"
  />

<authenticator
      class="com.atlassian.confluence.user.ConfluenceCrowdSSOAuthenticator"
  /></security-config
>
blacklabelops commented 6 years ago

You can set CONFLUENCE_CROWD_SSO first to true and then back to false. Confluence should disable crowd sso and regain normal functionality.

If this does not happen then it's an issue of the xml file format. If it does reset functionality it's not an issue of the xml file format.

You can also try to manually set the SSO functionality inside the xml file.

Then check your whole configuration with this manual: https://confluence.atlassian.com/crowd/integrating-crowd-with-atlassian-confluence-198573.html

Note: The flag only activates Crowd SSO. If you cannot authenticate with confluence without SSO, then the problem is elsewhere. Only when you can successfully authenticate to confluence with crowd you should also activate SSO with crowd.

dragon788 commented 6 years ago

Turning off Crowd SSO via CONFLUENCE_CROWD_SSO=false or leaving it unset did allow me to configure Crowd as an authentication method without getting into the broken state. I also checked the seraph-config.xml and it appears more reasonable/normal now.

    <parameters>
        <init-param>
            <param-name>login.url</param-name>
            <param-value>/login.action?os_destination=${originalurl}&amp;permissionViolation=true</param-value>
        </init-param>
        <init-param>
            <param-name>link.login.url</param-name>
            <param-value>/login.action</param-value>
        </init-param>
        <init-param>
            <param-name>cookie.encoding</param-name>
            <param-value>cNf</param-value>
        </init-param>
        <init-param>
            <param-name>login.cookie.key</param-name>
            <param-value>seraph.confluence</param-value>
        </init-param>

        <!--only basic authentication available-->
        <init-param>
            <param-name>authentication.type</param-name>
            <param-value>os_authType</param-value>
        </init-param>

        <!-- Invalidate session on login to prevent session fixation attack -->
         <init-param>
            <param-name>invalidate.session.on.login</param-name>
            <param-value>true</param-value>
        </init-param>
        <!-- Add names for session attributes that must not be copied to a new session when the old one gets invalidated.
          Currently it is empty (i.e. all attributes will be copied). -->
        <init-param>
            <param-name>invalidate.session.exclude.list</param-name>
            <param-value></param-value>
        </init-param>
    </parameters>

    <rolemapper class="com.atlassian.confluence.security.ConfluenceRoleMapper"/>
    <controller class="com.atlassian.confluence.setup.seraph.ConfluenceSecurityController"/>

    <!-- Default Confluence authenticator, which uses the configured user management for authentication. -->
    <authenticator class="com.atlassian.confluence.user.ConfluenceAuthenticator"/>

    <!-- Custom authenticators appear below. To enable one of them, comment out the default authenticator above and uncomment the one below. -->

    <!-- Authenticator with support for Crowd single-sign on (SSO). -->
    <!-- <authenticator class="com.atlassian.confluence.user.ConfluenceCrowdSSOAuthenticator"/> -->

    <!-- Specialised version of the default authenticator which adds authenticated users to confluence-users if they aren't already a member. -->
    <!-- <authenticator class="com.atlassian.confluence.user.ConfluenceGroupJoiningAuthenticator"/> -->

    <services>
        <service class="com.atlassian.seraph.service.PathService">
            <init-param>
                <param-name>config.file</param-name>
                <param-value>seraph-paths.xml</param-value>
            </init-param>
        </service>
    </services>

    <elevatedsecurityguard class="com.atlassian.confluence.security.seraph.ConfluenceElevatedSecurityGuard"/>

</security-config>

I have a feeling there is something in the xmlstarlet that is unhappy because it is missing a cookie name or something else after this line triggers the updated config (with the weird line endings/breaks). I'll play with it a bit more, just wondered if you had any ideas offhand.

blacklabelops commented 6 years ago

The shown file has never been touched by xmlstarlet. My script deletes the authenticator-element and attaches it at the bottom. Both values true and false manipulates the file. The file format is the same in both cases.

blacklabelops commented 6 years ago

I can verify your problem. Though, the xml format is not at fault. Enabling the authenticator is not enough, you need to define a crowd.properties file: See here: https://confluence.atlassian.com/crowd/integrating-crowd-with-atlassian-confluence-198573.html

Under: Copy the crowd.properties file from CROWD/client/conf/ to CONFLUENCE/confluence/WEB-INF/classes. Edit CONFLUENCE/confluence/WEB-INF/classes/crowd.properties. Change the following properties:

Firefishy commented 6 years ago

@blacklabelops Need a PR for crowd.properties change or you on it? CC @devingops

blacklabelops commented 6 years ago

I would be glad if someone finishes the feature who began it. I am not even using this feature.

Do you use crowd and sso @Firefishy ? I have checked we have sso support inside bitbucket and confluence image. I have never checked functionality in both!

blacklabelops commented 6 years ago

Okay this code is rather copy & paste from my Jira solution. Before I commit anything, I will test the other images for SSO functionality. I rather hate to implement and offer things that do not work!

Anybody else is free to try.

blacklabelops commented 6 years ago

Same in Jira, needs a crowd.properties.

blacklabelops commented 6 years ago

Bitbucket seems to be more advanced, there you just need one property to enable everything.

Sooo back to the drawing board!

Firefishy commented 6 years ago

Tested the JIRA using the JIRA_CROWD_SSO=true setting + mapping in an external crowd.properties without issue. The mapping in of crowd.properties should likely be documented (or extra ENV created)

blacklabelops commented 6 years ago

I am still trying to get Confluence SSO working. Can you give me a hint an what your crowd.properties file looks like?

Firefishy commented 6 years ago

crowd.properties:

application.name                        APP-NAME-IN-CROWD
application.password                    APP-PASSWORD-IN-CROWD
application.login.url                   http://localhost:8095/crowd/console/
crowd.server.url                        http://localhost:8095/crowd/services/
crowd.base.url                          https://URL-FOR-CROWD
session.isauthenticated                 session.isauthenticated
session.tokenkey                        session.tokenkey
session.validationinterval              2
session.lastvalidation                  session.lastvalidation

We use Docker swarm docker-compose.yml:

version: "3.2"

services:

  jira:
    image: "blacklabelops/jira:7.8.0"
    ports:
      - mode: host
        target: 8080
        published: 8080
        protocol: tcp
    volumes:
      - /path-to/atlassian_data/jira:/var/atlassian/jira
      - /path-to/crowd.properties:/opt/jira/atlassian-jira/WEB-INF/classes/crowd.properties
    deploy:
      mode: replicated
      replicas: 1
    environment:
      - 'JIRA_PROXY_NAME=jira.example.com'
      - 'JIRA_PROXY_PORT=443'
      - 'JIRA_PROXY_SCHEME=https'
      - 'JIRA_CROWD_SSO=true'
      - 'TZ=UTC'
      - 'CATALINA_OPTS= -Xms8g -Xmx8g'

    healthcheck:
     test: "curl --fail --location http://localhost:8080/status || exit 1"
     interval: 60s
     timeout: 30s
     retries: 20

And we use haproxy to do SSL termination, we are very specific which headers we pass:

backend jira_example_com
  option forwardfor header X-Forwarded-For
  reqadd X-Forwarded-Proto:\ https
  reqadd X-Forwarded-Port:\ 443
  reqadd X-Forwarded-Host:\ jira.example.com
  reqidel ^X-Forwarded-For:.*
  reqidel ^X-Forwarded-Proto:.*
  reqidel ^X-Forwarded-Port:.*
  reqidel ^X-Forwarded-Host:.*
  reqidel ^Proxy:.*
  server atlassian01 10.0.0.1:8080 check
  server atlassian02 10.0.0.2:8080 check
  server atlassian03 10.0.0.3:8080 check
  server atlassian04 10.0.0.4:8080 check
blacklabelops commented 6 years ago

Ah I see, you have not tested everything with an actual instance of crowd. Well I tried, in order to make sure which properties we need envs for but didn't work so far.

blacklabelops commented 6 years ago

Finally got this working!

I can verify that the main issue is the file crowd.properties.

It needs the following properties and we need ENVs for all properties:

application.name=
application.password=
crowd.base.url=
session.validationinterval=
blacklabelops commented 6 years ago

Finished!

blacklabelops commented 6 years ago

Sorry, still has a bug.

blacklabelops commented 6 years ago

Now generates a working config.