From 1b55e3599962d96e9ca6d2bfe0c50fff4c839c59 Mon Sep 17 00:00:00 2001 From: Fabian Lindfors Date: Thu, 22 Aug 2019 13:30:40 +0100 Subject: [PATCH] CLOUDP-48516: Add TLS support (#49) --- README.md | 2 ++ dev/README.md | 13 ++++++++++ main.go | 38 ++++++++++++++++++++++++------ samples/kubernetes/deployment.yaml | 3 --- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index bb76a07..770a7b8 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ Configuration is handled with environment variables. Logs are written to | BROKER_HOST | `127.0.0.1` | Address which the broker server listens on | | BROKER_PORT | `4000` | Port which the broker server listens on | | BROKER_LOG_LEVEL | `INFO` | Accepted values: `DEBUG`, `INFO`, `WARN`, `ERROR` | +| BROKER_TLS_CERT_FILE | | Path to a certificate file to use for TLS. Leave empty to disable TLS. | +| BROKER_TLS_KEY_FILE | | Path to private key file to use for TLS. Leave empty to disable TLS. | ## License diff --git a/dev/README.md b/dev/README.md index aeb9d26..0778912 100644 --- a/dev/README.md +++ b/dev/README.md @@ -26,6 +26,19 @@ The release process consists of publishing a new Github release with attached bi Please include their license in the notices/ directory. +## Setting up TLS in Kubernetes + +To enable TLS, perform these steps before continuing with "Testing in Kubernetes". + +1. Generate a self-signed certificate and private key by running `openssl req -newkey rsa:2048 -nodes -keyout key-x509 -days 365 -out cert`. + When prompted for "Common Name", enter `atlas-service-broker.atlas`. All other fields can be left empty. +2. Create a new secret containing the key and cert by running `kubectl create secret generic aosb-tls --from-file=./key --from-file=./cert -n atlas`. +3. Update `samples/kubernetes/deployment.yaml` to mount the secret inside your pod in accordance with this guide: https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-files-from-a-pod. + Also add the `BROKER_TLS_KEY_FILE` and `BROKER_TLS_CERT_FILE` environment variables to point to the mounted secret. If mounted to `/etc/tls_secret` + the environment variables would be `/etc/tls_secret/key` and `/etc/tls_secret/cert`. Also change the service port from `80` to `443`. +4. Update `samples/kubernetes/service-broker.yaml` and add a `caBundle` field containing the base64 encoded contents of `cert`. + Run `base64 < cert` to get the base64 string. Also update the `url` field to use `https`. + ## Testing in Kubernetes Follow these steps to test the broker in a Kubernetes cluster. For local testing we recommend using [minikube](https://kubernetes.io/docs/setup/learning-environment/minikube/). We also recommend using the [service catalog CLI](https://github.com/kubernetes-sigs/service-catalog/blob/master/docs/cli.md) (`svcat`) to control the service catalog. diff --git a/main.go b/main.go index e9c9638..118c575 100644 --- a/main.go +++ b/main.go @@ -92,21 +92,45 @@ func startBrokerServer() { baseURL := strings.TrimRight(getEnvOrDefault("ATLAS_BASE_URL", DefaultAtlasBaseURL), "/") router.Use(atlasbroker.AuthMiddleware(baseURL)) - // Mount broker server at the root. - http.Handle("/", router) + // Configure TLS from environment variables. + tlsEnabled, tlsCertPath, tlsKeyPath := getTLSConfig(logger) - // Try parsing server config and set up broker API server. host := getEnvOrDefault("BROKER_HOST", DefaultServerHost) port := getIntEnvOrDefault("BROKER_PORT", DefaultServerPort) - logger.Infow("Starting API server", "releaseVersion", releaseVersion, "host", host, "port", port, "atlas_base_url", baseURL) + + logger.Infow("Starting API server", "releaseVersion", releaseVersion, "host", host, "port", port, "tls_enabled", tlsEnabled, "atlas_base_url", baseURL) // Start broker HTTP server. - endpoint := host + ":" + strconv.Itoa(port) - if err = http.ListenAndServe(endpoint, nil); err != nil { - logger.Fatal(err) + address := host + ":" + strconv.Itoa(port) + + var serverErr error + if tlsEnabled { + serverErr = http.ListenAndServeTLS(address, tlsCertPath, tlsKeyPath, router) + } else { + logger.Warn("TLS is disabled") + serverErr = http.ListenAndServe(address, router) + } + + if serverErr != nil { + logger.Fatal(serverErr) } } +func getTLSConfig(logger *zap.SugaredLogger) (bool, string, string) { + certPath := getEnvOrDefault("BROKER_TLS_CERT_FILE", "") + keyPath := getEnvOrDefault("BROKER_TLS_KEY_FILE", "") + + hasCertPath := certPath != "" + hasKeyPath := keyPath != "" + + // Bail if only one of the cert and key has been provided. + if (hasCertPath && !hasKeyPath) || (!hasCertPath && hasKeyPath) { + logger.Fatal("Both a certificate and private key are necessary to enable TLS") + } + + return hasCertPath && hasKeyPath, certPath, keyPath +} + // getEnvOrPanic will try getting an environment variable and fail with a // helpful error message in case it doesn't exist. func getEnvOrPanic(name string) string { diff --git a/samples/kubernetes/deployment.yaml b/samples/kubernetes/deployment.yaml index e9b4408..ac67528 100644 --- a/samples/kubernetes/deployment.yaml +++ b/samples/kubernetes/deployment.yaml @@ -19,14 +19,11 @@ spec: containers: - name: atlas-service-broker image: quay.io/mongodb/mongodb-atlas-service-broker:latest - imagePullPolicy: Never ports: - containerPort: 4000 env: - name: BROKER_HOST value: "0.0.0.0" - - name: ATLAS_BASE_URL - value: https://cloud-qa.mongodb.com --- # Service to expose the service broker inside the cluster.