Skip to content
Merged
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
18 changes: 18 additions & 0 deletions api/proto/teleport/legacy/types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5293,6 +5293,8 @@ message PluginSpecV1 {
PluginJamfSettings jamf = 5;
// Settings for the PagerDuty plugin
PluginPagerDutySettings pager_duty = 6;
// Settings for the Mattermost plugin
PluginMattermostSettings mattermost = 7;
}
}

Expand Down Expand Up @@ -5336,6 +5338,22 @@ message PluginOpenAISettings {
option (gogoproto.equal) = true;
}

// Defines settings for the Mattermost plugin.
message PluginMattermostSettings {
option (gogoproto.equal) = true;
// serverURL is the URL to access Mattermost.
string server_url = 1;
// team is the Mattermost workspace.
string team = 2;
// channel is the Mattermost channel in the workspace
// (team) to send notifications to.
string channel = 3;
// report_to_email is an optional email address of a Mattermost user
// to notify via a direct message when the plugin receives an
// Access Request event.
string report_to_email = 4;
}

// Defines settings for Jamf plugin.
message PluginJamfSettings {
option (gogoproto.equal) = true;
Expand Down
33 changes: 33 additions & 0 deletions api/types/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ const (
PluginTypeOpsgenie = "opsgenie"
// PluginTypePagerDuty is the PagerDuty access plugin
PluginTypePagerDuty = "pagerduty"
// PluginTypeMattermost is the PagerDuty access plugin
PluginTypeMattermost = "mattermost"
)

// PluginSubkind represents the type of the plugin, e.g., access request, MDM etc.
Expand Down Expand Up @@ -148,6 +150,21 @@ func (p *PluginV1) CheckAndSetDefaults() error {
if len(staticCreds.Labels) == 0 {
return trace.BadParameter("labels must be specified")
}
case *PluginSpecV1_Mattermost:
if settings.Mattermost == nil {
return trace.BadParameter("missing Mattermost settings")
}
if err := settings.Mattermost.CheckAndSetDefaults(); err != nil {
return trace.Wrap(err)
}

staticCreds := p.Credentials.GetStaticCredentialsRef()
if staticCreds == nil {
return trace.BadParameter("Mattermost plugin must be used with the static credentials ref type")
}
if len(staticCreds.Labels) == 0 {
return trace.BadParameter("labels must be specified")
}
case *PluginSpecV1_Jamf:
// Check Jamf settings.
if settings.Jamf == nil {
Expand Down Expand Up @@ -332,6 +349,8 @@ func (p *PluginV1) GetType() PluginType {
return PluginTypeOpsgenie
case *PluginSpecV1_PagerDuty:
return PluginTypePagerDuty
case *PluginSpecV1_Mattermost:
return PluginTypeMattermost
default:
return PluginTypeUnknown
}
Expand Down Expand Up @@ -372,6 +391,20 @@ func (s *PluginJamfSettings) CheckAndSetDefaults() error {
return nil
}

// CheckAndSetDefaults validates and set the default values
func (s *PluginMattermostSettings) CheckAndSetDefaults() error {
if s.ServerUrl == "" {
return trace.BadParameter("server url is required")
}
if s.Team == "" {
return trace.BadParameter("team is required")
}
if s.Channel == "" {
return trace.BadParameter("channel is required")
}
return nil
}

// CheckAndSetDefaults validates and set the default values
func (c *PluginOAuth2AuthorizationCodeCredentials) CheckAndSetDefaults() error {
if c.AuthorizationCode == "" {
Expand Down
127 changes: 127 additions & 0 deletions api/types/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,3 +426,130 @@ func TestPluginJamfValidation(t *testing.T) {
})
}
}

func TestPluginMattermostValidation(t *testing.T) {
defaultSettings := &PluginSpecV1_Mattermost{
Mattermost: &PluginMattermostSettings{
ServerUrl: "https://test.mattermost.com",
Team: "team-llama",
Channel: "teleport",
},
}

testCases := []struct {
name string
settings *PluginSpecV1_Mattermost
creds *PluginCredentialsV1
assertErr require.ErrorAssertionFunc
}{
{
name: "no settings",
settings: &PluginSpecV1_Mattermost{
Mattermost: nil,
},
creds: nil,
assertErr: func(t require.TestingT, err error, args ...any) {
require.True(t, trace.IsBadParameter(err))
require.Contains(t, err.Error(), "missing Mattermost settings")
},
},
{
name: "no server url",
settings: &PluginSpecV1_Mattermost{
Mattermost: &PluginMattermostSettings{},
},
creds: nil,
assertErr: func(t require.TestingT, err error, args ...any) {
require.True(t, trace.IsBadParameter(err))
require.Contains(t, err.Error(), "server url is required")
},
},
{
name: "no team",
settings: &PluginSpecV1_Mattermost{
Mattermost: &PluginMattermostSettings{
ServerUrl: "https://test.mattermost.com",
},
},
creds: nil,
assertErr: func(t require.TestingT, err error, args ...any) {
require.True(t, trace.IsBadParameter(err))
require.Contains(t, err.Error(), "team is required")
},
},
{
name: "no channel",
settings: &PluginSpecV1_Mattermost{
Mattermost: &PluginMattermostSettings{
ServerUrl: "https://test.mattermost.com",
Team: "team-llama",
},
},
creds: nil,
assertErr: func(t require.TestingT, err error, args ...any) {
require.True(t, trace.IsBadParameter(err))
require.Contains(t, err.Error(), "channel is required")
},
},
{
name: "no credentials inner",
settings: defaultSettings,
creds: &PluginCredentialsV1{},
assertErr: func(t require.TestingT, err error, args ...any) {
require.True(t, trace.IsBadParameter(err))
require.Contains(t, err.Error(), "must be used with the static credentials ref type")
},
},
{
name: "invalid credential type (oauth2)",
settings: defaultSettings,
creds: &PluginCredentialsV1{
Credentials: &PluginCredentialsV1_Oauth2AccessToken{},
},
assertErr: func(t require.TestingT, err error, args ...any) {
require.True(t, trace.IsBadParameter(err))
require.Contains(t, err.Error(), "must be used with the static credentials ref type")
},
},
{
name: "no labels for credentials",
settings: defaultSettings,
creds: &PluginCredentialsV1{
Credentials: &PluginCredentialsV1_StaticCredentialsRef{
&PluginStaticCredentialsRef{
Labels: map[string]string{},
},
},
},
assertErr: func(t require.TestingT, err error, args ...any) {
require.True(t, trace.IsBadParameter(err))
require.Contains(t, err.Error(), "labels must be specified")
},
},
{
name: "valid settings",
settings: defaultSettings,
creds: &PluginCredentialsV1{
Credentials: &PluginCredentialsV1_StaticCredentialsRef{
&PluginStaticCredentialsRef{
Labels: map[string]string{
"label1": "value1",
},
},
},
},
assertErr: func(t require.TestingT, err error, args ...any) {
require.NoError(t, err)
},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
plugin := NewPluginV1(Metadata{Name: "foobar"}, PluginSpecV1{
Settings: tc.settings,
}, tc.creds)
tc.assertErr(t, plugin.CheckAndSetDefaults())
})
}
}
Loading