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
20 changes: 20 additions & 0 deletions api/proto/teleport/legacy/types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5577,6 +5577,26 @@ message PluginOktaSettings {

// OrgUrl is the Okta organization URL to use for API communication.
string org_url = 1;

// Sync settings controls the user and access list sync settings for Okta.
PluginOktaSyncSettings sync_settings = 4;
}

// Defines settings for syncing users and access lists from Okta.
message PluginOktaSyncSettings {
option (gogoproto.equal) = true;

// SyncUsers controls the user sync in the Okta integration service.
bool sync_users = 1;

// SSOConnectorID is the name of the Teleport SSO connector created and used by the Okta plugin
string sso_connector_id = 2;

// SyncAccessLists controls the access list sync in the Okta integration service.
bool sync_access_lists = 3;

// DefaultOwners are the default owners for all imported access lists.
repeated string default_owners = 4;
}

// Defines a set of discord channel IDs
Expand Down
29 changes: 21 additions & 8 deletions api/types/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,27 @@ func (s *PluginOktaSettings) CheckAndSetDefaults() error {
return trace.BadParameter("org_url must be set")
}

// If sync settings is not set, default to an empty config.
if s.SyncSettings == nil {
s.SyncSettings = &PluginOktaSyncSettings{}
}

if s.SyncSettings.SyncUsers && s.SyncSettings.SsoConnectorId == "" {
return trace.BadParameter("sso_connector_id must be set when user sync enabled")
}

if s.SyncSettings.SyncAccessLists && len(s.SyncSettings.DefaultOwners) == 0 {
return trace.BadParameter("default owners must be set when access list import is enabled")
}

return nil
}

// CheckAndSetDefaults validates and set the default values
func (s *PluginOpsgenieAccessSettings) CheckAndSetDefaults() error {
if s.ApiEndpoint == "" {
return trace.BadParameter("opsgenie api endpoint url must be set")
}
return nil
}

Expand Down Expand Up @@ -444,14 +465,6 @@ func (s *PluginJiraSettings) CheckAndSetDefaults() error {
return nil
}

// CheckAndSetDefaults validates and set the default values
func (s *PluginOpsgenieAccessSettings) CheckAndSetDefaults() error {
if s.ApiEndpoint == "" {
return trace.BadParameter("opsgenie api endpoint url must be set")
}
return nil
}

// CheckAndSetDefaults validates and set the default values
func (s *PluginMattermostSettings) CheckAndSetDefaults() error {
if s.ServerUrl == "" {
Expand Down
139 changes: 101 additions & 38 deletions api/types/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,34 +201,71 @@ func TestPluginOpsgenieValidation(t *testing.T) {
}
}

func requireBadParameterWith(msg string) require.ErrorAssertionFunc {
return func(t require.TestingT, err error, args ...interface{}) {
require.True(t, trace.IsBadParameter(err), "error: %v", err)
require.Contains(t, err.Error(), msg)
}
}

func TestPluginOktaValidation(t *testing.T) {
validSettings := &PluginSpecV1_Okta{
Okta: &PluginOktaSettings{
OrgUrl: "https://test.okta.com",
SyncSettings: &PluginOktaSyncSettings{
SyncUsers: true,
SsoConnectorId: "some-sso-connector-id",
SyncAccessLists: true,
DefaultOwners: []string{"owner1"},
},
},
}

validCreds := &PluginCredentialsV1{
Credentials: &PluginCredentialsV1_StaticCredentialsRef{
&PluginStaticCredentialsRef{
Labels: map[string]string{
"label1": "value1",
},
},
},
}

testCases := []struct {
name string
settings *PluginSpecV1_Okta
creds *PluginCredentialsV1
assertErr require.ErrorAssertionFunc
name string
settings *PluginSpecV1_Okta
creds *PluginCredentialsV1
assertErr require.ErrorAssertionFunc
assertValue func(*testing.T, *PluginOktaSettings)
}{
{
name: "valid values are preserved",
settings: validSettings,
creds: validCreds,
assertErr: require.NoError,
assertValue: func(t *testing.T, settings *PluginOktaSettings) {
require.Equal(t, "https://test.okta.com", settings.OrgUrl)
require.True(t, settings.SyncSettings.SyncUsers)
require.Equal(t, "some-sso-connector-id", settings.SyncSettings.SsoConnectorId)
require.True(t, settings.SyncSettings.SyncAccessLists)
require.ElementsMatch(t, []string{"owner1"}, settings.SyncSettings.DefaultOwners)
},
},
{
name: "no settings",
settings: &PluginSpecV1_Okta{
Okta: nil,
},
creds: nil,
assertErr: func(t require.TestingT, err error, args ...any) {
require.True(t, trace.IsBadParameter(err))
require.Contains(t, err.Error(), "missing Okta settings")
},
creds: validCreds,
assertErr: requireBadParameterWith("missing Okta settings"),
},
{
name: "no org URL",
settings: &PluginSpecV1_Okta{
Okta: &PluginOktaSettings{},
},
creds: nil,
assertErr: func(t require.TestingT, err error, args ...any) {
require.True(t, trace.IsBadParameter(err))
require.Contains(t, err.Error(), "org_url must be set")
},
creds: validCreds,
assertErr: requireBadParameterWith("org_url must be set"),
},
{
name: "no credentials inner",
Expand All @@ -237,11 +274,8 @@ func TestPluginOktaValidation(t *testing.T) {
OrgUrl: "https://test.okta.com",
},
},
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")
},
creds: &PluginCredentialsV1{},
assertErr: requireBadParameterWith("must be used with the static credentials ref type"),
},
{
name: "invalid credential type (oauth2)",
Expand All @@ -253,10 +287,7 @@ func TestPluginOktaValidation(t *testing.T) {
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")
},
assertErr: requireBadParameterWith("must be used with the static credentials ref type"),
},
{
name: "invalid credentials (static credentials)",
Expand All @@ -272,30 +303,59 @@ func TestPluginOktaValidation(t *testing.T) {
},
},
},
assertErr: func(t require.TestingT, err error, args ...any) {
require.True(t, trace.IsBadParameter(err))
require.Contains(t, err.Error(), "labels must be specified")
assertErr: requireBadParameterWith("labels must be specified"),
}, {
name: "EnableUserSync defaults to false",
settings: &PluginSpecV1_Okta{
Okta: &PluginOktaSettings{
OrgUrl: "https://test.okta.com",
},
},
},
{
name: "valid credentials (static credentials)",
creds: validCreds,
assertErr: require.NoError,
assertValue: func(t *testing.T, settings *PluginOktaSettings) {
require.False(t, settings.SyncSettings.SyncUsers)
},
}, {
name: "SSO connector ID required for user sync",
settings: &PluginSpecV1_Okta{
Okta: &PluginOktaSettings{
OrgUrl: "https://test.okta.com",
SyncSettings: &PluginOktaSyncSettings{
SyncUsers: true,
},
},
},
creds: &PluginCredentialsV1{
Credentials: &PluginCredentialsV1_StaticCredentialsRef{
&PluginStaticCredentialsRef{
Labels: map[string]string{
"label1": "value1",
},
creds: validCreds,
assertErr: require.Error,
}, {
name: "SSO connector ID not required without user sync",
settings: &PluginSpecV1_Okta{
Okta: &PluginOktaSettings{
OrgUrl: "https://test.okta.com",
SyncSettings: &PluginOktaSyncSettings{
SyncUsers: false,
},
},
},
assertErr: func(t require.TestingT, err error, args ...any) {
require.NoError(t, err)
creds: validCreds,
assertErr: require.NoError,
assertValue: func(t *testing.T, settings *PluginOktaSettings) {
require.False(t, settings.SyncSettings.SyncUsers)
require.Empty(t, settings.SyncSettings.SsoConnectorId)
},
}, {
name: "import enabled without default owners",
settings: &PluginSpecV1_Okta{
Okta: &PluginOktaSettings{
OrgUrl: "https://test.okta.com",
SyncSettings: &PluginOktaSyncSettings{
SyncAccessLists: true,
},
},
},
creds: validCreds,
assertErr: requireBadParameterWith("default owners must be set when access list import is enabled"),
},
}

Expand All @@ -305,6 +365,9 @@ func TestPluginOktaValidation(t *testing.T) {
Settings: tc.settings,
}, tc.creds)
tc.assertErr(t, plugin.CheckAndSetDefaults())
if tc.assertValue != nil {
tc.assertValue(t, plugin.Spec.GetOkta())
}
})
}
}
Expand Down Expand Up @@ -688,7 +751,7 @@ func TestPluginDiscordValidation(t *testing.T) {
return &PluginSpecV1_Discord{
&PluginDiscordSettings{
RoleToRecipients: map[string]*DiscordChannels{
"*": &DiscordChannels{ChannelIds: []string{"1234567890"}},
"*": {ChannelIds: []string{"1234567890"}},
},
},
}
Expand Down
Loading