Merge branch 'master' into removetrunc

Signed-off-by: PIYUSH NEGI <43876655+npiyush97@users.noreply.github.com>
This commit is contained in:
PIYUSH NEGI
2024-05-10 17:25:23 +05:30
committed by GitHub
425 changed files with 15276 additions and 9256 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-search-backend-module-elasticsearch': patch
---
Fix never resolved indexer promise.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-node': minor
---
Added `LocationAnalyzer` type, moved from `@backstage/plugin-catalog-backend`.
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
The `build-workspace` command no longer manually runs `yarn postpack`, relying instead on the fact that running `yarn pack` will automatically invoke the `postpack` script. No action is necessary if you are running the latest version of yarn 1, 3, or 4.
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/plugin-catalog-backend-module-unprocessed': patch
'@backstage/backend-dynamic-feature-service': patch
'@backstage/plugin-search-backend-module-catalog': patch
---
Updated `README.md` to point to `packages/backend` instead of `packages/backend-next`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/create-app': patch
---
Bumped create-app version.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-gitlab': patch
---
Add merge method and squash option for project creation
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend': minor
---
Deprecated the `LocationAnalyzer` type, which has been moved to `@backstage/plugin-catalog-node`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-common': patch
---
Plugins created through the `legacyPlugin` helper are now able to authenticate requests from plugins that are fully implemented using the new backend system. This fixes the `Key for the ES256 algorithm must be one of type KeyObject or CryptoKey. Received an instance of Uint8Array` error.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-devtools-backend': patch
---
Added discovery property to the readme documentation to ensure that it will build when setting it up as new to a Backstage instance
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend': minor
---
The `/alpha` plugin export has had its implementation of the `catalogAnalysisExtensionPoint` updated to reflect the new API.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-scaffolder-backend': patch
'@backstage/plugin-scaffolder-node': patch
---
Scaffolder workspace serialization
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-signals-backend': patch
---
Improved signal lifecycle management and added server side pinging of connections
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-app-api': minor
---
Extensions in app-config now always affect ordering. Previously, only when enabling disabled extensions did they rise to the top.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-techdocs-backend': patch
'@backstage/plugin-techdocs': patch
---
The `techdocs.builder` config is now optional and it will default to `local`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-github': patch
---
Adding support to change the default commit author for `publish:github:pull-request`
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-notifications': patch
---
Add a new scaffolder action to allow sending notifications from templates
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-catalog-backend-module-github': patch
---
GitHub push events now schedule a refresh on entities that have a `refresh_key` matching the `catalogPath` config itself.
This allows to support a `catalogPath` configuration that uses glob patterns.
+40 -1
View File
@@ -283,73 +283,112 @@
"@backstage/plugin-vault-node": "0.1.10",
"@backstage/plugin-xcmetrics": "0.2.52",
"@backstage/plugin-catalog-backend-module-gitlab-org": "0.0.0",
"@backstage/plugin-notifications-backend-module-email": "0.0.0"
"@backstage/plugin-notifications-backend-module-email": "0.0.0",
"example-backend-legacy": "0.2.98-next.1",
"@backstage/plugin-scaffolder-backend-module-notifications": "0.0.0"
},
"changesets": [
"afraid-needles-divide",
"blue-hotels-shake",
"brave-carrots-glow",
"bright-pumpkins-rule",
"chatty-cycles-unite",
"chilly-adults-sing",
"chilly-fireants-roll",
"chilly-shoes-doubt",
"cold-cougars-float",
"cold-rats-leave",
"cool-elephants-march",
"create-app-1714476054",
"create-app-1715088359",
"cuddly-chairs-kick",
"curly-shirts-flow",
"curvy-planes-flash",
"cyan-eagles-hammer",
"cyan-suns-shave",
"dirty-chairs-march",
"dry-sloths-impress",
"early-starfishes-hammer",
"eighty-apricots-kneel",
"eighty-bats-stare",
"eleven-pandas-divide",
"empty-beers-relax",
"fix-stackoverflow",
"flat-countries-clap",
"fluffy-hotels-wait",
"four-cooks-serve",
"fresh-crews-impress",
"funny-bees-taste",
"fuzzy-seahorses-tell",
"giant-donkeys-talk",
"gold-waves-bake",
"gorgeous-cameras-cross",
"green-adults-push",
"green-boxes-rescue",
"grumpy-toes-tap",
"happy-radios-kiss",
"healthy-dots-ring",
"healthy-shirts-roll",
"heavy-trainers-fly",
"hip-carrots-drive",
"hot-forks-train",
"itchy-gorillas-hope",
"itchy-keys-wonder",
"kind-toes-scream",
"late-planes-fix",
"lazy-phones-worry",
"little-rockets-live",
"loud-frogs-eat",
"loud-timers-flow",
"loud-vans-greet",
"lovely-games-cry",
"lucky-news-guess",
"mean-ravens-dance",
"metal-years-rhyme",
"new-poets-promise",
"orange-numbers-think",
"perfect-beers-explode",
"perfect-points-hope",
"pink-years-peel",
"proud-comics-love",
"proud-doors-cheat",
"purple-parents-sin",
"purple-waves-smile",
"quick-cats-argue",
"quiet-boxes-build",
"rare-fireants-tickle",
"real-crabs-obey",
"renovate-0d0bd5c",
"rich-adults-float",
"selfish-pigs-glow",
"selfish-walls-visit",
"sharp-glasses-live",
"shy-students-clap",
"silent-wombats-hang",
"six-scissors-smile",
"sixty-bears-camp",
"slimy-kids-behave",
"smart-avocados-invent",
"smooth-garlics-behave",
"sour-socks-approve",
"stupid-onions-know",
"sweet-zoos-clap",
"swift-humans-hunt",
"tall-ads-shave",
"tame-jars-double",
"tasty-apes-learn",
"tasty-moles-jog",
"tasty-rats-explain",
"thick-llamas-itch",
"thick-terms-rush",
"thirty-mangos-travel",
"tough-eggs-wink",
"tricky-cougars-shout",
"unlucky-days-play",
"unlucky-rivers-collect",
"warm-fans-promise",
"wet-files-pretend",
"wild-seahorses-grin",
"young-guests-reflect",
"young-olives-drop"
]
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-catalog-react': minor
'@backstage/plugin-catalog': minor
---
Updated the presentation API to return a promise, in addition to the snapshot and observable that were there before. This makes it much easier to consume the API in a non-React context.
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/backend-test-utils': patch
'@backstage/backend-defaults': patch
'@backstage/plugin-events-node': patch
---
added `eventsServiceFactory` to `defaultServiceFactories` to resolve issue where different instances of the EventsServices could be used
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-api-docs': patch
---
Fix dark mode text color inside tables in `description:` from OpenAPI definitions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend-module-github': patch
---
Updated to use the new `catalogAnalysisExtensionPoint` API.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
Allow passing a `--require` argument through to the Node process during `package start`
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder': patch
---
Fixed a bug where the `MultiEntityPicker` was not able to be set as required
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-app-api': patch
---
The Backstage identity session expiration check will no longer fall back to using the provider expiration. This was introduced to smooth out the rollout of Backstage release 1.18, and is no longer needed.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
Add previously-missing semicolon in file templated by `backstage-cli new --select plugin`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-node': minor
---
Breaking change to `/alpha` API where the `catalogAnalysisExtensionPoint` has been reworked. The `addLocationAnalyzer` method has been renamed to `addScmLocationAnalyzer`, and a new `setLocationAnalyzer` method has been added which allows the full `LocationAnalyzer` implementation to be overridden.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-org': patch
---
Fix ownership card sometimes locking up for complex org structures
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-search-backend-module-techdocs': patch
'@backstage/plugin-search-backend-module-catalog': patch
---
Allow the `tokenManager` parameter to be optional when instantiating collator
+1
View File
@@ -61,6 +61,7 @@ yarn.lock @backstage/maintainers @backst
/plugins/linguist-common @backstage/maintainers @backstage/reviewers @awanlin
/plugins/notifications @backstage/maintainers @backstage/notifications-maintainers
/plugins/notifications-* @backstage/maintainers @backstage/notifications-maintainers
/plugins/scaffolder-backend-module-notifications @backstage/maintainers @backstage/notifications-maintainers
/plugins/octopus-deploy @backstage/maintainers @backstage/reviewers @jmezach
/plugins/permission-* @backstage/permission-maintainers
/plugins/playlist @backstage/maintainers @backstage/reviewers @kuangp
+8
View File
@@ -70,5 +70,13 @@
matchPackageNames: ['p-queue'],
allowedVersions: '<7.0.0',
},
{
matchPackageNames: ['serialize-error'],
allowedVersions: '<9.0.0',
},
{
matchPackageNames: ['yn'],
allowedVersions: '<5.0.0',
},
],
}
@@ -22,7 +22,7 @@ jobs:
action: ${{ steps.event.outputs.ACTION }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
disable-sudo: true
egress-policy: block
@@ -94,7 +94,7 @@ jobs:
# Identify comment to be updated
- name: Find comment for API Changes
uses: peter-evans/find-comment@d5fe37641ad8451bdd80312415672ba26c86575e # v3
uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3
id: find-comment
with:
issue-number: ${{ needs.setup.outputs.pr-number }}
+5 -3
View File
@@ -14,7 +14,7 @@ jobs:
if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -42,15 +42,17 @@ jobs:
yarn backstage-repo-tools repo schema openapi check --since origin/${{ github.base_ref }} > comment.md
- name: Upload Rendered Comment as Artifact
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4
with:
name: preview-spec
path: comment.md
retention-days: 2
overwrite: true
- name: Upload PR Event as Artifact
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: preview-spec
path: ${{ github.event_path }}
retention-days: 2
overwrite: true
+1 -1
View File
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -40,7 +40,7 @@ jobs:
name: Test ${{ matrix.node-version }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+2 -2
View File
@@ -28,7 +28,7 @@ jobs:
name: Install ${{ matrix.node-version }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -64,7 +64,7 @@ jobs:
name: Verify ${{ matrix.node-version }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -144,7 +144,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
if: github.repository == 'backstage/backstage'
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -20,7 +20,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -30,7 +30,8 @@ jobs:
run: |
mkdir -p ./pr
echo $PR_NUMBER > ./pr/pr_number
- uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: pr_number-${{ github.event.pull_request.number }}
path: pr/
overwrite: true
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
steps:
# Inspired by https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request )
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+3 -2
View File
@@ -29,7 +29,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -58,11 +58,12 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: 'Upload artifact'
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: SARIF file
path: results.sarif
retention-days: 5
overwrite: true
# Upload the results to GitHub's code scanning dashboard.
- name: 'Upload to code-scanning'
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -11,7 +11,7 @@ jobs:
if: github.actor == 'dependabot[bot]' && github.repository == 'backstage/backstage'
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -11,7 +11,7 @@ jobs:
if: github.actor == 'renovate[bot]' && github.repository == 'backstage/backstage'
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -12,7 +12,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+9 -6
View File
@@ -26,7 +26,7 @@ jobs:
tags: ${{ steps.meta.outputs.tags }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -84,7 +84,7 @@ jobs:
- build-backstage
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -98,17 +98,19 @@ jobs:
kustomize build . > manifests.rendered.yml
cat manifests.rendered.yml
- name: Upload Rendered Manifests File as Artifact
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4
with:
name: preview-spec
path: ./.github/uffizzi/k8s/manifests/manifests.rendered.yml
retention-days: 2
overwrite: true
- name: Upload PR Event as Artifact
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: preview-spec
path: ${{ github.event_path }}
retention-days: 2
overwrite: true
delete-preview:
name: Call for Preview Deletion
@@ -116,14 +118,15 @@ jobs:
if: ${{ github.event.action == 'closed' }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
# If this PR is closing, we will not render a compose file nor pass it to the next workflow.
- name: Upload PR Event as Artifact
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: preview-spec
path: ${{ github.event_path }}
retention-days: 2
overwrite: true
+1 -1
View File
@@ -23,7 +23,7 @@ jobs:
action: ${{ steps.event.outputs.ACTION }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
disable-sudo: true
egress-policy: block
@@ -26,7 +26,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -42,7 +42,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -23,7 +23,7 @@ jobs:
name: Kubernetes ${{ matrix.node-version }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
name: Kubernetes ${{ matrix.node-version }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -29,7 +29,7 @@ jobs:
name: E2E Linux ${{ matrix.node-version }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -41,7 +41,7 @@ jobs:
name: E2E Linux ${{ matrix.node-version }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -30,7 +30,7 @@ jobs:
name: Techdocs
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -25,7 +25,7 @@ jobs:
name: E2E Windows ${{ matrix.node-version }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -31,7 +31,7 @@ jobs:
name: E2E Windows ${{ matrix.node-version }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
name: Microsite
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+2 -2
View File
@@ -24,7 +24,7 @@ jobs:
name: Microsite
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -34,7 +34,7 @@ jobs:
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: 18.x
- uses: actions/setup-python@v5
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5
with:
python-version: '3.9'
@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
name: Storybook
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
name: Storybook
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+1 -1
View File
@@ -29,7 +29,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
egress-policy: audit
+2
View File
@@ -268,3 +268,5 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/
| [Aurora Innovation](https://aurorainnovation.com) | [@O5ten](https://github.com/O5ten) | Heavy usage of scaffolder, techdocs, homepage, k8s plugin and homegrown plugins to track migration paths and so on within a developer portal. It acts as a starting point for new and old developers to find all of our internal tooling in one place.
| [ENSEK](https://ensek.com/) | [Timothy Deakin](https://github.com/cftad) |We are using Backstage as our internal developer portal to provide a single pane of glass for our developers to access all the tools and services they need to build and maintain our software. |
| [OP Financial Group](https://www.op.fi/op-financial-group) | [Heikki Hellgren](https://github.com/drodil), [Jyrki Koistinen](https://github.com/snyvision) | We are using Backstage as a gateway into our internal development platform offering to simplify complexity. |
| [Scania](https://www.scania.com) | [Santosh Rangavajjula](https://linkedin.com/in/rsbth) | We are implementing backstage at Scania to consolidate operational information from Gitlab, Jira, Confluence, Artifactory, Servicenow and other tools into one place. |
| [Senora.dev](https://senora.dev) | [Shaked Braimok Yosef](https://github.com/ShakedBraimok) | We are using Backstage as a service catalog for our costumers. |
Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 KiB

+16 -8
View File
@@ -10,12 +10,16 @@ configure Backstage to have any number of authentication providers, but only
one of these will typically be used for sign-in, with the rest being used to provide
access to external resources.
> NOTE: Identity management and the Sign-In page in Backstage is NOT a method for blocking
> access for unauthorized users. The identity system only serves to provide a personalized
> experience and access to a Backstage Identity Token, which can be passed to backend plugins.
> This also means that your Backstage backend APIs are by default unauthenticated.
> Thus, if your Backstage instance is exposed to the Internet, anyone can access
> information in the Backstage. You can learn more [here](../overview/threat-model.md#integrator-responsibilities).
:::note Note
Identity management and the Sign-In page in Backstage is NOT a method for blocking
access for unauthorized users. The identity system only serves to provide a personalized
experience and access to a Backstage Identity Token, which can be passed to backend plugins.
This also means that your Backstage backend APIs are by default unauthenticated.
Thus, if your Backstage instance is exposed to the Internet, anyone can access
information in the Backstage. You can learn more [here](../overview/threat-model.md#integrator-responsibilities).
:::
## Built-in Authentication Providers
@@ -141,8 +145,12 @@ const app = createApp({
});
```
> NOTE: You can configure sign-in to use a redirect flow with no pop-up by adding
> `enableExperimentalRedirectFlow: true` to the root of your `app-config.yaml`
:::note Note
You can configure sign-in to use a redirect flow with no pop-up by adding
`enableExperimentalRedirectFlow: true` to the root of your `app-config.yaml`
:::
## Sign-In with Proxy Providers
+1 -1
View File
@@ -43,7 +43,7 @@ Cloud Console and within a Backstage app required to enable this capability.
Apps using the [new backend system](../../backend-system/index.md),
can enable the VMware Cloud provider with a small modification like:
```ts title="packages/backend-next/src/index.ts"
```ts title="packages/backend/src/index.ts"
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
+1 -1
View File
@@ -10,4 +10,4 @@ description: The Backend System
The new backend system is released and ready for production use, and many plugins and modules have already been migrated. We recommend all plugins and deployments to migrate to the new system.
You can find an example backend setup in [the `backend-next` package](https://github.com/backstage/backstage/tree/master/packages/backend-next).
You can find an example backend setup in [the `backend` package](https://github.com/backstage/backstage/tree/master/packages/backend).
+1 -1
View File
@@ -145,7 +145,7 @@ from `@backstage/core-plugin-api`.
In the old backend system plugins, the configuration is passed in via options from the main
backend package. See for example
[packages/backend/src/plugins/auth.ts](https://github.com/backstage/backstage/blob/244eef851f5aa19f91c7c9b5c12d5df95cf482ca/packages/backend/src/plugins/auth.ts#L23).
[packages/backend-legacy/src/plugins/auth.ts](https://github.com/backstage/backstage/blob/244eef851f5aa19f91c7c9b5c12d5df95cf482ca/packages/backend/src/plugins/auth.ts#L23).
### New Backend System
-2
View File
@@ -64,8 +64,6 @@ This feature assumes your backstage instance has enabled the [permissions framew
A sample policy like:
[packages/backend/src/plugins/permissions.ts](https://github.com/backstage/backstage/blob/master/packages/backend/src/plugins/permission.ts)
```typescript
import { BackstageIdentityResponse } from '@backstage/plugin-auth-node';
import {
+1 -1
View File
@@ -393,7 +393,7 @@ There are other more specific search results layout components that also accept
Recently, the Backstage maintainers [announced the new Backend System](https://backstage.io/blog/2023/02/15/backend-system-alpha). The search plugins are now migrated to support the new backend system. In this guide you will learn how to update your backend set up.
In "packages/backend-next/index.ts", install the search plugin [1], the search engine [2], and the search collators/decorators modules [3]:
In "packages/backend/index.ts", install the search plugin [1], the search engine [2], and the search collators/decorators modules [3]:
```ts
import { searchPlugin } from '@backstage/plugin-search-backend/alpha';
@@ -55,7 +55,7 @@ Some defining traits of entity providers:
The recommended way of instantiating the catalog backend classes is to use the
`CatalogBuilder`, as illustrated in the
[example backend here](https://github.com/backstage/backstage/blob/master/packages/backend/src/plugins/catalog.ts).
[example backend here](https://github.com/backstage/backstage/blob/master/packages/backend-legacy/src/plugins/catalog.ts).
We will create a new
[`EntityProvider`](https://github.com/backstage/backstage/blob/master/plugins/catalog-node/src/api/provider.ts)
subclass that can be added to this catalog builder.
@@ -531,7 +531,7 @@ does so!
The recommended way of instantiating the catalog backend classes is to use the
`CatalogBuilder`, as illustrated in the
[example backend here](https://github.com/backstage/backstage/blob/master/packages/backend/src/plugins/catalog.ts).
[example backend here](https://github.com/backstage/backstage/blob/master/packages/backend-legacy/src/plugins/catalog.ts).
We will create a new
[`CatalogProcessor`](https://github.com/backstage/backstage/blob/master/plugins/catalog-node/src/api/processor.ts)
subclass that can be added to this catalog builder.
@@ -654,6 +654,8 @@ how to use them in the Scaffolder templates. It's important to mention that Back
native filters from the Nunjucks library. For a complete list of these native filters and their usage,
refer to the [Nunjucks documentation](https://mozilla.github.io/nunjucks/templating.html#builtin-filters).
To create your own custom filters, look to the section [Custom Filters](#custom-filters) hereafter.
### parseRepoUrl
The `parseRepoUrl` filter parse a repository URL into
@@ -738,3 +740,150 @@ The `projectSlug` filter generates a project slug from a repository URL
- **Input**: `github.com?repo=backstage&org=backstage`
- **Output**: `backstage/backstage`
## Custom Filters
Whenever it is needed to extend the built-in filters with yours `${{ parameters.name | my-filter1 | my-filter2 | etc }}`, then you can add them
using the property `additionalTemplateFilters`.
The `additionalTemplateFilters` property accepts as type a `Record`
```ts title="plugins/scaffolder-backend/src/service/Router.ts"
additionalTemplateFilters?: Record<string, TemplateFilter>;
```
where the first parameter is the name of the filter and the second receives a list of `JSON value` arguments. The `templateFilter()` function must return a JsonValue which is either a Json array, object or primitive.
```ts title="plugins/scaffolder-node/src/types.ts"
export type TemplateFilter = (...args: JsonValue[]) => JsonValue | undefined;
```
From a practical coding point of view, you will translate that into the following snippet code handling 2 filters:
```ts"
...
additionalTemplateFilters: {
base64: (...args: JsonValue[]) => btoa(args.join("")),
betterFilter: (...args: JsonValue[]) => { return `This is a much better string than "${args}", don't you think?` }
}
```
And within your template, you will be able to use the filters using a parameter and the filter passed using the pipe symbol
```yaml
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: test
title: Test
spec:
owner: user:guest
type: service
parameters:
- title: Test custom filters
properties:
userName:
title: Name of the user
type: string
steps:
- id: debug
name: debug
action: debug:log
input:
message: ${{ parameters.userName | betterFilter | base64 }}
```
Next, you will have to register the property `addTemplateFilters` using the `scaffolderTemplatingExtensionPoint` of a new `BackendModule` [created](../../backend-system/architecture/06-modules.md).
Here is a very simplified example of how to do that:
```ts title="packages/backend-next/src/index.ts"
/* highlight-add-start */
import { scaffolderTemplatingExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha';
import { createBackendModule } from '@backstage/backend-plugin-api';
/* highlight-add-end */
/* highlight-add-start */
const scaffolderModuleCustomFilters = createBackendModule({
pluginId: 'scaffolder', // name of the plugin that the module is targeting
moduleId: 'custom-filters',
register(env) {
env.registerInit({
deps: {
scaffolder: scaffolderTemplatingExtensionPoint,
// ... and other dependencies as needed
},
async init({ scaffolder /* ..., other dependencies */ }) {
scaffolder.addTemplateFilters({
base64: (...args: JsonValue[]) => btoa(args.join('')),
betterFilter: (...args: JsonValue[]) => {
return `This is a much better string than "${args}", don't you think?`;
},
});
},
});
},
});
/* highlight-add-end */
const backend = createBackend();
backend.add(import('@backstage/plugin-scaffolder-backend/alpha'));
/* highlight-add-next-line */
backend.add(scaffolderModuleCustomFilters());
```
If you still use the legacy backend system, then you will use the `createRouter()` function of the `Scaffolder plugin`
```ts title="packages/backend/src/plugins/scaffolder.ts"
export default async function createPlugin({
logger,
config,
}: PluginEnvironment): Promise<Router> {
...
return await createRouter({
logger,
config,
additionalTemplateFilters: {
<YOUR_FILTERS>
}
});
```
## Template Editor
Writing template is most of the times an iterative process. You will need to test your template to make sure it has a good user experience and that it works as expected. To help on this process the scaffolder comes with a build in template editor that allows you to test your template in a real environment for querying data and execute the actions on dry-run mode to see the results of those one.
To access to the template editor you can go to the templates page and select "Template Editor" from the context menu or navigate to the `{scaffolder-path}/edit` url. (i.e. the default route would be `/create/edit`)
![Context menu](../../assets/software-templates/context-menu.png)
The template editor has 3 main sections:
1. **Load Template Directory**: Load a local template directory, allowing you to both edit and try executing your own template.
2. **Edit Template Form**: Preview and edit a template form, either using a sample template or by loading a template from the catalog.
3. **Custom Field Explorer**: View and play around with available installed custom field extensions.
### Load Template Directory
Allow to load a directory on your local file system that contains a template and editing the files in it while previewing the form and executing the template.
![template editor load dir](../../assets/software-templates/template-editor-load-dir.png)
If you complete the form in the right side and click on `Create` button, the template will be executed in dry-run mode and the result will be shown in the `Dry-run result` drawer that will pop-up at the bottom of the screen.
Here we could find all the file system results of the template execution as well as the logs of each action that was executed.
![dry run drawer example](../../assets/software-templates/template-editor-dry-run.png)
### Edit Template Form
This is a reduced version of the template editor that allows you to select any template from the catalog and do some modifications on the form presented to the user to test some changes.
Have in mind that changes in this form will not be saved on the template and is meant to test out changes to replicate them manually on the template file after.
### Custom Field Explorer
The custom filed explorer allows you to select any custom field loaded on the backstage instance and test different values and configurations.
@@ -108,7 +108,7 @@ const customSearchPage = createPageExtension({
loader: () => import('./SearchPage').then(m => m.<SearchPage/>),
});
export createExtensionOverrides({
export default createExtensionOverrides({
extensions: [customSearchPage]
});
```
+10 -2
View File
@@ -28,7 +28,11 @@ export const myTheme = createUnifiedTheme({
});
```
> Note: we recommend creating a `theme` folder in `packages/app/src` to place your theme file to keep things nicely organized.
:::note Note
we recommend creating a `theme` folder in `packages/app/src` to place your theme file to keep things nicely organized.
:::
You can also create a theme from scratch that matches the `BackstageTheme` type exported by [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). See the
[Material UI docs on theming](https://material-ui.com/customization/theming/) for more information about how that can be done.
@@ -504,7 +508,11 @@ You can add more icons, if the [default icons](https://github.com/backstage/back
You might want to use this method if you have an icon you want to use in several locations.
Note: If the icon is not available as one of the default icons or one you've added then it will fall back to Material UI's `LanguageIcon`
:::note Note
If the icon is not available as one of the default icons or one you've added then it will fall back to Material UI's `LanguageIcon`
:::
## Custom Sidebar
+376
View File
@@ -0,0 +1,376 @@
---
id: discovery--old
title: GitHub Discovery
sidebar_label: Discovery
# prettier-ignore
description: Automatically discovering catalog entities from repositories in a GitHub organization
---
:::info
This documentation is written for the old backend which has been replaced by [the new backend system](../../backend-system/index.md), being the default since Backstage [version 1.24](../../releases/v1.24.0.md). If have migrated to the new backend system, you may want to read [its own article](./discovery.md) instead. Otherwise, [consider migrating](../../backend-system/building-backends/08-migrating.md)!
:::
## GitHub Provider
The GitHub integration has a discovery provider for discovering catalog
entities within a GitHub organization. The provider will crawl the GitHub
organization and register entities matching the configured path. This can be
useful as an alternative to static locations or manually adding things to the
catalog. This is the preferred method for ingesting entities into the catalog.
## Installation without Events Support
You will have to add the provider in the catalog initialization code of your
backend. They are not installed by default, therefore you have to add a
dependency on `@backstage/plugin-catalog-backend-module-github` to your backend
package.
```bash
# From your Backstage root directory
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-github
```
And then add the entity provider to your catalog builder:
```ts title="packages/backend/src/plugins/catalog.ts"
/* highlight-add-next-line */
import { GithubEntityProvider } from '@backstage/plugin-catalog-backend-module-github';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
/* highlight-add-start */
builder.addEntityProvider(
GithubEntityProvider.fromConfig(env.config, {
logger: env.logger,
scheduler: env.scheduler,
}),
);
/* highlight-add-end */
// ..
}
```
## Installation with Events Support
_For the legacy backend system, please read the sub-section below._
The catalog module for GitHub comes with events support enabled.
This will make it subscribe to its relevant topics (`github.push`)
and expects these events to be published via the `EventsService`.
Additionally, you should install the
[event router by `events-backend-module-github`](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-github/README.md)
which will route received events from the generic topic `github` to more specific ones
based on the event type (e.g., `github.push`).
In order to receive Webhook events by GitHub, you have to decide how you want them
to be ingested into Backstage and published to its `EventsService`.
You can decide between the following options (extensible):
- [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
- [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md)
### Legacy Backend System
Please follow the installation instructions at
- <https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md>
- <https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-github/README.md>
Additionally, you need to decide how you want to receive events from external sources like
- [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
- [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md)
Set up your provider
```ts title="packages/backend/src/plugins/catalog.ts"
import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
/* highlight-add-next-line */
import { GithubEntityProvider } from '@backstage/plugin-catalog-backend-module-github';
import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
builder.addProcessor(new ScaffolderEntitiesProcessor());
/* highlight-add-start */
const githubProvider = GithubEntityProvider.fromConfig(env.config, {
events: env.events,
logger: env.logger,
scheduler: env.scheduler,
});
builder.addEntityProvider(githubProvider);
/* highlight-add-end */
const { processingEngine, router } = await builder.build();
await processingEngine.start();
return router;
}
```
You can check the official docs to [configure your webhook](https://docs.github.com/en/developers/webhooks-and-events/webhooks/creating-webhooks) and to [secure your request](https://docs.github.com/en/developers/webhooks-and-events/webhooks/securing-your-webhooks). The webhook will need to be configured to forward `push` events.
## Configuration
To use the discovery provider, you'll need a GitHub integration
[set up](locations.md) with either a [Personal Access Token](../../getting-started/config/authentication.md) or [GitHub Apps](./github-apps.md). For Personal Access Tokens you should pay attention to the [required scopes](https://backstage.io/docs/integrations/github/locations/#token-scopes), where you will need at least the `repo` scope for reading components. For GitHub Apps you will need to grant it the [required permissions](https://backstage.io/docs/integrations/github/github-apps#app-permissions) instead, where you will need at least the `Contents: Read-only` permissions for reading components.
Then you can add a `github` config to the catalog providers configuration:
```yaml
catalog:
providers:
github:
# the provider ID can be any camelCase string
providerId:
organization: 'backstage' # string
catalogPath: '/catalog-info.yaml' # string
filters:
branch: 'main' # string
repository: '.*' # Regex
schedule: # same options as in TaskScheduleDefinition
# supports cron, ISO duration, "human duration" as used in code
frequency: { minutes: 30 }
# supports ISO duration, "human duration" as used in code
timeout: { minutes: 3 }
customProviderId:
organization: 'new-org' # string
catalogPath: '/custom/path/catalog-info.yaml' # string
filters: # optional filters
branch: 'develop' # optional string
repository: '.*' # optional Regex
wildcardProviderId:
organization: 'new-org' # string
catalogPath: '/groups/**/*.yaml' # this will search all folders for files that end in .yaml
filters: # optional filters
branch: 'develop' # optional string
repository: '.*' # optional Regex
topicProviderId:
organization: 'backstage' # string
catalogPath: '/catalog-info.yaml' # string
filters:
branch: 'main' # string
repository: '.*' # Regex
topic: 'backstage-exclude' # optional string
topicFilterProviderId:
organization: 'backstage' # string
catalogPath: '/catalog-info.yaml' # string
filters:
branch: 'main' # string
repository: '.*' # Regex
topic:
include: ['backstage-include'] # optional array of strings
exclude: ['experiments'] # optional array of strings
validateLocationsExist:
organization: 'backstage' # string
catalogPath: '/catalog-info.yaml' # string
filters:
branch: 'main' # string
repository: '.*' # Regex
validateLocationsExist: true # optional boolean
visibilityProviderId:
organization: 'backstage' # string
catalogPath: '/catalog-info.yaml' # string
filters:
visibility:
- public
- internal
enterpriseProviderId:
host: ghe.example.net
organization: 'backstage' # string
catalogPath: '/catalog-info.yaml' # string
```
This provider supports multiple organizations via unique provider IDs.
> **Note:** It is possible but certainly not recommended to skip the provider ID level.
> If you do so, `default` will be used as provider ID.
- **`catalogPath`** _(optional)_:
Default: `/catalog-info.yaml`.
Path where to look for `catalog-info.yaml` files.
You can use wildcards - `*` or `**` - to search the path and/or the filename.
Wildcards cannot be used if the `validateLocationsExist` option is set to `true`.
- **`filters`** _(optional)_:
- **`branch`** _(optional)_:
String used to filter results based on the branch name.
- **`repository`** _(optional)_:
Regular expression used to filter results based on the repository name.
- **`topic`** _(optional)_:
Both of the filters below may be used at the same time but the exclusion filter has the highest priority.
In the example above, a repository with the `backstage-include` topic would still be excluded
if it were also carrying the `experiments` topic.
- **`include`** _(optional)_:
An array of strings used to filter in results based on their associated GitHub topics.
If configured, only repositories with one (or more) topic(s) present in the inclusion filter will be ingested
- **`exclude`** _(optional)_:
An array of strings used to filter out results based on their associated GitHub topics.
If configured, all repositories _except_ those with one (or more) topics(s) present in the exclusion filter will be ingested.
- **`visibility`** _(optional)_:
An array of strings used to filter results based on their visibility. Available options are `private`, `internal`, `public`. If configured (non empty), only repositories with visibility present in the filter will be ingested
- **`host`** _(optional)_:
The hostname of your GitHub Enterprise instance. It must match a host defined in [integrations.github](locations.md).
- **`organization`**:
Name of your organization account/workspace.
If you want to add multiple organizations, you need to add one provider config each.
- **`validateLocationsExist`** _(optional)_:
Whether to validate locations that exist before emitting them.
This option avoids generating locations for catalog info files that do not exist in the source repository.
Defaults to `false`.
Due to limitations in the GitHub API's ability to query for repository objects, this option cannot be used in
conjunction with wildcards in the `catalogPath`.
- **`schedule`**:
- **`frequency`**:
How often you want the task to run. The system does its best to avoid overlapping invocations.
- **`timeout`**:
The maximum amount of time that a single task invocation can take.
- **`initialDelay`** _(optional)_:
The amount of time that should pass before the first invocation happens.
- **`scope`** _(optional)_:
`'global'` or `'local'`. Sets the scope of concurrency control.
## GitHub API Rate Limits
GitHub [rate limits](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting) API requests to 5,000 per hour (or more for Enterprise
accounts). The snippet below refreshes the Backstage catalog data every 35 minutes, which issues an API request for each discovered location.
If your requests are too frequent then you may get throttled by
rate limiting. You can change the refresh frequency of the catalog in your `app-config.yaml` file by controlling the `schedule`.
```yaml
schedule:
frequency: { minutes: 35 }
timeout: { minutes: 3 }
```
More information about scheduling can be found on the [TaskScheduleDefinition](https://backstage.io/docs/reference/backend-tasks.taskscheduledefinition) page.
Alternatively, or additionally, you can configure [github-apps](github-apps.md) authentication
which carries a much higher rate limit at GitHub.
This is true for any method of adding GitHub entities to the catalog, but
especially easy to hit with automatic discovery.
## GitHub Processor (To Be Deprecated)
The GitHub integration has a special discovery processor for discovering catalog
entities within a GitHub organization. The processor will crawl the GitHub
organization and register entities matching the configured path. This can be
useful as an alternative to static locations or manually adding things to the
catalog.
## Installation
You will have to add the processors in the catalog initialization code of your
backend. They are not installed by default, therefore you have to add a
dependency on `@backstage/plugin-catalog-backend-module-github` to your backend
package, plus `@backstage/integration` for the basic credentials management:
```bash
# From your Backstage root directory
yarn --cwd packages/backend add @backstage/integration @backstage/plugin-catalog-backend-module-github
```
And then add the processors to your catalog builder:
```ts title="packages/backend/src/plugins/catalog.ts"
/* highlight-add-start */
import {
GithubDiscoveryProcessor,
GithubOrgReaderProcessor,
} from '@backstage/plugin-catalog-backend-module-github';
import {
ScmIntegrations,
DefaultGithubCredentialsProvider,
} from '@backstage/integration';
/* highlight-add-end */
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
/* highlight-add-start */
const integrations = ScmIntegrations.fromConfig(env.config);
const githubCredentialsProvider =
DefaultGithubCredentialsProvider.fromIntegrations(integrations);
builder.addProcessor(
GithubDiscoveryProcessor.fromConfig(env.config, {
logger: env.logger,
githubCredentialsProvider,
}),
GithubOrgReaderProcessor.fromConfig(env.config, {
logger: env.logger,
githubCredentialsProvider,
}),
);
/* highlight-add-end */
// ..
}
```
## Configuration
To use the discovery processor, you'll need a GitHub integration
[set up](locations.md) with either a [Personal Access Token](../../getting-started/config/authentication.md) or [GitHub Apps](./github-apps.md).
Then you can add a location target to the catalog configuration:
```yaml
catalog:
locations:
# (since 0.13.5) Scan all repositories for a catalog-info.yaml in the root of the default branch
- type: github-discovery
target: https://github.com/myorg
# Or use a custom pattern for a subset of all repositories with default repository
- type: github-discovery
target: https://github.com/myorg/service-*/blob/-/catalog-info.yaml
# Or use a custom file format and location
- type: github-discovery
target: https://github.com/*/blob/-/docs/your-own-format.yaml
# Or use a specific branch-name
- type: github-discovery
target: https://github.com/*/blob/backstage-docs/catalog-info.yaml
```
Note the `github-discovery` type, as this is not a regular `url` processor.
When using a custom pattern, the target is composed of three parts:
- The base organization URL, `https://github.com/myorg` in this case
- The repository blob to scan, which accepts \* wildcard tokens. This can simply
be `*` to scan all repositories in the organization. This example only looks
for repositories prefixed with `service-`.
- The path within each repository to find the catalog YAML file. This will
usually be `/blob/main/catalog-info.yaml`, `/blob/master/catalog-info.yaml` or
a similar variation for catalog files stored in the root directory of each
repository. You could also use a dash (`-`) for referring to the default
branch.
## GitHub API Rate Limits
GitHub [rate limits](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting) API requests to 5,000 per hour (or more for Enterprise
accounts). The default Backstage catalog backend refreshes data every 100
seconds, which issues an API request for each discovered location.
This means if you have more than ~140 catalog entities, you may get throttled by
rate limiting. You can change the refresh rate of the catalog in your `packages/backend/src/plugins/catalog.ts` file:
```typescript
const builder = await CatalogBuilder.create(env);
// For example, to refresh every 5 minutes (300 seconds).
builder.setProcessingIntervalSeconds(300);
```
Alternatively, or additionally, you can configure [github-apps](github-apps.md) authentication
which carries a much higher rate limit at GitHub.
This is true for any method of adding GitHub entities to the catalog, but
especially easy to hit with automatic discovery.
+9 -166
View File
@@ -6,6 +6,10 @@ sidebar_label: Discovery
description: Automatically discovering catalog entities from repositories in a GitHub organization
---
:::info
This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](./discovery--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
:::
## GitHub Provider
The GitHub integration has a discovery provider for discovering catalog
@@ -14,10 +18,9 @@ organization and register entities matching the configured path. This can be
useful as an alternative to static locations or manually adding things to the
catalog. This is the preferred method for ingesting entities into the catalog.
## Installation without Events Support
## Installation
You will have to add the provider in the catalog initialization code of your
backend. They are not installed by default, therefore you have to add a
You will have to add the GitHub Entity provider to your backend as it is not installed by default, therefore you have to add a
dependency on `@backstage/plugin-catalog-backend-module-github` to your backend
package.
@@ -29,13 +32,12 @@ yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-github
And then update your backend by adding the following line:
```ts title="packages/backend/src/index.ts"
// github discovery
backend.add(import('@backstage/plugin-catalog-backend/alpha'));
/* highlight-add-start */
backend.add(import('@backstage/plugin-catalog-backend-module-github/alpha'));
```
## Installation with Events Support
_For the legacy backend system, please read the sub-section below._
## Events Support
The catalog module for GitHub comes with events support enabled.
This will make it subscribe to its relevant topics (`github.push`)
@@ -53,47 +55,6 @@ You can decide between the following options (extensible):
- [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
- [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md)
### Legacy Backend System
Please follow the installation instructions at
- <https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md>
- <https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-github/README.md>
Additionally, you need to decide how you want to receive events from external sources like
- [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
- [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md)
Set up your provider
```ts title="packages/backend/src/plugins/catalog.ts"
import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
/* highlight-add-next-line */
import { GithubEntityProvider } from '@backstage/plugin-catalog-backend-module-github';
import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
builder.addProcessor(new ScaffolderEntitiesProcessor());
/* highlight-add-start */
const githubProvider = GithubEntityProvider.fromConfig(env.config, {
events: env.events,
logger: env.logger,
scheduler: env.scheduler,
});
builder.addEntityProvider(githubProvider);
/* highlight-add-end */
const { processingEngine, router } = await builder.build();
await processingEngine.start();
return router;
}
```
You can check the official docs to [configure your webhook](https://docs.github.com/en/developers/webhooks-and-events/webhooks/creating-webhooks) and to [secure your request](https://docs.github.com/en/developers/webhooks-and-events/webhooks/securing-your-webhooks). The webhook will need to be configured to forward `push` events.
## Configuration
@@ -236,121 +197,3 @@ which carries a much higher rate limit at GitHub.
This is true for any method of adding GitHub entities to the catalog, but
especially easy to hit with automatic discovery.
## GitHub Processor (To Be Deprecated)
The GitHub integration has a special discovery processor for discovering catalog
entities within a GitHub organization. The processor will crawl the GitHub
organization and register entities matching the configured path. This can be
useful as an alternative to static locations or manually adding things to the
catalog.
## Installation
You will have to add the processors in the catalog initialization code of your
backend. They are not installed by default, therefore you have to add a
dependency on `@backstage/plugin-catalog-backend-module-github` to your backend
package, plus `@backstage/integration` for the basic credentials management:
```bash
# From your Backstage root directory
yarn --cwd packages/backend add @backstage/integration @backstage/plugin-catalog-backend-module-github
```
And then add the processors to your catalog builder:
```ts title="packages/backend/src/plugins/catalog.ts"
/* highlight-add-start */
import {
GithubDiscoveryProcessor,
GithubOrgReaderProcessor,
} from '@backstage/plugin-catalog-backend-module-github';
import {
ScmIntegrations,
DefaultGithubCredentialsProvider,
} from '@backstage/integration';
/* highlight-add-end */
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
/* highlight-add-start */
const integrations = ScmIntegrations.fromConfig(env.config);
const githubCredentialsProvider =
DefaultGithubCredentialsProvider.fromIntegrations(integrations);
builder.addProcessor(
GithubDiscoveryProcessor.fromConfig(env.config, {
logger: env.logger,
githubCredentialsProvider,
}),
GithubOrgReaderProcessor.fromConfig(env.config, {
logger: env.logger,
githubCredentialsProvider,
}),
);
/* highlight-add-end */
// ..
}
```
## Configuration
To use the discovery processor, you'll need a GitHub integration
[set up](locations.md) with either a [Personal Access Token](../../getting-started/config/authentication.md) or [GitHub Apps](./github-apps.md).
Then you can add a location target to the catalog configuration:
```yaml
catalog:
locations:
# (since 0.13.5) Scan all repositories for a catalog-info.yaml in the root of the default branch
- type: github-discovery
target: https://github.com/myorg
# Or use a custom pattern for a subset of all repositories with default repository
- type: github-discovery
target: https://github.com/myorg/service-*/blob/-/catalog-info.yaml
# Or use a custom file format and location
- type: github-discovery
target: https://github.com/*/blob/-/docs/your-own-format.yaml
# Or use a specific branch-name
- type: github-discovery
target: https://github.com/*/blob/backstage-docs/catalog-info.yaml
```
Note the `github-discovery` type, as this is not a regular `url` processor.
When using a custom pattern, the target is composed of three parts:
- The base organization URL, `https://github.com/myorg` in this case
- The repository blob to scan, which accepts \* wildcard tokens. This can simply
be `*` to scan all repositories in the organization. This example only looks
for repositories prefixed with `service-`.
- The path within each repository to find the catalog YAML file. This will
usually be `/blob/main/catalog-info.yaml`, `/blob/master/catalog-info.yaml` or
a similar variation for catalog files stored in the root directory of each
repository. You could also use a dash (`-`) for referring to the default
branch.
## GitHub API Rate Limits
GitHub [rate limits](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting) API requests to 5,000 per hour (or more for Enterprise
accounts). The default Backstage catalog backend refreshes data every 100
seconds, which issues an API request for each discovered location.
This means if you have more than ~140 catalog entities, you may get throttled by
rate limiting. You can change the refresh rate of the catalog in your `packages/backend/src/plugins/catalog.ts` file:
```typescript
const builder = await CatalogBuilder.create(env);
// For example, to refresh every 5 minutes (300 seconds).
builder.setProcessingIntervalSeconds(300);
```
Alternatively, or additionally, you can configure [github-apps](github-apps.md) authentication
which carries a much higher rate limit at GitHub.
This is true for any method of adding GitHub entities to the catalog, but
especially easy to hit with automatic discovery.
+37 -6
View File
@@ -31,7 +31,7 @@ A GitHub app created with the cli will have read
access by default. You have to manually update the GitHub App settings in GitHub
to grant the app more permissions if needed.
### Using the CLI (public GitHub only)
## Using the CLI (public GitHub only)
You can use the `backstage-cli` to create a GitHub App using a manifest file
that we provide. This gives us a way to automate some of the work required to
@@ -53,7 +53,7 @@ Note that the created app will have a webhook that is disabled by default and
points to `smee.io`, which is intended for local development. There's also
currently no part of Backstage that makes use of the webhook.
### GitHub Enterprise
## GitHub Enterprise
You have to create the GitHub Application manually using these
[instructions](https://docs.github.com/en/free-pro-team@latest/developers/apps/creating-a-github-app)
@@ -76,7 +76,7 @@ privateKey: |
-----END RSA PRIVATE KEY-----
```
### Including in Integrations Config
## Including in Integrations Config
Once the credentials are stored in a YAML file generated by `create-github-app`,
or manually by following the [GitHub Enterprise](#github-enterprise)
@@ -95,7 +95,25 @@ integrations:
- $include: example-backstage-app-credentials.yaml
```
### Limiting the GitHub App installations
Alternatively you can use environment variables as well:
```yaml
integrations:
github:
- host: github.com
apps:
- appId: ${AUTH_ORG_APP_ID}
clientId: ${AUTH_ORG_CLIENT_ID}
clientSecret: ${AUTH_ORG_CLIENT_SECRET}
privateKey: ${AUTH_ORG1_PRIVATE_KEY}
webhookSecret: ${AUTH_ORG_WEBHOOK_SECRET}
```
:::Note
Note that in both examples above `apps` is an array which means you can add multiple GitHub Apps using `$include` or environment variables as long as they are each for a different GitHub Org as mentioned under the [Caveats](#caveats) section
:::
## Limiting the GitHub App installations
If you want to limit the GitHub app installations visible to backstage you may
optionally include the `allowedInstallationOwners` option. If you configure
@@ -117,7 +135,7 @@ privateKey: |
This will result in backstage preventing the use of any installation that is not
within the allow list.
### App permissions
## App permissions
When creating a GitHub App, you must select permissions to define the level of
access for the app. The permissions required vary depending on your use of the
@@ -140,7 +158,20 @@ integration:
- `Secrets`: `Read & write` (if templates include GitHub Action Repository Secrets)
- `Environments`: `Read & write` (if templates include GitHub Environments)
### Troubleshooting
## Updating Permissions
There may be times where you need to update the permissions for your GitHub App, to easily get at the GitHub App you can find it at this URL:
```sh
https://github.com/organizations/{ORG}/settings/apps/{APP_NAME}/permissions
```
**Please note that when you change permissions, the app owner will get an email
that must be approved first before the changes are applied.**
![email](../../assets/integrations/github/email.png)
## Troubleshooting
`HttpError: This endpoint requires you to be authenticated.`
+368
View File
@@ -0,0 +1,368 @@
---
id: org--old
title: GitHub Organizational Data
sidebar_label: Org Data
# prettier-ignore
description: Importing users and groups from a GitHub organization into Backstage
---
:::info
This documentation is written for the old backend which has been replaced by [the new backend system](../../backend-system/index.md), being the default since Backstage [version 1.24](../../releases/v1.24.0.md). If have migrated to the new backend system, you may want to read [its own article](./org.md) instead.Otherwise, [consider migrating](../../backend-system/building-backends/08-migrating.md)!
:::
The Backstage catalog can be set up to ingest organizational data - users and
teams - directly from an organization in GitHub or GitHub Enterprise. The result
is a hierarchy of
[`User`](../../features/software-catalog/descriptor-format.md#kind-user) and
[`Group`](../../features/software-catalog/descriptor-format.md#kind-group) kind
entities that mirror your org setup.
> Note: This adds `User` and `Group` entities to the catalog, but does not
> provide authentication. See the
> [GitHub auth provider](../../auth/github/provider.md) for that.
## Installation without Events Support
This guide will use the Entity Provider method. If you for some reason prefer
the Processor method (not recommended), it is described separately below.
The provider is not installed by default, therefore you have to add a dependency
to `@backstage/plugin-catalog-backend-module-github` to your backend package.
```bash
# From your Backstage root directory
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-github
```
> Note: When configuring to use a Provider instead of a Processor you do not
> need to add a _location_ pointing to your GitHub server/organization
Update the catalog plugin initialization in your backend to add the provider and
schedule it:
```ts title="packages/backend/src/plugins/catalog.ts"
/* highlight-add-next-line */
import { GithubOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-github';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
/* highlight-add-start */
// The org URL below needs to match a configured integrations.github entry
// specified in your app-config.
builder.addEntityProvider(
GithubOrgEntityProvider.fromConfig(env.config, {
id: 'production',
orgUrl: 'https://github.com/backstage',
logger: env.logger,
schedule: env.scheduler.createScheduledTaskRunner({
frequency: { minutes: 60 },
timeout: { minutes: 15 },
}),
}),
);
/* highlight-add-end */
// ..
}
```
Alternatively, if you wish to ingest data from multiple GitHub organizations you can use
the `GithubMultiOrgEntityProvider` instead. Note that by default, this provider will namespace
groups according to the org they originate from to avoid potential name duplicates:
```ts title="packages/backend/src/plugins/catalog.ts"
/* highlight-add-next-line */
import { GithubMultiOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-github';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
/* highlight-add-start */
// The GitHub URL below needs to match a configured integrations.github entry
// specified in your app-config.
builder.addEntityProvider(
GithubMultiOrgEntityProvider.fromConfig(env.config, {
id: 'production',
githubUrl: 'https://github.com',
// Set the following to list the GitHub orgs you wish to ingest from. You can
// also omit this option to ingest all orgs accessible by your GitHub integration
orgs: ['org-a', 'org-b'],
logger: env.logger,
schedule: env.scheduler.createScheduledTaskRunner({
frequency: { minutes: 60 },
timeout: { minutes: 15 },
}),
}),
);
/* highlight-add-end */
// ..
}
```
## Installation with Events Support
_For the legacy backend system, please read the subsection below._
The catalog module `github-org` comes with events support enabled for the `GithubMultiOrgEntityProvider`.
This will make it subscribe to its relevant topics and expects these events to be published via the `EventsService`.
Topics:
- `github.installation`
- `github.membership`
- `github.organization`
- `github.team`
Additionally, you should install the
[event router by `events-backend-module-github`](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-github/README.md)
which will route received events from the generic topic `github` to more specific ones
based on the event type (e.g., `github.membership`).
In order to receive Webhook events by GitHub, you have to decide how you want them
to be ingested into Backstage and published to its `EventsService`.
You can decide between the following options (extensible):
- [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
- [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md)
### Legacy Backend System
Please follow the installation instructions at
- <https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md>
- <https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-github/README.md>
Additionally, you need to decide how you want to receive events from external sources like
- [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
- [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md)
Set up your provider
```ts title="packages/backend/src/plugins/catalog.ts"
import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
/* highlight-add-next-line */
import { GithubOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-github';
import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
builder.addProcessor(new ScaffolderEntitiesProcessor());
/* highlight-add-start */
const githubOrgProvider = GithubOrgEntityProvider.fromConfig(env.config, {
id: 'production',
orgUrl: 'https://github.com/backstage',
logger: env.logger,
events: env.events,
schedule: env.scheduler.createScheduledTaskRunner({
frequency: { minutes: 60 },
timeout: { minutes: 15 },
}),
});
builder.addEntityProvider(githubOrgProvider);
/* highlight-add-end */
const { processingEngine, router } = await builder.build();
await processingEngine.start();
return router;
}
```
Or, alternatively, if using the `GithubMultiOrgEntityProvider`:
```ts title="packages/backend/src/plugins/catalog.ts"
/* highlight-add-next-line */
import { GithubMultiOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-github';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
/* highlight-add-start */
// The GitHub URL below needs to match a configured integrations.github entry
// specified in your app-config.
builder.addEntityProvider(
GithubMultiOrgEntityProvider.fromConfig(env.config, {
id: 'production',
githubUrl: 'https://github.com',
// Set the following to list the GitHub orgs you wish to ingest from. You can
// also omit this option to ingest all orgs accessible by your GitHub integration
orgs: ['org-a', 'org-b'],
logger: env.logger,
events: env.events,
schedule: env.scheduler.createScheduledTaskRunner({
frequency: { minutes: 60 },
timeout: { minutes: 15 },
}),
}),
);
/* highlight-add-end */
// ..
}
```
You can check the official docs to [configure your webhook](https://docs.github.com/en/developers/webhooks-and-events/webhooks/creating-webhooks) and to [secure your request](https://docs.github.com/en/developers/webhooks-and-events/webhooks/securing-your-webhooks).
The webhook will need to be configured to forward `organization`,`team` and `membership` events.
## Configuration
As mentioned above, you also must have some configuration in your app-config
that describes the targets that you want to import. This lets the entity
provider know what authorization to use, and what the API endpoints are. You may
or may not have such an entry already added since before:
```yaml
integrations:
github:
# example for public github
- host: github.com
token: ${GITHUB_TOKEN}
# example for a private GitHub Enterprise instance
- host: ghe.example.net
apiBaseUrl: https://ghe.example.net/api/v3
token: ${GHE_TOKEN}
```
These examples use `${}` placeholders to reference environment variables. This
is often suitable for production setups, but also means that you will have to
supply those variables to the backend as it starts up. If you want, for local
development in particular, you can experiment first by putting the actual tokens
in a mirrored config directly in your `app-config.local.yaml` as well.
If Backstage is configured to use GitHub Apps authentication you must grant
`Read-Only` access for `Members` under `Organization` in order to ingest users
correctly. You can modify the app's permissions under the organization settings,
`https://github.com/organizations/{ORG}/settings/apps/{APP_NAME}/permissions`.
![permissions](../../assets/integrations/github/permissions.png)
**Please note that when you change permissions, the app owner will get an email
that must be approved first before the changes are applied.**
![email](../../assets/integrations/github/email.png)
### Custom Transformers
You can inject your own transformation logic to help map from GH API responses
into backstage entities. You can do this on the user and team requests to
enable you to do further processing or updates to the entities.
To enable this you pass a function into the `GitHubOrgEntityProvider`. You can
pass a `UserTransformer`, `TeamTransformer` or both. The function is invoked
for each item (user or team) that is returned from the API. You can either
return an Entity (User or Group) or `undefined` if you do not want to import
that item.
There is also a `defaultUserTransformer` and `defaultOrganizationTeamTransformer`.
You could use these and simply decorate the response from the default
transformation if you only need to change a few properties.
### Resolving GitHub users via organization email
When you authenticate users you should resolve them to an entity within the
catalog. Often the authentication you use could be a corporate SSO system that
provides you with email as a key. To enable you to find and resolve GitHub users
it's useful to also import the private domain verified emails into the User
entity in backstage.
The integration attempts to return `organizationVerifiedDomainEmails` from the
GitHub API and makes this available as part of the object passed to
`UserTransformer`. The GitHub API will only return emails that use a domain
that's a verified domain for your GitHub Org. It also relies on the user having
configured such an email in their own account. The API will only return these
values when using GitHub App authentication and with the correct app permission
allowing access to emails.
You can decorate the default `userTransformer` to replace the org email in the
returned identity.
```ts title="packages/backend/src/plugins/catalog.ts"
const githubOrgProvider = GithubOrgEntityProvider.fromConfig(env.config, {
id: 'production',
orgUrl: 'https://github.com/backstage',
logger: env.logger,
schedule: env.scheduler.createScheduledTaskRunner({
frequency: { minutes: 60 },
timeout: { minutes: 15 },
}),
/* highlight-add-start */
userTransformer: async (user, ctx) => {
const entity = await defaultUserTransformer(user, ctx);
if (entity && user.organizationVerifiedDomainEmails?.length) {
entity.spec.profile!.email = user.organizationVerifiedDomainEmails[0];
}
return entity;
},
/* highlight-add-end */
});
```
Once you have imported the emails you can resolve users in your [sign-in
resolver](../../auth/github/provider.md) using the catalog entity search via email
```typescript title="packages/backend/src/plugins/auth.ts"
ctx.signInWithCatalogUser({
filter: {
kind: ['User'],
'spec.profile.email': email as string,
},
});
```
## Using a Processor instead of a Provider
An alternative to using the Provider for ingesting organizational entities is to
use a Processor. This is the old way that's based on registering locations with
the proper type and target, triggering the processor to run.
The drawback of this method is that it will leave orphaned Group/User entities
whenever they are deleted on your GitHub server, and you cannot control the
frequency with which they are refreshed, separately from other processors.
### Processor Installation
The `GithubOrgReaderProcessor` is not registered by default, so you have to
install and register it in the catalog plugin:
```bash
# From your Backstage root directory
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-github
```
```typescript title="packages/backend/src/plugins/catalog.ts"
import { GithubOrgReaderProcessor } from '@backstage/plugin-catalog-backend-module-github';
builder.addProcessor(
GithubOrgReaderProcessor.fromConfig(env.config, { logger: env.logger }),
);
```
### Processor Configuration
The integration section of your app-config needs to be set up in the same way as
for the Entity Provider - see above.
In addition to that, you typically want to add a few static locations to your
app-config, which reference your organizations to import. The following
configuration enables an import of the teams and users under the org
`https://github.com/my-org-name` on public GitHub.
```yaml
catalog:
locations:
- type: github-org
target: https://github.com/my-org-name
rules:
- allow: [User, Group]
```
+153 -262
View File
@@ -6,6 +6,10 @@ sidebar_label: Org Data
description: Importing users and groups from a GitHub organization into Backstage
---
:::info
This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](./org--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
:::
The Backstage catalog can be set up to ingest organizational data - users and
teams - directly from an organization in GitHub or GitHub Enterprise. The result
is a hierarchy of
@@ -17,95 +21,81 @@ entities that mirror your org setup.
> provide authentication. See the
> [GitHub auth provider](../../auth/github/provider.md) for that.
## Installation without Events Support
## Permissions
This guide will use the Entity Provider method. If you for some reason prefer
the Processor method (not recommended), it is described separately below.
Prior to installing the GitHub Org provider you should confirm you have the right permissions:
The provider is not installed by default, therefore you have to add a dependency
to `@backstage/plugin-catalog-backend-module-github` to your backend package.
- Personal Access Token permissions are listed in the [GitHub Locations](./locations.md#token-scopes) documentation
- GitHub App(s) permissions are listed in the [GitHub Apps](./github-apps.md#app-permissions) documentation
## Installation
You will have to add the GitHub Org provider to your backend as it is not installed by default, therefore you have to add a
dependency on `@backstage/plugin-catalog-backend-module-github-org` to your backend
package.
```bash
# From your Backstage root directory
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-github
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-github-org
```
> Note: When configuring to use a Provider instead of a Processor you do not
> need to add a _location_ pointing to your GitHub server/organization
Next add the basic configuration to `app-config.yaml`
Update the catalog plugin initialization in your backend to add the provider and
schedule it:
```ts title="packages/backend/src/plugins/catalog.ts"
/* highlight-add-next-line */
import { GithubOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-github';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
/* highlight-add-start */
// The org URL below needs to match a configured integrations.github entry
// specified in your app-config.
builder.addEntityProvider(
GithubOrgEntityProvider.fromConfig(env.config, {
id: 'production',
orgUrl: 'https://github.com/backstage',
logger: env.logger,
schedule: env.scheduler.createScheduledTaskRunner({
frequency: { minutes: 60 },
timeout: { minutes: 15 },
}),
}),
);
/* highlight-add-end */
// ..
}
```yaml title="app-config.yaml"
catalog:
providers:
githubOrg:
id: github
githubUrl: https://github.com
orgs: ['organization-1', 'organization-2', 'organization-3']
schedule:
initialDelay: { seconds: 30 }
frequency: { hours: 1 }
timeout: { minutes: 50 }
```
Alternatively, if you wish to ingest data from multiple GitHub organizations you can use
the `GithubMultiOrgEntityProvider` instead. Note that by default, this provider will namespace
groups according to the org they originate from to avoid potential name duplicates:
Finally, update your backend by adding the following line:
```ts title="packages/backend/src/plugins/catalog.ts"
/* highlight-add-next-line */
import { GithubMultiOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-github';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
/* highlight-add-start */
// The GitHub URL below needs to match a configured integrations.github entry
// specified in your app-config.
builder.addEntityProvider(
GithubMultiOrgEntityProvider.fromConfig(env.config, {
id: 'production',
githubUrl: 'https://github.com',
// Set the following to list the GitHub orgs you wish to ingest from. You can
// also omit this option to ingest all orgs accessible by your GitHub integration
orgs: ['org-a', 'org-b'],
logger: env.logger,
schedule: env.scheduler.createScheduledTaskRunner({
frequency: { minutes: 60 },
timeout: { minutes: 15 },
}),
}),
);
/* highlight-add-end */
// ..
}
```ts title="packages/backend/src/index.ts"
backend.add(import('@backstage/plugin-catalog-backend/alpha'));
/* highlight-add-start */
backend.add(import('@backstage/plugin-catalog-backend-module-github-org'));
```
## Installation with Events Support
### Configuration Details
_For the legacy backend system, please read the subsection below._
In the installation steps above we included an simple example of the needed configuration. The section goes into more details about the various configuration options.
The catalog module `github-org` comes with events support enabled for the `GithubMultiOrgEntityProvider`.
```yaml title="app-config.yaml"
catalog:
providers:
githubOrg:
- id: github
githubUrl: https://github.com
orgs: ['organization-1', 'organization-2', 'organization-3']
schedule:
initialDelay: { seconds: 30 }
frequency: { hours: 1 }
timeout: { minutes: 50 }
- id: ghe
githubUrl: https://ghe.mycompany.com
orgs: ['internal-1', 'internal-2', 'internal-3']
schedule:
initialDelay: { seconds: 30 }
frequency: { hours: 1 }
timeout: { minutes: 50 }
```
Directly under the `githubOrg` is a list of configurations, each entry is a structure with the following elements:
- `id`: A stable id for this provider. Entities from this provider will be associated with this ID, so you should take care not to change it over time since that may lead to orphaned entities and/or conflicts.
- `githubUrl`: The target that this provider should consume
- `orgs` (optional): The list of the GitHub orgs to consume. By default wil consume all accessible orgs on the given GitHub instance (support for GitHub App integration only).
- `schedule`: The refresh schedule to use, matches the structure of [`TaskScheduleDefinitionConfig`](https://backstage.io/docs/reference/backend-tasks.taskscheduledefinitionconfig/)
### Events Support
The catalog module for GitHub Org comes with events support enabled.
This will make it subscribe to its relevant topics and expects these events to be published via the `EventsService`.
Topics:
@@ -127,128 +117,10 @@ You can decide between the following options (extensible):
- [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
- [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md)
### Legacy Backend System
Please follow the installation instructions at
- <https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md>
- <https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-github/README.md>
Additionally, you need to decide how you want to receive events from external sources like
- [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
- [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md)
Set up your provider
```ts title="packages/backend/src/plugins/catalog.ts"
import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
/* highlight-add-next-line */
import { GithubOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-github';
import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
builder.addProcessor(new ScaffolderEntitiesProcessor());
/* highlight-add-start */
const githubOrgProvider = GithubOrgEntityProvider.fromConfig(env.config, {
id: 'production',
orgUrl: 'https://github.com/backstage',
logger: env.logger,
events: env.events,
schedule: env.scheduler.createScheduledTaskRunner({
frequency: { minutes: 60 },
timeout: { minutes: 15 },
}),
});
builder.addEntityProvider(githubOrgProvider);
/* highlight-add-end */
const { processingEngine, router } = await builder.build();
await processingEngine.start();
return router;
}
```
Or, alternatively, if using the `GithubMultiOrgEntityProvider`:
```ts title="packages/backend/src/plugins/catalog.ts"
/* highlight-add-next-line */
import { GithubMultiOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-github';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
/* highlight-add-start */
// The GitHub URL below needs to match a configured integrations.github entry
// specified in your app-config.
builder.addEntityProvider(
GithubMultiOrgEntityProvider.fromConfig(env.config, {
id: 'production',
githubUrl: 'https://github.com',
// Set the following to list the GitHub orgs you wish to ingest from. You can
// also omit this option to ingest all orgs accessible by your GitHub integration
orgs: ['org-a', 'org-b'],
logger: env.logger,
events: env.events,
schedule: env.scheduler.createScheduledTaskRunner({
frequency: { minutes: 60 },
timeout: { minutes: 15 },
}),
}),
);
/* highlight-add-end */
// ..
}
```
You can check the official docs to [configure your webhook](https://docs.github.com/en/developers/webhooks-and-events/webhooks/creating-webhooks) and to [secure your request](https://docs.github.com/en/developers/webhooks-and-events/webhooks/securing-your-webhooks).
The webhook will need to be configured to forward `organization`,`team` and `membership` events.
## Configuration
As mentioned above, you also must have some configuration in your app-config
that describes the targets that you want to import. This lets the entity
provider know what authorization to use, and what the API endpoints are. You may
or may not have such an entry already added since before:
```yaml
integrations:
github:
# example for public github
- host: github.com
token: ${GITHUB_TOKEN}
# example for a private GitHub Enterprise instance
- host: ghe.example.net
apiBaseUrl: https://ghe.example.net/api/v3
token: ${GHE_TOKEN}
```
These examples use `${}` placeholders to reference environment variables. This
is often suitable for production setups, but also means that you will have to
supply those variables to the backend as it starts up. If you want, for local
development in particular, you can experiment first by putting the actual tokens
in a mirrored config directly in your `app-config.local.yaml` as well.
If Backstage is configured to use GitHub Apps authentication you must grant
`Read-Only` access for `Members` under `Organization` in order to ingest users
correctly. You can modify the app's permissions under the organization settings,
`https://github.com/organizations/{ORG}/settings/apps/{APP_NAME}/permissions`.
![permissions](../../assets/integrations/github/permissions.png)
**Please note that when you change permissions, the app owner will get an email
that must be approved first before the changes are applied.**
![email](../../assets/integrations/github/email.png)
### Custom Transformers
## Custom Transformers
You can inject your own transformation logic to help map from GH API responses
into backstage entities. You can do this on the user and team requests to
@@ -264,6 +136,81 @@ There is also a `defaultUserTransformer` and `defaultOrganizationTeamTransformer
You could use these and simply decorate the response from the default
transformation if you only need to change a few properties.
Here's an example of how to use the transformers:
```ts title="packages/backend/src/index.ts"
import { createBackend } from '@backstage/backend-defaults';
import { createBackendModule } from '@backstage/backend-plugin-api';
import { githubOrgEntityProviderTransformsExtensionPoint } from '@backstage/plugin-catalog-backend-module-github-org';
import { myTeamTransformer, myUserTransformer } from './transformers';
const githubOrgModule = createBackendModule({
pluginId: 'catalog',
moduleId: 'github-org-extensions',
register(env) {
env.registerInit({
deps: {
githubOrg: githubOrgEntityProviderTransformsExtensionPoint,
},
async init({ githubOrg }) {
githubOrg.setTeamTransformer(myTeamTransformer);
githubOrg.setUserTransformer(myUserTransformer);
},
});
},
});
const backend = createBackend();
// Other items
backend.add(import('@backstage/plugin-catalog-backend/alpha'));
backend.add(githubOrgModule());
backend.start();
```
The `myTeamTransformer` and `myUserTransformer` transformer functions are from the examples in the section below.
### Transformer Examples
The following provides an example of each kind of transformer. We recommend creating a `transformers.ts` file in your `packages/backend/src` folder for these.
```ts title="packages/backend/src/transformers.ts"
import {
TeamTransformer,
UserTransformer,
defaultUserTransformer,
} from '@backstage/plugin-catalog-backend-module-github';
// This team transformer completely replaces the built in logic with custom logic.
export const myTeamTransformer: TeamTransformer = async team => {
return {
apiVersion: 'backstage.io/v1alpha1',
kind: 'Group',
metadata: {
name: team.slug,
annotations: {},
},
spec: {
type: 'GitHub Org Team',
profile: {},
children: [],
},
};
};
// This user transformer makes use of the built in logic, but also sets the description field
export const myUserTransformer: UserTransformer = async (user, ctx) => {
const backstageUser = await defaultUserTransformer(user, ctx);
if (backstageUser) {
backstageUser.metadata.description = 'Loaded from GitHub Org Data';
}
return backstageUser;
};
```
### Resolving GitHub users via organization email
When you authenticate users you should resolve them to an entity within the
@@ -283,31 +230,22 @@ allowing access to emails.
You can decorate the default `userTransformer` to replace the org email in the
returned identity.
```ts title="packages/backend/src/plugins/catalog.ts"
const githubOrgProvider = GithubOrgEntityProvider.fromConfig(env.config, {
id: 'production',
orgUrl: 'https://github.com/backstage',
logger: env.logger,
schedule: env.scheduler.createScheduledTaskRunner({
frequency: { minutes: 60 },
timeout: { minutes: 15 },
}),
/* highlight-add-start */
userTransformer: async (user, ctx) => {
const entity = await defaultUserTransformer(user, ctx);
if (entity && user.organizationVerifiedDomainEmails?.length) {
entity.spec.profile!.email = user.organizationVerifiedDomainEmails[0];
}
return entity;
},
/* highlight-add-end */
});
```ts title="packages/backend/src/transformers.ts"
export const myVerifiedUserTransformer: UserTransformer = async (user, ctx) => {
const backstageUser = await defaultUserTransformer(user, ctx);
if (backstageUser && user.organizationVerifiedDomainEmails?.length) {
backstageUser.spec.profile!.email =
user.organizationVerifiedDomainEmails[0];
}
return backstageUser;
};
```
Once you have imported the emails you can resolve users in your [sign-in
resolver](../../auth/github/provider.md) using the catalog entity search via email
This example assumes you have implemented the custom transformer following the [Custom Transformers](#custom-transformers) and [Transformer Examples](#transformer-examples) documentation in the sections above.
```typescript title="packages/backend/src/plugins/auth.ts"
Once you have imported the emails you can resolve users by building a [Custom Resolver](../../auth/identity-resolver.md#building-custom-resolvers). In this custom resolver you can then use this example to properly match the user:
```ts
ctx.signInWithCatalogUser({
filter: {
kind: ['User'],
@@ -315,50 +253,3 @@ ctx.signInWithCatalogUser({
},
});
```
## Using a Processor instead of a Provider
An alternative to using the Provider for ingesting organizational entities is to
use a Processor. This is the old way that's based on registering locations with
the proper type and target, triggering the processor to run.
The drawback of this method is that it will leave orphaned Group/User entities
whenever they are deleted on your GitHub server, and you cannot control the
frequency with which they are refreshed, separately from other processors.
### Processor Installation
The `GithubOrgReaderProcessor` is not registered by default, so you have to
install and register it in the catalog plugin:
```bash
# From your Backstage root directory
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-github
```
```typescript title="packages/backend/src/plugins/catalog.ts"
import { GithubOrgReaderProcessor } from '@backstage/plugin-catalog-backend-module-github';
builder.addProcessor(
GithubOrgReaderProcessor.fromConfig(env.config, { logger: env.logger }),
);
```
### Processor Configuration
The integration section of your app-config needs to be set up in the same way as
for the Entity Provider - see above.
In addition to that, you typically want to add a few static locations to your
app-config, which reference your organizations to import. The following
configuration enables an import of the teams and users under the org
`https://github.com/my-org-name` on public GitHub.
```yaml
catalog:
locations:
- type: github-org
target: https://github.com/my-org-name
rules:
- allow: [User, Group]
```
+23 -14
View File
@@ -14,21 +14,28 @@ The Backstage trust model is divided into three groups with different trust leve
An **internal user** is an authenticated user that generally belongs to the organization of a particular Backstage deployment. These users are trusted to the extent that they are not expected to compromise the availability of Backstage, but they are not trusted to not compromise data confidentiality or integrity.
An **integrator** is a user responsible for configuring and maintaining an instance of Backstage. Integrators are fully trusted, since they operate the system and database and therefore have root access to the host system. Additional measures can be taken by adopters of Backstage in order to restrict or observe the access of this group, but that falls outside of the current scope of Backstage.
An **operator** is a user responsible for configuring and maintaining an instance of Backstage. Operators are fully trusted, since they operate the system and database and therefore have root access to the host system. Additional measures can be taken by adopters of Backstage in order to restrict or observe the access of this group, but that falls outside of the current scope of Backstage.
Another group of de facto integrators is internal and external code contributors. When installing Backstage plugins you should vet them just like any other package from an external source. While its possible to limit the impact of for example a supply chain attack by splitting the deployment into separate services with different plugins, the Backstage project itself does not aim to prevent these kinds of attacks or in any other way sandbox or limit the access of plugins.
A **builder** is an internal or external code contributor and end up having a similar level of access as operators. When installing Backstage plugins you should vet them just like any other package from an external source. While its possible to limit the impact of for example a supply chain attack by splitting the deployment into separate services with different plugins, the Backstage project itself does not aim to prevent these kinds of attacks or in any other way sandbox or limit the access of plugins.
An **external user** is a user that does not belong to the other two groups, for example a malicious actor outside of the organization. The security model of Backstage currently assumes that this group does not have any direct access to Backstage, and it is the responsibility of each adopter of Backstage to make sure this is the case.
## Integrator Responsibilities
## Operator Responsibilities
As an integrator of Backstage you yourself are responsible for protecting your Backstage installation from external and unauthorized access. The sign-in system in Backstage does not exist to limit access, only to inform the system of the identity of the user. There are some plugins that have more fine-grained access control through the permissions system, but the primary purpose of that system is to restrict access to resources for internal users rather than Backstage as a whole. A common and recommended way to protect a Backstage deployment from unauthorized access is to deploy it behind an authenticating proxy such as AWSs ALB, GCPs IAP, or Cloudflare Access.
:::info
This section assumes that you are using the
[new backend system](../backend-system/index.md) and at least Backstage release [version 1.24](../releases/v1.24.0.md). Before that Backstage did not come with built-in protection against unauthorized access and you were required to deploy it in a protected environment.
:::
Other responsibilities include protecting the integrity of configuration files as it may otherwise be possible to introduce vulnerable configurations, as well as the confidentiality of configured secrets related to Backstage as these typically include authentication details to third party systems.
Backstage is primarily designed to be deployed in a protected environment rather than being exposed to the public internet. From a confidentiality and integrity perspective, Backstage is designed to protect against unauthorized access to data and to ensure that data is not tampered with. However, Backstage does not provide more than rudimentary protection against denial of service attacks, and it is the responsibility of the operator to ensure that the Backstage deployment is protected against such attacks. A common and recommended way to protect a Backstage deployment from unauthorized access is to deploy it behind an authenticating proxy such as AWSs ALB, GCPs IAP, or Cloudflare Access.
The integrator is ultimately responsible for auditing usage of internal and external plugins as these run on the host system and have access to configuration and secrets. When installing plugins from sources like NPM, you should vet these in the same way that you would vet any other package installed from that source.
Users that are signed-in in to Backstage generally have full access to all information and actions. If more fine-grained control is required, the [permissions system](../permissions/overview.md) should be enabled and configured to restrict access as necessary.
The integrator is also responsible for maintaining the resolved NPM dependencies of their Backstage project. This involves ensuring that `yarn.lock` receives updated versions of packages that have vulnerabilities, when those fixed versions are in range of what the Backstage packages request in their respective `package.json` files. This is commonly done by employing automated tooling such as [Dependabot](https://dependabot.com/), [Snyk](https://snyk.io/), and/or [Renovate](https://docs.renovatebot.com/) on your own repository. When fixed versions exist that are _not_ in range of what Backstage packages request, or when larger operations such as switching out an entire dependency for another one is required, maintainers collaborate with contributors to try to address those dependency declarations in the main project as soon as possible.
An operator is responsible for protecting the integrity of configuration files as it may otherwise be possible to introduce vulnerable configurations, as well as the confidentiality of configured secrets related to Backstage as these typically include authentication details to third party systems.
The operator is ultimately responsible for auditing usage of internal and external plugins as these run on the host system and have access to configuration and secrets. When installing plugins from sources like NPM, you should vet these in the same way that you would vet any other package installed from that source.
The operator is also responsible for maintaining the resolved NPM dependencies of their Backstage project. This involves ensuring that `yarn.lock` receives updated versions of packages that have vulnerabilities, when those fixed versions are in range of what the Backstage packages request in their respective `package.json` files. This is commonly done by employing automated tooling such as [Dependabot](https://dependabot.com/), [Snyk](https://snyk.io/), and/or [Renovate](https://docs.renovatebot.com/) on your own repository. When fixed versions exist that are _not_ in range of what Backstage packages request, or when larger operations such as switching out an entire dependency for another one is required, maintainers collaborate with contributors to try to address those dependency declarations in the main project as soon as possible.
## Common Backend Configuration
@@ -44,21 +51,23 @@ Note that the `UrlReader` system operates with a service context and is not inte
Backstage provides authentication of users through the `auth` plugin, which primarily acts as an authorization server for different OAuth 2.0 provider integrations. These integrations can both serve the purpose of signing users into Backstage, as well as providing delegated access to external resources, and are all subject to the common concerns of implementing secure OAuth 2.0 authorization servers. All auth provider integrations are disabled by default, and need to be enabled through configuration in order to be used. For each Backstage installation it is recommended to only enable the minimal set of providers that are in use by that instance.
It is not within scope of the `auth` backend to protect against unauthorized access, that is something that needs to be handled at a deployment level. See the [Integrator Responsibilities](#integrator-responsibilities) section for more information.
In order to use an auth provider to sign in users into Backstage, it needs to be configured with an [Identity resolver](https://backstage.io/docs/auth/identity-resolver), which is a custom callback implemented in code. The identity resolver is a sensitive part of configuring Backstage and it is important that it always resolves user identities correctly, based on information provided by the authentication provider. There are a number of built-in identity resolvers that can simplify configuration, and it is important that these all resolve users in a secure way, regardless of how they are used.
Backstage also supports authentication through an authenticating reverse proxy such as [AWS ALB](https://aws.amazon.com/elasticloadbalancing/application-load-balancer/), where the user identity is read from the incoming proxied decorated request. The following proxy auth providers verify the signature of incoming requests, and are therefore safe to deploy with direct access by users: `awsAlb`, `cfAccess`, and `gcpIap`. Providers like `oauth2Proxy` do not verify the incoming request and can therefore be spoofed by a malicious internal user to supply the `auth` backend with forged identity information. Its therefore highly recommended to restrict access to the `oauth2Proxy` endpoints, or use a different provider.
As part of signing in with an identity resolver, a Backstage Token is issued containing the resolved user identity. The tokens are asymmetrically signed JSON Web Tokens, with the public keys available to any service that wishes to verify a token. The signing keys are rotated continuously and are unique to each installation of Backstage, meaning that Backstage Tokens are not shared across installations. The token contains claims for the user identity and ownership information, which can be used to determine what Backstage resources are owned by that user or group. It is important that this token can not be forged outside of the `auth` plugin, with the exception of other plugins deployed in the same backend service or sharing the same database. For a high-security deployment, the `auth` backend should therefore be deployed in a separate service with its own database.
The token is used to prove the identity of the user within the Backstage system, and is used throughout Backstage plugins to control access. It is important that the ownership resolution logic is consistent across the entire Backstage ecosystem, with no possibility of misinterpreting the ownership information.
For cross-backend communication, the Backstage Token is typically forwarded or, in strict backend-to-backend communication without a user party, the backend itself issues a service token based on a pre-shared secret which is then validated on the receiving end. There are no unique service identities tied to these tokens at this point, meaning the tokens can be used across all services in a Backstage installation. This is something that we aim to improve in the future.
One of the claims in a user token is the User Identity Proof or `uip`. This is an additional signature of the token that allows for offline token transformation. By replacing the original signature with the `uip` the token is still proof of a user identity, but it no longer acts as a full access token and will be rejected by most plugin endpoints. Plugins can explicitly allow use of this limited token where required, but this should only be used when necessary when a full token is not available, and ideally just for read-only access. Use-cases for limited users tokens include cookie authentication of static assets, storage of user identity proofs in a database, and similar.
Backstage also supports authentication through a proxy where the user identity is read from the incoming request from the proxy, which has been decorated by an authenticating reverse proxy such as [AWS ALB](https://aws.amazon.com/elasticloadbalancing/application-load-balancer/). The following proxy auth providers verify the signature of incoming requests, and are therefore safe to deploy with direct access by users: `awsAlb`, `cfAccess`, and `gcpIap`. Providers like `oauth2Proxy` does not verify the incoming request and can therefore be spoofed by a malicious internal user to supply the `auth` backend with forged identity information. Its therefore highly recommended to restrict access to the `oauth2Proxy` endpoints, or use a different provider.
The communication across backend plugins uses a similar authentication scheme to the user authentication. Each backend plugin generates and publishes its own set of keys that it uses to sign its tokens, and the public keys are shared with all other plugins for verification. The expected location of each plugin's published JWKS is determined by the `DiscoveryService` implementation in the backend, which means that it is vital for any custom implementation of that service to be careful with user input. The tokens signed by each plugin contain both the source and target plugin ID, which means that the token can not be reused to access other plugins.
When forwarding a user identity in a call across backend plugins only the limited user token with `uip` is used, wrapped in a new service token that is signed by the calling plugin. This means that the receiving plugin can trust the user identity, but it is not able to make further calls on behalf of the user except for with the plugins that it is authorized to call. That is except for any endpoints in other plugins that accept limited user tokens, which is a reason to avoid accepting them when possible.
## Catalog
Integrators should configure [catalog rules](https://backstage.io/docs/features/software-catalog/configuration#catalog-rules) to limit the allowed entity kinds that users can define. In general it is best to restrict definition of User, Group, and Template entities so that internal users cannot register additional ones. Template entities define actions that are executed on the backend hosts, and while the goal is for these actions to be secure regardless of input, it is still a more sensitive context and it is recommended that you protect it with additional checks. It is very important to not allow registration of User and Group entities if you ingest and rely on these as organizational data in your catalog. Doing so could otherwise open up for the ability to impersonate users and confuse group membership information. You should always ingest organizational data using a statically configured catalog location or an entity provider reading from a trusted source. The entities emitted directly by an entity provider are always trusted and rules are not applied to them, but any entities produced further down the chain are still subject to the rules.
Operators should configure [catalog rules](https://backstage.io/docs/features/software-catalog/configuration#catalog-rules) to limit the allowed entity kinds that users can define. In general it is best to restrict definition of User, Group, and Template entities so that internal users cannot register additional ones. Template entities define actions that are executed on the backend hosts, and while the goal is for these actions to be secure regardless of input, it is still a more sensitive context and it is recommended that you protect it with additional checks. It is very important to not allow registration of User and Group entities if you ingest and rely on these as organizational data in your catalog. Doing so could otherwise open up for the ability to impersonate users and confuse group membership information. You should always ingest organizational data using a statically configured catalog location or an entity provider reading from a trusted source. The entities emitted directly by an entity provider are always trusted and rules are not applied to them, but any entities produced further down the chain are still subject to the rules.
The Catalog does not aim to protect against resource exhaustion attacks in its default setup. If you need to prevent your internal users from being able to register large amounts of entities, then it is recommended to disable entity registration and use a different approach for discovering entities. One way to mitigate any resource exhaustion attacks is to only allow the catalog to read from trusted SCM sources that have an audit trail. Catalog currently lacks limits for entity hierarchy depth and entity size, which we hope to address in the future.
@@ -68,11 +77,11 @@ By default all internal users are allowed to create and delete entities. If this
By default, Scaffolding jobs execute directly on the host machine, including any actions defined in the template. Because the Scaffolder templates are considered a more sensitive area it is recommended to control access to create and update templates to trusted parties. Template execution is intended to be secure regardless of input, but we still recommend this additional layer of protection. The string templating is executed in a [node VM sandbox](https://github.com/laverdet/isolated-vm) to mitigate the possibility of remote code execution attacks.
The Scaffolder often has elevated permissions to for example create repositories in a Github organization. The integrator should therefore be cautious of Scaffolder Templates that for example delete or update existing resources as the user input is typically user defined and can therefore delete or modify resources maliciously or by mistake.
The Scaffolder often has elevated permissions to for example create repositories in a Github organization. The operator should therefore be cautious of Scaffolder Templates that for example delete or update existing resources as the user input is typically user defined and can therefore delete or modify resources maliciously or by mistake.
One strategy that allows you to reduce the access that the Scaffolder service has is to rely on user credentials when executing actions. For example, a GitHub App integration could be configured with read-only permissions, with a separate user OAuth token used to create repositories. This requires that your users have access to create repositories in the first place.
The integrator should audit installed scaffolding actions just like any other plugin package. It is also important to verify that installed actions fall in line with your own security requirements, as some actions might be intended for more relaxed environments.
The operator should audit installed scaffolding actions just like any other plugin package. It is also important to verify that installed actions fall in line with your own security requirements, as some actions might be intended for more relaxed environments.
By default all internal users are allowed to execute templates in the scaffolder. If this does not fit your organization's needs it is recommended to enable and configure the [permission](https://backstage.io/docs/permissions/overview) system to restrict these operations.
@@ -37,7 +37,11 @@ export const todoListPermissions = [todoListCreatePermission];
For this tutorial, we've automatically exported all permissions from this file (see `plugins/todo-list-common/src/index.ts`).
> Note: We use a separate `todo-list-common` package since all permissions authorized by your plugin should be exported from a ["common-library" package](https://backstage.io/docs/local-dev/cli-build-system#package-roles). This allows Backstage integrators to reference them in frontend components as well as permission policies.
:::note Note
We use a separate `todo-list-common` package since all permissions authorized by your plugin should be exported from a ["common-library" package](https://backstage.io/docs/local-dev/cli-build-system#package-roles). This allows Backstage integrators to reference them in frontend components as well as permission policies.
:::
## Authorizing using the new permission
+3 -3
View File
@@ -46,9 +46,9 @@ To suggest an integration, please [open an issue][add-tool] for the analytics
tool your organization uses. Or jump to [Writing Integrations][int-howto] to
learn how to contribute the integration yourself!
[ga]: https://github.com/backstage/backstage/blob/master/plugins/analytics-module-ga/README.md
[ga4]: https://github.com/backstage/backstage/blob/master/plugins/analytics-module-ga4/README.md
[newrelic-browser]: https://github.com/backstage/backstage/blob/master/plugins/analytics-module-newrelic-browser/README.md
[ga]: https://github.com/backstage/community-plugins/blob/main/workspaces/analytics/plugins/analytics-module-ga/README.md
[ga4]: https://github.com/backstage/community-plugins/blob/main/workspaces/analytics/plugins/analytics-module-ga4/README.md
[newrelic-browser]: https://github.com/backstage/community-plugins/blob/main/workspaces/analytics/plugins/analytics-module-newrelic-browser/README.md
[qm]: https://github.com/quantummetric/analytics-module-qm/blob/main/README.md
[matomo]: https://github.com/janus-idp/backstage-plugins/blob/main/plugins/analytics-module-matomo/README.md
[add-tool]: https://github.com/backstage/backstage/issues/new?assignees=&labels=plugin&template=plugin_template.md&title=%5BAnalytics+Module%5D+THE+ANALYTICS+TOOL+TO+INTEGRATE
+16 -18
View File
@@ -6,39 +6,39 @@ description: Details the process of defining setting and reading a feature flag.
Backstage offers the ability to define feature flags inside a plugin or during application creation. This allows you to restrict parts of your plugin to those individual users who have toggled the feature flag to on.
This page describes the process of defining setting and reading a feature flag. If you are looking for using feature flags with software templates that can be found under [Writing Templates](https://backstage.io/docs/features/software-templates/writing-templates#remove-sections-or-fields-based-on-feature-flags).
This page describes the process of defining, setting and reading a feature flag. If you are looking for using feature flags specifically with software templates please see [Writing Templates](https://backstage.io/docs/features/software-templates/writing-templates#remove-sections-or-fields-based-on-feature-flags).
## Defining a Feature Flag
### In a plugin
Defining feature flag in a plugin is done by passing the name of the feature flag into the `featureFlags` array:
Defining a feature flag in a plugin is done by passing the name of the feature flag into the `featureFlags` array:
```ts
/* src/plugin.ts */
import { createPlugin, createRouteRef } from '@backstage/core-plugin-api';
import ExampleComponent from './components/ExampleComponent';
```ts title="src/plugin.ts"
import { createPlugin } from '@backstage/core-plugin-api';
export const examplePlugin = createPlugin({
id: 'example',
routes: {
root: rootRouteRef,
},
// ...
featureFlags: [{ name: 'show-example-feature' }],
// ...
});
```
### In the application
Defining feature flag in the application is done by adding feature flags in`featureFlags` array in
Defining a feature flag in the application is done by adding feature flags in `featureFlags` array in the
`createApp()` function call:
```ts
```ts title="packages/app/src/App.tsx"
import { createApp } from '@backstage/app-defaults';
const app = createApp({
// ...
featureFlags: [
{
pluginId: '', // pluginId is required for feature flags in plugins. It can be left blank for a feature flag leveraged in the application.
// pluginId is required for feature flags used in plugins.
// pluginId can be left blank for a feature flag used in the application and not in plugins.
pluginId: '',
name: 'tech-radar',
description: 'Enables the tech radar plugin',
},
@@ -49,11 +49,9 @@ const app = createApp({
## Enabling Feature Flags
Feature flags are defaulted to off and can be updated by individual users in the backstage interface.
Feature flags are defaulted to off and can be updated by individual users in the backstage interface. These are set by navigating to the page under `Settings` > `Feature Flags`.
These are set by navigating to the page under `Settings` > `Feature Flags`.
The users selection is saved in the users browsers local storage. Once toggled it may be required for a user to refresh the page to see any new changes.
The user's selection is saved in the user's browser local storage. Once a feature flag is toggled it may be required for a user to refresh the page to see the change.
## FeatureFlagged Component
@@ -75,7 +73,7 @@ import { FeatureFlagged } from '@backstage/core-app-api';
## Evaluating Feature Flag State
It is also possible to test the feature flag state using the [FeatureFlags Api](https://backstage.io/docs/reference/core-plugin-api.featureflagsapi).
It is also possible to query a feature flag using the [FeatureFlags Api](https://backstage.io/docs/reference/core-plugin-api.featureflagsapi).
```ts
import { useApi, featureFlagsApiRef } from '@backstage/core-plugin-api';

Some files were not shown because too many files have changed in this diff Show More