Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emit notifications when creating User Task for a given Integration #47556

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions api/proto/teleport/legacy/types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7573,6 +7573,25 @@ message IntegrationV1 {
(gogoproto.nullable) = false,
(gogoproto.jsontag) = "spec"
];

// Status has the current state of the integration.
IntegrationStatusV1 Status = 3 [
(gogoproto.nullable) = false,
(gogoproto.jsontag) = "status"
];
}

// IntegrationStatusV1 contains the current status for a given integration.
message IntegrationStatusV1 {
// PendingUserTasksNotificationID contains the notification ID that indicates that this integration has unresolved user tasks.
string PendingUserTasksNotificationID = 1 [(gogoproto.jsontag) = "pending_user_tasks_notification_id,omitempty"];
// PendingUserTasksNotificationExpires contains the expiration date for the notification.
// Used to ensure new notifications' expiration is the greater between the current notification and the new one.
google.protobuf.Timestamp PendingUserTasksNotificationExpires = 2 [
(gogoproto.stdtime) = true,
(gogoproto.nullable) = true,
(gogoproto.jsontag) = "pending_user_tasks_notification_expires,omitempty"
];
}

// IntegrationSpecV1 contains properties of all the supported integrations.
Expand Down
6 changes: 6 additions & 0 deletions api/types/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,12 @@ const (
// NotificationUserCreatedWarningSubKind is the subkind for a user-created warning notification.
NotificationUserCreatedWarningSubKind = "user-created-warning"

// NotificationPendingUserTaskIntegrationSubKind is the subkind for a notification that warns the user about pending User Tasks for a given integration.
NotificationPendingUserTaskIntegrationSubKind = "pending-user-task-for-integration"
// NotificationIntegrationLabel is the label which contains the name of the integration.
// To be used with NotificationUserTaskIntegrationSubKind.
NotificationIntegrationLabel = "integration-name"

// NotificationAccessRequestPendingSubKind is the subkind for a notification for an access request pending review.
NotificationAccessRequestPendingSubKind = "access-request-pending"
// NotificationAccessRequestApprovedSubKind is the subkind for a notification for a user's access request being approved.
Expand Down
27 changes: 27 additions & 0 deletions api/types/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ type Integration interface {
GetCredentials() PluginCredentials
// WithoutCredentials returns a copy without credentials.
WithoutCredentials() Integration

// GetStatus returns the Integration Status.
GetStatus() IntegrationStatusV1
// SetStatus sets the Integration Status.
SetStatus(IntegrationStatusV1)
}

var _ ResourceWithLabels = (*IntegrationV1)(nil)
Expand Down Expand Up @@ -339,6 +344,22 @@ func (ig *IntegrationV1) SetGitHubIntegrationSpec(spec *GitHubIntegrationSpecV1)
}
}

// GetStatus returns the Integration Status.
func (ig *IntegrationV1) GetStatus() IntegrationStatusV1 {
if ig == nil {
return IntegrationStatusV1{}
}
return ig.Status
}

// SetStatus sets the Integration Status.
func (ig *IntegrationV1) SetStatus(s IntegrationStatusV1) {
if ig == nil {
return
}
ig.Status = s
}

// Integrations is a list of Integration resources.
type Integrations []Integration

Expand Down Expand Up @@ -393,6 +414,7 @@ func (ig *IntegrationV1) UnmarshalJSON(data []byte) error {
GitHub json.RawMessage `json:"github"`
Credentials json.RawMessage `json:"credentials"`
} `json:"spec"`
Status IntegrationStatusV1 `json:"status"`
}{}

err := json.Unmarshal(data, &d)
Expand All @@ -401,6 +423,8 @@ func (ig *IntegrationV1) UnmarshalJSON(data []byte) error {
}

integration.ResourceHeader = d.ResourceHeader
integration.Status = d.Status

if len(d.Spec.Credentials) != 0 {
var credentials PluginCredentialsV1
if err := protojson.Unmarshal(d.Spec.Credentials, protoadapt.MessageV2Of(&credentials)); err != nil {
Expand Down Expand Up @@ -468,9 +492,12 @@ func (ig *IntegrationV1) MarshalJSON() ([]byte, error) {
GitHub GitHubIntegrationSpecV1 `json:"github,omitempty"`
Credentials json.RawMessage `json:"credentials,omitempty"`
} `json:"spec"`
Status IntegrationStatusV1 `json:"status"`
}{}

d.ResourceHeader = ig.ResourceHeader
d.Status = ig.Status

if ig.Spec.Credentials != nil {
data, err := protojson.Marshal(protoadapt.MessageV2Of(ig.Spec.Credentials))
if err != nil {
Expand Down
56 changes: 56 additions & 0 deletions api/types/notifications/notifications.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Copyright 2024 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package notifications

import (
"time"

"google.golang.org/protobuf/types/known/timestamppb"

headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1"
notificationsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/notifications/v1"
"github.com/gravitational/teleport/api/types"
)

// NewPendingUserTasksIntegrationNotification creates a new GlobalNotification for warning the users about pending UserTasks related to an integration.
func NewPendingUserTasksIntegrationNotification(integrationName string, expires time.Time) *notificationsv1.GlobalNotification {
return &notificationsv1.GlobalNotification{
Spec: &notificationsv1.GlobalNotificationSpec{
Matcher: &notificationsv1.GlobalNotificationSpec_ByPermissions{
ByPermissions: &notificationsv1.ByPermissions{
RoleConditions: []*types.RoleConditions{{
Rules: []types.Rule{{
Resources: []string{types.KindIntegration},
Verbs: []string{types.VerbList, types.VerbRead},
}},
}},
},
},
Notification: &notificationsv1.Notification{
Spec: &notificationsv1.NotificationSpec{},
SubKind: types.NotificationPendingUserTaskIntegrationSubKind,
Metadata: &headerv1.Metadata{
Labels: map[string]string{
types.NotificationTitleLabel: "Your integration needs attention.",
types.NotificationIntegrationLabel: integrationName,
},
Expires: timestamppb.New(expires),
},
},
},
}
}
Loading
Loading