1
16
17 package apiserver
18
19 import (
20 "context"
21 "fmt"
22 "time"
23
24 oteltrace "go.opentelemetry.io/otel/trace"
25
26 "k8s.io/apimachinery/pkg/runtime"
27 "k8s.io/apimachinery/pkg/util/sets"
28 "k8s.io/apimachinery/pkg/util/wait"
29 "k8s.io/apiserver/pkg/authorization/authorizer"
30 "k8s.io/apiserver/pkg/endpoints/discovery/aggregated"
31 openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
32 genericfeatures "k8s.io/apiserver/pkg/features"
33 "k8s.io/apiserver/pkg/reconcilers"
34 genericapiserver "k8s.io/apiserver/pkg/server"
35 "k8s.io/apiserver/pkg/server/egressselector"
36 "k8s.io/apiserver/pkg/server/filters"
37 serverstorage "k8s.io/apiserver/pkg/server/storage"
38 "k8s.io/apiserver/pkg/storageversion"
39 utilfeature "k8s.io/apiserver/pkg/util/feature"
40 "k8s.io/apiserver/pkg/util/openapi"
41 utilpeerproxy "k8s.io/apiserver/pkg/util/peerproxy"
42 clientgoinformers "k8s.io/client-go/informers"
43 clientgoclientset "k8s.io/client-go/kubernetes"
44 "k8s.io/client-go/transport"
45 "k8s.io/component-base/version"
46 "k8s.io/klog/v2"
47 openapicommon "k8s.io/kube-openapi/pkg/common"
48
49 "k8s.io/kubernetes/pkg/api/legacyscheme"
50 api "k8s.io/kubernetes/pkg/apis/core"
51 "k8s.io/kubernetes/pkg/controlplane"
52 controlplaneapiserver "k8s.io/kubernetes/pkg/controlplane/apiserver/options"
53 "k8s.io/kubernetes/pkg/kubeapiserver"
54 "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
55 rbacrest "k8s.io/kubernetes/pkg/registry/rbac/rest"
56 )
57
58
59 func BuildGenericConfig(
60 s controlplaneapiserver.CompletedOptions,
61 schemes []*runtime.Scheme,
62 getOpenAPIDefinitions func(ref openapicommon.ReferenceCallback) map[string]openapicommon.OpenAPIDefinition,
63 ) (
64 genericConfig *genericapiserver.Config,
65 versionedInformers clientgoinformers.SharedInformerFactory,
66 storageFactory *serverstorage.DefaultStorageFactory,
67
68 lastErr error,
69 ) {
70 genericConfig = genericapiserver.NewConfig(legacyscheme.Codecs)
71 genericConfig.MergedResourceConfig = controlplane.DefaultAPIResourceConfigSource()
72
73 if lastErr = s.GenericServerRunOptions.ApplyTo(genericConfig); lastErr != nil {
74 return
75 }
76
77 if lastErr = s.SecureServing.ApplyTo(&genericConfig.SecureServing, &genericConfig.LoopbackClientConfig); lastErr != nil {
78 return
79 }
80
81
82
83
84
85 genericConfig.LoopbackClientConfig.ContentConfig.ContentType = "application/vnd.kubernetes.protobuf"
86
87
88 genericConfig.LoopbackClientConfig.DisableCompression = true
89
90 kubeClientConfig := genericConfig.LoopbackClientConfig
91 clientgoExternalClient, err := clientgoclientset.NewForConfig(kubeClientConfig)
92 if err != nil {
93 lastErr = fmt.Errorf("failed to create real external clientset: %v", err)
94 return
95 }
96 versionedInformers = clientgoinformers.NewSharedInformerFactory(clientgoExternalClient, 10*time.Minute)
97
98 if lastErr = s.Features.ApplyTo(genericConfig, clientgoExternalClient, versionedInformers); lastErr != nil {
99 return
100 }
101 if lastErr = s.APIEnablement.ApplyTo(genericConfig, controlplane.DefaultAPIResourceConfigSource(), legacyscheme.Scheme); lastErr != nil {
102 return
103 }
104 if lastErr = s.EgressSelector.ApplyTo(genericConfig); lastErr != nil {
105 return
106 }
107 if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.APIServerTracing) {
108 if lastErr = s.Traces.ApplyTo(genericConfig.EgressSelector, genericConfig); lastErr != nil {
109 return
110 }
111 }
112
113 getOpenAPIDefinitions = openapi.GetOpenAPIDefinitionsWithoutDisabledFeatures(getOpenAPIDefinitions)
114 namer := openapinamer.NewDefinitionNamer(schemes...)
115 genericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(getOpenAPIDefinitions, namer)
116 genericConfig.OpenAPIConfig.Info.Title = "Kubernetes"
117 genericConfig.OpenAPIV3Config = genericapiserver.DefaultOpenAPIV3Config(getOpenAPIDefinitions, namer)
118 genericConfig.OpenAPIV3Config.Info.Title = "Kubernetes"
119
120 genericConfig.LongRunningFunc = filters.BasicLongRunningRequestCheck(
121 sets.NewString("watch", "proxy"),
122 sets.NewString("attach", "exec", "proxy", "log", "portforward"),
123 )
124
125 kubeVersion := version.Get()
126 genericConfig.Version = &kubeVersion
127
128 if genericConfig.EgressSelector != nil {
129 s.Etcd.StorageConfig.Transport.EgressLookup = genericConfig.EgressSelector.Lookup
130 }
131 if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.APIServerTracing) {
132 s.Etcd.StorageConfig.Transport.TracerProvider = genericConfig.TracerProvider
133 } else {
134 s.Etcd.StorageConfig.Transport.TracerProvider = oteltrace.NewNoopTracerProvider()
135 }
136
137 storageFactoryConfig := kubeapiserver.NewStorageFactoryConfig()
138 storageFactoryConfig.APIResourceConfig = genericConfig.MergedResourceConfig
139 storageFactory, lastErr = storageFactoryConfig.Complete(s.Etcd).New()
140 if lastErr != nil {
141 return
142 }
143 if lastErr = s.Etcd.ApplyWithStorageFactoryTo(storageFactory, genericConfig); lastErr != nil {
144 return
145 }
146
147 ctx := wait.ContextForChannel(genericConfig.DrainedNotify())
148
149
150 if lastErr = s.Authentication.ApplyTo(ctx, &genericConfig.Authentication, genericConfig.SecureServing, genericConfig.EgressSelector, genericConfig.OpenAPIConfig, genericConfig.OpenAPIV3Config, clientgoExternalClient, versionedInformers, genericConfig.APIServerID); lastErr != nil {
151 return
152 }
153
154 var enablesRBAC bool
155 genericConfig.Authorization.Authorizer, genericConfig.RuleResolver, enablesRBAC, err = BuildAuthorizer(
156 ctx,
157 s,
158 genericConfig.EgressSelector,
159 genericConfig.APIServerID,
160 versionedInformers,
161 )
162 if err != nil {
163 lastErr = fmt.Errorf("invalid authorization config: %v", err)
164 return
165 }
166 if s.Authorization != nil && !enablesRBAC {
167 genericConfig.DisabledPostStartHooks.Insert(rbacrest.PostStartHookName)
168 }
169
170 lastErr = s.Audit.ApplyTo(genericConfig)
171 if lastErr != nil {
172 return
173 }
174
175 if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.AggregatedDiscoveryEndpoint) {
176 genericConfig.AggregatedDiscoveryGroupManager = aggregated.NewResourceManager("apis")
177 }
178
179 return
180 }
181
182
183 func BuildAuthorizer(ctx context.Context, s controlplaneapiserver.CompletedOptions, egressSelector *egressselector.EgressSelector, apiserverID string, versionedInformers clientgoinformers.SharedInformerFactory) (authorizer.Authorizer, authorizer.RuleResolver, bool, error) {
184 authorizationConfig, err := s.Authorization.ToAuthorizationConfig(versionedInformers)
185 if err != nil {
186 return nil, nil, false, err
187 }
188 if authorizationConfig == nil {
189 return nil, nil, false, nil
190 }
191
192 if egressSelector != nil {
193 egressDialer, err := egressSelector.Lookup(egressselector.ControlPlane.AsNetworkContext())
194 if err != nil {
195 return nil, nil, false, err
196 }
197 authorizationConfig.CustomDial = egressDialer
198 }
199
200 enablesRBAC := false
201 for _, a := range authorizationConfig.AuthorizationConfiguration.Authorizers {
202 if string(a.Type) == modes.ModeRBAC {
203 enablesRBAC = true
204 break
205 }
206 }
207
208 authorizer, ruleResolver, err := authorizationConfig.New(ctx, apiserverID)
209
210 return authorizer, ruleResolver, enablesRBAC, err
211 }
212
213
214
215 func CreatePeerEndpointLeaseReconciler(c genericapiserver.Config, storageFactory serverstorage.StorageFactory) (reconcilers.PeerEndpointLeaseReconciler, error) {
216 ttl := controlplane.DefaultEndpointReconcilerTTL
217 config, err := storageFactory.NewConfig(api.Resource("apiServerPeerIPInfo"))
218 if err != nil {
219 return nil, fmt.Errorf("error creating storage factory config: %w", err)
220 }
221 reconciler, err := reconcilers.NewPeerEndpointLeaseReconciler(config, "/peerserverleases/", ttl)
222 return reconciler, err
223 }
224
225 func BuildPeerProxy(versionedInformer clientgoinformers.SharedInformerFactory, svm storageversion.Manager,
226 proxyClientCertFile string, proxyClientKeyFile string, peerCAFile string, peerAdvertiseAddress reconcilers.PeerAdvertiseAddress,
227 apiServerID string, reconciler reconcilers.PeerEndpointLeaseReconciler, serializer runtime.NegotiatedSerializer) (utilpeerproxy.Interface, error) {
228 if proxyClientCertFile == "" {
229 return nil, fmt.Errorf("error building peer proxy handler, proxy-cert-file not specified")
230 }
231 if proxyClientKeyFile == "" {
232 return nil, fmt.Errorf("error building peer proxy handler, proxy-key-file not specified")
233 }
234
235 clientConfig := &transport.Config{
236 TLS: transport.TLSConfig{
237 Insecure: false,
238 CertFile: proxyClientCertFile,
239 KeyFile: proxyClientKeyFile,
240 CAFile: peerCAFile,
241 ServerName: "kubernetes.default.svc",
242 }}
243
244
245 proxyRoundTripper, transportBuildingError := transport.New(clientConfig)
246 if transportBuildingError != nil {
247 klog.Error(transportBuildingError.Error())
248 return nil, transportBuildingError
249 }
250 return utilpeerproxy.NewPeerProxyHandler(
251 versionedInformer,
252 svm,
253 proxyRoundTripper,
254 apiServerID,
255 reconciler,
256 serializer,
257 ), nil
258 }
259
View as plain text