diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cc28b9e7eba20a..e5ef1eb70a7e7d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -28,6 +28,7 @@ /components/image-builder-bob @gitpod-io/engineering-workspace /components/image-builder-mk3 @gitpod-io/engineering-workspace /components/installation-telemetry @gitpod-io/engineering-self-hosted +/components/kots-config-check @gitpod-io/engineering-self-hosted /install @gitpod-io/engineering-self-hosted /install/installer @gitpod-io/engineering-self-hosted # For testdata a single review from anyone who is allowed to review PRs is sufficent. diff --git a/components/BUILD.yaml b/components/BUILD.yaml index 66e53c5014ce82..331c5ce715c2c1 100644 --- a/components/BUILD.yaml +++ b/components/BUILD.yaml @@ -73,6 +73,7 @@ packages: - components/ide-proxy:docker - components/ide-metrics:docker - components/ide-service:docker + - components/kots-config-check/certificate:docker - components/kots-config-check/database:docker - components/kots-config-check/registry:docker - components/kots-config-check/storage:docker diff --git a/components/dashboard/src/contexts/FeatureFlagContext.tsx b/components/dashboard/src/contexts/FeatureFlagContext.tsx index 20a023c43b98ae..9241fee21fbc21 100644 --- a/components/dashboard/src/contexts/FeatureFlagContext.tsx +++ b/components/dashboard/src/contexts/FeatureFlagContext.tsx @@ -41,7 +41,7 @@ const FeatureFlagContextProvider: React.FC = ({ children }) => { const featureFlags: FeatureFlagConfig = { workspace_classes: { defaultValue: true, setter: setShowWorkspaceClassesUI }, persistent_volume_claim: { defaultValue: true, setter: setShowPersistentVolumeClaimUI }, - usage_view: { defaultValue: true, setter: setShowUsageView }, + usage_view: { defaultValue: false, setter: setShowUsageView }, }; for (const [flagName, config] of Object.entries(featureFlags)) { const flagValue = await getExperimentsClient().getValueAsync(flagName, config.defaultValue, { diff --git a/components/ide/jetbrains/backend-plugin/build.gradle.kts b/components/ide/jetbrains/backend-plugin/build.gradle.kts index 050cd2af3a3028..4fb80e18f5ce40 100644 --- a/components/ide/jetbrains/backend-plugin/build.gradle.kts +++ b/components/ide/jetbrains/backend-plugin/build.gradle.kts @@ -95,15 +95,15 @@ detekt { tasks { withType { - sourceCompatibility = "11" - targetCompatibility = "11" + sourceCompatibility = "17" + targetCompatibility = "17" } withType { - kotlinOptions.jvmTarget = "11" + kotlinOptions.jvmTarget = "17" } withType { - jvmTarget = "11" + jvmTarget = "17" } buildSearchableOptions { diff --git a/components/ide/jetbrains/backend-plugin/gradle-latest.properties b/components/ide/jetbrains/backend-plugin/gradle-latest.properties index 432be7d91738de..5a857327159a1b 100644 --- a/components/ide/jetbrains/backend-plugin/gradle-latest.properties +++ b/components/ide/jetbrains/backend-plugin/gradle-latest.properties @@ -1,9 +1,9 @@ # See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html # for insight into build numbers and IntelliJ Platform versions. -pluginSinceBuild=222 -pluginUntilBuild=222.* +pluginSinceBuild=223 +pluginUntilBuild=223.* # Plugin Verifier integration -> https://github.com/JetBrains/gradle-intellij-plugin#plugin-verifier-dsl # See https://jb.gg/intellij-platform-builds-list for available build versions. -pluginVerifierIdeVersions=2022.2 +pluginVerifierIdeVersions=2022.3 # Version from "com.jetbrains.intellij.idea" which can be found at https://www.jetbrains.com/intellij-repository/snapshots -platformVersion=222.4167-EAP-CANDIDATE-SNAPSHOT +platformVersion=223.4884-EAP-CANDIDATE-SNAPSHOT diff --git a/components/ide/jetbrains/backend-plugin/launch-dev-server.sh b/components/ide/jetbrains/backend-plugin/launch-dev-server.sh index 7616cef5b12c24..4919005a80ec47 100755 --- a/components/ide/jetbrains/backend-plugin/launch-dev-server.sh +++ b/components/ide/jetbrains/backend-plugin/launch-dev-server.sh @@ -6,10 +6,28 @@ set -e set -o pipefail +JB_QUALIFIER="latest" +while getopts "s" OPTION +do + case $OPTION in + s) JB_QUALIFIER="stable" ;; + *) ;; + esac +done + TEST_BACKEND_DIR=/workspace/ide-backend if [ ! -d "$TEST_BACKEND_DIR" ]; then mkdir -p $TEST_BACKEND_DIR - cp -r /ide-desktop/backend/* $TEST_BACKEND_DIR + if [[ $JB_QUALIFIER == "stable" ]]; then + PRODUCT_TYPE="release" + else + PRODUCT_TYPE="release,rc,eap" + fi + (cd $TEST_BACKEND_DIR && + echo "Downloading the ${JB_QUALIFIER} version of IntelliJ IDEA..." && + curl -sSLo backend.tar.gz "https://download.jetbrains.com/product?type=${PRODUCT_TYPE}&distribution=linux&code=IIU" && + tar -xf backend.tar.gz --strip-components=1 && + rm backend.tar.gz) fi TEST_PLUGINS_DIR="$TEST_BACKEND_DIR/plugins" @@ -17,7 +35,7 @@ TEST_PLUGIN_DIR="$TEST_PLUGINS_DIR/gitpod-remote" rm -rf $TEST_PLUGIN_DIR GITPOD_PLUGIN_DIR=/workspace/gitpod/components/ide/jetbrains/backend-plugin -$GITPOD_PLUGIN_DIR/gradlew buildPlugin +$GITPOD_PLUGIN_DIR/gradlew -PenvironmentName="$JB_QUALIFIER" buildPlugin # TODO(ak) actually should be gradle task to make use of output GITPOD_PLUGIN_DIST="$GITPOD_PLUGIN_DIR/build/distributions/gitpod-remote.zip" @@ -31,7 +49,7 @@ if [ ! -d "$TEST_DIR" ]; then case $OPTION in r) TEST_REPO=$OPTARG ;; *) ;; - esac + esac done git clone "$TEST_REPO" $TEST_DIR fi @@ -47,7 +65,7 @@ export IJ_HOST_SYSTEM_BASE_DIR=/workspace/.cache/JetBrains export CWM_HOST_STATUS_OVER_HTTP_TOKEN=gitpod # Build and move idea-cli, then overwrite environment variables initially defined by `components/ide/jetbrains/image/leeway.Dockerfile` -IDEA_CLI_DEV_PATH=/ide-desktop/bin/idea-cli-dev +IDEA_CLI_DEV_PATH=$TEST_BACKEND_DIR/bin/idea-cli-dev (cd ../cli && go build -o $IDEA_CLI_DEV_PATH) export EDITOR="$IDEA_CLI_DEV_PATH open" export VISUAL="$EDITOR" diff --git a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodCLIService.kt b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodCLIService.kt index 63b6f39892212f..29060c622d25e2 100644 --- a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodCLIService.kt +++ b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodCLIService.kt @@ -25,13 +25,17 @@ import io.netty.channel.ChannelHandlerContext import io.netty.handler.codec.http.FullHttpRequest import io.netty.handler.codec.http.QueryStringDecoder import io.prometheus.client.exporter.common.TextFormat +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.jetbrains.ide.RestService import org.jetbrains.io.response import java.io.OutputStreamWriter import java.nio.file.InvalidPathException import java.nio.file.Path -@Suppress("UnstableApiUsage") +@Suppress("UnstableApiUsage", "OPT_IN_USAGE") class GitpodCLIService : RestService() { private val manager = service() @@ -65,7 +69,11 @@ class GitpodCLIService : RestService() { val file = parseFilePath(fileStr) ?: return "invalid file" val shouldWait = getBooleanParameter("wait", urlDecoder) return withClient(request, context) { - CommandLineProcessor.doOpenFileOrProject(file, shouldWait).future.get() + GlobalScope.launch { + withContext(Dispatchers.IO) { + CommandLineProcessor.doOpenFileOrProject(file, shouldWait).future.get() + } + } } } if (operation == "preview") { diff --git a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodClientProjectSessionTracker.kt b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodClientProjectSessionTracker.kt index d00efb4b83584c..895e0f508993eb 100644 --- a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodClientProjectSessionTracker.kt +++ b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodClientProjectSessionTracker.kt @@ -6,7 +6,6 @@ package io.gitpod.jetbrains.remote import com.intellij.codeWithMe.ClientId import com.intellij.ide.BrowserUtil -import com.intellij.idea.StartupUtil import com.intellij.notification.NotificationAction import com.intellij.notification.NotificationType import com.intellij.openapi.Disposable @@ -29,7 +28,6 @@ import io.grpc.stub.ClientCallStreamObserver import io.grpc.stub.ClientResponseObserver import kotlinx.coroutines.* import kotlinx.coroutines.future.await -import org.jetbrains.ide.BuiltInServerManager import java.util.concurrent.CancellationException import java.util.concurrent.CompletableFuture @@ -44,6 +42,8 @@ class GitpodClientProjectSessionTracker( private lateinit var info: Info.WorkspaceInfoResponse private val lifetime = Lifetime.Eternal.createNested() + private val ignoredPortsForNotificationService = service() + override fun dispose() { lifetime.terminate() } @@ -118,10 +118,6 @@ class GitpodClientProjectSessionTracker( return@launch } - // Ignore ports that aren't actually used by the user (e.g. ports used internally by JetBrains IDEs) - val backendPort = BuiltInServerManager.getInstance().waitForStart().port - val serverPort = StartupUtil.getServerFuture().await().port - val ignorePorts = listOf(backendPort, serverPort, 5990) val portsStatus = hashMapOf() val status = StatusServiceGrpc.newStub(GitpodManager.supervisorChannel) @@ -141,7 +137,7 @@ class GitpodClientProjectSessionTracker( override fun onNext(ps: Status.PortsStatusResponse) { for (port in ps.portsList) { // Avoiding undesired notifications - if (ignorePorts.contains(port.localPort)) { + if (ignoredPortsForNotificationService.getIgnoredPorts().contains(port.localPort)) { continue } diff --git a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodIgnoredPortsForNotificationService.kt b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodIgnoredPortsForNotificationService.kt new file mode 100644 index 00000000000000..38832a441cc128 --- /dev/null +++ b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodIgnoredPortsForNotificationService.kt @@ -0,0 +1,11 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package io.gitpod.jetbrains.remote + +interface GitpodIgnoredPortsForNotificationService { + fun ignorePort(portNumber: Int) + /** Get ports that aren't actually used by the user (e.g. ports used internally by JetBrains IDEs) */ + fun getIgnoredPorts(): Set +} diff --git a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/latest/GitpodIgnoredPortsForNotificationServiceImpl.kt b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/latest/GitpodIgnoredPortsForNotificationServiceImpl.kt new file mode 100644 index 00000000000000..ff70c41f4bc79f --- /dev/null +++ b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/latest/GitpodIgnoredPortsForNotificationServiceImpl.kt @@ -0,0 +1,31 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package io.gitpod.jetbrains.remote.latest + +import com.intellij.idea.getServerFutureAsync +import io.gitpod.jetbrains.remote.GitpodIgnoredPortsForNotificationService +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import org.jetbrains.ide.BuiltInServerManager + +@Suppress("OPT_IN_USAGE") +class GitpodIgnoredPortsForNotificationServiceImpl : GitpodIgnoredPortsForNotificationService { + private val ignoredPortsForNotification = mutableSetOf(5990) + + init { + GlobalScope.launch { + BuiltInServerManager.getInstance().waitForStart().port.let { ignorePort(it) } + getServerFutureAsync().await()?.port?.let { ignorePort(it) } + } + } + + override fun ignorePort(portNumber: Int) { + ignoredPortsForNotification.add(portNumber) + } + + override fun getIgnoredPorts(): Set { + return ignoredPortsForNotification.toSet() + } +} diff --git a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/latest/GitpodPortForwardingService.kt b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/latest/GitpodPortForwardingService.kt index 669c3da12d9226..3e13e22a95ab57 100644 --- a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/latest/GitpodPortForwardingService.kt +++ b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/latest/GitpodPortForwardingService.kt @@ -91,8 +91,9 @@ class GitpodPortForwardingService(private val project: Project) { for (port in response.portsList) { val hostPort = port.localPort val isServed = port.served + val isForwarded = forwardedPortsList.find { it.hostPort == hostPort } != null - if (isServed && !forwardedPortsList.containsKey(hostPort)) { + if (isServed && !isForwarded) { val portEventsProcessor = object : PortEventsProcessor { override fun onPortForwarded(hostPort: Int, clientPort: Int) { portsService.setForwardedPort(hostPort, clientPort) @@ -111,7 +112,10 @@ class GitpodPortForwardingService(private val project: Project) { val portInfo = ForwardedPortInfo( hostPort, RdPortType.HTTP, - FORWARDED_PORT_LABEL, + port.exposed.url, + port.name, + port.description, + setOf(FORWARDED_PORT_LABEL), emptyList(), portEventsProcessor ) @@ -119,7 +123,7 @@ class GitpodPortForwardingService(private val project: Project) { portForwardingManager.forwardPort(portInfo) } - if (!isServed && forwardedPortsList.containsKey(hostPort)) { + if (!isServed && isForwarded) { portForwardingManager.removePort(hostPort) portsService.removeForwardedPort(hostPort) thisLogger().info("gitpod: Stopped forwarding port $hostPort.") diff --git a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/stable/GitpodIgnoredPortsForNotificationServiceImpl.kt b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/stable/GitpodIgnoredPortsForNotificationServiceImpl.kt new file mode 100644 index 00000000000000..3c64f1dfcd3c5c --- /dev/null +++ b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/stable/GitpodIgnoredPortsForNotificationServiceImpl.kt @@ -0,0 +1,32 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package io.gitpod.jetbrains.remote.stable + +import com.intellij.idea.StartupUtil +import io.gitpod.jetbrains.remote.GitpodIgnoredPortsForNotificationService +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.future.await +import org.jetbrains.ide.BuiltInServerManager + +@Suppress("OPT_IN_USAGE") +class GitpodIgnoredPortsForNotificationServiceImpl : GitpodIgnoredPortsForNotificationService { + private val ignoredPortsForNotification = mutableSetOf(5990) + + init { + GlobalScope.launch { + BuiltInServerManager.getInstance().waitForStart().port.let { ignorePort(it) } + StartupUtil.getServerFuture().await().port?.let { ignorePort(it) } + } + } + + override fun ignorePort(portNumber: Int) { + ignoredPortsForNotification.add(portNumber) + } + + override fun getIgnoredPorts(): Set { + return ignoredPortsForNotification.toSet() + } +} diff --git a/components/ide/jetbrains/backend-plugin/src/main/resources-latest/META-INF/extensions.xml b/components/ide/jetbrains/backend-plugin/src/main/resources-latest/META-INF/extensions.xml index 207e8a1a0003e1..b2ae56126e5d60 100644 --- a/components/ide/jetbrains/backend-plugin/src/main/resources-latest/META-INF/extensions.xml +++ b/components/ide/jetbrains/backend-plugin/src/main/resources-latest/META-INF/extensions.xml @@ -3,8 +3,10 @@ Licensed under the GNU Affero General Public License (AGPL). See License-AGPL.txt in the project root for license information. --> + + diff --git a/components/ide/jetbrains/backend-plugin/src/main/resources-stable/META-INF/extensions.xml b/components/ide/jetbrains/backend-plugin/src/main/resources-stable/META-INF/extensions.xml index edc5701e617818..a761b1b5842ba1 100644 --- a/components/ide/jetbrains/backend-plugin/src/main/resources-stable/META-INF/extensions.xml +++ b/components/ide/jetbrains/backend-plugin/src/main/resources-stable/META-INF/extensions.xml @@ -3,7 +3,9 @@ Licensed under the GNU Affero General Public License (AGPL). See License-AGPL.txt in the project root for license information. --> + + diff --git a/components/kots-config-check/certificate/BUILD.yaml b/components/kots-config-check/certificate/BUILD.yaml new file mode 100644 index 00000000000000..ee96c494ef4078 --- /dev/null +++ b/components/kots-config-check/certificate/BUILD.yaml @@ -0,0 +1,14 @@ +packages: + - name: docker + type: docker + argdeps: + - imageRepoBase + srcs: + - entrypoint.sh + config: + dockerfile: leeway.Dockerfile + metadata: + helm-component: kots-config-check.certificate + image: + - ${imageRepoBase}/kots-config-check/certificate:${version} + - ${imageRepoBase}/kots-config-check/certificate:commit-${__git_commit} diff --git a/components/kots-config-check/certificate/entrypoint.sh b/components/kots-config-check/certificate/entrypoint.sh new file mode 100755 index 00000000000000..32a317a166f7bb --- /dev/null +++ b/components/kots-config-check/certificate/entrypoint.sh @@ -0,0 +1,105 @@ +#!/bin/bash +# Copyright (c) 2022 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +set -euo pipefail + +DOMAIN="${1:-""}" +NAMESPACE="${2:-""}" +SECRET_NAME="${3:-""}" +TLS_CRT_KEY="${4:-"tls.crt"}" +TLS_KEY_KEY="${5:-"tls.key"}" + +cert_exists="false" +domain="false" +in_date="false" + +CRT_FILE="/tmp/tls.crt" +CRT_CONTENTS_FILE="/tmp/tls.crt.txt" +KEY_FILE="/tmp/tls.key" + +function get_cert() { + # Get certificate from secret + kubectl get secret \ + -n "${NAMESPACE}" \ + "${SECRET_NAME}" \ + -o jsonpath="{.data.${TLS_CRT_KEY//./\\.}}" \ + | base64 -d \ + > "${CRT_FILE}" || return 1 + + kubectl get secret \ + -n "${NAMESPACE}" \ + "${SECRET_NAME}" \ + -o jsonpath="{.data.${TLS_KEY_KEY//./\\.}}" \ + | base64 -d \ + > "${KEY_FILE}" || return 1 + + # Decode it as an x509 certificate + openssl x509 -in "${CRT_FILE}" -text -noout > "${CRT_CONTENTS_FILE}" + + CRT_SIG="$(openssl x509 -noout -modulus -in "${CRT_FILE}" | openssl md5)" + KEY_SIG="$(openssl rsa -noout -modulus -in "${KEY_FILE}" | openssl md5)" + + if [ "${CRT_SIG}" != "${KEY_SIG}" ]; then + echo "Certificate (${TLS_CRT_KEY}) does not match key (${TLS_KEY_KEY})" + return 1 + fi +} + +function cert_matches_domain_name() { + grep "${DOMAIN}" "${CRT_CONTENTS_FILE}" || return 1 + grep "\*.${DOMAIN}" "${CRT_CONTENTS_FILE}" || return 1 + grep "\*.ws.${DOMAIN}" "${CRT_CONTENTS_FILE}" || return 1 +} + +function cert_in_date() { + DATES="$(openssl x509 -in "${CRT_FILE}" -noout -dates)" + + START_DATE="$(echo "${DATES}" | awk -F= '{a[$1]=$2} END {print(a["notBefore"])}')" + END_DATE="$(echo "${DATES}" | awk -F= '{a[$1]=$2} END {print(a["notAfter"])}')" + + echo "Certificate start date: ${START_DATE}" + echo "Certificate end date: ${END_DATE}" + + START_EPOCH="$(date -u -D "%b %e %H:%M:%S %Y" -d "${START_DATE}" "+%s")" + END_EPOCH="$(date -u -D "%b %e %H:%M:%S %Y" -d "${END_DATE}" "+%s")" + NOW_EPOCH="$(date -u "+%s")" + + if [ "${NOW_EPOCH}" -gt "${START_EPOCH}" ] && [ "${NOW_EPOCH}" -lt "${END_EPOCH}" ]; then + echo "Certificate is in date" + return 0 + fi + + return 1 +} + +if get_cert; then + cert_exists="true" + + if cert_matches_domain_name; then + domain="true" + fi + + if cert_in_date; then + in_date="true" + fi +fi + +if [ "${cert_exists}" = "true" ]; then + echo "cert_exists: ok" +else + echo "cert_exists: error" +fi + +if [ "${domain}" = "true" ]; then + echo "domain_name: ok" +else + echo "domain_name: error" +fi + +if [ "${in_date}" = "true" ]; then + echo "in_date: ok" +else + echo "in_date: error" +fi diff --git a/components/kots-config-check/certificate/leeway.Dockerfile b/components/kots-config-check/certificate/leeway.Dockerfile new file mode 100644 index 00000000000000..b40652d700e96c --- /dev/null +++ b/components/kots-config-check/certificate/leeway.Dockerfile @@ -0,0 +1,9 @@ +# Copyright (c) 2022 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +FROM alpine/openssl +COPY --from=bitnami/kubectl /opt/bitnami/kubectl/bin/kubectl /usr/local/bin/kubectl +COPY entrypoint.sh /entrypoint.sh +RUN apk add --no-cache bash +ENTRYPOINT [ "/entrypoint.sh" ] diff --git a/components/server/ee/src/workspace/gitpod-server-impl.ts b/components/server/ee/src/workspace/gitpod-server-impl.ts index 40234b2956400e..28734eed559663 100644 --- a/components/server/ee/src/workspace/gitpod-server-impl.ts +++ b/components/server/ee/src/workspace/gitpod-server-impl.ts @@ -1596,11 +1596,13 @@ export class GitpodServerEEImpl extends GitpodServerImpl { { teamId, chargebeeSubscriptionId }, ); } - const subscriptionId = await this.stripeService.findUncancelledSubscriptionByAttributionId( - AttributionId.render({ kind: "team", teamId: teamId }), - ); - if (subscriptionId) { - await this.stripeService.cancelSubscription(subscriptionId); + if (this.config.enablePayment) { + const subscriptionId = await this.stripeService.findUncancelledSubscriptionByAttributionId( + AttributionId.render({ kind: "team", teamId: teamId }), + ); + if (subscriptionId) { + await this.stripeService.cancelSubscription(subscriptionId); + } } } diff --git a/components/ws-manager/pkg/manager/manager.go b/components/ws-manager/pkg/manager/manager.go index 96232c053fcac1..96398011a7321a 100644 --- a/components/ws-manager/pkg/manager/manager.go +++ b/components/ws-manager/pkg/manager/manager.go @@ -328,23 +328,23 @@ func (m *Manager) StartWorkspace(ctx context.Context, req *api.StartWorkspaceReq safePod, _ := log.RedactJSON(m) if k8serr.IsAlreadyExists(err) { - clog.WithError(err).WithField("req", req).WithField("pod", string(safePod)).Warn("was unable to start workspace which already exists") + clog.WithError(err).WithField("pod", string(safePod)).Warn("was unable to start workspace which already exists") return nil, status.Error(codes.AlreadyExists, "workspace instance already exists") } - clog.WithError(err).WithField("req", req).WithField("pod", string(safePod)).Warn("was unable to start workspace") + clog.WithError(err).WithField("pod", string(safePod)).Warn("was unable to start workspace") return nil, err } // if we reach this point the pod is created err = wait.PollImmediateWithContext(ctx, 100*time.Millisecond, 7*time.Minute, podRunning(m.Clientset, pod.Name, pod.Namespace)) if err != nil { - clog.WithError(err).WithField("req", req).WithField("pod", pod.Name).Warn("was unable to start workspace") + clog.WithError(err).WithField("pod", pod.Name).Warn("was unable to start workspace") if err == wait.ErrWaitTimeout && isPodUnschedulable(m.Clientset, pod.Name, pod.Namespace) { // this could be an error due to a scale-up event delErr := deleteWorkspacePodForce(m.Clientset, pod.Name, pod.Namespace) if delErr != nil { - clog.WithError(delErr).WithField("req", req).WithField("pod", pod.Name).Warn("was unable to delete workspace pod") + clog.WithError(delErr).WithField("pod", pod.Name).Warn("was unable to delete workspace pod") return nil, xerrors.Errorf("workspace pod never reached Running state: %w", err) } diff --git a/install/installer/cmd/testdata/render/aws-setup/output.golden b/install/installer/cmd/testdata/render/aws-setup/output.golden index 4f543fef1b68d0..216ebd030c9c47 100644 --- a/install/installer/cmd/testdata/render/aws-setup/output.golden +++ b/install/installer/cmd/testdata/render/aws-setup/output.golden @@ -4351,7 +4351,9 @@ data: "workspaceDefaults": { "workspaceImage": "docker.io/gitpod/workspace-full:latest", "previewFeatureFlags": [], - "defaultFeatureFlags": [] + "defaultFeatureFlags": [ + "protected_secrets" + ] }, "session": { "maxAgeMs": 259200000, @@ -8514,7 +8516,7 @@ spec: template: metadata: annotations: - gitpod.io/checksum_config: 995570947a2f55d5a098f8b0a2bfb24c210784db8d69664f6ac4f9b1f3107e24 + gitpod.io/checksum_config: ce0a2d97e238fbc5a51fc82603d9d34ee6f5ce5a1a86fcca196a984978917622 creationTimestamp: null labels: app: gitpod diff --git a/install/installer/cmd/testdata/render/azure-setup/output.golden b/install/installer/cmd/testdata/render/azure-setup/output.golden index 60bbfc7d3d70e0..946847eed7cd20 100644 --- a/install/installer/cmd/testdata/render/azure-setup/output.golden +++ b/install/installer/cmd/testdata/render/azure-setup/output.golden @@ -4214,7 +4214,9 @@ data: "workspaceDefaults": { "workspaceImage": "docker.io/gitpod/workspace-full:latest", "previewFeatureFlags": [], - "defaultFeatureFlags": [] + "defaultFeatureFlags": [ + "protected_secrets" + ] }, "session": { "maxAgeMs": 259200000, @@ -8365,7 +8367,7 @@ spec: template: metadata: annotations: - gitpod.io/checksum_config: 995570947a2f55d5a098f8b0a2bfb24c210784db8d69664f6ac4f9b1f3107e24 + gitpod.io/checksum_config: ce0a2d97e238fbc5a51fc82603d9d34ee6f5ce5a1a86fcca196a984978917622 creationTimestamp: null labels: app: gitpod diff --git a/install/installer/cmd/testdata/render/customization/output.golden b/install/installer/cmd/testdata/render/customization/output.golden index a82228df66376b..841084fb82a36d 100644 --- a/install/installer/cmd/testdata/render/customization/output.golden +++ b/install/installer/cmd/testdata/render/customization/output.golden @@ -5161,7 +5161,9 @@ data: "workspaceDefaults": { "workspaceImage": "docker.io/gitpod/workspace-full:latest", "previewFeatureFlags": [], - "defaultFeatureFlags": [] + "defaultFeatureFlags": [ + "protected_secrets" + ] }, "session": { "maxAgeMs": 259200000, @@ -9933,7 +9935,7 @@ spec: metadata: annotations: gitpod.io: hello - gitpod.io/checksum_config: 35452a9f4990442ea17f71d2d9e729d67c7e68b199c17018489a68e758d3727e + gitpod.io/checksum_config: 726633abfa81d0a9975542a43ae9193481d70a88ace564cc2d757af0bea11914 hello: world creationTimestamp: null labels: diff --git a/install/installer/cmd/testdata/render/external-registry/output.golden b/install/installer/cmd/testdata/render/external-registry/output.golden index 638a2572157bdd..a32bf8e4055518 100644 --- a/install/installer/cmd/testdata/render/external-registry/output.golden +++ b/install/installer/cmd/testdata/render/external-registry/output.golden @@ -4401,7 +4401,9 @@ data: "workspaceDefaults": { "workspaceImage": "docker.io/gitpod/workspace-full:latest", "previewFeatureFlags": [], - "defaultFeatureFlags": [] + "defaultFeatureFlags": [ + "protected_secrets" + ] }, "session": { "maxAgeMs": 259200000, @@ -8791,7 +8793,7 @@ spec: template: metadata: annotations: - gitpod.io/checksum_config: bf68cc4a7116d9616d776cb6f70b478533681e14350d22f09083c96ab2ab1983 + gitpod.io/checksum_config: f33e43e071a076a2e8bab7f7937c75b5081b6ae3002bedc79d89f5e73229ab9d creationTimestamp: null labels: app: gitpod diff --git a/install/installer/cmd/testdata/render/gcp-setup/output.golden b/install/installer/cmd/testdata/render/gcp-setup/output.golden index 3d3b6e41f4969d..e401ed1eb4d515 100644 --- a/install/installer/cmd/testdata/render/gcp-setup/output.golden +++ b/install/installer/cmd/testdata/render/gcp-setup/output.golden @@ -4175,7 +4175,9 @@ data: "workspaceDefaults": { "workspaceImage": "docker.io/gitpod/workspace-full:latest", "previewFeatureFlags": [], - "defaultFeatureFlags": [] + "defaultFeatureFlags": [ + "protected_secrets" + ] }, "session": { "maxAgeMs": 259200000, @@ -8294,7 +8296,7 @@ spec: template: metadata: annotations: - gitpod.io/checksum_config: f494f4b9ea8f35ead669c76cc215ace1626a68609c5fd5451de5e364c6367a9b + gitpod.io/checksum_config: af84bc676704bfd8f580529a808c9463fe65f3fb9acaf41eddeb1bf9426f6b3a creationTimestamp: null labels: app: gitpod diff --git a/install/installer/cmd/testdata/render/http-proxy/output.golden b/install/installer/cmd/testdata/render/http-proxy/output.golden index 6dce3b6042a3c4..e2309971ae476f 100644 --- a/install/installer/cmd/testdata/render/http-proxy/output.golden +++ b/install/installer/cmd/testdata/render/http-proxy/output.golden @@ -4624,7 +4624,9 @@ data: "workspaceDefaults": { "workspaceImage": "docker.io/gitpod/workspace-full:latest", "previewFeatureFlags": [], - "defaultFeatureFlags": [] + "defaultFeatureFlags": [ + "protected_secrets" + ] }, "session": { "maxAgeMs": 259200000, @@ -10212,7 +10214,7 @@ spec: template: metadata: annotations: - gitpod.io/checksum_config: bf68cc4a7116d9616d776cb6f70b478533681e14350d22f09083c96ab2ab1983 + gitpod.io/checksum_config: f33e43e071a076a2e8bab7f7937c75b5081b6ae3002bedc79d89f5e73229ab9d creationTimestamp: null labels: app: gitpod diff --git a/install/installer/cmd/testdata/render/insecure-s3-setup/output.golden b/install/installer/cmd/testdata/render/insecure-s3-setup/output.golden index abf1174e0abccc..3f50c014f29b02 100644 --- a/install/installer/cmd/testdata/render/insecure-s3-setup/output.golden +++ b/install/installer/cmd/testdata/render/insecure-s3-setup/output.golden @@ -4535,7 +4535,9 @@ data: "workspaceDefaults": { "workspaceImage": "docker.io/gitpod/workspace-full:latest", "previewFeatureFlags": [], - "defaultFeatureFlags": [] + "defaultFeatureFlags": [ + "protected_secrets" + ] }, "session": { "maxAgeMs": 259200000, @@ -8937,7 +8939,7 @@ spec: template: metadata: annotations: - gitpod.io/checksum_config: bf68cc4a7116d9616d776cb6f70b478533681e14350d22f09083c96ab2ab1983 + gitpod.io/checksum_config: f33e43e071a076a2e8bab7f7937c75b5081b6ae3002bedc79d89f5e73229ab9d creationTimestamp: null labels: app: gitpod diff --git a/install/installer/cmd/testdata/render/minimal/output.golden b/install/installer/cmd/testdata/render/minimal/output.golden index d162c1c63ca5f1..e331a7b72e2ca5 100644 --- a/install/installer/cmd/testdata/render/minimal/output.golden +++ b/install/installer/cmd/testdata/render/minimal/output.golden @@ -4621,7 +4621,9 @@ data: "workspaceDefaults": { "workspaceImage": "docker.io/gitpod/workspace-full:latest", "previewFeatureFlags": [], - "defaultFeatureFlags": [] + "defaultFeatureFlags": [ + "protected_secrets" + ] }, "session": { "maxAgeMs": 259200000, @@ -9166,7 +9168,7 @@ spec: template: metadata: annotations: - gitpod.io/checksum_config: bf68cc4a7116d9616d776cb6f70b478533681e14350d22f09083c96ab2ab1983 + gitpod.io/checksum_config: f33e43e071a076a2e8bab7f7937c75b5081b6ae3002bedc79d89f5e73229ab9d creationTimestamp: null labels: app: gitpod diff --git a/install/installer/cmd/testdata/render/statefulset-customization/output.golden b/install/installer/cmd/testdata/render/statefulset-customization/output.golden index f9d55799663eab..a8293326abd9dc 100644 --- a/install/installer/cmd/testdata/render/statefulset-customization/output.golden +++ b/install/installer/cmd/testdata/render/statefulset-customization/output.golden @@ -4633,7 +4633,9 @@ data: "workspaceDefaults": { "workspaceImage": "docker.io/gitpod/workspace-full:latest", "previewFeatureFlags": [], - "defaultFeatureFlags": [] + "defaultFeatureFlags": [ + "protected_secrets" + ] }, "session": { "maxAgeMs": 259200000, @@ -9178,7 +9180,7 @@ spec: template: metadata: annotations: - gitpod.io/checksum_config: bf68cc4a7116d9616d776cb6f70b478533681e14350d22f09083c96ab2ab1983 + gitpod.io/checksum_config: f33e43e071a076a2e8bab7f7937c75b5081b6ae3002bedc79d89f5e73229ab9d creationTimestamp: null labels: app: gitpod diff --git a/install/installer/cmd/testdata/render/use-pod-security-policies/output.golden b/install/installer/cmd/testdata/render/use-pod-security-policies/output.golden index 0a5fee05e68637..3fd593369d5ba1 100644 --- a/install/installer/cmd/testdata/render/use-pod-security-policies/output.golden +++ b/install/installer/cmd/testdata/render/use-pod-security-policies/output.golden @@ -4954,7 +4954,9 @@ data: "workspaceDefaults": { "workspaceImage": "docker.io/gitpod/workspace-full:latest", "previewFeatureFlags": [], - "defaultFeatureFlags": [] + "defaultFeatureFlags": [ + "protected_secrets" + ] }, "session": { "maxAgeMs": 259200000, @@ -9610,7 +9612,7 @@ spec: template: metadata: annotations: - gitpod.io/checksum_config: bf68cc4a7116d9616d776cb6f70b478533681e14350d22f09083c96ab2ab1983 + gitpod.io/checksum_config: f33e43e071a076a2e8bab7f7937c75b5081b6ae3002bedc79d89f5e73229ab9d creationTimestamp: null labels: app: gitpod diff --git a/install/installer/cmd/testdata/render/workspace-requests-limits/output.golden b/install/installer/cmd/testdata/render/workspace-requests-limits/output.golden index a65eba63f37434..28c4e64adb9310 100644 --- a/install/installer/cmd/testdata/render/workspace-requests-limits/output.golden +++ b/install/installer/cmd/testdata/render/workspace-requests-limits/output.golden @@ -4624,7 +4624,9 @@ data: "workspaceDefaults": { "workspaceImage": "docker.io/gitpod/workspace-full:latest", "previewFeatureFlags": [], - "defaultFeatureFlags": [] + "defaultFeatureFlags": [ + "protected_secrets" + ] }, "session": { "maxAgeMs": 259200000, @@ -9169,7 +9171,7 @@ spec: template: metadata: annotations: - gitpod.io/checksum_config: bf68cc4a7116d9616d776cb6f70b478533681e14350d22f09083c96ab2ab1983 + gitpod.io/checksum_config: f33e43e071a076a2e8bab7f7937c75b5081b6ae3002bedc79d89f5e73229ab9d creationTimestamp: null labels: app: gitpod diff --git a/install/installer/pkg/components/server/configmap.go b/install/installer/pkg/components/server/configmap.go index c972e051827983..ee798e9fcab133 100644 --- a/install/installer/pkg/components/server/configmap.go +++ b/install/installer/pkg/components/server/configmap.go @@ -162,6 +162,19 @@ func configmap(ctx *common.RenderContext) ([]runtime.Object, error) { return nil }) + // Enable protected_secrets by default + defaultFeatureFlags := []NamedWorkspaceFeatureFlag{NamedWorkspaceFeatureProtectedSecrets} + _ = ctx.WithExperimental(func(cfg *experimental.Config) error { + if cfg == nil || cfg.Workspace == nil || cfg.Workspace.EnableProtectedSecrets == nil { + return nil + } + if !*cfg.Workspace.EnableProtectedSecrets { + // Disable protected_secrets unless explicitly set to false in the installer configuration + defaultFeatureFlags = []NamedWorkspaceFeatureFlag{} + } + return nil + }) + // todo(sje): all these values are configurable scfg := ConfigSerialized{ Version: ctx.VersionManifest.Version, @@ -175,7 +188,7 @@ func configmap(ctx *common.RenderContext) ([]runtime.Object, error) { WorkspaceDefaults: WorkspaceDefaults{ WorkspaceImage: workspaceImage, PreviewFeatureFlags: []NamedWorkspaceFeatureFlag{}, - DefaultFeatureFlags: []NamedWorkspaceFeatureFlag{}, + DefaultFeatureFlags: defaultFeatureFlags, TimeoutDefault: ctx.Config.Workspace.TimeoutDefault, TimeoutExtended: ctx.Config.Workspace.TimeoutExtended, }, diff --git a/install/installer/pkg/components/server/types.go b/install/installer/pkg/components/server/types.go index 97f63aa0cd0f5a..5414b696b30278 100644 --- a/install/installer/pkg/components/server/types.go +++ b/install/installer/pkg/components/server/types.go @@ -147,6 +147,7 @@ type NamedWorkspaceFeatureFlag string const ( NamedWorkspaceFeatureFlagFullWorkspaceBackup NamedWorkspaceFeatureFlag = "full_workspace_backup" + NamedWorkspaceFeatureProtectedSecrets NamedWorkspaceFeatureFlag = "protected_secrets" ) type WorkspaceClassCategory string diff --git a/install/installer/pkg/config/v1/experimental/experimental.go b/install/installer/pkg/config/v1/experimental/experimental.go index 16746da15890ec..351f2736287e6d 100644 --- a/install/installer/pkg/config/v1/experimental/experimental.go +++ b/install/installer/pkg/config/v1/experimental/experimental.go @@ -119,6 +119,8 @@ type WorkspaceConfig struct { // Deprecated UsageReportBucketName string `json:"usageReportBucketName"` } `json:"contentService"` + + EnableProtectedSecrets *bool `json:"enableProtectedSecrets"` } type PersistentVolumeClaim struct { diff --git a/install/installer/scripts/kots-install.sh b/install/installer/scripts/kots-install.sh index be664bf76e5f04..91ef8eafc25c10 100755 --- a/install/installer/scripts/kots-install.sh +++ b/install/installer/scripts/kots-install.sh @@ -111,6 +111,11 @@ EOF return 0 fi + # Delete old serviceaccount/clusterrolebinding + echo "Deleting pre-2022.9.0 serviceaccount/clusterrolebinding" + kubectl delete serviceaccounts -n "${NAMESPACE}" installer || true + kubectl delete clusterrolebindings -n "${NAMESPACE}" installer || true + # Combine the pull secrets echo "${LOCAL_REGISTRY_IMAGE_PULL_DOCKER_CONFIG_JSON}" > /tmp/kotsregistry.json if [ "${REGISTRY_INCLUSTER_ENABLED}" = "1" ]; then diff --git a/install/kots/manifests/kots-support-bundle.yaml b/install/kots/manifests/kots-support-bundle.yaml index d0781baaf60769..c7c2e335e7eb0b 100644 --- a/install/kots/manifests/kots-support-bundle.yaml +++ b/install/kots/manifests/kots-support-bundle.yaml @@ -7,6 +7,20 @@ metadata: name: gitpod spec: collectors: + - runPod: + name: certificate + namespace: '{{repl Namespace }}' + podSpec: + serviceAccountName: kotsadm + containers: + - name: certificate + image: eu.gcr.io/gitpod-core-dev/build/kots-config-check/certificate:mrsimonemms-add-kots-support-bundle-11865.7 + args: + - '{{repl ConfigOption "domain" }}' # DOMAIN + - '{{repl Namespace }}' # NAMESPACE + - https-certificates # SECRET_NAME + - tls.crt # TLS_CRT_KEY + - tls.key # TLS_KEY_KEY - run: collectorName: database image: eu.gcr.io/gitpod-core-dev/build/kots-config-check/database:sje-kots-config-check.9 @@ -102,6 +116,11 @@ spec: - app=gitpod namespace: '{{repl Namespace }}' includeAllData: true + - configMap: + selector: + - kots.io/kotsadm=true + namespace: '{{repl Namespace }}' + includeAllData: true - secret: selector: - app=gitpod @@ -120,3 +139,34 @@ spec: - '{{repl LicenseFieldValue "appSlug" }}' - --namespace - '{{repl Namespace }}' + analyzers: + - textAnalyze: + checkName: TLS certificate exists + fileName: certificate/certificate.log + regexGroups: 'cert_exists: (?P\w+)' + outcomes: + - pass: + when: "Valid == ok" + message: TLS certificate exists + - fail: + message: TLS certificate does not exist. If using cert-manager, please check your settings and that your domain name is pointing to the correct name server. If you are supplying your own certificate, this will need to be re-uploaded. + - textAnalyze: + checkName: TLS certificate domain name + fileName: certificate/certificate.log + regexGroups: 'domain_name: (?P\w+)' + outcomes: + - pass: + when: "Valid == ok" + message: TLS certificate has the correct domain names + - fail: + message: TLS certificate does not have the correct domain names. It requires the DNS names `{{repl ConfigOption "domain" }}`, `*.{{repl ConfigOption "domain" }}` and `*.ws.{{repl ConfigOption "domain" }}` on the certificate. + - textAnalyze: + checkName: TLS certificate in date + fileName: certificate/certificate.log + regexGroups: 'in_date: (?P\w+)' + outcomes: + - pass: + when: "Valid == ok" + message: TLS certificate is in date + - fail: + message: TLS certificate is not date and will need to be reissued. If using cert-manager, please check your settings and that your domain name is pointing to the correct name server. If you are supplying your own certificate, this will need to be re-uploaded.