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
14 changes: 14 additions & 0 deletions deploy/charts/disco-agent/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,17 @@ data:
group: external-secrets.io
version: v1
resource: clustersecretstores
- kind: k8s-dynamic
name: ark/secretproviderclasses
config:
resource-type:
group: secrets-store.csi.x-k8s.io
version: v1
resource: secretproviderclasses
- kind: k8s-dynamic
name: ark/secretproviderclasspodstatuses
config:
resource-type:
group: secrets-store.csi.x-k8s.io
version: v1
resource: secretproviderclasspodstatuses
28 changes: 28 additions & 0 deletions deploy/charts/disco-agent/templates/rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,31 @@ subjects:
- kind: ServiceAccount
name: {{ include "disco-agent.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "disco-agent.fullname" . }}-csi-reader
labels:
{{- include "disco-agent.labels" . | nindent 4 }}
rules:
- apiGroups: ["secrets-store.csi.x-k8s.io"]
resources:
- secretproviderclasses
- secretproviderclasspodstatuses
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "disco-agent.fullname" . }}-csi-reader
labels:
{{- include "disco-agent.labels" . | nindent 4 }}
roleRef:
kind: ClusterRole
name: {{ include "disco-agent.fullname" . }}-csi-reader
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: {{ include "disco-agent.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,20 @@ custom-cluster-description:
group: external-secrets.io
version: v1
resource: clustersecretstores
- kind: k8s-dynamic
name: ark/secretproviderclasses
config:
resource-type:
group: secrets-store.csi.x-k8s.io
version: v1
resource: secretproviderclasses
- kind: k8s-dynamic
name: ark/secretproviderclasspodstatuses
config:
resource-type:
group: secrets-store.csi.x-k8s.io
version: v1
resource: secretproviderclasspodstatuses
kind: ConfigMap
metadata:
labels:
Expand Down Expand Up @@ -278,6 +292,20 @@ custom-cluster-name:
group: external-secrets.io
version: v1
resource: clustersecretstores
- kind: k8s-dynamic
name: ark/secretproviderclasses
config:
resource-type:
group: secrets-store.csi.x-k8s.io
version: v1
resource: secretproviderclasses
- kind: k8s-dynamic
name: ark/secretproviderclasspodstatuses
config:
resource-type:
group: secrets-store.csi.x-k8s.io
version: v1
resource: secretproviderclasspodstatuses
kind: ConfigMap
metadata:
labels:
Expand Down Expand Up @@ -423,6 +451,20 @@ custom-period:
group: external-secrets.io
version: v1
resource: clustersecretstores
- kind: k8s-dynamic
name: ark/secretproviderclasses
config:
resource-type:
group: secrets-store.csi.x-k8s.io
version: v1
resource: secretproviderclasses
- kind: k8s-dynamic
name: ark/secretproviderclasspodstatuses
config:
resource-type:
group: secrets-store.csi.x-k8s.io
version: v1
resource: secretproviderclasspodstatuses
kind: ConfigMap
metadata:
labels:
Expand Down Expand Up @@ -568,6 +610,20 @@ defaults:
group: external-secrets.io
version: v1
resource: clustersecretstores
- kind: k8s-dynamic
name: ark/secretproviderclasses
config:
resource-type:
group: secrets-store.csi.x-k8s.io
version: v1
resource: secretproviderclasses
- kind: k8s-dynamic
name: ark/secretproviderclasspodstatuses
config:
resource-type:
group: secrets-store.csi.x-k8s.io
version: v1
resource: secretproviderclasspodstatuses
kind: ConfigMap
metadata:
labels:
Expand Down
4 changes: 4 additions & 0 deletions internal/cyberark/dataupload/dataupload.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ type Snapshot struct {
ClusterExternalSecrets []runtime.Object `json:"clusterexternalsecrets"`
// ClusterSecretStores is a list of ClusterSecretStore resources in the cluster.
ClusterSecretStores []runtime.Object `json:"clustersecretstores"`
// SecretProviderClasses is a list of SecretProviderClass resources in the cluster.
SecretProviderClasses []runtime.Object `json:"secretproviderclasses"`
// SecretProviderClassPodStatuses is a list of SecretProviderClassPodStatus resources in the cluster.
SecretProviderClassPodStatuses []runtime.Object `json:"secretproviderclasspodstatuses"`
// 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
6 changes: 6 additions & 0 deletions pkg/client/client_cyberark.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,12 @@ var defaultExtractorFunctions = map[string]func(*api.DataReading, *dataupload.Sn
"ark/esoclustersecretstores": func(r *api.DataReading, s *dataupload.Snapshot) error {
return extractResourceListFromReading(r, &s.ClusterSecretStores)
},
"ark/secretproviderclasses": func(r *api.DataReading, s *dataupload.Snapshot) error {
return extractResourceListFromReading(r, &s.SecretProviderClasses)
},
"ark/secretproviderclasspodstatuses": func(r *api.DataReading, s *dataupload.Snapshot) error {
return extractResourceListFromReading(r, &s.SecretProviderClassPodStatuses)
},
}

// convertDataReadings processes a list of DataReadings using the provided
Expand Down
182 changes: 182 additions & 0 deletions pkg/client/client_cyberark_convertdatareadings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,188 @@ func TestConvertDataReadings_ClusterSecretStores(t *testing.T) {
assert.Equal(t, "aws-cluster-secret-store", css2.GetName())
}

// TestConvertDataReadings_SecretProviderClasses tests that secretproviderclasses are correctly converted.
func TestConvertDataReadings_SecretProviderClasses(t *testing.T) {
extractorFunctions := map[string]func(*api.DataReading, *dataupload.Snapshot) error{
"ark/discovery": extractClusterIDAndServerVersionFromReading,
"ark/secretproviderclasses": func(reading *api.DataReading, snapshot *dataupload.Snapshot) error {
return extractResourceListFromReading(reading, &snapshot.SecretProviderClasses)
},
}

readings := []*api.DataReading{
{
DataGatherer: "ark/discovery",
Data: &api.DiscoveryData{
ClusterID: "test-cluster-id",
ServerVersion: &version.Info{
GitVersion: "v1.21.0",
},
},
},
{
DataGatherer: "ark/secretproviderclasses",
Data: &api.DynamicData{
Items: []*api.GatheredResource{
{
Resource: &unstructured.Unstructured{
Object: map[string]any{
"apiVersion": "secrets-store.csi.x-k8s.io/v1",
"kind": "SecretProviderClass",
"metadata": map[string]any{
"name": "conjur-spc",
"namespace": "default",
},
"spec": map[string]any{
"provider": "conjur",
},
},
},
},
{
Resource: &unstructured.Unstructured{
Object: map[string]any{
"apiVersion": "secrets-store.csi.x-k8s.io/v1",
"kind": "SecretProviderClass",
"metadata": map[string]any{
"name": "vault-spc",
"namespace": "default",
},
"spec": map[string]any{
"provider": "vault",
},
},
},
},
// Deleted secretproviderclass should be ignored
{
DeletedAt: api.Time{Time: time.Now()},
Resource: &unstructured.Unstructured{
Object: map[string]any{
"apiVersion": "secrets-store.csi.x-k8s.io/v1",
"kind": "SecretProviderClass",
"metadata": map[string]any{
"name": "deleted-spc",
"namespace": "default",
},
},
},
},
},
},
},
}

var snapshot dataupload.Snapshot
err := convertDataReadings(extractorFunctions, readings, &snapshot)
require.NoError(t, err)

assert.Equal(t, "test-cluster-id", snapshot.ClusterID)
require.Len(t, snapshot.SecretProviderClasses, 2, "should have 2 secretproviderclasses (deleted one should be excluded)")

spc1, ok := snapshot.SecretProviderClasses[0].(*unstructured.Unstructured)
require.True(t, ok, "secretproviderclass should be unstructured")
assert.Equal(t, "SecretProviderClass", spc1.GetKind())
assert.Equal(t, "conjur-spc", spc1.GetName())

spc2, ok := snapshot.SecretProviderClasses[1].(*unstructured.Unstructured)
require.True(t, ok, "secretproviderclass should be unstructured")
assert.Equal(t, "SecretProviderClass", spc2.GetKind())
assert.Equal(t, "vault-spc", spc2.GetName())
}

// TestConvertDataReadings_SecretProviderClassPodStatuses tests that secretproviderclasspodstatuses are correctly converted.
func TestConvertDataReadings_SecretProviderClassPodStatuses(t *testing.T) {
extractorFunctions := map[string]func(*api.DataReading, *dataupload.Snapshot) error{
"ark/discovery": extractClusterIDAndServerVersionFromReading,
"ark/secretproviderclasspodstatuses": func(reading *api.DataReading, snapshot *dataupload.Snapshot) error {
return extractResourceListFromReading(reading, &snapshot.SecretProviderClassPodStatuses)
},
}

readings := []*api.DataReading{
{
DataGatherer: "ark/discovery",
Data: &api.DiscoveryData{
ClusterID: "test-cluster-id",
ServerVersion: &version.Info{
GitVersion: "v1.21.0",
},
},
},
{
DataGatherer: "ark/secretproviderclasspodstatuses",
Data: &api.DynamicData{
Items: []*api.GatheredResource{
{
Resource: &unstructured.Unstructured{
Object: map[string]any{
"apiVersion": "secrets-store.csi.x-k8s.io/v1",
"kind": "SecretProviderClassPodStatus",
"metadata": map[string]any{
"name": "my-pod-conjur-spc",
"namespace": "default",
},
"status": map[string]any{
"mounted": true,
"podName": "my-pod",
},
},
},
},
{
Resource: &unstructured.Unstructured{
Object: map[string]any{
"apiVersion": "secrets-store.csi.x-k8s.io/v1",
"kind": "SecretProviderClassPodStatus",
"metadata": map[string]any{
"name": "other-pod-conjur-spc",
"namespace": "default",
},
"status": map[string]any{
"mounted": false,
"podName": "other-pod",
},
},
},
},
// Deleted secretproviderclasspodstatus should be ignored
{
DeletedAt: api.Time{Time: time.Now()},
Resource: &unstructured.Unstructured{
Object: map[string]any{
"apiVersion": "secrets-store.csi.x-k8s.io/v1",
"kind": "SecretProviderClassPodStatus",
"metadata": map[string]any{
"name": "deleted-pod-spc",
"namespace": "default",
},
},
},
},
},
},
},
}

var snapshot dataupload.Snapshot
err := convertDataReadings(extractorFunctions, readings, &snapshot)
require.NoError(t, err)

assert.Equal(t, "test-cluster-id", snapshot.ClusterID)
require.Len(t, snapshot.SecretProviderClassPodStatuses, 2, "should have 2 secretproviderclasspodstatuses (deleted one should be excluded)")

spcps1, ok := snapshot.SecretProviderClassPodStatuses[0].(*unstructured.Unstructured)
require.True(t, ok, "secretproviderclasspodstatus should be unstructured")
assert.Equal(t, "SecretProviderClassPodStatus", spcps1.GetKind())
assert.Equal(t, "my-pod-conjur-spc", spcps1.GetName())

spcps2, ok := snapshot.SecretProviderClassPodStatuses[1].(*unstructured.Unstructured)
require.True(t, ok, "secretproviderclasspodstatus should be unstructured")
assert.Equal(t, "SecretProviderClassPodStatus", spcps2.GetKind())
assert.Equal(t, "other-pod-conjur-spc", spcps2.GetName())
}

// TestConvertDataReadings_ServiceAccounts tests that serviceaccounts are correctly converted.
func TestConvertDataReadings_ServiceAccounts(t *testing.T) {
extractorFunctions := map[string]func(*api.DataReading, *dataupload.Snapshot) error{
Expand Down
2 changes: 2 additions & 0 deletions pkg/client/client_cyberark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ var defaultDynamicDatagathererNames = []string{
"ark/esosecretstores",
"ark/esoclusterexternalsecrets",
"ark/esoclustersecretstores",
"ark/secretproviderclasses",
"ark/secretproviderclasspodstatuses",
"ark/roles",
"ark/clusterroles",
"ark/rolebindings",
Expand Down
Loading