Mono-repo with multi-services support + local setup and scope config file improvement (.infisical.json)
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 :
frontendbackenddatabase
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:devproject-three:devproject-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.jsonstructure and theinfisical initprocess (make it possible to setup aproject+envnon-interactively from.infisical.json) - [ ] check if it's be better to use YAML instead of JSON for
.infisical.jsonand~/.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.jsonfor the user (callinginfisicalwill 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
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! 📊 🚀
Thank you so much @Grraahaam! This is SUPER useful!
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!
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!
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
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?
https://github.com/Infisical/infisical/issues/148
CC: @jon4hz @asheliahut
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
alltag 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:
- I store
.infisical.jsonin the root of my mono repository. If any service within wishes, or needs, its own project; it can then created a nested.infisical.jsonand it "escapes" from inherited behaviour. - If I run
infisical runat the top of my mono repository, I should only seeCLOUDFLARE_API_TOKEN. This works atm. - If I run
infisical runat./service-nameI should seeCLOUDFLARE_API_TOKENandCLOUDFLARE_ACCOUNT_ID. a. Currently, this will only work with a secret reference atservice-namefolder 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.
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
I closed #1329 as I was unable to get any feedback from Infisical to progress with making Infisical work for monorepositories.