Skip to content

Commit

Permalink
teleport-operator - Leverage App platform (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
tuladhar authored Aug 15, 2023
1 parent 46400dd commit 6d6d18f
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 161 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed
- Leverage app platform for deploying teleport-kube-agent app

## [0.1.0] - 2023-08-09

[Unreleased]: https://github.com/giantswarm/teleport-operator/compare/v0.1.0...HEAD
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ go 1.19

require (
github.com/giantswarm/apiextensions-application v0.6.0
github.com/giantswarm/k8smetadata v0.21.0
github.com/giantswarm/microerror v0.4.0
github.com/go-logr/logr v1.2.4
github.com/google/uuid v1.3.0
github.com/gravitational/teleport/api v0.0.0-20230607072028-2f3f42ef14ad
github.com/onsi/ginkgo/v2 v2.9.5
github.com/onsi/gomega v1.27.7
github.com/pkg/errors v0.9.1
go.uber.org/zap v1.19.1
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.25.0
k8s.io/apimachinery v0.25.0
k8s.io/client-go v0.25.0
Expand Down Expand Up @@ -41,6 +42,7 @@ require (
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/giantswarm/k8smetadata v0.21.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
Expand Down Expand Up @@ -89,7 +91,6 @@ require (
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.19.1 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9 // indirect
golang.org/x/net v0.14.0 // indirect
Expand All @@ -105,7 +106,6 @@ require (
google.golang.org/grpc v1.55.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.25.0 // indirect
k8s.io/component-base v0.25.0 // indirect
Expand Down
50 changes: 24 additions & 26 deletions internal/controller/cluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,11 @@ func (r *ClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct

return ctrl.Result{}, microerror.Mask(err)
}
log.Info("Reconciling cluster", "cluster", cluster)

var (
installNamespace = key.TeleportKubeAppDefaultNamespace
registerName = cluster.Name
isManagementCluster = true
)

registerName := cluster.Name
if cluster.Name != r.Teleport.SecretConfig.ManagementClusterName {
installNamespace = cluster.Namespace
registerName = key.GetRegisterName(r.Teleport.SecretConfig.ManagementClusterName, cluster.Name)
isManagementCluster = false
}

// Check if the cluster instance is marked to be deleted, which is indicated by the deletion timestamp being set.
Expand All @@ -87,11 +81,6 @@ func (r *ClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl.Result{}, microerror.Mask(err)
}

// Delete teleport kubernetes resource for the cluster
if err := r.Teleport.DeleteClusterFromTeleport(ctx, log, registerName); err != nil {
return ctrl.Result{}, microerror.Mask(err)
}

// Delete Secret for the cluster
if err := r.Teleport.DeleteSecret(ctx, log, r.Client, cluster.Name, cluster.Namespace); err != nil {
return ctrl.Result{}, microerror.Mask(err)
Expand Down Expand Up @@ -151,35 +140,44 @@ func (r *ClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl.Result{}, microerror.Mask(err)
}
} else {
log.Info("Secret has valid teleport join token", "secretName", secret.GetName())
log.Info("Secret has valid teleport node join token", "secretName", secret.GetName())
}
}

// Check if the cluster is registered in teleport, if not, check if app is teleport-kube-agent app installed
// if app is not installed, installed it
clusterRegisteredInTeleport, err := r.Teleport.IsClusterRegisteredInTeleport(ctx, log, registerName)
// Check if the confimap exists in the cluster, if not, generate teleport token and create the config map
// if it is, check teleport token validity, and update the configmap if teleport token has expired
configMap, err := r.Teleport.GetConfigMap(ctx, log, r.Client, cluster.Name, cluster.Namespace)
if err != nil {
return ctrl.Result{}, microerror.Mask(err)
}

if !clusterRegisteredInTeleport {
// Check if teleport-kube-agent app is installed for the cluster, if not,
// create configmap with newly generated teleport token and install the app
kubeAgentAppInstalled, err := r.Teleport.IsKubeAgentAppInstalled(ctx, r.Client, cluster.Name, installNamespace)
if configMap != nil {
token, err := r.Teleport.GetTokenFromConfigMap(ctx, configMap)
if err != nil {
return ctrl.Result{}, microerror.Mask(err)
}
if !kubeAgentAppInstalled {
tokenValid, err := r.Teleport.IsTokenValid(ctx, registerName, token, "kube")
if err != nil {
return ctrl.Result{}, microerror.Mask(err)
}
if !tokenValid {
token, err := r.Teleport.GenerateToken(ctx, registerName, "kube")
if err != nil {
return ctrl.Result{}, microerror.Mask(err)
}
if err := r.Teleport.CreateConfigMap(ctx, log, r.Client, cluster.Name, registerName, installNamespace, token); err != nil {
return ctrl.Result{}, microerror.Mask(err)
}
if err := r.Teleport.InstallKubeAgentApp(ctx, log, r.Client, cluster.Name, registerName, installNamespace, isManagementCluster); err != nil {
if err := r.Teleport.UpdateConfigMap(ctx, log, r.Client, configMap, token); err != nil {
return ctrl.Result{}, microerror.Mask(err)
}
} else {
log.Info("ConfigMap has valid teleport kube join token", "configMapName", configMap.GetName())
}
} else {
token, err := r.Teleport.GenerateToken(ctx, registerName, "kube")
if err != nil {
return ctrl.Result{}, microerror.Mask(err)
}
if err := r.Teleport.CreateConfigMap(ctx, log, r.Client, cluster.Name, cluster.Namespace, registerName, token); err != nil {
return ctrl.Result{}, microerror.Mask(err)
}
}

Expand Down
1 change: 0 additions & 1 deletion internal/pkg/key/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ func GetConfigmapDataFromTemplate(authToken string, proxyAddr string, kubeCluste
authToken: "%s"
proxyAddr: "%s"
kubeClusterName: "%s"
apps: []
`

if teleportVersion != "" {
Expand Down
82 changes: 0 additions & 82 deletions internal/pkg/teleport/app.go

This file was deleted.

77 changes: 69 additions & 8 deletions internal/pkg/teleport/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,69 @@ package teleport

import (
"context"
"fmt"

"github.com/giantswarm/k8smetadata/pkg/label"
"github.com/giantswarm/microerror"
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"

"github.com/giantswarm/teleport-operator/internal/pkg/key"

"gopkg.in/yaml.v2"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

func (t *Teleport) CreateConfigMap(ctx context.Context, log logr.Logger, ctrlClient client.Client, clusterName string, registerName string, installNamespace string, token string) error {
func (t *Teleport) GetConfigMap(ctx context.Context, log logr.Logger, ctrlClient client.Client, clusterName string, clusterNamespace string) (*corev1.ConfigMap, error) {
var (
configMapName = key.GetConfigmapName(clusterName, t.SecretConfig.AppName)
configMap = &corev1.ConfigMap{}
)

if err := ctrlClient.Get(ctx, client.ObjectKey{Name: configMapName, Namespace: clusterNamespace}, configMap); err != nil {
if apierrors.IsNotFound(err) {
return nil, nil
}
return nil, microerror.Mask(fmt.Errorf("failed to get ConfigMap: %w", err))
}

return configMap, nil
}

func (t *Teleport) GetTokenFromConfigMap(ctx context.Context, configMap *corev1.ConfigMap) (string, error) {
valuesBytes, ok := configMap.Data["values"]
if !ok {
return "", microerror.Mask(fmt.Errorf("malformed ConfigMap: key `values` not found"))
}

var valuesYaml map[string]interface{}
if err := yaml.Unmarshal([]byte(valuesBytes), &valuesYaml); err != nil {
return "", microerror.Mask(fmt.Errorf("failed to parse YAML: %w", err))
}

token, ok := valuesYaml["authToken"].(string)
if !ok {
return "", microerror.Mask(fmt.Errorf("malformed ConfigMap: key `authToken` not found"))
}

return token, nil
}

func (t *Teleport) CreateConfigMap(ctx context.Context, log logr.Logger, ctrlClient client.Client, clusterName string, clusterNamespace string, registerName string, token string) error {
configMapName := key.GetConfigmapName(clusterName, t.SecretConfig.AppName)

configMapData := map[string]string{
"values": t.getConfigMapData(registerName, token),
}

cm := corev1.ConfigMap{}
if err := ctrlClient.Get(ctx, client.ObjectKey{Name: configMapName, Namespace: installNamespace}, &cm); err != nil {
if err := ctrlClient.Get(ctx, client.ObjectKey{Name: configMapName, Namespace: clusterNamespace}, &cm); err != nil {
if apierrors.IsNotFound(err) {
cm := corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: configMapName,
Namespace: installNamespace,
Labels: map[string]string{
label.ManagedBy: key.TeleportOperatorLabelValue,
},
Namespace: clusterNamespace,
},
Data: configMapData,
}
Expand All @@ -40,7 +73,7 @@ func (t *Teleport) CreateConfigMap(ctx context.Context, log logr.Logger, ctrlCli
return microerror.Mask(err)
}

log.Info("Created configmap", "configMapName", configMapName)
log.Info("Created config map with new teleport kube join token", "configMapName", configMapName)
return nil
}

Expand All @@ -50,6 +83,34 @@ func (t *Teleport) CreateConfigMap(ctx context.Context, log logr.Logger, ctrlCli
return nil
}

func (t *Teleport) UpdateConfigMap(ctx context.Context, log logr.Logger, ctrlClient client.Client, configMap *corev1.ConfigMap, token string) error {
valuesBytes, ok := configMap.Data["values"]
if !ok {
return microerror.Mask(fmt.Errorf("malformed ConfigMap: key `values` not found"))
}

var valuesYaml map[string]interface{}
if err := yaml.Unmarshal([]byte(valuesBytes), &valuesYaml); err != nil {
return microerror.Mask(fmt.Errorf("failed to parse YAML: %w", err))
}

// Modify the authToken value
valuesYaml["authToken"] = token

updatedValuesYaml, err := yaml.Marshal(valuesYaml)
if err != nil {
return fmt.Errorf("failed to marshal updated content into YAML: %w", err)
}

// Update the ConfigMap's data with the modified value
configMap.Data["values"] = string(updatedValuesYaml)
if err := ctrlClient.Update(ctx, configMap); err != nil {
return microerror.Mask(fmt.Errorf("failed to update ConfigMap: %w", err))
}
log.Info("Updated config map with new teleport kube join token", "configMap", configMap.GetName())
return nil
}

func (t *Teleport) DeleteConfigMap(ctx context.Context, log logr.Logger, ctrlClient client.Client, clusterName string, clusterNamespace string) error {
configMapName := key.GetConfigmapName(clusterName, t.SecretConfig.AppName)
cm := corev1.ConfigMap{
Expand Down
4 changes: 2 additions & 2 deletions internal/pkg/teleport/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (t *Teleport) CreateSecret(ctx context.Context, log logr.Logger, ctrlClient
if err := ctrlClient.Create(ctx, secret); err != nil {
return microerror.Mask(fmt.Errorf("failed to create Secret: %w", err))
}
log.Info("Created secret with new teleport join token", "secretName", secretName)
log.Info("Created secret with new teleport node join token", "secretName", secretName)
return nil
}

Expand All @@ -159,7 +159,7 @@ func (t *Teleport) UpdateSecret(ctx context.Context, log logr.Logger, ctrlClient
if err := ctrlClient.Update(ctx, secret); err != nil {
return microerror.Mask(fmt.Errorf("failed to update Secret: %w", err))
}
log.Info("Updated secret with new teleport join token", "secretName", secretName)
log.Info("Updated secret with new teleport node join token", "secretName", secretName)
return nil
}

Expand Down
Loading

0 comments on commit 6d6d18f

Please sign in to comment.