diff --git a/Makefile b/Makefile
index d177ec5d2..c9c2de33f 100644
--- a/Makefile
+++ b/Makefile
@@ -34,7 +34,6 @@ PG_VERSION=11.9.8
DRACON_NS=dracon
TEKTON_NS=tekton-pipelines
ARANGODB_NS=arangodb
-BASE_IMAGE=scratch
DOCKER=docker
PROTOC=protoc
@@ -47,22 +46,31 @@ export
.PHONY: components component-binaries cmd/draconctl/bin protos build publish-component-containers publish-containers draconctl-image draconctl-image-publish clean-protos clean
$(component_binaries):
- CGO_ENABLED=0 ./scripts/build_component_binary.sh $@
+ ./scripts/build_component_binary.sh $@
component-binaries: $(component_binaries)
$(component_containers): %/docker: %/bin
+ $(eval GOOS:=linux)
+ $(eval GOARCH:=amd64)
./scripts/build_component_container.sh $@
components: $(component_containers)
cmd/draconctl/bin:
- CGO_ENABLED=0 go build -o bin/cmd/draconctl cmd/draconctl/main.go
+ $(eval GOOS:=linux)
+ $(eval GOARCH:=amd64)
+ CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o bin/cmd/$(GOOS)/$(GOARCH)/draconctl cmd/draconctl/main.go
draconctl-image: cmd/draconctl/bin
+ $(eval GOOS:=linux)
+ $(eval GOARCH:=amd64)
$(DOCKER) build -t "${CONTAINER_REPO}/draconctl:${DRACON_VERSION}" \
+ --build-arg GOOS=$(GOOS) \
+ --build-arg GOARCH=$(GOARCH) \
$$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \
- -f containers/Dockerfile.draconctl .
+ -f containers/Dockerfile.draconctl . \
+ --platform "$(GOOS)/$(GOARCH)"
draconctl-image-publish: draconctl-image
$(DOCKER) push "${CONTAINER_REPO}/draconctl:${DRACON_VERSION}"
@@ -229,23 +237,23 @@ install: deploy-cluster dev-infra deploy-elasticoperator deploy-arangodb-crds ad
@echo "deploying dracon"
@helm upgrade dracon ./deploy/dracon/chart \
- --install \
- --values ./deploy/dracon/values/dev.yaml \
- --create-namespace \
- --set "image.registry=$(CONTAINER_REPO)" \
- --namespace $(DRACON_NS) \
- --version $(DRACON_VERSION) \
- --wait
+ --install \
+ --values ./deploy/dracon/values/dev.yaml \
+ --create-namespace \
+ --set "image.registry=$(CONTAINER_REPO)" \
+ --namespace $(DRACON_NS) \
+ --version $(DRACON_VERSION) \
+ --wait
@echo "Applying migrations"
@helm upgrade deduplication-db-migrations ./deploy/deduplication-db-migrations/chart \
- --install \
- --values ./deploy/deduplication-db-migrations/values/dev.yaml \
- --create-namespace \
- --set "image.registry=$(CONTAINER_REPO)" \
- --namespace $(DRACON_NS) \
- --set "image.tag=$(DRACON_VERSION)" \
- --wait
+ --install \
+ --values ./deploy/deduplication-db-migrations/values/dev.yaml \
+ --create-namespace \
+ --set "image.registry=$(CONTAINER_REPO)" \
+ --namespace $(DRACON_NS) \
+ --set "image.tag=$(DRACON_VERSION)" \
+ --wait
@echo "Installing Components"
# we are setting the container repo to it's own value so that we can override it from other make targets
@@ -267,23 +275,35 @@ install-oss-components:
--values ./deploy/deduplication-db-migrations/values/dev.yaml
@echo "Done! Bumped version to $(DRACON_VERSION)"
-dev-build-oss-components: cmd/draconctl/bin
+dev-build-oss-components:
@echo "Building open-source components for local dracon instance..."
- $(eval CONTAINER_REPO:=localhost:5000)
+ $(eval GOOS:=linux)
+ $(eval GOARCH:=amd64)
+ $(eval CONTAINER_REPO:=localhost:5000/ocurity/dracon)
+ $(eval TMP_DIR:=tmp)
+ @mkdir $(TMP_DIR)
+ $(MAKE) cmd/draconctl/bin
$(MAKE) -j 16 publish-component-containers CONTAINER_REPO=$(CONTAINER_REPO)
- @./bin/cmd/draconctl components package \
- --version $(DRACON_VERSION) \
- --chart-version $(DRACON_VERSION) \
- --name $(DRACON_OSS_COMPONENTS_NAME) \
- ./components
+ @docker run \
+ --platform $(GOOS)/$(GOARCH) \
+ -v ./components:/components \
+ -v ./tmp:/tmp \
+ $(CONTAINER_REPO)/draconctl:$(DRACON_VERSION) components package \
+ --version $(DRACON_VERSION) \
+ --chart-version $(DRACON_VERSION) \
+ --name $(DRACON_OSS_COMPONENTS_NAME) \
+ ./components
+ @rm -r $(TMP_DIR)
dev-dracon:
- $(eval CONTAINER_REPO:=localhost:5000)
+ $(eval GOOS:=linux)
+ $(eval GOARCH:=amd64)
+ $(eval CONTAINER_REPO:=localhost:5000/ocurity/dracon)
$(eval DRACON_OSS_COMPONENTS_PACKAGE_URL:=./$(DRACON_OSS_COMPONENTS_NAME)-$(DRACON_VERSION).tgz)
- $(eval IN_CLUSTER_CONTAINER_REPO:=kind-registry:5000)
-
- $(MAKE) -j 16 publish-containers CONTAINER_REPO=$(CONTAINER_REPO)
+ $(eval IN_CLUSTER_CONTAINER_REPO:=kind-registry:5000/ocurity/dracon)
+
+ $(MAKE) -j 16 draconctl-image-publish CONTAINER_REPO=$(CONTAINER_REPO)
$(MAKE) -j 16 dev-build-oss-components CONTAINER_REPO=$(CONTAINER_REPO)
$(MAKE) install CONTAINER_REPO=$(IN_CLUSTER_CONTAINER_REPO) DRACON_OSS_COMPONENTS_PACKAGE_URL=$(DRACON_OSS_COMPONENTS_PACKAGE_URL)
diff --git a/components/consumers/dependency-track/Dockerfile b/components/consumers/dependency-track/Dockerfile
deleted file mode 100644
index 17a6cd3ae..000000000
--- a/components/consumers/dependency-track/Dockerfile
+++ /dev/null
@@ -1,7 +0,0 @@
-FROM alpine:3.20
-
-RUN apk add --no-cache ca-certificates
-
-COPY ./components/consumers/dependency-track/dependency-track /app/components/consumers/dependency-track/dependency-track
-
-ENTRYPOINT ["/app/components/consumers/dependency-track/dependency-track"]
diff --git a/components/consumers/dependency-track/Makefile b/components/consumers/dependency-track/Makefile
deleted file mode 100644
index b160f0073..000000000
--- a/components/consumers/dependency-track/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-.PHONY: container publish
-
-CONTAINER_REPO=
-DRACON_VERSION=
-SOURCE_CODE_REPO=
-PRODUCER_AGGREGATOR_BASE_IMAGE=$(shell test -e .custom_image && cat .custom_image || echo "scratch")
-
-DOCKER=docker
-
-container:
- $(DOCKER) build --tag $(CONTAINER_REPO)/components/consumers/dependency-track:$(DRACON_VERSION) \
- --file Dockerfile \
- $$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \
- ../../../bin 1>&2
-
-publish:
- $(DOCKER) push $(CONTAINER_REPO)/components/consumers/dependency-track:$(DRACON_VERSION) 1>&2
diff --git a/components/consumers/dependency-track/main.go b/components/consumers/dependency-track/main.go
index bd02d89f4..cfea8da05 100644
--- a/components/consumers/dependency-track/main.go
+++ b/components/consumers/dependency-track/main.go
@@ -28,7 +28,8 @@ var (
client *dtrack.Client
ownerAnnotation string
// used for debugging, turns off certificate and enables debug
- debugDT bool
+ debugDTConnection string
+ debugDT bool
)
func main() {
@@ -37,7 +38,7 @@ func main() {
flag.StringVar(&projectName, "projectName", "", "dependency track project name")
flag.StringVar(&projectUUID, "projectUUID", "", "dependency track project name")
flag.StringVar(&projectVersion, "projectVersion", "", "dependency track project version")
- flag.BoolVar(&debugDT, "debugDependencyTrackConnection", false, "setup client with no tls and enable debug")
+ flag.StringVar(&debugDTConnection, "debugDependencyTrackConnection", "false", "setup client with no tls and enable debug")
flag.StringVar(
&ownerAnnotation,
"ownerAnnotation",
@@ -65,7 +66,10 @@ func main() {
if projectVersion == "" {
log.Fatal("project version is mandatory for dependency track")
}
-
+ if debugDTConnection == "true" {
+ debugDT = true
+ slog.Info("running in debug mode, skipping certificate verification and printing requests and responses")
+ }
c, err := dtrack.NewClient(
authURL,
dtrack.WithHttpClient(
diff --git a/components/consumers/elasticsearch/main.go b/components/consumers/elasticsearch/main.go
index 58ea61038..81c3d3c5a 100644
--- a/components/consumers/elasticsearch/main.go
+++ b/components/consumers/elasticsearch/main.go
@@ -6,6 +6,7 @@ import (
"flag"
"fmt"
"log"
+ "log/slog"
"strings"
"time"
@@ -14,33 +15,28 @@ import (
"github.com/ocurity/dracon/pkg/enumtransformers"
"github.com/ocurity/dracon/pkg/templating"
- // TODO: Support multiple versions of ES
elasticsearch "github.com/elastic/go-elasticsearch/v8"
)
var (
- esUrls string
- esAddrs []string
- esIndex string
+ esUrls string
+ esAddrs []string
+ esIndex string
+
+ esAPIKey string
+ esCloudID string
+
basicAuthUser string
basicAuthPass string
issueTemplate string
)
-func init() {
- flag.StringVar(&esUrls, "es-urls", "", "[OPTIONAL] URLs to connect to elasticsearch comma separated. Can also use env variable ELASTICSEARCH_URL")
- flag.StringVar(&esIndex, "es-index", "", "the index in elasticsearch to push results to")
- flag.StringVar(&basicAuthUser, "basic-auth-user", "", "[OPTIONAL] the basic auth username")
- flag.StringVar(&basicAuthPass, "basic-auth-pass", "", "[OPTIONAL] the basic auth password")
- flag.StringVar(&issueTemplate, "descriptionTemplate", "", "a Go Template string describing how to show Raw or Enriched issues")
-}
-
func parseFlags() error {
if err := consumers.ParseFlags(); err != nil {
return err
}
- if len(esIndex) < 1 {
- return fmt.Errorf("es-index is undefined")
+ if len(esIndex) == 0 {
+ return fmt.Errorf("esIndex '%s' is undefined", esIndex)
}
if len(esUrls) > 0 {
for _, u := range strings.Split(esUrls, ",") {
@@ -51,6 +47,19 @@ func parseFlags() error {
}
func main() {
+ flag.StringVar(&esIndex, "esIndex", "", "the index in elasticsearch to push results to")
+ flag.StringVar(&issueTemplate, "descriptionTemplate", "", "a Go Template string describing how to show Raw or Enriched issues")
+
+ // es SaaS options
+ flag.StringVar(&esAPIKey, "esAPIKey", "", "the api key in elasticsearch to contact results to")
+ flag.StringVar(&esCloudID, "esCloudID", "", "the cloud id in elasticsearch to contact results to")
+
+ // es self-hosted options
+ flag.StringVar(&esUrls, "esURL", "", "[OPTIONAL] URLs to connect to elasticsearch comma separated. Can also use env variable ELASTICSEARCH_URL")
+ flag.StringVar(&basicAuthUser, "basic-auth-user", "", "[OPTIONAL] the basic auth username")
+ flag.StringVar(&basicAuthPass, "basic-auth-pass", "", "[OPTIONAL] the basic auth password")
+ flag.Parse()
+
if err := parseFlags(); err != nil {
log.Fatal(err)
}
@@ -61,15 +70,16 @@ func main() {
}
if consumers.Raw {
- log.Print("Parsing Raw results")
+ slog.Debug("Parsing Raw results")
responses, err := consumers.LoadToolResponse()
if err != nil {
log.Fatal("could not load raw results, file malformed: ", err)
}
+ numIssues := 0
for _, res := range responses {
scanStartTime := res.GetScanInfo().GetScanStartTime().AsTime()
+ numIssues += len(res.GetIssues())
for _, iss := range res.GetIssues() {
- log.Printf("Pushing %d, issues to es \n", len(responses))
b, err := getRawIssue(scanStartTime, res, iss)
if err != nil {
log.Fatal("Could not parse raw issue", err)
@@ -81,26 +91,29 @@ func main() {
}
}
}
+ slog.Info("Pushed", "numIssues", numIssues, "issues to Elasticsearch", "")
} else {
log.Print("Parsing Enriched results")
responses, err := consumers.LoadEnrichedToolResponse()
if err != nil {
log.Fatal("could not load enriched results, file malformed: ", err)
}
+ numIssues := 0
for _, res := range responses {
scanStartTime := res.GetOriginalResults().GetScanInfo().GetScanStartTime().AsTime()
+ numIssues += len(res.GetIssues())
for _, iss := range res.GetIssues() {
b, err := getEnrichedIssue(scanStartTime, res, iss)
if err != nil {
log.Fatal("Could not parse enriched issue", err)
}
res, err := es.Index(esIndex, bytes.NewBuffer(b))
- log.Printf("%+v", res)
- if err != nil {
- log.Fatal("Could not push enriched issue", err)
+ if err != nil || res.IsError() {
+ log.Fatal("Could not push enriched issue", err, "received", res.StatusCode)
}
}
}
+ slog.Info("Pushed", "numIssues", numIssues, "issues to Elasticsearch", "")
}
}
@@ -194,7 +207,12 @@ func getESClient() (*elasticsearch.Client, error) {
esConfig.Username = basicAuthUser
esConfig.Password = basicAuthPass
}
-
+ if esAPIKey != "" {
+ esConfig.APIKey = esAPIKey
+ }
+ if esCloudID != "" {
+ esConfig.CloudID = esCloudID
+ }
if len(esAddrs) > 0 {
esConfig.Addresses = esAddrs
}
@@ -217,11 +235,8 @@ func getESClient() (*elasticsearch.Client, error) {
if err := json.NewDecoder(res.Body).Decode(&info); err != nil {
return nil, err
}
- switch info.Version.Number[0] {
- case '8':
- // noop - we support this version
- default:
- err = fmt.Errorf("unsupported ES Server version %s", info.Version.Number)
+ if info.Version.Number[0] != '8' {
+ return nil, fmt.Errorf("unsupported ES Server version %s", info.Version.Number)
}
return es, err
}
diff --git a/components/consumers/elasticsearch/main_test.go b/components/consumers/elasticsearch/main_test.go
index f1032682d..718a5293a 100644
--- a/components/consumers/elasticsearch/main_test.go
+++ b/components/consumers/elasticsearch/main_test.go
@@ -11,7 +11,6 @@ import (
v1 "github.com/ocurity/dracon/api/proto/v1"
- "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -55,21 +54,21 @@ func TestEsPushBasicAuth(t *testing.T) {
if r.Method == http.MethodGet {
uname, pass, ok := r.BasicAuth()
- assert.Equal(t, uname, "foo")
- assert.Equal(t, pass, "bar")
- assert.Equal(t, ok, true)
+ require.Equal(t, uname, "foo")
+ require.Equal(t, pass, "bar")
+ require.Equal(t, ok, true)
_, err = w.Write([]byte(info))
require.NoError(t, err)
} else if r.Method == http.MethodPost {
// assert non authed operation (write results to index)
- assert.Equal(t, buf.String(), string(esIn))
- assert.Equal(t, r.RequestURI, "/"+esIndex+"/_doc")
+ require.Equal(t, buf.String(), string(esIn))
+ require.Equal(t, r.RequestURI, "/"+esIndex+"/_doc")
uname, pass, ok := r.BasicAuth()
- assert.Equal(t, uname, "foo")
- assert.Equal(t, pass, "bar")
- assert.Equal(t, ok, true)
+ require.Equal(t, uname, "foo")
+ require.Equal(t, pass, "bar")
+ require.Equal(t, ok, true)
_, err = w.Write([]byte(want))
require.NoError(t, err)
@@ -99,8 +98,8 @@ func TestEsPush(t *testing.T) {
_, err = w.Write([]byte(info))
} else if r.Method == http.MethodPost {
// assert non authed operation (write results to index)
- assert.Equal(t, buf.String(), string(esIn))
- assert.Equal(t, r.RequestURI, "/"+esIndex+"/_doc")
+ require.Equal(t, buf.String(), string(esIn))
+ require.Equal(t, r.RequestURI, "/"+esIndex+"/_doc")
_, err = w.Write([]byte(want))
}
require.NoError(t, err)
@@ -112,3 +111,39 @@ func TestEsPush(t *testing.T) {
_, err = client.Index(esIndex, bytes.NewBuffer(esIn))
require.NoError(t, err)
}
+func TestEsPushAPIKey(t *testing.T) {
+ esIndex = "dracon-es-test"
+
+ esStub := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ buf := new(bytes.Buffer)
+ _, err := buf.ReadFrom(r.Body)
+ require.NoError(t, err)
+
+ w.Header().Set("X-Elastic-Product", "Elasticsearch")
+ w.WriteHeader(http.StatusOK)
+
+ require.Equal(t, r.Header.Get("Authorization"), "APIKey foo")
+
+ if r.Method == http.MethodGet {
+ _, err = w.Write([]byte(info))
+ require.NoError(t, err)
+ } else if r.Method == http.MethodPost {
+ // assert non authed operation (write results to index)
+ require.Equal(t, buf.String(), string(esIn))
+ require.Equal(t, r.RequestURI, "/"+esIndex+"/_doc")
+
+ _, err = w.Write([]byte(want))
+ require.NoError(t, err)
+ }
+ }))
+ defer esStub.Close()
+ os.Setenv("ELASTICSEARCH_URL", esStub.URL)
+
+ // apikey ops
+ esAPIKey = "foo"
+ esCloudID = esStub.Config.Addr
+ client, err := getESClient()
+ require.NoError(t, err)
+ _, err = client.Index(esIndex, bytes.NewBuffer(esIn))
+ require.NoError(t, err)
+}
diff --git a/components/consumers/elasticsearch/task.yaml b/components/consumers/elasticsearch/task.yaml
index 714af7af3..ad33e59fe 100644
--- a/components/consumers/elasticsearch/task.yaml
+++ b/components/consumers/elasticsearch/task.yaml
@@ -14,6 +14,18 @@ spec:
- name: consumer-elasticsearch-description-template
type: string
default: ""
+ - name: consumer-elasticsearch-api-key
+ type: string
+ default: ""
+ - name: consumer-elasticsearch-index-name
+ type: string
+ default: ""
+ - name: consumer-elasticsearch-index
+ type: string
+ default: ""
+ - name: consumer-elasticsearch-cloud-id
+ type: string
+ default: ""
workspaces:
- name: output
description: The workspace containing the source-code to scan.
@@ -22,11 +34,11 @@ spec:
imagePullPolicy: IfNotPresent
image: '{{ default "ghcr.io/ocurity/dracon" .Values.image.registry }}/components/consumers/elasticsearch:{{ .Chart.AppVersion }}'
command: ["/app/components/consumers/elasticsearch/elasticsearch"]
- env:
- - name: ELASTICSEARCH_URL
- value: "$(params.consumer-elasticsearch-url)"
args: [
"-in", "$(workspaces.output.path)/.dracon/enrichers/",
- "-es-index", "dracon",
- "-descriptionTemplate","$(params.consumer-elasticsearch-description-template)"
+ "-descriptionTemplate","$(params.consumer-elasticsearch-description-template)",
+ "-esIndex", "$(params.consumer-elasticsearch-index-name)",
+ "-esAPIKey", "$(params.consumer-elasticsearch-api-key)",
+ "-esURL", "$(params.consumer-elasticsearch-url)",
+ "-esCloudID", "$(params.consumer-elasticsearch-cloud-id)",
]
diff --git a/components/consumers/jira/Dockerfile b/components/consumers/jira/Dockerfile
deleted file mode 100644
index 003b59928..000000000
--- a/components/consumers/jira/Dockerfile
+++ /dev/null
@@ -1,7 +0,0 @@
-FROM alpine:3.20
-
-RUN apk add --no-cache ca-certificates
-
-COPY ./components/consumers/jira/jira /app/components/consumers/jira/jira
-
-ENTRYPOINT ["/app/components/consumers/jira/jira"]
diff --git a/components/consumers/jira/Makefile b/components/consumers/jira/Makefile
deleted file mode 100644
index bb2408a88..000000000
--- a/components/consumers/jira/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-.PHONY: container publish
-
-CONTAINER_REPO=
-DRACON_VERSION=
-SOURCE_CODE_REPO=
-PRODUCER_AGGREGATOR_BASE_IMAGE=$(shell test -e .custom_image && cat .custom_image || echo "scratch")
-
-DOCKER=docker
-
-container:
- $(DOCKER) build --tag $(CONTAINER_REPO)/components/consumers/jira:$(DRACON_VERSION) \
- --file Dockerfile \
- $$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \
- ../../../bin 1>&2
-
-publish:
- $(DOCKER) push $(CONTAINER_REPO)/components/consumers/jira:$(DRACON_VERSION) 1>&2
diff --git a/components/consumers/pdf/Dockerfile b/components/consumers/pdf/Dockerfile
index 3946bbbef..b2ffb4a6b 100644
--- a/components/consumers/pdf/Dockerfile
+++ b/components/consumers/pdf/Dockerfile
@@ -1,11 +1,11 @@
FROM golang:latest
WORKDIR /playwright
-RUN go mod init github.com/ocurity/pdf-consumer &&\
- go get -u github.com/playwright-community/playwright-go &&\
- go run github.com/playwright-community/playwright-go/cmd/playwright@latest install --with-deps
+RUN go mod init github.com/ocurity/pdf-consumer && \
+ go get -u github.com/playwright-community/playwright-go && \
+ go run github.com/playwright-community/playwright-go/cmd/playwright@latest install --with-deps
ENV PATH="${PATH}:/go/pkg/mod/github.com/playwright-community"
COPY components/consumers/pdf/pdf /playwright/pdf
COPY components/consumers/pdf/default.html /playwright/default.html
-ENTRYPOINT ["/playwright/pdf"]
\ No newline at end of file
+ENTRYPOINT ["/playwright/pdf"]
diff --git a/components/consumers/slack/Dockerfile b/components/consumers/slack/Dockerfile
deleted file mode 100644
index 8d0a1774e..000000000
--- a/components/consumers/slack/Dockerfile
+++ /dev/null
@@ -1,7 +0,0 @@
-FROM alpine:3.20
-
-RUN apk add --no-cache ca-certificates
-
-COPY ./components/consumers/slack/slack /app/components/consumers/slack/slack
-
-ENTRYPOINT ["/app/components/consumers/slack/slack"]
\ No newline at end of file
diff --git a/components/consumers/slack/Makefile b/components/consumers/slack/Makefile
deleted file mode 100644
index abf3c1326..000000000
--- a/components/consumers/slack/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-.PHONY: container publish
-
-CONTAINER_REPO=
-DRACON_VERSION=
-SOURCE_CODE_REPO=
-PRODUCER_AGGREGATOR_BASE_IMAGE=$(shell test -e .custom_image && cat .custom_image || echo "scratch")
-
-DOCKER=docker
-
-container:
- $(DOCKER) build --tag $(CONTAINER_REPO)/components/consumers/slack:$(DRACON_VERSION) \
- --file Dockerfile \
- $$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \
- ../../../bin 1>&2
-
-publish:
- $(DOCKER) push $(CONTAINER_REPO)/components/consumers/slack:$(DRACON_VERSION) 1>&2
diff --git a/components/producers/aggregator/Dockerfile b/components/producers/aggregator/Dockerfile
deleted file mode 100644
index 3f74d3b26..000000000
--- a/components/producers/aggregator/Dockerfile
+++ /dev/null
@@ -1,6 +0,0 @@
-ARG PRODUCER_AGGREGATOR_BASE_IMAGE
-FROM ${PRODUCER_AGGREGATOR_BASE_IMAGE}
-
-COPY ./components/producers/aggregator/aggregator-parser /app/components/producers/aggregator/tagger
-
-ENTRYPOINT ["/app/components/producers/aggregator/tagger"]
diff --git a/components/producers/aggregator/Makefile b/components/producers/aggregator/Makefile
index bc174363f..2e3bcc0c8 100644
--- a/components/producers/aggregator/Makefile
+++ b/components/producers/aggregator/Makefile
@@ -3,15 +3,17 @@
CONTAINER_REPO=
DRACON_VERSION=
SOURCE_CODE_REPO=
-PRODUCER_AGGREGATOR_BASE_IMAGE=$(shell test -e .custom_image && cat .custom_image || echo "scratch")
+BUILD_ARCHITECTURE=
DOCKER=docker
container:
$(DOCKER) build --tag $(CONTAINER_REPO)/components/producers/tagger:$(DRACON_VERSION) \
- --file Dockerfile \
+ --build-arg EXECUTABLE_SRC_PATH=components/producers/aggregator/$(BUILD_ARCHITECTURE)/aggregator-parser \
+ --build-arg EXECUTABLE_TARGET_PATH=components/producers/aggregator/tagger \
$$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \
- --build-arg PRODUCER_AGGREGATOR_BASE_IMAGE=$(PRODUCER_AGGREGATOR_BASE_IMAGE) ../../../bin 1>&2
+ --platform "$(BUILD_ARCHITECTURE)" \
+ --file "${BASE_IMAGE_PATH}" ../../../bin 1>&2
publish:
$(DOCKER) push $(CONTAINER_REPO)/components/producers/tagger:$(DRACON_VERSION) 1>&2
diff --git a/components/producers/github-code-scanning/Dockerfile b/components/producers/github-code-scanning/Dockerfile
deleted file mode 100644
index 8fe764be4..000000000
--- a/components/producers/github-code-scanning/Dockerfile
+++ /dev/null
@@ -1,7 +0,0 @@
-FROM alpine:3.20
-
-RUN apk add --no-cache ca-certificates
-
-COPY ./components/producers/github-code-scanning/github-code-scanning-parser /app/components/producers/github-code-scanning/github-code-scanning-parser
-
-ENTRYPOINT ["/app/components/producers/github-code-scanning/github-code-scanning-parser"]
diff --git a/components/producers/github-code-scanning/Makefile b/components/producers/github-code-scanning/Makefile
deleted file mode 100644
index 949c455e1..000000000
--- a/components/producers/github-code-scanning/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-.PHONY: container publish
-
-CONTAINER_REPO=
-DRACON_VERSION=
-SOURCE_CODE_REPO=
-PRODUCER_AGGREGATOR_BASE_IMAGE=$(shell test -e .custom_image && cat .custom_image || echo "scratch")
-
-DOCKER=docker
-
-container:
- $(DOCKER) build --tag $(CONTAINER_REPO)/components/producers/github-code-scanning:$(DRACON_VERSION) \
- --file Dockerfile \
- $$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \
- ../../../bin 1>&2
-
-publish:
- $(DOCKER) push $(CONTAINER_REPO)/components/producers/github-code-scanning:$(DRACON_VERSION) 1>&2
diff --git a/components/producers/ossf-scorecard/Dockerfile b/components/producers/ossf-scorecard/Dockerfile
deleted file mode 100644
index d81c6bc86..000000000
--- a/components/producers/ossf-scorecard/Dockerfile
+++ /dev/null
@@ -1,8 +0,0 @@
-ARG OSSF_SCORECARD_SAFETY_BASE_IMAGE
-FROM gcr.io/openssf/scorecard:stable
-
-FROM ${OSSF_SCORECARD_SAFETY_BASE_IMAGE}
-
-COPY --from=0 /scorecard /scorecard
-
-ENTRYPOINT ["/scorecard"]
\ No newline at end of file
diff --git a/components/producers/ossf-scorecard/Makefile b/components/producers/ossf-scorecard/Makefile
deleted file mode 100644
index e93faa1f5..000000000
--- a/components/producers/ossf-scorecard/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-.PHONY: extras publish-extras
-
-CONTAINER_REPO=
-DRACON_VERSION=
-OSSF_SCORECARD_SAFETY_BASE_IMAGE=$(shell test -e .custom_image && cat .custom_image || echo "alpine:latest")
-
-DOCKER=docker
-
-extras:
- $(DOCKER) build --tag $(CONTAINER_REPO)/components/producers/ossf-scorecard/scorecard-dracon:$(DRACON_VERSION) \
- --file Dockerfile \
- $$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \
- --build-arg OSSF_SCORECARD_SAFETY_BASE_IMAGE=$(OSSF_SCORECARD_SAFETY_BASE_IMAGE) ../../.. 1>&2
-
-publish-extras:
- $(DOCKER) push $(CONTAINER_REPO)/components/producers/ossf-scorecard/scorecard-dracon:$(DRACON_VERSION) 1>&2
diff --git a/components/producers/typescript-eslint/eslint-wrapper/Dockerfile b/components/producers/typescript-eslint/eslint-wrapper/Dockerfile
index 134be31fd..a5847bfd9 100644
--- a/components/producers/typescript-eslint/eslint-wrapper/Dockerfile
+++ b/components/producers/typescript-eslint/eslint-wrapper/Dockerfile
@@ -1,10 +1,11 @@
ARG ESLINT_WRAPPER_BASE_IMAGE
-FROM ${ESLINT_WRAPPER_BASE_IMAGE}
+FROM ${ESLINT_WRAPPER_BASE_IMAGE:-node:lts}
+ARG BUILD_ARCHITECTURE
WORKDIR /home/node/workspace
COPY components/producers/typescript-eslint/eslint-wrapper/eslintrc.js /home/node/workspace
COPY components/producers/typescript-eslint/eslint-wrapper/package.json /home/node/workspace
-COPY bin/components/producers/typescript-eslint/eslint-wrapper/eslint-wrapper-parser /home/node/workspace/
+COPY bin/components/producers/typescript-eslint/eslint-wrapper/${BUILD_ARCHITECTURE}/eslint-wrapper-parser /home/node/workspace/
RUN npm uninstall --save bcrypt &&\
npm install --save-dev \
@@ -14,4 +15,4 @@ RUN npm uninstall --save bcrypt &&\
eslint-plugin-no-unsanitized \
eslint-plugin-security-node
-ENTRYPOINT [ "/home/node/workspace/eslint-wrapper-parser"]
+ENTRYPOINT ["/home/node/workspace/eslint-wrapper-parser"]
diff --git a/components/producers/typescript-eslint/eslint-wrapper/Makefile b/components/producers/typescript-eslint/eslint-wrapper/Makefile
index a4e344bfc..845557f1b 100644
--- a/components/producers/typescript-eslint/eslint-wrapper/Makefile
+++ b/components/producers/typescript-eslint/eslint-wrapper/Makefile
@@ -2,7 +2,7 @@
CONTAINER_REPO=
DRACON_VERSION=
-ESLINT_WRAPPER_BASE_IMAGE=$(shell test -e .custom_image && cat .custom_image || echo "node:lts")
+BUILD_ARCHITECTURE=
DOCKER=docker
@@ -10,4 +10,6 @@ container:
$(DOCKER) build --tag $(CONTAINER_REPO)/components/producers/typescript-eslint/eslint-wrapper:$(DRACON_VERSION) \
--file Dockerfile \
$$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \
- --build-arg ESLINT_WRAPPER_BASE_IMAGE=$(ESLINT_WRAPPER_BASE_IMAGE) ../../../.. 1>&2
+ --build-arg ESLINT_WRAPPER_BASE_IMAGE=$(ESLINT_WRAPPER_BASE_IMAGE) \
+ --build-arg BUILD_ARCHITECTURE=$(BUILD_ARCHITECTURE) \
+ ../../../.. 1>&2
diff --git a/containers/Dockerfile.base b/containers/Dockerfile.base
new file mode 100644
index 000000000..5f3c57bae
--- /dev/null
+++ b/containers/Dockerfile.base
@@ -0,0 +1,21 @@
+FROM golang:alpine AS builder
+
+ARG EXECUTABLE_SRC_PATH
+ARG EXECUTABLE_TARGET_PATH
+ENV EXECUTABLE_TARGET_PATH=${EXECUTABLE_TARGET_PATH}
+COPY ${EXECUTABLE_SRC_PATH} /app/${EXECUTABLE_TARGET_PATH}
+
+RUN apk update && \
+ apk upgrade && \
+ apk add --no-cache ca-certificates && \
+ update-ca-certificates && \
+ ln -s /app/${EXECUTABLE_TARGET_PATH} /bin/component
+
+FROM scratch
+
+ARG EXECUTABLE_TARGET_PATH
+COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
+COPY --from=builder /app/${EXECUTABLE_TARGET_PATH} /app/${EXECUTABLE_TARGET_PATH}
+COPY --from=builder /bin/component /bin/component
+
+ENTRYPOINT ["/bin/component"]
diff --git a/containers/Dockerfile.draconctl b/containers/Dockerfile.draconctl
index 01b66bdfe..05ef77304 100644
--- a/containers/Dockerfile.draconctl
+++ b/containers/Dockerfile.draconctl
@@ -1,9 +1,13 @@
ARG BASE_MIGRATION_IMAGE
+
FROM ${BASE_MIGRATION_IMAGE:-scratch}
-LABEL org.opencontainers.image.description "Draconctl is a command line tool for interacting with Dracon, you can find documentation for it at github.com/ocurity/dracon"
+ARG GOOS=linux
+ARG GOARCH=amd64
+
+LABEL org.opencontainers.image.description="Draconctl is a command line tool for interacting with Dracon, you can find documentation for it at github.com/ocurity/dracon"
-COPY ./bin/cmd/draconctl /bin/draconctl
+COPY ./bin/cmd/${GOOS}/${GOARCH}/draconctl /bin/draconctl
COPY ./pkg/enrichment/migrations /etc/dracon/migrations/enrichment
-ENTRYPOINT [ "/bin/draconctl" ]
+ENTRYPOINT ["/bin/draconctl"]
diff --git a/deploy/dracon/chart/values.yaml b/deploy/dracon/chart/values.yaml
index 333da2551..95a75adf2 100644
--- a/deploy/dracon/chart/values.yaml
+++ b/deploy/dracon/chart/values.yaml
@@ -38,9 +38,10 @@ arangodb:
className: ""
host: ""
-postgresql:
- # if set, a PostgreSQL instance will be deployed
- enabled: true
+# this section controls the database that components have access to
+# the database should use the Postgres dialect.
+# the database is used by the deduplication enricher
+database: &psqlConfig
host: ""
auth:
username: ""
@@ -50,19 +51,20 @@ postgresql:
querystringargs: ""
fullnameOverride: ""
+postgresql:
+ # if set, a PostgreSQL instance will be deployed
+ enabled: true
+ <<: *psqlConfig
+
+
# this section controls aspects of managing a database used to store deduplication enrichments
# the database should use the Postgres dialect.
deduplication-db-migrations:
# if set, a Job will be deployed that applies migrations to the deduplication database
# the Job will run as part of the post-install/post-upgrade hook
enabled: true
- database:
- host: ""
- auth:
- username: ""
- password: ""
- database: ""
- querystringargs: ""
+ database: *psqlConfig
+
image:
# registry to use for all
diff --git a/deploy/dracon/values/dev.yaml b/deploy/dracon/values/dev.yaml
index 1ea59896e..c6b807faa 100644
--- a/deploy/dracon/values/dev.yaml
+++ b/deploy/dracon/values/dev.yaml
@@ -30,28 +30,22 @@ arangodb:
image:
registry: kind-registry:5000/ocurity/dracon
-postgresql:
- enabled: true
-
-database:
+database: &psqlConfig
+ host: dracon-postgresql:5432
auth:
username: dracon
password: dracon
database: dracon
postgresPassword: dracon
querystringargs: "sslmode=disable"
- host: dracon-postgresql:5432
+
+postgresql:
+ enabled: true
+ <<: *psqlConfig
tekton:
enabled: true
deduplication-db-migrations:
enabled: true
- database:
- auth:
- username: dracon
- password: dracon
- database: dracon
- postgresPassword: dracon
- querystringargs: "sslmode=disable"
- host: dracon-postgresql:5432
+ database: *psqlConfig
diff --git a/docs/code-style/go/README.md b/docs/code-style/go/README.md
new file mode 100644
index 000000000..0b115b375
--- /dev/null
+++ b/docs/code-style/go/README.md
@@ -0,0 +1,4 @@
+# Code Style
+
+* [Enumeration Generation](enumeration-generation.md)
+* [Style](style.md)
diff --git a/docs/code-style/enumeration-generation.md b/docs/code-style/go/enumeration-generation.md
similarity index 100%
rename from docs/code-style/enumeration-generation.md
rename to docs/code-style/go/enumeration-generation.md
diff --git a/docs/code-style/go/style.md b/docs/code-style/go/style.md
new file mode 100644
index 000000000..352e2b8d3
--- /dev/null
+++ b/docs/code-style/go/style.md
@@ -0,0 +1,208 @@
+# Smithy Go Style Guide
+
+* [Introduction](#introduction)
+* [Guidelines](#guidelines)
+ * [Pointers to Interfaces](#pointers-to-interfaces)
+ * [Don't Panic](#dont-panic)
+
+## Introduction
+
+Styles are the conventions that govern our code. The term style is a bit of a
+misnomer, since these conventions cover far more than just source file
+formatting—gofmt handles that for us.
+
+The goal of this guide is to manage this complexity by describing in detail the
+Dos and Don'ts of writing Go code at Uber. These rules exist to keep the code
+base manageable while still allowing engineers to use Go language features
+productively.
+
+This documents idiomatic conventions in Go code that we follow at Smithy. A lot
+of these are general guidelines for Go, while others extend upon external
+resources:
+
+1. [Effective Go](https://go.dev/doc/effective_go)
+2. [Go Common Mistakes](https://go.dev/wiki/CommonMistakes)
+3. [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments)
+4. [Uber Go Style Guide](https://github.com/uber-go/guide/blob/master/style.md)
+
+## Guidelines
+
+### Pointers to Interfaces
+
+You almost never need a pointer to an interface. You should be passing
+interfaces as values—the underlying data can still be a pointer.
+
+An interface is two fields:
+
+1. A pointer to some type-specific information. You can think of this as
+ "type."
+2. Data pointer. If the data stored is a pointer, it’s stored directly. If
+ the data stored is a value, then a pointer to the value is stored.
+
+If you want interface methods to modify the underlying data, you must use a
+pointer.
+
+Pointer to interfaces are quite tedious to dereference.
+
+
+Bad | Good |
+
+
+
+```go
+type (
+ Shape interface {
+ Area() float64
+ }
+
+ Circle struct {
+ Radius float64
+ }
+)
+
+func (c *Circle) Area() float64 {
+ return 3.14 * c.Radius * c.Radius
+}
+
+func printArea(s *Shape) {
+ fmt.Println((*s).Area()) // Dereferencing pointer to interface
+}
+
+func main() {
+ c := &Circle{Radius: 5}
+
+ var s Shape = c // Assign Circle to Shape
+ printArea(&s) // Passing pointer to interface (bad)
+}
+```
+
+ |
+
+```go
+type (
+ Shape interface {
+ Area() float64
+ }
+
+ Circle struct {
+ Radius float64
+ }
+)
+
+func (c *Circle) Area() float64 {
+ return 3.14 * c.Radius * c.Radius
+}
+
+func printArea(s Shape) {
+ fmt.Println(s.Area()) // No need to dereference
+}
+
+func main() {
+ c := &Circle{Radius: 5}
+
+ var s Shape = c // Assign Circle to Shape
+ printArea(s) // Passing interface by value
+}
+```
+
+ |
+
+
+### Don't Panic
+
+Code running in production must avoid panics. Panics are a major source of
+[cascading failures](https://en.wikipedia.org/wiki/Cascading_failure).
+If an error occurs, the function must return an error and
+allow the caller to decide how to handle it.
+
+
+Bad | Good |
+
+
+
+```go
+func run(args []string) {
+ if len(args) == 0 {
+ panic("an argument is required")
+ }
+ // ...
+}
+
+func main() {
+ run(os.Args[1:])
+}
+```
+
+ |
+
+```go
+func run(args []string) error {
+ if len(args) == 0 {
+ return errors.New("an argument is required")
+ }
+ // ...
+ return nil
+}
+
+func main() {
+ if err := run(os.Args[1:]); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+```
+
+ |
+
+
+Panic/recover is not an error handling strategy.
+A program must panic only when
+something irrecoverable happens such as a nil dereference.
+An exception to this is
+program initialization: bad things at program startup that
+should abort the program may cause panic.
+
+```go
+var _statusTemplate = template.Must(template.New("name").Parse("_statusHTML"))
+```
+
+Even in tests, prefer `t.Fatal` or `t.FailNow` over panics to ensure that the
+test is marked as failed.
+
+
+Bad | Good |
+
+
+
+```go
+// func TestFoo(t *testing.T)
+
+f, err := os.CreateTemp("", "test")
+if err != nil {
+ panic("failed to set up test")
+}
+```
+
+ |
+
+```go
+// func TestFoo(t *testing.T)
+
+f, err := os.CreateTemp("", "test")
+if err != nil {
+ t.Fatal("failed to set up test")
+}
+```
+
+ |
+
+
+Panics should always be reported in a way that
+the team is aware that a service is having such
+issue. A tool like [Sentry](https://sentry.io/welcome/)
+is excellent to report such extreme issues and make
+sure that the team is notified to resolve the root cause.
+
+[It's useful to see the stacktrace at the moment
+of a process panicking](https://yourbasic.org/golang/recover-from-panic/).
+Logs, Traces and Metrics should be enriched with the latter.
diff --git a/docs/getting-started.md b/docs/getting-started.md
index ce6903a55..d4b4a57c7 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -176,7 +176,8 @@ KiND cluster, that's not the case. Instead, the registry's host is
deploy the pipelines and their image repositories will also have to be set to
this value.*
-*\*\*Make sure that you use the draconctl image that you pushed in the repository.*
+*\*\*Make sure that you use the draconctl image that you pushed in the
+repository.*
#### Using a different base image for your images
@@ -191,6 +192,45 @@ these components have their own Makefiles. In those cases you can place a
`.custom_image` file in the directory with the base image you wish to use and
that will be picked up by the Makefile and build the container.
+#### Building binaries and images for non linux/amd64 architecture
+
+*\*Useful for Apple Silicon chips users.*
+
+###### Containers
+
+If you need your images to be built for non linux/amd64 architecture,
+you can supply the flag `CONTAINER_OS_ARCH` for customisation of containers.
+
+This can be passed to the make commands used to build images, for example:
+
+```bash
+make CONTAINER_OS_ARCH=linux/arm64 components
+```
+
+or:
+
+```bash
+make CONTAINER_OS_ARCH=linux/arm64 publish-containers
+```
+
+By default, when `CONTAINER_ARCH` is not supplied, `linux/amd64` is used.
+
+###### Binaries
+
+`GOOS` and `GOARCH` can be supplied for customisation of the go binaries.
+
+These can be passed to the make commands used to build binaries, for example:
+
+```bash
+make GOOS=linux GOARCH=arm64 component-binaries
+```
+
+By default `linux` and `amd64` are used.
+
+\**For Apple Silicon chips, you might want to use
+`GOOS=darwin` and `GOARCH=arm64` when building binaries
+locally for development.*
+
#### Deploying your custom Dracon components Helm package
You can package your components into a Helm package by running the following
diff --git a/package-lock.json b/package-lock.json
index a7f7bfbf0..98cec1b1c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4,9 +4,8 @@
"requires": true,
"packages": {
"": {
- "name": "dracon",
"devDependencies": {
- "remark-cli": "^12.0.0",
+ "remark-cli": "^12.0.1",
"remark-lint-list-item-indent": "^4.0.0",
"remark-lint-no-shell-dollars": "^4.0.0",
"remark-preset-lint-consistent": "^6.0.0",
@@ -698,10 +697,11 @@
}
},
"node_modules/import-meta-resolve": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-3.1.1.tgz",
- "integrity": "sha512-qeywsE/KC3w9Fd2ORrRDUw6nS/nLwZpXgfrOc2IILvZYnCaEMd+D56Vfg9k4G29gIeVi3XKql1RQatME8iYsiw==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz",
+ "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==",
"dev": true,
+ "license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
@@ -915,16 +915,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/load-plugin/node_modules/import-meta-resolve": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz",
- "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==",
- "dev": true,
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
"node_modules/longest-streak": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
@@ -1838,12 +1828,13 @@
}
},
"node_modules/remark-cli": {
- "version": "12.0.0",
- "resolved": "https://registry.npmjs.org/remark-cli/-/remark-cli-12.0.0.tgz",
- "integrity": "sha512-IGxCo2VsXC/GS2YdlF7+S8DsUiyULyiauik01NFoiMIrOlbDhXjrKLD8hYazwQdD67nw2k7cwOBIxcK/cbNd9Q==",
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/remark-cli/-/remark-cli-12.0.1.tgz",
+ "integrity": "sha512-2NAEOACoTgo+e+YAaCTODqbrWyhMVmlUyjxNCkTrDRHHQvH6+NbrnqVvQaLH/Q8Ket3v90A43dgAJmXv8y5Tkw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "import-meta-resolve": "^3.0.0",
+ "import-meta-resolve": "^4.0.0",
"markdown-extensions": "^2.0.0",
"remark": "^15.0.0",
"unified-args": "^11.0.0"
diff --git a/package.json b/package.json
index 386220237..1def70236 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,7 @@
]
},
"devDependencies": {
- "remark-cli": "^12.0.0",
+ "remark-cli": "^12.0.1",
"remark-lint-list-item-indent": "^4.0.0",
"remark-lint-no-shell-dollars": "^4.0.0",
"remark-preset-lint-consistent": "^6.0.0",
diff --git a/scripts/build_component_binary.sh b/scripts/build_component_binary.sh
index 64d97e651..1dc3380ac 100755
--- a/scripts/build_component_binary.sh
+++ b/scripts/build_component_binary.sh
@@ -19,6 +19,11 @@ echo "${1}" | grep -Eq ^components/consumers/.*$ && executable="${executable}" |
executable_src_path=$(dirname "${1}")
executable_path=$(dirname $(dirname "${1}"))/"${executable}"
-echo "building bin/${executable_path}/${executable}" > /dev/stderr
+# Customised binary per OS/ARCH.
+GOOS=${GOOS:-$(go env GOOS)}
+GOARCH=${GOARCH:-$(go env GOARCH)}
+out_bin_path="bin/${executable_src_path}/${GOOS}/${GOARCH}/${executable}"
-go build -o "bin/${executable_src_path}/${executable}" "./${executable_src_path}/main.go"
+echo "building $out_bin_path" > /dev/stderr
+
+CGO_ENABLED=0 go build -o $out_bin_path "./${executable_src_path}/main.go"
diff --git a/scripts/build_component_container.sh b/scripts/build_component_container.sh
index 2ad5e8d9e..860ff4485 100755
--- a/scripts/build_component_container.sh
+++ b/scripts/build_component_container.sh
@@ -4,38 +4,45 @@ set -e;
source ./scripts/util.sh
+# Sanity check for not arguments being passed.
if [ "$#" -eq 0 ]
then
- util::error "No directory provided to build"
+ util::error "No directory argument provided to build."
exit 1
fi
-executable=$(basename $(dirname "${1}"))
+dir_name="$1"
+GOOS="${GOOS}"
+GOARCH="${GOARCH}"
+build_architecture="${GOOS}/${GOARCH}"
-echo "${1}" | grep -Eq ^components/producers/.*$ && executable="${executable}-parser" || true
-echo "${1}" | grep -Eq ^components/enrichers/.*$ && executable="${executable}" || true
-echo "${1}" | grep -Eq ^components/consumers/.*$ && executable="${executable}" || true
+executable=$(basename $(dirname ${dir_name}))
-executable_src_path=$(dirname "${1}")
-executable_path=$(dirname "${1}")/"${executable}"
+echo ${dir_name} | grep -Eq ^components/producers/.*$ && executable="${executable}-parser" || true
+echo ${dir_name} | grep -Eq ^components/enrichers/.*$ && executable="${executable}" || true
+echo ${dir_name} | grep -Eq ^components/consumers/.*$ && executable="${executable}" || true
-if make -C "${executable_src_path}" --no-print-directory --dry-run container >/dev/null 2>&1
+EXECUTABLE_SRC_PATH="$(dirname ${dir_name})/${build_architecture}/${executable}"
+COMPONENT_PATH="$(dirname ${dir_name})"
+EXECUTABLE_TARGET_PATH="${COMPONENT_PATH}/${executable}"
+
+BASE_IMAGE_PATH=$(realpath ${BASE_IMAGE_PATH:-./containers/Dockerfile.base})
+
+if make -C "${COMPONENT_PATH}" --no-print-directory --dry-run container >/dev/null 2>&1
then
- make -C "${executable_src_path}" --no-print-directory --quiet container CONTAINER_REPO="${CONTAINER_REPO}" DRACON_VERSION="${DRACON_VERSION}"
+ make -C "${COMPONENT_PATH}" --no-print-directory --quiet container BASE_IMAGE_PATH="${BASE_IMAGE_PATH}" CONTAINER_REPO="${CONTAINER_REPO}" DRACON_VERSION="${DRACON_VERSION}" BUILD_ARCHITECTURE="${build_architecture}"
else
- dockerfile_template="
- FROM ${BASE_IMAGE:-scratch} \n
- COPY ${executable_path} /app/${executable_path} \n
- ENTRYPOINT ["/app/${executable_path}"] \n
- "
- dockerfile_path=$(mktemp)
- printf "${dockerfile_template}" > "${dockerfile_path}"
- docker build -t "${CONTAINER_REPO}/${executable_src_path}:${DRACON_VERSION}" \
+ docker build \
+ --build-arg EXECUTABLE_SRC_PATH="${EXECUTABLE_SRC_PATH}" \
+ --build-arg EXECUTABLE_TARGET_PATH="${EXECUTABLE_TARGET_PATH}" \
+ --tag "${CONTAINER_REPO}/${COMPONENT_PATH}:${DRACON_VERSION}" \
$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \
- -f "${dockerfile_path}" ./bin
+ --file "${BASE_IMAGE_PATH}" \
+ --platform "${build_architecture}" \
+ ./bin
fi
-if make -C "${executable_src_path}" --no-print-directory --dry-run extras >/dev/null 2>&1
+if make -C "${COMPONENT_PATH}" --no-print-directory --dry-run extras >/dev/null 2>&1
then
- make -C "${executable_src_path}" --no-print-directory --quiet extras CONTAINER_REPO="${CONTAINER_REPO}" DRACON_VERSION="${DRACON_VERSION}"
+ make -C "${COMPONENT_PATH}" --no-print-directory --quiet extras CONTAINER_REPO="${CONTAINER_REPO}" DRACON_VERSION="${DRACON_VERSION}"
fi