Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add kube-apiserver wiring #20578

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion hack/import-restrictions.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
"github.com/openshift/origin/pkg/quota/admission/clusterresourceoverride",
"github.com/openshift/origin/pkg/oc/cli/admin/createbootstrapprojecttemplate",
"github.com/openshift/origin/pkg/cmd/server",
"github.com/openshift/origin/pkg/cmd/openshift-apiserver"
"github.com/openshift/origin/pkg/cmd/openshift-apiserver",
"github.com/openshift/origin/pkg/cmd/openshift-kube-apiserver/openshiftkubeapiserver"
],
"forbiddenImportPackageRoots": [
"github.com/openshift/origin/pkg/apps/apiserver",
Expand Down
2 changes: 1 addition & 1 deletion install/kube-dns/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ objects:
spec:
serviceAccountName: kube-dns
containers:
- name: kube-proxy
- name: kube-dns
image: ${IMAGE}
imagePullPolicy: ${OPENSHIFT_PULL_POLICY}
command: ["openshift", "start", "network"]
Expand Down
2 changes: 2 additions & 0 deletions install/kube-proxy/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ objects:
- kind: ServiceAccount
name: kube-proxy
namespace: ${NAMESPACE}
- kind: Group
name: system:nodes
roleRef:
kind: ClusterRole
name: system:node-proxier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
kapi "k8s.io/kubernetes/pkg/apis/core"
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
kinternalinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
rbacrest "k8s.io/kubernetes/pkg/registry/rbac/rest"
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
rbacauthorizer "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac"

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

// register our poststarthooks
s.GenericAPIServer.AddPostStartHookOrDie("authorization.openshift.io-bootstrapclusterroles",
func(context genericapiserver.PostStartHookContext) error {
newContext := genericapiserver.PostStartHookContext{
LoopbackClientConfig: c.ExtraConfig.KubeAPIServerClientConfig,
StopCh: context.StopCh,
}
return bootstrapData(bootstrappolicy.Policy()).EnsureRBACPolicy()(newContext)

})
s.GenericAPIServer.AddPostStartHookOrDie("authorization.openshift.io-ensureopenshift-infra", c.EnsureOpenShiftInfraNamespace)
s.GenericAPIServer.AddPostStartHookOrDie("project.openshift.io-projectcache", c.startProjectCache)
s.GenericAPIServer.AddPostStartHookOrDie("project.openshift.io-projectauthorizationcache", c.startProjectAuthorizationCache)
s.GenericAPIServer.AddPostStartHookOrDie("security.openshift.io-bootstrapscc", c.bootstrapSCC)
Expand Down Expand Up @@ -712,13 +723,13 @@ func (c *completedConfig) bootstrapSCC(context genericapiserver.PostStartHookCon
}

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

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

return nil
}

// bootstrapData casts our policy data to the rbacrest helper that can
// materialize the policy.
func bootstrapData(data *bootstrappolicy.PolicyData) *rbacrest.PolicyData {
return &rbacrest.PolicyData{
ClusterRoles: data.ClusterRoles,
ClusterRoleBindings: data.ClusterRoleBindings,
Roles: data.Roles,
RoleBindings: data.RoleBindings,
ClusterRolesToAggregate: data.ClusterRolesToAggregate,
}
}
268 changes: 268 additions & 0 deletions pkg/cmd/openshift-kube-apiserver/openshiftkubeapiserver/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
package openshiftkubeapiserver

import (
"fmt"
"net"
"sort"

"io/ioutil"

"bytes"

configapi "github.com/openshift/origin/pkg/cmd/server/apis/config"
configapilatest "github.com/openshift/origin/pkg/cmd/server/apis/config/latest"
originadmission "github.com/openshift/origin/pkg/cmd/server/origin/admission"
"k8s.io/apimachinery/pkg/runtime"
)

func ConfigToFlags(kubeAPIServerConfig *configapi.MasterConfig) ([]string, error) {
args := map[string][]string{}
for key, slice := range kubeAPIServerConfig.KubernetesMasterConfig.APIServerArguments {
for _, val := range slice {
args[key] = append(args[key], val)
}
}

host, portString, err := net.SplitHostPort(kubeAPIServerConfig.ServingInfo.BindAddress)
if err != nil {
return nil, err
}

// TODO this list (and the content below) will be used to drive a config struct and a reflective test matching config to flags
// these flags are overridden by a patch
// admission-control
// authentication-token-webhook-cache-ttl
// authentication-token-webhook-config-file
// authorization-mode
// authorization-policy-file
// authorization-webhook-cache-authorized-ttl
// authorization-webhook-cache-unauthorized-ttl
// authorization-webhook-config-file
// basic-auth-file
// enable-aggregator-routing
// enable-bootstrap-token-auth
// oidc-client-id
// oidc-groups-claim
// oidc-groups-prefix
// oidc-issuer-url
// oidc-required-claim
// oidc-signing-algs
// oidc-username-claim
// oidc-username-prefix
// service-account-lookup
// token-auth-file

// alsologtostderr - don't know whether to change it
// apiserver-count - ignored, hopefully we don't have to fix via patch
// cert-dir - ignored because we set certs

// these flags were never supported via config
// cloud-config
// cloud-provider
// cloud-provider-gce-lb-src-cidrs
// contention-profiling
// default-not-ready-toleration-seconds
// default-unreachable-toleration-seconds
// default-watch-cache-size
// delete-collection-workers
// deserialization-cache-size
// enable-garbage-collector
// etcd-compaction-interval
// etcd-count-metric-poll-period
// etcd-servers-overrides
// experimental-encryption-provider-config
// feature-gates
// http2-max-streams-per-connection
// insecure-bind-address
// kubelet-timeout
// log-backtrace-at
// log-dir
// log-flush-frequency
// logtostderr
// master-service-namespace
// max-connection-bytes-per-sec
// profiling
// request-timeout
// runtime-config
// service-account-api-audiences
// service-account-issuer
// service-account-key-file
// service-account-max-token-expiration
// service-account-signing-key-file
// stderrthreshold
// storage-versions
// target-ram-mb
// v
// version
// vmodule
// watch-cache
// watch-cache-sizes

// TODO, we need to set these in order to enable the right admission plugins in each of the servers
// TODO this is needed for a viable cluster up
admissionFlags, err := admissionFlags(kubeAPIServerConfig)
if err != nil {
return nil, err
}
for flag, value := range admissionFlags {
setIfUnset(args, flag, value...)
}
setIfUnset(args, "allow-privileged", "true")
setIfUnset(args, "anonymous-auth", "false")
setIfUnset(args, "authorization-mode", "RBAC", "Node") // overridden later, but this runs the poststarthook for bootstrapping RBAC
for flag, value := range auditFlags(kubeAPIServerConfig) {
setIfUnset(args, flag, value...)
}
setIfUnset(args, "bind-address", host)
setIfUnset(args, "client-ca-file", kubeAPIServerConfig.ServingInfo.ClientCA)
setIfUnset(args, "cors-allowed-origins", kubeAPIServerConfig.CORSAllowedOrigins...)
setIfUnset(args, "enable-logs-handler", "false")
setIfUnset(args, "enable-swagger-ui", "true")
setIfUnset(args, "endpoint-reconciler-type", "lease")
setIfUnset(args, "etcd-cafile", kubeAPIServerConfig.EtcdClientInfo.CA)
setIfUnset(args, "etcd-certfile", kubeAPIServerConfig.EtcdClientInfo.ClientCert.CertFile)
setIfUnset(args, "etcd-keyfile", kubeAPIServerConfig.EtcdClientInfo.ClientCert.KeyFile)
setIfUnset(args, "etcd-prefix", kubeAPIServerConfig.EtcdStorageConfig.KubernetesStoragePrefix)
setIfUnset(args, "etcd-servers", kubeAPIServerConfig.EtcdClientInfo.URLs...)
setIfUnset(args, "insecure-port", "0")
setIfUnset(args, "kubelet-certificate-authority", kubeAPIServerConfig.KubeletClientInfo.CA)
setIfUnset(args, "kubelet-client-certificate", kubeAPIServerConfig.KubeletClientInfo.ClientCert.CertFile)
setIfUnset(args, "kubelet-client-key", kubeAPIServerConfig.KubeletClientInfo.ClientCert.KeyFile)
setIfUnset(args, "kubelet-https", "true")
setIfUnset(args, "kubelet-preferred-address-types", "Hostname", "InternalIP", "ExternalIP")
setIfUnset(args, "kubelet-read-only-port", "0")
setIfUnset(args, "kubernetes-service-node-port", "0")
setIfUnset(args, "max-mutating-requests-inflight", fmt.Sprintf("%d", kubeAPIServerConfig.ServingInfo.MaxRequestsInFlight/2))
setIfUnset(args, "max-requests-inflight", fmt.Sprintf("%d", kubeAPIServerConfig.ServingInfo.MaxRequestsInFlight))
setIfUnset(args, "min-request-timeout", fmt.Sprintf("%d", kubeAPIServerConfig.ServingInfo.RequestTimeoutSeconds))
setIfUnset(args, "proxy-client-cert-file", kubeAPIServerConfig.AggregatorConfig.ProxyClientInfo.CertFile)
setIfUnset(args, "proxy-client-key-file", kubeAPIServerConfig.AggregatorConfig.ProxyClientInfo.KeyFile)
setIfUnset(args, "requestheader-allowed-names", kubeAPIServerConfig.AuthConfig.RequestHeader.ClientCommonNames...)
setIfUnset(args, "requestheader-client-ca-file", kubeAPIServerConfig.AuthConfig.RequestHeader.ClientCA)
setIfUnset(args, "requestheader-extra-headers-prefix", kubeAPIServerConfig.AuthConfig.RequestHeader.ExtraHeaderPrefixes...)
setIfUnset(args, "requestheader-group-headers", kubeAPIServerConfig.AuthConfig.RequestHeader.GroupHeaders...)
setIfUnset(args, "requestheader-username-headers", kubeAPIServerConfig.AuthConfig.RequestHeader.UsernameHeaders...)
setIfUnset(args, "secure-port", portString)
setIfUnset(args, "service-cluster-ip-range", kubeAPIServerConfig.KubernetesMasterConfig.ServicesSubnet)
setIfUnset(args, "service-node-port-range", kubeAPIServerConfig.KubernetesMasterConfig.ServicesNodePortRange)
setIfUnset(args, "storage-backend", "etcd3")
setIfUnset(args, "storage-media-type", "application/vnd.kubernetes.protobuf")
setIfUnset(args, "tls-cert-file", kubeAPIServerConfig.ServingInfo.ServerCert.CertFile)
setIfUnset(args, "tls-cipher-suites", kubeAPIServerConfig.ServingInfo.CipherSuites...)
setIfUnset(args, "tls-min-version", kubeAPIServerConfig.ServingInfo.MinTLSVersion)
setIfUnset(args, "tls-private-key-file", kubeAPIServerConfig.ServingInfo.ServerCert.KeyFile)
// TODO re-enable SNI for cluster up
// tls-sni-cert-key
setIfUnset(args, "secure-port", portString)

var keys []string
for key := range args {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keys := append([]string(nil), args...)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keys := append([]string(nil), args...)

args is a map

keys = append(keys, key)
}
sort.Strings(keys)

var arguments []string
for _, key := range keys {
for _, token := range args[key] {
arguments = append(arguments, fmt.Sprintf("--%s=%v", key, token))
}
}
return arguments, nil
}

// currently for cluster up, audit is just broken.
// TODO fix this
func auditFlags(kubeAPIServerConfig *configapi.MasterConfig) map[string][]string {
args := map[string][]string{}
for key, slice := range kubeAPIServerConfig.KubernetesMasterConfig.APIServerArguments {
for _, val := range slice {
args[key] = append(args[key], val)
}
}

return args
}

func setIfUnset(cmdLineArgs map[string][]string, key string, value ...string) {
if _, ok := cmdLineArgs[key]; !ok {
cmdLineArgs[key] = value
}
}

func admissionFlags(kubeAPIServerConfig *configapi.MasterConfig) (map[string][]string, error) {
args := map[string][]string{}

forceOn := []string{}
forceOff := []string{}
pluginConfig := map[string]configapi.AdmissionPluginConfig{}
for pluginName, config := range kubeAPIServerConfig.AdmissionConfig.DeepCopy().PluginConfig {
if len(config.Location) > 0 {
content, err := ioutil.ReadFile(config.Location)
if err != nil {
return nil, err
}
// if the config isn't a DefaultAdmissionConfig, then assume we're enabled (we were called out after all)
// if the config *is* a DefaultAdmissionConfig and it explicitly said to disable us, we are disabled
obj, err := configapilatest.ReadYAML(bytes.NewBuffer(content))
// if we can't read it, let the plugin deal with it
// if nothing was there, let the plugin deal with it
if err != nil || obj == nil {
forceOn = append(forceOn, pluginName)
config.Location = ""
config.Configuration = &runtime.Unknown{Raw: content}
pluginConfig[pluginName] = *config
continue
}

if defaultConfig, ok := obj.(*configapi.DefaultAdmissionConfig); !ok {
forceOn = append(forceOn, pluginName)
config.Location = ""
config.Configuration = &runtime.Unknown{Raw: content}
pluginConfig[pluginName] = *config

} else if defaultConfig.Disable {
forceOff = append(forceOff, pluginName)

} else {
forceOn = append(forceOn, pluginName)
}

continue
}
// if it wasn't a DefaultAdmissionConfig object, let the plugin deal with it
if defaultConfig, ok := config.Configuration.(*configapi.DefaultAdmissionConfig); !ok {
forceOn = append(forceOn, pluginName)
pluginConfig[pluginName] = *config

} else if defaultConfig.Disable {
forceOff = append(forceOff, pluginName)

} else {
forceOn = append(forceOn, pluginName)
}

}
upstreamAdmissionConfig, err := originadmission.ConvertOpenshiftAdmissionConfigToKubeAdmissionConfig(pluginConfig)
if err != nil {
return nil, err
}
configBytes, err := configapilatest.WriteYAML(upstreamAdmissionConfig)
if err != nil {
return nil, err
}

tempFile, err := ioutil.TempFile("", "kubeapiserver-admission-config.yaml")
if err != nil {
return nil, err
}
if _, err := tempFile.Write(configBytes); err != nil {
return nil, err
}
tempFile.Close()

setIfUnset(args, "admission-control-config-file", tempFile.Name())
setIfUnset(args, "disable-admission-plugins", forceOff...)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are additive to the default values. Maybe we should append?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are additive to the default values. Maybe we should append?

We've always stomped admission with our choices. I only want one way to set via config.

setIfUnset(args, "enable-admission-plugins", forceOn...)

return args, nil
}
Loading