Skip to content
This repository has been archived by the owner on Nov 28, 2022. It is now read-only.

Commit

Permalink
Do not inject sidecars if only job and secrets modes are enabled and …
Browse files Browse the repository at this point in the history
…secrets type is "static" (#45)
  • Loading branch information
asaintsever authored Apr 2, 2021
1 parent 2877ebb commit ffa41a0
Show file tree
Hide file tree
Showing 25 changed files with 323 additions and 70 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog for Vault Sidecar Injector

## Release v7.1.1 - 2021-04-02

**Fixed**

- [VSI #45](https://github.com/Talend/vault-sidecar-injector/pull/45) - Do not inject sidecars if only job and secrets modes are enabled and secrets type is "static"

## Release v7.1.0 - 2021-02-09

A new `sidecar.vault.talend.org/vault-image` annotation has been added to override the default injected image. Refer to the [samples](samples) for a [working example](samples/app-dep-10-secrets_custom_image_notify.yaml).
Expand Down
2 changes: 1 addition & 1 deletion VERSION_CHART
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4.2.0
4.2.1
2 changes: 1 addition & 1 deletion VERSION_RELEASE
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7.1.0
7.1.1
2 changes: 1 addition & 1 deletion VERSION_VSI
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7.1.0
7.1.1
6 changes: 3 additions & 3 deletions doc/Usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ Depending on the modes you decide to enable and whether you opt for static or dy
<td align="center">X</td><td/><td/><td/><td align="center" bgcolor="grey">X</td><td bgcolor="grey"/>
</tr>
<tr>
<td align="center">X</td><td/><td/><td align="center">X<b><i>¹</i></b></td><td align="center" bgcolor="grey">X (secrets)</td><td align="center" bgcolor="grey">X (job)</td>
<td align="center">X</td><td/><td/><td align="center">X<b><i>¹</i></b></td><td align="center" bgcolor="grey">X (secrets)</td><td align="center" bgcolor="grey"/>
</tr>
<tr>
<td/><td align="center">X</td><td/><td/><td bgcolor="grey"/><td align="center" bgcolor="grey">X</td>
Expand Down Expand Up @@ -141,6 +141,6 @@ Depending on the modes you decide to enable and whether you opt for static or dy
</tr>
</table>

> **[1]** *on job mode:* if you only set mode annotation's value to "job", `secrets` mode will be enabled automatically and configured to handle dynamic secrets (unless you set `sidecar.vault.talend.org/secrets-type` to "static" but note that in this situation, there is no need, although we do not prevent it, to enable job mode as no Vault Agent will be injected as sidecar).
> **[1]** *on job mode:* if you only set mode annotation's value to "job", `secrets` mode will be enabled automatically and configured to handle dynamic secrets (unless you set `sidecar.vault.talend.org/secrets-type` to "static" but note that in this situation, there is no need, although we do not prevent it, to enable job mode explicitly as no sidecar will be injected).
> **[2]** *on number of injected sidecars:* for Kubernetes **Deployment** workloads, **only one sidecar container** is added to your pod to handle dynamic secrets and/or proxy. For Kubernetes **Job** workloads, **two sidecars** are injected to achieve the same tasks.
> **[2]** *on number of injected sidecars:* for Kubernetes **Deployment** workloads, **only one sidecar container** is added to your pod to handle dynamic secrets and/or proxy. For Kubernetes **Job** workloads, **two sidecars** are injected to achieve the same tasks (or 0 in case you only enable job mode with static secrets).
2 changes: 1 addition & 1 deletion doc/announcements/Static-vs-Dynamic-Secrets.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Available with `Vault Sidecar Injector` version **`6.0.0`**, *static secrets* su

A new annotation, `sidecar.vault.talend.org/secrets-type`, is supported to explicitly define what kind of secrets you intend to fetch, default being *dynamic secrets*.

When *static secrets* are set, `Vault Sidecar Injector` will only inject an init container in your workload's pod. Fetched secrets will be stored in a file in a shared memory volume, the same way it is already done for *dynamic secrets*. As a result, if you do not enable other modes (e.g. *proxy*, *job*) no sidecar will be added. It also means that you don't have to leverage hooks or wait for the injected Vault Agent to fetch your secrets: your workload can access the values right after its container is started. The drawback of course is that your secrets **will not be automatically refreshed upon changes**, opt for *dynamic secrets* if this behavior is required.
When *static secrets* are set, `Vault Sidecar Injector` will only inject an init container in your workload's pod. Fetched secrets will be stored in a file in a shared memory volume, the same way it is already done for *dynamic secrets*. As a result, if you do not enable other modes (e.g. *proxy*) no sidecar will be added (Note that enabling *job* mode with static secrets will not incur any sidecar injection either). It also means that you don't have to leverage hooks or wait for the injected Vault Agent to fetch your secrets: your workload can access the values right after its container is started. The drawback of course is that your secrets **will not be automatically refreshed upon changes**, opt for *dynamic secrets* if this behavior is required.

If you enable several modes, you may end up with both init container and sidecar(s) in your workload. A comprehensive table is provided in the main documention in section [Modes and Injection Config Overview](../Usage.md#modes-and-injection-config-overview).

Expand Down
22 changes: 22 additions & 0 deletions pkg/mode/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright © 2019-2021 Talend - www.talend.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package mode

const (
//--- Vault Sidecar Injector supported modes
VaultInjectorModeSecrets = "secrets" // Enable fetching of secrets from Vault store
VaultInjectorModeProxy = "proxy" // Enable local Vault proxy
VaultInjectorModeJob = "job" // Enable handling of Kubernetes Job
)
5 changes: 0 additions & 5 deletions pkg/mode/job/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,3 @@ const (
jobContainerNameEnv = "VSI_JOB_CNT_NAME" // Env var for name of the app job's container
jobWorkloadEnv = "VSI_JOB_WORKLOAD" // Env var set to "true" if submitted workload is a k8s job
)

const (
//--- Vault Sidecar Injector supported modes
VaultInjectorModeJob = "job" // Enable handling of Kubernetes Job
)
16 changes: 13 additions & 3 deletions pkg/mode/job/job-func-inject.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2019-2020 Talend - www.talend.com
// Copyright © 2019-2021 Talend - www.talend.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,8 @@ package job
import (
"errors"
ctx "talend/vault-sidecar-injector/pkg/context"
m "talend/vault-sidecar-injector/pkg/mode"
"talend/vault-sidecar-injector/pkg/mode/secrets"

corev1 "k8s.io/api/core/v1"
"k8s.io/klog"
Expand All @@ -25,13 +27,21 @@ import (
func jobModeInject(containerBasePath string, podContainers []corev1.Container, containerName string, env []corev1.EnvVar, context *ctx.InjectionContext) (bool, error) {
if (containerBasePath == ctx.JsonPathContainers) && (len(podContainers) != 1) {
err := errors.New("Submitted pod should contain only one container")
klog.Errorf("[%s] %s", VaultInjectorModeJob, err.Error())
klog.Errorf("[%s] %s", m.VaultInjectorModeJob, err.Error())
return false, err
}

// If static secrets and job (+ secrets as it'll be enabled also) are the only enabled modes then do not inject job containers as sidecars (no need for job babysitter nor Vault Agent)
if (containerBasePath == ctx.JsonPathContainers) &&
m.IsEnabledModes(context.ModesStatus, []string{m.VaultInjectorModeSecrets, m.VaultInjectorModeJob}) &&
secrets.IsSecretsStatic(context) {
klog.Infof("[%s] Static secrets in use and only enabled modes are '%s' and '%s': skip injecting job container %s (path: %s)", m.VaultInjectorModeJob, m.VaultInjectorModeJob, m.VaultInjectorModeSecrets, containerName, containerBasePath)
return false, nil
}

for _, cntName := range jobContainerNames[containerBasePath] {
if cntName == containerName {
klog.Infof("[%s] Injecting container %s (path: %s)", VaultInjectorModeJob, containerName, containerBasePath)
klog.Infof("[%s] Injecting container %s (path: %s)", m.VaultInjectorModeJob, containerName, containerBasePath)

// Resolve job env vars
for envIdx := range env {
Expand Down
4 changes: 2 additions & 2 deletions pkg/mode/job/job.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2019-2020 Talend - www.talend.com
// Copyright © 2019-2021 Talend - www.talend.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -22,7 +22,7 @@ func init() {
// Register mode
m.RegisterMode(
m.VaultInjectorModeInfo{
Key: VaultInjectorModeJob,
Key: m.VaultInjectorModeJob,
DefaultMode: false,
EnableDefaultMode: true, // Default mode will also be enabled if job is **the only mode on** (as it does not make sense to have only this mode)
InjectContainerFunc: jobModeInject,
Expand Down
21 changes: 20 additions & 1 deletion pkg/mode/mode.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2019-2020 Talend - www.talend.com
// Copyright © 2019-2021 Talend - www.talend.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,7 @@ package mode
import (
"os"

"github.com/stretchr/testify/assert"
"k8s.io/klog"
)

Expand Down Expand Up @@ -78,3 +79,21 @@ func GetModesStatus(requestedModes []string, modes map[string]bool) {
modes[defaultModeKey] = true
}
}

// Use assert.ElementsMatch for comparing slices, but with a bool result.
type dummyt struct{}

func (t dummyt) Errorf(string, ...interface{}) {}

func IsEnabledModes(modesStatus map[string]bool, modesToCheck []string) bool {
var enabledModes []string

for mode, enabled := range modesStatus {
if enabled {
enabledModes = append(enabledModes, mode)
}
}

// Allow to check for equality on slices without order. See https://stackoverflow.com/a/66062073
return assert.ElementsMatch(dummyt{}, enabledModes, modesToCheck)
}
5 changes: 0 additions & 5 deletions pkg/mode/proxy/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,3 @@ const (
//--- Vault Agent env vars related to modes
vaultProxyConfigPlaceholderEnv = "VSI_PROXY_CONFIG_PLACEHOLDER"
)

const (
//--- Vault Sidecar Injector supported modes
VaultInjectorModeProxy = "proxy" // Enable local Vault proxy
)
7 changes: 4 additions & 3 deletions pkg/mode/proxy/proxy-func-inject.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2019-2020 Talend - www.talend.com
// Copyright © 2019-2021 Talend - www.talend.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,7 @@ package proxy

import (
ctx "talend/vault-sidecar-injector/pkg/context"
m "talend/vault-sidecar-injector/pkg/mode"

corev1 "k8s.io/api/core/v1"
"k8s.io/klog"
Expand All @@ -24,12 +25,12 @@ import (
func proxyModeInject(containerBasePath string, podContainers []corev1.Container, containerName string, env []corev1.EnvVar, context *ctx.InjectionContext) (bool, error) {
for _, cntName := range proxyContainerNames[containerBasePath] {
if cntName == containerName {
klog.Infof("[%s] Injecting container %s (path: %s)", VaultInjectorModeProxy, containerName, containerBasePath)
klog.Infof("[%s] Injecting container %s (path: %s)", m.VaultInjectorModeProxy, containerName, containerBasePath)

// Resolve proxy env vars
for envIdx := range env {
if env[envIdx].Name == vaultProxyConfigPlaceholderEnv {
env[envIdx].Value = context.ModesConfig[VaultInjectorModeProxy].GetTemplate()
env[envIdx].Value = context.ModesConfig[m.VaultInjectorModeProxy].GetTemplate()
}
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/mode/proxy/proxy.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2019-2020 Talend - www.talend.com
// Copyright © 2019-2021 Talend - www.talend.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -22,7 +22,7 @@ func init() {
// Register mode
m.RegisterMode(
m.VaultInjectorModeInfo{
Key: VaultInjectorModeProxy,
Key: m.VaultInjectorModeProxy,
DefaultMode: false,
EnableDefaultMode: false,
Annotations: []string{vaultInjectorAnnotationProxyPortKey},
Expand Down
5 changes: 0 additions & 5 deletions pkg/mode/secrets/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,6 @@ const (
secretsTemplatesPlaceholderEnv = "VSI_SECRETS_TEMPLATES_PLACEHOLDER"
)

const (
//--- Vault Sidecar Injector supported modes
VaultInjectorModeSecrets = "secrets" // Enable fetching of secrets from Vault store
)

const (
//--- Vault Sidecar Injector secrets type
vaultInjectorSecretsTypeDynamic = "dynamic"
Expand Down
17 changes: 9 additions & 8 deletions pkg/mode/secrets/secrets-func-compute.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2019-2020 Talend - www.talend.com
// Copyright © 2019-2021 Talend - www.talend.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -20,6 +20,7 @@ import (
"strings"
cfg "talend/vault-sidecar-injector/pkg/config"
ctx "talend/vault-sidecar-injector/pkg/context"
m "talend/vault-sidecar-injector/pkg/mode"

"k8s.io/klog"
)
Expand Down Expand Up @@ -49,7 +50,7 @@ func secretsModeCompute(config *cfg.VSIConfig, labels, annotations map[string]st

if !secretsTypeSupported {
err := fmt.Errorf("Submitted pod makes use of unsupported secrets type '%s'", secretsType)
klog.Errorf("[%s] %s", VaultInjectorModeSecrets, err.Error())
klog.Errorf("[%s] %s", m.VaultInjectorModeSecrets, err.Error())
return nil, err
}
}
Expand All @@ -67,22 +68,22 @@ func secretsModeCompute(config *cfg.VSIConfig, labels, annotations map[string]st

if !secretsInjectionMethodSupported {
err := fmt.Errorf("Submitted pod makes use of unsupported secrets injection method '%s'", secretsInjectionMethod)
klog.Errorf("[%s] %s", VaultInjectorModeSecrets, err.Error())
klog.Errorf("[%s] %s", m.VaultInjectorModeSecrets, err.Error())
return nil, err
}
}

// If dynamic secrets and injection method is "env": return error (unsupported)
if secretsType == vaultInjectorSecretsTypeDynamic && secretsInjectionMethod == vaultInjectorSecretsInjectionMethodEnv {
err := fmt.Errorf("Submitted pod uses unsupported combination of secrets injection method '%s' with dynamic secrets", vaultInjectorSecretsInjectionMethodEnv)
klog.Errorf("[%s] %s", VaultInjectorModeSecrets, err.Error())
klog.Errorf("[%s] %s", m.VaultInjectorModeSecrets, err.Error())
return nil, err
}

// If authentication method is "approle" and static secrets: return error (unsupported because, as static secrets, approle needs initContainer)
if secretsType == vaultInjectorSecretsTypeStatic && annotations[config.VaultInjectorAnnotationsFQ[ctx.VaultInjectorAnnotationAuthMethodKey]] == ctx.VaultAppRoleAuthMethod {
err := fmt.Errorf("Submitted pod uses unsupported combination of Vault Auth Method '%s' with static secrets", ctx.VaultAppRoleAuthMethod)
klog.Errorf("[%s] %s", VaultInjectorModeSecrets, err.Error())
klog.Errorf("[%s] %s", m.VaultInjectorModeSecrets, err.Error())
return nil, err
}

Expand All @@ -92,7 +93,7 @@ func secretsModeCompute(config *cfg.VSIConfig, labels, annotations map[string]st

if applicationLabel == "" || applicationServiceLabel == "" {
err := fmt.Errorf("Submitted pod must contain labels %s and %s", config.ApplicationLabelKey, config.ApplicationServiceLabelKey)
klog.Errorf("[%s] %s", VaultInjectorModeSecrets, err.Error())
klog.Errorf("[%s] %s", m.VaultInjectorModeSecrets, err.Error())
return nil, err
}

Expand All @@ -107,7 +108,7 @@ func secretsModeCompute(config *cfg.VSIConfig, labels, annotations map[string]st
// We must have same numbers of secrets path & secrets destinations
if templateDestNum != secretsPathNum {
err := errors.New("Submitted pod must contain same numbers of secrets path and secrets destinations")
klog.Errorf("[%s] %s", VaultInjectorModeSecrets, err.Error())
klog.Errorf("[%s] %s", m.VaultInjectorModeSecrets, err.Error())
return nil, err
}

Expand All @@ -120,7 +121,7 @@ func secretsModeCompute(config *cfg.VSIConfig, labels, annotations map[string]st
// We must have same numbers of custom templates & secrets destinations ...
if templateDestNum != secretsTemplateNum {
err := errors.New("Submitted pod must contain same numbers of templates and secrets destinations")
klog.Errorf("[%s] %s", VaultInjectorModeSecrets, err.Error())
klog.Errorf("[%s] %s", m.VaultInjectorModeSecrets, err.Error())
return nil, err
}

Expand Down
13 changes: 7 additions & 6 deletions pkg/mode/secrets/secrets-func-inject.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2019-2020 Talend - www.talend.com
// Copyright © 2019-2021 Talend - www.talend.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,7 @@ package secrets

import (
ctx "talend/vault-sidecar-injector/pkg/context"
m "talend/vault-sidecar-injector/pkg/mode"

corev1 "k8s.io/api/core/v1"
"k8s.io/klog"
Expand All @@ -25,20 +26,20 @@ func secretsModeInject(containerBasePath string, podContainers []corev1.Containe
for _, cntName := range secretsContainerNames[containerBasePath] {
if cntName == containerName {
// Look type of secrets: inject init container only for static secrets
if (isSecretsStatic(context) && (containerBasePath == ctx.JsonPathInitContainers)) ||
(!isSecretsStatic(context) && (containerBasePath == ctx.JsonPathContainers)) {
if (IsSecretsStatic(context) && (containerBasePath == ctx.JsonPathInitContainers)) ||
(!IsSecretsStatic(context) && (containerBasePath == ctx.JsonPathContainers)) {

if (cntName == secretsEnvInitContainerName) && !isSecretsInjectionEnv(context) {
if (cntName == secretsEnvInitContainerName) && !IsSecretsInjectionEnv(context) {
// Do not inject env init container if injection method is not 'env'
return false, nil
}

klog.Infof("[%s] Injecting container %s (path: %s)", VaultInjectorModeSecrets, containerName, containerBasePath)
klog.Infof("[%s] Injecting container %s (path: %s)", m.VaultInjectorModeSecrets, containerName, containerBasePath)

// Resolve secrets env vars
for envIdx := range env {
if env[envIdx].Name == secretsTemplatesPlaceholderEnv {
env[envIdx].Value = context.ModesConfig[VaultInjectorModeSecrets].GetTemplate()
env[envIdx].Value = context.ModesConfig[m.VaultInjectorModeSecrets].GetTemplate()
}
}

Expand Down
Loading

0 comments on commit ffa41a0

Please sign in to comment.