Compare commits

..

36 Commits

Author SHA1 Message Date
356e981401 Merge pull request #1313 from akhilmhdh/feat/migration-mode
feat(infisical-pg): added migration mode env and page
2024-01-27 00:58:58 -05:00
5b41fb0ff5 update text and patch notice 2024-01-27 00:21:57 -05:00
8893aec213 patch saml sso for rippling 2024-01-23 01:11:29 -05:00
c4cb8f8008 Merge pull request #1319 from Infisical/daniel/better-sdk-docs
(Docs): Improve SDK docs
2024-01-23 08:53:28 +04:00
046557c97f Add .NET 2024-01-23 08:47:29 +04:00
a15ba28c18 Update node guide to reflect new SDK 2024-01-23 08:47:20 +04:00
8386f4dcbd Update python guide to reflect new SDK 2024-01-23 08:47:11 +04:00
ada0fd9c5b Add new item for fallbacks 2024-01-23 08:47:01 +04:00
6376c29e49 update maintenace notice 2024-01-19 17:28:35 -05:00
402692614e updated maintenance page 2024-01-19 12:59:18 -08:00
34de6d4e29 feat(infisical-pg): added migration mode env and page 2024-01-20 01:20:14 +05:30
829e906650 Merge pull request #1311 from Infisical/daniel/changelog-jan-2024
[JAN] Changelog points
2024-01-18 20:25:52 -05:00
b7cbb0f1a8 Update overview.mdx 2024-01-19 00:14:03 +04:00
a50ffbb59d Update overview.mdx 2024-01-19 00:13:57 +04:00
48eda0c684 Update overview.mdx 2024-01-15 15:55:37 +04:00
ed89413689 Merge pull request #1293 from Infisical/update-blog
Update blog notification
2024-01-12 13:52:11 -05:00
0c94f77a6d Merge pull request #1302 from akhilmhdh/feat/banner
feat: added main banner for migration
2024-01-12 10:48:21 -05:00
e6068826f8 update migration notification 2024-01-11 23:34:46 -08:00
cfa0a2044e Merge pull request #1304 from Infisical/add-project-config-flag-for-workspace
add project-config-dir flag for run command
2024-01-11 17:21:03 -05:00
134b503c28 remove log 2024-01-11 17:19:39 -05:00
efcbf1aa88 add project-config-dir flag for run command 2024-01-11 16:39:02 -05:00
284c18db07 Merge pull request #1303 from Infisical/daniel/sdk-seo-improvements
(Docs): SDK SEO Improvements & links to packages/repos
2024-01-11 10:53:08 -08:00
1410a44610 SEO Improvements and links to packages/repos 2024-01-11 22:34:11 +04:00
746ffb3840 feat: added main banner for migration 2024-01-11 23:09:57 +05:30
f9f12eafdf Update saml docs 2024-01-10 15:02:10 -08:00
11470a5a0e Merge pull request #1300 from Infisical/daniel/project-docs-secret-reminders
(Docs): Personal overrides and secret reminders awareness
2024-01-10 17:43:16 -05:00
9fe2190115 Update project.mdx 2024-01-11 02:40:37 +04:00
9e2bd31833 Merge pull request #1298 from Infisical/daniel/csharp-docs
(Docs): .NET SDK documentation & updates existing SDK docs
2024-01-10 16:28:40 -05:00
e88b0ad3c4 Update python.mdx 2024-01-11 01:25:10 +04:00
74644fd8bb Added cryptography docs and fixed formatting 2024-01-11 01:12:38 +04:00
2069ac1554 Added CSharp and removed unfinished SDK's 2024-01-11 01:12:26 +04:00
5a2516e0a7 Removed unsupported languages to remove clutter 2024-01-11 01:12:17 +04:00
b52bc3bed7 Added CSharp docs 2024-01-11 01:12:05 +04:00
4a153e5658 Merge pull request #1295 from akhilmhdh/fix/sec-interpolation-undefined
fix(secret-reference): fixed undefined if value not found
2024-01-10 09:59:09 -05:00
7324822be5 fix(secret-reference): fixed undefined if value not found 2024-01-10 11:45:46 +05:30
766f301aea patch agent config by env 2024-01-09 14:30:29 -05:00
35 changed files with 927 additions and 183 deletions

View File

@ -6,6 +6,9 @@ export const client = new InfisicalClient({
token: process.env.INFISICAL_TOKEN!
});
export const getIsMigrationMode = async () =>
(await client.getSecret("MIGRATION_MODE")).secretValue === "true";
export const getPort = async () => (await client.getSecret("PORT")).secretValue || 4000;
export const getEncryptionKey = async () => {
const secretValue = (await client.getSecret("ENCRYPTION_KEY")).secretValue;

View File

@ -3,11 +3,11 @@ import { IServerConfig, ServerConfig } from "../models/serverConfig";
let serverConfig: IServerConfig;
export const serverConfigInit = async () => {
const cfg = await ServerConfig.findOne({});
const cfg = await ServerConfig.findOne({}).lean();
if (!cfg) {
const cfg = new ServerConfig();
await cfg.save();
serverConfig = cfg;
serverConfig = cfg.toObject();
} else {
serverConfig = cfg;
}
@ -19,6 +19,6 @@ export const getServerConfig = () => serverConfig;
export const updateServerConfig = async (data: Partial<IServerConfig>) => {
const cfg = await ServerConfig.findByIdAndUpdate(serverConfig._id, data, { new: true });
if (!cfg) throw new Error("Failed to update server config");
serverConfig = cfg;
serverConfig = cfg.toObject();
return serverConfig;
};

View File

@ -1,5 +1,5 @@
import { Request, Response } from "express";
import { getHttpsEnabled } from "../../config";
import { getHttpsEnabled, getIsMigrationMode } from "../../config";
import { getServerConfig, updateServerConfig as setServerConfig } from "../../config/serverConfig";
import { initializeDefaultOrg, issueAuthTokens } from "../../helpers";
import { validateRequest } from "../../helpers/validation";
@ -8,9 +8,10 @@ import { TelemetryService } from "../../services";
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
import * as reqValidator from "../../validation/admin";
export const getServerConfigInfo = (_req: Request, res: Response) => {
export const getServerConfigInfo = async (_req: Request, res: Response) => {
const config = getServerConfig();
return res.send({ config });
const isMigrationModeOn = await getIsMigrationMode();
return res.send({ config: { ...config, isMigrationModeOn } });
};
export const updateServerConfig = async (req: Request, res: Response) => {

View File

@ -579,7 +579,9 @@ export const getSecretsHelper = async ({
event: "secrets pulled",
distinctId: await TelemetryService.getDistinctId({ authData }),
properties: {
numberOfSecrets: shouldRecordK8Event ? approximateForNoneCapturedEvents : secrets.length,
numberOfSecrets: shouldRecordK8Event
? approximateForNoneCapturedEvents
: secrets.length,
environment,
workspaceId,
folderId,
@ -614,7 +616,6 @@ export const getSecretHelper = async ({
include_imports = true,
version
}: GetSecretParams) => {
const secretBlindIndex = await generateSecretBlindIndexHelper({
secretName,
workspaceId: new Types.ObjectId(workspaceId)
@ -644,7 +645,7 @@ export const getSecretHelper = async ({
type: type ?? SECRET_PERSONAL,
version
}).lean();
if (secretVersion) {
secret = await new Secret({
...secretVersion,
@ -673,7 +674,7 @@ export const getSecretHelper = async ({
type: SECRET_SHARED,
version
}).lean();
if (secretVersion) {
secret = await new Secret({
...secretVersion,
@ -682,10 +683,16 @@ export const getSecretHelper = async ({
}
}
}
if (!secret && include_imports) {
// if still no secret found search in imported secret and retreive
secret = await getAnImportedSecret(secretName, workspaceId.toString(), environment, folderId, version);
secret = await getAnImportedSecret(
secretName,
workspaceId.toString(),
environment,
folderId,
version
);
}
if (!secret) throw SecretNotFoundError();
@ -1180,11 +1187,12 @@ const recursivelyExpandSecret = async (
const secRefKey = entities[entities.length - 1];
const val = await fetchCrossEnv(secRefEnv, secRefPath, secRefKey);
interpolatedValue = interpolatedValue.replaceAll(interpolationSyntax, val);
if (val !== undefined) {
interpolatedValue = interpolatedValue.replaceAll(interpolationSyntax, val);
}
}
}
}
expandedSec[key] = interpolatedValue;
return interpolatedValue;
};

View File

@ -83,6 +83,7 @@ import { healthCheck } from "./routes/status";
import { RouteNotFoundError } from "./utils/errors";
import { requestErrorHandler } from "./middleware/requestErrorHandler";
import {
getIsMigrationMode,
getMongoURL,
getNodeEnv,
getPort,
@ -107,8 +108,8 @@ const main = async () => {
const port = await getPort();
// initializing the database connection + redis
await initRedis()
// initializing the database connection + redis
await initRedis();
await DatabaseService.initDatabase(await getMongoURL());
const serverCfg = await serverConfigInit();
await setup();
@ -198,6 +199,18 @@ const main = async () => {
handler = nextApp.getRequestHandler();
}
app.use((req, _res, next) => {
getIsMigrationMode()
.then((el) => {
if (el && req.method !== "GET") {
next(new Error("Migration mode"));
} else {
next();
}
})
.catch(next);
});
// (EE) routes
app.use("/api/v1/identities", v1IdentitiesRouter);
app.use("/api/v1/secret", eeSecretRouter);

View File

@ -76,10 +76,10 @@ export const initializeSamlStrategy = async () => {
if (!organization) return done(OrganizationNotFoundError());
const email = profile.email;
const email = profile?.email ?? profile?.emailAddress // emailRippling is added because in Rippling the field `email` reserved
const firstName = profile.firstName;
const lastName = profile.lastName;
let user = await User.findOne({
email
}).select("+publicKey");

View File

@ -498,7 +498,7 @@ var agentCmd = &cobra.Command{
agentConfigInBase64 := os.Getenv("INFISICAL_AGENT_CONFIG_BASE64")
if configPath != "" {
if agentConfigInBase64 == "" {
data, err := ioutil.ReadFile(configPath)
if err != nil {
if !FileExists(configPath) {
@ -506,7 +506,6 @@ var agentCmd = &cobra.Command{
return
}
}
agentConfigInBytes = data
}

View File

@ -74,7 +74,7 @@ var exportCmd = &cobra.Command{
util.HandleError(err, "Unable to parse flag")
}
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, WorkspaceId: projectId, SecretsPath: secretsPath})
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, WorkspaceId: projectId, SecretsPath: secretsPath}, "")
if err != nil {
util.HandleError(err, "Unable to fetch secrets")
}
@ -87,7 +87,7 @@ var exportCmd = &cobra.Command{
var output string
if shouldExpandSecrets {
substitutions := util.ExpandSecrets(secrets, infisicalToken)
substitutions := util.ExpandSecrets(secrets, infisicalToken, "")
output, err = formatEnvs(substitutions, format)
if err != nil {
util.HandleError(err)

View File

@ -67,6 +67,11 @@ var runCmd = &cobra.Command{
util.HandleError(err, "Unable to parse flag")
}
projectConfigDir, err := cmd.Flags().GetString("project-config-dir")
if err != nil {
util.HandleError(err, "Unable to parse flag")
}
secretOverriding, err := cmd.Flags().GetBool("secret-overriding")
if err != nil {
util.HandleError(err, "Unable to parse flag")
@ -92,7 +97,7 @@ var runCmd = &cobra.Command{
util.HandleError(err, "Unable to parse flag")
}
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports})
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports}, projectConfigDir)
if err != nil {
util.HandleError(err, "Could not fetch secrets", "If you are using a service token to fetch secrets, please ensure it is valid")
@ -105,7 +110,7 @@ var runCmd = &cobra.Command{
}
if shouldExpandSecrets {
secrets = util.ExpandSecrets(secrets, infisicalToken)
secrets = util.ExpandSecrets(secrets, infisicalToken, projectConfigDir)
}
secretsByKey := getSecretsByKeys(secrets)
@ -198,6 +203,7 @@ func init() {
runCmd.Flags().StringP("command", "c", "", "chained commands to execute (e.g. \"npm install && npm run dev; echo ...\")")
runCmd.Flags().StringP("tags", "t", "", "filter secrets by tag slugs ")
runCmd.Flags().String("path", "/", "get secrets within a folder path")
runCmd.Flags().String("project-config-dir", "", "explicitly set the directory where the .infisical.json resides")
}
// Will execute a single command and pass in the given secrets into the process

View File

@ -68,7 +68,7 @@ var secretsCmd = &cobra.Command{
util.HandleError(err, "Unable to parse flag")
}
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports})
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports}, "")
if err != nil {
util.HandleError(err)
}
@ -80,7 +80,7 @@ var secretsCmd = &cobra.Command{
}
if shouldExpandSecrets {
secrets = util.ExpandSecrets(secrets, infisicalToken)
secrets = util.ExpandSecrets(secrets, infisicalToken, "")
}
visualize.PrintAllSecretDetails(secrets)
@ -169,7 +169,7 @@ var secretsSetCmd = &cobra.Command{
plainTextEncryptionKey := crypto.DecryptAsymmetric(encryptedWorkspaceKey, encryptedWorkspaceKeyNonce, encryptedWorkspaceKeySenderPublicKey, currentUsersPrivateKey)
// pull current secrets
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, SecretsPath: secretsPath})
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, SecretsPath: secretsPath}, "")
if err != nil {
util.HandleError(err, "unable to retrieve secrets")
}
@ -406,7 +406,7 @@ func getSecretsByNames(cmd *cobra.Command, args []string) {
util.HandleError(err, "Unable to parse path flag")
}
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath})
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath}, "")
if err != nil {
util.HandleError(err, "To fetch all secrets")
}
@ -455,7 +455,7 @@ func generateExampleEnv(cmd *cobra.Command, args []string) {
util.HandleError(err, "Unable to parse flag")
}
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath})
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath}, "")
if err != nil {
util.HandleError(err, "To fetch all secrets")
}

View File

@ -113,6 +113,28 @@ func GetWorkSpaceFromFile() (models.WorkspaceConfigFile, error) {
return workspaceConfigFile, nil
}
func GetWorkSpaceFromFilePath(configFileDir string) (models.WorkspaceConfigFile, error) {
configFilePath := filepath.Join(configFileDir, ".infisical.json")
_, configFileStatusError := os.Stat(configFilePath)
if os.IsNotExist(configFileStatusError) {
return models.WorkspaceConfigFile{}, fmt.Errorf("file %s does not exist", configFilePath)
}
configFileAsBytes, err := os.ReadFile(configFilePath)
if err != nil {
return models.WorkspaceConfigFile{}, err
}
var workspaceConfigFile models.WorkspaceConfigFile
err = json.Unmarshal(configFileAsBytes, &workspaceConfigFile)
if err != nil {
return models.WorkspaceConfigFile{}, err
}
return workspaceConfigFile, nil
}
// FindWorkspaceConfigFile searches for a .infisical.json file in the current directory and all parent directories.
func FindWorkspaceConfigFile() (string, error) {
dir, err := os.Getwd()

View File

@ -105,6 +105,17 @@ func RequireLocalWorkspaceFile() {
}
}
func ValidateWorkspaceFile(projectConfigFilePath string) {
workspaceFilePath, err := GetWorkSpaceFromFilePath(projectConfigFilePath)
if err != nil {
PrintErrorMessageAndExit(fmt.Sprintf("error reading your project config %v", err))
}
if workspaceFilePath.WorkspaceId == "" {
PrintErrorMessageAndExit("Your project id is missing in your local config file. Please add it or run again [infisical init]")
}
}
func GetHashFromStringList(list []string) string {
hash := sha256.New()

View File

@ -220,7 +220,7 @@ func InjectImportedSecret(plainTextWorkspaceKey []byte, secrets []models.SingleE
return secrets, nil
}
func GetAllEnvironmentVariables(params models.GetAllSecretsParameters) ([]models.SingleEnvironmentVariable, error) {
func GetAllEnvironmentVariables(params models.GetAllSecretsParameters, projectConfigFilePath string) ([]models.SingleEnvironmentVariable, error) {
var infisicalToken string
if params.InfisicalToken == "" {
infisicalToken = os.Getenv(INFISICAL_TOKEN_NAME)
@ -236,7 +236,13 @@ func GetAllEnvironmentVariables(params models.GetAllSecretsParameters) ([]models
if infisicalToken == "" {
if isConnected {
log.Debug().Msg("GetAllEnvironmentVariables: Connected to internet, checking logged in creds")
RequireLocalWorkspaceFile()
if projectConfigFilePath == "" {
RequireLocalWorkspaceFile()
} else {
ValidateWorkspaceFile(projectConfigFilePath)
}
RequireLogin()
}
@ -251,13 +257,26 @@ func GetAllEnvironmentVariables(params models.GetAllSecretsParameters) ([]models
PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again")
}
workspaceFile, err := GetWorkSpaceFromFile()
if err != nil {
return nil, err
var infisicalDotJson models.WorkspaceConfigFile
if projectConfigFilePath == "" {
projectConfig, err := GetWorkSpaceFromFile()
if err != nil {
return nil, err
}
infisicalDotJson = projectConfig
} else {
projectConfig, err := GetWorkSpaceFromFilePath(projectConfigFilePath)
if err != nil {
return nil, err
}
infisicalDotJson = projectConfig
}
if params.WorkspaceId != "" {
workspaceFile.WorkspaceId = params.WorkspaceId
infisicalDotJson.WorkspaceId = params.WorkspaceId
}
// // Verify environment
@ -266,18 +285,18 @@ func GetAllEnvironmentVariables(params models.GetAllSecretsParameters) ([]models
// return nil, fmt.Errorf("unable to validate environment name because [err=%s]", err)
// }
secretsToReturn, errorToReturn = GetPlainTextSecretsViaJTW(loggedInUserDetails.UserCredentials.JTWToken, loggedInUserDetails.UserCredentials.PrivateKey, workspaceFile.WorkspaceId,
secretsToReturn, errorToReturn = GetPlainTextSecretsViaJTW(loggedInUserDetails.UserCredentials.JTWToken, loggedInUserDetails.UserCredentials.PrivateKey, infisicalDotJson.WorkspaceId,
params.Environment, params.TagSlugs, params.SecretsPath, params.IncludeImport)
log.Debug().Msgf("GetAllEnvironmentVariables: Trying to fetch secrets JTW token [err=%s]", errorToReturn)
backupSecretsEncryptionKey := []byte(loggedInUserDetails.UserCredentials.PrivateKey)[0:32]
if errorToReturn == nil {
WriteBackupSecrets(workspaceFile.WorkspaceId, params.Environment, backupSecretsEncryptionKey, secretsToReturn)
WriteBackupSecrets(infisicalDotJson.WorkspaceId, params.Environment, backupSecretsEncryptionKey, secretsToReturn)
}
// only attempt to serve cached secrets if no internet connection and if at least one secret cached
if !isConnected {
backedSecrets, err := ReadBackupSecrets(workspaceFile.WorkspaceId, params.Environment, backupSecretsEncryptionKey)
backedSecrets, err := ReadBackupSecrets(infisicalDotJson.WorkspaceId, params.Environment, backupSecretsEncryptionKey)
if len(backedSecrets) > 0 {
PrintWarning("Unable to fetch latest secret(s) due to connection error, serving secrets from last successful fetch. For more info, run with --debug")
secretsToReturn = backedSecrets
@ -421,7 +440,7 @@ func getSecretsByKeys(secrets []models.SingleEnvironmentVariable) map[string]mod
return secretMapByName
}
func ExpandSecrets(secrets []models.SingleEnvironmentVariable, infisicalToken string) []models.SingleEnvironmentVariable {
func ExpandSecrets(secrets []models.SingleEnvironmentVariable, infisicalToken string, projectConfigPathDir string) []models.SingleEnvironmentVariable {
expandedSecs := make(map[string]string)
interpolatedSecs := make(map[string]string)
// map[env.secret-path][keyname]Secret
@ -454,7 +473,7 @@ func ExpandSecrets(secrets []models.SingleEnvironmentVariable, infisicalToken st
if crossRefSec, ok := crossEnvRefSecs[uniqKey]; !ok {
// if not in cross reference cache, fetch it from server
refSecs, err := GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: env, InfisicalToken: infisicalToken, SecretsPath: secPath})
refSecs, err := GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: env, InfisicalToken: infisicalToken, SecretsPath: secPath}, projectConfigPathDir)
if err != nil {
HandleError(err, fmt.Sprintf("Could not fetch secrets in environment: %s secret-path: %s", env, secPath), "If you are using a service token to fetch secrets, please ensure it is valid")
}

View File

@ -4,6 +4,14 @@ title: "Changelog"
The changelog below reflects new product developments and updates on a monthly basis.
## January 2024
- Reduced size of Infisical Node.js SDK by ≈90%.
- Added secret fallback support to all SDK's.
- Added Machine Identity support to [Terraform Provider](https://github.com/Infisical/terraform-provider-infisical).
- Released [.NET SDK](https://infisical.com/docs/sdks/languages/csharp).
- Added symmetric encryption support to all SDK's.
- Fixed secret reminders bug, where reminders were not being updated correctly.
## December 2023
- Released [(machine) identities](https://infisical.com/docs/documentation/platform/identities/overview) and [universal auth](https://infisical.com/docs/documentation/platform/identities/universal-auth) features.

View File

@ -62,6 +62,16 @@ Inject secrets from Infisical into your application process.
</Accordion>
### Flags
<Accordion title="--project-config-dir">
Explicitly set the directory where the .infisical.json resides. This is useful for some monorepo setups.
```bash
# Example
infisical run --project-config-dir=/some-dir -- printenv
```
</Accordion>
<Accordion title="--command">
Pass secrets into multiple commands at once

View File

@ -16,5 +16,6 @@ Follow the instructions for your language use the SDK for it:
- [Node SDK](https://infisical.com/docs/sdks/languages/node)
- [Python SDK](https://infisical.com/docs/sdks/languages/python)
- [Java SDK](https://infisical.com/docs/sdks/languages/java)
- [.NET SDK](https://infisical.com/docs/sdks/languages/csharp)
Missing a language? [Throw in a request](https://github.com/Infisical/infisical/issues).

View File

@ -5,7 +5,7 @@ title: "Node"
This guide demonstrates how to use Infisical to manage secrets for your Node stack from local development to production. It uses:
- Infisical (you can use [Infisical Cloud](https://app.infisical.com) or a [self-hosted instance of Infisical](https://infisical.com/docs/self-hosting/overview)) to store your secrets.
- The [infisical-node](https://github.com/Infisical/infisical-node) client SDK to fetch secrets back to your Node application on demand.
- The [@infisical/sdk](https://github.com/Infisical/sdk/tree/main/languages/node) Node.js client SDK to fetch secrets back to your Node application on demand.
## Project Setup
@ -17,13 +17,11 @@ To begin, we need to set up a project in Infisical and add secrets to an environ
2. Add a secret to the development environment of this project so we can pull it back for local development. In the **Secrets Overview** page, press **Explore Development** and add a secret with the key `NAME` and value `YOUR_NAME`.
### Create an Infisical Token
### Create a Machine Identity
Now that we've created a project and added a secret to its development environment, we need to provision an Infisical Token that our Node application can use to access the secret.
Now that we've created a project and added a secret to its development environment, we need to configure an Infisical Machine Identity that our Node application can use to access the secret.
1. Head to the **Project Settings > Service Tokens** and press **Add New Token**.
2. Call the token anything like **My App Token** and select **Development** under **Environment**.
3. Copy the token and keep it handy.
- [How to setup machine identities](/documentation/platform/identities/overview)
## Create a Node app
@ -41,27 +39,43 @@ npm init -y
Install `express` and [infisical-node](https://github.com/Infisical/infisical-node), the client Node SDK for Infisical.
```console
npm install express infisical-node
npm install express @infisical/sdk
```
Finally, create an index.js file containing the application code.
```js
const express = require("express");
const express = require('express');
const { InfisicalClient, LogLevel } = require("@infisical/sdk");
const app = express();
const PORT = 3000;
const client = new InfisicalClient({
token: "YOUR_INFISICAL_TOKEN"
clientId: "YOUR_CLIENT_ID",
clientSecret: "YOUR_CLIENT_SECRET",
logLevel: LogLevel.Error
});
app.get("/", async (req, res) => {
const name = (await client.getSecret("NAME")).secretValue;
res.send(`Hello, ${name}!`);
// access value
const name = await client.getSecret({
environment: "dev",
projectId: "PROJECT_ID",
path: "/",
type: "shared",
secretName: "NAME"
});
res.send(`Hello! My name is: ${name.secretValue}`);
});
app.listen(PORT, () => {
console.log(`Example app listening on port ${PORT}`);
app.listen(PORT, async () => {
// initialize client
console.log(`App listening on port ${port}`);
});
```
@ -82,13 +96,6 @@ At this stage, you know how to fetch secrets from Infisical back to your Node ap
## FAQ
<AccordionGroup>
<Accordion title="Are my secrets exposed in transit every time the SDK fetches them?">
No. Infisical uses end-to-end encryption which ensures that secrets are always encrypted in transit
and decrypted on the client side. In fact, not even the server can decrypt your secrets (unless
that permission is explicitly granted from within the platform).
Check out the [security guide](/security/overview).
</Accordion>
<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
@ -98,10 +105,6 @@ At this stage, you know how to fetch secrets from Infisical back to your Node ap
The SDK caches every secret and falls back to the cached value if a request fails. If no cached
value ever-existed, the SDK falls back to whatever value is on `process.env`.
</Accordion>
<Accordion title="Can I still use process.env with the SDK?">
Yes. If no `token` parameter is passed in at the time of initializing the client or nothing is found when requesting for a secret,
then the SDK falls back to whatever value is on `process.env`.
</Accordion>
<Accordion title="What's the point if I still have to manage a token for the SDK?">
The token enables the SDK to authenticate with Infisical to fetch back your secrets.
Although the SDK requires you to pass in a token, it enables greater efficiency and security
@ -118,4 +121,4 @@ At this stage, you know how to fetch secrets from Infisical back to your Node ap
See also:
- Explore the [Node SDK](https://github.com/Infisical/infisical-node)
- Explore the [Node SDK](https://github.com/Infisical/sdk/tree/main/languages/node)

View File

@ -5,7 +5,7 @@ title: "Python"
This guide demonstrates how to use Infisical to manage secrets for your Python stack from local development to production. It uses:
- Infisical (you can use [Infisical Cloud](https://app.infisical.com) or a [self-hosted instance of Infisical](https://infisical.com/docs/self-hosting/overview)) to store your secrets.
- The [infisical-python](https://github.com/Infisical/infisical-python) client SDK to fetch secrets back to your Python application on demand.
- The [infisical-python](https://github.com/Infisical/sdk/tree/main/crates/infisical-py) Python client SDK to fetch secrets back to your Python application on demand.
## Project Setup
@ -17,13 +17,11 @@ To begin, we need to set up a project in Infisical and add secrets to an environ
2. Add a secret to the development environment of this project so we can pull it back for local development. In the **Secrets Overview** page, press **Explore Development** and add a secret with the key `NAME` and value `YOUR_NAME`.
### Create an Infisical Token
### Create a Machine Identity
Now that we've created a project and added a secret to its development environment, we need to provision an Infisical Token that our Node application can use to access the secret.
Now that we've created a project and added a secret to its development environment, we need to configure an Infisical Machine Identity that our Python application can use to access the secret.
1. Head to the **Project Settings > Service Tokens** and press **Add New Token**.
2. Call the token anything like **My App Token** and select **Development** under **Environment**.
3. Copy the token and keep it handy.
- [How to setup machine identities](/documentation/platform/identities/overview)
## Create a Python app
@ -38,27 +36,36 @@ python3 -m venv env
source env/bin/activate
```
Install Flask and [infisical-python](https://github.com/Infisical/infisical-python), the client Python SDK for Infisical.
Install Flask and [infisical-python](https://github.com/Infisical/sdk/tree/main/crates/infisical-py), the client Python SDK for Infisical.
```console
pip install Flask infisical
pip install Flask infisical-python
```
Finally, create an `app.py` file containing the application code.
```python
```py
from flask import Flask
from infisical import InfisicalClient
from infisical_client import ClientSettings, InfisicalClient, GetSecretOptions
app = Flask(__name__)
client = InfisicalClient(token="your_infisical_token")
client = InfisicalClient(ClientSettings(
client_id="MACHINE_IDENTITY_CLIENT_ID",
client_secret="MACHINE_IDENTITY_CLIENT_SECRET",
))
@app.route("/")
def hello_world():
# access value
name = client.get_secret("NAME")
return f"Hello, {name.secret_value}!"
name = client.getSecret(options=GetSecretOptions(
environment="dev",
project_id="PROJECT_ID",
secret_name="NAME"
))
return f"Hello! My name is: {name.secret_value}"
```
Here, we initialized a `client` instance of the Infisical Python SDK with the Infisical Token
@ -78,13 +85,6 @@ At this stage, you know how to fetch secrets from Infisical back to your Python
## FAQ
<AccordionGroup>
<Accordion title="Are my secrets exposed in transit every time the SDK fetches them?">
No. Infisical uses end-to-end encryption which ensures that secrets are always encrypted in transit
and decrypted on the client side. In fact, not even the server can decrypt your secrets (unless
that permission is explicitly granted from within the platform).
Check out the [security guide](/security/overview).
</Accordion>
<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
@ -94,10 +94,6 @@ At this stage, you know how to fetch secrets from Infisical back to your Python
The SDK caches every secret and falls back to the cached value if a request fails. If no cached
value ever-existed, the SDK falls back to whatever value is on `process.env`.
</Accordion>
<Accordion title="Can I still use process.env with the SDK?">
Yes. If no `token` parameter is passed in at the time of initializing the client or nothing is found when requesting for a secret,
then the SDK falls back to whatever value is on `process.env`.
</Accordion>
<Accordion title="What's the point if I still have to manage a token for the SDK?">
The token enables the SDK to authenticate with Infisical to fetch back your secrets.
Although the SDK requires you to pass in a token, it enables greater efficiency and security
@ -114,6 +110,6 @@ At this stage, you know how to fetch secrets from Infisical back to your Python
See also:
- Explore the [Python SDK](https://github.com/Infisical/infisical-python)
- Explore the [Python SDK](https://github.com/Infisical/sdk/tree/main/crates/infisical-py)

View File

@ -89,6 +89,10 @@ Then:
- If user A fetches the secret D back, they get the value F.
- If users B and C fetch the secret D back, they both get the value E.
<Info>
Please keep in mind that secret reminders won't work with personal overrides.
</Info>
![project override secret](../../images/platform/project/project-secrets-override.png)
### Drawer

View File

@ -7,9 +7,8 @@ description: "Log in to Infisical via SSO protocols"
Infisical offers Google SSO and GitHub SSO for free across both Infisical Cloud and Infisical Self-hosted.
Infisical also offers SAML SSO authentication but as paid features that can be unlocked on Infisical Cloud's **Pro** tier
or via enterprise license on self-hosted instances of Infisical. On this front, we currently support Okta, Azure AD, and JumpCloud and
are expanding support for other IdPs in the coming months; stay tuned and feel free to request a IdP at this
[issue](https://github.com/Infisical/infisical/issues/442).
or via enterprise license on self-hosted instances of Infisical. On this front, we support industry-leading providers including
Okta, Azure AD, and JumpCloud; with any questions, please reach out to [sales@infisical.com](mailto:sales@infisical.com).
</Warning>
You can configure your organization in Infisical to have members authenticate with the platform via protocols like [SAML 2.0](https://en.wikipedia.org/wiki/SAML_2.0).
@ -22,4 +21,4 @@ your IdP cannot and will not have access to the decryption key needed to decrypt
- [GitLab SSO](/documentation/platform/sso/gitlab)
- [Okta SAML](/documentation/platform/sso/okta)
- [Azure SAML](/documentation/platform/sso/azure)
- [JumpCloud SAML](/documentation/platform/sso/jumpcloud)
- [JumpCloud SAML](/documentation/platform/sso/jumpcloud)

View File

@ -0,0 +1,394 @@
---
title: "Infisical .NET SDK"
icon: "C#"
---
If you're working with C#, the official [Infisical C# SDK](https://github.com/Infisical/sdk/tree/main/languages/csharp) package is the easiest way to fetch and work with secrets for your application.
- [Nuget Package](https://www.nuget.org/packages/Infisical.Sdk)
- [Github Repository](https://github.com/Infisical/sdk/tree/main/languages/csharp)
## Basic Usage
```cs
using Infisical.Sdk;
namespace Example
{
class Program
{
static void Main(string[] args)
{
var settings = new ClientSettings
{
ClientId = "CLIENT_ID",
ClientSecret = "CLIENT_SECRET",
// SiteUrl = "http://localhost:8080", <-- This line can be omitted if you're using Infisical Cloud.
};
var infisical = new InfisicalClient(settings);
var options = new GetSecretOptions
{
SecretName = "TEST",
ProjectId = "PROJECT_ID",
Environment = "dev",
};
var secret = infisical.GetSecret(options);
Console.WriteLine($"The value of secret '{secret.SecretKey}', is: {secret.SecretValue}");
}
}
}
```
This example demonstrates how to use the Infisical C# SDK in a C# application. The application retrieves a secret named `TEST` from the `dev` environment of the `PROJECT_ID` project.
<Warning>
We do not recommend hardcoding your [Machine Identity Tokens](/platform/identities/overview). Setting it as an environment variable would be best.
</Warning>
# Installation
Run `npm` to add `@infisical/sdk` to your project.
```console
$ dotnet add package Infisical.Sdk
```
# Configuration
Import the SDK and create a client instance with your [Machine Identity](/platform/identities/universal-auth).
```cs
using Infisical.Sdk;
namespace Example
{
class Program
{
static void Main(string[] args)
{
var settings = new ClientSettings
{
ClientId = "CLIENT_ID",
ClientSecret = "CLIENT_SECRET",
};
var infisical = new InfisicalClient(settings); // <-- Your SDK instance!
}
}
}
```
### ClientSettings methods
<ParamField query="options" type="object">
<Expandable title="properties">
<ParamField query="ClientId" type="string" optional>
Your machine identity client ID.
</ParamField>
<ParamField query="ClientSecret" type="string" optional>
Your machine identity client secret.
</ParamField>
<ParamField query="AccessToken" type="string" optional>
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>
</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)
```cs
var options = new ListSecretsOptions
{
ProjectId = "PROJECT_ID",
Environment = "dev",
Path = "/foo/bar",
AttachToProcessEnv = false,
};
var secrets = infisical.ListSecrets(options);
```
Retrieve all secrets within the Infisical project and environment that client is connected to
#### Parameters
<ParamField query="Parameters" type="object">
<Expandable title="properties">
<ParamField query="Environment" type="string" required>
The slug name (dev, prod, etc) of the environment from where secrets should be fetched from.
</ParamField>
<ParamField query="ProjectId" type="string">
The project ID where the secret lives in.
</ParamField>
<ParamField query="Path" type="string" optional>
The path from where secrets should be fetched from.
</ParamField>
<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 `System.getenv("SECRET_NAME")`.
</ParamField>
<ParamField query="IncludeImports" 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>
</ParamField>
### client.GetSecret(options)
```cs
var options = new GetSecretOptions
{
SecretName = "AAAA",
ProjectId = "659c781eb2d4fe3e307b77bd",
Environment = "dev",
};
var secret = infisical.GetSecret(options);
```
Retrieve a secret from Infisical.
By default, `GetSecret()` fetches and returns a shared secret.
#### Parameters
<ParamField query="Parameters" type="object" optional>
<Expandable title="properties">
<ParamField query="SecretName" type="string" required>
The key of the secret to retrieve.
</ParamField>
<ParamField query="ProjectId" type="string" required>
The project ID where the secret lives in.
</ParamField>
<ParamField query="Environment" type="string" required>
The slug name (dev, prod, etc) of the environment from where secrets should be fetched from.
</ParamField>
<ParamField query="Path" type="string" optional>
The path from where secret should be fetched from.
</ParamField>
<ParamField query="Type" type="string" optional>
The type of the secret. Valid options are "shared" or "personal". If not specified, the default value is "shared".
</ParamField>
</Expandable>
</ParamField>
### client.CreateSecret(options)
```cs
var options = new CreateSecretOptions {
Environment = "dev",
ProjectId = "PROJECT_ID",
SecretName = "NEW_SECRET",
SecretValue = "NEW_SECRET_VALUE",
SecretComment = "This is a new secret",
};
var newSecret = infisical.CreateSecret(options);
```
Create a new secret in Infisical.
#### Parameters
<ParamField query="Parameters" type="object" optional>
<Expandable title="properties">
<ParamField query="SecretName" type="string" required>
The key of the secret to create.
</ParamField>
<ParamField query="SecretValue" type="string" required>
The value of the secret.
</ParamField>
<ParamField query="ProjectId" type="string" required>
The project ID where the secret lives in.
</ParamField>
<ParamField query="Environment" type="string" required>
The slug name (dev, prod, etc) of the environment from where secrets should be fetched from.
</ParamField>
<ParamField query="Path" type="string" optional>
The path from where secret should be created.
</ParamField>
<ParamField query="Type" type="string" optional>
The type of the secret. Valid options are "shared" or "personal". If not specified, the default value is "shared".
</ParamField>
</Expandable>
</ParamField>
### client.UpdateSecret(options)
```cs
var options = new UpdateSecretOptions {
Environment = "dev",
ProjectId = "PROJECT_ID",
SecretName = "SECRET_TO_UPDATE",
SecretValue = "NEW VALUE"
};
var updatedSecret = infisical.UpdateSecret(options);
```
Update an existing secret in Infisical.
#### Parameters
<ParamField query="Parameters" type="object" optional>
<Expandable title="properties">
<ParamField query="SecretName" type="string" required>
The key of the secret to update.
</ParamField>
<ParamField query="SecretValue" type="string" required>
The new value of the secret.
</ParamField>
<ParamField query="ProjectId" type="string" required>
The project ID where the secret lives in.
</ParamField>
<ParamField query="Environment" type="string" required>
The slug name (dev, prod, etc) of the environment from where secrets should be fetched from.
</ParamField>
<ParamField query="Path" type="string" optional>
The path from where secret should be updated.
</ParamField>
<ParamField query="Type" type="string" optional>
The type of the secret. Valid options are "shared" or "personal". If not specified, the default value is "shared".
</ParamField>
</Expandable>
</ParamField>
### client.DeleteSecret(options)
```cs
var options = new DeleteSecretOptions
{
Environment = "dev",
ProjectId = "PROJECT_ID",
SecretName = "NEW_SECRET",
};
var deletedSecret = infisical.DeleteSecret(options);
```
Delete a secret in Infisical.
#### Parameters
<ParamField query="Parameters" type="object" optional>
<Expandable title="properties">
<ParamField query="SecretName" type="string">
The key of the secret to update.
</ParamField>
<ParamField query="ProjectId" type="string" required>
The project ID where the secret lives in.
</ParamField>
<ParamField query="Environment" type="string" required>
The slug name (dev, prod, etc) of the environment from where secrets should be fetched from.
</ParamField>
<ParamField query="Path" type="string" optional>
The path from where secret should be deleted.
</ParamField>
<ParamField query="Type" type="string" optional>
The type of the secret. Valid options are "shared" or "personal". If not specified, the default value is "shared".
</ParamField>
</Expandable>
</ParamField>
## Cryptography
### Create a symmetric key
Create a base64-encoded, 256-bit symmetric key to be used for encryption/decryption.
```cs
var key = infisical.CreateSymmetricKey();
```
#### Returns (string)
`key` (string): A base64-encoded, 256-bit symmetric key, that can be used for encryption/decryption purposes.
### Encrypt symmetric
```cs
var options = new EncryptSymmetricOptions
{
Plaintext = "Infisical is awesome!",
Key = key,
};
var encryptedData = infisical.EncryptSymmetric(options);
```
#### Parameters
<ParamField query="Parameters" type="object" required>
<Expandable title="properties">
<ParamField query="Plaintext" type="string">
The plaintext you want to encrypt.
</ParamField>
<ParamField query="Key" type="string" required>
The symmetric key to use for encryption.
</ParamField>
</Expandable>
</ParamField>
#### Returns (object)
`Tag` (string): A base64-encoded, 128-bit authentication tag.
`Iv` (string): A base64-encoded, 96-bit initialization vector.
`CipherText` (string): A base64-encoded, encrypted ciphertext.
### Decrypt symmetric
```cs
var decryptOptions = new DecryptSymmetricOptions
{
Key = key,
Ciphertext = encryptedData.Ciphertext,
Iv = encryptedData.Iv,
Tag = encryptedData.Tag,
};
var decryptedPlaintext = infisical.DecryptSymmetric(decryptOptions);
```
#### Parameters
<ParamField query="Parameters" type="object" required>
<Expandable title="properties">
<ParamField query="Ciphertext" type="string">
The ciphertext you want to decrypt.
</ParamField>
<ParamField query="Key" type="string" required>
The symmetric key to use for encryption.
</ParamField>
<ParamField query="Iv" type="string" required>
The initialization vector to use for decryption.
</ParamField>
<ParamField query="Tag" type="string" required>
The authentication tag to use for decryption.
</ParamField>
</Expandable>
</ParamField>
#### Returns (string)
`Plaintext` (string): The decrypted plaintext.

View File

@ -1,8 +0,0 @@
---
title: "Go"
icon: "golang"
---
Coming soon.
Star our GitHub repository to stay updated [cross-language SDK](https://github.com/Infisical/sdk) GitHub repository to stay updated.

View File

@ -1,10 +1,13 @@
---
title: "Java"
title: "Infisical Java SDK"
icon: "java"
---
If you're working with Java, the official [Infisical Java SDK](https://github.com/Infisical/sdk/tree/main/languages/java) package is the easiest way to fetch and work with secrets for your application.
- [Maven Package](https://github.com/Infisical/sdk/packages/2019741)
- [Github Repository](https://github.com/Infisical/sdk/tree/main/languages/java)
## Basic Usage
```java
@ -121,7 +124,7 @@ SecretElement[] secrets = client.listSecrets(options);
Retrieve all secrets within the Infisical project and environment that client is connected to
### Methods
#### Methods
<ParamField query="Parameters" type="object">
<Expandable title="properties">
@ -165,7 +168,7 @@ Retrieve a secret from Infisical.
By default, `getSecret()` fetches and returns a shared secret.
### Methods
#### Methods
<ParamField query="Parameters" type="object" optional>
<Expandable title="properties">
@ -203,7 +206,7 @@ CreateSecretResponseSecret newSecret = client.createSecret(createOptions);
Create a new secret in Infisical.
### Methods
#### Methods
<ParamField query="Parameters" type="object" optional>
<Expandable title="properties">
@ -245,7 +248,7 @@ UpdateSecretResponseSecret updatedSecret = client.updateSecret(options);
Update an existing secret in Infisical.
### Methods
#### Methods
<ParamField query="Parameters" type="object" optional>
<Expandable title="properties">
@ -286,7 +289,7 @@ DeleteSecretResponseSecret deletedSecret = client.deleteSecret(options);
Delete a secret in Infisical.
### Methods
#### Methods
<ParamField query="Parameters" type="object" optional>
<Expandable title="properties">
@ -307,3 +310,76 @@ Delete a secret in Infisical.
</ParamField>
</Expandable>
</ParamField>
## Cryptography
### Create a symmetric key
Create a base64-encoded, 256-bit symmetric key to be used for encryption/decryption.
```java
String key = client.createSymmetricKey();
```
#### Returns (string)
`key` (string): A base64-encoded, 256-bit symmetric key, that can be used for encryption/decryption purposes.
### Encrypt symmetric
```java
EncryptSymmetricOptions options = new EncryptSymmetricOptions();
options.setKey(key);
options.setPlaintext("Infisical is awesome!");
EncryptSymmetricResponse encryptedData = client.encryptSymmetric(options);
```
#### Methods
<ParamField query="Parameters" type="object" required>
<Expandable title="properties">
<ParamField query="setPlaintext()" type="string">
The plaintext you want to encrypt.
</ParamField>
<ParamField query="setKey()" type="string" required>
The symmetric key to use for encryption.
</ParamField>
</Expandable>
</ParamField>
#### Returns (object)
`tag (getTag())` (string): A base64-encoded, 128-bit authentication tag.
`iv (getIv())` (string): A base64-encoded, 96-bit initialization vector.
`ciphertext (getCipherText())` (string): A base64-encoded, encrypted ciphertext.
### Decrypt symmetric
```java
DecryptSymmetricOptions decryptOptions = new DecryptSymmetricOptions();
decryptOptions.setKey(key);
decryptOptions.setCiphertext(encryptedData.getCiphertext());
decryptOptions.setIv(encryptedData.getIv());
decryptOptions.setTag(encryptedData.getTag());
String decryptedString = client.decryptSymmetric(decryptOptions);
```
#### Methods
<ParamField query="Parameters" type="object" required>
<Expandable title="properties">
<ParamField query="setCiphertext()" type="string">
The ciphertext you want to decrypt.
</ParamField>
<ParamField query="setKey()" type="string" required>
The symmetric key to use for encryption.
</ParamField>
<ParamField query="setIv()" type="string" required>
The initialization vector to use for decryption.
</ParamField>
<ParamField query="setTag()" type="string" required>
The authentication tag to use for decryption.
</ParamField>
</Expandable>
</ParamField>
#### Returns (string)
`Plaintext` (string): The decrypted plaintext.

View File

@ -1,10 +1,13 @@
---
title: "Node"
title: "Infisical Node.js SDK"
icon: "node"
---
If you're working with Node.js, the official [infisical-node](https://github.com/Infisical/sdk/tree/main/languages/node) package is the easiest way to fetch and work with secrets for your application.
- [NPM Package](https://www.npmjs.com/package/@infisical/sdk)
- [Github Repository](https://github.com/Infisical/sdk/tree/main/languages/node)
## Basic Usage
```js
@ -84,12 +87,12 @@ Import the SDK and create a client instance with your [Machine Identity](/docume
clientSecret: "YOUR_CLIENT_SECRET",
logLevel: LogLevel.Error
});
````
```
</Tab>
</Tabs>
### Parameters
#### Parameters
<ParamField query="options" type="object">
<Expandable title="properties">
@ -138,7 +141,7 @@ const secrets = await client.listSecrets({
Retrieve all secrets within the Infisical project and environment that client is connected to
### Parameters
#### Parameters
<ParamField query="Parameters" type="object">
<Expandable title="properties">
@ -180,7 +183,7 @@ Retrieve a secret from Infisical.
By default, `getSecret()` fetches and returns a shared secret.
### Parameters
#### Parameters
<ParamField query="Parameters" type="object" optional>
<Expandable title="properties">
@ -255,7 +258,7 @@ const updatedApiKey = await client.updateSecret({
Update an existing secret in Infisical.
### Parameters
#### Parameters
<ParamField query="Parameters" type="object" optional>
<Expandable title="properties">
@ -315,3 +318,73 @@ Delete a secret in Infisical.
</ParamField>
</Expandable>
</ParamField>
## Cryptography
### Create a symmetric key
Create a base64-encoded, 256-bit symmetric key to be used for encryption/decryption.
```js
const key = client.createSymmetricKey();
```
#### Returns (string)
`key` (string): A base64-encoded, 256-bit symmetric key, that can be used for encryption/decryption purposes.
### Encrypt symmetric
```js
const { iv, tag, ciphertext } = await client.encryptSymmetric({
key: key,
plaintext: "Infisical is awesome!",
})
```
#### Parameters
<ParamField query="Parameters" type="object" required>
<Expandable title="properties">
<ParamField query="plaintext" type="string">
The plaintext you want to encrypt.
</ParamField>
<ParamField query="key" type="string" required>
The symmetric key to use for encryption.
</ParamField>
</Expandable>
</ParamField>
#### Returns (object)
`tag` (string): A base64-encoded, 128-bit authentication tag.
`iv` (string): A base64-encoded, 96-bit initialization vector.
`ciphertext` (string): A base64-encoded, encrypted ciphertext.
### Decrypt symmetric
```js
const decryptedString = await client.decryptSymmetric({
key: key,
iv: iv,
tag: tag,
ciphertext: ciphertext,
});
```
#### Parameters
<ParamField query="Parameters" type="object" required>
<Expandable title="properties">
<ParamField query="ciphertext" type="string">
The ciphertext you want to decrypt.
</ParamField>
<ParamField query="key" type="string" required>
The symmetric key to use for encryption.
</ParamField>
<ParamField query="iv" type="string" required>
The initialization vector to use for decryption.
</ParamField>
<ParamField query="tag" type="string" required>
The authentication tag to use for decryption.
</ParamField>
</Expandable>
</ParamField>
#### Returns (string)
`plaintext` (string): The decrypted plaintext.

View File

@ -1,8 +0,0 @@
---
title: "PHP"
icon: "php"
---
Coming soon.
Star our GitHub repository to stay updated [cross-language SDK](https://github.com/Infisical/sdk) GitHub repository to stay updated.

View File

@ -1,10 +1,13 @@
---
title: "Python"
title: "Infisical Python SDK"
icon: "python"
---
If you're working with Python, the official [infisical-python](https://github.com/Infisical/sdk/edit/main/crates/infisical-py) package is the easiest way to fetch and work with secrets for your application.
- [PyPi Package](https://pypi.org/project/infisical-python/)
- [Github Repository](https://github.com/Infisical/sdk/edit/main/crates/infisical-py)
## Basic Usage
```py
@ -60,7 +63,7 @@ client = InfisicalClient(ClientSettings(
))
```
### Parameters
#### Parameters
<ParamField query="options" type="object">
<Expandable title="properties">
@ -110,7 +113,7 @@ client.listSecrets(options=ListSecretsOptions(
Retrieve all secrets within the Infisical project and environment that client is connected to
### Parameters
#### Parameters
<ParamField query="Parameters" type="object">
<Expandable title="properties">
@ -149,7 +152,7 @@ value = secret.secret_value # get its value
By default, `getSecret()` fetches and returns a shared secret. If not found, it returns a personal secret.
### Parameters
#### Parameters
<ParamField query="Parameters" type="object" optional>
<Expandable title="properties">
@ -187,7 +190,7 @@ api_key = client.createSecret(options=CreateSecretOptions(
Create a new secret in Infisical.
### Parameters
#### Parameters
<ParamField query="Parameters" type="object" optional>
<Expandable title="properties">
@ -225,7 +228,7 @@ client.updateSecret(options=UpdateSecretOptions(
Update an existing secret in Infisical.
### Parameters
#### Parameters
<ParamField query="Parameters" type="object" optional>
<Expandable title="properties">
@ -262,7 +265,7 @@ client.deleteSecret(options=DeleteSecretOptions(
Delete a secret in Infisical.
### Parameters
#### Parameters
<ParamField query="Parameters" type="object" optional>
<Expandable title="properties">
@ -283,3 +286,79 @@ Delete a secret in Infisical.
</ParamField>
</Expandable>
</ParamField>
## Cryptography
### Create a symmetric key
Create a base64-encoded, 256-bit symmetric key to be used for encryption/decryption.
```py
key = client.createSymmetricKey()
```
#### Returns (string)
`key` (string): A base64-encoded, 256-bit symmetric key, that can be used for encryption/decryption purposes.
### Encrypt symmetric
```py
encryptOptions = EncryptSymmetricOptions(
key=key,
plaintext="Infisical is awesome!"
)
encryptedData = client.encryptSymmetric(encryptOptions)
```
#### Parameters
<ParamField query="Parameters" type="object" required>
<Expandable title="properties">
<ParamField query="plaintext" type="string">
The plaintext you want to encrypt.
</ParamField>
<ParamField query="key" type="string" required>
The symmetric key to use for encryption.
</ParamField>
</Expandable>
</ParamField>
#### Returns (object)
`tag` (string): A base64-encoded, 128-bit authentication tag.
`iv` (string): A base64-encoded, 96-bit initialization vector.
`ciphertext` (string): A base64-encoded, encrypted ciphertext.
### Decrypt symmetric
```py
decryptOptions = DecryptSymmetricOptions(
ciphertext=encryptedData.ciphertext,
iv=encryptedData.iv,
tag=encryptedData.tag,
key=key
)
decryptedString = client.decryptSymmetric(decryptOptions)
```
#### Parameters
<ParamField query="Parameters" type="object" required>
<Expandable title="properties">
<ParamField query="ciphertext" type="string">
The ciphertext you want to decrypt.
</ParamField>
<ParamField query="key" type="string" required>
The symmetric key to use for encryption.
</ParamField>
<ParamField query="iv" type="string" required>
The initialization vector to use for decryption.
</ParamField>
<ParamField query="tag" type="string" required>
The authentication tag to use for decryption.
</ParamField>
</Expandable>
</ParamField>
#### Returns (string)
`plaintext` (string): The decrypted plaintext.

View File

@ -1,8 +0,0 @@
---
title: "Ruby"
icon: "gem"
---
Coming soon.
Star our GitHub repository to stay updated [cross-language SDK](https://github.com/Infisical/sdk) GitHub repository to stay updated.

View File

@ -1,8 +0,0 @@
---
title: "Rust"
icon: "rust"
---
Coming soon.
Star our GitHub repository to stay updated [cross-language SDK](https://github.com/Infisical/sdk) GitHub repository to stay updated.

View File

@ -18,17 +18,8 @@ From local development to production, Infisical SDKs provide the easiest way for
<Card href="/sdks/languages/java" title="Java" icon="java" color="#e41f23">
Manage secrets for your Java application on demand
</Card>
<Card href="/sdks/languages/ruby" title="Ruby" icon="gem" color="#ac0d01">
Manage secrets for your Ruby application on demand
</Card>
<Card href="/sdks/languages/go" title="Golang" icon="golang" color="#00add8">
Manage secrets for your Go application on demand
</Card>
<Card href="/sdks/languages/rust" title="Rust" icon="rust" color="#cd412b">
Manage secrets for your Rust application on demand
</Card>
<Card href="/sdks/languages/php" title="PHP" icon="php" color="#787cb4">
Manage secrets for your PHP application on demand
<Card href="/sdks/languages/csharp" title="C#" icon="bars" color="#368833">
Manage secrets for your C#/.NET application on demand
</Card>
</CardGroup>
@ -41,6 +32,10 @@ From local development to production, Infisical SDKs provide the easiest way for
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 ever-existed, the SDK falls back to whatever value is on the process environment.
</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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 708 KiB

View File

@ -58,7 +58,10 @@ const Alert = forwardRef<
{typeof icon !== "undefined" ? (
<>{icon} </>
) : (
<FontAwesomeIcon className="text-lg" icon={variantIconMap[variant ?? "default"]} />
<FontAwesomeIcon
className="text-lg text-primary"
icon={variantIconMap[variant ?? "default"]}
/>
)}
</div>
<div className="flex flex-col gap-y-1">

View File

@ -1,4 +1,5 @@
import { createContext, ReactNode, useContext, useEffect, useMemo } from "react";
import Head from "next/head";
import { useRouter } from "next/router";
import { ContentLoader } from "@app/components/v2/ContentLoader";
@ -27,11 +28,37 @@ export const ServerConfigProvider = ({ children }: Props): JSX.Element => {
}, [data]);
useEffect(() => {
if (!isLoading && data && !data.initialized) {
if (!isLoading && data && !data.initialized && !data.isMigrationModeOn) {
router.push("/admin/signup");
}
}, [isLoading, data]);
if (!isLoading && data?.isMigrationModeOn) {
return (
<div className="relative mx-auto flex h-screen w-full flex-col items-center justify-center space-y-8 bg-bunker-800 px-8 text-mineshaft-50 dark:[color-scheme:dark]">
<Head>
<title>Infisical Maintenance Mode</title>
<link rel='icon' href='/infisical.ico' />
</Head>
<img src="/images/maintenance.png" height={175} width={300} alt="maintenance mode" className="w-[40rem]"/>
<p className="mx-8 mb-4 flex justify-center bg-gradient-to-tr from-mineshaft-300 to-white bg-clip-text text-4xl font-bold text-transparent md:mx-16">
Scheduled Maintenance
</p>
<div className="mt-2 text-center text-lg text-bunker-300">
Infisical is undergoing planned maintenance. <br /> No action is required on your end your applications will continue to fetch secrets.
<br /> If you have questions, please <a
className="text-bunker-300 underline underline-offset-4 decoration-primary-800 hover:decoration-primary-600 hover:text-mineshaft-100 duration-200"
href="https://infisical.com/slack"
target="_blank"
rel="noopener noreferrer"
>
join our Slack community
</a>.
</div>
</div>
);
}
if (isLoading || (!data?.initialized && router.pathname !== "/admin/signup")) {
return (
<div className="bg-bunker-800">

View File

@ -1,6 +1,7 @@
export type TServerConfig = {
initialized: boolean;
allowSignUp: boolean;
isMigrationModeOn?: boolean;
};
export type TCreateAdminUserDTO = {

View File

@ -23,7 +23,9 @@ import {
faNetworkWired,
faPlug,
faPlus,
faUserPlus
faUserPlus,
faWarning,
faXmark
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { yupResolver } from "@hookform/resolvers/yup";
@ -56,6 +58,7 @@ import {
fetchOrgUsers,
useAddUserToWs,
useCreateWorkspace,
useGetUserAction,
useRegisterUserAction,
useUploadWsKey
} from "@app/hooks/api";
@ -70,13 +73,12 @@ const features = [
link: "https://infisical.com/docs/documentation/getting-started/kubernetes",
description:
"Pull secrets into your Kubernetes containers and automatically redeploy upon secret changes."
},
},
{
_id: 1,
name: "Infisical Agent",
link: "https://infisical.com/docs/infisical-agent/overview",
description:
"Inject secrets into your apps without modifying any application logic."
description: "Inject secrets into your apps without modifying any application logic."
}
];
@ -122,13 +124,13 @@ const CodeItem = ({
}) => {
return (
<>
<p className="mb-2 mt-4 text-bunker-300 text-sm leading-normal">{textExplanation}</p>
<div className="font-mono text-sm px-3 py-2 bg-bunker rounded-md border border-mineshaft-600 flex flex-row items-center justify-between">
<p className="mb-2 mt-4 text-sm leading-normal text-bunker-300">{textExplanation}</p>
<div className="flex flex-row items-center justify-between rounded-md border border-mineshaft-600 bg-bunker px-3 py-2 font-mono text-sm">
<input disabled value={code} id={id} className="w-full bg-transparent text-bunker-200" />
<button
type="button"
onClick={() => copyToClipboard(id, setIsCopied)}
className="h-full pl-3.5 pr-2 text-bunker-300 hover:text-primary-200 duration-200"
className="h-full pl-3.5 pr-2 text-bunker-300 duration-200 hover:text-primary-200"
>
{isCopied ? (
<FontAwesomeIcon icon={faCheck} className="pr-0.5" />
@ -150,21 +152,21 @@ const TabsObject = () => {
return (
<Tabs.Root
className="flex flex-col w-full cursor-default border border-mineshaft-600 rounded-md"
className="flex w-full cursor-default flex-col rounded-md border border-mineshaft-600"
defaultValue="tab1"
>
<Tabs.List
className="shrink-0 flex border-b border-mineshaft-600"
className="flex shrink-0 border-b border-mineshaft-600"
aria-label="Manage your account"
>
<Tabs.Trigger
className="bg-bunker-700 px-5 h-10 flex-1 flex items-center justify-center text-sm leading-none text-bunker-300 select-none first:rounded-tl-md last:rounded-tr-md data-[state=active]:text-primary data-[state=active]:font-medium data-[state=active]:focus:relative data-[state=active]:border-b data-[state=active]:border-primary outline-none cursor-default"
className="flex h-10 flex-1 cursor-default select-none items-center justify-center bg-bunker-700 px-5 text-sm leading-none text-bunker-300 outline-none first:rounded-tl-md last:rounded-tr-md data-[state=active]:border-b data-[state=active]:border-primary data-[state=active]:font-medium data-[state=active]:text-primary data-[state=active]:focus:relative"
value="tab1"
>
MacOS
</Tabs.Trigger>
<Tabs.Trigger
className="bg-bunker-700 px-5 h-10 flex-1 flex items-center justify-center text-sm leading-none text-bunker-300 select-none first:rounded-tl-md last:rounded-tr-md data-[state=active]:text-primary data-[state=active]:font-medium data-[state=active]:focus:relative data-[state=active]:border-b data-[state=active]:border-primary outline-none cursor-default"
className="flex h-10 flex-1 cursor-default select-none items-center justify-center bg-bunker-700 px-5 text-sm leading-none text-bunker-300 outline-none first:rounded-tl-md last:rounded-tr-md data-[state=active]:border-b data-[state=active]:border-primary data-[state=active]:font-medium data-[state=active]:text-primary data-[state=active]:focus:relative"
value="tab2"
>
Windows
@ -178,14 +180,14 @@ const TabsObject = () => {
<a
target="_blank"
rel="noopener noreferrer"
className="bg-bunker-700 hover:text-bunker-100 duration-200 px-5 h-10 flex-1 flex items-center justify-center text-sm leading-none text-bunker-300 select-none first:rounded-tl-md last:rounded-tr-md data-[state=active]:text-primary data-[state=active]:font-medium data-[state=active]:focus:relative data-[state=active]:border-b data-[state=active]:border-primary outline-none cursor-default"
className="flex h-10 flex-1 cursor-default select-none items-center justify-center bg-bunker-700 px-5 text-sm leading-none text-bunker-300 outline-none duration-200 first:rounded-tl-md last:rounded-tr-md hover:text-bunker-100 data-[state=active]:border-b data-[state=active]:border-primary data-[state=active]:font-medium data-[state=active]:text-primary data-[state=active]:focus:relative"
href="https://infisical.com/docs/cli/overview"
>
Other Platforms <FontAwesomeIcon icon={faArrowUpRightFromSquare} className="ml-2" />
</a>
</Tabs.List>
<Tabs.Content
className="grow p-5 pt-0 bg-bunker-700 rounded-b-md outline-none cursor-default"
className="grow cursor-default rounded-b-md bg-bunker-700 p-5 pt-0 outline-none"
value="tab1"
>
<CodeItem
@ -216,7 +218,7 @@ const TabsObject = () => {
code="infisical run -- [YOUR USUAL CODE START SCRIPT GOES HERE]"
id="runCode"
/>
<p className="text-bunker-300 text-sm mt-2">
<p className="mt-2 text-sm text-bunker-300">
You can find example of start commands for different frameworks{" "}
<a
className="text-primary underline underline-offset-2"
@ -229,7 +231,7 @@ const TabsObject = () => {
.{" "}
</p>
</Tabs.Content>
<Tabs.Content className="grow p-5 pt-0 bg-bunker-700 rounded-b-md outline-none" value="tab2">
<Tabs.Content className="grow rounded-b-md bg-bunker-700 p-5 pt-0 outline-none" value="tab2">
<CodeItem
isCopied={downloadCodeCopied}
setIsCopied={setDownloadCodeCopied}
@ -237,7 +239,7 @@ const TabsObject = () => {
code="scoop bucket add org https://github.com/Infisical/scoop-infisical.git"
id="downloadCodeW"
/>
<div className="font-mono text-sm px-3 py-2 mt-2 bg-bunker rounded-md border border-mineshaft-600 flex flex-row items-center justify-between">
<div className="mt-2 flex flex-row items-center justify-between rounded-md border border-mineshaft-600 bg-bunker px-3 py-2 font-mono text-sm">
<input
disabled
value="scoop install infisical"
@ -247,7 +249,7 @@ const TabsObject = () => {
<button
type="button"
onClick={() => copyToClipboard("downloadCodeW2", setDownloadCode2Copied)}
className="h-full pl-3.5 pr-2 text-bunker-300 hover:text-primary-200 duration-200"
className="h-full pl-3.5 pr-2 text-bunker-300 duration-200 hover:text-primary-200"
>
{downloadCode2Copied ? (
<FontAwesomeIcon icon={faCheck} className="pr-0.5" />
@ -277,7 +279,7 @@ const TabsObject = () => {
code="infisical run -- [YOUR USUAL CODE START SCRIPT GOES HERE]"
id="runCodeW"
/>
<p className="text-bunker-300 text-sm mt-2">
<p className="mt-2 text-sm text-bunker-300">
You can find example of start commands for different frameworks{" "}
<a
className="text-primary underline underline-offset-2"
@ -481,6 +483,13 @@ const OrganizationPage = withPermission(
const { createNotification } = useNotificationContext();
const addWsUser = useAddUserToWs();
const { data: updateClosed } = useGetUserAction("jan_2024_db_update_closed");
const registerUserAction = useRegisterUserAction();
const closeUpdate = async () => {
await registerUserAction.mutateAsync("jan_2024_db_update_closed");
};
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
"addNewWs",
"upgradePlan"
@ -586,10 +595,10 @@ const OrganizationPage = withPermission(
{!serverDetails?.redisConfigured && (
<div className="mb-4 flex flex-col items-start justify-start px-6 py-6 pb-0 text-3xl">
<p className="mr-4 mb-4 font-semibold text-white">Announcements</p>
<div className="w-full border border-blue-400/70 rounded-md bg-blue-900/70 p-2 text-base text-mineshaft-100 flex items-center">
<div className="flex w-full items-center rounded-md border border-blue-400/70 bg-blue-900/70 p-2 text-base text-mineshaft-100">
<FontAwesomeIcon
icon={faExclamationCircle}
className="text-2xl mr-4 p-4 text-mineshaft-50"
className="mr-4 p-4 text-2xl text-mineshaft-50"
/>
Attention: Updated versions of Infisical now require Redis for full functionality.
Learn how to configure it
@ -597,7 +606,7 @@ const OrganizationPage = withPermission(
href="https://infisical.com/docs/self-hosting/configuration/redis"
target="_blank"
>
<span className="pl-1 text-white underline underline-offset-2 hover:decoration-blue-400 hover:text-blue-200 duration-100 cursor-pointer">
<span className="cursor-pointer pl-1 text-white underline underline-offset-2 duration-100 hover:text-blue-200 hover:decoration-blue-400">
here
</span>
</Link>
@ -606,6 +615,22 @@ const OrganizationPage = withPermission(
</div>
)}
<div className="mb-4 flex flex-col items-start justify-start px-6 py-6 pb-0 text-3xl">
<div className={`${
!updateClosed ? "block" : "hidden"
} mb-4 w-full border rounded-md p-2 text-base border-primary-600 bg-primary/10 text-white flex flex-row items-center`}>
<FontAwesomeIcon icon={faWarning} className="text-primary text-4xl p-6"/>
<div className="text-sm">
<span className="text-lg font-semibold">Scheduled maintenance on January 27th</span> <br />
We&apos;ve planned a database upgrade and need to pause certain functionality for approximately 3 hours on Saturday, January 27th, 10am EST. During these hours, read operations will continue to function normally but no resources will be editable. No action is required on your end your applications can continue to fetch secrets.<br />
</div>
<button
type="button"
onClick={() => closeUpdate()}
className="text-mineshaft-100 duration-200 hover:text-red-400 h-full flex items-start"
>
<FontAwesomeIcon icon={faXmark} />
</button>
</div>
<p className="mr-4 font-semibold text-white">Projects</p>
<div className="mt-6 flex w-full flex-row">
<Input
@ -701,7 +726,7 @@ const OrganizationPage = withPermission(
</div>
<div className="mb-4 flex flex-col items-start justify-start px-6 py-6 pb-6 text-3xl">
<p className="mr-4 font-semibold text-white">Explore Infisical</p>
<div className="mt-4 grid grid-cols-3 w-full gap-4">
<div className="mt-4 grid w-full grid-cols-3 gap-4">
{features.map((feature) => (
<div
key={feature._id}

View File

@ -61,7 +61,7 @@ export const SignUpPage = () => {
router.push("/login");
}
}
}, []);
}, [config?.initialized]);
const { mutateAsync: createAdminUser } = useCreateAdminUser();
@ -117,7 +117,7 @@ export const SignUpPage = () => {
return <ContentLoader text="Redirecting to admin page..." />;
return (
<div className="flex justify-center items-center">
<div className="flex items-center justify-center">
<AnimatePresence exitBeforeEnter>
{step === SignupSteps.DetailsForm && (
<motion.div
@ -128,7 +128,7 @@ export const SignUpPage = () => {
animate={{ opacity: 1, translateX: 0 }}
exit={{ opacity: 0, translateX: 30 }}
>
<div className="text-center flex flex-col items-center space-y-4">
<div className="flex flex-col items-center space-y-4 text-center">
<img src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical logo" />
<div className="text-4xl">Welcome to Infisical</div>
<div>Create your first Admin Account</div>