diff --git a/api/gen/proto/go/accesslist/v1/accesslist.pb.go b/api/gen/proto/go/teleport/accesslist/v1/accesslist.pb.go similarity index 98% rename from api/gen/proto/go/accesslist/v1/accesslist.pb.go rename to api/gen/proto/go/teleport/accesslist/v1/accesslist.pb.go index f2e7926546e9d..729ce58e2c38f 100644 --- a/api/gen/proto/go/accesslist/v1/accesslist.pb.go +++ b/api/gen/proto/go/teleport/accesslist/v1/accesslist.pb.go @@ -18,11 +18,11 @@ // protoc (unknown) // source: teleport/accesslist/v1/accesslist.proto -package accesslist +package accesslistv1 import ( - v1 "github.com/gravitational/teleport/api/gen/proto/go/header/v1" - v11 "github.com/gravitational/teleport/api/gen/proto/go/trait/v1" + v1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + v11 "github.com/gravitational/teleport/api/gen/proto/go/teleport/trait/v1" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" durationpb "google.golang.org/protobuf/types/known/durationpb" @@ -602,12 +602,13 @@ var file_teleport_accesslist_v1_accesslist_proto_rawDesc = []byte{ 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x61, 0x64, 0x64, 0x65, 0x64, 0x42, 0x79, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74, + 0x52, 0x07, 0x61, 0x64, 0x64, 0x65, 0x64, 0x42, 0x79, 0x42, 0x58, 0x5a, 0x56, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, - 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, + 0x69, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, + 0x74, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/gen/proto/go/header/v1/metadata.pb.go b/api/gen/proto/go/teleport/header/v1/metadata.pb.go similarity index 96% rename from api/gen/proto/go/header/v1/metadata.pb.go rename to api/gen/proto/go/teleport/header/v1/metadata.pb.go index 3265dd7159571..4e3882daa0ce5 100644 --- a/api/gen/proto/go/header/v1/metadata.pb.go +++ b/api/gen/proto/go/teleport/header/v1/metadata.pb.go @@ -18,7 +18,7 @@ // protoc (unknown) // source: teleport/header/v1/metadata.proto -package header +package headerv1 import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" @@ -157,12 +157,13 @@ var file_teleport_header_v1_metadata_proto_rawDesc = []byte{ 0x64, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x45, 0x5a, 0x43, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x50, 0x5a, 0x4e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x67, 0x6f, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x68, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x76, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/gen/proto/go/header/v1/resourceheader.pb.go b/api/gen/proto/go/teleport/header/v1/resourceheader.pb.go similarity index 96% rename from api/gen/proto/go/header/v1/resourceheader.pb.go rename to api/gen/proto/go/teleport/header/v1/resourceheader.pb.go index ce6feafd97d33..53a48cb167e77 100644 --- a/api/gen/proto/go/header/v1/resourceheader.pb.go +++ b/api/gen/proto/go/teleport/header/v1/resourceheader.pb.go @@ -18,7 +18,7 @@ // protoc (unknown) // source: teleport/header/v1/resourceheader.proto -package header +package headerv1 import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" @@ -128,12 +128,12 @@ var file_teleport_header_v1_resourceheader_proto_rawDesc = []byte{ 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x45, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x50, 0x5a, 0x4e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, - 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x68, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x3b, + 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/gen/proto/go/trait/v1/trait.pb.go b/api/gen/proto/go/teleport/trait/v1/trait.pb.go similarity index 95% rename from api/gen/proto/go/trait/v1/trait.pb.go rename to api/gen/proto/go/teleport/trait/v1/trait.pb.go index ca7d56a07c7c2..69410ec94493c 100644 --- a/api/gen/proto/go/trait/v1/trait.pb.go +++ b/api/gen/proto/go/teleport/trait/v1/trait.pb.go @@ -18,7 +18,7 @@ // protoc (unknown) // source: teleport/trait/v1/trait.proto -package trait +package traitv1 import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" @@ -101,12 +101,12 @@ var file_teleport_trait_v1_trait_proto_rawDesc = []byte{ 0x76, 0x31, 0x22, 0x31, 0x0a, 0x05, 0x54, 0x72, 0x61, 0x69, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x43, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x4e, 0x5a, 0x4c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, - 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x69, - 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x74, 0x72, 0x61, 0x69, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x74, 0x72, 0x61, 0x69, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x74, 0x72, + 0x61, 0x69, 0x74, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/proto/teleport/accesslist/v1/accesslist.proto b/api/proto/teleport/accesslist/v1/accesslist.proto index 7745b35b30dc2..039f847755b5e 100644 --- a/api/proto/teleport/accesslist/v1/accesslist.proto +++ b/api/proto/teleport/accesslist/v1/accesslist.proto @@ -21,7 +21,7 @@ import "google/protobuf/timestamp.proto"; import "teleport/header/v1/resourceheader.proto"; import "teleport/trait/v1/trait.proto"; -option go_package = "github.com/gravitational/teleport/api/gen/proto/go/accesslist/v1;accesslist"; +option go_package = "github.com/gravitational/teleport/api/gen/proto/go/teleport/accesslist/v1;accesslistv1"; // AccessList describes the basic building block of access grants, which are // similar to access requests but for longer lived permissions that need to be diff --git a/api/proto/teleport/header/v1/metadata.proto b/api/proto/teleport/header/v1/metadata.proto index f430c942401f2..0811609a0e884 100644 --- a/api/proto/teleport/header/v1/metadata.proto +++ b/api/proto/teleport/header/v1/metadata.proto @@ -18,7 +18,7 @@ package teleport.header.v1; import "google/protobuf/timestamp.proto"; -option go_package = "github.com/gravitational/teleport/api/gen/proto/go/header/v1;header"; +option go_package = "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1;headerv1"; // Metadata is resource metadata. message Metadata { diff --git a/api/proto/teleport/header/v1/resourceheader.proto b/api/proto/teleport/header/v1/resourceheader.proto index 7c2de3551cc8c..654e1cd07ddba 100644 --- a/api/proto/teleport/header/v1/resourceheader.proto +++ b/api/proto/teleport/header/v1/resourceheader.proto @@ -18,7 +18,7 @@ package teleport.header.v1; import "teleport/header/v1/metadata.proto"; -option go_package = "github.com/gravitational/teleport/api/gen/proto/go/header/v1;header"; +option go_package = "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1;headerv1"; // ResourceHeader is a shared resource header. message ResourceHeader { diff --git a/api/proto/teleport/trait/v1/trait.proto b/api/proto/teleport/trait/v1/trait.proto index 0d6889d698b34..6597331cd1625 100644 --- a/api/proto/teleport/trait/v1/trait.proto +++ b/api/proto/teleport/trait/v1/trait.proto @@ -16,7 +16,7 @@ syntax = "proto3"; package teleport.trait.v1; -option go_package = "github.com/gravitational/teleport/api/gen/proto/go/trait/v1;trait"; +option go_package = "github.com/gravitational/teleport/api/gen/proto/go/teleport/trait/v1;traitv1"; // Trait is a trait that can be use in various resources. message Trait { diff --git a/api/types/resource.go b/api/types/resource.go index 63031b50a2872..906c87ae75a65 100644 --- a/api/types/resource.go +++ b/api/types/resource.go @@ -25,7 +25,6 @@ import ( "github.com/gravitational/teleport/api/defaults" "github.com/gravitational/teleport/api/types/common" - "github.com/gravitational/teleport/api/types/header" "github.com/gravitational/teleport/api/utils" ) @@ -368,17 +367,6 @@ func (h *ResourceHeader) CheckAndSetDefaults() error { return trace.Wrap(h.Metadata.CheckAndSetDefaults()) } -// FromHeaderMetadata will convert a *header.Metadata object to this metadata object. -// TODO: Remove this once we get rid of the old Metadata object. -func FromHeaderMetadata(metadata header.Metadata) Metadata { - return Metadata{ - ID: metadata.ID, - Name: metadata.Name, - Description: metadata.Description, - Labels: metadata.Labels, - } -} - // GetID returns resource ID func (m *Metadata) GetID() int64 { return m.ID diff --git a/lib/services/access_list.go b/lib/services/access_list.go index 4be77b032239d..fd70264edd810 100644 --- a/lib/services/access_list.go +++ b/lib/services/access_list.go @@ -21,16 +21,16 @@ import ( "github.com/gravitational/trace" - "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/types/accesslist" "github.com/gravitational/teleport/lib/utils" ) // AccessListsGetter defines an interface for reading access lists. type AccessListsGetter interface { // GetAccessLists returns a list of all access lists. - GetAccessLists(context.Context) ([]*types.AccessList, error) + GetAccessLists(context.Context) ([]*accesslist.AccessList, error) // GetAccessList returns the specified access list resource. - GetAccessList(context.Context, string) (*types.AccessList, error) + GetAccessList(context.Context, string) (*accesslist.AccessList, error) } // AccessLists defines an interface for managing AccessLists. @@ -38,7 +38,7 @@ type AccessLists interface { AccessListsGetter // UpsertAccessList creates or updates an access list resource. - UpsertAccessList(context.Context, *types.AccessList) error + UpsertAccessList(context.Context, *accesslist.AccessList) error // DeleteAccessList removes the specified access list resource. DeleteAccessList(context.Context, string) error // DeleteAllAccessLists removes all access lists. @@ -46,7 +46,7 @@ type AccessLists interface { } // MarshalAccessList marshals the access list resource to JSON. -func MarshalAccessList(accessList *types.AccessList, opts ...MarshalOption) ([]byte, error) { +func MarshalAccessList(accessList *accesslist.AccessList, opts ...MarshalOption) ([]byte, error) { if err := accessList.CheckAndSetDefaults(); err != nil { return nil, trace.Wrap(err) } @@ -65,7 +65,7 @@ func MarshalAccessList(accessList *types.AccessList, opts ...MarshalOption) ([]b } // UnmarshalAccessList unmarshals the access list resource from JSON. -func UnmarshalAccessList(data []byte, opts ...MarshalOption) (*types.AccessList, error) { +func UnmarshalAccessList(data []byte, opts ...MarshalOption) (*accesslist.AccessList, error) { if len(data) == 0 { return nil, trace.BadParameter("missing access list data") } @@ -73,7 +73,7 @@ func UnmarshalAccessList(data []byte, opts ...MarshalOption) (*types.AccessList, if err != nil { return nil, trace.Wrap(err) } - var accessList *types.AccessList + var accessList *accesslist.AccessList if err := utils.FastUnmarshal(data, &accessList); err != nil { return nil, trace.BadParameter(err.Error()) } diff --git a/lib/services/access_list_test.go b/lib/services/access_list_test.go index 3c9f179cad378..c99998e16bd47 100644 --- a/lib/services/access_list_test.go +++ b/lib/services/access_list_test.go @@ -22,20 +22,20 @@ import ( "github.com/stretchr/testify/require" - "github.com/gravitational/teleport/api/types" - "github.com/gravitational/teleport/api/types/header" + "github.com/gravitational/teleport/lib/types/accesslist" + "github.com/gravitational/teleport/lib/types/header" "github.com/gravitational/teleport/lib/utils" ) // TestAccessListUnmarshal verifies an access list resource can be unmarshaled. func TestAccessListUnmarshal(t *testing.T) { - expected, err := types.NewAccessList( + expected, err := accesslist.NewAccessList( header.Metadata{ Name: "test-access-list", }, - types.AccessListSpec{ + accesslist.Spec{ Description: "test access list", - Owners: []types.AccessListOwner{ + Owners: []accesslist.Owner{ { Name: "test-user1", Description: "test user 1", @@ -45,31 +45,31 @@ func TestAccessListUnmarshal(t *testing.T) { Description: "test user 2", }, }, - Audit: types.AccessListAudit{ + Audit: accesslist.Audit{ Frequency: time.Hour, }, - MembershipRequires: types.AccessListRequires{ + MembershipRequires: accesslist.Requires{ Roles: []string{"mrole1", "mrole2"}, Traits: map[string][]string{ "mtrait1": {"mvalue1", "mvalue2"}, "mtrait2": {"mvalue3", "mvalue4"}, }, }, - OwnershipRequires: types.AccessListRequires{ + OwnershipRequires: accesslist.Requires{ Roles: []string{"orole1", "orole2"}, Traits: map[string][]string{ "otrait1": {"ovalue1", "ovalue2"}, "otrait2": {"ovalue3", "ovalue4"}, }, }, - Grants: types.AccessListGrants{ + Grants: accesslist.Grants{ Roles: []string{"grole1", "grole2"}, Traits: map[string][]string{ "gtrait1": {"gvalue1", "gvalue2"}, "gtrait2": {"gvalue3", "gvalue4"}, }, }, - Members: []types.AccessListMember{ + Members: []accesslist.Member{ { Name: "member1", Joined: time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC), @@ -97,13 +97,13 @@ func TestAccessListUnmarshal(t *testing.T) { // TestAccessListMarshal verifies a marshaled access list resource can be unmarshaled back. func TestAccessListMarshal(t *testing.T) { - expected, err := types.NewAccessList( + expected, err := accesslist.NewAccessList( header.Metadata{ Name: "test-rule", }, - types.AccessListSpec{ + accesslist.Spec{ Description: "test access list", - Owners: []types.AccessListOwner{ + Owners: []accesslist.Owner{ { Name: "test-user1", Description: "test user 1", @@ -113,31 +113,31 @@ func TestAccessListMarshal(t *testing.T) { Description: "test user 2", }, }, - Audit: types.AccessListAudit{ + Audit: accesslist.Audit{ Frequency: time.Hour, }, - MembershipRequires: types.AccessListRequires{ + MembershipRequires: accesslist.Requires{ Roles: []string{"mrole1", "mrole2"}, Traits: map[string][]string{ "mtrait1": {"mvalue1", "mvalue2"}, "mtrait2": {"mvalue3", "mvalue4"}, }, }, - OwnershipRequires: types.AccessListRequires{ + OwnershipRequires: accesslist.Requires{ Roles: []string{"orole1", "orole2"}, Traits: map[string][]string{ "otrait1": {"ovalue1", "ovalue2"}, "otrait2": {"ovalue3", "ovalue4"}, }, }, - Grants: types.AccessListGrants{ + Grants: accesslist.Grants{ Roles: []string{"grole1", "grole2"}, Traits: map[string][]string{ "gtrait1": {"gvalue1", "gvalue2"}, "gtrait2": {"gvalue3", "gvalue4"}, }, }, - Members: []types.AccessListMember{ + Members: []accesslist.Member{ { Name: "member1", Joined: time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC), diff --git a/lib/services/local/access_list.go b/lib/services/local/access_list.go index f23a020ce51d1..d24ba8b2a9ec8 100644 --- a/lib/services/local/access_list.go +++ b/lib/services/local/access_list.go @@ -27,6 +27,7 @@ import ( "github.com/gravitational/teleport/lib/backend" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/services/local/generic" + "github.com/gravitational/teleport/lib/types/accesslist" ) const ( @@ -37,12 +38,12 @@ const ( type AccessListService struct { log logrus.FieldLogger clock clockwork.Clock - svc *generic.Service[*types.AccessList] + svc *generic.Service[*accesslist.AccessList] } // NewAccessListService creates a new AccessListService. func NewAccessListService(backend backend.Backend, clock clockwork.Clock) (*AccessListService, error) { - svc, err := generic.NewService(&generic.ServiceConfig[*types.AccessList]{ + svc, err := generic.NewService(&generic.ServiceConfig[*accesslist.AccessList]{ Backend: backend, ResourceKind: types.KindAccessList, BackendPrefix: accessListPrefix, @@ -61,19 +62,19 @@ func NewAccessListService(backend backend.Backend, clock clockwork.Clock) (*Acce } // GetAccessLists returns a list of all access lists. -func (a *AccessListService) GetAccessLists(ctx context.Context) ([]*types.AccessList, error) { +func (a *AccessListService) GetAccessLists(ctx context.Context) ([]*accesslist.AccessList, error) { accessLists, err := a.svc.GetResources(ctx) return accessLists, trace.Wrap(err) } // GetAccessList returns the specified access list resource. -func (a *AccessListService) GetAccessList(ctx context.Context, name string) (*types.AccessList, error) { +func (a *AccessListService) GetAccessList(ctx context.Context, name string) (*accesslist.AccessList, error) { accessList, err := a.svc.GetResource(ctx, name) return accessList, trace.Wrap(err) } // UpsertAccessList creates or updates an access list resource. -func (a *AccessListService) UpsertAccessList(ctx context.Context, accessList *types.AccessList) error { +func (a *AccessListService) UpsertAccessList(ctx context.Context, accessList *accesslist.AccessList) error { return trace.Wrap(a.svc.UpsertResource(ctx, accessList)) } diff --git a/lib/services/local/access_list_test.go b/lib/services/local/access_list_test.go index 329e6173920c5..cd723e4f6d703 100644 --- a/lib/services/local/access_list_test.go +++ b/lib/services/local/access_list_test.go @@ -27,9 +27,9 @@ import ( "github.com/jonboulle/clockwork" "github.com/stretchr/testify/require" - "github.com/gravitational/teleport/api/types" - "github.com/gravitational/teleport/api/types/header" "github.com/gravitational/teleport/lib/backend/memory" + "github.com/gravitational/teleport/lib/types/accesslist" + "github.com/gravitational/teleport/lib/types/header" ) // TestAccessListCRUD tests backend operations with access list resources. @@ -64,7 +64,7 @@ func TestAccessListCRUD(t *testing.T) { // Fetch all access lists. out, err = service.GetAccessLists(ctx) require.NoError(t, err) - require.Empty(t, cmp.Diff([]*types.AccessList{accessList1, accessList2}, out, + require.Empty(t, cmp.Diff([]*accesslist.AccessList{accessList1, accessList2}, out, cmpopts.IgnoreFields(header.Metadata{}, "ID"), )) @@ -94,7 +94,7 @@ func TestAccessListCRUD(t *testing.T) { require.NoError(t, err) out, err = service.GetAccessLists(ctx) require.NoError(t, err) - require.Empty(t, cmp.Diff([]*types.AccessList{accessList2}, out, + require.Empty(t, cmp.Diff([]*accesslist.AccessList{accessList2}, out, cmpopts.IgnoreFields(header.Metadata{}, "ID"), )) @@ -110,16 +110,16 @@ func TestAccessListCRUD(t *testing.T) { require.Empty(t, out) } -func newAccessList(t *testing.T, name string) *types.AccessList { +func newAccessList(t *testing.T, name string) *accesslist.AccessList { t.Helper() - accessList, err := types.NewAccessList( + accessList, err := accesslist.NewAccessList( header.Metadata{ Name: name, }, - types.AccessListSpec{ + accesslist.Spec{ Description: "test access list", - Owners: []types.AccessListOwner{ + Owners: []accesslist.Owner{ { Name: "test-user1", Description: "test user 1", @@ -129,31 +129,31 @@ func newAccessList(t *testing.T, name string) *types.AccessList { Description: "test user 2", }, }, - Audit: types.AccessListAudit{ + Audit: accesslist.Audit{ Frequency: time.Hour, }, - MembershipRequires: types.AccessListRequires{ + MembershipRequires: accesslist.Requires{ Roles: []string{"mrole1", "mrole2"}, Traits: map[string][]string{ "mtrait1": {"mvalue1", "mvalue2"}, "mtrait2": {"mvalue3", "mvalue4"}, }, }, - OwnershipRequires: types.AccessListRequires{ + OwnershipRequires: accesslist.Requires{ Roles: []string{"orole1", "orole2"}, Traits: map[string][]string{ "otrait1": {"ovalue1", "ovalue2"}, "otrait2": {"ovalue3", "ovalue4"}, }, }, - Grants: types.AccessListGrants{ + Grants: accesslist.Grants{ Roles: []string{"grole1", "grole2"}, Traits: map[string][]string{ "gtrait1": {"gvalue1", "gvalue2"}, "gtrait2": {"gvalue3", "gvalue4"}, }, }, - Members: []types.AccessListMember{ + Members: []accesslist.Member{ { Name: "member1", Joined: time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC), diff --git a/api/types/access_list.go b/lib/types/accesslist/accesslist.go similarity index 65% rename from api/types/access_list.go rename to lib/types/accesslist/accesslist.go index 14a7304301a1a..dfd5f0f4e2978 100644 --- a/api/types/access_list.go +++ b/lib/types/accesslist/accesslist.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package types +package accesslist import ( "encoding/json" @@ -23,56 +23,13 @@ import ( "github.com/gravitational/trace" - accesslistpb "github.com/gravitational/teleport/api/gen/proto/go/accesslist/v1" - "github.com/gravitational/teleport/api/types/header" - "github.com/gravitational/teleport/api/types/traits" + "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/utils" + "github.com/gravitational/teleport/lib/types/header" + "github.com/gravitational/teleport/lib/types/header/convert/legacy" + "github.com/gravitational/teleport/lib/types/trait" ) -// FromAccessListV1 converts a v1 access list into an internal access list object. -func FromAccessListV1(msg *accesslistpb.AccessList) (*AccessList, error) { - owners := make([]AccessListOwner, len(msg.Spec.Owners)) - for i, owner := range msg.Spec.Owners { - owners[i] = AccessListOwner{ - Name: owner.Name, - Description: owner.Description, - } - } - - members := make([]AccessListMember, len(msg.Spec.Members)) - for i, member := range msg.Spec.Members { - members[i] = AccessListMember{ - Name: member.Name, - Joined: member.Joined.AsTime(), - Expires: member.Expires.AsTime(), - Reason: member.Reason, - AddedBy: member.AddedBy, - } - } - - accessList, err := NewAccessList(header.FromMetadataV1(msg.Header.Metadata), AccessListSpec{ - Owners: owners, - Audit: AccessListAudit{ - Frequency: msg.Spec.Audit.Frequency.AsDuration(), - }, - MembershipRequires: AccessListRequires{ - Roles: msg.Spec.MembershipRequires.Roles, - Traits: traits.FromV1(msg.Spec.MembershipRequires.Traits), - }, - OwnershipRequires: AccessListRequires{ - Roles: msg.Spec.OwnershipRequires.Roles, - Traits: traits.FromV1(msg.Spec.OwnershipRequires.Traits), - }, - Grants: AccessListGrants{ - Roles: msg.Spec.Grants.Roles, - Traits: traits.FromV1(msg.Spec.Grants.Traits), - }, - Members: members, - }) - - return accessList, trace.Wrap(err) -} - // AccessList describes the basic building block of access grants, which are // similar to access requests but for longer lived permissions that need to be // regularly audited. @@ -81,39 +38,39 @@ type AccessList struct { header.ResourceHeader // Spec is the specification for the access list. - Spec AccessListSpec `json:"spec" yaml:"spec"` + Spec Spec `json:"spec" yaml:"spec"` } -// AccessListSpec is the specification for an access list. -type AccessListSpec struct { +// Spec is the specification for an access list. +type Spec struct { // Description is a plaintext description of the access list. Description string `json:"description" yaml:"description"` // Owners is a list of owners of the access list. - Owners []AccessListOwner `json:"owners" yaml:"owners"` + Owners []Owner `json:"owners" yaml:"owners"` // Audit describes the frequency that this access list must be audited. - Audit AccessListAudit `json:"audit" yaml:"audit"` + Audit Audit `json:"audit" yaml:"audit"` // MembershipRequires describes the requirements for a user to be a member of the access list. // For a membership to an access list to be effective, the user must meet the requirements of // MembershipRequires and must be in the members list. - MembershipRequires AccessListRequires `json:"membership_requires" yaml:"membership_requires"` + MembershipRequires Requires `json:"membership_requires" yaml:"membership_requires"` // OwnershipRequires describes the requirements for a user to be an owner of the access list. // For ownership of an access list to be effective, the user must meet the requirements of // OwnershipRequires and must be in the owners list. - OwnershipRequires AccessListRequires `json:"ownership_requires" yaml:"ownership_requires"` + OwnershipRequires Requires `json:"ownership_requires" yaml:"ownership_requires"` // Grants describes the access granted by membership to this access list. - Grants AccessListGrants `json:"grants" yaml:"grants"` + Grants Grants `json:"grants" yaml:"grants"` // Members describes the current members of the access list. - Members []AccessListMember `json:"members" yaml:"members"` + Members []Member `json:"members" yaml:"members"` } -// AccessListOwner is an owner of an access list. -type AccessListOwner struct { +// Owner is an owner of an access list. +type Owner struct { // Name is the username of the owner. Name string `json:"name" yaml:"name"` @@ -121,33 +78,33 @@ type AccessListOwner struct { Description string `json:"description" yaml:"description"` } -// AccessListAudit describes the audit configuration for an access list. -type AccessListAudit struct { +// Audit describes the audit configuration for an access list. +type Audit struct { // Frequency is a duration that describes how often an access list must be audited. Frequency time.Duration `json:"frequency" yaml:"frequency"` } -// AccessListRequires describes a requirement section for an access list. A user must +// Requires describes a requirement section for an access list. A user must // meet the following criteria to obtain the specific access to the list. -type AccessListRequires struct { +type Requires struct { // Roles are the user roles that must be present for the user to obtain access. Roles []string `json:"roles" yaml:"roles"` // Traits are the traits that must be present for the user to obtain access. - Traits map[string][]string `json:"traits" yaml:"traits"` + Traits trait.Traits `json:"traits" yaml:"traits"` } -// AccessListGrants describes what access is granted by membership to the access list. -type AccessListGrants struct { +// Grants describes what access is granted by membership to the access list. +type Grants struct { // Roles are the roles that are granted to users who are members of the access list. Roles []string `json:"roles" yaml:"roles"` // Traits are the traits that are granted to users who are members of the access list. - Traits map[string][]string `json:"traits" yaml:"traits"` + Traits trait.Traits `json:"traits" yaml:"traits"` } -// AccessListMember describes a member of an access list. -type AccessListMember struct { +// Member describes a member of an access list. +type Member struct { // Name is the name of the member of the access list. Name string `json:"name" yaml:"name"` @@ -165,7 +122,7 @@ type AccessListMember struct { } // NewAccessList will create a new access list. -func NewAccessList(metadata header.Metadata, spec AccessListSpec) (*AccessList, error) { +func NewAccessList(metadata header.Metadata, spec Spec) (*AccessList, error) { accessList := &AccessList{ ResourceHeader: header.ResourceHeaderFromMetadata(metadata), Spec: spec, @@ -180,8 +137,8 @@ func NewAccessList(metadata header.Metadata, spec AccessListSpec) (*AccessList, // CheckAndSetDefaults validates fields and populates empty fields with default values. func (a *AccessList) CheckAndSetDefaults() error { - a.SetKind(KindAccessList) - a.SetVersion(V1) + a.SetKind(types.KindAccessList) + a.SetVersion(types.V1) if err := a.ResourceHeader.CheckAndSetDefaults(); err != nil { return trace.Wrap(err) @@ -235,7 +192,7 @@ func (a *AccessList) CheckAndSetDefaults() error { } // GetOwners returns the list of owners from the access list. -func (a *AccessList) GetOwners() []AccessListOwner { +func (a *AccessList) GetOwners() []Owner { return a.Spec.Owners } @@ -245,39 +202,39 @@ func (a *AccessList) GetAuditFrequency() time.Duration { } // GetMembershipRequires returns the membership requires configuration from the access list. -func (a *AccessList) GetMembershipRequires() AccessListRequires { +func (a *AccessList) GetMembershipRequires() Requires { return a.Spec.MembershipRequires } // GetOwnershipRequires returns the ownership requires configuration from the access list. -func (a *AccessList) GetOwnershipRequires() AccessListRequires { +func (a *AccessList) GetOwnershipRequires() Requires { return a.Spec.OwnershipRequires } // GetGrants returns the grants from the access list. -func (a *AccessList) GetGrants() AccessListGrants { +func (a *AccessList) GetGrants() Grants { return a.Spec.Grants } // GetMembers returns the members from the access list. -func (a *AccessList) GetMembers() []AccessListMember { +func (a *AccessList) GetMembers() []Member { return a.Spec.Members } // GetMetadata returns metadata. This is specifically for conforming to the Resource interface, // and should be removed when possible. -func (a *AccessList) GetMetadata() Metadata { - return FromHeaderMetadata(a.Metadata) +func (a *AccessList) GetMetadata() types.Metadata { + return legacy.FromHeaderMetadata(a.Metadata) } // MatchSearch goes through select field values of a resource // and tries to match against the list of search values. func (a *AccessList) MatchSearch(values []string) bool { fieldVals := append(utils.MapToStrings(a.GetAllLabels()), a.GetName()) - return MatchSearch(fieldVals, values, nil) + return types.MatchSearch(fieldVals, values, nil) } -func (a *AccessListAudit) UnmarshalJSON(data []byte) error { +func (a *Audit) UnmarshalJSON(data []byte) error { var audit map[string]interface{} if err := json.Unmarshal(data, &audit); err != nil { return trace.Wrap(err) @@ -291,7 +248,7 @@ func (a *AccessListAudit) UnmarshalJSON(data []byte) error { return nil } -func (a *AccessListAudit) MarshalJSON() ([]byte, error) { +func (a *Audit) MarshalJSON() ([]byte, error) { audit := map[string]interface{}{} audit["frequency"] = a.Frequency.String() data, err := json.Marshal(audit) diff --git a/api/types/access_list_test.go b/lib/types/accesslist/accesslist_test.go similarity index 94% rename from api/types/access_list_test.go rename to lib/types/accesslist/accesslist_test.go index 8d60effd52c6b..9a93b21f28e47 100644 --- a/api/types/access_list_test.go +++ b/lib/types/accesslist/accesslist_test.go @@ -1,9 +1,12 @@ /* Copyright 2023 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. @@ -11,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package types +package accesslist import ( "encoding/json" @@ -22,7 +25,7 @@ import ( ) func TestAuditMarshaling(t *testing.T) { - audit := AccessListAudit{ + audit := Audit{ Frequency: time.Hour, } @@ -43,7 +46,7 @@ func TestAuditUnmarshaling(t *testing.T) { data, err := json.Marshal(&raw) require.NoError(t, err) - var audit AccessListAudit + var audit Audit require.NoError(t, json.Unmarshal(data, &audit)) require.Equal(t, time.Hour, audit.Frequency) diff --git a/lib/types/accesslist/convert/v1/accesslist.go b/lib/types/accesslist/convert/v1/accesslist.go new file mode 100644 index 0000000000000..f0c42bc253007 --- /dev/null +++ b/lib/types/accesslist/convert/v1/accesslist.go @@ -0,0 +1,119 @@ +/* +Copyright 2023 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" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/timestamppb" + + accesslistv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accesslist/v1" + "github.com/gravitational/teleport/lib/types/accesslist" + headerv1 "github.com/gravitational/teleport/lib/types/header/convert/v1" + traitv1 "github.com/gravitational/teleport/lib/types/trait/convert/v1" +) + +// FromProto converts a v1 access list into an internal access list object. +func FromProto(msg *accesslistv1.AccessList) (*accesslist.AccessList, error) { + owners := make([]accesslist.Owner, len(msg.Spec.Owners)) + for i, owner := range msg.Spec.Owners { + owners[i] = accesslist.Owner{ + Name: owner.Name, + Description: owner.Description, + } + } + + members := make([]accesslist.Member, len(msg.Spec.Members)) + for i, member := range msg.Spec.Members { + members[i] = accesslist.Member{ + Name: member.Name, + Joined: member.Joined.AsTime(), + Expires: member.Expires.AsTime(), + Reason: member.Reason, + AddedBy: member.AddedBy, + } + } + + accessList, err := accesslist.NewAccessList(headerv1.FromMetadataProto(msg.Header.Metadata), accesslist.Spec{ + Description: msg.Spec.Description, + Owners: owners, + Audit: accesslist.Audit{ + Frequency: msg.Spec.Audit.Frequency.AsDuration(), + }, + MembershipRequires: accesslist.Requires{ + Roles: msg.Spec.MembershipRequires.Roles, + Traits: traitv1.FromProto(msg.Spec.MembershipRequires.Traits), + }, + OwnershipRequires: accesslist.Requires{ + Roles: msg.Spec.OwnershipRequires.Roles, + Traits: traitv1.FromProto(msg.Spec.OwnershipRequires.Traits), + }, + Grants: accesslist.Grants{ + Roles: msg.Spec.Grants.Roles, + Traits: traitv1.FromProto(msg.Spec.Grants.Traits), + }, + Members: members, + }) + + return accessList, trace.Wrap(err) +} + +// ToProto converts an internal access list into a v1 access list object. +func ToProto(accessList *accesslist.AccessList) *accesslistv1.AccessList { + owners := make([]*accesslistv1.AccessListOwner, len(accessList.Spec.Owners)) + for i, owner := range accessList.Spec.Owners { + owners[i] = &accesslistv1.AccessListOwner{ + Name: owner.Name, + Description: owner.Description, + } + } + + members := make([]*accesslistv1.AccessListMember, len(accessList.Spec.Members)) + for i, member := range accessList.Spec.Members { + members[i] = &accesslistv1.AccessListMember{ + Name: member.Name, + Joined: timestamppb.New(member.Joined), + Expires: timestamppb.New(member.Expires), + Reason: member.Reason, + AddedBy: member.AddedBy, + } + } + + return &accesslistv1.AccessList{ + Header: headerv1.ToResourceHeaderProto(accessList.ResourceHeader), + Spec: &accesslistv1.AccessListSpec{ + Description: accessList.Spec.Description, + Owners: owners, + Audit: &accesslistv1.AccessListAudit{ + Frequency: durationpb.New(accessList.Spec.Audit.Frequency), + }, + MembershipRequires: &accesslistv1.AccessListRequires{ + Roles: accessList.Spec.MembershipRequires.Roles, + Traits: traitv1.ToProto(accessList.Spec.MembershipRequires.Traits), + }, + OwnershipRequires: &accesslistv1.AccessListRequires{ + Roles: accessList.Spec.OwnershipRequires.Roles, + Traits: traitv1.ToProto(accessList.Spec.OwnershipRequires.Traits), + }, + Grants: &accesslistv1.AccessListGrants{ + Roles: accessList.Spec.Grants.Roles, + Traits: traitv1.ToProto(accessList.Spec.Grants.Traits), + }, + Members: members, + }, + } +} diff --git a/lib/types/accesslist/convert/v1/accesslist_test.go b/lib/types/accesslist/convert/v1/accesslist_test.go new file mode 100644 index 0000000000000..57ac002782e8c --- /dev/null +++ b/lib/types/accesslist/convert/v1/accesslist_test.go @@ -0,0 +1,95 @@ +/* +Copyright 2023 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" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" + + "github.com/gravitational/teleport/lib/types/accesslist" + "github.com/gravitational/teleport/lib/types/header" +) + +func TestRoundtrip(t *testing.T) { + accessList, err := accesslist.NewAccessList( + header.Metadata{ + Name: "access-list", + }, + accesslist.Spec{ + Description: "test access list", + Owners: []accesslist.Owner{ + { + Name: "test-user1", + Description: "test user 1", + }, + { + Name: "test-user2", + Description: "test user 2", + }, + }, + Audit: accesslist.Audit{ + Frequency: time.Hour, + }, + MembershipRequires: accesslist.Requires{ + Roles: []string{"mrole1", "mrole2"}, + Traits: map[string][]string{ + "mtrait1": {"mvalue1", "mvalue2"}, + "mtrait2": {"mvalue3", "mvalue4"}, + }, + }, + OwnershipRequires: accesslist.Requires{ + Roles: []string{"orole1", "orole2"}, + Traits: map[string][]string{ + "otrait1": {"ovalue1", "ovalue2"}, + "otrait2": {"ovalue3", "ovalue4"}, + }, + }, + Grants: accesslist.Grants{ + Roles: []string{"grole1", "grole2"}, + Traits: map[string][]string{ + "gtrait1": {"gvalue1", "gvalue2"}, + "gtrait2": {"gvalue3", "gvalue4"}, + }, + }, + Members: []accesslist.Member{ + { + Name: "member1", + Joined: time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC), + Expires: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC), + Reason: "because", + AddedBy: "test-user1", + }, + { + Name: "member2", + Joined: time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC), + Expires: time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC), + Reason: "because again", + AddedBy: "test-user2", + }, + }, + }, + ) + require.NoError(t, err) + + converted, err := FromProto(ToProto(accessList)) + require.NoError(t, err) + + require.Empty(t, cmp.Diff(accessList, converted)) +} diff --git a/lib/types/header/convert/legacy/header.go b/lib/types/header/convert/legacy/header.go new file mode 100644 index 0000000000000..05cf155fde6c0 --- /dev/null +++ b/lib/types/header/convert/legacy/header.go @@ -0,0 +1,33 @@ +/* +Copyright 2023 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 legacy + +import ( + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/types/header" +) + +// FromHeaderMetadata will convert a *header.Metadata object to this metadata object. +// TODO: Remove this once we get rid of the old Metadata object. +func FromHeaderMetadata(metadata header.Metadata) types.Metadata { + return types.Metadata{ + ID: metadata.ID, + Name: metadata.Name, + Description: metadata.Description, + Labels: metadata.Labels, + } +} diff --git a/lib/types/header/convert/v1/header.go b/lib/types/header/convert/v1/header.go new file mode 100644 index 0000000000000..cc04bf51358a4 --- /dev/null +++ b/lib/types/header/convert/v1/header.go @@ -0,0 +1,67 @@ +/* +Copyright 2023 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 headerv1 + +import ( + "google.golang.org/protobuf/types/known/timestamppb" + + headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + "github.com/gravitational/teleport/lib/types/header" +) + +// FromResourceHeaderProto converts the resource header protobuf message into an internal resource header object. +// This function does not use the builder due to the generics for the builder object. +func FromResourceHeaderProto(msg *headerv1.ResourceHeader) header.ResourceHeader { + return header.ResourceHeader{ + Kind: msg.Kind, + SubKind: msg.SubKind, + Version: msg.Version, + Metadata: FromMetadataProto(msg.Metadata), + } +} + +// ToResourceHeaderProto converts an internal resource header object into a v1 resource header protobuf message. +func ToResourceHeaderProto(resourceHeader header.ResourceHeader) *headerv1.ResourceHeader { + return &headerv1.ResourceHeader{ + Kind: resourceHeader.Kind, + SubKind: resourceHeader.SubKind, + Version: resourceHeader.Version, + Metadata: ToMetadataProto(resourceHeader.Metadata), + } +} + +// FromMetadataProto converts v1 metadata into an internal metadata object. +func FromMetadataProto(msg *headerv1.Metadata) header.Metadata { + return header.Metadata{ + Name: msg.Name, + Description: msg.Description, + Labels: msg.Labels, + Expires: msg.Expires.AsTime(), + ID: msg.Id, + } +} + +// ToMetadataProto converts an internal metadata object into a v1 metadata protobuf message. +func ToMetadataProto(metadata header.Metadata) *headerv1.Metadata { + return &headerv1.Metadata{ + Name: metadata.Name, + Description: metadata.Description, + Labels: metadata.Labels, + Expires: timestamppb.New(metadata.Expires), + Id: metadata.ID, + } +} diff --git a/lib/types/header/convert/v1/header_test.go b/lib/types/header/convert/v1/header_test.go new file mode 100644 index 0000000000000..c32f1b8ed4f05 --- /dev/null +++ b/lib/types/header/convert/v1/header_test.go @@ -0,0 +1,60 @@ +/* +Copyright 2023 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 headerv1 + +import ( + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" + + "github.com/gravitational/teleport/lib/types/header" +) + +func TestResourceHeaderRoundtrip(t *testing.T) { + resourceHeader := header.ResourceHeader{ + Kind: "kind", + SubKind: "subkind", + Version: "version", + Metadata: header.Metadata{ + Name: "name", + Description: "description", + Labels: map[string]string{"label": "value"}, + Expires: time.Now(), + ID: 12345, + }, + } + + converted := FromResourceHeaderProto(ToResourceHeaderProto(resourceHeader)) + + require.Empty(t, cmp.Diff(resourceHeader, converted)) +} + +func TestMetadataRoundtrip(t *testing.T) { + metadata := header.Metadata{ + Name: "name", + Description: "description", + Labels: map[string]string{"label": "value"}, + Expires: time.Now(), + ID: 12345, + } + + converted := FromMetadataProto(ToMetadataProto(metadata)) + + require.Empty(t, cmp.Diff(metadata, converted)) +} diff --git a/api/types/header/header.go b/lib/types/header/header.go similarity index 90% rename from api/types/header/header.go rename to lib/types/header/header.go index 48b5839fc407a..34d0668bf1da6 100644 --- a/api/types/header/header.go +++ b/lib/types/header/header.go @@ -22,22 +22,10 @@ import ( "github.com/gravitational/trace" "golang.org/x/exp/slices" - headerv1 "github.com/gravitational/teleport/api/gen/proto/go/header/v1" "github.com/gravitational/teleport/api/types/common" "github.com/gravitational/teleport/api/utils" ) -// FromResourceHeaderV1 converts the resource header protobuf message into an internal resource header object. -// This function does not use the builder due to the generics for the builder object. -func FromResourceHeaderV1(msg *headerv1.ResourceHeader) *ResourceHeader { - return &ResourceHeader{ - Kind: msg.Kind, - SubKind: msg.SubKind, - Version: msg.Version, - Metadata: FromMetadataV1(msg.Metadata), - } -} - func ResourceHeaderFromMetadata(metadata Metadata) ResourceHeader { return ResourceHeader{ Metadata: metadata, @@ -164,16 +152,6 @@ func (h *ResourceHeader) CheckAndSetDefaults() error { return trace.Wrap(h.Metadata.CheckAndSetDefaults()) } -// FromMetadataV1 converts v1 metadata into an internal metadata object. -func FromMetadataV1(msg *headerv1.Metadata) Metadata { - return Metadata{ - Name: msg.Name, - Description: msg.Description, - Labels: msg.Labels, - Expires: msg.Expires.AsTime(), - } -} - // Metadata is resource metadata type Metadata struct { // Name is an object name diff --git a/lib/types/trait/convert/v1/trait.go b/lib/types/trait/convert/v1/trait.go new file mode 100644 index 0000000000000..3b0084d341b2b --- /dev/null +++ b/lib/types/trait/convert/v1/trait.go @@ -0,0 +1,43 @@ +/* +Copyright 2023 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 traitv1 + +import ( + traitv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/trait/v1" + "github.com/gravitational/teleport/lib/types/trait" +) + +// FromProto converts an array of v1 traits into a map of string to string array. +func FromProto(traits []*traitv1.Trait) trait.Traits { + out := map[string][]string{} + for _, trait := range traits { + out[trait.Key] = trait.Values + } + return out +} + +// ToV1 converts a map of string to string array to an array of v1 traits. +func ToProto(traits trait.Traits) []*traitv1.Trait { + out := make([]*traitv1.Trait, 0, len(traits)) + for key, values := range traits { + out = append(out, &traitv1.Trait{ + Key: key, + Values: values, + }) + } + return out +} diff --git a/lib/types/trait/convert/v1/trait_test.go b/lib/types/trait/convert/v1/trait_test.go new file mode 100644 index 0000000000000..dca5748c9da2c --- /dev/null +++ b/lib/types/trait/convert/v1/trait_test.go @@ -0,0 +1,38 @@ +/* +Copyright 2023 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 traitv1 + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" + + "github.com/gravitational/teleport/lib/types/trait" +) + +func TestRoundtrip(t *testing.T) { + traits := trait.Traits{ + "trait1": {"value1", "value2"}, + "trait2": {"value3", "value4"}, + "trait3": {"value5", "value6"}, + } + + converted := FromProto(ToProto(traits)) + + require.Empty(t, cmp.Diff(traits, converted)) +} diff --git a/api/types/traits/traits.go b/lib/types/trait/trait.go similarity index 61% rename from api/types/traits/traits.go rename to lib/types/trait/trait.go index 8f3593b76ad8f..c700e9a310d1f 100644 --- a/api/types/traits/traits.go +++ b/lib/types/trait/trait.go @@ -14,17 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package traits +package trait -import ( - traitv1 "github.com/gravitational/teleport/api/gen/proto/go/trait/v1" -) - -// FromV1 converts an array of traits into a map of string to string array. -func FromV1(traits []*traitv1.Trait) map[string][]string { - traitMap := map[string][]string{} - for _, trait := range traits { - traitMap[trait.Key] = trait.Values - } - return traitMap -} +// Traits is a mapping of traits to values. +type Traits map[string][]string