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
82 changes: 82 additions & 0 deletions api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import (
"github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/api/defaults"
devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1"
integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1"
kubeproto "github.com/gravitational/teleport/api/gen/proto/go/teleport/kube/v1"
loginrulepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/loginrule/v1"
oktapb "github.com/gravitational/teleport/api/gen/proto/go/teleport/okta/v1"
Expand Down Expand Up @@ -3349,6 +3350,87 @@ func (c *Client) DeleteAllUserGroups(ctx context.Context) error {
return nil
}

// integrationsClient returns an unadorned Integration client, using the underlying
// Auth gRPC connection.
func (c *Client) integrationsClient() integrationpb.IntegrationServiceClient {
return integrationpb.NewIntegrationServiceClient(c.conn)
}

// ListIntegrations returns a paginated list of Integrations.
// The response includes a nextKey which must be used to fetch the next page.
func (c *Client) ListIntegrations(ctx context.Context, pageSize int, nextKey string) ([]types.Integration, string, error) {
resp, err := c.integrationsClient().ListIntegrations(ctx, &integrationpb.ListIntegrationsRequest{
Limit: int32(pageSize),
NextKey: nextKey,
})
if err != nil {
return nil, "", trail.FromGRPC(err)
}

integrations := make([]types.Integration, 0, len(resp.GetIntegrations()))
for _, ig := range resp.GetIntegrations() {
integrations = append(integrations, ig)
}

return integrations, resp.GetNextKey(), nil
}

// GetIntegration returns an Integration by its name.
func (c *Client) GetIntegration(ctx context.Context, name string) (types.Integration, error) {
ig, err := c.integrationsClient().GetIntegration(ctx, &integrationpb.GetIntegrationRequest{
Name: name,
})
if err != nil {
return nil, trail.FromGRPC(err)
}

return ig, nil
}

// CreateIntegration creates a new Integration.
func (c *Client) CreateIntegration(ctx context.Context, ig types.Integration) (types.Integration, error) {
igV1, ok := ig.(*types.IntegrationV1)
if !ok {
return nil, trace.BadParameter("unsupported integration type %T", ig)
}

ig, err := c.integrationsClient().CreateIntegration(ctx, &integrationpb.CreateIntegrationRequest{Integration: igV1})
if err != nil {
return nil, trail.FromGRPC(err)
}

return ig, nil
}

// UpdateIntegration updates an existing Integration.
func (c *Client) UpdateIntegration(ctx context.Context, ig types.Integration) (types.Integration, error) {
igV1, ok := ig.(*types.IntegrationV1)
if !ok {
return nil, trace.BadParameter("unsupported integration type %T", ig)
}

ig, err := c.integrationsClient().UpdateIntegration(ctx, &integrationpb.UpdateIntegrationRequest{Integration: igV1})
if err != nil {
return nil, trail.FromGRPC(err)
}

return ig, nil
}

// DeleteIntegration removes an Integration by its name.
func (c *Client) DeleteIntegration(ctx context.Context, name string) error {
_, err := c.integrationsClient().DeleteIntegration(ctx, &integrationpb.DeleteIntegrationRequest{
Name: name,
})
return trail.FromGRPC(err)
}

// DeleteAllIntegrations removes all Integrations.
func (c *Client) DeleteAllIntegrations(ctx context.Context) error {
_, err := c.integrationsClient().DeleteAllIntegrations(ctx, &integrationpb.DeleteAllIntegrationsRequest{})
return trail.FromGRPC(err)
}

// GetLoginRule retrieves a login rule described by name.
func (c *Client) GetLoginRule(ctx context.Context, name string) (*loginrulepb.LoginRule, error) {
rule, err := c.LoginRuleClient().GetLoginRule(ctx, &loginrulepb.GetLoginRuleRequest{
Expand Down
7 changes: 7 additions & 0 deletions api/client/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ func EventToGRPC(in types.Event) (*proto.Event, error) {
out.Resource = &proto.Event_OktaAssignment{
OktaAssignment: r,
}
case *types.IntegrationV1:
out.Resource = &proto.Event_Integration{
Integration: r,
}
default:
return nil, trace.BadParameter("resource type %T is not supported", in.Resource)
}
Expand Down Expand Up @@ -341,6 +345,9 @@ func EventFromGRPC(in proto.Event) (*types.Event, error) {
} else if r := in.GetOktaAssignment(); r != nil {
out.Resource = r
return &out, nil
} else if r := in.GetIntegration(); r != nil {
out.Resource = r
return &out, nil
} else {
return nil, trace.BadParameter("received unsupported resource %T", in.Resource)
}
Expand Down
4 changes: 4 additions & 0 deletions api/types/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,10 @@ const (
// VerbEnroll allows enrollment of trusted devices.
// Device Trust is a Teleport Enterprise feature.
VerbEnroll = "enroll"

// VerbUse allows the usage of an Integration.
// Roles with this verb can issue API calls using the integration.
VerbUse = "use"
)

const (
Expand Down
3 changes: 3 additions & 0 deletions lib/auth/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,9 @@ type Cache interface {
ListSAMLIdPServiceProviders(ctx context.Context, pageSize int, nextKey string) ([]types.SAMLIdPServiceProvider, string, error)
// GetSAMLIdPServiceProvider returns the specified SAML IdP service provider resources.
GetSAMLIdPServiceProvider(ctx context.Context, name string) (types.SAMLIdPServiceProvider, error)

// IntegrationsGetter defines read/list methods for integrations.
services.IntegrationsGetter
}

type NodeWrapper struct {
Expand Down
8 changes: 8 additions & 0 deletions lib/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,12 @@ func NewServer(cfg *InitConfig, opts ...ServerOption) (*Server, error) {
return nil, trace.Wrap(err)
}
}
if cfg.Integrations == nil {
cfg.Integrations, err = local.NewIntegrationsService(cfg.Backend)
if err != nil {
return nil, trace.Wrap(err)
}
}

limiter, err := limiter.NewConnectionsLimiter(limiter.Config{
MaxConnections: defaults.LimiterMaxConcurrentSignatures,
Expand Down Expand Up @@ -267,6 +273,7 @@ func NewServer(cfg *InitConfig, opts ...ServerOption) (*Server, error) {
UserGroups: cfg.UserGroups,
SessionTrackerService: cfg.SessionTrackerService,
ConnectionsDiagnostic: cfg.ConnectionsDiagnostic,
Integrations: cfg.Integrations,
StatusInternal: cfg.Status,
UsageReporter: cfg.UsageReporter,

Expand Down Expand Up @@ -361,6 +368,7 @@ type Services struct {
services.SessionTrackerService
services.ConnectionsDiagnostic
services.StatusInternal
services.Integrations
usagereporter.UsageReporter
types.Events
events.IAuditLog
Expand Down
116 changes: 116 additions & 0 deletions lib/auth/auth_with_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/gravitational/teleport/api/constants"
apidefaults "github.com/gravitational/teleport/api/defaults"
devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1"
integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1"
loginrulepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/loginrule/v1"
pluginspb "github.com/gravitational/teleport/api/gen/proto/go/teleport/plugins/v1"
samlidppb "github.com/gravitational/teleport/api/gen/proto/go/teleport/samlidp/v1"
Expand All @@ -45,6 +46,7 @@ import (
apievents "github.com/gravitational/teleport/api/types/events"
"github.com/gravitational/teleport/api/types/wrappers"
apiutils "github.com/gravitational/teleport/api/utils"
"github.com/gravitational/teleport/lib/auth/integration/integrationv1"
"github.com/gravitational/teleport/lib/authz"
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/defaults"
Expand Down Expand Up @@ -299,6 +301,120 @@ func (a *ServerWithRoles) SAMLIdPClient() samlidppb.SAMLIdPServiceClient {
panic("SAMLIdPClient not implemented by ServerWithRoles")
}

// integrationsService returns an Integrations Service.
func (a *ServerWithRoles) integrationsService() (*integrationv1.Service, error) {
igSvc, err := integrationv1.NewService(&integrationv1.ServiceConfig{
Authorizer: authz.AuthorizerFunc(func(context.Context) (*authz.Context, error) {
return &a.context, nil
}),
Cache: a.authServer.Cache,
Backend: a.authServer.Services,
})
if err != nil {
return nil, trace.Wrap(err)
}

return igSvc, nil
}

// CreateIntegration creates an Integration.
func (a *ServerWithRoles) CreateIntegration(ctx context.Context, ig types.Integration) (types.Integration, error) {
igSvc, err := a.integrationsService()
if err != nil {
return nil, trace.Wrap(err)
}

igv1, ok := ig.(*types.IntegrationV1)
if !ok {
return nil, trace.BadParameter("unexpected integration type %T", ig)
}

ig, err = igSvc.CreateIntegration(ctx, &integrationpb.CreateIntegrationRequest{Integration: igv1})
if err != nil {
return nil, trace.Wrap(err)
}
return ig, nil
}

// GetIntegration returns an Integration by its name.
func (a *ServerWithRoles) GetIntegration(ctx context.Context, name string) (types.Integration, error) {
igSvc, err := a.integrationsService()
if err != nil {
return nil, trace.Wrap(err)
}

ig, err := igSvc.GetIntegration(ctx, &integrationpb.GetIntegrationRequest{Name: name})
if err != nil {
return nil, trace.Wrap(err)
}
return ig, nil
}

// ListIntegrations returns a list of Integrations.
// A next page can be retreived by calling ListIntegrations again and passing the nextKey from the previous response.
func (a *ServerWithRoles) ListIntegrations(ctx context.Context, pageSize int, nextKey string) ([]types.Integration, string, error) {
igSvc, err := a.integrationsService()
if err != nil {
return nil, "", trace.Wrap(err)
}

resp, err := igSvc.ListIntegrations(ctx, &integrationpb.ListIntegrationsRequest{
Limit: int32(pageSize),
NextKey: nextKey,
})
if err != nil {
return nil, "", trace.Wrap(err)
}

integrations := make([]types.Integration, 0, len(resp.GetIntegrations()))
for _, ig := range resp.GetIntegrations() {
integrations = append(integrations, ig)
}

return integrations, resp.GetNextKey(), nil
}

// UpdateIntegration updates an Integration.
func (a *ServerWithRoles) UpdateIntegration(ctx context.Context, ig types.Integration) (types.Integration, error) {
igSvc, err := a.integrationsService()
if err != nil {
return nil, trace.Wrap(err)
}

igv1, ok := ig.(*types.IntegrationV1)
if !ok {
return nil, trace.BadParameter("unexpected integration type %T", ig)
}

ig, err = igSvc.UpdateIntegration(ctx, &integrationpb.UpdateIntegrationRequest{Integration: igv1})
if err != nil {
return nil, trace.Wrap(err)
}
return ig, nil
}

// DeleteAllIntegrations deletes all integrations.
func (a *ServerWithRoles) DeleteAllIntegrations(ctx context.Context) error {
igSvc, err := a.integrationsService()
if err != nil {
return trace.Wrap(err)
}

_, err = igSvc.DeleteAllIntegrations(ctx, &integrationpb.DeleteAllIntegrationsRequest{})
return trace.Wrap(err)
}

// DeleteIntegration deletes an integration integrations.
func (a *ServerWithRoles) DeleteIntegration(ctx context.Context, name string) error {
igSvc, err := a.integrationsService()
if err != nil {
return trace.Wrap(err)
}

_, err = igSvc.DeleteIntegration(ctx, &integrationpb.DeleteIntegrationRequest{Name: name})
return trace.Wrap(err)
}

// CreateSessionTracker creates a tracker resource for an active session.
func (a *ServerWithRoles) CreateSessionTracker(ctx context.Context, tracker types.SessionTracker) (types.SessionTracker, error) {
if err := a.serverAction(); err != nil {
Expand Down
1 change: 1 addition & 0 deletions lib/auth/clt.go
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ type ClientI interface {
services.SessionTrackerService
services.ConnectionsDiagnostic
services.SAMLIdPSession
services.Integrations
types.Events

types.WebSessionsGetter
Expand Down
12 changes: 12 additions & 0 deletions lib/auth/grpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ import (
"github.com/gravitational/teleport/api/client"
"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/constants"
integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1"
oktapb "github.com/gravitational/teleport/api/gen/proto/go/teleport/okta/v1"
"github.com/gravitational/teleport/api/metadata"
"github.com/gravitational/teleport/api/types"
apievents "github.com/gravitational/teleport/api/types/events"
"github.com/gravitational/teleport/api/types/installers"
"github.com/gravitational/teleport/api/types/wrappers"
integrationService "github.com/gravitational/teleport/lib/auth/integration/integrationv1"
"github.com/gravitational/teleport/lib/auth/okta"
wanlib "github.com/gravitational/teleport/lib/auth/webauthn"
"github.com/gravitational/teleport/lib/authz"
Expand Down Expand Up @@ -5038,6 +5040,16 @@ func NewGRPCServer(cfg GRPCServerConfig) (*GRPCServer, error) {
}
oktapb.RegisterOktaServiceServer(server, oktaServiceServer)

integrationServiceServer, err := integrationService.NewService(&integrationService.ServiceConfig{
Authorizer: cfg.Authorizer,
Backend: cfg.AuthServer.Services,
Cache: cfg.AuthServer.Cache,
})
if err != nil {
return nil, trace.Wrap(err)
}
integrationpb.RegisterIntegrationServiceServer(server, integrationServiceServer)

return authServer, nil
}

Expand Down
3 changes: 3 additions & 0 deletions lib/auth/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ type InitConfig struct {
// UserGroups is a service that manages user groups.
UserGroups services.UserGroups

// Integrations is a service that manages Integrations.
Integrations services.Integrations

// SessionTrackerService is a service that manages trackers for all active sessions.
SessionTrackerService services.SessionTrackerService

Expand Down
1 change: 1 addition & 0 deletions lib/authz/permissions.go
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,7 @@ func roleSpecForProxy(clusterName string) types.RoleSpecV6 {
types.NewRule(types.KindDatabaseService, services.RO()),
types.NewRule(types.KindSAMLIdPServiceProvider, services.RO()),
types.NewRule(types.KindUserGroup, services.RO()),
types.NewRule(types.KindIntegration, services.RO()),
// this rule allows local proxy to update the remote cluster's host certificate authorities
// during certificates renewal
{
Expand Down
Loading