diff --git a/cluster/deployment/mock/config.yaml b/cluster/deployment/mock/config.yaml index 19e7ad88e8..e82e5fdc23 100644 --- a/cluster/deployment/mock/config.yaml +++ b/cluster/deployment/mock/config.yaml @@ -117,3 +117,30 @@ svs: kms: keyRingId: sv-3_participant_mock locationId: us-central1 +infra: + extraCustomResources: + deny-onboard-prepare-endpoint: + apiVersion: security.istio.io/v1 + kind: AuthorizationPolicy + metadata: + name: deny-onboard-prepare-endpoint + # if we pass a list here, pulumi will multiply the CR for us + namespace: [ sv-1, sv-2 ] + spec: + selector: + matchLabels: + app: sv-app + action: DENY + rules: + - to: + - operation: + paths: ["/api/sv/v0/devnet/onboard/validator/prepare"] + mock-cr: + apiVersion: mock.example.com/v1 + kind: MockResource + metadata: + name: mock-resource + namespace: validator1 + spec: + key: value + anotherKey: anotherValue diff --git a/cluster/expected/infra/expected.json b/cluster/expected/infra/expected.json index d68a706d1c..ae1ebcce94 100644 --- a/cluster/expected/infra/expected.json +++ b/cluster/expected/infra/expected.json @@ -2047,6 +2047,25 @@ "provider": "", "type": "command:local:Command" }, + { + "custom": true, + "id": "", + "inputs": { + "apiVersion": "mock.example.com/v1", + "kind": "MockResource", + "metadata": { + "name": "mock-resource", + "namespace": "validator1" + }, + "spec": { + "anotherKey": "anotherValue", + "key": "value" + } + }, + "name": "mock-cr", + "provider": "", + "type": "kubernetes:mock.example.com/v1:MockResource" + }, { "custom": true, "id": "", @@ -2928,6 +2947,78 @@ "provider": "", "type": "kubernetes:core/v1:Secret" }, + { + "custom": true, + "id": "", + "inputs": { + "apiVersion": "security.istio.io/v1", + "kind": "AuthorizationPolicy", + "metadata": { + "name": "deny-onboard-prepare-endpoint", + "namespace": "sv-1" + }, + "spec": { + "action": "DENY", + "rules": [ + { + "to": [ + { + "operation": { + "paths": [ + "/api/sv/v0/devnet/onboard/validator/prepare" + ] + } + } + ] + } + ], + "selector": { + "matchLabels": { + "app": "sv-app" + } + } + } + }, + "name": "sv-1-deny-onboard-prepare-endpoint", + "provider": "", + "type": "kubernetes:security.istio.io/v1:AuthorizationPolicy" + }, + { + "custom": true, + "id": "", + "inputs": { + "apiVersion": "security.istio.io/v1", + "kind": "AuthorizationPolicy", + "metadata": { + "name": "deny-onboard-prepare-endpoint", + "namespace": "sv-2" + }, + "spec": { + "action": "DENY", + "rules": [ + { + "to": [ + { + "operation": { + "paths": [ + "/api/sv/v0/devnet/onboard/validator/prepare" + ] + } + } + ] + } + ], + "selector": { + "matchLabels": { + "app": "sv-app" + } + } + } + }, + "name": "sv-2-deny-onboard-prepare-endpoint", + "provider": "", + "type": "kubernetes:security.istio.io/v1:AuthorizationPolicy" + }, { "custom": true, "id": "", diff --git a/cluster/pulumi/infra/src/config.ts b/cluster/pulumi/infra/src/config.ts index 056965ebc9..574db4ccb3 100644 --- a/cluster/pulumi/infra/src/config.ts +++ b/cluster/pulumi/infra/src/config.ts @@ -53,6 +53,7 @@ export const InfraConfigSchema = z.object({ istio: z.object({ enableIngressAccessLogging: z.boolean(), }), + extraCustomResources: z.object({}).catchall(z.any()).default({}), }), monitoring: MonitoringConfigSchema, }); diff --git a/cluster/pulumi/infra/src/extraCustomResources.ts b/cluster/pulumi/infra/src/extraCustomResources.ts new file mode 100644 index 0000000000..4680c2b5f3 --- /dev/null +++ b/cluster/pulumi/infra/src/extraCustomResources.ts @@ -0,0 +1,27 @@ +// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +import * as k8s from '@pulumi/kubernetes'; + +import { infraConfig } from './config'; + +// Automatically duplicates CRs if multiple namespaces given +export function installExtraCustomResources(): void { + const extraCrs = infraConfig.extraCustomResources; + Object.entries(extraCrs).forEach(([name, spec]) => { + if (Array.isArray(spec.metadata?.namespace)) { + spec.metadata.namespace.forEach((ns: string) => { + const patchedName = `${ns}-${name}`; + const patchedSpec = { + ...spec, + metadata: { + ...spec.metadata, + namespace: ns, + }, + }; + new k8s.apiextensions.CustomResource(patchedName, patchedSpec); + }); + } else { + new k8s.apiextensions.CustomResource(name, spec); + } + }); +} diff --git a/cluster/pulumi/infra/src/index.ts b/cluster/pulumi/infra/src/index.ts index 27f3082928..601f0fdf5a 100644 --- a/cluster/pulumi/infra/src/index.ts +++ b/cluster/pulumi/infra/src/index.ts @@ -6,6 +6,7 @@ import { config } from 'splice-pulumi-common'; import { clusterIsResetPeriodically, enableAlerts } from './alertings'; import { configureAuth0 } from './auth0'; import { clusterBaseDomain, clusterBasename, monitoringConfig } from './config'; +import { installExtraCustomResources } from './extraCustomResources'; import { getNotificationChannel, installCloudSQLMaintenanceUpdateAlerts, @@ -40,6 +41,8 @@ istioMonitoring(network.ingressNs, []); configureStorage(); +installExtraCustomResources(); + let configuredAuth0; if (config.envFlag('CLUSTER_CONFIGURE_AUTH0', true)) { configuredAuth0 = configureAuth0(clusterBasename, network.dnsNames);