mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 16:27:46 +00:00
Merge pull request #2652 from Infisical/feat/add-support-for-custom-ca
feat: add support for custom ca in k8 operator
This commit is contained in:
@@ -10,7 +10,9 @@ It uses an `InfisicalSecret` resource to specify authentication and storage meth
|
|||||||
The operator continuously updates secrets and can also reload dependent deployments automatically.
|
The operator continuously updates secrets and can also reload dependent deployments automatically.
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
If you are already using the External Secrets operator, you can view the integration documentation for it [here](https://external-secrets.io/latest/provider/infisical/).
|
If you are already using the External Secrets operator, you can view the
|
||||||
|
integration documentation for it
|
||||||
|
[here](https://external-secrets.io/latest/provider/infisical/).
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
## Install Operator
|
## Install Operator
|
||||||
@@ -31,7 +33,7 @@ The operator can be install via [Helm](https://helm.sh) or [kubectl](https://git
|
|||||||
To select a specific version, view the application versions [here](https://hub.docker.com/r/infisical/kubernetes-operator/tags) and chart versions [here](https://cloudsmith.io/~infisical/repos/helm-charts/packages/detail/helm/secrets-operator/#versions)
|
To select a specific version, view the application versions [here](https://hub.docker.com/r/infisical/kubernetes-operator/tags) and chart versions [here](https://cloudsmith.io/~infisical/repos/helm-charts/packages/detail/helm/secrets-operator/#versions)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
helm install --generate-name infisical-helm-charts/secrets-operator
|
helm install --generate-name infisical-helm-charts/secrets-operator
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -61,109 +63,106 @@ Once you apply the manifest, the operator will be installed in `infisical-operat
|
|||||||
Once you have installed the operator to your cluster, you'll need to create a `InfisicalSecret` custom resource definition (CRD).
|
Once you have installed the operator to your cluster, you'll need to create a `InfisicalSecret` custom resource definition (CRD).
|
||||||
|
|
||||||
```yaml example-infisical-secret-crd.yaml
|
```yaml example-infisical-secret-crd.yaml
|
||||||
|
|
||||||
apiVersion: secrets.infisical.com/v1alpha1
|
apiVersion: secrets.infisical.com/v1alpha1
|
||||||
kind: InfisicalSecret
|
kind: InfisicalSecret
|
||||||
metadata:
|
metadata:
|
||||||
name: infisicalsecret-sample
|
name: infisicalsecret-sample
|
||||||
labels:
|
labels:
|
||||||
label-to-be-passed-to-managed-secret: sample-value
|
label-to-be-passed-to-managed-secret: sample-value
|
||||||
annotations:
|
annotations:
|
||||||
example.com/annotation-to-be-passed-to-managed-secret: "sample-value"
|
example.com/annotation-to-be-passed-to-managed-secret: "sample-value"
|
||||||
spec:
|
spec:
|
||||||
hostAPI: https://app.infisical.com/api
|
hostAPI: https://app.infisical.com/api
|
||||||
resyncInterval: 10
|
resyncInterval: 10
|
||||||
authentication:
|
authentication:
|
||||||
# Make sure to only have 1 authentication method defined, serviceToken/universalAuth.
|
# Make sure to only have 1 authentication method defined, serviceToken/universalAuth.
|
||||||
# If you have multiple authentication methods defined, it may cause issues.
|
# If you have multiple authentication methods defined, it may cause issues.
|
||||||
|
|
||||||
# (Deprecated) Service Token Auth
|
# (Deprecated) Service Token Auth
|
||||||
serviceToken:
|
serviceToken:
|
||||||
serviceTokenSecretReference:
|
serviceTokenSecretReference:
|
||||||
secretName: service-token
|
secretName: service-token
|
||||||
secretNamespace: default
|
|
||||||
secretsScope:
|
|
||||||
envSlug: <env-slug>
|
|
||||||
secretsPath: <secrets-path>
|
|
||||||
recursive: true
|
|
||||||
|
|
||||||
# Universal Auth
|
|
||||||
universalAuth:
|
|
||||||
secretsScope:
|
|
||||||
projectSlug: new-ob-em
|
|
||||||
envSlug: dev # "dev", "staging", "prod", etc..
|
|
||||||
secretsPath: "/" # Root is "/"
|
|
||||||
recursive: true # Wether or not to use recursive mode (Fetches all secrets in an environment from a given secret path, and all folders inside the path) / defaults to false
|
|
||||||
credentialsRef:
|
|
||||||
secretName: universal-auth-credentials
|
|
||||||
secretNamespace: default
|
|
||||||
|
|
||||||
# Native Kubernetes Auth
|
|
||||||
kubernetesAuth:
|
|
||||||
identityId: <machine-identity-id>
|
|
||||||
serviceAccountRef:
|
|
||||||
name: <service-account-name>
|
|
||||||
namespace: <service-account-namespace>
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# AWS IAM Auth
|
|
||||||
awsIamAuth:
|
|
||||||
identityId: <your-machine-identity-id>
|
|
||||||
|
|
||||||
# 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>
|
|
||||||
resource: https://management.azure.com/&client_id=CLIENT_ID # (Optional) This is the Azure resource that you want to access. For example, "https://management.azure.com/". If no value is provided, it will default to "https://management.azure.com/"
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# GCP ID Token Auth
|
|
||||||
gcpIdTokenAuth:
|
|
||||||
identityId: <your-machine-identity-id>
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# GCP IAM Auth
|
|
||||||
gcpIamAuth:
|
|
||||||
identityId: <your-machine-identity-id>
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
managedSecretReference:
|
|
||||||
secretName: managed-secret
|
|
||||||
secretNamespace: default
|
secretNamespace: default
|
||||||
creationPolicy: "Orphan" ## Owner | Orphan
|
secretsScope:
|
||||||
# secretType: kubernetes.io/dockerconfigjson
|
envSlug: <env-slug>
|
||||||
|
secretsPath: <secrets-path>
|
||||||
|
recursive: true
|
||||||
|
|
||||||
|
# Universal Auth
|
||||||
|
universalAuth:
|
||||||
|
secretsScope:
|
||||||
|
projectSlug: new-ob-em
|
||||||
|
envSlug: dev # "dev", "staging", "prod", etc..
|
||||||
|
secretsPath: "/" # Root is "/"
|
||||||
|
recursive: true # Wether or not to use recursive mode (Fetches all secrets in an environment from a given secret path, and all folders inside the path) / defaults to false
|
||||||
|
credentialsRef:
|
||||||
|
secretName: universal-auth-credentials
|
||||||
|
secretNamespace: default
|
||||||
|
|
||||||
|
# Native Kubernetes Auth
|
||||||
|
kubernetesAuth:
|
||||||
|
identityId: <machine-identity-id>
|
||||||
|
serviceAccountRef:
|
||||||
|
name: <service-account-name>
|
||||||
|
namespace: <service-account-namespace>
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# AWS IAM Auth
|
||||||
|
awsIamAuth:
|
||||||
|
identityId: <your-machine-identity-id>
|
||||||
|
|
||||||
|
# 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>
|
||||||
|
resource: https://management.azure.com/&client_id=CLIENT_ID # (Optional) This is the Azure resource that you want to access. For example, "https://management.azure.com/". If no value is provided, it will default to "https://management.azure.com/"
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# GCP ID Token Auth
|
||||||
|
gcpIdTokenAuth:
|
||||||
|
identityId: <your-machine-identity-id>
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# GCP IAM Auth
|
||||||
|
gcpIamAuth:
|
||||||
|
identityId: <your-machine-identity-id>
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
managedSecretReference:
|
||||||
|
secretName: managed-secret
|
||||||
|
secretNamespace: default
|
||||||
|
creationPolicy: "Orphan" ## Owner | Orphan
|
||||||
|
# secretType: kubernetes.io/dockerconfigjson
|
||||||
```
|
```
|
||||||
|
|
||||||
### InfisicalSecret CRD properties
|
### InfisicalSecret CRD properties
|
||||||
@@ -193,6 +192,31 @@ When `hostAPI` is not defined the operator fetches secrets from Infisical Cloud.
|
|||||||
available on paid plans. Default re-sync interval is every 1 minute.
|
available on paid plans. Default re-sync interval is every 1 minute.
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
|
<Accordion title="tls">
|
||||||
|
This block defines the TLS settings to use for connecting to the Infisical
|
||||||
|
instance.
|
||||||
|
</Accordion>
|
||||||
|
|
||||||
|
<Accordion title="tls.caRef">
|
||||||
|
This block defines the reference to the CA certificate to use for connecting
|
||||||
|
to the Infisical instance with SSL/TLS.
|
||||||
|
</Accordion>
|
||||||
|
|
||||||
|
<Accordion title="tls.caRef.secretName">
|
||||||
|
The name of the Kubernetes secret containing the CA certificate to use for
|
||||||
|
connecting to the Infisical instance with SSL/TLS.
|
||||||
|
</Accordion>
|
||||||
|
|
||||||
|
<Accordion title="tls.caRef.secretNamespace">
|
||||||
|
The namespace of the Kubernetes secret containing the CA certificate to use
|
||||||
|
for connecting to the Infisical instance with SSL/TLS.
|
||||||
|
</Accordion>
|
||||||
|
|
||||||
|
<Accordion title="tls.caRef.key">
|
||||||
|
The name of the key in the Kubernetes secret which contains the value of the
|
||||||
|
CA certificate to use for connecting to the Infisical instance with SSL/TLS.
|
||||||
|
</Accordion>
|
||||||
|
|
||||||
<Accordion title="authentication">
|
<Accordion title="authentication">
|
||||||
This block defines the method that will be used to authenticate with Infisical
|
This block defines the method that will be used to authenticate with Infisical
|
||||||
so that secrets can be fetched
|
so that secrets can be fetched
|
||||||
@@ -222,8 +246,6 @@ When `hostAPI` is not defined the operator fetches secrets from Infisical Cloud.
|
|||||||
|
|
||||||
</Steps>
|
</Steps>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Info>
|
<Info>
|
||||||
Make sure to also populate the `secretsScope` field with the project slug
|
Make sure to also populate the `secretsScope` field with the project slug
|
||||||
_`projectSlug`_, environment slug _`envSlug`_, and secrets path
|
_`projectSlug`_, environment slug _`envSlug`_, and secrets path
|
||||||
@@ -365,15 +387,15 @@ spec:
|
|||||||
|
|
||||||
</Step>
|
</Step>
|
||||||
<Step title="Add your identity ID & service account to your InfisicalSecret resource">
|
<Step title="Add your identity ID & service account to your InfisicalSecret resource">
|
||||||
Once you have created your machine identity and added it to your project(s), you will need to add the identity ID to your InfisicalSecret resource.
|
Once you have created your machine identity and added it to your project(s), you will need to add the identity ID to your InfisicalSecret resource.
|
||||||
In the `authentication.kubernetesAuth.identityId` field, add the identity ID of the machine identity you created.
|
In the `authentication.kubernetesAuth.identityId` field, add the identity ID of the machine identity you created.
|
||||||
See the example below for more details.
|
See the example below for more details.
|
||||||
</Step>
|
</Step>
|
||||||
<Step title="Add your Kubernetes service account token to the InfisicalSecret resource">
|
<Step title="Add your Kubernetes service account token to the InfisicalSecret resource">
|
||||||
Add the service account details from the previous steps under `authentication.kubernetesAuth.serviceAccountRef`.
|
Add the service account details from the previous steps under `authentication.kubernetesAuth.serviceAccountRef`.
|
||||||
Here you will need to enter the name and namespace of the service account.
|
Here you will need to enter the name and namespace of the service account.
|
||||||
The example below shows a complete InfisicalSecret resource with all required fields defined.
|
The example below shows a complete InfisicalSecret resource with all required fields defined.
|
||||||
</Step>
|
</Step>
|
||||||
|
|
||||||
</Steps>
|
</Steps>
|
||||||
|
|
||||||
@@ -539,8 +561,6 @@ spec:
|
|||||||
|
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Accordion title="authentication.gcpIamAuth">
|
<Accordion title="authentication.gcpIamAuth">
|
||||||
The GCP IAM machine identity authentication method is used to authenticate with Infisical. The identity ID is stored in a field in the InfisicalSecret resource. This authentication method can only be used both within and outside GCP environments.
|
The GCP IAM machine identity authentication method is used to authenticate with Infisical. The identity ID is stored in a field in the InfisicalSecret resource. This authentication method can only be used both within and outside GCP environments.
|
||||||
|
|
||||||
@@ -877,6 +897,42 @@ spec:
|
|||||||
|
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
|
### Connecting to instances with private/self-signed certificate
|
||||||
|
|
||||||
|
To connect to Infisical instances behind a private/self-signed certificate, you can configure the TLS settings in the `InfisicalSecret` CRD
|
||||||
|
to point to a CA certificate stored in a Kubernetes secret resource.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
spec:
|
||||||
|
hostAPI: https://app.infisical.com/api
|
||||||
|
resyncInterval: 10
|
||||||
|
tls:
|
||||||
|
caRef:
|
||||||
|
secretName: custom-ca-certificate
|
||||||
|
secretNamespace: default
|
||||||
|
key: ca.crt
|
||||||
|
authentication:
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
The definition file of the Kubernetes secret for the CA certificate can be structured like the following:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: custom-ca-certificate
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
ca.crt: |
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEZzCCA0+gAwIBAgIUDk9+HZcMHppiNy0TvoBg8/aMEqIwDQYJKoZIhvcNAQEL
|
||||||
|
...
|
||||||
|
BQAwDTELMAkGA1UEChMCUEgwHhcNMjQxMDI1MTU0MjAzWhcNMjUxMDI1MjE0MjAz
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
```
|
||||||
|
|
||||||
## Auto redeployment
|
## Auto redeployment
|
||||||
|
|
||||||
Deployments using managed secrets don't reload automatically on updates, so they may use outdated secrets unless manually redeployed.
|
Deployments using managed secrets don't reload automatically on updates, so they may use outdated secrets unless manually redeployed.
|
||||||
@@ -889,6 +945,7 @@ To enable auto redeployment you simply have to add the following annotation to t
|
|||||||
```yaml
|
```yaml
|
||||||
secrets.infisical.com/auto-reload: "true"
|
secrets.infisical.com/auto-reload: "true"
|
||||||
```
|
```
|
||||||
|
|
||||||
<Accordion title="Deployment example with auto redeploy enabled">
|
<Accordion title="Deployment example with auto redeploy enabled">
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
|
|||||||
@@ -149,6 +149,26 @@ type MangedKubeSecretConfig struct {
|
|||||||
CreationPolicy string `json:"creationPolicy"`
|
CreationPolicy string `json:"creationPolicy"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CaReference struct {
|
||||||
|
// The name of the Kubernetes Secret
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
SecretName string `json:"secretName"`
|
||||||
|
|
||||||
|
// The namespace where the Kubernetes Secret is located
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
SecretNamespace string `json:"secretNamespace"`
|
||||||
|
|
||||||
|
// +kubebuilder:validation:Required
|
||||||
|
// The name of the secret property with the CA certificate value
|
||||||
|
SecretKey string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TLSConfig struct {
|
||||||
|
// Reference to secret containing CA cert
|
||||||
|
// +kubebuilder:validation:Optional
|
||||||
|
CaRef CaReference `json:"caRef,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// InfisicalSecretSpec defines the desired state of InfisicalSecret
|
// InfisicalSecretSpec defines the desired state of InfisicalSecret
|
||||||
type InfisicalSecretSpec struct {
|
type InfisicalSecretSpec struct {
|
||||||
// +kubebuilder:validation:Optional
|
// +kubebuilder:validation:Optional
|
||||||
@@ -166,6 +186,9 @@ type InfisicalSecretSpec struct {
|
|||||||
// Infisical host to pull secrets from
|
// Infisical host to pull secrets from
|
||||||
// +kubebuilder:validation:Optional
|
// +kubebuilder:validation:Optional
|
||||||
HostAPI string `json:"hostAPI"`
|
HostAPI string `json:"hostAPI"`
|
||||||
|
|
||||||
|
// +kubebuilder:validation:Optional
|
||||||
|
TLS TLSConfig `json:"tls"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// InfisicalSecretStatus defines the observed state of InfisicalSecret
|
// InfisicalSecretStatus defines the observed state of InfisicalSecret
|
||||||
|
|||||||
@@ -81,6 +81,21 @@ func (in *AzureAuthDetails) DeepCopy() *AzureAuthDetails {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *CaReference) DeepCopyInto(out *CaReference) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CaReference.
|
||||||
|
func (in *CaReference) DeepCopy() *CaReference {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(CaReference)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *GCPIdTokenAuthDetails) DeepCopyInto(out *GCPIdTokenAuthDetails) {
|
func (in *GCPIdTokenAuthDetails) DeepCopyInto(out *GCPIdTokenAuthDetails) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@@ -178,6 +193,7 @@ func (in *InfisicalSecretSpec) DeepCopyInto(out *InfisicalSecretSpec) {
|
|||||||
out.TokenSecretReference = in.TokenSecretReference
|
out.TokenSecretReference = in.TokenSecretReference
|
||||||
out.Authentication = in.Authentication
|
out.Authentication = in.Authentication
|
||||||
out.ManagedSecretReference = in.ManagedSecretReference
|
out.ManagedSecretReference = in.ManagedSecretReference
|
||||||
|
out.TLS = in.TLS
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfisicalSecretSpec.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfisicalSecretSpec.
|
||||||
@@ -337,6 +353,22 @@ func (in *ServiceTokenDetails) DeepCopy() *ServiceTokenDetails {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *TLSConfig) DeepCopyInto(out *TLSConfig) {
|
||||||
|
*out = *in
|
||||||
|
out.CaRef = in.CaRef
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSConfig.
|
||||||
|
func (in *TLSConfig) DeepCopy() *TLSConfig {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(TLSConfig)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *UniversalAuthDetails) DeepCopyInto(out *UniversalAuthDetails) {
|
func (in *UniversalAuthDetails) DeepCopyInto(out *UniversalAuthDetails) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
|||||||
@@ -290,6 +290,28 @@ spec:
|
|||||||
resyncInterval:
|
resyncInterval:
|
||||||
default: 60
|
default: 60
|
||||||
type: integer
|
type: integer
|
||||||
|
tls:
|
||||||
|
properties:
|
||||||
|
caRef:
|
||||||
|
description: Reference to secret containing CA cert
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: The name of the secret property with the CA certificate
|
||||||
|
value
|
||||||
|
type: string
|
||||||
|
secretName:
|
||||||
|
description: The name of the Kubernetes Secret
|
||||||
|
type: string
|
||||||
|
secretNamespace:
|
||||||
|
description: The namespace where the Kubernetes Secret is
|
||||||
|
located
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
- secretName
|
||||||
|
- secretNamespace
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
tokenSecretReference:
|
tokenSecretReference:
|
||||||
properties:
|
properties:
|
||||||
secretName:
|
secretName:
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: custom-ca-certificate
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
ca.crt: |
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEZzCCA0+gAwIBAgIUDk9+HZcMHppiNy0TvoBg8/aMEqIwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwDTELMAkGA1UEChMCUEgwHhcNMjQxMDI1MTU0MjAzWhcNMjUxMDI1MjE0MjAz
|
||||||
|
WjAfMR0wGwYDVQQDExRob3N0LmRvY2tlci5pbnRlcm5hbDCCASIwDQYJKoZIhvcN
|
||||||
|
AQEBBQADggEPADCCAQoCggEBALPBCPhZHCizZWbyGI0LzTLYprsvTMoeZBeR84lj
|
||||||
|
hv/VDUkH3K6jw5g2o2eXg4Aisb/GcQkTxHjmGlUKymhrLBH9zUHjh1yFKPUJdSy1
|
||||||
|
X4YCG+ABNQ8obrTZM/ry5WRHF/KcFIELt/4JpY8OWkxEIisYfe98vObsGH39spcN
|
||||||
|
c3x3Oo4vsBd6ETQOjrXL81kXLoNZoHdsVIU0ZwNpXR1geI477ce3eHOuEhBvKfUR
|
||||||
|
ugRdmX6xUhFNZcKRYiv3RRkm/vnuxWx2CxsecJ0BRoB7nT00gJkkxbt1b5MrPFF4
|
||||||
|
XIdhWIdxSMdMUwtnEo9hT2mzUCkJohLEeqwivZfewghLo88CAwEAAaOCAaswggGn
|
||||||
|
MAkGA1UdEwQCMAAwXgYDVR0fBFcwVTBToFGgT4ZNaHR0cDovL2xvY2FsaG9zdDo4
|
||||||
|
MDgwL2FwaS92MS9wa2kvY3JsLzY2ZDk3OTNkLWMzMTYtNDNhZS05N2RiLTkzNDBj
|
||||||
|
ZmJkNTYxNy9kZXIwHwYDVR0jBBgwFoAU3+CiMP0BF+BnjXBYawENOrnQ+q8wHQYD
|
||||||
|
VR0OBBYEFKUIOV5qAwf0Bd1dMnxIYYglcZT1MIGdBggrBgEFBQcBAQSBkDCBjTCB
|
||||||
|
igYIKwYBBQUHMAKGfmh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9hcGkvdjEvcGtpL2Nh
|
||||||
|
L2EyNDIyZTdlLTAwZWYtNDlhZC1iY2ZhLTUxMzZhODQxNjEyZC9jZXJ0aWZpY2F0
|
||||||
|
ZXMvYWJhNTRjNGEtNjYxOS00MDFlLTk2YTYtN2UwN2MxNzdjOTI4L2RlcjARBgNV
|
||||||
|
HSAECjAIMAYGBFUdIAAwDgYDVR0PAQH/BAQDAgWgMBYGA1UdJQEB/wQMMAoGCCsG
|
||||||
|
AQUFBwMBMB8GA1UdEQQYMBaCFGhvc3QuZG9ja2VyLmludGVybmFsMA0GCSqGSIb3
|
||||||
|
DQEBCwUAA4IBAQAtUUloE1xU+BNF2Fjc/PSOesHz6dFCzGWvCc0QZceK/6v4EWuZ
|
||||||
|
vEU07brGrufhwJ3UnOXO4zxIl3UplQ1S14Xrba4R69Fp3dggFV39ON8R5lpL9hZe
|
||||||
|
cSRywBycKil2C7SytPsjJtvCXY6RXb6YxFse6rDk0qoMwD/g/ou3JIEpgtB2cPuX
|
||||||
|
Blg9ZWAsaOtKhtmi1IyLjwgHDd86XhMzd9osOna1iuARZMZs80ek5b5H4cdFIBTl
|
||||||
|
rwIQc6b9ZbHAD56NttCIE18YmLWbYBCdvga0Qmqwr2fRPg2DE9qoyF1ZJVbwisOc
|
||||||
|
cJ23MFdpsXKiIoQyDmpZl5jg8aKD/jh0wdUx
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -1,104 +1,109 @@
|
|||||||
apiVersion: secrets.infisical.com/v1alpha1
|
apiVersion: secrets.infisical.com/v1alpha1
|
||||||
kind: InfisicalSecret
|
kind: InfisicalSecret
|
||||||
metadata:
|
metadata:
|
||||||
name: infisicalsecret-sample
|
name: infisicalsecret-sample
|
||||||
labels:
|
labels:
|
||||||
label-to-be-passed-to-managed-secret: sample-value
|
label-to-be-passed-to-managed-secret: sample-value
|
||||||
annotations:
|
annotations:
|
||||||
example.com/annotation-to-be-passed-to-managed-secret: "sample-value"
|
example.com/annotation-to-be-passed-to-managed-secret: "sample-value"
|
||||||
spec:
|
spec:
|
||||||
hostAPI: https://app.infisical.com/api
|
hostAPI: https://app.infisical.com/api
|
||||||
resyncInterval: 10
|
resyncInterval: 10
|
||||||
authentication:
|
# tls:
|
||||||
# Make sure to only have 1 authentication method defined, serviceToken/universalAuth.
|
# caRef:
|
||||||
# If you have multiple authentication methods defined, it may cause issues.
|
# secretName: custom-ca-certificate
|
||||||
|
# secretNamespace: default
|
||||||
|
# key: ca.crt
|
||||||
|
authentication:
|
||||||
|
# Make sure to only have 1 authentication method defined, serviceToken/universalAuth.
|
||||||
|
# If you have multiple authentication methods defined, it may cause issues.
|
||||||
|
|
||||||
# (Deprecated) Service Token Auth
|
# (Deprecated) Service Token Auth
|
||||||
serviceToken:
|
serviceToken:
|
||||||
serviceTokenSecretReference:
|
serviceTokenSecretReference:
|
||||||
secretName: service-token
|
secretName: service-token
|
||||||
secretNamespace: default
|
|
||||||
secretsScope:
|
|
||||||
envSlug: <env-slug>
|
|
||||||
secretsPath: <secrets-path>
|
|
||||||
recursive: true
|
|
||||||
|
|
||||||
# Universal Auth
|
|
||||||
universalAuth:
|
|
||||||
secretsScope:
|
|
||||||
projectSlug: new-ob-em
|
|
||||||
envSlug: dev # "dev", "staging", "prod", etc..
|
|
||||||
secretsPath: "/" # Root is "/"
|
|
||||||
recursive: true # Wether or not to use recursive mode (Fetches all secrets in an environment from a given secret path, and all folders inside the path) / defaults to false
|
|
||||||
credentialsRef:
|
|
||||||
secretName: universal-auth-credentials
|
|
||||||
secretNamespace: default
|
|
||||||
|
|
||||||
# Native Kubernetes Auth
|
|
||||||
kubernetesAuth:
|
|
||||||
identityId: <machine-identity-id>
|
|
||||||
serviceAccountTokenPath: "/path/to/your/service-account/token" # Optional, defaults to /var/run/secrets/kubernetes.io/serviceaccount/token
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# AWS IAM Auth
|
|
||||||
awsIamAuth:
|
|
||||||
identityId: <your-machine-identity-id>
|
|
||||||
|
|
||||||
# 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>
|
|
||||||
resource: https://management.azure.com/&client_id=your_client_id # This field is optional, and will default to "https://management.azure.com/" if nothing is provided.
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# GCP ID Token Auth
|
|
||||||
gcpIdTokenAuth:
|
|
||||||
identityId: <your-machine-identity-id>
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# GCP IAM Auth
|
|
||||||
gcpIamAuth:
|
|
||||||
identityId: <your-machine-identity-id>
|
|
||||||
serviceAccountKeyFilePath: "/path/to-service-account-key-file-path.json"
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
managedSecretReference:
|
|
||||||
secretName: managed-secret
|
|
||||||
secretNamespace: default
|
secretNamespace: default
|
||||||
creationPolicy: "Orphan" ## Owner | Orphan
|
secretsScope:
|
||||||
# secretType: kubernetes.io/dockerconfigjson
|
envSlug: <env-slug>
|
||||||
|
secretsPath: <secrets-path>
|
||||||
|
recursive: true
|
||||||
|
|
||||||
# # To be depreciated soon
|
# Universal Auth
|
||||||
# tokenSecretReference:
|
universalAuth:
|
||||||
# secretName: service-token
|
secretsScope:
|
||||||
# secretNamespace: default
|
projectSlug: new-ob-em
|
||||||
|
envSlug: dev # "dev", "staging", "prod", etc..
|
||||||
|
secretsPath: "/" # Root is "/"
|
||||||
|
recursive: true # Wether or not to use recursive mode (Fetches all secrets in an environment from a given secret path, and all folders inside the path) / defaults to false
|
||||||
|
credentialsRef:
|
||||||
|
secretName: universal-auth-credentials
|
||||||
|
secretNamespace: default
|
||||||
|
|
||||||
|
# Native Kubernetes Auth
|
||||||
|
kubernetesAuth:
|
||||||
|
identityId: <machine-identity-id>
|
||||||
|
serviceAccountTokenPath: "/path/to/your/service-account/token" # Optional, defaults to /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# AWS IAM Auth
|
||||||
|
awsIamAuth:
|
||||||
|
identityId: <your-machine-identity-id>
|
||||||
|
|
||||||
|
# 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>
|
||||||
|
resource: https://management.azure.com/&client_id=your_client_id # This field is optional, and will default to "https://management.azure.com/" if nothing is provided.
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# GCP ID Token Auth
|
||||||
|
gcpIdTokenAuth:
|
||||||
|
identityId: <your-machine-identity-id>
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# GCP IAM Auth
|
||||||
|
gcpIamAuth:
|
||||||
|
identityId: <your-machine-identity-id>
|
||||||
|
serviceAccountKeyFilePath: "/path/to-service-account-key-file-path.json"
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
managedSecretReference:
|
||||||
|
secretName: managed-secret
|
||||||
|
secretNamespace: default
|
||||||
|
creationPolicy: "Orphan" ## Owner | Orphan
|
||||||
|
# secretType: kubernetes.io/dockerconfigjson
|
||||||
|
|
||||||
|
# # To be depreciated soon
|
||||||
|
# tokenSecretReference:
|
||||||
|
# secretName: service-token
|
||||||
|
# secretNamespace: default
|
||||||
|
|||||||
@@ -107,6 +107,20 @@ func (r *InfisicalSecretReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
|||||||
api.API_HOST_URL = infisicalSecretCR.Spec.HostAPI
|
api.API_HOST_URL = infisicalSecretCR.Spec.HostAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if infisicalSecretCR.Spec.TLS.CaRef.SecretName != "" {
|
||||||
|
api.API_CA_CERTIFICATE, err = r.GetInfisicalCaCertificateFromKubeSecret(ctx, infisicalSecretCR)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("unable to fetch CA certificate [err=%s]. Will requeue after [requeueTime=%v]\n", err, requeueTime)
|
||||||
|
return ctrl.Result{
|
||||||
|
RequeueAfter: requeueTime,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Using custom CA certificate...")
|
||||||
|
} else {
|
||||||
|
api.API_CA_CERTIFICATE = ""
|
||||||
|
}
|
||||||
|
|
||||||
err = r.ReconcileInfisicalSecret(ctx, infisicalSecretCR)
|
err = r.ReconcileInfisicalSecret(ctx, infisicalSecretCR)
|
||||||
r.SetReadyToSyncSecretsConditions(ctx, &infisicalSecretCR, err)
|
r.SetReadyToSyncSecretsConditions(ctx, &infisicalSecretCR, err)
|
||||||
|
|
||||||
|
|||||||
@@ -177,6 +177,27 @@ func (r *InfisicalSecretReconciler) GetInfisicalUniversalAuthFromKubeSecret(ctx
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *InfisicalSecretReconciler) GetInfisicalCaCertificateFromKubeSecret(ctx context.Context, infisicalSecret v1alpha1.InfisicalSecret) (caCertificate string, err error) {
|
||||||
|
|
||||||
|
caCertificateFromKubeSecret, err := r.GetKubeSecretByNamespacedName(ctx, types.NamespacedName{
|
||||||
|
Namespace: infisicalSecret.Spec.TLS.CaRef.SecretNamespace,
|
||||||
|
Name: infisicalSecret.Spec.TLS.CaRef.SecretName,
|
||||||
|
})
|
||||||
|
|
||||||
|
if k8Errors.IsNotFound(err) {
|
||||||
|
return "", fmt.Errorf("kubernetes secret containing custom CA certificate cannot be found. [err=%s]", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("something went wrong when fetching your CA certificate [err=%s]", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
caCertificateFromSecret := string(caCertificateFromKubeSecret.Data[infisicalSecret.Spec.TLS.CaRef.SecretKey])
|
||||||
|
|
||||||
|
return caCertificateFromSecret, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Fetches service account credentials from a Kubernetes secret specified in the infisicalSecret object, extracts the access key, public key, and private key from the secret, and returns them as a ServiceAccountCredentials object.
|
// Fetches service account credentials from a Kubernetes secret specified in the infisicalSecret object, extracts the access key, public key, and private key from the secret, and returns them as a ServiceAccountCredentials object.
|
||||||
// If any keys are missing or an error occurs, returns an empty object or an error object, respectively.
|
// If any keys are missing or an error occurs, returns an empty object or an error object, respectively.
|
||||||
func (r *InfisicalSecretReconciler) GetInfisicalServiceAccountCredentialsFromKubeSecret(ctx context.Context, infisicalSecret v1alpha1.InfisicalSecret) (serviceAccountDetails model.ServiceAccountDetails, err error) {
|
func (r *InfisicalSecretReconciler) GetInfisicalServiceAccountCredentialsFromKubeSecret(ctx context.Context, infisicalSecret v1alpha1.InfisicalSecret) (serviceAccountDetails model.ServiceAccountDetails, err error) {
|
||||||
@@ -296,8 +317,9 @@ func (r *InfisicalSecretReconciler) GetResourceVariables(infisicalSecret v1alpha
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
client := infisicalSdk.NewInfisicalClient(ctx, infisicalSdk.Config{
|
client := infisicalSdk.NewInfisicalClient(ctx, infisicalSdk.Config{
|
||||||
SiteUrl: api.API_HOST_URL,
|
SiteUrl: api.API_HOST_URL,
|
||||||
UserAgent: api.USER_AGENT_NAME,
|
CaCertificate: api.API_CA_CERTIFICATE,
|
||||||
|
UserAgent: api.USER_AGENT_NAME,
|
||||||
})
|
})
|
||||||
|
|
||||||
resourceVariablesMap[string(infisicalSecret.UID)] = ResourceVariables{
|
resourceVariablesMap[string(infisicalSecret.UID)] = ResourceVariables{
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ module github.com/Infisical/infisical/k8-operator
|
|||||||
go 1.21
|
go 1.21
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/infisical/go-sdk v0.3.7
|
github.com/infisical/go-sdk v0.4.1
|
||||||
github.com/onsi/ginkgo/v2 v2.6.0
|
github.com/onsi/ginkgo/v2 v2.6.0
|
||||||
github.com/onsi/gomega v1.24.1
|
github.com/onsi/gomega v1.24.1
|
||||||
k8s.io/apimachinery v0.26.1
|
k8s.io/apimachinery v0.26.1
|
||||||
|
|||||||
+2
-2
@@ -217,8 +217,8 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
|||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
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/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
github.com/infisical/go-sdk v0.3.7 h1:EE0ALjjdJtNvDzHtxotkBxYZ6L9ZmeruH89u6jh1Bik=
|
github.com/infisical/go-sdk v0.4.1 h1:ZeLyc2+2TeIaw9odjxR3ipQqYzVSMOnd8/RaqyUNvBg=
|
||||||
github.com/infisical/go-sdk v0.3.7/go.mod h1:HHW7DgUqoolyQIUw/9HdpkZ3bDLwWyZ0HEtYiVaDKQw=
|
github.com/infisical/go-sdk v0.4.1/go.mod h1:6fWzAwTPIoKU49mQ2Oxu+aFnJu9n7k2JcNrZjzhHM2M=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
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 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
var API_HOST_URL string = "https://app.infisical.com/api"
|
var API_HOST_URL string = "https://app.infisical.com/api"
|
||||||
|
var API_CA_CERTIFICATE string = ""
|
||||||
|
|||||||
Reference in New Issue
Block a user