Documentation
¶
Index ¶
- Constants
- Variables
- func AirgapRegistryHost(ociRegistry string) string
- func AppImagePullSecretNameFor(app string) string
- func DefaultOrgID() string
- func IsDBStale(updatedAt *time.Time, now time.Time) bool
- func IsGatewayCRD(name string) bool
- func NormalizeSeverity(severity string) string
- func OTelCollectorOTLPGRPCEndpoint(namespace string) string
- func OTelCollectorOTLPHTTPEndpoint(namespace string) string
- func OTelCollectorServiceName() string
- func RuntimeImages() []string
- func SeverityRank(severity string) int
- func SonarQubeServerEndpoint(namespace string) string
- func TrivyDBRepository(ociRegistry string) string
- func TrivyJavaDBRepository(ociRegistry string) string
- func TrivyServerEndpoint(namespace string) string
- type AppError
- type BaseEvent
- type DomainEvent
- type EventBus
- type EventHandler
- type ImageVulnerability
- type InMemoryEventBus
- type SeverityCounts
- type TrivyReportSummary
- type VulnerabilityClass
- type VulnerabilityFilter
- type VulnerabilityPage
- type VulnerabilityTarget
Constants ¶
const ( // AppManagedByLabel / AppManagedByCICD 는 CI/CD 모듈이 만든 리소스의 표시다. AppManagedByLabel = "app.kubernetes.io/managed-by" AppManagedByCICD = "nullus-cicd" // AppImagePullSecretName 은 앱별 이름 이전에 만든 파이프라인의 pull 자격증명이다. 네임스페이스에 // 하나라 같은 네임스페이스의 다음 앱이 덮어썼다. 그 전에 만든 Deployment 가 아직 이 이름을 참조하므로 // 백업은 계속 담는다. 새 파이프라인은 AppImagePullSecretNameFor 를 쓴다. AppImagePullSecretName = "nullus-registry" // #nosec G101 -- Secret 리소스 이름 // AppImagePullSecretType 은 pull 자격증명 Secret 의 종류다. 백업이 라벨과 함께 이것으로 고른다. AppImagePullSecretType = "kubernetes.io/dockerconfigjson" // #nosec G101 -- Secret 종류 이름 )
앱 네임스페이스 — CI/CD 모듈이 파이프라인을 만들 때 앱을 배포할 자리로 만드는 네임스페이스.
CI/CD(stack 밖, internal/cicd)가 만들고 백업(internal/backup)이 담아야 한다. 두 모듈은 서로 import 하지 않으므로 이름을 여기 둔다. 앱의 Deployment·Service·HTTPRoute 는 Argo CD 가 Git 에서 되살리지만, 이 네임스페이스 자체와 그 안의 이미지 pull Secret 은 Nullus 가 직접 만든 것이라 Git 에 없다 — 앱 네임스페이스를 잃으면 Deployment 는 돌아와도 pull 이 실패한다(2026-10-12 리허설 실측).
const ( DefaultVulnerabilityPageSize = 50 MaxVulnerabilityPageSize = 200 )
const ( VulnerabilityListAvailable = "available" // VulnerabilityReasonReportExpired 는 CI 리포트가 보관 기간이 지나 사라졌다는 뜻이다. VulnerabilityReasonReportExpired = "report_expired" // VulnerabilityReasonReportMissing 은 이 스캔에 리포트 위치가 기록되지 않았다는 뜻이다. VulnerabilityReasonReportMissing = "report_missing" // VulnerabilityReasonCIUnreachable 은 CI 서버에 닿지 못했다는 뜻이다. VulnerabilityReasonCIUnreachable = "ci_unreachable" // VulnerabilityReasonNotRecorded 는 목록 기능 전에 스캔해 목록이 없다는 뜻이다. VulnerabilityReasonNotRecorded = "not_recorded" )
목록 조회 결과의 상태와 사유. 목록을 못 보이면 이유를 숨기지 않는다.
const ( // PostgresReleaseName 은 플랫폼이 설치하는 PostgreSQL 릴리스다. PostgresReleaseName = "nullus-postgresql" // MinIOReleaseName 은 플랫폼이 설치하는 MinIO 릴리스다. MinIOReleaseName = "nullus-minio" // SeaweedFSReleaseName 은 MinIO 대신 고를 수 있는 S3 호환 스토리지 릴리스다. SeaweedFSReleaseName = "nullus-seaweedfs" )
플랫폼이 설치하는 공유 인프라의 Helm 릴리스 이름.
여기 있는 이유는 두 모듈이 같은 이름을 봐야 하기 때문이다 — stack 은 이 이름으로 차트를 설치하고 접속 정보를 안내하고, admin 의 시크릿 회전은 같은 이름으로 워크로드를 재시작한다. 모듈끼리 서로의 internal 을 참조할 수 없으므로 이름의 단일 출처를 shared 에 둔다.
Helm 은 릴리스명을 그대로 Service 이름에 쓰므로, 이 값이 곧 클러스터 안의 접속 주소이기도 하다. 한쪽만 바꾸면 다른 쪽이 조용히 어긋난다.
const ( // OTelCollectorReleaseName 은 게이트웨이 수집기의 릴리스명이다. // // 차트 이름(opentelemetry-collector)을 그대로 쓰지 않는 이유는 추적 계층 // 단계가 같은 차트를 설치할 수 있어 릴리스명이 충돌하기 때문이다. OTelCollectorReleaseName = "otel-collector" // OTelAgentReleaseName 은 노드마다 서는 로그 수집 에이전트의 릴리스명이다. OTelAgentReleaseName = "otel-agent" // OTLP 수신 포트. 차트 기본값이며 애플리케이션이 붙는 지점이다. OTelCollectorOTLPGRPCPort = 4317 OTelCollectorOTLPHTTPPort = 4318 // TrivyReleaseName 은 이미지 취약점 스캐너의 릴리스명이다. // // stack 은 이 이름으로 차트를 설치하고, cicd 는 CI 잡이 붙을 주소를 만든다. // OTLP 와 같은 이유로 규칙을 여기 둔다. TrivyReleaseName = "trivy" // TrivyServicePort 는 client 가 CVE 매칭을 요청하는 포트다. // aqua/trivy 차트의 service.port 기본값과 같아야 한다. TrivyServicePort = 4954 )
OpenTelemetry Collector 의 이름과 주소 규칙.
stack 은 이 이름으로 차트를 설치하고, cicd 는 배포하는 앱에 "어디로 텔레메트리를 보낼지" 를 넣어 준다. 두 모듈이 같은 주소를 봐야 하므로 규칙을 여기 둔다 — 한쪽이 문자열을 흉내 내면 차트 이름이 바뀔 때 조용히 어긋난다.
const ( SonarQubeReleaseName = "sonarqube" // SonarQubeServicePort 는 차트 Service 의 포트다(service.externalPort). SonarQubeServicePort = 9000 // SonarQubeAnalysisTokenPath 는 CI 가 분석에 쓸 토큰의 OpenBao 경로 접미사다. // 스택 설치(provisioning_sonarqube)가 발급해 쓰고, cicd 가 파이프라인을 만들 때 읽는다. SonarQubeAnalysisTokenPath = "security/sonarqube/analysis-token" )
SonarQube 는 소스 정적 분석 서버다. stack 은 이 이름으로 차트를 설치하고(fullnameOverride), cicd 는 CI 잡이 붙을 주소를 만든다. Trivy 와 같은 이유로 규칙을 여기 둔다.
const ( // 오브젝트 스토리지 이미지는 MinIO 포크인 SILO(pgsty/silo)에서 받는다. // // MinIO 는 Docker Hub 배포를 멈춘 데 이어(docker.io/minio/* 거절) quay.io 저장소도 // 익명 pull 을 막았다 — 2026-10-17 실측: quay.io/minio/minio 와 quay.io/minio/mc 가 // `latest` 든 고정 RELEASE 태그든 401 unauthorized 다. 받을 수 있는 출처가 없어 // 로컬 인프라 기동과 스택 설치(installing_minio)가 처음부터 멈춘다. // // SILO 는 MinIO 서버의 커뮤니티 포크다(AGPL-3.0, MinIO Inc. 와 무관). 라이선스는 // 업스트림과 같으므로 AGPL 의무는 그대로다 — 해결되는 것은 "받을 수 없다" 뿐이다. // 데이터 포맷(.minio.sys)·환경변수(MINIO_*)·프로토콜(minio_* 메트릭, x-minio-* 헤더, // /minio/* 경로)을 그대로 유지하므로 설치 코드와 클라이언트는 손대지 않는다. // // MinIOServerImage — 스택 오브젝트 스토리지(installing_minio). 차트 기본값이 // quay.io 를 가리키므로 values 로 덮는다. MinIOServerImage = "docker.io/pgsty/silo:RELEASE.2026-10-15T00-00-00Z" // MinIOClientImage — MinIO 차트의 버킷 훅(mcImage). 차트 기본값이 quay.io 라 덮는다. // // GitLab 버킷 부트스트랩 Job 은 더 이상 이것을 쓰지 않는다 — 구현체를 갈아 // 끼울 수 있게 S3 CreateBucket 을 curl 로 직접 부른다(CurlImage). MinIOClientImage = "docker.io/pgsty/mc:RELEASE.2026-09-16T00-00-00Z" // SeaweedFSImage — 스택 오브젝트 스토리지의 다른 구현체(installing_seaweedfs). // Apache-2.0 이고 상류가 amd64·arm64 를 함께 낸다. 태그는 차트 appVersion 과 같게 둔다 // (domain.SeaweedFSAppVersion) — 차트 기본값도 같은 태그지만, 출처를 values 로 못박아 // 에어갭 번들과 같은 참조를 보게 한다. SeaweedFSImage = "docker.io/chrislusf/seaweedfs:4.48" // CurlImage — Harbor·Nexus 프로비저닝 Job 이 REST API 를 호출한다. // (internal/stack/adapter/helm/{harbor,nexus}-provisioning.go) CurlImage = "curlimages/curl:8.11.1" // KubectlImage — OpenBao init/bootstrap 사이드카. // (internal/stack/adapter/helm/openbao-values.go) KubectlImage = "docker.io/bitnamilegacy/kubectl:1.33.4" // NodeBuilderImage — 생성된 React 앱 Dockerfile 의 빌드 단계. // 파이프라인이 클러스터 안에서 이 이미지로 빌드한다. // (internal/cicd/adapter/scaffold/react_app.go) NodeBuilderImage = "node:22-alpine" // JenkinsAgentImage — Jenkins kubernetes 플러그인이 빌드마다 띄우는 파드. // GitLab CI 와 달리 실행기를 차트로 세우지 않는다. // (internal/cicd/adapter/scaffold/jenkins_renderer.go) JenkinsAgentImage = "docker:27-cli" // DindImage — 이미지 빌드용 docker 데몬. Jenkins 빌드 파드의 사이드카이자 // GitLab build 잡의 서비스다. // (internal/cicd/adapter/scaffold/{jenkins_renderer,renderer}.go) DindImage = "docker:27-dind" // GitLabCIBuildImage / GitLabCIDeployImage — 생성된 .gitlab-ci.yml 의 build·deploy 잡. // 쿠버네티스 실행기가 잡마다 이 이미지로 파드를 띄운다. // (internal/cicd/adapter/scaffold/renderer.go) GitLabCIBuildImage = "docker:27" GitLabCIDeployImage = "alpine:3.20" // TrivyCLIImage — 파이프라인 이미지 스캔 단계의 Trivy CLI. 취약점 DB 는 들어 있지 않다 — // client 로 붙어 스택 Trivy 서버에 매칭을 맡긴다. 에어갭 번들은 Trivy 차트가 같은 태그를 // 이미 싣는다(images.txt). RuntimeImages 에 넣지 않는 이유다 — 넣으면 생성기가 두 번 싣는다. // 정책 변수와 함께 CI 에 밀린다(port.ScanPolicyVariables) — 올리면 파이프라인 정의를 // 다시 쓰지 않아도 다음 실행부터 따라온다. // (internal/cicd/adapter/scaffold/image_scan.go) TrivyCLIImage = "aquasec/trivy:0.74.0" // SonarScannerImage — 파이프라인 SAST 단계(GitLab CI·GitHub Actions·Jenkins). 공식 // sonarsource/sonar-scanner-cli 는 amd64 빌드만 게시해(Docker Hub 전 태그 실측, 2026-10) // arm64 노드와 에어갭 arm64 번들에서 단계가 서지 않았다 — 플랫폼 독립 스캐너 zip 을 멀티아치 // JRE 위에 우리가 굽는다(deploy/images/sonar-scanner, CD 의 build-and-push-sonar-scanner, // 로컬은 scripts/build-sonar-scanner-image.sh). 태그는 Dockerfile 의 스캐너 버전-이미지 리비전이다 // (scripts/sonar-scanner-image-tag.sh, 테스트가 둘을 묶는다) — 같은 버전에서 내용이 바뀌면 리비전이 // 올라 태그가 바뀐다. ghcr 패키지는 처음 만들어질 때 private 이므로 public 으로 바꿔야 // 익명 pull 이 된다(릴리즈 정책 §7.1). // (internal/cicd/adapter/scaffold/sast.go) SonarScannerImage = "ghcr.io/cloud-nullus/nullus/nullus-sonar-scanner:8.1.0.6389-2" // GitleaksImage 는 파이프라인 시크릿 탐지 단계가 쓰는 gitleaks 다(nullus-plan#80). 상류가 // amd64·arm64 를 모두 내므로 그대로 쓴다. 태그는 앱 저장소에 넣는 pre-commit 훅의 rev 와 // 같아야 한다(scaffold.gitleaksVersionTag 가 여기서 뽑는다) — 로컬과 CI 가 같은 규칙을 봐야 한다. GitleaksImage = "ghcr.io/gitleaks/gitleaks:v8.30.1" )
런타임에 만들어지는 매니페스트가 참조하는 컨테이너 이미지.
── 왜 여기 모아 두는가 ────────────────────────────────────────────────── 에어갭 이미지 목록(`airgap/images/images.txt`)은 `helm template` 렌더 결과 에서 자동 생성된다. 그래서 **차트에 없는 이미지는 목록에 오르지 않는다.**
Nullus 는 설치·프로비저닝·파이프라인 과정에서 매니페스트를 Go 코드로 직접 만들어 적용한다. 그 안의 이미지는 helm 이 볼 수 없어 번들에서 조용히 빠지고, 폐쇄망에서 ImagePullBackOff 로만 드러난다 — 설치가 한참 진행된 뒤에.
실제로 그렇게 빠져 있었다(2026-09-02 실측): mc · curl · node · docker 5종. 그중 Jenkins 이미지 하나만 과거에 손으로 INFRA_IMAGES 에 덧붙여져 있었고, 그 주석이 같은 문제를 이미 기록하고 있었다 — 한 건씩 손으로 막는 방식으로는 다음 것을 놓친다.
그래서 상수를 여기 모으고, RuntimeImages() 가 돌려주는 것이 번들에 전부 들어 있는지 테스트가 지킨다(runtime_images_test.go).
**이미지를 새로 참조하게 되면 여기 상수를 만들고 아래 목록에 넣는다.** 그러지 않으면 폐쇄망 설치에서 그 단계가 실패한다.
const ( // LabelInstalledBy 는 Nullus 가 새로 설치한 공용 자원의 표시다. 설치는 클러스터에 이미 // 있던 것을 재사용하므로, 새로 깐 것에만 달아 둘을 가른다. LabelInstalledBy = "nullus.io/installed-by" InstalledByNullus = "nullus" // 내부 CA — 설치가 cert-manager 단계에서 만든다. 이름이 Nullus 전용이라 표시 없이도 Nullus // 것이다. CA Secret 은 cert-manager 가 설치된 네임스페이스(cluster-resource-namespace)에 있다. InternalCABootstrapIssuerName = "nullus-selfsigned-bootstrap" InternalCAIssuerName = "nullus-internal-ca-issuer" InternalCACertName = "nullus-internal-ca-cert" InternalCASecretName = "nullus-internal-ca" // EnvoyGatewayClassName 은 설치기가 만드는 GatewayClass 다. EnvoyGatewayClassName = "envoy" EnvoyGatewayControllerName = "gateway.envoyproxy.io/gatewayclass-controller" // CertManagerCRDSuffix 는 cert-manager CRD 의 API 그룹이다(acme.cert-manager.io 포함). CertManagerCRDSuffix = ".cert-manager.io" )
스택이 클러스터에 하나만 두고 함께 쓰는 공용 자원의 식별자.
설치(stack/adapter/helm)가 만들고, 클러스터의 마지막 스택을 지울 때(stack/usecase) 회수하며, 백업(backup/adapter/kube)이 담는다. 세 곳이 같은 이름과 같은 판별 규칙을 봐야 한다 — 백업 모듈은 스택 모듈을 import 하지 않으므로(모듈 경계) 여기 둔다. 지우는 쪽은 알고 백업하는 쪽은 모르던 것이 실제로 있었다(Argo CD CRD).
const DefaultStackNamespace = "nullus"
DefaultStackNamespace 는 스택 네임스페이스가 정해지지 않았을 때의 기본값이다.
const RestoredFromBackupAnnotation = "backup.nullus.io/restored-from"
RestoredFromBackupAnnotation 은 복구가 만든 볼륨에 그 출처를 남기는 표시다.
설치 preflight 는 네임스페이스에 볼륨이 남아 있으면 설치를 막는다 — 새 설치가 옛 데이터베이스를 물려받으면 이번에 만든 비밀번호와 어긋나고, 그 사실이 한참 뒤 엉뚱한 도구의 오류로 드러나기 때문이다.
그런데 **복구가 방금 놓아둔 볼륨**은 사정이 다르다. 복구는 볼륨과 함께 그 시점의 Secret 과 금고(OpenBao)까지 되돌리므로 비밀번호가 어긋나지 않는다. 막아야 할 것은 "실패한 설치의 잔여" 이지 "복구된 상태" 가 아니다.
두 경우를 구분할 근거가 볼륨 자체에 있어야 한다 — 네임스페이스 밖의 기록에 의존하면 그 기록이 사라진 뒤에는 다시 구분할 수 없다.
값은 백업 실행 ID 다. 남은 볼륨이 **모두 같은 백업에서 왔을 때만** 통과시킨다 (설계 §6.1). 섞여 있으면 어느 시점의 상태인지 말할 수 없으므로 막는다.
const SeededDefaultOrgID = "11111111-1111-1111-1111-111111111111"
SeededDefaultOrgID 는 시드 마이그레이션이 만드는 기본 조직이다.
인증이 꺼진 개발 모드에는 principal 도 헤더도 없어 폴백 조직이 필요하다. 이 값이 실제 organizations 행과 달라지면 쓰기 경로는 stacks_org_id_fkey FK 위반으로 실패하고, 읽기 경로는 빈 결과만 돌려준다.
이전에 쓰이던 00000000-0000-0000-0000-000000000001 은 어떤 마이그레이션에도 존재하지 않는 유령 조직이었다.
const StaleDBAge = 30 * 24 * time.Hour
StaleDBAge 는 취약점 DB 를 낡았다고 보는 나이다 (이미지 스캔 설계 §6.4).
에어갭에서 DB 는 사람이 가져다 넣는 만큼만 새것이다. 강제로 막을 수는 없지만 언제 것인지 숨기지 않는다.
const TrivyClientImage = "aquasec/trivy:0.74.0"
TrivyClientImage 는 스택 서버에 붙는 trivy client 이미지다. 서버(스택 차트)와 버전을 맞춘다 — client 와 server 의 버전이 갈리면 스캔 요청이 거절될 수 있다.
RuntimeImages 에는 넣지 않는다. 이 이미지를 쓰는 설치 이미지 스캔 Job 은 에어갭에서 돌지 않는다.
Variables ¶
var ( ErrNotFound = NewAppError("NOT_FOUND", 404, "Resource not found", "", false) ErrForbidden = NewAppError("FORBIDDEN", 403, "Access denied", "", false) ErrValidation = NewAppError("VALIDATION_ERROR", 422, "Validation failed", "", false) )
Common errors.
Functions ¶
func AirgapRegistryHost ¶ added in v0.6.0
AirgapRegistryHost 는 에어갭 레지스트리 설정(NULLUS_HELM_OCI_REGISTRY, 예 kind-registry:5000/charts)에서 호스트만 뗀다. 파드가 그 레지스트리를 부르는 이름이다 — 호스트에서 쓰는 localhost:5001 은 파드 안에서 파드 자신이다. 에어갭이 아니면 빈 값이다.
func AppImagePullSecretNameFor ¶ added in v0.6.0
AppImagePullSecretNameFor 는 앱 하나의 레지스트리 pull 자격증명 이름이다. 스캐폴딩된 Deployment 가 imagePullSecrets 로 이 이름을 참조한다.
앱마다 따로 둔다. GitLab 프로젝트 레지스트리의 토큰은 그 프로젝트 이미지만 읽는다 — 이름이 네임스페이스에 하나면 같은 네임스페이스에 만든 다음 앱이 그 토큰을 덮어써 앞 앱의 pull 이 insufficient_scope 로 막힌다(2026-10-19 kind 실측).
func DefaultOrgID ¶
func DefaultOrgID() string
DefaultOrgID 는 폴백 조직 ID 를 반환한다. 시드 조직 ID 가 다른 환경에서는 NULLUS_DEFAULT_ORG_ID 로 덮어쓴다.
func IsDBStale ¶ added in v0.6.0
IsDBStale 은 취약점 DB 가 낡았는지 본다. 시각을 모르면 낡은 것으로 본다 — 모르는 채로 초록불을 켜지 않는다.
func IsGatewayCRD ¶ added in v0.6.0
IsGatewayCRD 는 게이트웨이 단계가 까는 CRD 인지 본다.
func NormalizeSeverity ¶ added in v0.6.0
NormalizeSeverity 는 심각도를 소문자 어휘로 옮긴다. 모르는 값은 unknown 이다.
func OTelCollectorOTLPGRPCEndpoint ¶
OTelCollectorOTLPGRPCEndpoint 는 애플리케이션이 OTLP/gRPC 로 보낼 주소다.
func OTelCollectorOTLPHTTPEndpoint ¶
OTelCollectorOTLPHTTPEndpoint 는 애플리케이션이 OTLP/HTTP 로 보낼 주소다.
func OTelCollectorServiceName ¶
func OTelCollectorServiceName() string
OTelCollectorServiceName 은 수집기 Service 이름이다. 차트의 fullname 규칙이 "<릴리스>-<차트>" 라 릴리스명만으로는 맞지 않는다.
func RuntimeImages ¶ added in v0.6.0
func RuntimeImages() []string
RuntimeImages 는 위 이미지 전부를 돌려준다.
에어갭 번들 생성기와 드리프트 검사가 이 목록을 단일 출처로 쓴다.
func SeverityRank ¶ added in v0.6.0
SeverityRank 는 정렬 순서다. 심각할수록 작다.
func SonarQubeServerEndpoint ¶ added in v0.6.0
SonarQubeServerEndpoint 는 CI 잡의 sonar-scanner 가 붙을 주소다.
SonarQube 를 고르지 않은 스택에서는 부르지 않는다 — 호출부가 "있음" 으로 오해한다. 네임스페이스가 비면 빈 문자열이다.
func TrivyDBRepository ¶ added in v0.6.0
TrivyDBRepository 는 에어갭 Trivy 서버가 취약점 DB 를 받을 곳이다(stack 모듈).
func TrivyJavaDBRepository ¶ added in v0.6.0
TrivyJavaDBRepository 는 에어갭 CI 잡의 trivy client 가 Java DB 를 받을 곳이다(cicd 모듈). client 는 Maven 메타데이터가 없는 JAR 을 만나면 Java DB 를 스스로 받는데, 기본 주소 (mirror.gcr.io)는 에어갭에서 닿지 않는다.
func TrivyServerEndpoint ¶ added in v0.6.0
TrivyServerEndpoint 는 CI 잡의 trivy client 가 붙을 주소다.
스캐너를 고르지 않은 스택에서는 네임스페이스만으로 주소를 만들면 안 된다 — 호출부가 "스캐너 있음" 으로 오해한다. 네임스페이스가 비면 빈 문자열이다.
Types ¶
type AppError ¶
type AppError struct {
Code string `json:"code"`
HTTPStatus int `json:"http_status"`
Message string `json:"message"`
Detail string `json:"detail,omitempty"`
Retryable bool `json:"retryable"`
TraceID string `json:"trace_id,omitempty"`
}
AppError represents a structured application error.
func NewAppError ¶
NewAppError creates a new AppError.
type BaseEvent ¶
type BaseEvent struct {
Name string `json:"name"`
Timestamp time.Time `json:"occurred_at"`
AggregateId string `json:"aggregate_id"`
}
BaseEvent provides a base implementation of DomainEvent.
func (BaseEvent) AggregateID ¶
func (BaseEvent) OccurredAt ¶
type DomainEvent ¶
DomainEvent represents an event that occurred in the domain.
type EventBus ¶
type EventBus interface {
Publish(event DomainEvent) error
Subscribe(eventName string, handler EventHandler)
}
EventBus defines the interface for publishing and subscribing to domain events.
type EventHandler ¶
type EventHandler func(event DomainEvent) error
EventHandler is a function that handles a domain event.
type ImageVulnerability ¶ added in v0.6.0
type ImageVulnerability struct {
ID string `json:"id"`
PkgName string `json:"pkg"`
InstalledVersion string `json:"installed"`
// FixedVersion 이 비면 아직 고친 버전이 없다.
FixedVersion string `json:"fixed"`
Severity string `json:"severity"`
Class VulnerabilityClass `json:"class"`
Target string `json:"target"`
PrimaryURL string `json:"url"`
}
ImageVulnerability 는 이미지 안의 취약점 하나다.
func FilterVulnerabilities ¶ added in v0.6.0
func FilterVulnerabilities(vulns []ImageVulnerability, f VulnerabilityFilter) ([]ImageVulnerability, int)
FilterVulnerabilities 는 조건에 맞는 것을 심각한 순으로 정렬해 한 쪽을 돌려준다. total 은 쪽 나누기 전 건수다.
func ParseTrivyVulnerabilities ¶ added in v0.6.0
func ParseTrivyVulnerabilities(raw []byte) ([]ImageVulnerability, error)
ParseTrivyVulnerabilities 는 Trivy JSON 리포트에서 취약점 목록을 뽑는다.
func ParseVulnerabilityLines ¶ added in v0.6.0
func ParseVulnerabilityLines(text string) []ImageVulnerability
ParseVulnerabilityLines 는 탭으로 나눈 한 줄에 하나씩 적힌 취약점을 읽는다.
필드 순서: 심각도, ID, 패키지, 설치 버전, 수정 버전, Trivy Class, 대상, 링크. 설치 이미지 스캔 Job 이 Trivy 템플릿으로 이 모양을 찍는다. 모양이 맞지 않는 줄은 버린다.
type InMemoryEventBus ¶
type InMemoryEventBus struct {
// contains filtered or unexported fields
}
InMemoryEventBus is an in-memory implementation of EventBus.
func NewInMemoryEventBus ¶
func NewInMemoryEventBus() *InMemoryEventBus
NewInMemoryEventBus creates a new InMemoryEventBus.
func (*InMemoryEventBus) Publish ¶
func (b *InMemoryEventBus) Publish(event DomainEvent) error
Publish sends an event to all registered handlers.
func (*InMemoryEventBus) Subscribe ¶
func (b *InMemoryEventBus) Subscribe(eventName string, handler EventHandler)
Subscribe registers a handler for a specific event name.
type SeverityCounts ¶ added in v0.6.0
type SeverityCounts struct {
Critical int `json:"critical"`
High int `json:"high"`
Medium int `json:"medium"`
Low int `json:"low"`
Unknown int `json:"unknown"`
}
SeverityCounts 는 심각도별 취약점 건수다.
func CountVulnerabilities ¶ added in v0.6.0
func CountVulnerabilities(vulns []ImageVulnerability) (all, fixable SeverityCounts)
CountVulnerabilities 는 목록을 심각도별로 센다. fixable 은 수정 버전이 있는 것만 센다.
func (*SeverityCounts) Add ¶ added in v0.6.0
func (c *SeverityCounts) Add(severity string)
Add 는 취약점 하나를 심각도에 따라 센다.
func (SeverityCounts) Plus ¶ added in v0.6.0
func (c SeverityCounts) Plus(o SeverityCounts) SeverityCounts
Plus 는 두 건수를 더한다.
type TrivyReportSummary ¶ added in v0.6.0
type TrivyReportSummary struct {
ImageRepository string
ImageTag string
ImageDigest string
ScannerVersion string
// DBUpdatedAt 은 서버 모드에서 서버가 알려준 취약점 DB 시각이다.
// 리포트에 없으면 nil 이다.
DBUpdatedAt *time.Time
// All 은 모든 취약점, Fixable 은 수정본이 있는 것만 센 값이다.
All SeverityCounts
Fixable SeverityCounts
// Targets 는 리포트의 Results 수다 — 이미지면 OS · 언어 패키지 묶음, 저장소(trivy fs)면 검사한
// 락파일 수다. 의존성 스캔에서 0 이면 검사할 것이 없었다는 뜻이라 "취약점 0건" 과 다르다.
Targets int
}
TrivyReportSummary 는 Trivy JSON 리포트에서 판정에 필요한 것만 뽑은 것이다.
func ParseTrivyReport ¶ added in v0.6.0
func ParseTrivyReport(raw []byte) (*TrivyReportSummary, error)
ParseTrivyReport 는 Trivy JSON 리포트(SchemaVersion 2)를 요약한다.
형식은 kind 의 Trivy 서버로 실제 스캔한 리포트에 맞췄다 (testdata/trivy-report-node16.json).
type VulnerabilityClass ¶ added in v0.6.0
type VulnerabilityClass string
VulnerabilityClass 는 취약점이 어디서 왔는지다.
const ( // VulnerabilityClassOS 는 베이스 이미지의 OS 패키지다(Trivy os-pkgs). VulnerabilityClassOS VulnerabilityClass = "os" // VulnerabilityClassLibrary 는 앱이 넣은 언어 패키지 의존성이다(Trivy lang-pkgs). VulnerabilityClassLibrary VulnerabilityClass = "library" VulnerabilityClassOther VulnerabilityClass = "other" )
func VulnerabilityClassFromTrivy ¶ added in v0.6.0
func VulnerabilityClassFromTrivy(class string) VulnerabilityClass
VulnerabilityClassFromTrivy 는 Trivy 결과 묶음의 Class 를 옮긴다.
type VulnerabilityFilter ¶ added in v0.6.0
type VulnerabilityFilter struct {
Severities []string
Class VulnerabilityClass
FixableOnly bool
Query string
Limit int
Offset int
}
VulnerabilityFilter 는 목록 조회 조건이다. 빈 값은 "전체" 다.
func NewVulnerabilityFilter ¶ added in v0.6.0
func NewVulnerabilityFilter(severity, class, fixable, query, limit, offset string) VulnerabilityFilter
NewVulnerabilityFilter 는 조회 파라미터 문자열로 조건을 만든다. 모르는 값은 버린다.
func (VulnerabilityFilter) Matches ¶ added in v0.6.0
func (f VulnerabilityFilter) Matches(v ImageVulnerability) bool
Matches 는 취약점이 조건에 맞는지 본다. 쪽 나눔은 보지 않는다.
func (VulnerabilityFilter) Normalized ¶ added in v0.6.0
func (f VulnerabilityFilter) Normalized() VulnerabilityFilter
Normalized 는 쪽 크기와 시작 위치를 허용 범위로 맞춘다.
type VulnerabilityPage ¶ added in v0.6.0
type VulnerabilityPage struct {
Status string `json:"status"`
Reason string `json:"reason"`
Targets []VulnerabilityTarget `json:"targets"`
Items []ImageVulnerability `json:"items"`
Total int `json:"total"`
Limit int `json:"limit"`
Offset int `json:"offset"`
}
VulnerabilityPage 는 목록 조회 응답이다.
func NewVulnerabilityPage ¶ added in v0.6.0
func NewVulnerabilityPage(all []ImageVulnerability, f VulnerabilityFilter) VulnerabilityPage
NewVulnerabilityPage 는 전체 목록에서 조건에 맞는 한 쪽과 대상 요약을 만든다.
func UnavailableVulnerabilityPage ¶ added in v0.6.0
func UnavailableVulnerabilityPage(reason string, f VulnerabilityFilter) VulnerabilityPage
UnavailableVulnerabilityPage 는 목록을 보일 수 없을 때의 응답이다.
type VulnerabilityTarget ¶ added in v0.6.0
type VulnerabilityTarget struct {
Target string `json:"target"`
Class VulnerabilityClass `json:"class"`
Total int `json:"total"`
}
VulnerabilityTarget 은 스캔 대상(베이스 이미지 OS, 앱 의존성 묶음) 하나의 전체 건수다.
func SummarizeVulnerabilityTargets ¶ added in v0.6.0
func SummarizeVulnerabilityTargets(vulns []ImageVulnerability) []VulnerabilityTarget
SummarizeVulnerabilityTargets 는 대상별 전체 건수다. 베이스 이미지(OS)가 먼저 온다.