From c3ce9665e5e5ac8ec92d14cf5f14b9fb01eaefc8 Mon Sep 17 00:00:00 2001 From: Lucas Pape Date: Tue, 20 Jun 2023 19:36:07 +0200 Subject: [PATCH] feat(dtrack): expose mTLS configuration (#427) Signed-off-by: Lucas Pape --- README.md | 3 ++ internal/config.go | 6 +++ internal/processor/processor.go | 5 ++- internal/target/dtrack/dtrack_target.go | 50 ++++++++++++++++++++++--- 4 files changed, 58 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index cdf3ec96..752b2a89 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,9 @@ not present in the cluster anymore are removed from the configured targets (exce | `dtrack-base-url` | `true` when `dtrack` target is used | `""` | Dependency-Track base URL, e.g. 'https://dtrack.example.com' | | `dtrack-api-key` | `true` when `dtrack` target is used | `""` | Dependency-Track API key | | `dtrack-label-tag-matcher` | `false` | `""` | Dependency-Track Pod-Label-Tag matcher regex | +| `dtrack-ca-cert-file` | `false` | `""` | CA-Certificate filepath when using mTLS to connect to dtrack | +| `dtrack-client-cert-file` | `true` when `dtrack-ca-cert-file` is provided | `""` | Client-Certificate filepath when using mTLS to connect to dtrack | +| `dtrack-client-key-file` | `true` when `dtrack-ca-cert-file` is provided | `""` | Client-Key filepath when using mTLS to connect to dtrack | | `kubernetes-cluster-id` | `false` | `"default"` | Kubernetes Cluster ID (to be used in Dependency-Track or Job-Images) | Each image in the cluster is created as project with the full-image name (registry and image-path without tag) and the image-tag as project-version. diff --git a/internal/config.go b/internal/config.go index 62fa5b00..092246a7 100644 --- a/internal/config.go +++ b/internal/config.go @@ -22,6 +22,9 @@ type Config struct { DtrackBaseUrl string `yaml:"dtrackBaseUrl" env:"SBOM_DTRACK_BASE_URL" flag:"dtrack-base-url"` DtrackApiKey string `yaml:"dtrackApiKey" env:"SBOM_DTRACK_API_KEY" flag:"dtrack-api-key"` DtrackLabelTagMatcher string `yaml:"dtrackLabelTagMatcher" env:"SBOM_DTRACK_LABEL_TAG_MATCHER" flag:"dtrack-label-tag-matcher"` + DtrackCaCertFile string `yaml:"dtrackCaCertFile" env:"SBOM_DTRACK_CA_CERT_FILE" flag:"dtrack-ca-cert-file"` + DtrackClientCertFile string `yaml:"dtrackClientCertFile" env:"SBOM_DTRACK_CLIENT_CERT_FILE" flag:"dtrack-client-cert-file"` + DtrackClientKeyFile string `yaml:"dtrackClientKeyFile" env:"SBOM_DTRACK_CLIENT_KEY_FILE" flag:"dtrack-client-key-file"` KubernetesClusterId string `yaml:"kubernetesClusterId" env:"SBOM_KUBERNETES_CLUSTER_ID" flag:"kubernetes-cluster-id"` JobImage string `yaml:"jobImage" env:"SBOM_JOB_IMAGE" flag:"job-image"` JobImagePullSecret string `yaml:"jobImagePullSecret" env:"SBOM_JOB_IMAGE_PULL_SECRET" flag:"job-image-pull-secret"` @@ -56,6 +59,9 @@ var ( /* #nosec */ ConfigKeyDependencyTrackApiKey = "dtrack-api-key" ConfigKeyDependencyTrackLabelTagMatcher = "dtrack-label-tag-matcher" + ConfigKeyDependencyTrackCaCertFile = "dtrack-ca-cert-file" + ConfigKeyDependencyTrackClientCertFile = "dtrack-client-cert-file" + ConfigKeyDependencyTrackClientKeyFile = "dtrack-client-key-file" ConfigKeyKubernetesClusterId = "kubernetes-cluster-id" ConfigKeyJobImage = "job-image" /* #nosec */ diff --git a/internal/processor/processor.go b/internal/processor/processor.go index f6df472f..b296697e 100644 --- a/internal/processor/processor.go +++ b/internal/processor/processor.go @@ -135,8 +135,11 @@ func initTargets(k8s *kubernetes.KubeClient) []target.Target { baseUrl := internal.OperatorConfig.DtrackBaseUrl apiKey := internal.OperatorConfig.DtrackApiKey podLabelTagMatcher := internal.OperatorConfig.DtrackLabelTagMatcher + caCertFile := internal.OperatorConfig.DtrackCaCertFile + clientCertFile := internal.OperatorConfig.DtrackClientCertFile + clientKeyFile := internal.OperatorConfig.DtrackClientKeyFile k8sClusterId := internal.OperatorConfig.KubernetesClusterId - t := dtrack.NewDependencyTrackTarget(baseUrl, apiKey, podLabelTagMatcher, k8sClusterId) + t := dtrack.NewDependencyTrackTarget(baseUrl, apiKey, podLabelTagMatcher, caCertFile, clientCertFile, clientKeyFile, k8sClusterId) err = t.ValidateConfig() targets = append(targets, t) } else if ta == "oci" { diff --git a/internal/target/dtrack/dtrack_target.go b/internal/target/dtrack/dtrack_target.go index 87330337..ead9ced8 100644 --- a/internal/target/dtrack/dtrack_target.go +++ b/internal/target/dtrack/dtrack_target.go @@ -18,9 +18,14 @@ import ( ) type DependencyTrackTarget struct { + clientOptions []dtrack.ClientOption + baseUrl string apiKey string podLabelTagMatcher string + caCertFile string + clientCertFile string + clientKeyFile string k8sClusterId string imageProjectMap map[string]uuid.UUID } @@ -32,12 +37,15 @@ const ( podNamespaceTagKey = "namespace" ) -func NewDependencyTrackTarget(baseUrl, apiKey, podLabelTagMatcher, k8sClusterId string) *DependencyTrackTarget { +func NewDependencyTrackTarget(baseUrl, apiKey, podLabelTagMatcher, caCertFile, clientCertFile, clientKeyFile, k8sClusterId string) *DependencyTrackTarget { return &DependencyTrackTarget{ baseUrl: baseUrl, apiKey: apiKey, - k8sClusterId: k8sClusterId, podLabelTagMatcher: podLabelTagMatcher, + caCertFile: caCertFile, + clientCertFile: clientCertFile, + clientKeyFile: clientKeyFile, + k8sClusterId: k8sClusterId, } } @@ -48,10 +56,36 @@ func (g *DependencyTrackTarget) ValidateConfig() error { if g.apiKey == "" { return fmt.Errorf("%s is empty", internal.ConfigKeyDependencyTrackApiKey) } + if g.caCertFile != "" { + if g.clientCertFile == "" { + return fmt.Errorf( + "%s provided but %s is empty", + internal.ConfigKeyDependencyTrackCaCertFile, + internal.ConfigKeyDependencyTrackClientCertFile, + ) + } + + if g.clientKeyFile == "" { + return fmt.Errorf( + "%s provided but %s is empty", + internal.ConfigKeyDependencyTrackCaCertFile, + internal.ConfigKeyDependencyTrackClientKeyFile, + ) + } + } + return nil } func (g *DependencyTrackTarget) Initialize() error { + g.clientOptions = []dtrack.ClientOption{} + + g.clientOptions = append(g.clientOptions, dtrack.WithAPIKey(g.apiKey)) + + if len(g.caCertFile) > 0 { + g.clientOptions = append(g.clientOptions, dtrack.WithMTLS(g.caCertFile, g.clientCertFile, g.clientKeyFile)) + } + return nil } @@ -63,7 +97,7 @@ func (g *DependencyTrackTarget) ProcessSbom(ctx *target.TargetContext) error { return nil } - client, err := dtrack.NewClient(g.baseUrl, dtrack.WithAPIKey(g.apiKey)) + client, err := dtrack.NewClient(g.baseUrl, g.clientOptions...) if err != nil { logrus.WithError(err).Errorf("failed to init dtrack client") return err @@ -135,7 +169,10 @@ func (g *DependencyTrackTarget) ProcessSbom(ctx *target.TargetContext) error { } func (g *DependencyTrackTarget) LoadImages() []*libk8s.RegistryImage { - client, _ := dtrack.NewClient(g.baseUrl, dtrack.WithAPIKey(g.apiKey)) + client, err := dtrack.NewClient(g.baseUrl, g.clientOptions...) + if err != nil { + logrus.WithError(err).Errorf("failed to init dtrack client") + } if g.imageProjectMap == nil { g.imageProjectMap = make(map[string]uuid.UUID) @@ -200,7 +237,10 @@ func (g *DependencyTrackTarget) Remove(images []*libk8s.RegistryImage) { g.LoadImages() } - client, _ := dtrack.NewClient(g.baseUrl, dtrack.WithAPIKey(g.apiKey)) + client, err := dtrack.NewClient(g.baseUrl, g.clientOptions...) + if err != nil { + logrus.WithError(err).Errorf("failed to init dtrack client") + } for _, img := range images { uuid := g.imageProjectMap[img.ImageID]