Dashboard
@@ -205,200 +185,41 @@ export default function Integrations() {
content="Infisical a simple end-to-end encrypted platform that enables teams to sync and manage their .env files."
/>
-
-
-
-
-
-
Current Project Integrations
-
-
- Manage your integrations of Infisical with third-party services.
-
-
- {projectIntegrations.length > 0 ? (
- projectIntegrations.map((projectIntegration) => (
-
- ))
- ) : (
-
-
-
- You {"don't"} have any integrations set up yet. When you do,
- they will appear here.
-
-
- To start, click on any of the options below. It takes 5 clicks
- to set up.
-
-
-
- )}
-
-
-
- Platform & Cloud Integrations
-
-
-
- Click on the itegration you want to connect. This will let your
- environment variables flow automatically into selected third-party
- services.
-
-
- Note: during an integration with Heroku, for security reasons, it
- is impossible to maintain end-to-end encryption. In theory, this
- lets Infisical decrypt yor environment variables. In practice, we
- can assure you that this will never be done, and it allows us to
- protect your secrets from bad actors online. The core Infisical
- service will always stay end-to-end encrypted. With any questions,
- reach out support@infisical.com.
-
-
-
- {Object.keys(integrations).map((integration) => (
-
- ))}
-
-
-
-
Framework Integrations
-
-
- Click on a framework to get the setup instructions.
-
-
-
- {frameworks.map((framework) => (
-
- ))}
-
-
+
+
+
setIsActivateBotDialogOpen(false)}
+ selectedIntegrationOption={selectedIntegrationOption}
+ handleBotActivate={handleBotActivate}
+ handleIntegrationOption={handleIntegrationOption}
+ />
+ {/* setIntegrationAccessTokenDialogOpen(false)}
+ selectedIntegrationOption={selectedIntegrationOption}
+ handleBotActivate={handleBotActivate}
+ handleIntegrationOption={handleIntegrationOption}
+ /> */}
+
+ {cloudIntegrationOptions.length > 0 ? (
+
+ ) : (
+
+ )}
+
- ) : (
-
);
}
diff --git a/frontend/pages/netlify.js b/frontend/pages/netlify.js
new file mode 100644
index 000000000..6907d6db4
--- /dev/null
+++ b/frontend/pages/netlify.js
@@ -0,0 +1,41 @@
+import React, { useEffect } from "react";
+import Head from "next/head";
+import { useRouter } from "next/router";
+const queryString = require("query-string");
+import AuthorizeIntegration from "./api/integrations/authorizeIntegration";
+
+export default function Netlify() {
+ const router = useRouter();
+ const parsedUrl = queryString.parse(router.asPath.split("?")[1]);
+ const code = parsedUrl.code;
+ const state = parsedUrl.state;
+ // modify comment here
+
+ /**
+ * Here we forward to the default workspace if a user opens this url
+ */
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ useEffect(async () => {
+ try {
+ if (state === localStorage.getItem('latestCSRFToken')) {
+ localStorage.removeItem('latestCSRFToken');
+
+ await AuthorizeIntegration({
+ workspaceId: localStorage.getItem('projectData.id'),
+ code,
+ integration: "netlify"
+ });
+
+ router.push("/integrations/" + localStorage.getItem("projectData.id"));
+ }
+ } catch (err) {
+ console.error('Netlify integration error: ', err);
+ }
+
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ return
;
+}
+
+Netlify.requireAuth = true;
diff --git a/frontend/pages/vercel.js b/frontend/pages/vercel.js
new file mode 100644
index 000000000..adfffe77e
--- /dev/null
+++ b/frontend/pages/vercel.js
@@ -0,0 +1,40 @@
+import React, { useEffect } from "react";
+import Head from "next/head";
+import { useRouter } from "next/router";
+const queryString = require("query-string");
+import AuthorizeIntegration from "./api/integrations/authorizeIntegration";
+
+export default function Vercel() {
+ const router = useRouter();
+ const parsedUrl = queryString.parse(router.asPath.split("?")[1]);
+ const code = parsedUrl.code;
+ const state = parsedUrl.state
+
+ /**
+ * Here we forward to the default workspace if a user opens this url
+ */
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ useEffect(async () => {
+ try {
+ if (state === localStorage.getItem('latestCSRFToken')) {
+ localStorage.removeItem('latestCSRFToken');
+
+ await AuthorizeIntegration({
+ workspaceId: localStorage.getItem('projectData.id'),
+ code,
+ integration: "vercel"
+ });
+
+ router.push("/integrations/" + localStorage.getItem("projectData.id"));
+ }
+ } catch (err) {
+ console.error('Vercel integration error: ', err);
+ }
+
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ return
;
+}
+
+Vercel.requireAuth = true;
diff --git a/frontend/public/data/frequentConstants.ts b/frontend/public/data/frequentConstants.ts
index fbc0034d3..d2beee6d2 100644
--- a/frontend/public/data/frequentConstants.ts
+++ b/frontend/public/data/frequentConstants.ts
@@ -1,82 +1,37 @@
-const envMapping = {
+interface Mapping {
+ [key: string]: string;
+}
+
+const envMapping: Mapping = {
Development: "dev",
Staging: "staging",
Production: "prod",
Testing: "test",
};
-
-const reverseEnvMapping = {
+
+const reverseEnvMapping: Mapping = {
dev: "Development",
staging: "Staging",
prod: "Production",
test: "Testing",
};
-const frameworks = [{
- "name": "Docker",
- "image": "Docker",
- "link": "https://infisical.com/docs/integrations/platforms/docker"
- }, {
- "name": "Docker Compose",
- "image": "Docker Compose",
- "link": "https://infisical.com/docs/integrations/platforms/docker-compose"
- }, {
- "name": "React",
- "image": "React",
- "link": "https://infisical.com/docs/integrations/frameworks/react"
- }, {
- "name": "Vue",
- "image": "Vue",
- "link": "https://infisical.com/docs/integrations/frameworks/vue"
- }, {
- "image": "Express",
- "link": "https://infisical.com/docs/integrations/frameworks/express"
- },{
- "image": "Next.js",
- "link": "https://infisical.com/docs/integrations/frameworks/nextjs"
- }, {
- "name": "Django",
- "image": "Django",
- "link": "https://infisical.com/docs/integrations/frameworks/django"
- }, {
- "name": "NestJS",
- "image": "NestJS",
- "link": "https://infisical.com/docs/integrations/frameworks/nestjs"
- }, {
- "name": "Nuxt",
- "image": "Nuxt",
- "link": "https://infisical.com/docs/integrations/frameworks/nuxt"
- }, {
- "name": "Gatsby",
- "image": "Gatsby",
- "link": "https://infisical.com/docs/integrations/frameworks/gatsby"
- }, {
- "name": "Remix",
- "image": "Remix",
- "link": "https://infisical.com/docs/integrations/frameworks/remix"
- }, {
- "name": "Vite",
- "image": "Vite",
- "link": "https://infisical.com/docs/integrations/frameworks/vite"
- }, {
- "image": "Fiber",
- "link": "https://infisical.com/docs/integrations/frameworks/fiber"
- }, {
- "name": "Flask",
- "image": "Flask",
- "link": "https://infisical.com/docs/integrations/frameworks/flask"
- }, {
- "name": "Laravel",
- "image": "Laravel",
- "link": "https://infisical.com/docs/integrations/frameworks/laravel"
- }, {
- "image": "Rails",
- "link": "https://infisical.com/docs/integrations/frameworks/rails"
- }
-]
+const contextNetlifyMapping: Mapping = {
+ "dev": "Local development",
+ "branch-deploy": "Branch deploys",
+ "deploy-review": "Deploy Previews",
+ "production": "Production"
+}
+
+const reverseContextNetlifyMapping: Mapping = {
+ "Local development": "dev",
+ "Branch deploys": "branch-deploy",
+ "Deploy Previews": "deploy-preview",
+ "Production": "production"
+}
export {
+ contextNetlifyMapping,
envMapping,
- frameworks,
- reverseEnvMapping
-};
+ reverseContextNetlifyMapping,
+ reverseEnvMapping}
diff --git a/frontend/public/images/integrations/Vercel.png b/frontend/public/images/integrations/Vercel.png
new file mode 100644
index 000000000..7bdcd2a19
Binary files /dev/null and b/frontend/public/images/integrations/Vercel.png differ
diff --git a/frontend/public/json/frameworkIntegrations.json b/frontend/public/json/frameworkIntegrations.json
new file mode 100644
index 000000000..fb8b30c9e
--- /dev/null
+++ b/frontend/public/json/frameworkIntegrations.json
@@ -0,0 +1,98 @@
+[
+ {
+ "name": "Docker",
+ "slug": "docker",
+ "image": "Docker",
+ "docsLink": "https://infisical.com/docs/integrations/platforms/docker"
+ },
+ {
+ "name": "Docker Compose",
+ "slug": "docker-compose",
+ "image": "Docker Compose",
+ "docsLink": "https://infisical.com/docs/integrations/platforms/docker-compose"
+ },
+ {
+ "name": "React",
+ "slug": "react",
+ "image": "React",
+ "docsLink": "https://infisical.com/docs/integrations/frameworks/react"
+ },
+ {
+ "name": "Vue",
+ "slug": "vue",
+ "image": "Vue",
+ "docsLink": "https://infisical.com/docs/integrations/frameworks/vue"
+ },
+ {
+ "name": "Express",
+ "slug": "express",
+ "image": "Express",
+ "docsLink": "https://infisical.com/docs/integrations/frameworks/express"
+ },
+ {
+ "name": "Next.js",
+ "slug": "nextjs",
+ "image": "Next.js",
+ "docsLink": "https://infisical.com/docs/integrations/frameworks/nextjs"
+ },
+ {
+ "name": "Django",
+ "slug": "django",
+ "image": "Django",
+ "docsLink": "https://infisical.com/docs/integrations/frameworks/django"
+ },
+ {
+ "name": "NestJS",
+ "slug": "nestjs",
+ "image": "NestJS",
+ "docsLink": "https://infisical.com/docs/integrations/frameworks/nestjs"
+ },
+ {
+ "name": "Nuxt",
+ "slug": "nuxt",
+ "image": "Nuxt",
+ "docsLink": "https://infisical.com/docs/integrations/frameworks/nuxt"
+ },
+ {
+ "name": "Gatsby",
+ "slug": "gatsby",
+ "image": "Gatsby",
+ "docsLink": "https://infisical.com/docs/integrations/frameworks/gatsby"
+ },
+ {
+ "name": "Remix",
+ "slug": "remix",
+ "image": "Remix",
+ "docsLink": "https://infisical.com/docs/integrations/frameworks/remix"
+ },
+ {
+ "name": "Vite",
+ "slug": "vite",
+ "image": "Vite",
+ "docsLink": "https://infisical.com/docs/integrations/frameworks/vite"
+ },
+ {
+ "name": "Fiber",
+ "slug": "fiber",
+ "image": "Fiber",
+ "docsLink": "https://infisical.com/docs/integrations/frameworks/fiber"
+ },
+ {
+ "name": "Flask",
+ "slug": "flask",
+ "image": "Flask",
+ "docsLink": "https://infisical.com/docs/integrations/frameworks/flask"
+ },
+ {
+ "name": "Laravel",
+ "slug": "laravel",
+ "image": "Laravel",
+ "docsLink": "https://infisical.com/docs/integrations/frameworks/laravel"
+ },
+ {
+ "name": "Rails",
+ "slug": "rails",
+ "image": "Rails",
+ "docsLink": "https://infisical.com/docs/integrations/frameworks/rails"
+ }
+]
\ No newline at end of file
diff --git a/helm-charts/infisical/Chart.yaml b/helm-charts/infisical/Chart.yaml
index a9297b385..961a13f76 100644
--- a/helm-charts/infisical/Chart.yaml
+++ b/helm-charts/infisical/Chart.yaml
@@ -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: 0.1.3
+version: 0.1.5
# 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
diff --git a/helm-charts/infisical/templates/backend-deployment.yaml b/helm-charts/infisical/templates/backend-deployment.yaml
index 6a2faa688..437995e58 100644
--- a/helm-charts/infisical/templates/backend-deployment.yaml
+++ b/helm-charts/infisical/templates/backend-deployment.yaml
@@ -20,6 +20,11 @@ spec:
imagePullPolicy: {{ .Values.backend.image.pullPolicy }}
ports:
- containerPort: 4000
+ {{- if .Values.backend.kubeSecretRef }}
+ envFrom:
+ - secretRef:
+ name: {{ .Values.backend.kubeSecretRef }}
+ {{- end }}
env:
{{- range $key, $value := .Values.backendEnvironmentVariables }}
{{- if $value | quote | eq "MUST_REPLACE" }}
diff --git a/helm-charts/infisical/templates/frontend-deployment.yaml b/helm-charts/infisical/templates/frontend-deployment.yaml
index 3cd29f326..3930fda2b 100644
--- a/helm-charts/infisical/templates/frontend-deployment.yaml
+++ b/helm-charts/infisical/templates/frontend-deployment.yaml
@@ -18,6 +18,12 @@ spec:
- name: frontend
image: infisical/frontend
imagePullPolicy: {{ .Values.frontend.image.pullPolicy }}
+ {{- if .Values.frontend.kubeSecretRef }}
+ envFrom:
+ - secretRef:
+ name: {{ .Values.frontend.kubeSecretRef }}
+ {{- end }}
+ {{- if .Values.frontendEnvironmentVariables }}
env:
{{- range $key, $value := .Values.frontendEnvironmentVariables }}
{{- if $value | quote | eq "MUST_REPLACE" }}
@@ -26,6 +32,7 @@ spec:
- name: {{ $key }}
value: {{ quote $value }}
{{- end }}
+ {{- end }}
ports:
- containerPort: 4000
---
diff --git a/helm-charts/infisical/values.yaml b/helm-charts/infisical/values.yaml
index a93a4769d..b78543774 100644
--- a/helm-charts/infisical/values.yaml
+++ b/helm-charts/infisical/values.yaml
@@ -3,14 +3,14 @@
# PLEASE REPLACE VALUES/EDIT AS REQUIRED
#####
-namespace: infisical
-
frontend:
replicaCount: 1
image:
repository:
pullPolicy: IfNotPresent
tag: "latest"
+ # kubeSecretRef: some-kube-secret-name
+
backend:
replicaCount: 1
@@ -18,6 +18,7 @@ backend:
repository:
pullPolicy: IfNotPresent
tag: "latest"
+ # kubeSecretRef: some-kube-secret-name
ingress:
enabled: true
@@ -54,8 +55,6 @@ ingress:
###
backendEnvironmentVariables:
# Required keys for platform encryption/decryption ops. Replace with nacl sk keys
- PRIVATE_KEY: MUST_REPLACE
- PUBLIC_KEY: MUST_REPLACE
ENCRYPTION_KEY: MUST_REPLACE
# JWT
@@ -71,9 +70,8 @@ backendEnvironmentVariables:
SMTP_USERNAME: MUST_REPLACE
SMTP_PASSWORD: MUST_REPLACE
- # You may replace with Mongo Cloud URI
+ # Recommended to replace with Mongo Cloud URI as the DB instance in the cluster does not have persistence yet
MONGO_URL: mongodb://root:root@mongodb-service:27017/
# frontendEnvironmentVariables:
-# INFISICAL_TELEMETRY_ENABLED: true
\ No newline at end of file
diff --git a/helm-charts/secrets-operator/templates/infisicalsecret-crd.yaml b/helm-charts/secrets-operator/templates/infisicalsecret-crd.yaml
index 8628a57d9..c5b82fa14 100644
--- a/helm-charts/secrets-operator/templates/infisicalsecret-crd.yaml
+++ b/helm-charts/secrets-operator/templates/infisicalsecret-crd.yaml
@@ -38,19 +38,11 @@ spec:
environment:
description: The Infisical environment such as dev, prod, testing
type: string
- infisicalToken:
- properties:
- secretName:
- description: The name of the Kubernetes Secret
- type: string
- secretNamespace:
- description: The name space where the Kubernetes Secret is located
- type: string
- required:
- - secretName
- - secretNamespace
- type: object
- managedSecret:
+ hostAPI:
+ default: https://app.infisical.com/api
+ description: Infisical host to pull secrets from
+ type: string
+ managedSecretReference:
properties:
secretName:
description: The name of the Kubernetes Secret
@@ -65,6 +57,18 @@ spec:
projectId:
description: The Infisical project id
type: string
+ tokenSecretReference:
+ properties:
+ secretName:
+ description: The name of the Kubernetes Secret
+ type: string
+ secretNamespace:
+ description: The name space where the Kubernetes Secret is located
+ type: string
+ required:
+ - secretName
+ - secretNamespace
+ type: object
required:
- environment
- projectId
diff --git a/k8-operator/Makefile b/k8-operator/Makefile
index 541e26b60..a8b056376 100644
--- a/k8-operator/Makefile
+++ b/k8-operator/Makefile
@@ -1,6 +1,6 @@
# Image URL to use all building/pushing image targets
-IMG ?= controller:latest
+IMG ?= infisical/kubernetes-operator:latest
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.25.0
@@ -41,6 +41,12 @@ help: ## Display this help.
helm-chart:
$(KUSTOMIZE) build config/default | helmify ../helm-charts/secrets-operator
+## Yaml for Kubectl
+kubectl-install: manifests kustomize
+ mkdir -p kubectl-install
+ cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
+ $(KUSTOMIZE) build config/default > kubectl-install/install-secrets-operator.yaml
+
##@ Development
.PHONY: manifests
diff --git a/k8-operator/README.md b/k8-operator/README.md
index 6d953997e..807476c0c 100644
--- a/k8-operator/README.md
+++ b/k8-operator/README.md
@@ -1,8 +1,8 @@
# k8-operator
-// TODO(user): Add simple overview of use/purpose
+// TODO
## Description
-// TODO(user): An in-depth paragraph about your project and overview of use
+// TODO
## Getting Started
You’ll need a Kubernetes cluster to run against. You can use [KIND](https://sigs.k8s.io/kind) to get a local cluster for testing, or run against a remote cluster.
@@ -42,7 +42,7 @@ make undeploy
```
## Contributing
-// TODO(user): Add detailed information on how you would like others to contribute to this project
+// TODO
### How it works
This project aims to follow the Kubernetes [Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)
@@ -76,19 +76,3 @@ make manifests
More information can be found via the [Kubebuilder Documentation](https://book.kubebuilder.io/introduction.html)
-## License
-
-Copyright 2022.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
diff --git a/k8-operator/api/v1alpha1/infisicalsecret_types.go b/k8-operator/api/v1alpha1/infisicalsecret_types.go
index 74e3f9788..7940474f9 100644
--- a/k8-operator/api/v1alpha1/infisicalsecret_types.go
+++ b/k8-operator/api/v1alpha1/infisicalsecret_types.go
@@ -16,8 +16,8 @@ type KubeSecretReference struct {
// InfisicalSecretSpec defines the desired state of InfisicalSecret
type InfisicalSecretSpec struct {
- InfisicalToken KubeSecretReference `json:"infisicalToken,omitempty"`
- ManagedSecret KubeSecretReference `json:"managedSecret,omitempty"`
+ TokenSecretReference KubeSecretReference `json:"tokenSecretReference,omitempty"`
+ ManagedSecretReference KubeSecretReference `json:"managedSecretReference,omitempty"`
// The Infisical project id
// +kubebuilder:validation:Required
@@ -26,6 +26,10 @@ type InfisicalSecretSpec struct {
// The Infisical environment such as dev, prod, testing
// +kubebuilder:validation:Required
Environment string `json:"environment"`
+
+ // Infisical host to pull secrets from
+ // +kubebuilder:default="https://app.infisical.com/api"
+ HostAPI string `json:"hostAPI,omitempty"`
}
// InfisicalSecretStatus defines the observed state of InfisicalSecret
diff --git a/k8-operator/api/v1alpha1/zz_generated.deepcopy.go b/k8-operator/api/v1alpha1/zz_generated.deepcopy.go
index e6053ba74..af9eff318 100644
--- a/k8-operator/api/v1alpha1/zz_generated.deepcopy.go
+++ b/k8-operator/api/v1alpha1/zz_generated.deepcopy.go
@@ -88,8 +88,8 @@ func (in *InfisicalSecretList) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InfisicalSecretSpec) DeepCopyInto(out *InfisicalSecretSpec) {
*out = *in
- out.InfisicalToken = in.InfisicalToken
- out.ManagedSecret = in.ManagedSecret
+ out.TokenSecretReference = in.TokenSecretReference
+ out.ManagedSecretReference = in.ManagedSecretReference
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfisicalSecretSpec.
diff --git a/k8-operator/config/crd/bases/secrets.infisical.com_infisicalsecrets.yaml b/k8-operator/config/crd/bases/secrets.infisical.com_infisicalsecrets.yaml
index ca00676b4..c885fbdde 100644
--- a/k8-operator/config/crd/bases/secrets.infisical.com_infisicalsecrets.yaml
+++ b/k8-operator/config/crd/bases/secrets.infisical.com_infisicalsecrets.yaml
@@ -38,19 +38,11 @@ spec:
environment:
description: The Infisical environment such as dev, prod, testing
type: string
- infisicalToken:
- properties:
- secretName:
- description: The name of the Kubernetes Secret
- type: string
- secretNamespace:
- description: The name space where the Kubernetes Secret is located
- type: string
- required:
- - secretName
- - secretNamespace
- type: object
- managedSecret:
+ hostAPI:
+ default: https://app.infisical.com/api
+ description: Infisical host to pull secrets from
+ type: string
+ managedSecretReference:
properties:
secretName:
description: The name of the Kubernetes Secret
@@ -65,6 +57,18 @@ spec:
projectId:
description: The Infisical project id
type: string
+ tokenSecretReference:
+ properties:
+ secretName:
+ description: The name of the Kubernetes Secret
+ type: string
+ secretNamespace:
+ description: The name space where the Kubernetes Secret is located
+ type: string
+ required:
+ - secretName
+ - secretNamespace
+ type: object
required:
- environment
- projectId
diff --git a/k8-operator/config/default/kustomization.yaml b/k8-operator/config/default/kustomization.yaml
index 4cab9014c..1237b893d 100644
--- a/k8-operator/config/default/kustomization.yaml
+++ b/k8-operator/config/default/kustomization.yaml
@@ -1,12 +1,12 @@
# Adds namespace to all resources.
-namespace: k8-operator-system
+namespace: infisical-operator-system
# Value of this field is prepended to the
# names of all resources, e.g. a deployment named
# "wordpress" becomes "alices-wordpress".
# Note that it should also match with the prefix (text before '-') of the namespace
# field above.
-namePrefix: k8-operator-
+namePrefix: infisical-operator-
# Labels to add to all resources and selectors.
#commonLabels:
diff --git a/k8-operator/config/manager/kustomization.yaml b/k8-operator/config/manager/kustomization.yaml
index 5c5f0b84c..96ea36924 100644
--- a/k8-operator/config/manager/kustomization.yaml
+++ b/k8-operator/config/manager/kustomization.yaml
@@ -1,2 +1,8 @@
resources:
- manager.yaml
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+images:
+- name: controller
+ newName: infisical/kubernetes-operator
+ newTag: latest
diff --git a/k8-operator/config/samples/sample.yaml b/k8-operator/config/samples/sample.yaml
new file mode 100644
index 000000000..ad352d3e7
--- /dev/null
+++ b/k8-operator/config/samples/sample.yaml
@@ -0,0 +1,13 @@
+apiVersion: secrets.infisical.com/v1alpha1
+kind: InfisicalSecret
+metadata:
+ name: infisicalsecret-sample
+spec:
+ projectId: 62faf98ae0b05e8529b5da46
+ environment: dev
+ tokenSecretReference:
+ secretName: service-token
+ secretNamespace: first-project
+ managedSecretReference:
+ secretName: managed-secret
+ secretNamespace: first-project
diff --git a/k8-operator/config/samples/secrets_v1alpha1_infisicalsecret.yaml b/k8-operator/config/samples/secrets_v1alpha1_infisicalsecret.yaml
deleted file mode 100644
index 7ab08e9cd..000000000
--- a/k8-operator/config/samples/secrets_v1alpha1_infisicalsecret.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-apiVersion: secrets.infisical.com/v1alpha1
-kind: InfisicalSecret
-metadata:
- labels:
- app.kubernetes.io/name: infisicalsecret
- app.kubernetes.io/instance: infisicalsecret-sample
- app.kubernetes.io/part-of: k8-operator
- app.kubernetes.io/managed-by: kustomize
- app.kubernetes.io/created-by: k8-operator
- name: infisicalsecret-sample
-spec:
- projectId: 62faf98ae0b05e8529b5da46
- environment: dev
- infisicalToken:
- secretName: service-token
- secretNamespace: default
- managedSecret:
- secretName: managed-secret
- secretNamespace: default
diff --git a/k8-operator/controllers/infisicalsecret_controller.go b/k8-operator/controllers/infisicalsecret_controller.go
index 297e29bfb..f6422e177 100644
--- a/k8-operator/controllers/infisicalsecret_controller.go
+++ b/k8-operator/controllers/infisicalsecret_controller.go
@@ -36,6 +36,8 @@ func (r *InfisicalSecretReconciler) Reconcile(ctx context.Context, req ctrl.Requ
var infisicalSecretCR v1alpha1.InfisicalSecret
err := r.Get(ctx, req.NamespacedName, &infisicalSecretCR)
+ requeueTime := time.Minute * 5
+
if err != nil {
if errors.IsNotFound(err) {
log.Info("Infisical Secret not found")
@@ -43,7 +45,7 @@ func (r *InfisicalSecretReconciler) Reconcile(ctx context.Context, req ctrl.Requ
} else {
log.Error(err, "Unable to fetch Infisical Secret from cluster. Will retry")
return ctrl.Result{
- RequeueAfter: time.Minute,
+ RequeueAfter: requeueTime,
}, nil
}
}
@@ -58,13 +60,13 @@ func (r *InfisicalSecretReconciler) Reconcile(ctx context.Context, req ctrl.Requ
if err != nil {
log.Error(err, "Unable to reconcile Infisical Secret and will try again")
return ctrl.Result{
- RequeueAfter: time.Minute,
+ RequeueAfter: requeueTime,
}, nil
}
// Sync again after the specified time
return ctrl.Result{
- RequeueAfter: time.Minute,
+ RequeueAfter: requeueTime,
}, nil
}
diff --git a/k8-operator/controllers/infisicalsecret_helper.go b/k8-operator/controllers/infisicalsecret_helper.go
index fbcacadea..be4e35dd5 100644
--- a/k8-operator/controllers/infisicalsecret_helper.go
+++ b/k8-operator/controllers/infisicalsecret_helper.go
@@ -29,12 +29,12 @@ func (r *InfisicalSecretReconciler) GetKubeSecretByNamespacedName(ctx context.Co
func (r *InfisicalSecretReconciler) GetInfisicalToken(ctx context.Context, infisicalSecret v1alpha1.InfisicalSecret) (string, error) {
tokenSecret, err := r.GetKubeSecretByNamespacedName(ctx, types.NamespacedName{
- Namespace: infisicalSecret.Spec.InfisicalToken.SecretNamespace,
- Name: infisicalSecret.Spec.InfisicalToken.SecretName,
+ Namespace: infisicalSecret.Spec.TokenSecretReference.SecretNamespace,
+ Name: infisicalSecret.Spec.TokenSecretReference.SecretName,
})
if err != nil {
- return "", fmt.Errorf("failed to read Infisical token secret from secret named [%s] in namespace [%s]: with error [%w]", infisicalSecret.Spec.ManagedSecret.SecretName, infisicalSecret.Spec.ManagedSecret.SecretNamespace, err)
+ return "", fmt.Errorf("failed to read Infisical token secret from secret named [%s] in namespace [%s]: with error [%w]", infisicalSecret.Spec.ManagedSecretReference.SecretName, infisicalSecret.Spec.ManagedSecretReference.SecretNamespace, err)
}
infisicalServiceToken := tokenSecret.Data[INFISICAL_TOKEN_SECRET_KEY_NAME]
@@ -54,8 +54,8 @@ func (r *InfisicalSecretReconciler) CreateInfisicalManagedKubeSecret(ctx context
// create a new secret as specified by the managed secret spec of CRD
newKubeSecretInstance := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
- Name: infisicalSecret.Spec.ManagedSecret.SecretName,
- Namespace: infisicalSecret.Spec.ManagedSecret.SecretNamespace,
+ Name: infisicalSecret.Spec.ManagedSecretReference.SecretName,
+ Namespace: infisicalSecret.Spec.ManagedSecretReference.SecretNamespace,
},
Type: "Opaque",
Data: plainProcessedSecrets,
@@ -94,15 +94,15 @@ func (r *InfisicalSecretReconciler) ReconcileInfisicalSecret(ctx context.Context
}
managedKubeSecret, err := r.GetKubeSecretByNamespacedName(ctx, types.NamespacedName{
- Name: infisicalSecret.Spec.ManagedSecret.SecretName,
- Namespace: infisicalSecret.Spec.ManagedSecret.SecretNamespace,
+ Name: infisicalSecret.Spec.ManagedSecretReference.SecretName,
+ Namespace: infisicalSecret.Spec.ManagedSecretReference.SecretNamespace,
})
if err != nil && !errors.IsNotFound(err) {
return fmt.Errorf("something went wrong when fetching the managed Kubernetes secret [%w]", err)
}
- secretsFromApi, err := api.GetAllEnvironmentVariables(infisicalSecret.Spec.ProjectId, infisicalSecret.Spec.Environment, infisicalToken)
+ secretsFromApi, err := api.GetAllEnvironmentVariables(infisicalSecret.Spec.ProjectId, infisicalSecret.Spec.Environment, infisicalToken, infisicalSecret.Spec.HostAPI)
if err != nil {
return err
diff --git a/k8-operator/kubectl-install/install-secrets-operator.yaml b/k8-operator/kubectl-install/install-secrets-operator.yaml
new file mode 100644
index 000000000..6a3cb8e6d
--- /dev/null
+++ b/k8-operator/kubectl-install/install-secrets-operator.yaml
@@ -0,0 +1,475 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ labels:
+ app.kubernetes.io/component: manager
+ app.kubernetes.io/created-by: k8-operator
+ app.kubernetes.io/instance: system
+ app.kubernetes.io/managed-by: kustomize
+ app.kubernetes.io/name: namespace
+ app.kubernetes.io/part-of: k8-operator
+ control-plane: controller-manager
+ name: infisical-operator-system
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.10.0
+ creationTimestamp: null
+ name: infisicalsecrets.secrets.infisical.com
+spec:
+ group: secrets.infisical.com
+ names:
+ kind: InfisicalSecret
+ listKind: InfisicalSecretList
+ plural: infisicalsecrets
+ singular: infisicalsecret
+ scope: Namespaced
+ versions:
+ - name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: InfisicalSecret is the Schema for the infisicalsecrets API
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: InfisicalSecretSpec defines the desired state of InfisicalSecret
+ properties:
+ environment:
+ description: The Infisical environment such as dev, prod, testing
+ type: string
+ hostAPI:
+ default: https://app.infisical.com/api
+ description: Infisical host to pull secrets from
+ type: string
+ managedSecretReference:
+ properties:
+ secretName:
+ description: The name of the Kubernetes Secret
+ type: string
+ secretNamespace:
+ description: The name space where the Kubernetes Secret is located
+ type: string
+ required:
+ - secretName
+ - secretNamespace
+ type: object
+ projectId:
+ description: The Infisical project id
+ type: string
+ tokenSecretReference:
+ properties:
+ secretName:
+ description: The name of the Kubernetes Secret
+ type: string
+ secretNamespace:
+ description: The name space where the Kubernetes Secret is located
+ type: string
+ required:
+ - secretName
+ - secretNamespace
+ type: object
+ required:
+ - environment
+ - projectId
+ type: object
+ status:
+ description: InfisicalSecretStatus defines the observed state of InfisicalSecret
+ properties:
+ conditions:
+ items:
+ description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating details about the transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ type: array
+ required:
+ - conditions
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ labels:
+ app.kubernetes.io/component: rbac
+ app.kubernetes.io/created-by: k8-operator
+ app.kubernetes.io/instance: controller-manager
+ app.kubernetes.io/managed-by: kustomize
+ app.kubernetes.io/name: serviceaccount
+ app.kubernetes.io/part-of: k8-operator
+ name: infisical-operator-controller-manager
+ namespace: infisical-operator-system
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ labels:
+ app.kubernetes.io/component: rbac
+ app.kubernetes.io/created-by: k8-operator
+ app.kubernetes.io/instance: leader-election-role
+ app.kubernetes.io/managed-by: kustomize
+ app.kubernetes.io/name: role
+ app.kubernetes.io/part-of: k8-operator
+ name: infisical-operator-leader-election-role
+ namespace: infisical-operator-system
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - configmaps
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - patch
+ - delete
+- apiGroups:
+ - coordination.k8s.io
+ resources:
+ - leases
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - patch
+ - delete
+- apiGroups:
+ - ""
+ resources:
+ - events
+ verbs:
+ - create
+ - patch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ creationTimestamp: null
+ name: infisical-operator-manager-role
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - secrets
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - update
+ - watch
+- apiGroups:
+ - apps
+ resources:
+ - deployments
+ verbs:
+ - get
+ - list
+ - update
+ - watch
+- apiGroups:
+ - secrets.infisical.com
+ resources:
+ - infisicalsecrets
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - secrets.infisical.com
+ resources:
+ - infisicalsecrets/finalizers
+ verbs:
+ - update
+- apiGroups:
+ - secrets.infisical.com
+ resources:
+ - infisicalsecrets/status
+ verbs:
+ - get
+ - patch
+ - update
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ labels:
+ app.kubernetes.io/component: kube-rbac-proxy
+ app.kubernetes.io/created-by: k8-operator
+ app.kubernetes.io/instance: metrics-reader
+ app.kubernetes.io/managed-by: kustomize
+ app.kubernetes.io/name: clusterrole
+ app.kubernetes.io/part-of: k8-operator
+ name: infisical-operator-metrics-reader
+rules:
+- nonResourceURLs:
+ - /metrics
+ verbs:
+ - get
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ labels:
+ app.kubernetes.io/component: kube-rbac-proxy
+ app.kubernetes.io/created-by: k8-operator
+ app.kubernetes.io/instance: proxy-role
+ app.kubernetes.io/managed-by: kustomize
+ app.kubernetes.io/name: clusterrole
+ app.kubernetes.io/part-of: k8-operator
+ name: infisical-operator-proxy-role
+rules:
+- apiGroups:
+ - authentication.k8s.io
+ resources:
+ - tokenreviews
+ verbs:
+ - create
+- apiGroups:
+ - authorization.k8s.io
+ resources:
+ - subjectaccessreviews
+ verbs:
+ - create
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ labels:
+ app.kubernetes.io/component: rbac
+ app.kubernetes.io/created-by: k8-operator
+ app.kubernetes.io/instance: leader-election-rolebinding
+ app.kubernetes.io/managed-by: kustomize
+ app.kubernetes.io/name: rolebinding
+ app.kubernetes.io/part-of: k8-operator
+ name: infisical-operator-leader-election-rolebinding
+ namespace: infisical-operator-system
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: infisical-operator-leader-election-role
+subjects:
+- kind: ServiceAccount
+ name: infisical-operator-controller-manager
+ namespace: infisical-operator-system
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ labels:
+ app.kubernetes.io/component: rbac
+ app.kubernetes.io/created-by: k8-operator
+ app.kubernetes.io/instance: manager-rolebinding
+ app.kubernetes.io/managed-by: kustomize
+ app.kubernetes.io/name: clusterrolebinding
+ app.kubernetes.io/part-of: k8-operator
+ name: infisical-operator-manager-rolebinding
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: infisical-operator-manager-role
+subjects:
+- kind: ServiceAccount
+ name: infisical-operator-controller-manager
+ namespace: infisical-operator-system
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ labels:
+ app.kubernetes.io/component: kube-rbac-proxy
+ app.kubernetes.io/created-by: k8-operator
+ app.kubernetes.io/instance: proxy-rolebinding
+ app.kubernetes.io/managed-by: kustomize
+ app.kubernetes.io/name: clusterrolebinding
+ app.kubernetes.io/part-of: k8-operator
+ name: infisical-operator-proxy-rolebinding
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: infisical-operator-proxy-role
+subjects:
+- kind: ServiceAccount
+ name: infisical-operator-controller-manager
+ namespace: infisical-operator-system
+---
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ app.kubernetes.io/component: kube-rbac-proxy
+ app.kubernetes.io/created-by: k8-operator
+ app.kubernetes.io/instance: controller-manager-metrics-service
+ app.kubernetes.io/managed-by: kustomize
+ app.kubernetes.io/name: service
+ app.kubernetes.io/part-of: k8-operator
+ control-plane: controller-manager
+ name: infisical-operator-controller-manager-metrics-service
+ namespace: infisical-operator-system
+spec:
+ ports:
+ - name: https
+ port: 8443
+ protocol: TCP
+ targetPort: https
+ selector:
+ control-plane: controller-manager
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ app.kubernetes.io/component: manager
+ app.kubernetes.io/created-by: k8-operator
+ app.kubernetes.io/instance: controller-manager
+ app.kubernetes.io/managed-by: kustomize
+ app.kubernetes.io/name: deployment
+ app.kubernetes.io/part-of: k8-operator
+ control-plane: controller-manager
+ name: infisical-operator-controller-manager
+ namespace: infisical-operator-system
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ control-plane: controller-manager
+ template:
+ metadata:
+ annotations:
+ kubectl.kubernetes.io/default-container: manager
+ labels:
+ control-plane: controller-manager
+ spec:
+ affinity:
+ nodeAffinity:
+ requiredDuringSchedulingIgnoredDuringExecution:
+ nodeSelectorTerms:
+ - matchExpressions:
+ - key: kubernetes.io/arch
+ operator: In
+ values:
+ - amd64
+ - arm64
+ - ppc64le
+ - s390x
+ - key: kubernetes.io/os
+ operator: In
+ values:
+ - linux
+ containers:
+ - args:
+ - --secure-listen-address=0.0.0.0:8443
+ - --upstream=http://127.0.0.1:8080/
+ - --logtostderr=true
+ - --v=0
+ image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.1
+ name: kube-rbac-proxy
+ ports:
+ - containerPort: 8443
+ name: https
+ protocol: TCP
+ resources:
+ limits:
+ cpu: 500m
+ memory: 128Mi
+ requests:
+ cpu: 5m
+ memory: 64Mi
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
+ - args:
+ - --health-probe-bind-address=:8081
+ - --metrics-bind-address=127.0.0.1:8080
+ - --leader-elect
+ command:
+ - /manager
+ image: infisical/kubernetes-operator:latest
+ livenessProbe:
+ httpGet:
+ path: /healthz
+ port: 8081
+ initialDelaySeconds: 15
+ periodSeconds: 20
+ name: manager
+ readinessProbe:
+ httpGet:
+ path: /readyz
+ port: 8081
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ resources:
+ limits:
+ cpu: 500m
+ memory: 128Mi
+ requests:
+ cpu: 10m
+ memory: 64Mi
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
+ securityContext:
+ runAsNonRoot: true
+ serviceAccountName: infisical-operator-controller-manager
+ terminationGracePeriodSeconds: 10
diff --git a/k8-operator/packages/api/api.go b/k8-operator/packages/api/api.go
index ac2cc5b25..64f8add46 100644
--- a/k8-operator/packages/api/api.go
+++ b/k8-operator/packages/api/api.go
@@ -13,10 +13,8 @@ import (
"golang.org/x/crypto/nacl/box"
)
-const INFISICAL_URL = "https://app.infisical.com/api"
-
-func GetAllEnvironmentVariables(projectId string, envName string, infisicalToken string) ([]models.SingleEnvironmentVariable, error) {
- envsFromApi, err := GetSecretsFromAPIUsingInfisicalToken(infisicalToken, envName, projectId)
+func GetAllEnvironmentVariables(projectId string, envName string, infisicalToken string, hostAPI string) ([]models.SingleEnvironmentVariable, error) {
+ envsFromApi, err := GetSecretsFromAPIUsingInfisicalToken(infisicalToken, envName, projectId, hostAPI)
if err != nil {
return nil, err
}
@@ -24,7 +22,7 @@ func GetAllEnvironmentVariables(projectId string, envName string, infisicalToken
return SubstituteSecrets(envsFromApi), nil
}
-func GetSecretsFromAPIUsingInfisicalToken(infisicalToken string, envName string, projectId string) ([]models.SingleEnvironmentVariable, error) {
+func GetSecretsFromAPIUsingInfisicalToken(infisicalToken string, envName string, projectId string, hostAPI string) ([]models.SingleEnvironmentVariable, error) {
if infisicalToken == "" || projectId == "" || envName == "" {
return nil, errors.New("infisical token, project id and or environment name cannot be empty")
}
@@ -44,7 +42,7 @@ func GetSecretsFromAPIUsingInfisicalToken(infisicalToken string, envName string,
SetQueryParam("environment", envName).
SetQueryParam("channel", "cli").
SetResult(&pullSecretsByInfisicalTokenResponse).
- Get(fmt.Sprintf("%v/v1/secret/%v/service-token", INFISICAL_URL, projectId))
+ Get(fmt.Sprintf("%v/v1/secret/%v/service-token", hostAPI, projectId))
if err != nil {
return nil, err
diff --git a/package-lock.json b/package-lock.json
index 3a4157902..cf02a1760 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,8 +8,7 @@
"license": "ISC",
"devDependencies": {
"eslint": "^8.29.0",
- "husky": "^8.0.2",
- "prettier": "^2.8.1"
+ "husky": "^8.0.2"
}
},
"node_modules/@eslint/eslintrc": {
@@ -899,21 +898,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/prettier": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.1.tgz",
- "integrity": "sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==",
- "dev": true,
- "bin": {
- "prettier": "bin-prettier.js"
- },
- "engines": {
- "node": ">=10.13.0"
- },
- "funding": {
- "url": "https://github.com/prettier/prettier?sponsor=1"
- }
- },
"node_modules/punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
@@ -1809,12 +1793,6 @@
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true
},
- "prettier": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.1.tgz",
- "integrity": "sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==",
- "dev": true
- },
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
diff --git a/package.json b/package.json
index b0d02f3a0..4d042a13d 100644
--- a/package.json
+++ b/package.json
@@ -14,15 +14,12 @@
"prepare": "husky install"
},
"lint-staged": {
- "**/*": "prettier --write --ignore-unknown",
"*.{js,jsx,ts,tsx}": [
- "eslint --fix",
- "prettier --write"
+ "eslint --fix"
]
},
"devDependencies": {
"eslint": "^8.29.0",
- "husky": "^8.0.2",
- "prettier": "^2.8.1"
+ "husky": "^8.0.2"
}
}