Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Workspace Controller generate TLS certs for webhook server #24

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ docker build -t quay.io/che-incubator/che-workspace-controller:7.1.0 -f ./build/
2. `kubectl create namespace che-workspace-controller`
3. Make sure that the right domain is set in `./deploy/controller_config.yaml` and `./deploy/registry/local/ingress.yaml`
4. `kubectl apply -f ./deploy/registry/local`
5. Generate certificates for Webhook server by executing: `./deploy/webhook-server-certs/deploy-webhook-server-certs.sh`
6. [Optional] Modify ./deploy/controller.yaml and put your docker image and pull policy there.
7. `kubectl apply -f ./deploy`
5. [Optional] Modify ./deploy/controller.yaml and put your docker image and pull policy there.
6. `kubectl apply -f ./deploy`

### Run controller locally
1. `kubectl apply -f ./deploy/crds`
Expand Down
11 changes: 2 additions & 9 deletions deploy/controller.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ spec:
serviceAccountName: che-workspace-controller
containers:
- name: che-workspace-controller
image: quay.io/che-incubator/che-workspace-controller:nightly
image: sleshchenko/che-workspace-controller:webhook
imagePullPolicy: Always
env:
- name: WATCH_NAMESPACE
Expand All @@ -31,15 +31,8 @@ spec:
ports:
- name: webhook-server
containerPort: 8443
volumeMounts:
- name: webhook-tls-certs
mountPath: /tmp/k8s-webhook-server/serving-certs
readOnly: true
volumes:
- name: webhook-tls-certs
secret:
secretName: webhook-server-tls
---
#TODO move creating of it on fly if needed
apiVersion: v1
kind: Service
metadata:
Expand Down
18 changes: 0 additions & 18 deletions deploy/webhook-server-certs/Dockerfile

This file was deleted.

41 changes: 0 additions & 41 deletions deploy/webhook-server-certs/deploy-webhook-server-certs.sh

This file was deleted.

33 changes: 0 additions & 33 deletions deploy/webhook-server-certs/generate-cert.sh

This file was deleted.

15 changes: 15 additions & 0 deletions internal/cluster/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
package cluster

import (
"io/ioutil"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/discovery"
"os"
"sigs.k8s.io/controller-runtime/pkg/client/config"
)

Expand All @@ -38,6 +40,19 @@ func IsOpenShift() (bool, error) {
}
}

func IsInCluster() (bool, error) {
//TODO Try to find a better check
_, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token")
if err != nil {
if !os.IsNotExist(err) {
return false, err
}
return false, nil
}

return true, nil
}

func findAPIGroup(source []metav1.APIGroup, apiName string) *metav1.APIGroup {
for i := 0; i < len(source); i++ {
if source[i].Name == apiName {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ package ownerref
import (
"context"
"github.com/operator-framework/operator-sdk/pkg/k8sutil"
v1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -72,3 +73,65 @@ func findFinalOwnerRef(ctx context.Context, client crclient.Client, ns string, o
Log.V(1).Info("Pods owner found", "Kind", ownerRef.Kind, "Name", ownerRef.Name, "Namespace", ns)
return ownerRef, nil
}

//FindControllerOwner returns OwnerReferent that owns controller process
//it starts searching from the current pod and then resolves owners recursively
//until object without owner is not found
func FindControllerDeployment(ctx context.Context, client crclient.Client) (*v1.Deployment, error) {
ns, err := k8sutil.GetOperatorNamespace()
if err != nil {
return nil, err
}

// Get current Pod the operator is running in
pod, err := k8sutil.GetPod(ctx, client, ns)
if err != nil {
return nil, err
}
// Get Owner that the Pod belongs to
//TODO Take a look, maybe it's a better thing to use
//podOwnerRefs := metav1.NewControllerRef(pod, pod.GroupVersionKind())
ownerRef := metav1.GetControllerOf(pod)
deployment, err := findDeployment(ctx, client, ns, ownerRef)
if err != nil {
return nil, err
}
if deployment != nil {
return deployment, nil
}

// Default to returning Pod as the Owner
return nil, nil
}

// findFinalOwnerRef tries to locate the final controller/owner based on the owner reference provided.
func findDeployment(ctx context.Context, client crclient.Client, ns string, ownerRef *metav1.OwnerReference) (*v1.Deployment, error) {
if ownerRef == nil {
return nil, nil
}

if ownerRef.Kind == "Deployment" {
d := &v1.Deployment{}
err := client.Get(ctx, types.NamespacedName{Namespace: ns, Name: ownerRef.Name}, d)
d.APIVersion = ownerRef.APIVersion
d.Kind = ownerRef.Kind
if err != nil {
return nil, err
}
return d, nil
}
obj := &unstructured.Unstructured{}
obj.SetAPIVersion(ownerRef.APIVersion)
obj.SetKind(ownerRef.Kind)
err := client.Get(ctx, types.NamespacedName{Namespace: ns, Name: ownerRef.Name}, obj)
if err != nil {
return nil, err
}
newOwnerRef := metav1.GetControllerOf(obj)
if newOwnerRef != nil {
return findDeployment(ctx, client, ns, newOwnerRef)
}

Log.V(1).Info("Deployment is not found =(", "Kind", ownerRef.Kind, "Name", ownerRef.Name, "Namespace", ns)
return nil, nil
}
2 changes: 1 addition & 1 deletion pkg/controller/registry/embedded_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ package registry
import (
"context"
"fmt"
"github.com/che-incubator/che-workspace-operator/pkg/controller/ownerref"
"github.com/che-incubator/che-workspace-operator/internal/ownerref"

"github.com/operator-framework/operator-sdk/pkg/k8sutil"

Expand Down
2 changes: 1 addition & 1 deletion pkg/webhook/creator/creator.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ package creator

import (
"context"
"github.com/che-incubator/che-workspace-operator/pkg/controller/ownerref"
"github.com/che-incubator/che-workspace-operator/internal/ownerref"
"k8s.io/api/admissionregistration/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down
21 changes: 16 additions & 5 deletions pkg/webhook/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
package server

import (
"context"
"github.com/che-incubator/che-workspace-operator/internal/cluster"
"io/ioutil"
"os"
"sigs.k8s.io/controller-runtime/pkg/manager"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
)
Expand All @@ -22,13 +22,14 @@ const (
webhookServerHost = "0.0.0.0"
webhookServerPort = 8443
webhookServerCertDir = "/tmp/k8s-webhook-server/serving-certs"
webhookCADir = "/tmp/k8s-webhook-server/certificate-authority"
)

var log = logf.Log.WithName("webhook.server")

var CABundle []byte

func ConfigureWebhookServer(mgr manager.Manager) (bool, error) {
func ConfigureWebhookServer(mgr manager.Manager, ctx context.Context) (bool, error) {
enabled, err := cluster.IsWebhookConfigurationEnabled()

if err != nil {
Expand All @@ -43,12 +44,22 @@ func ConfigureWebhookServer(mgr manager.Manager) (bool, error) {
return false, nil
}

CABundle, err = ioutil.ReadFile(webhookServerCertDir + "/ca.crt")
if os.IsNotExist(err) {
log.Info("CA certificate is not found. Webhook server is not set up")
if inCluster, err := cluster.IsInCluster(); !inCluster || err != nil {
if err != nil {
return false, err
}
log.Info("Controller is run outside of cluster. Skipping setting webhook server up")
return false, nil
}

if err := generateTLSCerts(mgr, ctx); err != nil {
return false, err
}

CABundle, err = ioutil.ReadFile(webhookCADir + "/ca.crt")
if err != nil {
//after generating TLS certs first run will fail.
//TODO Rework and read certs directly from configmap,secret to avoid rebooting
return false, err
}

Expand Down
Loading