Skip to content

Commit

Permalink
feat: Add Webhook Hostname (#668) (#670)
Browse files Browse the repository at this point in the history
Co-authored-by: Anand Capur <anand.capur@corelight.com>
Co-authored-by: Louis Garman <louisgarman@gmail.com>
  • Loading branch information
3 people authored Dec 16, 2023
1 parent b518d44 commit f2dc7e9
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 5 deletions.
1 change: 1 addition & 0 deletions cmd/otfd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func parseFlags(ctx context.Context, args []string, out io.Writer) error {
cmd.Flags().StringSliceVar(&cfg.SiteAdmins, "site-admins", nil, "Promote a list of users to site admin.")
cmd.Flags().BytesHexVar(&cfg.Secret, "secret", nil, "Hex-encoded 16 byte secret for cryptographic work. Required.")
cmd.Flags().Int64Var(&cfg.MaxConfigSize, "max-config-size", cfg.MaxConfigSize, "Maximum permitted configuration size in bytes.")
cmd.Flags().StringVar(&cfg.WebhookHost, "webhook-hostname", "", "External hostname for otf webhooks")

cmd.Flags().IntVar(&cfg.CacheConfig.Size, "cache-size", 0, "Maximum cache size in MB. 0 means unlimited size.")
cmd.Flags().DurationVar(&cfg.CacheConfig.TTL, "cache-expiry", internal.DefaultCacheTTL, "Cache entry TTL.")
Expand Down
7 changes: 7 additions & 0 deletions docs/config/flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ Github pull request.

It is highly advisable to set this flag in a production deployment.

## `--webhook-hostname`

* System: `otfd`
* Default: `localhost:8080` or `--address` if specified.

Sets the hostname that VCS providers can use to access the OTF webhooks.

## `--log-format`

* System: `otfd`, `otf-agent`
Expand Down
1 change: 1 addition & 0 deletions internal/daemon/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type Config struct {
Secret []byte // 16-byte secret for signing URLs and encrypting payloads
SiteToken string
Host string
WebhookHost string
Address string
Database string
MaxConfigSize int64
Expand Down
3 changes: 3 additions & 0 deletions internal/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ func New(ctx context.Context, logger logr.Logger, cfg Config) (*Daemon, error) {
}

hostnameService := internal.NewHostnameService(cfg.Host)
hostnameService.SetWebhookHostname(cfg.WebhookHost)

renderer, err := html.NewRenderer(cfg.DevMode)
if err != nil {
Expand Down Expand Up @@ -454,7 +455,9 @@ func (d *Daemon) Start(ctx context.Context, started chan struct{}) error {
listenAddress := ln.Addr().(*net.TCPAddr)
d.System.SetHostname(internal.NormalizeAddress(listenAddress))
}

d.V(0).Info("set system hostname", "hostname", d.System.Hostname())
d.V(0).Info("set webhook hostname", "webhook_hostname", d.System.WebhookHostname())

subsystems := []*Subsystem{
{
Expand Down
4 changes: 3 additions & 1 deletion internal/github/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ func (h *webHandlers) addHandlers(r *mux.Router) {
}

func (h *webHandlers) new(w http.ResponseWriter, r *http.Request) {
// Github manifest documented here:
// https://docs.github.com/en/apps/sharing-github-apps/registering-a-github-app-from-a-manifest#implementing-the-github-app-manifest-flow
type (
hookAttrs struct {
URL string `json:"url"`
Expand All @@ -74,7 +76,7 @@ func (h *webHandlers) new(w http.ResponseWriter, r *http.Request) {
Name: "otf-" + internal.GenerateRandomString(4),
URL: h.URL(""),
SetupURL: h.URL(paths.GithubApps()),
HookAttrs: hookAttrs{URL: h.URL(AppEventsPath)},
HookAttrs: hookAttrs{URL: h.WebhookURL(AppEventsPath)},
Redirect: h.URL(paths.ExchangeCodeGithubApp()),
Description: "Trigger terraform runs in OTF from GitHub",
Events: []string{"push", "pull_request"},
Expand Down
25 changes: 22 additions & 3 deletions internal/hostname.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,25 @@ import (
)

type HostnameService struct {
hostname string
hostname string
webhookHostname string
}

func NewHostnameService(hostname string) *HostnameService {
return &HostnameService{hostname}
return &HostnameService{hostname, hostname}
}

func (s *HostnameService) Hostname() string { return s.hostname }
func (s *HostnameService) Hostname() string { return s.hostname }
func (s *HostnameService) WebhookHostname() string {
if s.webhookHostname == "" {
return s.hostname
}
return s.webhookHostname
}
func (s *HostnameService) SetHostname(hostname string) { s.hostname = hostname }
func (s *HostnameService) SetWebhookHostname(webhookHostname string) {
s.webhookHostname = webhookHostname
}

func (s *HostnameService) URL(path string) string {
u := url.URL{
Expand All @@ -27,6 +37,15 @@ func (s *HostnameService) URL(path string) string {
return u.String()
}

func (s *HostnameService) WebhookURL(path string) string {
u := url.URL{
Scheme: "https",
Host: s.WebhookHostname(),
Path: path,
}
return u.String()
}

// NormalizeAddress takes a host:port and converts it into a host:port
// appropriate for setting as the addressable hostname of otfd, e.g. converting
// 0.0.0.0 to 127.0.0.1.
Expand Down
53 changes: 53 additions & 0 deletions internal/hostname_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,59 @@ import (
"github.com/stretchr/testify/assert"
)

func TestHostnameService(t *testing.T) {
tests := []struct {
name string
svc *HostnameService
wantHostname string
wantWebhookHostname string
}{
{
"default",
NewHostnameService("localhost:8080"),
"localhost:8080",
"localhost:8080",
},
{
"set hostname",
func() *HostnameService {
svc := NewHostnameService("")
svc.SetHostname("otf.local")
return svc
}(),
"otf.local",
"otf.local",
},
{
"set webhook hostname",
func() *HostnameService {
svc := NewHostnameService("localhost:8080")
svc.SetWebhookHostname("otf.local")
return svc
}(),
"localhost:8080",
"otf.local",
},
{
"set both hostnames",
func() *HostnameService {
svc := NewHostnameService("localhost:8080")
svc.SetHostname("otf.local")
svc.SetWebhookHostname("webhooks.otf.local")
return svc
}(),
"otf.local",
"webhooks.otf.local",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.wantHostname, tt.svc.Hostname())
assert.Equal(t, tt.wantWebhookHostname, tt.svc.WebhookHostname())
})
}
}

func TestNormalizeAddress(t *testing.T) {
tests := []struct {
name string
Expand Down
2 changes: 1 addition & 1 deletion internal/repohooks/repohook.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func newRepohook(opts newRepohookOptions) (*hook, error) {
}
hook.secret = secret
}
hook.endpoint = opts.URL(path.Join(handlerPrefix, hook.id.String()))
hook.endpoint = opts.WebhookURL(path.Join(handlerPrefix, hook.id.String()))
return &hook, nil
}

Expand Down

0 comments on commit f2dc7e9

Please sign in to comment.