From 980ae6dd857ee0583aa85176ca5c14c973b66a23 Mon Sep 17 00:00:00 2001 From: Johan Siebens Date: Fri, 23 Sep 2022 14:04:23 +0200 Subject: [PATCH] feat: add flags to create tailnet with some proper default IAM policies --- internal/cmd/tailnet.go | 48 +++++++++++++- internal/domain/repository.go | 2 +- internal/domain/tailnet.go | 4 +- internal/provider/oidc.go | 4 ++ internal/service/tailnet.go | 10 ++- pkg/gen/ionscale/v1/tailnets.pb.go | 103 +++++++++++++++++------------ proto/ionscale/v1/tailnets.proto | 3 + 7 files changed, 124 insertions(+), 50 deletions(-) diff --git a/internal/cmd/tailnet.go b/internal/cmd/tailnet.go index a11fbb2..cb4de62 100644 --- a/internal/cmd/tailnet.go +++ b/internal/cmd/tailnet.go @@ -4,9 +4,11 @@ import ( "context" "fmt" "github.com/bufbuild/connect-go" + idomain "github.com/jsiebens/ionscale/internal/domain" api "github.com/jsiebens/ionscale/pkg/gen/ionscale/v1" "github.com/muesli/coral" "github.com/rodaine/table" + "strings" ) func tailnetCommand() *coral.Command { @@ -71,20 +73,62 @@ func createTailnetsCommand() *coral.Command { } var name string + var domain string + var email string var target = Target{} target.prepareCommand(command) command.Flags().StringVarP(&name, "name", "n", "", "") - _ = command.MarkFlagRequired("name") + command.Flags().StringVar(&domain, "domain", "", "") + command.Flags().StringVar(&email, "email", "", "") + + command.PreRunE = func(cmd *coral.Command, args []string) error { + if name == "" && email == "" && domain == "" { + return fmt.Errorf("at least flag --name, --email or --domain is required") + } + if domain != "" && email != "" { + return fmt.Errorf("flags --email and --domain are mutually exclusive") + } + return nil + } command.RunE = func(command *coral.Command, args []string) error { + var tailnetName = "" + var iamPolicy = api.IAMPolicy{} + + if len(domain) != 0 { + domainToLower := strings.ToLower(domain) + tailnetName = domainToLower + iamPolicy = api.IAMPolicy{ + Filters: []string{fmt.Sprintf("domain == %s", domainToLower)}, + } + } + + if len(email) != 0 { + emailToLower := strings.ToLower(email) + tailnetName = emailToLower + iamPolicy = api.IAMPolicy{ + Emails: []string{emailToLower}, + Roles: map[string]string{ + emailToLower: string(idomain.UserRoleAdmin), + }, + } + } + + if len(name) != 0 { + tailnetName = name + } + client, err := target.createGRPCClient() if err != nil { return err } - resp, err := client.CreateTailnet(context.Background(), connect.NewRequest(&api.CreateTailnetRequest{Name: name})) + resp, err := client.CreateTailnet(context.Background(), connect.NewRequest(&api.CreateTailnetRequest{ + Name: tailnetName, + IamPolicy: &iamPolicy, + })) if err != nil { return err diff --git a/internal/domain/repository.go b/internal/domain/repository.go index d9bff2c..b116cb8 100644 --- a/internal/domain/repository.go +++ b/internal/domain/repository.go @@ -18,7 +18,7 @@ type Repository interface { GetOrCreateAccount(ctx context.Context, externalID, loginName string) (*Account, bool, error) SaveTailnet(ctx context.Context, tailnet *Tailnet) error - GetOrCreateTailnet(ctx context.Context, name string) (*Tailnet, bool, error) + GetOrCreateTailnet(ctx context.Context, name string, iamPolicy IAMPolicy) (*Tailnet, bool, error) GetTailnet(ctx context.Context, id uint64) (*Tailnet, error) ListTailnets(ctx context.Context) ([]Tailnet, error) DeleteTailnet(ctx context.Context, id uint64) error diff --git a/internal/domain/tailnet.go b/internal/domain/tailnet.go index 48a0139..1885342 100644 --- a/internal/domain/tailnet.go +++ b/internal/domain/tailnet.go @@ -25,13 +25,13 @@ func (r *repository) SaveTailnet(ctx context.Context, tailnet *Tailnet) error { return nil } -func (r *repository) GetOrCreateTailnet(ctx context.Context, name string) (*Tailnet, bool, error) { +func (r *repository) GetOrCreateTailnet(ctx context.Context, name string, iamPolicy IAMPolicy) (*Tailnet, bool, error) { tailnet := &Tailnet{} id := util.NextID() tx := r.withContext(ctx). Where(Tailnet{Name: name}). - Attrs(Tailnet{ID: id, ACLPolicy: DefaultPolicy()}). + Attrs(Tailnet{ID: id, ACLPolicy: DefaultPolicy(), IAMPolicy: iamPolicy}). FirstOrCreate(tailnet) if tx.Error != nil { diff --git a/internal/provider/oidc.go b/internal/provider/oidc.go index 44def2e..ab4070f 100644 --- a/internal/provider/oidc.go +++ b/internal/provider/oidc.go @@ -85,10 +85,14 @@ func (p *OIDCProvider) Exchange(redirectURI, code string) (*User, error) { return nil, err } + domain := strings.Split(email, "@")[1] + return &User{ ID: sub, Name: email, Attr: map[string]interface{}{ + "email": email, + "domain": domain, "token": tokenClaims, "userinfo": userInfoClaims, }, diff --git a/internal/service/tailnet.go b/internal/service/tailnet.go index fbf940e..8d1e3af 100644 --- a/internal/service/tailnet.go +++ b/internal/service/tailnet.go @@ -16,7 +16,15 @@ func (s *Service) CreateTailnet(ctx context.Context, req *connect.Request[api.Cr return nil, connect.NewError(connect.CodePermissionDenied, errors.New("permission denied")) } - tailnet, created, err := s.repository.GetOrCreateTailnet(ctx, req.Msg.Name) + name := req.Msg.Name + iamPolicy := domain.IAMPolicy{ + Subs: req.Msg.IamPolicy.Subs, + Emails: req.Msg.IamPolicy.Emails, + Filters: req.Msg.IamPolicy.Filters, + Roles: apiRolesMapToDomainRolesMap(req.Msg.IamPolicy.Roles), + } + + tailnet, created, err := s.repository.GetOrCreateTailnet(ctx, name, iamPolicy) if err != nil { return nil, err } diff --git a/pkg/gen/ionscale/v1/tailnets.pb.go b/pkg/gen/ionscale/v1/tailnets.pb.go index d81b068..dcda98a 100644 --- a/pkg/gen/ionscale/v1/tailnets.pb.go +++ b/pkg/gen/ionscale/v1/tailnets.pb.go @@ -80,7 +80,8 @@ type CreateTailnetRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + IamPolicy *IAMPolicy `protobuf:"bytes,2,opt,name=iam_policy,json=iamPolicy,proto3" json:"iam_policy,omitempty"` } func (x *CreateTailnetRequest) Reset() { @@ -122,6 +123,13 @@ func (x *CreateTailnetRequest) GetName() string { return "" } +func (x *CreateTailnetRequest) GetIamPolicy() *IAMPolicy { + if x != nil { + return x.IamPolicy + } + return nil +} + type CreateTailnetResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -446,41 +454,45 @@ var File_ionscale_v1_tailnets_proto protoreflect.FileDescriptor var file_ionscale_v1_tailnets_proto_rawDesc = []byte{ 0x0a, 0x1a, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x69, 0x6f, - 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x22, 0x2d, 0x0a, 0x07, 0x54, 0x61, 0x69, - 0x6c, 0x6e, 0x65, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2a, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x47, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, - 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, - 0x07, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, - 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x69, - 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x07, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x22, 0x23, 0x0a, - 0x11, 0x47, 0x65, 0x74, 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, - 0x69, 0x64, 0x22, 0x44, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x74, 0x61, 0x69, 0x6c, - 0x6e, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x6f, 0x6e, 0x73, - 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x52, - 0x07, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x22, 0x14, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, - 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x45, - 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x07, 0x74, 0x61, - 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x22, 0x4b, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, - 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, - 0x0a, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x09, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, - 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, - 0x63, 0x65, 0x22, 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x69, 0x6c, - 0x6e, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3d, 0x5a, 0x3b, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x73, 0x69, 0x65, 0x62, 0x65, - 0x6e, 0x73, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, - 0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, - 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x15, 0x69, 0x6f, 0x6e, 0x73, 0x63, + 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x61, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x22, 0x2d, 0x0a, 0x07, 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, + 0x61, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x0a, 0x69, + 0x61, 0x6d, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x16, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x41, + 0x4d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x09, 0x69, 0x61, 0x6d, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x22, 0x47, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x69, 0x6c, + 0x6e, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x74, + 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, + 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x69, 0x6c, 0x6e, + 0x65, 0x74, 0x52, 0x07, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x22, 0x23, 0x0a, 0x11, 0x47, + 0x65, 0x74, 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, + 0x22, 0x44, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, + 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x07, 0x74, + 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x22, 0x14, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, + 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x45, 0x0a, 0x13, + 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x07, 0x74, 0x61, 0x69, 0x6c, + 0x6e, 0x65, 0x74, 0x22, 0x4b, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x69, + 0x6c, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x74, + 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x09, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, + 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, + 0x22, 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x69, 0x6c, 0x6e, 0x65, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x73, 0x69, 0x65, 0x62, 0x65, 0x6e, 0x73, + 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, + 0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f, + 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -506,16 +518,18 @@ var file_ionscale_v1_tailnets_proto_goTypes = []interface{}{ (*ListTailnetResponse)(nil), // 6: ionscale.v1.ListTailnetResponse (*DeleteTailnetRequest)(nil), // 7: ionscale.v1.DeleteTailnetRequest (*DeleteTailnetResponse)(nil), // 8: ionscale.v1.DeleteTailnetResponse + (*IAMPolicy)(nil), // 9: ionscale.v1.IAMPolicy } var file_ionscale_v1_tailnets_proto_depIdxs = []int32{ - 0, // 0: ionscale.v1.CreateTailnetResponse.tailnet:type_name -> ionscale.v1.Tailnet - 0, // 1: ionscale.v1.GetTailnetResponse.tailnet:type_name -> ionscale.v1.Tailnet - 0, // 2: ionscale.v1.ListTailnetResponse.tailnet:type_name -> ionscale.v1.Tailnet - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 9, // 0: ionscale.v1.CreateTailnetRequest.iam_policy:type_name -> ionscale.v1.IAMPolicy + 0, // 1: ionscale.v1.CreateTailnetResponse.tailnet:type_name -> ionscale.v1.Tailnet + 0, // 2: ionscale.v1.GetTailnetResponse.tailnet:type_name -> ionscale.v1.Tailnet + 0, // 3: ionscale.v1.ListTailnetResponse.tailnet:type_name -> ionscale.v1.Tailnet + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name } func init() { file_ionscale_v1_tailnets_proto_init() } @@ -523,6 +537,7 @@ func file_ionscale_v1_tailnets_proto_init() { if File_ionscale_v1_tailnets_proto != nil { return } + file_ionscale_v1_iam_proto_init() if !protoimpl.UnsafeEnabled { file_ionscale_v1_tailnets_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Tailnet); i { diff --git a/proto/ionscale/v1/tailnets.proto b/proto/ionscale/v1/tailnets.proto index c0db4d3..31cd8a1 100644 --- a/proto/ionscale/v1/tailnets.proto +++ b/proto/ionscale/v1/tailnets.proto @@ -3,6 +3,8 @@ syntax = "proto3"; package ionscale.v1; option go_package = "github.com/jsiebens/ionscale/pkg/gen/ionscale/v1;ionscalev1"; +import "ionscale/v1/iam.proto"; + message Tailnet { uint64 id = 1; string name = 2; @@ -10,6 +12,7 @@ message Tailnet { message CreateTailnetRequest { string name = 1; + IAMPolicy iam_policy = 2; } message CreateTailnetResponse {