Skip to content

Commit

Permalink
prevent saml service provider from deletion if referenced by ic plugin (
Browse files Browse the repository at this point in the history
  • Loading branch information
flyinghermit authored Nov 1, 2024
1 parent 18d6810 commit dd92a6a
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 3 deletions.
36 changes: 33 additions & 3 deletions lib/services/local/saml_idp_service_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ const (

// SAMLIdPServiceProviderService manages IdP service providers in the Backend.
type SAMLIdPServiceProviderService struct {
svc generic.Service[types.SAMLIdPServiceProvider]
svc generic.Service[types.SAMLIdPServiceProvider]
// backend is used to spawn Plugins storage service so that
// it can be queried from the SAML service.
backend backend.Backend
log logrus.FieldLogger
httpClient *http.Client
}
Expand Down Expand Up @@ -81,8 +84,9 @@ func NewSAMLIdPServiceProviderService(b backend.Backend, opts ...SAMLIdPOption)
}

samlSPService := &SAMLIdPServiceProviderService{
svc: *svc,
log: logrus.WithFields(logrus.Fields{teleport.ComponentKey: "saml-idp"}),
svc: *svc,
backend: b,
log: logrus.WithFields(logrus.Fields{teleport.ComponentKey: "saml-idp"}),
}

for _, opt := range opts {
Expand Down Expand Up @@ -198,6 +202,9 @@ func (s *SAMLIdPServiceProviderService) UpdateSAMLIdPServiceProvider(ctx context

// DeleteSAMLIdPServiceProvider removes the specified SAML IdP service provider resource.
func (s *SAMLIdPServiceProviderService) DeleteSAMLIdPServiceProvider(ctx context.Context, name string) error {
if err := spReferencedByAWSICPlugin(ctx, s.backend, name); err != nil {
return trace.Wrap(err)
}
return s.svc.DeleteResource(ctx, name)
}

Expand Down Expand Up @@ -397,3 +404,26 @@ func genTeleportSPSSODescriptor(attributeMapping []*types.SAMLAttributeMapping)
},
}
}

// spReferencedByAWSICPlugin returns a BadParameter error if the serviceProviderName
// is referenced in the AWS Identity Center plugin.
func spReferencedByAWSICPlugin(ctx context.Context, bk backend.Backend, serviceProviderName string) error {
pluginService := NewPluginsService(bk)
plugins, err := pluginService.GetPlugins(ctx, false /* withSecrets */)
if err != nil {
return trace.Wrap(err)
}

for _, p := range plugins {
pluginV1, ok := p.(*types.PluginV1)
if !ok {
continue
}

if pluginV1.Spec.GetAwsIc().SamlIdpServiceProviderName == serviceProviderName {
return trace.BadParameter("cannot delete SAML service provider currently referenced by AWS Identity Center integration %q", pluginV1.GetName())
}
}

return nil
}
58 changes: 58 additions & 0 deletions lib/services/local/saml_idp_service_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -589,3 +589,61 @@ func TestCreateSAMLIdPServiceProvider_GetTeleportSPSSODescriptor(t *testing.T) {
index, _ := GetTeleportSPSSODescriptor(ed.SPSSODescriptors)
require.Equal(t, 3, index)
}

func TestDeleteSAMLServiceProviderWhenReferencedByPlugin(t *testing.T) {
ctx := context.Background()
backend, err := memory.New(memory.Config{
Context: ctx,
Clock: clockwork.NewFakeClock(),
})
require.NoError(t, err)
samlService, err := NewSAMLIdPServiceProviderService(backend)
require.NoError(t, err)
pluginService := NewPluginsService(backend)

sp, err := types.NewSAMLIdPServiceProvider(
types.Metadata{
Name: "sp",
},
types.SAMLIdPServiceProviderSpecV1{
EntityDescriptor: newEntityDescriptor("sp"),
EntityID: "sp",
})
require.NoError(t, err)
require.NoError(t, samlService.CreateSAMLIdPServiceProvider(ctx, sp))

// service provider should not be deleted when referenced by the plugin.
require.NoError(t, pluginService.CreatePlugin(ctx, newPlugin(t, sp.GetName())))
err = samlService.DeleteSAMLIdPServiceProvider(ctx, sp.GetName())
require.ErrorContains(t, err, "referenced by AWS Identity Center integration")

// service provider should be deleted once the referenced plugin itself is deleted.
require.NoError(t, pluginService.DeletePlugin(ctx, types.PluginTypeAWSIdentityCenter))
require.NoError(t, samlService.DeleteSAMLIdPServiceProvider(ctx, sp.GetName()))
}

func newPlugin(t *testing.T, serviceProviderName string) *types.PluginV1 {
t.Helper()
return &types.PluginV1{
Metadata: types.Metadata{
Name: types.PluginTypeAWSIdentityCenter,
Labels: map[string]string{
types.HostedPluginLabel: "true",
},
},
Spec: types.PluginSpecV1{
Settings: &types.PluginSpecV1_AwsIc{
AwsIc: &types.PluginAWSICSettings{
IntegrationName: "test-integration",
Region: "test-region",
Arn: "test-arn",
AccessListDefaultOwners: []string{"user1", "user2"},
ProvisioningSpec: &types.AWSICProvisioningSpec{
BaseUrl: "https://example.com",
},
SamlIdpServiceProviderName: serviceProviderName,
},
},
},
}
}

0 comments on commit dd92a6a

Please sign in to comment.