Read git auth token from backend config (#2992)
This commit is contained in:
@@ -17,6 +17,13 @@ import fetch, { RequestInit } from 'node-fetch';
|
||||
import parseGitUrl from 'git-url-parse';
|
||||
import { Config } from '@backstage/config';
|
||||
import { getRootLogger, loadBackendConfig } from '@backstage/backend-common';
|
||||
import {
|
||||
getAzureHostToken,
|
||||
getGitHost,
|
||||
getGithubHostToken,
|
||||
getGitlabHostToken,
|
||||
getGitRepoType,
|
||||
} from './git-auth';
|
||||
|
||||
interface IGitlabBranch {
|
||||
name: string;
|
||||
@@ -73,15 +80,12 @@ function getAzureApiUrl(url: string): URL {
|
||||
);
|
||||
}
|
||||
|
||||
function getGithubRequestOptions(config: Config): RequestInit {
|
||||
function getGithubRequestOptions(config: Config, host: string): RequestInit {
|
||||
const headers: HeadersInit = {
|
||||
Accept: 'application/vnd.github.v3.raw',
|
||||
};
|
||||
|
||||
const token =
|
||||
config.getOptionalString('catalog.processors.github.privateToken') ??
|
||||
config.getOptionalString('catalog.processors.githubApi.privateToken') ??
|
||||
process.env.GITHUB_TOKEN;
|
||||
const token = getGithubHostToken(config, host);
|
||||
|
||||
if (token) {
|
||||
headers.Authorization = `token ${token}`;
|
||||
@@ -92,16 +96,12 @@ function getGithubRequestOptions(config: Config): RequestInit {
|
||||
};
|
||||
}
|
||||
|
||||
function getGitlabRequestOptions(config: Config): RequestInit {
|
||||
function getGitlabRequestOptions(config: Config, host: string): RequestInit {
|
||||
const headers: HeadersInit = {
|
||||
'PRIVATE-TOKEN': '',
|
||||
};
|
||||
|
||||
const token =
|
||||
config.getOptionalString('catalog.processors.gitlab.privateToken') ??
|
||||
config.getOptionalString('catalog.processors.gitlabApi.privateToken') ??
|
||||
process.env.GITLAB_TOKEN;
|
||||
|
||||
const token = getGitlabHostToken(config, host);
|
||||
if (token) {
|
||||
headers['PRIVATE-TOKEN'] = token;
|
||||
}
|
||||
@@ -111,12 +111,10 @@ function getGitlabRequestOptions(config: Config): RequestInit {
|
||||
};
|
||||
}
|
||||
|
||||
function getAzureRequestOptions(config: Config): RequestInit {
|
||||
function getAzureRequestOptions(config: Config, host: string): RequestInit {
|
||||
const headers: HeadersInit = {};
|
||||
|
||||
const token =
|
||||
config.getOptionalString('catalog.processors.azureApi.privateToken') ??
|
||||
process.env.AZURE_TOKEN;
|
||||
const token = getAzureHostToken(config, host);
|
||||
|
||||
if (token !== '') {
|
||||
headers.Authorization = `Basic ${Buffer.from(`:${token}`, 'utf8').toString(
|
||||
@@ -136,7 +134,8 @@ async function getGithubDefaultBranch(
|
||||
config: Config,
|
||||
): Promise<string> {
|
||||
const path = getGithubApiUrl(config, repositoryUrl).toString();
|
||||
const options = getGithubRequestOptions(config);
|
||||
const host = getGitHost(repositoryUrl);
|
||||
const options = getGithubRequestOptions(config, host);
|
||||
|
||||
try {
|
||||
const raw = await fetch(path, options);
|
||||
@@ -165,7 +164,8 @@ async function getGitlabDefaultBranch(
|
||||
): Promise<string> {
|
||||
const path = getGitlabApiUrl(repositoryUrl).toString();
|
||||
|
||||
const options = getGitlabRequestOptions(config);
|
||||
const gitlabHost = getGitHost(repositoryUrl);
|
||||
const options = getGitlabRequestOptions(config, gitlabHost);
|
||||
|
||||
try {
|
||||
const raw = await fetch(path, options);
|
||||
@@ -196,8 +196,8 @@ async function getAzureDefaultBranch(
|
||||
config: Config,
|
||||
): Promise<string> {
|
||||
const path = getAzureApiUrl(repositoryUrl).toString();
|
||||
|
||||
const options = getAzureRequestOptions(config);
|
||||
const host = getGitHost(repositoryUrl);
|
||||
const options = getAzureRequestOptions(config, host);
|
||||
|
||||
try {
|
||||
const urlResponse = await fetch(path, options);
|
||||
@@ -232,14 +232,7 @@ export const getDefaultBranch = async (
|
||||
): Promise<string> => {
|
||||
// TODO(Rugvip): Config should not be loaded here, pass it in instead
|
||||
const config = await loadBackendConfig({ logger: getRootLogger() });
|
||||
const typeMapping = [
|
||||
{ url: /github*/g, type: 'github' },
|
||||
{ url: /gitlab*/g, type: 'gitlab' },
|
||||
{ url: /azure*/g, type: 'azure/api' },
|
||||
];
|
||||
|
||||
const type = typeMapping.filter(item => item.url.test(repositoryUrl))[0]
|
||||
?.type;
|
||||
const type = getGitRepoType(repositoryUrl);
|
||||
|
||||
try {
|
||||
switch (type) {
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import parseGitUrl from 'git-url-parse';
|
||||
import { Config } from '@backstage/config';
|
||||
import { getRootLogger, loadBackendConfig } from '@backstage/backend-common';
|
||||
|
||||
export function getGitHost(url: string): string {
|
||||
const { resource } = parseGitUrl(url);
|
||||
return resource;
|
||||
}
|
||||
|
||||
export function getGitRepoType(url: string): string {
|
||||
const typeMapping = [
|
||||
{ url: /github*/g, type: 'github' },
|
||||
{ url: /gitlab*/g, type: 'gitlab' },
|
||||
{ url: /azure*/g, type: 'azure/api' },
|
||||
];
|
||||
|
||||
const type = typeMapping.filter(item => item.url.test(url))[0]?.type;
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
export function getGithubHostToken(
|
||||
config: Config,
|
||||
host: string,
|
||||
): string | undefined {
|
||||
const providerConfigs =
|
||||
config.getOptionalConfigArray('integrations.github') ?? [];
|
||||
|
||||
const hostConfig = providerConfigs.filter(
|
||||
providerConfig => providerConfig.getOptionalString('host') === host,
|
||||
);
|
||||
const token =
|
||||
hostConfig[0]?.getOptionalString('token') ??
|
||||
config.getOptionalString('catalog.processors.github.privateToken') ??
|
||||
config.getOptionalString('catalog.processors.githubApi.privateToken') ??
|
||||
process.env.GITHUB_TOKEN;
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
export function getGitlabHostToken(
|
||||
config: Config,
|
||||
host: string,
|
||||
): string | undefined {
|
||||
const providerConfigs =
|
||||
config.getOptionalConfigArray('integrations.gitlab') ?? [];
|
||||
|
||||
const hostConfig = providerConfigs.filter(
|
||||
providerConfig => providerConfig.getOptionalString('host') === host,
|
||||
);
|
||||
const token =
|
||||
hostConfig[0]?.getOptionalString('token') ??
|
||||
config.getOptionalString('catalog.processors.gitlab.privateToken') ??
|
||||
config.getOptionalString('catalog.processors.gitlabApi.privateToken') ??
|
||||
process.env.GITLAB_TOKEN;
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
export function getAzureHostToken(
|
||||
config: Config,
|
||||
host: string,
|
||||
): string | undefined {
|
||||
const providerConfigs =
|
||||
config.getOptionalConfigArray('integrations.azure') ?? [];
|
||||
|
||||
const hostConfig = providerConfigs.filter(
|
||||
providerConfig => providerConfig.getOptionalString('host') === host,
|
||||
);
|
||||
const token =
|
||||
hostConfig[0]?.getOptionalString('token') ??
|
||||
config.getOptionalString('catalog.processors.azureApi.privateToken') ??
|
||||
process.env.AZURE_TOKEN;
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
export const getTokenForGitRepo = async (
|
||||
repositoryUrl: string,
|
||||
): Promise<string | undefined> => {
|
||||
const config = await loadBackendConfig({ logger: getRootLogger() });
|
||||
|
||||
const host = getGitHost(repositoryUrl);
|
||||
const type = getGitRepoType(repositoryUrl);
|
||||
|
||||
try {
|
||||
switch (type) {
|
||||
case 'github':
|
||||
return getGithubHostToken(config, host);
|
||||
case 'gitlab':
|
||||
return getGitlabHostToken(config, host);
|
||||
case 'azure/api':
|
||||
return getAzureHostToken(config, host);
|
||||
|
||||
default:
|
||||
throw new Error('Failed to get repository type');
|
||||
}
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@@ -20,6 +20,7 @@ import parseGitUrl from 'git-url-parse';
|
||||
import NodeGit, { Clone, Repository } from 'nodegit';
|
||||
import fs from 'fs-extra';
|
||||
import { getDefaultBranch } from './default-branch';
|
||||
import { getTokenForGitRepo } from './git-auth';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { InputError } from '@backstage/backend-common';
|
||||
import { RemoteProtocol } from './techdocs/stages/prepare/types';
|
||||
@@ -127,11 +128,8 @@ export const checkoutGitRepository = async (
|
||||
process.env.GITLAB_PRIVATE_TOKEN_USER ||
|
||||
process.env.AZURE_PRIVATE_TOKEN_USER ||
|
||||
'';
|
||||
const token =
|
||||
process.env.GITHUB_TOKEN ||
|
||||
process.env.GITLAB_PRIVATE_TOKEN_USER ||
|
||||
process.env.AZURE_TOKEN ||
|
||||
'';
|
||||
|
||||
const token = await getTokenForGitRepo(repoUrl);
|
||||
|
||||
if (fs.existsSync(repositoryTmpPath)) {
|
||||
try {
|
||||
@@ -153,7 +151,7 @@ export const checkoutGitRepository = async (
|
||||
}
|
||||
}
|
||||
|
||||
if (user && token) {
|
||||
if (token) {
|
||||
parsedGitLocation.token = `${user}:${token}`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user