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
72 changes: 72 additions & 0 deletions lib/auth/auth_with_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -3235,6 +3235,10 @@ func (a *ServerWithRoles) UpsertOIDCConnector(ctx context.Context, connector typ
return nil, trace.AccessDenied("OIDC is only available in Teleport Enterprise")
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return nil, trace.Wrap(err)
}

upserted, err := a.authServer.UpsertOIDCConnector(ctx, connector)
return upserted, trace.Wrap(err)
}
Expand All @@ -3251,6 +3255,10 @@ func (a *ServerWithRoles) UpdateOIDCConnector(ctx context.Context, connector typ
return nil, trace.AccessDenied("OIDC is only available in Teleport Enterprise")
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return nil, trace.Wrap(err)
}

updated, err := a.authServer.UpdateOIDCConnector(ctx, connector)
return updated, trace.Wrap(err)
}
Expand All @@ -3267,6 +3275,10 @@ func (a *ServerWithRoles) CreateOIDCConnector(ctx context.Context, connector typ
return nil, trace.AccessDenied("OIDC is only available in Teleport Enterprise")
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return nil, trace.Wrap(err)
}

creted, err := a.authServer.CreateOIDCConnector(ctx, connector)
return creted, trace.Wrap(err)
}
Expand Down Expand Up @@ -3303,6 +3315,10 @@ func (a *ServerWithRoles) CreateOIDCAuthRequest(ctx context.Context, req types.O
return nil, trace.Wrap(err)
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return nil, trace.Wrap(err)
}

// require additional permissions for executing SSO test flow.
if req.SSOTestFlow {
if err := a.authConnectorAction(apidefaults.Namespace, types.KindOIDC, types.VerbCreate); err != nil {
Expand Down Expand Up @@ -3352,6 +3368,11 @@ func (a *ServerWithRoles) DeleteOIDCConnector(ctx context.Context, connectorID s
if err := a.authConnectorAction(apidefaults.Namespace, types.KindOIDC, types.VerbDelete); err != nil {
return trace.Wrap(err)
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return trace.Wrap(err)
}

return a.authServer.DeleteOIDCConnector(ctx, connectorID)
}

Expand All @@ -3364,10 +3385,15 @@ func (a *ServerWithRoles) UpsertSAMLConnector(ctx context.Context, connector typ
if err := a.authConnectorAction(apidefaults.Namespace, types.KindSAML, types.VerbCreate); err != nil {
return nil, trace.Wrap(err)
}

if err := a.authConnectorAction(apidefaults.Namespace, types.KindSAML, types.VerbUpdate); err != nil {
return nil, trace.Wrap(err)
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return nil, trace.Wrap(err)
}

upserted, err := a.authServer.UpsertSAMLConnector(ctx, connector)
return upserted, trace.Wrap(err)
}
Expand All @@ -3382,6 +3408,10 @@ func (a *ServerWithRoles) CreateSAMLConnector(ctx context.Context, connector typ
return nil, trace.Wrap(err)
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return nil, trace.Wrap(err)
}

created, err := a.authServer.CreateSAMLConnector(ctx, connector)
return created, trace.Wrap(err)
}
Expand All @@ -3396,6 +3426,10 @@ func (a *ServerWithRoles) UpdateSAMLConnector(ctx context.Context, connector typ
return nil, trace.Wrap(err)
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return nil, trace.Wrap(err)
}

updated, err := a.authServer.UpdateSAMLConnector(ctx, connector)
return updated, trace.Wrap(err)
}
Expand All @@ -3404,11 +3438,13 @@ func (a *ServerWithRoles) GetSAMLConnector(ctx context.Context, id string, withS
if err := a.authConnectorAction(apidefaults.Namespace, types.KindSAML, types.VerbReadNoSecrets); err != nil {
return nil, trace.Wrap(err)
}

if withSecrets {
if err := a.authConnectorAction(apidefaults.Namespace, types.KindSAML, types.VerbRead); err != nil {
return nil, trace.Wrap(err)
}
}

return a.authServer.GetSAMLConnector(ctx, id, withSecrets)
}

Expand All @@ -3432,6 +3468,10 @@ func (a *ServerWithRoles) CreateSAMLAuthRequest(ctx context.Context, req types.S
return nil, trace.Wrap(err)
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return nil, trace.Wrap(err)
}

// require additional permissions for executing SSO test flow.
if req.SSOTestFlow {
if err := a.authConnectorAction(apidefaults.Namespace, types.KindSAML, types.VerbCreate); err != nil {
Expand Down Expand Up @@ -3510,6 +3550,11 @@ func (a *ServerWithRoles) DeleteSAMLConnector(ctx context.Context, connectorID s
if err := a.authConnectorAction(apidefaults.Namespace, types.KindSAML, types.VerbDelete); err != nil {
return trace.Wrap(err)
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return trace.Wrap(err)
}

return a.authServer.DeleteSAMLConnector(ctx, connectorID)
}

Expand Down Expand Up @@ -3537,13 +3582,19 @@ func (a *ServerWithRoles) UpsertGithubConnector(ctx context.Context, connector t
if err := a.authConnectorAction(apidefaults.Namespace, types.KindGithub, types.VerbCreate); err != nil {
return nil, trace.Wrap(err)
}

if err := a.authConnectorAction(apidefaults.Namespace, types.KindGithub, types.VerbUpdate); err != nil {
return nil, trace.Wrap(err)
}

if err := a.checkGithubConnector(connector); err != nil {
return nil, trace.Wrap(err)
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return nil, trace.Wrap(err)
}

upserted, err := a.authServer.upsertGithubConnector(ctx, connector)
return upserted, trace.Wrap(err)
}
Expand All @@ -3553,9 +3604,15 @@ func (a *ServerWithRoles) CreateGithubConnector(ctx context.Context, connector t
if err := a.authConnectorAction(apidefaults.Namespace, types.KindGithub, types.VerbCreate); err != nil {
return nil, trace.Wrap(err)
}

if err := a.checkGithubConnector(connector); err != nil {
return nil, trace.Wrap(err)
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return nil, trace.Wrap(err)
}

created, err := a.authServer.createGithubConnector(ctx, connector)
return created, trace.Wrap(err)
}
Expand All @@ -3565,9 +3622,15 @@ func (a *ServerWithRoles) UpdateGithubConnector(ctx context.Context, connector t
if err := a.authConnectorAction(apidefaults.Namespace, types.KindGithub, types.VerbUpdate); err != nil {
return nil, trace.Wrap(err)
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return nil, trace.Wrap(err)
}

if err := a.checkGithubConnector(connector); err != nil {
return nil, trace.Wrap(err)
}

updated, err := a.authServer.updateGithubConnector(ctx, connector)
return updated, trace.Wrap(err)
}
Expand Down Expand Up @@ -3604,6 +3667,11 @@ func (a *ServerWithRoles) DeleteGithubConnector(ctx context.Context, connectorID
if err := a.authConnectorAction(apidefaults.Namespace, types.KindGithub, types.VerbDelete); err != nil {
return trace.Wrap(err)
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return trace.Wrap(err)
}

return a.authServer.deleteGithubConnector(ctx, connectorID)
}

Expand All @@ -3612,6 +3680,10 @@ func (a *ServerWithRoles) CreateGithubAuthRequest(ctx context.Context, req types
return nil, trace.Wrap(err)
}

if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil {
return nil, trace.Wrap(err)
}

// require additional permissions for executing SSO test flow.
if req.SSOTestFlow {
if err := a.authConnectorAction(apidefaults.Namespace, types.KindGithub, types.VerbCreate); err != nil {
Expand Down
154 changes: 154 additions & 0 deletions tool/tctl/common/admin_action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
wantypes "github.com/gravitational/teleport/lib/auth/webauthntypes"
libclient "github.com/gravitational/teleport/lib/client"
libmfa "github.com/gravitational/teleport/lib/client/mfa"
"github.com/gravitational/teleport/lib/modules"
"github.com/gravitational/teleport/lib/service/servicecfg"
"github.com/gravitational/teleport/lib/utils"
tctl "github.com/gravitational/teleport/tool/tctl/common"
Expand All @@ -57,6 +58,9 @@ func TestAdminActionMFA(t *testing.T) {
t.Run("Bots", s.testBots)
t.Run("Roles", s.testRoles)
t.Run("UserGroups", s.testUserGroups)
t.Run("OIDCConnector", s.testOIDCConnector)
t.Run("SAMLConnector", s.testSAMLConnector)
t.Run("GithubConnector", s.testGithubConnector)
}

func (s *adminActionTestSuite) testUsers(t *testing.T) {
Expand Down Expand Up @@ -206,6 +210,149 @@ func (s *adminActionTestSuite) testUserGroups(t *testing.T) {
})
}

func (s *adminActionTestSuite) testOIDCConnector(t *testing.T) {
ctx := context.Background()

connector, err := types.NewOIDCConnector("oidc", types.OIDCConnectorSpecV3{
ClientID: "12345",
ClientSecret: "678910",
RedirectURLs: []string{"https://proxy.example.com/v1/webapi/oidc/callback"},
Display: "OIDC",
ClaimsToRoles: []types.ClaimMapping{
{
Claim: "test",
Value: "test",
Roles: []string{"access", "editor", "auditor"},
},
},
})
require.NoError(t, err)

createOIDCConnector := func() error {
_, err := s.authServer.CreateOIDCConnector(ctx, connector)
return trace.Wrap(err)
}

getOIDCConnector := func() (types.Resource, error) {
return s.authServer.GetOIDCConnector(ctx, connector.GetName(), true)
}

deleteOIDCConnector := func() error {
return s.authServer.DeleteOIDCConnector(ctx, connector.GetName())
}

t.Run("ResourceCommands", func(t *testing.T) {
s.testResourceCommand(t, ctx, resourceCommandTestCase{
resource: connector,
resourceCreate: createOIDCConnector,
resourceDelete: deleteOIDCConnector,
})
})

t.Run("EditCommand", func(t *testing.T) {
s.testEditCommand(t, ctx, editCommandTestCase{
resourceRef: getResourceRef(connector),
resourceCreate: createOIDCConnector,
resourceGet: getOIDCConnector,
resourceDelete: deleteOIDCConnector,
})
})
}

func (s *adminActionTestSuite) testSAMLConnector(t *testing.T) {
ctx := context.Background()

connector, err := types.NewSAMLConnector("saml", types.SAMLConnectorSpecV2{
AssertionConsumerService: "http://localhost:65535/acs", // not called
Issuer: "test",
SSO: "https://localhost:65535/sso", // not called
AttributesToRoles: []types.AttributeMapping{
// not used. can be any name, value but role must exist
{Name: "groups", Value: "admin", Roles: []string{"access"}},
},
})
require.NoError(t, err)

createSAMLConnector := func() error {
_, err := s.authServer.CreateSAMLConnector(ctx, connector)
return trace.Wrap(err)
}

getSAMLConnector := func() (types.Resource, error) {
return s.authServer.GetSAMLConnector(ctx, connector.GetName(), true)
}

deleteSAMLConnector := func() error {
return s.authServer.DeleteSAMLConnector(ctx, connector.GetName())
}

t.Run("ResourceCommands", func(t *testing.T) {
s.testResourceCommand(t, ctx, resourceCommandTestCase{
resource: connector,
resourceCreate: createSAMLConnector,
resourceDelete: deleteSAMLConnector,
})
})

t.Run("EditCommand", func(t *testing.T) {
s.testEditCommand(t, ctx, editCommandTestCase{
resourceRef: getResourceRef(connector),
resourceCreate: createSAMLConnector,
resourceGet: getSAMLConnector,
resourceDelete: deleteSAMLConnector,
})
})
}

func (s *adminActionTestSuite) testGithubConnector(t *testing.T) {
ctx := context.Background()

connector, err := types.NewGithubConnector("github", types.GithubConnectorSpecV3{
ClientID: "12345",
ClientSecret: "678910",
RedirectURL: "https://proxy.example.com/v1/webapi/github/callback",
Display: "Github",
TeamsToRoles: []types.TeamRolesMapping{
{
Organization: "acme",
Team: "users",
Roles: []string{"access", "editor", "auditor"},
},
},
})
require.NoError(t, err)

createGithubConnector := func() error {
_, err := s.authServer.CreateGithubConnector(ctx, connector)
return trace.Wrap(err)
}

getGithubConnector := func() (types.Resource, error) {
return s.authServer.GetGithubConnector(ctx, connector.GetName(), true)
}

deleteGithubConnector := func() error {
return s.authServer.DeleteGithubConnector(ctx, connector.GetName())
}

t.Run("ResourceCommands", func(t *testing.T) {
s.testResourceCommand(t, ctx, resourceCommandTestCase{
resource: connector,
resourceCreate: createGithubConnector,
resourceDelete: deleteGithubConnector,
})
})

t.Run("EditCommand", func(t *testing.T) {
s.testEditCommand(t, ctx, editCommandTestCase{
resourceRef: getResourceRef(connector),
resourceCreate: createGithubConnector,
resourceGet: getGithubConnector,
resourceDelete: deleteGithubConnector,
})
})
}

type resourceCommandTestCase struct {
resource types.Resource
resourceCreate func() error
Expand Down Expand Up @@ -289,6 +436,13 @@ type adminActionTestSuite struct {
func newAdminActionTestSuite(t *testing.T) *adminActionTestSuite {
t.Helper()
ctx := context.Background()
modules.SetTestModules(t, &modules.TestModules{
TestBuildType: modules.BuildEnterprise,
TestFeatures: modules.Features{
OIDC: true,
SAML: true,
},
})

authPref, err := types.NewAuthPreference(types.AuthPreferenceSpecV2{
Type: constants.Local,
Expand Down