Compare commits

..

25 Commits

Author SHA1 Message Date
ebd3d7c7c4 Merge pull request #1274 from Infisical/fix-vercel-preview-env
Fix: Vercel integration preview environment client side error
2024-01-04 10:18:25 -05:00
9ecbfe201b Update create.tsx 2024-01-04 17:42:31 +04:00
ba2a03897f update secret import create notif 2024-01-04 01:55:34 -05:00
304f14c0ed update service token create notif 2024-01-04 01:52:03 -05:00
51e5c25e16 update imports/service token crud 2024-01-04 00:55:03 -05:00
0f6490b1e7 move cli to bin folder 2024-01-03 20:17:34 -05:00
f894e48fcb remove unused import 2024-01-02 13:55:01 -05:00
37cfa22619 add back macos build 2024-01-02 13:47:15 -05:00
94557344b7 wrap cli into a docker image 2024-01-02 13:43:55 -05:00
d5063018eb Added identities, universal auth, agent to changelog 2024-01-02 10:05:43 +01:00
51d68505d3 Merge pull request #1268 from Infisical/posthog-revamp
removed posthog cli export events
2023-12-29 15:18:59 -05:00
683c512bce Merge pull request #1266 from Infisical/ui-improvements
ui and docs improvements
2023-12-25 14:33:47 -05:00
43ff28b5fb added terraform useragent 2023-12-24 17:13:29 -08:00
ce41855e84 added sdk useragent and channel 2023-12-24 16:58:48 -08:00
d24461b17c removed posthog cli export events 2023-12-24 15:49:18 -08:00
74f3ca5356 Merge pull request #1267 from Infisical/sdk/docs-update-2
Sdk/docs update 2
2023-12-24 21:57:52 +04:00
db27beaf0b Update overview.mdx 2023-12-24 21:54:57 +04:00
d6e55f51f2 Updated Python docs 2023-12-24 21:36:47 +04:00
e9b5996567 Updated node caching docs 2023-12-24 21:36:40 +04:00
094fe73917 Updated Java caching docs 2023-12-24 21:36:31 +04:00
dc3f85e92e Re-added an updated FAQ 2023-12-24 17:11:20 +04:00
c463256058 Updated Python docs 2023-12-24 17:11:08 +04:00
8df22302fd Updated Node docs 2023-12-24 17:11:03 +04:00
f37fa2bbf5 Updated Java docs 2023-12-24 17:10:54 +04:00
382cb910af tps 2023-12-23 17:31:34 -05:00
19 changed files with 192 additions and 62 deletions

View File

@ -108,7 +108,7 @@ brews:
zsh_completion.install "completions/infisical.zsh" => "_infisical"
fish_completion.install "completions/infisical.fish"
man1.install "manpages/infisical.1.gz"
- name: 'infisical@{{.Version}}'
- name: "infisical@{{.Version}}"
tap:
owner: Infisical
name: homebrew-get-cli
@ -186,12 +186,14 @@ aurs:
# man pages
install -Dm644 "./manpages/infisical.1.gz" "${pkgdir}/usr/share/man/man1/infisical.1.gz"
# dockers:
# - dockerfile: cli/docker/Dockerfile
# goos: linux
# goarch: amd64
# ids:
# - infisical
# image_templates:
# - "infisical/cli:{{ .Version }}"
# - "infisical/cli:latest"
dockers:
- dockerfile: docker/alpine
goos: linux
goarch: amd64
ids:
- all-other-builds
image_templates:
- "infisical/cli:{{ .Version }}"
- "infisical/cli:{{ .Major }}.{{ .Minor }}"
- "infisical/cli:{{ .Major }}"
- "infisical/cli:latest"

View File

@ -111,11 +111,17 @@ export const createSecretImp = async (req: Request, res: Response) => {
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: directory })
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment: secretImport.environment, secretPath: secretImport.secretPath })
);
}
const folders = await Folder.findOne({
@ -323,7 +329,7 @@ export const updateSecretImport = async (req: Request, res: Response) => {
authData: req.authData,
workspaceId: importSecDoc.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
subject(ProjectPermissionSub.Secrets, {
@ -331,6 +337,13 @@ export const updateSecretImport = async (req: Request, res: Response) => {
secretPath
})
);
secretImports.forEach(({ environment, secretPath }) => {
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
);
})
}
const orderBefore = importSecDoc.imports;
@ -453,7 +466,7 @@ export const deleteSecretImport = async (req: Request, res: Response) => {
authData: req.authData,
workspaceId: importSecDoc.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
subject(ProjectPermissionSub.Secrets, {
@ -620,7 +633,7 @@ export const getAllSecretsFromImport = async (req: Request, res: Response) => {
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, {
@ -677,7 +690,7 @@ export const getAllSecretsFromImport = async (req: Request, res: Response) => {
authData: req.authData,
workspaceId: importSecDoc.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, {

View File

@ -13,7 +13,7 @@ import {
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../ee/services/ProjectRoleService";
import { ForbiddenError } from "@casl/ability";
import { ForbiddenError, subject } from "@casl/ability";
import { Types } from "mongoose";
/**
@ -86,6 +86,14 @@ export const createServiceTokenData = async (req: Request, res: Response) => {
ProjectPermissionSub.ServiceTokens
);
scopes.forEach(({ environment, secretPath }) => {
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: secretPath })
);
})
const secret = crypto.randomBytes(16).toString("hex");
const secretHash = await bcrypt.hash(secret, await getSaltRounds());

View File

@ -8,7 +8,10 @@ export enum UserAgentType {
WEB = "web",
CLI = "cli",
K8_OPERATOR = "k8-operator",
OTHER = "other"
TERRAFORM = "terraform",
OTHER = "other",
PYTHON_SDK = "InfisicalPythonSDK",
NODE_SDK = "InfisicalNodeSDK"
}
export enum EventType {

View File

@ -10,7 +10,7 @@ export const apiLimiter = rateLimit({
// errorHandler: console.error.bind(null, 'rate-limit-mongo')
// }),
windowMs: 60 * 1000,
max: 350,
max: 480,
standardHeaders: true,
legacyHeaders: false,
skip: (request) => {
@ -30,7 +30,7 @@ const authLimit = rateLimit({
// collectionName: "expressRateRecords-authLimit",
// }),
windowMs: 60 * 1000,
max: 100,
max: 300,
standardHeaders: true,
legacyHeaders: false,
keyGenerator: (req, res) => {
@ -46,8 +46,8 @@ export const passwordLimiter = rateLimit({
// errorHandler: console.error.bind(null, 'rate-limit-mongo'),
// collectionName: "expressRateRecords-passwordLimiter",
// }),
windowMs: 60 * 60 * 1000,
max: 10,
windowMs: 60 * 1000,
max: 300,
standardHeaders: true,
legacyHeaders: false,
keyGenerator: (req, res) => {

View File

@ -7,8 +7,14 @@ export const getUserAgentType = function (userAgent: string | undefined) {
return UserAgentType.CLI;
} else if (userAgent == UserAgentType.K8_OPERATOR) {
return UserAgentType.K8_OPERATOR;
} else if (userAgent == UserAgentType.TERRAFORM) {
return UserAgentType.TERRAFORM;
} else if (userAgent.toLowerCase().includes("mozilla")) {
return UserAgentType.WEB;
} else if (userAgent.includes(UserAgentType.NODE_SDK)) {
return UserAgentType.NODE_SDK;
} else if (userAgent.includes(UserAgentType.PYTHON_SDK)) {
return UserAgentType.PYTHON_SDK;
} else {
return UserAgentType.OTHER;
}

View File

@ -1,4 +0,0 @@
FROM alpine
RUN apk add --no-cache tini
COPY infisical /bin/infisical
ENTRYPOINT ["/sbin/tini", "--", "/bin/infisical"]

9
cli/docker/alpine Normal file
View File

@ -0,0 +1,9 @@
FROM alpine
RUN apk add --no-cache tini
## Upgrade OpenSSL libraries to mitigate known vulnerabilities as the current Alpine image has not been patched yet.
RUN apk update && apk upgrade --no-cache libcrypto3 libssl3
COPY infisical /bin/infisical
ENTRYPOINT ["/sbin/tini", "--", "/bin/infisical"]

View File

@ -11,7 +11,6 @@ import (
"github.com/Infisical/infisical-merge/packages/models"
"github.com/Infisical/infisical-merge/packages/util"
"github.com/posthog/posthog-go"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
)
@ -102,7 +101,7 @@ var exportCmd = &cobra.Command{
fmt.Print(output)
Telemetry.CaptureEvent("cli-command:export", posthog.NewProperties().Set("secretsCount", len(secrets)).Set("version", util.CLI_VERSION))
// Telemetry.CaptureEvent("cli-command:export", posthog.NewProperties().Set("secretsCount", len(secrets)).Set("version", util.CLI_VERSION))
},
}

View File

@ -6,8 +6,10 @@ The changelog below reflects new product developments and updates on a monthly b
## December 2023
- Added ability to [manage folders via CLI](https://infisical.com/docs/cli/commands/secrets).
- Released [(machine) identities](https://infisical.com/docs/documentation/platform/identities/overview) and [universal auth](https://infisical.com/docs/documentation/platform/identities/universal-auth) features.
- Created new cross-language SDKs for [Python](https://infisical.com/docs/sdks/languages/python), [Node](https://infisical.com/docs/sdks/languages/node), and [Java](https://infisical.com/docs/sdks/languages/java).
- Released first version of the [Infisical Agent](https://infisical.com/docs/infisical-agent/overview)
- Added ability to [manage folders via CLI](https://infisical.com/docs/cli/commands/secrets).
## November 2023

View File

@ -19,6 +19,7 @@ public class Example {
ClientSettings settings = new ClientSettings();
settings.setClientID("MACHINE_IDENTITY_CLIENT_ID");
settings.setClientSecret("MACHINE_IDENTITY_CLIENT_SECRET");
settings.setCacheTTL(Long.valueOf(300)); // 300 seconds, 5 minutes
InfisicalClient client = new InfisicalClient(settings);
@ -88,6 +89,11 @@ public class App {
An access token obtained from the machine identity login endpoint.
</ParamField>
<ParamField query="setCacheTTL()" type="number" default="300" optional>
Time-to-live (in seconds) for refreshing cached secrets.
If manually set to 0, caching will be disabled, this is not recommended.
</ParamField>
<ParamField query="setSiteURL()" type="string" default="https://app.infisical.com" optional>
Your self-hosted absolute site URL including the protocol (e.g. `https://app.infisical.com`)
</ParamField>
@ -95,6 +101,10 @@ public class App {
</ParamField>
### Caching
To reduce the number of API requests, the SDK temporarily stores secrets it retrieves. By default, a secret remains cached for 5 minutes after it's first fetched. Each time it's fetched again, this 5-minute timer resets. You can adjust this caching duration by setting the "cacheTTL" option when creating the client.
## Working with Secrets
### client.listSecrets(options)
@ -127,7 +137,11 @@ Retrieve all secrets within the Infisical project and environment that client is
The path from where secrets should be fetched from.
</ParamField>
<ParamField query="setIncludeImports" type="string" default="https://app.infisical.com" optional>
<ParamField query="setAttachToProcessEnv()" type="boolean" default="false" optional>
Whether or not to set the fetched secrets to the process environment. If true, you can access the secrets like so `System.getenv("SECRET_NAME")`.
</ParamField>
<ParamField query="setIncludeImports()" type="boolean" default="false" optional>
Whether or not to include imported secrets from the current path. Read about [secret import](/documentation/platform/secret-reference)
</ParamField>
</Expandable>

View File

@ -104,6 +104,11 @@ Import the SDK and create a client instance with your [Machine Identity](/docume
An access token obtained from the machine identity login endpoint.
</ParamField>
<ParamField query="cacheTtl" type="number" default="300" optional>
Time-to-live (in seconds) for refreshing cached secrets.
If manually set to 0, caching will be disabled, this is not recommended.
</ParamField>
<ParamField query="siteUrl" type="string" default="https://app.infisical.com" optional>
Your self-hosted absolute site URL including the protocol (e.g. `https://app.infisical.com`)
</ParamField>
@ -113,6 +118,11 @@ Import the SDK and create a client instance with your [Machine Identity](/docume
</Expandable>
</ParamField>
### Caching
To reduce the number of API requests, the SDK temporarily stores secrets it retrieves. By default, a secret remains cached for 5 minutes after it's first fetched. Each time it's fetched again, this 5-minute timer resets. You can adjust this caching duration by setting the "cacheTtl" option when creating the client.
## Working with Secrets
### client.listSecrets(options)
@ -143,7 +153,11 @@ Retrieve all secrets within the Infisical project and environment that client is
The path from where secrets should be fetched from.
</ParamField>
<ParamField query="includeImports" type="string" default="https://app.infisical.com" optional>
<ParamField query="attachToProcessEnv" type="boolean" default="false" optional>
Whether or not to set the fetched secrets to the process environment. If true, you can access the secrets like so `process.env["SECRET_NAME"]`.
</ParamField>
<ParamField query="includeImports" type="false" default="boolean" optional>
Whether or not to include imported secrets from the current path. Read about [secret import](/documentation/platform/secret-reference)
</ParamField>
</Expandable>

View File

@ -62,24 +62,40 @@ client = InfisicalClient(ClientSettings(
### Parameters
<ParamField query="client_id" type="string" optional>
Your Infisical Client ID.
</ParamField>
<ParamField query="client_secret" type="string" optional>
Your Infisical Client Secret.
</ParamField>
<ParamField query="access_token" type="string" optional>
If you want to directly pass an access token obtained from the authentication endpoints, you can do so.
</ParamField>
<ParamField
query="site_url"
type="string"
default="https://app.infisical.com"
optional
>
Your self-hosted absolute site URL including the protocol (e.g.
`https://app.infisical.com`)
</ParamField>
<ParamField query="options" type="object">
<Expandable title="properties">
<ParamField query="client_id" type="string" optional>
Your Infisical Client ID.
</ParamField>
<ParamField query="client_secret" type="string" optional>
Your Infisical Client Secret.
</ParamField>
<ParamField query="access_token" type="string" optional>
If you want to directly pass an access token obtained from the authentication endpoints, you can do so.
</ParamField>
<ParamField query="cache_ttl" type="number" default="300" optional>
Time-to-live (in seconds) for refreshing cached secrets.
If manually set to 0, caching will be disabled, this is not recommended.
</ParamField>
<ParamField
query="site_url"
type="string"
default="https://app.infisical.com"
optional
>
Your self-hosted absolute site URL including the protocol (e.g.
`https://app.infisical.com`)
</ParamField>
</Expandable>
</ParamField>
### Caching
To reduce the number of API requests, the SDK temporarily stores secrets it retrieves. By default, a secret remains cached for 5 minutes after it's first fetched. Each time it's fetched again, this 5-minute timer resets. You can adjust this caching duration by setting the "cache_ttl" option when creating the client.
## Working with Secrets
@ -109,7 +125,11 @@ Retrieve all secrets within the Infisical project and environment that client is
The path from where secrets should be fetched from.
</ParamField>
<ParamField query="include_imports" type="string" default="https://app.infisical.com" optional>
<ParamField query="attach_to_process_env" type="boolean" default="false" optional>
Whether or not to set the fetched secrets to the process environment. If true, you can access the secrets like so `process.env["SECRET_NAME"]`.
</ParamField>
<ParamField query="include_imports" type="boolean" default="false" optional>
Whether or not to include imported secrets from the current path. Read about [secret import](/documentation/platform/secret-reference)
</ParamField>
</Expandable>
@ -148,7 +168,7 @@ By default, `getSecret()` fetches and returns a shared secret. If not found, it
<ParamField query="type" type="string" optional>
The type of the secret. Valid options are "shared" or "personal". If not specified, the default value is "personal".
</ParamField>
<ParamField query="include_imports" type="string" default="https://app.infisical.com" optional>
<ParamField query="include_imports" type="boolean" default="false" optional>
Whether or not to include imported secrets from the current path. Read about [secret import](/documentation/platform/secret-reference)
</ParamField>
</Expandable>

View File

@ -31,3 +31,23 @@ From local development to production, Infisical SDKs provide the easiest way for
Manage secrets for your PHP application on demand
</Card>
</CardGroup>
## FAQ
<AccordionGroup>
<Accordion title="Isn't it inefficient if my app makes a request every time it needs a secret?">
The client SDK caches every secret and implements a 5-minute waiting period before re-requesting it. The waiting period can be controlled by
setting the `cacheTTL` parameter at the time of initializing the client.
Note: The exact parameter name may differ depending on the language.
</Accordion>
<Accordion title="Can I attach the environment variables to my process environment?">
Yes you can! The client SDK provides a method to attach the secrets to your process environment. When using the `listSecrets()` method, you
can pass a `attachToProcessEnv` parameter, which tells the SDK to attach all the found secrets to your process environment.
Note: The exact parameter name may differ depending on the language.
</Accordion>
<Accordion title="What if a request for a secret fails?">
The SDK caches every secret and falls back to the cached value if a request fails. If no cached value is found, and the request fails, then the SDK throws an error.
</Accordion>
</AccordionGroup>

View File

@ -50,5 +50,8 @@ export const userAgentTTypeoNameMap: { [K in UserAgentType]: string } = {
[UserAgentType.WEB]: "Web",
[UserAgentType.CLI]: "CLI",
[UserAgentType.K8_OPERATOR]: "K8s operator",
[UserAgentType.TERRAFORM]: "Terraform",
[UserAgentType.NODE_SDK]: "InfisicalNodeSDK",
[UserAgentType.PYTHON_SDK]: "InfisicalPythonSDK",
[UserAgentType.OTHER]: "Other",
};

View File

@ -8,6 +8,9 @@ export enum UserAgentType {
WEB = "web",
CLI = "cli",
K8_OPERATOR = "k8-operator",
TERRAFORM = "terraform",
NODE_SDK = "node-sdk",
PYTHON_SDK = "python-sdk",
OTHER = "other"
}

View File

@ -56,7 +56,7 @@ export default function VercelCreateIntegrationPage() {
appId: targetAppId
});
const filteredBranches = branches?.filter((branchName) => branchName !== "main").concat("");
const filteredBranches = branches?.filter((branchName) => branchName !== "main").concat();
useEffect(() => {
if (workspace) {
@ -125,7 +125,7 @@ export default function VercelCreateIntegrationPage() {
subTitle="Select which environment or folder in Infisical you want to sync to Vercel's environment variables."
>
<div className="flex flex-row items-center">
<div className="inline flex items-center">
<div className="flex items-center">
<Image
src="/images/integrations/Vercel.png"
height={30}

View File

@ -6,6 +6,7 @@ import { useTranslation } from "react-i18next";
import { faCheck, faCopy, faPlus, faTrashCan } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { yupResolver } from "@hookform/resolvers/yup";
import { AxiosError } from "axios";
import * as yup from "yup";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
@ -160,10 +161,18 @@ export const AddServiceTokenModal = ({ popUp, handlePopUpToggle }: Props) => {
});
} catch (err) {
console.error(err);
createNotification({
text: "Failed to create a service token",
type: "error"
});
const axiosError = err as AxiosError
if (axiosError?.response?.status === 401) {
createNotification({
text: "You do not have access to the selected environment/path",
type: "error"
});
} else {
createNotification({
text: "Failed to create a service token",
type: "error"
});
}
}
};

View File

@ -1,5 +1,6 @@
import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { AxiosError } from "axios";
import { z } from "zod";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
@ -78,12 +79,20 @@ export const CreateSecretImportForm = ({
type: "success",
text: "Successfully linked"
});
} catch (error) {
console.log(error);
createNotification({
type: "error",
text: "Failed to link secrets"
});
} catch (err) {
console.error(err);
const axiosError = err as AxiosError
if (axiosError?.response?.status === 401) {
createNotification({
text: "You do not have access to the selected environment/path",
type: "error"
});
} else {
createNotification({
type: "error",
text: "Failed to link secrets"
});
}
}
};