Skip to content

Commit 2df5d43

Browse files
committed
fix: K8s API does not accept unauthorized requests
Signed-off-by: Jan Bouska <[email protected]>
1 parent 07b0302 commit 2df5d43

File tree

2 files changed

+312
-101
lines changed

2 files changed

+312
-101
lines changed

pkg/config/config.go

Lines changed: 86 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,17 @@ type verifierWithConfig struct {
5151
*oidc.Config
5252
}
5353

54+
type bearerTokenTransport struct {
55+
Transport http.RoundTripper
56+
Token string
57+
}
58+
59+
func (t *bearerTokenTransport) RoundTrip(req *http.Request) (*http.Response, error) {
60+
req = req.Clone(req.Context())
61+
req.Header.Set("Authorization", "Bearer "+t.Token)
62+
return t.Transport.RoundTrip(req)
63+
}
64+
5465
type FulcioConfig struct {
5566
OIDCIssuers map[string]OIDCIssuer `json:"OIDCIssuers,omitempty" yaml:"oidc-issuers,omitempty"`
5667

@@ -292,55 +303,100 @@ func httpClientForIssuer(iss OIDCIssuer) (*http.Client, error) {
292303
}
293304

294305
func (fc *FulcioConfig) prepare() error {
295-
if _, ok := fc.GetIssuer("https://kubernetes.default.svc"); ok {
296-
// Add the Kubernetes cluster's CA to the system CA pool, and to
297-
// the default transport.
306+
fc.verifiers = make(map[string][]*verifierWithConfig, len(fc.OIDCIssuers))
307+
for _, iss := range fc.OIDCIssuers {
308+
if err := fc.insertVerifier(iss); err != nil {
309+
log.Logger.Errorf("error creating provider for issuer URL %q: %v", iss.IssuerURL, err)
310+
continue
311+
}
312+
}
313+
314+
_, verifierPresent := fc.verifiers[k8sIssuerURL]
315+
k8sIssuer, issuerConfigured := fc.GetIssuer(k8sIssuerURL)
316+
if issuerConfigured && !verifierPresent {
317+
// configure static validator for k8s that cover metaIssuers
318+
if err := fc.insertVerifier(k8sIssuer); err != nil {
319+
log.Logger.Errorf("error creating provider for issuer URL %q: %v", k8sIssuer.IssuerURL, err)
320+
}
321+
}
322+
323+
cache, err := lru.New2Q[string, []*verifierWithConfig](100 /* size */)
324+
if err != nil {
325+
return fmt.Errorf("lru: %w", err)
326+
}
327+
fc.lru = cache
328+
return nil
329+
}
330+
331+
var (
332+
k8sCA = "/var/run/fulcio/ca.crt"
333+
// k8sTokenFile specifies the standard path where Kubernetes automatically
334+
// mounts the projected service account token for a pod.
335+
// This path is publicly known and not a sensitive credential itself,
336+
// hence the Gosec G101 warning is a false positive and is suppressed.
337+
// #nosec G101
338+
k8sTokenFile = "/var/run/secrets/kubernetes.io/serviceaccount/token"
339+
k8sIssuerURL = "https://kubernetes.default.svc"
340+
)
341+
342+
func (fc *FulcioConfig) insertVerifier(iss OIDCIssuer) error {
343+
var client *http.Client
344+
if iss.IssuerURL == k8sIssuerURL {
345+
var transport http.RoundTripper
346+
// Add the Kubernetes cluster's CA to the client's CA pool
298347
rootCAs, _ := x509.SystemCertPool()
299348
if rootCAs == nil {
300349
rootCAs = x509.NewCertPool()
301350
}
302-
const k8sCA = "/var/run/fulcio/ca.crt"
303351
certs, err := os.ReadFile(k8sCA)
304352
if err != nil {
305-
return fmt.Errorf("read file: %w", err)
353+
return fmt.Errorf("unable to read cluster CA file: %w", err)
306354
}
307355
if ok := rootCAs.AppendCertsFromPEM(certs); !ok {
308-
return fmt.Errorf("unable to append certs")
356+
return fmt.Errorf("unable to append cluster certs")
309357
}
310358

311-
t := originalTransport.(*http.Transport).Clone()
359+
t := http.DefaultTransport.(*http.Transport).Clone()
312360
t.TLSClientConfig.RootCAs = rootCAs
313-
http.DefaultTransport = t
314-
} else {
315-
// If we parse a config that doesn't include a cluster issuer
316-
// signed with the cluster'sCA, then restore the original transport
317-
// (in case we overwrote it)
318-
http.DefaultTransport = originalTransport
319-
}
361+
transport = t
320362

321-
fc.verifiers = make(map[string][]*verifierWithConfig, len(fc.OIDCIssuers))
322-
for _, iss := range fc.OIDCIssuers {
323-
ctx, cancel := context.WithTimeout(context.Background(), defaultOIDCDiscoveryTimeout)
324-
defer cancel()
325-
client, err := httpClientForIssuer(iss)
326-
if err != nil {
327-
log.Logger.Errorf("error creating http client for issuer URL %q: %v", iss.IssuerURL, err)
328-
continue
363+
if _, err := os.Stat(k8sTokenFile); err != nil {
364+
if errors.Is(err, os.ErrNotExist) {
365+
log.Logger.Warnf("Kubernetes token file can't be found on path: %s", k8sTokenFile)
366+
} else {
367+
return err
368+
}
369+
} else {
370+
// add the authentication header
371+
tokenBytes, err := os.ReadFile(k8sTokenFile)
372+
if err != nil {
373+
return fmt.Errorf("unable to read cluster token file: %w", err)
374+
}
375+
transport = &bearerTokenTransport{
376+
Transport: transport,
377+
Token: string(tokenBytes),
378+
}
329379
}
330-
provider, err := oidc.NewProvider(oidc.ClientContext(ctx, client), iss.IssuerURL)
380+
381+
client = &http.Client{Transport: transport}
382+
383+
} else {
384+
var err error
385+
client, err = httpClientForIssuer(iss)
331386
if err != nil {
332-
log.Logger.Errorf("error creating provider for issuer URL %q: %v", iss.IssuerURL, err)
333-
} else {
334-
cfg := &oidc.Config{ClientID: iss.ClientID}
335-
fc.verifiers[iss.IssuerURL] = []*verifierWithConfig{{provider.Verifier(cfg), cfg}}
387+
return err
336388
}
337389
}
338390

339-
cache, err := lru.New2Q[string, []*verifierWithConfig](100 /* size */)
391+
ctx, cancel := context.WithTimeout(context.Background(), defaultOIDCDiscoveryTimeout)
392+
defer cancel()
393+
provider, err := oidc.NewProvider(oidc.ClientContext(ctx, client), iss.IssuerURL)
340394
if err != nil {
341-
return fmt.Errorf("lru: %w", err)
395+
return err
396+
} else {
397+
cfg := &oidc.Config{ClientID: iss.ClientID}
398+
fc.verifiers[iss.IssuerURL] = []*verifierWithConfig{{provider.Verifier(cfg), cfg}}
342399
}
343-
fc.lru = cache
344400
return nil
345401
}
346402

@@ -507,8 +563,6 @@ var DefaultConfig = &FulcioConfig{
507563
},
508564
}
509565

510-
var originalTransport = http.DefaultTransport
511-
512566
type configKey struct{}
513567

514568
func With(ctx context.Context, cfg *FulcioConfig) context.Context {

0 commit comments

Comments
 (0)