diff --git a/.github/workflows/release_docker_k8_operator.yaml b/.github/workflows/release_docker_k8_operator.yaml
index 788d414b6..517549ea8 100644
--- a/.github/workflows/release_docker_k8_operator.yaml
+++ b/.github/workflows/release_docker_k8_operator.yaml
@@ -1,10 +1,16 @@
-name: Release Docker image for K8 operator
-on: [workflow_dispatch]
+name: Release Docker image for K8 operator
+on:
+ push:
+ tags:
+ - "infisical-k8-operator/v*.*.*"
jobs:
release:
runs-on: ubuntu-latest
steps:
+ - name: Extract version from tag
+ id: extract_version
+ run: echo "::set-output name=version::${GITHUB_REF_NAME#infisical-k8-operator/}"
- uses: actions/checkout@v2
- name: 🔧 Set up QEMU
@@ -26,4 +32,6 @@ jobs:
context: k8-operator
push: true
platforms: linux/amd64,linux/arm64
- tags: infisical/kubernetes-operator:latest
\ No newline at end of file
+ tags: |
+ infisical/kubernetes-operator:latest
+ infisical/kubernetes-operator:${{ steps.extract_version.outputs.version }}
diff --git a/backend/src/ee/controllers/v1/organizationsController.ts b/backend/src/ee/controllers/v1/organizationsController.ts
index fb13a6575..652fc4b32 100644
--- a/backend/src/ee/controllers/v1/organizationsController.ts
+++ b/backend/src/ee/controllers/v1/organizationsController.ts
@@ -27,6 +27,30 @@ export const getOrganizationPlan = async (req: Request, res: Response) => {
});
}
+/**
+ * Return checkout url for pro trial
+ * @param req
+ * @param res
+ * @returns
+ */
+export const startOrganizationTrial = async (req: Request, res: Response) => {
+ const { organizationId } = req.params;
+ const { success_url } = req.body;
+
+ const { data: { url } } = await licenseServerKeyRequest.post(
+ `${await getLicenseServerUrl()}/api/license-server/v1/customers/${req.organization.customerId}/session/trial`,
+ {
+ success_url
+ }
+ );
+
+ EELicenseService.delPlan(organizationId);
+
+ return res.status(200).send({
+ url
+ });
+}
+
/**
* Return the organization's current plan's billing info
* @param req
diff --git a/backend/src/ee/routes/v1/organizations.ts b/backend/src/ee/routes/v1/organizations.ts
index 37be3a96d..c9104d964 100644
--- a/backend/src/ee/routes/v1/organizations.ts
+++ b/backend/src/ee/routes/v1/organizations.ts
@@ -41,6 +41,21 @@ router.get(
organizationsController.getOrganizationPlan
);
+router.post(
+ "/:organizationId/session/trial",
+ requireAuth({
+ acceptedAuthModes: ["jwt"],
+ }),
+ requireOrganizationAuth({
+ acceptedRoles: [OWNER, ADMIN, MEMBER],
+ acceptedStatuses: [ACCEPTED],
+ }),
+ param("organizationId").exists().trim(),
+ body("success_url").exists().trim(),
+ validateRequest,
+ organizationsController.startOrganizationTrial
+);
+
router.get(
"/:organizationId/plan/billing",
requireAuth({
diff --git a/backend/src/ee/services/EELicenseService.ts b/backend/src/ee/services/EELicenseService.ts
index b4bb97753..88220933d 100644
--- a/backend/src/ee/services/EELicenseService.ts
+++ b/backend/src/ee/services/EELicenseService.ts
@@ -32,6 +32,7 @@ interface FeatureSet {
auditLogs: boolean;
status: 'incomplete' | 'incomplete_expired' | 'trialing' | 'active' | 'past_due' | 'canceled' | 'unpaid' | null;
trial_end: number | null;
+ has_used_trial: boolean;
}
/**
@@ -63,7 +64,8 @@ class EELicenseService {
customAlerts: true,
auditLogs: false,
status: null,
- trial_end: null
+ trial_end: null,
+ has_used_trial: true
}
public localFeatureSet: NodeCache;
@@ -71,7 +73,7 @@ class EELicenseService {
constructor() {
this._isLicenseValid = true;
this.localFeatureSet = new NodeCache({
- stdTTL: 300,
+ stdTTL: 60,
});
}
@@ -112,6 +114,12 @@ class EELicenseService {
await this.getPlan(organizationId, workspaceId);
}
}
+
+ public async delPlan(organizationId: string) {
+ if (this.instanceType === "cloud") {
+ this.localFeatureSet.del(`${organizationId}-`);
+ }
+ }
public async initGlobalFeatureSet() {
const licenseServerKey = await getLicenseServerKey();
diff --git a/backend/src/services/smtp.ts b/backend/src/services/smtp.ts
index 4bd58020b..b067d499a 100644
--- a/backend/src/services/smtp.ts
+++ b/backend/src/services/smtp.ts
@@ -2,9 +2,10 @@ import nodemailer from "nodemailer";
import {
SMTP_HOST_GMAIL,
SMTP_HOST_MAILGUN,
+ SMTP_HOST_OFFICE365,
SMTP_HOST_SENDGRID,
SMTP_HOST_SOCKETLABS,
- SMTP_HOST_ZOHOMAIL,
+ SMTP_HOST_ZOHOMAIL
} from "../variables";
import SMTPConnection from "nodemailer/lib/smtp-connection";
import * as Sentry from "@sentry/node";
@@ -15,6 +16,7 @@ import {
getSmtpSecure,
getSmtpUsername,
} from "../config";
+import { getLogger } from "../utils/logger";
export const initSmtp = async () => {
const mailOpts: SMTPConnection.Options = {
@@ -58,6 +60,12 @@ export const initSmtp = async () => {
ciphers: "TLSv1.2",
}
break;
+ case SMTP_HOST_OFFICE365:
+ mailOpts.requireTLS = true;
+ mailOpts.tls = {
+ ciphers: "TLSv1.2"
+ }
+ break;
default:
if ((await getSmtpHost()).includes("amazonaws.com")) {
mailOpts.tls = {
@@ -73,10 +81,12 @@ export const initSmtp = async () => {
const transporter = nodemailer.createTransport(mailOpts);
transporter
.verify()
- .then((err) => {
+ .then(async () => {
Sentry.setUser(null);
Sentry.captureMessage("SMTP - Successfully connected");
- console.log("SMTP - Successfully connected")
+ (await getLogger("backend-main")).info(
+ "SMTP - Successfully connected"
+ );
})
.catch(async (err) => {
Sentry.setUser(null);
diff --git a/backend/src/variables/smtp.ts b/backend/src/variables/smtp.ts
index 8a0e752eb..4ad68c356 100644
--- a/backend/src/variables/smtp.ts
+++ b/backend/src/variables/smtp.ts
@@ -3,3 +3,4 @@ export const SMTP_HOST_MAILGUN = "smtp.mailgun.org";
export const SMTP_HOST_SOCKETLABS = "smtp.socketlabs.com";
export const SMTP_HOST_ZOHOMAIL = "smtp.zoho.com";
export const SMTP_HOST_GMAIL = "smtp.gmail.com";
+export const SMTP_HOST_OFFICE365 = "smtp.office365.com";
\ No newline at end of file
diff --git a/cli/packages/api/api.go b/cli/packages/api/api.go
index a94be0ab0..5afec6782 100644
--- a/cli/packages/api/api.go
+++ b/cli/packages/api/api.go
@@ -246,7 +246,11 @@ func CallGetSecretsV3(httpClient *resty.Client, request GetEncryptedSecretsV3Req
}
if response.IsError() {
- return GetEncryptedSecretsV3Response{}, fmt.Errorf("CallGetSecretsV3: Unsuccessful response. Please make sure your secret path, workspace and environment name are all correct [response=%s]", response)
+ if response.StatusCode() == 401 {
+ return GetEncryptedSecretsV3Response{}, fmt.Errorf("CallGetSecretsV3: Request to access secrets with [environment=%v] [path=%v] [workspaceId=%v] is denied. Please check if your authentication method has access to requested scope", request.Environment, request.SecretPath, request.WorkspaceId)
+ } else {
+ return GetEncryptedSecretsV3Response{}, fmt.Errorf("CallGetSecretsV3: Unsuccessful response. Please make sure your secret path, workspace and environment name are all correct [response=%v]", response.RawResponse)
+ }
}
return secretsResponse, nil
diff --git a/cli/packages/cmd/login.go b/cli/packages/cmd/login.go
index c629130a4..f8d397233 100644
--- a/cli/packages/cmd/login.go
+++ b/cli/packages/cmd/login.go
@@ -73,7 +73,6 @@ var loginCmd = &cobra.Command{
return
}
}
-
//override domain
domainQuery := true
if config.INFISICAL_URL_MANUAL_OVERRIDE != "" && config.INFISICAL_URL_MANUAL_OVERRIDE != util.INFISICAL_DEFAULT_API_URL {
@@ -322,6 +321,8 @@ func DomainOverridePrompt() (bool, error) {
)
options := []string{PRESET, OVERRIDE}
+ //trim the '/' from the end of the domain url
+ config.INFISICAL_URL_MANUAL_OVERRIDE = strings.TrimRight(config.INFISICAL_URL_MANUAL_OVERRIDE, "/")
optionsPrompt := promptui.Select{
Label: fmt.Sprintf("Current INFISICAL_API_URL Domain Override: %s", config.INFISICAL_URL_MANUAL_OVERRIDE),
Items: options,
@@ -380,7 +381,8 @@ func askForDomain() error {
if err != nil {
return err
}
-
+ //trimmed the '/' from the end of the self hosting url
+ domain = strings.TrimRight(domain, "/")
//set api and login url
config.INFISICAL_URL = fmt.Sprintf("%s/api", domain)
config.INFISICAL_LOGIN_URL = fmt.Sprintf("%s/login", domain)
diff --git a/docs/changelog/overview.mdx b/docs/changelog/overview.mdx
index 7acab93c6..3ff0736f4 100644
--- a/docs/changelog/overview.mdx
+++ b/docs/changelog/overview.mdx
@@ -4,6 +4,21 @@ title: "Changelog"
The changelog below reflects new product developments and updates on a monthly basis; it will be updated later this quarter to include issues-addressed on a weekly basis.
+## July 2023
+
+- Released [secret referencing](https://infisical.com/docs/documentation/platform/secret-reference) across folders and environments.
+- Added the [intergation with Laravel Forge](https://infisical.com/docs/integrations/cloud/laravel-forge).
+- Redesigned the project/organization experience.
+
+## June 2023
+
+- Released the [Terraform Provider](https://infisical.com/docs/integrations/frameworks/terraform#5-run-terraform).
+- Updated the usage and billing page. Added the free trial for the professional tier.
+- Added the intergation with [Checkly](https://infisical.com/docs/integrations/cloud/checkly), [Hashicorp Vault](https://infisical.com/docs/integrations/cloud/hashicorp-vault), and [Cloudflare Pages](https://infisical.com/docs/integrations/cloud/cloudflare-pages).
+- Comleted a penetration test with a `very good` result.
+- Added support for multi-line secrets.
+
+
## May 2023
- Released secret scanning capability for the CLI.
@@ -11,8 +26,7 @@ The changelog below reflects new product developments and updates on a monthly b
- Completed penetration test.
- Released new landing page.
- Started SOC 2 (Type II) compliance certification preparation.
-
-More coming soon.
+- Released new deployment options for Fly.io, Digital Ocean and Render.
## April 2023
@@ -107,4 +121,4 @@ More coming soon.
- Added search bar to dashboard to query for keys on client-side.
- Added capability to rename a project.
- Added user roles for projects.
-- Added incident contacts.
\ No newline at end of file
+- Added incident contacts.
diff --git a/docs/cli/commands/secrets.mdx b/docs/cli/commands/secrets.mdx
index a15829d5f..b3fab541b 100644
--- a/docs/cli/commands/secrets.mdx
+++ b/docs/cli/commands/secrets.mdx
@@ -99,13 +99,12 @@ $ infisical secrets set STRIPE_API_KEY=sjdgwkeudyjwe DOMAIN=example.com HASH=jeb
Default value: `dev`
- The `--path` flag indicates which project folder secrets will be injected from.
+ Used to select the project folder in which the secrets will be set. This is useful when creating new secrets under a particular path.
```bash
# Example
- infisical secrets set ... --path="/"
+ infisical secrets set DOMAIN=example.com --path="common/backend"
```
-
diff --git a/docs/contributing/overview.mdx b/docs/contributing/overview.mdx
index 76475862d..f73422388 100644
--- a/docs/contributing/overview.mdx
+++ b/docs/contributing/overview.mdx
@@ -30,7 +30,7 @@ If you're ever in doubt about whether or not a proposed feature aligns with Infi
## Writing and submitting code
Anyone can contribute code to Infisical. To get started, check out the [local development guide](/contributing/developing), make your changes, and submit a pull request to the main repository
-adhering to the [pull request guide](/).
+adhering to the [pull request guide](/contributing/pull-requests).
## Licensing
diff --git a/docs/integrations/frameworks/terraform.mdx b/docs/integrations/frameworks/terraform.mdx
index 0826a833e..2643ca5af 100644
--- a/docs/integrations/frameworks/terraform.mdx
+++ b/docs/integrations/frameworks/terraform.mdx
@@ -44,10 +44,17 @@ provider "infisical" {
### 3. Fetch Infisical Secrets
-Use the `infisical_secrets` data source to fetch your secrets. This is defined with an empty block `{}` as the provider automatically fetches all secrets associated with your service token.
+Use the `infisical_secrets` data source to fetch your secrets. In this block, you must set the `env_slug` and `folder_path` to scope the secrets you want.
+
+`env_slug` is the slug of the environment name. This slug name can be found under the project settings page on the Infisical dashboard.
+
+`folder_path` is the path to the folder in a given environment. The path `/` for root of the environment where as `/folder1` is the folder at the root of the environment.
```hcl main.tf
-data "infisical_secrets" "my-secrets" {}
+data "infisical_secrets" "my-secrets" {
+ env_slug = "dev"
+ folder_path = "/some-folder/another-folder"
+}
```
### 4. Define Outputs
diff --git a/docs/mint.json b/docs/mint.json
index 25db15c63..d1175c9e1 100644
--- a/docs/mint.json
+++ b/docs/mint.json
@@ -21,6 +21,10 @@
"to": "#F8B7BD"
}
},
+ "feedback": {
+ "suggestEdit": true,
+ "raiseIssue": true
+ },
"api": {
"baseUrl": ["https://app.infisical.com", "http://localhost:8080"],
"auth": {
diff --git a/docs/self-hosting/configuration/email.mdx b/docs/self-hosting/configuration/email.mdx
index 4c6e13a49..15797d73b 100644
--- a/docs/self-hosting/configuration/email.mdx
+++ b/docs/self-hosting/configuration/email.mdx
@@ -3,12 +3,12 @@ title: "Configure email service"
description: "How to configure your email when self-hosting Infisical."
---
-By default, the core functions of Infisical work without any email service configuration. Without email service, basic sign up/login and secret operations will function without any issue.
+By default, the core functions of Infisical work without any email service configuration. Without email service, basic sign up/login and secret operations will function without any issue.
However, the following functionality will be disabled.
-- Multi-factor authentication
+- Multi-factor authentication
- Sending invite links via email for projects to teammates
-- Sending alerts such as suspicious login attempts
+- Sending alerts such as suspicious login attempts
## General configuration
@@ -157,11 +157,30 @@ SMTP_FROM_NAME=Infisical
As per the [notice](https://support.google.com/accounts/answer/6010255?hl=en) by Google, you should note that using Gmail credentials for SMTP configuration
will only work for Google Workspace or Google Cloud Identity customers as of May 30, 2022.
- Put differently, the SMTP configuration is only possible with business (not personal) Gmail credentials.
+Put differently, the SMTP configuration is only possible with business (not personal) Gmail credentials.
+
+
+
+1. Create an account and configure [Office365](https://www.office.com/) to send emails.
+
+2. With your login credentials, you can now set up your SMTP environment variables:
+
+```
+SMTP_HOST=smtp.office365.com
+SMTP_USERNAME=username@yourdomain.com # your username
+SMTP_PASSWORD=password # your password
+SMTP_PORT=587
+SMTP_SECURE=true
+SMTP_FROM_ADDRESS=username@yourdomain.com
+SMTP_FROM_NAME=Infisical
+```
+
+
+
1. Create an account and configure [Zoho Mail](https://www.zoho.com/mail/) to send emails.
diff --git a/docs/self-hosting/configuration/envars.mdx b/docs/self-hosting/configuration/envars.mdx
index ef9fc1fd0..fddf6f82e 100644
--- a/docs/self-hosting/configuration/envars.mdx
+++ b/docs/self-hosting/configuration/envars.mdx
@@ -105,7 +105,7 @@ Other environment variables are listed below to increase the functionality of yo
- OAuth2 slug for Netlify integration
+ OAuth2 slug for Vercel integration
diff --git a/frontend/src/components/login/InitialLoginStep.tsx b/frontend/src/components/login/InitialLoginStep.tsx
index fbdd12c82..dcc8106f9 100644
--- a/frontend/src/components/login/InitialLoginStep.tsx
+++ b/frontend/src/components/login/InitialLoginStep.tsx
@@ -1,4 +1,4 @@
-import { useState } from "react";
+import { FormEvent, useState } from "react";
import { useTranslation } from "react-i18next";
import Link from "next/link";
import { useRouter } from "next/router";
@@ -32,7 +32,8 @@ export default function InitialLoginStep({
const [isLoading, setIsLoading] = useState(false);
const [loginError, setLoginError] = useState(false);
- const handleLogin = async () => {
+ const handleLogin = async (e: FormEvent) => {
+ e.preventDefault()
try {
if (!email || !password) {
return;
@@ -101,7 +102,7 @@ export default function InitialLoginStep({
setIsLoading(false);
}
- return