Implement attachment checking in CLI (#141)
This commit is contained in:
parent
34275baa2f
commit
9a530e1c66
16 changed files with 374 additions and 17 deletions
5
.github/workflows/codeql.yml
vendored
5
.github/workflows/codeql.yml
vendored
|
@ -30,6 +30,11 @@ jobs:
|
|||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
|
|
7
api.go
7
api.go
|
@ -39,6 +39,7 @@ func (a apiServer) Register(r *mux.Router) {
|
|||
r.HandleFunc("/create", a.handleCreate)
|
||||
r.HandleFunc("/get/{id}", a.handleRead)
|
||||
r.HandleFunc("/isWritable", func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNoContent) })
|
||||
r.HandleFunc("/settings", a.handleSettings).Methods(http.MethodGet)
|
||||
}
|
||||
|
||||
func (a apiServer) handleCreate(res http.ResponseWriter, r *http.Request) {
|
||||
|
@ -111,6 +112,10 @@ func (a apiServer) handleRead(res http.ResponseWriter, r *http.Request) {
|
|||
})
|
||||
}
|
||||
|
||||
func (a apiServer) handleSettings(w http.ResponseWriter, _ *http.Request) {
|
||||
a.jsonResponse(w, http.StatusOK, cust)
|
||||
}
|
||||
|
||||
func (a apiServer) errorResponse(res http.ResponseWriter, status int, err error, desc string) {
|
||||
errID := uuid.Must(uuid.NewV4()).String()
|
||||
|
||||
|
@ -124,7 +129,7 @@ func (a apiServer) errorResponse(res http.ResponseWriter, status int, err error,
|
|||
})
|
||||
}
|
||||
|
||||
func (apiServer) jsonResponse(res http.ResponseWriter, status int, response apiResponse) {
|
||||
func (apiServer) jsonResponse(res http.ResponseWriter, status int, response any) {
|
||||
res.Header().Set("Content-Type", "application/json")
|
||||
res.Header().Set("Cache-Control", "no-store, max-age=0")
|
||||
res.WriteHeader(status)
|
||||
|
|
|
@ -93,7 +93,7 @@ func createRunE(cmd *cobra.Command, _ []string) (err error) {
|
|||
})
|
||||
}
|
||||
|
||||
// Create the secret
|
||||
// Get flags for creation
|
||||
logrus.Info("creating the secret...")
|
||||
instanceURL, err := cmd.Flags().GetString("instance")
|
||||
if err != nil {
|
||||
|
@ -105,6 +105,12 @@ func createRunE(cmd *cobra.Command, _ []string) (err error) {
|
|||
return fmt.Errorf("getting expire flag: %w", err)
|
||||
}
|
||||
|
||||
// Execute sanity checks
|
||||
if err = client.SanityCheck(instanceURL, secret); err != nil {
|
||||
return fmt.Errorf("sanity checking secret: %w", err)
|
||||
}
|
||||
|
||||
// Create the secret
|
||||
secretURL, expiresAt, err := client.Create(instanceURL, secret, expire)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating secret: %w", err)
|
||||
|
|
|
@ -2,7 +2,10 @@ module github.com/Luzifer/ots/cmd/ots-cli
|
|||
|
||||
go 1.21.1
|
||||
|
||||
replace github.com/Luzifer/ots/pkg/client => ../../pkg/client
|
||||
replace (
|
||||
github.com/Luzifer/ots/pkg/client => ../../pkg/client
|
||||
github.com/Luzifer/ots/pkg/customization => ../../pkg/customization
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Luzifer/ots/pkg/client v0.0.0-20231009165114-f1e303cbe5a7
|
||||
|
@ -12,8 +15,12 @@ require (
|
|||
|
||||
require (
|
||||
github.com/Luzifer/go-openssl/v4 v4.2.1 // indirect
|
||||
github.com/Luzifer/ots/pkg/customization v0.0.0-00010101000000-000000000000 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
|
|
@ -6,9 +6,13 @@ 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/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
|
||||
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
||||
|
@ -24,7 +28,10 @@ golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf
|
|||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
9
go.mod
9
go.mod
|
@ -1,9 +1,14 @@
|
|||
module github.com/Luzifer/ots
|
||||
|
||||
go 1.20
|
||||
go 1.21.1
|
||||
|
||||
toolchain go1.21.2
|
||||
|
||||
replace github.com/Luzifer/ots/pkg/customization => ./pkg/customization
|
||||
|
||||
require (
|
||||
github.com/Luzifer/go_helpers/v2 v2.20.0
|
||||
github.com/Luzifer/ots/pkg/customization v0.0.0-00010101000000-000000000000
|
||||
github.com/Luzifer/rconfig/v2 v2.4.0
|
||||
github.com/Masterminds/sprig/v3 v3.2.3
|
||||
github.com/gofrs/uuid v4.4.0+incompatible
|
||||
|
@ -11,7 +16,6 @@ require (
|
|||
github.com/pkg/errors v0.9.1
|
||||
github.com/redis/go-redis/v9 v9.2.1
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -30,4 +34,5 @@ require (
|
|||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
gopkg.in/validator.v2 v2.0.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
|
16
go.sum
16
go.sum
|
@ -10,7 +10,9 @@ github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYr
|
|||
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -19,10 +21,13 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
|
@ -35,7 +40,9 @@ github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH
|
|||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
|
@ -43,8 +50,11 @@ github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx
|
|||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
|
||||
github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
|
@ -52,6 +62,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
|||
github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg=
|
||||
github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
|
@ -67,6 +78,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
|
@ -79,6 +91,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -98,13 +111,16 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/validator.v2 v2.0.1 h1:xF0KWyGWXm/LM2G1TrEjqOu4pa6coO9AlWSf3msVfDY=
|
||||
gopkg.in/validator.v2 v2.0.1/go.mod h1:lIUZBlB3Im4s/eYp39Ry/wkR02yOPhZ9IwIRBjuPuG8=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
7
main.go
7
main.go
|
@ -18,6 +18,7 @@ import (
|
|||
|
||||
file_helpers "github.com/Luzifer/go_helpers/v2/file"
|
||||
http_helpers "github.com/Luzifer/go_helpers/v2/http"
|
||||
"github.com/Luzifer/ots/pkg/customization"
|
||||
"github.com/Luzifer/rconfig/v2"
|
||||
)
|
||||
|
||||
|
@ -34,7 +35,7 @@ var (
|
|||
}
|
||||
|
||||
assets file_helpers.FSStack
|
||||
cust customize
|
||||
cust customization.Customize
|
||||
indexTpl *template.Template
|
||||
|
||||
version = "dev"
|
||||
|
@ -70,7 +71,7 @@ func initApp() error {
|
|||
}
|
||||
logrus.SetLevel(l)
|
||||
|
||||
if cust, err = loadCustomize(cfg.Customize); err != nil {
|
||||
if cust, err = customization.Load(cfg.Customize); err != nil {
|
||||
return errors.Wrap(err, "loading customizations")
|
||||
}
|
||||
|
||||
|
@ -182,7 +183,7 @@ func handleIndex(w http.ResponseWriter, _ *http.Request) {
|
|||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
|
||||
if err := indexTpl.Execute(w, struct {
|
||||
Customize customize
|
||||
Customize customization.Customize
|
||||
InlineContentNonce string
|
||||
MaxSecretExpiry int64
|
||||
Version string
|
||||
|
|
|
@ -19,9 +19,18 @@ import (
|
|||
"github.com/Luzifer/go-openssl/v4"
|
||||
)
|
||||
|
||||
type (
|
||||
// HTTPClientIntf describes a minimal interface to be fulfilled
|
||||
// by the given HTTP client. This can be used for mocking and to
|
||||
// pass in authenticated clients
|
||||
HTTPClientIntf interface {
|
||||
Do(*http.Request) (*http.Response, error)
|
||||
}
|
||||
)
|
||||
|
||||
// HTTPClient defines the client to use for create and fetch requests
|
||||
// and can be overwritten to provide authentication
|
||||
var HTTPClient = http.DefaultClient
|
||||
var HTTPClient HTTPClientIntf = http.DefaultClient
|
||||
|
||||
// KeyDerivationFunc defines the key derivation algorithm used in OTS
|
||||
// to derive the key / iv from the password for encryption. You only
|
||||
|
|
|
@ -2,14 +2,22 @@ module github.com/Luzifer/ots/pkg/client
|
|||
|
||||
go 1.21.1
|
||||
|
||||
replace github.com/Luzifer/ots/pkg/customization => ../customization
|
||||
|
||||
require (
|
||||
github.com/Luzifer/go-openssl/v4 v4.2.1
|
||||
github.com/Luzifer/ots/pkg/customization v0.0.0-00010101000000-000000000000
|
||||
github.com/ryanuber/go-glob v1.0.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/crypto v0.12.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
|
@ -1,14 +1,29 @@
|
|||
github.com/Luzifer/go-openssl/v4 v4.2.1 h1:0+/gaQ5TcBhGmVqGrfyA21eujlbbaNwj0VlOA3nh4ts=
|
||||
github.com/Luzifer/go-openssl/v4 v4.2.1/go.mod h1:CZZZWY0buCtkxrkqDPQYigC4Kn55UuO97TEoV+hwz2s=
|
||||
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
|
||||
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
136
pkg/client/sanity.go
Normal file
136
pkg/client/sanity.go
Normal file
|
@ -0,0 +1,136 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/Luzifer/ots/pkg/customization"
|
||||
"github.com/ryanuber/go-glob"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrAttachmentsDisabled signalizes the instance has attachments
|
||||
// disabled but the checked secret contains attachments
|
||||
ErrAttachmentsDisabled = errors.New("attachments are disabled on this instance")
|
||||
// ErrAttachmentsTooLarge signalizes the size of the attached files
|
||||
// exceeds the configured maximum size of the given instance
|
||||
ErrAttachmentsTooLarge = errors.New("attachment size exceeds allowed size")
|
||||
// ErrAttachmentTypeNotAllowed signalizes any file does not match
|
||||
// the allowed extensions / mime types
|
||||
ErrAttachmentTypeNotAllowed = errors.New("attachment type is not allowed")
|
||||
|
||||
errSettingsNotFound = errors.New("settings not found")
|
||||
mimeRegex = regexp.MustCompile(`^(?:[a-z]+|\*)\/(?:[a-zA-Z0-9.+_-]+|\*)$`)
|
||||
)
|
||||
|
||||
// SanityCheck fetches the instance settings and validates the secret
|
||||
// against those settings (matching file size, disabled attachments,
|
||||
// allowed file types, ...)
|
||||
func SanityCheck(instanceURL string, secret Secret) error {
|
||||
cust, err := loadSettings(instanceURL)
|
||||
if err != nil {
|
||||
if errors.Is(err, errSettingsNotFound) {
|
||||
// Sanity check is not possible when the API endpoint is not
|
||||
// supported, therefore we ignore this.
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("fetching settings: %w", err)
|
||||
}
|
||||
|
||||
// Check whether attachments are allowed at all
|
||||
if cust.DisableFileAttachment && len(secret.Attachments) > 0 {
|
||||
return ErrAttachmentsDisabled
|
||||
}
|
||||
|
||||
// Check whether attachments are too large
|
||||
var totalAttachmentSize int64
|
||||
for _, a := range secret.Attachments {
|
||||
totalAttachmentSize += int64(len(a.Content))
|
||||
}
|
||||
if cust.MaxAttachmentSizeTotal > 0 && totalAttachmentSize > cust.MaxAttachmentSizeTotal {
|
||||
return ErrAttachmentsTooLarge
|
||||
}
|
||||
|
||||
// Check for allowed types
|
||||
if cust.AcceptedFileTypes != "" {
|
||||
allowed := strings.Split(cust.AcceptedFileTypes, ",")
|
||||
for _, a := range secret.Attachments {
|
||||
if !attachmentAllowed(a, allowed) {
|
||||
return ErrAttachmentTypeNotAllowed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func attachmentAllowed(file SecretAttachment, allowed []string) bool {
|
||||
for _, a := range allowed {
|
||||
switch {
|
||||
case mimeRegex.MatchString(a):
|
||||
// That's a mime type
|
||||
if glob.Glob(a, file.Type) {
|
||||
// The mime "glob" matches the file type
|
||||
return true
|
||||
}
|
||||
|
||||
case a[0] == '.':
|
||||
// That's a file extension
|
||||
if strings.HasSuffix(file.Name, a) {
|
||||
// The filename has the right extension
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func loadSettings(instanceURL string) (c customization.Customize, err error) {
|
||||
u, err := url.Parse(instanceURL)
|
||||
if err != nil {
|
||||
return c, fmt.Errorf("parsing instance URL: %w", err)
|
||||
}
|
||||
|
||||
createURL := u.JoinPath(strings.Join([]string{".", "api", "settings"}, "/"))
|
||||
ctx, cancel := context.WithTimeout(context.Background(), RequestTimeout)
|
||||
defer cancel()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, createURL.String(), nil)
|
||||
if err != nil {
|
||||
return c, fmt.Errorf("creating request: %w", err)
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("User-Agent", UserAgent)
|
||||
|
||||
resp, err := HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return c, fmt.Errorf("executing request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close() //nolint:errcheck // possible leaked-fd, lib should not log, potential short-lived leak
|
||||
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
return c, errSettingsNotFound
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return c, fmt.Errorf("unexpected HTTP status %d", resp.StatusCode)
|
||||
}
|
||||
return c, fmt.Errorf("unexpected HTTP status %d (%s)", resp.StatusCode, respBody)
|
||||
}
|
||||
|
||||
if err = json.NewDecoder(resp.Body).Decode(&c); err != nil {
|
||||
return c, fmt.Errorf("decoding response: %w", err)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
100
pkg/client/sanity_test.go
Normal file
100
pkg/client/sanity_test.go
Normal file
|
@ -0,0 +1,100 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/Luzifer/ots/pkg/customization"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type custMockClient struct {
|
||||
Response *customization.Customize
|
||||
}
|
||||
|
||||
func (c custMockClient) Do(r *http.Request) (*http.Response, error) {
|
||||
m := http.NewServeMux()
|
||||
m.HandleFunc(r.URL.Path, func(w http.ResponseWriter, _ *http.Request) {
|
||||
if c.Response == nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
d, _ := c.Response.ToJSON()
|
||||
_, _ = w.Write([]byte(d))
|
||||
})
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
m.ServeHTTP(w, r)
|
||||
|
||||
return w.Result(), nil
|
||||
}
|
||||
|
||||
func TestSanityCheck(t *testing.T) {
|
||||
var (
|
||||
err error
|
||||
m = custMockClient{&customization.Customize{
|
||||
AcceptedFileTypes: "text/*,image/png,.gif",
|
||||
DisableFileAttachment: true,
|
||||
MaxAttachmentSizeTotal: 64,
|
||||
}}
|
||||
u = "http://localhost/"
|
||||
)
|
||||
|
||||
HTTPClient = &m
|
||||
defer func() { HTTPClient = http.DefaultClient }()
|
||||
|
||||
s := Secret{Secret: "ohai"}
|
||||
|
||||
// no attachments & attachments disabled
|
||||
err = SanityCheck(u, s)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// attachments & attachmetns disabled
|
||||
s.Attachments = []SecretAttachment{
|
||||
{Name: "myfile.webm", Type: "video/webm", Content: []byte{0x0}},
|
||||
}
|
||||
|
||||
err = SanityCheck(u, s)
|
||||
assert.ErrorIs(t, err, ErrAttachmentsDisabled)
|
||||
|
||||
// disallowed attachment
|
||||
m.Response.DisableFileAttachment = false
|
||||
err = SanityCheck(u, s)
|
||||
assert.ErrorIs(t, err, ErrAttachmentTypeNotAllowed)
|
||||
|
||||
// attachment allowed by extension
|
||||
s.Attachments = []SecretAttachment{
|
||||
{Name: "doesthiswork.gif", Type: "image/gif", Content: []byte{0x0}},
|
||||
}
|
||||
err = SanityCheck(u, s)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// attachment allowed by mime type
|
||||
s.Attachments = []SecretAttachment{
|
||||
{Name: "doesthiswork.png", Type: "image/png", Content: []byte{0x0}},
|
||||
}
|
||||
err = SanityCheck(u, s)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// attachment allowed by mime type wildcard
|
||||
s.Attachments = []SecretAttachment{
|
||||
{Name: "doesthiswork.md", Type: "text/markdown", Content: []byte{0x0}},
|
||||
}
|
||||
err = SanityCheck(u, s)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// attachment too large
|
||||
s.Attachments = []SecretAttachment{
|
||||
{Name: "doesthiswork.md", Type: "text/markdown", Content: bytes.Repeat([]byte{0x0}, 128)},
|
||||
}
|
||||
err = SanityCheck(u, s)
|
||||
assert.ErrorIs(t, err, ErrAttachmentsTooLarge)
|
||||
|
||||
// check without settings API on instance
|
||||
m.Response = nil
|
||||
err = SanityCheck(u, s)
|
||||
assert.NoError(t, err)
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
package main
|
||||
// Package customization contains the structure for the customization
|
||||
// file to configure the OTS web- and command-line interface
|
||||
package customization
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -11,7 +13,8 @@ import (
|
|||
)
|
||||
|
||||
type (
|
||||
customize struct {
|
||||
// Customize holds the structure of the customization file
|
||||
Customize struct {
|
||||
AppIcon string `json:"appIcon,omitempty" yaml:"appIcon"`
|
||||
AppTitle string `json:"appTitle,omitempty" yaml:"appTitle"`
|
||||
DisableAppTitle bool `json:"disableAppTitle,omitempty" yaml:"disableAppTitle"`
|
||||
|
@ -31,7 +34,8 @@ type (
|
|||
}
|
||||
)
|
||||
|
||||
func loadCustomize(filename string) (cust customize, err error) {
|
||||
// Load retrieves the Customization file from filesystem
|
||||
func Load(filename string) (cust Customize, err error) {
|
||||
if filename == "" {
|
||||
// None given, take a shortcut
|
||||
cust.applyFixes()
|
||||
|
@ -61,12 +65,14 @@ func loadCustomize(filename string) (cust customize, err error) {
|
|||
return cust, nil
|
||||
}
|
||||
|
||||
func (c customize) ToJSON() (string, error) {
|
||||
// ToJSON is a templating helper which returns the customization
|
||||
// serialized as JSON in a string
|
||||
func (c Customize) ToJSON() (string, error) {
|
||||
j, err := json.Marshal(c)
|
||||
return string(j), errors.Wrap(err, "marshalling JSON")
|
||||
}
|
||||
|
||||
func (c *customize) applyFixes() {
|
||||
func (c *Customize) applyFixes() {
|
||||
if len(c.AppTitle) == 0 {
|
||||
c.AppTitle = "OTS - One Time Secrets"
|
||||
}
|
11
pkg/customization/go.mod
Normal file
11
pkg/customization/go.mod
Normal file
|
@ -0,0 +1,11 @@
|
|||
module github.com/Luzifer/ots/pkg/customization
|
||||
|
||||
go 1.21.1
|
||||
|
||||
require (
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
|
20
pkg/customization/go.sum
Normal file
20
pkg/customization/go.sum
Normal file
|
@ -0,0 +1,20 @@
|
|||
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
Loading…
Reference in a new issue