Add a parameterized types.Resource153UnwrapperT (#53567)

Provides a type safe resource 153 unwrapping variant to replace
types.Resource153Unwrapper. Most uses have been switched over to
the new type, though a few still exist and may be harder, if not
possible to convert without a considerable amount of change.
This commit is contained in:
rosstimothy
2025-04-01 10:39:44 -04:00
committed by GitHub
parent d7a8c1d4fb
commit e7069792bc
16 changed files with 209 additions and 315 deletions
+79 -84
View File
@@ -62,90 +62,85 @@ func EventToGRPC(in types.Event) (*proto.Event, error) {
return &out, nil
}
switch r := in.Resource.(type) {
case types.Resource153Unwrapper:
switch r := r.Unwrap().(type) {
case *kubewaitingcontainerpb.KubernetesWaitingContainer:
out.Resource = &proto.Event_KubernetesWaitingContainer{
KubernetesWaitingContainer: r,
}
case *notificationsv1.Notification:
out.Resource = &proto.Event_UserNotification{
UserNotification: r,
}
case *notificationsv1.GlobalNotification:
out.Resource = &proto.Event_GlobalNotification{
GlobalNotification: r,
}
case *accessmonitoringrulesv1.AccessMonitoringRule:
out.Resource = &proto.Event_AccessMonitoringRule{
AccessMonitoringRule: r,
}
case *crownjewelv1.CrownJewel:
out.Resource = &proto.Event_CrownJewel{
CrownJewel: r,
}
case *dbobjectv1.DatabaseObject:
out.Resource = &proto.Event_DatabaseObject{
DatabaseObject: r,
}
case *machineidv1.BotInstance:
out.Resource = &proto.Event_BotInstance{
BotInstance: r,
}
case *clusterconfigpb.AccessGraphSettings:
out.Resource = &proto.Event_AccessGraphSettings{
AccessGraphSettings: r,
}
case *machineidv1.SPIFFEFederation:
out.Resource = &proto.Event_SPIFFEFederation{
SPIFFEFederation: r,
}
case *userprovisioningpb.StaticHostUser:
out.Resource = &proto.Event_StaticHostUserV2{
StaticHostUserV2: r,
}
case *autoupdate.AutoUpdateConfig:
out.Resource = &proto.Event_AutoUpdateConfig{
AutoUpdateConfig: r,
}
case *autoupdate.AutoUpdateVersion:
out.Resource = &proto.Event_AutoUpdateVersion{
AutoUpdateVersion: r,
}
case *usertasksv1.UserTask:
out.Resource = &proto.Event_UserTask{
UserTask: r,
}
case *provisioningv1.PrincipalState:
out.Resource = &proto.Event_ProvisioningPrincipalState{
ProvisioningPrincipalState: r,
}
case *autoupdate.AutoUpdateAgentRollout:
out.Resource = &proto.Event_AutoUpdateAgentRollout{
AutoUpdateAgentRollout: r,
}
case *identitycenterv1.Account:
out.Resource = &proto.Event_IdentityCenterAccount{
IdentityCenterAccount: r,
}
case *identitycenterv1.PrincipalAssignment:
out.Resource = &proto.Event_IdentityCenterPrincipalAssignment{
IdentityCenterPrincipalAssignment: r,
}
case *identitycenterv1.AccountAssignment:
out.Resource = &proto.Event_IdentityCenterAccountAssignment{
IdentityCenterAccountAssignment: r,
}
case *workloadidentityv1pb.WorkloadIdentity:
out.Resource = &proto.Event_WorkloadIdentity{
WorkloadIdentity: r,
}
case *workloadidentityv1pb.WorkloadIdentityX509Revocation:
out.Resource = &proto.Event_WorkloadIdentityX509Revocation{
WorkloadIdentityX509Revocation: r,
}
default:
return nil, trace.BadParameter("resource type %T is not supported", r)
case types.Resource153UnwrapperT[*kubewaitingcontainerpb.KubernetesWaitingContainer]:
out.Resource = &proto.Event_KubernetesWaitingContainer{
KubernetesWaitingContainer: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*notificationsv1.Notification]:
out.Resource = &proto.Event_UserNotification{
UserNotification: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*notificationsv1.GlobalNotification]:
out.Resource = &proto.Event_GlobalNotification{
GlobalNotification: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*accessmonitoringrulesv1.AccessMonitoringRule]:
out.Resource = &proto.Event_AccessMonitoringRule{
AccessMonitoringRule: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*crownjewelv1.CrownJewel]:
out.Resource = &proto.Event_CrownJewel{
CrownJewel: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*dbobjectv1.DatabaseObject]:
out.Resource = &proto.Event_DatabaseObject{
DatabaseObject: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*machineidv1.BotInstance]:
out.Resource = &proto.Event_BotInstance{
BotInstance: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*clusterconfigpb.AccessGraphSettings]:
out.Resource = &proto.Event_AccessGraphSettings{
AccessGraphSettings: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*machineidv1.SPIFFEFederation]:
out.Resource = &proto.Event_SPIFFEFederation{
SPIFFEFederation: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*userprovisioningpb.StaticHostUser]:
out.Resource = &proto.Event_StaticHostUserV2{
StaticHostUserV2: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*autoupdate.AutoUpdateConfig]:
out.Resource = &proto.Event_AutoUpdateConfig{
AutoUpdateConfig: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*autoupdate.AutoUpdateVersion]:
out.Resource = &proto.Event_AutoUpdateVersion{
AutoUpdateVersion: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*usertasksv1.UserTask]:
out.Resource = &proto.Event_UserTask{
UserTask: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*provisioningv1.PrincipalState]:
out.Resource = &proto.Event_ProvisioningPrincipalState{
ProvisioningPrincipalState: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*autoupdate.AutoUpdateAgentRollout]:
out.Resource = &proto.Event_AutoUpdateAgentRollout{
AutoUpdateAgentRollout: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*identitycenterv1.Account]:
out.Resource = &proto.Event_IdentityCenterAccount{
IdentityCenterAccount: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*identitycenterv1.PrincipalAssignment]:
out.Resource = &proto.Event_IdentityCenterPrincipalAssignment{
IdentityCenterPrincipalAssignment: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*identitycenterv1.AccountAssignment]:
out.Resource = &proto.Event_IdentityCenterAccountAssignment{
IdentityCenterAccountAssignment: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*workloadidentityv1pb.WorkloadIdentity]:
out.Resource = &proto.Event_WorkloadIdentity{
WorkloadIdentity: r.UnwrapT(),
}
case types.Resource153UnwrapperT[*workloadidentityv1pb.WorkloadIdentityX509Revocation]:
out.Resource = &proto.Event_WorkloadIdentityX509Revocation{
WorkloadIdentityX509Revocation: r.UnwrapT(),
}
case *types.ResourceHeader:
out.Resource = &proto.Event_ResourceHeader{
+57 -54
View File
@@ -132,37 +132,44 @@ func (r *legacyToResource153Adapter) GetVersion() string {
//
// Note that CheckAndSetDefaults is a noop for the returned resource and
// SetSubKind is not implemented and panics on use.
func Resource153ToLegacy(r Resource153) Resource {
return &resource153ToLegacyAdapter{inner: r}
func Resource153ToLegacy[T Resource153](r T) Resource {
return &resource153ToLegacyAdapter[T]{inner: r}
}
// Resource153Unwrapper returns a legacy [Resource] type from a wrapped RFD
// 153 style resource
type Resource153Unwrapper interface {
Unwrap() Resource153
}
// Resource153Unwrapper returns a legacy [Resource153] type from a wrapped RFD
// 153 style resource. Prefer using the stronger typed [Resource153UnwrapperT]
// where possible.
type Resource153Unwrapper interface{ Unwrap() Resource153 }
// Resource153UnwrapperT returns a [T] from a wrapped RFD
// 153 style resource.
type Resource153UnwrapperT[T Resource153] interface{ UnwrapT() T }
// resource153ToLegacyAdapter wraps a new-style resource in a type implementing
// the legacy resource interfaces
type resource153ToLegacyAdapter struct {
inner Resource153
type resource153ToLegacyAdapter[T Resource153] struct {
inner T
}
// Unwrap is an escape hatch for Resource153 instances that are piped down into
// the codebase as a legacy Resource.
//
// Ideally you shouldn't depend on this.
func (r *resource153ToLegacyAdapter) Unwrap() Resource153 {
func (r *resource153ToLegacyAdapter[T]) Unwrap() Resource153 {
return r.inner
}
func (r *resource153ToLegacyAdapter[T]) UnwrapT() T {
return r.inner
}
// MarshalJSON adds support for marshaling the wrapped resource (instead of
// marshaling the adapter itself).
func (r *resource153ToLegacyAdapter) MarshalJSON() ([]byte, error) {
func (r *resource153ToLegacyAdapter[T]) MarshalJSON() ([]byte, error) {
return json.Marshal(r.inner)
}
func (r *resource153ToLegacyAdapter) Expiry() time.Time {
func (r *resource153ToLegacyAdapter[T]) Expiry() time.Time {
expires := r.inner.GetMetadata().Expires
// return zero time.time{} for zero *timestamppb.Timestamp, instead of 01/01/1970.
if expires == nil {
@@ -172,7 +179,7 @@ func (r *resource153ToLegacyAdapter) Expiry() time.Time {
return expires.AsTime()
}
func (r *resource153ToLegacyAdapter) GetKind() string {
func (r *resource153ToLegacyAdapter[T]) GetKind() string {
return r.inner.GetKind()
}
@@ -195,39 +202,39 @@ func Metadata153ToLegacy(md *headerv1.Metadata) Metadata {
}
}
func (r *resource153ToLegacyAdapter) GetMetadata() Metadata {
func (r *resource153ToLegacyAdapter[T]) GetMetadata() Metadata {
return Metadata153ToLegacy(r.inner.GetMetadata())
}
func (r *resource153ToLegacyAdapter) GetName() string {
func (r *resource153ToLegacyAdapter[T]) GetName() string {
return r.inner.GetMetadata().Name
}
func (r *resource153ToLegacyAdapter) GetRevision() string {
func (r *resource153ToLegacyAdapter[T]) GetRevision() string {
return r.inner.GetMetadata().Revision
}
func (r *resource153ToLegacyAdapter) GetSubKind() string {
func (r *resource153ToLegacyAdapter[T]) GetSubKind() string {
return r.inner.GetSubKind()
}
func (r *resource153ToLegacyAdapter) GetVersion() string {
func (r *resource153ToLegacyAdapter[T]) GetVersion() string {
return r.inner.GetVersion()
}
func (r *resource153ToLegacyAdapter) SetExpiry(t time.Time) {
func (r *resource153ToLegacyAdapter[T]) SetExpiry(t time.Time) {
r.inner.GetMetadata().Expires = timestamppb.New(t)
}
func (r *resource153ToLegacyAdapter) SetName(name string) {
func (r *resource153ToLegacyAdapter[T]) SetName(name string) {
r.inner.GetMetadata().Name = name
}
func (r *resource153ToLegacyAdapter) SetRevision(rev string) {
func (r *resource153ToLegacyAdapter[T]) SetRevision(rev string) {
r.inner.GetMetadata().Revision = rev
}
func (r *resource153ToLegacyAdapter) SetSubKind(subKind string) {
func (r *resource153ToLegacyAdapter[T]) SetSubKind(subKind string) {
panic("interface Resource153 does not implement SetSubKind")
}
@@ -235,9 +242,9 @@ func (r *resource153ToLegacyAdapter) SetSubKind(subKind string) {
// the legacy [Resource] and [ResourceWithLabels] interfaces.
//
// The same caveats that apply to [Resource153ToLegacy] apply.
func Resource153ToResourceWithLabels(r Resource153) ResourceWithLabels {
return &resource153ToResourceWithLabelsAdapter{
resource153ToLegacyAdapter{
func Resource153ToResourceWithLabels[T Resource153](r T) ResourceWithLabels {
return &resource153ToResourceWithLabelsAdapter[T]{
resource153ToLegacyAdapter[T]{
inner: r,
},
}
@@ -245,12 +252,12 @@ func Resource153ToResourceWithLabels(r Resource153) ResourceWithLabels {
// resource153ToResourceWithLabelsAdapter wraps a new-style resource in a
// type implementing the legacy resource interfaces
type resource153ToResourceWithLabelsAdapter struct {
resource153ToLegacyAdapter
type resource153ToResourceWithLabelsAdapter[T Resource153] struct {
resource153ToLegacyAdapter[T]
}
// Origin implements ResourceWithLabels for the adapter.
func (r *resource153ToResourceWithLabelsAdapter) Origin() string {
func (r *resource153ToResourceWithLabelsAdapter[T]) Origin() string {
m := r.inner.GetMetadata()
if m == nil {
return ""
@@ -259,7 +266,7 @@ func (r *resource153ToResourceWithLabelsAdapter) Origin() string {
}
// SetOrigin implements ResourceWithLabels for the adapter.
func (r *resource153ToResourceWithLabelsAdapter) SetOrigin(origin string) {
func (r *resource153ToResourceWithLabelsAdapter[T]) SetOrigin(origin string) {
m := r.inner.GetMetadata()
if m == nil {
return
@@ -268,7 +275,7 @@ func (r *resource153ToResourceWithLabelsAdapter) SetOrigin(origin string) {
}
// GetLabel implements ResourceWithLabels for the adapter.
func (r *resource153ToResourceWithLabelsAdapter) GetLabel(key string) (value string, ok bool) {
func (r *resource153ToResourceWithLabelsAdapter[T]) GetLabel(key string) (value string, ok bool) {
m := r.inner.GetMetadata()
if m == nil {
return "", false
@@ -278,7 +285,7 @@ func (r *resource153ToResourceWithLabelsAdapter) GetLabel(key string) (value str
}
// GetAllLabels implements ResourceWithLabels for the adapter.
func (r *resource153ToResourceWithLabelsAdapter) GetAllLabels() map[string]string {
func (r *resource153ToResourceWithLabelsAdapter[T]) GetAllLabels() map[string]string {
m := r.inner.GetMetadata()
if m == nil {
return nil
@@ -287,12 +294,12 @@ func (r *resource153ToResourceWithLabelsAdapter) GetAllLabels() map[string]strin
}
// GetStaticLabels implements ResourceWithLabels for the adapter.
func (r *resource153ToResourceWithLabelsAdapter) GetStaticLabels() map[string]string {
func (r *resource153ToResourceWithLabelsAdapter[T]) GetStaticLabels() map[string]string {
return r.GetAllLabels()
}
// SetStaticLabels implements ResourceWithLabels for the adapter.
func (r *resource153ToResourceWithLabelsAdapter) SetStaticLabels(labels map[string]string) {
func (r *resource153ToResourceWithLabelsAdapter[T]) SetStaticLabels(labels map[string]string) {
m := r.inner.GetMetadata()
if m == nil {
return
@@ -303,8 +310,8 @@ func (r *resource153ToResourceWithLabelsAdapter) SetStaticLabels(labels map[stri
// MatchSearch implements ResourceWithLabels for the adapter. If the underlying
// type exposes a MatchSearch method, this method will defer to that, otherwise
// it will match against the resource label values and name.
func (r *resource153ToResourceWithLabelsAdapter) MatchSearch(searchValues []string) bool {
if matcher, ok := r.inner.(interface{ MatchSearch([]string) bool }); ok {
func (r *resource153ToResourceWithLabelsAdapter[T]) MatchSearch(searchValues []string) bool {
if matcher, ok := any(r.inner).(interface{ MatchSearch([]string) bool }); ok {
return matcher.MatchSearch(searchValues)
}
fieldVals := append(utils.MapToStrings(r.GetAllLabels()), r.GetName())
@@ -330,10 +337,10 @@ type UnifiedResource interface {
// with the Teleport Unified Resources Cache.
//
// The same caveats that apply to [Resource153ToLegacy] apply.
func Resource153ToUnifiedResource(r ClonableResource153) UnifiedResource {
return &resource153ToUnifiedResourceAdapter{
resource153ToResourceWithLabelsAdapter: resource153ToResourceWithLabelsAdapter{
resource153ToLegacyAdapter{
func Resource153ToUnifiedResource[T ClonableResource153](r T) UnifiedResource {
return &resource153ToUnifiedResourceAdapter[T]{
resource153ToResourceWithLabelsAdapter: resource153ToResourceWithLabelsAdapter[T]{
resource153ToLegacyAdapter[T]{
inner: r,
},
},
@@ -342,17 +349,13 @@ func Resource153ToUnifiedResource(r ClonableResource153) UnifiedResource {
// resource153ToUnifiedResourceAdapter wraps a [resource153ToLegacyAdapter] to
// provide an implementation of [UnifiedResource]
type resource153ToUnifiedResourceAdapter struct {
resource153ToResourceWithLabelsAdapter
type resource153ToUnifiedResourceAdapter[T ClonableResource153] struct {
resource153ToResourceWithLabelsAdapter[T]
}
// CloneResource clones the underlying resource and wraps it in
func (r *resource153ToUnifiedResourceAdapter) CloneResource() ResourceWithLabels {
// We assume that this type assertion will work because we force `inner`
// to implement ClonableResource153 in [Resource153ToUnifiedResource], which
// is the only externally-visible constructor function.
clone := r.inner.(ClonableResource153).CloneResource()
return Resource153ToUnifiedResource(clone)
func (r *resource153ToUnifiedResourceAdapter[T]) CloneResource() ResourceWithLabels {
return Resource153ToUnifiedResource(r.inner.CloneResource().(T))
}
// ProtoResource153 is a Resource153 implemented by a protobuf-generated struct.
@@ -361,14 +364,14 @@ type ProtoResource153 interface {
proto.Message
}
type protoResource153ToLegacyAdapter struct {
inner ProtoResource153
resource153ToLegacyAdapter
type protoResource153ToLegacyAdapter[T ProtoResource153] struct {
inner T
resource153ToLegacyAdapter[T]
}
// MarshalJSON adds support for marshaling the wrapped resource (instead of
// marshaling the adapter itself).
func (r *protoResource153ToLegacyAdapter) MarshalJSON() ([]byte, error) {
func (r *protoResource153ToLegacyAdapter[T]) MarshalJSON() ([]byte, error) {
return protojson.MarshalOptions{
UseProtoNames: true,
}.Marshal(r.inner)
@@ -381,9 +384,9 @@ func (r *protoResource153ToLegacyAdapter) MarshalJSON() ([]byte, error) {
//
// Note that CheckAndSetDefaults is a noop for the returned resource and
// SetSubKind is not implemented and panics on use.
func ProtoResource153ToLegacy(r ProtoResource153) Resource {
return &protoResource153ToLegacyAdapter{
func ProtoResource153ToLegacy[T ProtoResource153](r T) Resource {
return &protoResource153ToLegacyAdapter[T]{
r,
resource153ToLegacyAdapter{r},
resource153ToLegacyAdapter[T]{r},
}
}
+6
View File
@@ -87,6 +87,12 @@ func TestResource153ToLegacy(t *testing.T) {
if diff := cmp.Diff(bot, unwrapped, protocmp.Transform()); diff != "" {
t.Errorf("Unwrap mismatch (-want +got)\n%s", diff)
}
unwrapperT := legacyResource.(types.Resource153UnwrapperT[*machineidv1.Bot])
unwrappedT := unwrapperT.UnwrapT()
if diff := cmp.Diff(bot, unwrappedT, protocmp.Transform()); diff != "" {
t.Errorf("Unwrap mismatch (-want +got)\n%s", diff)
}
})
// Marshaling as JSON marshals the underlying resource.
@@ -116,15 +116,11 @@ func (amrh *RuleHandler) HandleAccessMonitoringRule(ctx context.Context, event t
defer amrh.accessMonitoringRules.Unlock()
switch op := event.Type; op {
case types.OpPut:
e, ok := event.Resource.(types.Resource153Unwrapper)
e, ok := event.Resource.(types.Resource153UnwrapperT[*accessmonitoringrulesv1.AccessMonitoringRule])
if !ok {
return trace.BadParameter("expected Resource153Unwrapper resource type, got %T", event.Resource)
}
req, ok := e.Unwrap().(*accessmonitoringrulesv1.AccessMonitoringRule)
if !ok {
return trace.BadParameter("expected AccessMonitoringRule resource type, got %T", event.Resource)
}
req := e.UnwrapT()
// In the event an existing rule no longer applies we must remove it.
if !amrh.ruleApplies(req) {
delete(amrh.accessMonitoringRules.rules, event.Resource.GetName())
+7 -12
View File
@@ -1968,20 +1968,15 @@ func (r resourceChecker) CanAccess(resource types.Resource) error {
}
case types.SAMLIdPServiceProvider:
return r.CheckAccess(rr, state)
case types.Resource153Unwrapper:
case types.Resource153UnwrapperT[services.IdentityCenterAccount]:
checkable, isCheckable := rr.(services.AccessCheckable)
if isCheckable {
switch unwrapped := rr.Unwrap().(type) {
case services.IdentityCenterAccount:
return r.CheckAccess(checkable, state, services.NewIdentityCenterAccountMatcher(unwrapped))
case services.IdentityCenterAccountAssignment:
return r.CheckAccess(checkable, state, services.NewIdentityCenterAccountAssignmentMatcher(unwrapped))
default:
return r.CheckAccess(checkable, state)
}
return r.CheckAccess(checkable, state, services.NewIdentityCenterAccountMatcher(rr.UnwrapT()))
}
case types.Resource153UnwrapperT[services.IdentityCenterAccountAssignment]:
checkable, isCheckable := rr.(services.AccessCheckable)
if isCheckable {
return r.CheckAccess(checkable, state, services.NewIdentityCenterAccountAssignmentMatcher(rr.UnwrapT()))
}
}
@@ -490,22 +490,14 @@ func (s *RevocationService) watchAndSign(ctx context.Context) error {
handleEvent := func(e types.Event) (bool, error) {
switch e.Type {
case types.OpPut:
unwrapper, ok := e.Resource.(types.Resource153Unwrapper)
unwrapper, ok := e.Resource.(types.Resource153UnwrapperT[*workloadidentityv1pb.WorkloadIdentityX509Revocation])
if !ok {
return false, trace.BadParameter(
"expected event resource (%s) to implement Resource153Wrapper",
e.Resource.GetName(),
)
}
unwrapped := unwrapper.Unwrap()
revocation, ok := unwrapped.(*workloadidentityv1pb.WorkloadIdentityX509Revocation)
if !ok {
return false, trace.BadParameter(
"expected event resource (%s) to be a WorkloadIdentityX509Revocation, but it was %T",
e.Resource.GetName(),
unwrapped,
)
}
revocation := unwrapper.UnwrapT()
revocationsMap[revocation.Metadata.Name] = revocation
return true, nil
case types.OpDelete:
+14 -27
View File
@@ -2428,18 +2428,16 @@ func (kubeWaitingContainerExecutor) deleteAll(ctx context.Context, cache *Cache)
func (kubeWaitingContainerExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
switch r := resource.(type) {
case types.Resource153Unwrapper:
switch wc := r.Unwrap().(type) {
case *kubewaitingcontainerpb.KubernetesWaitingContainer:
err := cache.kubeWaitingContsCache.DeleteKubernetesWaitingContainer(ctx, &kubewaitingcontainerpb.DeleteKubernetesWaitingContainerRequest{
Username: wc.Spec.Username,
Cluster: wc.Spec.Cluster,
Namespace: wc.Spec.Namespace,
PodName: wc.Spec.PodName,
ContainerName: wc.Spec.ContainerName,
})
return trace.Wrap(err)
}
case types.Resource153UnwrapperT[*kubewaitingcontainerpb.KubernetesWaitingContainer]:
wc := r.UnwrapT()
err := cache.kubeWaitingContsCache.DeleteKubernetesWaitingContainer(ctx, &kubewaitingcontainerpb.DeleteKubernetesWaitingContainerRequest{
Username: wc.Spec.Username,
Cluster: wc.Spec.Cluster,
Namespace: wc.Spec.Namespace,
PodName: wc.Spec.PodName,
ContainerName: wc.Spec.ContainerName,
})
return trace.Wrap(err)
}
return trace.BadParameter("unknown KubeWaitingContainer type, expected *kubewaitingcontainerpb.KubernetesWaitingContainer, got %T", resource)
@@ -3342,16 +3340,11 @@ func (userNotificationExecutor) deleteAll(ctx context.Context, cache *Cache) err
}
func (userNotificationExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
r, ok := resource.(types.Resource153Unwrapper)
r, ok := resource.(types.Resource153UnwrapperT[*notificationsv1.Notification])
if !ok {
return trace.BadParameter("unknown resource type, expected types.Resource153Unwrapper, got %T", resource)
}
notification, ok := r.Unwrap().(*notificationsv1.Notification)
if !ok {
return trace.BadParameter("unknown Notification type, expected *notificationsv1.Notification, got %T", resource)
}
notification := r.UnwrapT()
username := notification.GetSpec().GetUsername()
notificationId := notification.GetMetadata().GetName()
@@ -3405,17 +3398,11 @@ func (globalNotificationExecutor) deleteAll(ctx context.Context, cache *Cache) e
}
func (globalNotificationExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
r, ok := resource.(types.Resource153Unwrapper)
r, ok := resource.(types.Resource153UnwrapperT[*notificationsv1.GlobalNotification])
if !ok {
return trace.BadParameter("unknown resource type, expected types.Resource153Unwrapper, got %T", resource)
}
globalNotification, ok := r.Unwrap().(*notificationsv1.GlobalNotification)
if !ok {
return trace.BadParameter("unknown Notification type, expected *notificationsv1.GlobalNotification, got %T", resource)
}
globalNotification := r.UnwrapT()
notificationId := globalNotification.GetMetadata().GetName()
err := cache.notificationsCache.DeleteGlobalNotification(ctx, notificationId)
+2 -6
View File
@@ -70,16 +70,12 @@ func (provisioningStateExecutor) upsert(ctx context.Context, cache *Cache, resou
}
func (provisioningStateExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
unwrapper, ok := resource.(types.Resource153Unwrapper)
unwrapper, ok := resource.(types.Resource153UnwrapperT[*provisioningv1.PrincipalState])
if !ok {
return trace.BadParameter("resource must implement Resource153Unwrapper: %T", resource)
}
principalState, ok := unwrapper.Unwrap().(*provisioningv1.PrincipalState)
if !ok {
return trace.BadParameter("wrapped resource must be a PrincipalState: %T", resource)
}
principalState := unwrapper.UnwrapT()
principalStateID := principalState.GetMetadata().GetName()
downstreamID := principalState.GetSpec().GetDownstreamId()
if principalStateID == "" || downstreamID == "" {
+4 -8
View File
@@ -462,14 +462,10 @@ func (a *accessChecker) CheckAccess(r AccessCheckable, state AccessState, matche
}
switch rr := r.(type) {
case types.Resource153Unwrapper:
switch urr := rr.Unwrap().(type) {
case IdentityCenterAccount:
matchers = append(matchers, NewIdentityCenterAccountMatcher(urr))
case IdentityCenterAccountAssignment:
matchers = append(matchers, NewIdentityCenterAccountAssignmentMatcher(urr))
}
case types.Resource153UnwrapperT[IdentityCenterAccount]:
matchers = append(matchers, NewIdentityCenterAccountMatcher(rr.UnwrapT()))
case types.Resource153UnwrapperT[IdentityCenterAccountAssignment]:
matchers = append(matchers, NewIdentityCenterAccountAssignmentMatcher(rr.UnwrapT()))
}
return trace.Wrap(a.RoleSet.checkAccess(r, a.info.Traits, state, matchers...))
+4 -8
View File
@@ -2175,14 +2175,10 @@ func (m *RequestValidator) pruneResourceRequestRoles(
}
switch rr := resource.(type) {
case types.Resource153Unwrapper:
switch urr := rr.Unwrap().(type) {
case IdentityCenterAccount:
matchers = append(matchers, NewIdentityCenterAccountMatcher(urr))
case IdentityCenterAccountAssignment:
matchers = append(matchers, NewIdentityCenterAccountAssignmentMatcher(urr))
}
case types.Resource153UnwrapperT[IdentityCenterAccount]:
matchers = append(matchers, NewIdentityCenterAccountMatcher(rr.UnwrapT()))
case types.Resource153UnwrapperT[IdentityCenterAccountAssignment]:
matchers = append(matchers, NewIdentityCenterAccountAssignmentMatcher(rr.UnwrapT()))
}
for _, role := range allRoles {
+3 -4
View File
@@ -56,12 +56,11 @@ func newTestContext(t *testing.T) context.Context {
return ctx
}
func unwrapResource153[T any](t *testing.T, r types.Resource) T {
u, ok := r.(types.Resource153Unwrapper)
func unwrapResource153[T types.Resource153](t *testing.T, r types.Resource) T {
u, ok := r.(types.Resource153UnwrapperT[T])
require.True(t, ok, "expected event to implement Resource153Unwrapper")
dst, ok := u.Unwrap().(T)
require.True(t, ok, "expected event to cast to %T", dst)
dst := u.UnwrapT()
return dst
}
+5 -12
View File
@@ -73,14 +73,7 @@ func itemsFromResource(resource types.Resource) ([]backend.Item, error) {
var extItems []backend.Item
var err error
// Unwrap "new style" resources.
// We always want to switch over the underlying type.
var res any = resource
if w, ok := res.(types.Resource153Unwrapper); ok {
res = w.Unwrap()
}
switch r := res.(type) {
switch r := resource.(type) {
case types.User:
item, err = itemFromUser(r)
if auth := r.GetLocalAuth(); err == nil && auth != nil {
@@ -106,10 +99,10 @@ func itemsFromResource(resource types.Resource) ([]backend.Item, error) {
item, err = itemFromClusterNetworkingConfig(r)
case types.AuthPreference:
item, err = itemFromAuthPreference(r)
case *autoupdatev1pb.AutoUpdateConfig:
item, err = itemFromAutoUpdateConfig(r)
case *autoupdatev1pb.AutoUpdateVersion:
item, err = itemFromAutoUpdateVersion(r)
case types.Resource153UnwrapperT[*autoupdatev1pb.AutoUpdateConfig]:
item, err = itemFromAutoUpdateConfig(r.UnwrapT())
case types.Resource153UnwrapperT[*autoupdatev1pb.AutoUpdateVersion]:
item, err = itemFromAutoUpdateVersion(r.UnwrapT())
default:
return nil, trace.NotImplemented("cannot itemFrom resource of type %T", resource)
}
+4 -16
View File
@@ -462,18 +462,12 @@ func (c *UserNotificationCache) processEventsAndUpdateCurrent(ctx context.Contex
case types.OpPut:
// Since the EventsService watcher currently only supports legacy resources, we had to use types.Resource153ToLegacy() when parsing the event
// to transform the notification into a legacy resource. We now have to use Unwrap() to get the original RFD153-style notification out and add it to the cache.
resource153, ok := event.Resource.(types.Resource153Unwrapper)
resource153, ok := event.Resource.(types.Resource153UnwrapperT[*notificationsv1.Notification])
if !ok {
slog.WarnContext(ctx, "Unexpected resource type in event (expected types.Resource153Unwrapper)", "resource_type", logutils.TypeAttr(resource153))
continue
}
resource := resource153.Unwrap()
notification, ok := resource.(*notificationsv1.Notification)
if !ok {
slog.WarnContext(ctx, "Unexpected resource type in event (expected *notificationsv1.Notification)", "resource_type", logutils.TypeAttr(resource))
continue
}
notification := resource153.UnwrapT()
if evicted := cache.Put(notification); evicted > 1 {
slog.WarnContext(ctx, "Processing of put event for notification resulted in multiple cache evictions (this is a bug).", "notification", notification.GetMetadata().GetName())
}
@@ -493,18 +487,12 @@ func (c *GlobalNotificationCache) processEventsAndUpdateCurrent(ctx context.Cont
for _, event := range events {
switch event.Type {
case types.OpPut:
resource153, ok := event.Resource.(types.Resource153Unwrapper)
resource153, ok := event.Resource.(types.Resource153UnwrapperT[*notificationsv1.GlobalNotification])
if !ok {
slog.WarnContext(ctx, "Unexpected resource type in event (expected types.Resource153Unwrapper)", "resource_type", logutils.TypeAttr(resource153))
continue
}
resource := resource153.Unwrap()
globalNotification, ok := resource.(*notificationsv1.GlobalNotification)
if !ok {
slog.WarnContext(ctx, "Unexpected resource type in event (expected *notificationsv1.GlobalNotification)", "resource_type", logutils.TypeAttr(resource))
continue
}
globalNotification := resource153.UnwrapT()
if evicted := cache.Put(globalNotification); evicted > 1 {
slog.WarnContext(ctx, "Processing of put event for notification resulted in multiple cache evictions (this is a bug).", "notification", globalNotification.GetMetadata().GetName())
}
+14 -52
View File
@@ -349,7 +349,7 @@ func (c *UnifiedResourceCache) SAMLIdPServiceProviders(ctx context.Context, para
func (c *UnifiedResourceCache) IdentityCenterAccounts(ctx context.Context, params UnifiedResourcesIterateParams) iter.Seq2[*identitycenterv1.Account, error] {
// cloning is performed on the concrete resource below instead of
// on the wrapper type.
cloneFn := func(account IdentityCenterAccount) IdentityCenterAccount {
cloneFn := func(account types.Resource153UnwrapperT[IdentityCenterAccount]) types.Resource153UnwrapperT[IdentityCenterAccount] {
return account
}
return func(yield func(*identitycenterv1.Account, error) bool) {
@@ -359,7 +359,7 @@ func (c *UnifiedResourceCache) IdentityCenterAccounts(ctx context.Context, param
return
}
if !yield(apiutils.CloneProtoMsg(account.Account), nil) {
if !yield(apiutils.CloneProtoMsg(account.UnwrapT().Account), nil) {
return
}
}
@@ -370,7 +370,7 @@ func (c *UnifiedResourceCache) IdentityCenterAccounts(ctx context.Context, param
func (c *UnifiedResourceCache) IdentityCenterAccountAssignments(ctx context.Context, params UnifiedResourcesIterateParams) iter.Seq2[*identitycenterv1.AccountAssignment, error] {
// cloning is performed on the concrete resource below instead of
// on the wrapper type.
cloneFn := func(account IdentityCenterAccountAssignment) IdentityCenterAccountAssignment {
cloneFn := func(account types.Resource153UnwrapperT[IdentityCenterAccountAssignment]) types.Resource153UnwrapperT[IdentityCenterAccountAssignment] {
return account
}
return func(yield func(*identitycenterv1.AccountAssignment, error) bool) {
@@ -380,7 +380,7 @@ func (c *UnifiedResourceCache) IdentityCenterAccountAssignments(ctx context.Cont
return
}
if !yield(apiutils.CloneProtoMsg(assignment.AccountAssignment), nil) {
if !yield(apiutils.CloneProtoMsg(assignment.UnwrapT().AccountAssignment), nil) {
return
}
}
@@ -397,20 +397,8 @@ func iterateUnifiedResourceCache[T any](ctx context.Context, c *UnifiedResourceC
return
}
switch r := i.resource.(type) {
case T:
if !yield(cloneFn(r), nil) {
return
}
case types.Resource153Unwrapper:
res, ok := r.Unwrap().(T)
if !ok {
continue
}
if !yield(cloneFn(res), nil) {
return
}
if !yield(cloneFn(i.resource.(T)), nil) {
return
}
}
}
@@ -975,30 +963,13 @@ func (c *UnifiedResourceCache) processEventsAndUpdateCurrent(ctx context.Context
switch r := event.Resource.(type) {
case resource:
c.putLocked(r)
case types.Resource153Unwrapper:
// Raw RFD-153 style resources generally have very few methods
// defined on them by design. One way to add complex behavior to
// these resources is to wrap them inside another type that implements
// any methods or interfaces they need. Resources arriving here
// via the cache protocol will have those wrappers stripped away,
// so we unfortunately need to unwrap and re-wrap these values
// to restore them to a useful state.
switch unwrapped := r.Unwrap().(type) {
case IdentityCenterAccount:
c.putLocked(types.Resource153ToUnifiedResource(unwrapped))
case IdentityCenterAccountAssignment:
c.putLocked(types.Resource153ToUnifiedResource(unwrapped))
default:
c.logger.WarnContext(ctx, "unsupported Resource153 type", "resource_type", logutils.TypeAttr(unwrapped))
}
case types.Resource153UnwrapperT[IdentityCenterAccount]:
c.putLocked(types.Resource153ToUnifiedResource(r.UnwrapT()))
case types.Resource153UnwrapperT[IdentityCenterAccountAssignment]:
c.putLocked(types.Resource153ToUnifiedResource(r.UnwrapT()))
default:
c.logger.WarnContext(ctx, "unsupported Resource type", "resource_type", logutils.TypeAttr(r))
}
default:
c.logger.WarnContext(ctx, "unsupported event type", "event_type", event.Type)
continue
@@ -1208,17 +1179,11 @@ func MakePaginatedResource(ctx context.Context, requestType string, r types.Reso
}
case types.KindIdentityCenterAccountAssignment:
unwrapper, ok := resource.(types.Resource153Unwrapper)
unwrapper, ok := resource.(types.Resource153UnwrapperT[IdentityCenterAccountAssignment])
if !ok {
return nil, trace.BadParameter("%s has invalid type %T", resourceKind, resource)
}
assignment, ok := unwrapper.Unwrap().(IdentityCenterAccountAssignment)
if !ok {
return nil, trace.BadParameter(
"Unexpected type for Identity Center Account Assignment: %T",
unwrapper)
}
assignment := unwrapper.UnwrapT()
protoResource = &proto.PaginatedResource{
Resource: proto.PackICAccountAssignment(assignment.AccountAssignment),
RequiresRequest: requiresRequest,
@@ -1247,14 +1212,11 @@ func MakePaginatedResource(ctx context.Context, requestType string, r types.Reso
// makePaginatedIdentityCenterAccount returns a representation of the supplied
// Identity Center account as an App.
func makePaginatedIdentityCenterAccount(resourceKind string, resource types.ResourceWithLabels, requiresRequest bool) (*proto.PaginatedResource, error) {
unwrapper, ok := resource.(types.Resource153Unwrapper)
unwrapper, ok := resource.(types.Resource153UnwrapperT[IdentityCenterAccount])
if !ok {
return nil, trace.BadParameter("%s has invalid type %T", resourceKind, resource)
}
acct, ok := unwrapper.Unwrap().(IdentityCenterAccount)
if !ok {
return nil, trace.BadParameter("%s has invalid inner type %T", resourceKind, resource)
}
acct := unwrapper.UnwrapT()
srcPSs := acct.GetSpec().GetPermissionSetInfo()
pss := make([]*types.IdentityCenterPermissionSet, len(srcPSs))
for i, ps := range acct.GetSpec().GetPermissionSetInfo() {
+4 -6
View File
@@ -27,6 +27,7 @@ import (
"github.com/jonboulle/clockwork"
userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2"
userprovisioningv2 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/types/label"
apiutils "github.com/gravitational/teleport/api/utils"
@@ -184,16 +185,13 @@ func (s *StaticHostUserHandler) run(ctx context.Context) error {
if event.Type != types.OpPut {
continue
}
r, ok := event.Resource.(types.Resource153Unwrapper)
if !ok {
slog.WarnContext(ctx, "Unexpected resource type.", "resource", event.Resource)
continue
}
hostUser, ok := r.Unwrap().(*userprovisioningpb.StaticHostUser)
r, ok := event.Resource.(types.Resource153UnwrapperT[*userprovisioningv2.StaticHostUser])
if !ok {
slog.WarnContext(ctx, "Unexpected resource type.", "resource", event.Resource)
continue
}
hostUser := r.UnwrapT()
if err := s.handleNewHostUser(ctx, hostUser); err != nil {
// Log the error so we don't stop the handler.
slog.WarnContext(ctx, "Error handling static host user.", "error", err, "login", hostUser.GetMetadata().Name)
@@ -470,7 +470,7 @@ func (m *TrustBundleCache) processEvent(ctx context.Context, event types.Event)
bundleSet.Local = bundle
m.setBundleSet(bundleSet)
case types.KindSPIFFEFederation:
r153, ok := event.Resource.(types.Resource153Unwrapper)
r153, ok := event.Resource.(types.Resource153UnwrapperT[*machineidv1pb.SPIFFEFederation])
if !ok {
log.WarnContext(
ctx,
@@ -479,15 +479,7 @@ func (m *TrustBundleCache) processEvent(ctx context.Context, event types.Event)
)
return
}
federation, ok := r153.Unwrap().(*machineidv1pb.SPIFFEFederation)
if !ok {
log.WarnContext(
ctx,
"Event did not contain expected type",
"got", reflect.TypeOf(event.Resource),
)
return
}
federation := r153.UnwrapT()
log.DebugContext(
ctx,
"Processing update for federated trust bundle",