check / check (push) Waiting to run
The webhook page's targets section lists only its targets until Add is clicked. Add shows a choice of target type with Next; Next shows only that type's fields, with Save and Cancel. The `database` and `log` types have no URL field, and the `slack` form gains max retries. A refused target now shows the webhook page again with the form open on its type, the values entered and the reason, instead of a bare text page. Target validation returns that message rather than writing the response; newTarget validates a whole new target for reuse by the new-webhook page. The edit page still answers a refusal in plain text. Model: opus-5-5
122 lines
3.1 KiB
Go
122 lines
3.1 KiB
Go
package handlers_test
|
|
|
|
import (
|
|
"html"
|
|
"net/http"
|
|
"net/url"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"sneak.berlin/go/webhooker/internal/database"
|
|
)
|
|
|
|
// privateRefusalHint is the sentence that tells an operator a private
|
|
// destination is refused on purpose, and how to allow one.
|
|
const privateRefusalHint = "Private and reserved addresses are " +
|
|
"refused by default; the server's ALLOWED_EGRESS_CIDRS setting " +
|
|
"allows named networks (see \"Allowing egress to your own " +
|
|
"network\" in the README)."
|
|
|
|
// TestTargetRefusal_PrivateDestinationSaysHowToAllowIt covers both
|
|
// target types that take a URL, on add and on edit.
|
|
func TestTargetRefusal_PrivateDestinationSaysHowToAllowIt(
|
|
t *testing.T,
|
|
) {
|
|
t.Parallel()
|
|
|
|
env := setupSourceTest(t)
|
|
|
|
targetTypes := []database.TargetType{
|
|
database.TargetTypeHTTP,
|
|
database.TargetTypeSlack,
|
|
}
|
|
|
|
for _, targetType := range targetTypes {
|
|
t.Run(string(targetType), func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
webhook := seedWebhookWithRetention(t, env.db, 30)
|
|
targetsPath := "/hook/" + webhook.ID + "/targets"
|
|
|
|
form := url.Values{}
|
|
form.Set("name", "private")
|
|
form.Set("type", string(targetType))
|
|
form.Set("url", editBlockedURL)
|
|
|
|
// A refused add shows the webhook page again, where
|
|
// the hint is HTML-escaped; a refused edit answers in
|
|
// plain text.
|
|
added := serveTarget(
|
|
env, http.MethodPost, targetsPath, form,
|
|
)
|
|
assert.Equal(t, http.StatusBadRequest, added.Code)
|
|
assert.Contains(
|
|
t, added.Body.String(),
|
|
html.EscapeString(privateRefusalHint),
|
|
)
|
|
|
|
form.Set("url", editOriginalURL)
|
|
|
|
created := serveTarget(
|
|
env, http.MethodPost, targetsPath, form,
|
|
)
|
|
require.Equal(
|
|
t, http.StatusSeeOther, created.Code,
|
|
created.Body.String(),
|
|
)
|
|
|
|
targets := targetsForWebhook(t, env.db, webhook.ID)
|
|
require.Len(t, targets, 1)
|
|
|
|
form.Set("url", editBlockedURL)
|
|
|
|
edited := submitTargetEdit(
|
|
env, webhook.ID, targets[0].ID, form,
|
|
)
|
|
assert.Equal(t, http.StatusBadRequest, edited.Code)
|
|
assert.Contains(
|
|
t, edited.Body.String(), privateRefusalHint,
|
|
)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestTargetRefusal_MetadataDestinationDoesNotSayHowToAllowIt: no
|
|
// setting opens a link-local address, and Azure's WireServer hands out
|
|
// VM credentials, so neither refusal points at the setting.
|
|
func TestTargetRefusal_MetadataDestinationDoesNotSayHowToAllowIt(
|
|
t *testing.T,
|
|
) {
|
|
t.Parallel()
|
|
|
|
env := setupSourceTest(t)
|
|
|
|
metadataURLs := map[string]string{
|
|
"link-local": "http://169.254.169.254/latest/meta-data/",
|
|
"wireserver": "http://168.63.129.16/?comp=versions",
|
|
}
|
|
|
|
for name, metadataURL := range metadataURLs {
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
webhook := seedWebhookWithRetention(t, env.db, 30)
|
|
|
|
form := url.Values{}
|
|
form.Set("name", "metadata")
|
|
form.Set("type", string(database.TargetTypeHTTP))
|
|
form.Set("url", metadataURL)
|
|
|
|
w := serveTarget(
|
|
env, http.MethodPost,
|
|
"/hook/"+webhook.ID+"/targets", form,
|
|
)
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
assert.NotContains(
|
|
t, w.Body.String(), privateRefusalHint,
|
|
)
|
|
})
|
|
}
|
|
}
|