Skip to content
Closed
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
13 changes: 9 additions & 4 deletions api/client/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1"
machineidv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1"
notificationsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/notifications/v1"
userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v1"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/types/accesslist"
accesslistv1conv "github.com/gravitational/teleport/api/types/accesslist/convert/v1"
Expand All @@ -35,6 +34,8 @@ import (
secreprotsv1conv "github.com/gravitational/teleport/api/types/secreports/convert/v1"
"github.com/gravitational/teleport/api/types/userloginstate"
userloginstatev1conv "github.com/gravitational/teleport/api/types/userloginstate/convert/v1"
"github.com/gravitational/teleport/api/types/userprovisioning"
userprovisioningv1conv "github.com/gravitational/teleport/api/types/userprovisioning/convert/v1"
)

// EventToGRPC converts types.Event to proto.Event.
Expand Down Expand Up @@ -95,9 +96,9 @@ func EventToGRPC(in types.Event) (*proto.Event, error) {
out.Resource = &proto.Event_SPIFFEFederation{
SPIFFEFederation: r,
}
case *userprovisioningpb.StaticHostUser:
case *userprovisioning.StaticHostUser:
out.Resource = &proto.Event_StaticHostUser{
StaticHostUser: r,
StaticHostUser: userprovisioningv1conv.ToProto(r),
}
default:
return nil, trace.BadParameter("resource type %T is not supported", r)
Expand Down Expand Up @@ -540,7 +541,11 @@ func EventFromGRPC(in *proto.Event) (*types.Event, error) {
out.Resource = types.Resource153ToLegacy(r)
return &out, nil
} else if r := in.GetStaticHostUser(); r != nil {
out.Resource = types.Resource153ToLegacy(r)
hostUser, err := userprovisioningv1conv.FromProto(r)
if err != nil {
return nil, trace.Wrap(err)
}
out.Resource = types.Resource153ToLegacy(hostUser)
return &out, nil
} else {
return nil, trace.BadParameter("received unsupported resource %T", in.Resource)
Expand Down
52 changes: 39 additions & 13 deletions api/client/statichostuser/statichostuser.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"github.com/gravitational/trace"

userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v1"
"github.com/gravitational/teleport/api/types/userprovisioning"
convertv1 "github.com/gravitational/teleport/api/types/userprovisioning/convert/v1"
)

// Client is a StaticHostUser client.
Expand All @@ -35,50 +37,74 @@ func NewClient(grpcClient userprovisioningpb.StaticHostUsersServiceClient) *Clie
}

// ListStaticHostUsers lists static host users.
func (c *Client) ListStaticHostUsers(ctx context.Context, pageSize int, pageToken string) ([]*userprovisioningpb.StaticHostUser, string, error) {
func (c *Client) ListStaticHostUsers(ctx context.Context, pageSize int, pageToken string) ([]*userprovisioning.StaticHostUser, string, error) {
resp, err := c.grpcClient.ListStaticHostUsers(ctx, &userprovisioningpb.ListStaticHostUsersRequest{
PageSize: int32(pageSize),
PageToken: pageToken,
})
if err != nil {
return nil, "", trace.Wrap(err)
}
return resp.Users, resp.NextPageToken, nil
hostUsers := make([]*userprovisioning.StaticHostUser, 0, len(resp.Users))
for _, hostUserProto := range resp.Users {
hostUser, err := convertv1.FromProto(hostUserProto)
if err != nil {
return nil, "", trace.Wrap(err)
}
hostUsers = append(hostUsers, hostUser)
}
return hostUsers, resp.NextPageToken, nil
}

// GetStaticHostUser returns a static host user by name.
func (c *Client) GetStaticHostUser(ctx context.Context, name string) (*userprovisioningpb.StaticHostUser, error) {
func (c *Client) GetStaticHostUser(ctx context.Context, name string) (*userprovisioning.StaticHostUser, error) {
if name == "" {
return nil, trace.BadParameter("missing name")
}
out, err := c.grpcClient.GetStaticHostUser(ctx, &userprovisioningpb.GetStaticHostUserRequest{
Name: name,
})
return out, trace.Wrap(err)
if err != nil {
return nil, trace.Wrap(err)
}
hostUser, err := convertv1.FromProto(out)
return hostUser, trace.Wrap(err)
}

// CreateStaticHostUser creates a static host user.
func (c *Client) CreateStaticHostUser(ctx context.Context, in *userprovisioningpb.StaticHostUser) (*userprovisioningpb.StaticHostUser, error) {
func (c *Client) CreateStaticHostUser(ctx context.Context, in *userprovisioning.StaticHostUser) (*userprovisioning.StaticHostUser, error) {
out, err := c.grpcClient.CreateStaticHostUser(ctx, &userprovisioningpb.CreateStaticHostUserRequest{
User: in,
User: convertv1.ToProto(in),
})
return out, trace.Wrap(err)
if err != nil {
return nil, trace.Wrap(err)
}
hostUser, err := convertv1.FromProto(out)
return hostUser, trace.Wrap(err)
}

// UpdateStaticHostUser updates a static host user.
func (c *Client) UpdateStaticHostUser(ctx context.Context, in *userprovisioningpb.StaticHostUser) (*userprovisioningpb.StaticHostUser, error) {
func (c *Client) UpdateStaticHostUser(ctx context.Context, in *userprovisioning.StaticHostUser) (*userprovisioning.StaticHostUser, error) {
out, err := c.grpcClient.UpdateStaticHostUser(ctx, &userprovisioningpb.UpdateStaticHostUserRequest{
User: in,
User: convertv1.ToProto(in),
})
return out, trace.Wrap(err)
if err != nil {
return nil, trace.Wrap(err)
}
hostUser, err := convertv1.FromProto(out)
return hostUser, trace.Wrap(err)
}

// UpsertStaticHostUser upserts a static host user.
func (c *Client) UpsertStaticHostUser(ctx context.Context, in *userprovisioningpb.StaticHostUser) (*userprovisioningpb.StaticHostUser, error) {
func (c *Client) UpsertStaticHostUser(ctx context.Context, in *userprovisioning.StaticHostUser) (*userprovisioning.StaticHostUser, error) {
out, err := c.grpcClient.UpsertStaticHostUser(ctx, &userprovisioningpb.UpsertStaticHostUserRequest{
User: in,
User: convertv1.ToProto(in),
})
return out, trace.Wrap(err)
if err != nil {
return nil, trace.Wrap(err)
}
hostUser, err := convertv1.FromProto(out)
return hostUser, trace.Wrap(err)
}

// DeleteStaticHostUser deletes a static host user. Note that this does not
Expand Down
74 changes: 74 additions & 0 deletions api/types/userprovisioning/convert/v1/statichostuser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2024 Gravitational, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package v1

import (
"github.com/gravitational/trace"

userprovisioningv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v1"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/types/userprovisioning"
)

// FromProto converts a v1 static host user into an internal static host user.
func FromProto(msg *userprovisioningv1.StaticHostUser) (*userprovisioning.StaticHostUser, error) {
if msg == nil {
return nil, trace.BadParameter("static host user message is missing")
}
if msg.Spec == nil {
return nil, trace.BadParameter("spec is missing")
}
if msg.Spec.Login == "" {
return nil, trace.BadParameter("login is missing")
}

labels := make(types.Labels)
if msgLabels := msg.Spec.NodeLabels; msgLabels != nil {
for k, v := range msgLabels.Values {
labels[k] = v.Values
}
}

u := userprovisioning.NewStaticHostUser(msg.GetMetadata(), userprovisioning.Spec{
Login: msg.Spec.Login,
Groups: msg.Spec.Groups,
Sudoers: msg.Spec.Sudoers,
Uid: msg.Spec.Uid,
Gid: msg.Spec.Gid,
NodeLabels: labels,
NodeLabelsExpression: msg.Spec.NodeLabelsExpression,
})
return u, nil
}

// ToProto converts an internal static host user into a v1 static host user.
func ToProto(hostUser *userprovisioning.StaticHostUser) *userprovisioningv1.StaticHostUser {
u := &userprovisioningv1.StaticHostUser{
Kind: hostUser.GetKind(),
SubKind: hostUser.GetSubKind(),
Version: hostUser.GetVersion(),
Metadata: hostUser.GetMetadata(),
Spec: &userprovisioningv1.StaticHostUserSpec{
Login: hostUser.Spec.Login,
Groups: hostUser.Spec.Groups,
Sudoers: hostUser.Spec.Sudoers,
Uid: hostUser.Spec.Uid,
Gid: hostUser.Spec.Gid,
NodeLabels: hostUser.Spec.NodeLabels.ToProto(),
NodeLabelsExpression: hostUser.Spec.NodeLabelsExpression,
},
}
return u
}
59 changes: 59 additions & 0 deletions api/types/userprovisioning/convert/v1/statichostuser_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2024 Gravitational, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package v1

import (
"testing"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/require"

headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/types/userprovisioning"
)

func TestRoundtrip(t *testing.T) {
t.Parallel()
hostUser := newStaticHostUser()
converted, err := FromProto(ToProto(hostUser))
require.NoError(t, err)
require.Empty(t, cmp.Diff(hostUser, converted,
cmpopts.IgnoreUnexported(headerv1.ResourceHeader{}, headerv1.Metadata{})))
}

func TestNoPanicOnNilSpec(t *testing.T) {
hostUser := ToProto(newStaticHostUser())
hostUser.Spec = nil
_, err := FromProto(hostUser)
require.Error(t, err)
}

func newStaticHostUser() *userprovisioning.StaticHostUser {
return userprovisioning.NewStaticHostUser(&headerv1.Metadata{
Name: "test-user",
}, userprovisioning.Spec{
Login: "alice",
Groups: []string{"foo", "bar"},
Sudoers: []string{"abcd1234"},
Uid: "1234",
Gid: "5678",
NodeLabels: types.Labels{
"foo": {"bar"},
},
NodeLabelsExpression: "labels['foo'] == labels['bar']",
})
}
41 changes: 34 additions & 7 deletions api/types/userprovisioning/statichostuser.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,44 @@ package userprovisioning

import (
headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1"
userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v1"
"github.com/gravitational/teleport/api/types"
)

// StaticHostUser is a resource that represents host users that should be
// created on matching nodes.
type StaticHostUser struct {
headerv1.ResourceHeader
// Spec is the static host user spec.
Spec Spec
}

// Spec is the static host user spec.
type Spec struct {
// Login is the login to create on the node.
Login string `json:"login"`
// Groups is a list of additional groups to add the user to.
Groups []string `json:"groups"`
// Sudoers is a list of sudoer entries to add.
Sudoers []string `json:"sudoers"`
// Uid is the new user's uid.
Uid string `json:"uid"`
// Gid is the new user's gid.
Gid string `json:"gid"`
// NodeLabels is a map of node labels that will create a user from this
// resource.
NodeLabels types.Labels `json:"node_labels"`
// NodeLabelsExpression is a predicate expression to create a user from
// this resource.
NodeLabelsExpression string `json:"node_labels_expression"`
}

// NewStaticHostUser creates a new host user to be applied to matching SSH nodes.
func NewStaticHostUser(name string, spec *userprovisioningpb.StaticHostUserSpec) *userprovisioningpb.StaticHostUser {
return &userprovisioningpb.StaticHostUser{
Kind: types.KindStaticHostUser,
Version: types.V1,
Metadata: &headerv1.Metadata{
Name: name,
func NewStaticHostUser(metadata *headerv1.Metadata, spec Spec) *StaticHostUser {
return &StaticHostUser{
ResourceHeader: headerv1.ResourceHeader{
Kind: types.KindStaticHostUser,
Version: types.V1,
Metadata: metadata,
},
Spec: spec,
}
Expand Down
6 changes: 3 additions & 3 deletions lib/auth/authclient/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ import (
integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1"
kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1"
machineidv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1"
userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v1"
userspb "github.com/gravitational/teleport/api/gen/proto/go/teleport/users/v1"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/types/accesslist"
"github.com/gravitational/teleport/api/types/discoveryconfig"
"github.com/gravitational/teleport/api/types/userprovisioning"
"github.com/gravitational/teleport/lib/events"
"github.com/gravitational/teleport/lib/services"
)
Expand Down Expand Up @@ -1186,9 +1186,9 @@ type Cache interface {
ListSPIFFEFederations(ctx context.Context, pageSize int, lastToken string) ([]*machineidv1.SPIFFEFederation, string, error)

// ListStaticHostUsers lists static host users.
ListStaticHostUsers(ctx context.Context, pageSize int, startKey string) ([]*userprovisioningpb.StaticHostUser, string, error)
ListStaticHostUsers(ctx context.Context, pageSize int, startKey string) ([]*userprovisioning.StaticHostUser, string, error)
// GetStaticHostUser returns a static host user by name.
GetStaticHostUser(ctx context.Context, name string) (*userprovisioningpb.StaticHostUser, error)
GetStaticHostUser(ctx context.Context, name string) (*userprovisioning.StaticHostUser, error)
}

type NodeWrapper struct {
Expand Down
Loading