Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>

Contents

Atlassian Crowd

Atlassian Crowd는 Jira, Confluence, Bitbucket 등을 통합운용하기 위한 SSO(Single Sign-On) 솔류션이다. Atlassian 제품외에도 GitLab, nexus3와 같은 솔류션을 통합 할 수도 있다. Crowd SSO를 지원하지 않는 애플리케이션이라면 Crowd API를 이용해서 직접 개발해도 된다. 물론 Active Directory, LDAP 도 지원한다.

나는 Crowd를 기반으로 Jira, Confluence, GitLab의 계정을 연동해 보려 한다. 그리고 GoLang-Crowd 패키지를 이용해서 Crowd 연동 되는 인증서버를 직접 구축할 것이다.

시나리오

(가상의 회사)Joinc는 클라우드 개발팀을 운영하고 있다. 이들 클라우드 개발팀은 Jira, Confluence, GitLab, 내부에서 개발한 백오피스 서비스등 다양한 솔류션을 이용하고 있다. 이들을 하나의 계정으로 통합하려 한다.

테스트 환경

  • 서버 : 우분투 리눅스 19.04
  • 배포환경 : 로컬 docker-compose
  • CPU : Ryzen 7 2700 8코어 16 스레드
  • RAM : 32 기가
테스트하는데 부족함 없는 시스템이다.

인프라 구성

인프라는 아래와 같이 구성한다.

 Crowd 테스트 인프라

소프트웨어 구성은 아래와 같다.
소프트웨어 설명 도커 이미지
traefik 오픈소스 Edge router https://hub.docker.com/_/traefik
Crowd 전체 소프트웨어를 SSO로 통합한다. https://hub.docker.com/r/atlassian/crowd
Jira 이슈 트래킹 시스템 https://hub.docker.com/r/atlassian/jira-software
GitLab Git 저장소 https://hub.docker.com/r/gitlab/gitlab-ce
Mattermost 오픈소스 Slack Alternative
아래와 같이 host를 설정했다.
# cat /etc/hosts
127.0.0.1   localhost  crowd.joinc.co.kr  jira.joinc.co.kr  gitlab.joinc.co.kr chat.joinc.co.kr

  1. crowd.joinc.co.kr, jira.joinc.co.kr, gitlab.joinc.co.kr, chat.joinc.co.kr
  2. 사용자 요청은 traefik 으로 reverse proxy 한다.
  3. traefik는 도메인 기반으로 각 도커에 사용자 요청을 전송한다.
traefik의 포트만 80번(실제 서비스라면 443도 함께) 포트로 외부로 노출된다. 테스트를 위한 docker-compose 파일이다.
version: "2"

services:
    traefik:
        image: "traefik"
        container_name: "traefik"
        depends_on:
            - "mattermost"
            - "jira"
            - "crowd"
            - "confluence"
        ports:
            - "80:80"
            - "8080:8080"
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock
            - /home/yundream/workspace/devops/traefik.yml:/etc/traefik/traefik.yml
    mattermost:
        image: mattermost/mattermost-prod-app
        environment:
            - DB_PORT_NUMBER=3306
            - MM_SQLSETTINGS_DRIVERNAME=mysql
            - MM_SQLSETTINGS_DATASOURCE=mmuser:1234abcd@tcp(db:3306)/mattermost?charset=utf8mb4,utf8&readTimeout=30s&writeTimeout=30s
            - MM_USERNAME=mmuser
            - MM_PASSWORD=1234abcd
            - MM_DBNAME=mattermost
        labels:
            - "traefik.enable=true"
            - "traefik.port=8000"
            - "traefik.frontend.rule=Host:chat.joinc.co.kr"
            - "traefik.http.routers.mattermost.rule=Host(`chat.joinc.co.kr`)"

    db:
        image: mysql/mysql-server:8.0
        # read_only: true
        restart: unless-stopped
        volumes:
            - ./volumes/db/var/lib/mysql:/var/lib/mysql
            - /etc/localtime:/etc/localtime:ro
        environment:
            - MYSQL_ROOT_PASSWORD=mysql-root-password
            - MYSQL_USER=mmuser
            - MYSQL_PASSWORD=1234abcd
            - MYSQL_DATABASE=mattermost
              #        networks:
              #internal-network:


    crowd:
        image: atlassian/crowd
        container_name: crowd
        labels:
            - "traefik.enable=true"
            - "traefik.port=8095"
            - "traefik.frontend.rule=Host:crowd.joinc.co.kr"
            - "traefik.http.routers.crowd.rule=Host(`crowd.joinc.co.kr`)"
 
    jira:
        image: atlassian/jira-software:latest
        container_name: jira
        labels:
            - "traefik.enable=true"
            - "traefik.port=8080"
            - "traefik.frontend.rule=Host:jira.joinc.co.kr"
            - "traefik.http.routers.jira.rule=Host(`jira.joinc.co.kr`)"

    confluence:
        image: atlassian/confluence-server
        container_name: confluence
        labels:
            - "traefik.enable=true"
            - "traefik.port=8090"
            - "traefik.frontend.rule=Host:confluence.joinc.co.kr"
            - "traefik.http.routers.confluence.rule=Host(`confluence.joinc.co.kr`)"


    postgresql:
        image: postgres:9.5-alpine
        environment:
            - 'POSTGRES_USER=jira'
              # CHANGE THE PASSWORD!
            - 'POSTGRES_PASSWORD=jellyfish'
            - 'POSTGRES_DB=jiradb'
            - 'POSTGRES_ENCODING=UNICODE'
            - 'POSTGRES_COLLATE=C'
            - 'POSTGRES_COLLATE_TYPE=C'
        logging:
            # limit logs retained on host to 25MB
            driver: "json-file"
            options:
                max-size: "500k"
                max-file: "50"
주요 설정을 확인해 보자.

컨테이너 네트워크 하나의 네트워크만 사용하고 있다. 제대로 하려면 퍼블릭 네트워크와 프라이빗 네트워크를 구분, traefik는 퍼블릭 네트워크에 나머지는 프라이빗 네트워크에 두도록 해야 할 것이다. 나중에 바꿔보도록 하겠다.

jira, confluence, mattermost 애플리케이션의 컨테이너 설정은 각 컨테이너 설정 메뉴얼을 보고 작성하면 되니 특별히 언급할게 없다. traefik에서 프락시하기 위한 정보를 설정하는게 핵심이다.

traefik는 서비스의 labels를 읽어서 프락시를 설정한다. traefik 서비스의 volumes을 확인해보자.
volumes:
     - /var/run/docker.sock:/var/run/docker.sock
     - /home/yundream/workspace/devops/traefik.yml:/etc/traefik/traefik.yml
호스트의 도커 소켓파일(docker.sock)를 마운트하고 있다. traefik는 이 소켓을 이용해서, jira, confluence, crowd 컨테이너의 label을 읽어서 프락시를 설정한다. jira 서비스 정보를 살펴보자.
jira:
   image: atlassian/jira-software:latest
   container_name: jira
   labels:
       - "traefik.enable=true"
       - "traefik.port=8080"
       - "traefik.frontend.rule=Host:jira.joinc.co.kr"
       - "traefik.http.routers.jira.rule=Host(`jira.joinc.co.kr`)"
traefik는 "jira.joinc.co.kr"로 흐르는 트래픽은 jira 컨테이너의 8080포트(traefik.port)로 프락시 한다.

crowd를 이용한 SSO 설정

jira, confluence 등의 초기 설정은 이 문서에서는 다루지 않는다. 개발 환경은 여러 애플리케이션으로 구성되는데, 각 애플리케이션 단위로 인증/권한 시스템이 분리되면 개발 환경을 제대로 관리 할 수 없을 것이다. Atlasian crowd는 분산된 애플리케이션의 인증/권한 시스템을 통합관리해주는 SSO 및 ID 관리 시스템이다. SSO(Single Sign-On)은 하나의 사용자 이름과 암호로 여러 애플리케이션을 사용 할 수 있도록 도와주는 솔류션이다. Crowd를 이용해서 Jira, Confluence, Bitbucket등의 Atlassian 솔류션들을 통합 할 수 있다.

또한 AD, LDAP, Microsoft Azure AD, Novell eDirectory의 디렉토리를 통합 할 수 있다. 이 기능을 이용하면 회사에 기 구축된 유저 환경에 애플리케이션을 통합 할 수 있다. 여기에서는 디렉토리 통합은 다루지 않을 것이다. Atlassian 제품의 통합만을 다룰 것이다.

디렉토리 구성

디렉토리는 조직을 계층적으로 구조화하기 위해서 사용한다. 회사 조직의 "실 > 부 > 과 > 팀"과 같은 계층구조를 생각하면 된다. 나는 joinc-company라는 그룹을 만들기로 했다. corwd.joinc.co.kr 로 접근했다. traefik은 해당 요청을 crowd 서비스로 프락시한다.

 crowd directory - 1

Crowd는 외부 LDAP, Active Directory 등의 디렉토리 서비스를 연동 할 수 있다. 이 기능을 이용해서, 기존에 운영중인 디렉토리 서비스를 연동 할 수 있다. 이 기능은 온-프레미스 조직을 유연한 클라우드 조직으로 확장하려고 할 때 유용하게 사용 할 수 있다. 여기에서는 internal을 이용해서 crowd 디렉토리 서비스를 이용할 것이다.

crowd 세부 설정을 한다. 디렉토리 이름은 "joinc-company"로 했다. 다른 옵션은 넘어간다.

joinc-company 디렉토리를 확인 할 수 있다. 이제 joinc-company 조직(디렉토리)에 개발 그룹을 만든다. 개발 그룹의 이름은 "joinc-dev" 다.

개발조직으로 부터 foo, bar 유저를 추가해 달라는 요청이들어왔다. 두 유저를 추가하자.

joinc-dev 그룹에 foo, bar 유저를 멤버로 등록한다.

joinc-dev 그룹을 joinc-company 디렉토리에 등록한다. "Directory > joinc-company > Options > Add groups"에서 등록 할 수 있다.

이렇게 해서 아래와 같은 조직 구조를 만들었다.

 Directory Group User 구조

애플리케이션 연동

이렇게 만들어진 디렉토리와 그룹에 Jira, Confluece, BitBucket 같은 애플리케이션을 연동하면 된다. 나는 joinc-dev 그룹에 포함된 유저에게 jira, confluence 권한을 주기로 결정했다. 아래와 같은 그림이 될 것이다.

 Application 연동

"Crowd > Application" 에서 애플리케이션을 등록 할 수 있다.

아래 타입의 애플리케이션을 등록 할 수 있다.
  • Jira : 이슈 관리 시스템
  • Confluence : 위키 문서 솔류션
  • Bamboo : CICD 솔류션
  • Fisheye : 코드 변경 관리 및 검색
  • Crucible : 코드 리뷰
  • Bitbucket Server : Git 서버
  • Generic Application

Jira를 선택했다.

Jira를 연동하기 위해서 서버정보를 입력한다.

애플리케이션을 연동할 디렉토리 "joinc-company"를 선택한다.

joinc-company 디렉토리의 joinc-dev 개발자 그룹을 선택했다. 이렇게 joinc-company > joinc-dev 그룹에 jira 애플리케이션을 SSO로 연동하기 위한 설정을 끝냈다. 다만 jira 서버의 주소를 IP로 설정했는데, 도커로 올릴 경우 IP가 변경될 수 있다. 서비스 이름으로 jira를 찾을 수 있도록 설정을 변경하자.

"Application > Remote addresses"에 jira 서비스를 추가했다. 이제 jira 서버 아이피가 변경되더라도 연결에 문제가 생기지 않을 것이다. IP 주소는 삭제(remove)해도 괜찮다.

Jira 설정

애플리케이션간 연동은 "상호 연동 설정"을 해야 하는 경우가 대부분이다. corwd & 애플리케이션 연동도 마찬가지라서 jira에서 관리자 권한으로 "crowd 디렉토리 서비스를 사용 할 것을 설정"해줘야 한다.

"Jira > 사용자 설정 > 사용자 디렉토리"로 이동한다.

이제 디렉토리 설정을 한다. 중요 내용만 다룬다.
  • 이름 : 디렉토리 서비스 이름
  • 서버 URL : crowd 서버 URL
  • 응용프로그램 이름 : 한글이라서 헷갈릴 수 있겠다. crowd에 등록된 애플리케이션 이름이다.
  • 응용프로그램 비밀번호 : crowd에 등록된 애플리케이션 비밀번호다.
  • Crowd 권한 : 읽기/쓰기와 읽기 전용 두 가지 모드가 있다. Jira 애플리케이션 내에서의 권한을 변경이 필요하기 때문에 "읽기/쓰기" 모드를 선택했다. 예를 들어 나는 foo 유저를 관리자 권한을 줘서 jira 프로젝트를 관리하게 할 것이다.
  • 테스트 설정 : 작동을 테스트 할 수 있다.

Jira 사용자 관리 페이지에서 crowd 디렉토리에 추가한 유저가 보인다.

하지만 bar와 foo 유저로 로그인을 하면 실패 할 것이다. 아직 jira 애플리케이션 사용권한이 없기 때문이다.

joinc-dev "그룹에 응용프로그램 사용 권한"을 주자. 비로서 joinc-dev 사용자들은 jira를 사용 할 수 있게 된다.

confluence 연동

confluece 연동은 jira와 동일하므로 자세히 설명하지는 않겠다.
  1. crowd에 application을 만든다.
  2. application을 joinc-dev 그룹에 연결한다.
  3. confluence에 접속해서 사용자 디렉토리 설정으로 joinc-company 디렉토리를 추가한다.
  4. 글로벌 권한으로 가서 joinc-dev 그룹에 대한 "개인공간", "공간만들기" 권한을 부여한다.

정리

  • ECS 기반으로 올려야 겠다.
  • Atlassian 기반으로 완전한 개발환경을 설정하는 것 해봄직하다.
  • Atlassian 사용 할 때 마다 느끼는 건데, 유저/권한관리가 일관성이 없어서 할 때마다 헤맨다. 좀 정리 좀 해주라.
  • GitLab, Mattermost와 연동을 해봐야 겠다.