Compare commits

...

9 Commits

Author SHA1 Message Date
Scott Wilson
499ff3635b feature: add general env var for allowing internal ip connections and update relevant docs 2025-04-14 14:04:26 -07:00
carlosmonastyrski
ac8b3aca60 Merge pull request #3415 from Infisical/feat/addBackstagePluginsDocs
Add Backstage Plugins docs
2025-04-14 15:18:20 -03:00
carlosmonastyrski
4ea0cc62e3 Change External Integrations to Others 2025-04-14 15:07:16 -03:00
Sheen
bdab16f64b Merge pull request #3414 from Infisical/misc/add-proper-display-of-auth-failure-message
misc: add proper display of auth failure message for OIDC
2025-04-15 01:54:08 +08:00
Akhil Mohan
3c07204532 Merge pull request #3416 from Infisical/daniel/make-idoment
fix: improve kms key migration
2025-04-14 23:08:59 +05:30
Daniel Hougaard
c0926bec69 fix: no check for encryption algorithm on external KMS 2025-04-14 21:36:38 +04:00
Daniel Hougaard
b9d74e0aed requested changes 2025-04-14 21:36:16 +04:00
Daniel Hougaard
f3078040fc fix: improve kms key migration 2025-04-14 21:22:59 +04:00
carlosmonastyrski
f2fead7a51 Add Backstage Plugins docs 2025-04-14 14:15:42 -03:00
11 changed files with 174 additions and 19 deletions

View File

@@ -5,15 +5,21 @@ import { KmsKeyUsage } from "@app/services/kms/kms-types";
import { TableName } from "../schemas";
export async function up(knex: Knex): Promise<void> {
const hasTypeColumn = await knex.schema.hasColumn(TableName.KmsKey, "type");
const hasKeyUsageColumn = await knex.schema.hasColumn(TableName.KmsKey, "keyUsage");
await knex.schema.alterTable(TableName.KmsKey, (t) => {
if (!hasTypeColumn) t.string("keyUsage").notNullable().defaultTo(KmsKeyUsage.ENCRYPT_DECRYPT);
});
if (!hasKeyUsageColumn) {
await knex.schema.alterTable(TableName.KmsKey, (t) => {
t.string("keyUsage").notNullable().defaultTo(KmsKeyUsage.ENCRYPT_DECRYPT);
});
}
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.alterTable(TableName.KmsKey, (t) => {
t.dropColumn("keyUsage");
});
const hasKeyUsageColumn = await knex.schema.hasColumn(TableName.KmsKey, "keyUsage");
if (hasKeyUsageColumn) {
await knex.schema.alterTable(TableName.KmsKey, (t) => {
t.dropColumn("keyUsage");
});
}
}

View File

@@ -42,7 +42,7 @@ export const verifyHostInputValidity = async (host: string, isGateway = false) =
inputHostIps.push(...resolvedIps);
}
if (!isGateway && !appCfg.DYNAMIC_SECRET_ALLOW_INTERNAL_IP) {
if (!isGateway && !(appCfg.DYNAMIC_SECRET_ALLOW_INTERNAL_IP || appCfg.ALLOW_INTERNAL_IP_CONNECTIONS)) {
const isInternalIp = inputHostIps.some((el) => isPrivateIp(el));
if (isInternalIp) throw new BadRequestError({ message: "Invalid db host" });
}

View File

@@ -197,6 +197,7 @@ const envSchema = z
/* ----------------------------------------------------------------------------- */
/* App Connections ----------------------------------------------------------------------------- */
ALLOW_INTERNAL_IP_CONNECTIONS: zodStrBool.default("false"),
// aws
INF_APP_CONNECTION_AWS_ACCESS_KEY_ID: zpStr(z.string().optional()),

View File

@@ -2,10 +2,16 @@ import dns from "node:dns/promises";
import { isIPv4 } from "net";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError } from "../errors";
import { isPrivateIp } from "../ip/ipRange";
export const blockLocalAndPrivateIpAddresses = async (url: string) => {
const appCfg = getConfig();
if (appCfg.isDevelopmentMode) return;
const validUrl = new URL(url);
const inputHostIps: string[] = [];
if (isIPv4(validUrl.host)) {
@@ -18,7 +24,8 @@ export const blockLocalAndPrivateIpAddresses = async (url: string) => {
inputHostIps.push(...resolvedIps);
}
const isInternalIp = inputHostIps.some((el) => isPrivateIp(el));
if (isInternalIp) throw new BadRequestError({ message: "Local IPs not allowed as URL" });
if (isInternalIp && !appCfg.ALLOW_INTERNAL_IP_CONNECTIONS)
throw new BadRequestError({ message: "Local IPs not allowed as URL" });
};
type FQDNOptions = {

View File

@@ -288,11 +288,6 @@ export const kmsServiceFactory = ({
throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` });
}
const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as SymmetricKeyAlgorithm;
verifyKeyTypeAndAlgorithm(kmsDoc.keyUsage as KmsKeyUsage, encryptionAlgorithm, {
forceType: KmsKeyUsage.ENCRYPT_DECRYPT
});
if (kmsDoc.externalKms) {
let externalKms: TExternalKmsProviderFns;
@@ -353,6 +348,11 @@ export const kmsServiceFactory = ({
};
}
const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as SymmetricKeyAlgorithm;
verifyKeyTypeAndAlgorithm(kmsDoc.keyUsage as KmsKeyUsage, encryptionAlgorithm, {
forceType: KmsKeyUsage.ENCRYPT_DECRYPT
});
// internal KMS
const keyCipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256);
const dataCipher = symmetricCipherService(encryptionAlgorithm);
@@ -509,11 +509,6 @@ export const kmsServiceFactory = ({
throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` });
}
const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as SymmetricKeyAlgorithm;
verifyKeyTypeAndAlgorithm(kmsDoc.keyUsage as KmsKeyUsage, encryptionAlgorithm, {
forceType: KmsKeyUsage.ENCRYPT_DECRYPT
});
if (kmsDoc.externalKms) {
let externalKms: TExternalKmsProviderFns;
if (!kmsDoc.orgKms.id || !kmsDoc.orgKms.encryptedDataKey) {
@@ -568,6 +563,11 @@ export const kmsServiceFactory = ({
};
}
const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as SymmetricKeyAlgorithm;
verifyKeyTypeAndAlgorithm(kmsDoc.keyUsage as KmsKeyUsage, encryptionAlgorithm, {
forceType: KmsKeyUsage.ENCRYPT_DECRYPT
});
// internal KMS
const keyCipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256);
const dataCipher = symmetricCipherService(encryptionAlgorithm);

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 KiB

View File

@@ -51,6 +51,10 @@ Infisical supports connecting to Microsoft SQL Server using database principals.
- `username` - The username of the login created in the steps above
- `password` - The password of the login created in the steps above
- `sslCertificate` (optional) - The SSL certificate required for connection (if configured)
<Note>
If you are self-hosting Infisical and intend to connect to an internal/private IP address, be sure to set the `ALLOW_INTERNAL_IP_CONNECTIONS` environment variable to `true`.
</Note>
</Step>
</Steps>

View File

@@ -41,6 +41,10 @@ Infisical supports connecting to PostgreSQL using a database role.
- `username` - The role name of the login created in the steps above
- `password` - The role password of the login created in the steps above
- `sslCertificate` (optional) - The SSL certificate required for connection (if configured)
<Note>
If you are self-hosting Infisical and intend to connect to an internal/private IP address, be sure to set the `ALLOW_INTERNAL_IP_CONNECTIONS` environment variable to `true`.
</Note>
</Step>
</Steps>

123
docs/integrations/external/backstage.mdx vendored Normal file
View File

@@ -0,0 +1,123 @@
---
title: Backstage Infisical Plugin
description: A powerful plugin that integrates Infisical secrets management into your Backstage developer portal.
---
Integrate secrets management into your developer portal with the Backstage Infisical plugin suite. This plugin provides a seamless interface to manage your [Infisical](https://infisical.com) secrets directly within Backstage, including full support for environments and folder structure.
## Features
- **Secrets Management**: View, create, update, and delete secrets from Infisical
- **Folder Navigation**: Explore the full folder structure of your Infisical projects
- **Multi-Environment Support**: Easily switch between and manage different environments
- **Entity Linking**: Map Backstage entities to specific Infisical projects via annotations
---
## Installation
### Frontend Plugin
```bash
# From your Backstage root directory
yarn --cwd packages/app add @infisical/backstage-plugin-infisical
```
### Backend Plugin
```bash
# From your Backstage root directory
yarn --cwd packages/backend add @infisical/backstage-backend-plugin-infisical
```
## Configuration
### Backend
Update your `app-config.yaml`:
```yaml
infisical:
baseUrl: https://app.infisical.com
authentication:
# Option 1: API Token Authentication
auth_token:
token: ${INFISICAL_API_TOKEN}
# Option 2: Client Credentials Authentication
universalAuth:
clientId: ${INFISICAL_CLIENT_ID}
clientSecret: ${INFISICAL_CLIENT_SECRET}
```
<Tip>
If you have not created a machine identity yet, you can do so in [Identities](/documentation/platform/identities/machine-identities)
</Tip>
Register the plugin in `packages/backend/src/index.ts`:
```ts
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
backend.add(import('@infisical/backstage-backend-plugin-infisical'));
backend.start();
```
### Frontend
Update `packages/app/src/App.tsx` to include the plugin:
```tsx
import { infisicalPlugin } from '@infisical/backstage-plugin-infisical';
const app = createApp({
plugins: [
infisicalPlugin,
// ...other plugins
],
});
```
Modify `packages/app/src/components/catalog/EntityPage.tsx`:
```tsx
import { EntityInfisicalContent } from '@infisical/backstage-plugin-infisical';
const serviceEntityPage = (
<EntityLayout>
{/* ...other tabs */}
<EntityLayout.Route path="/infisical" title="Secrets">
<EntityInfisicalContent />
</EntityLayout.Route>
</EntityLayout>
);
```
### Entity Annotation
Add the Infisical project ID to your entity yaml settings:
```yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: example-service
annotations:
infisical/projectId: <your-infisical-project-id>
```
> Replace `<your-infisical-project-id>` with the actual project ID from Infisical.
## Usage
Once installed and configured, you can:
1. **View and manage secrets** in Infisical from within Backstage
2. **Create, update, and delete** secrets using the Infisical tab in entity pages
3. **Navigate environments and folders**
4. **Search and filter** secrets by key, value, or comments
![Backstage Plugin Table](/images/integrations/external/backstage/backstage-plugin-infisical.png)

View File

@@ -552,6 +552,12 @@
"group": "Build Tool Integrations",
"pages": ["integrations/build-tools/gradle"]
},
{
"group": "Others",
"pages": [
"integrations/external/backstage"
]
},
{
"group": "",
"pages": ["sdks/overview"]

View File

@@ -34,6 +34,10 @@ Used to configure platform-specific security and operational settings
this to `false`.
</ParamField>
<ParamField query="ALLOW_INTERNAL_IP_CONNECTIONS" type="bool" default="false" optional>
Determines whether App Connections and Dynamic Secrets are permitted to connect with internal/private IP addresses.
</ParamField>
## CORS
Cross-Origin Resource Sharing (CORS) is a security feature that allows web applications running on one domain to access resources from another domain.