Compare commits

...

7 Commits

Author SHA1 Message Date
=
6826b1c242 feat: made review changed 2025-08-04 23:36:05 +05:30
Daniel Hougaard
35012fde03 fix: added ldap identity auth example 2025-08-04 21:57:07 +04:00
=
4b9e57ae61 feat: review changes for reptile 2025-08-01 21:10:26 +05:30
Akhil Mohan
eb27983990 Update k8-operator/packages/util/kubernetes.go
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2025-08-01 21:08:33 +05:30
=
fa311b032c feat: removed comments 2025-08-01 21:06:17 +05:30
=
71651f85fe docs: ldap auth in operator 2025-08-01 21:04:44 +05:30
=
d28d3449de feat: added ldap authentication to operator 2025-08-01 21:04:29 +05:30
20 changed files with 726 additions and 363 deletions

View File

@@ -68,6 +68,11 @@ spec:
serviceAccountKeyFilePath: </path-to-service-account-key-file.json>
gcpIdTokenAuth:
identityId: <machine-identity-id>
ldapAuth:
identityId: <machine-identity-id>
credentialsRef:
secretName: <secret-name> # ldap-auth-credentials
secretNamespace: <secret-namespace> # default
kubernetesAuth:
identityId: <machine-identity-id>
serviceAccountRef:
@@ -137,6 +142,7 @@ When `hostAPI` is not defined the operator fetches secrets from Infisical Cloud.
<Note>
The lease duration at most be 1 day (24 hours). And the TTL must be less than the max TTL defined on the dynamic secret.
</Note>
</Accordion>
@@ -300,7 +306,6 @@ The available authentication methods are `universalAuth`, `kubernetesAuth`, `aws
- `autoCreateServiceAccountToken`: If set to `true`, the operator will automatically create a short-lived service account token on-demand for the service account. Defaults to `false`.
- `serviceAccountTokenAudiences`: Optionally specify audience for the service account token. This field is only relevant if you have set `autoCreateServiceAccountToken` to `true`. No audience is specified by default.
Example:
```yaml
@@ -316,7 +321,40 @@ The available authentication methods are `universalAuth`, `kubernetesAuth`, `aws
```
</Accordion>
<Accordion title="ldapAuth">
The LDAP machine identity authentication method is used to authenticate with a configured LDAP directory. [Read more about LDAP Auth](/documentation/platform/identities/ldap-auth).
Valid fields:
- `identityId`: The identity ID of the machine identity you created.
- `credentialsRef`: The name and namespace of the Kubernetes secret that stores the LDAP credentials.
- `credentialsRef.secretName`: The name of the Kubernetes secret.
- `credentialsRef.secretNamespace`: The namespace of the Kubernetes secret.
Example:
```yaml
# infisical-push-secret.yaml
spec:
ldapAuth:
identityId: <machine-identity-id>
credentialsRef:
secretName: <secret-name>
secretNamespace: <secret-namespace>
```
```yaml
# machine-identity-credentials.yaml
apiVersion: v1
kind: Secret
metadata:
name: ldap-auth-credentials
type: Opaque
stringData:
username: <ldap-username>
password: <ldap-password>
```
</Accordion>
<Accordion title="awsIamAuth">
The AWS IAM machine identity authentication method is used to authenticate with Infisical.
[Read more about AWS IAM Auth](/documentation/platform/identities/aws-auth).

View File

@@ -70,6 +70,11 @@ Before applying the InfisicalPushSecret CRD, you need to create a Kubernetes sec
serviceAccountRef:
name: <secret-name>
namespace: <secret-namespace>
ldapAuth:
identityId: <machine-identity-id>
credentialsRef:
secretName: <secret-name> # ldap-auth-credentials
secretNamespace: <secret-namespace> # default
universalAuth:
credentialsRef:
secretName: <secret-name> # universal-auth-credentials
@@ -324,7 +329,39 @@ After applying the InfisicalPushSecret CRD, you should notice that the secrets y
namespace: <secret-namespace>
```
</Accordion>
<Accordion title="ldapAuth">
The LDAP machine identity authentication method is used to authenticate with a configured LDAP directory. [Read more about LDAP Auth](/documentation/platform/identities/ldap-auth).
Valid fields:
- `identityId`: The identity ID of the machine identity you created.
- `credentialsRef`: The name and namespace of the Kubernetes secret that stores the LDAP credentials.
- `credentialsRef.secretName`: The name of the Kubernetes secret.
- `credentialsRef.secretNamespace`: The namespace of the Kubernetes secret.
Example:
```yaml
# infisical-push-secret.yaml
spec:
ldapAuth:
identityId: <machine-identity-id>
credentialsRef:
secretName: <secret-name>
secretNamespace: <secret-namespace>
```
```yaml
# machine-identity-credentials.yaml
apiVersion: v1
kind: Secret
metadata:
name: ldap-auth-credentials
type: Opaque
stringData:
username: <ldap-username>
password: <ldap-password>
```
</Accordion>
<Accordion title="awsIamAuth">
The AWS IAM machine identity authentication method is used to authenticate with Infisical.
[Read more about AWS IAM Auth](/documentation/platform/identities/aws-auth).

View File

@@ -525,49 +525,6 @@ spec:
...
```
</Tab>
</Tabs>
@@ -747,6 +704,59 @@ spec:
</Accordion>
<Accordion title="authentication.ldapAuth">
The LDAP machine identity authentication method is used to authenticate with Infisical using the configured LDAP directory. The username and password needs to be stored in a Kubernetes secret. This block defines the reference to the name and namespace of secret that stores these credentials.
<Steps>
<Step title="Create a machine identity">
You need to create a machine identity, and give it access to the project(s) you want to interact with. You can [read more about machine identities here](/documentation/platform/identities/universal-auth).
</Step>
<Step title="Create Kubernetes secret containing machine identity credentials">
Once you have created your machine identity and added it to your project(s), you will need to create a Kubernetes secret containing the identity credentials.
To quickly create a Kubernetes secret containing the identity credentials, you can run the command below.
Make sure you replace `<your-identity-ldap-username>` with the identity LDAP username and `<your-identity-ldap-password>` with the identity LDAP password.
``` bash
kubectl create secret generic ldap-auth-credentials --from-literal=username="<your-identity-ldap-username>" --from-literal=password="<your-identity-ldap-password>"
```
</Step>
<Step title="Add reference for the Kubernetes secret containing the identity credentials">
Once the secret is created, add the `secretName` and `secretNamespace` of the secret that was just created under `authentication.ldapAuth.credentialsRef` field in the InfisicalSecret resource.
</Step>
</Steps>
<Info>
Make sure to also populate the `secretsScope` field with the project slug
_`projectSlug`_, environment slug _`envSlug`_, and secrets path
_`secretsPath`_ that you want to fetch secrets from. Please see the example
below.
</Info>
## Example
```yaml
apiVersion: secrets.infisical.com/v1alpha1
kind: InfisicalSecret
metadata:
name: infisicalsecret-sample-crd
spec:
authentication:
ldapAuth:
secretsScope:
projectSlug: <project-slug> # <-- project slug
envSlug: <env-slug> # "dev", "staging", "prod", etc..
secretsPath: "<secrets-path>" # Root is "/"
identityId: <machine-identity-id>
credentialsRef:
secretName: ldap-auth-credentials # <-- name of the Kubernetes secret that stores our machine identity credentials
secretNamespace: default # <-- namespace of the Kubernetes secret that stores our machine identity credentials
```
</Accordion>
<Accordion title="authentication.serviceToken">
The service token required to authenticate with Infisical needs to be stored in a Kubernetes secret. This block defines the reference to the name and namespace of secret that stores this service token.
@@ -928,7 +938,9 @@ The properties includes defining the name and namespace of the Kubernetes config
The Infisical operator will automatically create the Kubernetes config map in the specified name/namespace and ensure it stays up-to-date. If a config map already exists in the specified namespace, the operator will update the existing config map with the new data.
<Warning>
The usage of config maps is only intended for storing non-sensitive data. If you are looking to store sensitive data, please use the [managed secret](#operator-managed-secrets) property instead.
The usage of config maps is only intended for storing non-sensitive data. If
you are looking to store sensitive data, please use the [managed
secret](#operator-managed-secrets) property instead.
</Warning>
<Accordion title="managedKubeConfigMapReferences">
@@ -955,7 +967,6 @@ The Infisical operator will automatically create the Kubernetes config map in th
</Accordion>
#### Managed ConfigMap Templating
Fetching secrets from Infisical as is via the operator may not be enough. This is where templating functionality may be helpful.
@@ -1025,6 +1036,7 @@ Using Go templates, you can format, combine, and create new key-value pairs from
### Available templating functions
Please refer to the [templating functions documentation](/integrations/platforms/kubernetes/overview#available-helper-functions) for more information.
</Accordion>
## Applying CRD
@@ -1061,8 +1073,6 @@ To verify that the operator has successfully created the managed secret, you can
</Tab>
</Tabs>
## Using Managed Secret In Your Deployment
To make use of the managed secret created by the operator into your deployment can be achieved through several methods.
@@ -1150,6 +1160,7 @@ Here, we will highlight three of the most common ways to utilize it. Learn more
ports:
- containerPort: 80
```
</Accordion>
<Accordion title="volumes">
@@ -1339,9 +1350,11 @@ secrets.infisical.com/auto-reload: "true"
</Accordion>
<Info>
#### How it works
When a managed secret is updated, the operator checks for any Deployments, DaemonSets, or StatefulSets that consume the updated secret and have the annotation
`secrets.infisical.com/auto-reload: "true"`. For each matching workload, the operator triggers a rolling restart to ensure it picks up the latest secret values.
#### How it works When a managed secret is updated, the operator checks for
any Deployments, DaemonSets, or StatefulSets that consume the updated secret
and have the annotation `secrets.infisical.com/auto-reload: "true"`. For each
matching workload, the operator triggers a rolling restart to ensure it picks
up the latest secret values.
</Info>
## Using Managed ConfigMap In Your Deployment
@@ -1350,10 +1363,10 @@ To make use of the managed ConfigMap created by the operator into your deploymen
Here, we will highlight three of the most common ways to utilize it. Learn more about Kubernetes ConfigMaps [here](https://kubernetes.io/docs/concepts/configuration/configmap/)
<Tip>
Automatic redeployment of deployments using managed ConfigMaps is not yet supported.
Automatic redeployment of deployments using managed ConfigMaps is not yet
supported.
</Tip>
<Accordion title="envFrom">
This will take all the secrets from your managed ConfigMap and expose them to your container
@@ -1490,6 +1503,7 @@ Here, we will highlight three of the most common ways to utilize it. Learn more
configMap:
name: managed-configmap # <- managed configmap
```
</Accordion>
The definition file of the Kubernetes secret for the CA certificate can be structured like the following:
@@ -1548,4 +1562,5 @@ Thus, if a specific label is required on the resulting secret, it can be applied
namespace: default
type: Opaque
```
</Accordion>

View File

@@ -13,6 +13,8 @@ type GenericInfisicalAuthentication struct {
GcpIdTokenAuth GenericGcpIdTokenAuth `json:"gcpIdTokenAuth,omitempty"`
// +kubebuilder:validation:Optional
GcpIamAuth GenericGcpIamAuth `json:"gcpIamAuth,omitempty"`
// +kubebuilder:validation:Optional
LdapAuth GenericLdapAuth `json:"ldapAuth,omitempty"`
}
type GenericUniversalAuth struct {
@@ -20,6 +22,13 @@ type GenericUniversalAuth struct {
CredentialsRef KubeSecretReference `json:"credentialsRef"`
}
type GenericLdapAuth struct {
// +kubebuilder:validation:Required
IdentityID string `json:"identityId"`
// +kubebuilder:validation:Required
CredentialsRef KubeSecretReference `json:"credentialsRef"`
}
type GenericAwsIamAuth struct {
// +kubebuilder:validation:Required
IdentityID string `json:"identityId"`

View File

@@ -21,6 +21,8 @@ type Authentication struct {
GcpIdTokenAuth GCPIdTokenAuthDetails `json:"gcpIdTokenAuth"`
// +kubebuilder:validation:Optional
GcpIamAuth GcpIamAuthDetails `json:"gcpIamAuth"`
// +kubebuilder:validation:Optional
LdapAuth LdapAuthDetails `json:"ldapAuth"`
}
type UniversalAuthDetails struct {
@@ -30,6 +32,15 @@ type UniversalAuthDetails struct {
SecretsScope MachineIdentityScopeInWorkspace `json:"secretsScope"`
}
type LdapAuthDetails struct {
// +kubebuilder:validation:Required
IdentityID string `json:"identityId"`
// +kubebuilder:validation:Required
CredentialsRef KubeSecretReference `json:"credentialsRef"`
// +kubebuilder:validation:Required
SecretsScope MachineIdentityScopeInWorkspace `json:"secretsScope"`
}
type KubernetesAuthDetails struct {
// +kubebuilder:validation:Required
IdentityID string `json:"identityId"`

View File

@@ -53,6 +53,7 @@ func (in *Authentication) DeepCopyInto(out *Authentication) {
out.AzureAuth = in.AzureAuth
out.GcpIdTokenAuth = in.GcpIdTokenAuth
out.GcpIamAuth = in.GcpIamAuth
out.LdapAuth = in.LdapAuth
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Authentication.
@@ -326,6 +327,7 @@ func (in *GenericInfisicalAuthentication) DeepCopyInto(out *GenericInfisicalAuth
out.AzureAuth = in.AzureAuth
out.GcpIdTokenAuth = in.GcpIdTokenAuth
out.GcpIamAuth = in.GcpIamAuth
out.LdapAuth = in.LdapAuth
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenericInfisicalAuthentication.
@@ -359,6 +361,22 @@ func (in *GenericKubernetesAuth) DeepCopy() *GenericKubernetesAuth {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GenericLdapAuth) DeepCopyInto(out *GenericLdapAuth) {
*out = *in
out.CredentialsRef = in.CredentialsRef
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenericLdapAuth.
func (in *GenericLdapAuth) DeepCopy() *GenericLdapAuth {
if in == nil {
return nil
}
out := new(GenericLdapAuth)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GenericUniversalAuth) DeepCopyInto(out *GenericUniversalAuth) {
*out = *in
@@ -810,6 +828,23 @@ func (in *KubernetesServiceAccountRef) DeepCopy() *KubernetesServiceAccountRef {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LdapAuthDetails) DeepCopyInto(out *LdapAuthDetails) {
*out = *in
out.CredentialsRef = in.CredentialsRef
out.SecretsScope = in.SecretsScope
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LdapAuthDetails.
func (in *LdapAuthDetails) DeepCopy() *LdapAuthDetails {
if in == nil {
return nil
}
out := new(LdapAuthDetails)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MachineIdentityScopeInWorkspace) DeepCopyInto(out *MachineIdentityScopeInWorkspace) {
*out = *in

View File

@@ -103,6 +103,27 @@ spec:
- identityId
- serviceAccountRef
type: object
ldapAuth:
properties:
credentialsRef:
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
identityId:
type: string
required:
- credentialsRef
- identityId
type: object
universalAuth:
properties:
credentialsRef:

View File

@@ -103,6 +103,27 @@ spec:
- identityId
- serviceAccountRef
type: object
ldapAuth:
properties:
credentialsRef:
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
identityId:
type: string
required:
- credentialsRef
- identityId
type: object
universalAuth:
properties:
credentialsRef:

View File

@@ -181,6 +181,43 @@ spec:
- secretsScope
- serviceAccountRef
type: object
ldapAuth:
properties:
credentialsRef:
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
identityId:
type: string
secretsScope:
properties:
envSlug:
type: string
projectSlug:
type: string
recursive:
type: boolean
secretsPath:
type: string
required:
- envSlug
- projectSlug
- secretsPath
type: object
required:
- credentialsRef
- identityId
- secretsScope
type: object
serviceAccount:
properties:
environmentName:

View File

@@ -65,6 +65,19 @@ spec:
secretsPath: "/path"
recursive: true
ldapAuth:
identityId: <machine-identity-id>
credentialsRef:
secretName: <secret-name> # ldap-auth-credentials
secretNamespace: <secret-namespace> # default
# secretsScope is identical to the secrets scope in the universalAuth field in this sample.
secretsScope:
projectSlug: your-project-slug
envSlug: prod
secretsPath: "/path"
recursive: true
# Azure Auth
azureAuth:
identityId: <your-machine-identity-id>

View File

@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: ldap-auth-credentials
type: Opaque
stringData:
username: <ldap-username>
password: <ldap-password>

View File

@@ -85,6 +85,7 @@ func (r *InfisicalDynamicSecretReconciler) handleAuthentication(ctx context.Cont
util.AuthStrategy.AZURE_MACHINE_IDENTITY: util.HandleAzureAuth,
util.AuthStrategy.GCP_ID_TOKEN_MACHINE_IDENTITY: util.HandleGcpIdTokenAuth,
util.AuthStrategy.GCP_IAM_MACHINE_IDENTITY: util.HandleGcpIamAuth,
util.AuthStrategy.LDAP_MACHINE_IDENTITY: util.HandleLdapAuth,
}
for authStrategy, authHandler := range authStrategies {

View File

@@ -32,6 +32,7 @@ func (r *InfisicalPushSecretReconciler) handleAuthentication(ctx context.Context
util.AuthStrategy.AZURE_MACHINE_IDENTITY: util.HandleAzureAuth,
util.AuthStrategy.GCP_ID_TOKEN_MACHINE_IDENTITY: util.HandleGcpIdTokenAuth,
util.AuthStrategy.GCP_IAM_MACHINE_IDENTITY: util.HandleGcpIamAuth,
util.AuthStrategy.LDAP_MACHINE_IDENTITY: util.HandleLdapAuth,
}
for authStrategy, authHandler := range authStrategies {

View File

@@ -57,6 +57,7 @@ func (r *InfisicalSecretReconciler) handleAuthentication(ctx context.Context, in
util.AuthStrategy.AZURE_MACHINE_IDENTITY: util.HandleAzureAuth,
util.AuthStrategy.GCP_ID_TOKEN_MACHINE_IDENTITY: util.HandleGcpIdTokenAuth,
util.AuthStrategy.GCP_IAM_MACHINE_IDENTITY: util.HandleGcpIamAuth,
util.AuthStrategy.LDAP_MACHINE_IDENTITY: util.HandleLdapAuth,
}
for authStrategy, authHandler := range authStrategies {

View File

@@ -5,7 +5,7 @@ go 1.21
require (
github.com/Masterminds/sprig/v3 v3.3.0
github.com/aws/smithy-go v1.20.3
github.com/infisical/go-sdk v0.5.97
github.com/infisical/go-sdk v0.5.99
github.com/lestrrat-go/jwx/v2 v2.1.4
github.com/onsi/ginkgo/v2 v2.6.0
github.com/onsi/gomega v1.24.1
@@ -40,6 +40,7 @@ require (
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/goccy/go-json v0.10.3 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.5 // indirect
@@ -52,9 +53,12 @@ require (
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/oracle/oci-go-sdk/v65 v65.95.2 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sony/gobreaker v0.5.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect

View File

@@ -152,6 +152,8 @@ github.com/go-resty/resty/v2 v2.13.1/go.mod h1:GznXlLxkq6Nh4sU59rPmUw3VtgpO3aS96
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
@@ -237,6 +239,8 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/infisical/go-sdk v0.5.97 h1:veOi6Hduda6emtwjdUI5SBg2qd2iDQc5xLKqZ15KSoM=
github.com/infisical/go-sdk v0.5.97/go.mod h1:ExjqFLRz7LSpZpGluqDLvFl6dFBLq5LKyLW7GBaMAIs=
github.com/infisical/go-sdk v0.5.99 h1:trvn7JhKYuSzDkc44h+yqToVjclkrRyP42t315k5kEE=
github.com/infisical/go-sdk v0.5.99/go.mod h1:j2D2a5WPNdKXDfHO+3y/TNyLWh5Aq9QYS7EcGI96LZI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
@@ -303,6 +307,8 @@ github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc=
github.com/onsi/ginkgo/v2 v2.6.0/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E=
github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
github.com/oracle/oci-go-sdk/v65 v65.95.2 h1:0HJ0AgpLydp/DtvYrF2d4str2BjXOVAeNbuW7E07g94=
github.com/oracle/oci-go-sdk/v65 v65.95.2/go.mod h1:u6XRPsw9tPziBh76K7GrrRXPa8P8W3BQeqJ6ZZt9VLA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -347,6 +353,8 @@ github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+D
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg=
github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -365,8 +373,11 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -407,6 +418,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
@@ -551,6 +563,7 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
@@ -559,6 +572,7 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=

View File

@@ -6,11 +6,16 @@ type ServiceAccountDetails struct {
PrivateKey string
}
type MachineIdentityDetails struct {
type UniversalAuthIdentityDetails struct {
ClientId string
ClientSecret string
}
type LdapIdentityDetails struct {
Username string
Password string
}
type SingleEnvironmentVariable struct {
Key string `json:"key"`
Value string `json:"value"`

View File

@@ -88,6 +88,7 @@ var AuthStrategy = struct {
AZURE_MACHINE_IDENTITY AuthStrategyType
GCP_ID_TOKEN_MACHINE_IDENTITY AuthStrategyType
GCP_IAM_MACHINE_IDENTITY AuthStrategyType
LDAP_MACHINE_IDENTITY AuthStrategyType
}{
SERVICE_TOKEN: "SERVICE_TOKEN",
SERVICE_ACCOUNT: "SERVICE_ACCOUNT",
@@ -97,6 +98,7 @@ var AuthStrategy = struct {
AZURE_MACHINE_IDENTITY: "AZURE_MACHINE_IDENTITY",
GCP_ID_TOKEN_MACHINE_IDENTITY: "GCP_ID_TOKEN_MACHINE_IDENTITY",
GCP_IAM_MACHINE_IDENTITY: "GCP_IAM_MACHINE_IDENTITY",
LDAP_MACHINE_IDENTITY: "LDAP_MACHINE_IDENTITY",
}
type SecretCrdType string
@@ -188,6 +190,71 @@ func HandleUniversalAuth(ctx context.Context, reconcilerClient client.Client, se
}, nil
}
func HandleLdapAuth(ctx context.Context, reconcilerClient client.Client, secretCrd SecretAuthInput, infisicalClient infisicalSdk.InfisicalClientInterface) (AuthenticationDetails, error) {
var ldapAuthSpec v1alpha1.LdapAuthDetails
switch secretCrd.Type {
case SecretCrd.INFISICAL_SECRET:
infisicalSecret, ok := secretCrd.Secret.(v1alpha1.InfisicalSecret)
if !ok {
return AuthenticationDetails{}, errors.New("unable to cast secret to InfisicalSecret")
}
ldapAuthSpec = infisicalSecret.Spec.Authentication.LdapAuth
case SecretCrd.INFISICAL_PUSH_SECRET:
infisicalPushSecret, ok := secretCrd.Secret.(v1alpha1.InfisicalPushSecret)
if !ok {
return AuthenticationDetails{}, errors.New("unable to cast secret to InfisicalPushSecret")
}
ldapAuthSpec = v1alpha1.LdapAuthDetails{
CredentialsRef: infisicalPushSecret.Spec.Authentication.LdapAuth.CredentialsRef,
SecretsScope: v1alpha1.MachineIdentityScopeInWorkspace{},
IdentityID: infisicalPushSecret.Spec.Authentication.LdapAuth.IdentityID,
}
case SecretCrd.INFISICAL_DYNAMIC_SECRET:
infisicalDynamicSecret, ok := secretCrd.Secret.(v1alpha1.InfisicalDynamicSecret)
if !ok {
return AuthenticationDetails{}, errors.New("unable to cast secret to InfisicalDynamicSecret")
}
ldapAuthSpec = v1alpha1.LdapAuthDetails{
CredentialsRef: infisicalDynamicSecret.Spec.Authentication.LdapAuth.CredentialsRef,
SecretsScope: v1alpha1.MachineIdentityScopeInWorkspace{},
IdentityID: infisicalDynamicSecret.Spec.Authentication.LdapAuth.IdentityID,
}
}
ldapAuthKubeSecret, err := GetInfisicalLdapAuthFromKubeSecret(ctx, reconcilerClient, v1alpha1.KubeSecretReference{
SecretNamespace: ldapAuthSpec.CredentialsRef.SecretNamespace,
SecretName: ldapAuthSpec.CredentialsRef.SecretName,
})
if err != nil {
return AuthenticationDetails{}, fmt.Errorf("ReconcileInfisicalSecret: unable to get machine identity creds from kube secret [err=%s]", err)
}
if ldapAuthKubeSecret.Username == "" && ldapAuthKubeSecret.Password == "" {
return AuthenticationDetails{}, ErrAuthNotApplicable
}
_, err = infisicalClient.Auth().LdapAuthLogin(ldapAuthSpec.IdentityID, ldapAuthKubeSecret.Username, ldapAuthKubeSecret.Password)
if err != nil {
return AuthenticationDetails{}, fmt.Errorf("unable to login with machine identity credentials [err=%s]", err)
}
return AuthenticationDetails{
AuthStrategy: AuthStrategy.LDAP_MACHINE_IDENTITY,
MachineIdentityScope: ldapAuthSpec.SecretsScope,
IsMachineIdentityAuth: true,
SecretType: secretCrd.Type,
}, nil
}
func HandleKubernetesAuth(ctx context.Context, reconcilerClient client.Client, secretCrd SecretAuthInput, infisicalClient infisicalSdk.InfisicalClientInterface) (AuthenticationDetails, error) {
var kubernetesAuthSpec v1alpha1.KubernetesAuthDetails

View File

@@ -18,6 +18,9 @@ import (
const INFISICAL_MACHINE_IDENTITY_CLIENT_ID = "clientId"
const INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET = "clientSecret"
const INFISICAL_MACHINE_IDENTITY_LDAP_USERNAME = "username"
const INFISICAL_MACHINE_IDENTITY_LDAP_PASSWORD = "password"
func GetKubeSecretByNamespacedName(ctx context.Context, reconcilerClient client.Client, namespacedName types.NamespacedName) (*corev1.Secret, error) {
kubeSecret := &corev1.Secret{}
err := reconcilerClient.Get(ctx, namespacedName, kubeSecret)
@@ -38,7 +41,7 @@ func GetKubeConfigMapByNamespacedName(ctx context.Context, reconcilerClient clie
return kubeConfigMap, err
}
func GetInfisicalUniversalAuthFromKubeSecret(ctx context.Context, reconcilerClient client.Client, universalAuthRef v1alpha1.KubeSecretReference) (machineIdentityDetails model.MachineIdentityDetails, err error) {
func GetInfisicalUniversalAuthFromKubeSecret(ctx context.Context, reconcilerClient client.Client, universalAuthRef v1alpha1.KubeSecretReference) (machineIdentityDetails model.UniversalAuthIdentityDetails, err error) {
universalAuthCredsFromKubeSecret, err := GetKubeSecretByNamespacedName(ctx, reconcilerClient, types.NamespacedName{
Namespace: universalAuthRef.SecretNamespace,
@@ -48,17 +51,39 @@ func GetInfisicalUniversalAuthFromKubeSecret(ctx context.Context, reconcilerClie
})
if k8Errors.IsNotFound(err) {
return model.MachineIdentityDetails{}, nil
return model.UniversalAuthIdentityDetails{}, nil
}
if err != nil {
return model.MachineIdentityDetails{}, fmt.Errorf("something went wrong when fetching your machine identity credentials [err=%s]", err)
return model.UniversalAuthIdentityDetails{}, fmt.Errorf("something went wrong when fetching your machine identity credentials [err=%s]", err)
}
clientIdFromSecret := universalAuthCredsFromKubeSecret.Data[INFISICAL_MACHINE_IDENTITY_CLIENT_ID]
clientSecretFromSecret := universalAuthCredsFromKubeSecret.Data[INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET]
return model.MachineIdentityDetails{ClientId: string(clientIdFromSecret), ClientSecret: string(clientSecretFromSecret)}, nil
return model.UniversalAuthIdentityDetails{ClientId: string(clientIdFromSecret), ClientSecret: string(clientSecretFromSecret)}, nil
}
func GetInfisicalLdapAuthFromKubeSecret(ctx context.Context, reconcilerClient client.Client, ldapAuthRef v1alpha1.KubeSecretReference) (machineIdentityDetails model.LdapIdentityDetails, err error) {
ldapAuthCredsFromKubeSecret, err := GetKubeSecretByNamespacedName(ctx, reconcilerClient, types.NamespacedName{
Namespace: ldapAuthRef.SecretNamespace,
Name: ldapAuthRef.SecretName,
})
if k8Errors.IsNotFound(err) {
return model.LdapIdentityDetails{}, nil
}
if err != nil {
return model.LdapIdentityDetails{}, fmt.Errorf("something went wrong when fetching your machine identity credentials [err=%s]", err)
}
usernameFromSecret := ldapAuthCredsFromKubeSecret.Data[INFISICAL_MACHINE_IDENTITY_LDAP_USERNAME]
passwordFromSecret := ldapAuthCredsFromKubeSecret.Data[INFISICAL_MACHINE_IDENTITY_LDAP_PASSWORD]
return model.LdapIdentityDetails{Username: string(usernameFromSecret), Password: string(passwordFromSecret)}, nil
}