특징

- 업그레이드 및 설치 시, 기존 서비스는 중지한 후 설치함

- 언인스톨러는 설정 > 앱 > 설치된 앱에서 확인 가능

- 언인스톨 시, 기존 서비스를 중지하고 제거함

- GUID가 같으면 설치되지 않음

 

테스트 서비스 프로그램 만들기

1. Visual Studio 2022 → 새 프로젝트 만들기 → 작업자 서비스 선택하여 프로젝트 생성

2. NuGet 패키지 관리자로 아래 두 개 설치

3. Program.cs 를 아래와 같이 코딩 후 빌드

using WorkerService1;
using Microsoft.Extensions.Hosting.WindowsServices;

var builder = Host.CreateApplicationBuilder(args);
// Windows 서비스로 동작하도록
builder.Services.AddWindowsService(o =>
{
    o.ServiceName = "My Worker Service";
});
builder.Services.AddHostedService<Worker>();

var host = builder.Build();
host.Run();

4. 단일 배포 파일 생성

dotnet publish -c Release -r win-x64 -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -p:SelfContained=true

 

WiX v4 설치 후 구성

다운로드 및 설치 : https://marketplace.visualstudio.com/items?itemName=FireGiant.FireGiantHeatWaveDev17

1. Visual Studio 2022 → 새 프로젝트 만들기 → MSI Package 선택하여 프로젝트 생성

2. 코드 수정 및 빌드

// ExampleComponents.wxs
<!-- ExampleComponents.wxs -->
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
     xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
	<Fragment>
		<ComponentGroup Id="ExampleComponents" Directory="INSTALLFOLDER">
			<Component>
				<File Id="Service1"
					  Source="C:\Users\codetronik\source\repos\WorkerService1\WorkerService1\bin\Release\net8.0\win-x64\publish\WorkerService1.exe"
					  KeyPath="yes" />

				<!-- 서비스 등록 -->
				<ServiceInstall
					Name="MyService1"
					DisplayName="My Service"
					Description="Service example"
					Type="ownProcess"
					Start="auto"
					Account="LocalSystem"
					ErrorControl="normal"/>

				<!-- 설치/업그레이드/제거 시 제어 -->
				<ServiceControl
					Name="MyService1"
					Stop="both"
					Start="install"
					Remove="uninstall"
					Wait="yes"/>

			</Component>
		</ComponentGroup>
	</Fragment>
</Wix>

// Folder.wxs
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
	<Fragment>
		<StandardDirectory Id="ProgramFiles64Folder">
			<Directory Id="INSTALLFOLDER"
					   Name="!(bind.Property.Manufacturer) !(bind.Property.ProductName)" />
		</StandardDirectory>
	</Fragment>
</Wix>

// Package.en-us.wxl
<!--
This file contains the declaration of all the localizable strings.
-->
<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">

  <String Id="DowngradeError" Value="A newer version of [ProductName] is already installed." />

</WixLocalization>

// Package.wxs
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
	<Package Id="MyServicePkg"
			 Name="ServiceExample"
			 Manufacturer="Codetronik"
			 Version="1.0.0.0"
			 UpgradeCode="{1B29FC40-CA47-1067-131D-00DD010662DA}">
		<MajorUpgrade Schedule="afterInstallValidate"
					  DowngradeErrorMessage="!(loc.DowngradeError)" />
		<Feature Id="Main">
			<ComponentGroupRef Id="ExampleComponents" />
		</Feature>
	</Package>
</Wix>

 

 

환경 : Ubuntu 24.04.3 / 램 16G

SaaS를 사용 못하는 내부망에서 사용하기 위함

2025.08.12 기준

1. 도커 설치 (https://docs.docker.com/engine/install/ubuntu/ 참조)

$ wget https://download.docker.com/linux/ubuntu/dists/noble/pool/stable/amd64/containerd.io_1.7.27-1_amd64.deb && \
wget https://download.docker.com/linux/ubuntu/dists/noble/pool/stable/amd64/docker-ce-cli_28.3.3-1~ubuntu.24.04~noble_amd64.deb && \
wget https://download.docker.com/linux/ubuntu/dists/noble/pool/stable/amd64/docker-ce_28.3.3-1~ubuntu.24.04~noble_amd64.deb && \
wget https://download.docker.com/linux/ubuntu/dists/noble/pool/stable/amd64/docker-buildx-plugin_0.26.1-1~ubuntu.24.04~noble_amd64.deb && \
wget https://download.docker.com/linux/ubuntu/dists/noble/pool/stable/amd64/docker-compose-plugin_2.39.1-1~ubuntu.24.04~noble_amd64.deb
$ sudo dpkg -i ./containerd.io_1.7.27-1_amd64.deb ./docker-ce-cli_28.3.3-1~ubuntu.24.04~noble_amd64.deb ./docker-ce_28.3.3-1~ubuntu.24.04~noble_amd64.deb ./docker-buildx-plugin_0.26.1-1~ubuntu.24.04~noble_amd64.deb ./docker-compose-plugin_2.39.1-1~ubuntu.24.04~noble_amd64.deb
$ sudo service docker start & sudo docker run hello-world

2. 리버스 프록시 설치

$ sudo apt-get install nginx
# 인증서 만들기
$ IP=192.168.130.189
$ sudo openssl req -x509 -newkey rsa:2048 -days 825 -nodes -subj "/CN=${IP}" -addext "subjectAltName = IP:${IP}" -keyout /etc/ssl/private/sentry-ip.key -out /etc/ssl/certs/sentry-ip.crt
$ sudo vim /etc/nginx/sites-available/sentry.conf
# 80 -> 443 리다이렉트
server {
  listen 80;
  return 301 https://$host$request_uri;
}

# HTTPS 종단 (IP 기반, 기본 서버)
server {
  listen 443 ssl http2;

  ssl_certificate     /etc/ssl/certs/sentry-ip.crt;
  ssl_certificate_key /etc/ssl/private/sentry-ip.key;

  client_max_body_size 50m;

  location / {
    proxy_set_header Host               $host;
    proxy_set_header X-Forwarded-Host   $host;
    proxy_set_header X-Forwarded-Proto  https;
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:9000;
  }
}
$ sudo ln -s /etc/nginx/sites-available/sentry.conf /etc/nginx/sites-enabled/sentry.conf
$ sudo nginx -t
$ sudo systemctl reload nginx

3. Self-Hosted Sentry 설치 (https://develop.sentry.dev/self-hosted/ 참조)

$ sudo apt-get install git curl
$ VERSION=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/getsentry/self-hosted/releases/latest)
$ VERSION=${VERSION##*/}
$ git clone https://github.com/getsentry/self-hosted.git
4 cd self-hosted
$ git checkout ${VERSION}
$ sudo ./install.sh

$ vim sentry/config.yml
system.url-prefix: "https://192.168.130.189"
$ vim sentry/sentry.conf.py
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
USE_X_FORWARDED_HOST = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SOCIAL_AUTH_REDIRECT_IS_HTTPS = True
CSRF_TRUSTED_ORIGINS = ["https://192.168.130.189"]
$ sudo sed -i -E 's|proxy_set_header[[:space:]]+X-Forwarded-Proto[[:space:]]+\$scheme;|proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;|g' nginx.conf

$ sudo docker compose up --wait

4. curl  + sentry 에러 전송 예제

라이브러리 설치

$ sudo apt install -y libcurl4-openssl-dev
$ git clone --recursive https://github.com/getsentry/sentry-native.git
$ cd sentry-native
$ cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo   # 백엔드는 기본값 사용
$ cmake --build build --parallel
$ sudo cmake --install build

CMakeLists.txt 생성

cmake_minimum_required(VERSION 3.20)
project(app CXX)

find_package(sentry CONFIG REQUIRED)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE sentry::sentry)
#include <sentry.h>
#include <cstdio>
#include <stdexcept>

int main() {
    const char* DSN = "https://님_공개키@192.168.130.189/2";

    sentry_options_t* options = sentry_options_new();
    sentry_options_set_debug(options, 1);
    sentry_options_set_logger(options,
        [](sentry_level_e lvl, const char* msg, void*) {
            std::fprintf(stderr, "[sentry:%d] %s\n", (int)lvl, msg);
        }, nullptr);

  
    sentry_options_set_dsn(options, DSN);
    sentry_options_set_database_path(options, ".sentry-native");
    sentry_options_set_ca_certs(options, "아까만든인증서.crt");
    sentry_options_set_release(options, "myproject@1.0.0");    
    sentry_options_set_handler_path(options, "/usr/local/bin/crashpad_handler");

    // 원한다면 환경/태그
    sentry_options_set_environment(options, "dev");
    
    if (sentry_init(options) != 0) {
        throw std::runtime_error("sentry_init failed");
    }

    // 테스트 이벤트
    std::array<void*, 256> frames{};
    int n = backtrace(frames.data(), frames.size());

    sentry_value_t st  = sentry_value_new_stacktrace(frames.data(), n);
    sentry_value_t exc = sentry_value_new_exception("error", std::string(msg).c_str());
    sentry_value_set_by_key(exc, "stacktrace", st);

    sentry_value_t evt = sentry_value_new_event();
    sentry_event_add_exception(evt, exc);
    sentry_capture_event(evt);

    // 크래시
    int* p = nullptr; *p = 42;

    sentry_close();
}

4. sentry-cli 설치 및 환경 설정

https://192.168.130.189/settings/account/api/auth-tokens/new-token/ 에서 토큰 생성

$ curl -sL https://sentry.io/get-cli/ | bash
# 환경 파일 설정
$ vim ~/.sentryclirc
[defaults]
url = https://192.168.130.189
org = sentry # 조직 slug
project = agent # 프로젝트 slug

[http]
verify_ssl = false

[auth]
token = 님_토큰

# 정상 동작 확인
$ sentry-cli info
# 조직 slug 확인
$ sentry-cli organizations list
+----+--------+--------+--------------+---------------+--------------+
| ID | Name   | Slug   | Date Created | Early Adopter | Requires 2FA |
+----+--------+--------+--------------+---------------+--------------+
| 1  | Sentry | sentry | 2025-08-12   | false         | false        |
+----+--------+--------+--------------+---------------+--------------+
# 프로젝트 slug 확인
$ sentry-cli projects list -o sentry
+----+----------+--------+----------+
| ID | Slug     | Team   | Name     |
+----+----------+--------+----------+
| 1  | internal | Sentry | Internal |
| 2  | agent    | Sentry | agent    |
+----+----------+--------+----------+

# 파일 유효성 확인
$ sentry-cli debug-files check 님_실행파일
# 분리 심볼 생성
objcopy --only-keep-debug 님_실행파일 님_실행파일.debug
objcopy --add-gnu-debuglink=님_실행파일.debug 님_실행파일
# 파일 업로드
$ sentry-cli debug-files upload --include-sources 님_실행파일 님_실행파일.debug

5. 크래시패드 정상 전송을 위해 프로그램을 설치한 pc에 인증서 설치

# sentry 서버에서 인증서 가져와서 루트 인증서에 설정
$ sudo cp sentry-ip.crt /usr/local/share/ca-certificates/sentry-ip.crt
$ sudo update-ca-certificates

'Linux > Dev' 카테고리의 다른 글

VMware + clion + libbpf 구축  (0) 2025.07.08
#include <iostream>
#include <Poco/Logger.h>
#include <Poco/PatternFormatter.h>
#include <Poco/FormattingChannel.h>
#include <Poco/ConsoleChannel.h>
#include <Poco/FileChannel.h>
#include <Poco/SplitterChannel.h>
#include <Poco/AutoPtr.h>
#include <Poco/Thread.h>
#include <Poco/Runnable.h>

using namespace Poco;

class LevelFilterFileChannel : public FileChannel
{
public:
    LevelFilterFileChannel() : FileChannel() {}

    void log(const Message& msg) override
    {
        // debug, trace 로그 제외
        if (msg.getPriority() <= Message::PRIO_INFORMATION)
        {
            FileChannel::log(msg);
        }
    }
};

class MyWorker : public Runnable
{
public:
    void run() override
    {
        Logger& logger = Logger::get("aLogger");
        for (int i = 0; i < 5; ++i)
        {
            logger.notice("Poco Thread is running! i = " + std::to_string(i));
            Poco::Thread::sleep(500); // 0.5초 대기
        }
        logger.information("Poco Thread done.");
    }
};

int main()
{
    AutoPtr<ColorConsoleChannel> colorConsoleChannel(new ColorConsoleChannel);
    AutoPtr<LevelFilterFileChannel> fileChannel(new LevelFilterFileChannel);
    fileChannel->setProperty("path", "myapp.log");
    fileChannel->setProperty("rotation", "50000 K"); // 50,000KB 초과시 회전
    fileChannel->setProperty("archive", "timestamp");
    fileChannel->setProperty("purgeAge", "30 days"); // 30일 초과 로그 파일 삭제

    AutoPtr<PatternFormatter> patternFormatter(new PatternFormatter);
    patternFormatter->setProperty(
        "pattern",
        "[%Y-%m-%d %H:%M:%S] [%p] [PID:%P][TID:%T][TH:%I] %t"
    );
    patternFormatter->setProperty("times", "local");
   
    AutoPtr<FormattingChannel> fcConsole(new FormattingChannel(patternFormatter, colorConsoleChannel));  // 콘솔은 모든 로그
    AutoPtr<FormattingChannel> fcFile(new FormattingChannel(patternFormatter, fileChannel));

    // 콘솔 및 파일 채널로 메시지를 전달
    AutoPtr<SplitterChannel> splitter(new SplitterChannel);
    splitter->addChannel(fcConsole);
    splitter->addChannel(fcFile);  

    Logger& logger = Logger::get("Logger");
    logger.setChannel(splitter);
    logger.setLevel(Message::PRIO_TRACE); // 모든 로그 레벨 허용

    logger.fatal("FATAL 메시지");
    logger.critical("CRITICAL 메시지");
    logger.error("ERROR 메시지");
    logger.warning("WARNING 메시지");
    logger.notice("NOTICE 메시지");
    logger.information("INFO 메시지");
    logger.debug("DEBUG 메시지 - 콘솔만");
    logger.trace("TRACE 메시지 - 콘솔만");

    MyWorker worker;
    Thread thread;
    thread.start(worker);

    // 메인 스레드도 로그 남기기
    for (int i = 0; i < 3; ++i)
    {
        logger.notice("Main thread working... i = " + std::to_string(i));
        std::this_thread::sleep_for(std::chrono::milliseconds(400));
    }

    thread.join();
    logger.information("모든 작업 종료");
}

'Language > C++' 카테고리의 다른 글

[C++20] std::span  (0) 2025.05.25
[C++] 함수 const 선언 정리  (0) 2024.09.12

환경 : ubuntu 24.04.02 LTS

 

# copy & paste 활성화
sudo apt install open-vm-tools open-vm-tools-desktop -y

#재부팅!

# clion 설치
sudo snap install clion --classic

# libbpf 관련 설치
cd ~
sudo passwd root
su
apt install clang clang-tools git libelf-dev make gcc llvm pkg-config libcap-dev libbfd-dev cmake
git clone --recurse-submodules https://github.com/libbpf/libbpf
git clone --recurse-submodules https://github.com/libbpf/bpftool
cd libbpf/src
make install
cd ~/bpftool/src
make install

'Linux > Dev' 카테고리의 다른 글

[가이드] Self-Hosted Sentry 설치 + cpp + 콜스택 추적 예제  (0) 2025.08.12

 

  • 함수가 배열 또는 컨테이너(예: std::vector)의 뷰(view) 만을 필요로 할 때.
  • 함수가 읽기 전용 또는 수정 가능한 시퀀스를 받아야 할 때.
  • 함수가 컨테이너의 타입에 독립적이어야 할 때 (std::vector, std::array, C-style 배열 모두 수용).

 

✅ 예제 시나리오: 버퍼를 받아 총합 계산

✅ std::span 사용 버전 (깔끔, 안전, 범용)

#include <iostream>
#include <vector>
#include <array>
#include <span>

int sum(std::span<const int> data) {
    int total = 0;
    for (int value : data) {
        total += value;
    }
    return total;
}

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    std::array<int, 5> arr = {1, 2, 3, 4, 5};
    int c_array[] = {1, 2, 3, 4, 5};

    std::cout << sum(vec) << "\n";      // OK
    std::cout << sum(arr) << "\n";      // OK
    std::cout << sum(c_array) << "\n";  // OK

    return 0;
}

❌ std::span 없이 타입별 오버로드 버전 (지저분하고 유지보수 어려움)

#include <iostream>
#include <vector>
#include <array>

int sum_vector(const std::vector<int>& data) {
    int total = 0;
    for (int value : data) {
        total += value;
    }
    return total;
}

int sum_array(const std::array<int, 5>& data) {
    int total = 0;
    for (int value : data) {
        total += value;
    }
    return total;
}

int sum_c_array(const int* data, size_t size) {
    int total = 0;
    for (size_t i = 0; i < size; ++i) {
        total += data[i];
    }
    return total;
}

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    std::array<int, 5> arr = {1, 2, 3, 4, 5};
    int c_array[] = {1, 2, 3, 4, 5};

    std::cout << sum_vector(vec) << "\n";             // OK
    std::cout << sum_array(arr) << "\n";              // OK
    std::cout << sum_c_array(c_array, 5) << "\n";     // OK

    return 0;
}

'Language > C++' 카테고리의 다른 글

[poco] 로그 예제  (0) 2025.07.22
[C++] 함수 const 선언 정리  (0) 2024.09.12

다수의 제어기가 신뢰할 수 있는 CA를 기반으로 암호화 된 메시지를 주고 받을 수 있도록 설계

1. CA 키 세러머니 (secp256r1)
2. 제어기 1, 2는 EC 키 쌍 생성 (secp256r1)
3. TEE 스토리지에 개인키 저장
4. 제어기 1, 2는 CSR 생성 (OID, 기기명 포함) 후 CA에 전송
5. CA에서 CSR 서명하여 각 제어기에 인증서 발급
6. 제어기 1,2에 CA 및 제어기 인증서를 하드 디스크에 저장
7. 제어기 1,2는 CA에 CRL 목록 요청 후 하드 디스크에 저장

제어기 1 Side
8. 제어기 2로 전송할 평문 생성
9. EC 임시키 생성 (secp256r1) : 1회 사용 후 폐기 (ECDHE 연산에만 사용하고, 그 결과로 세션키(HKDF)를 도출하는 용도)
10. TEE내 안전 저장소에서 개인키 로드 (2번에서 생성)
11. HKDF 인자(랜덤 salt, info(제어기1➜제어기2)) 생성 : 1회용 세션 설정을 위함.
12. HKDF 인자, 제어기1 인증서, 제어기1 임시공개키를 개인키(2번에서 생성)로 서명(SHA256withECDSA)
13. 제어기 1, 2간 세션(소켓) 생성
14. HKDF 인자, 제어기 1 인증서, 임시 공개키, 12번 값을 제어기2에 전송

제어기 2 Side
15. CA 공개키로 제어기 1의 인증서 검증 (검증 실패하면 에러 처리)
16. CRL 확인하여 폐기 여부 검사 (검사 실패하면 에러 처리)
17. 인증서 용도 확인(oid 및 인증 용도)
18. 제어기1 인증서(공개키)로 데이터 서명값 검증 (SHA256withECDSA) (검증 실패하면 에러 처리)
19. EC 임시키 생성 (secp256r1)
20. TEE내 안전 저장소에서 개인키 로드 (2번에서 생성)
21. 제어기2 인증서, 제어기2 임시공개키를 개인키(2번에서 생성) 로 서명 (SHA256withECDSA)
22. 제어기1의 임시 공개키와 제어기2의 임시 개인키로 ECDHE 공유키 유도 
23. 수신한 salt, info 및 공유키를 사용하여 HKDF(HMAC-based Key Derivation Function) 세션키 유도
24. 제어기 2 인증서, 임시 공개키, 21번 값을 제어기1에 전송

제어기 1 Side
25. CA 공개키로 제어기 2의 인증서 검증 (검증 실패하면 에러 처리)
26. CRL 확인하여 폐기 여부 검사 (검사 실패하면 에러 처리)
27. 제어기2 인증서(공개키)로 데이터 서명값 검증 (SHA256withECDSA) (검증 실패하면 에러 처리)
28. 제어기2 의 임시 공개키와 제어기1의 임시 개인키로 ECDHE 공유키 유도 
29. salt, info 및 공유키를 사용하여 HKDF 세션키 유도
30. 제어기2에 전송할 랜덤 IV, AAD(제어기1 기기명, timestamp, 시퀀스(리플레이 공격 대비)) 생성
31. HKDF 세션키로 평문을 AES-GCM 암호화
32. iv, aad, tag, 암호문을 개인키로 서명 (SHA256withECDSA)
33. iv, aad, tag, 암호문, 32번 을 제어기2에 전송

제어기 2 Side
34 제어기1 인증서(공개키)로 데이터 서명값 검증 (SHA256withECDSA) (검증 실패하면 에러 처리)
35. aad 내 timestamp 검증 (10초 이내면 통과)
36. aad내 시퀀스 검증 (최근 수신된 aad의 시퀀스를 확인후, 그 다음으로 예상되는 시퀀스값이 아니면 replay 공격으로 간주)
37. AAD내 기기명과 제어기1 인증서 확장필드의 기기명이 일치하는지 확인
38. HKDF 세션키로 AES-GCM 복호화 (iv, aad, tag 사용)
39. 제어기1, 2 간 세션(소켓) 해제

목표 : github CI에 AI SAST 도구인 CodeRabbit을 통합하여 취약점을 관리하도록 함. SonarCloud와는 다르게 Pull Request만 리뷰 가능함. (2주 무료)

CodeRabbit 설정

1. https://www.coderabbit.ai/

2. Get a free trial

3. Login with GitHub

4. Add Repositories

5. repo Settting에서 Review Language 변경

GitHub 설정

6. repo 루트에 .coderabbit.yaml 생성

language: "ko-KR"
early_access: false
reviews:
  profile: "chill"
  request_changes_workflow: false
  high_level_summary: true
  poem: true
  review_status: true
  collapse_walkthrough: false
  auto_review:
    enabled: true
    drafts: false
chat:
  auto_reply: true

7. 코드 수정 후 Pull Request

8. 리뷰 참조 : https://github.com/codetronik/aabbcc/pull/3

'devSecOps' 카테고리의 다른 글

[GitHub] SonarCloud 통합  (0) 2025.04.07
[GitHub] 기본 CI 구축  (0) 2025.04.07

목표 : github CI에 SAST 도구인 SonarCloud을 통합하여 취약점을 관리하도록 함

SonarCloud 설정

1. https://sonarcloud.io/

2. GitHub / Birbucket / GitLab 등을 선택할 수 있다. GitHub 선택

3. Import an organization 선택 

4. 적용을 원하는 repo 선택 후 Install & Authorize

5. 키와 Organization 키 설정 후, 요금 플랜 선택 후 Create Organization 선택

6. 분석을 원하는 repo 선택 후 Set Up 선택

7. 새 코드 범위 설정 후 Create project 선택

Previous Version : 커밋 후 변경된 모든 코드를 새코드로 간주

Number of days : 지난 x일 동안 변경된 모든 코드는 새코드로 간주

8. Information에서 Project Key와 Organization Key 확인

이 키는 GitHub가 SonarCloud에 접근할 때 사용 됨

9. Administration -> Analysis Method -> Automatic Analysis 해제

9. My Account -> Security -> 토큰 이름 지정 후 Generate Token 선택

이 토큰은 GitHub가 SonarCloud에 접근할 때 사용 됨

GitHub 설정 (예제가 궁금하다면 https://github.com/codetronik/KeyStoreExample 참조)

1. Settings -> Secrets and variables -> Actions -> New repository secret  선택

Name엔 SONAR_TOKEN, Secret엔 9번에서 생성한 토큰 입력

2. build.gradle.kts 수정

plugins {
	alias(libs.plugins.android.application) apply false
	alias(libs.plugins.kotlin.android) apply false
	id("org.sonarqube") version "4.4.1.3373" // 추가!!
}

3. yml 수정

name: Android Build with SonarCloud

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    name: Build Debug APK & Analyze with SonarCloud
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v4

    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        distribution: 'temurin'
        java-version: '17'
        cache: gradle

    - name: Set up Android SDK
      uses: android-actions/setup-android@v3

    - name: Grant execute permission for Gradle
      run: chmod +x ./gradlew

    - name: Run SonarCloud analysis
      env:
        SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
      run: |
        ./gradlew sonar \
          -Dsonar.projectKey=8번에서 확인한 키 \
          -Dsonar.organization=8번에서 확인한 키 \
          -Dsonar.host.url=https://sonarcloud.io \
          -Dsonar.login=${SONAR_TOKEN}
          
    - name: Build Debug APK
      run: ./gradlew assembleDebug

    - name: Upload Debug APK
      uses: actions/upload-artifact@v4
      with:
        name: debug-apk
        path: app/build/outputs/apk/debug/app-debug.apk

4. 빌드 완료 후, 분석 결과를 SonarCloud  에서 확인 가능

시큐리티 failed 발생

내용을 확인하면, 자격 증명(pin / 패턴 등) 없이 키스토어에 접근이 가능하다고 함.

'devSecOps' 카테고리의 다른 글

[GitHub] CodeRabbit 통합  (0) 2025.04.07
[GitHub] 기본 CI 구축  (0) 2025.04.07

목표 : 기존 github repo에 CI 구축

1. repo에서 Actions 선택

2. CI설정이 안되어 있다면, Suggested for this repository가 보일 것이다. Simple workflow -> Configure 선택

3. 기존 내용은 지우고, 아래와 같이 입력

name: Android Build (Debug APK)

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    name: Build Debug APK
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v4

    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        distribution: 'temurin'
        java-version: '17'
        cache: gradle

    - name: Set up Android SDK
      uses: android-actions/setup-android@v3

    - name: Grant execute permission for Gradle
      run: chmod +x ./gradlew

    - name: Build Debug APK
      run: ./gradlew assembleDebug

    - name: Upload Debug APK
      uses: actions/upload-artifact@v4
      with:
        name: debug-apk
        path: app/build/outputs/apk/debug/app-debug.apk

4. 빌드가 진행되는 것을 확인할 수 있다.

'devSecOps' 카테고리의 다른 글

[GitHub] CodeRabbit 통합  (0) 2025.04.07
[GitHub] SonarCloud 통합  (0) 2025.04.07

+ Recent posts