diff --git a/pkg/apis/provisioning/v0alpha1/types.go b/pkg/apis/provisioning/v0alpha1/types.go index 7583af30dc1..5b5936d568a 100644 --- a/pkg/apis/provisioning/v0alpha1/types.go +++ b/pkg/apis/provisioning/v0alpha1/types.go @@ -207,6 +207,7 @@ type WebhookStatus struct { ID int64 `json:"id,omitempty"` URL string `json:"url,omitempty"` Secret string `json:"secret,omitempty"` + EncryptedSecret []byte `json:"encryptedSecret,omitempty"` SubscribedEvents []string `json:"subscribedEvents,omitempty"` } diff --git a/pkg/apis/provisioning/v0alpha1/zz_generated.deepcopy.go b/pkg/apis/provisioning/v0alpha1/zz_generated.deepcopy.go index a31190ecb79..fefbc6ea297 100644 --- a/pkg/apis/provisioning/v0alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/provisioning/v0alpha1/zz_generated.deepcopy.go @@ -857,6 +857,11 @@ func (in *WebhookResponse) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WebhookStatus) DeepCopyInto(out *WebhookStatus) { *out = *in + if in.EncryptedSecret != nil { + in, out := &in.EncryptedSecret, &out.EncryptedSecret + *out = make([]byte, len(*in)) + copy(*out, *in) + } if in.SubscribedEvents != nil { in, out := &in.SubscribedEvents, &out.SubscribedEvents *out = make([]string, len(*in)) diff --git a/pkg/apis/provisioning/v0alpha1/zz_generated.openapi.go b/pkg/apis/provisioning/v0alpha1/zz_generated.openapi.go index fd73980698f..a53c4380bd0 100644 --- a/pkg/apis/provisioning/v0alpha1/zz_generated.openapi.go +++ b/pkg/apis/provisioning/v0alpha1/zz_generated.openapi.go @@ -1909,6 +1909,12 @@ func schema_pkg_apis_provisioning_v0alpha1_WebhookStatus(ref common.ReferenceCal Format: "", }, }, + "encryptedSecret": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "byte", + }, + }, "subscribedEvents": { SchemaProps: spec.SchemaProps{ Type: []string{"array"}, diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/webhookstatus.go b/pkg/generated/applyconfiguration/provisioning/v0alpha1/webhookstatus.go index e42f7b9c134..d550e4fc753 100644 --- a/pkg/generated/applyconfiguration/provisioning/v0alpha1/webhookstatus.go +++ b/pkg/generated/applyconfiguration/provisioning/v0alpha1/webhookstatus.go @@ -10,6 +10,7 @@ type WebhookStatusApplyConfiguration struct { ID *int64 `json:"id,omitempty"` URL *string `json:"url,omitempty"` Secret *string `json:"secret,omitempty"` + EncryptedSecret []byte `json:"encryptedSecret,omitempty"` SubscribedEvents []string `json:"subscribedEvents,omitempty"` } @@ -43,6 +44,16 @@ func (b *WebhookStatusApplyConfiguration) WithSecret(value string) *WebhookStatu return b } +// WithEncryptedSecret adds the given value to the EncryptedSecret field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the EncryptedSecret field. +func (b *WebhookStatusApplyConfiguration) WithEncryptedSecret(values ...byte) *WebhookStatusApplyConfiguration { + for i := range values { + b.EncryptedSecret = append(b.EncryptedSecret, values[i]) + } + return b +} + // WithSubscribedEvents adds the given value to the SubscribedEvents field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the SubscribedEvents field. diff --git a/pkg/registry/apis/provisioning/register.go b/pkg/registry/apis/provisioning/register.go index 07b8cafbe79..a09100cf4c1 100644 --- a/pkg/registry/apis/provisioning/register.go +++ b/pkg/registry/apis/provisioning/register.go @@ -804,5 +804,14 @@ func (b *APIBuilder) encryptSecrets(ctx context.Context, repo *provisioning.Repo } repo.Spec.GitHub.Token = "" } + + if repo.Status.Webhook != nil && + repo.Status.Webhook.Secret != "" { + repo.Status.Webhook.EncryptedSecret, err = b.secrets.Encrypt(ctx, []byte(repo.Status.Webhook.Secret)) + if err != nil { + return err + } + repo.Status.Webhook.Secret = "" + } return nil } diff --git a/pkg/registry/apis/provisioning/repository/github.go b/pkg/registry/apis/provisioning/repository/github.go index 38392403c0d..3b777aa46ed 100644 --- a/pkg/registry/apis/provisioning/repository/github.go +++ b/pkg/registry/apis/provisioning/repository/github.go @@ -525,7 +525,12 @@ func (r *githubRepository) Webhook(ctx context.Context, req *http.Request) (*pro return nil, fmt.Errorf("unexpected webhook request") } - payload, err := github.ValidatePayload(req, []byte(r.config.Status.Webhook.Secret)) + secret, err := r.secrets.Decrypt(ctx, r.config.Status.Webhook.EncryptedSecret) + if err != nil { + return nil, fmt.Errorf("failed to decrypt secret: %w", err) + } + + payload, err := github.ValidatePayload(req, secret) if err != nil { return nil, apierrors.NewUnauthorized("invalid signature") } diff --git a/pkg/tests/apis/openapi_snapshots/provisioning.grafana.app-v0alpha1.json b/pkg/tests/apis/openapi_snapshots/provisioning.grafana.app-v0alpha1.json index e42bcfce665..a3f821512cc 100644 --- a/pkg/tests/apis/openapi_snapshots/provisioning.grafana.app-v0alpha1.json +++ b/pkg/tests/apis/openapi_snapshots/provisioning.grafana.app-v0alpha1.json @@ -4007,6 +4007,10 @@ "com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.WebhookStatus": { "type": "object", "properties": { + "encryptedSecret": { + "type": "string", + "format": "byte" + }, "id": { "type": "integer", "format": "int64" diff --git a/public/app/features/provisioning/api/endpoints.gen.ts b/public/app/features/provisioning/api/endpoints.gen.ts index db71cc177eb..af3482a40ed 100644 --- a/public/app/features/provisioning/api/endpoints.gen.ts +++ b/public/app/features/provisioning/api/endpoints.gen.ts @@ -829,6 +829,7 @@ export type SyncStatus = { state: 'error' | 'pending' | 'success' | 'working'; }; export type WebhookStatus = { + encryptedSecret?: string; id?: number; secret?: string; subscribedEvents?: string[];