Compare commits

...

27 Commits

Author SHA1 Message Date
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
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
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
8fbc930012 updated notification text 2024-01-08 13:51:40 -08:00
0e5190a920 added the december update blog 2024-01-08 13:47:58 -08:00
25 changed files with 253 additions and 123 deletions

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)
@ -685,7 +686,13 @@ 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);
if (val !== undefined) {
interpolatedValue = interpolatedValue.replaceAll(interpolationSyntax, val);
}
}
}
}
expandedSec[key] = interpolatedValue;
return interpolatedValue;
};

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")
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()
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).

View File

@ -1,10 +1,13 @@
---
title: "C#"
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

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

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

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

View File

@ -32,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: 78 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

@ -70,7 +70,7 @@ export const AdminLayout = ({ children }: LayoutProps) => {
const { user } = useUser();
const { subscription } = useSubscription();
const { data: updateClosed } = useGetUserAction("september_update_closed");
const { data: updateClosed } = useGetUserAction("december_update_closed");
const infisicalPlatformVersion = process.env.NEXT_PUBLIC_INFISICAL_PLATFORM_VERSION;
const { t } = useTranslation();
@ -78,7 +78,7 @@ export const AdminLayout = ({ children }: LayoutProps) => {
const registerUserAction = useRegisterUserAction();
const closeUpdate = async () => {
await registerUserAction.mutateAsync("september_update_closed");
await registerUserAction.mutateAsync("december_update_closed");
};
const logout = useLogoutUser();
@ -182,14 +182,14 @@ export const AdminLayout = ({ children }: LayoutProps) => {
} relative z-10 mb-6 flex pb-2 w-52 flex-col items-center justify-start rounded-md border border-mineshaft-600 bg-mineshaft-900 px-3`}
>
<div className="text-md mt-2 w-full font-semibold text-mineshaft-100">
Infisical September update
Infisical December update
</div>
<div className="mt-1 mb-1 w-full text-sm font-normal leading-[1.2rem] text-mineshaft-300">
Improved RBAC, new integrations, dashboard remake, and more!
Infisical Agent, new SDKs, Machine Identities, and more!
</div>
<div className="mt-2 h-[6.77rem] w-full rounded-md border border-mineshaft-700">
<Image
src="/images/infisical-update-september-2023.png"
src="/images/infisical-update-december-2023.png"
height={319}
width={539}
alt="kubernetes image"
@ -205,7 +205,7 @@ export const AdminLayout = ({ children }: LayoutProps) => {
Close
</button>
<a
href="https://infisical.com/blog/infisical-update-september-2023"
href="https://infisical.com/blog/infisical-update-december-2023"
target="_blank"
rel="noopener noreferrer"
className="text-sm font-normal leading-[1.2rem] text-mineshaft-400 duration-200 hover:text-mineshaft-100"

View File

@ -121,7 +121,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
const { user } = useUser();
const { subscription } = useSubscription();
const workspaceId = currentWorkspace?._id || "";
const { data: updateClosed } = useGetUserAction("september_update_closed");
const { data: updateClosed } = useGetUserAction("december_update_closed");
const { data: secretApprovalReqCount } = useGetSecretApprovalRequestCount({ workspaceId });
@ -153,7 +153,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
const registerUserAction = useRegisterUserAction();
const closeUpdate = async () => {
await registerUserAction.mutateAsync("september_update_closed");
await registerUserAction.mutateAsync("december_update_closed");
};
const logout = useLogoutUser();
@ -646,14 +646,14 @@ export const AppLayout = ({ children }: LayoutProps) => {
} relative z-10 mb-6 flex h-64 w-52 flex-col items-center justify-start rounded-md border border-mineshaft-600 bg-mineshaft-900 px-3`}
>
<div className="text-md mt-2 w-full font-semibold text-mineshaft-100">
Infisical September update
Infisical December update
</div>
<div className="mt-1 mb-1 w-full text-sm font-normal leading-[1.2rem] text-mineshaft-300">
Improved RBAC, new integrations, dashboard remake, and more!
Infisical Agent, new SDKs, Machine Identities, and more!
</div>
<div className="mt-2 h-[6.77rem] w-full rounded-md border border-mineshaft-700">
<Image
src="/images/infisical-update-september-2023.png"
src="/images/infisical-update-december-2023.png"
height={319}
width={539}
alt="kubernetes image"
@ -669,7 +669,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
Close
</button>
<a
href="https://infisical.com/blog/infisical-update-september-2023"
href="https://infisical.com/blog/infisical-update-december-2023"
target="_blank"
rel="noopener noreferrer"
className="text-sm font-normal leading-[1.2rem] text-mineshaft-400 duration-200 hover:text-mineshaft-100"

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";
@ -75,8 +78,7 @@ const features = [
_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}