Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mono-repo with multi-services support + local setup and scope config file improvement (.infisical.json) #243

Open
5 tasks
Grraahaam opened this issue Jan 21, 2023 · 9 comments
Assignees
Labels
🚀 feature request New feature or request

Comments

@Grraahaam
Copy link
Contributor

Grraahaam commented Jan 21, 2023

Feature description 🚀

Today, AKAIK there's no easy way to run Infisical's CLI in a monorepo with multiple services divided into multiple infisical projects, e.g. infisical run -- docker-compose up -d ...

Imagine a monorepo with three services (pretty common) controlled by docker-compose :

  • frontend
  • backend
  • database

I have a Infisical project for each of the above services (best practice?) and I can't easily find a way without refactoring the code (e.g. install infisical CLI in a specific Dockerfile stage and pass a env token as an argument) to inject my secrets within when running docker-compose

Suggestions ✨

Writing documentation about Infisical monorepo/multi-service best practices, support and maybe adaptation of the API/CLI (I presume, to generate tokens bound to multiple projects)

An option in both the dashboard & the CLI to generate single access token to multiple projects, and a single config in each of them (otherwise it won't make sense 🙃 )

Token structure integration 🎫

For the token structure, the token xxxx-xxxxxxxxxxxxxxx-xxxxxxx points to three different Infisical projects (<project-name>:<config>) :

  • project-one:dev
  • project-three:dev
  • project-four:prd

When requesting the secrets with this token, I'd like to get all the secrets of the above projects (from their respective configs), making it mono-repo friendly by allowing the user to easily inject multiple infisical projects secrets into a single app (made of multiple services)

⚠️ There might be a conflict between same env names, in that case we could either warn the user and block the token creation until he fixes the name duplications or overwrite the value with the latest variable of the same name

CLI integration 💻

For the CLI, here's two suggestions :

Interactive setup

# Allow multiple project selection (e.g. spacebar)
$ infisical init
"Space to select, Enter to confirm"
> project-one
  project-two
  project-three
> project-four

# Press <ENTER>

# Select a single config per project
$ infisical init
"Space to select, Enter to confirm"

"Select config for : project-one"
> dev
  stg
  prd
"Select config for : project-four"
  dev
> stg
  prd

And the .infisical.json repository setup file could look like the following (check if we want to keep using JSON instead of YAML?) :

{
  // "workspaceId":"63c7c37331ffe61437214e61" we could use the project name instead easier for the user experience (project pre-config)
  // and format the project names at the creation time, in the dashboard (enforce alpha+hyphen maximum)
  "project":"my-project",  
  "env":"dev", // if specified, infisical secrets will automatically know what project + env to use
  "projects": [
    {
      "project": "project-api",
      "config": "dev",
      "path": "./api",
    },
    {
      "project": "project-backend",
      "config": "dev",
      "path": "./backend",
    },
    {
      "project": "project-frontend",
      "config": "stg",
      "path": "./frontend",
    },
  ]
}

Then, running infisical init --no-interactive would auto-generate the following entries in ~/.infisical/.infisical.json (we could have a global scope in the USER home directory, allowing us to use the infisical command anywhere without providing project/env args) :

{
  "scope": [
    // OS wide scope (overriden in below directories)
    "/": {
      "token": "secret-xxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxx",
      "api-host": "https://app.infisical.com/api",
      "dashboard-host": "https://app.infisical.com/dashboard",
      "project": "project-common",
      "env": "prd",
    },
    "/home/user/infisical-demo": {
      "token": "secret-xxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxx",
      "api-host": "https://app.infisical.com/api",
      "dashboard-host": "https://app.infisical.com/dashboard",
      "project": "project-global",
      "env": "dev",
    },
    "/home/user/infisical-demo/api": {
      "token": "secret-xxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxx",
      "api-host": "https://app.infisical.com/api",
      "dashboard-host": "https://app.infisical.com/dashboard",
      "project": "project-api",
      "env": "stg",
    },
    "/home/user/infisical-demo/backend": {
      "token": "secret-xxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxx",
      "api-host": "https://app.infisical.com/api",
      "dashboard-host": "https://app.infisical.com/dashboard",
      "project": "project-backend",
      "env": "dev",
    },
    "/home/user/infisical-demo/frontend": {
      "token": "secret-xxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxx",
      "api-host": "https://app.infisical.com/api",
      "dashboard-host": "https://app.infisical.com/dashboard",
      "project": "project-frontend",
      "env": "stg",
    },
  ]
}

Finally, how to use it in the CLI :

# Only returns the secrets from the filepath scope (e.g. in  /home/user/infisical-demo/api only project-api:dev secrets)
infisical secrets

# Returns all the secrets from the filepath scope and childrens defined in infisical.json
infisical secrets --all

# Allowing the user to inject all its secrets in a single simple command
infisical run --all -- docker-compose up -d

Inline command

# Get secrets from multiple projects passed inline (':' aren't allowed in the project names so it works as a separator) 
infisical secrets --project project-one:dev,project-two:stg

Recap

Here's a simplified list of the above suggestions :

  • multi-project (single environment) token
  • mono-repo with multiple services best practices (docs)
  • refactoring of the .infisical.json structure and the infisical init process (make it possible to setup a project+env non-interactively from .infisical.json)
  • check if it's be better to use YAML instead of JSON for .infisical.json and ~/.infisical/.infisical.json (YAML is commonly used by the devops and the syntax may be a bit easier)
  • possibility to configure a global scope e.g. ~/.infisical/.infisical.json for the user (calling infisical will use those defaults)

Disclaimer: Since our company still use Doppler, and they lack this feature as well, I've cross-posted this request initially posted in their repository

@Grraahaam
Copy link
Contributor Author

I'm aware that's a big issue which combine multiple feature requests, but they're all related, I'll try to split it into smaller issues, easier to work on ✌🏽

I'll try to attach a flow/structure diagram for the above, soon! 📊 🚀

@vv24ua
Copy link

vv24ua commented Jan 21, 2023

Thank you so much @Grraahaam! This is SUPER useful!

@maidul98
Copy link
Collaborator

Hey @Grraahaam just reading this, quite comprehensive. I agree, Infisical needs better mongo repo support. I'll get back to you with more questions as I think about the suggestions. Side note, are you also looking to contribute to the CLI code base? If so let us know!

@maidul98 maidul98 added the 🚀 feature request New feature or request label Jan 21, 2023
@Grraahaam
Copy link
Contributor Author

Hey @Grraahaam just reading this, quite comprehensive. I agree, Infisical needs better mongo repo support. I'll get back to you with more questions as I think about the suggestions.

Thanks for your consideration!

Side note, are you also looking to contribute to the CLI code base? If so let us know!

It's on my todo list, I'd be my second experience with Go, so let's see how it goes!

@Grraahaam
Copy link
Contributor Author

We could even simplify it to avoid a big backend refactoring by simply looping through the main project 's "dependencies" (projects), fetch their secrets and bulk inject them. Does that sounds better? I'll try to define it clearly in a diagram

@maidul98 maidul98 self-assigned this Jan 28, 2023
@maidul98
Copy link
Collaborator

maidul98 commented Feb 2, 2023

We are thinking of creating a new feature that allows secrets to be tagged. For instance, if you have multiple microservices for a specific project, you can tag secrets according to the microservice they belong to. So we can tag secrets such as microservice-1, microservice-2, etc within the same project. When you start a mongo repo application, you can specify all tag in the cli which will pull all secrets in bulk. I think this would simplify mono repo experience because the issue is you want to inject secrets from multiple projects, but with the new tags, you can have several applications within one project. What do you think? Are there some use cases that won't be covered by this?

#148

CC: @jon4hz @asheliahut

@rawkode
Copy link
Contributor

rawkode commented Jan 18, 2024

We are thinking of creating a new feature that allows secrets to be tagged. For instance, if you have multiple microservices for a specific project, you can tag secrets according to the microservice they belong to. So we can tag secrets such as microservice-1, microservice-2, etc within the same project. When you start a mongo repo application, you can specify all tag in the cli which will pull all secrets in bulk. I think this would simplify mono repo experience because the issue is you want to inject secrets from multiple projects, but with the new tags, you can have several applications within one project. What do you think? Are there some use cases that won't be covered by this?

#148

CC: @jon4hz @asheliahut

I think you've got this the wrong way round, as I'm trying to explore using Infisical in a mono repository with a few dozen services and at the moment it's rather painful.

Infisical already supports folders, which is almost perfect to map to a mono repository. Imagine an Infisical project with the following structure:

  • CLOUDFLARE_ACCOUNT_ID=value
  • service-name
    • CLOUDFLARE_API_TOKEN=secret
  • another-service-name
    • CLOUDFLARE_API_TOKEN=secret
    • infrastructure
      • AWS_ACCESS_KEY=secret
      • TERRAFORM_CLOUD_KEY=secret
    • web
      • VERCEL_TOKEN=secret

We want to use a single project for the mono repository, so that we can have shared globals, such as the CLOUDFLARE_ACCOUNT_ID.

We want to use path based structure that resembles the mono repositories own hierarchy.

We need every developer, backend and frontend, and operator, and potentially product, access to this single project. RBAC now becomes a huge challenge based on current implementation.

The way I would love this to work:

  1. I store .infisical.json in the root of my mono repository. If any service within wishes, or needs, its own project; it can then created a nested .infisical.json and it "escapes" from inherited behaviour.
  2. If I run infisical run at the top of my mono repository, I should only see CLOUDFLARE_API_TOKEN. This works atm.
  3. If I run infisical run at ./service-name I should see CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID.
    a. Currently, this will only work with a secret reference at service-name folder and that's fine; but the ability to apply a "propegate" semantic to variables to leak down the hierarchy would be cool.

Now we have the RBAC problem, currently roles only allow me to assign glob paths to them. But we do have tags and those shouldn't be used to allocate secrets to services; but instead to expose secrets to roles.

I have 3 main users who need access:

  • infrastructure developers, they have access to AWS, Terraform, and Cloudflare tokens for all projects
  • frontend developers, likely to need access to clark.dev, firebase, so forth
  • backend developers, likely need access GitHub for container registries and database credentials

If I tag my secrets, the values returned for infisical run should be filtered based on the tags assigned to the role of the person executing the command.

I hope this makes sense, @maidul98; happy to go into it more detail if we want to cover more use-cases.

@rawkode
Copy link
Contributor

rawkode commented Jan 18, 2024

One final suggestion:

Allow me in .infisical.json to turn on "directory-filtering: true" which checks the cwd when executing infisical run and automatically sets the --path argument to the path from the .infisical.json to cwd

related: #938

@rawkode
Copy link
Contributor

rawkode commented Jul 31, 2024

I closed #1329 as I was unable to get any feedback from Infisical to progress with making Infisical work for monorepositories.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🚀 feature request New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants