Skip to content

Commit

Permalink
feat: Add basic TLS configuration checks (#599)
Browse files Browse the repository at this point in the history
* Add basic TLS configuration checks

Signed-off-by: Mykola Morhun <mmorhun@redhat.com>
  • Loading branch information
mmorhun committed Mar 25, 2020
1 parent 0cdfd51 commit 884028b
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 8 deletions.
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,15 @@ OPTIONS
-s, --tls
Enable TLS encryption.
Note, that this option is turned on by default for kubernetes infrastructure.
If it is needed to provide own certificate, 'che-tls' secret with TLS certificate must be
created in the configured namespace. Otherwise, it will be automatically generated.
Note, this option is turned on by default.
For Kubernetes infrastructure, it is required to provide own certificate: 'che-tls' secret with
TLS certificate must be pre-created in the configured namespace.
The only exception is Helm installer. In that case the secret will be generated automatically.
For OpenShift, router will use default cluster certificates.
If the certificate is self-signed, '--self-signed-cert' option should be provided, otherwise
Che won't be able to start.
Please see docs for more details:
https://www.eclipse.org/che/docs/che-7/setup-che-in-tls-mode-with-self-signed-certificate/
-t, --templates=templates
[default: templates] Path to the templates folder
Expand Down
9 changes: 6 additions & 3 deletions src/commands/server/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,12 @@ export default class Start extends Command {
tls: flags.boolean({
char: 's',
description: `Enable TLS encryption.
Note, that this option is turned on by default for kubernetes infrastructure.
If it is needed to provide own certificate, 'che-tls' secret with TLS certificate must be created in the configured namespace. Otherwise, it will be automatically generated.
For OpenShift, router will use default cluster certificates.`
Note, this option is turned on by default.
For Kubernetes infrastructure, it is required to provide own certificate: 'che-tls' secret with TLS certificate must be pre-created in the configured namespace.
The only exception is Helm installer. In that case the secret will be generated automatically.
For OpenShift, router will use default cluster certificates.
If the certificate is self-signed, '--self-signed-cert' option should be provided, otherwise Che won't be able to start.
Please see docs for more details: https://www.eclipse.org/che/docs/che-7/setup-che-in-tls-mode-with-self-signed-certificate/`
}),
'self-signed-cert': flags.boolean({
description: `Authorize usage of self signed certificates for encryption.
Expand Down
101 changes: 99 additions & 2 deletions src/tasks/installers/operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import { V1Deployment } from '@kubernetes/client-node'
import { Command } from '@oclif/command'
import { cli } from 'cli-ux'
import * as execa from 'execa'
import { readFileSync } from 'fs'
import * as fs from 'fs'
import { copy, mkdirp, remove } from 'fs-extra'
import * as yaml from 'js-yaml'
import * as Listr from 'listr'
import * as path from 'path'

import { CheHelper } from '../../api/che'
import { KubeHelper } from '../../api/kube'
import { isKubernetesPlatformFamily } from '../../util'

export class OperatorTasks {
operatorServiceAccount = 'che-operator'
Expand Down Expand Up @@ -60,6 +61,68 @@ export class OperatorTasks {
}
}
},
{
title: 'Checking for pre-created TLS secret',
// In case of Openshift infrastructure the certificate from cluster router will be used, so no need in the `che-tls` secret.
skip: () => !isKubernetesPlatformFamily(flags.platform),
task: async (_: any, task: any) => {
// Che is being deployed on Kubernetes infrastructure

if (! await this.checkTlsMode(flags)) {
// No TLS mode, skip this check
return
}

const cheSecretName = 'che-tls'
const cheSecret = await kube.getSecret(cheSecretName, flags.chenamespace)
if (cheSecret) {
task.title = `${task.title}... "${cheSecretName}" secret found`
return
}

// The secret is required but doesn't exist, show error message.
const errorMessage =
`Che TLS mode is turned on, but required "${cheSecretName}" secret is not pre-created in "${flags.chenamespace}" namespace, so Eclipse Che cannot be started. \n` +
'This is not bug in Eclipse Che and such behavior is expected. \n' +
'Please refer to Che documentation for more informations: ' +
'https://www.eclipse.org/che/docs/che-7/setup-che-in-tls-mode-with-self-signed-certificate/'
throw new Error(errorMessage)
}
},
{
title: 'Checking certificate',
// If the flag is set no need to check if it is required
skip: () => flags['self-signed-cert'],
task: async (_: any, task: any) => {
if (! await this.checkTlsMode(flags)) {
// No TLS mode, skip this check
return
}

const warningMessage = 'Self-signed certificate is used, so "--self-signed-cert" option is required. Added automatically.'

const platform = flags.platform
if (platform === 'minikube' || platform === 'crc' || platform === 'minishift') {
// There is no way to use real certificate on listed above platforms
cli.warn(warningMessage)
flags['self-signed-cert'] = true
task.title = `${task.title}... self-signed`
return
}

if (flags.domain && (flags.domain.endsWith('nip.io') || flags.domain.endsWith('xip.io'))) {
// It is not possible to use real certificate with *.nip.io and similar services
cli.warn(warningMessage)
flags['self-signed-cert'] = true
task.title = `${task.title}... self-signed`
return
}

// TODO check the secret certificate if it is commonly trusted.
cli.info('TLS mode is turned on, however we failed to determine whether self-signed certificate is used. \n\
Please rerun chectl with "--self-signed-cert" option if it is the case, otherwise Eclipse Che will fail to start.')
}
},
{
title: `Create ServiceAccount ${this.operatorServiceAccount} in namespace ${flags.chenamespace}`,
task: async (_ctx: any, task: any) => {
Expand Down Expand Up @@ -471,7 +534,7 @@ export class OperatorTasks {
return flags['che-operator-image']
} else {
const filePath = flags.templates + '/che-operator/operator.yaml'
const yamlFile = readFileSync(filePath)
const yamlFile = fs.readFileSync(filePath)
const yamlDeployment = yaml.safeLoad(yamlFile.toString()) as V1Deployment
return yamlDeployment.spec!.template.spec!.containers[0].image!
}
Expand All @@ -497,4 +560,38 @@ export class OperatorTasks {

return container.image
}

/**
* Checks if TLS is disabled via operator custom resource.
* Returns true if TLS is enabled (or omitted) and false if it is explicitly disabled.
*/
private async checkTlsMode(flags: any): Promise<boolean> {
if (flags['che-operator-cr-yaml']) {
const cheOperatorCrYamlPath = flags['che-operator-cr-yaml']
if (fs.existsSync(cheOperatorCrYamlPath)) {
const cr = yaml.safeLoad(fs.readFileSync(cheOperatorCrYamlPath).toString())
if (cr && cr.spec && cr.spec.server && cr.spec.server.tlsSupport === false) {
return false
}
}
}

if (flags['che-operator-cr-patch-yaml']) {
const cheOperatorCrPatchYamlPath = flags['che-operator-cr-patch-yaml']
if (fs.existsSync(cheOperatorCrPatchYamlPath)) {
const crPatch = yaml.safeLoad(fs.readFileSync(cheOperatorCrPatchYamlPath).toString())
if (crPatch && crPatch.spec && crPatch.spec.server && crPatch.spec.server.tlsSupport === false) {
return false
}
}
}

// If tls flag is undefined we suppose that tls is turned on
if (flags.tls === false) {
return false
}

// TLS is on
return true
}
}
8 changes: 8 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,11 @@ export function getClusterClientCommand(): string {

throw new Error('No cluster CLI client is installed.')
}

export function isKubernetesPlatformFamily(platform: string): boolean {
return platform === 'k8s' || platform === 'minikube' || platform === 'microk8s'
}

export function isOpenshiftPlatformFamily(platform: string): boolean {
return platform === 'openshift' || platform === 'minishift' || platform === 'crc'
}

0 comments on commit 884028b

Please sign in to comment.