Skip to content

Commit d16c74e

Browse files
committed
fix sha generation and token exchange error handling
1 parent 3fd8aad commit d16c74e

File tree

4 files changed

+57
-13
lines changed

4 files changed

+57
-13
lines changed

modules/common/client/args/args.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,17 @@ var (
1515
argCacheRefreshDebounce = pflag.Duration("cache-refresh-debounce", 5*time.Second, "minimal time between cache refreshes in the background")
1616
)
1717

18+
func Ensure() {
19+
if *argClusterContextEnabled && len(*argTokenExchangeEndpoint) == 0 {
20+
panic("token-exchange-endpoint must be set when cluster-context-enabled is set to true")
21+
}
22+
}
23+
1824
func CacheEnabled() bool {
1925
return *argCacheEnabled
2026
}
2127

2228
func ClusterContextEnabled() bool {
23-
if *argClusterContextEnabled && len(*argTokenExchangeEndpoint) == 0 {
24-
panic("token-exchange-endpoint must be set when cluster-context-enabled is set to true")
25-
}
26-
2729
return *argClusterContextEnabled
2830
}
2931

modules/common/client/cache/client/common/resourcelister.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import (
44
"context"
55
"fmt"
66

7+
"github.com/samber/lo"
78
authorizationapiv1 "k8s.io/api/authorization/v1"
89
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
910
authorizationv1 "k8s.io/client-go/kubernetes/typed/authorization/v1"
10-
"k8s.io/dashboard/client/cache"
1111
"k8s.io/klog/v2"
1212

13+
"k8s.io/dashboard/client/cache"
14+
1315
"k8s.io/dashboard/errors"
1416
"k8s.io/dashboard/types"
1517
)
@@ -29,13 +31,13 @@ func (in CachedResourceLister[T]) List(ctx context.Context, lister ResourceListe
2931
cacheKey := in.cacheKey(opts)
3032
cachedList, found, err := cache.Get[*T](cacheKey)
3133
if err != nil {
32-
return nil, err
34+
return new(T), err
3335
}
3436

3537
if !found {
3638
list, err := lister.List(ctx, opts)
3739
if err != nil {
38-
return list, err
40+
return new(T), err
3941
}
4042

4143
klog.V(3).InfoS("resource not found in cache, initializing")
@@ -44,7 +46,7 @@ func (in CachedResourceLister[T]) List(ctx context.Context, lister ResourceListe
4446

4547
review, err := in.authorizationV1.SelfSubjectAccessReviews().Create(ctx, in.selfSubjectAccessReview(), metav1.CreateOptions{})
4648
if err != nil {
47-
return nil, err
49+
return new(T), err
4850
}
4951

5052
if review.Status.Allowed {
@@ -55,7 +57,7 @@ func (in CachedResourceLister[T]) List(ctx context.Context, lister ResourceListe
5557
return cachedList, nil
5658
}
5759

58-
return nil, errors.NewForbidden(
60+
return lo.Empty[*T](), errors.NewForbidden(
5961
errors.MsgForbiddenError,
6062
fmt.Errorf("%s: %s", review.Status.Reason, review.Status.EvaluationError),
6163
)

modules/common/client/cache/key.go

+41-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package cache
22

33
import (
4+
"encoding/json"
5+
"fmt"
46
"io"
57
"net/http"
68

@@ -9,6 +11,7 @@ import (
911
"k8s.io/klog/v2"
1012

1113
"k8s.io/dashboard/client/args"
14+
"k8s.io/dashboard/errors"
1215
"k8s.io/dashboard/helpers"
1316
"k8s.io/dashboard/types"
1417
)
@@ -18,6 +21,13 @@ import (
1821
// multi-cluster resources.
1922
var contextCache *theine.Cache[string, string]
2023

24+
func init() {
25+
var err error
26+
if contextCache, err = theine.NewBuilder[string, string](int64(args.CacheSize())).Build(); err != nil {
27+
panic(err)
28+
}
29+
}
30+
2131
// key is an internal structure used for creating
2232
// a unique cache key SHA. It is used when
2333
// `cluster-context-enabled=false`.
@@ -34,10 +44,21 @@ type key struct {
3444

3545
// SHA calculates sha based on the internal key fields.
3646
func (k key) SHA() (string, error) {
37-
k.opts = metav1.ListOptions{LabelSelector: k.opts.LabelSelector, FieldSelector: k.opts.FieldSelector}
3847
return helpers.HashObject(k)
3948
}
4049

50+
func (k key) MarshalJSON() ([]byte, error) {
51+
return json.Marshal(struct {
52+
Kind types.ResourceKind
53+
Namespace string
54+
Opts metav1.ListOptions
55+
}{
56+
Kind: k.kind,
57+
Namespace: k.namespace,
58+
Opts: metav1.ListOptions{LabelSelector: k.opts.LabelSelector, FieldSelector: k.opts.FieldSelector},
59+
})
60+
}
61+
4162
// Key embeds an internal key structure and extends it with the support
4263
// for the multi-cluster cache key creation. It is used when
4364
// `cluster-context-enabled=true`.
@@ -53,6 +74,16 @@ type Key struct {
5374
context string
5475
}
5576

77+
func (k Key) MarshalJSON() ([]byte, error) {
78+
return json.Marshal(struct {
79+
K key
80+
Context string
81+
}{
82+
K: k.key,
83+
Context: k.context,
84+
})
85+
}
86+
5687
// SHA calculates sha based on the internal struct fields.
5788
// It is also responsible for exchanging the [Key.Token] for
5889
// the context identifier with the external source of truth
@@ -72,8 +103,6 @@ func (k Key) SHA() (sha string, err error) {
72103
contextCache.SetWithTTL(k.token, contextKey, 1, args.CacheTTL())
73104
}
74105

75-
k.opts = metav1.ListOptions{LabelSelector: k.opts.LabelSelector, FieldSelector: k.opts.FieldSelector}
76-
k.token = ""
77106
k.context = contextKey
78107
return helpers.HashObject(k)
79108
}
@@ -100,6 +129,15 @@ func exchangeToken(token string) (string, error) {
100129
return "", err
101130
}
102131

132+
if response.StatusCode == http.StatusUnauthorized || response.StatusCode == http.StatusForbidden {
133+
return "", errors.NewUnauthorized(fmt.Sprintf("could not exchange token: %s", response.Status))
134+
}
135+
136+
if response.StatusCode != http.StatusOK {
137+
klog.ErrorS(errors.NewBadRequest(response.Status), "could not exchange token", "url", args.TokenExchangeEndpoint())
138+
return "", errors.NewBadRequest(response.Status)
139+
}
140+
103141
defer func(body io.ReadCloser) {
104142
if err := body.Close(); err != nil {
105143
klog.V(3).ErrorS(err, "could not close response body writer")

modules/common/client/init.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"k8s.io/client-go/tools/clientcmd/api"
2626
"k8s.io/klog/v2"
2727

28+
"k8s.io/dashboard/client/args"
2829
"k8s.io/dashboard/errors"
2930
)
3031

@@ -206,8 +207,9 @@ func handleImpersonation(authInfo *api.AuthInfo, request *http.Request) {
206207
}
207208

208209
func Init(options ...Option) {
209-
builder := newConfigBuilder(options...)
210+
args.Ensure()
210211

212+
builder := newConfigBuilder(options...)
211213
config, err := builder.buildBaseConfig()
212214
if err != nil {
213215
klog.Errorf("Could not init kubernetes client config: %s", err)

0 commit comments

Comments
 (0)