Compare commits

..

17 Commits

Author SHA1 Message Date
Maidul Islam
4748b546c2 Merge pull request #1497 from Infisical/add-cert-to-knex-command
Add postgres cert to migration knex command
2024-02-29 15:05:55 -05:00
Maidul Islam
96887cdbfa add cert support to knex migration 2024-02-29 14:37:01 -05:00
Maidul Islam
553b56e57e fix make down command from Makefile 2024-02-29 14:18:33 -05:00
Maidul Islam
a33f542647 Merge pull request #1493 from akhilmhdh/fix/dup-sec-del
fix(server): duplicate secret deletion made possible
2024-02-29 14:16:44 -05:00
Maidul Islam
06b03fc450 update fnSecretBlindIndexCheck function comment 2024-02-29 14:01:32 -05:00
Maidul Islam
031a834ab1 Merge pull request #1495 from Salman2301/feat-cloud-worker-path
feat: add support for secret path for cloud worker
2024-02-29 12:24:44 -05:00
Akhil Mohan
89e942fea3 Merge pull request #1496 from Infisical/tag-migration-guide
update mongo to postgres doc
2024-02-29 22:28:43 +05:30
Maidul Islam
3c0908a788 update mongo to postgres doc 2024-02-29 11:56:48 -05:00
Salman
14e42b7ff2 feat: add support for secret path for cloud worker 2024-02-29 21:40:19 +05:30
Maidul Islam
9476594978 Merge pull request #1494 from akhilmhdh/fix/migration-admin-bug
fix(pg-migrator): added uuid 0000 for admin config
2024-02-29 10:57:26 -05:00
Maidul Islam
02be9ebd5e Merge pull request #1492 from akhilmhdh/fix/create-tag 2024-02-29 09:03:18 -05:00
Akhil Mohan
eb29d1dc28 fix(pg-migrator): added uuid 0000 for admin config 2024-02-29 15:38:45 +05:30
Akhil Mohan
21d5c44ea1 fix(server): duplicate secret deletion made possible 2024-02-29 14:58:45 +05:30
Akhil Mohan
114a4b1412 fix(server): resolved broken create tag scoped to project 2024-02-29 13:02:09 +05:30
Maidul Islam
cde8cef8b0 Merge pull request #1490 from 24601/patch-1
fix(helm-charts): standalone chart rbac fix for jobs
2024-02-28 22:41:27 -05:00
Maidul Islam
7207997cea update chart version 2024-02-28 22:40:15 -05:00
Basit Mustafa
aaabfb7870 fix(helm-charts): standalone chart rbac fix for jobs 2024-02-28 19:31:16 -07:00
16 changed files with 122 additions and 234 deletions

View File

@@ -11,4 +11,4 @@ up-prod:
docker-compose -f docker-compose.prod.yml up --build
down:
docker-compose down
docker compose -f docker-compose.dev.yml down

View File

@@ -17,7 +17,15 @@ dotenv.config({
export default {
development: {
client: "postgres",
connection: process.env.DB_CONNECTION_URI,
connection: {
connectionString: process.env.DB_CONNECTION_URI,
ssl: process.env.DB_ROOT_CERT
? {
rejectUnauthorized: true,
ca: Buffer.from(process.env.DB_ROOT_CERT, "base64").toString("ascii")
}
: false
},
pool: {
min: 2,
max: 10
@@ -31,7 +39,15 @@ export default {
},
production: {
client: "postgres",
connection: process.env.DB_CONNECTION_URI,
connection: {
connectionString: process.env.DB_CONNECTION_URI,
ssl: process.env.DB_ROOT_CERT
? {
rejectUnauthorized: true,
ca: Buffer.from(process.env.DB_ROOT_CERT, "base64").toString("ascii")
}
: false
},
pool: {
min: 2,
max: 10

View File

@@ -19,7 +19,7 @@ export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSe
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Tags);
const existingTag = await secretTagDAL.findOne({ slug });
const existingTag = await secretTagDAL.findOne({ slug, projectId });
if (existingTag) throw new BadRequestError({ message: "Tag already exist" });
const newTag = await secretTagDAL.create({

View File

@@ -7,7 +7,7 @@ import { TSecretSnapshotServiceFactory } from "@app/ee/services/secret-snapshot/
import { getConfig } from "@app/lib/config/env";
import { buildSecretBlindIndexFromName, encryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto";
import { BadRequestError } from "@app/lib/errors";
import { groupBy, pick } from "@app/lib/fn";
import { groupBy, pick, unique } from "@app/lib/fn";
import { logger } from "@app/lib/logger";
import { ActorType } from "../auth/auth-type";
@@ -202,12 +202,13 @@ export const secretServiceFactory = ({
return deletedSecrets;
};
// this is a utility function for secret modification
// this will check given secret name blind index exist or not
// if its a created secret set isNew to true
// thus if these blindindex exist it will throw an error
// vice versa when u need to check for updated secret
// this will also return the blind index grouped by secretName
/**
* Checks and handles secrets using a blind index method.
* The function generates mappings between secret names and their blind indexes, validates user IDs for personal secrets, and retrieves secrets from the database based on their blind indexes.
* For new secrets (isNew = true), it ensures they don't already exist in the database.
* For existing secrets, it verifies their presence in the database.
* If discrepancies are found, errors are thrown. The function returns mappings and the fetched secrets.
*/
const fnSecretBlindIndexCheck = async ({
inputSecrets,
folderId,
@@ -242,10 +243,18 @@ export const secretServiceFactory = ({
if (isNew) {
if (secrets.length) throw new BadRequestError({ message: "Secret already exist" });
} else if (secrets.length !== inputSecrets.length)
throw new BadRequestError({
message: `Secret not found: blind index ${JSON.stringify(keyName2BlindIndex)}`
});
} else {
const secretKeysInDB = unique(secrets, (el) => el.secretBlindIndex as string).map(
(el) => blindIndex2KeyName[el.secretBlindIndex as string]
);
const hasUnknownSecretsProvided = secretKeysInDB.length !== inputSecrets.length;
if (hasUnknownSecretsProvided) {
const keysMissingInDB = Object.keys(keyName2BlindIndex).filter((key) => !secretKeysInDB.includes(key));
throw new BadRequestError({
message: `Secret not found: blind index ${keysMissingInDB.join(",")}`
});
}
}
return { blindIndex2KeyName, keyName2BlindIndex, secrets };
};

View File

@@ -1,5 +1,5 @@
infisical:
address: "https://app.infisical.com/"
address: "http://localhost:8080"
auth:
type: "universal-auth"
config:
@@ -13,12 +13,3 @@ sinks:
templates:
- source-path: my-dot-ev-secret-template
destination-path: my-dot-env.env
config:
polling-interval: 60s
execute:
command: docker-compose -f docker-compose.prod.yml down && docker-compose -f docker-compose.prod.yml up -d
- source-path: my-dot-ev-secret-template1
destination-path: my-dot-env-1.env
config:
exec:
command: mkdir hello-world1

View File

@@ -490,7 +490,5 @@ func CallGetRawSecretsV3(httpClient *resty.Client, request GetRawSecretsV3Reques
return GetRawSecretsV3Response{}, fmt.Errorf("CallGetRawSecretsV3: Unsuccessful response [%v %v] [status-code=%v] [response=%v]", response.Request.Method, response.Request.URL, response.StatusCode(), response.String())
}
getRawSecretsV3Response.ETag = response.Header().Get(("etag"))
return getRawSecretsV3Response, nil
}

View File

@@ -505,5 +505,4 @@ type GetRawSecretsV3Response struct {
SecretComment string `json:"secretComment"`
} `json:"secrets"`
Imports []any `json:"imports"`
ETag string
}

View File

@@ -5,15 +5,12 @@ package cmd
import (
"bytes"
"context"
"encoding/base64"
"fmt"
"io/ioutil"
"os"
"os/exec"
"os/signal"
"path"
"runtime"
"strings"
"sync"
"syscall"
@@ -74,56 +71,12 @@ type Template struct {
SourcePath string `yaml:"source-path"`
Base64TemplateContent string `yaml:"base64-template-content"`
DestinationPath string `yaml:"destination-path"`
Config struct { // Configurations for the template
PollingInterval string `yaml:"polling-interval"` // How often to poll for changes in the secret
Execute struct {
Command string `yaml:"command"` // Command to execute once the template has been rendered
Timeout int64 `yaml:"timeout"` // Timeout for the command
} `yaml:"execute"` // Command to execute once the template has been rendered
} `yaml:"config"`
}
func ReadFile(filePath string) ([]byte, error) {
return ioutil.ReadFile(filePath)
}
func ExecuteCommandWithTimeout(command string, timeout int64) error {
shell := [2]string{"sh", "-c"}
if runtime.GOOS == "windows" {
shell = [2]string{"cmd", "/C"}
} else {
currentShell := os.Getenv("SHELL")
if currentShell != "" {
shell[0] = currentShell
}
}
ctx := context.Background()
if timeout > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
defer cancel()
}
cmd := exec.CommandContext(ctx, shell[0], shell[1], command)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
if exitError, ok := err.(*exec.ExitError); ok { // type assertion
if exitError.ProcessState.ExitCode() == -1 {
return fmt.Errorf("command timed out")
}
}
return err
} else {
return nil
}
}
func FileExists(filepath string) bool {
info, err := os.Stat(filepath)
if os.IsNotExist(err) {
@@ -217,24 +170,20 @@ func ParseAgentConfig(configFile []byte) (*Config, error) {
return config, nil
}
func secretTemplateFunction(accessToken string, existingEtag string, currentEtag *string) func(string, string, string) ([]models.SingleEnvironmentVariable, error) {
func secretTemplateFunction(accessToken string) func(string, string, string) ([]models.SingleEnvironmentVariable, error) {
return func(projectID, envSlug, secretPath string) ([]models.SingleEnvironmentVariable, error) {
res, err := util.GetPlainTextSecretsViaMachineIdentity(accessToken, projectID, envSlug, secretPath, false)
secrets, err := util.GetPlainTextSecretsViaMachineIdentity(accessToken, projectID, envSlug, secretPath, false)
if err != nil {
return nil, err
}
if existingEtag != res.Etag {
*currentEtag = res.Etag
}
return res.Secrets, nil
return secrets, nil
}
}
func ProcessTemplate(templatePath string, data interface{}, accessToken string, existingEtag string, currentEtag *string) (*bytes.Buffer, error) {
func ProcessTemplate(templatePath string, data interface{}, accessToken string) (*bytes.Buffer, error) {
// custom template function to fetch secrets from Infisical
secretFunction := secretTemplateFunction(accessToken, existingEtag, currentEtag)
secretFunction := secretTemplateFunction(accessToken)
funcs := template.FuncMap{
"secret": secretFunction,
}
@@ -254,7 +203,7 @@ func ProcessTemplate(templatePath string, data interface{}, accessToken string,
return &buf, nil
}
func ProcessBase64Template(encodedTemplate string, data interface{}, accessToken string, existingEtag string, currentEtag *string) (*bytes.Buffer, error) {
func ProcessBase64Template(encodedTemplate string, data interface{}, accessToken string) (*bytes.Buffer, error) {
// custom template function to fetch secrets from Infisical
decoded, err := base64.StdEncoding.DecodeString(encodedTemplate)
if err != nil {
@@ -263,7 +212,7 @@ func ProcessBase64Template(encodedTemplate string, data interface{}, accessToken
templateString := string(decoded)
secretFunction := secretTemplateFunction(accessToken, existingEtag, currentEtag) // TODO: Fix this
secretFunction := secretTemplateFunction(accessToken)
funcs := template.FuncMap{
"secret": secretFunction,
}
@@ -301,16 +250,7 @@ type TokenManager struct {
}
func NewTokenManager(fileDeposits []Sink, templates []Template, clientIdPath string, clientSecretPath string, newAccessTokenNotificationChan chan bool, removeClientSecretOnRead bool, exitAfterAuth bool) *TokenManager {
return &TokenManager{
filePaths: fileDeposits,
templates: templates,
clientIdPath: clientIdPath,
clientSecretPath: clientSecretPath,
newAccessTokenNotificationChan: newAccessTokenNotificationChan,
removeClientSecretOnRead: removeClientSecretOnRead,
exitAfterAuth: exitAfterAuth,
}
return &TokenManager{filePaths: fileDeposits, templates: templates, clientIdPath: clientIdPath, clientSecretPath: clientSecretPath, newAccessTokenNotificationChan: newAccessTokenNotificationChan, removeClientSecretOnRead: removeClientSecretOnRead, exitAfterAuth: exitAfterAuth}
}
func (tm *TokenManager) SetToken(token string, accessTokenTTL time.Duration, accessTokenMaxTTL time.Duration) {
@@ -488,80 +428,38 @@ func (tm *TokenManager) WriteTokenToFiles() {
}
}
func (tm *TokenManager) WriteTemplateToFile(bytes *bytes.Buffer, template *Template) {
if err := WriteBytesToFile(bytes, template.DestinationPath); err != nil {
log.Error().Msgf("template engine: unable to write secrets to path because %s. Will try again on next cycle", err)
return
}
log.Info().Msgf("template engine: secret template at path %s has been rendered and saved to path %s", template.SourcePath, template.DestinationPath)
}
func (tm *TokenManager) MonitorSecretChanges(secretTemplate Template, sigChan chan os.Signal) {
pollingInterval := time.Duration(5 * time.Minute)
if secretTemplate.Config.PollingInterval != "" {
interval, err := util.ConvertPollingIntervalToTime(secretTemplate.Config.PollingInterval)
if err != nil {
log.Error().Msgf("unable to convert polling interval to time because %v", err)
sigChan <- syscall.SIGINT
return
} else {
pollingInterval = interval
}
}
var existingEtag string
var currentEtag string
var firstRun = true
execTimeout := secretTemplate.Config.Execute.Timeout
execCommand := secretTemplate.Config.Execute.Command
func (tm *TokenManager) FetchSecrets() {
log.Info().Msgf("template engine started...")
for {
token := tm.GetToken()
if token != "" {
var processedTemplate *bytes.Buffer
var err error
if secretTemplate.SourcePath != "" {
processedTemplate, err = ProcessTemplate(secretTemplate.SourcePath, nil, token, existingEtag, &currentEtag)
} else {
processedTemplate, err = ProcessBase64Template(secretTemplate.Base64TemplateContent, nil, token, existingEtag, &currentEtag)
}
if err != nil {
log.Error().Msgf("unable to process template because %v", err)
} else {
if (existingEtag != currentEtag) || firstRun {
tm.WriteTemplateToFile(processedTemplate, &secretTemplate)
existingEtag = currentEtag
if !firstRun && execCommand != "" {
log.Info().Msgf("executing command: %s", execCommand)
err := ExecuteCommandWithTimeout(execCommand, execTimeout)
if err != nil {
log.Error().Msgf("unable to execute command because %v", err)
}
}
if firstRun {
firstRun = false
}
for _, secretTemplate := range tm.templates {
var processedTemplate *bytes.Buffer
var err error
if secretTemplate.SourcePath != "" {
processedTemplate, err = ProcessTemplate(secretTemplate.SourcePath, nil, token)
} else {
processedTemplate, err = ProcessBase64Template(secretTemplate.Base64TemplateContent, nil, token)
}
}
time.Sleep(pollingInterval)
} else {
// It fails to get the access token. So we will re-try in 3 seconds. We do this because if we don't, the user will have to wait for the next polling interval to get the first secret render.
time.Sleep(3 * time.Second)
}
if err != nil {
log.Error().Msgf("template engine: unable to render secrets because %s. Will try again on next cycle", err)
continue
}
if err := WriteBytesToFile(processedTemplate, secretTemplate.DestinationPath); err != nil {
log.Error().Msgf("template engine: unable to write secrets to path because %s. Will try again on next cycle", err)
continue
}
log.Info().Msgf("template engine: secret template at path %s has been rendered and saved to path %s", secretTemplate.SourcePath, secretTemplate.DestinationPath)
}
// fetch new secrets every 5 minutes (TODO: add PubSub in the future )
time.Sleep(5 * time.Minute)
}
}
}
@@ -646,11 +544,7 @@ var agentCmd = &cobra.Command{
tm := NewTokenManager(filePaths, agentConfig.Templates, configUniversalAuthType.ClientIDPath, configUniversalAuthType.ClientSecretPath, tokenRefreshNotifier, configUniversalAuthType.RemoveClientSecretOnRead, agentConfig.Infisical.ExitAfterAuth)
go tm.ManageTokenLifecycle()
for i, template := range agentConfig.Templates {
log.Info().Msgf("template engine started for template %v...", i+1)
go tm.MonitorSecretChanges(template, sigChan)
}
go tm.FetchSecrets()
for {
select {

View File

@@ -34,11 +34,6 @@ type SingleEnvironmentVariable struct {
Comment string `json:"comment"`
}
type PlaintextSecretResult struct {
Secrets []SingleEnvironmentVariable
Etag string
}
type SingleFolder struct {
ID string `json:"_id"`
Name string `json:"name"`

View File

@@ -1,41 +0,0 @@
package util
import (
"fmt"
"strconv"
"time"
)
// ConvertPollingIntervalToTime converts a string representation of a polling interval to a time.Duration
func ConvertPollingIntervalToTime(pollingInterval string) (time.Duration, error) {
length := len(pollingInterval)
if length < 2 {
return 0, fmt.Errorf("invalid format")
}
unit := pollingInterval[length-1:]
numberPart := pollingInterval[:length-1]
number, err := strconv.Atoi(numberPart)
if err != nil {
return 0, err
}
switch unit {
case "s":
if number < 60 {
return 0, fmt.Errorf("polling interval should be at least 60 seconds")
}
return time.Duration(number) * time.Second, nil
case "m":
return time.Duration(number) * time.Minute, nil
case "h":
return time.Duration(number) * time.Hour, nil
case "d":
return time.Duration(number) * 24 * time.Hour, nil
case "w":
return time.Duration(number) * 7 * 24 * time.Hour, nil
default:
return 0, fmt.Errorf("invalid time unit")
}
}

View File

@@ -152,7 +152,7 @@ func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, work
return plainTextSecrets, nil
}
func GetPlainTextSecretsViaMachineIdentity(accessToken string, workspaceId string, environmentName string, secretsPath string, includeImports bool) (models.PlaintextSecretResult, error) {
func GetPlainTextSecretsViaMachineIdentity(accessToken string, workspaceId string, environmentName string, secretsPath string, includeImports bool) ([]models.SingleEnvironmentVariable, error) {
httpClient := resty.New()
httpClient.SetAuthToken(accessToken).
SetHeader("Accept", "application/json")
@@ -170,12 +170,12 @@ func GetPlainTextSecretsViaMachineIdentity(accessToken string, workspaceId strin
rawSecrets, err := api.CallGetRawSecretsV3(httpClient, api.GetRawSecretsV3Request{WorkspaceId: workspaceId, SecretPath: secretsPath, Environment: environmentName})
if err != nil {
return models.PlaintextSecretResult{}, err
return nil, err
}
plainTextSecrets := []models.SingleEnvironmentVariable{}
if err != nil {
return models.PlaintextSecretResult{}, fmt.Errorf("unable to decrypt your secrets [err=%v]", err)
return nil, fmt.Errorf("unable to decrypt your secrets [err=%v]", err)
}
for _, secret := range rawSecrets.Secrets {
@@ -189,10 +189,7 @@ func GetPlainTextSecretsViaMachineIdentity(accessToken string, workspaceId strin
// }
// }
return models.PlaintextSecretResult{
Secrets: plainTextSecrets,
Hash: rawSecrets.ETag,
}, nil
return plainTextSecrets, nil
}
func InjectImportedSecret(plainTextWorkspaceKey []byte, secrets []models.SingleEnvironmentVariable, importedSecrets []api.ImportedSecretV3) ([]models.SingleEnvironmentVariable, error) {

View File

@@ -14,6 +14,7 @@ The newly released Postgres version of Infisical is the only version of Infisica
Before starting the migration, ensure you have the following command line tools installed:
- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
- [pg_dump](https://www.postgresql.org/docs/current/app-pgrestore.html)
- [pg_restore](https://www.postgresql.org/docs/current/app-pgdump.html)
- [mongodump](https://www.mongodb.com/docs/database-tools/mongodump/)
@@ -103,7 +104,7 @@ Once started, the migration script will transform MongoDB data into an equivalen
<Step title="Clone Infisical Repository">
Clone the Infisical MongoDB repository.
```
git clone https://github.com/Infisical/infisical.git
git clone -b infisical/v0.46.7-postgres https://github.com/Infisical/infisical.git
```
</Step>
<Step title="Install dependencies for backend">
@@ -186,9 +187,14 @@ Rather than transferring the data row-by-row from your local machine to the prod
## Post-Migration Steps
After successfully migrating the data to PostgreSQL, you can proceed to deploy Infisical using your preferred deployment method.
Refer to [Infisical's self-hosting documentation](https://infisical.com/docs/self-hosting/overview) for deployment options.
Remember to use your production PostgreSQL connection string for the new deployment and transfer all [environment variables](/self-hosting/configuration/envars) from the MongoDB version of Infisical to the new version (they are all compatible).
Once the data migration to PostgreSQL is complete, you're ready to deploy Infisical using the deployment method of your choice.
For guidance on deployment options, please visit the [self-hosting documentation](/self-hosting/overview).
Remember to transfer the necessary [environment variables](/self-hosting/configuration/envars) from the MongoDB version of Infisical to the new Postgres based Infisical; rest assured, they are fully compatible.
<Warning>
The first deployment of Postgres based Infisical must be deployed with Docker image tag `v0.46.7-postgres`.
After deploying this version, you can proceed to update to any subsequent versions.
</Warning>
## Additional discussion
- When you visit Infisical's [docker hub](https://hub.docker.com/r/infisical/infisical) page, you will notice that image tags end with `-postgres`.

View File

@@ -1,10 +1,12 @@
import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import axios from "axios";
import queryString from "query-string";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
import { useCreateIntegration, useGetWorkspaceById } from "@app/hooks/api";
import { Button, Card, CardTitle, FormControl, Select, SelectItem } from "../../../components/v2";
import { Button, Card, CardTitle, FormControl, Input, Select, SelectItem } from "../../../components/v2";
import {
useGetIntegrationAuthApps,
useGetIntegrationAuthById
@@ -13,6 +15,7 @@ import {
export default function CloudflareWorkersIntegrationPage() {
const router = useRouter();
const { mutateAsync } = useCreateIntegration();
const { createNotification } = useNotificationContext();
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
@@ -22,6 +25,8 @@ export default function CloudflareWorkersIntegrationPage() {
});
const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState("");
const [secretPath, setSecretPath] = useState("/");
const [targetApp, setTargetApp] = useState("");
const [targetAppId, setTargetAppId] = useState("");
@@ -56,7 +61,7 @@ export default function CloudflareWorkersIntegrationPage() {
app: targetApp,
appId: targetAppId,
sourceEnvironment: selectedSourceEnvironment,
secretPath: "/"
secretPath
});
setIsLoading(false);
@@ -64,6 +69,18 @@ export default function CloudflareWorkersIntegrationPage() {
router.push(`/integrations/${localStorage.getItem("projectData.id")}`);
} catch (err) {
console.error(err);
let errorMessage: string = "Something went wrong!";
if (axios.isAxiosError(err)) {
const { message } = err?.response?.data as { message: string };
errorMessage = message;
}
createNotification({
text: errorMessage,
type: "error"
});
setIsLoading(false);
}
};
@@ -96,6 +113,13 @@ export default function CloudflareWorkersIntegrationPage() {
))}
</Select>
</FormControl>
<FormControl label="Infisical Secret Path" className="mt-2 px-6">
<Input
value={secretPath}
onChange={(evt) => setSecretPath(evt.target.value)}
placeholder="Provide a path, default is /"
/>
</FormControl>
<FormControl label="Cloudflare Workers Project" className="mt-4 px-6">
<Select
value={targetApp}

View File

@@ -7,7 +7,7 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 1.0.5
version: 1.0.6
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to

View File

@@ -13,8 +13,9 @@ metadata:
name: default
subjects:
- kind: ServiceAccount
name: {{ .Release.Namespace }}
name: default
namespace: {{ .Release.Namespace }}
roleRef:
kind: Role
name: k8s-wait-for-infisical-schema-migration
apiGroup: rbac.authorization.k8s.io
apiGroup: rbac.authorization.k8s.io

View File

@@ -532,9 +532,8 @@ const main = async () => {
postgresTableName: TableName.SuperAdmin,
returnKeys: ["id"],
preProcessing: async (doc) => {
const id = uuidV4();
return {
id,
id: "00000000-0000-0000-0000-000000000000",
allowSignUp: doc.allowSignUp,
initialized: doc.initialized,
createdAt: new Date((doc as any).createdAt),