Skip to content

Commit 228829a

Browse files
ugiordanclaude
andcommitted
fix: handle transient API errors and improve TLS profile fallback
Two fixes to the TLS profile integration: 1. NewTLSConfigFromProfile was only called in the success branch of the TLS profile fetch. On error paths (non-OpenShift, not found), no TLS config was applied, leaving Go's bare defaults. Now it always runs with an explicit Intermediate fallback on all error paths. 2. Transient API errors (ServiceUnavailable, Timeout, ServerTimeout, TooManyRequests, DeadlineExceeded) crashed the operator. Now they fall back to Intermediate defaults and set tlsProfileFetched=true so the SecurityProfileWatcher self-heals when the API recovers. Also adds context.WithTimeout (10s) to both TLS profile and adherence policy fetches, and simplifies adherence error handling since the watcher will retry on its own. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Ugo Giordano <ugiordan@redhat.com>
1 parent 104ad10 commit 228829a

1 file changed

Lines changed: 25 additions & 19 deletions

File tree

infra/feast-operator/cmd/main.go

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ package main
1919
import (
2020
"context"
2121
"crypto/tls"
22+
"errors"
2223
"flag"
2324
"os"
25+
"time"
2426

2527
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
2628
// to ensure that exec-entrypoint and run can make use of them.
@@ -102,7 +104,7 @@ func main() {
102104
var probeAddr string
103105
var secureMetrics bool
104106
var featureStoreMetrics bool
105-
var tlsOpts []func(*tls.Config)
107+
tlsOpts := make([]func(*tls.Config), 0, 2)
106108
flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
107109
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
108110
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
@@ -131,38 +133,42 @@ func main() {
131133
}
132134

133135
tlsProfileFetched := false
134-
tlsProfile, err := tlspkg.FetchAPIServerTLSProfile(context.Background(), bootstrapClient)
136+
profileCtx, cancelProfile := context.WithTimeout(context.Background(), 10*time.Second)
137+
defer cancelProfile()
138+
tlsProfile, err := tlspkg.FetchAPIServerTLSProfile(profileCtx, bootstrapClient)
135139
if err != nil {
136140
switch {
137141
case apimeta.IsNoMatchError(err):
138-
setupLog.Info("TLS profile not available, using hardened defaults (non-OpenShift cluster)")
142+
setupLog.Info("TLS profile not available, using Intermediate defaults (non-OpenShift cluster)")
139143
case apierrors.IsNotFound(err):
140-
setupLog.Info("APIServer resource not found, using hardened defaults")
144+
setupLog.Info("APIServer resource not found, using Intermediate defaults")
145+
case apierrors.IsServiceUnavailable(err),
146+
apierrors.IsTimeout(err),
147+
apierrors.IsServerTimeout(err),
148+
apierrors.IsTooManyRequests(err),
149+
errors.Is(err, context.DeadlineExceeded):
150+
setupLog.Info("Transient API error reading TLS profile, using Intermediate defaults", "error", err)
151+
tlsProfileFetched = true
141152
default:
142153
setupLog.Error(err, "unable to read APIServer TLS profile, refusing to start with unknown TLS posture")
143154
os.Exit(1)
144155
}
156+
tlsProfile = *configv1.TLSProfiles[configv1.TLSProfileIntermediateType]
145157
} else {
146158
tlsProfileFetched = true
147-
tlsConfigFn, unsupported := tlspkg.NewTLSConfigFromProfile(tlsProfile)
148-
if len(unsupported) > 0 {
149-
setupLog.Info("TLS profile contains ciphers unsupported by Go", "unsupported", unsupported)
150-
}
151-
tlsOpts = append(tlsOpts, tlsConfigFn)
152159
}
160+
tlsConfigFn, unsupported := tlspkg.NewTLSConfigFromProfile(tlsProfile)
161+
if len(unsupported) > 0 {
162+
setupLog.Info("TLS profile contains ciphers unsupported by Go", "unsupported", unsupported)
163+
}
164+
tlsOpts = append(tlsOpts, tlsConfigFn)
153165

154166
tlsAdherenceFetched := false
155-
tlsAdherence, err := tlspkg.FetchAPIServerTLSAdherencePolicy(context.Background(), bootstrapClient)
167+
adherenceCtx, cancelAdherence := context.WithTimeout(context.Background(), 10*time.Second)
168+
defer cancelAdherence()
169+
tlsAdherence, err := tlspkg.FetchAPIServerTLSAdherencePolicy(adherenceCtx, bootstrapClient)
156170
if err != nil {
157-
switch {
158-
case apimeta.IsNoMatchError(err):
159-
setupLog.Info("TLS adherence policy not available (non-OpenShift cluster)")
160-
case apierrors.IsNotFound(err):
161-
setupLog.Info("APIServer resource not found, skipping adherence policy")
162-
default:
163-
setupLog.Error(err, "unable to read APIServer TLS adherence policy, refusing to start")
164-
os.Exit(1)
165-
}
171+
setupLog.Info("unable to fetch TLS adherence policy, watcher will retry", "error", err)
166172
} else {
167173
tlsAdherenceFetched = true
168174
}

0 commit comments

Comments
 (0)