mirror of
https://github.com/gocsaf/csaf.git
synced 2025-12-22 11:55:40 +01:00
Change openpgp key providing code to use local directory
* Adjust provider and aggregator to copy the used openpgp pubkey into a locally provided directory `openpgp` beside the `prodiver-metadata.json`. This more robust and self-reliant than using a public pubkey server, which is the reason why the CSAF 2.0 csd02 mentions it as example in "7.1.20 Requirement 20: Public OpenPGP Key". * Improve aggregator by removing a typo `aggreator` from one written paths. (Done with this change as it also affects the openpgp/ paths writing.) solve #85
This commit is contained in:
parent
a849ac0d5f
commit
69f0f3499a
8 changed files with 229 additions and 97 deletions
|
|
@ -15,7 +15,6 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
|
|
@ -31,7 +30,6 @@ const (
|
|||
defaultFolder = "/var/www"
|
||||
defaultWeb = "/var/www/html"
|
||||
defaultDomain = "https://example.com"
|
||||
defaultOpenPGPURL = "https://openpgp.circl.lu/pks/lookup?op=get&search=${FINGERPRINT}" // Default OpenPGP URL.
|
||||
)
|
||||
|
||||
type provider struct {
|
||||
|
|
@ -54,8 +52,8 @@ type config struct {
|
|||
Insecure *bool `toml:"insecure"`
|
||||
Aggregator csaf.AggregatorInfo `toml:"aggregator"`
|
||||
Providers []*provider `toml:"providers"`
|
||||
Key string `toml:"key"`
|
||||
OpenPGPURL string `toml:"openpgp_url"`
|
||||
OpenPGPPrivateKey string `toml:"openpgp_private_key"`
|
||||
OpenPGPPublicKey string `toml:"openpgp_public_key"`
|
||||
Passphrase *string `toml:"passphrase"`
|
||||
AllowSingleProvider bool `toml:"allow_single_provider"`
|
||||
|
||||
|
|
@ -80,17 +78,8 @@ func (c *config) runAsMirror() bool {
|
|||
*c.Aggregator.Category == csaf.AggregatorAggregator
|
||||
}
|
||||
|
||||
func (c *config) GetOpenPGPURL(key *crypto.Key) string {
|
||||
if key == nil {
|
||||
return c.OpenPGPURL
|
||||
}
|
||||
return strings.NewReplacer(
|
||||
"${FINGERPRINT}", "0x"+key.GetFingerprint(),
|
||||
"${KEY_ID}", "0x"+key.GetHexKeyID()).Replace(c.OpenPGPURL)
|
||||
}
|
||||
|
||||
func (c *config) cryptoKey() (*crypto.Key, error) {
|
||||
if c.Key == "" {
|
||||
func (c *config) privateOpenPGPKey() (*crypto.Key, error) {
|
||||
if c.OpenPGPPrivateKey == "" {
|
||||
return nil, nil
|
||||
}
|
||||
c.keyMu.Lock()
|
||||
|
|
@ -99,7 +88,7 @@ func (c *config) cryptoKey() (*crypto.Key, error) {
|
|||
return c.key, c.keyErr
|
||||
}
|
||||
var f *os.File
|
||||
if f, c.keyErr = os.Open(c.Key); c.keyErr != nil {
|
||||
if f, c.keyErr = os.Open(c.OpenPGPPrivateKey); c.keyErr != nil {
|
||||
return nil, c.keyErr
|
||||
}
|
||||
defer f.Close()
|
||||
|
|
@ -179,10 +168,6 @@ func (c *config) setDefaults() {
|
|||
c.Domain = defaultDomain
|
||||
}
|
||||
|
||||
if c.OpenPGPURL == "" {
|
||||
c.OpenPGPURL = defaultOpenPGPURL
|
||||
}
|
||||
|
||||
if c.Workers <= 0 {
|
||||
if n := runtime.NumCPU(); n > defaultWorkers {
|
||||
c.Workers = defaultWorkers
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import (
|
|||
"bytes"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
|
@ -177,7 +178,7 @@ func (w *worker) mirrorInternal() (*csaf.AggregatorCSAFProvider, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Add us as a miiror.
|
||||
// Add us as a mirror.
|
||||
mirrorURL := csaf.ProviderURL(
|
||||
fmt.Sprintf("%s/.well-known/csaf-aggregator/%s/provider-metadata.json",
|
||||
w.cfg.Domain, w.provider.Name))
|
||||
|
|
@ -204,7 +205,7 @@ func (w *worker) writeProviderMetadata() error {
|
|||
fname := filepath.Join(w.dir, "provider-metadata.json")
|
||||
|
||||
pm := csaf.NewProviderMetadataPrefix(
|
||||
w.cfg.Domain+"/.well-known/csaf-aggreator/"+w.provider.Name,
|
||||
w.cfg.Domain+"/.well-known/csaf-aggregator/"+w.provider.Name,
|
||||
w.labelsFromSummaries())
|
||||
|
||||
// Figure out the role
|
||||
|
|
@ -231,12 +232,9 @@ func (w *worker) writeProviderMetadata() error {
|
|||
log.Printf("extracting data from orignal provider failed: %v\n", err)
|
||||
}
|
||||
|
||||
key, err := w.cfg.cryptoKey()
|
||||
if err != nil {
|
||||
log.Printf("error: %v\n", err)
|
||||
}
|
||||
if key != nil {
|
||||
pm.SetPGP(key.GetFingerprint(), w.cfg.GetOpenPGPURL(key))
|
||||
// We are mirroring the remote public keys, too.
|
||||
if err := w.mirrorPGPKeys(pm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
la := csaf.TimeStamp(lastUpdate)
|
||||
|
|
@ -245,7 +243,106 @@ func (w *worker) writeProviderMetadata() error {
|
|||
return util.WriteToFile(fname, pm)
|
||||
}
|
||||
|
||||
// createAggregatorProvider, der the "metadata" section in the "csaf_providers" of
|
||||
// mirrorPGPKeys creates a local openpgp folder and downloads the referenced
|
||||
// OpenPGP keys into it. The own key is also inserted.
|
||||
func (w *worker) mirrorPGPKeys(pm *csaf.ProviderMetadata) error {
|
||||
openPGPFolder := filepath.Join(w.dir, "openpgp")
|
||||
if err := os.MkdirAll(openPGPFolder, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
localKeyURL := func(fingerprint string) string {
|
||||
return fmt.Sprintf("%s/.well-known/csaf-aggregator/%s/openpgp/%s.asc",
|
||||
w.cfg.Domain, w.provider.Name, fingerprint)
|
||||
}
|
||||
|
||||
for i := range pm.PGPKeys {
|
||||
pgpKey := &pm.PGPKeys[i]
|
||||
if pgpKey.URL == nil {
|
||||
log.Printf("ignoring PGP key without URL: %s\n", pgpKey.Fingerprint)
|
||||
continue
|
||||
}
|
||||
if _, err := hex.DecodeString(string(pgpKey.Fingerprint)); err != nil {
|
||||
log.Printf("ignoring PGP with invalid fingerprint: %s\n", *pgpKey.URL)
|
||||
continue
|
||||
}
|
||||
|
||||
// Fetch remote key.
|
||||
res, err := w.client.Get(*pgpKey.URL)
|
||||
if err != nil {
|
||||
os.RemoveAll(openPGPFolder)
|
||||
return err
|
||||
}
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
os.RemoveAll(openPGPFolder)
|
||||
return fmt.Errorf("cannot fetch PGP key %s: %s (%d)",
|
||||
*pgpKey.URL, res.Status, res.StatusCode)
|
||||
}
|
||||
|
||||
fingerprint := strings.ToUpper(string(pgpKey.Fingerprint))
|
||||
|
||||
localFile := filepath.Join(openPGPFolder, fingerprint+".asc")
|
||||
|
||||
// Download the remote key into our new folder.
|
||||
if err := func() error {
|
||||
defer res.Body.Close()
|
||||
out, err := os.Create(localFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err1 := io.Copy(out, res.Body)
|
||||
err2 := out.Close()
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
return err2
|
||||
}(); err != nil {
|
||||
os.RemoveAll(openPGPFolder)
|
||||
return err
|
||||
}
|
||||
|
||||
// replace the URL
|
||||
url := localKeyURL(fingerprint)
|
||||
pgpKey.URL = &url
|
||||
}
|
||||
|
||||
// If we have public key configured copy it into the new folder
|
||||
|
||||
if w.cfg.OpenPGPPublicKey == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Load the key for the fingerprint.
|
||||
data, err := os.ReadFile(w.cfg.OpenPGPPublicKey)
|
||||
if err != nil {
|
||||
os.RemoveAll(openPGPFolder)
|
||||
return err
|
||||
}
|
||||
|
||||
key, err := crypto.NewKeyFromArmoredReader(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
os.RemoveAll(openPGPFolder)
|
||||
return err
|
||||
}
|
||||
|
||||
fingerprint := strings.ToUpper(key.GetFingerprint())
|
||||
|
||||
localFile := filepath.Join(openPGPFolder, fingerprint+".asc")
|
||||
|
||||
// Write copy back into new folder.
|
||||
if err := os.WriteFile(localFile, data, 0644); err != nil {
|
||||
os.RemoveAll(openPGPFolder)
|
||||
return err
|
||||
}
|
||||
|
||||
// Add to the URLs.
|
||||
pm.SetPGP(fingerprint, localKeyURL(fingerprint))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// createAggregatorProvider fills the "metadata" section in the "csaf_providers" of
|
||||
// the aggregator document.
|
||||
func (w *worker) createAggregatorProvider() (*csaf.AggregatorCSAFProvider, error) {
|
||||
const (
|
||||
|
|
@ -373,7 +470,7 @@ func (w *worker) downloadSignature(path string) (string, error) {
|
|||
// sign signs the given data with the configured key.
|
||||
func (w *worker) sign(data []byte) (string, error) {
|
||||
if w.signRing == nil {
|
||||
key, err := w.cfg.cryptoKey()
|
||||
key, err := w.cfg.privateOpenPGPKey()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,12 +55,6 @@ func (c *controller) handleSignature(
|
|||
data []byte,
|
||||
) (string, *crypto.Key, error) {
|
||||
|
||||
// Either way ... we need the key.
|
||||
key, err := c.cfg.loadCryptoKey()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
// Was the signature given via request?
|
||||
if c.cfg.UploadSignature {
|
||||
sigText := r.FormValue("signature")
|
||||
|
|
@ -73,7 +67,12 @@ func (c *controller) handleSignature(
|
|||
return "", nil, err
|
||||
}
|
||||
|
||||
// Use as public key
|
||||
// Use the public key
|
||||
key, err := loadCryptoKeyFromFile(c.cfg.OpenPGPPublicKey)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
signRing, err := crypto.NewKeyRing(key)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
|
|
@ -91,13 +90,18 @@ func (c *controller) handleSignature(
|
|||
|
||||
// Sign ourself
|
||||
|
||||
// Use the private key
|
||||
key, err := loadCryptoKeyFromFile(c.cfg.OpenPGPPrivateKey)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
if passwd := r.FormValue("passphrase"); !c.cfg.NoPassphrase && passwd != "" {
|
||||
if key, err = key.Unlock([]byte(passwd)); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Use as private key
|
||||
signRing, err := crypto.NewKeyRing(key)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
|
|
@ -317,7 +321,8 @@ func (c *controller) upload(r *http.Request) (interface{}, error) {
|
|||
warn("Publishers in provider metadata and CSAF do not match.")
|
||||
}
|
||||
|
||||
pmd.SetPGP(key.GetFingerprint(), c.cfg.GetOpenPGPURL(key))
|
||||
fingerprint := strings.ToUpper(key.GetFingerprint())
|
||||
pmd.SetPGP(fingerprint, c.cfg.openPGPPublicURL(fingerprint))
|
||||
|
||||
return nil
|
||||
},
|
||||
|
|
|
|||
|
|
@ -22,12 +22,14 @@ import (
|
|||
|
||||
const (
|
||||
// The environment name, that contains the path to the config file.
|
||||
configEnv = "CSAF_CONFIG"
|
||||
defaultConfigPath = "/usr/lib/csaf/config.toml" // Default path to the config file.
|
||||
defaultFolder = "/var/www/" // Default folder path.
|
||||
defaultWeb = "/var/www/html" // Default web path.
|
||||
defaultOpenPGPURL = "https://openpgp.circl.lu/pks/lookup?op=get&search=${FINGERPRINT}" // Default OpenPGP URL.
|
||||
defaultUploadLimit = 50 * 1024 * 1024 // Default limit size of the uploaded file.
|
||||
configEnv = "CSAF_CONFIG"
|
||||
configPrefix = "/usr/lib/csaf"
|
||||
defaultConfigPath = configPrefix + "/config.toml" // Default path to the config file.
|
||||
defaultOpenPGPPrivateKey = configPrefix + "/openpgp_private.asc"
|
||||
defaultOpenPGPPublicKey = configPrefix + "/openpgp_public.asc"
|
||||
defaultFolder = "/var/www/" // Default folder path.
|
||||
defaultWeb = "/var/www/html" // Default web path.
|
||||
defaultUploadLimit = 50 * 1024 * 1024 // Default limit size of the uploaded file.
|
||||
)
|
||||
|
||||
type providerMetadataConfig struct {
|
||||
|
|
@ -39,12 +41,12 @@ type providerMetadataConfig struct {
|
|||
// configs contains the config values for the provider.
|
||||
type config struct {
|
||||
Password *string `toml:"password"`
|
||||
Key string `toml:"key"`
|
||||
OpenPGPPublicKey string `toml:"openpgp_public_key"`
|
||||
OpenPGPPrivateKey string `toml:"openpgp_private_key"`
|
||||
Folder string `toml:"folder"`
|
||||
Web string `toml:"web"`
|
||||
TLPs []tlp `toml:"tlps"`
|
||||
UploadSignature bool `toml:"upload_signature"`
|
||||
OpenPGPURL string `toml:"openpgp_url"`
|
||||
CanonicalURLPrefix string `toml:"canonical_url_prefix"`
|
||||
NoPassphrase bool `toml:"no_passphrase"`
|
||||
NoValidation bool `toml:"no_validation"`
|
||||
|
|
@ -108,15 +110,6 @@ func (cfg *config) uploadLimiter(r io.Reader) io.Reader {
|
|||
return io.LimitReader(r, *cfg.UploadLimit)
|
||||
}
|
||||
|
||||
func (cfg *config) GetOpenPGPURL(key *crypto.Key) string {
|
||||
if key == nil {
|
||||
return cfg.OpenPGPURL
|
||||
}
|
||||
return strings.NewReplacer(
|
||||
"${FINGERPRINT}", "0x"+key.GetFingerprint(),
|
||||
"${KEY_ID}", "0x"+key.GetHexKeyID()).Replace(cfg.OpenPGPURL)
|
||||
}
|
||||
|
||||
func (cfg *config) modelTLPs() []csaf.TLPLabel {
|
||||
tlps := make([]csaf.TLPLabel, 0, len(cfg.TLPs))
|
||||
for _, t := range cfg.TLPs {
|
||||
|
|
@ -127,10 +120,9 @@ func (cfg *config) modelTLPs() []csaf.TLPLabel {
|
|||
return tlps
|
||||
}
|
||||
|
||||
// loadCryptoKey loads the armored data into the key stored in the file specified by the
|
||||
// "key" config value and return it with nil, otherwise an error.
|
||||
func (cfg *config) loadCryptoKey() (*crypto.Key, error) {
|
||||
f, err := os.Open(cfg.Key)
|
||||
// loadCryptoKeyFromFile loads an armored key from file.
|
||||
func loadCryptoKeyFromFile(filename string) (*crypto.Key, error) {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -138,6 +130,13 @@ func (cfg *config) loadCryptoKey() (*crypto.Key, error) {
|
|||
return crypto.NewKeyFromArmoredReader(f)
|
||||
}
|
||||
|
||||
// openPGPPublicURL constructs the public OpenPGP key URL for a given key.
|
||||
func (cfg *config) openPGPPublicURL(fingerprint string) string {
|
||||
return fmt.Sprintf(
|
||||
"%s/.well-known/csaf/openpgp/%s.asc",
|
||||
cfg.CanonicalURLPrefix, fingerprint)
|
||||
}
|
||||
|
||||
// checkPassword compares the given hashed password with the plaintext in the "password" config value.
|
||||
// It returns true if these matches or if the "password" config value is not set, otherwise false.
|
||||
func (cfg *config) checkPassword(hash string) bool {
|
||||
|
|
@ -162,6 +161,14 @@ func loadConfig() (*config, error) {
|
|||
|
||||
// Preset defaults
|
||||
|
||||
if cfg.OpenPGPPrivateKey == "" {
|
||||
cfg.OpenPGPPrivateKey = defaultOpenPGPPrivateKey
|
||||
}
|
||||
|
||||
if cfg.OpenPGPPublicKey == "" {
|
||||
cfg.OpenPGPPublicKey = defaultOpenPGPPublicKey
|
||||
}
|
||||
|
||||
if cfg.Folder == "" {
|
||||
cfg.Folder = defaultFolder
|
||||
}
|
||||
|
|
@ -178,10 +185,6 @@ func loadConfig() (*config, error) {
|
|||
cfg.TLPs = []tlp{tlpCSAF, tlpWhite, tlpGreen, tlpAmber, tlpRed}
|
||||
}
|
||||
|
||||
if cfg.OpenPGPURL == "" {
|
||||
cfg.OpenPGPURL = defaultOpenPGPURL
|
||||
}
|
||||
|
||||
if cfg.ProviderMetaData == nil {
|
||||
cfg.ProviderMetaData = &providerMetadataConfig{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ package main
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
|
@ -17,6 +18,7 @@ import (
|
|||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/csaf-poc/csaf_distribution/csaf"
|
||||
"github.com/csaf-poc/csaf_distribution/util"
|
||||
)
|
||||
|
|
@ -28,16 +30,15 @@ func ensureFolders(c *config) error {
|
|||
wellknown := filepath.Join(c.Web, ".well-known")
|
||||
wellknownCSAF := filepath.Join(wellknown, "csaf")
|
||||
|
||||
if err := createWellknown(wellknownCSAF); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := createFeedFolders(c, wellknownCSAF); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := createProviderMetadata(c, wellknownCSAF); err != nil {
|
||||
return err
|
||||
for _, create := range []func(*config, string) error{
|
||||
createWellknown,
|
||||
createFeedFolders,
|
||||
createOpenPGPFolder,
|
||||
createProviderMetadata,
|
||||
} {
|
||||
if err := create(c, wellknownCSAF); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return setupSecurity(c, wellknown)
|
||||
|
|
@ -45,7 +46,7 @@ func ensureFolders(c *config) error {
|
|||
|
||||
// createWellknown creates ".well-known" directory if not exist and returns nil.
|
||||
// An error is returned if the it is not a directory.
|
||||
func createWellknown(wellknown string) error {
|
||||
func createWellknown(_ *config, wellknown string) error {
|
||||
st, err := os.Stat(wellknown)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
|
|
@ -86,6 +87,46 @@ func createFeedFolders(c *config, wellknown string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// createOpenPGPFolder creates an openpgp folder besides
|
||||
// the provider-metadata.json in the csaf folder.
|
||||
func createOpenPGPFolder(c *config, wellknown string) error {
|
||||
|
||||
openPGPFolder := filepath.Join(wellknown, "openpgp")
|
||||
|
||||
if _, err := os.Stat(openPGPFolder); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(openPGPFolder, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
keyData, err := os.ReadFile(c.OpenPGPPublicKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot load public OpenPGP key: %v", err)
|
||||
}
|
||||
|
||||
key, err := crypto.NewKeyFromArmoredReader(bytes.NewReader(keyData))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fp := strings.ToUpper(key.GetFingerprint())
|
||||
|
||||
dst := filepath.Join(openPGPFolder, fp+".asc")
|
||||
|
||||
// If we don't have it write it.
|
||||
if _, err = os.Stat(dst); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = os.WriteFile(dst, keyData, 0644)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// setupSecurity creates the "security.txt" file if does not exist
|
||||
// and writes the CSAF field inside the file. If the file exists
|
||||
// it checks ig the CSAF entry with the provider-metadata.json
|
||||
|
|
@ -187,12 +228,13 @@ func createProviderMetadata(c *config, wellknownCSAF string) error {
|
|||
pm := csaf.NewProviderMetadataDomain(c.CanonicalURLPrefix, c.modelTLPs())
|
||||
c.ProviderMetaData.apply(pm)
|
||||
|
||||
// Set OpenPGP key.
|
||||
key, err := c.loadCryptoKey()
|
||||
key, err := loadCryptoKeyFromFile(c.OpenPGPPublicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("cannot load public key: %v", err)
|
||||
}
|
||||
pm.SetPGP(key.GetFingerprint(), c.GetOpenPGPURL(key))
|
||||
|
||||
fingerprint := strings.ToUpper(key.GetFingerprint())
|
||||
pm.SetPGP(fingerprint, c.openPGPPublicURL(fingerprint))
|
||||
|
||||
return util.WriteToFile(path, pm)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,20 +53,20 @@ SHELL=/bin/bash
|
|||
The following options can be used in the config file in TOML format:
|
||||
|
||||
```
|
||||
workers // number of parallel workers to start (default 10)
|
||||
folder // target folder on disc for writing the downloaded documents
|
||||
web // directory to be served by the webserver
|
||||
domain // base url where the contents will be reachable from outside
|
||||
rate // overall downloading limit per worker
|
||||
insecure // do not check validity of TLS certificates
|
||||
aggregator // table with basic infos for the aggregator object
|
||||
providers // array of tables, each entry to be mirrored or listed
|
||||
key // OpenPGP key
|
||||
openpgp_url // URL where the OpenPGP public key part can be found
|
||||
passphrase // passphrase of the OpenPGP key
|
||||
lock_file // path to lockfile, to stop other instances if one is not done
|
||||
interim_years // limiting the years for which interim documents are searched
|
||||
verbose // print more diagnostic output, e.g. https request
|
||||
workers // number of parallel workers to start (default 10)
|
||||
folder // target folder on disc for writing the downloaded documents
|
||||
web // directory to be served by the webserver
|
||||
domain // base url where the contents will be reachable from outside
|
||||
rate // overall downloading limit per worker
|
||||
insecure // do not check validity of TLS certificates
|
||||
aggregator // table with basic infos for the aggregator object
|
||||
providers // array of tables, each entry to be mirrored or listed
|
||||
openpgp_private_key // OpenPGP private key
|
||||
openpgp_public_key // OpenPGP public key
|
||||
passphrase // passphrase of the OpenPGP key
|
||||
lock_file // path to lockfile, to stop other instances if one is not done
|
||||
interim_years // limiting the years for which interim documents are searched
|
||||
verbose // print more diagnostic output, e.g. https request
|
||||
allow_single_provider // debugging option
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ explain how to wire this up with nginx and where the config file lives.
|
|||
Following options are supported in the config file:
|
||||
|
||||
- password: Authentication password for accessing the CSAF provider.
|
||||
- key: The private OpenPGP key.
|
||||
- openpgp_public_key: The public OpenPGP key. Default: `/ust/lib/csaf/openpgp_public.asc`
|
||||
- openpgp_private_key: The private OpenPGP key. Default: `/ust/lib/csaf/openpgp_private.asc`
|
||||
- folder: Specify the root folder. Default: `/var/www/`.
|
||||
- web: Specify the web folder. Default: `/var/www/html`.
|
||||
- tlps: Set the allowed TLP comming with the upload request (one or more of "csaf", "white", "amber", "green", "red").
|
||||
|
|
@ -16,7 +17,6 @@ Following options are supported in the config file:
|
|||
These affects the list items in the web interface.
|
||||
Default: `["csaf", "white", "amber", "green", "red"]`.
|
||||
- upload_signature: Send signature with the request, an additional input-field in the web interface will be shown to let user enter an ascii armored signature. Default: `false`.
|
||||
- openpgp_url: URL to OpenPGP key-server. Default: `https://openpgp.circl.lu`.
|
||||
- canonical_url_prefix: start of the URL where contents shall be accessible from the internet. Default: `https://$SERVER_NAME`.
|
||||
- no_passphrase: Let user send password with the request, if set to true the input-field in the web interface will be disappeared. Default: `false`.
|
||||
- no_validation: Validate the uploaded CSAF document against the JSON schema. Default: `false`.
|
||||
|
|
|
|||
|
|
@ -92,8 +92,8 @@ sudo chmod o-rwx /usr/lib/csaf/private.asc
|
|||
# Configuration file
|
||||
echo '
|
||||
# upload_signature = true
|
||||
# key = "/usr/lib/csaf/public.asc"
|
||||
key = "/usr/lib/csaf/private.asc"
|
||||
openpgp_private_key = "/usr/lib/csaf/private.asc"
|
||||
openpgp_public_key = "/usr/lib/csaf/public.asc"
|
||||
#tlps = ["green", "red"]
|
||||
canonical_url_prefix = "https://localhost:8443"
|
||||
#no_passphrase = true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue