mirror of https://github.com/kubernetes/kops.git
Seed the random number generator on AWS
This commit is contained in:
parent
7ec956dd00
commit
42bf3ee85b
|
|
@ -43,11 +43,7 @@ func (b BootstrapClientBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
var err error
|
||||
switch kops.CloudProviderID(b.Cluster.Spec.CloudProvider) {
|
||||
case kops.CloudProviderAWS:
|
||||
region, regionErr := awsup.FindRegion(b.Cluster)
|
||||
if regionErr != nil {
|
||||
return fmt.Errorf("querying AWS region: %v", regionErr)
|
||||
}
|
||||
authenticator, err = awsup.NewAWSAuthenticator(region)
|
||||
authenticator, err = awsup.NewAWSAuthenticator(b.Cloud.Region())
|
||||
default:
|
||||
return fmt.Errorf("unsupported cloud provider %s", b.Cluster.Spec.CloudProvider)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ type Config struct {
|
|||
InstanceGroupRole kops.InstanceGroupRole
|
||||
// ClusterName is the name of the cluster
|
||||
ClusterName string `json:",omitempty"`
|
||||
// CloudProvider is the cloud provider in use.
|
||||
CloudProvider string
|
||||
// Channels is a list of channels that we should apply
|
||||
Channels []string `json:"channels,omitempty"`
|
||||
// ApiserverAdditionalIPs are additional IP address to put in the apiserver server cert.
|
||||
|
|
@ -91,9 +93,6 @@ type ConfigServerOptions struct {
|
|||
Server string `json:"server,omitempty"`
|
||||
// CA is the ca-certificate to require for the configuration server
|
||||
CA string `json:"ca,omitempty"`
|
||||
|
||||
// CloudProvider is the cloud provider in use (needed for authentication)
|
||||
CloudProvider string `json:"cloudProvider,omitempty"`
|
||||
}
|
||||
|
||||
// Image is a docker image we should pre-load
|
||||
|
|
|
|||
|
|
@ -247,6 +247,7 @@ func (r *NodeRoleAPIServer) BuildAWSPolicy(b *PolicyBuilder) (*Policy, error) {
|
|||
addMasterEC2Policies(p, resource, b.Cluster.GetName())
|
||||
addASLifecyclePolicies(p, resource, b.Cluster.GetName(), r.warmPool)
|
||||
addCertIAMPolicies(p, resource)
|
||||
addKMSGenerateRandomPolicies(p)
|
||||
|
||||
var err error
|
||||
if p, err = b.AddS3Permissions(p); err != nil {
|
||||
|
|
@ -293,6 +294,7 @@ func (r *NodeRoleMaster) BuildAWSPolicy(b *PolicyBuilder) (*Policy, error) {
|
|||
addMasterASPolicies(p, resource, b.Cluster.GetName())
|
||||
addMasterELBPolicies(p, resource)
|
||||
addCertIAMPolicies(p, resource)
|
||||
addKMSGenerateRandomPolicies(p)
|
||||
|
||||
var err error
|
||||
if p, err = b.AddS3Permissions(p); err != nil {
|
||||
|
|
@ -354,6 +356,7 @@ func (r *NodeRoleNode) BuildAWSPolicy(b *PolicyBuilder) (*Policy, error) {
|
|||
|
||||
addNodeEC2Policies(p, resource)
|
||||
addASLifecyclePolicies(p, resource, b.Cluster.GetName(), r.enableLifecycleHookPermissions)
|
||||
addKMSGenerateRandomPolicies(p)
|
||||
|
||||
var err error
|
||||
if p, err = b.AddS3Permissions(p); err != nil {
|
||||
|
|
@ -866,6 +869,17 @@ func addKMSIAMPolicies(p *Policy, resource stringorslice.StringOrSlice) {
|
|||
})
|
||||
}
|
||||
|
||||
func addKMSGenerateRandomPolicies(p *Policy) {
|
||||
// For nodeup to seed the instance's random number generator.
|
||||
p.Statement = append(p.Statement, &Statement{
|
||||
Effect: StatementEffectAllow,
|
||||
Action: stringorslice.Of(
|
||||
"kms:GenerateRandom",
|
||||
),
|
||||
Resource: stringorslice.Slice([]string{"*"}),
|
||||
})
|
||||
}
|
||||
|
||||
func addNodeEC2Policies(p *Policy, resource stringorslice.StringOrSlice) {
|
||||
// Protokube makes a DescribeInstances call, DescribeRegions when finding S3 State Bucket
|
||||
p.Statement = append(p.Statement, &Statement{
|
||||
|
|
|
|||
|
|
@ -1319,6 +1319,7 @@ func (n *nodeUpConfigBuilder) BuildConfig(ig *kops.InstanceGroup, apiserverAddit
|
|||
}
|
||||
config.ClusterName = cluster.ObjectMeta.Name
|
||||
config.InstanceGroupName = ig.ObjectMeta.Name
|
||||
config.CloudProvider = cluster.Spec.CloudProvider
|
||||
|
||||
if isMaster || useGossip {
|
||||
for _, arch := range architectures.GetSupported() {
|
||||
|
|
@ -1349,9 +1350,8 @@ func (n *nodeUpConfigBuilder) BuildConfig(ig *kops.InstanceGroup, apiserverAddit
|
|||
}
|
||||
|
||||
configServer := &nodeup.ConfigServerOptions{
|
||||
Server: baseURL.String(),
|
||||
CloudProvider: cluster.Spec.CloudProvider,
|
||||
CA: ca,
|
||||
Server: baseURL.String(),
|
||||
CA: ca,
|
||||
}
|
||||
|
||||
config.ConfigServer = configServer
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ go_library(
|
|||
"//vendor/github.com/aws/aws-sdk-go/aws/session:go_default_library",
|
||||
"//vendor/github.com/aws/aws-sdk-go/service/autoscaling:go_default_library",
|
||||
"//vendor/github.com/aws/aws-sdk-go/service/ec2:go_default_library",
|
||||
"//vendor/github.com/aws/aws-sdk-go/service/kms:go_default_library",
|
||||
"//vendor/k8s.io/klog/v2:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -26,11 +26,13 @@ import (
|
|||
"io/ioutil"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/kms"
|
||||
"k8s.io/kops/nodeup/pkg/model"
|
||||
"k8s.io/kops/nodeup/pkg/model/networking"
|
||||
api "k8s.io/kops/pkg/apis/kops"
|
||||
|
|
@ -91,13 +93,21 @@ func (c *NodeUpCommand) Run(out io.Writer) error {
|
|||
return fmt.Errorf("CacheDir is required")
|
||||
}
|
||||
|
||||
region, err := getRegion(ctx, c.config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = seedRNG(ctx, c.config, region); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var configBase vfs.Path
|
||||
|
||||
// If we're using a config server instead of vfs, nodeConfig will hold our configuration
|
||||
var nodeConfig *nodeup.NodeConfig
|
||||
|
||||
if c.config.ConfigServer != nil {
|
||||
response, err := getNodeConfigFromServer(ctx, c.config.ConfigServer)
|
||||
response, err := getNodeConfigFromServer(ctx, c.config, region)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -182,7 +192,7 @@ func (c *NodeUpCommand) Run(out io.Writer) error {
|
|||
return fmt.Errorf("auxiliary config hash mismatch")
|
||||
}
|
||||
|
||||
err := evaluateSpec(c)
|
||||
err = evaluateSpec(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -209,10 +219,6 @@ func (c *NodeUpCommand) Run(out io.Writer) error {
|
|||
var cloud fi.Cloud
|
||||
|
||||
if api.CloudProviderID(c.cluster.Spec.CloudProvider) == api.CloudProviderAWS {
|
||||
region, err := awsup.FindRegion(c.cluster)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
awsCloud, err := awsup.NewAWSCloud(region, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -674,16 +680,60 @@ func loadKernelModules(context *model.NodeupModelContext) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// getNodeConfigFromServer queries kops-controller for our node's configuration.
|
||||
func getNodeConfigFromServer(ctx context.Context, config *nodeup.ConfigServerOptions) (*nodeup.BootstrapResponse, error) {
|
||||
var authenticator fi.Authenticator
|
||||
|
||||
// getRegionAndSeedRNG queries the cloud provider for the region and adds entropy to the random number generator.
|
||||
func getRegion(ctx context.Context, config *nodeup.Config) (string, error) {
|
||||
switch api.CloudProviderID(config.CloudProvider) {
|
||||
case api.CloudProviderAWS:
|
||||
region, err := awsup.RegionFromMetadata(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
return region, nil
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// seedRNG adds entropy to the random number generator.
|
||||
func seedRNG(ctx context.Context, config *nodeup.Config, region string) error {
|
||||
switch api.CloudProviderID(config.CloudProvider) {
|
||||
case api.CloudProviderAWS:
|
||||
config := aws.NewConfig().WithCredentialsChainVerboseErrors(true).WithRegion(region)
|
||||
sess, err := session.NewSession(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
random, err := kms.New(sess, config).GenerateRandom(&kms.GenerateRandomInput{
|
||||
NumberOfBytes: aws.Int64(64),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("generating random seed: %v", err)
|
||||
}
|
||||
|
||||
f, err := os.OpenFile("/dev/urandom", os.O_WRONLY, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("opening /dev/urandom: %v", err)
|
||||
}
|
||||
_, err = f.Write(random.Plaintext)
|
||||
if err1 := f.Close(); err1 != nil && err == nil {
|
||||
err = err1
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("writing /dev/urandom: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getNodeConfigFromServer queries kops-controller for our node's configuration.
|
||||
func getNodeConfigFromServer(ctx context.Context, config *nodeup.Config, region string) (*nodeup.BootstrapResponse, error) {
|
||||
var authenticator fi.Authenticator
|
||||
|
||||
switch api.CloudProviderID(config.CloudProvider) {
|
||||
case api.CloudProviderAWS:
|
||||
a, err := awsup.NewAWSAuthenticator(region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -697,13 +747,13 @@ func getNodeConfigFromServer(ctx context.Context, config *nodeup.ConfigServerOpt
|
|||
Authenticator: authenticator,
|
||||
}
|
||||
|
||||
if config.CA != "" {
|
||||
client.CA = []byte(config.CA)
|
||||
if config.ConfigServer.CA != "" {
|
||||
client.CA = []byte(config.ConfigServer.CA)
|
||||
}
|
||||
|
||||
u, err := url.Parse(config.Server)
|
||||
u, err := url.Parse(config.ConfigServer.Server)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse configuration server url %q: %w", config.Server, err)
|
||||
return nil, fmt.Errorf("unable to parse configuration server url %q: %w", config.ConfigServer.Server, err)
|
||||
}
|
||||
client.BaseURL = *u
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue