diff --git a/cmd/csaf_downloader/config.go b/cmd/csaf_downloader/config.go index 2c18ebe..df1fdf0 100644 --- a/cmd/csaf_downloader/config.go +++ b/cmd/csaf_downloader/config.go @@ -9,8 +9,10 @@ package main import ( + "crypto/tls" "net/http" + "github.com/csaf-poc/csaf_distribution/v2/internal/certs" "github.com/csaf-poc/csaf_distribution/v2/internal/filter" "github.com/csaf-poc/csaf_distribution/v2/internal/models" "github.com/csaf-poc/csaf_distribution/v2/internal/options" @@ -25,6 +27,9 @@ type config struct { Directory *string `short:"d" long:"directory" description:"DIRectory to store the downloaded files in" value-name:"DIR" toml:"directory"` Insecure bool `long:"insecure" description:"Do not check TLS certificates from provider" toml:"insecure"` IgnoreSignatureCheck bool `long:"ignoresigcheck" description:"Ignore signature check results, just warn on mismatch" toml:"ignoresigcheck"` + ClientCert *string `long:"client-cert" description:"TLS client certificate file (PEM encoded data)" value-name:"CERT-FILE" toml:"client_cert"` + ClientKey *string `long:"client-key" description:"TLS client private key file (PEM encoded data)" value-name:"KEY-FILE" toml:"client_key"` + ClientPassphrase *string `long:"client-passphrase" description:"Optional passphrase for the client certificate" value-name:"PASSPHRASE" toml:"client_passphrase"` Version bool `long:"version" description:"Display version of the binary" toml:"-"` Verbose bool `long:"verbose" short:"v" description:"Verbose output" toml:"verbose"` Rate *float64 `long:"rate" short:"r" description:"The average upper limit of https operations per second (defaults to unlimited)" toml:"rate"` @@ -41,6 +46,7 @@ type config struct { Config string `short:"c" long:"config" description:"Path to config TOML file" value-name:"TOML-FILE" toml:"-"` + clientCerts []tls.Certificate ignorePattern filter.PatternMatcher } @@ -90,7 +96,21 @@ func (cfg *config) compileIgnorePatterns() error { return nil } +// prepareCertificates loads the client side certificates used by the HTTP client. +func (cfg *config) prepareCertificates() error { + cert, err := certs.LoadCertificate( + cfg.ClientCert, cfg.ClientKey, cfg.ClientPassphrase) + if err != nil { + return err + } + cfg.clientCerts = cert + return nil +} + // prepare prepares internal state of a loaded configuration. func (cfg *config) prepare() error { + if err := cfg.prepareCertificates(); err != nil { + return err + } return cfg.compileIgnorePatterns() } diff --git a/cmd/csaf_downloader/downloader.go b/cmd/csaf_downloader/downloader.go index 8d6fd80..9720aa5 100644 --- a/cmd/csaf_downloader/downloader.go +++ b/cmd/csaf_downloader/downloader.go @@ -84,9 +84,14 @@ func (d *downloader) httpClient() util.Client { var tlsConfig tls.Config if d.cfg.Insecure { tlsConfig.InsecureSkipVerify = true - hClient.Transport = &http.Transport{ - TLSClientConfig: &tlsConfig, - } + } + + if len(d.cfg.clientCerts) != 0 { + tlsConfig.Certificates = d.cfg.clientCerts + } + + hClient.Transport = &http.Transport{ + TLSClientConfig: &tlsConfig, } client := util.Client(&hClient) diff --git a/docs/csaf_downloader.md b/docs/csaf_downloader.md index 6008e26..772b10c 100644 --- a/docs/csaf_downloader.md +++ b/docs/csaf_downloader.md @@ -7,24 +7,27 @@ A tool to download CSAF documents from CSAF providers. csaf_downloader [OPTIONS] domain... Application Options: - -d, --directory=DIR DIRectory to store the downloaded files in - --insecure Do not check TLS certificates from provider - --ignoresigcheck Ignore signature check results, just warn on mismatch - --version Display version of the binary - -v, --verbose Verbose output - -r, --rate= The average upper limit of https operations per second (defaults to unlimited) - -w, --worker=NUM NUMber of concurrent downloads (default: 2) - -t, --timerange=RANGE RANGE of time from which advisories to download - -f, --folder=FOLDER Download into a given FOLDER - -i, --ignorepattern=PATTERN Dont download files if there URLs match any of the given PATTERNs - -H, --header= One or more extra HTTP header fields - --validator=URL URL to validate documents remotely - --validatorcache=FILE FILE to cache remote validations - --validatorpreset=PRESETS One or more PRESETS to validate remotely (default: [mandatory]) - -c, --config=TOML-FILE Path to config TOML file + -d, --directory=DIR DIRectory to store the downloaded files in + --insecure Do not check TLS certificates from provider + --ignoresigcheck Ignore signature check results, just warn on mismatch + --client-cert=CERT-FILE TLS client certificate file (PEM encoded data) + --client-key=KEY-FILE TLS client private key file (PEM encoded data) + --client-passphrase=PASSPHRASE Optional passphrase for the client certificate + --version Display version of the binary + -v, --verbose Verbose output + -r, --rate= The average upper limit of https operations per second (defaults to unlimited) + -w, --worker=NUM NUMber of concurrent downloads (default: 2) + -t, --timerange=RANGE RANGE of time from which advisories to download + -f, --folder=FOLDER Download into a given FOLDER + -i, --ignorepattern=PATTERN Dont download files if there URLs match any of the given PATTERNs + -H, --header= One or more extra HTTP header fields + --validator=URL URL to validate documents remotely + --validatorcache=FILE FILE to cache remote validations + --validatorpreset=PRESETS One or more PRESETS to validate remotely (default: [mandatory]) + -c, --config=TOML-FILE Path to config TOML file Help Options: - -h, --help Show this help message + -h, --help Show this help message ``` Will download all CSAF documents for the given _domains_, by trying each as a CSAF provider. @@ -47,19 +50,22 @@ with `~` expanding to `$HOME` on unixoid systems and `%HOMEPATH` on Windows syst Supported options in config files: ``` -directory # not set by default -insecure = false -ignoresigcheck = false -verbose = false -# rate # set to unlimited -worker = 2 -# timerange # not set by default -# folder # not set by default -# ignorepattern # not set by default -# header # not set by default -# validator # not set by default -# validatorcache # not set by default -validatorpreset = ["mandatory"] +# directory # not set by default +insecure = false +# client_cert # not set by default +# client_key # not set by default +# client_passphrase # not set by default +ignoresigcheck = false +verbose = false +# rate # set to unlimited +worker = 2 +# timerange # not set by default +# folder # not set by default +# ignorepattern # not set by default +# header # not set by default +# validator # not set by default +# validatorcache # not set by default +validatorpreset = ["mandatory"] ``` The `timerange` parameter enables downloading advisories which last changes falls