mirror of
https://github.com/gocsaf/csaf.git
synced 2025-12-22 05:40:11 +01:00
commit
d779a3fd7e
7 changed files with 256 additions and 34 deletions
|
|
@ -19,3 +19,5 @@
|
||||||
| golang.org/x/term | BSD-3-Clause |
|
| golang.org/x/term | BSD-3-Clause |
|
||||||
| golang.org/x/text | BSD-3-Clause |
|
| golang.org/x/text | BSD-3-Clause |
|
||||||
| github.com/gofrs/flock | BSD-3-Clause |
|
| github.com/gofrs/flock | BSD-3-Clause |
|
||||||
|
| github.com/PuerkitoBio/goquery | BSD-3-Clause |
|
||||||
|
| github.com/andybalholm/cascadia | BSD-2-Clause |
|
||||||
|
|
|
||||||
110
cmd/csaf_checker/links.go
Normal file
110
cmd/csaf_checker/links.go
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
// This file is Free Software under the MIT License
|
||||||
|
// without warranty, see README.md and LICENSES/MIT.txt for details.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: 2022 German Federal Office for Information Security (BSI) <https://www.bsi.bund.de>
|
||||||
|
// Software-Engineering: 2022 Intevation GmbH <https://intevation.de>
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/PuerkitoBio/goquery"
|
||||||
|
"github.com/csaf-poc/csaf_distribution/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
pageContent struct {
|
||||||
|
err error
|
||||||
|
links map[string]struct{}
|
||||||
|
}
|
||||||
|
pages map[string]*pageContent
|
||||||
|
)
|
||||||
|
|
||||||
|
func (pgs pages) listed(path string, pro *processor) (bool, error) {
|
||||||
|
base, err := util.BaseURL(path)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
content := pgs[base]
|
||||||
|
if content != nil { // already loaded
|
||||||
|
if content.err != nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
_, ok := content.links[path]
|
||||||
|
return ok, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
baseURL, err := url.Parse(base)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// load page
|
||||||
|
client := pro.httpClient()
|
||||||
|
pro.checkTLS(base)
|
||||||
|
res, err := client.Get(base)
|
||||||
|
|
||||||
|
pro.badDirListings.use()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
pro.badDirListings.add("Fetching %s failed: %v", base, err)
|
||||||
|
return false, errContinue
|
||||||
|
}
|
||||||
|
if res.StatusCode != http.StatusOK {
|
||||||
|
pro.badDirListings.add("Fetching %s failed. Status code %d (%s)",
|
||||||
|
base, res.StatusCode, res.Status)
|
||||||
|
return false, errContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
content = &pageContent{
|
||||||
|
links: map[string]struct{}{},
|
||||||
|
}
|
||||||
|
|
||||||
|
pgs[base] = content
|
||||||
|
|
||||||
|
// Build link index for this page.
|
||||||
|
|
||||||
|
if err := func() error {
|
||||||
|
defer res.Body.Close()
|
||||||
|
return linksOnPage(res.Body, func(link string) error {
|
||||||
|
u, err := url.Parse(link)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Links may be relative
|
||||||
|
abs := baseURL.ResolveReference(u).String()
|
||||||
|
content.links[abs] = struct{}{}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}(); err != nil {
|
||||||
|
return false, errContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := content.links[path]
|
||||||
|
return ok, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func linksOnPage(r io.Reader, visit func(string) error) error {
|
||||||
|
|
||||||
|
doc, err := goquery.NewDocumentFromReader(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.Find("a").Each(func(_ int, s *goquery.Selection) {
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if link, ok := s.Attr("href"); ok {
|
||||||
|
err = visit(link)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
52
cmd/csaf_checker/links_test.go
Normal file
52
cmd/csaf_checker/links_test.go
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const page0 = `<html>
|
||||||
|
<body>
|
||||||
|
<a href="not-a-json">Not a JSON</a>
|
||||||
|
<a href="link0.json">link0</a>
|
||||||
|
<ol>
|
||||||
|
<li><a href="link1.json">link1</a></li>
|
||||||
|
<li><a href="link2.json">link1</a></li>
|
||||||
|
</ol>
|
||||||
|
<p>
|
||||||
|
<div>
|
||||||
|
<li><a href="link3.json">link1</a></li>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
</body>
|
||||||
|
</html>`
|
||||||
|
|
||||||
|
func TestLinksOnPage(t *testing.T) {
|
||||||
|
|
||||||
|
var links []string
|
||||||
|
|
||||||
|
err := linksOnPage(
|
||||||
|
strings.NewReader(page0),
|
||||||
|
func(s string) error {
|
||||||
|
if strings.HasSuffix(s, ".json") {
|
||||||
|
links = append(links, s)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if l := len(links); l != 4 {
|
||||||
|
t.Fatalf("Expected 4 links, go %d\n", l)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, link := range links {
|
||||||
|
href := fmt.Sprintf("link%d.json", i)
|
||||||
|
if href != link {
|
||||||
|
t.Fatalf("Expected link '%s', got '%s'\n", href, link)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -59,6 +59,7 @@ type processor struct {
|
||||||
badFolders topicMessages
|
badFolders topicMessages
|
||||||
badWellknownMetadata topicMessages
|
badWellknownMetadata topicMessages
|
||||||
badDNSPath topicMessages
|
badDNSPath topicMessages
|
||||||
|
badDirListings topicMessages
|
||||||
|
|
||||||
expr *util.PathEval
|
expr *util.PathEval
|
||||||
}
|
}
|
||||||
|
|
@ -85,6 +86,8 @@ const (
|
||||||
rolieChangesMask
|
rolieChangesMask
|
||||||
indexMask
|
indexMask
|
||||||
changesMask
|
changesMask
|
||||||
|
listingMask
|
||||||
|
rolieListingMask
|
||||||
)
|
)
|
||||||
|
|
||||||
func (wt whereType) String() string {
|
func (wt whereType) String() string {
|
||||||
|
|
@ -99,6 +102,10 @@ func (wt whereType) String() string {
|
||||||
return "index.txt"
|
return "index.txt"
|
||||||
case changesMask:
|
case changesMask:
|
||||||
return "changes.csv"
|
return "changes.csv"
|
||||||
|
case listingMask:
|
||||||
|
return "directory listing"
|
||||||
|
case rolieListingMask:
|
||||||
|
return "directory listing [ROLIE]"
|
||||||
default:
|
default:
|
||||||
var mixed []string
|
var mixed []string
|
||||||
for mask := rolieMask; mask <= changesMask; mask <<= 1 {
|
for mask := rolieMask; mask <= changesMask; mask <<= 1 {
|
||||||
|
|
@ -157,6 +164,10 @@ func (p *processor) clean() {
|
||||||
p.badSecurity.reset()
|
p.badSecurity.reset()
|
||||||
p.badIndices.reset()
|
p.badIndices.reset()
|
||||||
p.badChanges.reset()
|
p.badChanges.reset()
|
||||||
|
p.badFolders.reset()
|
||||||
|
p.badWellknownMetadata.reset()
|
||||||
|
p.badDNSPath.reset()
|
||||||
|
p.badDirListings.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
// run calls checkDomain function for each domain in the given "domains" parameter.
|
// run calls checkDomain function for each domain in the given "domains" parameter.
|
||||||
|
|
@ -193,6 +204,7 @@ func (p *processor) checkDomain(domain string) error {
|
||||||
(*processor).checkSecurity,
|
(*processor).checkSecurity,
|
||||||
(*processor).checkCSAFs,
|
(*processor).checkCSAFs,
|
||||||
(*processor).checkMissing,
|
(*processor).checkMissing,
|
||||||
|
(*processor).checkListing,
|
||||||
(*processor).checkWellknownMetadataReporter,
|
(*processor).checkWellknownMetadataReporter,
|
||||||
(*processor).checkDNSPathReporter,
|
(*processor).checkDNSPathReporter,
|
||||||
} {
|
} {
|
||||||
|
|
@ -241,7 +253,7 @@ func (p *processor) checkRedirect(r *http.Request, via []*http.Request) error {
|
||||||
p.redirects[url] = path.String()
|
p.redirects[url] = path.String()
|
||||||
|
|
||||||
if len(via) > 10 {
|
if len(via) > 10 {
|
||||||
return errors.New("Too many redirections")
|
return errors.New("too many redirections")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -696,7 +708,7 @@ func (p *processor) checkMissing(string) error {
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
v := p.alreadyChecked[f]
|
v := p.alreadyChecked[f]
|
||||||
var where []string
|
var where []string
|
||||||
for mask := rolieMask; mask <= changesMask; mask <<= 1 {
|
for mask := rolieMask; mask <= rolieListingMask; mask <<= 1 {
|
||||||
if maxMask&mask == mask {
|
if maxMask&mask == mask {
|
||||||
var in string
|
var in string
|
||||||
if v&mask == mask {
|
if v&mask == mask {
|
||||||
|
|
@ -712,6 +724,35 @@ func (p *processor) checkMissing(string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkListing wents over all found adivisories URLs and checks,
|
||||||
|
// if their parent directory is listable.
|
||||||
|
func (p *processor) checkListing(string) error {
|
||||||
|
|
||||||
|
p.badDirListings.use()
|
||||||
|
|
||||||
|
pgs := pages{}
|
||||||
|
|
||||||
|
var unlisted []string
|
||||||
|
|
||||||
|
for f := range p.alreadyChecked {
|
||||||
|
found, err := pgs.listed(f, p)
|
||||||
|
if err != nil && err != errContinue {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
unlisted = append(unlisted, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(unlisted) > 0 {
|
||||||
|
sort.Strings(unlisted)
|
||||||
|
p.badDirListings.add("Not listed advisories: %s",
|
||||||
|
strings.Join(unlisted, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var providerMetadataLocations = [...]string{
|
var providerMetadataLocations = [...]string{
|
||||||
".well-known/csaf",
|
".well-known/csaf",
|
||||||
"security/data/csaf",
|
"security/data/csaf",
|
||||||
|
|
@ -803,7 +844,7 @@ func (p *processor) extractProviderURL(r io.Reader) (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if len(urls) == 0 {
|
if len(urls) == 0 {
|
||||||
return "", errors.New("No provider-metadata.json found")
|
return "", errors.New("no provider-metadata.json found")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(urls) > 1 {
|
if len(urls) > 1 {
|
||||||
|
|
|
||||||
|
|
@ -186,10 +186,17 @@ func (r *changesReporter) report(p *processor, domain *Domain) {
|
||||||
req.Messages = p.badChanges
|
req.Messages = p.badChanges
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *directoryListingsReporter) report(_ *processor, domain *Domain) {
|
func (r *directoryListingsReporter) report(p *processor, domain *Domain) {
|
||||||
// TODO: Implement me!
|
|
||||||
req := r.requirement(domain)
|
req := r.requirement(domain)
|
||||||
_ = req
|
if !p.badDirListings.used() {
|
||||||
|
req.message("No directory listings checked.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(p.badDirListings) == 0 {
|
||||||
|
req.message("All directory listings are valid.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.Messages = p.badDirListings
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *integrityReporter) report(p *processor, domain *Domain) {
|
func (r *integrityReporter) report(p *processor, domain *Domain) {
|
||||||
|
|
|
||||||
23
go.mod
23
go.mod
|
|
@ -3,25 +3,26 @@ module github.com/csaf-poc/csaf_distribution
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v0.4.1
|
github.com/BurntSushi/toml v1.1.0
|
||||||
github.com/PaesslerAG/gval v1.1.2
|
github.com/PaesslerAG/gval v1.1.2
|
||||||
github.com/PaesslerAG/jsonpath v0.1.1
|
github.com/PaesslerAG/jsonpath v0.1.1
|
||||||
github.com/ProtonMail/gopenpgp/v2 v2.3.0
|
github.com/ProtonMail/gopenpgp/v2 v2.4.7
|
||||||
|
github.com/PuerkitoBio/goquery v1.8.0
|
||||||
github.com/gofrs/flock v0.8.1
|
github.com/gofrs/flock v0.8.1
|
||||||
github.com/jessevdk/go-flags v1.5.0
|
github.com/jessevdk/go-flags v1.5.0
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0
|
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0
|
||||||
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e
|
golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8
|
golang.org/x/time v0.0.0-20220411224347-583f2d630306
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3 // indirect
|
github.com/ProtonMail/go-crypto v0.0.0-20220512085406-902f79d34c9f // indirect
|
||||||
github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a // indirect
|
github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f // indirect
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
|
github.com/andybalholm/cascadia v1.3.1 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/sirupsen/logrus v1.4.2 // indirect
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
|
golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a // indirect
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
|
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 // indirect
|
||||||
golang.org/x/text v0.3.6 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
43
go.sum
43
go.sum
|
|
@ -1,5 +1,5 @@
|
||||||
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
|
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
|
||||||
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
|
github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
|
||||||
github.com/PaesslerAG/gval v1.1.2 h1:EROKxV4/fAKWb0Qoj7NOxmHZA7gcpjOV9XgiRZMRCUU=
|
github.com/PaesslerAG/gval v1.1.2 h1:EROKxV4/fAKWb0Qoj7NOxmHZA7gcpjOV9XgiRZMRCUU=
|
||||||
|
|
@ -7,12 +7,18 @@ github.com/PaesslerAG/gval v1.1.2/go.mod h1:Fa8gfkCmUsELXgayr8sfL/sw+VzCVoa03dcO
|
||||||
github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8=
|
github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8=
|
||||||
github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk=
|
github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk=
|
||||||
github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY=
|
github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY=
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3 h1:XcF0cTDJeiuZ5NU8w7WUDge0HRwwNRmxj/GGk6KSA6g=
|
github.com/ProtonMail/go-crypto v0.0.0-20220113124808-70ae35bab23f/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
github.com/ProtonMail/go-crypto v0.0.0-20220512085406-902f79d34c9f h1:CP4ZCltXExnPiLQFuj0oucZxRRH5ZLL+lT5Bl7Eh37g=
|
||||||
github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a h1:W6RrgN/sTxg1msqzFFb+G80MFmpjMw61IU+slm+wln4=
|
github.com/ProtonMail/go-crypto v0.0.0-20220512085406-902f79d34c9f/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||||
github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4=
|
github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4=
|
||||||
github.com/ProtonMail/gopenpgp/v2 v2.3.0 h1:eniutitHk02Yn3GtaDfJTVm/Ca1e8s6zkS0SpeaocXI=
|
github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc=
|
||||||
github.com/ProtonMail/gopenpgp/v2 v2.3.0/go.mod h1:F62x0m3akQuisX36pOgAtKOHZ1E7/MpnX8bZWCK+5dA=
|
github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM=
|
||||||
|
github.com/ProtonMail/gopenpgp/v2 v2.4.7 h1:V3xeelvXgJiZXZuPtSSE+uYbtPw4RmbmyPqXDAESPhg=
|
||||||
|
github.com/ProtonMail/gopenpgp/v2 v2.4.7/go.mod h1:ZW1KxHNG6q5LMgFKf9Ap/d2eVYeyGf5+fAUEAjJWtmo=
|
||||||
|
github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
|
||||||
|
github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
|
||||||
|
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
|
||||||
|
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
|
@ -20,7 +26,6 @@ github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||||
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
|
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
|
||||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
|
@ -30,7 +35,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 h1:TToq11gyfNlrMFZiYujSekIsPd9AmsA2Bj/iv+s4JHE=
|
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 h1:TToq11gyfNlrMFZiYujSekIsPd9AmsA2Bj/iv+s4JHE=
|
||||||
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
|
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
|
||||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
|
@ -41,8 +45,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e h1:MUP6MR3rJ7Gk9LEia0LP2ytiH6MuCfs7qYz+47jGdD8=
|
golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9 h1:NUzdAbFtCJSXU20AOXgeqaUwg8Ypg4MPYmL+d+rsB5c=
|
||||||
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
|
@ -55,6 +59,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
|
@ -63,17 +69,20 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a h1:N2T1jUrTQE9Re6TFF5PhvEHXHCguynGhKjWVsIUt5cY=
|
||||||
|
golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 h1:EH1Deb8WZJ0xc0WK//leUHXcX9aLE5SymusoTmMZye8=
|
||||||
|
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w=
|
||||||
|
golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue