Add weave network encryption secret

This commit is contained in:
Christian Kampka 2018-07-06 15:36:04 +02:00
parent 35b7d5791d
commit 3bf8a8fcd2
11 changed files with 275 additions and 8 deletions

View File

@ -14,6 +14,7 @@ go_library(
"create_secret_keypair_ca.go",
"create_secret_sshpublickey.go",
"create_secret_tls.go",
"create_secret_weave_encryptionconfig.go",
"delete.go",
"delete_cluster.go",
"delete_instancegroup.go",

View File

@ -57,6 +57,7 @@ func NewCmdCreateSecret(f *util.Factory, out io.Writer) *cobra.Command {
cmd.AddCommand(NewCmdCreateSecretDockerConfig(f, out))
cmd.AddCommand(NewCmdCreateSecretEncryptionConfig(f, out))
cmd.AddCommand(NewCmdCreateKeypairSecret(f, out))
cmd.AddCommand(NewCmdCreateSecretWeaveEncryptionConfig(f, out))
return cmd
}

View File

@ -0,0 +1,137 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"io"
"io/ioutil"
"os"
"github.com/spf13/cobra"
"k8s.io/kops/cmd/kops/util"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
)
var (
createSecretWeaveEncryptionconfigLong = templates.LongDesc(i18n.T(`
Create a new weave encryption secret, and store it in the state store.
Used to weave networking to use encrypted communication between nodes.
WARNING: cannot be enabled on a running cluster without downtime.`))
createSecretWeaveEncryptionconfigExample = templates.Examples(i18n.T(`
# Create an new weave password.
kops create secret weavepassword -f /path/to/weavepassword \
--name k8s-cluster.example.com --state s3://example.com
# Replace an existing weavepassword secret.
kops create secret weavepassword -f /path/to/weavepassword --force \
--name k8s-cluster.example.com --state s3://example.com
`))
createSecretWeaveEncryptionconfigShort = i18n.T(`Create a weave encryption config.`)
)
type CreateSecretWeaveEncryptionConfigOptions struct {
ClusterName string
WeavePasswordFilePath string
Force bool
}
func NewCmdCreateSecretWeaveEncryptionConfig(f *util.Factory, out io.Writer) *cobra.Command {
options := &CreateSecretWeaveEncryptionConfigOptions{}
cmd := &cobra.Command{
Use: "weavepassword",
Short: createSecretWeaveEncryptionconfigShort,
Long: createSecretWeaveEncryptionconfigLong,
Example: createSecretWeaveEncryptionconfigExample,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 0 {
exitWithError(fmt.Errorf("syntax: -f <WeavePasswordFile>"))
}
err := rootCommand.ProcessArgs(args[0:])
if err != nil {
exitWithError(err)
}
options.ClusterName = rootCommand.ClusterName()
err = RunCreateSecretWeaveEncryptionConfig(f, os.Stdout, options)
if err != nil {
exitWithError(err)
}
},
}
cmd.Flags().StringVarP(&options.WeavePasswordFilePath, "", "f", "", "Path to the weave password file")
cmd.Flags().BoolVar(&options.Force, "force", options.Force, "Force replace the kops secret if it already exists")
return cmd
}
func RunCreateSecretWeaveEncryptionConfig(f *util.Factory, out io.Writer, options *CreateSecretWeaveEncryptionConfigOptions) error {
if options.WeavePasswordFilePath == "" {
return fmt.Errorf("weave password file path is required (use -f)")
}
secret, err := fi.CreateSecret()
if err != nil {
return fmt.Errorf("error creating encryption secret: %v", err)
}
cluster, err := GetCluster(f, options.ClusterName)
if err != nil {
return err
}
clientset, err := f.Clientset()
if err != nil {
return err
}
secretStore, err := clientset.SecretStore(cluster)
if err != nil {
return err
}
data, err := ioutil.ReadFile(options.WeavePasswordFilePath)
if err != nil {
return fmt.Errorf("error reading weave password file %v: %v", options.WeavePasswordFilePath, err)
}
secret.Data = data
if !options.Force {
_, created, err := secretStore.GetOrCreateSecret("weavepassword", secret)
if err != nil {
return fmt.Errorf("error adding weavepassword secret: %v", err)
}
if !created {
return fmt.Errorf("failed to create the weavepassword secret as it already exists. The `--force` flag can be passed to replace an existing secret.")
}
} else {
_, err := secretStore.ReplaceSecret("weavepassword", secret)
if err != nil {
return fmt.Errorf("error updating weavepassword secret: %v", err)
}
}
return nil
}

View File

@ -51,4 +51,5 @@ Create a secret
* [kops create secret encryptionconfig](kops_create_secret_encryptionconfig.md) - Create an encryption config.
* [kops create secret keypair](kops_create_secret_keypair.md) - Create a secret keypair.
* [kops create secret sshpublickey](kops_create_secret_sshpublickey.md) - Create a ssh public key.
* [kops create secret weavepassword](kops_create_secret_weavepassword.md) - Create a weave encryption config.

View File

@ -0,0 +1,55 @@
<!--- This file is automatically generated by make gen-cli-docs; changes should be made in the go CLI command code (under cmd/kops) -->
## kops create secret weavepassword
Create a weave encryption config.
### Synopsis
Create a new weave encryption secret, and store it in the state store. Used to weave networking to use encrypted communication between nodes.
WARNING: cannot be enabled on a running cluster without downtime.
```
kops create secret weavepassword [flags]
```
### Examples
```
# Create an new weave password.
kops create secret weavepassword -f /path/to/weavepassword \
--name k8s-cluster.example.com --state s3://example.com
# Replace an existing weavepassword secret.
kops create secret weavepassword -f /path/to/weavepassword --force \
--name k8s-cluster.example.com --state s3://example.com
```
### Options
```
-f, -- string Path to the weave password file
--force Force replace the kops secret if it already exists
-h, --help help for weavepassword
```
### Options inherited from parent commands
```
--alsologtostderr log to standard error as well as files
--config string yaml config file (default is $HOME/.kops.yaml)
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
--log_dir string If non-empty, write log files in this directory
--logtostderr log to standard error instead of files (default false)
--name string Name of cluster. Overrides KOPS_CLUSTER_NAME environment variable
--state string Location of state storage (kops 'config' file). Overrides KOPS_STATE_STORE environment variable
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
-v, --v Level log level for V logs
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [kops create secret](kops_create_secret.md) - Create a secret.

View File

@ -10,7 +10,7 @@ Kubernetes Operations (kops) currently supports 4 networking modes:
### kops Default Networking
Kubernetes Operations (kops) uses `kubenet` networking by default. This sets up networking on AWS using VPC
networking, where the master allocates a /24 CIDR to each Node, drawing from the Node network.
networking, where the master allocates a /24 CIDR to each Node, drawing from the Node network.
Using `kubenet` mode routes for each node are then configured in the AWS VPC routing tables.
One important limitation when using `kubenet` networking is that an AWS routing table cannot have more than
@ -110,6 +110,18 @@ spec:
mtu: 8912
```
### Configuring Weave network encryption
The Weave network encryption is configurable by creating a weave network secret password.
Weaveworks recommends choosing a secret with [at least 50 bits of entropy](https://www.weave.works/docs/net/latest/tasks/manage/security-untrusted-networks/).
```console
$ cat /dev/urandom | tr -dc A-Za-z0-9 | head -c9 > password
$ kops create secret weavepassword -f password
$ kops update cluster
```
Since unencrypted nodes will not be able to connect to nodes configured with encryption enabled, this configuration cannot be changed easily without downtime.
### Calico Example for CNI and Network Policy
@ -138,7 +150,7 @@ when its destined to subnets with intermediate infrastructure lacking Calico
With this mode, IP-in-IP encapsulation is only performed selectively. This provides better performance in AWS
multi-AZ deployments, and in general when deploying on networks where pools of nodes with L2 connectivity
are connected via a router.
are connected via a router.
Reference: [Calico 2.1 Release Notes](https://www.projectcalico.org/project-calico-2-1-released/)
@ -260,7 +272,7 @@ $ kops create cluster \
Currently kube-router supports 1.6 and above. Please note that kube-router will also provide service proxy, so kube-proxy will not be deployed in to the cluster.
No additional configurations are required to be done by user. Kube-router automatically disables source-destination check on all AWS EC2 instances. For the traffic within a subnet there is no overlay or tunneling used. For cross-subnet pod traffic ip-ip tunneling is used implicitly and no configuration is required.
No additional configurations are required to be done by user. Kube-router automatically disables source-destination check on all AWS EC2 instances. For the traffic within a subnet there is no overlay or tunneling used. For cross-subnet pod traffic ip-ip tunneling is used implicitly and no configuration is required.
### Romana Example for CNI

View File

@ -1,3 +1,14 @@
{{- if WeaveSecret }}
apiVersion: v1
kind: Secret
metadata:
name: weave-net
namespace: kube-system
stringData:
network-password: {{ WeaveSecret }}
---
{{- end }}
apiVersion: v1
kind: ServiceAccount
metadata:
@ -130,6 +141,13 @@ spec:
- name: CONN_LIMIT
value: "{{ .Networking.Weave.ConnLimit }}"
{{- end }}
{{- if WeaveSecret }}
- name: WEAVE_PASSWORD
valueFrom:
secretKeyRef:
name: weave-net
key: network-password
{{- end }}
image: 'weaveworks/weave-kube:2.3.0'
livenessProbe:
httpGet:

View File

@ -538,7 +538,11 @@ func (c *ApplyClusterCmd) Run() error {
if err != nil {
return fmt.Errorf("error loading templates: %v", err)
}
tf.AddTo(templates.TemplateFunctions)
err = tf.AddTo(templates.TemplateFunctions, secretStore)
if err != nil {
return err
}
l.Builders = append(l.Builders,
&BootstrapChannelBuilder{
@ -733,7 +737,10 @@ func (c *ApplyClusterCmd) Run() error {
l.TemplateFunctions["Masters"] = tf.modelContext.MasterInstanceGroups
tf.AddTo(l.TemplateFunctions)
err = tf.AddTo(l.TemplateFunctions, secretStore)
if err != nil {
return err
}
taskMap, err := l.BuildTasks(modelStore, fileModels, assetBuilder, &stageAssetsLifecycle, c.LifecycleOverrides)
if err != nil {

View File

@ -24,6 +24,7 @@ import (
api "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/assets"
"k8s.io/kops/pkg/client/simple/vfsclientset"
"k8s.io/kops/pkg/diff"
"k8s.io/kops/pkg/kopscodecs"
"k8s.io/kops/pkg/model"
@ -32,6 +33,7 @@ import (
"k8s.io/kops/upup/models"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/fitasks"
"k8s.io/kops/util/pkg/vfs"
)
func TestBootstrapChannelBuilder_BuildTasks(t *testing.T) {
@ -74,8 +76,22 @@ func runChannelBuilderTest(t *testing.T, key string) {
if err != nil {
t.Fatalf("error building templates: %v", err)
}
vfs.Context.ResetMemfsContext(true)
basePath, err := vfs.Context.BuildVfsPath("memfs://tests")
if err != nil {
t.Errorf("error building vfspath: %v", err)
}
clientset := vfsclientset.NewVFSClientset(basePath, true)
secretStore, err := clientset.SecretStore(cluster)
if err != nil {
t.Error(err)
}
tf := &TemplateFunctions{cluster: cluster, modelContext: &model.KopsModelContext{Cluster: cluster}}
tf.AddTo(templates.TemplateFunctions)
tf.AddTo(templates.TemplateFunctions, secretStore)
bcb := BootstrapChannelBuilder{
cluster: cluster,

View File

@ -268,7 +268,10 @@ func (c *populateClusterSpec) run(clientset simple.Clientset) error {
templateFunctions := make(template.FuncMap)
tf.AddTo(templateFunctions)
err = tf.AddTo(templateFunctions, secretStore)
if err != nil {
return err
}
if cluster.Spec.KubernetesVersion == "" {
return fmt.Errorf("KubernetesVersion is required")

View File

@ -56,7 +56,7 @@ type TemplateFunctions struct {
// This will define the available functions we can use in our YAML models
// If we are trying to get a new function implemented it MUST
// be defined here.
func (tf *TemplateFunctions) AddTo(dest template.FuncMap) {
func (tf *TemplateFunctions) AddTo(dest template.FuncMap, secretStore fi.SecretStore) (err error) {
dest["EtcdScheme"] = tf.EtcdScheme
dest["SharedVPC"] = tf.SharedVPC
dest["ToJSON"] = tf.ToJSON
@ -109,6 +109,22 @@ func (tf *TemplateFunctions) AddTo(dest template.FuncMap) {
}
dest["FlannelBackendType"] = func() string { return flannelBackendType }
}
if tf.cluster.Spec.Networking != nil && tf.cluster.Spec.Networking.Weave != nil {
weavesecretString := ""
weavesecret, _ := secretStore.Secret("weavepassword")
if weavesecret != nil {
weavesecretString, err = weavesecret.AsString()
if err != nil {
return err
}
glog.V(4).Info("Weave secret function successfully registered")
}
dest["WeaveSecret"] = func() string { return weavesecretString }
}
return nil
}
// ToJSON returns a json representation of the struct or on error an empty string