mirror of
https://github.com/Infisical/infisical.git
synced 2025-08-31 15:32:32 +00:00
Compare commits
16 Commits
daniel/mi-
...
infisical/
Author | SHA1 | Date | |
---|---|---|---|
|
c8c5caba62 | ||
|
f408a6f60c | ||
|
391ed0ed74 | ||
|
aef40212d2 | ||
|
5aa7cd46c1 | ||
|
6c0b916ad8 | ||
|
d7bc80308d | ||
|
b7c7b242e8 | ||
|
37827367ed | ||
|
403b1ce993 | ||
|
b64672a921 | ||
|
227e013502 | ||
|
d2a93eb1d2 | ||
|
203e00216f | ||
|
7a3a6663f1 | ||
|
115b4664bf |
@@ -50,7 +50,7 @@ jobs:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
build-args: |
|
||||
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
|
||||
INFISICAL_PLATFORM_VERSION=${{ steps.extract_version.outputs.version }}
|
||||
INFISICAL_PLATFORM_VERSION=${{ steps.commit.outputs.short }}
|
||||
|
||||
gamma-deployment:
|
||||
name: Deploy to gamma
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
with:
|
||||
audience: sts.amazonaws.com
|
||||
aws-region: us-east-1
|
||||
role-to-assume: arn:aws:iam::135906656851:role/github-action-deploy-prod
|
||||
role-to-assume: arn:aws:iam::905418227878:role/deploy-new-ecs-img
|
||||
- name: Save commit hashes for tag
|
||||
id: commit
|
||||
uses: pr-mpt/actions-commit-hash@v2
|
||||
@@ -125,7 +125,7 @@ jobs:
|
||||
with:
|
||||
audience: sts.amazonaws.com
|
||||
aws-region: us-east-1
|
||||
role-to-assume: arn:aws:iam::135906656851:role/github-action-deploy-prod
|
||||
role-to-assume: arn:aws:iam::905418227878:role/deploy-new-ecs-img
|
||||
- name: Save commit hashes for tag
|
||||
id: commit
|
||||
uses: pr-mpt/actions-commit-hash@v2
|
||||
|
@@ -406,14 +406,14 @@ func CallDeleteSecretsV3(httpClient *resty.Client, request DeleteSecretV3Request
|
||||
return nil
|
||||
}
|
||||
|
||||
func CallUpdateSecretsV3(httpClient *resty.Client, request UpdateSecretByNameV3Request) error {
|
||||
func CallUpdateSecretsV3(httpClient *resty.Client, request UpdateSecretByNameV3Request, secretName string) error {
|
||||
var secretsResponse GetEncryptedSecretsV3Response
|
||||
response, err := httpClient.
|
||||
R().
|
||||
SetResult(&secretsResponse).
|
||||
SetHeader("User-Agent", USER_AGENT).
|
||||
SetBody(request).
|
||||
Patch(fmt.Sprintf("%v/v3/secrets/%s", config.INFISICAL_URL, request.SecretName))
|
||||
Patch(fmt.Sprintf("%v/v3/secrets/%s", config.INFISICAL_URL, secretName))
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("CallUpdateSecretsV3: Unable to complete api request [err=%s]", err)
|
||||
|
@@ -401,7 +401,6 @@ type DeleteSecretV3Request struct {
|
||||
}
|
||||
|
||||
type UpdateSecretByNameV3Request struct {
|
||||
SecretName string `json:"secretName"`
|
||||
WorkspaceID string `json:"workspaceId"`
|
||||
Environment string `json:"environment"`
|
||||
Type string `json:"type"`
|
||||
|
@@ -297,7 +297,6 @@ var secretsSetCmd = &cobra.Command{
|
||||
updateSecretRequest := api.UpdateSecretByNameV3Request{
|
||||
WorkspaceID: workspaceFile.WorkspaceId,
|
||||
Environment: environmentName,
|
||||
SecretName: secret.PlainTextKey,
|
||||
SecretValueCiphertext: secret.SecretValueCiphertext,
|
||||
SecretValueIV: secret.SecretValueIV,
|
||||
SecretValueTag: secret.SecretValueTag,
|
||||
@@ -305,7 +304,7 @@ var secretsSetCmd = &cobra.Command{
|
||||
SecretPath: secretsPath,
|
||||
}
|
||||
|
||||
err = api.CallUpdateSecretsV3(httpClient, updateSecretRequest)
|
||||
err = api.CallUpdateSecretsV3(httpClient, updateSecretRequest, secret.PlainTextKey)
|
||||
if err != nil {
|
||||
util.HandleError(err, "Unable to process secret update request")
|
||||
return
|
||||
|
@@ -21,13 +21,13 @@ const syntaxHighlight = (content?: string | null, isVisible?: boolean, isImport?
|
||||
if (!isVisible) return replaceContentWithDot(content);
|
||||
|
||||
let skipNext = false;
|
||||
const formatedContent = content.split(REGEX).flatMap((el, i) => {
|
||||
const formattedContent = content.split(REGEX).flatMap((el, i) => {
|
||||
const isInterpolationSyntax = el.startsWith("${") && el.endsWith("}");
|
||||
if (isInterpolationSyntax) {
|
||||
skipNext = true;
|
||||
return (
|
||||
<span className="ph-no-capture text-yellow" key={`secret-value-${i + 1}`}>
|
||||
${<span className="ph-no-capture text-yello-200/80">{el.slice(2, -1)}</span>
|
||||
${<span className="ph-no-capture text-yellow-200/80">{el.slice(2, -1)}</span>
|
||||
}
|
||||
</span>
|
||||
);
|
||||
@@ -41,7 +41,7 @@ const syntaxHighlight = (content?: string | null, isVisible?: boolean, isImport?
|
||||
|
||||
// akhilmhdh: Dont remove this br. I am still clueless how this works but weirdly enough
|
||||
// when break is added a line break works properly
|
||||
return formatedContent.concat(<br />);
|
||||
return formattedContent.concat(<br />);
|
||||
};
|
||||
|
||||
type Props = TextareaHTMLAttributes<HTMLTextAreaElement> & {
|
||||
|
@@ -41,7 +41,7 @@ export const Select = forwardRef<HTMLButtonElement, SelectProps>(
|
||||
ref={ref}
|
||||
className={twMerge(
|
||||
`inline-flex items-center justify-between rounded-md
|
||||
bg-mineshaft-900 px-3 py-2 font-inter text-sm font-normal text-bunker-200 outline-none data-[placeholder]:text-mineshaft-200`,
|
||||
bg-mineshaft-900 px-3 py-2 font-inter text-sm font-normal text-bunker-200 outline-none data-[placeholder]:text-mineshaft-200 focus:bg-mineshaft-700/80`,
|
||||
className
|
||||
)}
|
||||
>
|
||||
@@ -106,7 +106,7 @@ export const SelectItem = forwardRef<HTMLDivElement, SelectItemProps>(
|
||||
className={twMerge(
|
||||
`relative mb-0.5 flex
|
||||
cursor-pointer select-none items-center rounded-md py-2 pl-10 pr-4 text-sm
|
||||
outline-none transition-all hover:bg-mineshaft-500`,
|
||||
outline-none transition-all hover:bg-mineshaft-500 data-[highlighted]:bg-mineshaft-700/80`,
|
||||
isSelected && "bg-primary",
|
||||
isDisabled &&
|
||||
"cursor-not-allowed text-gray-600 hover:bg-transparent hover:text-mineshaft-600",
|
||||
|
@@ -9,16 +9,22 @@ import { useNotificationContext } from "@app/components/context/Notifications/No
|
||||
import { useProjectPermission } from "@app/context";
|
||||
import { useGetUpgradeProjectStatus, useUpgradeProject } from "@app/hooks/api";
|
||||
import { Workspace } from "@app/hooks/api/types";
|
||||
import { workspaceKeys } from "@app/hooks/api/workspace/queries";
|
||||
import { ProjectVersion } from "@app/hooks/api/workspace/types";
|
||||
import { queryClient } from "@app/reactQuery";
|
||||
|
||||
import { Button } from "../Button";
|
||||
import { Tooltip } from "../Tooltip";
|
||||
|
||||
export type UpgradeProjectAlertProps = {
|
||||
project: Workspace;
|
||||
transparent?: boolean;
|
||||
};
|
||||
|
||||
export const UpgradeProjectAlert = ({ project }: UpgradeProjectAlertProps): JSX.Element | null => {
|
||||
export const UpgradeProjectAlert = ({
|
||||
project,
|
||||
transparent
|
||||
}: UpgradeProjectAlertProps): JSX.Element | null => {
|
||||
const { createNotification } = useNotificationContext();
|
||||
const router = useRouter();
|
||||
const { membership } = useProjectPermission();
|
||||
@@ -48,6 +54,7 @@ export const UpgradeProjectAlert = ({ project }: UpgradeProjectAlertProps): JSX.
|
||||
}
|
||||
|
||||
if (currentStatus !== null && data?.status === null) {
|
||||
queryClient.invalidateQueries(workspaceKeys.getAllUserWorkspace);
|
||||
router.reload();
|
||||
}
|
||||
}
|
||||
@@ -87,10 +94,25 @@ export const UpgradeProjectAlert = ({ project }: UpgradeProjectAlertProps): JSX.
|
||||
|
||||
if (project.version !== ProjectVersion.V1) return null;
|
||||
|
||||
if (transparent) {
|
||||
return (
|
||||
<Button
|
||||
colorSchema="primary"
|
||||
variant="solid"
|
||||
size="md"
|
||||
isLoading={isLoading}
|
||||
isDisabled={isLoading || membership.role !== "admin"}
|
||||
onClick={onUpgradeProject}
|
||||
>
|
||||
Upgrade
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={twMerge(
|
||||
"mt-4 flex w-full flex-row items-center rounded-md border border-primary-600/70 bg-primary/[.07] p-4 text-base text-white",
|
||||
"mt-4 flex w-full flex-row items-center rounded-md border border-primary-600/70 bg-primary/[.07] p-4 text-base text-white",
|
||||
membership.role !== "admin" && "opacity-80"
|
||||
)}
|
||||
>
|
||||
|
@@ -1,10 +1,19 @@
|
||||
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
|
||||
@@ -18,8 +27,10 @@ const cloudflareEnvironments = [
|
||||
export default function CloudflarePagesIntegrationPage() {
|
||||
const router = useRouter();
|
||||
const { mutateAsync } = useCreateIntegration();
|
||||
const { createNotification } = useNotificationContext();
|
||||
|
||||
const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]);
|
||||
const [secretPath, setSecretPath] = useState("/");
|
||||
const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? "");
|
||||
const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? "");
|
||||
const { data: integrationAuthApps } = useGetIntegrationAuthApps({
|
||||
@@ -65,7 +76,7 @@ export default function CloudflarePagesIntegrationPage() {
|
||||
appId: targetAppId,
|
||||
sourceEnvironment: selectedSourceEnvironment,
|
||||
targetEnvironment,
|
||||
secretPath: "/"
|
||||
secretPath
|
||||
});
|
||||
|
||||
setIsLoading(false);
|
||||
@@ -73,6 +84,18 @@ export default function CloudflarePagesIntegrationPage() {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -106,6 +129,13 @@ export default function CloudflarePagesIntegrationPage() {
|
||||
))}
|
||||
</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 Pages Project" className="mt-4 px-6">
|
||||
<Select
|
||||
value={targetApp}
|
||||
|
@@ -1,121 +1,36 @@
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import {
|
||||
decryptAssymmetric,
|
||||
encryptAssymmetric
|
||||
} from "@app/components/utilities/cryptography/crypto";
|
||||
import { Alert, AlertDescription, Checkbox } from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { useGetUserWsKey, useGetWorkspaceBot, useUpdateBotActiveStatus } from "@app/hooks/api";
|
||||
import Link from "next/link";
|
||||
|
||||
import { UpgradeProjectAlert } from "@app/components/v2/UpgradeProjectAlert";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useGetWorkspaceBot } from "@app/hooks/api";
|
||||
import { ProjectVersion } from "@app/hooks/api/workspace/types";
|
||||
|
||||
export const E2EESection = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { data: bot } = useGetWorkspaceBot(currentWorkspace?.id ?? "");
|
||||
const { mutateAsync: updateBotActiveStatus } = useUpdateBotActiveStatus();
|
||||
const { data: wsKey } = useGetUserWsKey(currentWorkspace?.id ?? "");
|
||||
|
||||
/**
|
||||
* Activate bot for project by performing the following steps:
|
||||
* 1. Get the (encrypted) project key
|
||||
* 2. Decrypt project key with user's private key
|
||||
* 3. Encrypt project key with bot's public key
|
||||
* 4. Send encrypted project key to backend and set bot status to active
|
||||
*/
|
||||
|
||||
const toggleBotActivate = async () => {
|
||||
let botKey;
|
||||
try {
|
||||
if (!currentWorkspace?.id) return;
|
||||
|
||||
if (bot && wsKey) {
|
||||
// case: there is a bot
|
||||
|
||||
if (!bot.isActive) {
|
||||
// bot is not active -> activate bot
|
||||
|
||||
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY");
|
||||
|
||||
if (!PRIVATE_KEY) {
|
||||
throw new Error("Private Key missing");
|
||||
}
|
||||
|
||||
const WORKSPACE_KEY = decryptAssymmetric({
|
||||
ciphertext: wsKey.encryptedKey,
|
||||
nonce: wsKey.nonce,
|
||||
publicKey: wsKey.sender.publicKey,
|
||||
privateKey: PRIVATE_KEY
|
||||
});
|
||||
|
||||
const { ciphertext, nonce } = encryptAssymmetric({
|
||||
plaintext: WORKSPACE_KEY,
|
||||
publicKey: bot.publicKey,
|
||||
privateKey: PRIVATE_KEY
|
||||
});
|
||||
|
||||
botKey = {
|
||||
encryptedKey: ciphertext,
|
||||
nonce
|
||||
};
|
||||
|
||||
await updateBotActiveStatus({
|
||||
workspaceId: currentWorkspace.id,
|
||||
botKey,
|
||||
isActive: true,
|
||||
botId: bot.id
|
||||
});
|
||||
} else {
|
||||
// bot is active -> deactivate bot
|
||||
await updateBotActiveStatus({
|
||||
isActive: false,
|
||||
botId: bot.id,
|
||||
workspaceId: currentWorkspace.id
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
if (!currentWorkspace) return null;
|
||||
|
||||
return bot && currentWorkspace.version === ProjectVersion.V1 ? (
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<p className="mb-3 text-xl font-semibold">End-to-End Encryption</p>
|
||||
<p className="mb-8 text-gray-400">
|
||||
Disabling, end-to-end encryption (E2EE) unlocks capabilities like native integrations to
|
||||
cloud providers as well as HTTP calls to get secrets back raw but enables the server to
|
||||
read/decrypt your secret values.
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<p className="text-xl font-semibold">End-to-End Encryption</p>
|
||||
<UpgradeProjectAlert transparent project={currentWorkspace} />
|
||||
</div>
|
||||
|
||||
<p className="mt-5 max-w-2xl text-sm text-gray-400">
|
||||
We are updating our encryption logic to make sure that Infisical can be the most versatile
|
||||
secret management platform. <br />
|
||||
<br />
|
||||
Upgrading the project version is required to continue receiving the latest improvements and
|
||||
patches.
|
||||
</p>
|
||||
<p className="mb-8 text-gray-400">
|
||||
Note that, even with E2EE disabled, your secrets are always encrypted at rest.
|
||||
</p>
|
||||
<ProjectPermissionCan I={ProjectPermissionActions.Edit} a={ProjectPermissionSub.Settings}>
|
||||
{(isAllowed) => (
|
||||
<div className="flex w-full flex-col gap-y-3">
|
||||
<div className="w-max">
|
||||
<Checkbox
|
||||
className="data-[state=checked]:bg-primary"
|
||||
id="end-to-end-encryption"
|
||||
isChecked={!bot.isActive}
|
||||
isDisabled={!isAllowed}
|
||||
onCheckedChange={async () => {
|
||||
await toggleBotActivate();
|
||||
}}
|
||||
>
|
||||
End-to-end encryption enabled
|
||||
</Checkbox>
|
||||
</div>
|
||||
<div>
|
||||
<Alert variant="warning">
|
||||
<AlertDescription>
|
||||
Enabling End-to-end encryption disables all the integrations
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
|
||||
<Link href="https://infisical.com/docs/documentation/platform/project-upgrade">
|
||||
<a target="_blank" className="text-sm text-primary-400">
|
||||
Learn more about project upgrades
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
) : (
|
||||
<div />
|
||||
|
@@ -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.6
|
||||
version: 1.0.7
|
||||
|
||||
# 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
|
||||
|
@@ -24,7 +24,7 @@ infisical:
|
||||
|
||||
resources:
|
||||
limits:
|
||||
memory: 350Mi
|
||||
memory: 600Mi
|
||||
requests:
|
||||
cpu: 350m
|
||||
|
||||
|
Reference in New Issue
Block a user