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

[v14] Add initial servicenow plugin #32131

Merged
merged 4 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions api/proto/teleport/legacy/types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5336,6 +5336,8 @@ message PluginSpecV1 {
PluginJiraSettings jira = 8;
// Settings for the Discord plugin
PluginDiscordSettings discord = 9;
// Settings for the ServiceNow plugin
PluginServiceNowSettings serviceNow = 10;
}
}

Expand All @@ -5361,6 +5363,20 @@ message PluginOpsgenieAccessSettings {
string api_endpoint = 5;
}

// PluginServiceNowSettings are the settings for the serviceNow plugin
message PluginServiceNowSettings {
option (gogoproto.equal) = true;

// ApiEndpoint is the ServiceNow API endpoint.
string api_endpoint = 1 [(gogoproto.jsontag) = "api_endpoint,omitempty"];
// Username is the ServiceNow API username.
string username = 2 [(gogoproto.jsontag) = "username,omitempty"];
// Password is the ServiceNow API password.
string password = 3 [(gogoproto.jsontag) = "password,omitempty"];
// CloseCode is the close code that ServiceNow incidents will use.
string close_code = 4 [(gogoproto.jsontag) = "close_code,omitempty"];
}

message PluginPagerDutySettings {
option (gogoproto.equal) = true;

Expand Down
25 changes: 25 additions & 0 deletions api/types/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ type PluginType string
const (
// PluginTypeUnknown is returned when no plugin type matches.
PluginTypeUnknown PluginType = ""
// PluginTypeServiceNow is the Servicenow access request plugin
PluginTypeServiceNow = "servicenow"
// PluginTypeSlack is the Slack access request plugin
PluginTypeSlack = "slack"
// PluginTypeOpenAI is the OpenAI plugin
Expand Down Expand Up @@ -249,6 +251,18 @@ func (p *PluginV1) CheckAndSetDefaults() error {
if staticCreds == nil {
return trace.BadParameter("Discord plugin must be used with the static credentials ref type")
}
case *PluginSpecV1_ServiceNow:
if settings.ServiceNow == nil {
return trace.BadParameter("missing ServiceNow settings")
}
if err := settings.ServiceNow.CheckAndSetDefaults(); err != nil {
return trace.Wrap(err)
}

staticCreds := p.Credentials.GetStaticCredentialsRef()
if staticCreds == nil {
return trace.BadParameter("ServiceNow plugin must be used with the static credentials ref type")
}

default:
return trace.BadParameter("settings are not set or have an unknown type")
Expand Down Expand Up @@ -406,6 +420,8 @@ func (p *PluginV1) GetType() PluginType {
return PluginTypeMattermost
case *PluginSpecV1_Discord:
return PluginTypeDiscord
case *PluginSpecV1_ServiceNow:
return PluginTypeServiceNow
default:
return PluginTypeUnknown
}
Expand Down Expand Up @@ -516,6 +532,15 @@ func (c *PluginDiscordSettings) CheckAndSetDefaults() error {
return nil
}

// CheckAndSetDefaults checks that the required fields for the servicenow plugin are set.
func (c *PluginServiceNowSettings) CheckAndSetDefaults() error {
if c.ApiEndpoint == "" {
return trace.BadParameter("API endpoint must be set")
}

return nil
}

// CheckAndSetDefaults validates and set the default values
func (c *PluginOAuth2AccessTokenCredentials) CheckAndSetDefaults() error {
if c.AccessToken == "" {
Expand Down
3,652 changes: 2,054 additions & 1,598 deletions api/types/types.pb.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion integrations/access/common/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ func (a *BaseApp) getMessageRecipients(ctx context.Context, req types.AccessRequ
recipientSet := NewRecipientSet()

switch a.Conf.GetPluginType() {
case types.PluginTypeOpsgenie:
case types.PluginTypeOpsgenie, types.PluginTypeServiceNow:
if recipients, ok := req.GetSystemAnnotations()[types.TeleportNamespace+types.ReqAnnotationSchedulesLabel]; ok {
for _, recipient := range recipients {
rec, err := a.bot.FetchRecipient(ctx, recipient)
Expand Down
13 changes: 11 additions & 2 deletions integrations/access/common/plugindata.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"fmt"
"strings"

"github.com/gravitational/trace"

"github.com/gravitational/teleport/integrations/lib/plugindata"
)

Expand All @@ -44,7 +46,11 @@ type SentMessages []MessageData
func DecodePluginData(dataMap map[string]string) (GenericPluginData, error) {
data := GenericPluginData{}

data.AccessRequestData = plugindata.DecodeAccessRequestData(dataMap)
var err error
data.AccessRequestData, err = plugindata.DecodeAccessRequestData(dataMap)
if err != nil {
return GenericPluginData{}, trace.Wrap(err)
}

if channelID, timestamp := dataMap["channel_id"], dataMap["timestamp"]; channelID != "" && timestamp != "" {
data.SentMessages = append(data.SentMessages, MessageData{ChannelID: channelID, MessageID: timestamp})
Expand All @@ -62,7 +68,10 @@ func DecodePluginData(dataMap map[string]string) (GenericPluginData, error) {

// EncodePluginData serializes a GenericPluginData struct into a string map.
func EncodePluginData(data GenericPluginData) (map[string]string, error) {
result := plugindata.EncodeAccessRequestData(data.AccessRequestData)
result, err := plugindata.EncodeAccessRequestData(data.AccessRequestData)
if err != nil {
return nil, trace.Wrap(err)
}

var encodedMessages []string
for _, msg := range data.SentMessages {
Expand Down
2 changes: 2 additions & 0 deletions integrations/access/common/recipient.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (
const (
// RecipientKindSchedule shows a recipient is a schedule.
RecipientKindSchedule = "schedule"
// RecipientKindRotation shows a recipient is a rotation.
RecipientKindRotation = "rota"
)

// RawRecipientsMap is a mapping of roles to recipient(s).
Expand Down