소나큐브 적용기 본문

우아한테크코스 4기/프로젝트

소나큐브 적용기

giron 2022. 8. 15. 23:38
728x90

SonarQube 란

  • 정적 코드 분석을 자동을 수행하는 오픈 소스 플랫폼
  • 중복 코드, 코딩 표준, 유닛 테스트, 코드 커버리지, 코드 복잡도, 주석, 버그 및 보안 취약점에 대해서 검사하고 결과를 보고서로 작성한다.
  • 20개 이상의 언어에 대한 분석이 가능하다.

정적 코드 분석 이란

  • 프로그램을 실행하지 않고 소스 코드나 컴파일된 코드를 분석하는 작업
  • 프로그램을 실행하지 않고 버그나 취약점을 분석할 수 있다.
  • 주로 개발 단계에서 코드의 구조적인 문제나 실수를 찾아내기 위해서 사용한다.
  • 코드 작성단계에서 차후 코드를 실행했을 때 발생할 가능성이 높은 문제를 미리 찾고 대처할 수 있다.
  • 단순이 버그나 오류를 찾아내는 것 뿐만 아니라 더 좋은 코드를 위한 개선점을 제시한다.

반대로 동적 분석에는 모니터링이나 테스트가 있다.

정적 코드 분석을 위해 SonarQube 를 사용한 이유

  • SonarCloud도 있었지만 SonarColud같은 경우는 소나큐브에 비해 한정적 기능을 제공한다.
  • 레퍼런스가 많다.
    • sonar cloud가 나오기 훨씬 전부터 나왔으므로 안정적이다. 
    • 오픈 소스 플랫폼이기 때문에 기본적으로 무료로 제공되고 레퍼런스가 많다.
  • 20개 이상의 다양한 언어에 대한 검사가 가능하기 때문에 다른 언어로 작성할 때도 SonarQube 를 정적 분석 도구로 사용할 수 있다.
  • GitHub, Jenkins 등의 툴과 다양한 방식으로 연동이 가능하다.

SonarQube 동작 개념

  1. SonarQube Scanner 가 소스코드를 Scan 한다.
    • Gradle, Jenkins 등 다양한 플랫폼에서 SonarQube Scanner 를 지원한다.
  2. SonarQube 어플리케이션이 설치된 서버로 Scan 한 소스코드를 전달한다.
  3. SonarQube 어플리케이션이 전달받은 소스코드를 분석하여 보고서를 작성한다.

SonarQube 사용 방법

사용 환경

  • GitHub & GitHub Actions
  • Gradle
  • Aws ec2
    • ubuntu 22.04
    • Arm 아키텍쳐
  • java 11
  • SonarQube 8.9.9 (lts버전)

사용 개요

  • 개발자가 GitHub Repository 에 PR 을 열거나 이미 열려있는 PR 의 branch 에 새로운 commit 을 push 한다.
  • GitHub Actions 를 통해 자동으로 Gradle 의 Scanner Task 가 실행된다.
  • Scan 된 소스코드가 SonarQube 어플리케이션이 설치된 ec2 서버로 전달된다.
  • SonarQube 어플리케이션이 전달받은 소스코드를 분석하여 보고서를 작성한다.
  • 보고서 작성이 끝나면 GitHub PR 에 보고서 링크를 남긴다.

적용

ec2 인스턴스에 SonarQube 설치 & 실행

// apt 업데이트 & unzip 설치

$ sudo apt update
$ sudo apt install unzip

소나큐브는 자바로 만들어져있어서 자바8 이상을 설치해야 한다.

// 자바 11 설치

$ wget -O- https://apt.corretto.aws/corretto.key | sudo apt-key add - 
 sudo add-apt-repository 'deb https://apt.corretto.aws stable main'
$ sudo apt-get update; sudo apt-get install -y java-11-amazon-corretto-jdk

// SonarQube 를 설치할 폴더 생성, 이동

$ sudo mkdir app
$ cd app
$ sudo mkdir sonarqube
$ cd sonarqube
// wget 으로 소나큐브 설치, 압축 해제(설치)

$ sudo wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-8.9.9.56886.zip
$ sudo unzip sonarqube-8.9.9.56886.zip

  • SonarQube 를 sudo 로 설치했기 때문에 SonarQube 의 실행을 위해서는 root 권한이 있어야한다.
  • 나의 root user 이름은 ubuntu 였다.

 

// SonarQube 실행 권한 변경

$ sudo chown -R ubuntu /app/sonarqube

8081로 포트 번호 수정 (우테코에서는 8080과 8081만 인바운드를 열어줘서 8081로 바꿨다)기본 port 번호는 9000이다.

// sonar.properties 파일 에서 소나큐브 포트 수정

vi /app/sonarqube/sonarqube-8.9.9.56886/conf/sonar.properties
...
sonar.web.port=8081
...

// lib 폴더에서 직접 소나큐브의 jar 파일 실행

cd /app/sonarqube/sonarqube-8.9.9.56886/lib
nohup java -jar sonar-application-8.9.9.56886.jar &

원래는 /app/sonarqube/sonarqube-8.9.9.56886/bin 디렉토리에서 sonar.sh파일을 실행시키면 실행이 된다고 한다.

하지만 저희 인스턴스가 arm아키텍처를 사용하므로 jar파일을 직접 실행시켜야 한다.

소나큐브가 아직 arm아키텍처를 지원하지 않는다고 한다.


이제 소나큐브에 ip:8081을 통해서 접근이 가능하다. 기본 계정의 아이디와 비밀번호는 admin 이다.

  • SonarQube 어플리케이션에 접근하여 우측 상단의 A를 클릭 -> My Account에 들어간다.
  • Security 탭에서 토큰을 생성한다. 생성된 토큰을 저장해둔다.
  • 생성된 Token 문자열을 잘 저장해두고 차후 Scanner 를 발동시킬 때 사용한다. 
  • 그후, projects에 들어가서 프로젝트도 만들어주면 된다.

토큰 생성

build.gradle 파일에 Scanner 설정 추가

plugins {
    id 'org.sonarqube' version '3.3' 
    id 'java'
    id 'jacoco'
}

sourceCompatibility = '11'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3'
}

test {
    useJUnitPlatform()
    finalizedBy 'jacocoTestReport'
}

jacoco { 
    toolVersion = "0.8.7"
}

jacocoTestReport { 
    reports {
        xml.enabled true
        csv.enabled false
        html.enabled false
    }
}

sonarqube { 
    properties {
        property "sonar.host.url", "SonarQube 서버 url"
        property "sonar.login", "SonarQube 어플리케이션에서 생성한 token"
        property "sonar.projectKey", "프로젝트 이름"
        property "sonar.projectName" , "SonarQube 로 전달할 소스 코드의 이름 or 버전"
        property "sonar.sources", "src" // 소스 경로
        property "sonar.language", "java" // 언어
        property "sonar.sourceEncoding", "UTF-8"
        property "sonar.profile", "Sonar way" // SonarQube 에서 분석할 때 적용할 프로필(분석할 수준 설정)
        property "sonar.java.binaries", "${buildDir}/classes" // 자바 클래스 파일위치
        property "sonar.test.inclusions", "**/*Test.java" // 코드 분석에 사용할 테스트 소스 
        property "sonar.coverage.jacoco.xmlReportPaths", "${buildDir}/reports/jacoco/test/jacocoTestReport.xml" // jacoco 플러그인의 결과 파일
    }
}

sonarqube 서버 url이나 login같은 경우는 노출되면 안되므로 해당 property를 지우고 환경변수로 넣어서 사용하면 좋다.

명령어같은 경우는 소나큐브에 들어가면 친절히 알려준다.

./gradlew -Dsonar.login={token} -Dsonar.host.url={sonarqube url}

Scanner 발동을 위한 GitHub Actions 설정

  • 개발자가 GitHub Repository 에 PR 을 열거나 이미 열려있는 PR 의 branch 에 새로운 commit 을 push 할 때 Gradle 의 Scanner 를 발동시켜 정적 분석을 자동으로 수행하기 위해서는 GitHub Actions 의 Workflow 를 사용해야 한다.
  • GitHub Actions 의 Workflow yml 파일 설정

.github/workflow/sonarqube.yml 파일

name: gongseek-backend-sonarqube

# 하기 내용에 해당하는 이벤트 발생 시 github action 동작
on:
  pull_request: # 모든 브랜치에서 PR이 일어났을 때 github action 동작
    branches:
      - '*'
    types: [opened, synchronize]
defaults:
  run:
    working-directory: ./backend

jobs:
  build:
    runs-on: ubuntu-22.04 # 실행 환경 지정

    steps:
      - name: Checkout source code
        uses: actions/checkout@v2
  analysis:
    runs-on: ubuntu-22.04
    env:
      SONARQUBE_PROJECT_KEY: gongseek
      SONARQUBE_URL: ${{secrets.SONARQUBE_URL}}
      SONARQUBE_TOKEN: ${{secrets.SONARQUBE_TOKEN}}
      PR_NUMBER: ${{github.event.pull_request.number}}
    steps:
      # 소스코드 체크아웃 수행
      - name: Checkout source code
        uses: actions/checkout@v2

      # gradlw 파일 권한 변경
      - name: gradlew permission change
        run: sudo chmod 755 gradlew

      # Gralde 의 Scanner 발동, 위의 env 에서 선언한 환경변수와 함께 발동
      - name: Sonaqube Analysis
        run: ./gradlew test sonarqube
          -Dsonar.host.url=${{ env.SONARQUBE_URL }}
          -Dsonar.projectKey=${{ env.SONARQUBE_PROJECT_KEY }}
          -Dsonar.projectName=${{ env.SONARQUBE_PROJECT_KEY }}-${{ env.PR_NUMBER }}
          -Dsonar.login=${{ env.SONARQUBE_TOKEN }}
      # PR 에 Comment 를 달아주는 스크립트 실행
      - name: Comment Sonarqube URL
        uses: actions/github-script@v4
        with:
          script: |
            const { SONARQUBE_PROJECT_KEY, SONARQUBE_URL, PR_NUMBER } = process.env
            github.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `📊 ${ SONARQUBE_PROJECT_KEY }-${ PR_NUMBER } 분석 결과 확인하기 [링크](${SONARQUBE_URL})`
            })

이제 거의 다 했다. 환경변수를 넣어주기만 하면 된다.

Github Actions에 환경변수 설정

레포지토리의 settings로 이동

new repository secret을 클릭해서 토큰을 입력해주면 된다.

소나큐브 실행

nohup java -jar sonar-application-8.9.9.56886.jar &

Reference

https://astonishing-message-fd2.notion.site/SonarQube-87663a36f4604441a56dca3357251f9b

https://techblog.woowahan.com/2661/

728x90
Comments