mirror of
https://github.com/gocsaf/csaf.git
synced 2025-12-22 11:55:40 +01:00
Merge pull request #424 from csaf-poc/aggregator-client-certs
Aggregator: Add support for client certificates and extra header
This commit is contained in:
commit
f4d00cd9d8
3 changed files with 112 additions and 24 deletions
|
|
@ -20,6 +20,7 @@ import (
|
||||||
|
|
||||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||||
"github.com/csaf-poc/csaf_distribution/v2/csaf"
|
"github.com/csaf-poc/csaf_distribution/v2/csaf"
|
||||||
|
"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/filter"
|
||||||
"github.com/csaf-poc/csaf_distribution/v2/internal/options"
|
"github.com/csaf-poc/csaf_distribution/v2/internal/options"
|
||||||
"github.com/csaf-poc/csaf_distribution/v2/util"
|
"github.com/csaf-poc/csaf_distribution/v2/util"
|
||||||
|
|
@ -52,6 +53,15 @@ type provider struct {
|
||||||
|
|
||||||
// IgnorePattern is a list of patterns of advisory URLs to be ignored.
|
// IgnorePattern is a list of patterns of advisory URLs to be ignored.
|
||||||
IgnorePattern []string `toml:"ignorepattern"`
|
IgnorePattern []string `toml:"ignorepattern"`
|
||||||
|
|
||||||
|
// ExtraHeader adds extra HTTP header fields to client
|
||||||
|
ExtraHeader http.Header `toml:"header"`
|
||||||
|
|
||||||
|
ClientCert *string `toml:"client_cert"`
|
||||||
|
ClientKey *string `toml:"client_key"`
|
||||||
|
ClientPassphrase *string `toml:"client_passphrase"`
|
||||||
|
|
||||||
|
clientCerts []tls.Certificate
|
||||||
ignorePattern filter.PatternMatcher
|
ignorePattern filter.PatternMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,6 +84,10 @@ type config struct {
|
||||||
Passphrase *string `toml:"passphrase"`
|
Passphrase *string `toml:"passphrase"`
|
||||||
AllowSingleProvider bool `toml:"allow_single_provider"`
|
AllowSingleProvider bool `toml:"allow_single_provider"`
|
||||||
|
|
||||||
|
ClientCert *string `toml:"client_cert"`
|
||||||
|
ClientKey *string `toml:"client_key"`
|
||||||
|
ClientPassphrase *string `toml:"client_passphrase"`
|
||||||
|
|
||||||
// LockFile tries to lock to a given file.
|
// LockFile tries to lock to a given file.
|
||||||
LockFile *string `toml:"lock_file"`
|
LockFile *string `toml:"lock_file"`
|
||||||
|
|
||||||
|
|
@ -97,13 +111,18 @@ type config struct {
|
||||||
|
|
||||||
// IgnorePattern is a list of patterns of advisory URLs to be ignored.
|
// IgnorePattern is a list of patterns of advisory URLs to be ignored.
|
||||||
IgnorePattern []string `toml:"ignorepattern"`
|
IgnorePattern []string `toml:"ignorepattern"`
|
||||||
ignorePattern filter.PatternMatcher
|
|
||||||
|
// ExtraHeader adds extra HTTP header fields to client
|
||||||
|
ExtraHeader http.Header `toml:"header"`
|
||||||
|
|
||||||
Config string `short:"c" long:"config" description:"Path to config TOML file" value-name:"TOML-FILE" toml:"-"`
|
Config string `short:"c" long:"config" description:"Path to config TOML file" value-name:"TOML-FILE" toml:"-"`
|
||||||
|
|
||||||
keyMu sync.Mutex
|
keyMu sync.Mutex
|
||||||
key *crypto.Key
|
key *crypto.Key
|
||||||
keyErr error
|
keyErr error
|
||||||
|
|
||||||
|
clientCerts []tls.Certificate
|
||||||
|
ignorePattern filter.PatternMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
// configPaths are the potential file locations of the config file.
|
// configPaths are the potential file locations of the config file.
|
||||||
|
|
@ -217,20 +236,44 @@ func (c *config) privateOpenPGPKey() (*crypto.Key, error) {
|
||||||
func (c *config) httpClient(p *provider) util.Client {
|
func (c *config) httpClient(p *provider) util.Client {
|
||||||
|
|
||||||
hClient := http.Client{}
|
hClient := http.Client{}
|
||||||
|
|
||||||
|
var tlsConfig tls.Config
|
||||||
if p.Insecure != nil && *p.Insecure || c.Insecure != nil && *c.Insecure {
|
if p.Insecure != nil && *p.Insecure || c.Insecure != nil && *c.Insecure {
|
||||||
hClient.Transport = &http.Transport{
|
tlsConfig.InsecureSkipVerify = true
|
||||||
TLSClientConfig: &tls.Config{
|
}
|
||||||
InsecureSkipVerify: true,
|
|
||||||
},
|
// Use client certs if needed.
|
||||||
|
switch {
|
||||||
|
// Provider has precedence over global.
|
||||||
|
case len(p.clientCerts) != 0:
|
||||||
|
tlsConfig.Certificates = p.clientCerts
|
||||||
|
case len(c.clientCerts) != 0:
|
||||||
|
tlsConfig.Certificates = c.clientCerts
|
||||||
|
}
|
||||||
|
|
||||||
|
hClient.Transport = &http.Transport{
|
||||||
|
TLSClientConfig: &tlsConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
client := util.Client(&hClient)
|
||||||
|
|
||||||
|
// Add extra headers.
|
||||||
|
switch {
|
||||||
|
// Provider has precedence over global.
|
||||||
|
case len(p.ExtraHeader) > 0:
|
||||||
|
client = &util.HeaderClient{
|
||||||
|
Client: client,
|
||||||
|
Header: p.ExtraHeader,
|
||||||
|
}
|
||||||
|
case len(c.ExtraHeader) > 0:
|
||||||
|
client = &util.HeaderClient{
|
||||||
|
Client: client,
|
||||||
|
Header: c.ExtraHeader,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var client util.Client
|
|
||||||
|
|
||||||
if c.Verbose {
|
if c.Verbose {
|
||||||
client = &util.LoggingClient{Client: &hClient}
|
client = &util.LoggingClient{Client: client}
|
||||||
} else {
|
|
||||||
client = &hClient
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.Rate == nil && c.Rate == nil {
|
if p.Rate == nil && c.Rate == nil {
|
||||||
|
|
@ -325,7 +368,7 @@ func (c *config) setDefaults() {
|
||||||
func (p *provider) compileIgnorePatterns() error {
|
func (p *provider) compileIgnorePatterns() error {
|
||||||
pm, err := filter.NewPatternMatcher(p.IgnorePattern)
|
pm, err := filter.NewPatternMatcher(p.IgnorePattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("invalid ignore patterns for %q: %w", p.Name, err)
|
||||||
}
|
}
|
||||||
p.ignorePattern = pm
|
p.ignorePattern = pm
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -342,7 +385,37 @@ func (c *config) compileIgnorePatterns() error {
|
||||||
// Compile the patterns of the providers.
|
// Compile the patterns of the providers.
|
||||||
for _, p := range c.Providers {
|
for _, p := range c.Providers {
|
||||||
if err := p.compileIgnorePatterns(); err != nil {
|
if err := p.compileIgnorePatterns(); err != nil {
|
||||||
return fmt.Errorf("invalid ignore patterns for %q: %w", p.Name, err)
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepareCertificates loads the provider specific client side certificates
|
||||||
|
// used by the HTTP client.
|
||||||
|
func (p *provider) prepareCertificates() error {
|
||||||
|
cert, err := certs.LoadCertificate(
|
||||||
|
p.ClientCert, p.ClientKey, p.ClientPassphrase)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid certificates for %q: %w", p.Name, err)
|
||||||
|
}
|
||||||
|
p.clientCerts = cert
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepareCertificates loads the client side certificates used by the HTTP client.
|
||||||
|
func (c *config) prepareCertificates() error {
|
||||||
|
// Global certificates
|
||||||
|
cert, err := certs.LoadCertificate(
|
||||||
|
c.ClientCert, c.ClientKey, c.ClientPassphrase)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.clientCerts = cert
|
||||||
|
// Provider certificates
|
||||||
|
for _, p := range c.Providers {
|
||||||
|
if err := p.prepareCertificates(); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -355,17 +428,16 @@ func (c *config) prepare() error {
|
||||||
return errors.New("no providers given in configuration")
|
return errors.New("no providers given in configuration")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.compileIgnorePatterns(); err != nil {
|
for _, prepare := range []func() error{
|
||||||
return err
|
c.prepareCertificates,
|
||||||
|
c.compileIgnorePatterns,
|
||||||
|
c.Aggregator.Validate,
|
||||||
|
c.checkProviders,
|
||||||
|
c.checkMirror,
|
||||||
|
} {
|
||||||
|
if err := prepare(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
if err := c.Aggregator.Validate(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.checkProviders(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.checkMirror()
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,10 @@ interim_years // limiting the years for which interim documents are se
|
||||||
verbose // print more diagnostic output, e.g. https requests (default false)
|
verbose // print more diagnostic output, e.g. https requests (default false)
|
||||||
allow_single_provider // debugging option (default false)
|
allow_single_provider // debugging option (default false)
|
||||||
ignorepattern // patterns of advisory URLs to be ignored
|
ignorepattern // patterns of advisory URLs to be ignored
|
||||||
|
client_cert // path to client certificate to access access-protected advisories
|
||||||
|
client_key // path to client key to access access-protected advisories
|
||||||
|
client_passphrase // client passphrase to access access-protected advisories
|
||||||
|
header // adds extra HTTP header fields to the client
|
||||||
```
|
```
|
||||||
|
|
||||||
Next we have two TOML _tables_:
|
Next we have two TOML _tables_:
|
||||||
|
|
@ -125,6 +129,10 @@ update_interval
|
||||||
create_service_document
|
create_service_document
|
||||||
categories
|
categories
|
||||||
ignorepattern
|
ignorepattern
|
||||||
|
client_cert
|
||||||
|
client_key
|
||||||
|
client_passphrase
|
||||||
|
header
|
||||||
```
|
```
|
||||||
|
|
||||||
Where valid `name` and `domain` settings are required.
|
Where valid `name` and `domain` settings are required.
|
||||||
|
|
@ -196,6 +204,10 @@ insecure = true
|
||||||
# rate = 1.2
|
# rate = 1.2
|
||||||
# insecure = true
|
# insecure = true
|
||||||
write_indices = true
|
write_indices = true
|
||||||
|
client_cert = "./../devca1/testclient1.crt"
|
||||||
|
client_key = "./../devca1/testclient1-key.pem"
|
||||||
|
# client_passphrase =
|
||||||
|
# header =
|
||||||
|
|
||||||
[[providers]]
|
[[providers]]
|
||||||
name = "local-dev-provider3"
|
name = "local-dev-provider3"
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,10 @@ insecure = true
|
||||||
# rate = 1.2
|
# rate = 1.2
|
||||||
# insecure = true
|
# insecure = true
|
||||||
write_indices = true
|
write_indices = true
|
||||||
|
client_cert = "./../devca1/testclient1.crt"
|
||||||
|
client_key = "./../devca1/testclient1-key.pem"
|
||||||
|
# client_passphrase =
|
||||||
|
# header =
|
||||||
|
|
||||||
[[providers]]
|
[[providers]]
|
||||||
name = "local-dev-provider3"
|
name = "local-dev-provider3"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue