Skip to content

Commit 1d2c1a7

Browse files
committed
wire hypershift openshift-kube-apiserver to use minimal patching strategy
1 parent 1cdf926 commit 1d2c1a7

File tree

14 files changed

+446
-103
lines changed

14 files changed

+446
-103
lines changed

hack/import-restrictions.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@
5050
"github.com/openshift/origin/pkg/quota/admission/clusterresourceoverride",
5151
"github.com/openshift/origin/pkg/oc/cli/admin/createbootstrapprojecttemplate",
5252
"github.com/openshift/origin/pkg/cmd/server",
53-
"github.com/openshift/origin/pkg/cmd/openshift-apiserver"
53+
"github.com/openshift/origin/pkg/cmd/openshift-apiserver",
54+
"github.com/openshift/origin/pkg/cmd/openshift-kube-apiserver/openshiftkubeapiserver"
5455
],
5556
"forbiddenImportPackageRoots": [
5657
"github.com/openshift/origin/pkg/apps/apiserver",

install/kube-dns/install.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ objects:
4242
spec:
4343
serviceAccountName: kube-dns
4444
containers:
45-
- name: kube-proxy
45+
- name: kube-dns
4646
image: ${IMAGE}
4747
imagePullPolicy: ${OPENSHIFT_PULL_POLICY}
4848
command: ["openshift", "start", "network"]

install/kube-proxy/install.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ objects:
3030
- kind: ServiceAccount
3131
name: kube-proxy
3232
namespace: ${NAMESPACE}
33+
- kind: Group
34+
name: system:nodes
3335
roleRef:
3436
kind: ClusterRole
3537
name: system:node-proxier

pkg/cmd/openshift-apiserver/openshiftapiserver/openshift_apiserver.go

+25-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
kapi "k8s.io/kubernetes/pkg/apis/core"
2727
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
2828
kinternalinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
29+
rbacrest "k8s.io/kubernetes/pkg/registry/rbac/rest"
2930
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
3031
rbacauthorizer "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac"
3132

@@ -578,6 +579,16 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget)
578579
AddOpenshiftVersionRoute(s.GenericAPIServer.Handler.GoRestfulContainer, "/version/openshift")
579580

580581
// register our poststarthooks
582+
s.GenericAPIServer.AddPostStartHookOrDie("authorization.openshift.io-bootstrapclusterroles",
583+
func(context genericapiserver.PostStartHookContext) error {
584+
newContext := genericapiserver.PostStartHookContext{
585+
LoopbackClientConfig: c.ExtraConfig.KubeAPIServerClientConfig,
586+
StopCh: context.StopCh,
587+
}
588+
return bootstrapData(bootstrappolicy.Policy()).EnsureRBACPolicy()(newContext)
589+
590+
})
591+
s.GenericAPIServer.AddPostStartHookOrDie("authorization.openshift.io-ensureopenshift-infra", c.EnsureOpenShiftInfraNamespace)
581592
s.GenericAPIServer.AddPostStartHookOrDie("project.openshift.io-projectcache", c.startProjectCache)
582593
s.GenericAPIServer.AddPostStartHookOrDie("project.openshift.io-projectauthorizationcache", c.startProjectAuthorizationCache)
583594
s.GenericAPIServer.AddPostStartHookOrDie("security.openshift.io-bootstrapscc", c.bootstrapSCC)
@@ -712,13 +723,13 @@ func (c *completedConfig) bootstrapSCC(context genericapiserver.PostStartHookCon
712723
}
713724

714725
// EnsureOpenShiftInfraNamespace is called as part of global policy initialization to ensure infra namespace exists
715-
func EnsureOpenShiftInfraNamespace(context genericapiserver.PostStartHookContext) error {
726+
func (c *completedConfig) EnsureOpenShiftInfraNamespace(context genericapiserver.PostStartHookContext) error {
716727
namespaceName := bootstrappolicy.DefaultOpenShiftInfraNamespace
717728

718729
var coreClient coreclient.CoreInterface
719730
err := wait.Poll(1*time.Second, 30*time.Second, func() (bool, error) {
720731
var err error
721-
coreClient, err = coreclient.NewForConfig(context.LoopbackClientConfig)
732+
coreClient, err = coreclient.NewForConfig(c.ExtraConfig.KubeAPIServerClientConfig)
722733
if err != nil {
723734
utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err))
724735
return false, nil
@@ -744,3 +755,15 @@ func EnsureOpenShiftInfraNamespace(context genericapiserver.PostStartHookContext
744755

745756
return nil
746757
}
758+
759+
// bootstrapData casts our policy data to the rbacrest helper that can
760+
// materialize the policy.
761+
func bootstrapData(data *bootstrappolicy.PolicyData) *rbacrest.PolicyData {
762+
return &rbacrest.PolicyData{
763+
ClusterRoles: data.ClusterRoles,
764+
ClusterRoleBindings: data.ClusterRoleBindings,
765+
Roles: data.Roles,
766+
RoleBindings: data.RoleBindings,
767+
ClusterRolesToAggregate: data.ClusterRolesToAggregate,
768+
}
769+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
package openshiftkubeapiserver
2+
3+
import (
4+
"fmt"
5+
"net"
6+
"sort"
7+
8+
"io/ioutil"
9+
10+
"bytes"
11+
12+
configapi "github.com/openshift/origin/pkg/cmd/server/apis/config"
13+
configapilatest "github.com/openshift/origin/pkg/cmd/server/apis/config/latest"
14+
originadmission "github.com/openshift/origin/pkg/cmd/server/origin/admission"
15+
"k8s.io/apimachinery/pkg/runtime"
16+
)
17+
18+
func ConfigToFlags(kubeAPIServerConfig *configapi.MasterConfig) ([]string, error) {
19+
args := map[string][]string{}
20+
for key, slice := range kubeAPIServerConfig.KubernetesMasterConfig.APIServerArguments {
21+
for _, val := range slice {
22+
args[key] = append(args[key], val)
23+
}
24+
}
25+
26+
host, portString, err := net.SplitHostPort(kubeAPIServerConfig.ServingInfo.BindAddress)
27+
if err != nil {
28+
return nil, err
29+
}
30+
31+
// these flags are overridden by a patch
32+
// admission-control
33+
// authentication-token-webhook-cache-ttl
34+
// authentication-token-webhook-config-file
35+
// authorization-mode
36+
// authorization-policy-file
37+
// authorization-webhook-cache-authorized-ttl
38+
// authorization-webhook-cache-unauthorized-ttl
39+
// authorization-webhook-config-file
40+
// basic-auth-file
41+
// enable-aggregator-routing
42+
// enable-bootstrap-token-auth
43+
// oidc-client-id
44+
// oidc-groups-claim
45+
// oidc-groups-prefix
46+
// oidc-issuer-url
47+
// oidc-required-claim
48+
// oidc-signing-algs
49+
// oidc-username-claim
50+
// oidc-username-prefix
51+
// service-account-lookup
52+
// token-auth-file
53+
54+
// alsologtostderr - don't know whether to change it
55+
// apiserver-count - ignored, hopefully we don't have to fix via patch
56+
// cert-dir - ignored because we set certs
57+
58+
// these flags were never supported via config
59+
// cloud-config
60+
// cloud-provider
61+
// cloud-provider-gce-lb-src-cidrs
62+
// contention-profiling
63+
// default-not-ready-toleration-seconds
64+
// default-unreachable-toleration-seconds
65+
// default-watch-cache-size
66+
// delete-collection-workers
67+
// deserialization-cache-size
68+
// enable-garbage-collector
69+
// etcd-compaction-interval
70+
// etcd-count-metric-poll-period
71+
// etcd-servers-overrides
72+
// experimental-encryption-provider-config
73+
// feature-gates
74+
// http2-max-streams-per-connection
75+
// insecure-bind-address
76+
// kubelet-timeout
77+
// log-backtrace-at
78+
// log-dir
79+
// log-flush-frequency
80+
// logtostderr
81+
// master-service-namespace
82+
// max-connection-bytes-per-sec
83+
// profiling
84+
// request-timeout
85+
// runtime-config
86+
// service-account-api-audiences
87+
// service-account-issuer
88+
// service-account-key-file
89+
// service-account-max-token-expiration
90+
// service-account-signing-key-file
91+
// stderrthreshold
92+
// storage-versions
93+
// target-ram-mb
94+
// v
95+
// version
96+
// vmodule
97+
// watch-cache
98+
// watch-cache-sizes
99+
100+
// TODO, we need to set these in order to enable the right admission plugins in each of the servers
101+
// TODO this is needed for a viable cluster up
102+
admissionFlags, err := admissionFlags(kubeAPIServerConfig)
103+
if err != nil {
104+
return nil, err
105+
}
106+
for flag, value := range admissionFlags {
107+
setIfUnset(args, flag, value...)
108+
}
109+
setIfUnset(args, "allow-privileged", "true")
110+
setIfUnset(args, "anonymous-auth", "false")
111+
setIfUnset(args, "authorization-mode", "RBAC", "Node") // overridden later, but this runs the poststarthook for bootstrapping RBAC
112+
for flag, value := range auditFlags(kubeAPIServerConfig) {
113+
setIfUnset(args, flag, value...)
114+
}
115+
setIfUnset(args, "bind-address", host)
116+
setIfUnset(args, "client-ca-file", kubeAPIServerConfig.ServingInfo.ClientCA)
117+
setIfUnset(args, "cors-allowed-origins", kubeAPIServerConfig.CORSAllowedOrigins...)
118+
setIfUnset(args, "enable-logs-handler", "false")
119+
setIfUnset(args, "enable-swagger-ui", "true")
120+
setIfUnset(args, "endpoint-reconciler-type", "lease")
121+
setIfUnset(args, "etcd-cafile", kubeAPIServerConfig.EtcdClientInfo.CA)
122+
setIfUnset(args, "etcd-certfile", kubeAPIServerConfig.EtcdClientInfo.ClientCert.CertFile)
123+
setIfUnset(args, "etcd-keyfile", kubeAPIServerConfig.EtcdClientInfo.ClientCert.KeyFile)
124+
setIfUnset(args, "etcd-prefix", kubeAPIServerConfig.EtcdStorageConfig.KubernetesStoragePrefix)
125+
setIfUnset(args, "etcd-servers", kubeAPIServerConfig.EtcdClientInfo.URLs...)
126+
setIfUnset(args, "insecure-port", "0")
127+
setIfUnset(args, "kubelet-certificate-authority", kubeAPIServerConfig.KubeletClientInfo.CA)
128+
setIfUnset(args, "kubelet-client-certificate", kubeAPIServerConfig.KubeletClientInfo.ClientCert.CertFile)
129+
setIfUnset(args, "kubelet-client-key", kubeAPIServerConfig.KubeletClientInfo.ClientCert.KeyFile)
130+
setIfUnset(args, "kubelet-https", "true")
131+
setIfUnset(args, "kubelet-preferred-address-types", "Hostname", "InternalIP", "ExternalIP")
132+
setIfUnset(args, "kubelet-read-only-port", "0")
133+
setIfUnset(args, "kubernetes-service-node-port", "0")
134+
setIfUnset(args, "max-mutating-requests-inflight", fmt.Sprintf("%d", kubeAPIServerConfig.ServingInfo.MaxRequestsInFlight/2))
135+
setIfUnset(args, "max-requests-inflight", fmt.Sprintf("%d", kubeAPIServerConfig.ServingInfo.MaxRequestsInFlight))
136+
setIfUnset(args, "min-request-timeout", fmt.Sprintf("%d", kubeAPIServerConfig.ServingInfo.RequestTimeoutSeconds))
137+
setIfUnset(args, "proxy-client-cert-file", kubeAPIServerConfig.AggregatorConfig.ProxyClientInfo.CertFile)
138+
setIfUnset(args, "proxy-client-key-file", kubeAPIServerConfig.AggregatorConfig.ProxyClientInfo.KeyFile)
139+
setIfUnset(args, "requestheader-allowed-names", kubeAPIServerConfig.AuthConfig.RequestHeader.ClientCommonNames...)
140+
setIfUnset(args, "requestheader-client-ca-file", kubeAPIServerConfig.AuthConfig.RequestHeader.ClientCA)
141+
setIfUnset(args, "requestheader-extra-headers-prefix", kubeAPIServerConfig.AuthConfig.RequestHeader.ExtraHeaderPrefixes...)
142+
setIfUnset(args, "requestheader-group-headers", kubeAPIServerConfig.AuthConfig.RequestHeader.GroupHeaders...)
143+
setIfUnset(args, "requestheader-username-headers", kubeAPIServerConfig.AuthConfig.RequestHeader.UsernameHeaders...)
144+
setIfUnset(args, "secure-port", portString)
145+
setIfUnset(args, "service-cluster-ip-range", kubeAPIServerConfig.KubernetesMasterConfig.ServicesSubnet)
146+
setIfUnset(args, "service-node-port-range", kubeAPIServerConfig.KubernetesMasterConfig.ServicesNodePortRange)
147+
setIfUnset(args, "storage-backend", "etcd3")
148+
setIfUnset(args, "storage-media-type", "application/vnd.kubernetes.protobuf")
149+
setIfUnset(args, "tls-cert-file", kubeAPIServerConfig.ServingInfo.ServerCert.CertFile)
150+
setIfUnset(args, "tls-cipher-suites", kubeAPIServerConfig.ServingInfo.CipherSuites...)
151+
setIfUnset(args, "tls-min-version", kubeAPIServerConfig.ServingInfo.MinTLSVersion)
152+
setIfUnset(args, "tls-private-key-file", kubeAPIServerConfig.ServingInfo.ServerCert.KeyFile)
153+
// TODO re-enable SNI for cluster up
154+
// tls-sni-cert-key
155+
setIfUnset(args, "secure-port", portString)
156+
157+
var keys []string
158+
for key := range args {
159+
keys = append(keys, key)
160+
}
161+
sort.Strings(keys)
162+
163+
var arguments []string
164+
for _, key := range keys {
165+
for _, token := range args[key] {
166+
arguments = append(arguments, fmt.Sprintf("--%s=%v", key, token))
167+
}
168+
}
169+
return arguments, nil
170+
}
171+
172+
// currently for cluster up, audit is just broken.
173+
// TODO fix this
174+
func auditFlags(kubeAPIServerConfig *configapi.MasterConfig) map[string][]string {
175+
args := map[string][]string{}
176+
for key, slice := range kubeAPIServerConfig.KubernetesMasterConfig.APIServerArguments {
177+
for _, val := range slice {
178+
args[key] = append(args[key], val)
179+
}
180+
}
181+
182+
return args
183+
}
184+
185+
func setIfUnset(cmdLineArgs map[string][]string, key string, value ...string) {
186+
if _, ok := cmdLineArgs[key]; !ok {
187+
cmdLineArgs[key] = value
188+
}
189+
}
190+
191+
func admissionFlags(kubeAPIServerConfig *configapi.MasterConfig) (map[string][]string, error) {
192+
args := map[string][]string{}
193+
194+
forceOn := []string{}
195+
forceOff := []string{}
196+
pluginConfig := map[string]configapi.AdmissionPluginConfig{}
197+
for pluginName, config := range kubeAPIServerConfig.AdmissionConfig.DeepCopy().PluginConfig {
198+
if len(config.Location) > 0 {
199+
content, err := ioutil.ReadFile(config.Location)
200+
if err != nil {
201+
return nil, err
202+
}
203+
// if the config isn't a DefaultAdmissionConfig, then assume we're enabled (we were called after all)
204+
// if the config *is* a DefaultAdmissionConfig and it explicitly said
205+
obj, err := configapilatest.ReadYAML(bytes.NewBuffer(content))
206+
// if we can't read it, let the plugin deal with it
207+
// if nothing was there, let the plugin deal with it
208+
if err != nil || obj == nil {
209+
forceOn = append(forceOn, pluginName)
210+
config.Location = ""
211+
config.Configuration = &runtime.Unknown{Raw: content}
212+
pluginConfig[pluginName] = *config
213+
continue
214+
}
215+
216+
if defaultConfig, ok := obj.(*configapi.DefaultAdmissionConfig); !ok {
217+
forceOn = append(forceOn, pluginName)
218+
config.Location = ""
219+
config.Configuration = &runtime.Unknown{Raw: content}
220+
pluginConfig[pluginName] = *config
221+
continue
222+
223+
} else if defaultConfig.Disable {
224+
forceOff = append(forceOff, pluginName)
225+
continue
226+
} else {
227+
forceOn = append(forceOn, pluginName)
228+
continue
229+
}
230+
231+
continue
232+
}
233+
// if it wasn't a DefaultAdmissionConfig object, let the plugin deal with it
234+
if defaultConfig, ok := config.Configuration.(*configapi.DefaultAdmissionConfig); !ok {
235+
forceOn = append(forceOn, pluginName)
236+
pluginConfig[pluginName] = *config
237+
continue
238+
239+
} else if defaultConfig.Disable {
240+
forceOff = append(forceOff, pluginName)
241+
continue
242+
} else {
243+
forceOn = append(forceOn, pluginName)
244+
continue
245+
}
246+
247+
}
248+
upstreamAdmissionConfig, err := originadmission.ConvertOpenshiftAdmissionConfigToKubeAdmissionConfig(pluginConfig)
249+
if err != nil {
250+
return nil, err
251+
}
252+
configBytes, err := configapilatest.WriteYAML(upstreamAdmissionConfig)
253+
if err != nil {
254+
return nil, err
255+
}
256+
257+
tempFile, err := ioutil.TempFile("", "kubeapiserver-admission-config.yaml")
258+
if err != nil {
259+
return nil, err
260+
}
261+
if _, err := tempFile.Write(configBytes); err != nil {
262+
return nil, err
263+
}
264+
tempFile.Close()
265+
266+
setIfUnset(args, "admission-control-config-file", tempFile.Name())
267+
setIfUnset(args, "disable-admission-plugins", forceOff...)
268+
setIfUnset(args, "enable-admission-plugins", forceOn...)
269+
270+
return args, nil
271+
}

0 commit comments

Comments
 (0)