GithubHelp home page GithubHelp logo

infisical / infisical-node Goto Github PK

View Code? Open in Web Editor NEW
68.0 4.0 19.0 208 KB

♾ Official Infisical SDK for Node

Home Page: https://infisical.com

License: MIT License

JavaScript 64.61% TypeScript 35.39%
end-to-end-encryption environment-variables javascript nodejs open-source secret-management secrets security typescript

infisical-node's Introduction

Open-source, end-to-end encrypted tool to manage secrets and configs across your team and infrastructure.

Deprecated!

This is now considered a legacy SDK, as we have released a new SDK that will be receiving all future updates. You can find it here.

Table of Contents

Links

Basic Usage

import express from "express";
import InfisicalClient from "infisical-node";
const app = express();
const PORT = 3000;

const client = new InfisicalClient({
    token: "YOUR_INFISICAL_TOKEN"
});

app.get("/", async (req, res) => {
    // access value
    const name = await client.getSecret("NAME", {
        environment: "dev",
        path: "/",
        type: "shared"
    });
    res.send(`Hello! My name is: ${name.secretValue}`);
});

app.listen(PORT, async () => {
    // initialize client
    console.log(`App listening on port ${port}`);
});

This example demonstrates how to use the Infisical Node SDK with an Express application. The application retrieves a secret named "NAME" and responds to requests with a greeting that includes the secret value.

It is also possible to use the SDK to encrypt/decrypt text; the implementation uses aes-256-gcm with components of the encryption/decryption encoded in base64.

import InfisicalClient from "infisical-node";
const client = new InfisicalClient();

// some plaintext you want to encrypt
const plaintext = "The quick brown fox jumps over the lazy dog";

// create a base64-encoded, 256-bit symmetric key
const key = client.createSymmetricKey();

// encrypt
const { ciphertext, iv, tag } = client.encryptSymmetric(plaintext, key);

// decrypt
const cleartext = client.decryptSymmetric(ciphertext, key, iv, tag);

Installation

$ npm install infisical-node

Configuration

Import the SDK and create a client instance with your Infisical Token.

const InfisicalClient = require("infisical-node");

const client = new InfisicalClient({
    token: "your_infisical_token"
});

Using ES6:

import InfisicalClient from "infisical-node";

const client = new InfisicalClient({
    token: "your_infisical_token"
});

// your app logic

Using Infisical Token V3 (Beta):

In v1.4.0, we released a superior token authentication method; this credential is a JSON containing a publicKey, privateKey, and serviceToken and can be used to initialize the Node SDK client instead of the regular service token.

You can use this beta feature like so:

const InfisicalClient = require("infisical-node");

const client = new InfisicalClient({
    tokenJson: "your_infisical_token_v3_json"
});

Options

Parameter Type Description
token string An Infisical Token scoped to a project and environment(s).
tokenJson string An Infisical Token V3 JSON scoped to a project and environment(s) - in beta
siteURL string Your self-hosted Infisical site URL. Default: https://app.infisical.com.
cacheTTL number Time-to-live (in seconds) for refreshing cached secrets. Default: 300.
debug boolean Turns debug mode on or off. Default: false.

Caching

The SDK caches every secret and updates it periodically based on the provided cacheTTL. For example, if cacheTTL of 300 is provided, then a secret will be refetched 5 minutes after the first fetch; if the fetch fails, the cached secret is returned.

Secrets

Get Secrets

const secrets = await client.getAllSecrets({
    environment: "dev",
    path: "/foo/bar/",
    attachToProcessEnv: false,
    includeImports: false
});

Retrieve all secrets within a given environment and folder path. The service token used must have access to the given path and environment.

Parameters

  • options (object)
    • environment The slug name (dev, prod, etc) of the environment from where secrets should be fetched from
    • path The path from where secrets should be fetched from
    • attachToProcessEnv (boolean, optional): Whether or not to attach fetched secrets to process.env. If not specified, the default value is false.
    • includeImports (boolean, optional): Whether or not to include imported secrets from the current path. Read about secret import.

Get Secret

Retrieve a secret from Infisical:

const secret = await client.getSecret("API_KEY", {
    environment: "dev",
    path: "/",
    type: "shared"
});
const value = secret.secretValue; // get its value

By default, getSecret() fetches and returns a personal secret. If not found, it returns a shared secret, or tries to retrieve the value from process.env. If a secret is fetched, getSecret() caches it to reduce excessive calls and re-fetches periodically based on the cacheTTL option (default is 300 seconds) when initializing the client — for more information, see the caching section.

To explicitly retrieve a shared secret:

const secret = await client.getSecret("API_KEY", {
    environment: "dev",
    path: "/",
    type: "shared"
});
const value = secret.secretValue; // get its value

Parameters

  • secretName (string): The key of the secret to retrieve.
  • options (object, optional): An options object to speify the type of secret.
    • environment The slug name (dev, prod, etc) of the environment from where secrets should be fetched from
    • path The path from where secrets should be fetched from
    • type (string, optional): The type of the secret. Valid options are "shared" or "personal". If not specified, the default value is "personal".

Create Secret

Create a new secret in Infisical:

const newApiKey = await client.createSecret("API_KEY", "FOO", {
    environment: "dev",
    path: "/",
    type: "shared"
});

Parameters

  • secretName (string): The key of the secret to create.
  • secretValue (string): The value of the secret.
  • options (object, optional): An options object to specify the type of secret.
    • environment The slug name (dev, prod, etc) of the environment where secret should be created
    • path The path from where secret should be created.
    • type (string, optional): The type of the secret. Valid options are "shared" or "personal". If not specified, the default value is "shared". A personal secret can only be created if a shared secret with the same name exists.

Update Secret

Update an existing secret in Infisical:

const updatedApiKey = await client.updateSecret("API_KEY", "BAR", {
    environment: "dev",
    path: "/",
    type: "shared"
});

Parameters

  • secretName (string): The key of the secret to update.
  • secretValue (string): The new value of the secret.
  • options (object, optional): An options object to specify the type of secret.
    • environment The slug name (dev, prod, etc) of the environment where secret should be updated.
    • path The path from where secret should be updated.
    • type (string, optional): The type of the secret. Valid options are "shared" or "personal". If not specified, the default value is "shared".

Delete Secret

Delete a secret in Infisical:

const deletedSecret = await client.deleteSecret("API_KEY", {
    environment: "dev",
    path: "/",
    type: "shared"
});

Parameters

  • secretName (string): The key of the secret to delete.
  • options (object, optional): An options object to specify the type of secret to delete.
    • environment The slug name (dev, prod, etc) of the environment where secret should be deleted.
    • path The path from where secret should be deleted.
    • type (string, optional): The type of the secret. Valid options are "shared" or "personal". If not specified, the default value is "shared". Note that deleting a shared secret also deletes all associated personal secrets.

Cryptography

Create Symmetric Key

Create a base64-encoded, 256-bit symmetric key to be used for encryption/decryption.

const key = client.createSymmetricKey();

Returns

key (string): A base64-encoded, 256-bit symmetric key.

Encrypt Symmetric

Encrypt plaintext -> ciphertext.

const { ciphertext, iv, tag } = client.encryptSymmetric(plaintext, key);

Parameters

  • plaintext (string): The plaintext to encrypt.
  • key (string): The base64-encoded, 256-bit symmetric key to use to encrypt the plaintext.

Returns

An object containing the following properties:

  • ciphertext (string): The base64-encoded, encrypted plaintext.
  • iv (string): The base64-encoded, 96-bit initialization vector generated for the encryption.
  • tag (string): The base64-encoded authentication tag generated during the encryption.

Decrypt Symmetric

Decrypt ciphertext -> plaintext/cleartext.

const cleartext = client.decryptSymmetric(ciphertext, key, iv, tag);

Parameters

  • ciphertext (string): The ciphertext to decrypt.
  • key (string): The base64-encoded, 256-bit symmetric key to use to decrypt the ciphertext.
  • iv (string): The base64-encoded, 96-bit initiatlization vector generated for the encryption.
  • tag (string): The base64-encoded authentication tag generated during encryption.

Returns

cleartext (string): The decrypted encryption that is the cleartext/plaintext.

Contributing

Bug fixes, docs, and library improvements are always welcome. Please refer to our Contributing Guide for detailed information on how you can contribute.

Getting Started

If you want to familiarize yourself with the SDK, you can start by forking the repository and cloning it in your local development environment. The project requires Node.js to be installed on your machine.

After cloning the repository, install the depenencies by running the following command in the directory of your cloned repository:

$ npm install

To run existing tests, you need to make a .env at the root of this project containing a INFISICAL_TOKEN and SITE_URL. This will execute the tests against a project and environment scoped to the INFISICAL_TOKEN on a running instance of Infisical at the SITE_URL (this could be Infisical Cloud).

To run all the tests you can use the following command:

$ npm test

License

infisical-node is distributed under the terms of the MIT license.

infisical-node's People

Contributors

dangtony98 avatar danielhougaard avatar gitsambhal avatar maidul98 avatar microtronics-jast avatar nicozweifel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

infisical-node's Issues

No errors

It's super annoying that this won't fail if you give an api key with the incorrect permissions

typescript error

getting

This expression is not constructable.
  Type 'typeof import("/home/uri/uriva/my-project/node_modules/infisical-node/lib/index")' has no construct signatures.ts(2351)

for

import { map, pipe } from "gamla";

import InfisicalClient from "infisical-node";

export const getSecrets = (): Promise<Record<string, string>> =>
  new InfisicalClient({ token: process.argv[2] }) // <------------------------------ error is here
    .getAllSecrets({
      environment: "prod",
      path: "/",
    })
    .then(
      pipe(
        map(({ secretName, secretValue }: any) => [secretName, secretValue]),
        Object.fromEntries,
        (secrets: Record<string, string>) => {
          process.env = { ...process.env, ...secrets };
          return secrets;
        },
      ),
    );

Only GET request should be cached and improve error handling

It makes no sense to return cached responses for request of creating, updating or removing secrets if they are not successfully.
I would expect, that these methods are throwing or that they are returning some (full) error object.
In any case, when an action is failing, the information is lost and data is not changed as expected.

Currently, you need to do something like this:

const result = await this.client.updateSecret(secretName, configValue)
if (result.isFallback) {
   throw new Error('Unable to update secret for unknown reason')
}

Also, as always some result is returned, errors are swallowed and not visible to the consumer.
At least in the returned ISecretBundle, there should be some optional error field, which contains the error.

Something like this:

const result = await this.client.updateSecret(secretName, configValue)
if (result.error) {
   console.error(result.error)
   throw new Error('Unable to update secret: ' + result.error.message )
}

Add validation for environment variables in `infisical.connect`

Currently, infisical.connect just fetches back secrets from Infisical.

In the future, we want infisical.connect to also be able to accept validator arguments so that you can for instance:

  • Cast environment variables that are fetched back as strings to a different type.
  • Throw an error if a required environment variable is missing.
  • Fallback to default values.

Here's what I have in mind:

Users can define a custom configuration object containing each environment variable and its details that such as description, type, default, transform (i.e. function that transforms the input environment variable).

This would significantly minimize errors for folks using the Infisical Node SDK.

References not resolved

It's the first time I'm using Infisical (self-hosted via docker at the last version you released) and the infisical-node.

I tried to fetch all secrets from a given path (e.g. /) in which I have a secret containing a reference to another secret (e.g. https://${X_MY_HOST}).

If I use the infisical-cli this reference is resolved, but using the getAllSecrets or the simple getSecret using the same token, the reference is not resolved.

These are the options I passed to the getAllSecrets:

{
  environment,
  path: `/${service}`,
  attachToProcessEnv: false,
  includeImports: true,
}

I hope it's not a bug of the infisical-node package.

Thanks in advance

TypeScript types only partial available

The package does not export types correctly.

As an example, the config type InfisicalClientOptions is only available via the source import { InfisicalClientOptions } from 'infisical-node/src/types/InfisicalClient'

Normally, there should also be no need to bundle the source, test, markdown & images.
Might be you can also reduce the bundle size here

types are not present in installed package

The expected "types" directory doesn't seem to be present in the installed package under node_modules/infisical-node/api

infisical-node@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/infisical-node/-/infisical-node-1.3.2.tgz#37c73dde05e8bf914fc7d3c0e1936524aedd9ddf"
integrity sha512-o1rxfOBAmpTiipka9Xnfa2AgTS8CkJHo0aRQwk6UGi+yEkKzXS7dDM7bZD56M/z+yKGLK15QkfFGZXp1VomlHw==
dependencies:
axios "^1.3.3"
dotenv "^16.0.3"
tweetnacl "^1.0.3"
tweetnacl-util "^0.15.1"

node_modules/infisical-node/lib/client/InfisicalClient.d.ts:1:31 - error TS2307: Cannot find module '../types/models' or its corresponding type declarations.

1 import { ISecretBundle } from '../types/models';
~~~~~~~~~~~~~~~~~
node_modules/infisical-node/lib/client/InfisicalClient.d.ts:2:138 - error TS2307: Cannot find module '../types/InfisicalClient' or its corresponding type declarations.

2 import { ServiceTokenClientConfig, GetAllOptions, GetOptions, CreateOptions, UpdateOptions, DeleteOptions, InfisicalClientOptions } from '../types/InfisicalClient';
~~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/infisical-node/lib/client/InfisicalClient.d.ts:3:41 - error TS2307: Cannot find module '../types/utils' or its corresponding type declarations.

relates to #8

Environment absolute reference

It would be so useful to have the ability to specify the path of an absolute env var without needing to specify the environment slug at the beginning (e.g. ${db.PASSWORD} instead of ${development.db.PASSWORD}).
Clearly this behavior should occur under the same environment.

Let me know.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.