Migrate to maintained httpsign library (#3839)

Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
qwerty287
2024-07-23 20:41:37 +02:00
committed by GitHub
parent 047eb19d42
commit b330c19bf4
10 changed files with 99 additions and 68 deletions

View File

@@ -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
}

View File

@@ -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)
}