diff --git a/WORKSPACE.yaml b/WORKSPACE.yaml index bff9ba10db40e1..ce9fe61f18d2e7 100644 --- a/WORKSPACE.yaml +++ b/WORKSPACE.yaml @@ -9,7 +9,7 @@ defaultArgs: localAppVersion: unknown codeCommit: 3fef802aa6bfd601cf182315ba949931401772f8 codeQuality: stable - intellijDownloadUrl: "https://download.jetbrains.com/idea/ideaIU-2022.1.4.tar.gz" + intellijDownloadUrl: "https://download.jetbrains.com/idea/ideaIU-2022.2.tar.gz" golandDownloadUrl: "https://download.jetbrains.com/go/goland-2022.1.4.tar.gz" pycharmDownloadUrl: "https://download.jetbrains.com/python/pycharm-professional-2022.1.4.tar.gz" phpstormDownloadUrl: "https://download.jetbrains.com/webide/PhpStorm-2022.1.4.tar.gz" diff --git a/components/server/ee/src/prebuilds/github-enterprise-app.ts b/components/server/ee/src/prebuilds/github-enterprise-app.ts index e5595b5a71cfeb..8447547b854484 100644 --- a/components/server/ee/src/prebuilds/github-enterprise-app.ts +++ b/components/server/ee/src/prebuilds/github-enterprise-app.ts @@ -57,7 +57,7 @@ export class GitHubEnterpriseApp { } if (!user) { res.statusCode = 401; - res.send("Unauthorized: Cannot find user."); + res.send("Unauthorized: Cannot find authorized user."); span.finish(); await this.webhookEvents.updateEvent(event.id, { status: "dismissed_unauthorized" }); return; @@ -82,7 +82,7 @@ export class GitHubEnterpriseApp { ctx: TraceContext, payload: GitHubEnterprisePushPayload, req: express.Request, - ): Promise { + ): Promise { const span = TraceContext.startSpan("GitHubEnterpriseApp.findUser", ctx); try { let host = req.header("X-Github-Enterprise-Host"); @@ -95,38 +95,39 @@ export class GitHubEnterpriseApp { if (!hostContext) { throw new Error("Unsupported GitHub Enterprise host: " + host); } - const { authProviderId } = hostContext.authProvider; - const authId = payload.sender.id; - const user = await this.userDB.findUserByIdentity({ authProviderId, authId }); - if (!user) { - throw new Error(`No user found with identity ${authProviderId}/${authId}.`); - } else if (!!user.blocked) { - throw new Error(`Blocked user ${user.id} tried to start prebuild.`); - } - const gitpodIdentity = user.identities.find( - (i) => i.authProviderId === TokenService.GITPOD_AUTH_PROVIDER_ID, - ); - if (!gitpodIdentity) { - throw new Error(`User ${user.id} has no identity for '${TokenService.GITPOD_AUTH_PROVIDER_ID}'.`); + const cloneURL = payload.repository.clone_url; + const projectOwners = await this.findProjectOwners(cloneURL); + if (!projectOwners) { + throw new Error("No project found."); } - // Verify the webhook signature - const signature = req.header("X-Hub-Signature-256"); - const body = (req as any).rawBody; - const tokenEntries = (await this.userDB.findTokensForIdentity(gitpodIdentity)).filter((tokenEntry) => { - return tokenEntry.token.scopes.includes(GitHubService.PREBUILD_TOKEN_SCOPE); - }); - const signingToken = tokenEntries.find((tokenEntry) => { - const sig = - "sha256=" + - createHmac("sha256", user.id + "|" + tokenEntry.token.value) - .update(body) - .digest("hex"); - return timingSafeEqual(Buffer.from(sig), Buffer.from(signature ?? "")); - }); - if (!signingToken) { - throw new Error(`User ${user.id} has no token matching the payload signature.`); + for (const user of projectOwners.users) { + const gitpodIdentity = user.identities.find( + (i) => i.authProviderId === TokenService.GITPOD_AUTH_PROVIDER_ID, + ); + if (!gitpodIdentity) { + continue; + } + // Verify the webhook signature + const signature = req.header("X-Hub-Signature-256"); + const body = (req as any).rawBody; + const tokenEntries = (await this.userDB.findTokensForIdentity(gitpodIdentity)).filter((tokenEntry) => { + return tokenEntry.token.scopes.includes(GitHubService.PREBUILD_TOKEN_SCOPE); + }); + const signatureMatched = tokenEntries.some((tokenEntry) => { + const sig = + "sha256=" + + createHmac("sha256", user.id + "|" + tokenEntry.token.value) + .update(body) + .digest("hex"); + return timingSafeEqual(Buffer.from(sig), Buffer.from(signature ?? "")); + }); + if (signatureMatched) { + if (!!user.blocked) { + throw new Error(`Blocked user ${user.id} tried to start prebuild.`); + } + return user; + } } - return user; } finally { span.finish(); } @@ -255,6 +256,33 @@ export class GitHubEnterpriseApp { return { user: webhookInstaller }; } + protected async findProjectOwners(cloneURL: string): Promise<{ users: User[]; project: Project } | undefined> { + const project = await this.projectDB.findProjectByCloneUrl(cloneURL); + if (project) { + if (project.userId) { + const user = await this.userDB.findUserById(project.userId); + if (user) { + return { users: [user], project }; + } + } else if (project.teamId) { + const users = []; + const owners = (await this.teamDB.findMembersByTeam(project.teamId || "")).filter( + (m) => m.role === "owner", + ); + const hostContext = this.hostContextProvider.get(new URL(cloneURL).host); + const authProviderId = hostContext?.authProvider.authProviderId; + for (const teamMember of owners) { + const user = await this.userDB.findUserById(teamMember.userId); + if (user && user.identities.some((i) => i.authProviderId === authProviderId)) { + users.push(user); + } + } + return { users, project }; + } + } + return undefined; + } + protected getBranchFromRef(ref: string): string | undefined { const headsPrefix = "refs/heads/"; if (ref.startsWith(headsPrefix)) { diff --git a/install/installer/pkg/components/image-builder-mk3/configmap.go b/install/installer/pkg/components/image-builder-mk3/configmap.go index d6300478c0af55..25a19c9eda1ab4 100644 --- a/install/installer/pkg/components/image-builder-mk3/configmap.go +++ b/install/installer/pkg/components/image-builder-mk3/configmap.go @@ -53,12 +53,17 @@ func configmap(ctx *common.RenderContext) ([]runtime.Object, error) { WorkspaceImageRepository: fmt.Sprintf("%s/workspace-images", registryName), } + workspaceImage := ctx.Config.Workspace.WorkspaceImage + if workspaceImage == "" { + workspaceImage = ctx.ImageName(common.ThirdPartyContainerRepo(ctx.Config.Repository, ""), workspace.DefaultWorkspaceImage, workspace.DefaultWorkspaceImageVersion) + } + imgcfg := config.ServiceConfig{ Orchestrator: orchestrator, RefCache: config.RefCacheConfig{ Interval: util.Duration(time.Hour * 6).String(), Refs: []string{ - ctx.ImageName(common.ThirdPartyContainerRepo(ctx.Config.Repository, ""), workspace.DefaultWorkspaceImage, workspace.DefaultWorkspaceImageVersion), + workspaceImage, }, }, Service: config.Service{ diff --git a/install/kots/manifests/kots-preflight.yaml b/install/kots/manifests/kots-preflight.yaml index 37272663315ce1..95eaf953f7c2ff 100644 --- a/install/kots/manifests/kots-preflight.yaml +++ b/install/kots/manifests/kots-preflight.yaml @@ -11,6 +11,7 @@ spec: collectorName: database image: eu.gcr.io/gitpod-core-dev/build/kots-config-check/database:sje-kots-config-check.9 name: database + namespace: '{{repl Namespace }}' args: - '{{repl ConfigOption "db_incluster" }}' # DB_IN_CLUSTER_ENABLED - '{{repl ConfigOption "db_cloudsql_enabled" }}' # DB_CLOUDSQL_ENABLED @@ -24,6 +25,7 @@ spec: collectorName: "kernel" image: alpine/semver name: kernel + namespace: '{{repl Namespace }}' command: - /bin/sh - -c @@ -33,6 +35,7 @@ spec: collectorName: registry image: eu.gcr.io/gitpod-core-dev/build/kots-config-check/registry:sje-kots-registry-check.16 name: registry + namespace: '{{repl Namespace }}' args: - '{{repl ConfigOption "reg_incluster" }}' # REG_IN_CLUSTER_ENABLED - '{{repl ConfigOption "reg_username" }}' # REG_USERNAME @@ -49,6 +52,7 @@ spec: collectorName: storage image: eu.gcr.io/gitpod-core-dev/build/kots-config-check/storage:sje-kots-storage-check.9 name: storage + namespace: '{{repl Namespace }}' args: - '{{repl ConfigOption "store_provider" }}' # STORE_PROVIDER - '{{repl ConfigOption "store_region" }}' # STORE_LOCATION @@ -65,6 +69,7 @@ spec: collectorName: ping-registry image: alpine/curl name: ping-registry + namespace: '{{repl Namespace }}' command: - /bin/sh - -c diff --git a/install/kots/manifests/kots-support-bundle.yaml b/install/kots/manifests/kots-support-bundle.yaml index 33fb521fd39c4c..c2de5313dbe3c8 100644 --- a/install/kots/manifests/kots-support-bundle.yaml +++ b/install/kots/manifests/kots-support-bundle.yaml @@ -11,6 +11,7 @@ spec: collectorName: database image: eu.gcr.io/gitpod-core-dev/build/kots-config-check/database:sje-kots-config-check.9 name: database + namespace: '{{repl Namespace }}' args: - '{{repl ConfigOption "db_incluster" }}' # DB_IN_CLUSTER_ENABLED - '{{repl ConfigOption "db_cloudsql_enabled" }}' # DB_CLOUDSQL_ENABLED @@ -24,6 +25,7 @@ spec: collectorName: registry image: eu.gcr.io/gitpod-core-dev/build/kots-config-check/registry:sje-kots-registry-check.16 name: registry + namespace: '{{repl Namespace }}' args: - '{{repl ConfigOption "reg_incluster" }}' # REG_IN_CLUSTER_ENABLED - '{{repl ConfigOption "reg_username" }}' # REG_USERNAME @@ -40,6 +42,7 @@ spec: collectorName: storage image: eu.gcr.io/gitpod-core-dev/build/kots-config-check/storage:sje-kots-storage-check.9 name: storage + namespace: '{{repl Namespace }}' args: - '{{repl ConfigOption "store_provider" }}' # STORE_PROVIDER - '{{repl ConfigOption "store_region" }}' # STORE_LOCATION @@ -55,6 +58,7 @@ spec: collectorName: ping-registry image: alpine/curl name: ping-registry + namespace: '{{repl Namespace }}' command: - /bin/sh - -c