@backstage/integration 1.4.5 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,44 @@
1
1
  # @backstage/integration
2
2
 
3
+ ## 1.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a316d226c780: Add credential provider for GitLab.
8
+ - c7f848bcea3c: Support authentication with a service principal or managed identity for Azure DevOps
9
+
10
+ Azure DevOps recently released support, in public preview, for authenticating with a service principal or managed identity instead of a personal access token (PAT): https://devblogs.microsoft.com/devops/introducing-service-principal-and-managed-identity-support-on-azure-devops/. With this change the Azure integration now supports service principals and managed identities for Azure AD backed Azure DevOps organizations. Service principal and managed identity authentication is not supported on Azure DevOps Server (on-premises) organizations.
11
+
12
+ ### Patch Changes
13
+
14
+ - 3c83550fdb62: Renamed ClientSecret to AzureClientSecretCredential and ManagedIdentity to AzureManagedIdentityCredential
15
+ - df8411779da1: Add support for Repository Variables and Secrets to the `publish:github` and `github:repo:create` scaffolder actions. You will need to add `read/write` permissions to your GITHUB_TOKEN and/or Github Backstage App for Repository `Secrets` and `Variables`
16
+
17
+ Upgrade octokit introduces some breaking changes.
18
+
19
+ - Updated dependencies
20
+ - @backstage/errors@1.2.0
21
+ - @backstage/config@1.0.8
22
+
23
+ ## 1.5.0-next.0
24
+
25
+ ### Minor Changes
26
+
27
+ - a316d226c780: Add credential provider for GitLab.
28
+ - c7f848bcea3c: Support authentication with a service principal or managed identity for Azure DevOps
29
+
30
+ Azure DevOps recently released support, in public preview, for authenticating with a service principal or managed identity instead of a personal access token (PAT): https://devblogs.microsoft.com/devops/introducing-service-principal-and-managed-identity-support-on-azure-devops/. With this change the Azure integration now supports service principals and managed identities for Azure AD backed Azure DevOps organizations. Service principal and managed identity authentication is not supported on Azure DevOps Server (on-premises) organizations.
31
+
32
+ ### Patch Changes
33
+
34
+ - df8411779da1: Add support for Repository Variables and Secrets to the `publish:github` and `github:repo:create` scaffolder actions. You will need to add `read/write` permissions to your GITHUB_TOKEN and/or Github Backstage App for Repository `Secrets` and `Variables`
35
+
36
+ Upgrade octokit introduces some breaking changes.
37
+
38
+ - Updated dependencies
39
+ - @backstage/errors@1.2.0-next.0
40
+ - @backstage/config@1.0.7
41
+
3
42
  ## 1.4.5
4
43
 
5
44
  ### Patch Changes
package/dist/index.cjs.js CHANGED
@@ -4,6 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var parseGitUrl = require('git-url-parse');
6
6
  var lodash = require('lodash');
7
+ var identity = require('@azure/identity');
7
8
  var fetch = require('cross-fetch');
8
9
  var authApp = require('@octokit/auth-app');
9
10
  var rest = require('@octokit/rest');
@@ -343,16 +344,43 @@ _ref = new WeakMap();
343
344
  _baseUrl = new WeakMap();
344
345
 
345
346
  const AZURE_HOST = "dev.azure.com";
347
+ const isAzureClientSecretCredential = (credential) => {
348
+ const clientSecretCredential = credential;
349
+ return Object.keys(credential).length === 3 && clientSecretCredential.clientId !== void 0 && clientSecretCredential.clientSecret !== void 0 && clientSecretCredential.tenantId !== void 0;
350
+ };
351
+ const isAzureManagedIdentityCredential = (credential) => {
352
+ return Object.keys(credential).length === 1 && credential.clientId !== void 0;
353
+ };
346
354
  function readAzureIntegrationConfig(config) {
347
355
  var _a;
348
356
  const host = (_a = config.getOptionalString("host")) != null ? _a : AZURE_HOST;
349
357
  const token = config.getOptionalString("token");
358
+ const credential = config.getOptional("credential") ? {
359
+ tenantId: config.getOptionalString("credential.tenantId"),
360
+ clientId: config.getOptionalString("credential.clientId"),
361
+ clientSecret: config.getOptionalString("credential.clientSecret")
362
+ } : void 0;
350
363
  if (!isValidHost(host)) {
351
364
  throw new Error(
352
365
  `Invalid Azure integration config, '${host}' is not a valid host`
353
366
  );
354
367
  }
355
- return { host, token };
368
+ if (credential && !isAzureClientSecretCredential(credential) && !isAzureManagedIdentityCredential(credential)) {
369
+ throw new Error(
370
+ `Invalid Azure integration config, credential is not valid`
371
+ );
372
+ }
373
+ if (credential && host !== AZURE_HOST) {
374
+ throw new Error(
375
+ `Invalid Azure integration config, credential can only be used with ${AZURE_HOST}`
376
+ );
377
+ }
378
+ if (credential && token) {
379
+ throw new Error(
380
+ `Invalid Azure integration config, specify either a token or a credential but not both`
381
+ );
382
+ }
383
+ return { host, token, credential };
356
384
  }
357
385
  function readAzureIntegrationConfigs(configs) {
358
386
  const result = configs.map(readAzureIntegrationConfig);
@@ -428,9 +456,27 @@ function getAzureDownloadUrl(url) {
428
456
  function getAzureCommitsUrl(url) {
429
457
  return AzureUrl.fromRepoUrl(url).toCommitsUrl();
430
458
  }
431
- function getAzureRequestOptions(config, additionalHeaders) {
459
+ async function getAzureRequestOptions(config, additionalHeaders) {
460
+ const azureDevOpsScope = "499b84ac-1321-427f-aa17-267ca6975798/.default";
432
461
  const headers = additionalHeaders ? { ...additionalHeaders } : {};
433
- if (config.token) {
462
+ const { token, credential } = config;
463
+ if (credential) {
464
+ if (isAzureClientSecretCredential(credential)) {
465
+ const servicePrincipal = new identity.ClientSecretCredential(
466
+ credential.tenantId,
467
+ credential.clientId,
468
+ credential.clientSecret
469
+ );
470
+ const accessToken = await servicePrincipal.getToken(azureDevOpsScope);
471
+ headers.Authorization = `Bearer ${accessToken.token}`;
472
+ } else if (isAzureManagedIdentityCredential(credential)) {
473
+ const managedIdentity = new identity.ManagedIdentityCredential(
474
+ credential.clientId
475
+ );
476
+ const accessToken = await managedIdentity.getToken(azureDevOpsScope);
477
+ headers.Authorization = `Bearer ${accessToken.token}`;
478
+ }
479
+ } else if (token) {
434
480
  const buffer = Buffer.from(`:${config.token}`, "utf8");
435
481
  headers.Authorization = `Basic ${buffer.toString("base64")}`;
436
482
  }
@@ -1313,8 +1359,8 @@ class GithubAppManager {
1313
1359
  const allInstallations = await this.getInstallations();
1314
1360
  const installation = allInstallations.find(
1315
1361
  (inst) => {
1316
- var _a, _b;
1317
- return ((_b = (_a = inst.account) == null ? void 0 : _a.login) == null ? void 0 : _b.toLocaleLowerCase("en-US")) === owner.toLocaleLowerCase("en-US");
1362
+ var _a;
1363
+ return inst.account && "login" in inst.account && ((_a = inst.account.login) == null ? void 0 : _a.toLocaleLowerCase("en-US")) === owner.toLocaleLowerCase("en-US");
1318
1364
  }
1319
1365
  );
1320
1366
  if (installation) {
@@ -1675,6 +1721,51 @@ function replaceGitLabUrlType(url, type) {
1675
1721
  return url.replace(/\/\-\/(blob|tree|edit)\//, `/-/${type}/`);
1676
1722
  }
1677
1723
 
1724
+ const _SingleInstanceGitlabCredentialsProvider = class {
1725
+ constructor(token) {
1726
+ this.token = token;
1727
+ }
1728
+ async getCredentials(_opts) {
1729
+ if (!this.token) {
1730
+ return {};
1731
+ }
1732
+ return {
1733
+ headers: {
1734
+ Authorization: `Bearer ${this.token}`
1735
+ },
1736
+ token: this.token
1737
+ };
1738
+ }
1739
+ };
1740
+ let SingleInstanceGitlabCredentialsProvider = _SingleInstanceGitlabCredentialsProvider;
1741
+ SingleInstanceGitlabCredentialsProvider.create = (config) => {
1742
+ return new _SingleInstanceGitlabCredentialsProvider(config.token);
1743
+ };
1744
+
1745
+ class DefaultGitlabCredentialsProvider {
1746
+ constructor(providers) {
1747
+ this.providers = providers;
1748
+ }
1749
+ static fromIntegrations(integrations) {
1750
+ const credentialsProviders = /* @__PURE__ */ new Map();
1751
+ integrations.gitlab.list().forEach((integration) => {
1752
+ const credentialsProvider = SingleInstanceGitlabCredentialsProvider.create(integration.config);
1753
+ credentialsProviders.set(integration.config.host, credentialsProvider);
1754
+ });
1755
+ return new DefaultGitlabCredentialsProvider(credentialsProviders);
1756
+ }
1757
+ async getCredentials(opts) {
1758
+ const parsed = new URL(opts.url);
1759
+ const provider = this.providers.get(parsed.host);
1760
+ if (!provider) {
1761
+ throw new Error(
1762
+ `There is no GitLab integration that matches ${opts.url}. Please add a configuration for an integration.`
1763
+ );
1764
+ }
1765
+ return provider.getCredentials(opts);
1766
+ }
1767
+ }
1768
+
1678
1769
  function readGoogleGcsIntegrationConfig(config) {
1679
1770
  if (!config) {
1680
1771
  return {};
@@ -1776,6 +1867,7 @@ exports.BitbucketCloudIntegration = BitbucketCloudIntegration;
1776
1867
  exports.BitbucketIntegration = BitbucketIntegration;
1777
1868
  exports.BitbucketServerIntegration = BitbucketServerIntegration;
1778
1869
  exports.DefaultGithubCredentialsProvider = DefaultGithubCredentialsProvider;
1870
+ exports.DefaultGitlabCredentialsProvider = DefaultGitlabCredentialsProvider;
1779
1871
  exports.GerritIntegration = GerritIntegration;
1780
1872
  exports.GitHubIntegration = GitHubIntegration;
1781
1873
  exports.GitLabIntegration = GitLabIntegration;