Skip to content

Commit

Permalink
Add capath flag to provide custom CA certificates (#106)
Browse files Browse the repository at this point in the history
This is required for private registries an air-gapped environments.

Signed-off-by: m.nabokikh <[email protected]>
  • Loading branch information
nabokihms authored Jan 5, 2024
1 parent 58fcb41 commit e8deedd
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 10 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,12 @@ spec:
```
Usage of k8s-image-availability-exporter:
-allow-plain-http
whether to fallback to HTTP scheme for registries that don't support HTTPS
-bind-address string
address:port to bind /metrics endpoint to (default ":8080")
-capath value
path to a file that contains CA certificates in the PEM format
-check-interval duration
image re-check interval (default 1m0s)
-default-registry string
Expand Down
18 changes: 16 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"flag"
"fmt"
"log"
"net/http"
"regexp"
"strings"
Expand All @@ -28,13 +27,16 @@ import (
)

func main() {
cp := &caPaths{}

imageCheckInterval := flag.Duration("check-interval", time.Minute, "image re-check interval")
ignoredImagesStr := flag.String("ignored-images", "", "tilde-separated image regexes to ignore, each image will be checked against this list of regexes")
bindAddr := flag.String("bind-address", ":8080", "address:port to bind /metrics endpoint to")
namespaceLabels := flag.String("namespace-label", "", "namespace label for checks")
insecureSkipVerify := flag.Bool("skip-registry-cert-verification", false, "whether to skip registries' certificate verification")
plainHTTP := flag.Bool("allow-plain-http", false, "whether to fallback to HTTP scheme for registries that don't support HTTPS") // named after the ctr cli flag
defaultRegistry := flag.String("default-registry", "", fmt.Sprintf("default registry to use in absence of a fully qualified image name, defaults to %q", name.DefaultRegistry))
flag.Var(cp, "capath", "path to a file that contains CA certificates in the PEM format") // named after the curl cli flag

flag.Parse()

Expand Down Expand Up @@ -78,6 +80,7 @@ func main() {
kubeClient,
*insecureSkipVerify,
*plainHTTP,
*cp,
regexes,
*defaultRegistry,
*namespaceLabels,
Expand All @@ -87,7 +90,7 @@ func main() {
http.Handle("/metrics", promhttp.Handler())
http.HandleFunc("/healthz", handlers.Healthz)
go func() {
log.Fatal(http.ListenAndServe(*bindAddr, nil))
logrus.Fatal(http.ListenAndServe(*bindAddr, nil))
}()

handlers.UpdateHealth(true)
Expand All @@ -97,3 +100,14 @@ func main() {
liveTicksCounter.Inc()
}, *imageCheckInterval, stopCh)
}

type caPaths []string

func (c *caPaths) String() string {
return fmt.Sprintf("%v", *c)
}

func (c *caPaths) Set(value string) error {
*c = append(*c, value)
return nil
}
8 changes: 4 additions & 4 deletions pkg/logging/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package logging
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
log "github.com/sirupsen/logrus"
"github.com/sirupsen/logrus"
)

func NewPrometheusHook() *PrometheusHook {
Expand All @@ -24,11 +24,11 @@ type PrometheusHook struct {
counter *prometheus.CounterVec
}

func (h *PrometheusHook) Levels() []log.Level {
return log.AllLevels
func (h *PrometheusHook) Levels() []logrus.Level {
return logrus.AllLevels
}

func (h *PrometheusHook) Fire(e *log.Entry) error {
func (h *PrometheusHook) Fire(e *logrus.Entry) error {
h.counter.WithLabelValues(e.Level.String()).Inc()
return nil
}
11 changes: 10 additions & 1 deletion pkg/registry/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package registry
import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"net/http"
"regexp"
Expand Down Expand Up @@ -66,16 +67,24 @@ func NewChecker(
kubeClient *kubernetes.Clientset,
skipVerify bool,
plainHTTP bool,
caPths []string,
ignoredImages []regexp.Regexp,
defaultRegistry string,
namespaceLabel string,
) *Checker {

informerFactory := informers.NewSharedInformerFactory(kubeClient, time.Hour)

customTransport := http.DefaultTransport.(*http.Transport).Clone()
if skipVerify {
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
} else if len(caPths) > 0 {
rootCAs := x509.NewCertPool()
for _, caPath := range caPths {
if ok := rootCAs.AppendCertsFromPEM([]byte(caPath)); !ok {
logrus.Fatalf("Error parsing CA file %s", caPath)
}
}
customTransport.TLSClientConfig = &tls.Config{RootCAs: rootCAs}
}

rc := &Checker{
Expand Down
6 changes: 3 additions & 3 deletions pkg/registry/indexers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/flant/k8s-image-availability-exporter/pkg/store"
"github.com/google/go-containerregistry/pkg/authn"
kubeauth "github.com/google/go-containerregistry/pkg/authn/kubernetes"
log "github.com/sirupsen/logrus"
"github.com/sirupsen/logrus"
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -201,7 +201,7 @@ func (ci ControllerIndexers) ExtractPullSecretRefs(obj interface{}) (ret []strin

saRaw, exists, err := ci.serviceAccountIndexer.GetByKey(fmt.Sprintf("%s/%s", cis.Namespace, serviceAccountName))
if err != nil {
log.Warn(err)
logrus.Warn(err)
return
}

Expand Down Expand Up @@ -284,7 +284,7 @@ func (ci ControllerIndexers) GetKeychainForImage(image string) authn.Keychain {

kc, err := kubeauth.NewFromPullSecrets(context.TODO(), dereferencedPullSecrets)
if err != nil {
log.Panic(err)
logrus.Panic(err)
}

return kc
Expand Down

0 comments on commit e8deedd

Please sign in to comment.