Adds filtering of hosts to DialContexts.

The provided DialContext wraps existing clients' DialContext in an attempt to
preserve any existing timeout configuration. In some cases, we may replace
infinite timeouts with golang defaults.

- scaleio: tcp connect/keepalive values changed from 0/15 to 30/30
- storageos: no change
This commit is contained in:
Matthew Cary 2020-06-09 21:30:40 +00:00
parent 74dbf274d9
commit f2e23afcf1
41 changed files with 346 additions and 65 deletions

View File

@ -370,6 +370,7 @@ API rule violation: list_type_missing,k8s.io/apiserver/pkg/apis/audit/v1beta1,Po
API rule violation: list_type_missing,k8s.io/apiserver/pkg/apis/audit/v1beta1,PolicyRule,Verbs API rule violation: list_type_missing,k8s.io/apiserver/pkg/apis/audit/v1beta1,PolicyRule,Verbs
API rule violation: list_type_missing,k8s.io/kube-controller-manager/config/v1alpha1,GarbageCollectorControllerConfiguration,GCIgnoredResources API rule violation: list_type_missing,k8s.io/kube-controller-manager/config/v1alpha1,GarbageCollectorControllerConfiguration,GCIgnoredResources
API rule violation: list_type_missing,k8s.io/kube-controller-manager/config/v1alpha1,GenericControllerManagerConfiguration,Controllers API rule violation: list_type_missing,k8s.io/kube-controller-manager/config/v1alpha1,GenericControllerManagerConfiguration,Controllers
API rule violation: list_type_missing,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeBinderControllerConfiguration,VolumeHostCIDRDenylist
API rule violation: list_type_missing,k8s.io/kube-proxy/config/v1alpha1,KubeProxyConfiguration,NodePortAddresses API rule violation: list_type_missing,k8s.io/kube-proxy/config/v1alpha1,KubeProxyConfiguration,NodePortAddresses
API rule violation: list_type_missing,k8s.io/kube-proxy/config/v1alpha1,KubeProxyIPVSConfiguration,ExcludeCIDRs API rule violation: list_type_missing,k8s.io/kube-proxy/config/v1alpha1,KubeProxyIPVSConfiguration,ExcludeCIDRs
API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,ExtenderTLSConfig,CAData API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,ExtenderTLSConfig,CAData
@ -569,6 +570,8 @@ API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,N
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,NodeLifecycleControllerConfiguration,UnhealthyZoneThreshold API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,NodeLifecycleControllerConfiguration,UnhealthyZoneThreshold
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeBinderControllerConfiguration,PVClaimBinderSyncPeriod API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeBinderControllerConfiguration,PVClaimBinderSyncPeriod
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeBinderControllerConfiguration,VolumeConfiguration API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeBinderControllerConfiguration,VolumeConfiguration
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeBinderControllerConfiguration,VolumeHostAllowLocalLoopback
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeBinderControllerConfiguration,VolumeHostCIDRDenylist
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeRecyclerConfiguration,IncrementTimeoutHostPath API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeRecyclerConfiguration,IncrementTimeoutHostPath
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeRecyclerConfiguration,IncrementTimeoutNFS API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeRecyclerConfiguration,IncrementTimeoutNFS
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeRecyclerConfiguration,MaximumRetry API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeRecyclerConfiguration,MaximumRetry

View File

@ -43,6 +43,7 @@ import (
servicecontroller "k8s.io/cloud-provider/controllers/service" servicecontroller "k8s.io/cloud-provider/controllers/service"
"k8s.io/component-base/metrics/prometheus/ratelimiter" "k8s.io/component-base/metrics/prometheus/ratelimiter"
csitrans "k8s.io/csi-translation-lib" csitrans "k8s.io/csi-translation-lib"
"k8s.io/kubernetes/cmd/kube-controller-manager/app/options"
"k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller"
endpointcontroller "k8s.io/kubernetes/pkg/controller/endpoint" endpointcontroller "k8s.io/kubernetes/pkg/controller/endpoint"
"k8s.io/kubernetes/pkg/controller/garbagecollector" "k8s.io/kubernetes/pkg/controller/garbagecollector"
@ -285,6 +286,12 @@ func startPersistentVolumeBinderController(ctx ControllerContext) (http.Handler,
if err != nil { if err != nil {
return nil, true, fmt.Errorf("failed to probe volume plugins when starting persistentvolume controller: %v", err) return nil, true, fmt.Errorf("failed to probe volume plugins when starting persistentvolume controller: %v", err)
} }
filteredDialOptions, err := options.ParseVolumeHostFilters(
ctx.ComponentConfig.PersistentVolumeBinderController.VolumeHostCIDRDenylist,
ctx.ComponentConfig.PersistentVolumeBinderController.VolumeHostAllowLocalLoopback)
if err != nil {
return nil, true, err
}
params := persistentvolumecontroller.ControllerParameters{ params := persistentvolumecontroller.ControllerParameters{
KubeClient: ctx.ClientBuilder.ClientOrDie("persistent-volume-binder"), KubeClient: ctx.ClientBuilder.ClientOrDie("persistent-volume-binder"),
SyncPeriod: ctx.ComponentConfig.PersistentVolumeBinderController.PVClaimBinderSyncPeriod.Duration, SyncPeriod: ctx.ComponentConfig.PersistentVolumeBinderController.PVClaimBinderSyncPeriod.Duration,
@ -297,6 +304,7 @@ func startPersistentVolumeBinderController(ctx ControllerContext) (http.Handler,
PodInformer: ctx.InformerFactory.Core().V1().Pods(), PodInformer: ctx.InformerFactory.Core().V1().Pods(),
NodeInformer: ctx.InformerFactory.Core().V1().Nodes(), NodeInformer: ctx.InformerFactory.Core().V1().Nodes(),
EnableDynamicProvisioning: ctx.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration.EnableDynamicProvisioning, EnableDynamicProvisioning: ctx.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration.EnableDynamicProvisioning,
FilteredDialOptions: filteredDialOptions,
} }
volumeController, volumeControllerErr := persistentvolumecontroller.NewController(params) volumeController, volumeControllerErr := persistentvolumecontroller.NewController(params)
if volumeControllerErr != nil { if volumeControllerErr != nil {
@ -324,6 +332,13 @@ func startAttachDetachController(ctx ControllerContext) (http.Handler, bool, err
return nil, true, fmt.Errorf("failed to probe volume plugins when starting attach/detach controller: %v", err) return nil, true, fmt.Errorf("failed to probe volume plugins when starting attach/detach controller: %v", err)
} }
filteredDialOptions, err := options.ParseVolumeHostFilters(
ctx.ComponentConfig.PersistentVolumeBinderController.VolumeHostCIDRDenylist,
ctx.ComponentConfig.PersistentVolumeBinderController.VolumeHostAllowLocalLoopback)
if err != nil {
return nil, true, err
}
attachDetachController, attachDetachControllerErr := attachDetachController, attachDetachControllerErr :=
attachdetach.NewAttachDetachController( attachdetach.NewAttachDetachController(
ctx.ClientBuilder.ClientOrDie("attachdetach-controller"), ctx.ClientBuilder.ClientOrDie("attachdetach-controller"),
@ -340,6 +355,7 @@ func startAttachDetachController(ctx ControllerContext) (http.Handler, bool, err
ctx.ComponentConfig.AttachDetachController.DisableAttachDetachReconcilerSync, ctx.ComponentConfig.AttachDetachController.DisableAttachDetachReconcilerSync,
ctx.ComponentConfig.AttachDetachController.ReconcilerSyncLoopPeriod.Duration, ctx.ComponentConfig.AttachDetachController.ReconcilerSyncLoopPeriod.Duration,
attachdetach.DefaultTimerConfig, attachdetach.DefaultTimerConfig,
filteredDialOptions,
) )
if attachDetachControllerErr != nil { if attachDetachControllerErr != nil {
return nil, true, fmt.Errorf("failed to start attach/detach controller: %v", attachDetachControllerErr) return nil, true, fmt.Errorf("failed to start attach/detach controller: %v", attachDetachControllerErr)
@ -355,6 +371,12 @@ func startVolumeExpandController(ctx ControllerContext) (http.Handler, bool, err
return nil, true, fmt.Errorf("failed to probe volume plugins when starting volume expand controller: %v", err) return nil, true, fmt.Errorf("failed to probe volume plugins when starting volume expand controller: %v", err)
} }
csiTranslator := csitrans.New() csiTranslator := csitrans.New()
filteredDialOptions, err := options.ParseVolumeHostFilters(
ctx.ComponentConfig.PersistentVolumeBinderController.VolumeHostCIDRDenylist,
ctx.ComponentConfig.PersistentVolumeBinderController.VolumeHostAllowLocalLoopback)
if err != nil {
return nil, true, err
}
expandController, expandControllerErr := expand.NewExpandController( expandController, expandControllerErr := expand.NewExpandController(
ctx.ClientBuilder.ClientOrDie("expand-controller"), ctx.ClientBuilder.ClientOrDie("expand-controller"),
ctx.InformerFactory.Core().V1().PersistentVolumeClaims(), ctx.InformerFactory.Core().V1().PersistentVolumeClaims(),
@ -363,7 +385,9 @@ func startVolumeExpandController(ctx ControllerContext) (http.Handler, bool, err
ctx.Cloud, ctx.Cloud,
plugins, plugins,
csiTranslator, csiTranslator,
csimigration.NewPluginManager(csiTranslator)) csimigration.NewPluginManager(csiTranslator),
filteredDialOptions,
)
if expandControllerErr != nil { if expandControllerErr != nil {
return nil, true, fmt.Errorf("failed to start volume expand controller: %v", expandControllerErr) return nil, true, fmt.Errorf("failed to start volume expand controller: %v", expandControllerErr)

View File

@ -63,6 +63,7 @@ go_library(
"//pkg/controller/volume/attachdetach/config:go_default_library", "//pkg/controller/volume/attachdetach/config:go_default_library",
"//pkg/controller/volume/persistentvolume/config:go_default_library", "//pkg/controller/volume/persistentvolume/config:go_default_library",
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//pkg/proxy/util:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/server/options:go_default_library", "//staging/src/k8s.io/apiserver/pkg/server/options:go_default_library",
@ -78,6 +79,7 @@ go_library(
"//staging/src/k8s.io/component-base/metrics:go_default_library", "//staging/src/k8s.io/component-base/metrics:go_default_library",
"//staging/src/k8s.io/kube-controller-manager/config/v1alpha1:go_default_library", "//staging/src/k8s.io/kube-controller-manager/config/v1alpha1:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/utils/net:go_default_library",
], ],
) )

View File

@ -100,6 +100,8 @@ var args = []string{
"--enable-taint-manager=false", "--enable-taint-manager=false",
"--cluster-signing-duration=10h", "--cluster-signing-duration=10h",
"--flex-volume-plugin-dir=/flex-volume-plugin", "--flex-volume-plugin-dir=/flex-volume-plugin",
"--volume-host-cidr-denylist=127.0.0.1/28,feed::/16",
"--volume-host-allow-local-loopback=false",
"--horizontal-pod-autoscaler-downscale-delay=2m", "--horizontal-pod-autoscaler-downscale-delay=2m",
"--horizontal-pod-autoscaler-sync-period=45s", "--horizontal-pod-autoscaler-sync-period=45s",
"--horizontal-pod-autoscaler-upscale-delay=1m", "--horizontal-pod-autoscaler-upscale-delay=1m",
@ -350,6 +352,8 @@ func TestAddFlags(t *testing.T) {
IncrementTimeoutHostPath: 45, IncrementTimeoutHostPath: 45,
}, },
}, },
VolumeHostCIDRDenylist: []string{"127.0.0.1/28", "feed::/16"},
VolumeHostAllowLocalLoopback: false,
}, },
}, },
PodGCController: &PodGCControllerOptions{ PodGCController: &PodGCControllerOptions{
@ -589,6 +593,8 @@ func TestApplyTo(t *testing.T) {
IncrementTimeoutHostPath: 45, IncrementTimeoutHostPath: 45,
}, },
}, },
VolumeHostCIDRDenylist: []string{"127.0.0.1/28", "feed::/16"},
VolumeHostAllowLocalLoopback: false,
}, },
PodGCController: podgcconfig.PodGCControllerConfiguration{ PodGCController: podgcconfig.PodGCControllerConfiguration{
TerminatedPodGCThreshold: 12000, TerminatedPodGCThreshold: 12000,

View File

@ -17,9 +17,13 @@ limitations under the License.
package options package options
import ( import (
"fmt"
"github.com/spf13/pflag" "github.com/spf13/pflag"
persistentvolumeconfig "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/config" persistentvolumeconfig "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/config"
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
netutils "k8s.io/utils/net"
) )
// PersistentVolumeBinderControllerOptions holds the PersistentVolumeBinderController options. // PersistentVolumeBinderControllerOptions holds the PersistentVolumeBinderController options.
@ -43,6 +47,8 @@ func (o *PersistentVolumeBinderControllerOptions) AddFlags(fs *pflag.FlagSet) {
fs.BoolVar(&o.VolumeConfiguration.EnableHostPathProvisioning, "enable-hostpath-provisioner", o.VolumeConfiguration.EnableHostPathProvisioning, "Enable HostPath PV provisioning when running without a cloud provider. This allows testing and development of provisioning features. HostPath provisioning is not supported in any way, won't work in a multi-node cluster, and should not be used for anything other than testing or development.") fs.BoolVar(&o.VolumeConfiguration.EnableHostPathProvisioning, "enable-hostpath-provisioner", o.VolumeConfiguration.EnableHostPathProvisioning, "Enable HostPath PV provisioning when running without a cloud provider. This allows testing and development of provisioning features. HostPath provisioning is not supported in any way, won't work in a multi-node cluster, and should not be used for anything other than testing or development.")
fs.BoolVar(&o.VolumeConfiguration.EnableDynamicProvisioning, "enable-dynamic-provisioning", o.VolumeConfiguration.EnableDynamicProvisioning, "Enable dynamic provisioning for environments that support it.") fs.BoolVar(&o.VolumeConfiguration.EnableDynamicProvisioning, "enable-dynamic-provisioning", o.VolumeConfiguration.EnableDynamicProvisioning, "Enable dynamic provisioning for environments that support it.")
fs.StringVar(&o.VolumeConfiguration.FlexVolumePluginDir, "flex-volume-plugin-dir", o.VolumeConfiguration.FlexVolumePluginDir, "Full path of the directory in which the flex volume plugin should search for additional third party volume plugins.") fs.StringVar(&o.VolumeConfiguration.FlexVolumePluginDir, "flex-volume-plugin-dir", o.VolumeConfiguration.FlexVolumePluginDir, "Full path of the directory in which the flex volume plugin should search for additional third party volume plugins.")
fs.StringSliceVar(&o.VolumeHostCIDRDenylist, "volume-host-cidr-denylist", o.VolumeHostCIDRDenylist, "A comma-separated list of CIDR ranges to avoid from volume plugins.")
fs.BoolVar(&o.VolumeHostAllowLocalLoopback, "volume-host-allow-local-loopback", o.VolumeHostAllowLocalLoopback, "If false, deny local loopback IPs in addition to any CIDR ranges in --volume-host-cidr-denylist")
} }
// ApplyTo fills up PersistentVolumeBinderController config with options. // ApplyTo fills up PersistentVolumeBinderController config with options.
@ -53,6 +59,8 @@ func (o *PersistentVolumeBinderControllerOptions) ApplyTo(cfg *persistentvolumec
cfg.PVClaimBinderSyncPeriod = o.PVClaimBinderSyncPeriod cfg.PVClaimBinderSyncPeriod = o.PVClaimBinderSyncPeriod
cfg.VolumeConfiguration = o.VolumeConfiguration cfg.VolumeConfiguration = o.VolumeConfiguration
cfg.VolumeHostCIDRDenylist = o.VolumeHostCIDRDenylist
cfg.VolumeHostAllowLocalLoopback = o.VolumeHostAllowLocalLoopback
return nil return nil
} }
@ -64,5 +72,17 @@ func (o *PersistentVolumeBinderControllerOptions) Validate() []error {
} }
errs := []error{} errs := []error{}
if _, err := ParseVolumeHostFilters(o.VolumeHostCIDRDenylist, o.VolumeHostAllowLocalLoopback); err != nil {
errs = append(errs, fmt.Errorf("Bad --volume-host-ip-denylist/--volume-host-allow-local-loopback %w", err))
}
return errs return errs
} }
// ParseVolumeHostFilters process the --volume-host-ip-denylist and --volume-host-allow-local-loopback flags.
func ParseVolumeHostFilters(denylist []string, allowLocalLoopback bool) (*proxyutil.FilteredDialOptions, error) {
denyCIDRs, err := netutils.ParseCIDRs(denylist)
if err != nil {
return nil, err
}
return &proxyutil.FilteredDialOptions{DialHostCIDRDenylist: denyCIDRs, AllowLocalLoopback: allowLocalLoopback}, nil
}

View File

@ -123,7 +123,7 @@ func (in *KubeControllerManagerConfiguration) DeepCopyInto(out *KubeControllerMa
out.NamespaceController = in.NamespaceController out.NamespaceController = in.NamespaceController
out.NodeIPAMController = in.NodeIPAMController out.NodeIPAMController = in.NodeIPAMController
out.NodeLifecycleController = in.NodeLifecycleController out.NodeLifecycleController = in.NodeLifecycleController
out.PersistentVolumeBinderController = in.PersistentVolumeBinderController in.PersistentVolumeBinderController.DeepCopyInto(&out.PersistentVolumeBinderController)
out.PodGCController = in.PodGCController out.PodGCController = in.PodGCController
out.ReplicaSetController = in.ReplicaSetController out.ReplicaSetController = in.ReplicaSetController
out.ReplicationController = in.ReplicationController out.ReplicationController = in.ReplicationController

View File

@ -19,6 +19,7 @@ go_library(
"//pkg/controller/volume/attachdetach/util:go_default_library", "//pkg/controller/volume/attachdetach/util:go_default_library",
"//pkg/controller/volume/common:go_default_library", "//pkg/controller/volume/common:go_default_library",
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//pkg/proxy/util:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/csimigration:go_default_library", "//pkg/volume/csimigration:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",

View File

@ -55,6 +55,7 @@ import (
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/util" "k8s.io/kubernetes/pkg/controller/volume/attachdetach/util"
"k8s.io/kubernetes/pkg/controller/volume/common" "k8s.io/kubernetes/pkg/controller/volume/common"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/csimigration" "k8s.io/kubernetes/pkg/volume/csimigration"
volumeutil "k8s.io/kubernetes/pkg/volume/util" volumeutil "k8s.io/kubernetes/pkg/volume/util"
@ -117,7 +118,8 @@ func NewAttachDetachController(
prober volume.DynamicPluginProber, prober volume.DynamicPluginProber,
disableReconciliationSync bool, disableReconciliationSync bool,
reconcilerSyncDuration time.Duration, reconcilerSyncDuration time.Duration,
timerConfig TimerConfig) (AttachDetachController, error) { timerConfig TimerConfig,
filteredDialOptions *proxyutil.FilteredDialOptions) (AttachDetachController, error) {
adc := &attachDetachController{ adc := &attachDetachController{
kubeClient: kubeClient, kubeClient: kubeClient,
@ -132,6 +134,7 @@ func NewAttachDetachController(
nodesSynced: nodeInformer.Informer().HasSynced, nodesSynced: nodeInformer.Informer().HasSynced,
cloud: cloud, cloud: cloud,
pvcQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "pvcs"), pvcQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "pvcs"),
filteredDialOptions: filteredDialOptions,
} }
if utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) && if utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) &&
@ -313,6 +316,9 @@ type attachDetachController struct {
// intreeToCSITranslator translates from in-tree volume specs to CSI // intreeToCSITranslator translates from in-tree volume specs to CSI
intreeToCSITranslator csimigration.InTreeToCSITranslator intreeToCSITranslator csimigration.InTreeToCSITranslator
// filteredDialOptions configures any dialing done by the controller.
filteredDialOptions *proxyutil.FilteredDialOptions
} }
func (adc *attachDetachController) Run(stopCh <-chan struct{}) { func (adc *attachDetachController) Run(stopCh <-chan struct{}) {
@ -813,6 +819,10 @@ func (adc *attachDetachController) GetSubpather() subpath.Interface {
return nil return nil
} }
func (adc *attachDetachController) GetFilteredDialOptions() *proxyutil.FilteredDialOptions {
return adc.filteredDialOptions
}
func (adc *attachDetachController) GetCSIDriverLister() storagelistersv1.CSIDriverLister { func (adc *attachDetachController) GetCSIDriverLister() storagelistersv1.CSIDriverLister {
return adc.csiDriverLister return adc.csiDriverLister
} }

View File

@ -55,6 +55,7 @@ func Test_NewAttachDetachController_Positive(t *testing.T) {
false, false,
5*time.Second, 5*time.Second,
DefaultTimerConfig, DefaultTimerConfig,
nil, /* filteredDialOptions */
) )
// Assert // Assert
@ -175,7 +176,9 @@ func attachDetachRecoveryTestCase(t *testing.T, extraPods1 []*v1.Pod, extraPods2
prober, prober,
false, false,
1*time.Second, 1*time.Second,
DefaultTimerConfig) DefaultTimerConfig,
nil, /* filteredDialOptions */
)
if err != nil { if err != nil {
t.Fatalf("Run failed with error. Expected: <no error> Actual: <%v>", err) t.Fatalf("Run failed with error. Expected: <no error> Actual: <%v>", err)

View File

@ -9,6 +9,7 @@ go_library(
deps = [ deps = [
"//pkg/apis/core/v1/helper:go_default_library", "//pkg/apis/core/v1/helper:go_default_library",
"//pkg/controller/volume/events:go_default_library", "//pkg/controller/volume/events:go_default_library",
"//pkg/proxy/util:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/csimigration:go_default_library", "//pkg/volume/csimigration:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",

View File

@ -47,6 +47,7 @@ import (
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
"k8s.io/kubernetes/pkg/controller/volume/events" "k8s.io/kubernetes/pkg/controller/volume/events"
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/csimigration" "k8s.io/kubernetes/pkg/volume/csimigration"
"k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util"
@ -104,6 +105,8 @@ type expandController struct {
translator CSINameTranslator translator CSINameTranslator
csiMigratedPluginManager csimigration.PluginManager csiMigratedPluginManager csimigration.PluginManager
filteredDialOptions *proxyutil.FilteredDialOptions
} }
// NewExpandController expands the pvs // NewExpandController expands the pvs
@ -115,7 +118,8 @@ func NewExpandController(
cloud cloudprovider.Interface, cloud cloudprovider.Interface,
plugins []volume.VolumePlugin, plugins []volume.VolumePlugin,
translator CSINameTranslator, translator CSINameTranslator,
csiMigratedPluginManager csimigration.PluginManager) (ExpandController, error) { csiMigratedPluginManager csimigration.PluginManager,
filteredDialOptions *proxyutil.FilteredDialOptions) (ExpandController, error) {
expc := &expandController{ expc := &expandController{
kubeClient: kubeClient, kubeClient: kubeClient,
@ -129,6 +133,7 @@ func NewExpandController(
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "volume_expand"), queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "volume_expand"),
translator: translator, translator: translator,
csiMigratedPluginManager: csiMigratedPluginManager, csiMigratedPluginManager: csiMigratedPluginManager,
filteredDialOptions: filteredDialOptions,
} }
if err := expc.volumePluginMgr.InitPlugins(plugins, nil, expc); err != nil { if err := expc.volumePluginMgr.InitPlugins(plugins, nil, expc); err != nil {
@ -449,3 +454,7 @@ func (expc *expandController) GetSubpather() subpath.Interface {
// not needed for expand controller // not needed for expand controller
return nil return nil
} }
func (expc *expandController) GetFilteredDialOptions() *proxyutil.FilteredDialOptions {
return expc.filteredDialOptions
}

View File

@ -126,7 +126,7 @@ func TestSyncHandler(t *testing.T) {
informerFactory.Storage().V1().StorageClasses().Informer().GetIndexer().Add(tc.storageClass) informerFactory.Storage().V1().StorageClasses().Informer().GetIndexer().Add(tc.storageClass)
} }
translator := csitrans.New() translator := csitrans.New()
expc, err := NewExpandController(fakeKubeClient, pvcInformer, pvInformer, storageClassInformer, nil, allPlugins, translator, csimigration.NewPluginManager(translator)) expc, err := NewExpandController(fakeKubeClient, pvcInformer, pvInformer, storageClassInformer, nil, allPlugins, translator, csimigration.NewPluginManager(translator), nil)
if err != nil { if err != nil {
t.Fatalf("error creating expand controller : %v", err) t.Fatalf("error creating expand controller : %v", err)
} }

View File

@ -23,6 +23,7 @@ go_library(
"//pkg/controller/volume/persistentvolume/metrics:go_default_library", "//pkg/controller/volume/persistentvolume/metrics:go_default_library",
"//pkg/controller/volume/persistentvolume/util:go_default_library", "//pkg/controller/volume/persistentvolume/util:go_default_library",
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//pkg/proxy/util:go_default_library",
"//pkg/util/goroutinemap:go_default_library", "//pkg/util/goroutinemap:go_default_library",
"//pkg/util/goroutinemap/exponentialbackoff:go_default_library", "//pkg/util/goroutinemap/exponentialbackoff:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",

View File

@ -28,6 +28,12 @@ type PersistentVolumeBinderControllerConfiguration struct {
PVClaimBinderSyncPeriod metav1.Duration PVClaimBinderSyncPeriod metav1.Duration
// volumeConfiguration holds configuration for volume related features. // volumeConfiguration holds configuration for volume related features.
VolumeConfiguration VolumeConfiguration VolumeConfiguration VolumeConfiguration
// VolumeHostCIDRDenylist is a list of CIDRs that should not be reachable by the
// controller from plugins.
VolumeHostCIDRDenylist []string
// VolumeHostAllowLocalLoopback indicates if local loopback hosts (127.0.0.1, etc)
// should be allowed from plugins.
VolumeHostAllowLocalLoopback bool
} }
// VolumeConfiguration contains *all* enumerated flags meant to configure all volume // VolumeConfiguration contains *all* enumerated flags meant to configure all volume

View File

@ -39,6 +39,11 @@ func RecommendedDefaultPersistentVolumeBinderControllerConfiguration(obj *kubect
obj.PVClaimBinderSyncPeriod = metav1.Duration{Duration: 15 * time.Second} obj.PVClaimBinderSyncPeriod = metav1.Duration{Duration: 15 * time.Second}
} }
if obj.VolumeHostAllowLocalLoopback == nil {
trueValue := true
obj.VolumeHostAllowLocalLoopback = &trueValue
}
// Use the default VolumeConfiguration options. // Use the default VolumeConfiguration options.
RecommendedDefaultVolumeConfiguration(&obj.VolumeConfiguration) RecommendedDefaultVolumeConfiguration(&obj.VolumeConfiguration)
} }

View File

@ -21,6 +21,8 @@ limitations under the License.
package v1alpha1 package v1alpha1
import ( import (
unsafe "unsafe"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion" conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime" runtime "k8s.io/apimachinery/pkg/runtime"
@ -105,6 +107,10 @@ func autoConvert_v1alpha1_PersistentVolumeBinderControllerConfiguration_To_confi
if err := Convert_v1alpha1_VolumeConfiguration_To_config_VolumeConfiguration(&in.VolumeConfiguration, &out.VolumeConfiguration, s); err != nil { if err := Convert_v1alpha1_VolumeConfiguration_To_config_VolumeConfiguration(&in.VolumeConfiguration, &out.VolumeConfiguration, s); err != nil {
return err return err
} }
out.VolumeHostCIDRDenylist = *(*[]string)(unsafe.Pointer(&in.VolumeHostCIDRDenylist))
if err := v1.Convert_Pointer_bool_To_bool(&in.VolumeHostAllowLocalLoopback, &out.VolumeHostAllowLocalLoopback, s); err != nil {
return err
}
return nil return nil
} }
@ -113,6 +119,10 @@ func autoConvert_config_PersistentVolumeBinderControllerConfiguration_To_v1alpha
if err := Convert_config_VolumeConfiguration_To_v1alpha1_VolumeConfiguration(&in.VolumeConfiguration, &out.VolumeConfiguration, s); err != nil { if err := Convert_config_VolumeConfiguration_To_v1alpha1_VolumeConfiguration(&in.VolumeConfiguration, &out.VolumeConfiguration, s); err != nil {
return err return err
} }
out.VolumeHostCIDRDenylist = *(*[]string)(unsafe.Pointer(&in.VolumeHostCIDRDenylist))
if err := v1.Convert_bool_To_Pointer_bool(&in.VolumeHostAllowLocalLoopback, &out.VolumeHostAllowLocalLoopback, s); err != nil {
return err
}
return nil return nil
} }

View File

@ -25,6 +25,11 @@ func (in *PersistentVolumeBinderControllerConfiguration) DeepCopyInto(out *Persi
*out = *in *out = *in
out.PVClaimBinderSyncPeriod = in.PVClaimBinderSyncPeriod out.PVClaimBinderSyncPeriod = in.PVClaimBinderSyncPeriod
out.VolumeConfiguration = in.VolumeConfiguration out.VolumeConfiguration = in.VolumeConfiguration
if in.VolumeHostCIDRDenylist != nil {
in, out := &in.VolumeHostCIDRDenylist, &out.VolumeHostCIDRDenylist
*out = make([]string, len(*in))
copy(*out, *in)
}
return return
} }

View File

@ -45,6 +45,7 @@ import (
"k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics" "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics"
pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util" pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
"k8s.io/kubernetes/pkg/util/goroutinemap" "k8s.io/kubernetes/pkg/util/goroutinemap"
"k8s.io/kubernetes/pkg/util/goroutinemap/exponentialbackoff" "k8s.io/kubernetes/pkg/util/goroutinemap/exponentialbackoff"
vol "k8s.io/kubernetes/pkg/volume" vol "k8s.io/kubernetes/pkg/volume"
@ -235,6 +236,9 @@ type PersistentVolumeController struct {
translator CSINameTranslator translator CSINameTranslator
csiMigratedPluginManager CSIMigratedPluginManager csiMigratedPluginManager CSIMigratedPluginManager
// filteredDialOptions configures any dialing done by the controller.
filteredDialOptions *proxyutil.FilteredDialOptions
} }
// syncClaim is the main controller method to decide what to do with a claim. // syncClaim is the main controller method to decide what to do with a claim.

View File

@ -44,6 +44,7 @@ import (
"k8s.io/kubernetes/pkg/controller/volume/common" "k8s.io/kubernetes/pkg/controller/volume/common"
"k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics" "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics"
pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util" pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util"
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
"k8s.io/kubernetes/pkg/util/goroutinemap" "k8s.io/kubernetes/pkg/util/goroutinemap"
vol "k8s.io/kubernetes/pkg/volume" vol "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/csimigration" "k8s.io/kubernetes/pkg/volume/csimigration"
@ -70,6 +71,7 @@ type ControllerParameters struct {
NodeInformer coreinformers.NodeInformer NodeInformer coreinformers.NodeInformer
EventRecorder record.EventRecorder EventRecorder record.EventRecorder
EnableDynamicProvisioning bool EnableDynamicProvisioning bool
FilteredDialOptions *proxyutil.FilteredDialOptions
} }
// NewController creates a new PersistentVolume controller // NewController creates a new PersistentVolume controller
@ -142,6 +144,8 @@ func NewController(p ControllerParameters) (*PersistentVolumeController, error)
controller.translator = csiTranslator controller.translator = csiTranslator
controller.csiMigratedPluginManager = csimigration.NewPluginManager(csiTranslator) controller.csiMigratedPluginManager = csimigration.NewPluginManager(csiTranslator)
controller.filteredDialOptions = p.FilteredDialOptions
return controller, nil return controller, nil
} }

View File

@ -30,6 +30,7 @@ import (
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
vol "k8s.io/kubernetes/pkg/volume" vol "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util/subpath" "k8s.io/kubernetes/pkg/volume/util/subpath"
) )
@ -138,3 +139,7 @@ func (ctrl *PersistentVolumeController) GetSubpather() subpath.Interface {
// No volume plugin needs Subpaths in PV controller. // No volume plugin needs Subpaths in PV controller.
return nil return nil
} }
func (ctrl *PersistentVolumeController) GetFilteredDialOptions() *proxyutil.FilteredDialOptions {
return ctrl.filteredDialOptions
}

View File

@ -98,6 +98,7 @@ go_library(
"//pkg/kubelet/util/queue:go_default_library", "//pkg/kubelet/util/queue:go_default_library",
"//pkg/kubelet/util/sliceutils:go_default_library", "//pkg/kubelet/util/sliceutils:go_default_library",
"//pkg/kubelet/volumemanager:go_default_library", "//pkg/kubelet/volumemanager:go_default_library",
"//pkg/proxy/util:go_default_library",
"//pkg/security/apparmor:go_default_library", "//pkg/security/apparmor:go_default_library",
"//pkg/security/podsecuritypolicy/sysctl:go_default_library", "//pkg/security/podsecuritypolicy/sysctl:go_default_library",
"//pkg/util/iptables:go_default_library", "//pkg/util/iptables:go_default_library",

View File

@ -38,6 +38,7 @@ import (
"k8s.io/kubernetes/pkg/kubelet/configmap" "k8s.io/kubernetes/pkg/kubelet/configmap"
"k8s.io/kubernetes/pkg/kubelet/secret" "k8s.io/kubernetes/pkg/kubelet/secret"
"k8s.io/kubernetes/pkg/kubelet/token" "k8s.io/kubernetes/pkg/kubelet/token"
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util"
"k8s.io/kubernetes/pkg/volume/util/hostutil" "k8s.io/kubernetes/pkg/volume/util/hostutil"
@ -151,6 +152,11 @@ func (kvh *kubeletVolumeHost) GetSubpather() subpath.Interface {
return kvh.kubelet.subpather return kvh.kubelet.subpather
} }
func (kvh *kubeletVolumeHost) GetFilteredDialOptions() *proxyutil.FilteredDialOptions {
// FilteredDial is not needed in the kubelet.
return nil
}
func (kvh *kubeletVolumeHost) GetHostUtil() hostutil.HostUtils { func (kvh *kubeletVolumeHost) GetHostUtil() hostutil.HostUtils {
return kvh.kubelet.hostutil return kvh.kubelet.hostutil
} }

View File

@ -21,6 +21,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"net/http"
"strconv" "strconv"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
@ -124,6 +125,16 @@ func IsProxyableHostname(ctx context.Context, resolv Resolver, hostname string)
return nil return nil
} }
// IsAllowedHost checks if the given IP host address is in a network in the denied list.
func IsAllowedHost(host net.IP, denied []*net.IPNet) error {
for _, ipNet := range denied {
if ipNet.Contains(host) {
return ErrAddressNotAllowed
}
}
return nil
}
// GetLocalAddrs returns a list of all network addresses on the local system // GetLocalAddrs returns a list of all network addresses on the local system
func GetLocalAddrs() ([]net.IP, error) { func GetLocalAddrs() ([]net.IP, error) {
var localAddrs []net.IP var localAddrs []net.IP
@ -311,3 +322,57 @@ func EnsureSysctl(sysctl utilsysctl.Interface, name string, newVal int) error {
} }
return nil return nil
} }
// DialContext is a dial function matching the signature of net.Dialer.DialContext.
type DialContext = func(context.Context, string, string) (net.Conn, error)
// FilteredDialOptions configures how a DialContext is wrapped by NewFilteredDialContext.
type FilteredDialOptions struct {
// DialHostIPDenylist restricts hosts from being dialed.
DialHostCIDRDenylist []*net.IPNet
// AllowLocalLoopback controls connections to local loopback hosts (as defined by
// IsProxyableIP).
AllowLocalLoopback bool
}
// NewFilteredDialContext returns a DialContext function that filters connections based on a FilteredDialOptions.
func NewFilteredDialContext(wrapped DialContext, resolv Resolver, opts *FilteredDialOptions) DialContext {
if wrapped == nil {
wrapped = http.DefaultTransport.(*http.Transport).DialContext
}
if opts == nil {
// Do no filtering
return wrapped
}
if resolv == nil {
resolv = net.DefaultResolver
}
if len(opts.DialHostCIDRDenylist) == 0 && opts.AllowLocalLoopback {
// Do no filtering.
return wrapped
}
return func(ctx context.Context, network, address string) (net.Conn, error) {
resp, err := resolv.LookupIPAddr(ctx, address)
if err != nil {
return nil, err
}
if len(resp) == 0 {
return nil, ErrNoAddresses
}
for _, host := range resp {
if !opts.AllowLocalLoopback {
if err := isProxyableIP(host.IP); err != nil {
return nil, err
}
}
if opts.DialHostCIDRDenylist != nil {
if err := IsAllowedHost(host.IP, opts.DialHostCIDRDenylist); err != nil {
return nil, err
}
}
}
return wrapped(ctx, network, address)
}
}

View File

@ -163,6 +163,39 @@ func TestIsProxyableHostname(t *testing.T) {
} }
} }
func TestIsAllowedHost(t *testing.T) {
testCases := []struct {
ip string
denied []string
want error
}{
{"8.8.8.8", []string{}, nil},
{"169.254.169.254", []string{"169.0.0.0/8"}, ErrAddressNotAllowed},
{"169.254.169.254", []string{"fce8::/15", "169.254.169.0/24"}, ErrAddressNotAllowed},
{"fce9:beef::", []string{"fce8::/15", "169.254.169.0/24"}, ErrAddressNotAllowed},
{"127.0.0.1", []string{"127.0.0.1/32"}, ErrAddressNotAllowed},
{"34.107.204.206", []string{"fce8::/15"}, nil},
{"fce9:beef::", []string{"127.0.0.1/32"}, nil},
{"34.107.204.206", []string{"127.0.0.1/32"}, nil},
{"127.0.0.1", []string{}, nil},
}
for i := range testCases {
var denyList []*net.IPNet
for _, cidrStr := range testCases[i].denied {
_, ipNet, err := net.ParseCIDR(cidrStr)
if err != nil {
t.Fatalf("bad IP for test case: %v: %v", cidrStr, err)
}
denyList = append(denyList, ipNet)
}
got := IsAllowedHost(net.ParseIP(testCases[i].ip), denyList)
if testCases[i].want != got {
t.Errorf("case %d: expected %v, got %v", i, testCases[i].want, got)
}
}
}
func TestShouldSkipService(t *testing.T) { func TestShouldSkipService(t *testing.T) {
testCases := []struct { testCases := []struct {
service *v1.Service service *v1.Service

View File

@ -18,6 +18,7 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/volume", importpath = "k8s.io/kubernetes/pkg/volume",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//pkg/proxy/util:go_default_library",
"//pkg/volume/util/fs:go_default_library", "//pkg/volume/util/fs:go_default_library",
"//pkg/volume/util/hostutil:go_default_library", "//pkg/volume/util/hostutil:go_default_library",
"//pkg/volume/util/recyclerclient:go_default_library", "//pkg/volume/util/recyclerclient:go_default_library",

View File

@ -39,6 +39,7 @@ import (
"k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
"k8s.io/kubernetes/pkg/volume/util/hostutil" "k8s.io/kubernetes/pkg/volume/util/hostutil"
"k8s.io/kubernetes/pkg/volume/util/recyclerclient" "k8s.io/kubernetes/pkg/volume/util/recyclerclient"
"k8s.io/kubernetes/pkg/volume/util/subpath" "k8s.io/kubernetes/pkg/volume/util/subpath"
@ -450,6 +451,9 @@ type VolumeHost interface {
// Returns an interface that should be used to execute subpath operations // Returns an interface that should be used to execute subpath operations
GetSubpather() subpath.Interface GetSubpather() subpath.Interface
// Returns options to pass for proxyutil filtered dialers.
GetFilteredDialOptions() *proxyutil.FilteredDialOptions
} }
// VolumePluginMgr tracks registered plugins. // VolumePluginMgr tracks registered plugins.

View File

@ -41,6 +41,7 @@ go_library(
], ],
importpath = "k8s.io/kubernetes/pkg/volume/scaleio", importpath = "k8s.io/kubernetes/pkg/volume/scaleio",
deps = [ deps = [
"//pkg/proxy/util:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",

View File

@ -20,6 +20,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
@ -33,6 +34,7 @@ import (
sio "github.com/thecodeteam/goscaleio" sio "github.com/thecodeteam/goscaleio"
siotypes "github.com/thecodeteam/goscaleio/types/v1" siotypes "github.com/thecodeteam/goscaleio/types/v1"
"k8s.io/klog/v2" "k8s.io/klog/v2"
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
) )
var ( var (
@ -79,14 +81,16 @@ type sioClient struct {
diskRegex *regexp.Regexp diskRegex *regexp.Regexp
mtx sync.Mutex mtx sync.Mutex
exec utilexec.Interface exec utilexec.Interface
filteredDialOptions *proxyutil.FilteredDialOptions
} }
func newSioClient(gateway, username, password string, sslEnabled bool, exec utilexec.Interface) (*sioClient, error) { func newSioClient(gateway, username, password string, sslEnabled bool, exec utilexec.Interface, filteredDialOptions *proxyutil.FilteredDialOptions) (*sioClient, error) {
client := new(sioClient) client := new(sioClient)
client.gateway = gateway client.gateway = gateway
client.username = username client.username = username
client.password = password client.password = password
client.exec = exec client.exec = exec
client.filteredDialOptions = filteredDialOptions
if sslEnabled { if sslEnabled {
client.insecure = false client.insecure = false
client.certsEnabled = true client.certsEnabled = true
@ -118,6 +122,15 @@ func (c *sioClient) init() error {
klog.Error(log("failed to create client: %v", err)) klog.Error(log("failed to create client: %v", err))
return err return err
} }
transport, ok := client.Http.Transport.(*http.Transport)
if !ok {
return errors.New("could not set http.Transport options for scaleio client")
}
//lint:ignore SA1019 DialTLS must be used to support legacy clients.
if transport.DialTLS != nil {
return errors.New("DialTLS will be used instead of DialContext")
}
transport.DialContext = proxyutil.NewFilteredDialContext(transport.DialContext, nil, c.filteredDialOptions)
c.client = client c.client = client
if _, err = c.client.Authenticate( if _, err = c.client.Authenticate(
&sio.ConfigConnect{ &sio.ConfigConnect{

View File

@ -21,6 +21,7 @@ import (
"strconv" "strconv"
"k8s.io/klog/v2" "k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/volume"
utilexec "k8s.io/utils/exec" utilexec "k8s.io/utils/exec"
siotypes "github.com/thecodeteam/goscaleio/types/v1" siotypes "github.com/thecodeteam/goscaleio/types/v1"
@ -30,9 +31,10 @@ type sioMgr struct {
client sioInterface client sioInterface
configData map[string]string configData map[string]string
exec utilexec.Interface exec utilexec.Interface
host volume.VolumeHost
} }
func newSioMgr(configs map[string]string, exec utilexec.Interface) (*sioMgr, error) { func newSioMgr(configs map[string]string, host volume.VolumeHost, exec utilexec.Interface) (*sioMgr, error) {
if configs == nil { if configs == nil {
return nil, errors.New("missing configuration data") return nil, errors.New("missing configuration data")
} }
@ -41,7 +43,7 @@ func newSioMgr(configs map[string]string, exec utilexec.Interface) (*sioMgr, err
configs[confKey.sdcRootPath] = defaultString(configs[confKey.sdcRootPath], sdcRootPath) configs[confKey.sdcRootPath] = defaultString(configs[confKey.sdcRootPath], sdcRootPath)
configs[confKey.storageMode] = defaultString(configs[confKey.storageMode], "ThinProvisioned") configs[confKey.storageMode] = defaultString(configs[confKey.storageMode], "ThinProvisioned")
mgr := &sioMgr{configData: configs, exec: exec} mgr := &sioMgr{configData: configs, host: host, exec: exec}
return mgr, nil return mgr, nil
} }
@ -61,7 +63,7 @@ func (m *sioMgr) getClient() (sioInterface, error) {
certsEnabled := b certsEnabled := b
klog.V(4).Info(log("creating new client for gateway %s", gateway)) klog.V(4).Info(log("creating new client for gateway %s", gateway))
client, err := newSioClient(gateway, username, password, certsEnabled, m.exec) client, err := newSioClient(gateway, username, password, certsEnabled, m.exec, m.host.GetFilteredDialOptions())
if err != nil { if err != nil {
klog.Error(log("failed to create scaleio client: %v", err)) klog.Error(log("failed to create scaleio client: %v", err))
return nil, err return nil, err

View File

@ -22,6 +22,7 @@ import (
"time" "time"
siotypes "github.com/thecodeteam/goscaleio/types/v1" siotypes "github.com/thecodeteam/goscaleio/types/v1"
volumetesting "k8s.io/kubernetes/pkg/volume/testing"
"k8s.io/utils/exec/testing" "k8s.io/utils/exec/testing"
) )
@ -42,7 +43,8 @@ var (
) )
func newTestMgr(t *testing.T) *sioMgr { func newTestMgr(t *testing.T) *sioMgr {
mgr, err := newSioMgr(fakeConfig, &testingexec.FakeExec{}) host := volumetesting.NewFakeVolumeHost(t, "/tmp/fake", nil, nil)
mgr, err := newSioMgr(fakeConfig, host, &testingexec.FakeExec{})
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -51,7 +53,8 @@ func newTestMgr(t *testing.T) *sioMgr {
} }
func TestMgrNew(t *testing.T) { func TestMgrNew(t *testing.T) {
mgr, err := newSioMgr(fakeConfig, &testingexec.FakeExec{}) host := volumetesting.NewFakeVolumeHost(t, "/tmp/fake", nil, nil)
mgr, err := newSioMgr(fakeConfig, host, &testingexec.FakeExec{})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -405,7 +405,7 @@ func (v *sioVolume) setSioMgr() error {
klog.Error(log("failed to retrieve sdc guid: %v", err)) klog.Error(log("failed to retrieve sdc guid: %v", err))
return err return err
} }
mgr, err := newSioMgr(configData, v.plugin.host.GetExec(v.plugin.GetPluginName())) mgr, err := newSioMgr(configData, v.plugin.host, v.plugin.host.GetExec(v.plugin.GetPluginName()))
if err != nil { if err != nil {
klog.Error(log("failed to reset sio manager: %v", err)) klog.Error(log("failed to reset sio manager: %v", err))
@ -444,8 +444,7 @@ func (v *sioVolume) resetSioMgr() error {
klog.Error(log("failed to retrieve sdc guid: %v", err)) klog.Error(log("failed to retrieve sdc guid: %v", err))
return err return err
} }
mgr, err := newSioMgr(configData, v.plugin.host, v.plugin.host.GetExec(v.plugin.GetPluginName()))
mgr, err := newSioMgr(configData, v.plugin.host.GetExec(v.plugin.GetPluginName()))
if err != nil { if err != nil {
klog.Error(log("failed to reset scaleio mgr: %v", err)) klog.Error(log("failed to reset scaleio mgr: %v", err))
@ -480,8 +479,7 @@ func (v *sioVolume) setSioMgrFromConfig() error {
klog.Error(log("failed to load secret: %v", err)) klog.Error(log("failed to load secret: %v", err))
return err return err
} }
mgr, err := newSioMgr(data, v.plugin.host, v.plugin.host.GetExec(v.plugin.GetPluginName()))
mgr, err := newSioMgr(data, v.plugin.host.GetExec(v.plugin.GetPluginName()))
if err != nil { if err != nil {
klog.Error(log("failed while setting scaleio mgr from config: %v", err)) klog.Error(log("failed while setting scaleio mgr from config: %v", err))
@ -516,8 +514,7 @@ func (v *sioVolume) setSioMgrFromSpec() error {
klog.Error(log("failed to load secret: %v", err)) klog.Error(log("failed to load secret: %v", err))
return err return err
} }
mgr, err := newSioMgr(configData, v.plugin.host, v.plugin.host.GetExec(v.plugin.GetPluginName()))
mgr, err := newSioMgr(configData, v.plugin.host.GetExec(v.plugin.GetPluginName()))
if err != nil { if err != nil {
klog.Error(log("failed to reset sio manager: %v", err)) klog.Error(log("failed to reset sio manager: %v", err))

View File

@ -15,6 +15,7 @@ go_library(
], ],
importpath = "k8s.io/kubernetes/pkg/volume/storageos", importpath = "k8s.io/kubernetes/pkg/volume/storageos",
deps = [ deps = [
"//pkg/proxy/util:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",

View File

@ -110,7 +110,7 @@ func (plugin *storageosPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volu
return nil, err return nil, err
} }
return plugin.newMounterInternal(spec, pod, apiCfg, &storageosUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName())) return plugin.newMounterInternal(spec, pod, apiCfg, &storageosUtil{host: plugin.host}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
} }
func (plugin *storageosPlugin) newMounterInternal(spec *volume.Spec, pod *v1.Pod, apiCfg *storageosAPIConfig, manager storageosManager, mounter mount.Interface, exec utilexec.Interface) (volume.Mounter, error) { func (plugin *storageosPlugin) newMounterInternal(spec *volume.Spec, pod *v1.Pod, apiCfg *storageosAPIConfig, manager storageosManager, mounter mount.Interface, exec utilexec.Interface) (volume.Mounter, error) {
@ -142,7 +142,7 @@ func (plugin *storageosPlugin) newMounterInternal(spec *volume.Spec, pod *v1.Pod
} }
func (plugin *storageosPlugin) NewUnmounter(pvName string, podUID types.UID) (volume.Unmounter, error) { func (plugin *storageosPlugin) NewUnmounter(pvName string, podUID types.UID) (volume.Unmounter, error) {
return plugin.newUnmounterInternal(pvName, podUID, &storageosUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName())) return plugin.newUnmounterInternal(pvName, podUID, &storageosUtil{host: plugin.host}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
} }
func (plugin *storageosPlugin) newUnmounterInternal(pvName string, podUID types.UID, manager storageosManager, mounter mount.Interface, exec utilexec.Interface) (volume.Unmounter, error) { func (plugin *storageosPlugin) newUnmounterInternal(pvName string, podUID types.UID, manager storageosManager, mounter mount.Interface, exec utilexec.Interface) (volume.Unmounter, error) {
@ -194,7 +194,7 @@ func (plugin *storageosPlugin) NewDeleter(spec *volume.Spec) (volume.Deleter, er
return nil, fmt.Errorf("failed to get admin secret from [%q/%q]: %v", adminSecretNamespace, adminSecretName, err) return nil, fmt.Errorf("failed to get admin secret from [%q/%q]: %v", adminSecretNamespace, adminSecretName, err)
} }
return plugin.newDeleterInternal(spec, apiCfg, &storageosUtil{}) return plugin.newDeleterInternal(spec, apiCfg, &storageosUtil{host: plugin.host})
} }
func (plugin *storageosPlugin) newDeleterInternal(spec *volume.Spec, apiCfg *storageosAPIConfig, manager storageosManager) (volume.Deleter, error) { func (plugin *storageosPlugin) newDeleterInternal(spec *volume.Spec, apiCfg *storageosAPIConfig, manager storageosManager) (volume.Deleter, error) {
@ -215,7 +215,7 @@ func (plugin *storageosPlugin) newDeleterInternal(spec *volume.Spec, apiCfg *sto
} }
func (plugin *storageosPlugin) NewProvisioner(options volume.VolumeOptions) (volume.Provisioner, error) { func (plugin *storageosPlugin) NewProvisioner(options volume.VolumeOptions) (volume.Provisioner, error) {
return plugin.newProvisionerInternal(options, &storageosUtil{}) return plugin.newProvisionerInternal(options, &storageosUtil{host: plugin.host})
} }
func (plugin *storageosPlugin) newProvisionerInternal(options volume.VolumeOptions, manager storageosManager) (volume.Provisioner, error) { func (plugin *storageosPlugin) newProvisionerInternal(options volume.VolumeOptions, manager storageosManager) (volume.Provisioner, error) {

View File

@ -26,6 +26,8 @@ import (
storageosapi "github.com/storageos/go-api" storageosapi "github.com/storageos/go-api"
storageostypes "github.com/storageos/go-api/types" storageostypes "github.com/storageos/go-api/types"
"k8s.io/klog/v2" "k8s.io/klog/v2"
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
"k8s.io/kubernetes/pkg/volume"
utilexec "k8s.io/utils/exec" utilexec "k8s.io/utils/exec"
) )
@ -77,12 +79,16 @@ type apiImplementer interface {
// storageosUtil is the utility structure to interact with the StorageOS API. // storageosUtil is the utility structure to interact with the StorageOS API.
type storageosUtil struct { type storageosUtil struct {
api apiImplementer api apiImplementer
host volume.VolumeHost
} }
func (u *storageosUtil) NewAPI(apiCfg *storageosAPIConfig) error { func (u *storageosUtil) NewAPI(apiCfg *storageosAPIConfig) error {
if u.api != nil { if u.api != nil {
return nil return nil
} }
if u.host == nil {
return errors.New("host must not be nil")
}
if apiCfg == nil { if apiCfg == nil {
apiCfg = &storageosAPIConfig{ apiCfg = &storageosAPIConfig{
apiAddr: defaultAPIAddress, apiAddr: defaultAPIAddress,
@ -98,6 +104,9 @@ func (u *storageosUtil) NewAPI(apiCfg *storageosAPIConfig) error {
return err return err
} }
api.SetAuth(apiCfg.apiUser, apiCfg.apiPass) api.SetAuth(apiCfg.apiUser, apiCfg.apiPass)
if err := api.SetDialContext(proxyutil.NewFilteredDialContext(api.GetDialContext(), nil, u.host.GetFilteredDialOptions())); err != nil {
return fmt.Errorf("failed to set DialContext in storageos client: %v", err)
}
u.api = api u.api = api
return nil return nil
} }

View File

@ -49,8 +49,12 @@ func GetAPIConfig() *storageosAPIConfig {
} }
func TestClient(t *testing.T) { func TestClient(t *testing.T) {
util := storageosUtil{} tmpDir, err := utiltesting.MkTmpdir("storageos_test")
err := util.NewAPI(GetAPIConfig()) if err != nil {
t.Fatalf("error creating tmpdir: %v", err)
}
util := storageosUtil{host: volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil)}
err = util.NewAPI(GetAPIConfig())
if err != nil { if err != nil {
t.Fatalf("error getting api config: %v", err) t.Fatalf("error getting api config: %v", err)
} }

View File

@ -13,6 +13,7 @@ go_library(
], ],
importpath = "k8s.io/kubernetes/pkg/volume/testing", importpath = "k8s.io/kubernetes/pkg/volume/testing",
deps = [ deps = [
"//pkg/proxy/util:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//pkg/volume/util/hostutil:go_default_library", "//pkg/volume/util/hostutil:go_default_library",

View File

@ -46,6 +46,7 @@ import (
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
utiltesting "k8s.io/client-go/util/testing" utiltesting "k8s.io/client-go/util/testing"
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
. "k8s.io/kubernetes/pkg/volume" . "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util"
"k8s.io/kubernetes/pkg/volume/util/hostutil" "k8s.io/kubernetes/pkg/volume/util/hostutil"
@ -118,6 +119,7 @@ type fakeVolumeHost struct {
informerFactory informers.SharedInformerFactory informerFactory informers.SharedInformerFactory
kubeletErr error kubeletErr error
mux sync.Mutex mux sync.Mutex
filteredDialOptions *proxyutil.FilteredDialOptions
} }
var _ VolumeHost = &fakeVolumeHost{} var _ VolumeHost = &fakeVolumeHost{}
@ -207,6 +209,10 @@ func (f *fakeVolumeHost) GetSubpather() subpath.Interface {
return f.subpather return f.subpather
} }
func (f *fakeVolumeHost) GetFilteredDialOptions() *proxyutil.FilteredDialOptions {
return f.filteredDialOptions
}
func (f *fakeVolumeHost) GetPluginMgr() *VolumePluginMgr { func (f *fakeVolumeHost) GetPluginMgr() *VolumePluginMgr {
return f.pluginMgr return f.pluginMgr
} }

View File

@ -471,6 +471,12 @@ type PersistentVolumeBinderControllerConfiguration struct {
PVClaimBinderSyncPeriod metav1.Duration PVClaimBinderSyncPeriod metav1.Duration
// volumeConfiguration holds configuration for volume related features. // volumeConfiguration holds configuration for volume related features.
VolumeConfiguration VolumeConfiguration VolumeConfiguration VolumeConfiguration
// VolumeHostCIDRDenylist is a list of CIDRs that should not be reachable by the
// controller from plugins.
VolumeHostCIDRDenylist []string
// VolumeHostAllowLocalLoopback indicates if local loopback hosts (127.0.0.1, etc)
// should be allowed from plugins.
VolumeHostAllowLocalLoopback *bool
} }
// PodGCControllerConfiguration contains elements describing PodGCController. // PodGCControllerConfiguration contains elements describing PodGCController.

View File

@ -442,6 +442,16 @@ func (in *PersistentVolumeBinderControllerConfiguration) DeepCopyInto(out *Persi
*out = *in *out = *in
out.PVClaimBinderSyncPeriod = in.PVClaimBinderSyncPeriod out.PVClaimBinderSyncPeriod = in.PVClaimBinderSyncPeriod
in.VolumeConfiguration.DeepCopyInto(&out.VolumeConfiguration) in.VolumeConfiguration.DeepCopyInto(&out.VolumeConfiguration)
if in.VolumeHostCIDRDenylist != nil {
in, out := &in.VolumeHostCIDRDenylist, &out.VolumeHostCIDRDenylist
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.VolumeHostAllowLocalLoopback != nil {
in, out := &in.VolumeHostAllowLocalLoopback, &out.VolumeHostAllowLocalLoopback
*out = new(bool)
**out = **in
}
return return
} }

View File

@ -35,9 +35,6 @@ go_library(
"@io_bazel_rules_go//go/platform:freebsd": [ "@io_bazel_rules_go//go/platform:freebsd": [
"//vendor/k8s.io/utils/io:go_default_library", "//vendor/k8s.io/utils/io:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:illumos": [
"//vendor/k8s.io/utils/io:go_default_library",
],
"@io_bazel_rules_go//go/platform:ios": [ "@io_bazel_rules_go//go/platform:ios": [
"//vendor/k8s.io/utils/io:go_default_library", "//vendor/k8s.io/utils/io:go_default_library",
], ],

View File

@ -438,7 +438,9 @@ func createAdClients(ns *v1.Namespace, t *testing.T, server *httptest.Server, sy
nil, /* prober */ nil, /* prober */
false, false,
5*time.Second, 5*time.Second,
timers) timers,
nil, /* filteredDialOptions */
)
if err != nil { if err != nil {
t.Fatalf("Error creating AttachDetach : %v", err) t.Fatalf("Error creating AttachDetach : %v", err)