Skanuj projekt z SonarQube
Darmowa aplikacja ułatwiająca poprawę jakości kodu i łatania luk bezpieczeństwa w projekcie zespołowym

Aplikacja usprawniająca pracę w zespole
SonarQube to darmowa aplikacja, która identyfikuje oraz pomaga naprawiać luki bezpieczeństwa i poprawiać jakość kodu w projekcie zespołowym. Podobnie jak SonarLint jest projektem Open Source.
SonarLint i SonarQube korzystają z tej samej listy reguł, jednakże reguły te można włączać i wyłączać. SonarLint to rozszerzenie IDE (np. InteliJ IDEA), więc włączanie/wyłączanie reguł w jego ustawieniach dotyczy tylko Twojego IDE.

Co gdy pracujesz zespołowo i chciałbyś by wszyscy w zespole posiadali taką samą listę reguł? Do tego właśnie służy aplikacja SonarQube, gdzie lista włączonych/wyłączonych reguł jest w jednym miejscu, czyli w uruchomionej aplikacji na serwerze. Pozostałe osoby w zespole korzystają z tej listy w swoim IDE poprzez połączenie pluginu SonarLint z aplikacją SonarQube. W tym przypadku lista reguł w ustawieniach SonarLint jest ignorowana (poza kategorią Secrets
).
Wymagane ustawienia systemowe
Do uruchomienia aplikacji SonarQube użyjemy najprostszego i polecanego przeze mnie sposobu, czyli Dockera. Skorzystamy w tym celu z oficjalnego obrazu SonarQube znajdującego się na Docker Hub. Jednakże zanim uruchomimy kontener w systemie Linux musimy sprawdzić wartości jakie wyświetlają poniższe komendy:
sysctl vm.max_map_count
sysctl fs.file-max
ulimit -n
ulimit -u

SonarQube korzysta z Elastic Search, który wymaga następujących ustawień do prawidłowego działania:
vm.max_map_count
większego lub równego 524288, inaczej możemy spodziewać się wyjątków Out of Memory (brakuje pamięci RAM)fs.file-max
większego lub równego 131072, inaczej możemy spodziewać się utraty danych- użytkownik uruchamiający SonarQube może otworzyć przynajmniej 131072 deskryptory pliku (
ulimit -n
), inaczej możemy spodziewać się utraty danych - użytkownik uruchamiający SonarQube może otworzyć przynajmniej 8192 wątki (
ulimit -u
), aby aplikacja mogła wykonywać wszystkie swoje operacje
Aby ustawić te wartości tymczasowo dla otwartej sesji terminala należy wykonać poniższe komendy logując się wcześniej na użytkownika root
(komendą sudo su
, do poprzedniego użytkownika wracamy komendą su nazwa-użytkownika
):
sysctl -w vm.max_map_count=524288
sysctl -w fs.file-max=131072
ulimit -n 131072
ulimit -u 8192
Aby ustawić je na stałe dla użytkownika root
(wymagane przez Dockera) oraz innych (co może przydać się później przy korzystaniu z Elastic Search w swojej aplikacji) należy:
- dla
vm.max_map_count
ifs.file-max
do pliku/etc/sysctl.conf
dodać poniższe linie:vm.max_map_count = 524288
fs.file-max = 131072
- dla
ulimit -n
:- do plików
/etc/systemd/system.conf
i/etc/systemd/user.conf
dodać linięDefaultLimitNOFILE=131072
- do pliku
/etc/security/limits.conf
dodać poniższe linie:root soft nofile 131072
root hard nofile 131072
* soft nofile 131072
* hard nofile 131072
- do plików
- dla
ulimit -n
:- do plików
/etc/systemd/system.conf
i/etc/systemd/user.conf
dodać linięDefaultLimitNPROC=8192
- do pliku
/etc/security/limits.conf
dodać poniższe linie:root soft nproc 8192
root hard nproc 8192
* soft nproc 8192
* hard nproc 8192
- do plików
Następnie należy zrestartować Wirtualną Maszynę, aby zobaczyć zmiany.

Pierwsze uruchomienie - Docker
Do pierwszego uruchomienia SonarQube będzie nam potrzebna poniższa komenda:
docker container run --name sonarqube -d -p 9000:9000 -v sonardata:/opt/sonarqube/data -v sonarlogs:/opt/sonarqube/logs -v sonarextensions:/opt/sonarqube/extensions sonarqube:9.2.3-community
Wersja 9.2.1 była najnowsza w chwili pisania postu, ale polecem użyć 9.2.3 lub wyższą z uwagi na podatność Log4J. Informacja o SonarQube jest dostępna tutaj.

Uruchomiliśmy SonarQube Community, czyli darmową edycję. Za inne edycje trzeba zapłacić. Porównanie możesz znaleźć tutaj.
Jeżeli nie wiesz co oznaczają poszczególne części komendy, zajrzyj do artykułu "Jak zacząć pracę z Dockerem?", gdzie dokładnie je wytłumaczyłem. Jedyną nową częścią komendy jest flaga -v
(można używać zamiennie z --volume
). Służy ona do tworzenia woluminów z nazwami (ang. named volumes), w których przechowywane są dane. Dzięki tym woluminom nie stracimy danych, gdy zatrzymamy i usuniemy kontener. Wystarczy, że przy uruchamianiu nowego kontenera ponownie wskażemy te same woluminy. Stworzyliśmy więc następujące woluminy:
sonardata
przechowujący pliki z danymi wykorzystywanymi m.in. przez indeksy ElasticSearch i embedowaną bazę danych H2sonarlogs
przechowujący logi SonarQube i ElasticSearchsonarextensions
przechowujący pluginy
Pierwsze uruchomienie - Przeglądarka
Po uruchomieniu kontenera przejdź w przeglądarce pod adres internetowy http://localhost:9000, gdzie przywita Cię ekran logowania do SonarQube. Domyślne dane logowania wyglądają następująco:
- Login:
admin
- Password:
admin

Po kliknięciu przycisku Log in
będziemy musieli zmienić hasło domyślne:

Następnie będziemy mieli możliwość stworzenia naszego pierwszego projektu:

Wybieramy opcję Manually
(manualnie) i w polu Project display name
wpisujemy wyświetlaną nazwę projektu, zaś w polu Project key
unikalny identyfikator projektu (mogą być takie same).

Następnie po wciśnięciu przycisku Set Up
możemy wybrać sposób w jaki będziemy analizowali (skanowali) nasz projekt. W tej chwili interesuje nas opcja Locally
(lokalnie), którą wybieramy.

W kolejnym oknie będziemy musieli podać nazwę tokena. Potem wystarczy kliknąć przycisk Generate
by wygenerować token, który będzie Ciebie identyfikował podczas operacji skanowania. Bez niego nie będzie możliwe przeskanowanie Twojego projektu.


Zapisz sobie gdzieś token (twój będzie inny). Po kliknięciu przycisku Continue
będziemy musieli wybrać metodę skanowania projektu. Nas interesuje technologia Maven
.

Aby wykonać pierwsze skanowanie należy w terminalu przejść do folderu z projektem i następnie uruchomić wyświetloną komendę.
mvn clean verify sonar:sonar \
-Dsonar.projectKey=skanuj-projekt-z-sonarqube \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.login=ed9360f4160db9d320a25f572362ac3665f10700
Jednakże polecenie jest dość długie, więc jak je skrócić?
Plugin Mavena, czyli jak skanować kod
Użyjemy w tym celu plugin Mavena sonar-maven-plugin i zdefiniujemy profil w pliku pom.xml
znajdującym się w projekcie, który chcemy skanować. Na początek dodajmy sekcję właściwości po tagu </artifactId>
z najnowszymi wersjami (w chwili pisania posta) już wspomnianego sonar-maven-plugin
oraz properties-maven-plugin, który przyda się nam już za chwilę:
<properties>
<properties-maven-plugin.version>1.0.0</properties-maven-plugin.version>
<sonar-maven-plugin.version>3.9.1.2184</sonar-maven-plugin.version>
</properties>
Następnie stwórzmy sobie profil mavenowy o nazwie (id
) sonar
:
<profiles>
<profile>
<id>sonar</id>
<properties>
<sonar.host.url>http://localhost:9000</sonar.host.url>
<sonar.projectKey>skanuj-projekt-z-sonarqube</sonar.projectKey>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>${properties-maven-plugin.version}</version>
<executions>
<execution>
<id>read-sonar-properties</id>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>src/main/resources/sonar.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>${sonar-maven-plugin.version}</version>
<executions>
<execution>
<id>sonar-scan</id>
<phase>verify</phase>
<goals>
<goal>sonar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Profil ten składa się z właściwości sonar.host.url
oraz sonar.projectKey
. Pierwsza to adres do naszej aplikacji SonarQube: http://localhost:9000
. Druga to klucz projektu, który musi być taki sam jak ten ustawiony wcześniej w aplikacji SonarQube: skanuj-projekt-z-sonarqube
. Jest jeszcze potrzebna trzecia właściwość, a mianowicie sonar.login
, który jest naszym tokenem.
Token jest przypisany do naszego konta w SonarQube, w związku z czym nie powinniśmy go nikomu pokazywać, a tym bardziej commitować do wspólnego repozytorium Git. Dlatego w pliku .gitignore
musimy najpierw dodać następujący wpis, który sprawi, że plik z tokenem będzie ignorowany przy wykonywaniu commita:
### Project ###
sonar.properties
Następnie plik sonar.properties
możemy stworzyć pod ścieżką w projekcie src/main/resources
z poniższą zawartością (pamiętaj by podmienić wartość ze swoim tokenem):
sonar.login=ed9360f4160db9d320a25f572362ac3665f10700
Maven musi w jakiś sposób odczytać właściwość znajdującą się w pliku. Właśnie do tego będzie potrzebny nam properties-maven-plugin
. Został ustawiony w taki sposób by cel (ang. goal) read-project-properties
, który czyta właściwości projektu jak sama nazwa wskazuje, uruchamiał się podczas fazy (ang. phase) initialize
. Faza ta jest drugą fazą w domyślnym cyklu życia Mavena i ma za zadanie inicjalizować stan buildu. Pozostaje jeszcze konfiguracja celu, czyli wskazanie z którego pliku Maven ma odczytać właściwości: src/main/resources/sonar.properties
. W praktyce właściwość z tego pliku jest tym samym co poniższy zapis:
<properties>
<sonar.login>ed9360f4160db9d320a25f572362ac3665f10700</sonar.login>
</properties>
Teraz, gdy mamy ustawione wszystkie trzy właściwości potrzebne do wykonania skanowania, sonar-maven-plugin
może zostać skonfigurowany tak by uruchamiał cel sonar
podczas fazy verify
. Faza ta jest jedną z ostatnich w domyślnym cyklu życia Mavena i ma za zadanie zweryfikować czy nasz projekt spełnia założone wymagania.
Po stworzeniu profilu i pliku wystarczy przejść do folderu z projektem w wierszu poleceń i uruchomić komendę: mvn clean verify -Psonar
by wykonać skanowanie.
Część komendy mvn
wywołuje Mavena, część clean
czyści wygenerowane pliki w naszym projekcie (folder target
), verify
już znamy, a część -Psonar
wywołuje profil o nazwie sonar
. Łatwiejsze do zapamiętania prawda? 😁

mvn clean verify -Psonar
Po pomyślnym skanowaniu naszego projektu z wykorzystaniem Mavena, strona SonarQube odświeży się automatycznie i pokaże nam raport, z którego można wyczytać wiele ciekawych rzeczy. Więcej niż jest dostępne w pluginie SonarLint.


Połączenie SonarLint z SonarQube
To jest najłatwiejsza część. Otwierasz ustawienia InteliJ skrótem CTRL + ALT + S
, przechodzisz do Tools
-> SonarLint
i w zakładce Settings
w pozycji SonarQube / SonarCloud connections
klikasz ikonę plusa i dodajesz połączenie:


Opcje po kliknięciu przycisku Next
wypełnij według uznania. Po zakończeniu dodawania połączenia z SonarQube przejdź w ustawieniach InteliJ do Tools
-> SonarLint
-> Project Settings
, zaznacz opcję Bind project to SonarQube / SonarCloud
co umożliwi połączenie projektu z naszym lokalnym SonarQube i wypełnij resztę jak poniżej:

Od teraz korzystasz z listy reguł zarządzanej w aplikacji SonarQube, a nie lokalnej zdefiniowanej w InteliJ.

GitHub
Kod źródłowy jest udostępniony na GitHubie. Poniżej link 🙂
Podsumowanie
W tym artykule przedstawiłem Ci SonarQube, czyli darmową aplikację, która identyfikuje oraz pomaga naprawiać luki bezpieczeństwa i poprawiać jakość kodu w projekcie zespołowym. Ponadto pokazałem Ci:
- jak przygotować system operacyjny Ubuntu do uruchomienia SonarQube
- jak uruchomić SonarQube przy pomocy Dockera
- jak ustawić projekt SonarQube w przeglądarce
- jak wykonać skanowanie projektu przy pomocy Mavena
- jak połączyć plugin SonarLint i projekt z SonarQube.
W projekcie zespołowym aplikacja SonarQube powinna być postawiona na serwerze tak by każdy z członków zespołu mógł się z nią połączyć. W artykule SonarQube działa na lokalnej wirtualnej maszynie by móc Ci w prosty sposób go zademostrować.
Ponadto skan projektu powinien odbywać się automatycznie np. na Jenkinsie po każdym commicie członka zespołu. Jenkins to aplikacja Continuous Integration (w skrócie CI) i Continuous Delivery (w skrócie CD), która automatyzuje integrację i dostawę naszego projektu. W artykule projekt skanujemy ręcznie w ramach demonstracyjnych.
P.S. Skoro już o zespole mowa to Kubo, jeśli to czytasz, dziękuję za prawie 6 lat wspólnej pracy! Dzięki rozmowie z Tobą pierwszego dnia pracy, stres minął co umożliwiło mi późniejsze, komfortowe wdrożenie się w trening i pierwszy w życiu komercyjny projekt Java. Twoje pozytywne nastawienie do życia jest czymś co napędza ludzi do działania! Daje nadzieję, że z każdej negatywnej sytuacji można wyciągnąć coś pozytywnego. Wszystkiego dobrego i do zobaczenia w przyszłości!
Liczba komentarzy:
Zaloguj się lub dołącz do społeczności Javowców, aby móc uczestniczyć w dyskusji 🙂