diff --git a/lib/auth/machineid/machineidv1/spiffe_federation_service.go b/lib/auth/machineid/machineidv1/spiffe_federation_service.go index a58f3b7350dc2..fe0b1ada122f9 100644 --- a/lib/auth/machineid/machineidv1/spiffe_federation_service.go +++ b/lib/auth/machineid/machineidv1/spiffe_federation_service.go @@ -56,7 +56,7 @@ func NewSPIFFEFederationService( } if cfg.Logger == nil { - cfg.Logger = slog.With(teleport.ComponentKey, "bot_instance.service") + cfg.Logger = slog.With(teleport.ComponentKey, "spiffe_federation.service") } if cfg.Clock == nil { cfg.Clock = clockwork.NewRealClock() @@ -150,6 +150,9 @@ func (s *SPIFFEFederationService) DeleteSPIFFEFederation( if err := authCtx.CheckAccessToKind(types.KindSPIFFEFederation, types.VerbDelete); err != nil { return nil, trace.Wrap(err) } + if err := authCtx.AuthorizeAdminAction(); err != nil { + return nil, trace.Wrap(err) + } if req.Name == "" { return nil, trace.BadParameter("name: must be non-empty") @@ -174,6 +177,9 @@ func (s *SPIFFEFederationService) CreateSPIFFEFederation( if err := authCtx.CheckAccessToKind(types.KindSPIFFEFederation, types.VerbCreate); err != nil { return nil, trace.Wrap(err) } + if err := authCtx.AuthorizeAdminAction(); err != nil { + return nil, trace.Wrap(err) + } created, err := s.backend.CreateSPIFFEFederation(ctx, req.SpiffeFederation) if err != nil { diff --git a/lib/services/local/spiffe_federation.go b/lib/services/local/spiffe_federation.go new file mode 100644 index 0000000000000..877c56a138f91 --- /dev/null +++ b/lib/services/local/spiffe_federation.go @@ -0,0 +1,92 @@ +// Teleport +// Copyright (C) 2024 Gravitational, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package local + +import ( + "context" + + "github.com/gravitational/trace" + + machineidv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/backend" + "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/local/generic" +) + +const ( + spiffeFederationPrefix = "spiffe_federation" +) + +// SPIFFEFederationService exposes backend functionality for storing +// SPIFFEFederation +type SPIFFEFederationService struct { + service *generic.ServiceWrapper[*machineidv1.SPIFFEFederation] +} + +// NewSPIFFEFederationService creates a new SPIFFEFederationService. +func NewSPIFFEFederationService( + backend backend.Backend, +) (*SPIFFEFederationService, error) { + service, err := generic.NewServiceWrapper(backend, + types.KindSPIFFEFederation, + spiffeFederationPrefix, + services.MarshalSPIFFEFederation, + services.UnmarshalSPIFFEFederation, + ) + if err != nil { + return nil, trace.Wrap(err) + } + return &SPIFFEFederationService{ + service: service, + }, nil +} + +// CreateSPIFFEFederation inserts a new SPIFFEFederation into the backend. +func (b *SPIFFEFederationService) CreateSPIFFEFederation( + ctx context.Context, federation *machineidv1.SPIFFEFederation, +) (*machineidv1.SPIFFEFederation, error) { + if err := services.ValidateSPIFFEFederation(federation); err != nil { + return nil, trace.Wrap(err) + } + created, err := b.service.CreateResource(ctx, federation) + return created, trace.Wrap(err) +} + +// GetSPIFFEFederation retrieves a specific SPIFFEFederation given a name +func (b *SPIFFEFederationService) GetSPIFFEFederation( + ctx context.Context, name string, +) (*machineidv1.SPIFFEFederation, error) { + federation, err := b.service.GetResource(ctx, name) + return federation, trace.Wrap(err) +} + +// ListSPIFFEFederations lists all SPIFFEFederations using a given page size +// and last key. +func (b *SPIFFEFederationService) ListSPIFFEFederations( + ctx context.Context, pageSize int, currentToken string, +) ([]*machineidv1.SPIFFEFederation, string, error) { + r, nextToken, err := b.service.ListResources(ctx, pageSize, currentToken) + return r, nextToken, trace.Wrap(err) +} + +// DeleteSPIFFEFederation deletes a specific SPIFFEFederation. +func (b *SPIFFEFederationService) DeleteSPIFFEFederation( + ctx context.Context, name string, +) error { + return trace.Wrap(b.service.DeleteResource(ctx, name)) +} diff --git a/lib/services/spiffe_federation.go b/lib/services/spiffe_federation.go index cb61d5de94789..d7f6275ffc2f3 100644 --- a/lib/services/spiffe_federation.go +++ b/lib/services/spiffe_federation.go @@ -36,3 +36,17 @@ type SPIFFEFederation interface { // DeleteBotInstance DeleteSPIFFEFederation(ctx context.Context, name string) error } + +// MarshalSPIFFEFederation marshals the SPIFFEFederation object into a JSON byte array. +func MarshalSPIFFEFederation(object *machineidv1.SPIFFEFederation, opts ...MarshalOption) ([]byte, error) { + return MarshalProtoResource(object, opts...) +} + +// UnmarshalSPIFFEFederation unmarshals the CrownJewel object from a JSON byte array. +func UnmarshalSPIFFEFederation(data []byte, opts ...MarshalOption) (*machineidv1.SPIFFEFederation, error) { + return UnmarshalProtoResource[*machineidv1.SPIFFEFederation](data, opts...) +} + +func ValidateSPIFFEFederation(object *machineidv1.SPIFFEFederation) error { + +}