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
2 changes: 1 addition & 1 deletion internal/audit/crd_config_refs.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ func kedaTriggerAuthConfigRefs(u *unstructured.Unstructured) []bp.ConfigObjectRe
for _, ref := range mapsAt(u.Object, "spec", "configMapTargetRef") {
addConfigMap(&refs, ns, stringValue(ref["name"]))
}
addSecret(&refs, ns, stringAt(u.Object, "spec", "gcpSecretManager", "credentials", "clientSecret", "name"))
addSecret(&refs, ns, stringAt(u.Object, "spec", "gcpSecretManager", "credentials", "clientSecret", "valueFrom", "secretKeyRef", "name"))
return refs
}

Expand Down
9 changes: 8 additions & 1 deletion internal/audit/crd_config_refs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,17 @@ func TestDynamicConfigObjectRefs(t *testing.T) {
obj: map[string]any{"spec": map[string]any{
"secretTargetRef": []any{map[string]any{"name": "queue-secret"}},
"configMapTargetRef": []any{map[string]any{"name": "queue-config"}},
"gcpSecretManager": map[string]any{"credentials": map[string]any{"clientSecret": map[string]any{"name": "gcp-secret"}}},
"gcpSecretManager": map[string]any{"credentials": map[string]any{"clientSecret": map[string]any{"valueFrom": map[string]any{"secretKeyRef": map[string]any{"name": "gcp-secret", "key": "credentials.json"}}}}},
}},
want: refs(secret("app", "queue-secret"), configMap("app", "queue-config"), secret("app", "gcp-secret")),
},
{
name: "keda shallow GCP credentials are not a reference",
gvr: gvr("keda.sh", "v1alpha1", "triggerauthentications"),
ns: "app",
obj: map[string]any{"spec": map[string]any{"gcpSecretManager": map[string]any{"credentials": map[string]any{"clientSecret": map[string]any{"name": "fictional"}}}}},
want: refs(),
},
{
name: "prometheus servicemonitor refs",
gvr: gvr("monitoring.coreos.com", "v1", "servicemonitors"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// @vitest-environment jsdom
import { act } from 'react'
import { createRoot } from 'react-dom/client'
import { renderToStaticMarkup } from 'react-dom/server'
import { expect, it, vi } from 'vitest'
import { KedaTriggerAuthRenderer } from './KedaTriggerAuthRenderer'
Object.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true })
const spec = {
secretTargetRef: [{ parameter: 'token', name: 'direct', key: 'token' }],
gcpSecretManager: {
credentials: {
clientSecret: {
valueFrom: { secretKeyRef: { name: 'iam', key: 'credentials.json' } },
},
},
},
}

it('links the actual nested GCP credential Secret in the authentication namespace', async () => {
const element = document.createElement('div')
const root = createRoot(element)
const onNavigate = vi.fn()
try {
await act(async () =>
root.render(
<KedaTriggerAuthRenderer
data={{
kind: 'TriggerAuthentication',
metadata: { namespace: 'app' },
spec,
}}
onNavigate={onNavigate}
/>,
),
)
const button = [...element.querySelectorAll('button')].find(b => b.textContent === 'iam')
expect(button).toBeDefined()
await act(async () => button!.click())
expect(onNavigate).toHaveBeenCalledWith({
kind: 'secrets',
group: '',
namespace: 'app',
name: 'iam',
})
expect(element.textContent).toContain('credentials.json')
} finally {
await act(async () => root.unmount())
}
})

it('retains cluster-auth names without inventing an operator credential namespace', () => {
const html = renderToStaticMarkup(
<KedaTriggerAuthRenderer
data={{
kind: 'ClusterTriggerAuthentication',
metadata: { name: 'cluster' },
spec,
}}
onNavigate={() => {}}
/>,
)
const doc = new DOMParser().parseFromString(html, 'text/html')
expect(doc.body.textContent).toContain('iam')
expect(doc.body.textContent).toContain('direct')
expect([...doc.querySelectorAll('button')].some(b => b.textContent === 'iam' || b.textContent === 'direct')).toBe(
false,
)
})

it('does not accept the previously invented shallow GCP reference shape', () => {
const html = renderToStaticMarkup(
<KedaTriggerAuthRenderer
data={{
kind: 'TriggerAuthentication',
metadata: { namespace: 'app' },
spec: {
gcpSecretManager: {
credentials: { clientSecret: { name: 'fictional' } },
},
},
}}
/>,
)
expect(html).not.toContain('fictional')
})
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export function KedaTriggerAuthRenderer({ data, onNavigate }: KedaTriggerAuthRen
const awsSecretManager = spec.awsSecretManager
const gcpSecretManager = spec.gcpSecretManager
const podIdentity = spec.podIdentity
const credentialRef = gcpSecretManager?.credentials?.clientSecret?.valueFrom?.secretKeyRef
const namespace = data.metadata?.namespace

return (
<>
Expand Down Expand Up @@ -48,7 +50,7 @@ export function KedaTriggerAuthRenderer({ data, onNavigate }: KedaTriggerAuthRen
<div className="flex flex-wrap gap-x-4 gap-y-1 text-sm">
<span className="text-theme-text-primary font-medium">{ref.parameter}</span>
<span className="text-theme-text-secondary">
Secret: <ResourceLink name={ref.name} kind="secrets" namespace={data.metadata?.namespace || ''} onNavigate={onNavigate} /> / {ref.key}
Secret: {namespace ? <ResourceLink name={ref.name} kind="secrets" group="" namespace={namespace} onNavigate={onNavigate} /> : ref.name} / {ref.key}
</span>
</div>
</div>
Expand Down Expand Up @@ -150,9 +152,10 @@ export function KedaTriggerAuthRenderer({ data, onNavigate }: KedaTriggerAuthRen
{gcpSecretManager && (
<Section title="GCP Secret Manager" icon={Cloud}>
<PropertyList>
{gcpSecretManager.credentials?.clientSecret?.name && (
<Property label="Credentials Secret" value={gcpSecretManager.credentials.clientSecret.name} />
{credentialRef?.name && (
<Property label="Credentials Secret" value={namespace ? <ResourceLink name={credentialRef.name} kind="secrets" group="" namespace={namespace} onNavigate={onNavigate} /> : credentialRef.name} />
)}
{credentialRef?.key && <Property label="Credentials Key" value={credentialRef.key} />}
</PropertyList>
{gcpSecretManager.secrets && gcpSecretManager.secrets.length > 0 && (
<div className="mt-2 space-y-1">
Expand Down
Loading