Compare commits

...

16 Commits

Author SHA1 Message Date
Maidul Islam
c8c5caba62 Update Chart.yaml 2024-03-25 13:48:17 -04:00
Maidul Islam
f408a6f60c Update values.yaml 2024-03-25 13:48:01 -04:00
Maidul Islam
391ed0ed74 Update build-staging-and-deploy-aws.yml 2024-03-25 11:15:39 -04:00
Daniel Hougaard
aef40212d2 Merge pull request #1528 from rhythmbhiwani/cli-fix-update-vars
Fixed CLI issue of updating variables using `infisical secrets set`
2024-03-25 15:30:47 +01:00
Akhil Mohan
5aa7cd46c1 Merge pull request #1594 from Salman2301/feat-cloudflare-secret-path
feat: add support for secret path for cloudflare page
2024-03-25 11:37:00 +05:30
Maidul Islam
6c0b916ad8 set version to short commit sha 2024-03-25 01:54:53 -04:00
Akhil Mohan
d7bc80308d Merge pull request #1566 from Salman2301/fix-typo-input
fix class name typo
2024-03-25 11:14:55 +05:30
Akhil Mohan
b7c7b242e8 Merge pull request #1578 from Salman2301/fix-select-key-nav
fix: add highlighted style for select component
2024-03-25 11:13:48 +05:30
Maidul Islam
37827367ed Merge pull request #1622 from Infisical/daniel/mi-project-creation-bug
Fix: Creating projects with Machine Identities that aren't org admins
2024-03-24 14:46:23 -04:00
Maidul Islam
403b1ce993 Merge pull request #1620 from Infisical/daniel/e2ee-button
Feat: Deprecate E2EE mode switching
2024-03-24 14:33:44 -04:00
Daniel Hougaard
b64672a921 Update E2EESection.tsx 2024-03-22 19:33:53 +01:00
Daniel Hougaard
227e013502 Feat: Deprecate E2EE mode switching 2024-03-22 19:31:41 +01:00
Salman
d2a93eb1d2 feat: add support for secret path for cloudflare page 2024-03-18 21:31:21 +05:30
Salman
203e00216f fix: add highlighted style for select component 2024-03-16 17:53:48 +05:30
Salman
7a3a6663f1 fix class name typo 2024-03-14 03:37:54 +05:30
Rhythm Bhiwani
115b4664bf Fixed CLI issue of updating variables using infisical secrets set 2024-03-05 03:43:06 +05:30
11 changed files with 91 additions and 126 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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"`

View File

@@ -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

View File

@@ -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}`}>
&#36;&#123;<span className="ph-no-capture text-yello-200/80">{el.slice(2, -1)}</span>
&#36;&#123;<span className="ph-no-capture text-yellow-200/80">{el.slice(2, -1)}</span>
&#125;
</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> & {

View File

@@ -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",

View File

@@ -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"
)}
>

View File

@@ -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}

View File

@@ -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 />

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.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

View File

@@ -24,7 +24,7 @@ infisical:
resources:
limits:
memory: 350Mi
memory: 600Mi
requests:
cpu: 350m