Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 57 additions & 1 deletion helm-charts/falcon-image-analyzer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ The following tables list the Falcon sensor configurable parameters and their de
| `image.registryConfigJSON` optional | iar private registry secret in docker config format | None |
| `azure.enabled` optional | Set to `true` if cluster is Azure AKS or self-managed on Azure nodes. | false |
| `azure.azureConfig` optional | Azure config file path | `/etc/kubernetes/azure.json` |
| `azure.keyVault.enabled` optional | Enable Azure Key Vault provider for Secrets Store CSI Driver. Mutually exclusive with `crowdstrikeConfig.clientID`/`clientSecret` and `crowdstrikeConfig.existingSecret`. See [Azure Key Vault Integration](#azure-key-vault-integration). | `false` |
| `azure.keyVault.vaultName` optional | Azure Key Vault name | None |
| `azure.keyVault.tenantID` optional | Azure Tenant ID | None |
| `azure.keyVault.clientID` optional | Azure Workload Identity client ID. Only required if multiple managed identities are assigned to the node. | None |
| `podLabels` optional | Additional labels to add to pod metadata. Use to set `azure.workload.identity/use: "true"` for Azure Workload Identity. | `{}` |
| `gcp.enabled` optional | Set to `true` if cluster is Google GKE or self-managed on Google Cloud GCP nodes. | false |
| `exclusions.namespace` optional ( available in falcon-imageanalyzer >= 1.0.8 and Helm Chart v >= 1.1.3) | Set the value as a comma separate list of namespaces to be excluded. all pods in that namespace(s) will be excluded | "" |
| `exclusions.registry` optional ( available in falcon-imageanalyzer >= 1.0.8 and Helm Chart v >= 1.1.3) | Set the value as a comma separate list of registries to be excluded. all images in that registry(s) will be excluded | "" |
Expand All @@ -108,7 +113,7 @@ The following tables list the Falcon sensor configurable parameters and their de
| `crowdstrikeConfig.enableKlogs` optional | Set to `true` for kubernetes api log verbosity. | false |
| `crowdstrikeConfig.clientID` required | CrowdStrike Falcon OAuth API Client ID | None |
| `crowdstrikeConfig.clientSecret` required | CrowdStrike Falcon OAuth API Client secret | None |
| `crowdstrikeConfig.cid` required | Customer ID (CID) | None |
| `crowdstrikeConfig.cid` required unless `azure.keyVault.enabled` is true and `falcon-cid` is stored in AKV | Customer ID (CID) | None |
| `crowdstrikeConfig.dockerAPIToken` optional | Crowdstrike Artifactory Image Pull Token for pulling IAR image directly from `[CROWDSTRIKE_IMAGE_REGISTRY] described below` | None |
| `crowdstrikeConfig.existingSecret` optional | Existing secret ref name of the customer Kubernetes cluster | None |
| `crowdstrikeConfig.agentRegion` required | Region of the CrowdStrike API to connect to value should be one of `us-1/us-2/eu-1/gov1/gov2` | None |
Expand Down Expand Up @@ -406,6 +411,57 @@ and a trust-relationship as

Here `falcon-image-analyzer` is the namespace of IAR and `imageanalyzer-falcon-image-analyzer` is the name of the iar Service Account

### Azure Key Vault Integration

The chart supports sourcing `AGENT_CLIENT_ID` and `AGENT_CLIENT_SECRET` from [Azure Key Vault](https://azure.microsoft.com/en-us/products/key-vault) via the [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) and the [Azure Key Vault provider](https://azure.github.io/secrets-store-csi-driver-provider-azure/). This avoids storing sensitive values in Helm values or Kubernetes Secrets directly.

#### Prerequisites

The following must be installed and configured on your AKS cluster before enabling this feature:

- [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/getting-started/installation)
- [Azure Key Vault Provider for Secrets Store CSI Driver](https://azure.github.io/secrets-store-csi-driver-provider-azure/docs/getting-started/installation/)
- [Azure Workload Identity](https://azure.github.io/azure-workload-identity/docs/installation.html) webhook installed on the cluster
- AKS cluster with OIDC issuer enabled (`az aks update --enable-oidc-issuer --name <cluster> --resource-group <rg>`)
- A user-assigned managed identity with `Key Vault Secrets User` role on the vault
- A federated credential binding the managed identity to the chart's ServiceAccount in the `falcon-image-analyzer` namespace

#### Required secrets in Azure Key Vault

Create the following secrets in your Azure Key Vault before enabling the integration:

| Secret name | Required | Value |
|:------------------------|:---------|:-----------------------------------------|
| `falcon-client-id` | Yes | CrowdStrike Falcon OAuth API Client ID |
| `falcon-client-secret` | Yes | CrowdStrike Falcon OAuth API Client Secret |
| `falcon-cid` | Only if `crowdstrikeConfig.cid` and `global.falcon.cid` are not set | CrowdStrike Customer ID (CID) |

The `falcon-client-id` and `falcon-client-secret` secret names are fixed. `falcon-cid` is only fetched from AKV when CID is not supplied via `crowdstrikeConfig.cid` or `global.falcon.cid` — if either is set, `AGENT_CID` is sourced from the ConfigMap instead and `falcon-cid` does not need to exist in the vault.

#### Configuration

```yaml
azure:
keyVault:
enabled: true
vaultName: "my-keyvault"
tenantID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# clientID is optional - only required if multiple managed identities are assigned
clientID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

serviceAccount:
annotations:
azure.workload.identity/client-id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

# Add the Workload Identity label to the pod
podLabels:
azure.workload.identity/use: "true"
```

> [!NOTE]
> `azure.keyVault.enabled` cannot be combined with `crowdstrikeConfig.clientID`/`clientSecret` or `crowdstrikeConfig.existingSecret`. These are mutually exclusive secret sources for credentials.
> CID can still be supplied via `crowdstrikeConfig.cid` or `global.falcon.cid` alongside AKV — if either is set, `falcon-cid` is not fetched from the vault.

### Authentication for Private Registries
- If you are using ECR or cloud based Private Registries then assigning the IAM role to the iar service-account in `falcon-image-analyzer` namespace should be enough

Expand Down
51 changes: 49 additions & 2 deletions helm-charts/falcon-image-analyzer/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@ app.kubernetes.io/name: {{ include "falcon-image-analyzer.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
Pod template labels — standard chart labels plus any user-supplied podLabels.
Use instead of falcon-image-analyzer.labels in pod template metadata.
Example use: azure.workload.identity/use: "true" for Azure Workload Identity.
*/}}
{{- define "falcon-image-analyzer.podLabels" -}}
{{- include "falcon-image-analyzer.labels" . }}
{{- with .Values.podLabels }}
{{ toYaml . }}
{{- end }}
{{- end }}

{{/*
Create the name of the service account to use
*/}}
Expand Down Expand Up @@ -234,16 +246,51 @@ Get Falcon CID from global value if it exists
{{- end -}}

{{/*
Get Falcon secret name from global value if it exists
Get Falcon secret name from global value if it exists.
When Azure Key Vault is enabled, returns the name of the secret that
SecretProviderClass.secretObjects will sync from AKV, so that the
existing envFrom/secretRef wiring picks it up unchanged.
*/}}
{{- define "falcon-image-analyzer.falconSecretName" -}}
{{- if and .Values.global.falconSecret.secretName (not .Values.crowdstrikeConfig.existingSecret) -}}
{{- if (include "falcon-image-analyzer.akvEnabled" .) | eq "true" -}}
{{- printf "%s-akv" (include "falcon-image-analyzer.fullname" .) -}}
{{- else if and .Values.global.falconSecret.secretName (not .Values.crowdstrikeConfig.existingSecret) -}}
{{- .Values.global.falconSecret.secretName -}}
{{- else -}}
{{- .Values.crowdstrikeConfig.existingSecret -}}
{{- end -}}
{{- end -}}

{{/*
Returns true when AKV is enabled locally or globally.
*/}}
{{- define "falcon-image-analyzer.akvEnabled" -}}
{{- if or .Values.azure.keyVault.enabled .Values.global.azure.keyVault.enabled -}}
true
{{- end -}}
{{- end -}}

{{/*
Returns the effective AKV vault name (local overrides global).
*/}}
{{- define "falcon-image-analyzer.akvVaultName" -}}
{{- .Values.azure.keyVault.vaultName | default .Values.global.azure.keyVault.vaultName -}}
{{- end -}}

{{/*
Returns the effective AKV tenant ID (local overrides global).
*/}}
{{- define "falcon-image-analyzer.akvTenantID" -}}
{{- .Values.azure.keyVault.tenantID | default .Values.global.azure.keyVault.tenantID -}}
{{- end -}}

{{/*
Returns the effective AKV workload identity client ID (local overrides global).
*/}}
{{- define "falcon-image-analyzer.akvClientID" -}}
{{- .Values.azure.keyVault.clientID | default .Values.global.azure.keyVault.clientID -}}
{{- end -}}

{{/*
Get container registry pull secret from global value if it exists
*/}}
Expand Down
16 changes: 15 additions & 1 deletion helm-charts/falcon-image-analyzer/templates/daemonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ spec:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
labels:
{{- include "falcon-image-analyzer.labels" . | nindent 8 }}
{{- /* podLabels includes all standard chart labels plus optional user-supplied podLabels values */ -}}
{{- include "falcon-image-analyzer.podLabels" . | nindent 8 }}
spec:
{{- if or $imagePullSecret $registryConfigJson (.Values.crowdstrikeConfig.dockerAPIToken) }}
imagePullSecrets:
Expand Down Expand Up @@ -141,6 +142,11 @@ spec:
{{- if .Values.azure.enabled }}
- name: azure-config
mountPath: /etc/kubernetes/azure.json
{{- end }}
{{- if .Values.azure.keyVault.enabled }}
- name: akv-secrets
mountPath: /mnt/secrets-store
readOnly: true
{{- end }}
- mountPath: /run/secrets/tls
name: {{ include "falcon-image-analyzer.name" . }}-tls-certs
Expand All @@ -157,6 +163,14 @@ spec:
path: {{ .Values.azure.azureConfig }}
type: File
{{- end }}
{{- if .Values.azure.keyVault.enabled }}
- name: akv-secrets
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: {{ include "falcon-image-analyzer.fullname" . }}-akv
{{- end }}
- name: {{ include "falcon-image-analyzer.name" . }}-tls-certs
secret:
secretName: {{ include "falcon-image-analyzer.name" . }}-tls
Expand Down
16 changes: 15 additions & 1 deletion helm-charts/falcon-image-analyzer/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ spec:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
labels:
{{- include "falcon-image-analyzer.labels" . | nindent 8 }}
{{- /* podLabels includes all standard chart labels plus optional user-supplied podLabels values */ -}}
{{- include "falcon-image-analyzer.podLabels" . | nindent 8 }}
spec:
{{- if or $imagePullSecret $registryConfigJson (.Values.crowdstrikeConfig.dockerAPIToken) }}
imagePullSecrets:
Expand Down Expand Up @@ -152,6 +153,11 @@ spec:
{{- if .Values.azure.enabled }}
- name: azure-config
mountPath: /etc/kubernetes/azure.json
{{- end }}
{{- if .Values.azure.keyVault.enabled }}
- name: akv-secrets
mountPath: /mnt/secrets-store
readOnly: true
{{- end }}
- mountPath: /run/secrets/tls
name: {{ include "falcon-image-analyzer.name" . }}-tls-certs
Expand All @@ -168,6 +174,14 @@ spec:
path: {{ .Values.azure.azureConfig }}
type: File
{{- end }}
{{- if .Values.azure.keyVault.enabled }}
- name: akv-secrets
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: {{ include "falcon-image-analyzer.fullname" . }}-akv
{{- end }}
- name: {{ include "falcon-image-analyzer.name" . }}-tls-certs
secret:
secretName: {{ include "falcon-image-analyzer.name" . }}-tls
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{{- if (include "falcon-image-analyzer.akvEnabled" .) | eq "true" }}
{{- if .Values.crowdstrikeConfig.existingSecret }}
{{- fail "azure.keyVault and crowdstrikeConfig.existingSecret cannot be used together. Use one secret source." }}
{{- end }}
{{- if and .Values.crowdstrikeConfig.clientID .Values.crowdstrikeConfig.clientSecret }}
{{- fail "azure.keyVault and crowdstrikeConfig.clientID/clientSecret cannot be used together. Use one secret source." }}
{{- end }}
{{- if not (include "falcon-image-analyzer.akvVaultName" .) }}
{{- fail "azure.keyVault.vaultName (or global.azure.keyVault.vaultName) is required when AKV is enabled." }}
{{- end }}
{{- if not (include "falcon-image-analyzer.akvTenantID" .) }}
{{- fail "azure.keyVault.tenantID (or global.azure.keyVault.tenantID) is required when AKV is enabled." }}
{{- end }}
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: {{ include "falcon-image-analyzer.fullname" . }}-akv
namespace: {{ include "falcon-image-analyzer.namespace" . }}
labels:
{{- include "falcon-image-analyzer.labels" . | nindent 4 }}
spec:
provider: azure
parameters:
usePodIdentity: "false"
useVMManagedIdentity: "false"
{{- if (include "falcon-image-analyzer.akvClientID" .) }}
clientID: {{ include "falcon-image-analyzer.akvClientID" . | quote }}
{{- end }}
keyvaultName: {{ include "falcon-image-analyzer.akvVaultName" . | quote }}
tenantId: {{ include "falcon-image-analyzer.akvTenantID" . | quote }}
objects: |
array:
- |
objectName: "falcon-client-id"
objectType: secret
objectVersion: ""
- |
objectName: "falcon-client-secret"
objectType: secret
objectVersion: ""
{{- if not (or .Values.crowdstrikeConfig.cid .Values.global.falcon.cid) }}
- |
objectName: "falcon-cid"
objectType: secret
objectVersion: ""
{{- end }}
secretObjects:
- secretName: {{ include "falcon-image-analyzer.fullname" . }}-akv
type: Opaque
data:
- objectName: "falcon-client-id"
key: AGENT_CLIENT_ID
- objectName: "falcon-client-secret"
key: AGENT_CLIENT_SECRET
{{- if not (or .Values.crowdstrikeConfig.cid .Values.global.falcon.cid) }}
- objectName: "falcon-cid"
key: AGENT_CID
{{- end }}
{{- end }}
Loading