Compare commits

...

18 Commits

Author SHA1 Message Date
ef61bc6a40 upgrade axios 2023-12-08 16:26:42 -05:00
602afdefc3 Merge pull request #1221 from Infisical/k8s-doc-update-secret-type
add docs for k8 secret type and label propagation
2023-12-07 20:12:53 -05:00
5eb505326b add docs for k8 secret type and label propagation 2023-12-07 20:10:11 -05:00
fcf4153d87 Update Chart.yaml 2023-12-07 19:34:08 -05:00
097282c5e1 Merge pull request #1182 from Allex1/secret
Make secret type field configurable
2023-12-07 19:31:39 -05:00
0eeef9a66c revert managed secret name 2023-12-07 19:30:43 -05:00
df0bec8a68 update chart version 2023-12-07 19:28:57 -05:00
13014b5345 create separate struct for managed secret + propagate lables/annotations 2023-12-07 19:26:48 -05:00
66d0cae066 Merge pull request #1220 from akhilmhdh/fix/update-secret-approval
fix(secret-approval): resolved update failure in secret approval mode
2023-12-07 13:19:34 -05:00
8e82222fc5 fix(secret-approval): resolved update failure in secret approval mode and number not increasing on frontend 2023-12-07 23:48:00 +05:30
f822bcd10f Merge pull request #1218 from ntimo/patch-1
Fixed 'SMTP_PASSWORD' default value
2023-12-07 11:54:44 -05:00
c51f8c5838 Fixed 'SMTP_PASSWORD' default value 2023-12-06 21:41:34 +01:00
377a79f17d Make secret type field configurable 2023-12-05 10:13:20 +02:00
2a768a7bc4 Update postgres.mdx 2023-12-04 16:18:50 -08:00
4b41664fa4 chores: clean login 2023-12-02 13:28:32 -05:00
735cf093f0 Merge pull request #1210 from Infisical/hide-blind-index
Hide blind index notice
2023-11-30 18:15:58 -05:00
98906f190c Merge pull request #1205 from Infisical/add-docs-for-folders-cli
add docs for folder cli command
2023-11-30 17:28:49 -05:00
5f80e2f432 Merge pull request #1205 from Infisical/add-docs-for-folders-cli
add docs for folder cli command
2023-11-29 10:03:06 -05:00
21 changed files with 162 additions and 46 deletions

View File

@ -24,7 +24,7 @@
"ajv": "^8.12.0",
"argon2": "^0.30.3",
"aws-sdk": "^2.1364.0",
"axios": "^1.3.5",
"axios": "^1.6.0",
"axios-retry": "^3.4.0",
"bcrypt": "^5.1.0",
"bigint-conversion": "^2.4.0",
@ -8325,9 +8325,9 @@
}
},
"node_modules/axios": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz",
"integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz",
"integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
@ -25250,9 +25250,9 @@
}
},
"axios": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz",
"integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz",
"integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==",
"requires": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",

View File

@ -15,7 +15,7 @@
"ajv": "^8.12.0",
"argon2": "^0.30.3",
"aws-sdk": "^2.1364.0",
"axios": "^1.3.5",
"axios": "^1.6.0",
"axios-retry": "^3.4.0",
"bcrypt": "^5.1.0",
"bigint-conversion": "^2.4.0",

View File

@ -204,20 +204,16 @@ export const login2 = async (req: Request, res: Response) => {
* @param res
*/
export const sendMfaToken = async (req: Request, res: Response) => {
const {
body: { email }
} = await validateRequest(reqValidator.SendMfaTokenV2, req);
const code = await TokenService.createToken({
type: TOKEN_EMAIL_MFA,
email
email: req.user.email
});
// send MFA code [code] to [email]
await sendMail({
template: "emailMfa.handlebars",
subjectLine: "Infisical MFA code",
recipients: [email],
recipients: [req.user.email],
substitutions: {
code
}
@ -236,17 +232,17 @@ export const sendMfaToken = async (req: Request, res: Response) => {
*/
export const verifyMfaToken = async (req: Request, res: Response) => {
const {
body: { email, mfaToken }
body: { mfaToken }
} = await validateRequest(reqValidator.VerifyMfaTokenV2, req);
await TokenService.validateToken({
type: TOKEN_EMAIL_MFA,
email,
email: req.user.email,
token: mfaToken
});
const user = await User.findOne({
email
email: req.user.email
}).select(
"+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag +devices"
);

View File

@ -26,7 +26,7 @@ router.post(
);
//remove above ones after depreciation
router.post("/mfa/send", authLimiter, authController.sendMfaToken);
router.post("/mfa/send", authLimiter, requireMfaAuth, authController.sendMfaToken);
router.post("/mfa/verify", authLimiter, requireMfaAuth, authController.verifyMfaToken);

View File

@ -84,15 +84,8 @@ export const ResetPasswordV1 = z.object({
})
});
export const SendMfaTokenV2 = z.object({
body: z.object({
email: z.string().email().trim()
})
});
export const VerifyMfaTokenV2 = z.object({
body: z.object({
email: z.string().email().trim(),
mfaToken: z.string().trim()
})
});

View File

@ -429,6 +429,9 @@ export const UpdateSecretByNameBatchV3 = z.object({
secretValueCiphertext: z.string().trim(),
secretValueIV: z.string().trim(),
secretValueTag: z.string().trim(),
secretKeyCiphertext: z.string().trim(),
secretKeyIV: z.string().trim(),
secretKeyTag: z.string().trim(),
secretCommentCiphertext: z.string().trim().optional(),
secretCommentIV: z.string().trim().optional(),
secretCommentTag: z.string().trim().optional(),

View File

@ -1,6 +1,6 @@
---
title: "PostgreSQL/CockroachDB"
description: "Rotated database user password of a postgreSQL or cochroach db"
description: "Rotated database user password of a postgreSQL or cockroach db"
---
Infisical will update periodically the provided database user's password.

View File

@ -161,12 +161,65 @@ Default re-sync interval is every 1 minute.
</Accordion>
<Accordion title="managedSecretReference">
The `managedSecretReference` field in the InfisicalSecret resource is used to specify the location where secrets retrieved from an Infisical project should be stored.
You should specify the name and namespace of the Kubernetes secret that will hold these secrets. The operator will create the secret for you, you just need to provide its name and namespace.
The `managedSecretReference` field is used to define the target location for storing secrets retrieved from an Infisical project.
This field requires specifying both the name and namespace of the Kubernetes secret that will hold these secrets.
The Infisical operator will automatically create the Kubernetes secret with the specified name/namespace and keep it continuously updated.
The managed secret be should be created in the same namespace as the deployment that will use it.
Note: The managed secret be should be created in the same namespace as the deployment that will use it.
</Accordion>
<Accordion title="managedSecretReference.secretName">
The name of the managed Kubernetes secret to be created
</Accordion>
<Accordion title="managedSecretReference.secretNamespace">
The namespace of the managed Kubernetes secret to be created.
</Accordion>
<Accordion title="managedSecretReference.secretType">
Override the default Opaque type for managed secrets with this field. Useful for creating kubernetes.io/dockerconfigjson secrets.
</Accordion>
### Propagating labels & annotations
The operator will transfer all labels & annotations present on the `InfisicalSecret` CRD to the managed Kubernetes secret to be created.
Thus, if a specific label is required on the resulting secret, it can be applied as demonstrated in the following example:
<Accordion title="Example propagation">
```yaml
apiVersion: secrets.infisical.com/v1alpha1
kind: InfisicalSecret
metadata:
name: infisicalsecret-sample
labels:
label-to-be-passed-to-managed-secret: sample-value
annotations:
example.com/annotation-to-be-passed-to-managed-secret: "sample-value"
spec:
..
authentication:
...
managedSecretReference:
...
```
This would result in the following managed secret to be created:
```yaml
apiVersion: v1
data:
...
kind: Secret
metadata:
annotations:
example.com/annotation-to-be-passed-to-managed-secret: sample-value
secrets.infisical.com/version: W/"3f1-ZyOSsrCLGSkAhhCkY2USPu2ivRw"
labels:
label-to-be-passed-to-managed-secret: sample-value
name: managed-token
namespace: default
type: Opaque
```
</Accordion>
### Apply the Infisical CRD to your cluster
Once you have configured the Infisical CRD with the required fields, you can apply it to your cluster.

View File

@ -38,7 +38,7 @@ Other environment variables are listed below to increase the functionality of yo
Credential to connect to host (e.g. team@infisical.com)
</ParamField>
<ParamField query="SMTP_PASSWORD" type="string" default="587" optional>
<ParamField query="SMTP_PASSWORD" type="string" default="none" optional>
Credential to connect to host
</ParamField>

View File

@ -14,6 +14,7 @@ import { Button, Modal, ModalContent } from "@app/components/v2";
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context";
import { usePopUp, useToggle } from "@app/hooks";
import { useCreateSecretBatch, useUpdateSecretBatch } from "@app/hooks/api";
import { secretApprovalRequestKeys } from "@app/hooks/api/secretApprovalRequest/queries";
import { secretKeys } from "@app/hooks/api/secrets/queries";
import { DecryptedSecret, UserWsKeyPair } from "@app/hooks/api/types";
@ -194,6 +195,7 @@ export const SecretDropzone = ({
queryClient.invalidateQueries(
secretKeys.getProjectSecret({ workspaceId, environment, secretPath })
);
queryClient.invalidateQueries(secretApprovalRequestKeys.count({ workspaceId }));
handlePopUpClose("overlapKeyWarning");
createNotification({
type: "success",
@ -222,9 +224,9 @@ export const SecretDropzone = ({
onDragOver={handleDrag}
onDrop={handleDrop}
className={twMerge(
"relative mx-0.5 mb-4 mt-4 flex cursor-pointer items-center justify-center rounded-md bg-mineshaft-900 py-4 text-sm px-2 text-mineshaft-200 opacity-60 outline-dashed outline-2 outline-chicago-600 duration-200 hover:opacity-100",
"relative mx-0.5 mb-4 mt-4 flex cursor-pointer items-center justify-center rounded-md bg-mineshaft-900 py-4 px-2 text-sm text-mineshaft-200 opacity-60 outline-dashed outline-2 outline-chicago-600 duration-200 hover:opacity-100",
isDragActive && "opacity-100",
!isSmaller && "w-full max-w-3xl flex-col space-y-4 py-20 mx-auto",
!isSmaller && "mx-auto w-full max-w-3xl flex-col space-y-4 py-20",
isLoading && "bg-bunker-800"
)}
>
@ -238,7 +240,7 @@ export const SecretDropzone = ({
/>
</div>
) : (
<div className="flex items-center justify-cente flex-col space-y-2">
<div className="justify-cente flex flex-col items-center space-y-2">
<div>
<FontAwesomeIcon icon={faUpload} size={isSmaller ? "2x" : "5x"} />
</div>

View File

@ -7,6 +7,7 @@ import { CreateTagModal } from "@app/components/tags/CreateTagModal";
import { DeleteActionModal } from "@app/components/v2";
import { usePopUp } from "@app/hooks";
import { useCreateSecretV3, useDeleteSecretV3, useUpdateSecretV3 } from "@app/hooks/api";
import { secretApprovalRequestKeys } from "@app/hooks/api/secretApprovalRequest/queries";
import { secretKeys } from "@app/hooks/api/secrets/queries";
import { DecryptedSecret } from "@app/hooks/api/secrets/types";
import { secretSnapshotKeys } from "@app/hooks/api/secretSnapshots/queries";
@ -262,6 +263,7 @@ export const SecretListView = ({
queryClient.invalidateQueries(
secretSnapshotKeys.count({ workspaceId, environment, directory: secretPath })
);
queryClient.invalidateQueries(secretApprovalRequestKeys.count({ workspaceId }));
handlePopUpClose("secretDetail");
createNotification({
type: "success",
@ -284,6 +286,7 @@ export const SecretListView = ({
const { key, _id: secretId } = popUp.deleteSecret?.data as DecryptedSecret;
try {
await handleSecretOperation("delete", "shared", key, { secretId });
// wrap this in another function and then reuse
queryClient.invalidateQueries(
secretKeys.getProjectSecret({ workspaceId, environment, secretPath })
);
@ -293,6 +296,7 @@ export const SecretListView = ({
queryClient.invalidateQueries(
secretSnapshotKeys.count({ workspaceId, environment, directory: secretPath })
);
queryClient.invalidateQueries(secretApprovalRequestKeys.count({ workspaceId }));
handlePopUpClose("deleteSecret");
handlePopUpClose("secretDetail");
createNotification({

View File

@ -41,7 +41,7 @@ import {
} from "@app/hooks/api";
import { FolderBreadCrumbs } from "./components/FolderBreadCrumbs";
import { ProjectIndexSecretsSection } from "./components/ProjectIndexSecretsSection";
// import { ProjectIndexSecretsSection } from "./components/ProjectIndexSecretsSection";
import { SecretOverviewFolderRow } from "./components/SecretOverviewFolderRow";
import { SecretOverviewTableRow } from "./components/SecretOverviewTableRow";
@ -260,7 +260,7 @@ export const SecretOverviewPage = () => {
return (
<div className="container mx-auto px-6 text-mineshaft-50 dark:[color-scheme:dark]">
<ProjectIndexSecretsSection decryptFileKey={latestFileKey!} />
{/* <ProjectIndexSecretsSection decryptFileKey={latestFileKey!} /> */}
<div className="relative right-5 ml-4">
<NavHeader pageName={t("dashboard.title")} isProjectRelated />
</div>

View File

@ -13,7 +13,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.2.1
version: 0.3.1
# 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
# follow Semantic Versioning. They should reflect the version the application is using.

View File

@ -102,6 +102,11 @@ spec:
secretNamespace:
description: The name space where the Kubernetes Secret is located
type: string
secretType:
default: Opaque
description: 'The Kubernetes Secret type (experimental feature).
More info: https://kubernetes.io/docs/concepts/configuration/secret/#secret-types'
type: string
required:
- secretName
- secretNamespace

View File

@ -43,6 +43,21 @@ type KubeSecretReference struct {
SecretNamespace string `json:"secretNamespace"`
}
type MangedKubeSecretConfig struct {
// The name of the Kubernetes Secret
// +kubebuilder:validation:Required
SecretName string `json:"secretName"`
// The name space where the Kubernetes Secret is located
// +kubebuilder:validation:Required
SecretNamespace string `json:"secretNamespace"`
// The Kubernetes Secret type (experimental feature). More info: https://kubernetes.io/docs/concepts/configuration/secret/#secret-types
// +kubebuilder:validation:Optional
// +kubebuilder:default:=Opaque
SecretType string `json:"secretType"`
}
// InfisicalSecretSpec defines the desired state of InfisicalSecret
type InfisicalSecretSpec struct {
// +kubebuilder:validation:Optional
@ -52,7 +67,7 @@ type InfisicalSecretSpec struct {
Authentication Authentication `json:"authentication"`
// +kubebuilder:validation:Required
ManagedSecretReference KubeSecretReference `json:"managedSecretReference"`
ManagedSecretReference MangedKubeSecretConfig `json:"managedSecretReference"`
// +kubebuilder:default:=60
ResyncInterval int `json:"resyncInterval"`

View File

@ -157,6 +157,21 @@ func (in *KubeSecretReference) DeepCopy() *KubeSecretReference {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MangedKubeSecretConfig) DeepCopyInto(out *MangedKubeSecretConfig) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MangedKubeSecretConfig.
func (in *MangedKubeSecretConfig) DeepCopy() *MangedKubeSecretConfig {
if in == nil {
return nil
}
out := new(MangedKubeSecretConfig)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SecretScopeInWorkspace) DeepCopyInto(out *SecretScopeInWorkspace) {
*out = *in

View File

@ -102,6 +102,11 @@ spec:
secretNamespace:
description: The name space where the Kubernetes Secret is located
type: string
secretType:
default: Opaque
description: 'The Kubernetes Secret type (experimental feature).
More info: https://kubernetes.io/docs/concepts/configuration/secret/#secret-types'
type: string
required:
- secretName
- secretNamespace

View File

@ -2,8 +2,12 @@ apiVersion: secrets.infisical.com/v1alpha1
kind: InfisicalSecret
metadata:
name: infisicalsecret-sample
labels:
label-to-be-passed-to-managed-secret: sample-value
annotations:
example.com/annotation-to-be-passed-to-managed-secret: "sample-value"
spec:
hostAPI: http://localhost:8764/api
hostAPI: https://app.infisical.com/api
resyncInterval: 10
authentication:
serviceAccount:
@ -22,6 +26,8 @@ spec:
managedSecretReference:
secretName: managed-secret
secretNamespace: default
# secretType: kubernetes.io/dockerconfigjson
# # To be depreciated soon
# tokenSecretReference:
# secretName: service-token

View File

@ -36,6 +36,8 @@ func (r *InfisicalSecretReconciler) ReconcileDeploymentsWithManagedSecrets(ctx c
var wg sync.WaitGroup
// Iterate over the deployments and check if they use the managed secret
for _, deployment := range listOfDeployments.Items {
// Adding bc of https://github.com/golang/go/issues/16520
deployment := deployment
if deployment.Annotations[AUTO_RELOAD_DEPLOYMENT_ANNOTATION] == "true" && r.IsDeploymentUsingManagedSecret(deployment, infisicalSecret) {
// Start a goroutine to reconcile the deployment
wg.Add(1)

View File

@ -72,7 +72,6 @@ func (r *InfisicalSecretReconciler) GetInfisicalTokenFromKubeSecret(ctx context.
// default to new secret ref structure
secretName := infisicalSecret.Spec.Authentication.ServiceToken.ServiceTokenSecretReference.SecretName
secretNamespace := infisicalSecret.Spec.Authentication.ServiceToken.ServiceTokenSecretReference.SecretNamespace
// fall back to previous secret ref
if secretName == "" {
secretName = infisicalSecret.Spec.TokenSecretReference.SecretName
@ -129,20 +128,34 @@ func (r *InfisicalSecretReconciler) GetInfisicalServiceAccountCredentialsFromKub
func (r *InfisicalSecretReconciler) CreateInfisicalManagedKubeSecret(ctx context.Context, infisicalSecret v1alpha1.InfisicalSecret, secretsFromAPI []model.SingleEnvironmentVariable, encryptedSecretsResponse api.GetEncryptedSecretsV3Response) error {
plainProcessedSecrets := make(map[string][]byte)
secretType := infisicalSecret.Spec.ManagedSecretReference.SecretType
for _, secret := range secretsFromAPI {
plainProcessedSecrets[secret.Key] = []byte(secret.Value) // plain process
}
// copy labels and annotations from InfisicalSecret CRD
labels := map[string]string{}
for k, v := range infisicalSecret.Labels {
labels[k] = v
}
annotations := map[string]string{}
for k, v := range infisicalSecret.Annotations {
annotations[k] = v
}
annotations[SECRET_VERSION_ANNOTATION] = encryptedSecretsResponse.ETag
// create a new secret as specified by the managed secret spec of CRD
newKubeSecretInstance := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: infisicalSecret.Spec.ManagedSecretReference.SecretName,
Namespace: infisicalSecret.Spec.ManagedSecretReference.SecretNamespace,
Annotations: map[string]string{
SECRET_VERSION_ANNOTATION: encryptedSecretsResponse.ETag,
},
Name: infisicalSecret.Spec.ManagedSecretReference.SecretName,
Namespace: infisicalSecret.Spec.ManagedSecretReference.SecretNamespace,
Annotations: annotations,
Labels: labels,
},
Type: "Opaque",
Type: corev1.SecretType(secretType),
Data: plainProcessedSecrets,
}
@ -151,7 +164,7 @@ func (r *InfisicalSecretReconciler) CreateInfisicalManagedKubeSecret(ctx context
return fmt.Errorf("unable to create the managed Kubernetes secret : %w", err)
}
fmt.Println("Successfully created a managed Kubernetes secret with your Infisical secrets")
fmt.Printf("Successfully created a managed Kubernetes secret with your Infisical secrets. Type: %s\n", secretType)
return nil
}

View File

@ -108,6 +108,10 @@ spec:
secretNamespace:
description: The name space where the Kubernetes Secret is located
type: string
secretType:
default: Opaque
description: 'The Kubernetes Secret type (experimental feature). More info: https://kubernetes.io/docs/concepts/configuration/secret/#secret-types'
type: string
required:
- secretName
- secretNamespace