Compare commits

...

6 Commits

Author SHA1 Message Date
dependabot[bot]
df3866fa24 feat(deps): bump github.com/prometheus/client_golang (#899)
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.22.0 to 1.23.0.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/v1.23.0/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.22.0...v1.23.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-version: 1.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 10:32:39 +02:00
Mateusz Kwiatkowski
f52fe45c46 feat: add hostNetwork support for the Konnectivity Agent (#883)
This commit extends CRD API: Added hostNetwork field to KonnectivityAgentSpec struct.
It's false by default so it's backwards compatible.

Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
2025-07-30 22:31:38 +02:00
dependabot[bot]
c04d8ddc85 feat(deps): bump github.com/docker/docker (#897)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 28.3.2+incompatible to 28.3.3+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v28.3.2...v28.3.3)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-version: 28.3.3+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-30 16:02:57 +02:00
dependabot[bot]
3ecd84b68a feat(deps): bump github.com/nats-io/nats.go from 1.43.0 to 1.44.0 (#898)
Bumps [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) from 1.43.0 to 1.44.0.
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.43.0...v1.44.0)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats.go
  dependency-version: 1.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-30 16:02:47 +02:00
Dario Tranchitella
9ba9c65755 fix(gh): release create does not push git tag by default (#896)
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
2025-07-29 15:04:21 +02:00
Dario Tranchitella
5e68fd8fe0 fix: honouring certificate expiratin threshold (#886)
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
2025-07-28 09:40:16 +02:00
21 changed files with 206 additions and 101 deletions

View File

@@ -37,6 +37,12 @@ jobs:
run: |
export TAG="${{ steps.tag.outputs.tag }}"
envsubst < .github/release-template.md > release-notes.md
- name: create and push git tag
run: |
git config user.name "github-actions"
git config user.email "github-actions@github.com"
git tag "${{ steps.tag.outputs.tag }}"
git push origin "${{ steps.tag.outputs.tag }}"
- name: create GitHub release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -257,6 +257,12 @@ type KonnectivityAgentSpec struct {
//+kubebuilder:default={{key: "CriticalAddonsOnly", operator: "Exists"}}
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
ExtraArgs ExtraArgs `json:"extraArgs,omitempty"`
// HostNetwork enables the konnectivity agent to use the Host network namespace.
// By enabling this mode, the Agent doesn't need to wait for the CNI initialisation,
// enabling a sort of out-of-band access to nodes for troubleshooting scenarios,
// or when the agent needs direct access to the host network.
//+kubebuilder:default=false
HostNetwork bool `json:"hostNetwork,omitempty"`
// Mode allows specifying the Agent deployment mode: Deployment, or DaemonSet (default).
//+kubebuilder:default="DaemonSet"
//+kubebuilder:validation:Enum=DaemonSet;Deployment

View File

@@ -108,6 +108,14 @@ spec:
items:
type: string
type: array
hostNetwork:
default: false
description: |-
HostNetwork enables the konnectivity agent to use the Host network namespace.
By enabling this mode, the Agent doesn't need to wait for the CNI initialisation,
enabling a sort of out-of-band access to nodes for troubleshooting scenarios,
or when the agent needs direct access to the host network.
type: boolean
image:
default: registry.k8s.io/kas-network-proxy/proxy-agent
description: AgentImage defines the container image for Konnectivity's agent.

View File

@@ -149,11 +149,12 @@ func NewCmd(scheme *runtime.Scheme) *cobra.Command {
Client: mgr.GetClient(),
APIReader: mgr.GetAPIReader(),
Config: controllers.TenantControlPlaneReconcilerConfig{
ReconcileTimeout: controllerReconcileTimeout,
DefaultDataStoreName: datastore,
KineContainerImage: kineImage,
TmpBaseDirectory: tmpDirectory,
DefaultDataStoreName: datastore,
KineContainerImage: kineImage,
TmpBaseDirectory: tmpDirectory,
CertExpirationThreshold: certificateExpirationDeadline,
},
ReconcileTimeout: controllerReconcileTimeout,
CertificateChan: certChannel,
TriggerChan: tcpChannel,
KamajiNamespace: managerNamespace,

View File

@@ -0,0 +1,36 @@
apiVersion: kamaji.clastix.io/v1alpha1
kind: TenantControlPlane
metadata:
name: example-hostnetwork-tcp
namespace: tenant-system
spec:
controlPlane:
deployment:
replicas: 2
service:
serviceType: LoadBalancer
kubernetes:
version: v1.29.0
kubelet:
cgroupfs: systemd
preferredAddressTypes: ["InternalIP", "ExternalIP"]
networkProfile:
address: "10.0.0.100"
port: 6443
serviceCidr: "10.96.0.0/16"
podCidr: "10.244.0.0/16"
addons:
coreDNS: {}
konnectivity:
server:
port: 8132
agent:
hostNetwork: true
tolerations:
- key: "CriticalAddonsOnly"
operator: "Exists"
- key: "node.kubernetes.io/not-ready"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 300
kubeProxy: {}

View File

@@ -5,6 +5,7 @@ package controllers
import (
"fmt"
"time"
"github.com/go-logr/logr"
"github.com/google/uuid"
@@ -26,6 +27,7 @@ type GroupResourceBuilderConfiguration struct {
log logr.Logger
tcpReconcilerConfig TenantControlPlaneReconcilerConfig
tenantControlPlane kamajiv1alpha1.TenantControlPlane
ExpirationThreshold time.Duration
Connection datastore.Connection
DataStore kamajiv1alpha1.DataStore
KamajiNamespace string
@@ -78,8 +80,8 @@ func getDefaultResources(config GroupResourceBuilderConfiguration) []resources.R
resources = append(resources, getKubeadmConfigResources(config.client, getTmpDirectory(config.tcpReconcilerConfig.TmpBaseDirectory, config.tenantControlPlane), config.DataStore)...)
resources = append(resources, getKubernetesCertificatesResources(config.client, config.tcpReconcilerConfig, config.tenantControlPlane)...)
resources = append(resources, getKubeconfigResources(config.client, config.tcpReconcilerConfig, config.tenantControlPlane)...)
resources = append(resources, getKubernetesStorageResources(config.client, config.Connection, config.DataStore)...)
resources = append(resources, getKonnectivityServerRequirementsResources(config.client)...)
resources = append(resources, getKubernetesStorageResources(config.client, config.Connection, config.DataStore, config.ExpirationThreshold)...)
resources = append(resources, getKonnectivityServerRequirementsResources(config.client, config.ExpirationThreshold)...)
resources = append(resources, getKubernetesDeploymentResources(config.client, config.tcpReconcilerConfig, config.DataStore)...)
resources = append(resources, getKonnectivityServerPatchResources(config.client)...)
resources = append(resources, getDataStoreMigratingCleanup(config.client, config.KamajiNamespace)...)
@@ -148,28 +150,33 @@ func getKubeadmConfigResources(c client.Client, tmpDirectory string, dataStore k
func getKubernetesCertificatesResources(c client.Client, tcpReconcilerConfig TenantControlPlaneReconcilerConfig, tenantControlPlane kamajiv1alpha1.TenantControlPlane) []resources.Resource {
return []resources.Resource{
&resources.CACertificate{
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
CertExpirationThreshold: tcpReconcilerConfig.CertExpirationThreshold,
},
&resources.FrontProxyCACertificate{
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
CertExpirationThreshold: tcpReconcilerConfig.CertExpirationThreshold,
},
&resources.SACertificate{
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
},
&resources.APIServerCertificate{
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
CertExpirationThreshold: tcpReconcilerConfig.CertExpirationThreshold,
},
&resources.APIServerKubeletClientCertificate{
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
CertExpirationThreshold: tcpReconcilerConfig.CertExpirationThreshold,
},
&resources.FrontProxyClientCertificate{
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
CertExpirationThreshold: tcpReconcilerConfig.CertExpirationThreshold,
},
}
}
@@ -177,33 +184,37 @@ func getKubernetesCertificatesResources(c client.Client, tcpReconcilerConfig Ten
func getKubeconfigResources(c client.Client, tcpReconcilerConfig TenantControlPlaneReconcilerConfig, tenantControlPlane kamajiv1alpha1.TenantControlPlane) []resources.Resource {
return []resources.Resource{
&resources.KubeconfigResource{
Name: "admin-kubeconfig",
Client: c,
KubeConfigFileName: resources.AdminKubeConfigFileName,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
Client: c,
Name: "admin-kubeconfig",
KubeConfigFileName: resources.AdminKubeConfigFileName,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
CertExpirationThreshold: tcpReconcilerConfig.CertExpirationThreshold,
},
&resources.KubeconfigResource{
Name: "admin-kubeconfig",
Client: c,
KubeConfigFileName: resources.SuperAdminKubeConfigFileName,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
Client: c,
Name: "admin-kubeconfig",
KubeConfigFileName: resources.SuperAdminKubeConfigFileName,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
CertExpirationThreshold: tcpReconcilerConfig.CertExpirationThreshold,
},
&resources.KubeconfigResource{
Name: "controller-manager-kubeconfig",
Client: c,
KubeConfigFileName: resources.ControllerManagerKubeConfigFileName,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
Client: c,
Name: "controller-manager-kubeconfig",
KubeConfigFileName: resources.ControllerManagerKubeConfigFileName,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
CertExpirationThreshold: tcpReconcilerConfig.CertExpirationThreshold,
},
&resources.KubeconfigResource{
Name: "scheduler-kubeconfig",
Client: c,
KubeConfigFileName: resources.SchedulerKubeConfigFileName,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
Client: c,
Name: "scheduler-kubeconfig",
KubeConfigFileName: resources.SchedulerKubeConfigFileName,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
CertExpirationThreshold: tcpReconcilerConfig.CertExpirationThreshold,
},
}
}
func getKubernetesStorageResources(c client.Client, dbConnection datastore.Connection, datastore kamajiv1alpha1.DataStore) []resources.Resource {
func getKubernetesStorageResources(c client.Client, dbConnection datastore.Connection, datastore kamajiv1alpha1.DataStore, threshold time.Duration) []resources.Resource {
return []resources.Resource{
&ds.MultiTenancy{
DataStore: datastore,
@@ -219,8 +230,9 @@ func getKubernetesStorageResources(c client.Client, dbConnection datastore.Conne
DataStore: datastore,
},
&ds.Certificate{
Client: c,
DataStore: datastore,
Client: c,
DataStore: datastore,
CertExpirationThreshold: threshold,
},
}
}
@@ -251,10 +263,10 @@ func GetExternalKonnectivityResources(c client.Client) []resources.Resource {
}
}
func getKonnectivityServerRequirementsResources(c client.Client) []resources.Resource {
func getKonnectivityServerRequirementsResources(c client.Client, threshold time.Duration) []resources.Resource {
return []resources.Resource{
&konnectivity.EgressSelectorConfigurationResource{Client: c},
&konnectivity.CertificateResource{Client: c},
&konnectivity.CertificateResource{Client: c, CertExpirationThreshold: threshold},
&konnectivity.KubeconfigResource{Client: c},
}
}

View File

@@ -50,6 +50,7 @@ type TenantControlPlaneReconciler struct {
KamajiService string
KamajiMigrateImage string
MaxConcurrentReconciles int
ReconcileTimeout time.Duration
// CertificateChan is the channel used by the CertificateLifecycleController that is checking for
// certificates and kubeconfig user certs validity: a generic event for the given TCP will be triggered
// once the validity threshold for the given certificate is reached.
@@ -60,10 +61,10 @@ type TenantControlPlaneReconciler struct {
// TenantControlPlaneReconcilerConfig gives the necessary configuration for TenantControlPlaneReconciler.
type TenantControlPlaneReconcilerConfig struct {
ReconcileTimeout time.Duration
DefaultDataStoreName string
KineContainerImage string
TmpBaseDirectory string
DefaultDataStoreName string
KineContainerImage string
TmpBaseDirectory string
CertExpirationThreshold time.Duration
}
//+kubebuilder:rbac:groups=kamaji.clastix.io,resources=tenantcontrolplanes,verbs=get;list;watch;create;update;patch;delete
@@ -80,7 +81,7 @@ func (r *TenantControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R
log := log.FromContext(ctx)
var cancelFn context.CancelFunc
ctx, cancelFn = context.WithTimeout(ctx, r.Config.ReconcileTimeout)
ctx, cancelFn = context.WithTimeout(ctx, r.ReconcileTimeout)
defer cancelFn()
tenantControlPlane, err := r.getTenantControlPlane(ctx, req.NamespacedName)()

View File

@@ -39626,6 +39626,18 @@ parameters and cause konnectivity components to misbehave in
unxpected ways. Only modify if you know what you are doing.<br/>
</td>
<td>false</td>
</tr><tr>
<td><b>hostNetwork</b></td>
<td>boolean</td>
<td>
HostNetwork enables the konnectivity agent to use the Host network namespace.
By enabling this mode, the Agent doesn't need to wait for the CNI initialisation,
enabling a sort of out-of-band access to nodes for troubleshooting scenarios,
or when the agent needs direct access to the host network.<br/>
<br/>
<i>Default</i>: false<br/>
</td>
<td>false</td>
</tr><tr>
<td><b>image</b></td>
<td>string</td>

14
go.mod
View File

@@ -6,7 +6,7 @@ require (
github.com/JamesStewy/go-mysqldump v0.2.2
github.com/blang/semver v3.5.1+incompatible
github.com/clastix/kamaji-telemetry v1.0.0
github.com/docker/docker v28.3.2+incompatible
github.com/docker/docker v28.3.3+incompatible
github.com/go-logr/logr v1.4.3
github.com/go-pg/pg/v10 v10.14.0
github.com/go-sql-driver/mysql v1.9.3
@@ -14,11 +14,11 @@ require (
github.com/google/uuid v1.6.0
github.com/json-iterator/go v1.1.12
github.com/juju/mutex/v2 v2.0.0
github.com/nats-io/nats.go v1.43.0
github.com/nats-io/nats.go v1.44.0
github.com/onsi/ginkgo/v2 v2.23.4
github.com/onsi/gomega v1.38.0
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.22.0
github.com/prometheus/client_golang v1.23.0
github.com/spf13/cobra v1.9.1
github.com/spf13/pflag v1.0.7
github.com/spf13/viper v1.20.1
@@ -124,9 +124,9 @@ require (
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.65.0 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/shirou/gopsutil/v4 v4.25.5 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
@@ -162,7 +162,7 @@ require (
golang.org/x/crypto v0.39.0 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/oauth2 v0.27.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sync v0.15.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/term v0.32.0 // indirect

28
go.sum
View File

@@ -56,8 +56,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/docker v28.3.2+incompatible h1:wn66NJ6pWB1vBZIilP8G3qQPqHy5XymfYn5vsqeA5oA=
github.com/docker/docker v28.3.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI=
github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@@ -233,8 +233,8 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/nats-io/nats.go v1.43.0 h1:uRFZ2FEoRvP64+UUhaTokyS18XBCR/xM2vQZKO4i8ug=
github.com/nats-io/nats.go v1.43.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
github.com/nats-io/nats.go v1.44.0 h1:ECKVrDLdh/kDPV1g0gAQ+2+m2KprqZK5O/eJAyAnH2M=
github.com/nats-io/nats.go v1.44.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
@@ -264,14 +264,14 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -410,8 +410,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=

View File

@@ -22,7 +22,7 @@ import (
)
// CheckPublicAndPrivateKeyValidity checks if the given bytes for the private and public keys are valid.
func CheckPublicAndPrivateKeyValidity(publicKey []byte, privateKey []byte) (bool, error) {
func CheckPublicAndPrivateKeyValidity(publicKey, privateKey []byte) (bool, error) {
if len(publicKey) == 0 || len(privateKey) == 0 {
return false, nil
}
@@ -74,12 +74,12 @@ func CheckCertificateNamesAndIPs(certificateBytes []byte, entries []string) (boo
}
// CheckCertificateAndPrivateKeyPairValidity checks if the certificate and private key pair are valid.
func CheckCertificateAndPrivateKeyPairValidity(certificate []byte, privateKey []byte) (bool, error) {
func CheckCertificateAndPrivateKeyPairValidity(certificate, privateKey []byte, threshold time.Duration) (bool, error) {
switch {
case len(certificate) == 0, len(privateKey) == 0:
return false, nil
default:
return IsValidCertificateKeyPairBytes(certificate, privateKey)
return IsValidCertificateKeyPairBytes(certificate, privateKey, threshold)
}
}
@@ -159,7 +159,7 @@ func ParsePublicKeyBytes(content []byte) (*rsa.PublicKey, error) {
}
// IsValidCertificateKeyPairBytes checks if the certificate matches the private key bounded to it.
func IsValidCertificateKeyPairBytes(certificateBytes []byte, privateKeyBytes []byte) (bool, error) {
func IsValidCertificateKeyPairBytes(certificateBytes, privateKeyBytes []byte, expirationThreshold time.Duration) (bool, error) {
crt, err := ParseCertificateBytes(certificateBytes)
if err != nil {
return false, err
@@ -171,7 +171,7 @@ func IsValidCertificateKeyPairBytes(certificateBytes []byte, privateKeyBytes []b
}
switch {
case !checkCertificateValidity(*crt):
case !checkCertificateValidity(*crt, expirationThreshold):
return false, nil
case !checkPublicKeys(crt.PublicKey, key):
return false, nil
@@ -238,9 +238,9 @@ func generateCertificateKeyPairBytes(template *x509.Certificate, caCert *x509.Ce
return certPEM, certPrivKeyPEM, nil
}
func checkCertificateValidity(cert x509.Certificate) bool {
func checkCertificateValidity(cert x509.Certificate, threshold time.Duration) bool {
// Avoiding waiting for the exact expiration date by creating a one-day gap
notAfter := cert.NotAfter.After(time.Now().AddDate(0, 0, 1))
notAfter := cert.NotAfter.After(time.Now().Add(threshold))
notBefore := cert.NotBefore.Before(time.Now())
return notAfter && notBefore

View File

@@ -8,6 +8,7 @@ import (
"os"
"path"
"path/filepath"
"time"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
@@ -62,13 +63,13 @@ func IsKubeconfigCAValid(in, caCrt []byte) bool {
return true
}
func IsKubeconfigValid(bytes []byte) bool {
func IsKubeconfigValid(bytes []byte, expirationThreshold time.Duration) bool {
kc, err := utilities.DecodeKubeconfigYAML(bytes)
if err != nil {
return false
}
ok, _ := crypto.IsValidCertificateKeyPairBytes(kc.AuthInfos[0].AuthInfo.ClientCertificateData, kc.AuthInfos[0].AuthInfo.ClientKeyData)
ok, _ := crypto.IsValidCertificateKeyPairBytes(kc.AuthInfos[0].AuthInfo.ClientCertificateData, kc.AuthInfos[0].AuthInfo.ClientKeyData, expirationThreshold)
return ok
}

View File

@@ -7,6 +7,7 @@ import (
"context"
"crypto/x509"
"fmt"
"time"
"github.com/prometheus/client_golang/prometheus"
corev1 "k8s.io/api/core/v1"
@@ -27,9 +28,10 @@ import (
)
type APIServerCertificate struct {
resource *corev1.Secret
Client client.Client
TmpDirectory string
resource *corev1.Secret
Client client.Client
TmpDirectory string
CertExpirationThreshold time.Duration
}
func (r *APIServerCertificate) GetHistogram() prometheus.Histogram {
@@ -138,6 +140,7 @@ func (r *APIServerCertificate) mutate(ctx context.Context, tenantControlPlane *k
isCertValid, err := crypto.CheckCertificateAndPrivateKeyPairValidity(
r.resource.Data[kubeadmconstants.APIServerCertName],
r.resource.Data[kubeadmconstants.APIServerKeyName],
r.CertExpirationThreshold,
)
if err != nil {
logger.Info(fmt.Sprintf("%s certificate-private_key pair is not valid: %s", kubeadmconstants.APIServerCertAndKeyBaseName, err.Error()))

View File

@@ -7,6 +7,7 @@ import (
"context"
"crypto/x509"
"fmt"
"time"
"github.com/prometheus/client_golang/prometheus"
corev1 "k8s.io/api/core/v1"
@@ -26,9 +27,10 @@ import (
)
type APIServerKubeletClientCertificate struct {
resource *corev1.Secret
Client client.Client
TmpDirectory string
resource *corev1.Secret
Client client.Client
TmpDirectory string
CertExpirationThreshold time.Duration
}
func (r *APIServerKubeletClientCertificate) GetHistogram() prometheus.Histogram {
@@ -125,6 +127,7 @@ func (r *APIServerKubeletClientCertificate) mutate(ctx context.Context, tenantCo
isValid, err := crypto.CheckCertificateAndPrivateKeyPairValidity(
r.resource.Data[kubeadmconstants.APIServerKubeletClientCertName],
r.resource.Data[kubeadmconstants.APIServerKubeletClientKeyName],
r.CertExpirationThreshold,
)
if err != nil {
logger.Info(fmt.Sprintf("%s certificate-private_key pair is not valid: %s", kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName, err.Error()))

View File

@@ -7,6 +7,7 @@ import (
"bytes"
"context"
"fmt"
"time"
"github.com/prometheus/client_golang/prometheus"
corev1 "k8s.io/api/core/v1"
@@ -27,8 +28,9 @@ type CACertificate struct {
resource *corev1.Secret
isRotatingCA bool
Client client.Client
TmpDirectory string
Client client.Client
TmpDirectory string
CertExpirationThreshold time.Duration
}
func (r *CACertificate) GetHistogram() prometheus.Histogram {
@@ -102,6 +104,7 @@ func (r *CACertificate) mutate(ctx context.Context, tenantControlPlane *kamajiv1
isValid, err := crypto.CheckCertificateAndPrivateKeyPairValidity(
r.resource.Data[kubeadmconstants.CACertName],
r.resource.Data[kubeadmconstants.CAKeyName],
r.CertExpirationThreshold,
)
if err != nil {
logger.Info(fmt.Sprintf("%s certificate-private_key pair is not valid: %s", kubeadmconstants.CACertAndKeyBaseName, err.Error()))

View File

@@ -7,6 +7,7 @@ import (
"bytes"
"context"
"fmt"
"time"
"github.com/prometheus/client_golang/prometheus"
corev1 "k8s.io/api/core/v1"
@@ -24,10 +25,11 @@ import (
)
type Certificate struct {
resource *corev1.Secret
Client client.Client
Name string
DataStore kamajiv1alpha1.DataStore
resource *corev1.Secret
Client client.Client
Name string
DataStore kamajiv1alpha1.DataStore
CertExpirationThreshold time.Duration
}
func (r *Certificate) GetHistogram() prometheus.Histogram {
@@ -118,7 +120,7 @@ func (r *Certificate) mutate(ctx context.Context, tenantControlPlane *kamajiv1al
if utilities.GetObjectChecksum(r.resource) == utilities.CalculateMapChecksum(r.resource.Data) {
if r.DataStore.Spec.Driver == kamajiv1alpha1.EtcdDriver {
if isValid, _ := crypto.IsValidCertificateKeyPairBytes(r.resource.Data["server.crt"], r.resource.Data["server.key"]); isValid && !isRotationRequested {
if isValid, _ := crypto.IsValidCertificateKeyPairBytes(r.resource.Data["server.crt"], r.resource.Data["server.key"], r.CertExpirationThreshold); isValid && !isRotationRequested {
return nil
}
}

View File

@@ -7,6 +7,7 @@ import (
"context"
"crypto/x509"
"fmt"
"time"
"github.com/prometheus/client_golang/prometheus"
corev1 "k8s.io/api/core/v1"
@@ -26,9 +27,10 @@ import (
)
type FrontProxyClientCertificate struct {
resource *corev1.Secret
Client client.Client
TmpDirectory string
resource *corev1.Secret
Client client.Client
TmpDirectory string
CertExpirationThreshold time.Duration
}
func (r *FrontProxyClientCertificate) GetHistogram() prometheus.Histogram {
@@ -125,6 +127,7 @@ func (r *FrontProxyClientCertificate) mutate(ctx context.Context, tenantControlP
isValid, err := crypto.CheckCertificateAndPrivateKeyPairValidity(
r.resource.Data[kubeadmconstants.FrontProxyClientCertName],
r.resource.Data[kubeadmconstants.FrontProxyClientKeyName],
r.CertExpirationThreshold,
)
if err != nil {
logger.Info(fmt.Sprintf("%s certificate-private_key pair is not valid: %s", kubeadmconstants.FrontProxyClientCertAndKeyBaseName, err.Error()))

View File

@@ -6,6 +6,7 @@ package resources
import (
"context"
"fmt"
"time"
"github.com/prometheus/client_golang/prometheus"
corev1 "k8s.io/api/core/v1"
@@ -23,9 +24,10 @@ import (
)
type FrontProxyCACertificate struct {
resource *corev1.Secret
Client client.Client
TmpDirectory string
resource *corev1.Secret
Client client.Client
TmpDirectory string
CertExpirationThreshold time.Duration
}
func (r *FrontProxyCACertificate) GetHistogram() prometheus.Histogram {
@@ -95,6 +97,7 @@ func (r *FrontProxyCACertificate) mutate(ctx context.Context, tenantControlPlane
isValid, err := crypto.CheckCertificateAndPrivateKeyPairValidity(
r.resource.Data[kubeadmconstants.FrontProxyCACertName],
r.resource.Data[kubeadmconstants.FrontProxyCAKeyName],
r.CertExpirationThreshold,
)
if err != nil {
logger.Info(fmt.Sprintf("%s certificate-private_key pair is not valid: %s", kubeadmconstants.FrontProxyCACertAndKeyBaseName, err.Error()))

View File

@@ -190,6 +190,7 @@ func (r *Agent) mutate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.T
podTemplateSpec.SetLabels(utilities.MergeMaps(podTemplateSpec.GetLabels(), specSelector.MatchLabels))
podTemplateSpec.Spec.PriorityClassName = "system-cluster-critical"
podTemplateSpec.Spec.Tolerations = tenantControlPlane.Spec.Addons.Konnectivity.KonnectivityAgentSpec.Tolerations
podTemplateSpec.Spec.HostNetwork = tenantControlPlane.Spec.Addons.Konnectivity.KonnectivityAgentSpec.HostNetwork
podTemplateSpec.Spec.NodeSelector = map[string]string{
"kubernetes.io/os": "linux",
}

View File

@@ -6,6 +6,7 @@ package konnectivity
import (
"context"
"fmt"
"time"
"github.com/prometheus/client_golang/prometheus"
corev1 "k8s.io/api/core/v1"
@@ -27,8 +28,9 @@ import (
)
type CertificateResource struct {
resource *corev1.Secret
Client client.Client
resource *corev1.Secret
Client client.Client
CertExpirationThreshold time.Duration
}
func (r *CertificateResource) GetHistogram() prometheus.Histogram {
@@ -117,7 +119,7 @@ func (r *CertificateResource) mutate(ctx context.Context, tenantControlPlane *ka
isRotationRequested := utilities.IsRotationRequested(r.resource)
if checksum := tenantControlPlane.Status.Addons.Konnectivity.Certificate.Checksum; !isRotationRequested && (len(checksum) > 0 && checksum == utilities.CalculateMapChecksum(r.resource.Data)) {
isValid, err := crypto.IsValidCertificateKeyPairBytes(r.resource.Data[corev1.TLSCertKey], r.resource.Data[corev1.TLSPrivateKeyKey])
isValid, err := crypto.IsValidCertificateKeyPairBytes(r.resource.Data[corev1.TLSCertKey], r.resource.Data[corev1.TLSPrivateKeyKey], r.CertExpirationThreshold)
if err != nil {
logger.Info(fmt.Sprintf("%s certificate-private_key pair is not valid: %s", konnectivityCertAndKeyBaseName, err.Error()))
}

View File

@@ -7,6 +7,7 @@ import (
"context"
"fmt"
"strings"
"time"
"github.com/prometheus/client_golang/prometheus"
corev1 "k8s.io/api/core/v1"
@@ -33,11 +34,12 @@ const (
)
type KubeconfigResource struct {
resource *corev1.Secret
Client client.Client
Name string
KubeConfigFileName string
TmpDirectory string
resource *corev1.Secret
Client client.Client
Name string
KubeConfigFileName string
TmpDirectory string
CertExpirationThreshold time.Duration
}
func (r *KubeconfigResource) GetHistogram() prometheus.Histogram {
@@ -189,8 +191,8 @@ func (r *KubeconfigResource) mutate(ctx context.Context, tenantControlPlane *kam
shouldCreate = shouldCreate || len(r.resource.Data) == 0 // Missing data key
shouldCreate = shouldCreate || len(r.resource.Data[r.KubeConfigFileName]) == 0 // Missing kubeconfig file, must be generated
shouldCreate = shouldCreate || !kubeadm.IsKubeconfigCAValid(r.resource.Data[r.KubeConfigFileName], caCertificatesSecret.Data[kubeadmconstants.CACertName])
shouldCreate = shouldCreate || !kubeadm.IsKubeconfigValid(r.resource.Data[r.KubeConfigFileName]) // invalid kubeconfig, or expired client certificate
shouldCreate = shouldCreate || status.Checksum != checksum || len(r.resource.UID) == 0 // Wrong checksum
shouldCreate = shouldCreate || !kubeadm.IsKubeconfigValid(r.resource.Data[r.KubeConfigFileName], r.CertExpirationThreshold) // invalid kubeconfig, or expired client certificate
shouldCreate = shouldCreate || status.Checksum != checksum || len(r.resource.UID) == 0 // Wrong checksum
shouldRotate := utilities.IsRotationRequested(r.resource)