Skip to content

Commit

Permalink
generate proxy configuration (#290)
Browse files Browse the repository at this point in the history
  • Loading branch information
bavarianbidi authored Nov 15, 2022
1 parent dd9e75c commit e1a79b4
Show file tree
Hide file tree
Showing 15 changed files with 171 additions and 21 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
TODO
/cluster-apps-operator
!vendor/**
.vscode/
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`giantswarm.io/managed-by` label set to `flux` we check for the existence of two common Flux labels:
`kustomize.toolkit.fluxcd.io/name` and `kustomize.toolkit.fluxcd.io/namespace` regardless of values.

### Added

- Generating proxy-configuration for workload clusters.
By defining a `proxy` configuration (`noProxy`,`httpProxy` and `httpsProxy`) in `configmap/cluster-apps-operator`, these information will be propagated into the cluster specific `configmap` and `secret`.
The `noProxy` value will be computed on a cluster-base as some parameters (e.g. `baseDomain` or some defined `CIDRs` might differ).
Apps like `cert-manager` or `chart-operator` are able to use the global configuration.

## [2.4.0] - 2022-10-17

### Changed

- Enable cluster-values secret creation for CAPVCD.

## [2.3.0] - 2022-10-10
Expand Down
7 changes: 7 additions & 0 deletions flag/service/proxy/proxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package proxy

type Proxy struct {
NoProxy string `json:"noProxy"`
HttpProxy string `json:"http"`
HttpsProxy string `json:"https"`
}
2 changes: 2 additions & 0 deletions flag/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/giantswarm/cluster-apps-operator/v2/flag/service/app"
"github.com/giantswarm/cluster-apps-operator/v2/flag/service/image"
"github.com/giantswarm/cluster-apps-operator/v2/flag/service/provider"
"github.com/giantswarm/cluster-apps-operator/v2/flag/service/proxy"
"github.com/giantswarm/cluster-apps-operator/v2/flag/service/workload"
)

Expand All @@ -16,4 +17,5 @@ type Service struct {
Kubernetes kubernetes.Kubernetes
Provider provider.Provider
Workload workload.Workload
Proxy proxy.Proxy
}
2 changes: 2 additions & 0 deletions flag/service/workload/cluster/cluster.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cluster

import (
"github.com/giantswarm/cluster-apps-operator/v2/flag/service/proxy"
"github.com/giantswarm/cluster-apps-operator/v2/flag/service/workload/cluster/calico"
"github.com/giantswarm/cluster-apps-operator/v2/flag/service/workload/cluster/kubernetes"
)
Expand All @@ -10,4 +11,5 @@ type Cluster struct {
BaseDomain string
Calico calico.Calico
Kubernetes kubernetes.Kubernetes
Proxy proxy.Proxy
}
4 changes: 4 additions & 0 deletions helm/cluster-apps-operator/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ data:
keyFile: ''
provider:
kind: {{ .Values.provider.kind }}
proxy:
noProxy: {{ .Values.proxy.noProxy }}
http: {{ .Values.proxy.http }}
https: {{ .Values.proxy.https }}
workload:
cluster:
baseDomain: '{{ .Values.baseDomain }}'
Expand Down
7 changes: 6 additions & 1 deletion helm/cluster-apps-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ baseDomain: ""
provider:
kind: ""

proxy:
noProxy: ""
http: ""
https: ""

cni:
mask: 16
subnet: 10.1.0.0
Expand Down Expand Up @@ -45,7 +50,7 @@ project:
registry:
domain: docker.io
mirrors:
- giantswarm.azurecr.io
- giantswarm.azurecr.io
pullSecret:
dockerConfigJSON: ""

Expand Down
9 changes: 9 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ func mainE(ctx context.Context) error {
daemonCommand.PersistentFlags().String(f.Service.Workload.Cluster.Kubernetes.API.ClusterIPRange, "", "CIDR Range for Pods in cluster.")
daemonCommand.PersistentFlags().String(f.Service.Workload.Cluster.Kubernetes.ClusterDomain, "cluster.local", "Internal Kubernetes domain.")

daemonCommand.PersistentFlags().String(f.Service.Proxy.NoProxy, "", "Installation specific no_proxy values.")
daemonCommand.PersistentFlags().String(f.Service.Proxy.HttpProxy, "", "Installation specific http_proxy value.")
daemonCommand.PersistentFlags().String(f.Service.Proxy.HttpsProxy, "", "Installation specific https_proxy value.")
/*
TODO:
* set http and https from external
* inject into cluster values
*/

err = newCommand.CobraCommand().Execute()
if err != nil {
return microerror.Mask(err)
Expand Down
4 changes: 4 additions & 0 deletions service/controller/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
capi "sigs.k8s.io/cluster-api/api/v1alpha4"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/giantswarm/cluster-apps-operator/v2/flag/service/proxy"
"github.com/giantswarm/cluster-apps-operator/v2/pkg/project"
"github.com/giantswarm/cluster-apps-operator/v2/service/controller/resource/app"
"github.com/giantswarm/cluster-apps-operator/v2/service/controller/resource/clusterconfigmap"
Expand All @@ -37,6 +38,7 @@ type ClusterConfig struct {
DNSIP string
Provider string
RegistryDomain string
Proxy proxy.Proxy
}

type Cluster struct {
Expand Down Expand Up @@ -118,6 +120,7 @@ func newClusterResources(config ClusterConfig) ([]resource.Interface, error) {
DNSIP: config.DNSIP,
Provider: config.Provider,
RegistryDomain: config.RegistryDomain,
Proxy: config.Proxy,
}

clusterConfigMapGetter, err = clusterconfigmap.New(c)
Expand Down Expand Up @@ -155,6 +158,7 @@ func newClusterResources(config ClusterConfig) ([]resource.Interface, error) {
c := clustersecret.Config{
K8sClient: config.K8sClient,
Logger: config.Logger,
Proxy: config.Proxy,
}

clusterSecretGetter, err = clustersecret.New(c)
Expand Down
15 changes: 15 additions & 0 deletions service/controller/resource/clusterconfigmap/desired_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ func Test_ClusterValuesGCP(t *testing.T) {
Name: "test-cluster",
APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1",
},
ClusterNetwork: &capi.ClusterNetwork{
ServiceDomain: "cluster.local",
Services: &capi.NetworkRanges{
CIDRBlocks: []string{
"192.168.10.0/24",
"192.168.20.0/24",
},
},
Pods: &capi.NetworkRanges{
CIDRBlocks: []string{
"192.168.10.0/24",
"192.168.20.0/24",
},
},
},
},
}

Expand Down
4 changes: 4 additions & 0 deletions service/controller/resource/clusterconfigmap/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/giantswarm/microerror"
"github.com/giantswarm/micrologger"

"github.com/giantswarm/cluster-apps-operator/v2/flag/service/proxy"
"github.com/giantswarm/cluster-apps-operator/v2/service/internal/podcidr"
)

Expand All @@ -27,6 +28,7 @@ type Config struct {
DNSIP string
Provider string
RegistryDomain string
Proxy proxy.Proxy
}

// Resource implements the clusterConfigMap resource.
Expand All @@ -42,6 +44,7 @@ type Resource struct {
dnsIP string
provider string
registryDomain string
proxy proxy.Proxy
}

// New creates a new configured config map state getter resource managing
Expand Down Expand Up @@ -84,6 +87,7 @@ func New(config Config) (*Resource, error) {
dnsIP: config.DNSIP,
provider: config.Provider,
registryDomain: config.RegistryDomain,
proxy: config.Proxy,
}

return r, nil
Expand Down
114 changes: 97 additions & 17 deletions service/controller/resource/clustersecret/desired.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package clustersecret

import (
"bytes"
"context"
"fmt"
"html/template"
"reflect"
"strings"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -14,13 +18,29 @@ import (
"github.com/giantswarm/k8smetadata/pkg/label"
"github.com/giantswarm/microerror"

capi "sigs.k8s.io/cluster-api/api/v1alpha4"

capvcd "github.com/giantswarm/cluster-apps-operator/v2/api/capvcd/v1beta1"

capo "github.com/giantswarm/cluster-apps-operator/v2/api/capo/v1alpha4"
"github.com/giantswarm/cluster-apps-operator/v2/pkg/project"
"github.com/giantswarm/cluster-apps-operator/v2/service/controller/key"
)

const (
mainSecretSection = "values"
containerdProxySection = "containerdProxy"

containerdProxyTemplate = `[Service]
Environment="HTTP_PROXY={{ .HttpProxy }}"
Environment="http_proxy={{ .HttpProxy }}"
Environment="HTTPS_PROXY={{ .HttpsProxy }}"
Environment="https_proxy={{ .HttpsProxy }}"
Environment="NO_PROXY={{ .NoProxy}}"
Environment="no_proxy={{ .NoProxy }}"
`
)

func (r *Resource) GetDesiredState(ctx context.Context, obj interface{}) ([]*corev1.Secret, error) {
cr, err := key.ToCluster(obj)
if err != nil {
Expand Down Expand Up @@ -63,37 +83,63 @@ func (r *Resource) GetDesiredState(ctx context.Context, obj interface{}) ([]*cor
return nil, microerror.Mask(err)
}
}

}
}

secretSpecs := []secretSpec{
{
Name: key.ClusterValuesResourceName(&cr),
Namespace: cr.GetNamespace(),
Values: values,
Data: map[string][]byte{},
},
}

for _, spec := range secretSpecs {
secret, err := newSecret(cr, spec)
if err != nil {
return nil, microerror.Mask(err)
if !reflect.ValueOf(r.proxy).IsZero() {
r.logger.Debugf(ctx, "proxy secrets for cluster '%s/%s' : %v", cr.GetNamespace(), key.ClusterID(&cr), r.proxy)

values["cluster"] = map[string]interface{}{
"proxy": map[string]string{
"noProxy": noProxy(cr, r.proxy.NoProxy),
"http": r.proxy.HttpProxy,
"https": r.proxy.HttpsProxy,
},
}

secrets = append(secrets, secret)
}
// template containerd proxy configuration
t := template.Must(template.New("systemd-proxy-template").Parse(containerdProxyTemplate))
var tpl bytes.Buffer
if err := t.Execute(&tpl, r.proxy); err != nil {
return nil, err
}

return secrets, nil
}
containerdProxy := tpl.String()

secretSpecs = append(secretSpecs, secretSpec{
Name: fmt.Sprintf("%s-systemd-proxy", key.ClusterID(&cr)),
Namespace: cr.GetNamespace(),
Data: map[string][]byte{
containerdProxySection: []byte(containerdProxy),
},
})
}

func newSecret(cr apiv1alpha3.Cluster, secretSpec secretSpec) (*corev1.Secret, error) {
yamlValues, err := yaml.Marshal(secretSpec.Values)
yamlValues, err := yaml.Marshal(values)
if err != nil {
return nil, microerror.Mask(err)
}

secret := &corev1.Secret{
secretSpecs[0].Data[mainSecretSection] = []byte(yamlValues)

for _, spec := range secretSpecs {
secret := newSecret(cr, spec)
secrets = append(secrets, secret)
}

return secrets, nil
}

func newSecret(cr apiv1alpha3.Cluster, secretSpec secretSpec) *corev1.Secret {
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretSpec.Name,
Namespace: secretSpec.Namespace,
Expand All @@ -105,10 +151,44 @@ func newSecret(cr apiv1alpha3.Cluster, secretSpec secretSpec) (*corev1.Secret, e
label.ManagedBy: project.Name(),
},
},
Data: map[string][]byte{
"values": yamlValues,
},
Data: secretSpec.Data,
}
}

func noProxy(cluster capi.Cluster, globalNoProxy string) string {

// generic list of noProxy
// will be joined with custom defined noProxy targets

var appendString []string
if !reflect.ValueOf(cluster.Spec.ClusterNetwork).IsZero() {
if !reflect.ValueOf(cluster.Spec.ClusterNetwork.ServiceDomain).IsZero() {
appendString = append(appendString, cluster.Spec.ClusterNetwork.ServiceDomain)
}

if !reflect.ValueOf(cluster.Spec.ClusterNetwork.Services).IsZero() && !reflect.ValueOf(cluster.Spec.ClusterNetwork.Services.CIDRBlocks).IsZero() {
appendString = append(appendString, strings.Join(cluster.Spec.ClusterNetwork.Services.CIDRBlocks, ","))
}

if !reflect.ValueOf(cluster.Spec.ClusterNetwork.Pods).IsZero() && !reflect.ValueOf(cluster.Spec.ClusterNetwork.Pods.CIDRBlocks).IsZero() {
appendString = append(appendString, strings.Join(cluster.Spec.ClusterNetwork.Pods.CIDRBlocks, ","))
}
}

return secret, nil
if !reflect.ValueOf(cluster.Spec.ControlPlaneEndpoint.Host).IsZero() {
appendString = append(appendString, cluster.Spec.ControlPlaneEndpoint.Host)
}

if len(globalNoProxy) > 0 {
appendString = append(appendString, globalNoProxy)
}

noProxy := strings.Join([]string{
strings.Join(appendString, ","),
"svc",
"127.0.0.1",
"localhost",
}, ",")

return noProxy
}
5 changes: 5 additions & 0 deletions service/controller/resource/clustersecret/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"github.com/giantswarm/k8sclient/v7/pkg/k8sclient"
"github.com/giantswarm/microerror"
"github.com/giantswarm/micrologger"

"github.com/giantswarm/cluster-apps-operator/v2/flag/service/proxy"
)

const (
Expand All @@ -16,12 +18,14 @@ const (
type Config struct {
K8sClient k8sclient.Interface
Logger micrologger.Logger
Proxy proxy.Proxy
}

// Resource implements the clustersecret resource.
type Resource struct {
k8sClient k8sclient.Interface
logger micrologger.Logger
proxy proxy.Proxy
}

// New creates a new configured secret state getter resource managing
Expand All @@ -39,6 +43,7 @@ func New(config Config) (*Resource, error) {
r := &Resource{
k8sClient: config.K8sClient,
logger: config.Logger,
proxy: config.Proxy,
}

return r, nil
Expand Down
Loading

0 comments on commit e1a79b4

Please sign in to comment.