github.com/openshift/installer@v1.4.17/pkg/asset/manifests/proxy.go (about)

     1  package manifests
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/url"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/pkg/errors"
    11  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    12  	"k8s.io/apimachinery/pkg/util/sets"
    13  	"sigs.k8s.io/yaml"
    14  
    15  	configv1 "github.com/openshift/api/config/v1"
    16  	"github.com/openshift/installer/pkg/asset"
    17  	"github.com/openshift/installer/pkg/asset/installconfig"
    18  	"github.com/openshift/installer/pkg/types"
    19  	"github.com/openshift/installer/pkg/types/aws"
    20  	"github.com/openshift/installer/pkg/types/azure"
    21  	"github.com/openshift/installer/pkg/types/gcp"
    22  	"github.com/openshift/installer/pkg/types/openstack"
    23  )
    24  
    25  var proxyCfgFilename = filepath.Join(manifestDir, "cluster-proxy-01-config.yaml")
    26  
    27  // Proxy generates the cluster-proxy-*.yml files.
    28  type Proxy struct {
    29  	FileList []*asset.File
    30  	Config   *configv1.Proxy
    31  }
    32  
    33  var _ asset.WritableAsset = (*Proxy)(nil)
    34  
    35  // Name returns a human-friendly name for the asset.
    36  func (*Proxy) Name() string {
    37  	return "Proxy Config"
    38  }
    39  
    40  // Dependencies returns all of the dependencies directly needed to generate
    41  // the asset.
    42  func (*Proxy) Dependencies() []asset.Asset {
    43  	return []asset.Asset{
    44  		&installconfig.InstallConfig{},
    45  		&Networking{},
    46  	}
    47  }
    48  
    49  // Generate generates the Proxy config and its CRD.
    50  func (p *Proxy) Generate(_ context.Context, dependencies asset.Parents) error {
    51  	installConfig := &installconfig.InstallConfig{}
    52  	network := &Networking{}
    53  	dependencies.Get(installConfig, network)
    54  
    55  	p.Config = &configv1.Proxy{
    56  		TypeMeta: metav1.TypeMeta{
    57  			APIVersion: configv1.SchemeGroupVersion.String(),
    58  			Kind:       "Proxy",
    59  		},
    60  		ObjectMeta: metav1.ObjectMeta{
    61  			Name: "cluster",
    62  			// not namespaced
    63  		},
    64  	}
    65  
    66  	if installConfig.Config.Proxy != nil {
    67  		p.Config.Spec = configv1.ProxySpec{
    68  			HTTPProxy:  installConfig.Config.Proxy.HTTPProxy,
    69  			HTTPSProxy: installConfig.Config.Proxy.HTTPSProxy,
    70  			NoProxy:    installConfig.Config.Proxy.NoProxy,
    71  		}
    72  	}
    73  
    74  	if installConfig.Config.AdditionalTrustBundlePolicy == types.PolicyAlways ||
    75  		installConfig.Config.Proxy != nil {
    76  		if installConfig.Config.AdditionalTrustBundle != "" {
    77  			p.Config.Spec.TrustedCA = configv1.ConfigMapNameReference{
    78  				Name: additionalTrustBundleConfigMapName,
    79  			}
    80  		}
    81  	}
    82  
    83  	if p.Config.Spec.HTTPProxy != "" || p.Config.Spec.HTTPSProxy != "" {
    84  		noProxy, err := createNoProxy(installConfig, network)
    85  		if err != nil {
    86  			return err
    87  		}
    88  		if installConfig.Config.Proxy.NoProxy == "*" {
    89  			noProxy = installConfig.Config.Proxy.NoProxy
    90  		}
    91  		p.Config.Status = configv1.ProxyStatus{
    92  			HTTPProxy:  installConfig.Config.Proxy.HTTPProxy,
    93  			HTTPSProxy: installConfig.Config.Proxy.HTTPSProxy,
    94  			NoProxy:    noProxy,
    95  		}
    96  	}
    97  
    98  	configData, err := yaml.Marshal(p.Config)
    99  	if err != nil {
   100  		return errors.Wrapf(err, "failed to create %s manifests from InstallConfig", p.Name())
   101  	}
   102  
   103  	p.FileList = []*asset.File{
   104  		{
   105  			Filename: proxyCfgFilename,
   106  			Data:     configData,
   107  		},
   108  	}
   109  
   110  	return nil
   111  }
   112  
   113  // createNoProxy combines user-provided & platform-specific values to create a comma-separated
   114  // list of unique NO_PROXY values. Platform values are: serviceCIDR, podCIDR, machineCIDR,
   115  // localhost, 127.0.0.1, api.clusterdomain, api-int.clusterdomain.
   116  // If platform is AWS, GCP, Azure, or OpenStack add 169.254.169.254 to the list of NO_PROXY addresses.
   117  // If platform is AWS, add ".ec2.internal" for region us-east-1 or for all other regions add
   118  // ".<aws_region>.compute.internal" to the list of NO_PROXY addresses. We should not proxy
   119  // the instance metadata services:
   120  // https://docs.openstack.org/nova/latest/user/metadata.html
   121  // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html
   122  // https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service
   123  // https://cloud.google.com/compute/docs/storing-retrieving-metadata
   124  func createNoProxy(installConfig *installconfig.InstallConfig, network *Networking) (string, error) {
   125  	internalAPIServer, err := url.Parse(getInternalAPIServerURL(installConfig.Config))
   126  	if err != nil {
   127  		return "", errors.New("failed parsing internal API server when creating Proxy manifest")
   128  	}
   129  
   130  	set := sets.NewString(
   131  		"127.0.0.1",
   132  		"localhost",
   133  		".svc",
   134  		".cluster.local",
   135  		internalAPIServer.Hostname(),
   136  	)
   137  
   138  	platform := installConfig.Config.Platform.Name()
   139  
   140  	// FIXME: The cluster-network-operator duplicates this code in pkg/util/proxyconfig/no_proxy.go,
   141  	//  if altering this list of platforms, you must ALSO alter the code in cluster-network-operator.
   142  	switch platform {
   143  	case aws.Name, gcp.Name, azure.Name, openstack.Name:
   144  		set.Insert("169.254.169.254")
   145  	}
   146  
   147  	// TODO: Add support for additional cloud providers.
   148  	if platform == aws.Name {
   149  		region := installConfig.Config.AWS.Region
   150  		if region == "us-east-1" {
   151  			set.Insert(".ec2.internal")
   152  		} else {
   153  			set.Insert(fmt.Sprintf(".%s.compute.internal", region))
   154  		}
   155  	}
   156  
   157  	// TODO: IBM[#95]: proxy
   158  
   159  	if platform == azure.Name && installConfig.Azure.CloudName != azure.PublicCloud {
   160  		// https://learn.microsoft.com/en-us/azure/virtual-network/what-is-ip-address-168-63-129-16
   161  		set.Insert("168.63.129.16")
   162  		if installConfig.Azure.CloudName == azure.StackCloud {
   163  			set.Insert(installConfig.Config.Azure.ARMEndpoint)
   164  		}
   165  	}
   166  
   167  	// From https://cloud.google.com/vpc/docs/special-configurations add GCP metadata.
   168  	// "metadata.google.internal." added due to https://bugzilla.redhat.com/show_bug.cgi?id=1754049
   169  	if platform == gcp.Name {
   170  		set.Insert("metadata", "metadata.google.internal", "metadata.google.internal.")
   171  	}
   172  
   173  	for _, network := range installConfig.Config.Networking.ServiceNetwork {
   174  		set.Insert(network.String())
   175  	}
   176  
   177  	for _, network := range installConfig.Config.Networking.MachineNetwork {
   178  		set.Insert(network.CIDR.String())
   179  	}
   180  
   181  	for _, clusterNetwork := range network.Config.Spec.ClusterNetwork {
   182  		set.Insert(clusterNetwork.CIDR)
   183  	}
   184  
   185  	for _, userValue := range strings.Split(installConfig.Config.Proxy.NoProxy, ",") {
   186  		if userValue != "" {
   187  			set.Insert(userValue)
   188  		}
   189  	}
   190  
   191  	return strings.Join(set.List(), ","), nil
   192  }
   193  
   194  // Files returns the files generated by the asset.
   195  func (p *Proxy) Files() []*asset.File {
   196  	return p.FileList
   197  }
   198  
   199  // Load loads the already-rendered files back from disk.
   200  func (p *Proxy) Load(f asset.FileFetcher) (bool, error) {
   201  	return false, nil
   202  }