From ddbfa2ed29d143d213270161a73829301c8f1f60 Mon Sep 17 00:00:00 2001 From: Geoff Greer Date: Wed, 21 Jan 2026 10:19:55 -0800 Subject: [PATCH 01/10] Add support for role scope trait. --- pb/c1/connector/v2/annotation_resource.pb.go | 110 +++++++++ .../v2/annotation_resource.pb.validate.go | 138 ++++++++++++ .../v2/annotation_resource_protoopaque.pb.go | 110 +++++++++ pb/c1/connector/v2/annotation_trait.pb.go | 213 +++++++++++++----- .../v2/annotation_trait.pb.validate.go | 158 +++++++++++++ .../v2/annotation_trait_protoopaque.pb.go | 213 +++++++++++++----- pb/c1/connector/v2/resource.pb.go | 10 +- pb/c1/connector/v2/resource_protoopaque.pb.go | 10 +- pkg/types/resource/resource.go | 42 ++++ pkg/types/resource/role_scope_trait.go | 41 ++++ .../c1/connector/v2/annotation_resource.proto | 8 + proto/c1/connector/v2/annotation_trait.proto | 9 + proto/c1/connector/v2/resource.proto | 1 + 13 files changed, 945 insertions(+), 118 deletions(-) create mode 100644 pb/c1/connector/v2/annotation_resource.pb.go create mode 100644 pb/c1/connector/v2/annotation_resource.pb.validate.go create mode 100644 pb/c1/connector/v2/annotation_resource_protoopaque.pb.go create mode 100644 pkg/types/resource/role_scope_trait.go create mode 100644 proto/c1/connector/v2/annotation_resource.proto diff --git a/pb/c1/connector/v2/annotation_resource.pb.go b/pb/c1/connector/v2/annotation_resource.pb.go new file mode 100644 index 000000000..39fa94b8c --- /dev/null +++ b/pb/c1/connector/v2/annotation_resource.pb.go @@ -0,0 +1,110 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.10 +// protoc (unknown) +// source: c1/connector/v2/annotation_resource.proto + +//go:build !protoopaque + +package v2 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Resource was not deleted because the resource does not exist. +type ResourceDoesNotExist struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceDoesNotExist) Reset() { + *x = ResourceDoesNotExist{} + mi := &file_c1_connector_v2_annotation_resource_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceDoesNotExist) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceDoesNotExist) ProtoMessage() {} + +func (x *ResourceDoesNotExist) ProtoReflect() protoreflect.Message { + mi := &file_c1_connector_v2_annotation_resource_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +type ResourceDoesNotExist_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + +} + +func (b0 ResourceDoesNotExist_builder) Build() *ResourceDoesNotExist { + m0 := &ResourceDoesNotExist{} + b, x := &b0, m0 + _, _ = b, x + return m0 +} + +var File_c1_connector_v2_annotation_resource_proto protoreflect.FileDescriptor + +const file_c1_connector_v2_annotation_resource_proto_rawDesc = "" + + "\n" + + ")c1/connector/v2/annotation_resource.proto\x12\x0fc1.connector.v2\"\x16\n" + + "\x14ResourceDoesNotExistB6Z4github.com/conductorone/baton-sdk/pb/c1/connector/v2b\x06proto3" + +var file_c1_connector_v2_annotation_resource_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_c1_connector_v2_annotation_resource_proto_goTypes = []any{ + (*ResourceDoesNotExist)(nil), // 0: c1.connector.v2.ResourceDoesNotExist +} +var file_c1_connector_v2_annotation_resource_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_c1_connector_v2_annotation_resource_proto_init() } +func file_c1_connector_v2_annotation_resource_proto_init() { + if File_c1_connector_v2_annotation_resource_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_c1_connector_v2_annotation_resource_proto_rawDesc), len(file_c1_connector_v2_annotation_resource_proto_rawDesc)), + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_c1_connector_v2_annotation_resource_proto_goTypes, + DependencyIndexes: file_c1_connector_v2_annotation_resource_proto_depIdxs, + MessageInfos: file_c1_connector_v2_annotation_resource_proto_msgTypes, + }.Build() + File_c1_connector_v2_annotation_resource_proto = out.File + file_c1_connector_v2_annotation_resource_proto_goTypes = nil + file_c1_connector_v2_annotation_resource_proto_depIdxs = nil +} diff --git a/pb/c1/connector/v2/annotation_resource.pb.validate.go b/pb/c1/connector/v2/annotation_resource.pb.validate.go new file mode 100644 index 000000000..06cd9eab1 --- /dev/null +++ b/pb/c1/connector/v2/annotation_resource.pb.validate.go @@ -0,0 +1,138 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: c1/connector/v2/annotation_resource.proto + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) + +// Validate checks the field values on ResourceDoesNotExist with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *ResourceDoesNotExist) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ResourceDoesNotExist with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ResourceDoesNotExistMultiError, or nil if none found. +func (m *ResourceDoesNotExist) ValidateAll() error { + return m.validate(true) +} + +func (m *ResourceDoesNotExist) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return ResourceDoesNotExistMultiError(errors) + } + + return nil +} + +// ResourceDoesNotExistMultiError is an error wrapping multiple validation +// errors returned by ResourceDoesNotExist.ValidateAll() if the designated +// constraints aren't met. +type ResourceDoesNotExistMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ResourceDoesNotExistMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ResourceDoesNotExistMultiError) AllErrors() []error { return m } + +// ResourceDoesNotExistValidationError is the validation error returned by +// ResourceDoesNotExist.Validate if the designated constraints aren't met. +type ResourceDoesNotExistValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ResourceDoesNotExistValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ResourceDoesNotExistValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ResourceDoesNotExistValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ResourceDoesNotExistValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ResourceDoesNotExistValidationError) ErrorName() string { + return "ResourceDoesNotExistValidationError" +} + +// Error satisfies the builtin error interface +func (e ResourceDoesNotExistValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sResourceDoesNotExist.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ResourceDoesNotExistValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ResourceDoesNotExistValidationError{} diff --git a/pb/c1/connector/v2/annotation_resource_protoopaque.pb.go b/pb/c1/connector/v2/annotation_resource_protoopaque.pb.go new file mode 100644 index 000000000..3c9ff5901 --- /dev/null +++ b/pb/c1/connector/v2/annotation_resource_protoopaque.pb.go @@ -0,0 +1,110 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.10 +// protoc (unknown) +// source: c1/connector/v2/annotation_resource.proto + +//go:build protoopaque + +package v2 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Resource was not deleted because the resource does not exist. +type ResourceDoesNotExist struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceDoesNotExist) Reset() { + *x = ResourceDoesNotExist{} + mi := &file_c1_connector_v2_annotation_resource_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceDoesNotExist) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceDoesNotExist) ProtoMessage() {} + +func (x *ResourceDoesNotExist) ProtoReflect() protoreflect.Message { + mi := &file_c1_connector_v2_annotation_resource_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +type ResourceDoesNotExist_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + +} + +func (b0 ResourceDoesNotExist_builder) Build() *ResourceDoesNotExist { + m0 := &ResourceDoesNotExist{} + b, x := &b0, m0 + _, _ = b, x + return m0 +} + +var File_c1_connector_v2_annotation_resource_proto protoreflect.FileDescriptor + +const file_c1_connector_v2_annotation_resource_proto_rawDesc = "" + + "\n" + + ")c1/connector/v2/annotation_resource.proto\x12\x0fc1.connector.v2\"\x16\n" + + "\x14ResourceDoesNotExistB6Z4github.com/conductorone/baton-sdk/pb/c1/connector/v2b\x06proto3" + +var file_c1_connector_v2_annotation_resource_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_c1_connector_v2_annotation_resource_proto_goTypes = []any{ + (*ResourceDoesNotExist)(nil), // 0: c1.connector.v2.ResourceDoesNotExist +} +var file_c1_connector_v2_annotation_resource_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_c1_connector_v2_annotation_resource_proto_init() } +func file_c1_connector_v2_annotation_resource_proto_init() { + if File_c1_connector_v2_annotation_resource_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_c1_connector_v2_annotation_resource_proto_rawDesc), len(file_c1_connector_v2_annotation_resource_proto_rawDesc)), + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_c1_connector_v2_annotation_resource_proto_goTypes, + DependencyIndexes: file_c1_connector_v2_annotation_resource_proto_depIdxs, + MessageInfos: file_c1_connector_v2_annotation_resource_proto_msgTypes, + }.Build() + File_c1_connector_v2_annotation_resource_proto = out.File + file_c1_connector_v2_annotation_resource_proto_goTypes = nil + file_c1_connector_v2_annotation_resource_proto_depIdxs = nil +} diff --git a/pb/c1/connector/v2/annotation_trait.pb.go b/pb/c1/connector/v2/annotation_trait.pb.go index 7b79389ac..9b8ac73fe 100644 --- a/pb/c1/connector/v2/annotation_trait.pb.go +++ b/pb/c1/connector/v2/annotation_trait.pb.go @@ -650,6 +650,101 @@ func (b0 RoleTrait_builder) Build() *RoleTrait { return m0 } +// RoleScopeTrait is used to scope a role to a resource or set of resources. +// The scope may be static (determined at crawl time) or dynamic (determined based on conditions). +type RoleScopeTrait struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + RoleId *ResourceId `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"` // The role that is scoped. + ScopeResourceId *ResourceId `protobuf:"bytes,2,opt,name=scope_resource_id,json=scopeResourceId,proto3" json:"scope_resource_id,omitempty"` // The resource that the role is scoped to. + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RoleScopeTrait) Reset() { + *x = RoleScopeTrait{} + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoleScopeTrait) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoleScopeTrait) ProtoMessage() {} + +func (x *RoleScopeTrait) ProtoReflect() protoreflect.Message { + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *RoleScopeTrait) GetRoleId() *ResourceId { + if x != nil { + return x.RoleId + } + return nil +} + +func (x *RoleScopeTrait) GetScopeResourceId() *ResourceId { + if x != nil { + return x.ScopeResourceId + } + return nil +} + +func (x *RoleScopeTrait) SetRoleId(v *ResourceId) { + x.RoleId = v +} + +func (x *RoleScopeTrait) SetScopeResourceId(v *ResourceId) { + x.ScopeResourceId = v +} + +func (x *RoleScopeTrait) HasRoleId() bool { + if x == nil { + return false + } + return x.RoleId != nil +} + +func (x *RoleScopeTrait) HasScopeResourceId() bool { + if x == nil { + return false + } + return x.ScopeResourceId != nil +} + +func (x *RoleScopeTrait) ClearRoleId() { + x.RoleId = nil +} + +func (x *RoleScopeTrait) ClearScopeResourceId() { + x.ScopeResourceId = nil +} + +type RoleScopeTrait_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + RoleId *ResourceId + ScopeResourceId *ResourceId +} + +func (b0 RoleScopeTrait_builder) Build() *RoleScopeTrait { + m0 := &RoleScopeTrait{} + b, x := &b0, m0 + _, _ = b, x + x.RoleId = b.RoleId + x.ScopeResourceId = b.ScopeResourceId + return m0 +} + type AppTrait struct { state protoimpl.MessageState `protogen:"hybrid.v1"` HelpUrl string `protobuf:"bytes,1,opt,name=help_url,json=helpUrl,proto3" json:"help_url,omitempty"` @@ -663,7 +758,7 @@ type AppTrait struct { func (x *AppTrait) Reset() { *x = AppTrait{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -675,7 +770,7 @@ func (x *AppTrait) String() string { func (*AppTrait) ProtoMessage() {} func (x *AppTrait) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -810,7 +905,7 @@ type SecretTrait struct { func (x *SecretTrait) Reset() { *x = SecretTrait{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -822,7 +917,7 @@ func (x *SecretTrait) String() string { func (*SecretTrait) ProtoMessage() {} func (x *SecretTrait) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1000,7 +1095,7 @@ type UserTrait_Email struct { func (x *UserTrait_Email) Reset() { *x = UserTrait_Email{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1012,7 +1107,7 @@ func (x *UserTrait_Email) String() string { func (*UserTrait_Email) ProtoMessage() {} func (x *UserTrait_Email) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1072,7 +1167,7 @@ type UserTrait_Status struct { func (x *UserTrait_Status) Reset() { *x = UserTrait_Status{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1084,7 +1179,7 @@ func (x *UserTrait_Status) String() string { func (*UserTrait_Status) ProtoMessage() {} func (x *UserTrait_Status) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1142,7 +1237,7 @@ type UserTrait_MFAStatus struct { func (x *UserTrait_MFAStatus) Reset() { *x = UserTrait_MFAStatus{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1154,7 +1249,7 @@ func (x *UserTrait_MFAStatus) String() string { func (*UserTrait_MFAStatus) ProtoMessage() {} func (x *UserTrait_MFAStatus) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1199,7 +1294,7 @@ type UserTrait_SSOStatus struct { func (x *UserTrait_SSOStatus) Reset() { *x = UserTrait_SSOStatus{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1211,7 +1306,7 @@ func (x *UserTrait_SSOStatus) String() string { func (*UserTrait_SSOStatus) ProtoMessage() {} func (x *UserTrait_SSOStatus) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1260,7 +1355,7 @@ type UserTrait_StructuredName struct { func (x *UserTrait_StructuredName) Reset() { *x = UserTrait_StructuredName{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1272,7 +1367,7 @@ func (x *UserTrait_StructuredName) String() string { func (*UserTrait_StructuredName) ProtoMessage() {} func (x *UserTrait_StructuredName) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1421,7 +1516,10 @@ const file_c1_connector_v2_annotation_trait_proto_rawDesc = "" + "\x04icon\x18\x01 \x01(\v2\x19.c1.connector.v2.AssetRefR\x04icon\x121\n" + "\aprofile\x18\x02 \x01(\v2\x17.google.protobuf.StructR\aprofile\">\n" + "\tRoleTrait\x121\n" + - "\aprofile\x18\x01 \x01(\v2\x17.google.protobuf.StructR\aprofile\"\x9a\x03\n" + + "\aprofile\x18\x01 \x01(\v2\x17.google.protobuf.StructR\aprofile\"\x8f\x01\n" + + "\x0eRoleScopeTrait\x124\n" + + "\arole_id\x18\x01 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x06roleId\x12G\n" + + "\x11scope_resource_id\x18\x02 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x0fscopeResourceId\"\x9a\x03\n" + "\bAppTrait\x125\n" + "\bhelp_url\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15 \x01(\x80\b:\bhttps://\xd0\x01\x01\x88\x01\x01R\ahelpUrl\x12-\n" + "\x04icon\x18\x02 \x01(\v2\x19.c1.connector.v2.AssetRefR\x04icon\x12-\n" + @@ -1448,7 +1546,7 @@ const file_c1_connector_v2_annotation_trait_proto_rawDesc = "" + "identityIdB6Z4github.com/conductorone/baton-sdk/pb/c1/connector/v2b\x06proto3" var file_c1_connector_v2_annotation_trait_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_c1_connector_v2_annotation_trait_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_c1_connector_v2_annotation_trait_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_c1_connector_v2_annotation_trait_proto_goTypes = []any{ (UserTrait_AccountType)(0), // 0: c1.connector.v2.UserTrait.AccountType (UserTrait_Status_Status)(0), // 1: c1.connector.v2.UserTrait.Status.Status @@ -1456,48 +1554,51 @@ var file_c1_connector_v2_annotation_trait_proto_goTypes = []any{ (*UserTrait)(nil), // 3: c1.connector.v2.UserTrait (*GroupTrait)(nil), // 4: c1.connector.v2.GroupTrait (*RoleTrait)(nil), // 5: c1.connector.v2.RoleTrait - (*AppTrait)(nil), // 6: c1.connector.v2.AppTrait - (*SecretTrait)(nil), // 7: c1.connector.v2.SecretTrait - (*UserTrait_Email)(nil), // 8: c1.connector.v2.UserTrait.Email - (*UserTrait_Status)(nil), // 9: c1.connector.v2.UserTrait.Status - (*UserTrait_MFAStatus)(nil), // 10: c1.connector.v2.UserTrait.MFAStatus - (*UserTrait_SSOStatus)(nil), // 11: c1.connector.v2.UserTrait.SSOStatus - (*UserTrait_StructuredName)(nil), // 12: c1.connector.v2.UserTrait.StructuredName - (*structpb.Struct)(nil), // 13: google.protobuf.Struct - (*AssetRef)(nil), // 14: c1.connector.v2.AssetRef - (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp - (*ResourceId)(nil), // 16: c1.connector.v2.ResourceId + (*RoleScopeTrait)(nil), // 6: c1.connector.v2.RoleScopeTrait + (*AppTrait)(nil), // 7: c1.connector.v2.AppTrait + (*SecretTrait)(nil), // 8: c1.connector.v2.SecretTrait + (*UserTrait_Email)(nil), // 9: c1.connector.v2.UserTrait.Email + (*UserTrait_Status)(nil), // 10: c1.connector.v2.UserTrait.Status + (*UserTrait_MFAStatus)(nil), // 11: c1.connector.v2.UserTrait.MFAStatus + (*UserTrait_SSOStatus)(nil), // 12: c1.connector.v2.UserTrait.SSOStatus + (*UserTrait_StructuredName)(nil), // 13: c1.connector.v2.UserTrait.StructuredName + (*structpb.Struct)(nil), // 14: google.protobuf.Struct + (*AssetRef)(nil), // 15: c1.connector.v2.AssetRef + (*timestamppb.Timestamp)(nil), // 16: google.protobuf.Timestamp + (*ResourceId)(nil), // 17: c1.connector.v2.ResourceId } var file_c1_connector_v2_annotation_trait_proto_depIdxs = []int32{ - 8, // 0: c1.connector.v2.UserTrait.emails:type_name -> c1.connector.v2.UserTrait.Email - 9, // 1: c1.connector.v2.UserTrait.status:type_name -> c1.connector.v2.UserTrait.Status - 13, // 2: c1.connector.v2.UserTrait.profile:type_name -> google.protobuf.Struct - 14, // 3: c1.connector.v2.UserTrait.icon:type_name -> c1.connector.v2.AssetRef + 9, // 0: c1.connector.v2.UserTrait.emails:type_name -> c1.connector.v2.UserTrait.Email + 10, // 1: c1.connector.v2.UserTrait.status:type_name -> c1.connector.v2.UserTrait.Status + 14, // 2: c1.connector.v2.UserTrait.profile:type_name -> google.protobuf.Struct + 15, // 3: c1.connector.v2.UserTrait.icon:type_name -> c1.connector.v2.AssetRef 0, // 4: c1.connector.v2.UserTrait.account_type:type_name -> c1.connector.v2.UserTrait.AccountType - 15, // 5: c1.connector.v2.UserTrait.created_at:type_name -> google.protobuf.Timestamp - 15, // 6: c1.connector.v2.UserTrait.last_login:type_name -> google.protobuf.Timestamp - 10, // 7: c1.connector.v2.UserTrait.mfa_status:type_name -> c1.connector.v2.UserTrait.MFAStatus - 11, // 8: c1.connector.v2.UserTrait.sso_status:type_name -> c1.connector.v2.UserTrait.SSOStatus - 12, // 9: c1.connector.v2.UserTrait.structured_name:type_name -> c1.connector.v2.UserTrait.StructuredName - 14, // 10: c1.connector.v2.GroupTrait.icon:type_name -> c1.connector.v2.AssetRef - 13, // 11: c1.connector.v2.GroupTrait.profile:type_name -> google.protobuf.Struct - 13, // 12: c1.connector.v2.RoleTrait.profile:type_name -> google.protobuf.Struct - 14, // 13: c1.connector.v2.AppTrait.icon:type_name -> c1.connector.v2.AssetRef - 14, // 14: c1.connector.v2.AppTrait.logo:type_name -> c1.connector.v2.AssetRef - 13, // 15: c1.connector.v2.AppTrait.profile:type_name -> google.protobuf.Struct - 2, // 16: c1.connector.v2.AppTrait.flags:type_name -> c1.connector.v2.AppTrait.AppFlag - 13, // 17: c1.connector.v2.SecretTrait.profile:type_name -> google.protobuf.Struct - 15, // 18: c1.connector.v2.SecretTrait.created_at:type_name -> google.protobuf.Timestamp - 15, // 19: c1.connector.v2.SecretTrait.expires_at:type_name -> google.protobuf.Timestamp - 15, // 20: c1.connector.v2.SecretTrait.last_used_at:type_name -> google.protobuf.Timestamp - 16, // 21: c1.connector.v2.SecretTrait.created_by_id:type_name -> c1.connector.v2.ResourceId - 16, // 22: c1.connector.v2.SecretTrait.identity_id:type_name -> c1.connector.v2.ResourceId - 1, // 23: c1.connector.v2.UserTrait.Status.status:type_name -> c1.connector.v2.UserTrait.Status.Status - 24, // [24:24] is the sub-list for method output_type - 24, // [24:24] is the sub-list for method input_type - 24, // [24:24] is the sub-list for extension type_name - 24, // [24:24] is the sub-list for extension extendee - 0, // [0:24] is the sub-list for field type_name + 16, // 5: c1.connector.v2.UserTrait.created_at:type_name -> google.protobuf.Timestamp + 16, // 6: c1.connector.v2.UserTrait.last_login:type_name -> google.protobuf.Timestamp + 11, // 7: c1.connector.v2.UserTrait.mfa_status:type_name -> c1.connector.v2.UserTrait.MFAStatus + 12, // 8: c1.connector.v2.UserTrait.sso_status:type_name -> c1.connector.v2.UserTrait.SSOStatus + 13, // 9: c1.connector.v2.UserTrait.structured_name:type_name -> c1.connector.v2.UserTrait.StructuredName + 15, // 10: c1.connector.v2.GroupTrait.icon:type_name -> c1.connector.v2.AssetRef + 14, // 11: c1.connector.v2.GroupTrait.profile:type_name -> google.protobuf.Struct + 14, // 12: c1.connector.v2.RoleTrait.profile:type_name -> google.protobuf.Struct + 17, // 13: c1.connector.v2.RoleScopeTrait.role_id:type_name -> c1.connector.v2.ResourceId + 17, // 14: c1.connector.v2.RoleScopeTrait.scope_resource_id:type_name -> c1.connector.v2.ResourceId + 15, // 15: c1.connector.v2.AppTrait.icon:type_name -> c1.connector.v2.AssetRef + 15, // 16: c1.connector.v2.AppTrait.logo:type_name -> c1.connector.v2.AssetRef + 14, // 17: c1.connector.v2.AppTrait.profile:type_name -> google.protobuf.Struct + 2, // 18: c1.connector.v2.AppTrait.flags:type_name -> c1.connector.v2.AppTrait.AppFlag + 14, // 19: c1.connector.v2.SecretTrait.profile:type_name -> google.protobuf.Struct + 16, // 20: c1.connector.v2.SecretTrait.created_at:type_name -> google.protobuf.Timestamp + 16, // 21: c1.connector.v2.SecretTrait.expires_at:type_name -> google.protobuf.Timestamp + 16, // 22: c1.connector.v2.SecretTrait.last_used_at:type_name -> google.protobuf.Timestamp + 17, // 23: c1.connector.v2.SecretTrait.created_by_id:type_name -> c1.connector.v2.ResourceId + 17, // 24: c1.connector.v2.SecretTrait.identity_id:type_name -> c1.connector.v2.ResourceId + 1, // 25: c1.connector.v2.UserTrait.Status.status:type_name -> c1.connector.v2.UserTrait.Status.Status + 26, // [26:26] is the sub-list for method output_type + 26, // [26:26] is the sub-list for method input_type + 26, // [26:26] is the sub-list for extension type_name + 26, // [26:26] is the sub-list for extension extendee + 0, // [0:26] is the sub-list for field type_name } func init() { file_c1_connector_v2_annotation_trait_proto_init() } @@ -1513,7 +1614,7 @@ func file_c1_connector_v2_annotation_trait_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_c1_connector_v2_annotation_trait_proto_rawDesc), len(file_c1_connector_v2_annotation_trait_proto_rawDesc)), NumEnums: 3, - NumMessages: 10, + NumMessages: 11, NumExtensions: 0, NumServices: 0, }, diff --git a/pb/c1/connector/v2/annotation_trait.pb.validate.go b/pb/c1/connector/v2/annotation_trait.pb.validate.go index a0288dc3b..0356cb6b6 100644 --- a/pb/c1/connector/v2/annotation_trait.pb.validate.go +++ b/pb/c1/connector/v2/annotation_trait.pb.validate.go @@ -709,6 +709,164 @@ var _ interface { ErrorName() string } = RoleTraitValidationError{} +// Validate checks the field values on RoleScopeTrait with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *RoleScopeTrait) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on RoleScopeTrait with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in RoleScopeTraitMultiError, +// or nil if none found. +func (m *RoleScopeTrait) ValidateAll() error { + return m.validate(true) +} + +func (m *RoleScopeTrait) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetRoleId()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, RoleScopeTraitValidationError{ + field: "RoleId", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, RoleScopeTraitValidationError{ + field: "RoleId", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetRoleId()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RoleScopeTraitValidationError{ + field: "RoleId", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if all { + switch v := interface{}(m.GetScopeResourceId()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, RoleScopeTraitValidationError{ + field: "ScopeResourceId", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, RoleScopeTraitValidationError{ + field: "ScopeResourceId", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetScopeResourceId()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RoleScopeTraitValidationError{ + field: "ScopeResourceId", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if len(errors) > 0 { + return RoleScopeTraitMultiError(errors) + } + + return nil +} + +// RoleScopeTraitMultiError is an error wrapping multiple validation errors +// returned by RoleScopeTrait.ValidateAll() if the designated constraints +// aren't met. +type RoleScopeTraitMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m RoleScopeTraitMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m RoleScopeTraitMultiError) AllErrors() []error { return m } + +// RoleScopeTraitValidationError is the validation error returned by +// RoleScopeTrait.Validate if the designated constraints aren't met. +type RoleScopeTraitValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e RoleScopeTraitValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e RoleScopeTraitValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e RoleScopeTraitValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e RoleScopeTraitValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e RoleScopeTraitValidationError) ErrorName() string { return "RoleScopeTraitValidationError" } + +// Error satisfies the builtin error interface +func (e RoleScopeTraitValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRoleScopeTrait.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = RoleScopeTraitValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = RoleScopeTraitValidationError{} + // Validate checks the field values on AppTrait with the rules defined in the // proto definition for this message. If any rules are violated, the first // error encountered is returned, or nil if there are no violations. diff --git a/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go b/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go index c7a4531b7..8ea8a2a14 100644 --- a/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go +++ b/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go @@ -650,6 +650,101 @@ func (b0 RoleTrait_builder) Build() *RoleTrait { return m0 } +// RoleScopeTrait is used to scope a role to a resource or set of resources. +// The scope may be static (determined at crawl time) or dynamic (determined based on conditions). +type RoleScopeTrait struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_RoleId *ResourceId `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3"` + xxx_hidden_ScopeResourceId *ResourceId `protobuf:"bytes,2,opt,name=scope_resource_id,json=scopeResourceId,proto3"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RoleScopeTrait) Reset() { + *x = RoleScopeTrait{} + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoleScopeTrait) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoleScopeTrait) ProtoMessage() {} + +func (x *RoleScopeTrait) ProtoReflect() protoreflect.Message { + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *RoleScopeTrait) GetRoleId() *ResourceId { + if x != nil { + return x.xxx_hidden_RoleId + } + return nil +} + +func (x *RoleScopeTrait) GetScopeResourceId() *ResourceId { + if x != nil { + return x.xxx_hidden_ScopeResourceId + } + return nil +} + +func (x *RoleScopeTrait) SetRoleId(v *ResourceId) { + x.xxx_hidden_RoleId = v +} + +func (x *RoleScopeTrait) SetScopeResourceId(v *ResourceId) { + x.xxx_hidden_ScopeResourceId = v +} + +func (x *RoleScopeTrait) HasRoleId() bool { + if x == nil { + return false + } + return x.xxx_hidden_RoleId != nil +} + +func (x *RoleScopeTrait) HasScopeResourceId() bool { + if x == nil { + return false + } + return x.xxx_hidden_ScopeResourceId != nil +} + +func (x *RoleScopeTrait) ClearRoleId() { + x.xxx_hidden_RoleId = nil +} + +func (x *RoleScopeTrait) ClearScopeResourceId() { + x.xxx_hidden_ScopeResourceId = nil +} + +type RoleScopeTrait_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + RoleId *ResourceId + ScopeResourceId *ResourceId +} + +func (b0 RoleScopeTrait_builder) Build() *RoleScopeTrait { + m0 := &RoleScopeTrait{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_RoleId = b.RoleId + x.xxx_hidden_ScopeResourceId = b.ScopeResourceId + return m0 +} + type AppTrait struct { state protoimpl.MessageState `protogen:"opaque.v1"` xxx_hidden_HelpUrl string `protobuf:"bytes,1,opt,name=help_url,json=helpUrl,proto3"` @@ -663,7 +758,7 @@ type AppTrait struct { func (x *AppTrait) Reset() { *x = AppTrait{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -675,7 +770,7 @@ func (x *AppTrait) String() string { func (*AppTrait) ProtoMessage() {} func (x *AppTrait) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -810,7 +905,7 @@ type SecretTrait struct { func (x *SecretTrait) Reset() { *x = SecretTrait{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -822,7 +917,7 @@ func (x *SecretTrait) String() string { func (*SecretTrait) ProtoMessage() {} func (x *SecretTrait) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -999,7 +1094,7 @@ type UserTrait_Email struct { func (x *UserTrait_Email) Reset() { *x = UserTrait_Email{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1011,7 +1106,7 @@ func (x *UserTrait_Email) String() string { func (*UserTrait_Email) ProtoMessage() {} func (x *UserTrait_Email) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1071,7 +1166,7 @@ type UserTrait_Status struct { func (x *UserTrait_Status) Reset() { *x = UserTrait_Status{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1083,7 +1178,7 @@ func (x *UserTrait_Status) String() string { func (*UserTrait_Status) ProtoMessage() {} func (x *UserTrait_Status) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1141,7 +1236,7 @@ type UserTrait_MFAStatus struct { func (x *UserTrait_MFAStatus) Reset() { *x = UserTrait_MFAStatus{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1153,7 +1248,7 @@ func (x *UserTrait_MFAStatus) String() string { func (*UserTrait_MFAStatus) ProtoMessage() {} func (x *UserTrait_MFAStatus) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1198,7 +1293,7 @@ type UserTrait_SSOStatus struct { func (x *UserTrait_SSOStatus) Reset() { *x = UserTrait_SSOStatus{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1210,7 +1305,7 @@ func (x *UserTrait_SSOStatus) String() string { func (*UserTrait_SSOStatus) ProtoMessage() {} func (x *UserTrait_SSOStatus) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1259,7 +1354,7 @@ type UserTrait_StructuredName struct { func (x *UserTrait_StructuredName) Reset() { *x = UserTrait_StructuredName{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1271,7 +1366,7 @@ func (x *UserTrait_StructuredName) String() string { func (*UserTrait_StructuredName) ProtoMessage() {} func (x *UserTrait_StructuredName) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1420,7 +1515,10 @@ const file_c1_connector_v2_annotation_trait_proto_rawDesc = "" + "\x04icon\x18\x01 \x01(\v2\x19.c1.connector.v2.AssetRefR\x04icon\x121\n" + "\aprofile\x18\x02 \x01(\v2\x17.google.protobuf.StructR\aprofile\">\n" + "\tRoleTrait\x121\n" + - "\aprofile\x18\x01 \x01(\v2\x17.google.protobuf.StructR\aprofile\"\x9a\x03\n" + + "\aprofile\x18\x01 \x01(\v2\x17.google.protobuf.StructR\aprofile\"\x8f\x01\n" + + "\x0eRoleScopeTrait\x124\n" + + "\arole_id\x18\x01 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x06roleId\x12G\n" + + "\x11scope_resource_id\x18\x02 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x0fscopeResourceId\"\x9a\x03\n" + "\bAppTrait\x125\n" + "\bhelp_url\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15 \x01(\x80\b:\bhttps://\xd0\x01\x01\x88\x01\x01R\ahelpUrl\x12-\n" + "\x04icon\x18\x02 \x01(\v2\x19.c1.connector.v2.AssetRefR\x04icon\x12-\n" + @@ -1447,7 +1545,7 @@ const file_c1_connector_v2_annotation_trait_proto_rawDesc = "" + "identityIdB6Z4github.com/conductorone/baton-sdk/pb/c1/connector/v2b\x06proto3" var file_c1_connector_v2_annotation_trait_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_c1_connector_v2_annotation_trait_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_c1_connector_v2_annotation_trait_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_c1_connector_v2_annotation_trait_proto_goTypes = []any{ (UserTrait_AccountType)(0), // 0: c1.connector.v2.UserTrait.AccountType (UserTrait_Status_Status)(0), // 1: c1.connector.v2.UserTrait.Status.Status @@ -1455,48 +1553,51 @@ var file_c1_connector_v2_annotation_trait_proto_goTypes = []any{ (*UserTrait)(nil), // 3: c1.connector.v2.UserTrait (*GroupTrait)(nil), // 4: c1.connector.v2.GroupTrait (*RoleTrait)(nil), // 5: c1.connector.v2.RoleTrait - (*AppTrait)(nil), // 6: c1.connector.v2.AppTrait - (*SecretTrait)(nil), // 7: c1.connector.v2.SecretTrait - (*UserTrait_Email)(nil), // 8: c1.connector.v2.UserTrait.Email - (*UserTrait_Status)(nil), // 9: c1.connector.v2.UserTrait.Status - (*UserTrait_MFAStatus)(nil), // 10: c1.connector.v2.UserTrait.MFAStatus - (*UserTrait_SSOStatus)(nil), // 11: c1.connector.v2.UserTrait.SSOStatus - (*UserTrait_StructuredName)(nil), // 12: c1.connector.v2.UserTrait.StructuredName - (*structpb.Struct)(nil), // 13: google.protobuf.Struct - (*AssetRef)(nil), // 14: c1.connector.v2.AssetRef - (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp - (*ResourceId)(nil), // 16: c1.connector.v2.ResourceId + (*RoleScopeTrait)(nil), // 6: c1.connector.v2.RoleScopeTrait + (*AppTrait)(nil), // 7: c1.connector.v2.AppTrait + (*SecretTrait)(nil), // 8: c1.connector.v2.SecretTrait + (*UserTrait_Email)(nil), // 9: c1.connector.v2.UserTrait.Email + (*UserTrait_Status)(nil), // 10: c1.connector.v2.UserTrait.Status + (*UserTrait_MFAStatus)(nil), // 11: c1.connector.v2.UserTrait.MFAStatus + (*UserTrait_SSOStatus)(nil), // 12: c1.connector.v2.UserTrait.SSOStatus + (*UserTrait_StructuredName)(nil), // 13: c1.connector.v2.UserTrait.StructuredName + (*structpb.Struct)(nil), // 14: google.protobuf.Struct + (*AssetRef)(nil), // 15: c1.connector.v2.AssetRef + (*timestamppb.Timestamp)(nil), // 16: google.protobuf.Timestamp + (*ResourceId)(nil), // 17: c1.connector.v2.ResourceId } var file_c1_connector_v2_annotation_trait_proto_depIdxs = []int32{ - 8, // 0: c1.connector.v2.UserTrait.emails:type_name -> c1.connector.v2.UserTrait.Email - 9, // 1: c1.connector.v2.UserTrait.status:type_name -> c1.connector.v2.UserTrait.Status - 13, // 2: c1.connector.v2.UserTrait.profile:type_name -> google.protobuf.Struct - 14, // 3: c1.connector.v2.UserTrait.icon:type_name -> c1.connector.v2.AssetRef + 9, // 0: c1.connector.v2.UserTrait.emails:type_name -> c1.connector.v2.UserTrait.Email + 10, // 1: c1.connector.v2.UserTrait.status:type_name -> c1.connector.v2.UserTrait.Status + 14, // 2: c1.connector.v2.UserTrait.profile:type_name -> google.protobuf.Struct + 15, // 3: c1.connector.v2.UserTrait.icon:type_name -> c1.connector.v2.AssetRef 0, // 4: c1.connector.v2.UserTrait.account_type:type_name -> c1.connector.v2.UserTrait.AccountType - 15, // 5: c1.connector.v2.UserTrait.created_at:type_name -> google.protobuf.Timestamp - 15, // 6: c1.connector.v2.UserTrait.last_login:type_name -> google.protobuf.Timestamp - 10, // 7: c1.connector.v2.UserTrait.mfa_status:type_name -> c1.connector.v2.UserTrait.MFAStatus - 11, // 8: c1.connector.v2.UserTrait.sso_status:type_name -> c1.connector.v2.UserTrait.SSOStatus - 12, // 9: c1.connector.v2.UserTrait.structured_name:type_name -> c1.connector.v2.UserTrait.StructuredName - 14, // 10: c1.connector.v2.GroupTrait.icon:type_name -> c1.connector.v2.AssetRef - 13, // 11: c1.connector.v2.GroupTrait.profile:type_name -> google.protobuf.Struct - 13, // 12: c1.connector.v2.RoleTrait.profile:type_name -> google.protobuf.Struct - 14, // 13: c1.connector.v2.AppTrait.icon:type_name -> c1.connector.v2.AssetRef - 14, // 14: c1.connector.v2.AppTrait.logo:type_name -> c1.connector.v2.AssetRef - 13, // 15: c1.connector.v2.AppTrait.profile:type_name -> google.protobuf.Struct - 2, // 16: c1.connector.v2.AppTrait.flags:type_name -> c1.connector.v2.AppTrait.AppFlag - 13, // 17: c1.connector.v2.SecretTrait.profile:type_name -> google.protobuf.Struct - 15, // 18: c1.connector.v2.SecretTrait.created_at:type_name -> google.protobuf.Timestamp - 15, // 19: c1.connector.v2.SecretTrait.expires_at:type_name -> google.protobuf.Timestamp - 15, // 20: c1.connector.v2.SecretTrait.last_used_at:type_name -> google.protobuf.Timestamp - 16, // 21: c1.connector.v2.SecretTrait.created_by_id:type_name -> c1.connector.v2.ResourceId - 16, // 22: c1.connector.v2.SecretTrait.identity_id:type_name -> c1.connector.v2.ResourceId - 1, // 23: c1.connector.v2.UserTrait.Status.status:type_name -> c1.connector.v2.UserTrait.Status.Status - 24, // [24:24] is the sub-list for method output_type - 24, // [24:24] is the sub-list for method input_type - 24, // [24:24] is the sub-list for extension type_name - 24, // [24:24] is the sub-list for extension extendee - 0, // [0:24] is the sub-list for field type_name + 16, // 5: c1.connector.v2.UserTrait.created_at:type_name -> google.protobuf.Timestamp + 16, // 6: c1.connector.v2.UserTrait.last_login:type_name -> google.protobuf.Timestamp + 11, // 7: c1.connector.v2.UserTrait.mfa_status:type_name -> c1.connector.v2.UserTrait.MFAStatus + 12, // 8: c1.connector.v2.UserTrait.sso_status:type_name -> c1.connector.v2.UserTrait.SSOStatus + 13, // 9: c1.connector.v2.UserTrait.structured_name:type_name -> c1.connector.v2.UserTrait.StructuredName + 15, // 10: c1.connector.v2.GroupTrait.icon:type_name -> c1.connector.v2.AssetRef + 14, // 11: c1.connector.v2.GroupTrait.profile:type_name -> google.protobuf.Struct + 14, // 12: c1.connector.v2.RoleTrait.profile:type_name -> google.protobuf.Struct + 17, // 13: c1.connector.v2.RoleScopeTrait.role_id:type_name -> c1.connector.v2.ResourceId + 17, // 14: c1.connector.v2.RoleScopeTrait.scope_resource_id:type_name -> c1.connector.v2.ResourceId + 15, // 15: c1.connector.v2.AppTrait.icon:type_name -> c1.connector.v2.AssetRef + 15, // 16: c1.connector.v2.AppTrait.logo:type_name -> c1.connector.v2.AssetRef + 14, // 17: c1.connector.v2.AppTrait.profile:type_name -> google.protobuf.Struct + 2, // 18: c1.connector.v2.AppTrait.flags:type_name -> c1.connector.v2.AppTrait.AppFlag + 14, // 19: c1.connector.v2.SecretTrait.profile:type_name -> google.protobuf.Struct + 16, // 20: c1.connector.v2.SecretTrait.created_at:type_name -> google.protobuf.Timestamp + 16, // 21: c1.connector.v2.SecretTrait.expires_at:type_name -> google.protobuf.Timestamp + 16, // 22: c1.connector.v2.SecretTrait.last_used_at:type_name -> google.protobuf.Timestamp + 17, // 23: c1.connector.v2.SecretTrait.created_by_id:type_name -> c1.connector.v2.ResourceId + 17, // 24: c1.connector.v2.SecretTrait.identity_id:type_name -> c1.connector.v2.ResourceId + 1, // 25: c1.connector.v2.UserTrait.Status.status:type_name -> c1.connector.v2.UserTrait.Status.Status + 26, // [26:26] is the sub-list for method output_type + 26, // [26:26] is the sub-list for method input_type + 26, // [26:26] is the sub-list for extension type_name + 26, // [26:26] is the sub-list for extension extendee + 0, // [0:26] is the sub-list for field type_name } func init() { file_c1_connector_v2_annotation_trait_proto_init() } @@ -1512,7 +1613,7 @@ func file_c1_connector_v2_annotation_trait_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_c1_connector_v2_annotation_trait_proto_rawDesc), len(file_c1_connector_v2_annotation_trait_proto_rawDesc)), NumEnums: 3, - NumMessages: 10, + NumMessages: 11, NumExtensions: 0, NumServices: 0, }, diff --git a/pb/c1/connector/v2/resource.pb.go b/pb/c1/connector/v2/resource.pb.go index e86d89c8b..e39169429 100644 --- a/pb/c1/connector/v2/resource.pb.go +++ b/pb/c1/connector/v2/resource.pb.go @@ -35,6 +35,7 @@ const ( ResourceType_TRAIT_APP ResourceType_Trait = 4 ResourceType_TRAIT_SECRET ResourceType_Trait = 5 ResourceType_TRAIT_SECURITY_INSIGHT ResourceType_Trait = 6 + ResourceType_TRAIT_ROLE_SCOPE ResourceType_Trait = 7 ) // Enum value maps for ResourceType_Trait. @@ -47,6 +48,7 @@ var ( 4: "TRAIT_APP", 5: "TRAIT_SECRET", 6: "TRAIT_SECURITY_INSIGHT", + 7: "TRAIT_ROLE_SCOPE", } ResourceType_Trait_value = map[string]int32{ "TRAIT_UNSPECIFIED": 0, @@ -56,6 +58,7 @@ var ( "TRAIT_APP": 4, "TRAIT_SECRET": 5, "TRAIT_SECURITY_INSIGHT": 6, + "TRAIT_ROLE_SCOPE": 7, } ) @@ -4453,7 +4456,7 @@ var File_c1_connector_v2_resource_proto protoreflect.FileDescriptor const file_c1_connector_v2_resource_proto_rawDesc = "" + "\n" + - "\x1ec1/connector/v2/resource.proto\x12\x0fc1.connector.v2\x1a\x19google/protobuf/any.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x17validate/validate.proto\"\xd1\x03\n" + + "\x1ec1/connector/v2/resource.proto\x12\x0fc1.connector.v2\x1a\x19google/protobuf/any.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x17validate/validate.proto\"\xe7\x03\n" + "\fResourceType\x12\x1a\n" + "\x02id\x18\x01 \x01(\tB\n" + "\xfaB\ar\x05 \x01(\x80\bR\x02id\x120\n" + @@ -4463,7 +4466,7 @@ const file_c1_connector_v2_resource_proto_rawDesc = "" + "\vannotations\x18\x04 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x12/\n" + "\vdescription\x18\x05 \x01(\tB\r\xfaB\n" + "r\b \x01(\x80 \xd0\x01\x01R\vdescription\x12-\n" + - "\x12sourced_externally\x18\x06 \x01(\bR\x11sourcedExternally\"\x8c\x01\n" + + "\x12sourced_externally\x18\x06 \x01(\bR\x11sourcedExternally\"\xa2\x01\n" + "\x05Trait\x12\x15\n" + "\x11TRAIT_UNSPECIFIED\x10\x00\x12\x0e\n" + "\n" + @@ -4473,7 +4476,8 @@ const file_c1_connector_v2_resource_proto_rawDesc = "" + "TRAIT_ROLE\x10\x03\x12\r\n" + "\tTRAIT_APP\x10\x04\x12\x10\n" + "\fTRAIT_SECRET\x10\x05\x12\x1a\n" + - "\x16TRAIT_SECURITY_INSIGHT\x10\x06\"\xa6\x02\n" + + "\x16TRAIT_SECURITY_INSIGHT\x10\x06\x12\x14\n" + + "\x10TRAIT_ROLE_SCOPE\x10\a\"\xa6\x02\n" + ",ResourceTypesServiceListResourceTypesRequest\x121\n" + "\x06parent\x18\x01 \x01(\v2\x19.c1.connector.v2.ResourceR\x06parent\x12'\n" + "\tpage_size\x18\x02 \x01(\rB\n" + diff --git a/pb/c1/connector/v2/resource_protoopaque.pb.go b/pb/c1/connector/v2/resource_protoopaque.pb.go index c2093c67d..2029cf37f 100644 --- a/pb/c1/connector/v2/resource_protoopaque.pb.go +++ b/pb/c1/connector/v2/resource_protoopaque.pb.go @@ -35,6 +35,7 @@ const ( ResourceType_TRAIT_APP ResourceType_Trait = 4 ResourceType_TRAIT_SECRET ResourceType_Trait = 5 ResourceType_TRAIT_SECURITY_INSIGHT ResourceType_Trait = 6 + ResourceType_TRAIT_ROLE_SCOPE ResourceType_Trait = 7 ) // Enum value maps for ResourceType_Trait. @@ -47,6 +48,7 @@ var ( 4: "TRAIT_APP", 5: "TRAIT_SECRET", 6: "TRAIT_SECURITY_INSIGHT", + 7: "TRAIT_ROLE_SCOPE", } ResourceType_Trait_value = map[string]int32{ "TRAIT_UNSPECIFIED": 0, @@ -56,6 +58,7 @@ var ( "TRAIT_APP": 4, "TRAIT_SECRET": 5, "TRAIT_SECURITY_INSIGHT": 6, + "TRAIT_ROLE_SCOPE": 7, } ) @@ -4446,7 +4449,7 @@ var File_c1_connector_v2_resource_proto protoreflect.FileDescriptor const file_c1_connector_v2_resource_proto_rawDesc = "" + "\n" + - "\x1ec1/connector/v2/resource.proto\x12\x0fc1.connector.v2\x1a\x19google/protobuf/any.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x17validate/validate.proto\"\xd1\x03\n" + + "\x1ec1/connector/v2/resource.proto\x12\x0fc1.connector.v2\x1a\x19google/protobuf/any.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x17validate/validate.proto\"\xe7\x03\n" + "\fResourceType\x12\x1a\n" + "\x02id\x18\x01 \x01(\tB\n" + "\xfaB\ar\x05 \x01(\x80\bR\x02id\x120\n" + @@ -4456,7 +4459,7 @@ const file_c1_connector_v2_resource_proto_rawDesc = "" + "\vannotations\x18\x04 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x12/\n" + "\vdescription\x18\x05 \x01(\tB\r\xfaB\n" + "r\b \x01(\x80 \xd0\x01\x01R\vdescription\x12-\n" + - "\x12sourced_externally\x18\x06 \x01(\bR\x11sourcedExternally\"\x8c\x01\n" + + "\x12sourced_externally\x18\x06 \x01(\bR\x11sourcedExternally\"\xa2\x01\n" + "\x05Trait\x12\x15\n" + "\x11TRAIT_UNSPECIFIED\x10\x00\x12\x0e\n" + "\n" + @@ -4466,7 +4469,8 @@ const file_c1_connector_v2_resource_proto_rawDesc = "" + "TRAIT_ROLE\x10\x03\x12\r\n" + "\tTRAIT_APP\x10\x04\x12\x10\n" + "\fTRAIT_SECRET\x10\x05\x12\x1a\n" + - "\x16TRAIT_SECURITY_INSIGHT\x10\x06\"\xa6\x02\n" + + "\x16TRAIT_SECURITY_INSIGHT\x10\x06\x12\x14\n" + + "\x10TRAIT_ROLE_SCOPE\x10\a\"\xa6\x02\n" + ",ResourceTypesServiceListResourceTypesRequest\x121\n" + "\x06parent\x18\x01 \x01(\v2\x19.c1.connector.v2.ResourceR\x06parent\x12'\n" + "\tpage_size\x18\x02 \x01(\rB\n" + diff --git a/pkg/types/resource/resource.go b/pkg/types/resource/resource.go index 33d3f132e..55b94af37 100644 --- a/pkg/types/resource/resource.go +++ b/pkg/types/resource/resource.go @@ -132,6 +132,30 @@ func WithRoleTrait(opts ...RoleTraitOption) ResourceOption { } } +func WithRoleScopeTrait(opts ...RoleScopeTraitOption) ResourceOption { + return func(r *v2.Resource) error { + rt := &v2.RoleScopeTrait{} + + annos := annotations.Annotations(r.GetAnnotations()) + _, err := annos.Pick(rt) + if err != nil { + return err + } + + for _, o := range opts { + err := o(rt) + if err != nil { + return err + } + } + + annos.Update(rt) + r.SetAnnotations(annos) + + return nil + } +} + func WithAppTrait(opts ...AppTraitOption) ResourceOption { return func(r *v2.Resource) error { at := &v2.AppTrait{} @@ -304,6 +328,24 @@ func NewRoleResource( return ret, nil } +// NewRoleScopeResource returns a new resource instance with a configured role scope trait. +func NewRoleScopeResource( + name string, + resourceType *v2.ResourceType, + objectID interface{}, + roleScopeOpts []RoleScopeTraitOption, + opts ...ResourceOption, +) (*v2.Resource, error) { + opts = append(opts, WithRoleScopeTrait(roleScopeOpts...)) + + ret, err := NewResource(name, resourceType, objectID, opts...) + if err != nil { + return nil, err + } + + return ret, nil +} + // NewAppResource returns a new resource instance with a configured app trait. // The trait is configured with the provided helpURL and profile. func NewAppResource( diff --git a/pkg/types/resource/role_scope_trait.go b/pkg/types/resource/role_scope_trait.go new file mode 100644 index 000000000..c0ff81462 --- /dev/null +++ b/pkg/types/resource/role_scope_trait.go @@ -0,0 +1,41 @@ +package resource + +import ( + "fmt" + + v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2" + "github.com/conductorone/baton-sdk/pkg/annotations" +) + +type RoleScopeTraitOption func(rs *v2.RoleScopeTrait) error + +// WithRoleScopeRoleId sets the role of role scope. +func WithRoleScopeRoleId(resourceId *v2.ResourceId) RoleScopeTraitOption { + return func(rs *v2.RoleScopeTrait) error { + rs.RoleId = resourceId + return nil + } +} + +// WithRoleScopeResourceId sets the resource scope of role scope. +func WithRoleScopeResourceId(resourceId *v2.ResourceId) RoleScopeTraitOption { + return func(rs *v2.RoleScopeTrait) error { + rs.ScopeResourceId = resourceId + return nil + } +} + +// GetRoleScopeTrait attempts to return the RoleScopeTrait instance on a resource. +func GetRoleScopeTrait(resource *v2.Resource) (*v2.RoleScopeTrait, error) { + ret := &v2.RoleScopeTrait{} + annos := annotations.Annotations(resource.GetAnnotations()) + ok, err := annos.Pick(ret) + if err != nil { + return nil, err + } + if !ok { + return nil, fmt.Errorf("role scope trait was not found on resource") + } + + return ret, nil +} diff --git a/proto/c1/connector/v2/annotation_resource.proto b/proto/c1/connector/v2/annotation_resource.proto new file mode 100644 index 000000000..dba8d4cab --- /dev/null +++ b/proto/c1/connector/v2/annotation_resource.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +package c1.connector.v2; + +option go_package = "github.com/conductorone/baton-sdk/pb/c1/connector/v2"; + +// Resource was not deleted because the resource does not exist. +message ResourceDoesNotExist {} diff --git a/proto/c1/connector/v2/annotation_trait.proto b/proto/c1/connector/v2/annotation_trait.proto index e607acbc0..735d5618e 100644 --- a/proto/c1/connector/v2/annotation_trait.proto +++ b/proto/c1/connector/v2/annotation_trait.proto @@ -82,6 +82,15 @@ message RoleTrait { google.protobuf.Struct profile = 1; } +// RoleScopeTrait is used to scope a role to a resource or set of resources. +// The scope may be static (determined at crawl time) or dynamic (determined based on conditions). +message RoleScopeTrait { + c1.connector.v2.ResourceId role_id = 1; // The role that is scoped. + c1.connector.v2.ResourceId scope_resource_id = 2; // The resource that the role is scoped to. + // TODO: Add support for conditions. + // TODO: Add support for start/end times. +} + message AppTrait { string help_url = 1 [(validate.rules).string = { min_bytes: 1 diff --git a/proto/c1/connector/v2/resource.proto b/proto/c1/connector/v2/resource.proto index a4a8ba06a..56079437c 100644 --- a/proto/c1/connector/v2/resource.proto +++ b/proto/c1/connector/v2/resource.proto @@ -31,6 +31,7 @@ message ResourceType { TRAIT_APP = 4; TRAIT_SECRET = 5; TRAIT_SECURITY_INSIGHT = 6; + TRAIT_ROLE_SCOPE = 7; } repeated Trait traits = 3 [(validate.rules).repeated = { unique: true From 35046fd4303cdb15d3cd0cac08e5dbec9c68653e Mon Sep 17 00:00:00 2001 From: Geoff Greer Date: Thu, 22 Jan 2026 13:57:23 -0800 Subject: [PATCH 02/10] Add role scope conditions. --- pb/c1/connector/v2/annotation_trait.pb.go | 301 +++++++++++++---- .../v2/annotation_trait.pb.validate.go | 271 ++++++++++++++++ .../v2/annotation_trait_protoopaque.pb.go | 303 ++++++++++++++---- pkg/types/resource/role_trait.go | 16 + proto/c1/connector/v2/annotation_trait.proto | 10 + 5 files changed, 767 insertions(+), 134 deletions(-) diff --git a/pb/c1/connector/v2/annotation_trait.pb.go b/pb/c1/connector/v2/annotation_trait.pb.go index 9b8ac73fe..391f0c9e5 100644 --- a/pb/c1/connector/v2/annotation_trait.pb.go +++ b/pb/c1/connector/v2/annotation_trait.pb.go @@ -583,10 +583,11 @@ func (b0 GroupTrait_builder) Build() *GroupTrait { } type RoleTrait struct { - state protoimpl.MessageState `protogen:"hybrid.v1"` - Profile *structpb.Struct `protobuf:"bytes,1,opt,name=profile,proto3" json:"profile,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"hybrid.v1"` + Profile *structpb.Struct `protobuf:"bytes,1,opt,name=profile,proto3" json:"profile,omitempty"` + RoleScopeConditions *RoleScopeConditions `protobuf:"bytes,2,opt,name=role_scope_conditions,json=roleScopeConditions,proto3" json:"role_scope_conditions,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RoleTrait) Reset() { @@ -621,10 +622,21 @@ func (x *RoleTrait) GetProfile() *structpb.Struct { return nil } +func (x *RoleTrait) GetRoleScopeConditions() *RoleScopeConditions { + if x != nil { + return x.RoleScopeConditions + } + return nil +} + func (x *RoleTrait) SetProfile(v *structpb.Struct) { x.Profile = v } +func (x *RoleTrait) SetRoleScopeConditions(v *RoleScopeConditions) { + x.RoleScopeConditions = v +} + func (x *RoleTrait) HasProfile() bool { if x == nil { return false @@ -632,14 +644,26 @@ func (x *RoleTrait) HasProfile() bool { return x.Profile != nil } +func (x *RoleTrait) HasRoleScopeConditions() bool { + if x == nil { + return false + } + return x.RoleScopeConditions != nil +} + func (x *RoleTrait) ClearProfile() { x.Profile = nil } +func (x *RoleTrait) ClearRoleScopeConditions() { + x.RoleScopeConditions = nil +} + type RoleTrait_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - Profile *structpb.Struct + Profile *structpb.Struct + RoleScopeConditions *RoleScopeConditions } func (b0 RoleTrait_builder) Build() *RoleTrait { @@ -647,6 +671,135 @@ func (b0 RoleTrait_builder) Build() *RoleTrait { b, x := &b0, m0 _, _ = b, x x.Profile = b.Profile + x.RoleScopeConditions = b.RoleScopeConditions + return m0 +} + +type RoleScopeConditions struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + Conditions []*RoleScopeCondition `protobuf:"bytes,3,rep,name=conditions,proto3" json:"conditions,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RoleScopeConditions) Reset() { + *x = RoleScopeConditions{} + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoleScopeConditions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoleScopeConditions) ProtoMessage() {} + +func (x *RoleScopeConditions) ProtoReflect() protoreflect.Message { + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *RoleScopeConditions) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *RoleScopeConditions) GetConditions() []*RoleScopeCondition { + if x != nil { + return x.Conditions + } + return nil +} + +func (x *RoleScopeConditions) SetType(v string) { + x.Type = v +} + +func (x *RoleScopeConditions) SetConditions(v []*RoleScopeCondition) { + x.Conditions = v +} + +type RoleScopeConditions_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Type string + Conditions []*RoleScopeCondition +} + +func (b0 RoleScopeConditions_builder) Build() *RoleScopeConditions { + m0 := &RoleScopeConditions{} + b, x := &b0, m0 + _, _ = b, x + x.Type = b.Type + x.Conditions = b.Conditions + return m0 +} + +type RoleScopeCondition struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + Expression string `protobuf:"bytes,1,opt,name=expression,proto3" json:"expression,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RoleScopeCondition) Reset() { + *x = RoleScopeCondition{} + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoleScopeCondition) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoleScopeCondition) ProtoMessage() {} + +func (x *RoleScopeCondition) ProtoReflect() protoreflect.Message { + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *RoleScopeCondition) GetExpression() string { + if x != nil { + return x.Expression + } + return "" +} + +func (x *RoleScopeCondition) SetExpression(v string) { + x.Expression = v +} + +type RoleScopeCondition_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Expression string +} + +func (b0 RoleScopeCondition_builder) Build() *RoleScopeCondition { + m0 := &RoleScopeCondition{} + b, x := &b0, m0 + _, _ = b, x + x.Expression = b.Expression return m0 } @@ -662,7 +815,7 @@ type RoleScopeTrait struct { func (x *RoleScopeTrait) Reset() { *x = RoleScopeTrait{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -674,7 +827,7 @@ func (x *RoleScopeTrait) String() string { func (*RoleScopeTrait) ProtoMessage() {} func (x *RoleScopeTrait) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -758,7 +911,7 @@ type AppTrait struct { func (x *AppTrait) Reset() { *x = AppTrait{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -770,7 +923,7 @@ func (x *AppTrait) String() string { func (*AppTrait) ProtoMessage() {} func (x *AppTrait) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -905,7 +1058,7 @@ type SecretTrait struct { func (x *SecretTrait) Reset() { *x = SecretTrait{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -917,7 +1070,7 @@ func (x *SecretTrait) String() string { func (*SecretTrait) ProtoMessage() {} func (x *SecretTrait) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1095,7 +1248,7 @@ type UserTrait_Email struct { func (x *UserTrait_Email) Reset() { *x = UserTrait_Email{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1107,7 +1260,7 @@ func (x *UserTrait_Email) String() string { func (*UserTrait_Email) ProtoMessage() {} func (x *UserTrait_Email) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1167,7 +1320,7 @@ type UserTrait_Status struct { func (x *UserTrait_Status) Reset() { *x = UserTrait_Status{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1179,7 +1332,7 @@ func (x *UserTrait_Status) String() string { func (*UserTrait_Status) ProtoMessage() {} func (x *UserTrait_Status) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1237,7 +1390,7 @@ type UserTrait_MFAStatus struct { func (x *UserTrait_MFAStatus) Reset() { *x = UserTrait_MFAStatus{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1249,7 +1402,7 @@ func (x *UserTrait_MFAStatus) String() string { func (*UserTrait_MFAStatus) ProtoMessage() {} func (x *UserTrait_MFAStatus) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1294,7 +1447,7 @@ type UserTrait_SSOStatus struct { func (x *UserTrait_SSOStatus) Reset() { *x = UserTrait_SSOStatus{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1306,7 +1459,7 @@ func (x *UserTrait_SSOStatus) String() string { func (*UserTrait_SSOStatus) ProtoMessage() {} func (x *UserTrait_SSOStatus) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1355,7 +1508,7 @@ type UserTrait_StructuredName struct { func (x *UserTrait_StructuredName) Reset() { *x = UserTrait_StructuredName{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[10] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1367,7 +1520,7 @@ func (x *UserTrait_StructuredName) String() string { func (*UserTrait_StructuredName) ProtoMessage() {} func (x *UserTrait_StructuredName) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[10] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1514,9 +1667,19 @@ const file_c1_connector_v2_annotation_trait_proto_rawDesc = "" + "\n" + "GroupTrait\x12-\n" + "\x04icon\x18\x01 \x01(\v2\x19.c1.connector.v2.AssetRefR\x04icon\x121\n" + - "\aprofile\x18\x02 \x01(\v2\x17.google.protobuf.StructR\aprofile\">\n" + + "\aprofile\x18\x02 \x01(\v2\x17.google.protobuf.StructR\aprofile\"\x98\x01\n" + "\tRoleTrait\x121\n" + - "\aprofile\x18\x01 \x01(\v2\x17.google.protobuf.StructR\aprofile\"\x8f\x01\n" + + "\aprofile\x18\x01 \x01(\v2\x17.google.protobuf.StructR\aprofile\x12X\n" + + "\x15role_scope_conditions\x18\x02 \x01(\v2$.c1.connector.v2.RoleScopeConditionsR\x13roleScopeConditions\"n\n" + + "\x13RoleScopeConditions\x12\x12\n" + + "\x04type\x18\x01 \x01(\tR\x04type\x12C\n" + + "\n" + + "conditions\x18\x03 \x03(\v2#.c1.connector.v2.RoleScopeConditionR\n" + + "conditions\"4\n" + + "\x12RoleScopeCondition\x12\x1e\n" + + "\n" + + "expression\x18\x01 \x01(\tR\n" + + "expression\"\x8f\x01\n" + "\x0eRoleScopeTrait\x124\n" + "\arole_id\x18\x01 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x06roleId\x12G\n" + "\x11scope_resource_id\x18\x02 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x0fscopeResourceId\"\x9a\x03\n" + @@ -1546,7 +1709,7 @@ const file_c1_connector_v2_annotation_trait_proto_rawDesc = "" + "identityIdB6Z4github.com/conductorone/baton-sdk/pb/c1/connector/v2b\x06proto3" var file_c1_connector_v2_annotation_trait_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_c1_connector_v2_annotation_trait_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_c1_connector_v2_annotation_trait_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_c1_connector_v2_annotation_trait_proto_goTypes = []any{ (UserTrait_AccountType)(0), // 0: c1.connector.v2.UserTrait.AccountType (UserTrait_Status_Status)(0), // 1: c1.connector.v2.UserTrait.Status.Status @@ -1554,51 +1717,55 @@ var file_c1_connector_v2_annotation_trait_proto_goTypes = []any{ (*UserTrait)(nil), // 3: c1.connector.v2.UserTrait (*GroupTrait)(nil), // 4: c1.connector.v2.GroupTrait (*RoleTrait)(nil), // 5: c1.connector.v2.RoleTrait - (*RoleScopeTrait)(nil), // 6: c1.connector.v2.RoleScopeTrait - (*AppTrait)(nil), // 7: c1.connector.v2.AppTrait - (*SecretTrait)(nil), // 8: c1.connector.v2.SecretTrait - (*UserTrait_Email)(nil), // 9: c1.connector.v2.UserTrait.Email - (*UserTrait_Status)(nil), // 10: c1.connector.v2.UserTrait.Status - (*UserTrait_MFAStatus)(nil), // 11: c1.connector.v2.UserTrait.MFAStatus - (*UserTrait_SSOStatus)(nil), // 12: c1.connector.v2.UserTrait.SSOStatus - (*UserTrait_StructuredName)(nil), // 13: c1.connector.v2.UserTrait.StructuredName - (*structpb.Struct)(nil), // 14: google.protobuf.Struct - (*AssetRef)(nil), // 15: c1.connector.v2.AssetRef - (*timestamppb.Timestamp)(nil), // 16: google.protobuf.Timestamp - (*ResourceId)(nil), // 17: c1.connector.v2.ResourceId + (*RoleScopeConditions)(nil), // 6: c1.connector.v2.RoleScopeConditions + (*RoleScopeCondition)(nil), // 7: c1.connector.v2.RoleScopeCondition + (*RoleScopeTrait)(nil), // 8: c1.connector.v2.RoleScopeTrait + (*AppTrait)(nil), // 9: c1.connector.v2.AppTrait + (*SecretTrait)(nil), // 10: c1.connector.v2.SecretTrait + (*UserTrait_Email)(nil), // 11: c1.connector.v2.UserTrait.Email + (*UserTrait_Status)(nil), // 12: c1.connector.v2.UserTrait.Status + (*UserTrait_MFAStatus)(nil), // 13: c1.connector.v2.UserTrait.MFAStatus + (*UserTrait_SSOStatus)(nil), // 14: c1.connector.v2.UserTrait.SSOStatus + (*UserTrait_StructuredName)(nil), // 15: c1.connector.v2.UserTrait.StructuredName + (*structpb.Struct)(nil), // 16: google.protobuf.Struct + (*AssetRef)(nil), // 17: c1.connector.v2.AssetRef + (*timestamppb.Timestamp)(nil), // 18: google.protobuf.Timestamp + (*ResourceId)(nil), // 19: c1.connector.v2.ResourceId } var file_c1_connector_v2_annotation_trait_proto_depIdxs = []int32{ - 9, // 0: c1.connector.v2.UserTrait.emails:type_name -> c1.connector.v2.UserTrait.Email - 10, // 1: c1.connector.v2.UserTrait.status:type_name -> c1.connector.v2.UserTrait.Status - 14, // 2: c1.connector.v2.UserTrait.profile:type_name -> google.protobuf.Struct - 15, // 3: c1.connector.v2.UserTrait.icon:type_name -> c1.connector.v2.AssetRef + 11, // 0: c1.connector.v2.UserTrait.emails:type_name -> c1.connector.v2.UserTrait.Email + 12, // 1: c1.connector.v2.UserTrait.status:type_name -> c1.connector.v2.UserTrait.Status + 16, // 2: c1.connector.v2.UserTrait.profile:type_name -> google.protobuf.Struct + 17, // 3: c1.connector.v2.UserTrait.icon:type_name -> c1.connector.v2.AssetRef 0, // 4: c1.connector.v2.UserTrait.account_type:type_name -> c1.connector.v2.UserTrait.AccountType - 16, // 5: c1.connector.v2.UserTrait.created_at:type_name -> google.protobuf.Timestamp - 16, // 6: c1.connector.v2.UserTrait.last_login:type_name -> google.protobuf.Timestamp - 11, // 7: c1.connector.v2.UserTrait.mfa_status:type_name -> c1.connector.v2.UserTrait.MFAStatus - 12, // 8: c1.connector.v2.UserTrait.sso_status:type_name -> c1.connector.v2.UserTrait.SSOStatus - 13, // 9: c1.connector.v2.UserTrait.structured_name:type_name -> c1.connector.v2.UserTrait.StructuredName - 15, // 10: c1.connector.v2.GroupTrait.icon:type_name -> c1.connector.v2.AssetRef - 14, // 11: c1.connector.v2.GroupTrait.profile:type_name -> google.protobuf.Struct - 14, // 12: c1.connector.v2.RoleTrait.profile:type_name -> google.protobuf.Struct - 17, // 13: c1.connector.v2.RoleScopeTrait.role_id:type_name -> c1.connector.v2.ResourceId - 17, // 14: c1.connector.v2.RoleScopeTrait.scope_resource_id:type_name -> c1.connector.v2.ResourceId - 15, // 15: c1.connector.v2.AppTrait.icon:type_name -> c1.connector.v2.AssetRef - 15, // 16: c1.connector.v2.AppTrait.logo:type_name -> c1.connector.v2.AssetRef - 14, // 17: c1.connector.v2.AppTrait.profile:type_name -> google.protobuf.Struct - 2, // 18: c1.connector.v2.AppTrait.flags:type_name -> c1.connector.v2.AppTrait.AppFlag - 14, // 19: c1.connector.v2.SecretTrait.profile:type_name -> google.protobuf.Struct - 16, // 20: c1.connector.v2.SecretTrait.created_at:type_name -> google.protobuf.Timestamp - 16, // 21: c1.connector.v2.SecretTrait.expires_at:type_name -> google.protobuf.Timestamp - 16, // 22: c1.connector.v2.SecretTrait.last_used_at:type_name -> google.protobuf.Timestamp - 17, // 23: c1.connector.v2.SecretTrait.created_by_id:type_name -> c1.connector.v2.ResourceId - 17, // 24: c1.connector.v2.SecretTrait.identity_id:type_name -> c1.connector.v2.ResourceId - 1, // 25: c1.connector.v2.UserTrait.Status.status:type_name -> c1.connector.v2.UserTrait.Status.Status - 26, // [26:26] is the sub-list for method output_type - 26, // [26:26] is the sub-list for method input_type - 26, // [26:26] is the sub-list for extension type_name - 26, // [26:26] is the sub-list for extension extendee - 0, // [0:26] is the sub-list for field type_name + 18, // 5: c1.connector.v2.UserTrait.created_at:type_name -> google.protobuf.Timestamp + 18, // 6: c1.connector.v2.UserTrait.last_login:type_name -> google.protobuf.Timestamp + 13, // 7: c1.connector.v2.UserTrait.mfa_status:type_name -> c1.connector.v2.UserTrait.MFAStatus + 14, // 8: c1.connector.v2.UserTrait.sso_status:type_name -> c1.connector.v2.UserTrait.SSOStatus + 15, // 9: c1.connector.v2.UserTrait.structured_name:type_name -> c1.connector.v2.UserTrait.StructuredName + 17, // 10: c1.connector.v2.GroupTrait.icon:type_name -> c1.connector.v2.AssetRef + 16, // 11: c1.connector.v2.GroupTrait.profile:type_name -> google.protobuf.Struct + 16, // 12: c1.connector.v2.RoleTrait.profile:type_name -> google.protobuf.Struct + 6, // 13: c1.connector.v2.RoleTrait.role_scope_conditions:type_name -> c1.connector.v2.RoleScopeConditions + 7, // 14: c1.connector.v2.RoleScopeConditions.conditions:type_name -> c1.connector.v2.RoleScopeCondition + 19, // 15: c1.connector.v2.RoleScopeTrait.role_id:type_name -> c1.connector.v2.ResourceId + 19, // 16: c1.connector.v2.RoleScopeTrait.scope_resource_id:type_name -> c1.connector.v2.ResourceId + 17, // 17: c1.connector.v2.AppTrait.icon:type_name -> c1.connector.v2.AssetRef + 17, // 18: c1.connector.v2.AppTrait.logo:type_name -> c1.connector.v2.AssetRef + 16, // 19: c1.connector.v2.AppTrait.profile:type_name -> google.protobuf.Struct + 2, // 20: c1.connector.v2.AppTrait.flags:type_name -> c1.connector.v2.AppTrait.AppFlag + 16, // 21: c1.connector.v2.SecretTrait.profile:type_name -> google.protobuf.Struct + 18, // 22: c1.connector.v2.SecretTrait.created_at:type_name -> google.protobuf.Timestamp + 18, // 23: c1.connector.v2.SecretTrait.expires_at:type_name -> google.protobuf.Timestamp + 18, // 24: c1.connector.v2.SecretTrait.last_used_at:type_name -> google.protobuf.Timestamp + 19, // 25: c1.connector.v2.SecretTrait.created_by_id:type_name -> c1.connector.v2.ResourceId + 19, // 26: c1.connector.v2.SecretTrait.identity_id:type_name -> c1.connector.v2.ResourceId + 1, // 27: c1.connector.v2.UserTrait.Status.status:type_name -> c1.connector.v2.UserTrait.Status.Status + 28, // [28:28] is the sub-list for method output_type + 28, // [28:28] is the sub-list for method input_type + 28, // [28:28] is the sub-list for extension type_name + 28, // [28:28] is the sub-list for extension extendee + 0, // [0:28] is the sub-list for field type_name } func init() { file_c1_connector_v2_annotation_trait_proto_init() } @@ -1614,7 +1781,7 @@ func file_c1_connector_v2_annotation_trait_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_c1_connector_v2_annotation_trait_proto_rawDesc), len(file_c1_connector_v2_annotation_trait_proto_rawDesc)), NumEnums: 3, - NumMessages: 11, + NumMessages: 13, NumExtensions: 0, NumServices: 0, }, diff --git a/pb/c1/connector/v2/annotation_trait.pb.validate.go b/pb/c1/connector/v2/annotation_trait.pb.validate.go index 0356cb6b6..71cc30c52 100644 --- a/pb/c1/connector/v2/annotation_trait.pb.validate.go +++ b/pb/c1/connector/v2/annotation_trait.pb.validate.go @@ -632,6 +632,35 @@ func (m *RoleTrait) validate(all bool) error { } } + if all { + switch v := interface{}(m.GetRoleScopeConditions()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, RoleTraitValidationError{ + field: "RoleScopeConditions", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, RoleTraitValidationError{ + field: "RoleScopeConditions", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetRoleScopeConditions()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RoleTraitValidationError{ + field: "RoleScopeConditions", + reason: "embedded message failed validation", + cause: err, + } + } + } + if len(errors) > 0 { return RoleTraitMultiError(errors) } @@ -709,6 +738,248 @@ var _ interface { ErrorName() string } = RoleTraitValidationError{} +// Validate checks the field values on RoleScopeConditions with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *RoleScopeConditions) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on RoleScopeConditions with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// RoleScopeConditionsMultiError, or nil if none found. +func (m *RoleScopeConditions) ValidateAll() error { + return m.validate(true) +} + +func (m *RoleScopeConditions) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Type + + for idx, item := range m.GetConditions() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, RoleScopeConditionsValidationError{ + field: fmt.Sprintf("Conditions[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, RoleScopeConditionsValidationError{ + field: fmt.Sprintf("Conditions[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RoleScopeConditionsValidationError{ + field: fmt.Sprintf("Conditions[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return RoleScopeConditionsMultiError(errors) + } + + return nil +} + +// RoleScopeConditionsMultiError is an error wrapping multiple validation +// errors returned by RoleScopeConditions.ValidateAll() if the designated +// constraints aren't met. +type RoleScopeConditionsMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m RoleScopeConditionsMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m RoleScopeConditionsMultiError) AllErrors() []error { return m } + +// RoleScopeConditionsValidationError is the validation error returned by +// RoleScopeConditions.Validate if the designated constraints aren't met. +type RoleScopeConditionsValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e RoleScopeConditionsValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e RoleScopeConditionsValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e RoleScopeConditionsValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e RoleScopeConditionsValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e RoleScopeConditionsValidationError) ErrorName() string { + return "RoleScopeConditionsValidationError" +} + +// Error satisfies the builtin error interface +func (e RoleScopeConditionsValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRoleScopeConditions.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = RoleScopeConditionsValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = RoleScopeConditionsValidationError{} + +// Validate checks the field values on RoleScopeCondition with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *RoleScopeCondition) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on RoleScopeCondition with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// RoleScopeConditionMultiError, or nil if none found. +func (m *RoleScopeCondition) ValidateAll() error { + return m.validate(true) +} + +func (m *RoleScopeCondition) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Expression + + if len(errors) > 0 { + return RoleScopeConditionMultiError(errors) + } + + return nil +} + +// RoleScopeConditionMultiError is an error wrapping multiple validation errors +// returned by RoleScopeCondition.ValidateAll() if the designated constraints +// aren't met. +type RoleScopeConditionMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m RoleScopeConditionMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m RoleScopeConditionMultiError) AllErrors() []error { return m } + +// RoleScopeConditionValidationError is the validation error returned by +// RoleScopeCondition.Validate if the designated constraints aren't met. +type RoleScopeConditionValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e RoleScopeConditionValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e RoleScopeConditionValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e RoleScopeConditionValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e RoleScopeConditionValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e RoleScopeConditionValidationError) ErrorName() string { + return "RoleScopeConditionValidationError" +} + +// Error satisfies the builtin error interface +func (e RoleScopeConditionValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRoleScopeCondition.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = RoleScopeConditionValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = RoleScopeConditionValidationError{} + // Validate checks the field values on RoleScopeTrait with the rules defined in // the proto definition for this message. If any rules are violated, the first // error encountered is returned, or nil if there are no violations. diff --git a/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go b/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go index 8ea8a2a14..575a796a9 100644 --- a/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go +++ b/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go @@ -583,10 +583,11 @@ func (b0 GroupTrait_builder) Build() *GroupTrait { } type RoleTrait struct { - state protoimpl.MessageState `protogen:"opaque.v1"` - xxx_hidden_Profile *structpb.Struct `protobuf:"bytes,1,opt,name=profile,proto3"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Profile *structpb.Struct `protobuf:"bytes,1,opt,name=profile,proto3"` + xxx_hidden_RoleScopeConditions *RoleScopeConditions `protobuf:"bytes,2,opt,name=role_scope_conditions,json=roleScopeConditions,proto3"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RoleTrait) Reset() { @@ -621,10 +622,21 @@ func (x *RoleTrait) GetProfile() *structpb.Struct { return nil } +func (x *RoleTrait) GetRoleScopeConditions() *RoleScopeConditions { + if x != nil { + return x.xxx_hidden_RoleScopeConditions + } + return nil +} + func (x *RoleTrait) SetProfile(v *structpb.Struct) { x.xxx_hidden_Profile = v } +func (x *RoleTrait) SetRoleScopeConditions(v *RoleScopeConditions) { + x.xxx_hidden_RoleScopeConditions = v +} + func (x *RoleTrait) HasProfile() bool { if x == nil { return false @@ -632,14 +644,26 @@ func (x *RoleTrait) HasProfile() bool { return x.xxx_hidden_Profile != nil } +func (x *RoleTrait) HasRoleScopeConditions() bool { + if x == nil { + return false + } + return x.xxx_hidden_RoleScopeConditions != nil +} + func (x *RoleTrait) ClearProfile() { x.xxx_hidden_Profile = nil } +func (x *RoleTrait) ClearRoleScopeConditions() { + x.xxx_hidden_RoleScopeConditions = nil +} + type RoleTrait_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - Profile *structpb.Struct + Profile *structpb.Struct + RoleScopeConditions *RoleScopeConditions } func (b0 RoleTrait_builder) Build() *RoleTrait { @@ -647,6 +671,137 @@ func (b0 RoleTrait_builder) Build() *RoleTrait { b, x := &b0, m0 _, _ = b, x x.xxx_hidden_Profile = b.Profile + x.xxx_hidden_RoleScopeConditions = b.RoleScopeConditions + return m0 +} + +type RoleScopeConditions struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Type string `protobuf:"bytes,1,opt,name=type,proto3"` + xxx_hidden_Conditions *[]*RoleScopeCondition `protobuf:"bytes,3,rep,name=conditions,proto3"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RoleScopeConditions) Reset() { + *x = RoleScopeConditions{} + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoleScopeConditions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoleScopeConditions) ProtoMessage() {} + +func (x *RoleScopeConditions) ProtoReflect() protoreflect.Message { + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *RoleScopeConditions) GetType() string { + if x != nil { + return x.xxx_hidden_Type + } + return "" +} + +func (x *RoleScopeConditions) GetConditions() []*RoleScopeCondition { + if x != nil { + if x.xxx_hidden_Conditions != nil { + return *x.xxx_hidden_Conditions + } + } + return nil +} + +func (x *RoleScopeConditions) SetType(v string) { + x.xxx_hidden_Type = v +} + +func (x *RoleScopeConditions) SetConditions(v []*RoleScopeCondition) { + x.xxx_hidden_Conditions = &v +} + +type RoleScopeConditions_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Type string + Conditions []*RoleScopeCondition +} + +func (b0 RoleScopeConditions_builder) Build() *RoleScopeConditions { + m0 := &RoleScopeConditions{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Type = b.Type + x.xxx_hidden_Conditions = &b.Conditions + return m0 +} + +type RoleScopeCondition struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Expression string `protobuf:"bytes,1,opt,name=expression,proto3"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RoleScopeCondition) Reset() { + *x = RoleScopeCondition{} + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoleScopeCondition) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoleScopeCondition) ProtoMessage() {} + +func (x *RoleScopeCondition) ProtoReflect() protoreflect.Message { + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *RoleScopeCondition) GetExpression() string { + if x != nil { + return x.xxx_hidden_Expression + } + return "" +} + +func (x *RoleScopeCondition) SetExpression(v string) { + x.xxx_hidden_Expression = v +} + +type RoleScopeCondition_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Expression string +} + +func (b0 RoleScopeCondition_builder) Build() *RoleScopeCondition { + m0 := &RoleScopeCondition{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Expression = b.Expression return m0 } @@ -662,7 +817,7 @@ type RoleScopeTrait struct { func (x *RoleScopeTrait) Reset() { *x = RoleScopeTrait{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -674,7 +829,7 @@ func (x *RoleScopeTrait) String() string { func (*RoleScopeTrait) ProtoMessage() {} func (x *RoleScopeTrait) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[3] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -758,7 +913,7 @@ type AppTrait struct { func (x *AppTrait) Reset() { *x = AppTrait{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -770,7 +925,7 @@ func (x *AppTrait) String() string { func (*AppTrait) ProtoMessage() {} func (x *AppTrait) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[4] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -905,7 +1060,7 @@ type SecretTrait struct { func (x *SecretTrait) Reset() { *x = SecretTrait{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -917,7 +1072,7 @@ func (x *SecretTrait) String() string { func (*SecretTrait) ProtoMessage() {} func (x *SecretTrait) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1094,7 +1249,7 @@ type UserTrait_Email struct { func (x *UserTrait_Email) Reset() { *x = UserTrait_Email{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1106,7 +1261,7 @@ func (x *UserTrait_Email) String() string { func (*UserTrait_Email) ProtoMessage() {} func (x *UserTrait_Email) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[6] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1166,7 +1321,7 @@ type UserTrait_Status struct { func (x *UserTrait_Status) Reset() { *x = UserTrait_Status{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1178,7 +1333,7 @@ func (x *UserTrait_Status) String() string { func (*UserTrait_Status) ProtoMessage() {} func (x *UserTrait_Status) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[7] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1236,7 +1391,7 @@ type UserTrait_MFAStatus struct { func (x *UserTrait_MFAStatus) Reset() { *x = UserTrait_MFAStatus{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1248,7 +1403,7 @@ func (x *UserTrait_MFAStatus) String() string { func (*UserTrait_MFAStatus) ProtoMessage() {} func (x *UserTrait_MFAStatus) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[8] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1293,7 +1448,7 @@ type UserTrait_SSOStatus struct { func (x *UserTrait_SSOStatus) Reset() { *x = UserTrait_SSOStatus{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1305,7 +1460,7 @@ func (x *UserTrait_SSOStatus) String() string { func (*UserTrait_SSOStatus) ProtoMessage() {} func (x *UserTrait_SSOStatus) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[9] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1354,7 +1509,7 @@ type UserTrait_StructuredName struct { func (x *UserTrait_StructuredName) Reset() { *x = UserTrait_StructuredName{} - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[10] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1366,7 +1521,7 @@ func (x *UserTrait_StructuredName) String() string { func (*UserTrait_StructuredName) ProtoMessage() {} func (x *UserTrait_StructuredName) ProtoReflect() protoreflect.Message { - mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[10] + mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1513,9 +1668,19 @@ const file_c1_connector_v2_annotation_trait_proto_rawDesc = "" + "\n" + "GroupTrait\x12-\n" + "\x04icon\x18\x01 \x01(\v2\x19.c1.connector.v2.AssetRefR\x04icon\x121\n" + - "\aprofile\x18\x02 \x01(\v2\x17.google.protobuf.StructR\aprofile\">\n" + + "\aprofile\x18\x02 \x01(\v2\x17.google.protobuf.StructR\aprofile\"\x98\x01\n" + "\tRoleTrait\x121\n" + - "\aprofile\x18\x01 \x01(\v2\x17.google.protobuf.StructR\aprofile\"\x8f\x01\n" + + "\aprofile\x18\x01 \x01(\v2\x17.google.protobuf.StructR\aprofile\x12X\n" + + "\x15role_scope_conditions\x18\x02 \x01(\v2$.c1.connector.v2.RoleScopeConditionsR\x13roleScopeConditions\"n\n" + + "\x13RoleScopeConditions\x12\x12\n" + + "\x04type\x18\x01 \x01(\tR\x04type\x12C\n" + + "\n" + + "conditions\x18\x03 \x03(\v2#.c1.connector.v2.RoleScopeConditionR\n" + + "conditions\"4\n" + + "\x12RoleScopeCondition\x12\x1e\n" + + "\n" + + "expression\x18\x01 \x01(\tR\n" + + "expression\"\x8f\x01\n" + "\x0eRoleScopeTrait\x124\n" + "\arole_id\x18\x01 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x06roleId\x12G\n" + "\x11scope_resource_id\x18\x02 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x0fscopeResourceId\"\x9a\x03\n" + @@ -1545,7 +1710,7 @@ const file_c1_connector_v2_annotation_trait_proto_rawDesc = "" + "identityIdB6Z4github.com/conductorone/baton-sdk/pb/c1/connector/v2b\x06proto3" var file_c1_connector_v2_annotation_trait_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_c1_connector_v2_annotation_trait_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_c1_connector_v2_annotation_trait_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_c1_connector_v2_annotation_trait_proto_goTypes = []any{ (UserTrait_AccountType)(0), // 0: c1.connector.v2.UserTrait.AccountType (UserTrait_Status_Status)(0), // 1: c1.connector.v2.UserTrait.Status.Status @@ -1553,51 +1718,55 @@ var file_c1_connector_v2_annotation_trait_proto_goTypes = []any{ (*UserTrait)(nil), // 3: c1.connector.v2.UserTrait (*GroupTrait)(nil), // 4: c1.connector.v2.GroupTrait (*RoleTrait)(nil), // 5: c1.connector.v2.RoleTrait - (*RoleScopeTrait)(nil), // 6: c1.connector.v2.RoleScopeTrait - (*AppTrait)(nil), // 7: c1.connector.v2.AppTrait - (*SecretTrait)(nil), // 8: c1.connector.v2.SecretTrait - (*UserTrait_Email)(nil), // 9: c1.connector.v2.UserTrait.Email - (*UserTrait_Status)(nil), // 10: c1.connector.v2.UserTrait.Status - (*UserTrait_MFAStatus)(nil), // 11: c1.connector.v2.UserTrait.MFAStatus - (*UserTrait_SSOStatus)(nil), // 12: c1.connector.v2.UserTrait.SSOStatus - (*UserTrait_StructuredName)(nil), // 13: c1.connector.v2.UserTrait.StructuredName - (*structpb.Struct)(nil), // 14: google.protobuf.Struct - (*AssetRef)(nil), // 15: c1.connector.v2.AssetRef - (*timestamppb.Timestamp)(nil), // 16: google.protobuf.Timestamp - (*ResourceId)(nil), // 17: c1.connector.v2.ResourceId + (*RoleScopeConditions)(nil), // 6: c1.connector.v2.RoleScopeConditions + (*RoleScopeCondition)(nil), // 7: c1.connector.v2.RoleScopeCondition + (*RoleScopeTrait)(nil), // 8: c1.connector.v2.RoleScopeTrait + (*AppTrait)(nil), // 9: c1.connector.v2.AppTrait + (*SecretTrait)(nil), // 10: c1.connector.v2.SecretTrait + (*UserTrait_Email)(nil), // 11: c1.connector.v2.UserTrait.Email + (*UserTrait_Status)(nil), // 12: c1.connector.v2.UserTrait.Status + (*UserTrait_MFAStatus)(nil), // 13: c1.connector.v2.UserTrait.MFAStatus + (*UserTrait_SSOStatus)(nil), // 14: c1.connector.v2.UserTrait.SSOStatus + (*UserTrait_StructuredName)(nil), // 15: c1.connector.v2.UserTrait.StructuredName + (*structpb.Struct)(nil), // 16: google.protobuf.Struct + (*AssetRef)(nil), // 17: c1.connector.v2.AssetRef + (*timestamppb.Timestamp)(nil), // 18: google.protobuf.Timestamp + (*ResourceId)(nil), // 19: c1.connector.v2.ResourceId } var file_c1_connector_v2_annotation_trait_proto_depIdxs = []int32{ - 9, // 0: c1.connector.v2.UserTrait.emails:type_name -> c1.connector.v2.UserTrait.Email - 10, // 1: c1.connector.v2.UserTrait.status:type_name -> c1.connector.v2.UserTrait.Status - 14, // 2: c1.connector.v2.UserTrait.profile:type_name -> google.protobuf.Struct - 15, // 3: c1.connector.v2.UserTrait.icon:type_name -> c1.connector.v2.AssetRef + 11, // 0: c1.connector.v2.UserTrait.emails:type_name -> c1.connector.v2.UserTrait.Email + 12, // 1: c1.connector.v2.UserTrait.status:type_name -> c1.connector.v2.UserTrait.Status + 16, // 2: c1.connector.v2.UserTrait.profile:type_name -> google.protobuf.Struct + 17, // 3: c1.connector.v2.UserTrait.icon:type_name -> c1.connector.v2.AssetRef 0, // 4: c1.connector.v2.UserTrait.account_type:type_name -> c1.connector.v2.UserTrait.AccountType - 16, // 5: c1.connector.v2.UserTrait.created_at:type_name -> google.protobuf.Timestamp - 16, // 6: c1.connector.v2.UserTrait.last_login:type_name -> google.protobuf.Timestamp - 11, // 7: c1.connector.v2.UserTrait.mfa_status:type_name -> c1.connector.v2.UserTrait.MFAStatus - 12, // 8: c1.connector.v2.UserTrait.sso_status:type_name -> c1.connector.v2.UserTrait.SSOStatus - 13, // 9: c1.connector.v2.UserTrait.structured_name:type_name -> c1.connector.v2.UserTrait.StructuredName - 15, // 10: c1.connector.v2.GroupTrait.icon:type_name -> c1.connector.v2.AssetRef - 14, // 11: c1.connector.v2.GroupTrait.profile:type_name -> google.protobuf.Struct - 14, // 12: c1.connector.v2.RoleTrait.profile:type_name -> google.protobuf.Struct - 17, // 13: c1.connector.v2.RoleScopeTrait.role_id:type_name -> c1.connector.v2.ResourceId - 17, // 14: c1.connector.v2.RoleScopeTrait.scope_resource_id:type_name -> c1.connector.v2.ResourceId - 15, // 15: c1.connector.v2.AppTrait.icon:type_name -> c1.connector.v2.AssetRef - 15, // 16: c1.connector.v2.AppTrait.logo:type_name -> c1.connector.v2.AssetRef - 14, // 17: c1.connector.v2.AppTrait.profile:type_name -> google.protobuf.Struct - 2, // 18: c1.connector.v2.AppTrait.flags:type_name -> c1.connector.v2.AppTrait.AppFlag - 14, // 19: c1.connector.v2.SecretTrait.profile:type_name -> google.protobuf.Struct - 16, // 20: c1.connector.v2.SecretTrait.created_at:type_name -> google.protobuf.Timestamp - 16, // 21: c1.connector.v2.SecretTrait.expires_at:type_name -> google.protobuf.Timestamp - 16, // 22: c1.connector.v2.SecretTrait.last_used_at:type_name -> google.protobuf.Timestamp - 17, // 23: c1.connector.v2.SecretTrait.created_by_id:type_name -> c1.connector.v2.ResourceId - 17, // 24: c1.connector.v2.SecretTrait.identity_id:type_name -> c1.connector.v2.ResourceId - 1, // 25: c1.connector.v2.UserTrait.Status.status:type_name -> c1.connector.v2.UserTrait.Status.Status - 26, // [26:26] is the sub-list for method output_type - 26, // [26:26] is the sub-list for method input_type - 26, // [26:26] is the sub-list for extension type_name - 26, // [26:26] is the sub-list for extension extendee - 0, // [0:26] is the sub-list for field type_name + 18, // 5: c1.connector.v2.UserTrait.created_at:type_name -> google.protobuf.Timestamp + 18, // 6: c1.connector.v2.UserTrait.last_login:type_name -> google.protobuf.Timestamp + 13, // 7: c1.connector.v2.UserTrait.mfa_status:type_name -> c1.connector.v2.UserTrait.MFAStatus + 14, // 8: c1.connector.v2.UserTrait.sso_status:type_name -> c1.connector.v2.UserTrait.SSOStatus + 15, // 9: c1.connector.v2.UserTrait.structured_name:type_name -> c1.connector.v2.UserTrait.StructuredName + 17, // 10: c1.connector.v2.GroupTrait.icon:type_name -> c1.connector.v2.AssetRef + 16, // 11: c1.connector.v2.GroupTrait.profile:type_name -> google.protobuf.Struct + 16, // 12: c1.connector.v2.RoleTrait.profile:type_name -> google.protobuf.Struct + 6, // 13: c1.connector.v2.RoleTrait.role_scope_conditions:type_name -> c1.connector.v2.RoleScopeConditions + 7, // 14: c1.connector.v2.RoleScopeConditions.conditions:type_name -> c1.connector.v2.RoleScopeCondition + 19, // 15: c1.connector.v2.RoleScopeTrait.role_id:type_name -> c1.connector.v2.ResourceId + 19, // 16: c1.connector.v2.RoleScopeTrait.scope_resource_id:type_name -> c1.connector.v2.ResourceId + 17, // 17: c1.connector.v2.AppTrait.icon:type_name -> c1.connector.v2.AssetRef + 17, // 18: c1.connector.v2.AppTrait.logo:type_name -> c1.connector.v2.AssetRef + 16, // 19: c1.connector.v2.AppTrait.profile:type_name -> google.protobuf.Struct + 2, // 20: c1.connector.v2.AppTrait.flags:type_name -> c1.connector.v2.AppTrait.AppFlag + 16, // 21: c1.connector.v2.SecretTrait.profile:type_name -> google.protobuf.Struct + 18, // 22: c1.connector.v2.SecretTrait.created_at:type_name -> google.protobuf.Timestamp + 18, // 23: c1.connector.v2.SecretTrait.expires_at:type_name -> google.protobuf.Timestamp + 18, // 24: c1.connector.v2.SecretTrait.last_used_at:type_name -> google.protobuf.Timestamp + 19, // 25: c1.connector.v2.SecretTrait.created_by_id:type_name -> c1.connector.v2.ResourceId + 19, // 26: c1.connector.v2.SecretTrait.identity_id:type_name -> c1.connector.v2.ResourceId + 1, // 27: c1.connector.v2.UserTrait.Status.status:type_name -> c1.connector.v2.UserTrait.Status.Status + 28, // [28:28] is the sub-list for method output_type + 28, // [28:28] is the sub-list for method input_type + 28, // [28:28] is the sub-list for extension type_name + 28, // [28:28] is the sub-list for extension extendee + 0, // [0:28] is the sub-list for field type_name } func init() { file_c1_connector_v2_annotation_trait_proto_init() } @@ -1613,7 +1782,7 @@ func file_c1_connector_v2_annotation_trait_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_c1_connector_v2_annotation_trait_proto_rawDesc), len(file_c1_connector_v2_annotation_trait_proto_rawDesc)), NumEnums: 3, - NumMessages: 11, + NumMessages: 13, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/types/resource/role_trait.go b/pkg/types/resource/role_trait.go index bc5341335..51631a16c 100644 --- a/pkg/types/resource/role_trait.go +++ b/pkg/types/resource/role_trait.go @@ -23,6 +23,22 @@ func WithRoleProfile(profile map[string]interface{}) RoleTraitOption { } } +func WithRoleScopeConditions(typ string, conditions []string) RoleTraitOption { + return func(rt *v2.RoleTrait) error { + rt.RoleScopeConditions = &v2.RoleScopeConditions{ + Type: typ, + Conditions: make([]*v2.RoleScopeCondition, len(conditions)), + } + for i, condition := range conditions { + rt.RoleScopeConditions.Conditions[i] = &v2.RoleScopeCondition{ + Expression: condition, + } + } + + return nil + } +} + // NewRoleTrait creates a new `RoleTrait` with the provided profile. func NewRoleTrait(opts ...RoleTraitOption) (*v2.RoleTrait, error) { groupTrait := &v2.RoleTrait{} diff --git a/proto/c1/connector/v2/annotation_trait.proto b/proto/c1/connector/v2/annotation_trait.proto index 735d5618e..5eb6bd3e1 100644 --- a/proto/c1/connector/v2/annotation_trait.proto +++ b/proto/c1/connector/v2/annotation_trait.proto @@ -80,6 +80,16 @@ message GroupTrait { message RoleTrait { google.protobuf.Struct profile = 1; + RoleScopeConditions role_scope_conditions = 2; +} + +message RoleScopeConditions { + string type = 1; + repeated RoleScopeCondition conditions = 3; +} + +message RoleScopeCondition { + string expression = 1; } // RoleScopeTrait is used to scope a role to a resource or set of resources. From 87a3209d694532996b62f72f16f7b9af38c86126 Mon Sep 17 00:00:00 2001 From: Geoff Greer Date: Thu, 22 Jan 2026 13:57:36 -0800 Subject: [PATCH 03/10] Protofmt. --- proto/c1/connector/v2/annotation_resource_tree.proto | 2 +- proto/c1/connector/v2/annotation_security_insight.proto | 1 - proto/c1/connector/v2/connector.proto | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/proto/c1/connector/v2/annotation_resource_tree.proto b/proto/c1/connector/v2/annotation_resource_tree.proto index 678bfcf3d..d50d255e1 100644 --- a/proto/c1/connector/v2/annotation_resource_tree.proto +++ b/proto/c1/connector/v2/annotation_resource_tree.proto @@ -12,4 +12,4 @@ message SkipEntitlementsAndGrants {} message SkipGrants {} -message SkipEntitlements {} \ No newline at end of file +message SkipEntitlements {} diff --git a/proto/c1/connector/v2/annotation_security_insight.proto b/proto/c1/connector/v2/annotation_security_insight.proto index 91bb9c68f..2b30ed970 100644 --- a/proto/c1/connector/v2/annotation_security_insight.proto +++ b/proto/c1/connector/v2/annotation_security_insight.proto @@ -38,7 +38,6 @@ message SecurityInsightTrait { // When this insight was observed/captured from the source system google.protobuf.Timestamp observed_at = 3; - // The target entity this insight should be bound to oneof target { option (validate.required) = true; diff --git a/proto/c1/connector/v2/connector.proto b/proto/c1/connector/v2/connector.proto index 5199ddbcd..be80cce00 100644 --- a/proto/c1/connector/v2/connector.proto +++ b/proto/c1/connector/v2/connector.proto @@ -67,7 +67,7 @@ enum Capability { CAPABILITY_ACTIONS = 10; CAPABILITY_TARGETED_SYNC = 11; CAPABILITY_EVENT_FEED_V2 = 12; - CAPABILITY_SERVICE_MODE_TARGETED_SYNC = 13; + CAPABILITY_SERVICE_MODE_TARGETED_SYNC = 13; } enum CapabilityDetailCredentialOption { From db04ed978009697d840e9bb7387f3cd22f6ecf7b Mon Sep 17 00:00:00 2001 From: Geoff Greer Date: Mon, 26 Jan 2026 10:42:42 -0800 Subject: [PATCH 04/10] Clean up comments on RoleScopeTrait. --- proto/c1/connector/v2/annotation_trait.proto | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/proto/c1/connector/v2/annotation_trait.proto b/proto/c1/connector/v2/annotation_trait.proto index 5eb6bd3e1..595a62397 100644 --- a/proto/c1/connector/v2/annotation_trait.proto +++ b/proto/c1/connector/v2/annotation_trait.proto @@ -95,10 +95,8 @@ message RoleScopeCondition { // RoleScopeTrait is used to scope a role to a resource or set of resources. // The scope may be static (determined at crawl time) or dynamic (determined based on conditions). message RoleScopeTrait { - c1.connector.v2.ResourceId role_id = 1; // The role that is scoped. + c1.connector.v2.ResourceId role_id = 1; // The role that is scoped. Must be a resource with the role trait. c1.connector.v2.ResourceId scope_resource_id = 2; // The resource that the role is scoped to. - // TODO: Add support for conditions. - // TODO: Add support for start/end times. } message AppTrait { From f4ae82b0bb91a61245ac6c9ea2fd2d4ca17f2329 Mon Sep 17 00:00:00 2001 From: Geoff Greer Date: Mon, 26 Jan 2026 10:43:07 -0800 Subject: [PATCH 05/10] Deprecate ExternalID and CreationSource. They are no longer used. --- proto/c1/connector/v2/resource.proto | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/proto/c1/connector/v2/resource.proto b/proto/c1/connector/v2/resource.proto index 56079437c..3e164a3e4 100644 --- a/proto/c1/connector/v2/resource.proto +++ b/proto/c1/connector/v2/resource.proto @@ -307,10 +307,11 @@ message Resource { ignore_empty: true }]; bool baton_resource = 6; - ExternalId external_id = 7; - CreationSource creation_source = 8; + // Deprecated. This is no longer used. + ExternalId external_id = 7 [deprecated = true]; + // Deprecated. This is no longer used. + CreationSource creation_source = 8 [deprecated = true]; - // FIXME(mstanbCO): call this something else? Should it just be a bool? Possibly just use an annotation? enum CreationSource { CREATION_SOURCE_UNSPECIFIED = 0; CREATION_SOURCE_CONNECTOR_LIST_RESOURCES = 1; From 5e8e5a5eea3b775fc5632e0b4a18bfcfdb242f99 Mon Sep 17 00:00:00 2001 From: Geoff Greer Date: Mon, 26 Jan 2026 10:43:14 -0800 Subject: [PATCH 06/10] Protogen. --- pb/c1/connector/v2/annotation_trait.pb.go | 2 +- pb/c1/connector/v2/resource.pb.go | 55 ++++++++++++------- pb/c1/connector/v2/resource_protoopaque.pb.go | 27 ++++++--- 3 files changed, 56 insertions(+), 28 deletions(-) diff --git a/pb/c1/connector/v2/annotation_trait.pb.go b/pb/c1/connector/v2/annotation_trait.pb.go index 391f0c9e5..b05887d15 100644 --- a/pb/c1/connector/v2/annotation_trait.pb.go +++ b/pb/c1/connector/v2/annotation_trait.pb.go @@ -807,7 +807,7 @@ func (b0 RoleScopeCondition_builder) Build() *RoleScopeCondition { // The scope may be static (determined at crawl time) or dynamic (determined based on conditions). type RoleScopeTrait struct { state protoimpl.MessageState `protogen:"hybrid.v1"` - RoleId *ResourceId `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"` // The role that is scoped. + RoleId *ResourceId `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"` // The role that is scoped. Must be a resource with the role trait. ScopeResourceId *ResourceId `protobuf:"bytes,2,opt,name=scope_resource_id,json=scopeResourceId,proto3" json:"scope_resource_id,omitempty"` // The resource that the role is scoped to. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache diff --git a/pb/c1/connector/v2/resource.pb.go b/pb/c1/connector/v2/resource.pb.go index e39169429..0c04503a8 100644 --- a/pb/c1/connector/v2/resource.pb.go +++ b/pb/c1/connector/v2/resource.pb.go @@ -84,7 +84,6 @@ func (x ResourceType_Trait) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } -// FIXME(mstanbCO): call this something else? Should it just be a bool? Possibly just use an annotation? type Resource_CreationSource int32 const ( @@ -2823,17 +2822,23 @@ func (b0 ResourceId_builder) Build() *ResourceId { } type Resource struct { - state protoimpl.MessageState `protogen:"hybrid.v1"` - Id *ResourceId `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - ParentResourceId *ResourceId `protobuf:"bytes,2,opt,name=parent_resource_id,json=parentResourceId,proto3" json:"parent_resource_id,omitempty"` - DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` - Annotations []*anypb.Any `protobuf:"bytes,4,rep,name=annotations,proto3" json:"annotations,omitempty"` - Description string `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"` - BatonResource bool `protobuf:"varint,6,opt,name=baton_resource,json=batonResource,proto3" json:"baton_resource,omitempty"` - ExternalId *ExternalId `protobuf:"bytes,7,opt,name=external_id,json=externalId,proto3" json:"external_id,omitempty"` - CreationSource Resource_CreationSource `protobuf:"varint,8,opt,name=creation_source,json=creationSource,proto3,enum=c1.connector.v2.Resource_CreationSource" json:"creation_source,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"hybrid.v1"` + Id *ResourceId `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + ParentResourceId *ResourceId `protobuf:"bytes,2,opt,name=parent_resource_id,json=parentResourceId,proto3" json:"parent_resource_id,omitempty"` + DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` + Annotations []*anypb.Any `protobuf:"bytes,4,rep,name=annotations,proto3" json:"annotations,omitempty"` + Description string `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"` + BatonResource bool `protobuf:"varint,6,opt,name=baton_resource,json=batonResource,proto3" json:"baton_resource,omitempty"` + // Deprecated. This is no longer used. + // + // Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. + ExternalId *ExternalId `protobuf:"bytes,7,opt,name=external_id,json=externalId,proto3" json:"external_id,omitempty"` + // Deprecated. This is no longer used. + // + // Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. + CreationSource Resource_CreationSource `protobuf:"varint,8,opt,name=creation_source,json=creationSource,proto3,enum=c1.connector.v2.Resource_CreationSource" json:"creation_source,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Resource) Reset() { @@ -2903,6 +2908,7 @@ func (x *Resource) GetBatonResource() bool { return false } +// Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. func (x *Resource) GetExternalId() *ExternalId { if x != nil { return x.ExternalId @@ -2910,6 +2916,7 @@ func (x *Resource) GetExternalId() *ExternalId { return nil } +// Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. func (x *Resource) GetCreationSource() Resource_CreationSource { if x != nil { return x.CreationSource @@ -2941,10 +2948,12 @@ func (x *Resource) SetBatonResource(v bool) { x.BatonResource = v } +// Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. func (x *Resource) SetExternalId(v *ExternalId) { x.ExternalId = v } +// Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. func (x *Resource) SetCreationSource(v Resource_CreationSource) { x.CreationSource = v } @@ -2963,6 +2972,7 @@ func (x *Resource) HasParentResourceId() bool { return x.ParentResourceId != nil } +// Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. func (x *Resource) HasExternalId() bool { if x == nil { return false @@ -2978,6 +2988,7 @@ func (x *Resource) ClearParentResourceId() { x.ParentResourceId = nil } +// Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. func (x *Resource) ClearExternalId() { x.ExternalId = nil } @@ -2991,8 +3002,14 @@ type Resource_builder struct { Annotations []*anypb.Any Description string BatonResource bool - ExternalId *ExternalId - CreationSource Resource_CreationSource + // Deprecated. This is no longer used. + // + // Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. + ExternalId *ExternalId + // Deprecated. This is no longer used. + // + // Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. + CreationSource Resource_CreationSource } func (b0 Resource_builder) Build() *Resource { @@ -4619,7 +4636,7 @@ const file_c1_connector_v2_resource_proto_rawDesc = "" + "\xfaB\ar\x05 \x01(\x80\bR\fresourceType\x12&\n" + "\bresource\x18\x02 \x01(\tB\n" + "\xfaB\ar\x05 \x01(\x80\bR\bresource\x12%\n" + - "\x0ebaton_resource\x18\x03 \x01(\bR\rbatonResource\"\xf0\x04\n" + + "\x0ebaton_resource\x18\x03 \x01(\bR\rbatonResource\"\xf8\x04\n" + "\bResource\x12+\n" + "\x02id\x18\x01 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x02id\x12I\n" + "\x12parent_resource_id\x18\x02 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x10parentResourceId\x120\n" + @@ -4628,10 +4645,10 @@ const file_c1_connector_v2_resource_proto_rawDesc = "" + "\vannotations\x18\x04 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x12/\n" + "\vdescription\x18\x05 \x01(\tB\r\xfaB\n" + "r\b \x01(\x80\x10\xd0\x01\x01R\vdescription\x12%\n" + - "\x0ebaton_resource\x18\x06 \x01(\bR\rbatonResource\x12<\n" + - "\vexternal_id\x18\a \x01(\v2\x1b.c1.connector.v2.ExternalIdR\n" + - "externalId\x12Q\n" + - "\x0fcreation_source\x18\b \x01(\x0e2(.c1.connector.v2.Resource.CreationSourceR\x0ecreationSource\"\x98\x01\n" + + "\x0ebaton_resource\x18\x06 \x01(\bR\rbatonResource\x12@\n" + + "\vexternal_id\x18\a \x01(\v2\x1b.c1.connector.v2.ExternalIdB\x02\x18\x01R\n" + + "externalId\x12U\n" + + "\x0fcreation_source\x18\b \x01(\x0e2(.c1.connector.v2.Resource.CreationSourceB\x02\x18\x01R\x0ecreationSource\"\x98\x01\n" + "\x0eCreationSource\x12\x1f\n" + "\x1bCREATION_SOURCE_UNSPECIFIED\x10\x00\x12,\n" + "(CREATION_SOURCE_CONNECTOR_LIST_RESOURCES\x10\x01\x127\n" + diff --git a/pb/c1/connector/v2/resource_protoopaque.pb.go b/pb/c1/connector/v2/resource_protoopaque.pb.go index 2029cf37f..8b448661c 100644 --- a/pb/c1/connector/v2/resource_protoopaque.pb.go +++ b/pb/c1/connector/v2/resource_protoopaque.pb.go @@ -84,7 +84,6 @@ func (x ResourceType_Trait) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } -// FIXME(mstanbCO): call this something else? Should it just be a bool? Possibly just use an annotation? type Resource_CreationSource int32 const ( @@ -2881,6 +2880,7 @@ func (x *Resource) GetBatonResource() bool { return false } +// Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. func (x *Resource) GetExternalId() *ExternalId { if x != nil { return x.xxx_hidden_ExternalId @@ -2888,6 +2888,7 @@ func (x *Resource) GetExternalId() *ExternalId { return nil } +// Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. func (x *Resource) GetCreationSource() Resource_CreationSource { if x != nil { return x.xxx_hidden_CreationSource @@ -2919,10 +2920,12 @@ func (x *Resource) SetBatonResource(v bool) { x.xxx_hidden_BatonResource = v } +// Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. func (x *Resource) SetExternalId(v *ExternalId) { x.xxx_hidden_ExternalId = v } +// Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. func (x *Resource) SetCreationSource(v Resource_CreationSource) { x.xxx_hidden_CreationSource = v } @@ -2941,6 +2944,7 @@ func (x *Resource) HasParentResourceId() bool { return x.xxx_hidden_ParentResourceId != nil } +// Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. func (x *Resource) HasExternalId() bool { if x == nil { return false @@ -2956,6 +2960,7 @@ func (x *Resource) ClearParentResourceId() { x.xxx_hidden_ParentResourceId = nil } +// Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. func (x *Resource) ClearExternalId() { x.xxx_hidden_ExternalId = nil } @@ -2969,8 +2974,14 @@ type Resource_builder struct { Annotations []*anypb.Any Description string BatonResource bool - ExternalId *ExternalId - CreationSource Resource_CreationSource + // Deprecated. This is no longer used. + // + // Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. + ExternalId *ExternalId + // Deprecated. This is no longer used. + // + // Deprecated: Marked as deprecated in c1/connector/v2/resource.proto. + CreationSource Resource_CreationSource } func (b0 Resource_builder) Build() *Resource { @@ -4612,7 +4623,7 @@ const file_c1_connector_v2_resource_proto_rawDesc = "" + "\xfaB\ar\x05 \x01(\x80\bR\fresourceType\x12&\n" + "\bresource\x18\x02 \x01(\tB\n" + "\xfaB\ar\x05 \x01(\x80\bR\bresource\x12%\n" + - "\x0ebaton_resource\x18\x03 \x01(\bR\rbatonResource\"\xf0\x04\n" + + "\x0ebaton_resource\x18\x03 \x01(\bR\rbatonResource\"\xf8\x04\n" + "\bResource\x12+\n" + "\x02id\x18\x01 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x02id\x12I\n" + "\x12parent_resource_id\x18\x02 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x10parentResourceId\x120\n" + @@ -4621,10 +4632,10 @@ const file_c1_connector_v2_resource_proto_rawDesc = "" + "\vannotations\x18\x04 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x12/\n" + "\vdescription\x18\x05 \x01(\tB\r\xfaB\n" + "r\b \x01(\x80\x10\xd0\x01\x01R\vdescription\x12%\n" + - "\x0ebaton_resource\x18\x06 \x01(\bR\rbatonResource\x12<\n" + - "\vexternal_id\x18\a \x01(\v2\x1b.c1.connector.v2.ExternalIdR\n" + - "externalId\x12Q\n" + - "\x0fcreation_source\x18\b \x01(\x0e2(.c1.connector.v2.Resource.CreationSourceR\x0ecreationSource\"\x98\x01\n" + + "\x0ebaton_resource\x18\x06 \x01(\bR\rbatonResource\x12@\n" + + "\vexternal_id\x18\a \x01(\v2\x1b.c1.connector.v2.ExternalIdB\x02\x18\x01R\n" + + "externalId\x12U\n" + + "\x0fcreation_source\x18\b \x01(\x0e2(.c1.connector.v2.Resource.CreationSourceB\x02\x18\x01R\x0ecreationSource\"\x98\x01\n" + "\x0eCreationSource\x12\x1f\n" + "\x1bCREATION_SOURCE_UNSPECIFIED\x10\x00\x12,\n" + "(CREATION_SOURCE_CONNECTOR_LIST_RESOURCES\x10\x01\x127\n" + From 9cce1004486c9689e9e842fd8e976e170fcf33da Mon Sep 17 00:00:00 2001 From: Geoff Greer Date: Mon, 26 Jan 2026 10:54:31 -0800 Subject: [PATCH 07/10] Add comments on WithExternalID/WithExternalPrincipalID saying they're deprecated. Error in RoleScopeTrait if invalid/no role/scopes are provided. Fix lint. --- pb/c1/connector/v2/annotation_trait.pb.go | 6 +++--- pb/c1/connector/v2/annotation_trait.pb.validate.go | 11 +++++++++++ .../v2/annotation_trait_protoopaque.pb.go | 6 +++--- pkg/provisioner/provisioner.go | 4 ++-- pkg/sync/syncer.go | 3 --- pkg/types/grant/grant.go | 3 ++- pkg/types/resource/resource.go | 14 +++++++++++++- pkg/types/resource/role_scope_trait.go | 6 +++--- pkg/types/resource/role_trait.go | 6 +++--- proto/c1/connector/v2/annotation_trait.proto | 2 +- 10 files changed, 41 insertions(+), 20 deletions(-) diff --git a/pb/c1/connector/v2/annotation_trait.pb.go b/pb/c1/connector/v2/annotation_trait.pb.go index b05887d15..9ba212407 100644 --- a/pb/c1/connector/v2/annotation_trait.pb.go +++ b/pb/c1/connector/v2/annotation_trait.pb.go @@ -1679,9 +1679,9 @@ const file_c1_connector_v2_annotation_trait_proto_rawDesc = "" + "\x12RoleScopeCondition\x12\x1e\n" + "\n" + "expression\x18\x01 \x01(\tR\n" + - "expression\"\x8f\x01\n" + - "\x0eRoleScopeTrait\x124\n" + - "\arole_id\x18\x01 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x06roleId\x12G\n" + + "expression\"\x99\x01\n" + + "\x0eRoleScopeTrait\x12>\n" + + "\arole_id\x18\x01 \x01(\v2\x1b.c1.connector.v2.ResourceIdB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x06roleId\x12G\n" + "\x11scope_resource_id\x18\x02 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x0fscopeResourceId\"\x9a\x03\n" + "\bAppTrait\x125\n" + "\bhelp_url\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15 \x01(\x80\b:\bhttps://\xd0\x01\x01\x88\x01\x01R\ahelpUrl\x12-\n" + diff --git a/pb/c1/connector/v2/annotation_trait.pb.validate.go b/pb/c1/connector/v2/annotation_trait.pb.validate.go index 71cc30c52..742ef251a 100644 --- a/pb/c1/connector/v2/annotation_trait.pb.validate.go +++ b/pb/c1/connector/v2/annotation_trait.pb.validate.go @@ -1002,6 +1002,17 @@ func (m *RoleScopeTrait) validate(all bool) error { var errors []error + if m.GetRoleId() == nil { + err := RoleScopeTraitValidationError{ + field: "RoleId", + reason: "value is required", + } + if !all { + return err + } + errors = append(errors, err) + } + if all { switch v := interface{}(m.GetRoleId()).(type) { case interface{ ValidateAll() error }: diff --git a/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go b/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go index 575a796a9..cd99884b3 100644 --- a/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go +++ b/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go @@ -1680,9 +1680,9 @@ const file_c1_connector_v2_annotation_trait_proto_rawDesc = "" + "\x12RoleScopeCondition\x12\x1e\n" + "\n" + "expression\x18\x01 \x01(\tR\n" + - "expression\"\x8f\x01\n" + - "\x0eRoleScopeTrait\x124\n" + - "\arole_id\x18\x01 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x06roleId\x12G\n" + + "expression\"\x99\x01\n" + + "\x0eRoleScopeTrait\x12>\n" + + "\arole_id\x18\x01 \x01(\v2\x1b.c1.connector.v2.ResourceIdB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x06roleId\x12G\n" + "\x11scope_resource_id\x18\x02 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x0fscopeResourceId\"\x9a\x03\n" + "\bAppTrait\x125\n" + "\bhelp_url\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15 \x01(\x80\b:\bhttps://\xd0\x01\x01\x88\x01\x01R\ahelpUrl\x12-\n" + diff --git a/pkg/provisioner/provisioner.go b/pkg/provisioner/provisioner.go index 18bd2d632..1036de522 100644 --- a/pkg/provisioner/provisioner.go +++ b/pkg/provisioner/provisioner.go @@ -184,7 +184,7 @@ func (p *Provisioner) grant(ctx context.Context) error { DisplayName: principal.GetResource().GetDisplayName(), Annotations: principal.GetResource().GetAnnotations(), Description: principal.GetResource().GetDescription(), - ExternalId: principal.GetResource().GetExternalId(), + ExternalId: principal.GetResource().GetExternalId(), //nolint:staticcheck // Omit parent resource ID so that behavior is the same as ConductorOne's provisioning mode ParentResourceId: nil, }.Build() @@ -247,7 +247,7 @@ func (p *Provisioner) revoke(ctx context.Context) error { DisplayName: principal.GetResource().GetDisplayName(), Annotations: principal.GetResource().GetAnnotations(), Description: principal.GetResource().GetDescription(), - ExternalId: principal.GetResource().GetExternalId(), + ExternalId: principal.GetResource().GetExternalId(), //nolint:staticcheck // Omit parent resource ID so that behavior is the same as ConductorOne's provisioning mode ParentResourceId: nil, }.Build() diff --git a/pkg/sync/syncer.go b/pkg/sync/syncer.go index 8e175146b..d2e8be55f 100644 --- a/pkg/sync/syncer.go +++ b/pkg/sync/syncer.go @@ -1168,9 +1168,6 @@ func (s *syncer) syncResources(ctx context.Context) error { } } - // Set the resource creation source - r.SetCreationSource(v2.Resource_CREATION_SOURCE_CONNECTOR_LIST_RESOURCES) - bulkPutResoruces = append(bulkPutResoruces, r) err = s.getSubResources(ctx, r) diff --git a/pkg/types/grant/grant.go b/pkg/types/grant/grant.go index 972c63443..37a5f2675 100644 --- a/pkg/types/grant/grant.go +++ b/pkg/types/grant/grant.go @@ -36,9 +36,10 @@ func WithGrantMetadata(metadata map[string]interface{}) GrantOption { } } +// WithExternalPrincipalID: Deprecated. This field is no longer used. func WithExternalPrincipalID(externalID *v2.ExternalId) GrantOption { return func(g *v2.Grant) error { - g.GetPrincipal().SetExternalId(externalID) + g.GetPrincipal().SetExternalId(externalID) //nolint:staticcheck return nil } } diff --git a/pkg/types/resource/resource.go b/pkg/types/resource/resource.go index 55b94af37..4e4290f10 100644 --- a/pkg/types/resource/resource.go +++ b/pkg/types/resource/resource.go @@ -9,6 +9,8 @@ import ( "github.com/conductorone/baton-sdk/pkg/annotations" "github.com/conductorone/baton-sdk/pkg/pagination" "github.com/conductorone/baton-sdk/pkg/types/sessions" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" ) @@ -29,9 +31,10 @@ func WithAnnotation(msgs ...proto.Message) ResourceOption { } } +// WithExternalID: Deprecated. This field is no longer used. func WithExternalID(externalID *v2.ExternalId) ResourceOption { return func(r *v2.Resource) error { - r.SetExternalId(externalID) + r.SetExternalId(externalID) //nolint:staticcheck return nil } } @@ -149,6 +152,15 @@ func WithRoleScopeTrait(opts ...RoleScopeTraitOption) ResourceOption { } } + roleId := rt.GetRoleId() + scopeResourceId := rt.GetScopeResourceId() + if roleId == nil { + return status.Errorf(codes.InvalidArgument, "role ID is required for role scope trait") + } + if scopeResourceId == nil { + return status.Errorf(codes.InvalidArgument, "scope resource ID is required for role scope trait") + } + annos.Update(rt) r.SetAnnotations(annos) diff --git a/pkg/types/resource/role_scope_trait.go b/pkg/types/resource/role_scope_trait.go index c0ff81462..73e2cd3ec 100644 --- a/pkg/types/resource/role_scope_trait.go +++ b/pkg/types/resource/role_scope_trait.go @@ -1,10 +1,10 @@ package resource import ( - "fmt" - v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2" "github.com/conductorone/baton-sdk/pkg/annotations" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) type RoleScopeTraitOption func(rs *v2.RoleScopeTrait) error @@ -34,7 +34,7 @@ func GetRoleScopeTrait(resource *v2.Resource) (*v2.RoleScopeTrait, error) { return nil, err } if !ok { - return nil, fmt.Errorf("role scope trait was not found on resource") + return nil, status.Errorf(codes.NotFound, "role scope trait was not found on resource") } return ret, nil diff --git a/pkg/types/resource/role_trait.go b/pkg/types/resource/role_trait.go index 51631a16c..80b75a6df 100644 --- a/pkg/types/resource/role_trait.go +++ b/pkg/types/resource/role_trait.go @@ -1,10 +1,10 @@ package resource import ( - "fmt" - v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2" "github.com/conductorone/baton-sdk/pkg/annotations" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/structpb" ) @@ -62,7 +62,7 @@ func GetRoleTrait(resource *v2.Resource) (*v2.RoleTrait, error) { return nil, err } if !ok { - return nil, fmt.Errorf("role trait was not found on resource") + return nil, status.Errorf(codes.NotFound, "role trait was not found on resource") } return ret, nil diff --git a/proto/c1/connector/v2/annotation_trait.proto b/proto/c1/connector/v2/annotation_trait.proto index 595a62397..73294f221 100644 --- a/proto/c1/connector/v2/annotation_trait.proto +++ b/proto/c1/connector/v2/annotation_trait.proto @@ -95,7 +95,7 @@ message RoleScopeCondition { // RoleScopeTrait is used to scope a role to a resource or set of resources. // The scope may be static (determined at crawl time) or dynamic (determined based on conditions). message RoleScopeTrait { - c1.connector.v2.ResourceId role_id = 1; // The role that is scoped. Must be a resource with the role trait. + c1.connector.v2.ResourceId role_id = 1 [(validate.rules).message = {required: true}]; // The role that is scoped. Must be a resource with the role trait. c1.connector.v2.ResourceId scope_resource_id = 2; // The resource that the role is scoped to. } From 0258067142862a2bfc44dbf8fff384fb0cb81e08 Mon Sep 17 00:00:00 2001 From: Geoff Greer Date: Mon, 26 Jan 2026 12:45:01 -0800 Subject: [PATCH 08/10] Fix lint. --- pkg/provisioner/provisioner.go | 4 ++-- pkg/types/grant/grant.go | 2 +- pkg/types/resource/resource.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/provisioner/provisioner.go b/pkg/provisioner/provisioner.go index 1036de522..e69463df4 100644 --- a/pkg/provisioner/provisioner.go +++ b/pkg/provisioner/provisioner.go @@ -184,7 +184,7 @@ func (p *Provisioner) grant(ctx context.Context) error { DisplayName: principal.GetResource().GetDisplayName(), Annotations: principal.GetResource().GetAnnotations(), Description: principal.GetResource().GetDescription(), - ExternalId: principal.GetResource().GetExternalId(), //nolint:staticcheck + ExternalId: principal.GetResource().GetExternalId(), //nolint:staticcheck // Deprecated. // Omit parent resource ID so that behavior is the same as ConductorOne's provisioning mode ParentResourceId: nil, }.Build() @@ -247,7 +247,7 @@ func (p *Provisioner) revoke(ctx context.Context) error { DisplayName: principal.GetResource().GetDisplayName(), Annotations: principal.GetResource().GetAnnotations(), Description: principal.GetResource().GetDescription(), - ExternalId: principal.GetResource().GetExternalId(), //nolint:staticcheck + ExternalId: principal.GetResource().GetExternalId(), //nolint:staticcheck // Deprecated. // Omit parent resource ID so that behavior is the same as ConductorOne's provisioning mode ParentResourceId: nil, }.Build() diff --git a/pkg/types/grant/grant.go b/pkg/types/grant/grant.go index 37a5f2675..b472ca995 100644 --- a/pkg/types/grant/grant.go +++ b/pkg/types/grant/grant.go @@ -39,7 +39,7 @@ func WithGrantMetadata(metadata map[string]interface{}) GrantOption { // WithExternalPrincipalID: Deprecated. This field is no longer used. func WithExternalPrincipalID(externalID *v2.ExternalId) GrantOption { return func(g *v2.Grant) error { - g.GetPrincipal().SetExternalId(externalID) //nolint:staticcheck + g.GetPrincipal().SetExternalId(externalID) //nolint:staticcheck // Deprecated. return nil } } diff --git a/pkg/types/resource/resource.go b/pkg/types/resource/resource.go index 4e4290f10..8a135369d 100644 --- a/pkg/types/resource/resource.go +++ b/pkg/types/resource/resource.go @@ -34,7 +34,7 @@ func WithAnnotation(msgs ...proto.Message) ResourceOption { // WithExternalID: Deprecated. This field is no longer used. func WithExternalID(externalID *v2.ExternalId) ResourceOption { return func(r *v2.Resource) error { - r.SetExternalId(externalID) //nolint:staticcheck + r.SetExternalId(externalID) //nolint:staticcheck // Deprecated. return nil } } From 887f778ca4dee49046ce55aa414791f622c21752 Mon Sep 17 00:00:00 2001 From: Geoff Greer Date: Mon, 26 Jan 2026 13:42:02 -0800 Subject: [PATCH 09/10] Rename RoleScopeTrait to ScopeBindingTrait. --- pb/c1/connector/v2/annotation_trait.pb.go | 60 +++++++------- .../v2/annotation_trait.pb.validate.go | 83 +++++++++++-------- .../v2/annotation_trait_protoopaque.pb.go | 53 ++++++------ pb/c1/connector/v2/resource.pb.go | 14 ++-- pb/c1/connector/v2/resource_protoopaque.pb.go | 14 ++-- pkg/types/resource/resource.go | 18 ++-- pkg/types/resource/role_scope_trait.go | 18 ++-- proto/c1/connector/v2/annotation_trait.proto | 7 +- proto/c1/connector/v2/resource.proto | 2 +- 9 files changed, 143 insertions(+), 126 deletions(-) diff --git a/pb/c1/connector/v2/annotation_trait.pb.go b/pb/c1/connector/v2/annotation_trait.pb.go index 9ba212407..dd8339542 100644 --- a/pb/c1/connector/v2/annotation_trait.pb.go +++ b/pb/c1/connector/v2/annotation_trait.pb.go @@ -803,30 +803,31 @@ func (b0 RoleScopeCondition_builder) Build() *RoleScopeCondition { return m0 } -// RoleScopeTrait is used to scope a role to a resource or set of resources. +// ScopeBindingTrait is used to scope a role to a resource or set of resources. // The scope may be static (determined at crawl time) or dynamic (determined based on conditions). -type RoleScopeTrait struct { - state protoimpl.MessageState `protogen:"hybrid.v1"` - RoleId *ResourceId `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"` // The role that is scoped. Must be a resource with the role trait. - ScopeResourceId *ResourceId `protobuf:"bytes,2,opt,name=scope_resource_id,json=scopeResourceId,proto3" json:"scope_resource_id,omitempty"` // The resource that the role is scoped to. +type ScopeBindingTrait struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + RoleId *ResourceId `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"` // The role that is scoped. Must be a resource with the role trait. + // Remove required if we add more ways to scope roles. (eg: Expressions.) + ScopeResourceId *ResourceId `protobuf:"bytes,2,opt,name=scope_resource_id,json=scopeResourceId,proto3" json:"scope_resource_id,omitempty"` // The resource that the role is scoped to. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *RoleScopeTrait) Reset() { - *x = RoleScopeTrait{} +func (x *ScopeBindingTrait) Reset() { + *x = ScopeBindingTrait{} mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *RoleScopeTrait) String() string { +func (x *ScopeBindingTrait) String() string { return protoimpl.X.MessageStringOf(x) } -func (*RoleScopeTrait) ProtoMessage() {} +func (*ScopeBindingTrait) ProtoMessage() {} -func (x *RoleScopeTrait) ProtoReflect() protoreflect.Message { +func (x *ScopeBindingTrait) ProtoReflect() protoreflect.Message { mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -838,59 +839,60 @@ func (x *RoleScopeTrait) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -func (x *RoleScopeTrait) GetRoleId() *ResourceId { +func (x *ScopeBindingTrait) GetRoleId() *ResourceId { if x != nil { return x.RoleId } return nil } -func (x *RoleScopeTrait) GetScopeResourceId() *ResourceId { +func (x *ScopeBindingTrait) GetScopeResourceId() *ResourceId { if x != nil { return x.ScopeResourceId } return nil } -func (x *RoleScopeTrait) SetRoleId(v *ResourceId) { +func (x *ScopeBindingTrait) SetRoleId(v *ResourceId) { x.RoleId = v } -func (x *RoleScopeTrait) SetScopeResourceId(v *ResourceId) { +func (x *ScopeBindingTrait) SetScopeResourceId(v *ResourceId) { x.ScopeResourceId = v } -func (x *RoleScopeTrait) HasRoleId() bool { +func (x *ScopeBindingTrait) HasRoleId() bool { if x == nil { return false } return x.RoleId != nil } -func (x *RoleScopeTrait) HasScopeResourceId() bool { +func (x *ScopeBindingTrait) HasScopeResourceId() bool { if x == nil { return false } return x.ScopeResourceId != nil } -func (x *RoleScopeTrait) ClearRoleId() { +func (x *ScopeBindingTrait) ClearRoleId() { x.RoleId = nil } -func (x *RoleScopeTrait) ClearScopeResourceId() { +func (x *ScopeBindingTrait) ClearScopeResourceId() { x.ScopeResourceId = nil } -type RoleScopeTrait_builder struct { +type ScopeBindingTrait_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - RoleId *ResourceId + RoleId *ResourceId + // Remove required if we add more ways to scope roles. (eg: Expressions.) ScopeResourceId *ResourceId } -func (b0 RoleScopeTrait_builder) Build() *RoleScopeTrait { - m0 := &RoleScopeTrait{} +func (b0 ScopeBindingTrait_builder) Build() *ScopeBindingTrait { + m0 := &ScopeBindingTrait{} b, x := &b0, m0 _, _ = b, x x.RoleId = b.RoleId @@ -1679,10 +1681,10 @@ const file_c1_connector_v2_annotation_trait_proto_rawDesc = "" + "\x12RoleScopeCondition\x12\x1e\n" + "\n" + "expression\x18\x01 \x01(\tR\n" + - "expression\"\x99\x01\n" + - "\x0eRoleScopeTrait\x12>\n" + - "\arole_id\x18\x01 \x01(\v2\x1b.c1.connector.v2.ResourceIdB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x06roleId\x12G\n" + - "\x11scope_resource_id\x18\x02 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x0fscopeResourceId\"\x9a\x03\n" + + "expression\"\xa6\x01\n" + + "\x11ScopeBindingTrait\x12>\n" + + "\arole_id\x18\x01 \x01(\v2\x1b.c1.connector.v2.ResourceIdB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x06roleId\x12Q\n" + + "\x11scope_resource_id\x18\x02 \x01(\v2\x1b.c1.connector.v2.ResourceIdB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x0fscopeResourceId\"\x9a\x03\n" + "\bAppTrait\x125\n" + "\bhelp_url\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15 \x01(\x80\b:\bhttps://\xd0\x01\x01\x88\x01\x01R\ahelpUrl\x12-\n" + "\x04icon\x18\x02 \x01(\v2\x19.c1.connector.v2.AssetRefR\x04icon\x12-\n" + @@ -1719,7 +1721,7 @@ var file_c1_connector_v2_annotation_trait_proto_goTypes = []any{ (*RoleTrait)(nil), // 5: c1.connector.v2.RoleTrait (*RoleScopeConditions)(nil), // 6: c1.connector.v2.RoleScopeConditions (*RoleScopeCondition)(nil), // 7: c1.connector.v2.RoleScopeCondition - (*RoleScopeTrait)(nil), // 8: c1.connector.v2.RoleScopeTrait + (*ScopeBindingTrait)(nil), // 8: c1.connector.v2.ScopeBindingTrait (*AppTrait)(nil), // 9: c1.connector.v2.AppTrait (*SecretTrait)(nil), // 10: c1.connector.v2.SecretTrait (*UserTrait_Email)(nil), // 11: c1.connector.v2.UserTrait.Email @@ -1748,8 +1750,8 @@ var file_c1_connector_v2_annotation_trait_proto_depIdxs = []int32{ 16, // 12: c1.connector.v2.RoleTrait.profile:type_name -> google.protobuf.Struct 6, // 13: c1.connector.v2.RoleTrait.role_scope_conditions:type_name -> c1.connector.v2.RoleScopeConditions 7, // 14: c1.connector.v2.RoleScopeConditions.conditions:type_name -> c1.connector.v2.RoleScopeCondition - 19, // 15: c1.connector.v2.RoleScopeTrait.role_id:type_name -> c1.connector.v2.ResourceId - 19, // 16: c1.connector.v2.RoleScopeTrait.scope_resource_id:type_name -> c1.connector.v2.ResourceId + 19, // 15: c1.connector.v2.ScopeBindingTrait.role_id:type_name -> c1.connector.v2.ResourceId + 19, // 16: c1.connector.v2.ScopeBindingTrait.scope_resource_id:type_name -> c1.connector.v2.ResourceId 17, // 17: c1.connector.v2.AppTrait.icon:type_name -> c1.connector.v2.AssetRef 17, // 18: c1.connector.v2.AppTrait.logo:type_name -> c1.connector.v2.AssetRef 16, // 19: c1.connector.v2.AppTrait.profile:type_name -> google.protobuf.Struct diff --git a/pb/c1/connector/v2/annotation_trait.pb.validate.go b/pb/c1/connector/v2/annotation_trait.pb.validate.go index 742ef251a..c79b43ca7 100644 --- a/pb/c1/connector/v2/annotation_trait.pb.validate.go +++ b/pb/c1/connector/v2/annotation_trait.pb.validate.go @@ -980,22 +980,22 @@ var _ interface { ErrorName() string } = RoleScopeConditionValidationError{} -// Validate checks the field values on RoleScopeTrait with the rules defined in -// the proto definition for this message. If any rules are violated, the first -// error encountered is returned, or nil if there are no violations. -func (m *RoleScopeTrait) Validate() error { +// Validate checks the field values on ScopeBindingTrait with the rules defined +// in the proto definition for this message. If any rules are violated, the +// first error encountered is returned, or nil if there are no violations. +func (m *ScopeBindingTrait) Validate() error { return m.validate(false) } -// ValidateAll checks the field values on RoleScopeTrait with the rules defined -// in the proto definition for this message. If any rules are violated, the -// result is a list of violation errors wrapped in RoleScopeTraitMultiError, -// or nil if none found. -func (m *RoleScopeTrait) ValidateAll() error { +// ValidateAll checks the field values on ScopeBindingTrait with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ScopeBindingTraitMultiError, or nil if none found. +func (m *ScopeBindingTrait) ValidateAll() error { return m.validate(true) } -func (m *RoleScopeTrait) validate(all bool) error { +func (m *ScopeBindingTrait) validate(all bool) error { if m == nil { return nil } @@ -1003,7 +1003,7 @@ func (m *RoleScopeTrait) validate(all bool) error { var errors []error if m.GetRoleId() == nil { - err := RoleScopeTraitValidationError{ + err := ScopeBindingTraitValidationError{ field: "RoleId", reason: "value is required", } @@ -1017,7 +1017,7 @@ func (m *RoleScopeTrait) validate(all bool) error { switch v := interface{}(m.GetRoleId()).(type) { case interface{ ValidateAll() error }: if err := v.ValidateAll(); err != nil { - errors = append(errors, RoleScopeTraitValidationError{ + errors = append(errors, ScopeBindingTraitValidationError{ field: "RoleId", reason: "embedded message failed validation", cause: err, @@ -1025,7 +1025,7 @@ func (m *RoleScopeTrait) validate(all bool) error { } case interface{ Validate() error }: if err := v.Validate(); err != nil { - errors = append(errors, RoleScopeTraitValidationError{ + errors = append(errors, ScopeBindingTraitValidationError{ field: "RoleId", reason: "embedded message failed validation", cause: err, @@ -1034,7 +1034,7 @@ func (m *RoleScopeTrait) validate(all bool) error { } } else if v, ok := interface{}(m.GetRoleId()).(interface{ Validate() error }); ok { if err := v.Validate(); err != nil { - return RoleScopeTraitValidationError{ + return ScopeBindingTraitValidationError{ field: "RoleId", reason: "embedded message failed validation", cause: err, @@ -1042,11 +1042,22 @@ func (m *RoleScopeTrait) validate(all bool) error { } } + if m.GetScopeResourceId() == nil { + err := ScopeBindingTraitValidationError{ + field: "ScopeResourceId", + reason: "value is required", + } + if !all { + return err + } + errors = append(errors, err) + } + if all { switch v := interface{}(m.GetScopeResourceId()).(type) { case interface{ ValidateAll() error }: if err := v.ValidateAll(); err != nil { - errors = append(errors, RoleScopeTraitValidationError{ + errors = append(errors, ScopeBindingTraitValidationError{ field: "ScopeResourceId", reason: "embedded message failed validation", cause: err, @@ -1054,7 +1065,7 @@ func (m *RoleScopeTrait) validate(all bool) error { } case interface{ Validate() error }: if err := v.Validate(); err != nil { - errors = append(errors, RoleScopeTraitValidationError{ + errors = append(errors, ScopeBindingTraitValidationError{ field: "ScopeResourceId", reason: "embedded message failed validation", cause: err, @@ -1063,7 +1074,7 @@ func (m *RoleScopeTrait) validate(all bool) error { } } else if v, ok := interface{}(m.GetScopeResourceId()).(interface{ Validate() error }); ok { if err := v.Validate(); err != nil { - return RoleScopeTraitValidationError{ + return ScopeBindingTraitValidationError{ field: "ScopeResourceId", reason: "embedded message failed validation", cause: err, @@ -1072,19 +1083,19 @@ func (m *RoleScopeTrait) validate(all bool) error { } if len(errors) > 0 { - return RoleScopeTraitMultiError(errors) + return ScopeBindingTraitMultiError(errors) } return nil } -// RoleScopeTraitMultiError is an error wrapping multiple validation errors -// returned by RoleScopeTrait.ValidateAll() if the designated constraints +// ScopeBindingTraitMultiError is an error wrapping multiple validation errors +// returned by ScopeBindingTrait.ValidateAll() if the designated constraints // aren't met. -type RoleScopeTraitMultiError []error +type ScopeBindingTraitMultiError []error // Error returns a concatenation of all the error messages it wraps. -func (m RoleScopeTraitMultiError) Error() string { +func (m ScopeBindingTraitMultiError) Error() string { msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) @@ -1093,11 +1104,11 @@ func (m RoleScopeTraitMultiError) Error() string { } // AllErrors returns a list of validation violation errors. -func (m RoleScopeTraitMultiError) AllErrors() []error { return m } +func (m ScopeBindingTraitMultiError) AllErrors() []error { return m } -// RoleScopeTraitValidationError is the validation error returned by -// RoleScopeTrait.Validate if the designated constraints aren't met. -type RoleScopeTraitValidationError struct { +// ScopeBindingTraitValidationError is the validation error returned by +// ScopeBindingTrait.Validate if the designated constraints aren't met. +type ScopeBindingTraitValidationError struct { field string reason string cause error @@ -1105,22 +1116,24 @@ type RoleScopeTraitValidationError struct { } // Field function returns field value. -func (e RoleScopeTraitValidationError) Field() string { return e.field } +func (e ScopeBindingTraitValidationError) Field() string { return e.field } // Reason function returns reason value. -func (e RoleScopeTraitValidationError) Reason() string { return e.reason } +func (e ScopeBindingTraitValidationError) Reason() string { return e.reason } // Cause function returns cause value. -func (e RoleScopeTraitValidationError) Cause() error { return e.cause } +func (e ScopeBindingTraitValidationError) Cause() error { return e.cause } // Key function returns key value. -func (e RoleScopeTraitValidationError) Key() bool { return e.key } +func (e ScopeBindingTraitValidationError) Key() bool { return e.key } // ErrorName returns error name. -func (e RoleScopeTraitValidationError) ErrorName() string { return "RoleScopeTraitValidationError" } +func (e ScopeBindingTraitValidationError) ErrorName() string { + return "ScopeBindingTraitValidationError" +} // Error satisfies the builtin error interface -func (e RoleScopeTraitValidationError) Error() string { +func (e ScopeBindingTraitValidationError) Error() string { cause := "" if e.cause != nil { cause = fmt.Sprintf(" | caused by: %v", e.cause) @@ -1132,14 +1145,14 @@ func (e RoleScopeTraitValidationError) Error() string { } return fmt.Sprintf( - "invalid %sRoleScopeTrait.%s: %s%s", + "invalid %sScopeBindingTrait.%s: %s%s", key, e.field, e.reason, cause) } -var _ error = RoleScopeTraitValidationError{} +var _ error = ScopeBindingTraitValidationError{} var _ interface { Field() string @@ -1147,7 +1160,7 @@ var _ interface { Key() bool Cause() error ErrorName() string -} = RoleScopeTraitValidationError{} +} = ScopeBindingTraitValidationError{} // Validate checks the field values on AppTrait with the rules defined in the // proto definition for this message. If any rules are violated, the first diff --git a/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go b/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go index cd99884b3..197832bd6 100644 --- a/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go +++ b/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go @@ -805,9 +805,9 @@ func (b0 RoleScopeCondition_builder) Build() *RoleScopeCondition { return m0 } -// RoleScopeTrait is used to scope a role to a resource or set of resources. +// ScopeBindingTrait is used to scope a role to a resource or set of resources. // The scope may be static (determined at crawl time) or dynamic (determined based on conditions). -type RoleScopeTrait struct { +type ScopeBindingTrait struct { state protoimpl.MessageState `protogen:"opaque.v1"` xxx_hidden_RoleId *ResourceId `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3"` xxx_hidden_ScopeResourceId *ResourceId `protobuf:"bytes,2,opt,name=scope_resource_id,json=scopeResourceId,proto3"` @@ -815,20 +815,20 @@ type RoleScopeTrait struct { sizeCache protoimpl.SizeCache } -func (x *RoleScopeTrait) Reset() { - *x = RoleScopeTrait{} +func (x *ScopeBindingTrait) Reset() { + *x = ScopeBindingTrait{} mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *RoleScopeTrait) String() string { +func (x *ScopeBindingTrait) String() string { return protoimpl.X.MessageStringOf(x) } -func (*RoleScopeTrait) ProtoMessage() {} +func (*ScopeBindingTrait) ProtoMessage() {} -func (x *RoleScopeTrait) ProtoReflect() protoreflect.Message { +func (x *ScopeBindingTrait) ProtoReflect() protoreflect.Message { mi := &file_c1_connector_v2_annotation_trait_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -840,59 +840,60 @@ func (x *RoleScopeTrait) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -func (x *RoleScopeTrait) GetRoleId() *ResourceId { +func (x *ScopeBindingTrait) GetRoleId() *ResourceId { if x != nil { return x.xxx_hidden_RoleId } return nil } -func (x *RoleScopeTrait) GetScopeResourceId() *ResourceId { +func (x *ScopeBindingTrait) GetScopeResourceId() *ResourceId { if x != nil { return x.xxx_hidden_ScopeResourceId } return nil } -func (x *RoleScopeTrait) SetRoleId(v *ResourceId) { +func (x *ScopeBindingTrait) SetRoleId(v *ResourceId) { x.xxx_hidden_RoleId = v } -func (x *RoleScopeTrait) SetScopeResourceId(v *ResourceId) { +func (x *ScopeBindingTrait) SetScopeResourceId(v *ResourceId) { x.xxx_hidden_ScopeResourceId = v } -func (x *RoleScopeTrait) HasRoleId() bool { +func (x *ScopeBindingTrait) HasRoleId() bool { if x == nil { return false } return x.xxx_hidden_RoleId != nil } -func (x *RoleScopeTrait) HasScopeResourceId() bool { +func (x *ScopeBindingTrait) HasScopeResourceId() bool { if x == nil { return false } return x.xxx_hidden_ScopeResourceId != nil } -func (x *RoleScopeTrait) ClearRoleId() { +func (x *ScopeBindingTrait) ClearRoleId() { x.xxx_hidden_RoleId = nil } -func (x *RoleScopeTrait) ClearScopeResourceId() { +func (x *ScopeBindingTrait) ClearScopeResourceId() { x.xxx_hidden_ScopeResourceId = nil } -type RoleScopeTrait_builder struct { +type ScopeBindingTrait_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - RoleId *ResourceId + RoleId *ResourceId + // Remove required if we add more ways to scope roles. (eg: Expressions.) ScopeResourceId *ResourceId } -func (b0 RoleScopeTrait_builder) Build() *RoleScopeTrait { - m0 := &RoleScopeTrait{} +func (b0 ScopeBindingTrait_builder) Build() *ScopeBindingTrait { + m0 := &ScopeBindingTrait{} b, x := &b0, m0 _, _ = b, x x.xxx_hidden_RoleId = b.RoleId @@ -1680,10 +1681,10 @@ const file_c1_connector_v2_annotation_trait_proto_rawDesc = "" + "\x12RoleScopeCondition\x12\x1e\n" + "\n" + "expression\x18\x01 \x01(\tR\n" + - "expression\"\x99\x01\n" + - "\x0eRoleScopeTrait\x12>\n" + - "\arole_id\x18\x01 \x01(\v2\x1b.c1.connector.v2.ResourceIdB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x06roleId\x12G\n" + - "\x11scope_resource_id\x18\x02 \x01(\v2\x1b.c1.connector.v2.ResourceIdR\x0fscopeResourceId\"\x9a\x03\n" + + "expression\"\xa6\x01\n" + + "\x11ScopeBindingTrait\x12>\n" + + "\arole_id\x18\x01 \x01(\v2\x1b.c1.connector.v2.ResourceIdB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x06roleId\x12Q\n" + + "\x11scope_resource_id\x18\x02 \x01(\v2\x1b.c1.connector.v2.ResourceIdB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x0fscopeResourceId\"\x9a\x03\n" + "\bAppTrait\x125\n" + "\bhelp_url\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15 \x01(\x80\b:\bhttps://\xd0\x01\x01\x88\x01\x01R\ahelpUrl\x12-\n" + "\x04icon\x18\x02 \x01(\v2\x19.c1.connector.v2.AssetRefR\x04icon\x12-\n" + @@ -1720,7 +1721,7 @@ var file_c1_connector_v2_annotation_trait_proto_goTypes = []any{ (*RoleTrait)(nil), // 5: c1.connector.v2.RoleTrait (*RoleScopeConditions)(nil), // 6: c1.connector.v2.RoleScopeConditions (*RoleScopeCondition)(nil), // 7: c1.connector.v2.RoleScopeCondition - (*RoleScopeTrait)(nil), // 8: c1.connector.v2.RoleScopeTrait + (*ScopeBindingTrait)(nil), // 8: c1.connector.v2.ScopeBindingTrait (*AppTrait)(nil), // 9: c1.connector.v2.AppTrait (*SecretTrait)(nil), // 10: c1.connector.v2.SecretTrait (*UserTrait_Email)(nil), // 11: c1.connector.v2.UserTrait.Email @@ -1749,8 +1750,8 @@ var file_c1_connector_v2_annotation_trait_proto_depIdxs = []int32{ 16, // 12: c1.connector.v2.RoleTrait.profile:type_name -> google.protobuf.Struct 6, // 13: c1.connector.v2.RoleTrait.role_scope_conditions:type_name -> c1.connector.v2.RoleScopeConditions 7, // 14: c1.connector.v2.RoleScopeConditions.conditions:type_name -> c1.connector.v2.RoleScopeCondition - 19, // 15: c1.connector.v2.RoleScopeTrait.role_id:type_name -> c1.connector.v2.ResourceId - 19, // 16: c1.connector.v2.RoleScopeTrait.scope_resource_id:type_name -> c1.connector.v2.ResourceId + 19, // 15: c1.connector.v2.ScopeBindingTrait.role_id:type_name -> c1.connector.v2.ResourceId + 19, // 16: c1.connector.v2.ScopeBindingTrait.scope_resource_id:type_name -> c1.connector.v2.ResourceId 17, // 17: c1.connector.v2.AppTrait.icon:type_name -> c1.connector.v2.AssetRef 17, // 18: c1.connector.v2.AppTrait.logo:type_name -> c1.connector.v2.AssetRef 16, // 19: c1.connector.v2.AppTrait.profile:type_name -> google.protobuf.Struct diff --git a/pb/c1/connector/v2/resource.pb.go b/pb/c1/connector/v2/resource.pb.go index 0c04503a8..346018773 100644 --- a/pb/c1/connector/v2/resource.pb.go +++ b/pb/c1/connector/v2/resource.pb.go @@ -35,7 +35,7 @@ const ( ResourceType_TRAIT_APP ResourceType_Trait = 4 ResourceType_TRAIT_SECRET ResourceType_Trait = 5 ResourceType_TRAIT_SECURITY_INSIGHT ResourceType_Trait = 6 - ResourceType_TRAIT_ROLE_SCOPE ResourceType_Trait = 7 + ResourceType_TRAIT_SCOPE_BINDING ResourceType_Trait = 7 ) // Enum value maps for ResourceType_Trait. @@ -48,7 +48,7 @@ var ( 4: "TRAIT_APP", 5: "TRAIT_SECRET", 6: "TRAIT_SECURITY_INSIGHT", - 7: "TRAIT_ROLE_SCOPE", + 7: "TRAIT_SCOPE_BINDING", } ResourceType_Trait_value = map[string]int32{ "TRAIT_UNSPECIFIED": 0, @@ -58,7 +58,7 @@ var ( "TRAIT_APP": 4, "TRAIT_SECRET": 5, "TRAIT_SECURITY_INSIGHT": 6, - "TRAIT_ROLE_SCOPE": 7, + "TRAIT_SCOPE_BINDING": 7, } ) @@ -4473,7 +4473,7 @@ var File_c1_connector_v2_resource_proto protoreflect.FileDescriptor const file_c1_connector_v2_resource_proto_rawDesc = "" + "\n" + - "\x1ec1/connector/v2/resource.proto\x12\x0fc1.connector.v2\x1a\x19google/protobuf/any.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x17validate/validate.proto\"\xe7\x03\n" + + "\x1ec1/connector/v2/resource.proto\x12\x0fc1.connector.v2\x1a\x19google/protobuf/any.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x17validate/validate.proto\"\xea\x03\n" + "\fResourceType\x12\x1a\n" + "\x02id\x18\x01 \x01(\tB\n" + "\xfaB\ar\x05 \x01(\x80\bR\x02id\x120\n" + @@ -4483,7 +4483,7 @@ const file_c1_connector_v2_resource_proto_rawDesc = "" + "\vannotations\x18\x04 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x12/\n" + "\vdescription\x18\x05 \x01(\tB\r\xfaB\n" + "r\b \x01(\x80 \xd0\x01\x01R\vdescription\x12-\n" + - "\x12sourced_externally\x18\x06 \x01(\bR\x11sourcedExternally\"\xa2\x01\n" + + "\x12sourced_externally\x18\x06 \x01(\bR\x11sourcedExternally\"\xa5\x01\n" + "\x05Trait\x12\x15\n" + "\x11TRAIT_UNSPECIFIED\x10\x00\x12\x0e\n" + "\n" + @@ -4493,8 +4493,8 @@ const file_c1_connector_v2_resource_proto_rawDesc = "" + "TRAIT_ROLE\x10\x03\x12\r\n" + "\tTRAIT_APP\x10\x04\x12\x10\n" + "\fTRAIT_SECRET\x10\x05\x12\x1a\n" + - "\x16TRAIT_SECURITY_INSIGHT\x10\x06\x12\x14\n" + - "\x10TRAIT_ROLE_SCOPE\x10\a\"\xa6\x02\n" + + "\x16TRAIT_SECURITY_INSIGHT\x10\x06\x12\x17\n" + + "\x13TRAIT_SCOPE_BINDING\x10\a\"\xa6\x02\n" + ",ResourceTypesServiceListResourceTypesRequest\x121\n" + "\x06parent\x18\x01 \x01(\v2\x19.c1.connector.v2.ResourceR\x06parent\x12'\n" + "\tpage_size\x18\x02 \x01(\rB\n" + diff --git a/pb/c1/connector/v2/resource_protoopaque.pb.go b/pb/c1/connector/v2/resource_protoopaque.pb.go index 8b448661c..12dcb8a58 100644 --- a/pb/c1/connector/v2/resource_protoopaque.pb.go +++ b/pb/c1/connector/v2/resource_protoopaque.pb.go @@ -35,7 +35,7 @@ const ( ResourceType_TRAIT_APP ResourceType_Trait = 4 ResourceType_TRAIT_SECRET ResourceType_Trait = 5 ResourceType_TRAIT_SECURITY_INSIGHT ResourceType_Trait = 6 - ResourceType_TRAIT_ROLE_SCOPE ResourceType_Trait = 7 + ResourceType_TRAIT_SCOPE_BINDING ResourceType_Trait = 7 ) // Enum value maps for ResourceType_Trait. @@ -48,7 +48,7 @@ var ( 4: "TRAIT_APP", 5: "TRAIT_SECRET", 6: "TRAIT_SECURITY_INSIGHT", - 7: "TRAIT_ROLE_SCOPE", + 7: "TRAIT_SCOPE_BINDING", } ResourceType_Trait_value = map[string]int32{ "TRAIT_UNSPECIFIED": 0, @@ -58,7 +58,7 @@ var ( "TRAIT_APP": 4, "TRAIT_SECRET": 5, "TRAIT_SECURITY_INSIGHT": 6, - "TRAIT_ROLE_SCOPE": 7, + "TRAIT_SCOPE_BINDING": 7, } ) @@ -4460,7 +4460,7 @@ var File_c1_connector_v2_resource_proto protoreflect.FileDescriptor const file_c1_connector_v2_resource_proto_rawDesc = "" + "\n" + - "\x1ec1/connector/v2/resource.proto\x12\x0fc1.connector.v2\x1a\x19google/protobuf/any.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x17validate/validate.proto\"\xe7\x03\n" + + "\x1ec1/connector/v2/resource.proto\x12\x0fc1.connector.v2\x1a\x19google/protobuf/any.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x17validate/validate.proto\"\xea\x03\n" + "\fResourceType\x12\x1a\n" + "\x02id\x18\x01 \x01(\tB\n" + "\xfaB\ar\x05 \x01(\x80\bR\x02id\x120\n" + @@ -4470,7 +4470,7 @@ const file_c1_connector_v2_resource_proto_rawDesc = "" + "\vannotations\x18\x04 \x03(\v2\x14.google.protobuf.AnyR\vannotations\x12/\n" + "\vdescription\x18\x05 \x01(\tB\r\xfaB\n" + "r\b \x01(\x80 \xd0\x01\x01R\vdescription\x12-\n" + - "\x12sourced_externally\x18\x06 \x01(\bR\x11sourcedExternally\"\xa2\x01\n" + + "\x12sourced_externally\x18\x06 \x01(\bR\x11sourcedExternally\"\xa5\x01\n" + "\x05Trait\x12\x15\n" + "\x11TRAIT_UNSPECIFIED\x10\x00\x12\x0e\n" + "\n" + @@ -4480,8 +4480,8 @@ const file_c1_connector_v2_resource_proto_rawDesc = "" + "TRAIT_ROLE\x10\x03\x12\r\n" + "\tTRAIT_APP\x10\x04\x12\x10\n" + "\fTRAIT_SECRET\x10\x05\x12\x1a\n" + - "\x16TRAIT_SECURITY_INSIGHT\x10\x06\x12\x14\n" + - "\x10TRAIT_ROLE_SCOPE\x10\a\"\xa6\x02\n" + + "\x16TRAIT_SECURITY_INSIGHT\x10\x06\x12\x17\n" + + "\x13TRAIT_SCOPE_BINDING\x10\a\"\xa6\x02\n" + ",ResourceTypesServiceListResourceTypesRequest\x121\n" + "\x06parent\x18\x01 \x01(\v2\x19.c1.connector.v2.ResourceR\x06parent\x12'\n" + "\tpage_size\x18\x02 \x01(\rB\n" + diff --git a/pkg/types/resource/resource.go b/pkg/types/resource/resource.go index 8a135369d..b7dae67e2 100644 --- a/pkg/types/resource/resource.go +++ b/pkg/types/resource/resource.go @@ -135,9 +135,9 @@ func WithRoleTrait(opts ...RoleTraitOption) ResourceOption { } } -func WithRoleScopeTrait(opts ...RoleScopeTraitOption) ResourceOption { +func WithScopeBindingTrait(opts ...ScopeBindingTraitOption) ResourceOption { return func(r *v2.Resource) error { - rt := &v2.RoleScopeTrait{} + rt := &v2.ScopeBindingTrait{} annos := annotations.Annotations(r.GetAnnotations()) _, err := annos.Pick(rt) @@ -155,10 +155,10 @@ func WithRoleScopeTrait(opts ...RoleScopeTraitOption) ResourceOption { roleId := rt.GetRoleId() scopeResourceId := rt.GetScopeResourceId() if roleId == nil { - return status.Errorf(codes.InvalidArgument, "role ID is required for role scope trait") + return status.Errorf(codes.InvalidArgument, "role ID is required for scope binding trait") } if scopeResourceId == nil { - return status.Errorf(codes.InvalidArgument, "scope resource ID is required for role scope trait") + return status.Errorf(codes.InvalidArgument, "scope resource ID is required for scope binding trait") } annos.Update(rt) @@ -340,15 +340,15 @@ func NewRoleResource( return ret, nil } -// NewRoleScopeResource returns a new resource instance with a configured role scope trait. -func NewRoleScopeResource( +// NewScopeBindingResource returns a new resource instance with a configured scope binding trait. +func NewScopeBindingResource( name string, resourceType *v2.ResourceType, - objectID interface{}, - roleScopeOpts []RoleScopeTraitOption, + objectID any, + scopeBindingOpts []ScopeBindingTraitOption, opts ...ResourceOption, ) (*v2.Resource, error) { - opts = append(opts, WithRoleScopeTrait(roleScopeOpts...)) + opts = append(opts, WithScopeBindingTrait(scopeBindingOpts...)) ret, err := NewResource(name, resourceType, objectID, opts...) if err != nil { diff --git a/pkg/types/resource/role_scope_trait.go b/pkg/types/resource/role_scope_trait.go index 73e2cd3ec..0624f9eef 100644 --- a/pkg/types/resource/role_scope_trait.go +++ b/pkg/types/resource/role_scope_trait.go @@ -7,34 +7,34 @@ import ( "google.golang.org/grpc/status" ) -type RoleScopeTraitOption func(rs *v2.RoleScopeTrait) error +type ScopeBindingTraitOption func(rs *v2.ScopeBindingTrait) error // WithRoleScopeRoleId sets the role of role scope. -func WithRoleScopeRoleId(resourceId *v2.ResourceId) RoleScopeTraitOption { - return func(rs *v2.RoleScopeTrait) error { +func WithRoleScopeRoleId(resourceId *v2.ResourceId) ScopeBindingTraitOption { + return func(rs *v2.ScopeBindingTrait) error { rs.RoleId = resourceId return nil } } // WithRoleScopeResourceId sets the resource scope of role scope. -func WithRoleScopeResourceId(resourceId *v2.ResourceId) RoleScopeTraitOption { - return func(rs *v2.RoleScopeTrait) error { +func WithRoleScopeResourceId(resourceId *v2.ResourceId) ScopeBindingTraitOption { + return func(rs *v2.ScopeBindingTrait) error { rs.ScopeResourceId = resourceId return nil } } -// GetRoleScopeTrait attempts to return the RoleScopeTrait instance on a resource. -func GetRoleScopeTrait(resource *v2.Resource) (*v2.RoleScopeTrait, error) { - ret := &v2.RoleScopeTrait{} +// GetScopeBindingTrait attempts to return the ScopeBindingTrait instance on a resource. +func GetScopeBindingTrait(resource *v2.Resource) (*v2.ScopeBindingTrait, error) { + ret := &v2.ScopeBindingTrait{} annos := annotations.Annotations(resource.GetAnnotations()) ok, err := annos.Pick(ret) if err != nil { return nil, err } if !ok { - return nil, status.Errorf(codes.NotFound, "role scope trait was not found on resource") + return nil, status.Errorf(codes.NotFound, "scope binding trait was not found on resource") } return ret, nil diff --git a/proto/c1/connector/v2/annotation_trait.proto b/proto/c1/connector/v2/annotation_trait.proto index 73294f221..c8694b407 100644 --- a/proto/c1/connector/v2/annotation_trait.proto +++ b/proto/c1/connector/v2/annotation_trait.proto @@ -92,11 +92,12 @@ message RoleScopeCondition { string expression = 1; } -// RoleScopeTrait is used to scope a role to a resource or set of resources. +// ScopeBindingTrait is used to scope a role to a resource or set of resources. // The scope may be static (determined at crawl time) or dynamic (determined based on conditions). -message RoleScopeTrait { +message ScopeBindingTrait { c1.connector.v2.ResourceId role_id = 1 [(validate.rules).message = {required: true}]; // The role that is scoped. Must be a resource with the role trait. - c1.connector.v2.ResourceId scope_resource_id = 2; // The resource that the role is scoped to. + // Remove required if we add more ways to scope roles. (eg: Expressions.) + c1.connector.v2.ResourceId scope_resource_id = 2 [(validate.rules).message = {required: true}]; // The resource that the role is scoped to. } message AppTrait { diff --git a/proto/c1/connector/v2/resource.proto b/proto/c1/connector/v2/resource.proto index 3e164a3e4..b186b8bd2 100644 --- a/proto/c1/connector/v2/resource.proto +++ b/proto/c1/connector/v2/resource.proto @@ -31,7 +31,7 @@ message ResourceType { TRAIT_APP = 4; TRAIT_SECRET = 5; TRAIT_SECURITY_INSIGHT = 6; - TRAIT_ROLE_SCOPE = 7; + TRAIT_SCOPE_BINDING = 7; } repeated Trait traits = 3 [(validate.rules).repeated = { unique: true From c75c1123c34c53ec233c4023ad09ad8c61889384 Mon Sep 17 00:00:00 2001 From: Geoff Greer Date: Mon, 26 Jan 2026 14:47:16 -0800 Subject: [PATCH 10/10] Add comment with Azure example. --- pb/c1/connector/v2/annotation_trait.pb.go | 2 ++ pb/c1/connector/v2/annotation_trait_protoopaque.pb.go | 2 ++ proto/c1/connector/v2/annotation_trait.proto | 2 ++ 3 files changed, 6 insertions(+) diff --git a/pb/c1/connector/v2/annotation_trait.pb.go b/pb/c1/connector/v2/annotation_trait.pb.go index dd8339542..8a50448f5 100644 --- a/pb/c1/connector/v2/annotation_trait.pb.go +++ b/pb/c1/connector/v2/annotation_trait.pb.go @@ -805,6 +805,8 @@ func (b0 RoleScopeCondition_builder) Build() *RoleScopeCondition { // ScopeBindingTrait is used to scope a role to a resource or set of resources. // The scope may be static (determined at crawl time) or dynamic (determined based on conditions). +// For example, in Azure a role definition can be scoped to a subscription, management group, or resource group. +// In that case, the role ID would be the resource ID of the role definition, and the scope resource ID would be the resource ID of the subscription, management group, or resource group. type ScopeBindingTrait struct { state protoimpl.MessageState `protogen:"hybrid.v1"` RoleId *ResourceId `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3" json:"role_id,omitempty"` // The role that is scoped. Must be a resource with the role trait. diff --git a/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go b/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go index 197832bd6..db2e7db80 100644 --- a/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go +++ b/pb/c1/connector/v2/annotation_trait_protoopaque.pb.go @@ -807,6 +807,8 @@ func (b0 RoleScopeCondition_builder) Build() *RoleScopeCondition { // ScopeBindingTrait is used to scope a role to a resource or set of resources. // The scope may be static (determined at crawl time) or dynamic (determined based on conditions). +// For example, in Azure a role definition can be scoped to a subscription, management group, or resource group. +// In that case, the role ID would be the resource ID of the role definition, and the scope resource ID would be the resource ID of the subscription, management group, or resource group. type ScopeBindingTrait struct { state protoimpl.MessageState `protogen:"opaque.v1"` xxx_hidden_RoleId *ResourceId `protobuf:"bytes,1,opt,name=role_id,json=roleId,proto3"` diff --git a/proto/c1/connector/v2/annotation_trait.proto b/proto/c1/connector/v2/annotation_trait.proto index c8694b407..784df5b3d 100644 --- a/proto/c1/connector/v2/annotation_trait.proto +++ b/proto/c1/connector/v2/annotation_trait.proto @@ -94,6 +94,8 @@ message RoleScopeCondition { // ScopeBindingTrait is used to scope a role to a resource or set of resources. // The scope may be static (determined at crawl time) or dynamic (determined based on conditions). +// For example, in Azure a role definition can be scoped to a subscription, management group, or resource group. +// In that case, the role ID would be the resource ID of the role definition, and the scope resource ID would be the resource ID of the subscription, management group, or resource group. message ScopeBindingTrait { c1.connector.v2.ResourceId role_id = 1 [(validate.rules).message = {required: true}]; // The role that is scoped. Must be a resource with the role trait. // Remove required if we add more ways to scope roles. (eg: Expressions.)