Skip to content

Commit

Permalink
Merge pull request #1801 from Infisical/daniel/k8-recursive
Browse files Browse the repository at this point in the history
Feat: Recursive support for K8 operaetor
  • Loading branch information
DanielHougaard authored May 7, 2024
2 parents 37a59b2 + be2fc4f commit e18d830
Show file tree
Hide file tree
Showing 11 changed files with 40 additions and 10 deletions.
3 changes: 3 additions & 0 deletions docs/integrations/platforms/kubernetes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ spec:
projectSlug: <project-slug>
envSlug: <env-slug> # "dev", "staging", "prod", etc..
secretsPath: "<secrets-path>" # Root is "/"
recursive: true # Fetch all secrets from the specified path and all sub-directories. Default is false.

credentialsRef:
secretName: universal-auth-credentials
secretNamespace: default
Expand All @@ -89,6 +91,7 @@ spec:
secretsScope:
envSlug: <env-slug>
secretsPath: <secrets-path> # Root is "/"
recursive: true # Fetch all secrets from the specified path and all sub-directories. Default is false.

managedSecretReference:
secretName: managed-secret
Expand Down
2 changes: 1 addition & 1 deletion helm-charts/secrets-operator/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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: v0.5.0
version: v0.5.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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ spec:
properties:
envSlug:
type: string
recursive:
type: boolean
secretsPath:
type: string
required:
Expand Down Expand Up @@ -111,6 +113,8 @@ spec:
type: string
projectSlug:
type: string
recursive:
type: boolean
secretsPath:
type: string
required:
Expand Down
2 changes: 1 addition & 1 deletion helm-charts/secrets-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ controllerManager:
- ALL
image:
repository: infisical/kubernetes-operator
tag: v0.5.0 # fixed to prevent accidental upgrade
tag: v0.5.1 # fixed to prevent accidental upgrade
resources:
limits:
cpu: 500m
Expand Down
4 changes: 4 additions & 0 deletions k8-operator/api/v1alpha1/infisicalsecret_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ type SecretScopeInWorkspace struct {
SecretsPath string `json:"secretsPath"`
// +kubebuilder:validation:Required
EnvSlug string `json:"envSlug"`
// +kubebuilder:validation:Optional
Recursive bool `json:"recursive"`
}

type MachineIdentityScopeInWorkspace struct {
Expand All @@ -47,6 +49,8 @@ type MachineIdentityScopeInWorkspace struct {
EnvSlug string `json:"envSlug"`
// +kubebuilder:validation:Required
ProjectSlug string `json:"projectSlug"`
// +kubebuilder:validation:Optional
Recursive bool `json:"recursive"`
}

type KubeSecretReference struct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ spec:
properties:
envSlug:
type: string
recursive:
type: boolean
secretsPath:
type: string
required:
Expand Down Expand Up @@ -111,6 +113,8 @@ spec:
type: string
projectSlug:
type: string
recursive:
type: boolean
secretsPath:
type: string
required:
Expand Down
2 changes: 2 additions & 0 deletions k8-operator/config/samples/sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ spec:
secretsScope:
envSlug: <env-slug>
secretsPath: <secrets-path> # 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

universalAuth:
secretsScope:
projectSlug: <project-slug>
envSlug: <env-slug> # "dev", "staging", "prod", etc..
secretsPath: "<secrets-path>" # 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
Expand Down
5 changes: 3 additions & 2 deletions k8-operator/controllers/infisicalsecret_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ func (r *InfisicalSecretReconciler) ReconcileInfisicalSecret(ctx context.Context
} else if infisicalMachineIdentityCreds.ClientId != "" && infisicalMachineIdentityCreds.ClientSecret != "" {
authStrategy = AuthStrategy.UNIVERSAL_MACHINE_IDENTITY
} else {
return fmt.Errorf("no authentication method provided. You must provide either a valid service token or a service account details to fetch secrets")
return fmt.Errorf("no authentication method provided. You must provide either a valid service token or a service account details to fetch secrets\n")
}

r.SetInfisicalTokenLoadCondition(ctx, &infisicalSecret, err)
Expand Down Expand Up @@ -312,8 +312,9 @@ func (r *InfisicalSecretReconciler) ReconcileInfisicalSecret(ctx context.Context
} else if authStrategy == AuthStrategy.SERVICE_TOKEN { // Service Tokens (deprecated)
envSlug := infisicalSecret.Spec.Authentication.ServiceToken.SecretsScope.EnvSlug
secretsPath := infisicalSecret.Spec.Authentication.ServiceToken.SecretsScope.SecretsPath
recursive := infisicalSecret.Spec.Authentication.ServiceToken.SecretsScope.Recursive

plainTextSecretsFromApi, updateDetails, err = util.GetPlainTextSecretsViaServiceToken(infisicalToken, secretVersionBasedOnETag, envSlug, secretsPath)
plainTextSecretsFromApi, updateDetails, err = util.GetPlainTextSecretsViaServiceToken(infisicalToken, secretVersionBasedOnETag, envSlug, secretsPath, recursive)
if err != nil {
return fmt.Errorf("\nfailed to get secrets because [err=%v]", err)
}
Expand Down
16 changes: 12 additions & 4 deletions k8-operator/packages/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ func CallGetSecretsV3(httpClient *resty.Client, request GetEncryptedSecretsV3Req
httpRequest.SetQueryParam("secretPath", request.SecretPath)
}

if request.Recursive {
httpRequest.SetQueryParam("recursive", "true")
}

response, err := httpRequest.Get(fmt.Sprintf("%v/v3/secrets", API_HOST_URL))

if err != nil {
Expand Down Expand Up @@ -148,19 +152,23 @@ func CallUniversalMachineIdentityRefreshAccessToken(request MachineIdentityUnive
func CallGetDecryptedSecretsV3(httpClient *resty.Client, request GetDecryptedSecretsV3Request) (GetDecryptedSecretsV3Response, error) {
var decryptedSecretsResponse GetDecryptedSecretsV3Response

response, err := httpClient.
req := httpClient.
R().
SetResult(&decryptedSecretsResponse).
SetHeader("User-Agent", USER_AGENT_NAME).
SetQueryParam("secretPath", request.SecretPath).
SetQueryParam("workspaceSlug", request.ProjectSlug).
SetQueryParam("environment", request.Environment).
Get(fmt.Sprintf("%v/v3/secrets/raw", API_HOST_URL))
SetQueryParam("environment", request.Environment)

if request.Recursive {
req.SetQueryParam("recursive", "true")
}

response, err := req.Get(fmt.Sprintf("%v/v3/secrets/raw", API_HOST_URL))

if err != nil {
return GetDecryptedSecretsV3Response{}, fmt.Errorf("CallGetDecryptedSecretsV3: Unable to complete api request [err=%s]", err)
}

if response.IsError() {
return GetDecryptedSecretsV3Response{}, fmt.Errorf("CallGetDecryptedSecretsV3: Unsuccessful response: [response=%s]", response)
}
Expand Down
2 changes: 2 additions & 0 deletions k8-operator/packages/api/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type GetEncryptedWorkspaceKeyResponse struct {
type GetEncryptedSecretsV3Request struct {
Environment string `json:"environment"`
WorkspaceId string `json:"workspaceId"`
Recursive bool `json:"recursive"`
SecretPath string `json:"secretPath"`
IncludeImport bool `json:"include_imports"`
ETag string `json:"etag,omitempty"`
Expand Down Expand Up @@ -100,6 +101,7 @@ type GetDecryptedSecretsV3Request struct {
ProjectSlug string `json:"workspaceSlug"`
Environment string `json:"environment"`
SecretPath string `json:"secretPath"`
Recursive bool `json:"recursive"`
ETag string `json:"etag,omitempty"`
}

Expand Down
6 changes: 4 additions & 2 deletions k8-operator/packages/util/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func GetPlainTextSecretsViaUniversalAuth(accessToken string, etag string, secret
secretsResponse, err := api.CallGetDecryptedSecretsV3(httpClient, api.GetDecryptedSecretsV3Request{
ProjectSlug: secretScope.ProjectSlug,
Environment: secretScope.EnvSlug,
Recursive: secretScope.Recursive,
SecretPath: secretScope.SecretsPath,
ETag: etag,
})
Expand All @@ -85,7 +86,7 @@ func GetPlainTextSecretsViaUniversalAuth(accessToken string, etag string, secret
}, nil
}

func GetPlainTextSecretsViaServiceToken(fullServiceToken string, etag string, envSlug string, secretPath string) ([]model.SingleEnvironmentVariable, model.RequestUpdateUpdateDetails, error) {
func GetPlainTextSecretsViaServiceToken(fullServiceToken string, etag string, envSlug string, secretPath string, recursive bool) ([]model.SingleEnvironmentVariable, model.RequestUpdateUpdateDetails, error) {
serviceTokenParts := strings.SplitN(fullServiceToken, ".", 4)
if len(serviceTokenParts) < 4 {
return nil, model.RequestUpdateUpdateDetails{}, fmt.Errorf("invalid service token entered. Please double check your service token and try again")
Expand All @@ -106,6 +107,7 @@ func GetPlainTextSecretsViaServiceToken(fullServiceToken string, etag string, en
encryptedSecretsResponse, err := api.CallGetSecretsV3(httpClient, api.GetEncryptedSecretsV3Request{
WorkspaceId: serviceTokenDetails.Workspace,
Environment: envSlug,
Recursive: recursive,
ETag: etag,
SecretPath: secretPath,
})
Expand Down Expand Up @@ -376,7 +378,7 @@ func ExpandSecrets(secrets []model.SingleEnvironmentVariable, infisicalToken str

if crossRefSec, ok := crossEnvRefSecs[uniqKey]; !ok {
// if not in cross reference cache, fetch it from server
refSecs, _, err := GetPlainTextSecretsViaServiceToken(infisicalToken, "", env, secPath)
refSecs, _, err := GetPlainTextSecretsViaServiceToken(infisicalToken, "", env, secPath, false)
if err != nil {
fmt.Printf("Could not fetch secrets in environment: %s secret-path: %s", env, secPath)
// HandleError(err, fmt.Sprintf("Could not fetch secrets in environment: %s secret-path: %s", env, secPath), "If you are using a service token to fetch secrets, please ensure it is valid")
Expand Down

0 comments on commit e18d830

Please sign in to comment.