1
0
Fork 0
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:
Sascha L. Teichmann 2022-06-09 10:42:44 +02:00 committed by GitHub
parent a849ac0d5f
commit 69f0f3499a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 229 additions and 97 deletions

View file

@ -15,7 +15,6 @@ import (
"net/http" "net/http"
"os" "os"
"runtime" "runtime"
"strings"
"sync" "sync"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
@ -31,7 +30,6 @@ const (
defaultFolder = "/var/www" defaultFolder = "/var/www"
defaultWeb = "/var/www/html" defaultWeb = "/var/www/html"
defaultDomain = "https://example.com" defaultDomain = "https://example.com"
defaultOpenPGPURL = "https://openpgp.circl.lu/pks/lookup?op=get&search=${FINGERPRINT}" // Default OpenPGP URL.
) )
type provider struct { type provider struct {
@ -54,8 +52,8 @@ type config struct {
Insecure *bool `toml:"insecure"` Insecure *bool `toml:"insecure"`
Aggregator csaf.AggregatorInfo `toml:"aggregator"` Aggregator csaf.AggregatorInfo `toml:"aggregator"`
Providers []*provider `toml:"providers"` Providers []*provider `toml:"providers"`
Key string `toml:"key"` OpenPGPPrivateKey string `toml:"openpgp_private_key"`
OpenPGPURL string `toml:"openpgp_url"` OpenPGPPublicKey string `toml:"openpgp_public_key"`
Passphrase *string `toml:"passphrase"` Passphrase *string `toml:"passphrase"`
AllowSingleProvider bool `toml:"allow_single_provider"` AllowSingleProvider bool `toml:"allow_single_provider"`
@ -80,17 +78,8 @@ func (c *config) runAsMirror() bool {
*c.Aggregator.Category == csaf.AggregatorAggregator *c.Aggregator.Category == csaf.AggregatorAggregator
} }
func (c *config) GetOpenPGPURL(key *crypto.Key) string { func (c *config) privateOpenPGPKey() (*crypto.Key, error) {
if key == nil { if c.OpenPGPPrivateKey == "" {
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 == "" {
return nil, nil return nil, nil
} }
c.keyMu.Lock() c.keyMu.Lock()
@ -99,7 +88,7 @@ func (c *config) cryptoKey() (*crypto.Key, error) {
return c.key, c.keyErr return c.key, c.keyErr
} }
var f *os.File 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 return nil, c.keyErr
} }
defer f.Close() defer f.Close()
@ -179,10 +168,6 @@ func (c *config) setDefaults() {
c.Domain = defaultDomain c.Domain = defaultDomain
} }
if c.OpenPGPURL == "" {
c.OpenPGPURL = defaultOpenPGPURL
}
if c.Workers <= 0 { if c.Workers <= 0 {
if n := runtime.NumCPU(); n > defaultWorkers { if n := runtime.NumCPU(); n > defaultWorkers {
c.Workers = defaultWorkers c.Workers = defaultWorkers

View file

@ -12,6 +12,7 @@ import (
"bytes" "bytes"
"crypto/sha256" "crypto/sha256"
"crypto/sha512" "crypto/sha512"
"encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
@ -177,7 +178,7 @@ func (w *worker) mirrorInternal() (*csaf.AggregatorCSAFProvider, error) {
return nil, err return nil, err
} }
// Add us as a miiror. // Add us as a mirror.
mirrorURL := csaf.ProviderURL( mirrorURL := csaf.ProviderURL(
fmt.Sprintf("%s/.well-known/csaf-aggregator/%s/provider-metadata.json", fmt.Sprintf("%s/.well-known/csaf-aggregator/%s/provider-metadata.json",
w.cfg.Domain, w.provider.Name)) w.cfg.Domain, w.provider.Name))
@ -204,7 +205,7 @@ func (w *worker) writeProviderMetadata() error {
fname := filepath.Join(w.dir, "provider-metadata.json") fname := filepath.Join(w.dir, "provider-metadata.json")
pm := csaf.NewProviderMetadataPrefix( 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()) w.labelsFromSummaries())
// Figure out the role // Figure out the role
@ -231,12 +232,9 @@ func (w *worker) writeProviderMetadata() error {
log.Printf("extracting data from orignal provider failed: %v\n", err) log.Printf("extracting data from orignal provider failed: %v\n", err)
} }
key, err := w.cfg.cryptoKey() // We are mirroring the remote public keys, too.
if err != nil { if err := w.mirrorPGPKeys(pm); err != nil {
log.Printf("error: %v\n", err) return err
}
if key != nil {
pm.SetPGP(key.GetFingerprint(), w.cfg.GetOpenPGPURL(key))
} }
la := csaf.TimeStamp(lastUpdate) la := csaf.TimeStamp(lastUpdate)
@ -245,7 +243,106 @@ func (w *worker) writeProviderMetadata() error {
return util.WriteToFile(fname, pm) 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. // the aggregator document.
func (w *worker) createAggregatorProvider() (*csaf.AggregatorCSAFProvider, error) { func (w *worker) createAggregatorProvider() (*csaf.AggregatorCSAFProvider, error) {
const ( const (
@ -373,7 +470,7 @@ func (w *worker) downloadSignature(path string) (string, error) {
// sign signs the given data with the configured key. // sign signs the given data with the configured key.
func (w *worker) sign(data []byte) (string, error) { func (w *worker) sign(data []byte) (string, error) {
if w.signRing == nil { if w.signRing == nil {
key, err := w.cfg.cryptoKey() key, err := w.cfg.privateOpenPGPKey()
if err != nil { if err != nil {
return "", err return "", err
} }

View file

@ -55,12 +55,6 @@ func (c *controller) handleSignature(
data []byte, data []byte,
) (string, *crypto.Key, error) { ) (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? // Was the signature given via request?
if c.cfg.UploadSignature { if c.cfg.UploadSignature {
sigText := r.FormValue("signature") sigText := r.FormValue("signature")
@ -73,7 +67,12 @@ func (c *controller) handleSignature(
return "", nil, err 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) signRing, err := crypto.NewKeyRing(key)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
@ -91,13 +90,18 @@ func (c *controller) handleSignature(
// Sign ourself // 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 passwd := r.FormValue("passphrase"); !c.cfg.NoPassphrase && passwd != "" {
if key, err = key.Unlock([]byte(passwd)); err != nil { if key, err = key.Unlock([]byte(passwd)); err != nil {
return "", nil, err return "", nil, err
} }
} }
// Use as private key
signRing, err := crypto.NewKeyRing(key) signRing, err := crypto.NewKeyRing(key)
if err != nil { if err != nil {
return "", nil, err 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.") 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 return nil
}, },

View file

@ -23,10 +23,12 @@ import (
const ( const (
// The environment name, that contains the path to the config file. // The environment name, that contains the path to the config file.
configEnv = "CSAF_CONFIG" configEnv = "CSAF_CONFIG"
defaultConfigPath = "/usr/lib/csaf/config.toml" // Default path to the config file. 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. defaultFolder = "/var/www/" // Default folder path.
defaultWeb = "/var/www/html" // Default web 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. defaultUploadLimit = 50 * 1024 * 1024 // Default limit size of the uploaded file.
) )
@ -39,12 +41,12 @@ type providerMetadataConfig struct {
// configs contains the config values for the provider. // configs contains the config values for the provider.
type config struct { type config struct {
Password *string `toml:"password"` Password *string `toml:"password"`
Key string `toml:"key"` OpenPGPPublicKey string `toml:"openpgp_public_key"`
OpenPGPPrivateKey string `toml:"openpgp_private_key"`
Folder string `toml:"folder"` Folder string `toml:"folder"`
Web string `toml:"web"` Web string `toml:"web"`
TLPs []tlp `toml:"tlps"` TLPs []tlp `toml:"tlps"`
UploadSignature bool `toml:"upload_signature"` UploadSignature bool `toml:"upload_signature"`
OpenPGPURL string `toml:"openpgp_url"`
CanonicalURLPrefix string `toml:"canonical_url_prefix"` CanonicalURLPrefix string `toml:"canonical_url_prefix"`
NoPassphrase bool `toml:"no_passphrase"` NoPassphrase bool `toml:"no_passphrase"`
NoValidation bool `toml:"no_validation"` NoValidation bool `toml:"no_validation"`
@ -108,15 +110,6 @@ func (cfg *config) uploadLimiter(r io.Reader) io.Reader {
return io.LimitReader(r, *cfg.UploadLimit) 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 { func (cfg *config) modelTLPs() []csaf.TLPLabel {
tlps := make([]csaf.TLPLabel, 0, len(cfg.TLPs)) tlps := make([]csaf.TLPLabel, 0, len(cfg.TLPs))
for _, t := range cfg.TLPs { for _, t := range cfg.TLPs {
@ -127,10 +120,9 @@ func (cfg *config) modelTLPs() []csaf.TLPLabel {
return tlps return tlps
} }
// loadCryptoKey loads the armored data into the key stored in the file specified by the // loadCryptoKeyFromFile loads an armored key from file.
// "key" config value and return it with nil, otherwise an error. func loadCryptoKeyFromFile(filename string) (*crypto.Key, error) {
func (cfg *config) loadCryptoKey() (*crypto.Key, error) { f, err := os.Open(filename)
f, err := os.Open(cfg.Key)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -138,6 +130,13 @@ func (cfg *config) loadCryptoKey() (*crypto.Key, error) {
return crypto.NewKeyFromArmoredReader(f) 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. // 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. // It returns true if these matches or if the "password" config value is not set, otherwise false.
func (cfg *config) checkPassword(hash string) bool { func (cfg *config) checkPassword(hash string) bool {
@ -162,6 +161,14 @@ func loadConfig() (*config, error) {
// Preset defaults // Preset defaults
if cfg.OpenPGPPrivateKey == "" {
cfg.OpenPGPPrivateKey = defaultOpenPGPPrivateKey
}
if cfg.OpenPGPPublicKey == "" {
cfg.OpenPGPPublicKey = defaultOpenPGPPublicKey
}
if cfg.Folder == "" { if cfg.Folder == "" {
cfg.Folder = defaultFolder cfg.Folder = defaultFolder
} }
@ -178,10 +185,6 @@ func loadConfig() (*config, error) {
cfg.TLPs = []tlp{tlpCSAF, tlpWhite, tlpGreen, tlpAmber, tlpRed} cfg.TLPs = []tlp{tlpCSAF, tlpWhite, tlpGreen, tlpAmber, tlpRed}
} }
if cfg.OpenPGPURL == "" {
cfg.OpenPGPURL = defaultOpenPGPURL
}
if cfg.ProviderMetaData == nil { if cfg.ProviderMetaData == nil {
cfg.ProviderMetaData = &providerMetadataConfig{} cfg.ProviderMetaData = &providerMetadataConfig{}
} }

View file

@ -10,6 +10,7 @@ package main
import ( import (
"bufio" "bufio"
"bytes"
"errors" "errors"
"fmt" "fmt"
"os" "os"
@ -17,6 +18,7 @@ import (
"strings" "strings"
"unicode" "unicode"
"github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/csaf-poc/csaf_distribution/csaf" "github.com/csaf-poc/csaf_distribution/csaf"
"github.com/csaf-poc/csaf_distribution/util" "github.com/csaf-poc/csaf_distribution/util"
) )
@ -28,16 +30,15 @@ func ensureFolders(c *config) error {
wellknown := filepath.Join(c.Web, ".well-known") wellknown := filepath.Join(c.Web, ".well-known")
wellknownCSAF := filepath.Join(wellknown, "csaf") wellknownCSAF := filepath.Join(wellknown, "csaf")
if err := createWellknown(wellknownCSAF); err != nil { for _, create := range []func(*config, string) error{
createWellknown,
createFeedFolders,
createOpenPGPFolder,
createProviderMetadata,
} {
if err := create(c, wellknownCSAF); err != nil {
return err return err
} }
if err := createFeedFolders(c, wellknownCSAF); err != nil {
return err
}
if err := createProviderMetadata(c, wellknownCSAF); err != nil {
return err
} }
return setupSecurity(c, wellknown) return setupSecurity(c, wellknown)
@ -45,7 +46,7 @@ func ensureFolders(c *config) error {
// createWellknown creates ".well-known" directory if not exist and returns nil. // createWellknown creates ".well-known" directory if not exist and returns nil.
// An error is returned if the it is not a directory. // 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) st, err := os.Stat(wellknown)
if err != nil { if err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
@ -86,6 +87,46 @@ func createFeedFolders(c *config, wellknown string) error {
return nil 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 // setupSecurity creates the "security.txt" file if does not exist
// and writes the CSAF field inside the file. If the file exists // and writes the CSAF field inside the file. If the file exists
// it checks ig the CSAF entry with the provider-metadata.json // 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()) pm := csaf.NewProviderMetadataDomain(c.CanonicalURLPrefix, c.modelTLPs())
c.ProviderMetaData.apply(pm) c.ProviderMetaData.apply(pm)
// Set OpenPGP key. key, err := loadCryptoKeyFromFile(c.OpenPGPPublicKey)
key, err := c.loadCryptoKey()
if err != nil { 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) return util.WriteToFile(path, pm)
} }

View file

@ -61,8 +61,8 @@ rate // overall downloading limit per worker
insecure // do not check validity of TLS certificates insecure // do not check validity of TLS certificates
aggregator // table with basic infos for the aggregator object aggregator // table with basic infos for the aggregator object
providers // array of tables, each entry to be mirrored or listed providers // array of tables, each entry to be mirrored or listed
key // OpenPGP key openpgp_private_key // OpenPGP private key
openpgp_url // URL where the OpenPGP public key part can be found openpgp_public_key // OpenPGP public key
passphrase // passphrase of the OpenPGP key passphrase // passphrase of the OpenPGP key
lock_file // path to lockfile, to stop other instances if one is not done 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 interim_years // limiting the years for which interim documents are searched

View file

@ -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: Following options are supported in the config file:
- password: Authentication password for accessing the CSAF provider. - 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/`. - folder: Specify the root folder. Default: `/var/www/`.
- web: Specify the web folder. Default: `/var/www/html`. - 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"). - 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. These affects the list items in the web interface.
Default: `["csaf", "white", "amber", "green", "red"]`. 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`. - 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`. - 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_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`. - no_validation: Validate the uploaded CSAF document against the JSON schema. Default: `false`.

View file

@ -92,8 +92,8 @@ sudo chmod o-rwx /usr/lib/csaf/private.asc
# Configuration file # Configuration file
echo ' echo '
# upload_signature = true # upload_signature = true
# key = "/usr/lib/csaf/public.asc" openpgp_private_key = "/usr/lib/csaf/private.asc"
key = "/usr/lib/csaf/private.asc" openpgp_public_key = "/usr/lib/csaf/public.asc"
#tlps = ["green", "red"] #tlps = ["green", "red"]
canonical_url_prefix = "https://localhost:8443" canonical_url_prefix = "https://localhost:8443"
#no_passphrase = true #no_passphrase = true