Skip to content

Commit

Permalink
Initial aggregation support
Browse files Browse the repository at this point in the history
Create the keypairs, which are supposed to be signed by a different CA.
  • Loading branch information
justinsb committed Oct 22, 2017
1 parent 5e1f813 commit 5eb9fe7
Show file tree
Hide file tree
Showing 19 changed files with 350 additions and 62 deletions.
2 changes: 1 addition & 1 deletion nodeup/pkg/model/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func (c *NodeupModelContext) CNIConfDir() string {

// buildPKIKubeconfig generates a kubeconfig
func (c *NodeupModelContext) buildPKIKubeconfig(id string) (string, error) {
caCertificate, err := c.KeyStore.Cert(fi.CertificateId_CA, false)
caCertificate, err := c.KeyStore.FindCert(fi.CertificateId_CA)
if err != nil {
return "", fmt.Errorf("error fetching CA certificate from keystore: %v", err)
}
Expand Down
17 changes: 15 additions & 2 deletions nodeup/pkg/model/kube_apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,25 @@ func (b *KubeAPIServerBuilder) buildPod() (*v1.Pod, error) {
}

if b.IsKubernetesGTE("1.7") {
certPath := filepath.Join(b.PathSrvKubernetes(), "proxy-client.cert")
certPath := filepath.Join(b.PathSrvKubernetes(), "apiserver-aggregator.cert")
kubeAPIServer.ProxyClientCertFile = &certPath
keyPath := filepath.Join(b.PathSrvKubernetes(), "proxy-client.key")
keyPath := filepath.Join(b.PathSrvKubernetes(), "apiserver-aggregator.key")
kubeAPIServer.ProxyClientKeyFile = &keyPath
}

// APIServer aggregation options
if b.IsKubernetesGTE("1.7") {
cert, err := b.KeyStore.FindCert("apiserver-aggregator-ca")
if err != nil {
return nil, fmt.Errorf("apiserver aggregator CA cert lookup failed: %v", err.Error())
}

if cert != nil {
certPath := filepath.Join(b.PathSrvKubernetes(), "apiserver-aggregator-ca.cert")
kubeAPIServer.RequestheaderClientCAFile = certPath
}
}

// build the kube-apiserver flags for the service
flags, err := flagbuilder.BuildFlagsList(b.Cluster.Spec.KubeAPIServer)
if err != nil {
Expand Down
68 changes: 67 additions & 1 deletion nodeup/pkg/model/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"path/filepath"
"strings"

"github.com/golang/glog"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
)
Expand Down Expand Up @@ -117,7 +118,7 @@ func (b *SecretBuilder) Build(c *fi.ModelBuilderContext) error {
}

if b.IsKubernetesGTE("1.7") {

// TODO: Remove - we use the apiserver-aggregator keypair instead (which is signed by a different CA)
cert, err := b.KeyStore.Cert("apiserver-proxy-client", false)
if err != nil {
return fmt.Errorf("apiserver proxy client cert lookup failed: %v", err.Error())
Expand Down Expand Up @@ -153,6 +154,22 @@ func (b *SecretBuilder) Build(c *fi.ModelBuilderContext) error {
c.AddTask(t)
}

if b.IsKubernetesGTE("1.7") {
if err := b.writeCertificate(c, "apiserver-aggregator"); err != nil {
return err
}

if err := b.writePrivateKey(c, "apiserver-aggregator"); err != nil {
return err
}
}

if b.IsKubernetesGTE("1.7") {
if err := b.writeCertificate(c, "apiserver-aggregator-ca"); err != nil {
return err
}
}

if b.SecretStore != nil {
key := "kube"
token, err := b.SecretStore.FindSecret(key)
Expand Down Expand Up @@ -200,6 +217,55 @@ func (b *SecretBuilder) Build(c *fi.ModelBuilderContext) error {
return nil
}

// writeCertificate writes the specified certificate to the local filesystem, under PathSrvKubernetes()
func (b *SecretBuilder) writeCertificate(c *fi.ModelBuilderContext, id string) error {
cert, err := b.KeyStore.FindCert(id)
if err != nil {
return fmt.Errorf("cert lookup failed for %q: %v", id, err)
}

if cert != nil {
serialized, err := cert.AsString()
if err != nil {
return err
}

t := &nodetasks.File{
Path: filepath.Join(b.PathSrvKubernetes(), id+".cert"),
Contents: fi.NewStringResource(serialized),
Type: nodetasks.FileType_File,
}
c.AddTask(t)
} else {
// TODO: Make this an error?
glog.Warningf("certificate %q not found", id)
}

return nil
}

// writePrivateKey writes the specified private key to the local filesystem, under PathSrvKubernetes()
func (b *SecretBuilder) writePrivateKey(c *fi.ModelBuilderContext, id string) error {
key, err := b.KeyStore.FindPrivateKey(id)
if err != nil {
return fmt.Errorf("private key lookup failed for %q: %v", id, err)
}

serialized, err := key.AsString()
if err != nil {
return err
}

t := &nodetasks.File{
Path: filepath.Join(b.PathSrvKubernetes(), id+".key"),
Contents: fi.NewStringResource(serialized),
Type: nodetasks.FileType_File,
}
c.AddTask(t)

return nil
}

// allTokens returns a map of all tokens
func (b *SecretBuilder) allTokens() (map[string]string, error) {
tokens := make(map[string]string)
Expand Down
11 changes: 11 additions & 0 deletions pkg/apis/kops/componentconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,17 @@ type KubeAPIServerConfig struct {
AuthorizationRBACSuperUser *string `json:"authorizationRbacSuperUser,omitempty" flag:"authorization-rbac-super-user"`
// ExperimentalEncryptionProviderConfig enables encryption at rest for secrets.
ExperimentalEncryptionProviderConfig *string `json:"experimentalEncryptionProviderConfig,omitempty" flag:"experimental-encryption-provider-config"`

// List of request headers to inspect for usernames. X-Remote-User is common.
RequestheaderUsernameHeaders []string `json:"requestheaderUsernameHeaders,omitempty" flag:"requestheader-username-headers"`
// List of request headers to inspect for groups. X-Remote-Group is suggested.
RequestheaderGroupHeaders []string `json:"requestheaderGroupHeaders,omitempty" flag:"requestheader-group-headers"`
// List of request header prefixes to inspect. X-Remote-Extra- is suggested.
RequestheaderExtraHeaderPrefixes []string `json:"requestheaderExtraHeaderPrefixes,omitempty" flag:"requestheader-extra-headers-prefix"`
//Root certificate bundle to use to verify client certificates on incoming requests before trusting usernames in headers specified by --requestheader-username-headers
RequestheaderClientCAFile string `json:"requestheaderClientCAFile,omitempty" flag:"requestheader-client-ca-file"`
// List of client certificate common names to allow to provide usernames in headers specified by --requestheader-username-headers. If empty, any client certificate validated by the authorities in --requestheader-client-ca-file is allowed.
RequestheaderAllowedNames []string `json:"requestheaderAllowedNames,omitempty" flag:"requestheader-allowed-names"`
}

// KubeControllerManagerConfig is the configuration for the controller
Expand Down
11 changes: 11 additions & 0 deletions pkg/apis/kops/v1alpha1/componentconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,17 @@ type KubeAPIServerConfig struct {
AuthorizationRBACSuperUser *string `json:"authorizationRbacSuperUser,omitempty" flag:"authorization-rbac-super-user"`
// ExperimentalEncryptionProviderConfig enables encryption at rest for secrets.
ExperimentalEncryptionProviderConfig *string `json:"experimentalEncryptionProviderConfig,omitempty" flag:"experimental-encryption-provider-config"`

// List of request headers to inspect for usernames. X-Remote-User is common.
RequestheaderUsernameHeaders []string `json:"requestheaderUsernameHeaders,omitempty" flag:"requestheader-username-headers"`
// List of request headers to inspect for groups. X-Remote-Group is suggested.
RequestheaderGroupHeaders []string `json:"requestheaderGroupHeaders,omitempty" flag:"requestheader-group-headers"`
// List of request header prefixes to inspect. X-Remote-Extra- is suggested.
RequestheaderExtraHeaderPrefixes []string `json:"requestheaderExtraHeaderPrefixes,omitempty" flag:"requestheader-extra-headers-prefix"`
//Root certificate bundle to use to verify client certificates on incoming requests before trusting usernames in headers specified by --requestheader-username-headers
RequestheaderClientCAFile string `json:"requestheaderClientCAFile,omitempty" flag:"requestheader-client-ca-file"`
// List of client certificate common names to allow to provide usernames in headers specified by --requestheader-username-headers. If empty, any client certificate validated by the authorities in --requestheader-client-ca-file is allowed.
RequestheaderAllowedNames []string `json:"requestheaderAllowedNames,omitempty" flag:"requestheader-allowed-names"`
}

// KubeControllerManagerConfig is the configuration for the controller
Expand Down
10 changes: 10 additions & 0 deletions pkg/apis/kops/v1alpha1/zz_generated.conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -1810,6 +1810,11 @@ func autoConvert_v1alpha1_KubeAPIServerConfig_To_kops_KubeAPIServerConfig(in *Ku
out.AuthorizationMode = in.AuthorizationMode
out.AuthorizationRBACSuperUser = in.AuthorizationRBACSuperUser
out.ExperimentalEncryptionProviderConfig = in.ExperimentalEncryptionProviderConfig
out.RequestheaderUsernameHeaders = in.RequestheaderUsernameHeaders
out.RequestheaderGroupHeaders = in.RequestheaderGroupHeaders
out.RequestheaderExtraHeaderPrefixes = in.RequestheaderExtraHeaderPrefixes
out.RequestheaderClientCAFile = in.RequestheaderClientCAFile
out.RequestheaderAllowedNames = in.RequestheaderAllowedNames
return nil
}

Expand Down Expand Up @@ -1862,6 +1867,11 @@ func autoConvert_kops_KubeAPIServerConfig_To_v1alpha1_KubeAPIServerConfig(in *ko
out.AuthorizationMode = in.AuthorizationMode
out.AuthorizationRBACSuperUser = in.AuthorizationRBACSuperUser
out.ExperimentalEncryptionProviderConfig = in.ExperimentalEncryptionProviderConfig
out.RequestheaderUsernameHeaders = in.RequestheaderUsernameHeaders
out.RequestheaderGroupHeaders = in.RequestheaderGroupHeaders
out.RequestheaderExtraHeaderPrefixes = in.RequestheaderExtraHeaderPrefixes
out.RequestheaderClientCAFile = in.RequestheaderClientCAFile
out.RequestheaderAllowedNames = in.RequestheaderAllowedNames
return nil
}

Expand Down
20 changes: 20 additions & 0 deletions pkg/apis/kops/v1alpha1/zz_generated.deepcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2017,6 +2017,26 @@ func (in *KubeAPIServerConfig) DeepCopyInto(out *KubeAPIServerConfig) {
**out = **in
}
}
if in.RequestheaderUsernameHeaders != nil {
in, out := &in.RequestheaderUsernameHeaders, &out.RequestheaderUsernameHeaders
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.RequestheaderGroupHeaders != nil {
in, out := &in.RequestheaderGroupHeaders, &out.RequestheaderGroupHeaders
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.RequestheaderExtraHeaderPrefixes != nil {
in, out := &in.RequestheaderExtraHeaderPrefixes, &out.RequestheaderExtraHeaderPrefixes
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.RequestheaderAllowedNames != nil {
in, out := &in.RequestheaderAllowedNames, &out.RequestheaderAllowedNames
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}

Expand Down
11 changes: 11 additions & 0 deletions pkg/apis/kops/v1alpha2/componentconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,17 @@ type KubeAPIServerConfig struct {
AuthorizationRBACSuperUser *string `json:"authorizationRbacSuperUser,omitempty" flag:"authorization-rbac-super-user"`
// ExperimentalEncryptionProviderConfig enables encryption at rest for secrets.
ExperimentalEncryptionProviderConfig *string `json:"experimentalEncryptionProviderConfig,omitempty" flag:"experimental-encryption-provider-config"`

// List of request headers to inspect for usernames. X-Remote-User is common.
RequestheaderUsernameHeaders []string `json:"requestheaderUsernameHeaders,omitempty" flag:"requestheader-username-headers"`
// List of request headers to inspect for groups. X-Remote-Group is suggested.
RequestheaderGroupHeaders []string `json:"requestheaderGroupHeaders,omitempty" flag:"requestheader-group-headers"`
// List of request header prefixes to inspect. X-Remote-Extra- is suggested.
RequestheaderExtraHeaderPrefixes []string `json:"requestheaderExtraHeaderPrefixes,omitempty" flag:"requestheader-extra-headers-prefix"`
//Root certificate bundle to use to verify client certificates on incoming requests before trusting usernames in headers specified by --requestheader-username-headers
RequestheaderClientCAFile string `json:"requestheaderClientCAFile,omitempty" flag:"requestheader-client-ca-file"`
// List of client certificate common names to allow to provide usernames in headers specified by --requestheader-username-headers. If empty, any client certificate validated by the authorities in --requestheader-client-ca-file is allowed.
RequestheaderAllowedNames []string `json:"requestheaderAllowedNames,omitempty" flag:"requestheader-allowed-names"`
}

// KubeControllerManagerConfig is the configuration for the controller
Expand Down
10 changes: 10 additions & 0 deletions pkg/apis/kops/v1alpha2/zz_generated.conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -2072,6 +2072,11 @@ func autoConvert_v1alpha2_KubeAPIServerConfig_To_kops_KubeAPIServerConfig(in *Ku
out.AuthorizationMode = in.AuthorizationMode
out.AuthorizationRBACSuperUser = in.AuthorizationRBACSuperUser
out.ExperimentalEncryptionProviderConfig = in.ExperimentalEncryptionProviderConfig
out.RequestheaderUsernameHeaders = in.RequestheaderUsernameHeaders
out.RequestheaderGroupHeaders = in.RequestheaderGroupHeaders
out.RequestheaderExtraHeaderPrefixes = in.RequestheaderExtraHeaderPrefixes
out.RequestheaderClientCAFile = in.RequestheaderClientCAFile
out.RequestheaderAllowedNames = in.RequestheaderAllowedNames
return nil
}

Expand Down Expand Up @@ -2124,6 +2129,11 @@ func autoConvert_kops_KubeAPIServerConfig_To_v1alpha2_KubeAPIServerConfig(in *ko
out.AuthorizationMode = in.AuthorizationMode
out.AuthorizationRBACSuperUser = in.AuthorizationRBACSuperUser
out.ExperimentalEncryptionProviderConfig = in.ExperimentalEncryptionProviderConfig
out.RequestheaderUsernameHeaders = in.RequestheaderUsernameHeaders
out.RequestheaderGroupHeaders = in.RequestheaderGroupHeaders
out.RequestheaderExtraHeaderPrefixes = in.RequestheaderExtraHeaderPrefixes
out.RequestheaderClientCAFile = in.RequestheaderClientCAFile
out.RequestheaderAllowedNames = in.RequestheaderAllowedNames
return nil
}

Expand Down
20 changes: 20 additions & 0 deletions pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2143,6 +2143,26 @@ func (in *KubeAPIServerConfig) DeepCopyInto(out *KubeAPIServerConfig) {
**out = **in
}
}
if in.RequestheaderUsernameHeaders != nil {
in, out := &in.RequestheaderUsernameHeaders, &out.RequestheaderUsernameHeaders
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.RequestheaderGroupHeaders != nil {
in, out := &in.RequestheaderGroupHeaders, &out.RequestheaderGroupHeaders
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.RequestheaderExtraHeaderPrefixes != nil {
in, out := &in.RequestheaderExtraHeaderPrefixes, &out.RequestheaderExtraHeaderPrefixes
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.RequestheaderAllowedNames != nil {
in, out := &in.RequestheaderAllowedNames, &out.RequestheaderAllowedNames
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}

Expand Down
20 changes: 20 additions & 0 deletions pkg/apis/kops/zz_generated.deepcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2362,6 +2362,26 @@ func (in *KubeAPIServerConfig) DeepCopyInto(out *KubeAPIServerConfig) {
**out = **in
}
}
if in.RequestheaderUsernameHeaders != nil {
in, out := &in.RequestheaderUsernameHeaders, &out.RequestheaderUsernameHeaders
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.RequestheaderGroupHeaders != nil {
in, out := &in.RequestheaderGroupHeaders, &out.RequestheaderGroupHeaders
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.RequestheaderExtraHeaderPrefixes != nil {
in, out := &in.RequestheaderExtraHeaderPrefixes, &out.RequestheaderExtraHeaderPrefixes
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.RequestheaderAllowedNames != nil {
in, out := &in.RequestheaderAllowedNames, &out.RequestheaderAllowedNames
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}

Expand Down
16 changes: 16 additions & 0 deletions pkg/model/components/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ func (b *KubeAPIServerOptionsBuilder) BuildOptions(o interface{}) error {
clusterSpec.KubeAPIServer.AuthorizationMode = fi.String("RBAC")
}

if err := b.configureAggregation(clusterSpec); err != nil {
return nil
}

image, err := Image("kube-apiserver", clusterSpec, b.AssetBuilder)
if err != nil {
return err
Expand Down Expand Up @@ -243,3 +247,15 @@ func (b *KubeAPIServerOptionsBuilder) buildAPIServerCount(clusterSpec *kops.Clus

return count
}

// configureAggregation sets up the aggregation options
func (b *KubeAPIServerOptionsBuilder) configureAggregation(clusterSpec *kops.ClusterSpec) error {
if b.IsKubernetesGTE("1.7") {
clusterSpec.KubeAPIServer.RequestheaderAllowedNames = []string{"aggregator"}
clusterSpec.KubeAPIServer.RequestheaderExtraHeaderPrefixes = []string{"X-Remote-Extra-"}
clusterSpec.KubeAPIServer.RequestheaderGroupHeaders = []string{"X-Remote-Group"}
clusterSpec.KubeAPIServer.RequestheaderUsernameHeaders = []string{"X-Remote-User"}
}

return nil
}
Loading

0 comments on commit 5eb9fe7

Please sign in to comment.