AWS EC2に静的コード分析ツールSonarQubeを構築する

[KINTO Technologies Advent Calendar 2021](https://qiita.com/advent-calendar/2021/kinto-technologies)- Qiitaの22日目の記事です。
この記事では、プロジェットに静的分析ツールのSonarQubeをAWS EC2に適用してプロジェクトにCIと連動して使う方法について紹介します。


> うちのプロジェットでは、下記のFlowで活用しています。
>**github PR → sonarqubeから静的分析　→ PRに結果レポートリンク**

#静的分析とは何か
開発をする際に単に機能だけ動作するコードを作るだけでなく、読みやすいコード、メンテナンスに良いコードなどを作るために多くの努力をしていると思います。
このためにコードレビューなどを通じて同僚開発者が直接検討する場合もあるが、整形化されたパターンに対してはソースコードを分析するツールを利用することができる。これを静的コード分析と呼びます。
![Screenshot 2021-12-22 at 22.51.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337851/cc531f7c-1d92-eba3-f530-912240f70de2.png)



# なぜ静的分析なのか
**少ない費用で経験豊富な開発者の活動を置き換える方法ができる。**

非常に正常にうまく動作するだけの複雑さソースコードはソフトウェアは開発者にも、プロジェツトにもまったく役に立ちません。
間違ったコードはまた誤ったコードを作るし、落ちるコード可読生や高まる複雑さのおかげで、プロジェクトコードは時間の経過とともにますます理解するのが難しくなります。
開発者はもっと多くの努力と時間を必要とするし、プロジェクトはいつ爆発するのか分からない爆弾を抱いて生きていきます。
そのため、プログラミングでも誤った姿勢を指摘し、適切に開発できるように導く方法が必要です。
アジャイルで強調しているペアプログラミング、モブプログラミング、またはコードインスペクションアクティビティもまた良い選択肢ですが、
このような文化を導くことができるメンターがあれば、すぐにコードの品質を向上させることができますが問題は「人＝＝時間＝＝お金」。

きちんとした開発のためにはそれほど多くの費用が必要になります。このため 、コストがかからなくコードの品質を確認し、間違った部分を正しい方向に修正できるように指導するさまざまなツールが出てました。

#SonarQubeとは？
> SonarQubeは、20以上のプログラミング言語でバグ、コードスメル、セキュリティの脆弱性を発見するための静的コード分析をサポートしています。そして自動レビューを行い、
> 継続的なコード品>>質チェックを可能にするオープンソースプラットフォームです。出典：[SonarQubeウィキペディア](https://en.wikipedia.org/wiki/SonarQube)

SonarQubeは、上記で紹介した静的コード分析ツールの1つです。

静的コード分析ツールには、PMD、FindBugs、CheckStyleなどがあります。私たちのチームでSonarQubeを選択する主な理由は、リファレンスがたくさんあり、GithubやJenkinsとの連携を通じて自動静的コード分析を構成できるからです。

**[java基準静的分析ツール]**

+ PMD [PMD](https://pmd.github.io/) 
  + 未使用の変数、空のコードブロック、不要なオブジェクトの生成など、Defectを引き起こす可能性のあるコードを調べます。

+ FindBugs [FindBugs™ - Find Bugs in Java Programs](http://findbugs.sourceforge.net/)
 + 定められたルールで潜在的なエラータイプを探す

+ CheckStyle [checkstyle – Checkstyle 9.2](http://checkstyle.sourceforge.net/)
 + 定められたコーディングルールに従うかどうかの分析

###### SonarQubeがサーポートしてくれる言語
![e28435ef-516c-4016-83d5-fc732d0e0a12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337851/a5553ed8-76b5-a74f-4e32-d269cc9e82d1.png)
###### SonarQube Server version
![8771b44c-55ec-4b9b-a553-37824ee283a6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337851/c3c9329b-4808-ae43-0926-52c608547c45.png)

###### SonarQube Price[基準：2021/06]
![Screenshot 2021-12-22 at 22.52.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337851/9af180ab-e5cb-21fb-b7c5-9918859ede1c.png)

## SonarQube Architecture
SonarQubeプラットフォームは4つのコンポーネントで構成されています。
![Screenshot 2021-12-22 at 23.11.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337851/92b307a9-d75e-7f45-230e-5667f911da35.png)

+ 1.SonarQube Server

    + Web Server：ユーザーに分析結果を表示し、SonarQube設定ページを提供します。
    + Search Server：Elasticsearch Serverを使用し、ユーザーに検索機能を提供します。
    + Compute Engine Server：静的分析結果を生成し、SonarQube Databaseで保存

+ 2.SonarQube DataBase 
  + SonarQubeの基本設定（セキュリティ、プラグイン情報など）とプロジェクト分析のスナップショットを保存します。インストール時に、DefaultとしてH2 DBを含め、設定で様々なDBが利用可能

+  3.SonarQube Plugin
   + 内部で使用するさまざまな機能(分析プログラム言語、権限、管理、SCMなど)をプラグイン形式でインストール可能

+ 4.SonarQube Scanner
 + プロジェクトの静的分析を実行するためのツールで、さまざまな形式で提供され、CI Serverと連携して使用可能

## SonarQube Integration
![Screenshot 2021-12-22 at 23.43.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337851/65b55977-b741-cf54-63cb-fc2afecf2d97.png)

1. IDEでコードを作成し、Sonar Lintなどを介してローカルでコード分析を実行する。
2. 開発者は分析を通じて修正された完成コードをSCMにプッシュする。
3. CI Serverでトリガーされたビルドを実行するときにSonarQube Scannerを実行する
4. SonarQube Scannerは、生成された分析レポートの処理のためにSonarQubeに送信します。
5. SonarQube Serverは分析レポートの結果を処理してDBに保存し、結果をWebサーバー経由で提供します。
6. 開発者はWebページで分析結果を確認してコードを改善します。
7. 管理者は結果報告書を受け取る。

## SonarQubeソフトウェア品質
SonarQubeは、次の7つの品質要素に基づいてソフトウェア品質を区別して管理しています。

+ SonarQubeソフトウェア品質
 SonarQubeは、次の7つの品質要素に基づいてソフトウェア品質を区別して管理しています。

     + Code Smell：深刻な問題ではないが、ベスト・プレクティスで些細な問題として、モジュール性（modularity）、理解可能性（understandability）、変更可能性（changeability）、テスト容疑性（testability）、再使用性（reusability）などが含まれる。

     + Bugs：通常、潜在的なバグや実行時間に予想される動作をしないコードを示します。

     + Vulnerabilities：ハッカーにとって潜在的な弱点になる可能性があるセキュリティ上の問題を指します。 SQLインジェクション、クロスサイトスクリプトなどのセキュリティの脆弱性を見つけます。

     + Duplications：コードの冗長性は、コードの品質を阻害する最大の要因の1つです。

     + Unit Test ：ユニットテストのカバレッジを通じて、ユニットテストの実行の程度と実行されたテストの成功/失敗情報を提供します。

     + Complexity : コードの循環複雑度、認知複雑度を測定します。

     + Size：ソースコードサイズに関連するさまざまな指標を提供します。

# SonarQubeを使用してみよう
SonarQubeをLocalで使用する方法もあり、Dockerを利用してSonarQubeコンテナを浮かべて使うこともありますがうちのチームでは分析した結果の可視化と複数のアプリの移植性を考慮して、 EC2 Hostに設置する方法にしました。
ここでは、SonarQube Server version Communityで話します。
# 開発環境

+ Project
  + Android
    + java、Kotiln
+ インフラ
  + AWS EC2、Amazon Linux 2 
    + SonarQube Server version Community
        + Object-c,SwiftはSonarQube Server version _Develop version_が必要

SonarQube7.xは下記のような要件があります。
SonarQube versionによって要件に合わせて設定する必要があります
>最低 2GB / 1 vcpu 容量のServer
>PostgreSQL Version9.3以上
>OpenJDK 11及びJRE 11
>全てのSonarQube Processはsonar 使用者で実行

##順番


### AWS Instanceを生成して、ec2 user でssh接続

* Hardware Requirements of SonarQube
    * RAM：最小2GBとOSのための1GBの余裕RAM必要 - [SonarQube公式で確認](https://docs.sonarqube.org/latest/requirements/requirements/)
    

```shell
 __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
6 package(s) needed for security, out of 16 available
Run "sudo yum update" to apply all updates.
-bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory

```

###  Javaを設置
Updateと必要なPackagesを設置する。

```
sudo yum update -y
sudo yum install wget unzip -y
```
Java 11を設置する。
Amazon linuxでは次のように設置する。

```
sudo yum update -y
sudo yum install wget unzip -y
```
設置後はJava 11で設定されているかversion確認する。

```
Total download size: 3.4 M
Installed size: 5.2 M
Downloading packages:
java-11-openjdk-devel-11.0.13.0.8-1.amzn2.0.3.x86_64.rpm                           | 3.4 MB  00:00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : 1:java-11-openjdk-devel-11.0.13.0.8-1.amzn2.0.3.x86_64                                 1/1 
  Verifying  : 1:java-11-openjdk-devel-11.0.13.0.8-1.amzn2.0.3.x86_64                                 1/1 

Installed:
  java-11-openjdk-devel.x86_64 1:11.0.13.0.8-1.amzn2.0.3 
[ec2-user ~]$ java --version
openjdk 11.0.13 2021-10-19 LTS
OpenJDK Runtime Environment 18.9 (build 11.0.13+8-LTS)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.13+8-LTS, mixed mode, sharing)     
```

####  rootでLoginして実行する 

これはメモリ問題防止のため下記のように設定する- [Linuxの場合設定情報](https://docs.sonarqube.org/latest/requirements/requirements/)

```
[root@ip- ~]# sysctl vm.max_map_count
vm.max_map_count = 65530
[root@ip- ~]# sysctl -w vm.max_map_count=524288
vm.max_map_count = 524288
[root@ip- ~]# sysctl -w fs.file-max=131072
fs.file-max = 131072
[root@ip- ~]# ulimit -n 131072
[root@ip- ~]# ulimit -u 8192
```

###  SonarQube Databaseを設定する
ここではPostgreSQLでDatabaseを設置しました。

```
amazon-linux-extras install postgresql10 vim epel -y
yum install -y postgresql-server postgresql-devel
.
Installed:
   $ postgresql-devel.x86_64 0:10.17-1.amzn2.0.2                                
   $ postgresql-server.x86_64 0:10.17-1.amzn2.0.2 
Complete!
// 初期化
/usr/bin/postgresql-setup --initdb
 * Initializing database in '/var/lib/pgsql/data'
 * Initialized, logs are in /var/lib/pgsql/initdb_postgresql.log
 
 $ systemctl enable postgresql
Created symlink from /etc/systemd/system/multi-user.target.wants/postgresql.service to /usr/lib/systemd/system/postgresql.service
 $ systemctl start postgresql 
```
####  SonarQubeのDatabaseと使用者を生成する

```
// Database生成
sudo su - postgres
psql
postgres=# create user sonar with password 'sonar';
CREATE ROLE
postgres=# create database sonar owner sonar;
CREATE DATABASE
postgres-# \q
-bash-4.2$ exit
logout
```
####  PostgreSQL設定ファイルを修正する(今後の認証のため)
```
sudo vi /var/lib/pgsql/data/pg_hba.conf
```

```
# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     trust
# IPv4 local connections:
host    all             all             0.0.0.0/0               md5
# IPv6 local connections:
host    all             all             ::1/128                 md5
~                                                                   
```

####  PostgreSQLを起動する
```
sudo systemctl start postgresql
sudo systemctl enable postgresql
```

###  SonarQube Server設置
/optの下にSonarQube Serverを設置する。

```
cd /opt 
sudo wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-7.6.zip
```
####  zipファイルを解凍して新しいフォルダを生成する

```
sudo unzip sonarqube-7.6.zip
sudo mv sonarqube-7.6 sonarqube
```

####  sonar.propertiesにDatabaseと連動する情報を入力する
* ファイル

```
sudo vi /opt/sonarqube/conf/sonar.properties
```
* 内容

```
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar
sonar.jdbc.url=jdbc:postgresql://localhost/sonar
```

####  SonarQubeを実行ユーザーと権限を付与する

```
sudo useradd sonar
sudo chown -R sonar:sonar /opt/sonarqube
```

###  SonarQube実行する

それでは、設置したSonarQubeを実行してみる。

sonarでログインして、SonarQubeを実行するスクリプトがあるフォルダに移動します。

```
sudo su - sonar
cd /opt/sonarqube/bin/linux-x86-64
```

sonar.shスクリプトを実行して、状態を確認する。

```
./sonar.sh start
./sonar.sh status
./sonar.sh console
```

SonarQubeの場合、**基本が9000 Port**です。

このように実行して http://[EC2 Instance ip Address]:[port Number] で接続するとSonarQubeを確認できます。 
![Screenshot 2021-12-22 at 22.49.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337851/587e1bc9-f2fe-ddda-1203-d3199c0404fc.png)


初めてアクセスするとログインする必要がありますが、初期ID/パスワードは**admin/admin**です。
初期接続後、パスワードを設定してくれると、Server 設定完了です。

# SonarQubeとGitHub Actionsは統合

GitHub Actionsは、GitHubから提供する**CI/CDツール**です。
commit や push、cron、webhook などの状況でタスクを自動的に特定のタスクを行うことができます。
mainブランチプロジェクトのルートに **/.github/workflows/*.yml**形式で書くと、githubが認識して動作します。

### workflow文
大きくいつ実行するかを宣言する**on句**、
順番に実行されるフローjobを指定する**jobs句**、各jobで実行する機能を作成する**steps句**などがあります。
ワークフローについては公式文書を参照するのが最善です -[GitHub Actions](https://docs.github.com/en/actions)
ただし分量が膨大なので、workflowで必要な部分だけを追加するように学習するのが良いと思います。

実際にプロジェットで活用しているworkflow文をインポートしました。

# 適用してみたら
sonarqubeとgithubアクションを利用して、プロジェクトのコードがPRが発生するたびにレポートを受け取る機能を実装してみました。
適用して活用してみると、単にテストコードのカバレッジを越えてcode smell、security hotspot、bugsの可能性のあるコードをレポートしてくれて便利です。
あと、問題の根拠と修正方法までガイドしてくれるのでsonarqubeから学ぶこともかなりでした。


当社では、トヨタ車のサブスク「KINTO」等の企画/開発を行っており、エンジニアを募集中です。
[KINTO Technologies コーポレートサイト](https://www.kinto-technologies.com/)