mirror of
https://github.com/Dvorinka/Containr.git
synced 2026-10-28 15:51:26 +00:00
New public POST /api/git/webhooks/🆔 verifies provider signatures (GitHub/Gitea HMAC-SHA256, GitLab token), filters branch pushes, matches connected repo to services by clone_url/full_name + branch, inserts deployment rows and enqueues runDeploymentAndSync (trigger=webhook). Service-create dialog now connects the selected provider repo and registers a push webhook (409-tolerant via connected-repo lookup). api-client: connectGitRepository, listConnectedGitRepositories, createGitWebhook typed from generated schemas. GitWebhook spec schema corrected (events array + branch field). Authored By: TDvorak <[email protected]>
85 lines
1.9 KiB
Go
85 lines
1.9 KiB
Go
package api
|
|
|
|
import (
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"net/http/httptest"
|
|
"testing"
|
|
)
|
|
|
|
func signBody(t *testing.T, secret string, body []byte) string {
|
|
t.Helper()
|
|
mac := hmac.New(sha256.New, []byte(secret))
|
|
mac.Write(body)
|
|
return hex.EncodeToString(mac.Sum(nil))
|
|
}
|
|
|
|
func TestVerifyGitWebhookSignature(t *testing.T) {
|
|
body := []byte(`{"ref":"refs/heads/main"}`)
|
|
secret := "test-secret"
|
|
valid := signBody(t, secret, body)
|
|
|
|
cases := []struct {
|
|
name string
|
|
provider string
|
|
headers map[string]string
|
|
want bool
|
|
}{
|
|
{
|
|
name: "github sha256 prefix",
|
|
provider: "github",
|
|
headers: map[string]string{"X-Hub-Signature-256": "sha256=" + valid},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "gitea signature",
|
|
provider: "gitea",
|
|
headers: map[string]string{"X-Gitea-Signature": valid},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "gitlab token",
|
|
provider: "gitlab",
|
|
headers: map[string]string{"X-Gitlab-Token": secret},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "gitlab rejects wrong token",
|
|
provider: "gitlab",
|
|
headers: map[string]string{"X-Gitlab-Token": "wrong"},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "github rejects wrong signature",
|
|
provider: "github",
|
|
headers: map[string]string{"X-Hub-Signature-256": "sha256=" + signBody(t, "other", body)},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "missing signature",
|
|
provider: "github",
|
|
headers: map[string]string{},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "malformed hex",
|
|
provider: "github",
|
|
headers: map[string]string{"X-Hub-Signature-256": "sha256=zzz"},
|
|
want: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
req := httptest.NewRequest("POST", "/api/git/webhooks/x", nil)
|
|
for k, v := range tc.headers {
|
|
req.Header.Set(k, v)
|
|
}
|
|
if got := verifyGitWebhookSignature(tc.provider, secret, req, body); got != tc.want {
|
|
t.Fatalf("verifyGitWebhookSignature = %v, want %v", got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|