domain

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// ExecutionModeStackIntegrated 는 스택의 컴포넌트가 실행을 맡는 일반 경로다.
	// CI 플랫폼이 빌드해 이미지 레지스트리에 올리고, CD 도구가 클러스터에 반영한다.
	ExecutionModeStackIntegrated = "stack_integrated"
	// ExecutionModeEmergencyDirect 는 스택 컴포넌트를 쓸 수 없을 때 플랫폼이
	// 직접 빌드·배포하는 장애 대응 경로다.
	ExecutionModeEmergencyDirect = "emergency_direct"
)

실행 모드. 어느 쪽이 이미지를 만들고 클러스터에 반영하는지를 가른다.

자세한 설계는 docs/20_아키텍처/Stack_CICD_통합모드_설계.md 와 Stack_CICD_긴급모드_설계.md 에 있다.

View Source
const MaxStoredSecretFindings = 200

MaxStoredSecretFindings 는 결과 하나에 남기는 탐지 위치의 상한이다. 건수(FindingsCount)와 규칙별 건수는 자르지 않는다 — 오탐 규칙 하나가 수천 건을 내도 행이 커지지 않게 위치만 자른다.

View Source
const SecretScanSkippedReport = `{"nullus_skipped":"policy_off"}`

SecretScanSkippedReport 는 스택 정책이 시크릿 탐지를 끈 실행이 남기는 리포트다. 탐지 없음([])과 구별해야 한다 — 같은 [] 를 남기면 나중에 정책을 켠 뒤의 동기화가 그 실행을 "통과" 로 기록한다. 산출물 업로드가 실패하지 않도록 파일은 남긴다. 스캐폴딩(scaffold/secret_scan.go)이 같은 값을 쓴다.

View Source
const StaleDBAge = shareddomain.StaleDBAge

StaleDBAge 는 취약점 DB 를 낡았다고 보는 나이다 (설계 §6.4).

Variables

View Source
var ErrDeploymentNotFound = fmt.Errorf("deployment not found")

ErrDeploymentNotFound is returned when a deployment cannot be found.

View Source
var ErrGoldenPathAlreadyExists = fmt.Errorf("cicd golden path already exists")

ErrGoldenPathAlreadyExists 는 같은 ID 의 골든패스가 이미 있을 때 돌아온다.

View Source
var ErrGoldenPathInvalid = fmt.Errorf("cicd golden path invalid")

ErrGoldenPathInvalid 는 골든패스가 저장 규칙을 어길 때 돌아온다. 어느 필드인지는 감싼 메시지에 있다.

View Source
var ErrGoldenPathNotFound = fmt.Errorf("cicd golden path not found")

ErrGoldenPathNotFound 는 CI/CD 골든패스를 찾을 수 없을 때 돌아온다.

View Source
var ErrInvalidScanPolicy = errors.New("스캔 정책이 올바르지 않습니다")

ErrInvalidScanPolicy 는 정책 값이 허용 범위를 벗어났을 때의 오류다.

View Source
var ErrPipelineNotFound = fmt.Errorf("pipeline not found")

ErrPipelineNotFound is returned when a pipeline cannot be found.

View Source
var ErrStackClusterMismatch = errors.New("pipeline cluster must be the stack's cluster")

ErrStackClusterMismatch 는 스택에 묶인 앱에 스택과 다른 클러스터를 준 경우다. 스택의 CD 도구(Argo CD)는 자기 클러스터에만 배포하므로, 다른 클러스터는 배포 대상이 될 수 없다.

View Source
var ErrTemplateAlreadyExists = fmt.Errorf("pipeline template already exists")

ErrTemplateAlreadyExists 는 같은 ID 의 템플릿이 이미 있을 때 돌아온다.

View Source
var ErrTemplateInvalid = fmt.Errorf("pipeline template invalid")

ErrTemplateInvalid 는 템플릿이 저장 규칙을 어길 때 돌아온다. 어느 필드인지는 감싼 메시지에 있다.

View Source
var ErrTemplateNotFound = fmt.Errorf("pipeline template not found")

ErrTemplateNotFound is returned when a pipeline template cannot be found.

Functions

func AppAccessURL

func AppAccessURL(appName, accessDomain string) string

AppAccessURL 은 배포된 앱의 외부 접속 주소다.

스캐폴딩이 만드는 HTTPRoute 의 hostname 과 같은 규칙에서 나온다 (scaffold/renderer.go 의 renderHTTPRoute: `<앱>.<도메인>`). 화면이 보여 주는 주소를 따로 적으면 한쪽이 바뀔 때 다른 쪽이 거짓말을 한다.

스택에 접근 도메인이 없으면 앱은 클러스터 안에서만 닿는다. 그때는 빈 값을 돌려준다 — 없는 주소를 지어내면 사용자는 열리지 않는 링크를 계속 누른다.

func DependencyScanResultID added in v0.6.0

func DependencyScanResultID(deploymentID string) string

DependencyScanResultID 는 실행 하나에 대응하는 의존성 스캔 결과 ID 다. 같은 실행을 다시 동기화해도 기록이 늘지 않는다.

func IsDBStale added in v0.6.0

func IsDBStale(updatedAt *time.Time, now time.Time) bool

IsDBStale 은 취약점 DB 가 낡았는지 본다. 시각을 모르면 낡은 것으로 본다.

func MatchStackCluster added in v0.6.0

func MatchStackCluster(stackClusterID, requested string) (string, error)

MatchStackCluster 는 스택에 묶인 앱의 클러스터를 스택 클러스터와 맞춘다.

요청이 비어 있으면 스택 클러스터로 채우고, 다르면 ErrStackClusterMismatch 로 거절한다 — 조용히 바꾸면 요청한 쪽이 고른 클러스터가 거짓이 된다. 스택 클러스터를 모르면 요청을 그대로 둔다.

func SASTDashboardURL added in v0.6.0

func SASTDashboardURL(webBase, projectKey, reported string) string

SASTDashboardURL 은 사람이 열 SonarQube 프로젝트 화면 주소다.

스캐너가 리포트에 남기는 주소는 스캐너가 붙은 서버 주소(클러스터 내 서비스)라 브라우저에서 열리지 않는다 — 서버의 공개 주소 설정(sonar.core.serverBaseURL)이 있어도 그렇다(실측). 스택의 공개 주소(webBase)를 알면 그것으로 만들고, 모르면 리포트 주소를 쓰되 클러스터 안 주소는 버린다. 죽은 링크보다 없는 편이 낫다.

func SASTResultID added in v0.6.0

func SASTResultID(deploymentID string) string

SASTResultID 는 실행 하나에 대응하는 분석 결과 ID 다. 같은 실행을 다시 동기화해도 기록이 늘지 않는다.

func SecretScanResultID added in v0.6.0

func SecretScanResultID(deploymentID string) string

SecretScanResultID 는 실행 하나에 대응하는 시크릿 탐지 결과 ID 다.

Types

type AppType

type AppType string

AppType represents the application type for a pipeline.

const (
	AppTypeWeb     AppType = "web"
	AppTypeBackend AppType = "backend"
	AppTypeBatch   AppType = "batch"
)

func (AppType) IsValid added in v0.6.0

func (a AppType) IsValid() bool

IsValid 는 파이프라인이 받는 세 종류 중 하나인지 본다. pipelines.app_type 이 이 세 값의 ENUM 이라 템플릿에 다른 값이 들어가면 그 템플릿으로 만드는 파이프라인이 DB 에서 거부된다.

type BuildProfile added in v0.6.0

type BuildProfile string

BuildProfile 은 가져온 원본을 어떻게 빌드하고 띄울지다.

원본 Dockerfile 을 그대로 쓸지, 플랫폼이 Dockerfile 을 대신 쓸지, 배포 매니페스트에 어떤 헬스 체크와 자원을 둘지를 한 이름으로 묶는다. 이름별 실제 값은 스캐폴딩 (adapter/scaffold)이 가진다 — 매니페스트 모양은 거기서 정한다.

const (
	// BuildProfileRepository 는 원본 Dockerfile 을 그대로 쓰고 배포 설정은 기본값이다.
	BuildProfileRepository BuildProfile = ""
	// BuildProfileSpringBoot 는 원본 Dockerfile 을 쓰고, 없으면 플랫폼이 쓴다(Maven 으로 실행 jar →
	// JRE). JVM 에 맞춘 자원과 헬스 체크를 둔다. eGov 부트 샘플 v5.0.0 에는 Dockerfile 이 없다.
	BuildProfileSpringBoot BuildProfile = "spring-boot"
	// BuildProfileMavenWAR 는 플랫폼이 Dockerfile 을 쓴다(Maven 빌드 → Tomcat ROOT.war).
	// 미리 빌드한 WAR 를 복사하는 원본 Dockerfile 은 CI 의 `docker build .` 로 돌지 않는다.
	BuildProfileMavenWAR BuildProfile = "maven-war"
)

func (BuildProfile) GeneratesDockerfile added in v0.6.0

func (p BuildProfile) GeneratesDockerfile() bool

GeneratesDockerfile 은 원본에 Dockerfile 이 없을 때 플랫폼이 만들 수 있는지다.

func (BuildProfile) IsValid added in v0.6.0

func (p BuildProfile) IsValid() bool

IsValid 는 아는 프로필인지 본다.

func (BuildProfile) ReplacesDockerfile added in v0.6.0

func (p BuildProfile) ReplacesDockerfile() bool

ReplacesDockerfile 은 원본에 Dockerfile 이 있어도 플랫폼 것으로 바꾸는지다.

type CICDGoldenPath

type CICDGoldenPath struct {
	ID                   string     `json:"id"`
	Name                 string     `json:"name"`
	Description          string     `json:"description"`
	Tools                []CICDTool `json:"tools"`
	EstimatedInstallTime int        `json:"estimated_install_time"` // in minutes
	RecommendedUseCase   string     `json:"recommended_use_case"`
	MinResources         string     `json:"min_resources"`
	CreatedAt            time.Time  `json:"created_at"`
}

CICDGoldenPath represents a verified CI/CD tool combination (Golden Path).

type CICDTool

type CICDTool struct {
	Category    string `json:"category"` // ci_platform, cd_tool, monitoring, etc.
	Name        string `json:"name"`     // GitLab CI, ArgoCD, Prometheus, etc.
	HelmVersion string `json:"helm_version"`
	AppVersion  string `json:"app_version"`
}

CICDTool represents a tool in the CI/CD stack.

type DependencyScanResult added in v0.6.0

type DependencyScanResult struct {
	ID           string `json:"id"`
	PipelineID   string `json:"pipeline_id"`
	DeploymentID string `json:"deployment_id"`

	Scanner        string     `json:"scanner"`
	ScannerVersion string     `json:"scanner_version,omitempty"`
	DBUpdatedAt    *time.Time `json:"db_updated_at,omitempty"`

	// Counts 는 리포트를 읽었을 때만 있다. nil 은 "모름" 이다 — 0 으로 채우면 "취약점 0건" 으로 읽힌다.
	// 스택 정책의 ignore_unfixed 를 따른다(판정이 본 숫자와 같아야 한다).
	Counts *SeverityCounts `json:"counts,omitempty"`
	// Targets 는 검사한 락파일 수(리포트의 Results 수)다. nil 은 모름, 0 은 검사할 것이 없었다는 뜻이다 —
	// 스캐폴딩은 락파일을 만들지 않아 "0 개 검사 · 통과" 가 흔하다(#79 §1). 통과와 가른다.
	Targets *int `json:"targets,omitempty"`

	GateResult GateResult `json:"gate_result"`
	ReportURI  string     `json:"report_uri,omitempty"`
	ScannedAt  time.Time  `json:"scanned_at"`

	// ReportRef 는 CI 리포트를 다시 읽을 위치다. 화면에는 내보내지 않는다.
	ReportRef *ScanReportRef `json:"-"`
}

DependencyScanResult 는 실행 하나의 의존성 취약점 스캔(SCA, trivy fs) 결과 요약이다 (nullus-plan#79, Security Dashboard 설계 §8 G1).

이미지 스캔과 같은 틀이다 — 요약 + 판정 + 원본 위치만 둔다. 원본 리포트는 CI 산출물로만 남는다.

type DeployStep

type DeployStep struct {
	Name      string   `json:"name"`
	Status    string   `json:"status"`
	Kind      string   `json:"kind"`
	Message   string   `json:"message,omitempty"`
	AppliedAt string   `json:"applied_at,omitempty"`
	Logs      []string `json:"logs,omitempty"`
}

DeployStep tracks progress of a single resource application.

type Deployment

type Deployment struct {
	ID          string           `json:"id"`
	PipelineID  string           `json:"pipeline_id"`
	Version     string           `json:"version"`
	Status      DeploymentStatus `json:"status"`
	Steps       []DeployStep     `json:"steps,omitempty"`
	StartedAt   time.Time        `json:"started_at"`
	CompletedAt *time.Time       `json:"completed_at,omitempty"`
	DeployedBy  string           `json:"deployed_by"`
}

Deployment represents a single deployment run of a pipeline.

type DeploymentStatus

type DeploymentStatus string

DeploymentStatus represents the status of a deployment run.

const (
	DeploymentStatusPending    DeploymentStatus = "pending"
	DeploymentStatusRunning    DeploymentStatus = "running"
	DeploymentStatusSuccess    DeploymentStatus = "success"
	DeploymentStatusFailed     DeploymentStatus = "failed"
	DeploymentStatusRolledBack DeploymentStatus = "rolled_back"
)

type GateResult added in v0.6.0

type GateResult string

GateResult 는 이미지 스캔 게이트의 판정이다.

const (
	GateResultPass  GateResult = "pass"
	GateResultWarn  GateResult = "warn"
	GateResultBlock GateResult = "block"
	// GateResultError 는 판정할 수 없었다는 뜻이다(스캐너 도달 불가, 리포트 없음).
	//
	// 통과와 뭉치지 않는다 — 스캔이 못 돈 것과 취약점이 없는 것은 다르다.
	// 뭉치면 스캐너가 죽은 동안 모든 배포가 초록불로 지나간다.
	GateResultError GateResult = "error"
)

func EvaluateGate added in v0.6.0

func EvaluateGate(s *TrivyReportSummary, policy ScanPolicy) GateResult

EvaluateGate 는 요약을 정책으로 판정한다.

리포트가 없으면 error 다 — 통과로 뭉치지 않는다.

func GateFromStageAndReport added in v0.6.0

func GateFromStageAndReport(stageStatus string, report *TrivyReportSummary, policy ScanPolicy) (GateResult, bool)

GateFromStageAndReport 는 스캔 단계 결과와 리포트로 판정한다.

단계 결과만으로는 "막혔다" 와 "스캔이 못 돌았다" 를 가를 수 없다 — Trivy 는 서버에 닿지 못해도 게이트와 같은 exit 1 로 끝난다. 리포트가 차단 사유를 담고 있을 때만 차단이다.

report 가 nil 이면 리포트를 모른다는 뜻이다(읽지 못함, 산출물 조회 미배선). 그때는 단계 결과를 따른다. 끝나지 않은 단계는 판정하지 않는다.

func GateResultFromStageStatus added in v0.6.0

func GateResultFromStageStatus(status string) (GateResult, bool)

GateResultFromStageStatus 는 리포트 없이 CI 단계 상태만으로 판정을 남긴다.

스캔 단계는 --exit-code 1 로 차단하므로 성공이면 통과, 실패면 차단이다. 그 밖의 상태(실행 중·대기·건너뜀·모름)는 판정하지 않는다 — 도는 중인 것을 통과로 적으면 안 된다.

func GateWhenReportMissing added in v0.6.0

func GateWhenReportMissing(stageStatus string) (GateResult, bool)

GateWhenReportMissing 은 리포트가 확실히 없을 때의 판정이다.

스캔 명령은 리포트부터 쓴다. 리포트가 없으면 스캔을 수행하지 못한 것이다.

  • 실패: 스캐너에 닿지 못해 멈췄다 — 차단으로 세면 스캐너 장애가 "취약한 배포" 로 보인다.
  • 성공: 스캐너 장애를 허용(allow)한 정책이 통과시켰다 — 통과로 적으면 스캔하지 않은 이미지가 "통과" 로 보인다.

어느 쪽이든 스캔했다는 근거가 없으므로 error 다.

func SASTGateFromStageAndReport added in v0.6.0

func SASTGateFromStageAndReport(stageStatus string, r *SASTReport) (GateResult, bool)

SASTGateFromStageAndReport 는 분석 단계 결과와 리포트로 판정한다.

단계 결과에는 스택 정책이 이미 반영돼 있다 — 경고 정책이면 게이트에 걸려도 성공, 장애 허용 정책이면 분석을 못 해도 성공이다. 그래서 단계 결과만으로는 셋을 가를 수 없고, 리포트의 스캐너 종료 코드가 "게이트에 걸렸다" 와 "분석을 못 했다" 를 가른다.

리포트가 없으면 판정하지 않는다. 리포트를 남기기 전에 만든 파이프라인의 실패를 차단으로 적으면, 분석기 장애가 "보안 문제로 막힌 배포" 로 보인다.

func SecretScanGate added in v0.6.0

func SecretScanGate(stageStatus string, findings *int, policy ScanPolicy) (GateResult, bool)

SecretScanGate 는 시크릿 탐지 단계 결과와 탐지 건수로 판정한다(설계 §8 G2 표).

gitleaks 리포트에는 종료 코드가 없어 추론한다. 스크립트(scaffold/secret_scan.go)는 탐지 시 정책에 따라 차단(exit 1)·경고(exit 0)하고, 스캔 자체를 못 하면 장애 정책을 따른다.

리포트 없음(findings nil) · 끝남 → error  — 스캔했다는 근거가 없다(GateWhenReportMissing 과 같다)
탐지 > 0 · 실패             → block
탐지 > 0 · 성공             → warn   — 경고 정책이 통과시켰다
탐지 0  · 성공             → pass
탐지 0  · 실패             → error  — 탐지 없이 실패했다. 스캔이 실패한 것이다
스택 정책 off              → 기록하지 않는다(대시보드의 "미적용")

끝나지 않은 단계(실행 중·대기·취소·건너뜀)는 판정하지 않는다.

type ImageScanResult added in v0.6.0

type ImageScanResult struct {
	ID           string `json:"id"`
	PipelineID   string `json:"pipeline_id"`
	DeploymentID string `json:"deployment_id,omitempty"`

	ImageRepository string `json:"image_repository,omitempty"`
	ImageTag        string `json:"image_tag,omitempty"`
	// ImageDigest 에 결과를 붙인다 — 태그는 움직인다.
	ImageDigest string `json:"image_digest,omitempty"`

	ScanSource     string     `json:"scan_source"`
	Scanner        string     `json:"scanner"`
	ScannerVersion string     `json:"scanner_version,omitempty"`
	DBUpdatedAt    *time.Time `json:"db_updated_at,omitempty"`

	// Counts 는 리포트를 읽었을 때만 있다. nil 은 "모름" 이다 —
	// 0 으로 채우면 "취약점 0건" 으로 읽힌다.
	Counts *SeverityCounts `json:"counts,omitempty"`

	GateResult GateResult `json:"gate_result"`
	ReportURI  string     `json:"report_uri,omitempty"`
	ScannedAt  time.Time  `json:"scanned_at"`

	// ReportRef 는 CI 리포트를 다시 읽을 위치다. 취약점 목록은 볼 때 리포트를 다시
	// 내려받아 만든다(원본은 DB 에 넣지 않는다, 설계 §8). 화면에는 내보내지 않는다.
	ReportRef *ScanReportRef `json:"-"`
}

ImageScanResult 는 이미지 하나에 대한 스캔 결과 기록이다.

type Pipeline

type Pipeline struct {
	ID             string            `json:"id"`
	Name           string            `json:"name"`
	ExecutionMode  string            `json:"execution_mode,omitempty"`
	TemplateID     string            `json:"template_id"`
	OrgID          string            `json:"org_id"`
	ClusterID      string            `json:"cluster_id"`
	StackID        string            `json:"stack_id,omitempty"`
	Namespace      string            `json:"namespace"`
	AppType        AppType           `json:"app_type"`
	GitRepoURL     string            `json:"git_repo_url"`
	DockerfilePath string            `json:"dockerfile_path,omitempty"`
	DockerContext  string            `json:"docker_context,omitempty"`
	EnvVars        map[string]string `json:"env_vars,omitempty"`
	Status         PipelineStatus    `json:"status"`
	CreatedAt      time.Time         `json:"created_at"`
	// Stages 는 이 파이프라인이 실제로 가진 단계다 (예: Build · ImageScan · Deploy).
	//
	// 템플릿의 stages 와 따로 둔다 — 이미지 스캔 같은 선택 단계는 파이프라인
	// 단위로 켜고 끈다. 템플릿에만 두면 끈 파이프라인이 돌지도 않은 단계를
	// 보여준다(마이그레이션 000070). 비어 있으면 모른다는 뜻이고, 화면은
	// 템플릿으로 떨어진다 — 이 칸이 생기기 전에 만든 파이프라인이 그렇다.
	Stages []string `json:"stages,omitempty"`
	// Source 는 이 파이프라인의 저장소가 처음 가져온 원본이다. 원본을 가져오지 않았으면 nil 이다.
	//
	// 템플릿의 원본 커밋은 시간이 지나면 올라간다. 저장소가 어느 버전에서 시작했는지는
	// 여기에만 남는다.
	Source *TemplateSource `json:"source,omitempty"`
}

Pipeline represents a CI/CD pipeline configuration.

func (*Pipeline) DelegatesBuildToRunner

func (p *Pipeline) DelegatesBuildToRunner() bool

DelegatesBuildToRunner 는 실행을 스택의 CI 러너가 맡는지다.

플랫폼이 직접 빌드·적용하는 경로는 API 서버가 host 에서 돌던 시절에 만들어졌다. 지금 API 는 파드 안에서 돌고 그 안에는 도커 데몬이 없다 — 직접 빌드는 성공할 수 없는 경로다. 스택에 묶인 파이프라인의 실행은 스택의 CI 플랫폼이 맡는다(통합모드 설계 3.2: "Nullus API 서버가 정상 실행 과정에서 직접 git clone, docker build, kind load, kubectl apply 를 수행하지 않는다").

Dockerfile 경로가 비어 있어도 마찬가지다. 스택에 묶였는데 플랫폼이 매니페스트를 직접 적용하면 CD 도구가 동기화하는 같은 리소스를 서로 덮어쓴다 — API 로 Dockerfile 경로 없이 만든 파이프라인이 그 경로로 새고 있었다. 긴급모드만 예외다.

func (*Pipeline) DeployClusterID added in v0.6.0

func (p *Pipeline) DeployClusterID(stackClusterID string) string

DeployClusterID 는 파이프라인의 앱이 실제로 서 있는 클러스터다. stackClusterID 는 묶인 스택의 클러스터이고, 모르면 빈 값이다.

스택에 묶인 파이프라인의 앱은 스택의 CD 도구가 올린다. Argo CD 의 Application 은 자기 클러스터(kubernetes.default.svc)를 향하고 Application 도 스택 클러스터에 적용되므로, 앱은 스택 클러스터에 선다 — 파이프라인에 어느 클러스터가 적혀 있든. 생성이 스택 클러스터만 받기 전에 만든 파이프라인에는 화면에서 고른 클러스터가 남아 있다.

플랫폼이 직접 적용한 경로(스택 없음·긴급 직접 배포)는 파이프라인의 클러스터에 올렸으니 그 값을 그대로 쓴다. 스택 클러스터를 모를 때도 저장된 값이 가장 나은 추정이다.

type PipelineSecurityList added in v0.6.0

type PipelineSecurityList struct {
	Pipelines []*PipelineSecuritySnapshot
	// Truncated 는 상한에 닿아 최근 만든 것부터 잘랐다는 뜻이다.
	Truncated bool
}

PipelineSecurityList 는 조직 파이프라인의 단계별 최신 보안 결과다.

type PipelineSecuritySnapshot added in v0.6.0

type PipelineSecuritySnapshot struct {
	PipelineID string
	Name       string
	StackID    string
	ClusterID  string
	// Stages 는 파이프라인이 실제로 가진 단계다. 비어 있으면 모른다(단계 기록 전의 파이프라인).
	Stages []string
	// HasSecretScan · HasDependencyScan · HasSAST · HasImageScan 은 Stages 에 그 보안 단계가 있는지다.
	// CI 마다 다른 표기(ImageScan · image-scan)를 단계 키로 맞춰 본 것이다. Stages 가 비면 모두 거짓이다.
	HasSecretScan     bool
	HasDependencyScan bool
	HasSAST           bool
	HasImageScan      bool

	// LatestRun 은 최근 실행이다. 실행이 없으면 nil 이다.
	LatestRun *RunSummary

	SecretScan     *SecretScanResult
	DependencyScan *DependencyScanResult
	SAST           *SASTResult
	ImageScan      *ImageScanResult

	// RunVersions 는 결과 행이 가리키는 실행의 표시 번호(#42)다. 키는 deployment_id 다.
	RunVersions map[string]string

	// SecretDetection 은 스택 정책의 시크릿 탐지 동작이다(정책 행이 없으면 기본값 block). 스택에 묶이지
	// 않은 파이프라인은 빈 값이다 — 정책이 없어 단계 유무로만 본다.
	SecretDetection SecretDetectionAction
}

PipelineSecuritySnapshot 은 파이프라인 하나의 단계별 최신 보안 결과다(Security Dashboard 설계 §5).

결과 테이블은 cicd 가 소유한다. 대시보드(관측 모듈)는 테이블을 직접 읽지 않고 이 모양으로 받는다. 셀은 단계마다 그 단계의 최신 기록이다 — 앞 단계가 막으면 뒤 단계는 돌지 않으므로 최신 실행 하나의 결과만 보면 지금 돌고 있는 이미지의 CRITICAL 이 사라진다(설계 §2.1). 없는 결과는 nil 이다.

type PipelineStatus

type PipelineStatus string

PipelineStatus represents the status of a pipeline.

const (
	PipelineStatusActive   PipelineStatus = "active"
	PipelineStatusInactive PipelineStatus = "inactive"
)

type PipelineTemplate

type PipelineTemplate struct {
	ID             string            `json:"id"`
	Name           string            `json:"name"`
	Description    string            `json:"description"`
	AppType        AppType           `json:"app_type"`
	Stages         []string          `json:"stages"`
	GitRepoURL     string            `json:"git_repo_url,omitempty"`
	DockerfilePath string            `json:"dockerfile_path,omitempty"`
	DockerContext  string            `json:"docker_context,omitempty"`
	EnvVars        map[string]string `json:"env_vars,omitempty"`
	CreatedBy      string            `json:"created_by,omitempty"`
	// Source 가 있으면 파이프라인을 만들 때 이 원본을 새 저장소로 가져온다.
	// 없으면 예전처럼 app_type 에 맞춘 스캐폴딩만 커밋한다.
	Source *TemplateSource `json:"source,omitempty"`
}

PipelineTemplate represents a reusable CI/CD pipeline template.

func (*PipelineTemplate) Validate added in v0.6.0

func (t *PipelineTemplate) Validate() error

Validate 는 템플릿을 저장할 수 있는 모양인지 본다. 어기면 ErrTemplateInvalid 를 감싼다.

type QualityGateStatus added in v0.6.0

type QualityGateStatus string

QualityGateStatus 는 SonarQube 가 낸 Quality Gate 판정이다.

const (
	QualityGateOK    QualityGateStatus = "OK"
	QualityGateError QualityGateStatus = "ERROR"
	// QualityGateNone 은 게이트가 걸리지 않은 프로젝트다.
	QualityGateNone QualityGateStatus = "NONE"
)

type RunSummary added in v0.6.0

type RunSummary struct {
	DeploymentID string
	Version      string
	Status       DeploymentStatus
	StartedAt    time.Time
}

RunSummary 는 실행 하나의 요약이다.

type SASTCondition added in v0.6.0

type SASTCondition struct {
	Metric     string `json:"metric"`
	Comparator string `json:"comparator,omitempty"`
	Threshold  string `json:"threshold,omitempty"`
	Actual     string `json:"actual,omitempty"`
	// Status 는 OK 또는 ERROR 다.
	Status string `json:"status"`
}

SASTCondition 은 Quality Gate 조건 하나의 평가 결과다.

type SASTGateAction added in v0.6.0

type SASTGateAction string

SASTGateAction 은 소스 정적 분석의 Quality Gate 가 실패했을 때의 동작이다.

const (
	// SASTGateBlock 은 멈춘다. 기본값이다 — 이미지 스캔과 같다.
	SASTGateBlock SASTGateAction = "block"
	// SASTGateWarn 은 실패를 기록만 하고 통과시킨다. Quality Gate 를 막 도입한 팀이
	// 기존 코드의 문제로 배포가 멈추지 않게 하는 길이다.
	SASTGateWarn SASTGateAction = "warn"
)

type SASTMetrics added in v0.6.0

type SASTMetrics struct {
	Bugs                   *int     `json:"bugs,omitempty"`
	Vulnerabilities        *int     `json:"vulnerabilities,omitempty"`
	CodeSmells             *int     `json:"code_smells,omitempty"`
	SecurityHotspots       *int     `json:"security_hotspots,omitempty"`
	Coverage               *float64 `json:"coverage,omitempty"`
	DuplicatedLinesDensity *float64 `json:"duplicated_lines_density,omitempty"`
	Ncloc                  *int     `json:"ncloc,omitempty"`
}

SASTMetrics 는 프로젝트 전체 지표다. 응답에 없는 지표는 nil 이다.

type SASTReport added in v0.6.0

type SASTReport struct {
	// ScannerExitCode 는 sonar-scanner 의 종료 코드다. 0 통과, 3 엔진 단계 실패(Quality Gate 실패
	// 또는 분석 실패), 그 밖은 엔진을 띄우지도 못한 실패(서버 장애·인증 실패)다(실측).
	ScannerExitCode int
	// CETaskID 는 분석을 서버에 올렸을 때 생기는 작업 ID 다. 3 이 Quality Gate 실패인지 분석 실패인지는
	// 이것으로 가른다 — 게이트 판정은 올린 분석에만 있다.
	CETaskID          string
	ProjectKey        string
	AnalysisID        string
	DashboardURL      string
	QualityGateStatus QualityGateStatus
	Conditions        []SASTCondition
	Metrics           *SASTMetrics
}

SASTReport 는 파이프라인 SAST 잡이 남긴 리포트를 읽은 것이다.

func ParseSASTReport added in v0.6.0

func ParseSASTReport(raw []byte) (*SASTReport, error)

ParseSASTReport 는 SAST 잡이 남긴 리포트를 읽는다.

quality_gate·measures 는 SonarQube 응답을 그대로 담은 것이다. 스캐너 종료 코드가 없으면 판정의 근거가 없어 형식 오류로 본다.

type SASTResult added in v0.6.0

type SASTResult struct {
	ID           string `json:"id"`
	PipelineID   string `json:"pipeline_id"`
	DeploymentID string `json:"deployment_id,omitempty"`

	ProjectKey string `json:"project_key,omitempty"`
	AnalysisID string `json:"analysis_id,omitempty"`

	// QualityGateStatus 는 SonarQube 의 판정이다. 분석하지 못했으면 비어 있다.
	QualityGateStatus QualityGateStatus `json:"quality_gate_status,omitempty"`
	// GateResult 는 파이프라인 관점의 판정이다 — 같은 Quality Gate 실패도 스택 정책에 따라
	// 차단·경고로 갈린다.
	GateResult GateResult      `json:"gate_result"`
	Conditions []SASTCondition `json:"conditions,omitempty"`
	// Metrics 는 분석했을 때만 있다. nil 은 "모름" 이다 — 0 으로 채우면 "문제 0건" 으로 읽힌다.
	Metrics *SASTMetrics `json:"metrics,omitempty"`

	DashboardURL string    `json:"dashboard_url,omitempty"`
	AnalyzedAt   time.Time `json:"analyzed_at"`
}

SASTResult 는 실행 하나의 소스 정적 분석 결과 요약이다.

이미지 스캔처럼 요약·판정·위치만 둔다 — 이슈 목록 원본은 SonarQube 가 갖는다 (이미지 스캔 설계 §8 과 같은 범위). DashboardURL 로 SonarQube 화면을 연다.

type ScanPolicy added in v0.6.0

type ScanPolicy struct {
	// BlockSeverity 이상의 취약점이 있으면 차단한다. 바로 아래 등급은 경고로 남긴다.
	BlockSeverity Severity `json:"block_severity"`
	// IgnoreUnfixed 가 참이면 수정본이 없는 취약점은 판정에서 뺀다.
	IgnoreUnfixed bool `json:"ignore_unfixed"`
	// OnScannerUnreachable 은 스캔을 수행하지 못했을 때의 동작이다. 소스 정적 분석을
	// 수행하지 못했을 때(SonarQube 장애·인증 실패)도 이 값을 따른다.
	OnScannerUnreachable UnreachableAction `json:"on_scanner_unreachable"`
	// SASTOnGateFailure 는 소스 정적 분석의 Quality Gate 가 실패했을 때의 동작이다.
	// 비어 있으면 차단이다(이 필드를 모르는 옛 클라이언트·저장 행).
	SASTOnGateFailure SASTGateAction `json:"sast_on_gate_failure"`
	// SecretDetection 은 시크릿 탐지 단계가 시크릿을 찾았을 때의 동작이다(block·warn·off).
	// 비어 있으면 차단이다.
	SecretDetection SecretDetectionAction `json:"secret_detection"`
}

ScanPolicy 는 스택 하나의 차단 기준이다.

스캐너가 스택마다 서고 장애 영향도 스택 하나로 막히므로 정책도 스택 단위다. 플랫폼이 CI 변수로 푸시하고, CI 가 그 값으로 스스로 판정한다.

func DefaultScanPolicy added in v0.6.0

func DefaultScanPolicy() ScanPolicy

DefaultScanPolicy 는 기본 차단 기준이다 (설계 §6).

CRITICAL 차단 · HIGH 경고 · 수정본 없는 것 제외 · 스캔 불가 시 차단. HIGH 까지 막으면 흔한 베이스 이미지로 첫 배포가 안 되고, 수정본 없는 CVE 로 막으면 사용자가 할 수 있는 일이 없다 — debian:11 은 CRITICAL 5건이 전부 unfixed 였다(실측).

func (ScanPolicy) SASTGateActionOrDefault added in v0.6.0

func (p ScanPolicy) SASTGateActionOrDefault() SASTGateAction

SASTGateActionOrDefault 는 비어 있으면 기본값(block)이다.

func (ScanPolicy) SecretDetectionOrDefault added in v0.6.0

func (p ScanPolicy) SecretDetectionOrDefault() SecretDetectionAction

SecretDetectionOrDefault 는 비어 있으면 기본값(block)이다 — 이 필드를 모르는 옛 클라이언트·저장 행.

func (ScanPolicy) TrivySeverities added in v0.6.0

func (p ScanPolicy) TrivySeverities() string

TrivySeverities 는 게이트 명령의 --severity 값이다.

Trivy 의 --severity 는 "이 등급만" 이다. "이 등급 이상" 을 뜻하려면 위 등급을 모두 적어야 한다 — HIGH 만 적으면 CRITICAL 이 통과한다.

func (ScanPolicy) UnreachableActionOrDefault added in v0.6.0

func (p ScanPolicy) UnreachableActionOrDefault() UnreachableAction

UnreachableActionOrDefault 는 비어 있으면 기본값(block)이다.

func (ScanPolicy) Validate added in v0.6.0

func (p ScanPolicy) Validate() error

Validate 는 저장·푸시 전에 정책 값을 확인한다.

모르는 값을 기본값으로 바꿔 받지 않는다. 오타(HIGHT)가 조용히 CRITICAL 로 바뀌면 운영자는 HIGH 를 막는 줄 알고 있게 된다.

type ScanReportRef added in v0.6.0

type ScanReportRef struct {
	JobName     string `json:"job_name"`
	Branch      string `json:"branch,omitempty"`
	BuildID     string `json:"build_id,omitempty"`
	BuildNumber int    `json:"build_number"`
	StageID     string `json:"stage_id,omitempty"`
	StageName   string `json:"stage_name,omitempty"`
	Artifact    string `json:"artifact,omitempty"`
	Path        string `json:"path"`
}

ScanReportRef 는 CI 가 남긴 스캔 리포트의 위치다.

CI 마다 산출물을 묶는 단위가 달라(GitLab 잡, GitHub 실행, Jenkins 빌드) 셋에 필요한 식별자를 모두 담는다.

type SecretDetectionAction added in v0.6.0

type SecretDetectionAction string

SecretDetectionAction 은 시크릿 탐지 단계(gitleaks)가 시크릿을 찾았을 때의 동작이다(nullus-plan#80).

이미지 스캔·SAST 와 달리 "끄기" 가 있다 — 스택에 설치하는 것이 없어 단계가 모든 파이프라인에 렌더되므로, 끄는 길은 정책이어야 한다. 끄면 단계는 돌되 바로 통과한다.

const (
	// SecretDetectionBlock 은 멈춘다. 기본값이다 — 시크릿이 든 소스로 이미지를 만들어 올리는 것부터 막는다.
	SecretDetectionBlock SecretDetectionAction = "block"
	// SecretDetectionWarn 은 기록만 남기고 통과시킨다. 이력에 남은 옛 시크릿을 정리하는 동안의 길이다 —
	// 탐지 메시지의 폐기·회전 안내는 그대로 나온다.
	SecretDetectionWarn SecretDetectionAction = "warn"
	// SecretDetectionOff 는 탐지를 건너뛴다. 조직이 다른 수단(SCM push protection)으로 막을 때.
	SecretDetectionOff SecretDetectionAction = "off"
)

type SecretFinding added in v0.6.0

type SecretFinding struct {
	RuleID    string `json:"rule_id"`
	File      string `json:"file"`
	StartLine int    `json:"start_line"`
	// Commit 은 이력 검사(gitleaks git)일 때만 있다. 작업 트리 검사(gitleaks dir)는 커밋을 모른다.
	Commit      string `json:"commit,omitempty"`
	Fingerprint string `json:"fingerprint"`
}

SecretFinding 은 탐지 하나의 위치다. 비밀값(gitleaks 의 Secret · Match)은 필드로 두지 않는다 — 둘 자리가 없으면 실수로라도 저장되지 않는다.

type SecretRuleCount added in v0.6.0

type SecretRuleCount struct {
	RuleID string `json:"rule_id"`
	Count  int    `json:"count"`
}

SecretRuleCount 는 규칙 하나의 탐지 건수다.

type SecretScanReport added in v0.6.0

type SecretScanReport struct {
	// Count 는 전체 탐지 건수다.
	Count int
	// Rules 는 규칙별 건수다 — 건수가 많은 규칙부터, 같으면 규칙 이름 순.
	Rules []SecretRuleCount
	// Findings 는 리포트 순서대로 앞의 MaxStoredSecretFindings 건이다.
	Findings []SecretFinding
	// Skipped 는 정책 off 로 스캔하지 않은 실행의 리포트(SecretScanSkippedReport)라는 뜻이다. 기록하지 않는다.
	Skipped bool
}

SecretScanReport 는 gitleaks JSON 리포트를 요약한 것이다.

func ParseGitleaksReport added in v0.6.0

func ParseGitleaksReport(raw []byte) (*SecretScanReport, error)

ParseGitleaksReport 는 gitleaks 의 JSON 리포트(--report-format json, 탐지 배열)를 요약한다.

탐지가 없으면 gitleaks 는 [] 를 쓴다. 정책 off 인 스크립트는 SecretScanSkippedReport 를 쓰고, 그것은 Skipped 로 돌려준다. 빈 파일이나 그 밖의 것은 형식 오류다 — 0 건으로 읽으면 깨진 리포트가 "탐지 없음" 이 된다. 이 표식 전에 스캐폴딩한 파이프라인은 off 에서도 [] 를 쓰므로, 정의를 갱신하기 전까지는 구별되지 않는다.

type SecretScanResult added in v0.6.0

type SecretScanResult struct {
	ID           string `json:"id"`
	PipelineID   string `json:"pipeline_id"`
	DeploymentID string `json:"deployment_id"`

	Scanner        string `json:"scanner"`
	ScannerVersion string `json:"scanner_version,omitempty"`

	// FindingsCount 는 리포트를 읽었을 때만 있다. nil 은 "모름" 이다 — 0 으로 채우면 "탐지 없음" 으로 읽힌다.
	FindingsCount *int `json:"findings_count,omitempty"`
	// Rules 는 규칙별 탐지 건수다(잘리지 않는다). Findings 는 앞의 MaxStoredSecretFindings 건만이다.
	Rules    []SecretRuleCount `json:"rules"`
	Findings []SecretFinding   `json:"findings"`

	GateResult GateResult `json:"gate_result"`
	ReportURI  string     `json:"report_uri,omitempty"`
	ScannedAt  time.Time  `json:"scanned_at"`

	// ReportRef 는 CI 리포트를 다시 읽을 위치다. 화면에는 내보내지 않는다.
	ReportRef *ScanReportRef `json:"-"`
}

SecretScanResult 는 실행 하나의 시크릿 탐지(gitleaks) 결과 요약이다 (nullus-plan#80, Security Dashboard 설계 §8 G2).

비밀값은 담지 않는다 — 탐지 위치(규칙 · 파일 · 줄 · 커밋 · Fingerprint)만 둔다. 이것만으로 무엇을 폐기·회전할지, 오탐이면 .gitleaksignore 에 무엇을 적을지 알 수 있다.

type Severity added in v0.6.0

type Severity string

Severity 는 Trivy 가 매기는 취약점 등급이다.

const (
	SeverityCritical Severity = "CRITICAL"
	SeverityHigh     Severity = "HIGH"
	SeverityMedium   Severity = "MEDIUM"
	SeverityLow      Severity = "LOW"
)

type SeverityCounts added in v0.6.0

type SeverityCounts = shareddomain.SeverityCounts

SeverityCounts 는 심각도별 취약점 건수다. 스택 모듈도 설치 이미지를 같은 어휘로 세므로 shared 가 소유한다.

type TemplateSource added in v0.6.0

type TemplateSource struct {
	// RepoURL 은 원본 저장소 주소다(https).
	RepoURL string `json:"repo_url"`
	// Commit 은 가져올 커밋의 전체 SHA 다. 태그·브랜치는 받지 않는다 — 태그도 다시
	// 찍힌다(eGov 웹 샘플의 v4.3.0 은 2025-03 릴리스인데 2026-05 커밋을 가리킨다).
	Commit string `json:"commit"`
	// Label 은 화면에 보일 버전 이름이다(예: v5.0.0). 가져올 대상을 정하지 않는다.
	Label string `json:"label,omitempty"`
	// BuildProfile 은 가져온 원본을 어떻게 빌드하고 띄울지다.
	BuildProfile BuildProfile `json:"build_profile,omitempty"`
}

TemplateSource 는 템플릿이 새 저장소로 가져오는 외부 원본이다.

파이프라인을 만들 때 이 커밋의 파일을 그대로 복사해 앱 저장소의 첫 커밋으로 둔다. 원본을 따라가지 않는다 — 가져온 순간부터 그 저장소는 사용자 것이고, 새 버전은 템플릿의 Commit 을 올렸을 때 새로 만드는 파이프라인부터 들어온다.

파이프라인도 같은 값을 들고 있다. 템플릿의 Commit 은 시간이 지나면 올라가므로, 그 저장소가 어느 버전에서 시작했는지는 파이프라인 쪽에 따로 남아야 한다.

func (*TemplateSource) ShortCommit added in v0.6.0

func (s *TemplateSource) ShortCommit() string

ShortCommit 은 커밋 메시지와 화면에 쓸 짧은 SHA 다.

func (*TemplateSource) Validate added in v0.6.0

func (s *TemplateSource) Validate() error

Validate 는 원본을 가져올 수 있는 모양인지 본다. 어기면 ErrTemplateInvalid 를 감싼다.

type TrivyReportSummary added in v0.6.0

type TrivyReportSummary = shareddomain.TrivyReportSummary

TrivyReportSummary 는 Trivy JSON 리포트에서 판정에 필요한 것만 뽑은 것이다.

func ParseTrivyReport added in v0.6.0

func ParseTrivyReport(raw []byte) (*TrivyReportSummary, error)

ParseTrivyReport 는 Trivy JSON 리포트(SchemaVersion 2)를 요약한다.

type UnreachableAction added in v0.6.0

type UnreachableAction string

UnreachableAction 은 스캔을 수행하지 못했을 때(스캐너 도달 불가 등)의 동작이다.

const (
	// UnreachableBlock 은 멈춘다. 기본값이다 — 스캐너가 죽은 동안 모든 배포가
	// 초록불로 지나가는 것이 가장 나쁜 실패다 (설계 §6.1).
	UnreachableBlock UnreachableAction = "block"
	// UnreachableAllow 는 통과시킨다. 긴급 배포용 우회로다 — 우회로가 없으면
	// 사람들은 파이프라인 자체를 우회한다.
	UnreachableAllow UnreachableAction = "allow"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL