mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-24 08:02:18 +02:00
Migrate to maintained httpsign library (#3839)
Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
parent
047eb19d42
commit
b330c19bf4
@ -78,7 +78,7 @@
|
||||
"homelab",
|
||||
"HTMLURL",
|
||||
"HTTPFS",
|
||||
"httpsig",
|
||||
"httpsign",
|
||||
"HTTPURL",
|
||||
"httputil",
|
||||
"ianvs",
|
||||
|
@ -3,7 +3,7 @@
|
||||
To provide additional management and preprocessing capabilities for pipeline configurations Woodpecker supports an HTTP API which can be enabled to call an external config service.
|
||||
Before the run or restart of any pipeline Woodpecker will make a POST request to an external HTTP API sending the current repository, build information and all current config files retrieved from the repository. The external API can then send back new pipeline configurations that will be used immediately or respond with `HTTP 204` to tell the system to use the existing configuration.
|
||||
|
||||
Every request sent by Woodpecker is signed using a [http-signature](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures) by a private key (ed25519) generated on the first start of the Woodpecker server. You can get the public key for the verification of the http-signature from `http(s)://your-woodpecker-server/api/signature/public-key`.
|
||||
Every request sent by Woodpecker is signed using a [http-signature](https://datatracker.ietf.org/doc/html/rfc9421) by a private key (ed25519) generated on the first start of the Woodpecker server. You can get the public key for the verification of the http-signature from `http(s)://your-woodpecker-server/api/signature/public-key`.
|
||||
|
||||
A simplistic example configuration service can be found here: [https://github.com/woodpecker-ci/example-config-service](https://github.com/woodpecker-ci/example-config-service)
|
||||
|
||||
|
@ -22,6 +22,7 @@ Some versions need some changes to the server configuration or the pipeline conf
|
||||
- Deprecated slice definition for env vars
|
||||
- Deprecated `environment` filter, use `when.evaluate`
|
||||
- Deprecated `WOODPECKER_WEBHOOK_HOST` in favor of `WOODPECKER_EXPERT_WEBHOOK_HOST`
|
||||
- Migrated to rfc9421 for webhook signatures
|
||||
|
||||
## 2.0.0
|
||||
|
||||
|
13
go.mod
13
go.mod
@ -29,7 +29,6 @@ require (
|
||||
github.com/getkin/kin-openapi v0.126.0
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/gitsight/go-vcsurl v1.0.1
|
||||
github.com/go-ap/httpsig v0.0.0-20221203064646-3647b4d88fdf
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
github.com/google/go-github/v63 v63.0.0
|
||||
@ -60,6 +59,7 @@ require (
|
||||
github.com/urfave/cli/v3 v3.0.0-alpha9.0.20240711030030-937cfe918cb1
|
||||
github.com/xanzy/go-gitlab v0.107.0
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
github.com/yaronf/httpsign v0.3.1
|
||||
github.com/zalando/go-keyring v0.2.5
|
||||
go.uber.org/multierr v1.11.0
|
||||
golang.org/x/crypto v0.25.0
|
||||
@ -107,8 +107,10 @@ require (
|
||||
github.com/danieljoos/wincred v1.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.8.0 // indirect
|
||||
github.com/dunglas/httpsfv v1.0.2 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
@ -124,7 +126,7 @@ require (
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
@ -145,6 +147,12 @@ require (
|
||||
github.com/julienschmidt/httprouter v1.3.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
|
||||
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
||||
github.com/lestrrat-go/httprc v1.0.5 // indirect
|
||||
github.com/lestrrat-go/iter v1.0.2 // indirect
|
||||
github.com/lestrrat-go/jwx/v2 v2.1.0 // indirect
|
||||
github.com/lestrrat-go/option v1.0.1 // indirect
|
||||
github.com/libdns/libdns v0.2.2 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
@ -174,6 +182,7 @@ require (
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/segmentio/asm v1.2.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
|
30
go.sum
30
go.sum
@ -30,6 +30,8 @@ github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY=
|
||||
github.com/adrg/xdg v0.5.0/go.mod h1:dDdY4M4DF9Rjy4kHPeNL+ilVF+p2lK8IdM9/rTSGcI4=
|
||||
github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=
|
||||
github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||
@ -99,6 +101,8 @@ 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/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
|
||||
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
||||
github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+8Y+8shw=
|
||||
github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo=
|
||||
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
|
||||
@ -118,6 +122,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g=
|
||||
github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g=
|
||||
github.com/dunglas/httpsfv v1.0.2 h1:iERDp/YAfnojSDJ7PW3dj1AReJz4MrwbECSSE59JWL0=
|
||||
github.com/dunglas/httpsfv v1.0.2/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
@ -147,8 +153,6 @@ github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/gitsight/go-vcsurl v1.0.1 h1:wkijKsbVg9R2IBP97U7wOANeIW9WJJKkBwS9XqllzWo=
|
||||
github.com/gitsight/go-vcsurl v1.0.1/go.mod h1:qRFdKDa/0Lh9MT0xE+qQBYZ/01+mY1H40rZUHR24X9U=
|
||||
github.com/go-ap/httpsig v0.0.0-20221203064646-3647b4d88fdf h1:Ab5yBsD/dXhFmgf2hX7T/YYr+VK0Df7SrIxyNztT9YE=
|
||||
github.com/go-ap/httpsig v0.0.0-20221203064646-3647b4d88fdf/go.mod h1:+4SUDMvPlRMUPW5PlMTbxj3U5a4fWasBIbakUw7Kp6c=
|
||||
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
|
||||
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
@ -180,8 +184,9 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4
|
||||
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
||||
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
@ -324,6 +329,18 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
|
||||
github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
|
||||
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
|
||||
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
|
||||
github.com/lestrrat-go/httprc v1.0.5 h1:bsTfiH8xaKOJPrg1R+E3iE/AWZr/x0Phj9PBTG/OLUk=
|
||||
github.com/lestrrat-go/httprc v1.0.5/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
|
||||
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
|
||||
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
|
||||
github.com/lestrrat-go/jwx/v2 v2.1.0 h1:0zs7Ya6+39qoit7gwAf+cYm1zzgS3fceIdo7RmQ5lkw=
|
||||
github.com/lestrrat-go/jwx/v2 v2.1.0/go.mod h1:Xpw9QIaUGiIUD1Wx0NcY1sIHwFf8lDuZn/cmxtXYRys=
|
||||
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
|
||||
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
@ -447,6 +464,10 @@ github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWR
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
@ -467,6 +488,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
@ -503,6 +525,8 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
github.com/yaronf/httpsign v0.3.1 h1:A4pqjwOVCwlExyy/mPTTryCHcXn+xhq4+wxq4BKhi2k=
|
||||
github.com/yaronf/httpsign v0.3.1/go.mod h1:+7d6GccMcoljvE3QtU00NCmR1iTXCVNfbMe5nqaxRG4=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
|
@ -27,9 +27,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-ap/httpsig"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/yaronf/httpsign"
|
||||
|
||||
"go.woodpecker-ci.org/woodpecker/v2/server/forge/mocks"
|
||||
forge_types "go.woodpecker-ci.org/woodpecker/v2/server/forge/types"
|
||||
@ -120,25 +120,19 @@ func TestFetchFromConfigService(t *testing.T) {
|
||||
|
||||
fixtureHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
// check signature
|
||||
pubKeyID := "woodpecker-ci-plugins"
|
||||
pubKeyID := "woodpecker-ci-extensions"
|
||||
|
||||
keystore := httpsig.NewMemoryKeyStore()
|
||||
keystore.SetKey(pubKeyID, pubEd25519Key)
|
||||
verifier, err := httpsign.NewEd25519Verifier(pubEd25519Key,
|
||||
httpsign.NewVerifyConfig(),
|
||||
httpsign.Headers("@request-target", "content-digest")) // The Content-Digest header will be auto-generated
|
||||
assert.NoError(t, err)
|
||||
|
||||
verifier := httpsig.NewVerifier(keystore)
|
||||
verifier.SetRequiredHeaders([]string{"(request-target)", "date"})
|
||||
|
||||
keyID, err := verifier.Verify(r)
|
||||
err = httpsign.VerifyRequest(pubKeyID, *verifier, r)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid signature", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if keyID != pubKeyID {
|
||||
http.Error(w, "Used wrong key", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
type config struct {
|
||||
Name string `json:"name"`
|
||||
Data string `json:"data"`
|
||||
@ -163,12 +157,12 @@ func TestFetchFromConfigService(t *testing.T) {
|
||||
}
|
||||
|
||||
if req.Repo.Name == "Fetch empty" {
|
||||
w.WriteHeader(404)
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
if req.Repo.Name == "Use old config" {
|
||||
w.WriteHeader(204)
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
|
||||
@ -192,7 +186,7 @@ func TestFetchFromConfigService(t *testing.T) {
|
||||
|
||||
ts := httptest.NewServer(http.HandlerFunc(fixtureHandler))
|
||||
defer ts.Close()
|
||||
httpFetcher := config.NewHTTP(ts.URL, privEd25519Key)
|
||||
httpFetcher := config.NewHTTP(ts.URL+"/", privEd25519Key)
|
||||
|
||||
for _, tt := range testTable {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
@ -16,7 +16,7 @@ package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/ed25519"
|
||||
"fmt"
|
||||
net_http "net/http"
|
||||
|
||||
@ -28,7 +28,7 @@ import (
|
||||
|
||||
type http struct {
|
||||
endpoint string
|
||||
privateKey crypto.PrivateKey
|
||||
privateKey ed25519.PrivateKey
|
||||
}
|
||||
|
||||
// configData same as forge.FileMeta but with json tags and string data.
|
||||
@ -48,7 +48,7 @@ type responseStructure struct {
|
||||
Configs []*configData `json:"configs"`
|
||||
}
|
||||
|
||||
func NewHTTP(endpoint string, privateKey crypto.PrivateKey) Service {
|
||||
func NewHTTP(endpoint string, privateKey ed25519.PrivateKey) Service {
|
||||
return &http{endpoint, privateKey}
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ func setupSecretService(store store.Store) secret.Service {
|
||||
return secret.NewDB(store)
|
||||
}
|
||||
|
||||
func setupConfigService(c *cli.Command, privateSignatureKey crypto.PrivateKey) (config.Service, error) {
|
||||
func setupConfigService(c *cli.Command, privateSignatureKey ed25519.PrivateKey) (config.Service, error) {
|
||||
timeout := c.Duration("forge-timeout")
|
||||
retries := c.Uint("forge-retry")
|
||||
if retries == 0 {
|
||||
@ -74,7 +74,7 @@ func setupConfigService(c *cli.Command, privateSignatureKey crypto.PrivateKey) (
|
||||
}
|
||||
|
||||
// setupSignatureKeys generate or load key pair to sign webhooks requests (i.e. used for service extensions).
|
||||
func setupSignatureKeys(_store store.Store) (crypto.PrivateKey, crypto.PublicKey, error) {
|
||||
func setupSignatureKeys(_store store.Store) (ed25519.PrivateKey, crypto.PublicKey, error) {
|
||||
privKeyID := "signature-private-key"
|
||||
|
||||
privKey, err := _store.ServerConfigGet(privKeyID)
|
||||
|
@ -17,19 +17,19 @@ package utils
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/ed25519"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/go-ap/httpsig"
|
||||
"github.com/yaronf/httpsign"
|
||||
)
|
||||
|
||||
// Send makes an http request to the given endpoint, writing the input
|
||||
// to the request body and un-marshaling the output from the response body.
|
||||
func Send(ctx context.Context, method, path string, privateKey crypto.PrivateKey, in, out any) (int, error) {
|
||||
func Send(ctx context.Context, method, path string, privateKey ed25519.PrivateKey, in, out any) (int, error) {
|
||||
uri, err := url.Parse(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@ -54,12 +54,12 @@ func Send(ctx context.Context, method, path string, privateKey crypto.PrivateKey
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
err = SignHTTPRequest(privateKey, req)
|
||||
client, err := signClient(privateKey)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -79,10 +79,14 @@ func Send(ctx context.Context, method, path string, privateKey crypto.PrivateKey
|
||||
return resp.StatusCode, err
|
||||
}
|
||||
|
||||
func SignHTTPRequest(privateKey crypto.PrivateKey, req *http.Request) error {
|
||||
pubKeyID := "woodpecker-ci-plugins"
|
||||
func signClient(privateKey ed25519.PrivateKey) (*httpsign.Client, error) {
|
||||
pubKeyID := "woodpecker-ci-extensions"
|
||||
|
||||
signer := httpsig.NewEd25519Signer(pubKeyID, privateKey, nil)
|
||||
|
||||
return signer.Sign(req)
|
||||
signer, err := httpsign.NewEd25519Signer(privateKey,
|
||||
httpsign.NewSignConfig(),
|
||||
httpsign.Headers("@request-target", "content-digest")) // The Content-Digest header will be auto-generated
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return httpsign.NewDefaultClient(httpsign.NewClientConfig().SetSignatureName(pubKeyID).SetSigner(signer)), nil // sign requests, don't verify responses
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package utils_test
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -21,15 +21,14 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-ap/httpsig"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"go.woodpecker-ci.org/woodpecker/v2/server/services/utils"
|
||||
"github.com/yaronf/httpsign"
|
||||
)
|
||||
|
||||
func TestSign(t *testing.T) {
|
||||
pubKeyID := "woodpecker-ci-plugins"
|
||||
func TestSignClient(t *testing.T) {
|
||||
pubKeyID := "woodpecker-ci-extensions"
|
||||
|
||||
pubEd25519Key, privEd25519Key, err := ed25519.GenerateKey(rand.Reader)
|
||||
if !assert.NoError(t, err) {
|
||||
@ -38,36 +37,36 @@ func TestSign(t *testing.T) {
|
||||
|
||||
body := []byte("{\"foo\":\"bar\"}")
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://example.com", bytes.NewBuffer(body))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
err = utils.SignHTTPRequest(privEd25519Key, req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
verifyHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
keystore := httpsig.NewMemoryKeyStore()
|
||||
keystore.SetKey(pubKeyID, pubEd25519Key)
|
||||
|
||||
verifier := httpsig.NewVerifier(keystore)
|
||||
verifier.SetRequiredHeaders([]string{"(request-target)", "date"})
|
||||
|
||||
keyID, err := verifier.Verify(r)
|
||||
verifier, err := httpsign.NewEd25519Verifier(pubEd25519Key,
|
||||
httpsign.NewVerifyConfig(),
|
||||
httpsign.Headers("@request-target", "content-digest")) // The Content-Digest header will be auto-generated
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = httpsign.VerifyRequest(pubKeyID, *verifier, r)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, pubKeyID, keyID)
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := http.HandlerFunc(verifyHandler)
|
||||
server := httptest.NewServer(http.HandlerFunc(verifyHandler))
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
req, err := http.NewRequest("GET", server.URL+"/", bytes.NewBuffer(body))
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(t, http.StatusOK, rr.Code)
|
||||
req.Header.Set("Date", time.Now().Format(time.RFC3339))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
client, err := signClient(privEd25519Key)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
|
||||
rr, err := client.Do(req)
|
||||
assert.NoError(t, err)
|
||||
defer rr.Body.Close()
|
||||
|
||||
assert.Equal(t, http.StatusOK, rr.StatusCode)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user