Repository: kubernetes
Issue: apimachinery's unstructured converter panics if the destination struct contains private fields
Labels: kind/bug,sig/api-machinery,triage/accepted

### What happened?

Using the DefaultUnstructuredConverter with a destination struct containing a non-exported field throws a panic.

```
panic: reflect: reflect.Value.Set using value obtained using unexported field

goroutine 1 [running]:
reflect.flag.mustBeAssignableSlow(0x140000337a8?)
        /usr/local/go/src/reflect/value.go:269 +0xb4
reflect.flag.mustBeAssignable(...)
        /usr/local/go/src/reflect/value.go:259
reflect.Value.Set({0x100f4c3e0?, 0x14000169800?, 0x14000011168?}, {0x100f4c3e0?, 0x101232e40?, 0x98?})
        /usr/local/go/src/reflect/value.go:2319 +0x58
k8s.io/apimachinery/pkg/runtime.structFromUnstructured({0x100f63c60?, 0x140001697d0?, 0x1012f0248?}, {0x100f7e000?, 0x14000169800?, 0x100c2d5f8?}, 0x14000033e60)
        /Users/shaka/go/pkg/mod/k8s.io/apimachinery@v0.29.3/pkg/runtime/converter.go:556 +0x490
k8s.io/apimachinery/pkg/runtime.fromUnstructured({0x100f63c60?, 0x140001697d0?, 0x1400001115c?}, {0x100f7e000?, 0x14000169800?, 0x98?}, 0x14000033e60)
        /Users/shaka/go/pkg/mod/k8s.io/apimachinery@v0.29.3/pkg/runtime/converter.go:359 +0x2c4
k8s.io/apimachinery/pkg/runtime.structFromUnstructured({0x100f63c60?, 0x140001697a0?, 0x14000033c48?}, {0x100f71840?, 0x14000169800?, 0x100cabbf4?}, 0x14000033e60)
        /Users/shaka/go/pkg/mod/k8s.io/apimachinery@v0.29.3/pkg/runtime/converter.go:550 +0x64c
k8s.io/apimachinery/pkg/runtime.fromUnstructured({0x100f63c60?, 0x140001697a0?, 0x10?}, {0x100f71840?, 0x14000169800?, 0x100c35cec?}, 0x14000033e60)
        /Users/shaka/go/pkg/mod/k8s.io/apimachinery@v0.29.3/pkg/runtime/converter.go:359 +0x2c4
k8s.io/apimachinery/pkg/runtime.(*unstructuredConverter).FromUnstructuredWithValidation(0x1011c8df0, 0x140001697a0, {0x100f44b20, 0x14000169800}, 0x1)
        /Users/shaka/go/pkg/mod/k8s.io/apimachinery@v0.29.3/pkg/runtime/converter.go:247 +0x20c
main.main()
        /Users/shaka/playground/repro-runtime-panic/main.go:30 +0x110
```

I might be in a specific edge case, but we use protobuf to generate gRPC structs. Those structs contain [private fields holding the grpc state](https://github.com/gravitational/teleport/blob/19b09e5a5c60e5e15f72324965a19d4762adbc97/api/gen/proto/go/teleport/machineid/v1/bot.pb.go#L195-L208) and cause the converter to panic, even if the unstructured object only contains the public user-facing fields.

### What did you expect to happen?

I would expect the converter to ignore private fields and not panic.

### How can we reproduce it (as minimally and precisely as possible)?

```go
package main

import (
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime"
	"log"
)

type StructuredObject struct {
	Spec StructuredObjectSpec
}

type StructuredObjectSpec struct {
	bar []byte
	Foo string
}

func main() {
	u := &unstructured.Unstructured{
		Object: map[string]interface{}{
			"spec": map[string]interface{}{
				"foo": "value",
			},
		},
	}

	structured := StructuredObject{}
	err := runtime.DefaultUnstructuredConverter.FromUnstructuredWithValidation(
		u.Object,
		&structured,
		true, /* returnUnknownFields */
	)
	if err != nil {
		log.Fatal(err)
	}
}
```

### Anything else we need to know?

I can send a PR if you confirm this should be fixed and that the fix is to skip the private fields.

### Kubernetes version

The go module looks like
```
go 1.22

require k8s.io/apimachinery v0.29.3
```

### Cloud provider

No cloud provider.

### OS version

_No response_

### Install tools

Go 1.22

### Container runtime (CRI) and version (if applicable)

_No response_

### Related plugins (CNI, CSI, ...) and versions (if applicable)

_No response_