2023-04-28 13:47:22 +00:00
|
|
|
package webhook
|
|
|
|
|
|
|
|
import (
|
2023-04-28 23:15:39 +00:00
|
|
|
"context"
|
|
|
|
"fmt"
|
2023-04-28 13:47:22 +00:00
|
|
|
"net/http"
|
|
|
|
|
2023-04-28 15:15:05 +00:00
|
|
|
"go.step.sm/linkedca"
|
|
|
|
|
|
|
|
"github.com/smallstep/certificates/authority/provisioner"
|
|
|
|
"github.com/smallstep/certificates/webhook"
|
2023-04-28 13:47:22 +00:00
|
|
|
)
|
|
|
|
|
2023-04-28 23:15:39 +00:00
|
|
|
// Controller controls webhook execution
|
2023-04-28 13:47:22 +00:00
|
|
|
type Controller struct {
|
2023-04-28 15:15:05 +00:00
|
|
|
client *http.Client
|
|
|
|
webhooks []*provisioner.Webhook
|
2023-04-28 13:47:22 +00:00
|
|
|
}
|
|
|
|
|
2023-04-28 23:15:39 +00:00
|
|
|
// New returns a new SCEP webhook Controller
|
2023-04-28 15:15:05 +00:00
|
|
|
func New(webhooks []*provisioner.Webhook) (*Controller, error) {
|
|
|
|
return &Controller{
|
|
|
|
client: http.DefaultClient,
|
|
|
|
webhooks: webhooks,
|
|
|
|
}, nil
|
2023-04-28 13:47:22 +00:00
|
|
|
}
|
|
|
|
|
2023-04-28 23:15:39 +00:00
|
|
|
// Validate executes zero or more configured webhooks to
|
|
|
|
// validate the SCEP challenge. If at least one of indicates
|
|
|
|
// the challenge value is accepted, validation succeeds. Other
|
|
|
|
// webhooks will not be executed. If none of the webhooks
|
|
|
|
// indicates the challenge is accepted, an error is
|
|
|
|
// returned.
|
|
|
|
func (c *Controller) Validate(ctx context.Context, challenge string) error {
|
2023-04-28 15:15:05 +00:00
|
|
|
for _, wh := range c.webhooks {
|
|
|
|
if wh.Kind != linkedca.Webhook_SCEPCHALLENGE.String() {
|
|
|
|
continue
|
2023-04-28 13:47:22 +00:00
|
|
|
}
|
2023-04-28 15:15:05 +00:00
|
|
|
if !c.isCertTypeOK(wh) {
|
|
|
|
continue
|
2023-04-28 13:47:22 +00:00
|
|
|
}
|
2023-04-28 15:15:05 +00:00
|
|
|
req := &webhook.RequestBody{
|
|
|
|
SCEPChallenge: challenge,
|
2023-04-28 13:47:22 +00:00
|
|
|
}
|
2023-04-28 23:15:39 +00:00
|
|
|
resp, err := wh.DoWithContext(ctx, c.client, req, nil) // TODO(hs): support templated URL? Requires some refactoring
|
2023-04-28 15:15:05 +00:00
|
|
|
if err != nil {
|
2023-04-28 23:15:39 +00:00
|
|
|
return fmt.Errorf("failed executing webhook request: %w", err)
|
2023-04-28 13:47:22 +00:00
|
|
|
}
|
2023-04-28 23:15:39 +00:00
|
|
|
if resp.Allow {
|
|
|
|
return nil // return early when response is positive
|
2023-04-28 13:47:22 +00:00
|
|
|
}
|
|
|
|
}
|
2023-04-28 23:15:39 +00:00
|
|
|
|
|
|
|
return provisioner.ErrWebhookDenied
|
2023-04-28 13:47:22 +00:00
|
|
|
}
|
|
|
|
|
2023-04-28 23:15:39 +00:00
|
|
|
// isCertTypeOK returns whether or not the webhook is for X.509
|
|
|
|
// certificates.
|
2023-04-28 15:15:05 +00:00
|
|
|
func (c *Controller) isCertTypeOK(wh *provisioner.Webhook) bool {
|
|
|
|
return linkedca.Webhook_X509.String() == wh.CertType
|
2023-04-28 13:47:22 +00:00
|
|
|
}
|