Read git auth token from backend config (#2992)

This commit is contained in:
Sachin Tewari
2020-10-22 13:01:32 +05:30
committed by GitHub
parent 9ccb2c871d
commit 1d652bbb2f
3 changed files with 140 additions and 33 deletions
+20 -27
View File
@@ -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) {
+116
View File
@@ -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;
}
};
+4 -6
View File
@@ -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}`;
}