Skip to content
Merged
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
28 changes: 28 additions & 0 deletions deploy/charts/disco-agent/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,31 @@ data:
version: v1
label-selectors:
- conjur.org/name=conjur-connect-configmap
- kind: k8s-dynamic
name: ark/esoexternalsecrets
config:
resource-type:
group: external-secrets.io
version: v1
resource: externalsecrets
- kind: k8s-dynamic
name: ark/esosecretstores
config:
resource-type:
group: external-secrets.io
version: v1
resource: secretstores
- kind: k8s-dynamic
name: ark/esoclusterexternalsecrets
config:
resource-type:
group: external-secrets.io
version: v1
resource: clusterexternalsecrets
- kind: k8s-dynamic
name: ark/esoclustersecretstores
config:
resource-type:
group: external-secrets.io
version: v1
resource: clustersecretstores
Comment on lines +120 to +147
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These ESO CRD gatherers are enabled by default in the chart, but the chart RBAC currently only grants explicit access to core Secrets/RBAC plus the built-in view role. Custom resources like external-secrets.io/* typically require explicit RBAC (unless the CRDs aggregate into view), otherwise the informer will fail to list/watch and the gatherer will stay empty. Please add explicit ClusterRole rules for externalsecrets, secretstores, clusterexternalsecrets, and clustersecretstores in external-secrets.io (or make these gatherers opt-in).

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CRD does aggregate into view

112 changes: 112 additions & 0 deletions deploy/charts/disco-agent/tests/__snapshot__/configmap_test.yaml.snap
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,34 @@ custom-cluster-description:
version: v1
label-selectors:
- conjur.org/name=conjur-connect-configmap
- kind: k8s-dynamic
name: ark/esoexternalsecrets
config:
resource-type:
group: external-secrets.io
version: v1
resource: externalsecrets
- kind: k8s-dynamic
name: ark/esosecretstores
config:
resource-type:
group: external-secrets.io
version: v1
resource: secretstores
- kind: k8s-dynamic
name: ark/esoclusterexternalsecrets
config:
resource-type:
group: external-secrets.io
version: v1
resource: clusterexternalsecrets
- kind: k8s-dynamic
name: ark/esoclustersecretstores
config:
resource-type:
group: external-secrets.io
version: v1
resource: clustersecretstores
kind: ConfigMap
metadata:
labels:
Expand Down Expand Up @@ -222,6 +250,34 @@ custom-cluster-name:
version: v1
label-selectors:
- conjur.org/name=conjur-connect-configmap
- kind: k8s-dynamic
name: ark/esoexternalsecrets
config:
resource-type:
group: external-secrets.io
version: v1
resource: externalsecrets
- kind: k8s-dynamic
name: ark/esosecretstores
config:
resource-type:
group: external-secrets.io
version: v1
resource: secretstores
- kind: k8s-dynamic
name: ark/esoclusterexternalsecrets
config:
resource-type:
group: external-secrets.io
version: v1
resource: clusterexternalsecrets
- kind: k8s-dynamic
name: ark/esoclustersecretstores
config:
resource-type:
group: external-secrets.io
version: v1
resource: clustersecretstores
kind: ConfigMap
metadata:
labels:
Expand Down Expand Up @@ -339,6 +395,34 @@ custom-period:
version: v1
label-selectors:
- conjur.org/name=conjur-connect-configmap
- kind: k8s-dynamic
name: ark/esoexternalsecrets
config:
resource-type:
group: external-secrets.io
version: v1
resource: externalsecrets
- kind: k8s-dynamic
name: ark/esosecretstores
config:
resource-type:
group: external-secrets.io
version: v1
resource: secretstores
- kind: k8s-dynamic
name: ark/esoclusterexternalsecrets
config:
resource-type:
group: external-secrets.io
version: v1
resource: clusterexternalsecrets
- kind: k8s-dynamic
name: ark/esoclustersecretstores
config:
resource-type:
group: external-secrets.io
version: v1
resource: clustersecretstores
kind: ConfigMap
metadata:
labels:
Expand Down Expand Up @@ -456,6 +540,34 @@ defaults:
version: v1
label-selectors:
- conjur.org/name=conjur-connect-configmap
- kind: k8s-dynamic
name: ark/esoexternalsecrets
config:
resource-type:
group: external-secrets.io
version: v1
resource: externalsecrets
- kind: k8s-dynamic
name: ark/esosecretstores
config:
resource-type:
group: external-secrets.io
version: v1
resource: secretstores
- kind: k8s-dynamic
name: ark/esoclusterexternalsecrets
config:
resource-type:
group: external-secrets.io
version: v1
resource: clusterexternalsecrets
- kind: k8s-dynamic
name: ark/esoclustersecretstores
config:
resource-type:
group: external-secrets.io
version: v1
resource: clustersecretstores
kind: ConfigMap
metadata:
labels:
Expand Down
36 changes: 36 additions & 0 deletions examples/machinehub.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,39 @@ data-gatherers:
version: v1
label-selectors:
- conjur.org/name=conjur-connect-configmap

# Gather External Secrets Operator ExternalSecret resources
- name: ark/esoexternalsecrets
kind: k8s-dynamic
config:
resource-type:
group: external-secrets.io
version: v1
resource: externalsecrets

# Gather External Secrets Operator SecretStore resources
- name: ark/esosecretstores
kind: k8s-dynamic
config:
resource-type:
group: external-secrets.io
version: v1
resource: secretstores

# Gather External Secrets Operator ClusterExternalSecret resources
- name: ark/esoclusterexternalsecrets
kind: k8s-dynamic
config:
resource-type:
group: external-secrets.io
version: v1
resource: clusterexternalsecrets

# Gather External Secrets Operator ClusterSecretStore resources
- name: ark/esoclustersecretstores
kind: k8s-dynamic
config:
resource-type:
group: external-secrets.io
version: v1
resource: clustersecretstores
24 changes: 24 additions & 0 deletions examples/machinehub/input.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,5 +159,29 @@
"data": {
"items": []
}
},
{
"data-gatherer": "ark/esoexternalsecrets",
"data": {
"items": []
}
},
{
"data-gatherer": "ark/esosecretstores",
"data": {
"items": []
}
},
{
"data-gatherer": "ark/esoclusterexternalsecrets",
"data": {
"items": []
}
},
{
"data-gatherer": "ark/esoclustersecretstores",
"data": {
"items": []
}
}
]
27 changes: 27 additions & 0 deletions hack/ark/cluster-external-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Sample ClusterExternalSecret for e2e testing
# This is a minimal ClusterExternalSecret CR that will be discovered by the agent.
# This is a cluster-scoped resource that can create ExternalSecrets in multiple namespaces.
apiVersion: external-secrets.io/v1
kind: ClusterExternalSecret
metadata:
name: e2e-test-cluster-external-secret
labels:
app.kubernetes.io/name: e2e-test
app.kubernetes.io/component: cluster-external-secret
spec:
externalSecretSpec:
refreshInterval: 1h
secretStoreRef:
name: e2e-test-cluster-secret-store
kind: ClusterSecretStore
target:
name: e2e-test-synced-secret
creationPolicy: Owner
data:
- secretKey: example-key
remoteRef:
key: dummy/path/to/secret
property: password
namespaceSelector:
matchLabels:
environment: test
18 changes: 18 additions & 0 deletions hack/ark/cluster-secret-store.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Sample ClusterSecretStore for e2e testing
# This is a minimal ClusterSecretStore CR that will be discovered by the agent.
# This is a cluster-scoped resource that can be referenced by ExternalSecrets in any namespace.
apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
name: e2e-test-cluster-secret-store
labels:
app.kubernetes.io/name: e2e-test
app.kubernetes.io/component: cluster-secret-store
spec:
provider:
# Fake provider configuration - this won't actually work but allows the CR to be created
fake:
data:
- key: dummy/path/to/secret
value: dummy-value
version: "1"
25 changes: 25 additions & 0 deletions hack/ark/external-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Sample ExternalSecret for e2e testing
# This is a minimal ExternalSecret CR that will be discovered by the agent.
# Note: This requires the External Secrets Operator CRDs to be installed,
# but does not require a working secrets backend.
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: e2e-test-external-secret
namespace: default
labels:
app.kubernetes.io/name: e2e-test
app.kubernetes.io/component: external-secret
spec:
refreshInterval: 1h
secretStoreRef:
name: e2e-test-secret-store
kind: SecretStore
target:
name: e2e-test-synced-secret
creationPolicy: Owner
data:
- secretKey: example-key
remoteRef:
key: dummy/path/to/secret
property: password
20 changes: 20 additions & 0 deletions hack/ark/secret-store.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Sample SecretStore for e2e testing
# This is a minimal SecretStore CR that will be discovered by the agent.
# Note: This requires the External Secrets Operator CRDs to be installed,
# but does not require a working secrets backend.
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
name: e2e-test-secret-store
namespace: default
labels:
app.kubernetes.io/name: e2e-test
app.kubernetes.io/component: secret-store
spec:
provider:
# Fake provider configuration - this won't actually work but allows the CR to be created
fake:
data:
- key: dummy/path/to/secret
value: dummy-value
version: "1"
19 changes: 19 additions & 0 deletions hack/ark/test-e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,25 @@ kubectl create secret generic e2e-sample-secret-$(date '+%s') \
# in the ark/configmaps data gatherer (conjur.org/name=conjur-connect-configmap).
kubectl apply -f "${root_dir}/hack/ark/conjur-connect-configmap.yaml"

# Install External Secrets Operator CRDs and controller
#
# This is required for the agent to discover ExternalSecret and SecretStore resources.
echo "Installing External Secrets Operator..."
helm repo add external-secrets https://charts.external-secrets.io
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

helm repo add external-secrets ... is not idempotent and will exit non-zero if the repo already exists, which breaks reruns because the script is running with set -o errexit. Use --force-update (or otherwise handle the "already exists" case) so the e2e script can be re-run reliably.

Suggested change
helm repo add external-secrets https://charts.external-secrets.io
helm repo add external-secrets https://charts.external-secrets.io --force-update

Copilot uses AI. Check for mistakes.
helm repo update
helm upgrade --install external-secrets \
external-secrets/external-secrets \
--namespace external-secrets-system \
--create-namespace \
--wait \
--set installCRDs=true
Comment on lines +87 to +94
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script installs the external-secrets/external-secrets Helm chart from the public https://charts.external-secrets.io repository without pinning to a specific immutable version or verifying integrity, so each test run may execute arbitrary code if the chart repository or DNS is compromised. Because the chart deploys a controller with cluster-level RBAC, a malicious or hijacked chart could access Kubernetes secrets (including the agent-credentials secret created earlier) and other cluster resources. Pin the chart to a specific version or digest and, where possible, add integrity verification to reduce this supply-chain risk.

Copilot uses AI. Check for mistakes.

# Create sample External Secrets Operator resources that will be discovered by the agent
kubectl apply -f "${root_dir}/hack/ark/secret-store.yaml"
kubectl apply -f "${root_dir}/hack/ark/external-secret.yaml"
kubectl apply -f "${root_dir}/hack/ark/cluster-secret-store.yaml"
kubectl apply -f "${root_dir}/hack/ark/cluster-external-secret.yaml"

# We use a non-existent tag and omit the `--version` flag, to work around a Helm
# v4 bug. See: https://github.com/helm/helm/issues/31600
helm upgrade agent "oci://${ARK_CHART}:NON_EXISTENT_TAG@${ARK_CHART_DIGEST}" \
Expand Down
8 changes: 8 additions & 0 deletions internal/cyberark/dataupload/dataupload.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ type Snapshot struct {
ServiceAccounts []runtime.Object `json:"serviceaccounts"`
// ConfigMaps is a list of ConfigMap resources in the cluster.
ConfigMaps []runtime.Object `json:"configmaps"`
// ExternalSecrets is a list of ExternalSecret resources in the cluster.
ExternalSecrets []runtime.Object `json:"externalsecrets"`
// SecretStores is a list of SecretStore resources in the cluster.
SecretStores []runtime.Object `json:"secretstores"`
// ClusterExternalSecrets is a list of ClusterExternalSecret resources in the cluster.
ClusterExternalSecrets []runtime.Object `json:"clusterexternalsecrets"`
// ClusterSecretStores is a list of ClusterSecretStore resources in the cluster.
ClusterSecretStores []runtime.Object `json:"clustersecretstores"`
// Roles is a list of Role resources in the cluster.
Roles []runtime.Object `json:"roles"`
// ClusterRoles is a list of ClusterRole resources in the cluster.
Expand Down
12 changes: 12 additions & 0 deletions pkg/client/client_cyberark.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,18 @@ var defaultExtractorFunctions = map[string]func(*api.DataReading, *dataupload.Sn
"ark/configmaps": func(r *api.DataReading, s *dataupload.Snapshot) error {
return extractResourceListFromReading(r, &s.ConfigMaps)
},
"ark/esoexternalsecrets": func(r *api.DataReading, s *dataupload.Snapshot) error {
return extractResourceListFromReading(r, &s.ExternalSecrets)
},
"ark/esosecretstores": func(r *api.DataReading, s *dataupload.Snapshot) error {
return extractResourceListFromReading(r, &s.SecretStores)
},
"ark/esoclusterexternalsecrets": func(r *api.DataReading, s *dataupload.Snapshot) error {
return extractResourceListFromReading(r, &s.ClusterExternalSecrets)
},
"ark/esoclustersecretstores": func(r *api.DataReading, s *dataupload.Snapshot) error {
return extractResourceListFromReading(r, &s.ClusterSecretStores)
},
}

// convertDataReadings processes a list of DataReadings using the provided
Expand Down
Loading