fix(http): fix notfication endpoint secret store

pull/14848/head
Kelvin Wang 2019-08-28 16:02:17 -04:00
parent 2fa1ca3f49
commit 7a677e9532
10 changed files with 208 additions and 443 deletions

View File

@ -14,7 +14,6 @@ type NotificationEndpointService struct {
s influxdb.NotificationEndpointService
influxdb.UserResourceMappingService
influxdb.OrganizationService
influxdb.SecretService
}
// NewNotificationEndpointService constructs an instance of an authorizing notification endpoint serivce.
@ -22,13 +21,11 @@ func NewNotificationEndpointService(
s influxdb.NotificationEndpointService,
urm influxdb.UserResourceMappingService,
org influxdb.OrganizationService,
srt influxdb.SecretService,
) *NotificationEndpointService {
return &NotificationEndpointService{
s: s,
UserResourceMappingService: urm,
OrganizationService: org,
SecretService: srt,
}
}
@ -125,14 +122,14 @@ func (s *NotificationEndpointService) PatchNotificationEndpoint(ctx context.Cont
}
// DeleteNotificationEndpoint checks to see if the authorizer on context has write access to the notification endpoint provided.
func (s *NotificationEndpointService) DeleteNotificationEndpoint(ctx context.Context, id influxdb.ID) error {
func (s *NotificationEndpointService) DeleteNotificationEndpoint(ctx context.Context, id influxdb.ID) ([]influxdb.SecretField, influxdb.ID, error) {
edp, err := s.FindNotificationEndpointByID(ctx, id)
if err != nil {
return err
return nil, 0, err
}
if err := authorizeWriteOrg(ctx, edp.GetOrgID()); err != nil {
return err
return nil, 0, err
}
return s.s.DeleteNotificationEndpoint(ctx, id)

View File

@ -109,7 +109,7 @@ func TestNotificationEndpointService_FindNotificationEndpointByID(t *testing.T)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := authorizer.NewNotificationEndpointService(tt.fields.NotificationEndpointService, mock.NewUserResourceMappingService(), mock.NewOrganizationService(), mock.NewSecretService())
s := authorizer.NewNotificationEndpointService(tt.fields.NotificationEndpointService, mock.NewUserResourceMappingService(), mock.NewOrganizationService())
ctx := context.Background()
ctx = influxdbcontext.SetAuthorizer(ctx, &Authorizer{[]influxdb.Permission{tt.args.permission}})
@ -257,7 +257,7 @@ func TestNotificationEndpointService_FindNotificationEndpoints(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
s := authorizer.NewNotificationEndpointService(tt.fields.NotificationEndpointService,
mock.NewUserResourceMappingService(),
mock.NewOrganizationService(), mock.NewSecretService())
mock.NewOrganizationService())
ctx := context.Background()
ctx = influxdbcontext.SetAuthorizer(ctx, &Authorizer{[]influxdb.Permission{tt.args.permission}})
@ -382,7 +382,7 @@ func TestNotificationEndpointService_UpdateNotificationEndpoint(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
s := authorizer.NewNotificationEndpointService(tt.fields.NotificationEndpointService,
mock.NewUserResourceMappingService(),
mock.NewOrganizationService(), mock.NewSecretService())
mock.NewOrganizationService())
ctx := context.Background()
ctx = influxdbcontext.SetAuthorizer(ctx, &Authorizer{tt.args.permissions})
@ -502,7 +502,7 @@ func TestNotificationEndpointService_PatchNotificationEndpoint(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := authorizer.NewNotificationEndpointService(tt.fields.NotificationEndpointService, mock.NewUserResourceMappingService(),
mock.NewOrganizationService(), mock.NewSecretService())
mock.NewOrganizationService())
ctx := context.Background()
ctx = influxdbcontext.SetAuthorizer(ctx, &Authorizer{tt.args.permissions})
@ -543,8 +543,8 @@ func TestNotificationEndpointService_DeleteNotificationEndpoint(t *testing.T) {
},
}, nil
},
DeleteNotificationEndpointF: func(ctx context.Context, id influxdb.ID) error {
return nil
DeleteNotificationEndpointF: func(ctx context.Context, id influxdb.ID) ([]influxdb.SecretField, influxdb.ID, error) {
return nil, 0, nil
},
},
},
@ -583,8 +583,8 @@ func TestNotificationEndpointService_DeleteNotificationEndpoint(t *testing.T) {
},
}, nil
},
DeleteNotificationEndpointF: func(ctx context.Context, id influxdb.ID) error {
return nil
DeleteNotificationEndpointF: func(ctx context.Context, id influxdb.ID) ([]influxdb.SecretField, influxdb.ID, error) {
return nil, 0, nil
},
},
},
@ -613,13 +613,12 @@ func TestNotificationEndpointService_DeleteNotificationEndpoint(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
s := authorizer.NewNotificationEndpointService(tt.fields.NotificationEndpointService, mock.NewUserResourceMappingService(),
mock.NewOrganizationService(),
mock.NewSecretService(),
)
ctx := context.Background()
ctx = influxdbcontext.SetAuthorizer(ctx, &Authorizer{tt.args.permissions})
err := s.DeleteNotificationEndpoint(ctx, tt.args.id)
_, _, err := s.DeleteNotificationEndpoint(ctx, tt.args.id)
influxdbtesting.ErrorsEqual(t, err, tt.wants.err)
})
}
@ -722,8 +721,7 @@ func TestNotificationEndpointService_CreateNotificationEndpoint(t *testing.T) {
s := authorizer.NewNotificationEndpointService(tt.fields.NotificationEndpointService,
mock.NewUserResourceMappingService(),
mock.NewOrganizationService(),
mock.NewSecretService())
)
ctx := context.Background()
ctx = influxdbcontext.SetAuthorizer(ctx, &Authorizer{[]influxdb.Permission{tt.args.permission}})

View File

@ -171,7 +171,7 @@ func NewAPIHandler(b *APIBackend) *APIHandler {
notificationEndpointBackend := NewNotificationEndpointBackend(b)
notificationEndpointBackend.NotificationEndpointService = authorizer.NewNotificationEndpointService(b.NotificationEndpointService,
b.UserResourceMappingService, b.OrganizationService, b.SecretService)
b.UserResourceMappingService, b.OrganizationService)
h.NotificationEndpointHandler = NewNotificationEndpointHandler(notificationEndpointBackend)
checkBackend := NewCheckBackend(b)

View File

@ -25,6 +25,7 @@ type NotificationEndpointBackend struct {
LabelService influxdb.LabelService
UserService influxdb.UserService
OrganizationService influxdb.OrganizationService
SecretService influxdb.SecretService
}
// NewNotificationEndpointBackend returns a new instance of NotificationEndpointBackend.
@ -38,6 +39,7 @@ func NewNotificationEndpointBackend(b *APIBackend) *NotificationEndpointBackend
LabelService: b.LabelService,
UserService: b.UserService,
OrganizationService: b.OrganizationService,
SecretService: b.SecretService,
}
}
@ -52,6 +54,7 @@ type NotificationEndpointHandler struct {
LabelService influxdb.LabelService
UserService influxdb.UserService
OrganizationService influxdb.OrganizationService
SecretService influxdb.SecretService
}
const (
@ -77,6 +80,7 @@ func NewNotificationEndpointHandler(b *NotificationEndpointBackend) *Notificatio
LabelService: b.LabelService,
UserService: b.UserService,
OrganizationService: b.OrganizationService,
SecretService: b.SecretService,
}
h.HandlerFunc("POST", notificationEndpointsPath, h.handlePostNotificationEndpoint)
h.HandlerFunc("GET", notificationEndpointsPath, h.handleGetNotificationEndpoints)
@ -395,6 +399,19 @@ func (h *NotificationEndpointHandler) handlePostNotificationEndpoint(w http.Resp
h.HandleHTTPError(ctx, err, w)
return
}
for _, fld := range edp.SecretFields() {
if fld.Value != nil {
if err := h.SecretService.PutSecret(ctx, edp.GetOrgID(),
fld.Key, *fld.Value); err != nil {
h.HandleHTTPError(ctx, &influxdb.Error{
Op: "http/handlePostNotificationEndpoint",
Err: err,
}, w)
return
}
}
}
h.Logger.Debug("notificationEndpoint created", zap.String("notificationEndpoint", fmt.Sprint(edp)))
if err := encodeResponse(ctx, w, http.StatusCreated, newNotificationEndpointResponse(edp, []*influxdb.Label{})); err != nil {
@ -425,6 +442,19 @@ func (h *NotificationEndpointHandler) handlePutNotificationEndpoint(w http.Respo
return
}
for _, fld := range edp.SecretFields() {
if fld.Value != nil {
if err := h.SecretService.PutSecret(ctx, edp.GetOrgID(),
fld.Key, *fld.Value); err != nil {
h.HandleHTTPError(ctx, &influxdb.Error{
Op: "http/handlePutNotificationEndpoint",
Err: err,
}, w)
return
}
}
}
labels, err := h.LabelService.FindResourceLabels(ctx, influxdb.LabelMappingFilter{ResourceID: edp.GetID()})
if err != nil {
h.HandleHTTPError(ctx, err, w)
@ -477,10 +507,29 @@ func (h *NotificationEndpointHandler) handleDeleteNotificationEndpoint(w http.Re
return
}
if err = h.NotificationEndpointService.DeleteNotificationEndpoint(ctx, i); err != nil {
flds, orgID, err := h.NotificationEndpointService.DeleteNotificationEndpoint(ctx, i)
if err != nil {
h.HandleHTTPError(ctx, err, w)
return
}
keys := make([]string, len(flds))
for k, fld := range flds {
if fld.Key == "" {
h.HandleHTTPError(ctx, &influxdb.Error{
Op: "http/handleDeleteNotificationEndpoint",
Msg: "Bad Secret Key in endpoint " + i.String(),
}, w)
return
}
keys[k] = fld.Key
}
if err := h.SecretService.DeleteSecret(ctx, orgID, keys...); err != nil {
h.HandleHTTPError(ctx, &influxdb.Error{
Op: "http/handleDeleteNotificationEndpoint",
Err: err,
}, w)
return
}
h.Logger.Debug("notificationEndpoint deleted", zap.String("notificationEndpointID", fmt.Sprint(i)))
w.WriteHeader(http.StatusNoContent)

View File

@ -10,6 +10,8 @@ import (
"net/http/httptest"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/influxdata/influxdb"
pcontext "github.com/influxdata/influxdb/context"
"github.com/influxdata/influxdb/mock"
@ -29,6 +31,7 @@ func NewMockNotificationEndpointBackend() *NotificationEndpointBackend {
LabelService: mock.NewLabelService(),
UserService: mock.NewUserService(),
OrganizationService: mock.NewOrganizationService(),
SecretService: mock.NewSecretService(),
}
}
@ -388,18 +391,23 @@ func TestService_handleGetNotificationEndpoint(t *testing.T) {
func TestService_handlePostNotificationEndpoint(t *testing.T) {
type fields struct {
Secrets map[string]string
SecretService influxdb.SecretService
NotificationEndpointService influxdb.NotificationEndpointService
OrganizationService influxdb.OrganizationService
}
type args struct {
endpoint influxdb.NotificationEndpoint
endpoint interface{}
}
type wants struct {
statusCode int
contentType string
body string
secrets map[string]string
}
var secrets map[string]string
tests := []struct {
name string
fields fields
@ -409,9 +417,17 @@ func TestService_handlePostNotificationEndpoint(t *testing.T) {
{
name: "create a new notification endpoint",
fields: fields{
Secrets: map[string]string{},
SecretService: &mock.SecretService{
PutSecretFn: func(ctx context.Context, orgID influxdb.ID, k string, v string) error {
secrets[orgID.String()+"-"+k] = v
return nil
},
},
NotificationEndpointService: &mock.NotificationEndpointService{
CreateNotificationEndpointF: func(ctx context.Context, edp influxdb.NotificationEndpoint, userID influxdb.ID) error {
edp.SetID(influxTesting.MustIDBase16("020f755c3c082000"))
edp.BackfillSecretKeys()
return nil
},
},
@ -422,22 +438,25 @@ func TestService_handlePostNotificationEndpoint(t *testing.T) {
},
},
args: args{
endpoint: &endpoint.HTTP{
Base: endpoint.Base{
Name: "hello",
OrgID: influxTesting.MustIDBase16("6f626f7274697320"),
Description: "desc1",
Status: influxdb.Active,
},
URL: "example.com",
Username: influxdb.SecretField{Key: "http-user-key"},
Password: influxdb.SecretField{Key: "http-password-key"},
AuthMethod: "basic",
Method: "POST",
ContentTemplate: "template",
endpoint: map[string]interface{}{
"name": "hello",
"type": "http",
"orgID": "6f626f7274697320",
"description": "desc1",
"status": "active",
"url": "example.com",
"username": "user1",
"password": "password1",
"authMethod": "basic",
"method": "POST",
"contentTemplate": "template",
},
},
wants: wants{
secrets: map[string]string{
"6f626f7274697320-020f755c3c082000-password": "password1",
"6f626f7274697320-020f755c3c082000-username": "user1",
},
statusCode: http.StatusCreated,
contentType: "application/json; charset=utf-8",
body: `
@ -450,8 +469,8 @@ func TestService_handlePostNotificationEndpoint(t *testing.T) {
},
"url": "example.com",
"status": "active",
"username": "secret: http-user-key",
"password": "secret: http-password-key",
"username": "secret: 020f755c3c082000-username",
"password": "secret: 020f755c3c082000-password",
"token":"",
"authMethod": "basic",
"contentTemplate": "template",
@ -472,9 +491,11 @@ func TestService_handlePostNotificationEndpoint(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
secrets = tt.fields.Secrets
notificationEndpointBackend := NewMockNotificationEndpointBackend()
notificationEndpointBackend.NotificationEndpointService = tt.fields.NotificationEndpointService
notificationEndpointBackend.OrganizationService = tt.fields.OrganizationService
notificationEndpointBackend.SecretService = tt.fields.SecretService
h := NewNotificationEndpointHandler(notificationEndpointBackend)
b, err := json.Marshal(tt.args.endpoint)
@ -504,18 +525,25 @@ func TestService_handlePostNotificationEndpoint(t *testing.T) {
t.Errorf("%q. handlePostNotificationEndpoint() = ***%s***", tt.name, diff)
}
}
if diff := cmp.Diff(secrets, tt.wants.secrets); diff != "" {
t.Errorf("%q. handlePostNotificationEndpoint secrets are different ***%s***", tt.name, diff)
}
})
}
}
func TestService_handleDeleteNotificationEndpoint(t *testing.T) {
var secrets map[string]string
type fields struct {
Secrets map[string]string
SecretService influxdb.SecretService
NotificationEndpointService influxdb.NotificationEndpointService
}
type args struct {
id string
}
type wants struct {
secrets map[string]string
statusCode int
contentType string
body string
@ -530,13 +558,27 @@ func TestService_handleDeleteNotificationEndpoint(t *testing.T) {
{
name: "remove a notification endpoint by id",
fields: fields{
&mock.NotificationEndpointService{
DeleteNotificationEndpointF: func(ctx context.Context, id influxdb.ID) error {
Secrets: map[string]string{
"020f755c3c082001-k1": "v1",
"020f755c3c082001-k2": "v2",
},
SecretService: &mock.SecretService{
DeleteSecretFn: func(ctx context.Context, orgID influxdb.ID, ks ...string) error {
for _, k := range ks {
delete(secrets, orgID.String()+"-"+k)
}
return nil
},
},
NotificationEndpointService: &mock.NotificationEndpointService{
DeleteNotificationEndpointF: func(ctx context.Context, id influxdb.ID) ([]influxdb.SecretField, influxdb.ID, error) {
if id == influxTesting.MustIDBase16("020f755c3c082000") {
return nil
return []influxdb.SecretField{
{Key: "k1"},
}, influxTesting.MustIDBase16("020f755c3c082001"), nil
}
return fmt.Errorf("wrong id")
return nil, 0, fmt.Errorf("wrong id")
},
},
},
@ -544,15 +586,18 @@ func TestService_handleDeleteNotificationEndpoint(t *testing.T) {
id: "020f755c3c082000",
},
wants: wants{
secrets: map[string]string{
"020f755c3c082001-k2": "v2",
},
statusCode: http.StatusNoContent,
},
},
{
name: "notification endpoint not found",
fields: fields{
&mock.NotificationEndpointService{
DeleteNotificationEndpointF: func(ctx context.Context, id influxdb.ID) error {
return &influxdb.Error{
NotificationEndpointService: &mock.NotificationEndpointService{
DeleteNotificationEndpointF: func(ctx context.Context, id influxdb.ID) ([]influxdb.SecretField, influxdb.ID, error) {
return nil, 0, &influxdb.Error{
Code: influxdb.ENotFound,
Msg: "notification endpoint not found",
}
@ -570,9 +615,12 @@ func TestService_handleDeleteNotificationEndpoint(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
secrets = tt.fields.Secrets
notificationEndpointBackend := NewMockNotificationEndpointBackend()
notificationEndpointBackend.HTTPErrorHandler = ErrorHandler(0)
notificationEndpointBackend.NotificationEndpointService = tt.fields.NotificationEndpointService
notificationEndpointBackend.SecretService = tt.fields.SecretService
h := NewNotificationEndpointHandler(notificationEndpointBackend)
r := httptest.NewRequest("GET", "http://any.url", nil)
@ -608,6 +656,10 @@ func TestService_handleDeleteNotificationEndpoint(t *testing.T) {
t.Errorf("%q. handleDeleteNotificationEndpoint() = ***%s***", tt.name, diff)
}
}
if diff := cmp.Diff(secrets, tt.wants.secrets); diff != "" {
t.Errorf("%q. handlePostNotificationEndpoint secrets are different ***%s***", tt.name, diff)
}
})
}
}
@ -767,14 +819,18 @@ func TestService_handlePatchNotificationEndpoint(t *testing.T) {
}
func TestService_handleUpdateNotificationEndpoint(t *testing.T) {
var secrets map[string]string
type fields struct {
Secrets map[string]string
SecretService influxdb.SecretService
NotificationEndpointService influxdb.NotificationEndpointService
}
type args struct {
id string
edp influxdb.NotificationEndpoint
edp map[string]interface{}
}
type wants struct {
secrets map[string]string
statusCode int
contentType string
body string
@ -789,23 +845,21 @@ func TestService_handleUpdateNotificationEndpoint(t *testing.T) {
{
name: "update a notification endpoint name",
fields: fields{
&mock.NotificationEndpointService{
Secrets: map[string]string{
"020f755c3c082001-020f755c3c082000-token": "tok-0",
},
SecretService: &mock.SecretService{
PutSecretFn: func(ctx context.Context, orgID influxdb.ID, k string, v string) error {
secrets[orgID.String()+"-"+k] = v
return nil
},
},
NotificationEndpointService: &mock.NotificationEndpointService{
UpdateNotificationEndpointF: func(ctx context.Context, id influxdb.ID, edp influxdb.NotificationEndpoint, userID influxdb.ID) (influxdb.NotificationEndpoint, error) {
if id == influxTesting.MustIDBase16("020f755c3c082000") {
d := &endpoint.Slack{
Base: endpoint.Base{
ID: influxTesting.MustIDBase16("020f755c3c082000"),
Name: "hello",
Status: influxdb.Inactive,
OrgID: influxTesting.MustIDBase16("020f755c3c082000"),
},
}
d = edp.(*endpoint.Slack)
d.SetID(influxTesting.MustIDBase16("020f755c3c082000"))
d.SetOrgID(influxTesting.MustIDBase16("020f755c3c082000"))
return d, nil
edp.SetID(id)
edp.BackfillSecretKeys()
return edp, nil
}
return nil, fmt.Errorf("not found")
@ -814,16 +868,19 @@ func TestService_handleUpdateNotificationEndpoint(t *testing.T) {
},
args: args{
id: "020f755c3c082000",
edp: &endpoint.Slack{
Base: endpoint.Base{
Name: "example",
Status: influxdb.Active,
},
URL: "example.com",
Token: influxdb.SecretField{Key: "user-key"},
edp: map[string]interface{}{
"name": "example",
"status": "active",
"orgID": "020f755c3c082001",
"type": "slack",
"url": "example.com",
"token": "token-2",
},
},
wants: wants{
secrets: map[string]string{
"020f755c3c082001-020f755c3c082000-token": "token-2",
},
statusCode: http.StatusOK,
contentType: "application/json; charset=utf-8",
body: `
@ -837,10 +894,10 @@ func TestService_handleUpdateNotificationEndpoint(t *testing.T) {
"createdAt": "0001-01-01T00:00:00Z",
"updatedAt": "0001-01-01T00:00:00Z",
"id": "020f755c3c082000",
"orgID": "020f755c3c082000",
"orgID": "020f755c3c082001",
"name": "example",
"url": "example.com",
"token": "secret: user-key",
"token": "secret: 020f755c3c082000-token",
"type": "slack",
"status": "active",
"labels": []
@ -851,7 +908,8 @@ func TestService_handleUpdateNotificationEndpoint(t *testing.T) {
{
name: "notification endpoint not found",
fields: fields{
&mock.NotificationEndpointService{
Secrets: map[string]string{},
NotificationEndpointService: &mock.NotificationEndpointService{
UpdateNotificationEndpointF: func(ctx context.Context, id influxdb.ID, edp influxdb.NotificationEndpoint, userID influxdb.ID) (influxdb.NotificationEndpoint, error) {
return nil, &influxdb.Error{
Code: influxdb.ENotFound,
@ -862,13 +920,13 @@ func TestService_handleUpdateNotificationEndpoint(t *testing.T) {
},
args: args{
id: "020f755c3c082000",
edp: &endpoint.Slack{
Base: endpoint.Base{
Name: "example",
},
edp: map[string]interface{}{
"type": "slack",
"name": "example",
},
},
wants: wants{
secrets: map[string]string{},
statusCode: http.StatusNotFound,
},
},
@ -876,9 +934,11 @@ func TestService_handleUpdateNotificationEndpoint(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
secrets = tt.fields.Secrets
notificationEndpointBackend := NewMockNotificationEndpointBackend()
notificationEndpointBackend.HTTPErrorHandler = ErrorHandler(0)
notificationEndpointBackend.NotificationEndpointService = tt.fields.NotificationEndpointService
notificationEndpointBackend.SecretService = tt.fields.SecretService
h := NewNotificationEndpointHandler(notificationEndpointBackend)
b, err := json.Marshal(tt.args.edp)
@ -918,6 +978,9 @@ func TestService_handleUpdateNotificationEndpoint(t *testing.T) {
t.Errorf("%q. handlePutNotificationEndpoint() = ***%s***", tt.name, diff)
}
}
if diff := cmp.Diff(secrets, tt.wants.secrets); diff != "" {
t.Errorf("%q. handlePostNotificationEndpoint secrets are different ***%s***", tt.name, diff)
}
})
}
}

View File

@ -118,15 +118,6 @@ func (s *Service) createNotificationEndpoint(ctx context.Context, tx Tx, edp inf
edp.SetUpdatedAt(now)
edp.BackfillSecretKeys()
for _, fld := range edp.SecretFields() {
if fld.Value != nil {
if err := s.putSecret(ctx, tx, edp.GetOrgID(),
fld.Key, *fld.Value); err != nil {
return InternalNotificationEndpointStoreError(err)
}
}
}
if err := s.putNotificationEndpoint(ctx, tx, edp); err != nil {
return err
}
@ -224,14 +215,6 @@ func (s *Service) updateNotificationEndpoint(ctx context.Context, tx Tx, id infl
edp.SetUpdatedAt(s.TimeGenerator.Now())
edp.BackfillSecretKeys()
for _, fld := range edp.SecretFields() {
if fld.Value != nil {
if err = s.putSecret(ctx, tx, edp.GetOrgID(),
fld.Key, *fld.Value); err != nil {
return nil, InternalNotificationEndpointStoreError(err)
}
}
}
err = s.putNotificationEndpoint(ctx, tx, edp)
return edp, err
@ -309,14 +292,6 @@ func (s *Service) putNotificationEndpoint(ctx context.Context, tx Tx, edp influx
if err := edp.Valid(); err != nil {
return err
}
for _, k := range edp.SecretFields() {
if _, err := s.loadSecret(ctx, tx, edp.GetOrgID(), string(k.Key)); err != nil {
return &influxdb.Error{
Code: influxdb.EInvalid,
Msg: "Unable to locate secret key: " + string(k.Key),
}
}
}
encodedID, _ := edp.GetID().Encode()
v, err := json.Marshal(edp)
@ -511,29 +486,25 @@ func filterNotificationEndpointsFn(filter influxdb.NotificationEndpointFilter) f
}
// DeleteNotificationEndpoint removes a notification endpoint by ID.
func (s *Service) DeleteNotificationEndpoint(ctx context.Context, id influxdb.ID) error {
return s.kv.Update(ctx, func(tx Tx) error {
return s.deleteNotificationEndpoint(ctx, tx, id)
func (s *Service) DeleteNotificationEndpoint(ctx context.Context, id influxdb.ID) (flds []influxdb.SecretField, orgID influxdb.ID, err error) {
err = s.kv.Update(ctx, func(tx Tx) error {
flds, orgID, err = s.deleteNotificationEndpoint(ctx, tx, id)
return err
})
return flds, orgID, err
}
func (s *Service) deleteNotificationEndpoint(ctx context.Context, tx Tx, id influxdb.ID) error {
func (s *Service) deleteNotificationEndpoint(ctx context.Context, tx Tx, id influxdb.ID) (flds []influxdb.SecretField, orgID influxdb.ID, err error) {
edp, encID, bucket, err := s.findNotificationEndpointByID(ctx, tx, id)
if err != nil {
return err
return nil, 0, err
}
if err = bucket.Delete(encID); err != nil {
return InternalNotificationEndpointStoreError(err)
return nil, 0, InternalNotificationEndpointStoreError(err)
}
for _, fld := range edp.SecretFields() {
if err := s.deleteSecret(ctx, tx, edp.GetOrgID(), fld.Key); err != nil {
InternalNotificationEndpointStoreError(err)
}
}
return s.deleteUserResourceMappings(ctx, tx, influxdb.UserResourceMappingFilter{
return edp.SecretFields(), edp.GetOrgID(), s.deleteUserResourceMappings(ctx, tx, influxdb.UserResourceMappingFilter{
ResourceID: id,
ResourceType: influxdb.NotificationEndpointResourceType,
})

View File

@ -56,14 +56,6 @@ func initNotificationEndpointService(s kv.Store, f influxdbtesting.NotificationE
t.Fatalf("error initializing user service: %v", err)
}
for _, s := range f.Secrets {
for k, v := range s.Env {
if err := svc.PutSecret(ctx, s.OrganizationID, k, v); err != nil {
t.Fatalf("failed to populate secrets")
}
}
}
for _, edp := range f.NotificationEndpoints {
if err := svc.PutNotificationEndpoint(ctx, edp); err != nil {
t.Fatalf("failed to populate notification endpoint: %v", err)
@ -84,7 +76,7 @@ func initNotificationEndpointService(s kv.Store, f influxdbtesting.NotificationE
return svc, func() {
for _, edp := range f.NotificationEndpoints {
if err := svc.DeleteNotificationEndpoint(ctx, edp.GetID()); err != nil {
if _, _, err := svc.DeleteNotificationEndpoint(ctx, edp.GetID()); err != nil {
t.Logf("failed to remove notification endpoint: %v", err)
}
}
@ -99,13 +91,5 @@ func initNotificationEndpointService(s kv.Store, f influxdbtesting.NotificationE
t.Logf("failed to remove urm rule: %v", err)
}
}
for _, s := range f.Secrets {
for k, v := range s.Env {
if err := svc.DeleteSecret(ctx, s.OrganizationID, k, v); err != nil && influxdb.ErrorCode(err) != influxdb.ENotFound {
t.Fatalf("failed to populate secrets")
}
}
}
}
}

View File

@ -12,13 +12,12 @@ var _ influxdb.NotificationEndpointService = &NotificationEndpointService{}
type NotificationEndpointService struct {
OrganizationService
UserResourceMappingService
SecretService
FindNotificationEndpointByIDF func(ctx context.Context, id influxdb.ID) (influxdb.NotificationEndpoint, error)
FindNotificationEndpointsF func(ctx context.Context, filter influxdb.NotificationEndpointFilter, opt ...influxdb.FindOptions) ([]influxdb.NotificationEndpoint, int, error)
CreateNotificationEndpointF func(ctx context.Context, nr influxdb.NotificationEndpoint, userID influxdb.ID) error
UpdateNotificationEndpointF func(ctx context.Context, id influxdb.ID, nr influxdb.NotificationEndpoint, userID influxdb.ID) (influxdb.NotificationEndpoint, error)
PatchNotificationEndpointF func(ctx context.Context, id influxdb.ID, upd influxdb.NotificationEndpointUpdate) (influxdb.NotificationEndpoint, error)
DeleteNotificationEndpointF func(ctx context.Context, id influxdb.ID) error
DeleteNotificationEndpointF func(ctx context.Context, id influxdb.ID) ([]influxdb.SecretField, influxdb.ID, error)
}
// FindNotificationEndpointByID returns a single telegraf config by ID.
@ -50,6 +49,6 @@ func (s *NotificationEndpointService) PatchNotificationEndpoint(ctx context.Cont
}
// DeleteNotificationEndpoint removes a notification rule by ID.
func (s *NotificationEndpointService) DeleteNotificationEndpoint(ctx context.Context, id influxdb.ID) error {
func (s *NotificationEndpointService) DeleteNotificationEndpoint(ctx context.Context, id influxdb.ID) ([]influxdb.SecretField, influxdb.ID, error) {
return s.DeleteNotificationEndpointF(ctx, id)
}

View File

@ -97,8 +97,6 @@ type NotificationEndpointService interface {
UserResourceMappingService
// OrganizationService is needed for search filter
OrganizationService
// SecretService is needed to check if the secret key exists.
SecretService
// FindNotificationEndpointByID returns a single notification endpoint by ID.
FindNotificationEndpointByID(ctx context.Context, id ID) (NotificationEndpoint, error)
@ -118,6 +116,6 @@ type NotificationEndpointService interface {
// Returns the new notification endpoint state after update.
PatchNotificationEndpoint(ctx context.Context, id ID, upd NotificationEndpointUpdate) (NotificationEndpoint, error)
// DeleteNotificationEndpoint removes a notification endpoint by ID.
DeleteNotificationEndpoint(ctx context.Context, id ID) error
// DeleteNotificationEndpoint removes a notification endpoint by ID, returns secret fields, orgID for further deletion.
DeleteNotificationEndpoint(ctx context.Context, id ID) (flds []SecretField, orgID ID, err error)
}

View File

@ -20,7 +20,6 @@ type NotificationEndpointFields struct {
NotificationEndpoints []influxdb.NotificationEndpoint
Orgs []*influxdb.Organization
UserResourceMappings []*influxdb.UserResourceMapping
Secrets []Secret
}
var timeGen1 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 13, 4, 19, 10, 0, time.UTC)}
@ -107,14 +106,6 @@ func CreateNotificationEndpoint(
Orgs: []*influxdb.Organization{
{ID: MustIDBase16(fourID), Name: "org1"},
},
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
},
},
},
NotificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
@ -203,90 +194,6 @@ func CreateNotificationEndpoint(
},
},
},
{
name: "secret not found",
fields: NotificationEndpointFields{
IDGenerator: mock.NewIDGenerator(twoID, t),
TimeGenerator: fakeGenerator,
Orgs: []*influxdb.Organization{
{ID: MustIDBase16(fourID), Name: "org1"},
},
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
},
},
},
NotificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
ID: MustIDBase16(oneID),
Name: "name1",
OrgID: MustIDBase16(fourID),
Status: influxdb.Active,
CRUDLog: influxdb.CRUDLog{
CreatedAt: timeGen1.Now(),
UpdatedAt: timeGen2.Now(),
},
},
URL: "example-slack.com",
Token: influxdb.SecretField{Key: oneID + "-token"},
},
},
UserResourceMappings: []*influxdb.UserResourceMapping{
{
ResourceID: MustIDBase16(oneID),
ResourceType: influxdb.NotificationEndpointResourceType,
UserID: MustIDBase16(sixID),
UserType: influxdb.Member,
},
},
},
args: args{
userID: MustIDBase16(sixID),
notificationEndpoint: &endpoint.PagerDuty{
Base: endpoint.Base{
Name: "name2",
OrgID: MustIDBase16(fourID),
Status: influxdb.Active,
},
URL: "example-pagerduty.com",
RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"},
},
},
wants: wants{
err: &influxdb.Error{
Code: influxdb.EInvalid,
Msg: "Unable to locate secret key: " + twoID + "-routing-key",
},
notificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
ID: MustIDBase16(oneID),
Name: "name1",
OrgID: MustIDBase16(fourID),
Status: influxdb.Active,
CRUDLog: influxdb.CRUDLog{
CreatedAt: timeGen1.Now(),
UpdatedAt: timeGen2.Now(),
},
},
URL: "example-slack.com",
Token: influxdb.SecretField{Key: oneID + "-token"},
},
},
userResourceMapping: []*influxdb.UserResourceMapping{
{
ResourceID: MustIDBase16(oneID),
ResourceType: influxdb.NotificationEndpointResourceType,
UserID: MustIDBase16(sixID),
UserType: influxdb.Member,
},
},
},
},
}
for _, tt := range tests {
@ -358,15 +265,6 @@ func FindNotificationEndpointByID(
ResourceType: influxdb.NotificationEndpointResourceType,
},
},
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
twoID + "-routing-key": "pager-duty-secret-2",
},
},
},
NotificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
@ -425,15 +323,6 @@ func FindNotificationEndpointByID(
ResourceType: influxdb.NotificationEndpointResourceType,
},
},
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
twoID + "-routing-key": "pager-duty-secret-2",
},
},
},
NotificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
@ -492,15 +381,6 @@ func FindNotificationEndpointByID(
ResourceType: influxdb.NotificationEndpointResourceType,
},
},
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
twoID + "-routing-key": "pager-duty-secret-2",
},
},
},
NotificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
@ -602,15 +482,6 @@ func FindNotificationEndpoints(
{
name: "find all notification endpoints",
fields: NotificationEndpointFields{
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
twoID + "-routing-key": "pager-duty-secret-2",
},
},
},
NotificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
@ -681,21 +552,6 @@ func FindNotificationEndpoints(
{
name: "filter by organization id only",
fields: NotificationEndpointFields{
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
twoID + "-routing-key": "pager-duty-secret-2",
},
},
{
OrganizationID: MustIDBase16(oneID),
Env: map[string]string{
fourID + "-routing-key": "pager-duty-secret-3",
},
},
},
Orgs: []*influxdb.Organization{
{
ID: MustIDBase16(oneID),
@ -762,20 +618,6 @@ func FindNotificationEndpoints(
{
name: "filter by organization name only",
fields: NotificationEndpointFields{
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
},
},
{
OrganizationID: MustIDBase16(oneID),
Env: map[string]string{
fourID + "-routing-key": "pager-duty-secret-2",
},
},
},
Orgs: []*influxdb.Organization{
{
ID: MustIDBase16(oneID),
@ -854,20 +696,6 @@ func FindNotificationEndpoints(
{
name: "find by id",
fields: NotificationEndpointFields{
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
},
},
{
OrganizationID: MustIDBase16(oneID),
Env: map[string]string{
fourID + "-routing-key": "pager-duty-secret-2",
},
},
},
Orgs: []*influxdb.Organization{
{
ID: MustIDBase16(oneID),
@ -935,15 +763,6 @@ func FindNotificationEndpoints(
{
name: "look for organization not bound to any notification endpoint",
fields: NotificationEndpointFields{
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
threeID + "-routing-key": "pager-duty-secret-2",
},
},
},
Orgs: []*influxdb.Organization{
{
ID: MustIDBase16(oneID),
@ -999,15 +818,6 @@ func FindNotificationEndpoints(
{
name: "find nothing",
fields: NotificationEndpointFields{
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
threeID + "-routing-key": "pager-duty-secret-2",
},
},
},
Orgs: []*influxdb.Organization{
{
ID: MustIDBase16(oneID),
@ -1093,7 +903,6 @@ func UpdateNotificationEndpoint(
type wants struct {
notificationEndpoint influxdb.NotificationEndpoint
secret *Secret
err error
}
tests := []struct {
@ -1120,15 +929,6 @@ func UpdateNotificationEndpoint(
ResourceType: influxdb.NotificationEndpointResourceType,
},
},
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
twoID + "-routing-key": "pager-duty-secret-2",
},
},
},
NotificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
@ -1199,15 +999,6 @@ func UpdateNotificationEndpoint(
ResourceType: influxdb.NotificationEndpointResourceType,
},
},
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
twoID + "-routing-key": "pager-duty-secret-2",
},
},
},
NotificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
@ -1253,12 +1044,6 @@ func UpdateNotificationEndpoint(
},
},
wants: wants{
secret: &Secret{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
twoID + "-routing-key": "pager-duty-secret-2",
},
},
notificationEndpoint: &endpoint.PagerDuty{
Base: endpoint.Base{
ID: MustIDBase16(twoID),
@ -1293,15 +1078,6 @@ func UpdateNotificationEndpoint(
ResourceType: influxdb.NotificationEndpointResourceType,
},
},
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
twoID + "-routing-key": "pager-duty-secret-2",
},
},
},
NotificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
@ -1351,12 +1127,6 @@ func UpdateNotificationEndpoint(
},
},
wants: wants{
secret: &Secret{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
twoID + "-routing-key": "pager-duty-value2",
},
},
notificationEndpoint: &endpoint.PagerDuty{
Base: endpoint.Base{
ID: MustIDBase16(twoID),
@ -1392,20 +1162,6 @@ func UpdateNotificationEndpoint(
if err != nil {
return
}
scrt := &Secret{
OrganizationID: tt.args.orgID,
Env: make(map[string]string),
}
for _, fld := range edp.SecretFields() {
scrtValue, err := s.LoadSecret(ctx, tt.args.orgID, fld.Key)
if err != nil {
t.Fatalf("failed to retrieve keys")
}
scrt.Env[fld.Key] = scrtValue
}
if diff := cmp.Diff(scrt, tt.wants.secret, secretCmpOptions); diff != "" {
t.Errorf("secret is different -got/+want\ndiff %s", diff)
}
})
}
}
@ -1453,15 +1209,6 @@ func PatchNotificationEndpoint(
ResourceType: influxdb.NotificationEndpointResourceType,
},
},
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
twoID + "-routing-key": "pager-duty-secret-2",
},
},
},
NotificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
@ -1525,15 +1272,6 @@ func PatchNotificationEndpoint(
ResourceType: influxdb.NotificationEndpointResourceType,
},
},
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
twoID + "-routing-key": "pager-duty-secret-2",
},
},
},
NotificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
@ -1619,7 +1357,8 @@ func DeleteNotificationEndpoint(
type wants struct {
notificationEndpoints []influxdb.NotificationEndpoint
userResourceMappings []*influxdb.UserResourceMapping
secrets []string
secretFlds []influxdb.SecretField
orgID influxdb.ID
err error
}
tests := []struct {
@ -1645,15 +1384,6 @@ func DeleteNotificationEndpoint(
ResourceType: influxdb.NotificationEndpointResourceType,
},
},
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
twoID + "-routing-key": "pager-duty-secret-2",
},
},
},
NotificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
@ -1695,10 +1425,6 @@ func DeleteNotificationEndpoint(
Code: influxdb.EInvalid,
Msg: "provided notification endpoint ID has invalid format",
},
secrets: []string{
oneID + "-token",
twoID + "-routing-key",
},
userResourceMappings: []*influxdb.UserResourceMapping{
{
ResourceID: MustIDBase16(oneID),
@ -1761,15 +1487,6 @@ func DeleteNotificationEndpoint(
ResourceType: influxdb.NotificationEndpointResourceType,
},
},
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
twoID + "-routing-key": "pager-duty-secret-2",
},
},
},
NotificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
@ -1810,10 +1527,6 @@ func DeleteNotificationEndpoint(
Code: influxdb.ENotFound,
Msg: "notification endpoint not found",
},
secrets: []string{
oneID + "-token",
twoID + "-routing-key",
},
userResourceMappings: []*influxdb.UserResourceMapping{
{
ResourceID: MustIDBase16(oneID),
@ -1877,15 +1590,6 @@ func DeleteNotificationEndpoint(
ResourceType: influxdb.NotificationEndpointResourceType,
},
},
Secrets: []Secret{
{
OrganizationID: MustIDBase16(fourID),
Env: map[string]string{
oneID + "-token": "slack-secret-1",
twoID + "-routing-key": "pager-duty-secret-2",
},
},
},
NotificationEndpoints: []influxdb.NotificationEndpoint{
&endpoint.Slack{
Base: endpoint.Base{
@ -1923,9 +1627,10 @@ func DeleteNotificationEndpoint(
userID: MustIDBase16(sixID),
},
wants: wants{
secrets: []string{
oneID + "-token",
secretFlds: []influxdb.SecretField{
{Key: twoID + "-routing-key"},
},
orgID: MustIDBase16(fourID),
userResourceMappings: []*influxdb.UserResourceMapping{
{
ResourceID: MustIDBase16(oneID),
@ -1958,8 +1663,16 @@ func DeleteNotificationEndpoint(
s, done := init(tt.fields, t)
defer done()
ctx := context.Background()
err := s.DeleteNotificationEndpoint(ctx, tt.args.id)
flds, orgID, err := s.DeleteNotificationEndpoint(ctx, tt.args.id)
ErrorsEqual(t, err, tt.wants.err)
if err != nil {
if diff := cmp.Diff(flds, tt.wants.secretFlds); diff != "" {
t.Errorf("delete notification endpoint secret fields are different -got/+want\ndiff %s", diff)
}
if diff := cmp.Diff(orgID, tt.wants.orgID); diff != "" {
t.Errorf("delete notification endpoint org id is different -got/+want\ndiff %s", diff)
}
}
filter := influxdb.NotificationEndpointFilter{}
edps, n, err := s.FindNotificationEndpoints(ctx, filter)
@ -1990,13 +1703,6 @@ func DeleteNotificationEndpoint(
if diff := cmp.Diff(urms, tt.wants.userResourceMappings, userResourceMappingCmpOptions...); diff != "" {
t.Errorf("user resource mappings are different -got/+want\ndiff %s", diff)
}
scrtKeys, err := s.GetSecretKeys(ctx, tt.args.orgID)
if err != nil {
t.Fatalf("failed to retrieve secret keys: %v", err)
}
if diff := cmp.Diff(scrtKeys, tt.wants.secrets, secretCmpOptions...); diff != "" {
t.Errorf("secret keys are different -got/+want\ndiff %s", diff)
}
})
}
}