diff --git a/acm/deploy/helm/multicluster-engine-config/charts/policy/values.yaml b/acm/deploy/helm/multicluster-engine-config/charts/policy/values.yaml index a6e8161483..792fe6c69b 100644 --- a/acm/deploy/helm/multicluster-engine-config/charts/policy/values.yaml +++ b/acm/deploy/helm/multicluster-engine-config/charts/policy/values.yaml @@ -1,11 +1,11 @@ global: registryOverride: "registry.redhat.io/rhacm2" imageOverrides: - governance_policy_propagator: "governance-policy-propagator-rhel9@sha256:c77485c09619e9feb59f936f3e571c14366217687f6918669961d6b4af5e2610" + governance_policy_propagator: "governance-policy-propagator-rhel9@sha256:b2843da52a82d91e1e83581e2b717a198c98813832814e913d76c1a52988c1de" governance_policy_addon_controller: "acm-governance-policy-addon-controller-rhel9@sha256:cb0a37888d00b12401b92570b23aec98f5e8e36e0955a682bc4d1a4190eec7ab" - config_policy_controller: "config-policy-controller-rhel9@sha256:a8f663abd31fe7421a2b66f24b3e6e8e2a118fbe9822e10d7873dbb1be9492cf" + config_policy_controller: "config-policy-controller-rhel9@sha256:78ddb67fe7038fc93c13b20719bb4f54dd86850d8badf2385564782693c56da1" governance_policy_framework_addon: "acm-governance-policy-framework-addon-rhel9@sha256:01d469baa59e19d4cfd976fe50a6affbee358d284aa2c23d77c3c7411fe85b82" - klusterlet_addon_controller: "klusterlet-addon-controller-rhel9@sha256:d4abae5d4122b53755d6077b9c27dc0880a727b836e703f32ff00a346bda42c7" + klusterlet_addon_controller: "klusterlet-addon-controller-rhel9@sha256:0c54808fdef9aaf95f8fe4f6b8bc7a07d85f85b724bdb7a55004c850a6f44685" namespace: multicluster-engine pullSecret: open-cluster-management-image-pull-credentials cma: diff --git a/acm/deploy/helm/multicluster-engine-crds/Chart.yaml b/acm/deploy/helm/multicluster-engine-crds/Chart.yaml index bbff3379e2..954d07c7c0 100644 --- a/acm/deploy/helm/multicluster-engine-crds/Chart.yaml +++ b/acm/deploy/helm/multicluster-engine-crds/Chart.yaml @@ -7,6 +7,6 @@ keywords: - multiclusterengine name: multicluster-engine-crds sources: -- quay.io/redhat-user-workloads/crt-redhat-acm-tenant/mce-operator-bundle-mce-210@sha256:9ada289f06b9af65e2957f1eb5aa97c1add2ab0a85da11b27710b63029da1527 +- quay.io/redhat-user-workloads/crt-redhat-acm-tenant/mce-operator-bundle-mce-210@sha256:ba98af6c60952b7e8b4e682c16c31c560e342a090a1607adc47cd31d630905f3 type: application version: 2.10.2 diff --git a/acm/deploy/helm/multicluster-engine/Chart.yaml b/acm/deploy/helm/multicluster-engine/Chart.yaml index 8bc34e36ff..73f525e851 100644 --- a/acm/deploy/helm/multicluster-engine/Chart.yaml +++ b/acm/deploy/helm/multicluster-engine/Chart.yaml @@ -7,6 +7,6 @@ keywords: - multiclusterengine name: multicluster-engine sources: -- quay.io/redhat-user-workloads/crt-redhat-acm-tenant/mce-operator-bundle-mce-210@sha256:9ada289f06b9af65e2957f1eb5aa97c1add2ab0a85da11b27710b63029da1527 +- quay.io/redhat-user-workloads/crt-redhat-acm-tenant/mce-operator-bundle-mce-210@sha256:ba98af6c60952b7e8b4e682c16c31c560e342a090a1607adc47cd31d630905f3 type: application version: 2.10.2 diff --git a/acm/deploy/helm/multicluster-engine/templates/multicluster-engine-operator.deployment.yaml b/acm/deploy/helm/multicluster-engine/templates/multicluster-engine-operator.deployment.yaml index bc9dbe94fd..5dfc541a24 100644 --- a/acm/deploy/helm/multicluster-engine/templates/multicluster-engine-operator.deployment.yaml +++ b/acm/deploy/helm/multicluster-engine/templates/multicluster-engine-operator.deployment.yaml @@ -62,9 +62,9 @@ spec: - name: OPERAND_IMAGE_BACKPLANE_OPERATOR value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/backplane-rhel9-operator@sha256:3a84ce458e39a58d711066321edda05795462f1504d38f0c151bf680a324c026' - name: OPERAND_IMAGE_CLUSTER_API_PROVIDER_AGENT - value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/cluster-api-provider-agent-rhel9@sha256:6685ae0c29d3c958f54c2d7b73c91462ab3de46309ed2a2b04d728a790f39486' + value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/cluster-api-provider-agent-rhel9@sha256:872e04e8cfcf6c76035429ee2e48692d0b20c9aed5f6756014f3df7d21be36aa' - name: OPERAND_IMAGE_CLUSTER_API_PROVIDER_AWS_RHEL9 - value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/cluster-api-provider-aws-rhel9@sha256:242cc482b2b2e96a63c5d46ba51d22a5c2a2b26ca17aea0336edcf27f5d5c6f5' + value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/cluster-api-provider-aws-rhel9@sha256:b88ace19adc1c0bca9b53e206122f552dcc554dcf1be8cf3990871b8ed595bdb' - name: OPERAND_IMAGE_CLUSTER_API_PROVIDER_KUBEVIRT value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/cluster-api-provider-kubevirt-rhel9@sha256:5fb3ebcbfa0b13df06d9bfa922562ce0ec2429b50f66a3546a2c4bd661432ee2' - name: OPERAND_IMAGE_CLUSTER_API_PROVIDER_OPENSHIFT_ASSISTED_BOOTSTRAP @@ -72,13 +72,13 @@ spec: - name: OPERAND_IMAGE_CLUSTER_API_PROVIDER_OPENSHIFT_ASSISTED_CONTROL_PLANE value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/capoa-control-plane-rhel9@sha256:6fba0c74b610e5aec95009054a32d3c1cf69b9fb6bfb91e70aa4151a2f877342' - name: OPERAND_IMAGE_MCE_CAPI_WEBHOOK_CONFIG_RHEL9 - value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/mce-capi-webhook-config-rhel9@sha256:f6c509cf40ac600c88307da348535ecbed17669bafb1275e9d0e8bd67a049872' + value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/mce-capi-webhook-config-rhel9@sha256:f1564b995cd98d00dc6214d28902d343977ff60f7912feb6a409d5dd13d951f8' - name: OPERAND_IMAGE_CLUSTERCLAIMS_CONTROLLER value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/clusterclaims-controller-rhel9@sha256:efcbc547fb7a7f1334d2569f89e3c692a92c3a8b0d35418d26cf569c13fdf390' - name: OPERAND_IMAGE_CLUSTER_CURATOR_CONTROLLER value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/cluster-curator-controller-rhel9@sha256:8a0a0669025d98769075f56cdad4e19b1365b78c71f608a65048d092fa5a909b' - name: OPERAND_IMAGE_CLUSTER_IMAGE_SET_CONTROLLER - value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/cluster-image-set-controller-rhel9@sha256:ff66d0d4afb3da813ba1cfca227d6bcdb8a9641100e22fac3a6663d4c27b24ec' + value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/cluster-image-set-controller-rhel9@sha256:2d00ea2d8032ab114cf0c1447b9efbb0a8fdfc0938b27a1204e533b23c184024' - name: OPERAND_IMAGE_CLUSTERLIFECYCLE_STATE_METRICS value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/clusterlifecycle-state-metrics-rhel9@sha256:37b4f8aee9fbd2368412a6fa724b0265b0012728d2bc1ac7c571dc71a037f1b6' - name: OPERAND_IMAGE_CLUSTER_PROXY_ADDON @@ -94,9 +94,9 @@ spec: - name: OPERAND_IMAGE_HYPERSHIFT_ADDON_OPERATOR value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/hypershift-addon-rhel9-operator@sha256:035d73a3c839b8c2c3f775ceaa9d88be9d80f19eb4692f3236cda92904871ce6' - name: OPERAND_IMAGE_HYPERSHIFT_CLI - value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/hypershift-cli-rhel9@sha256:b073415373d1180394bb63229b74478728fbd79b5ffd6f8166a4ba06181bc008' + value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/hypershift-cli-rhel9@sha256:7baf5fb63d3188b0eb73cb8b1dab63015b844171d812763dc5b19bba6e18ea84' - name: OPERAND_IMAGE_HYPERSHIFT_OPERATOR - value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/hypershift-rhel9-operator@sha256:2092539927781af8def5507e959b6e78d58bba14f2aef00eea2d3b29bb855217' + value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/hypershift-rhel9-operator@sha256:3044b4a4ce2cd7f624fa8ea5eb6090310590cdfaf0437c6684fb4838d525cf95' - name: OPERAND_IMAGE_IMAGE_BASED_INSTALL_OPERATOR value: '{{ .Values.imageRegistry }}/{{ .Values.imageRootRepository }}/image-based-install-rhel9@sha256:d0d2e6598289081dd9384ba8d6135a5d6575dfc742ee25a44058cde892528822' - name: OPERAND_IMAGE_KUBE_RBAC_PROXY_MCE diff --git a/admin/README.md b/admin/README.md index 59fa1cd1c1..b8aa27d3d4 100644 --- a/admin/README.md +++ b/admin/README.md @@ -18,6 +18,7 @@ This prefix is abbreviated as `{resourceId}` below. |--------|------|-------------| | `PUT` | `/admin/v1/hcp{resourceId}/breakglass?group=...&ttl=...` | Create a breakglass session ([details](breakglass.md)) | | `GET` | `/admin/v1/hcp{resourceId}/breakglass/{sessionName}/kubeconfig` | Get kubeconfig for a breakglass session ([details](breakglass.md)) | +| `GET` | `/admin/v1/hcp{resourceId}/serialconsole?vmName=...` | Retrieve serial console logs for a VM | | `GET` | `/admin/v1/hcp{resourceId}/cosmosdump` | Cosmos DB dump for a cluster | | `GET` | `/admin/v1/hcp{resourceId}/helloworld` | HCP hello world (dev/test) | | `GET` | `/admin/helloworld` | Hello world (dev/test) | diff --git a/admin/server/go.mod b/admin/server/go.mod index 6b35dc56bd..b80ae2e5eb 100644 --- a/admin/server/go.mod +++ b/admin/server/go.mod @@ -7,6 +7,7 @@ require ( github.com/Azure/ARO-HCP/sessiongate v0.0.0-00010101000000-000000000000 github.com/Azure/azure-kusto-go v0.16.1 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6 v6.2.0 github.com/go-logr/logr v1.4.3 github.com/microsoft/go-otel-audit v0.2.2 diff --git a/admin/server/go.sum b/admin/server/go.sum index aadfe1aee3..9b56a29adb 100644 --- a/admin/server/go.sum +++ b/admin/server/go.sum @@ -14,12 +14,18 @@ github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.4.1 h1:ToPLhnXvatKVN4Zkcx github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.4.1/go.mod h1:Krtog/7tz27z75TwM5cIS8bxEH4dcBUezcq+kGVeZEo= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0/go.mod h1:QyiQdW4f4/BIfB8ZutZ2s+28RAgfa/pT+zS++ZHyM1I= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0/go.mod h1:LRr2FzBTQlONPPa5HREE5+RjSCTXl7BwOvYOaWTqCaI= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.1 h1:1kpY4qe+BGAH2ykv4baVSqyx+AY5VjXeJ15SldlU6hs= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.1/go.mod h1:nT6cWpWdUt+g81yuKmjeYPUtI73Ak3yQIT4PVVsCEEQ= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6 v6.2.0 h1:HYGD75g0bQ3VO/Omedm54v4LrD3B1cGImuRF3AJ5wLo= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6 v6.2.0/go.mod h1:ulHyBFJOI0ONiRL4vcJTmS7rx18jQQlEPmAgo80cRdM= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armdeployments v0.2.0 h1:bYq3jfB2x36hslKMHyge3+esWzROtJNk/4dCjsKlrl4= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armdeployments v0.2.0/go.mod h1:fewgRjNVE84QVVh798sIMFb7gPXPp7NmnekGnboSnXk= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources/v3 v3.0.1 h1:guyQA4b8XB2sbJZXzUnOF9mn0WDBv/ZT7me9wTipKtE= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources/v3 v3.0.1/go.mod h1:8h8yhzh9o+0HeSIhUxYny+rEQajScrfIpNktvgYG3Q8= github.com/Azure/retry v0.0.0-20250221010952-92c9290cea0f h1:XjKfallhRhddiRmBG0u2gs+Rd75QjvAlPVDy3ZWLjPg= diff --git a/admin/server/handlers/hcp/breakglass/create.go b/admin/server/handlers/hcp/breakglass/create.go index dbf0e90df4..80362bdf39 100644 --- a/admin/server/handlers/hcp/breakglass/create.go +++ b/admin/server/handlers/hcp/breakglass/create.go @@ -16,7 +16,6 @@ package breakglass import ( "encoding/json" - "errors" "fmt" "net/http" "time" @@ -25,8 +24,7 @@ import ( utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/utils/set" - ocmerrors "github.com/openshift-online/ocm-sdk-go/errors" - + hcphelpers "github.com/Azure/ARO-HCP/admin/server/handlers/hcp" "github.com/Azure/ARO-HCP/admin/server/middleware" "github.com/Azure/ARO-HCP/internal/api/arm" "github.com/Azure/ARO-HCP/internal/database" @@ -73,12 +71,12 @@ func (h *HCPBreakglassSessionCreationHandler) ServeHTTP(writer http.ResponseWrit clusterHypershiftDetails, err := h.csClient.GetClusterHypershiftDetails(request.Context(), hcp.ServiceProviderProperties.ClusterServiceID) if err != nil { - return clusterServiceError(err, "hypershift details") + return hcphelpers.ClusterServiceError(err, "hypershift details") } provisionShard, err := h.csClient.GetClusterProvisionShard(request.Context(), hcp.ServiceProviderProperties.ClusterServiceID) if err != nil { - return clusterServiceError(err, "provision shard") + return hcphelpers.ClusterServiceError(err, "provision shard") } group, ttl, err := h.validateSessionParameters(request) @@ -185,16 +183,3 @@ func (h *HCPBreakglassSessionCreationHandler) validateSessionParameters(request return body.Group, ttl, utilerrors.NewAggregate(errs) } - -// clusterServiceError checks if err is an OCM not-found error and returns a -// specific CloudError. This prevents ReportError from misinterpreting it as -// "HCP resource not found" (the HCP was already found in the database). -// Non-OCM errors are wrapped for ReportError to handle as internal errors. -func clusterServiceError(err error, what string) error { - var ocmErr *ocmerrors.Error - if errors.As(err, &ocmErr) && ocmErr.Status() == http.StatusNotFound { - return arm.NewCloudError(http.StatusNotFound, arm.CloudErrorCodeNotFound, "", - "%s not found in cluster service", what) - } - return fmt.Errorf("failed to get %s from cluster service: %w", what, err) -} diff --git a/admin/server/handlers/hcp/helpers.go b/admin/server/handlers/hcp/helpers.go new file mode 100644 index 0000000000..3b234fe2a1 --- /dev/null +++ b/admin/server/handlers/hcp/helpers.go @@ -0,0 +1,38 @@ +// Copyright 2025 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hcp + +import ( + "errors" + "fmt" + "net/http" + + ocmerrors "github.com/openshift-online/ocm-sdk-go/errors" + + "github.com/Azure/ARO-HCP/internal/api/arm" +) + +// ClusterServiceError checks if err is an OCM not-found error and returns a +// specific CloudError. This prevents ReportError from misinterpreting it as +// "HCP resource not found" (the HCP was already found in the database). +// Non-OCM errors are wrapped for ReportError to handle as internal errors. +func ClusterServiceError(err error, what string) error { + var ocmErr *ocmerrors.Error + if errors.As(err, &ocmErr) && ocmErr.Status() == http.StatusNotFound { + return arm.NewCloudError(http.StatusNotFound, arm.CloudErrorCodeNotFound, "", + "%s not found in cluster service", what) + } + return fmt.Errorf("failed to get %s from cluster service: %w", what, err) +} diff --git a/admin/server/handlers/hcp/helpers_test.go b/admin/server/handlers/hcp/helpers_test.go new file mode 100644 index 0000000000..84a9617ee5 --- /dev/null +++ b/admin/server/handlers/hcp/helpers_test.go @@ -0,0 +1,147 @@ +// Copyright 2025 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hcp + +import ( + "errors" + "net/http" + "strings" + "testing" + + ocmerrors "github.com/openshift-online/ocm-sdk-go/errors" + + "github.com/Azure/ARO-HCP/internal/api/arm" +) + +func TestClusterServiceError(t *testing.T) { + // Helper to create OCM errors + createOCMError := func(status int) error { + ocmErr, err := ocmerrors.NewError().Status(status).Build() + if err != nil { + t.Fatalf("Failed to create OCM error: %v", err) + } + return ocmErr + } + + tests := []struct { + name string + err error + what string + expectedStatusCode int + expectedErrorCode string + expectedMessage string + isCloudError bool + }{ + { + name: "OCM not-found error returns 404 CloudError", + err: createOCMError(http.StatusNotFound), + what: "cluster data", + expectedStatusCode: http.StatusNotFound, + expectedErrorCode: arm.CloudErrorCodeNotFound, + expectedMessage: "cluster data not found in cluster service", + isCloudError: true, + }, + { + name: "OCM not-found error for hypershift details", + err: createOCMError(http.StatusNotFound), + what: "hypershift details", + expectedStatusCode: http.StatusNotFound, + expectedErrorCode: arm.CloudErrorCodeNotFound, + expectedMessage: "hypershift details not found in cluster service", + isCloudError: true, + }, + { + name: "OCM internal server error wraps error", + err: createOCMError(http.StatusInternalServerError), + what: "cluster data", + expectedMessage: "failed to get cluster data from cluster service", + isCloudError: false, + }, + { + name: "OCM bad request error wraps error", + err: createOCMError(http.StatusBadRequest), + what: "provision shard", + expectedMessage: "failed to get provision shard from cluster service", + isCloudError: false, + }, + { + name: "OCM unauthorized error wraps error", + err: createOCMError(http.StatusUnauthorized), + what: "cluster data", + expectedMessage: "failed to get cluster data from cluster service", + isCloudError: false, + }, + { + name: "non-OCM error wraps error", + err: errors.New("network timeout"), + what: "cluster data", + expectedMessage: "failed to get cluster data from cluster service", + isCloudError: false, + }, + { + name: "generic error wraps error", + err: errors.New("connection refused"), + what: "hypershift details", + expectedMessage: "failed to get hypershift details from cluster service", + isCloudError: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := ClusterServiceError(tt.err, tt.what) + + if result == nil { + t.Fatal("Expected error but got nil") + } + + if tt.isCloudError { + // Check if it's a CloudError + var cloudErr *arm.CloudError + if !errors.As(result, &cloudErr) { + t.Fatalf("Expected CloudError but got %T: %v", result, result) + } + + if cloudErr.StatusCode != tt.expectedStatusCode { + t.Errorf("Expected status code %d, got %d", tt.expectedStatusCode, cloudErr.StatusCode) + } + + if cloudErr.Code != tt.expectedErrorCode { + t.Errorf("Expected error code %q, got %q", tt.expectedErrorCode, cloudErr.Code) + } + + if cloudErr.Message != tt.expectedMessage { + t.Errorf("Expected message %q, got %q", tt.expectedMessage, cloudErr.Message) + } + } else { + // Check if it's a wrapped error (not CloudError) + var cloudErr *arm.CloudError + if errors.As(result, &cloudErr) { + t.Fatalf("Expected wrapped error but got CloudError: %v", result) + } + + // Verify error message contains expected text + if !strings.Contains(result.Error(), tt.expectedMessage) { + t.Errorf("Expected error to contain %q, got %q", tt.expectedMessage, result.Error()) + } + + // Verify original error is wrapped + if !errors.Is(result, tt.err) { + t.Errorf("Expected error to wrap original error") + } + } + }) + } +} diff --git a/admin/server/handlers/hcp/serialconsole.go b/admin/server/handlers/hcp/serialconsole.go new file mode 100644 index 0000000000..78fe2d5bc0 --- /dev/null +++ b/admin/server/handlers/hcp/serialconsole.go @@ -0,0 +1,190 @@ +// Copyright 2025 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hcp + +import ( + "errors" + "fmt" + "io" + "net/http" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" + + "github.com/Azure/ARO-HCP/internal/api/arm" + "github.com/Azure/ARO-HCP/internal/database" + "github.com/Azure/ARO-HCP/internal/fpa" + "github.com/Azure/ARO-HCP/internal/utils" + "github.com/Azure/ARO-HCP/internal/validation" +) + +const ( + maxBytes = 100 * 1024 * 1024 // 100MB +) + +// HCPSerialConsoleHandler handles requests to retrieve VM serial console logs +// for debugging purposes. This endpoint allows SREs to access boot diagnostics +// and console output from VMs in the HCP cluster's managed resource group. +type HCPSerialConsoleHandler struct { + dbClient database.DBClient + fpaCredentialRetriever fpa.FirstPartyApplicationTokenCredentialRetriever +} + +// NewHCPSerialConsoleHandler creates a new serial console handler with the required dependencies +func NewHCPSerialConsoleHandler( + dbClient database.DBClient, + fpaCredentialRetriever fpa.FirstPartyApplicationTokenCredentialRetriever, +) *HCPSerialConsoleHandler { + return &HCPSerialConsoleHandler{ + dbClient: dbClient, + fpaCredentialRetriever: fpaCredentialRetriever, + } +} + +// ServeHTTP handles GET requests to retrieve serial console output for a specified VM. +func (h *HCPSerialConsoleHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) error { + resourceID, err := utils.ResourceIDFromContext(request.Context()) + if err != nil { + return arm.NewCloudError( + http.StatusBadRequest, + arm.CloudErrorCodeInvalidRequestContent, + "", + "invalid resource identifier in request", + ) + } + + vmName := request.URL.Query().Get("vmName") + if vmName == "" { + return arm.NewCloudError( + http.StatusBadRequest, + arm.CloudErrorCodeInvalidRequestContent, + "", + "vmName query parameter is required", + ) + } + + if !validation.IsValidAzureVMName(vmName) { + return arm.NewCloudError( + http.StatusBadRequest, + arm.CloudErrorCodeInvalidRequestContent, + "", + "vmName contains invalid characters or format", + ) + } + + hcp, err := h.dbClient.HCPClusters(resourceID.SubscriptionID, resourceID.ResourceGroupName).Get(request.Context(), resourceID.Name) + if err != nil { + return utils.TrackError(fmt.Errorf("failed to get HCP from database: %w", err)) + } + + subscription, err := h.dbClient.Subscriptions().Get(request.Context(), resourceID.SubscriptionID) + if database.IsResponseError(err, http.StatusNotFound) { + return arm.NewCloudError( + http.StatusNotFound, + arm.CloudErrorCodeNotFound, + "", + "subscription %s not found", resourceID.SubscriptionID, + ) + } + if err != nil { + return utils.TrackError(err) + } + + tokenCredential, err := h.fpaCredentialRetriever.RetrieveCredential(*subscription.Properties.TenantId) + if err != nil { + return utils.TrackError(fmt.Errorf("failed to retrieve Azure credentials: %w", err)) + } + + computeClient, err := armcompute.NewVirtualMachinesClient(hcp.ID.SubscriptionID, tokenCredential, nil) + if err != nil { + return utils.TrackError(fmt.Errorf("failed to create Azure compute client: %w", err)) + } + + managedResourceGroup := hcp.CustomerProperties.Platform.ManagedResourceGroup + sasTokenExpirationMinutes := int32(5) + options := &armcompute.VirtualMachinesClientRetrieveBootDiagnosticsDataOptions{ + SasURIExpirationTimeInMinutes: &sasTokenExpirationMinutes, + } + result, err := computeClient.RetrieveBootDiagnosticsData( + request.Context(), + managedResourceGroup, + vmName, + options, + ) + if err != nil { + var azErr *azcore.ResponseError + if ok := errors.As(err, &azErr); ok && azErr != nil { + if azErr.StatusCode == http.StatusNotFound { + return arm.NewCloudError( + http.StatusNotFound, + arm.CloudErrorCodeNotFound, + "", + "VM %s not found in resource group %s", vmName, managedResourceGroup, + ) + } + if azErr.StatusCode == http.StatusConflict { + return arm.NewCloudError( + http.StatusConflict, + arm.CloudErrorCodeConflict, + "", + "Diagnostics might be disabled for VM %s", vmName, + ) + } + } + return utils.TrackError(fmt.Errorf("failed to retrieve boot diagnostics data for VM %s: %w", vmName, err)) + } + + if result.SerialConsoleLogBlobURI == nil || *result.SerialConsoleLogBlobURI == "" { + return arm.NewCloudError( + http.StatusNotFound, + arm.CloudErrorCodeNotFound, + "", + "serial console not available for VM %s", + vmName, + ) + } + + blobReq, err := http.NewRequestWithContext(request.Context(), http.MethodGet, *result.SerialConsoleLogBlobURI, nil) + if err != nil { + return utils.TrackError(fmt.Errorf("failed to create blob request: %w", err)) + } + + httpClient := &http.Client{} + blobResp, err := httpClient.Do(blobReq) + if err != nil { + return utils.TrackError(fmt.Errorf("failed to download serial console log: %w", err)) + } + defer blobResp.Body.Close() + + if blobResp.StatusCode != http.StatusOK { + return utils.TrackError(fmt.Errorf("failed to download serial console log: unexpected status %d", blobResp.StatusCode)) + } + + // stream response as text/plain and prevent caching of potentially sensitive console output + writer.Header().Set("Content-Type", "text/plain; charset=utf-8") + writer.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") + writer.Header().Set("Pragma", "no-cache") + writer.Header().Set("Expires", "0") + writer.WriteHeader(http.StatusOK) + limitedReader := io.LimitReader(blobResp.Body, maxBytes) + _, err = io.Copy(writer, limitedReader) + if err != nil { + logger := utils.LoggerFromContext(request.Context()) + logger.Error(err, "failed to stream serial console log", "vmName", vmName) + return nil + } + + return nil +} diff --git a/admin/server/handlers/hcp/serialconsole_test.go b/admin/server/handlers/hcp/serialconsole_test.go new file mode 100644 index 0000000000..298e86f43a --- /dev/null +++ b/admin/server/handlers/hcp/serialconsole_test.go @@ -0,0 +1,253 @@ +// Copyright 2025 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hcp + +import ( + "context" + "errors" + "fmt" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/go-logr/logr/testr" + "github.com/stretchr/testify/require" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + + "github.com/Azure/ARO-HCP/internal/api" + "github.com/Azure/ARO-HCP/internal/api/arm" + "github.com/Azure/ARO-HCP/internal/databasetesting" + "github.com/Azure/ARO-HCP/internal/utils" +) + +// mockFPACredentialRetriever implements fpa.FirstPartyApplicationTokenCredentialRetriever for testing +type mockFPACredentialRetriever struct { + credential azcore.TokenCredential + err error +} + +func (m *mockFPACredentialRetriever) RetrieveCredential(tenantId string, additionallyAllowedTenants ...string) (azcore.TokenCredential, error) { + return m.credential, m.err +} + +func TestSerialConsoleHandler(t *testing.T) { + tests := []struct { + name string + resourceID string + vmName string + setupData func(context.Context, *testing.T, *databasetesting.MockDBClient, *azcorearm.ResourceID) + mockFPA *mockFPACredentialRetriever + expectedStatusCode int + expectedError string + }{ + { + name: "missing vmName parameter", + resourceID: api.TestClusterResourceID, + vmName: "", + setupData: func(ctx context.Context, t *testing.T, mockDB *databasetesting.MockDBClient, resourceID *azcorearm.ResourceID) { + }, + mockFPA: &mockFPACredentialRetriever{}, + expectedStatusCode: http.StatusBadRequest, + expectedError: "vmName query parameter is required", + }, + { + name: "invalid vmName format", + resourceID: api.TestClusterResourceID, + vmName: "-invalid-vm-name", + setupData: func(ctx context.Context, t *testing.T, mockDB *databasetesting.MockDBClient, resourceID *azcorearm.ResourceID) { + }, + mockFPA: &mockFPACredentialRetriever{}, + expectedStatusCode: http.StatusBadRequest, + expectedError: "vmName contains invalid characters or format", + }, + { + name: "HCP cluster not found in database", + resourceID: api.TestClusterResourceID, + vmName: "test-vm", + setupData: func(ctx context.Context, t *testing.T, mockDB *databasetesting.MockDBClient, resourceID *azcorearm.ResourceID) { + }, + mockFPA: &mockFPACredentialRetriever{}, + expectedStatusCode: http.StatusInternalServerError, + expectedError: "failed to get HCP from database", + }, + { + name: "subscription not found", + resourceID: api.TestClusterResourceID, + vmName: "test-vm", + setupData: func(ctx context.Context, t *testing.T, mockDB *databasetesting.MockDBClient, resourceID *azcorearm.ResourceID) { + // Create HCP cluster with InternalID + internalID, err := api.NewInternalID("/api/clusters_mgmt/v1/clusters/test-cluster-id") + require.NoError(t, err) + hcp := &api.HCPOpenShiftCluster{ + TrackedResource: arm.TrackedResource{ + Resource: arm.Resource{ID: resourceID}, + }, + ServiceProviderProperties: api.HCPOpenShiftClusterServiceProviderProperties{ + ClusterServiceID: internalID, + }, + } + _, err = mockDB.HCPClusters(resourceID.SubscriptionID, resourceID.ResourceGroupName).Create(ctx, hcp, nil) + require.NoError(t, err) + }, + mockFPA: &mockFPACredentialRetriever{}, + expectedStatusCode: http.StatusNotFound, + expectedError: "not found", + }, + { + name: "FPA credential retrieval fails", + resourceID: api.TestClusterResourceID, + vmName: "test-vm", + setupData: func(ctx context.Context, t *testing.T, mockDB *databasetesting.MockDBClient, resourceID *azcorearm.ResourceID) { + // Create HCP cluster with InternalID + internalID, err := api.NewInternalID("/api/clusters_mgmt/v1/clusters/test-cluster-id") + require.NoError(t, err) + hcp := &api.HCPOpenShiftCluster{ + TrackedResource: arm.TrackedResource{ + Resource: arm.Resource{ID: resourceID}, + }, + ServiceProviderProperties: api.HCPOpenShiftClusterServiceProviderProperties{ + ClusterServiceID: internalID, + }, + } + _, err = mockDB.HCPClusters(resourceID.SubscriptionID, resourceID.ResourceGroupName).Create(ctx, hcp, nil) + require.NoError(t, err) + + // Create subscription with tenant ID + tenantID := "test-tenant-id" + subscriptionResourceID := api.Must(azcorearm.ParseResourceID("/subscriptions/" + resourceID.SubscriptionID)) + subscription := &arm.Subscription{ + CosmosMetadata: arm.CosmosMetadata{ + ResourceID: subscriptionResourceID, + }, + ResourceID: subscriptionResourceID, + State: arm.SubscriptionStateRegistered, + Properties: &arm.SubscriptionProperties{ + TenantId: &tenantID, + }, + } + _, err = mockDB.Subscriptions().Create(ctx, subscription, nil) + require.NoError(t, err) + }, + mockFPA: &mockFPACredentialRetriever{ + err: fmt.Errorf("failed to get FPA credentials"), + }, + expectedStatusCode: http.StatusInternalServerError, + expectedError: "failed to retrieve Azure credentials", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := utils.ContextWithLogger(context.Background(), testr.New(t)) + + // Setup database and test data + mockDB := databasetesting.NewMockDBClient() + + // Parse resource ID and add to context + resourceID, err := azcorearm.ParseResourceID(tt.resourceID) + require.NoError(t, err) + + // Setup test data + tt.setupData(ctx, t, mockDB, resourceID) + + // Create handler + handler := NewHCPSerialConsoleHandler(mockDB, tt.mockFPA) + + ctx = utils.ContextWithResourceID(ctx, resourceID) + + // Create request + url := "/serialconsole" + if tt.vmName != "" { + url += "?vmName=" + tt.vmName + } + req := httptest.NewRequest(http.MethodGet, url, nil) + req = req.WithContext(ctx) + + // Execute request + recorder := httptest.NewRecorder() + err = handler.ServeHTTP(recorder, req) + + // Validate response + if tt.expectedStatusCode >= 400 { + if err == nil { + t.Errorf("Expected error but got none") + return + } + + // Check if it's a CloudError when status is 400 or 404 + if tt.expectedStatusCode == http.StatusBadRequest || tt.expectedStatusCode == http.StatusNotFound { + var cloudErr *arm.CloudError + if !errors.As(err, &cloudErr) { + t.Errorf("Expected CloudError but got %T: %v", err, err) + return + } + if cloudErr.StatusCode != tt.expectedStatusCode { + t.Errorf("Expected status code %d but got %d", tt.expectedStatusCode, cloudErr.StatusCode) + } + } + + // Check error message + if tt.expectedError != "" { + if !strings.Contains(err.Error(), tt.expectedError) { + t.Errorf("Expected error containing %q but got %q", tt.expectedError, err.Error()) + } + } + } else { + if err != nil { + t.Errorf("Expected no error but got %q", err.Error()) + } + } + }) + } +} + +func TestSerialConsoleHandler_InvalidResourceID(t *testing.T) { + ctx := utils.ContextWithLogger(context.Background(), testr.New(t)) + + mockDB := databasetesting.NewMockDBClient() + mockFPA := &mockFPACredentialRetriever{} + + handler := NewHCPSerialConsoleHandler(mockDB, mockFPA) + + // Create request WITHOUT adding resource ID to context + req := httptest.NewRequest(http.MethodGet, "/serialconsole?vmName=test-vm", nil) + req = req.WithContext(ctx) + + recorder := httptest.NewRecorder() + err := handler.ServeHTTP(recorder, req) + + if err == nil { + t.Error("Expected error for missing resource ID but got none") + return + } + + // Should be a CloudError with 400 status + var cloudErr *arm.CloudError + if !errors.As(err, &cloudErr) { + t.Errorf("Expected CloudError but got %T: %v", err, err) + return + } + + if cloudErr.StatusCode != http.StatusBadRequest { + t.Errorf("Expected status code %d but got %d", http.StatusBadRequest, cloudErr.StatusCode) + } + + if !strings.Contains(err.Error(), "invalid resource identifier") { + t.Errorf("Expected error containing 'invalid resource identifier' but got %q", err.Error()) + } +} diff --git a/admin/server/server/admin.go b/admin/server/server/admin.go index f6e8f35be2..fe2ffd0587 100644 --- a/admin/server/server/admin.go +++ b/admin/server/server/admin.go @@ -109,6 +109,10 @@ func NewAdminAPI( middleware.V1HCPResourcePattern("GET", "/cosmosdump"), hcpMiddleware.HandlerFunc(errorutils.ReportError(cosmosdump.NewCosmosDumpHandler(dbClient).ServeHTTP)), ) + middlewareMux.Handle( + middleware.V1HCPResourcePattern("GET", "/serialconsole"), + hcpMiddleware.HandlerFunc(errorutils.ReportError(hcp.NewHCPSerialConsoleHandler(dbClient, fpaCredentialRetriever).ServeHTTP)), + ) // Non-HCP admin routes middlewareMux.Handle("GET /admin/helloworld", handlers.HelloWorldHandler()) diff --git a/cluster-service/helm-charts/cluster-service/templates/azure-operators-managed-identities-config.configmap.yaml b/cluster-service/helm-charts/cluster-service/templates/azure-operators-managed-identities-config.configmap.yaml index a57ad5ed9b..0d08dec3f3 100644 --- a/cluster-service/helm-charts/cluster-service/templates/azure-operators-managed-identities-config.configmap.yaml +++ b/cluster-service/helm-charts/cluster-service/templates/azure-operators-managed-identities-config.configmap.yaml @@ -121,3 +121,9 @@ data: - name: 'azure-file-csi-driver-node-sa' namespace: 'openshift-cluster-csi-drivers' optional: false + serviceManagedIdentity: + roleDefinitions: + {{- range $azureOperatorsMI.serviceManagedIdentity.roleDefinitions }} + - resourceId: '/providers/Microsoft.Authorization/roleDefinitions/{{ .id }}' + name: '{{ .name }}' + {{- end }} diff --git a/cluster-service/helm-charts/cluster-service/values.yaml b/cluster-service/helm-charts/cluster-service/values.yaml index 2425f46407..8431b17a4b 100644 --- a/cluster-service/helm-charts/cluster-service/values.yaml +++ b/cluster-service/helm-charts/cluster-service/values.yaml @@ -221,43 +221,55 @@ managedIdentitiesDataPlaneAudienceResource: "https://dummy.org" # The Azure Operator Managed Identities. azureOperatorsMI: roleSetName: "" + # TODO (revisit mock MSI implementation): + # because we have a mock MSI identity, these roles do nothing from a permissions perspective + # for control plane identities. They still work as intended on the managed resource group + # for data plane identities. We should consider revisiting the usage of a mock MSI identity + # as it indirectly makes us think these permissions apply uniformly across dataplane and control + # plane identities in DEV and INT. + # We continue to keep a "dev" and "public" reference to allow for testing new permissions added + # on data plane operators without having to wait for a built-in role update. dev: clusterApiAzure: roleDefinitions: - - id: 66a367ff-d3c0-5788-a79c-7033bff12c11 - name: Azure Red Hat OpenShift Cluster API Role - Dev + - id: 88366f10-ed47-4cc0-9fab-c8a06148393e + name: Azure Red Hat OpenShift Hosted Control Planes Cluster API Provider controlPlane: roleDefinitions: - - id: 666e75a4-7ac9-5be2-949a-1e088ee1f1c1 - name: Azure Red Hat OpenShift Control Plane Operator Role - Dev + - id: fc0c873f-45e9-4d0d-a7d1-585aab30c6ed + name: Azure Red Hat OpenShift Hosted Control Planes Control Plane Operator cloudControllerManager: roleDefinitions: - - id: ebe170ec-1247-536a-86d9-74c829dd9844 - name: Azure Red Hat OpenShift Cloud Controller Manager - Dev + - id: a1f96423-95ce-4224-ab27-4e3dc72facd4 + name: Azure Red Hat OpenShift Cloud Controller Manager ingress: roleDefinitions: - - id: 589ca160-4fac-501e-ad6c-006a19583727 - name: Azure Red Hat OpenShift Cluster Ingress Operator - Dev + - id: 0336e1d3-7a87-462b-b6db-342b63f7802c + name: Azure Red Hat OpenShift Cluster Ingress Operator diskCsiDriver: roleDefinitions: - - id: 4367fe74-0b43-5033-b629-15d9f28415ac - name: Azure Red Hat OpenShift Disk Storage Operator - Dev + - id: 5b7237c5-45e1-49d6-bc18-a1f62f400748 + name: Azure Red Hat OpenShift Disk Storage Operator fileCsiDriver: roleDefinitions: - - id: fdc0aaaa-1c3e-548e-ad27-0321e5fab18b - name: Azure Red Hat OpenShift File Storage Operator - Dev + - id: 0d7aedc0-15fd-4a67-a412-efad370c947e + name: Azure Red Hat OpenShift File Storage Operator imageRegistry: roleDefinitions: - - id: 357b9263-656f-5d45-9d7a-ccb825f0683f - name: Azure Red Hat OpenShift Image Registry Operator - Dev + - id: 8b32b316-c2f5-4ddf-b05b-83dacd2d08b5 + name: Azure Red Hat OpenShift Image Registry Operator cloudNetworkConfig: roleDefinitions: - - id: 4e4f23fe-3fab-568b-a001-10b233b0f840 - name: Azure Red Hat OpenShift Network Operator - Dev + - id: be7a6435-15ae-4171-8f30-4a343eff9e8f + name: Azure Red Hat OpenShift Network Operator kms: roleDefinitions: - - id: db156713-c34d-53de-ae4b-3e85d24e1783 - name: Azure Red Hat OpenShift KMS Plugin - Dev + - id: 12338af0-0e69-4776-bea7-57ae8d297424 + name: Key Vault Crypto User + serviceManagedIdentity: + roleDefinitions: + - id: c0ff367d-66d8-445e-917c-583feb0ef0d4 + name: Azure Red Hat OpenShift Hosted Control Planes Service Managed Identity public: clusterApiAzure: roleDefinitions: @@ -295,6 +307,10 @@ azureOperatorsMI: roleDefinitions: - id: 12338af0-0e69-4776-bea7-57ae8d297424 name: Key Vault Crypto User + serviceManagedIdentity: + roleDefinitions: + - id: c0ff367d-66d8-445e-917c-583feb0ef0d4 + name: Azure Red Hat OpenShift Hosted Control Planes Service Managed Identity # Pull binding configuration for ACR Pull Operator pullBinding: registry: "" diff --git a/config/config.schema.json b/config/config.schema.json index 10aa7b113c..179533e142 100644 --- a/config/config.schema.json +++ b/config/config.schema.json @@ -1904,34 +1904,6 @@ "minLength": 4, "maxLength": 22 }, - "auditLogsEventHub": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of the Event Hub for AKS audit logs" - }, - "namespace": { - "type": "string", - "description": "Name of the Audit logs Event Hub namespace" - }, - "authRuleName": { - "type": "string", - "description": "Name of the authorization rule for the Event Hub for use by the aks clusters" - }, - "kustoConsumerGroupName": { - "type": "string", - "description": "Name of the consumer group for Kusto data connection" - } - }, - "additionalProperties": false, - "required": [ - "name", - "namespace", - "authRuleName", - "kustoConsumerGroupName" - ] - }, "resourceGroup": { "description": "DEPRECATED, for backward compatibility only", "type": "string" @@ -1963,8 +1935,45 @@ "adminGroups", "viewerGroups", "kustoName", - "enableAutoScale", - "auditLogsEventHub" + "enableAutoScale" + ] + }, + "auditLogsEventHub": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the Event Hub for AKS audit logs" + }, + "namespace": { + "type": "string", + "description": "Name of the Audit logs Event Hub namespace" + }, + "authRuleName": { + "type": "string", + "description": "Name of the authorization rule for the Event Hub for use by the aks clusters" + }, + "kustoConsumerGroupName": { + "type": "string", + "description": "Name of the consumer group for Kusto data connection" + }, + "kustoDataConnectionName": { + "type": "string", + "description": "Name of the Kusto data connection for AKS audit logs" + }, + "rg": { + "type": "string", + "description": "Resource group for the audit logs Event Hub namespace" + } + }, + "additionalProperties": false, + "required": [ + "name", + "namespace", + "authRuleName", + "kustoConsumerGroupName", + "kustoDataConnectionName", + "rg" ] }, "mise": { diff --git a/config/config.yaml b/config/config.yaml index 9e293427f3..3b608f39ff 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -134,7 +134,7 @@ defaults: image: registry: arohcpsvcdev.azurecr.io repository: arohcpmetrics - digest: sha256:38294123323d6fd6b64bf8095ad5cb1d11997023e20d61349d47f6615318205e # 10b5899 (2026-03-23 12:10) + digest: sha256:f51a27f9b992cc21fee6f455dce01c0b50341ca82c03a52332467a10e226ca9e # 4b91a3a (2026-03-24 11:25) # Secret Sync Controller secretSyncController: image: @@ -150,7 +150,7 @@ defaults: image: registry: quay.io repository: app-sre/backplane-api - digest: sha256:bfbd903e800a441b68c76a0eda0184c1114a395da58063050cd0305ad0971050 # 1ee114d (2026-03-11 06:16) + digest: sha256:9595652e07044226b90b19af2b7d1947684086c32e5049404139a72e0dd30b34 # 09ad80b (2026-03-24 00:51) tenantId: "" ev2: assistedId: @@ -226,17 +226,19 @@ defaults: viewerGroups: "" sku: "" tier: "" - auditLogsEventHub: - name: "aks-auditlogs" - namespace: "hcp-{{ .ctx.environment }}-{{ .ev2.geoShortId }}-eh" - authRuleName: "SendRule" - kustoConsumerGroupName: "AuditLogsToKusto" + auditLogsEventHub: + name: "aks-auditlogs" + namespace: "hcp-{{ .ctx.environment }}-{{ .ctx.region }}-auditlogs-eh" + authRuleName: "SendRule" + kustoConsumerGroupName: "AuditLogsToKusto" + kustoDataConnectionName: "{{ .ctx.environment }}-{{ .ctx.region }}-auditlogs" + rg: "{{ .ctx.region }}-shared-resources" # Hypershift hypershift: image: registry: quay.io repository: redhat-services-prod/crt-redhat-acm-tenant/hypershift/hypershift-operator - digest: sha256:e7748a72fa8e1bbcf9b7c823b94bdc3a9967f92b4f5080df360eda3d0187af52 # b17cf168e0e9e1806be79d5c954b342e356fad08 (2026-03-21 06:29) + digest: sha256:a190b2bd63a051cf4ef9d52f139a88df1dd326b50d627142ddfc62fede92558a # 2fc70ab3e7d12afec4a41bf15f022cf051a5dc87 (2026-03-25 08:24) namespace: hypershift additionalInstallArg: '--enable-cpo-overrides' # By default we set it to empty as this tag is only required for msft environments. We override @@ -345,6 +347,8 @@ defaults: poll: true 'Microsoft.DbForPostgreSQL': poll: true + 'Microsoft.Kusto': + poll: true rg: "hcp-underlay-{{ .ctx.environment }}-{{ .ctx.region }}-svc" nsp: name: nsp-{{ .ctx.regionShort }}-svc @@ -562,7 +566,7 @@ defaults: image: registry: arohcpsvcdev.azurecr.io repository: arohcpbackend - digest: sha256:1f02a6963d6e4d6734f8432777ac6b924f286fad0136dfff608a6904e77feac6 # 95ad3eb (2026-03-24 00:01) + digest: sha256:85deff1008fd3455d7ca9c308f2c1c64d82036832d3ca7d8572bfde7cfc19e0a # 4b91a3a (2026-03-24 11:27) tracing: address: "" exporter: "" @@ -583,7 +587,7 @@ defaults: image: registry: arohcpsvcdev.azurecr.io repository: arohcpadminapi - digest: sha256:01223f7c60e32210554ce46c63a47bc09507d08ddc98f49f89c8fef6bfcda3d3 # 95ad3eb (2026-03-24 00:01) + digest: sha256:aa49815f5f103e6a33911b8b9290a2b9eabae5a1e931a99386ced2cdb5f06738 # 4b91a3a (2026-03-24 11:28) managedIdentityName: admin-api k8s: replicas: 2 @@ -596,7 +600,7 @@ defaults: image: registry: arohcpsvcdev.azurecr.io repository: arohcpsessiongate - digest: sha256:ce93e49b2a1ca67b20897b15a809e38512e0bab52c2baf7fd3e47ddb6faf68f4 # 95ad3eb (2026-03-24 00:01) + digest: sha256:776f190c68a626f40ea9269b2aad5cd59c9da15060c0ff6261a0df1515fb6da6 # 4b91a3a (2026-03-24 11:27) managedIdentityName: sessiongate k8s: replicas: 2 @@ -611,7 +615,7 @@ defaults: image: registry: arohcpsvcdev.azurecr.io repository: arohcpfrontend - digest: sha256:78749a8731e7cb2d76893c27b5f5ae54db943f55302dbf9975fe66f784a4cc5f # 95ad3eb (2026-03-24 00:00) + digest: sha256:1e183eef45f161d6b3b0ba94982ebd30536ca94e1ac534410c92d804f509f653 # 4b91a3a (2026-03-24 11:26) tracing: address: "" exporter: "" @@ -758,7 +762,7 @@ defaults: image: registry: quay.io repository: redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro - digest: sha256:8afde7f961257dc948732ead18da933bd4472060a1723e7e594fcdc7c0152558 # 1584dc0758e40c2280e49fc36f202803e9d5920c (2026-03-23 08:21) + digest: sha256:195db1fb826c90b6f3a7621b2d11ed79d632e4e93a5dc475fb4e81d2c2e44cae # 8e59adbc040351456481cb12a2959e82d49ae432 (2026-03-24 09:15) # PKO pko: managedIdentityName: package-operator @@ -783,18 +787,18 @@ defaults: bundle: registry: quay.io repository: redhat-user-workloads/crt-redhat-acm-tenant/acm-operator-bundle-acm-215 - digest: sha256:12594107ba681cc0ac148c44d71175d1c7942d85ff0c556e3a6bd5a455563932 # v2.15.2-433 (2026-03-23 23:10) + digest: sha256:57efa3ac2136e8b32fde890c8010c3dbfb62611663797e17e90609f0ddc407ba # v2.15.2-434 (2026-03-24 05:31) mce: bundle: registry: quay.io repository: redhat-user-workloads/crt-redhat-acm-tenant/mce-operator-bundle-mce-210 - digest: sha256:9ada289f06b9af65e2957f1eb5aa97c1add2ab0a85da11b27710b63029da1527 # v2.10.2-455 (2026-03-23 23:08) + digest: sha256:ba98af6c60952b7e8b4e682c16c31c560e342a090a1607adc47cd31d630905f3 # v2.10.2-457 (2026-03-24 11:22) # Cluster Service clustersService: image: registry: quay.io repository: app-sre/aro-hcp-clusters-service - digest: sha256:e30ee0c2851431cc17f44a109f987cb845e77369036c9a8074f17b66163341c8 # edaa61ee0754262ff1328fb8f6ec4005c1aa42c6 (2026-03-22 10:06) + digest: sha256:5f079a0240687e6d2214d892a61019db3a3bbb4e3afb97bcf7731633af4ce7d8 # c2ae01ac53880f3edf6fe7ec1558dd3e371f6cee (2026-03-24 21:59) # controls how many HCPs can be placed on an MC, sadly not configurable per MC provisionShardClusterLimit: 100 # batch processes @@ -860,7 +864,7 @@ defaults: image: registry: arohcpsvcdev.azurecr.io repository: image-sync/oc-mirror - digest: sha256:b9a1de42a37c9b838dfa9028233e7d25bfbb1b6ba497f239b47d2cc3e3eae500 # 95ad3eb (2026-03-24 00:00) + digest: sha256:de93a4b3df98f85b9bb21965ea5ab859f7916e69bd6659783665d25e3f559e80 # 4b91a3a (2026-03-24 11:26) pullSecretName: ocmirror-pull-secret operatorVersionsToMirror: "4.18,4.19,4.20" # Automation Account @@ -943,11 +947,6 @@ clouds: adminGroups: "" viewerGroups: "64dc69e4-d083-49fc-9569-ebece1dd1408/6b6d3adf-8476-4727-9812-20ffdef2b85c" rg: "hcp-kusto-us" - auditLogsEventHub: - name: "aks-auditlogs" - namespace: "hcp-dev-us-eh" - authRuleName: "SendRule" - kustoConsumerGroupName: "AuditLogsToKusto" tenantId: "64dc69e4-d083-49fc-9569-ebece1dd1408" automationDryRun: false arobit: diff --git a/config/rendered/dev/cspr/westus3.yaml b/config/rendered/dev/cspr/westus3.yaml index 1ec5510b76..3209870a3f 100755 --- a/config/rendered/dev/cspr/westus3.yaml +++ b/config/rendered/dev/cspr/westus3.yaml @@ -1,12 +1,12 @@ acm: mce: bundle: - digest: sha256:9ada289f06b9af65e2957f1eb5aa97c1add2ab0a85da11b27710b63029da1527 + digest: sha256:ba98af6c60952b7e8b4e682c16c31c560e342a090a1607adc47cd31d630905f3 registry: quay.io repository: redhat-user-workloads/crt-redhat-acm-tenant/mce-operator-bundle-mce-210 operator: bundle: - digest: sha256:12594107ba681cc0ac148c44d71175d1c7942d85ff0c556e3a6bd5a455563932 + digest: sha256:57efa3ac2136e8b32fde890c8010c3dbfb62611663797e17e90609f0ddc407ba registry: quay.io repository: redhat-user-workloads/crt-redhat-acm-tenant/acm-operator-bundle-acm-215 acr: @@ -35,7 +35,7 @@ adminApi: issuer: Self name: admin-api-cert-cspr-usw3 image: - digest: sha256:01223f7c60e32210554ce46c63a47bc09507d08ddc98f49f89c8fef6bfcda3d3 + digest: sha256:aa49815f5f103e6a33911b8b9290a2b9eabae5a1e931a99386ced2cdb5f06738 registry: arohcpsvcdev.azurecr.io repository: arohcpadminapi k8s: @@ -71,6 +71,13 @@ arobit: digest: sha256:2ae5282c99fa8c82bb394b23dbcb9ea0fa553e4ec3cce9e39d110f44b6282062 registry: mcr.microsoft.com repository: geneva/distroless/mdsd +auditLogsEventHub: + authRuleName: SendRule + kustoConsumerGroupName: AuditLogsToKusto + kustoDataConnectionName: cspr-westus3-auditlogs + name: aks-auditlogs + namespace: hcp-cspr-westus3-auditlogs-eh + rg: westus3-shared-resources automationDryRun: false azureGeoShortId: us azureRegionAvailabilityZoneCount: 4 @@ -79,7 +86,7 @@ backend: tlsCertificatesIssuer: Self exitOnPanic: true image: - digest: sha256:1f02a6963d6e4d6734f8432777ac6b924f286fad0136dfff608a6904e77feac6 + digest: sha256:85deff1008fd3455d7ca9c308f2c1c64d82036832d3ca7d8572bfde7cfc19e0a registry: arohcpsvcdev.azurecr.io repository: arohcpbackend k8s: @@ -94,7 +101,7 @@ backend: exporter: "" backplaneAPI: image: - digest: sha256:bfbd903e800a441b68c76a0eda0184c1114a395da58063050cd0305ad0971050 + digest: sha256:9595652e07044226b90b19af2b7d1947684086c32e5049404139a72e0dd30b34 registry: quay.io repository: app-sre/backplane-api billing: @@ -138,7 +145,7 @@ clustersService: deployDebugJobs: false environment: arohcpcspr image: - digest: sha256:e30ee0c2851431cc17f44a109f987cb845e77369036c9a8074f17b66163341c8 + digest: sha256:5f079a0240687e6d2214d892a61019db3a3bbb4e3afb97bcf7731633af4ce7d8 registry: quay.io repository: app-sre/aro-hcp-clusters-service k8s: @@ -184,7 +191,7 @@ clustersService: exporter: "" customExporter: image: - digest: sha256:38294123323d6fd6b64bf8095ad5cb1d11997023e20d61349d47f6615318205e + digest: sha256:f51a27f9b992cc21fee6f455dce01c0b50341ca82c03a52332467a10e226ca9e registry: arohcpsvcdev.azurecr.io repository: arohcpmetrics k8s: @@ -240,7 +247,7 @@ frontend: zoneRedundantMode: Disabled exitOnPanic: true image: - digest: sha256:78749a8731e7cb2d76893c27b5f5ae54db943f55302dbf9975fe66f784a4cc5f + digest: sha256:1e183eef45f161d6b3b0ba94982ebd30536ca94e1ac534410c92d804f509f653 registry: arohcpsvcdev.azurecr.io repository: arohcpfrontend k8s: @@ -349,7 +356,7 @@ global: hypershift: additionalInstallArg: --enable-cpo-overrides image: - digest: sha256:e7748a72fa8e1bbcf9b7c823b94bdc3a9967f92b4f5080df360eda3d0187af52 + digest: sha256:a190b2bd63a051cf4ef9d52f139a88df1dd326b50d627142ddfc62fede92558a registry: quay.io repository: redhat-services-prod/crt-redhat-acm-tenant/hypershift/hypershift-operator limitClusterSizes: true @@ -360,7 +367,7 @@ imageSync: ocMirror: enabled: true image: - digest: sha256:b9a1de42a37c9b838dfa9028233e7d25bfbb1b6ba497f239b47d2cc3e3eae500 + digest: sha256:de93a4b3df98f85b9bb21965ea5ab859f7916e69bd6659783665d25e3f559e80 registry: arohcpsvcdev.azurecr.io repository: image-sync/oc-mirror jobNamePrefix: "" @@ -378,11 +385,6 @@ kubeEvents: repository: shared/kube-events kusto: adminGroups: "" - auditLogsEventHub: - authRuleName: SendRule - kustoConsumerGroupName: AuditLogsToKusto - name: aks-auditlogs - namespace: hcp-dev-us-eh autoScaleMax: 10 autoScaleMin: 2 enableAutoScale: true @@ -428,7 +430,7 @@ maestro: name: arohcp-cspr-maestro-usw3 private: false image: - digest: sha256:8afde7f961257dc948732ead18da933bd4472060a1723e7e594fcdc7c0152558 + digest: sha256:195db1fb826c90b6f3a7621b2d11ed79d632e4e93a5dc475fb4e81d2c2e44cae registry: quay.io repository: redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro postgres: @@ -744,7 +746,7 @@ sessiongate: issuer: Self name: sessiongate-cert-cspr-usw3 image: - digest: sha256:ce93e49b2a1ca67b20897b15a809e38512e0bab52c2baf7fd3e47ddb6faf68f4 + digest: sha256:776f190c68a626f40ea9269b2aad5cd59c9da15060c0ff6261a0df1515fb6da6 registry: arohcpsvcdev.azurecr.io repository: arohcpsessiongate k8s: @@ -874,6 +876,8 @@ svc: poll: true Microsoft.Insights: poll: true + Microsoft.Kusto: + poll: true Microsoft.Network: features: - name: AllowBringYourOwnPublicIpAddress diff --git a/config/rendered/dev/dev/westus3.yaml b/config/rendered/dev/dev/westus3.yaml index e8d94c6ecb..bdc757935d 100755 --- a/config/rendered/dev/dev/westus3.yaml +++ b/config/rendered/dev/dev/westus3.yaml @@ -1,12 +1,12 @@ acm: mce: bundle: - digest: sha256:9ada289f06b9af65e2957f1eb5aa97c1add2ab0a85da11b27710b63029da1527 + digest: sha256:ba98af6c60952b7e8b4e682c16c31c560e342a090a1607adc47cd31d630905f3 registry: quay.io repository: redhat-user-workloads/crt-redhat-acm-tenant/mce-operator-bundle-mce-210 operator: bundle: - digest: sha256:12594107ba681cc0ac148c44d71175d1c7942d85ff0c556e3a6bd5a455563932 + digest: sha256:57efa3ac2136e8b32fde890c8010c3dbfb62611663797e17e90609f0ddc407ba registry: quay.io repository: redhat-user-workloads/crt-redhat-acm-tenant/acm-operator-bundle-acm-215 acr: @@ -35,7 +35,7 @@ adminApi: issuer: Self name: admin-api-cert-dev-usw3 image: - digest: sha256:01223f7c60e32210554ce46c63a47bc09507d08ddc98f49f89c8fef6bfcda3d3 + digest: sha256:aa49815f5f103e6a33911b8b9290a2b9eabae5a1e931a99386ced2cdb5f06738 registry: arohcpsvcdev.azurecr.io repository: arohcpadminapi k8s: @@ -71,6 +71,13 @@ arobit: digest: sha256:2ae5282c99fa8c82bb394b23dbcb9ea0fa553e4ec3cce9e39d110f44b6282062 registry: mcr.microsoft.com repository: geneva/distroless/mdsd +auditLogsEventHub: + authRuleName: SendRule + kustoConsumerGroupName: AuditLogsToKusto + kustoDataConnectionName: dev-westus3-auditlogs + name: aks-auditlogs + namespace: hcp-dev-westus3-auditlogs-eh + rg: westus3-shared-resources automationDryRun: false azureGeoShortId: us azureRegionAvailabilityZoneCount: 4 @@ -79,7 +86,7 @@ backend: tlsCertificatesIssuer: Self exitOnPanic: true image: - digest: sha256:1f02a6963d6e4d6734f8432777ac6b924f286fad0136dfff608a6904e77feac6 + digest: sha256:85deff1008fd3455d7ca9c308f2c1c64d82036832d3ca7d8572bfde7cfc19e0a registry: arohcpsvcdev.azurecr.io repository: arohcpbackend k8s: @@ -94,7 +101,7 @@ backend: exporter: "" backplaneAPI: image: - digest: sha256:bfbd903e800a441b68c76a0eda0184c1114a395da58063050cd0305ad0971050 + digest: sha256:9595652e07044226b90b19af2b7d1947684086c32e5049404139a72e0dd30b34 registry: quay.io repository: app-sre/backplane-api billing: @@ -138,7 +145,7 @@ clustersService: deployDebugJobs: false environment: arohcpdev image: - digest: sha256:e30ee0c2851431cc17f44a109f987cb845e77369036c9a8074f17b66163341c8 + digest: sha256:5f079a0240687e6d2214d892a61019db3a3bbb4e3afb97bcf7731633af4ce7d8 registry: quay.io repository: app-sre/aro-hcp-clusters-service k8s: @@ -184,7 +191,7 @@ clustersService: exporter: "" customExporter: image: - digest: sha256:38294123323d6fd6b64bf8095ad5cb1d11997023e20d61349d47f6615318205e + digest: sha256:f51a27f9b992cc21fee6f455dce01c0b50341ca82c03a52332467a10e226ca9e registry: arohcpsvcdev.azurecr.io repository: arohcpmetrics k8s: @@ -240,7 +247,7 @@ frontend: zoneRedundantMode: Disabled exitOnPanic: true image: - digest: sha256:78749a8731e7cb2d76893c27b5f5ae54db943f55302dbf9975fe66f784a4cc5f + digest: sha256:1e183eef45f161d6b3b0ba94982ebd30536ca94e1ac534410c92d804f509f653 registry: arohcpsvcdev.azurecr.io repository: arohcpfrontend k8s: @@ -349,7 +356,7 @@ global: hypershift: additionalInstallArg: --enable-cpo-overrides image: - digest: sha256:e7748a72fa8e1bbcf9b7c823b94bdc3a9967f92b4f5080df360eda3d0187af52 + digest: sha256:a190b2bd63a051cf4ef9d52f139a88df1dd326b50d627142ddfc62fede92558a registry: quay.io repository: redhat-services-prod/crt-redhat-acm-tenant/hypershift/hypershift-operator limitClusterSizes: true @@ -360,7 +367,7 @@ imageSync: ocMirror: enabled: true image: - digest: sha256:b9a1de42a37c9b838dfa9028233e7d25bfbb1b6ba497f239b47d2cc3e3eae500 + digest: sha256:de93a4b3df98f85b9bb21965ea5ab859f7916e69bd6659783665d25e3f559e80 registry: arohcpsvcdev.azurecr.io repository: image-sync/oc-mirror jobNamePrefix: "" @@ -378,11 +385,6 @@ kubeEvents: repository: shared/kube-events kusto: adminGroups: "" - auditLogsEventHub: - authRuleName: SendRule - kustoConsumerGroupName: AuditLogsToKusto - name: aks-auditlogs - namespace: hcp-dev-us-eh autoScaleMax: 10 autoScaleMin: 2 enableAutoScale: true @@ -428,7 +430,7 @@ maestro: name: arohcp-dev-maestro-usw3 private: false image: - digest: sha256:8afde7f961257dc948732ead18da933bd4472060a1723e7e594fcdc7c0152558 + digest: sha256:195db1fb826c90b6f3a7621b2d11ed79d632e4e93a5dc475fb4e81d2c2e44cae registry: quay.io repository: redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro postgres: @@ -744,7 +746,7 @@ sessiongate: issuer: Self name: sessiongate-cert-dev-usw3 image: - digest: sha256:ce93e49b2a1ca67b20897b15a809e38512e0bab52c2baf7fd3e47ddb6faf68f4 + digest: sha256:776f190c68a626f40ea9269b2aad5cd59c9da15060c0ff6261a0df1515fb6da6 registry: arohcpsvcdev.azurecr.io repository: arohcpsessiongate k8s: @@ -874,6 +876,8 @@ svc: poll: true Microsoft.Insights: poll: true + Microsoft.Kusto: + poll: true Microsoft.Network: features: - name: AllowBringYourOwnPublicIpAddress diff --git a/config/rendered/dev/perf/westus3.yaml b/config/rendered/dev/perf/westus3.yaml index 64ae225cd9..8826a304a7 100755 --- a/config/rendered/dev/perf/westus3.yaml +++ b/config/rendered/dev/perf/westus3.yaml @@ -1,12 +1,12 @@ acm: mce: bundle: - digest: sha256:9ada289f06b9af65e2957f1eb5aa97c1add2ab0a85da11b27710b63029da1527 + digest: sha256:ba98af6c60952b7e8b4e682c16c31c560e342a090a1607adc47cd31d630905f3 registry: quay.io repository: redhat-user-workloads/crt-redhat-acm-tenant/mce-operator-bundle-mce-210 operator: bundle: - digest: sha256:12594107ba681cc0ac148c44d71175d1c7942d85ff0c556e3a6bd5a455563932 + digest: sha256:57efa3ac2136e8b32fde890c8010c3dbfb62611663797e17e90609f0ddc407ba registry: quay.io repository: redhat-user-workloads/crt-redhat-acm-tenant/acm-operator-bundle-acm-215 acr: @@ -35,7 +35,7 @@ adminApi: issuer: Self name: admin-api-cert-perf-usw3ptest image: - digest: sha256:01223f7c60e32210554ce46c63a47bc09507d08ddc98f49f89c8fef6bfcda3d3 + digest: sha256:aa49815f5f103e6a33911b8b9290a2b9eabae5a1e931a99386ced2cdb5f06738 registry: arohcpsvcdev.azurecr.io repository: arohcpadminapi k8s: @@ -71,6 +71,13 @@ arobit: digest: sha256:2ae5282c99fa8c82bb394b23dbcb9ea0fa553e4ec3cce9e39d110f44b6282062 registry: mcr.microsoft.com repository: geneva/distroless/mdsd +auditLogsEventHub: + authRuleName: SendRule + kustoConsumerGroupName: AuditLogsToKusto + kustoDataConnectionName: perf-westus3-auditlogs + name: aks-auditlogs + namespace: hcp-perf-westus3-auditlogs-eh + rg: westus3-shared-resources automationDryRun: false azureGeoShortId: us azureRegionAvailabilityZoneCount: 4 @@ -79,7 +86,7 @@ backend: tlsCertificatesIssuer: Self exitOnPanic: true image: - digest: sha256:1f02a6963d6e4d6734f8432777ac6b924f286fad0136dfff608a6904e77feac6 + digest: sha256:85deff1008fd3455d7ca9c308f2c1c64d82036832d3ca7d8572bfde7cfc19e0a registry: arohcpsvcdev.azurecr.io repository: arohcpbackend k8s: @@ -94,7 +101,7 @@ backend: exporter: "" backplaneAPI: image: - digest: sha256:bfbd903e800a441b68c76a0eda0184c1114a395da58063050cd0305ad0971050 + digest: sha256:9595652e07044226b90b19af2b7d1947684086c32e5049404139a72e0dd30b34 registry: quay.io repository: app-sre/backplane-api billing: @@ -138,7 +145,7 @@ clustersService: deployDebugJobs: false environment: arohcpperf image: - digest: sha256:e30ee0c2851431cc17f44a109f987cb845e77369036c9a8074f17b66163341c8 + digest: sha256:5f079a0240687e6d2214d892a61019db3a3bbb4e3afb97bcf7731633af4ce7d8 registry: quay.io repository: app-sre/aro-hcp-clusters-service k8s: @@ -184,7 +191,7 @@ clustersService: exporter: "" customExporter: image: - digest: sha256:38294123323d6fd6b64bf8095ad5cb1d11997023e20d61349d47f6615318205e + digest: sha256:f51a27f9b992cc21fee6f455dce01c0b50341ca82c03a52332467a10e226ca9e registry: arohcpsvcdev.azurecr.io repository: arohcpmetrics k8s: @@ -240,7 +247,7 @@ frontend: zoneRedundantMode: Auto exitOnPanic: true image: - digest: sha256:78749a8731e7cb2d76893c27b5f5ae54db943f55302dbf9975fe66f784a4cc5f + digest: sha256:1e183eef45f161d6b3b0ba94982ebd30536ca94e1ac534410c92d804f509f653 registry: arohcpsvcdev.azurecr.io repository: arohcpfrontend k8s: @@ -349,7 +356,7 @@ global: hypershift: additionalInstallArg: --enable-cpo-overrides image: - digest: sha256:e7748a72fa8e1bbcf9b7c823b94bdc3a9967f92b4f5080df360eda3d0187af52 + digest: sha256:a190b2bd63a051cf4ef9d52f139a88df1dd326b50d627142ddfc62fede92558a registry: quay.io repository: redhat-services-prod/crt-redhat-acm-tenant/hypershift/hypershift-operator limitClusterSizes: true @@ -360,7 +367,7 @@ imageSync: ocMirror: enabled: true image: - digest: sha256:b9a1de42a37c9b838dfa9028233e7d25bfbb1b6ba497f239b47d2cc3e3eae500 + digest: sha256:de93a4b3df98f85b9bb21965ea5ab859f7916e69bd6659783665d25e3f559e80 registry: arohcpsvcdev.azurecr.io repository: image-sync/oc-mirror jobNamePrefix: "" @@ -378,11 +385,6 @@ kubeEvents: repository: shared/kube-events kusto: adminGroups: "" - auditLogsEventHub: - authRuleName: SendRule - kustoConsumerGroupName: AuditLogsToKusto - name: aks-auditlogs - namespace: hcp-dev-us-eh autoScaleMax: 10 autoScaleMin: 2 enableAutoScale: true @@ -428,7 +430,7 @@ maestro: name: arohcp-perf-maestro-usw3ptest private: false image: - digest: sha256:8afde7f961257dc948732ead18da933bd4472060a1723e7e594fcdc7c0152558 + digest: sha256:195db1fb826c90b6f3a7621b2d11ed79d632e4e93a5dc475fb4e81d2c2e44cae registry: quay.io repository: redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro postgres: @@ -744,7 +746,7 @@ sessiongate: issuer: Self name: sessiongate-cert-perf-usw3ptest image: - digest: sha256:ce93e49b2a1ca67b20897b15a809e38512e0bab52c2baf7fd3e47ddb6faf68f4 + digest: sha256:776f190c68a626f40ea9269b2aad5cd59c9da15060c0ff6261a0df1515fb6da6 registry: arohcpsvcdev.azurecr.io repository: arohcpsessiongate k8s: @@ -874,6 +876,8 @@ svc: poll: true Microsoft.Insights: poll: true + Microsoft.Kusto: + poll: true Microsoft.Network: features: - name: AllowBringYourOwnPublicIpAddress diff --git a/config/rendered/dev/pers/westus3.yaml b/config/rendered/dev/pers/westus3.yaml index 9945b00aea..b42b545ebc 100755 --- a/config/rendered/dev/pers/westus3.yaml +++ b/config/rendered/dev/pers/westus3.yaml @@ -1,12 +1,12 @@ acm: mce: bundle: - digest: sha256:9ada289f06b9af65e2957f1eb5aa97c1add2ab0a85da11b27710b63029da1527 + digest: sha256:ba98af6c60952b7e8b4e682c16c31c560e342a090a1607adc47cd31d630905f3 registry: quay.io repository: redhat-user-workloads/crt-redhat-acm-tenant/mce-operator-bundle-mce-210 operator: bundle: - digest: sha256:12594107ba681cc0ac148c44d71175d1c7942d85ff0c556e3a6bd5a455563932 + digest: sha256:57efa3ac2136e8b32fde890c8010c3dbfb62611663797e17e90609f0ddc407ba registry: quay.io repository: redhat-user-workloads/crt-redhat-acm-tenant/acm-operator-bundle-acm-215 acr: @@ -35,7 +35,7 @@ adminApi: issuer: Self name: admin-api-cert-pers-usw3test image: - digest: sha256:01223f7c60e32210554ce46c63a47bc09507d08ddc98f49f89c8fef6bfcda3d3 + digest: sha256:aa49815f5f103e6a33911b8b9290a2b9eabae5a1e931a99386ced2cdb5f06738 registry: arohcpsvcdev.azurecr.io repository: arohcpadminapi k8s: @@ -71,6 +71,13 @@ arobit: digest: sha256:2ae5282c99fa8c82bb394b23dbcb9ea0fa553e4ec3cce9e39d110f44b6282062 registry: mcr.microsoft.com repository: geneva/distroless/mdsd +auditLogsEventHub: + authRuleName: SendRule + kustoConsumerGroupName: AuditLogsToKusto + kustoDataConnectionName: pers-westus3-auditlogs + name: aks-auditlogs + namespace: hcp-pers-westus3-auditlogs-eh + rg: westus3-shared-resources automationDryRun: false azureGeoShortId: us azureRegionAvailabilityZoneCount: 4 @@ -79,7 +86,7 @@ backend: tlsCertificatesIssuer: Self exitOnPanic: true image: - digest: sha256:1f02a6963d6e4d6734f8432777ac6b924f286fad0136dfff608a6904e77feac6 + digest: sha256:85deff1008fd3455d7ca9c308f2c1c64d82036832d3ca7d8572bfde7cfc19e0a registry: arohcpsvcdev.azurecr.io repository: arohcpbackend k8s: @@ -94,7 +101,7 @@ backend: exporter: otlp backplaneAPI: image: - digest: sha256:bfbd903e800a441b68c76a0eda0184c1114a395da58063050cd0305ad0971050 + digest: sha256:9595652e07044226b90b19af2b7d1947684086c32e5049404139a72e0dd30b34 registry: quay.io repository: app-sre/backplane-api billing: @@ -138,7 +145,7 @@ clustersService: deployDebugJobs: false environment: arohcppers image: - digest: sha256:e30ee0c2851431cc17f44a109f987cb845e77369036c9a8074f17b66163341c8 + digest: sha256:5f079a0240687e6d2214d892a61019db3a3bbb4e3afb97bcf7731633af4ce7d8 registry: quay.io repository: app-sre/aro-hcp-clusters-service k8s: @@ -184,7 +191,7 @@ clustersService: exporter: otlp customExporter: image: - digest: sha256:38294123323d6fd6b64bf8095ad5cb1d11997023e20d61349d47f6615318205e + digest: sha256:f51a27f9b992cc21fee6f455dce01c0b50341ca82c03a52332467a10e226ca9e registry: arohcpsvcdev.azurecr.io repository: arohcpmetrics k8s: @@ -240,7 +247,7 @@ frontend: zoneRedundantMode: Disabled exitOnPanic: true image: - digest: sha256:78749a8731e7cb2d76893c27b5f5ae54db943f55302dbf9975fe66f784a4cc5f + digest: sha256:1e183eef45f161d6b3b0ba94982ebd30536ca94e1ac534410c92d804f509f653 registry: arohcpsvcdev.azurecr.io repository: arohcpfrontend k8s: @@ -349,7 +356,7 @@ global: hypershift: additionalInstallArg: --enable-cpo-overrides image: - digest: sha256:e7748a72fa8e1bbcf9b7c823b94bdc3a9967f92b4f5080df360eda3d0187af52 + digest: sha256:a190b2bd63a051cf4ef9d52f139a88df1dd326b50d627142ddfc62fede92558a registry: quay.io repository: redhat-services-prod/crt-redhat-acm-tenant/hypershift/hypershift-operator limitClusterSizes: true @@ -360,7 +367,7 @@ imageSync: ocMirror: enabled: true image: - digest: sha256:b9a1de42a37c9b838dfa9028233e7d25bfbb1b6ba497f239b47d2cc3e3eae500 + digest: sha256:de93a4b3df98f85b9bb21965ea5ab859f7916e69bd6659783665d25e3f559e80 registry: arohcpsvcdev.azurecr.io repository: image-sync/oc-mirror jobNamePrefix: "" @@ -378,11 +385,6 @@ kubeEvents: repository: shared/kube-events kusto: adminGroups: "" - auditLogsEventHub: - authRuleName: SendRule - kustoConsumerGroupName: AuditLogsToKusto - name: aks-auditlogs - namespace: hcp-dev-us-eh autoScaleMax: 10 autoScaleMin: 2 enableAutoScale: true @@ -428,7 +430,7 @@ maestro: name: arohcp-pers-maestro-usw3test private: false image: - digest: sha256:8afde7f961257dc948732ead18da933bd4472060a1723e7e594fcdc7c0152558 + digest: sha256:195db1fb826c90b6f3a7621b2d11ed79d632e4e93a5dc475fb4e81d2c2e44cae registry: quay.io repository: redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro postgres: @@ -746,7 +748,7 @@ sessiongate: issuer: Self name: sessiongate-cert-pers-usw3test image: - digest: sha256:ce93e49b2a1ca67b20897b15a809e38512e0bab52c2baf7fd3e47ddb6faf68f4 + digest: sha256:776f190c68a626f40ea9269b2aad5cd59c9da15060c0ff6261a0df1515fb6da6 registry: arohcpsvcdev.azurecr.io repository: arohcpsessiongate k8s: @@ -878,6 +880,8 @@ svc: poll: true Microsoft.Insights: poll: true + Microsoft.Kusto: + poll: true Microsoft.Network: features: - name: AllowBringYourOwnPublicIpAddress diff --git a/config/rendered/dev/prow/westus3.yaml b/config/rendered/dev/prow/westus3.yaml index 823c14139b..1b44aa58f6 100755 --- a/config/rendered/dev/prow/westus3.yaml +++ b/config/rendered/dev/prow/westus3.yaml @@ -1,12 +1,12 @@ acm: mce: bundle: - digest: sha256:9ada289f06b9af65e2957f1eb5aa97c1add2ab0a85da11b27710b63029da1527 + digest: sha256:ba98af6c60952b7e8b4e682c16c31c560e342a090a1607adc47cd31d630905f3 registry: quay.io repository: redhat-user-workloads/crt-redhat-acm-tenant/mce-operator-bundle-mce-210 operator: bundle: - digest: sha256:12594107ba681cc0ac148c44d71175d1c7942d85ff0c556e3a6bd5a455563932 + digest: sha256:57efa3ac2136e8b32fde890c8010c3dbfb62611663797e17e90609f0ddc407ba registry: quay.io repository: redhat-user-workloads/crt-redhat-acm-tenant/acm-operator-bundle-acm-215 acr: @@ -35,7 +35,7 @@ adminApi: issuer: Self name: admin-api-cert-prow-j7654321 image: - digest: sha256:01223f7c60e32210554ce46c63a47bc09507d08ddc98f49f89c8fef6bfcda3d3 + digest: sha256:aa49815f5f103e6a33911b8b9290a2b9eabae5a1e931a99386ced2cdb5f06738 registry: arohcpsvcdev.azurecr.io repository: arohcpadminapi k8s: @@ -71,6 +71,13 @@ arobit: digest: sha256:2ae5282c99fa8c82bb394b23dbcb9ea0fa553e4ec3cce9e39d110f44b6282062 registry: mcr.microsoft.com repository: geneva/distroless/mdsd +auditLogsEventHub: + authRuleName: SendRule + kustoConsumerGroupName: AuditLogsToKusto + kustoDataConnectionName: prow-westus3-auditlogs + name: aks-auditlogs + namespace: hcp-prow-westus3-auditlogs-eh + rg: westus3-shared-resources automationDryRun: false azureGeoShortId: us azureRegionAvailabilityZoneCount: 4 @@ -79,7 +86,7 @@ backend: tlsCertificatesIssuer: Self exitOnPanic: true image: - digest: sha256:1f02a6963d6e4d6734f8432777ac6b924f286fad0136dfff608a6904e77feac6 + digest: sha256:85deff1008fd3455d7ca9c308f2c1c64d82036832d3ca7d8572bfde7cfc19e0a registry: arohcpsvcdev.azurecr.io repository: arohcpbackend k8s: @@ -94,7 +101,7 @@ backend: exporter: otlp backplaneAPI: image: - digest: sha256:bfbd903e800a441b68c76a0eda0184c1114a395da58063050cd0305ad0971050 + digest: sha256:9595652e07044226b90b19af2b7d1947684086c32e5049404139a72e0dd30b34 registry: quay.io repository: app-sre/backplane-api billing: @@ -138,7 +145,7 @@ clustersService: deployDebugJobs: false environment: arohcpprow image: - digest: sha256:e30ee0c2851431cc17f44a109f987cb845e77369036c9a8074f17b66163341c8 + digest: sha256:5f079a0240687e6d2214d892a61019db3a3bbb4e3afb97bcf7731633af4ce7d8 registry: quay.io repository: app-sre/aro-hcp-clusters-service k8s: @@ -184,7 +191,7 @@ clustersService: exporter: otlp customExporter: image: - digest: sha256:38294123323d6fd6b64bf8095ad5cb1d11997023e20d61349d47f6615318205e + digest: sha256:f51a27f9b992cc21fee6f455dce01c0b50341ca82c03a52332467a10e226ca9e registry: arohcpsvcdev.azurecr.io repository: arohcpmetrics k8s: @@ -240,7 +247,7 @@ frontend: zoneRedundantMode: Disabled exitOnPanic: true image: - digest: sha256:78749a8731e7cb2d76893c27b5f5ae54db943f55302dbf9975fe66f784a4cc5f + digest: sha256:1e183eef45f161d6b3b0ba94982ebd30536ca94e1ac534410c92d804f509f653 registry: arohcpsvcdev.azurecr.io repository: arohcpfrontend k8s: @@ -349,7 +356,7 @@ global: hypershift: additionalInstallArg: --enable-cpo-overrides image: - digest: sha256:e7748a72fa8e1bbcf9b7c823b94bdc3a9967f92b4f5080df360eda3d0187af52 + digest: sha256:a190b2bd63a051cf4ef9d52f139a88df1dd326b50d627142ddfc62fede92558a registry: quay.io repository: redhat-services-prod/crt-redhat-acm-tenant/hypershift/hypershift-operator limitClusterSizes: true @@ -360,7 +367,7 @@ imageSync: ocMirror: enabled: true image: - digest: sha256:b9a1de42a37c9b838dfa9028233e7d25bfbb1b6ba497f239b47d2cc3e3eae500 + digest: sha256:de93a4b3df98f85b9bb21965ea5ab859f7916e69bd6659783665d25e3f559e80 registry: arohcpsvcdev.azurecr.io repository: image-sync/oc-mirror jobNamePrefix: "" @@ -378,11 +385,6 @@ kubeEvents: repository: shared/kube-events kusto: adminGroups: "" - auditLogsEventHub: - authRuleName: SendRule - kustoConsumerGroupName: AuditLogsToKusto - name: aks-auditlogs - namespace: hcp-dev-us-eh autoScaleMax: 10 autoScaleMin: 2 enableAutoScale: true @@ -428,7 +430,7 @@ maestro: name: arohcp-prow-maestro-j7654321 private: false image: - digest: sha256:8afde7f961257dc948732ead18da933bd4472060a1723e7e594fcdc7c0152558 + digest: sha256:195db1fb826c90b6f3a7621b2d11ed79d632e4e93a5dc475fb4e81d2c2e44cae registry: quay.io repository: redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro postgres: @@ -746,7 +748,7 @@ sessiongate: issuer: Self name: sessiongate-cert-prow-j7654321 image: - digest: sha256:ce93e49b2a1ca67b20897b15a809e38512e0bab52c2baf7fd3e47ddb6faf68f4 + digest: sha256:776f190c68a626f40ea9269b2aad5cd59c9da15060c0ff6261a0df1515fb6da6 registry: arohcpsvcdev.azurecr.io repository: arohcpsessiongate k8s: @@ -878,6 +880,8 @@ svc: poll: true Microsoft.Insights: poll: true + Microsoft.Kusto: + poll: true Microsoft.Network: features: - name: AllowBringYourOwnPublicIpAddress diff --git a/config/rendered/dev/swft/uksouth.yaml b/config/rendered/dev/swft/uksouth.yaml index 2f238703ca..0f159c3534 100755 --- a/config/rendered/dev/swft/uksouth.yaml +++ b/config/rendered/dev/swft/uksouth.yaml @@ -1,12 +1,12 @@ acm: mce: bundle: - digest: sha256:9ada289f06b9af65e2957f1eb5aa97c1add2ab0a85da11b27710b63029da1527 + digest: sha256:ba98af6c60952b7e8b4e682c16c31c560e342a090a1607adc47cd31d630905f3 registry: quay.io repository: redhat-user-workloads/crt-redhat-acm-tenant/mce-operator-bundle-mce-210 operator: bundle: - digest: sha256:12594107ba681cc0ac148c44d71175d1c7942d85ff0c556e3a6bd5a455563932 + digest: sha256:57efa3ac2136e8b32fde890c8010c3dbfb62611663797e17e90609f0ddc407ba registry: quay.io repository: redhat-user-workloads/crt-redhat-acm-tenant/acm-operator-bundle-acm-215 acr: @@ -35,7 +35,7 @@ adminApi: issuer: Self name: admin-api-cert-swft-lnstest image: - digest: sha256:01223f7c60e32210554ce46c63a47bc09507d08ddc98f49f89c8fef6bfcda3d3 + digest: sha256:aa49815f5f103e6a33911b8b9290a2b9eabae5a1e931a99386ced2cdb5f06738 registry: arohcpsvcdev.azurecr.io repository: arohcpadminapi k8s: @@ -71,6 +71,13 @@ arobit: digest: sha256:2ae5282c99fa8c82bb394b23dbcb9ea0fa553e4ec3cce9e39d110f44b6282062 registry: mcr.microsoft.com repository: geneva/distroless/mdsd +auditLogsEventHub: + authRuleName: SendRule + kustoConsumerGroupName: AuditLogsToKusto + kustoDataConnectionName: swft-uksouth-auditlogs + name: aks-auditlogs + namespace: hcp-swft-uksouth-auditlogs-eh + rg: uksouth-shared-resources automationDryRun: false azureGeoShortId: uk azureRegionAvailabilityZoneCount: 3 @@ -79,7 +86,7 @@ backend: tlsCertificatesIssuer: Self exitOnPanic: true image: - digest: sha256:1f02a6963d6e4d6734f8432777ac6b924f286fad0136dfff608a6904e77feac6 + digest: sha256:85deff1008fd3455d7ca9c308f2c1c64d82036832d3ca7d8572bfde7cfc19e0a registry: arohcpsvcdev.azurecr.io repository: arohcpbackend k8s: @@ -94,7 +101,7 @@ backend: exporter: "" backplaneAPI: image: - digest: sha256:bfbd903e800a441b68c76a0eda0184c1114a395da58063050cd0305ad0971050 + digest: sha256:9595652e07044226b90b19af2b7d1947684086c32e5049404139a72e0dd30b34 registry: quay.io repository: app-sre/backplane-api billing: @@ -138,7 +145,7 @@ clustersService: deployDebugJobs: false environment: arohcpswft image: - digest: sha256:e30ee0c2851431cc17f44a109f987cb845e77369036c9a8074f17b66163341c8 + digest: sha256:5f079a0240687e6d2214d892a61019db3a3bbb4e3afb97bcf7731633af4ce7d8 registry: quay.io repository: app-sre/aro-hcp-clusters-service k8s: @@ -184,7 +191,7 @@ clustersService: exporter: "" customExporter: image: - digest: sha256:38294123323d6fd6b64bf8095ad5cb1d11997023e20d61349d47f6615318205e + digest: sha256:f51a27f9b992cc21fee6f455dce01c0b50341ca82c03a52332467a10e226ca9e registry: arohcpsvcdev.azurecr.io repository: arohcpmetrics k8s: @@ -240,7 +247,7 @@ frontend: zoneRedundantMode: Disabled exitOnPanic: true image: - digest: sha256:78749a8731e7cb2d76893c27b5f5ae54db943f55302dbf9975fe66f784a4cc5f + digest: sha256:1e183eef45f161d6b3b0ba94982ebd30536ca94e1ac534410c92d804f509f653 registry: arohcpsvcdev.azurecr.io repository: arohcpfrontend k8s: @@ -349,7 +356,7 @@ global: hypershift: additionalInstallArg: --enable-cpo-overrides image: - digest: sha256:e7748a72fa8e1bbcf9b7c823b94bdc3a9967f92b4f5080df360eda3d0187af52 + digest: sha256:a190b2bd63a051cf4ef9d52f139a88df1dd326b50d627142ddfc62fede92558a registry: quay.io repository: redhat-services-prod/crt-redhat-acm-tenant/hypershift/hypershift-operator limitClusterSizes: true @@ -360,7 +367,7 @@ imageSync: ocMirror: enabled: true image: - digest: sha256:b9a1de42a37c9b838dfa9028233e7d25bfbb1b6ba497f239b47d2cc3e3eae500 + digest: sha256:de93a4b3df98f85b9bb21965ea5ab859f7916e69bd6659783665d25e3f559e80 registry: arohcpsvcdev.azurecr.io repository: image-sync/oc-mirror jobNamePrefix: "" @@ -378,11 +385,6 @@ kubeEvents: repository: shared/kube-events kusto: adminGroups: "" - auditLogsEventHub: - authRuleName: SendRule - kustoConsumerGroupName: AuditLogsToKusto - name: aks-auditlogs - namespace: hcp-dev-us-eh autoScaleMax: 10 autoScaleMin: 2 enableAutoScale: true @@ -428,7 +430,7 @@ maestro: name: arohcp-swft-maestro-lnstest private: false image: - digest: sha256:8afde7f961257dc948732ead18da933bd4472060a1723e7e594fcdc7c0152558 + digest: sha256:195db1fb826c90b6f3a7621b2d11ed79d632e4e93a5dc475fb4e81d2c2e44cae registry: quay.io repository: redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro postgres: @@ -746,7 +748,7 @@ sessiongate: issuer: Self name: sessiongate-cert-swft-lnstest image: - digest: sha256:ce93e49b2a1ca67b20897b15a809e38512e0bab52c2baf7fd3e47ddb6faf68f4 + digest: sha256:776f190c68a626f40ea9269b2aad5cd59c9da15060c0ff6261a0df1515fb6da6 registry: arohcpsvcdev.azurecr.io repository: arohcpsessiongate k8s: @@ -876,6 +878,8 @@ svc: poll: true Microsoft.Insights: poll: true + Microsoft.Kusto: + poll: true Microsoft.Network: features: - name: AllowBringYourOwnPublicIpAddress diff --git a/dev-infrastructure/configurations/audit-logs-data-connection.tmpl.bicepparam b/dev-infrastructure/configurations/audit-logs-data-connection.tmpl.bicepparam new file mode 100644 index 0000000000..ef25f940bf --- /dev/null +++ b/dev-infrastructure/configurations/audit-logs-data-connection.tmpl.bicepparam @@ -0,0 +1,9 @@ +using '../templates/audit-logs-data-connection.bicep' + +param kustoName = '{{ .kusto.kustoName }}' +param auditLogsKustoConsumerGroupName = '{{ .auditLogsEventHub.kustoConsumerGroupName }}' +param auditLogsEventHubId = '__auditLogsEventHubId__' +param databaseName = '{{ .kusto.serviceLogsDatabase }}' +param kustoDataConnectionName = '{{ .auditLogsEventHub.kustoDataConnectionName }}' +param manageInstance = {{ .kusto.manageInstance }} +param kustoEnabled = {{ .arobit.kusto.enabled }} diff --git a/dev-infrastructure/configurations/audit-logs-eventhub.tmpl.bicepparam b/dev-infrastructure/configurations/audit-logs-eventhub.tmpl.bicepparam new file mode 100644 index 0000000000..36ad82617d --- /dev/null +++ b/dev-infrastructure/configurations/audit-logs-eventhub.tmpl.bicepparam @@ -0,0 +1,8 @@ +using '../templates/audit-logs-eventhub.bicep' + +param auditLogsKustoConsumerGroupName = '{{ .auditLogsEventHub.kustoConsumerGroupName }}' +param auditLogsDiagnosticSettingsRuleName = '{{ .auditLogsEventHub.authRuleName }}' +param auditLogsEventHubName = '{{ .auditLogsEventHub.name }}' +param auditLogsEventHubNamespaceName = '{{ .auditLogsEventHub.namespace }}' +param manageInstance = {{ .kusto.manageInstance }} +param kustoPrincipalId = '__kustoPrincipalId__' diff --git a/dev-infrastructure/configurations/kusto-lookup.tmpl.bicepparam b/dev-infrastructure/configurations/kusto-lookup.tmpl.bicepparam index b32f768b95..2c535bebf5 100644 --- a/dev-infrastructure/configurations/kusto-lookup.tmpl.bicepparam +++ b/dev-infrastructure/configurations/kusto-lookup.tmpl.bicepparam @@ -3,9 +3,3 @@ using '../templates/kusto-lookup.bicep' param kustoName = '{{ .kusto.kustoName }}' param kustoEnabled = {{ .arobit.kusto.enabled }} - -param auditLogsEventHubNamespaceName = '{{ .kusto.auditLogsEventHub.namespace }}' - -param auditLogsEventHubName = '{{ .kusto.auditLogsEventHub.name }}' - -param auditLogsEventHubAuthRuleName = '{{ .kusto.auditLogsEventHub.authRuleName }}' diff --git a/dev-infrastructure/configurations/kusto.tmpl.bicepparam b/dev-infrastructure/configurations/kusto.tmpl.bicepparam index efe22d4fc9..2371376932 100644 --- a/dev-infrastructure/configurations/kusto.tmpl.bicepparam +++ b/dev-infrastructure/configurations/kusto.tmpl.bicepparam @@ -21,11 +21,3 @@ param autoScaleMin = {{ .kusto.autoScaleMin }} param autoScaleMax = {{ .kusto.autoScaleMax }} param enableAutoScale = {{ .kusto.enableAutoScale }} - -param auditLogsEventHubNamespaceName = '{{ .kusto.auditLogsEventHub.namespace }}' - -param auditLogsEventHubName = '{{ .kusto.auditLogsEventHub.name }}' - -param auditLogsKustoConsumerGroupName = '{{ .kusto.auditLogsEventHub.kustoConsumerGroupName }}' - -param auditLogsDiagnosticSettingsRuleName = '{{ .kusto.auditLogsEventHub.authRuleName }}' diff --git a/dev-infrastructure/configurations/mgmt-cluster.tmpl.bicepparam b/dev-infrastructure/configurations/mgmt-cluster.tmpl.bicepparam index b75491b13d..731625db15 100644 --- a/dev-infrastructure/configurations/mgmt-cluster.tmpl.bicepparam +++ b/dev-infrastructure/configurations/mgmt-cluster.tmpl.bicepparam @@ -94,5 +94,5 @@ param owningTeamTagValue = '{{ .monitoring.alertRuleOwningTeamTag }}' param hcpBackupsStorageAccountName = '{{ .mgmt.hcpBackups.storageAccount.name }}' // Audit Logs Event Hub -param auditLogsEventHubName = '{{ .kusto.auditLogsEventHub.name }}' +param auditLogsEventHubName = '{{ .auditLogsEventHub.name }}' param auditLogsEventHubAuthRuleId = '__auditLogsEventHubAuthRuleId__' diff --git a/dev-infrastructure/configurations/output-audit-logs-eventhub.tmpl.bicepparam b/dev-infrastructure/configurations/output-audit-logs-eventhub.tmpl.bicepparam new file mode 100644 index 0000000000..8881207049 --- /dev/null +++ b/dev-infrastructure/configurations/output-audit-logs-eventhub.tmpl.bicepparam @@ -0,0 +1,5 @@ +using '../templates/output-audit-logs-eventhub.bicep' + +param auditLogsEventHubNamespaceName = '{{ .auditLogsEventHub.namespace }}' +param auditLogsEventHubAuthRuleName = '{{ .auditLogsEventHub.authRuleName }}' +param kustoEnabled = {{ .arobit.kusto.enabled }} diff --git a/dev-infrastructure/configurations/svc-cluster.tmpl.bicepparam b/dev-infrastructure/configurations/svc-cluster.tmpl.bicepparam index 9fdbaa36f3..5512bb1e13 100644 --- a/dev-infrastructure/configurations/svc-cluster.tmpl.bicepparam +++ b/dev-infrastructure/configurations/svc-cluster.tmpl.bicepparam @@ -168,7 +168,7 @@ param billingContainerMaxScale = {{ .frontend.cosmosDB.billingContainerMaxScale param locksContainerMaxScale = {{ .frontend.cosmosDB.locksContainerMaxScale }} // Audit Logs Event Hub -param auditLogsEventHubName = '{{ .kusto.auditLogsEventHub.name }}' +param auditLogsEventHubName = '{{ .auditLogsEventHub.name }}' param auditLogsEventHubAuthRuleId = '__auditLogsEventHubAuthRuleId__' // Exporter diff --git a/dev-infrastructure/global-pipeline.yaml b/dev-infrastructure/global-pipeline.yaml index 538c8d1c74..d7df3063e5 100644 --- a/dev-infrastructure/global-pipeline.yaml +++ b/dev-infrastructure/global-pipeline.yaml @@ -134,6 +134,8 @@ resourceGroups: configRef: ev2.assistedId.certificate.name dstsHost: configRef: ev2.assistedId.dstsHost + deploymentMode: + value: "Incremental" dependsOn: - resourceGroup: singleton step: infra @@ -150,6 +152,8 @@ resourceGroups: configRef: ev2.assistedId.certificate.name dstsHost: configRef: ev2.assistedId.dstsHost + deploymentMode: + value: "Incremental" dependsOn: - resourceGroup: singleton step: infra diff --git a/dev-infrastructure/mgmt-pipeline.yaml b/dev-infrastructure/mgmt-pipeline.yaml index 1b67a12693..1b1e1a3bc8 100644 --- a/dev-infrastructure/mgmt-pipeline.yaml +++ b/dev-infrastructure/mgmt-pipeline.yaml @@ -45,6 +45,16 @@ resourceGroups: parameters: configurations/output-region.tmpl.bicepparam deploymentLevel: ResourceGroup outputOnly: true +- name: auditLogs + resourceGroup: '{{ .auditLogsEventHub.rg }}' + subscription: '{{ .svc.subscription.key }}' + steps: + - name: output + action: ARM + template: templates/output-audit-logs-eventhub.bicep + parameters: configurations/output-audit-logs-eventhub.tmpl.bicepparam + deploymentLevel: ResourceGroup + outputOnly: true - name: kusto resourceGroup: '{{ .kusto.rg }}' subscription: '{{ .global.subscription.key }}' @@ -209,7 +219,7 @@ resourceGroups: name: maestroEventGridNamespaceId - name: auditLogsEventHubAuthRuleId input: - resourceGroup: kusto + resourceGroup: auditLogs step: output name: auditLogsEventHubAuthRuleId dependsOn: diff --git a/dev-infrastructure/modules/logs/eventhub/audit-logs-eventhub.bicep b/dev-infrastructure/modules/logs/eventhub/audit-logs-eventhub.bicep deleted file mode 100644 index 6b4546dc7a..0000000000 --- a/dev-infrastructure/modules/logs/eventhub/audit-logs-eventhub.bicep +++ /dev/null @@ -1,50 +0,0 @@ -@description('Event Hub namespace name for AKS audit logs') -param auditLogsEventHubNamespaceName string - -@description('Event Hub name for AKS audit logs') -param auditLogsEventHubName string - -@description('Consumer group name for Kusto data connection') -param auditLogsKustoConsumerGroupName string - -@description('Diagnostic settings authorization rule name') -param auditLogsDiagnosticSettingsRuleName string - -// Event Hub namespace for AKS audit logs -resource eventHubNamespace 'Microsoft.EventHub/namespaces@2024-01-01' = { - name: auditLogsEventHubNamespaceName - location: resourceGroup().location - sku: { - name: 'Standard' - tier: 'Standard' - capacity: 1 - } - properties: { - minimumTlsVersion: '1.2' - } - - // Authorization rule for diagnostic settings - resource diagnosticSettingsAuthRule 'authorizationRules@2024-01-01' = { - name: auditLogsDiagnosticSettingsRuleName - properties: { - rights: [ - 'Send' - ] - } - } - - // Event Hub for AKS audit logs - resource eventHub 'eventhubs@2024-01-01' = { - name: auditLogsEventHubName - properties: { - messageRetentionInDays: 7 - partitionCount: 2 - } - - // Consumer group for Kusto data connection - resource kustoConsumerGroup 'consumergroups@2024-01-01' = { - name: auditLogsKustoConsumerGroupName - } - } -} -output eventHubId string = eventHubNamespace::eventHub.id diff --git a/dev-infrastructure/modules/logs/kusto/main.bicep b/dev-infrastructure/modules/logs/kusto/main.bicep index 378288724f..053882015c 100644 --- a/dev-infrastructure/modules/logs/kusto/main.bicep +++ b/dev-infrastructure/modules/logs/kusto/main.bicep @@ -31,18 +31,6 @@ param autoScaleMax int @description('Toggle if autoscale should be enabled') param enableAutoScale bool -@description('Event Hub namespace name for AKS audit logs') -param auditLogsEventHubNamespaceName string - -@description('Event Hub name for AKS audit logs') -param auditLogsEventHubName string - -@description('Consumer group name for Kusto data connection') -param auditLogsKustoConsumerGroupName string - -@description('Diagnostic settings authorization rule name') -param auditLogsDiagnosticSettingsRuleName string - var db = { serviceLogs: serviceLogsDatabase hostedControlPlaneLogs: hostedControlPlaneLogsDatabase @@ -150,35 +138,7 @@ module databaseUserScripts 'database-users.bicep' = [ } ] -// 4. Event Hub for AKS audit logs -module auditLogsEventHub '../eventhub/audit-logs-eventhub.bicep' = { - name: 'audit-logs-eventhub-deployment' - params: { - auditLogsEventHubNamespaceName: auditLogsEventHubNamespaceName - auditLogsEventHubName: auditLogsEventHubName - auditLogsKustoConsumerGroupName: auditLogsKustoConsumerGroupName - auditLogsDiagnosticSettingsRuleName: auditLogsDiagnosticSettingsRuleName - } -} - -// 5. Data connections -// Kusto Event Hub data connection for AKS audit logs -resource kustoDataConnection 'Microsoft.Kusto/clusters/databases/dataConnections@2024-04-13' = { - name: '${kustoName}/${db.serviceLogs}/aks-audit-logs' - location: resourceGroup().location - kind: 'EventHub' - dependsOn: [serviceLogsTables] - properties: { - eventHubResourceId: auditLogsEventHub.outputs.eventHubId - consumerGroup: auditLogsKustoConsumerGroupName - tableName: 'rawAksEvents' - dataFormat: 'JSON' - compression: 'None' - mappingRuleName: 'rawAksEventsMapping' - } -} - -// 6. Remove the caller principal +// 5. Remove the caller principal // THIS MUST BE THE LAST SCRIPT TO RUN module removePermission 'script.bicep' = [ for (database, i) in databases: { diff --git a/dev-infrastructure/region-pipeline.yaml b/dev-infrastructure/region-pipeline.yaml index a1dc5ef38d..3d7a707711 100644 --- a/dev-infrastructure/region-pipeline.yaml +++ b/dev-infrastructure/region-pipeline.yaml @@ -129,6 +129,44 @@ resourceGroups: resourceGroup: global step: output name: globalMSIId +- name: kusto + resourceGroup: '{{ .kusto.rg }}' + subscription: '{{ .global.subscription.key }}' + steps: + - name: output + action: ARM + template: templates/kusto-lookup.bicep + parameters: configurations/kusto-lookup.tmpl.bicepparam + deploymentLevel: ResourceGroup + outputOnly: true + - name: kustoDataConnection + action: ARM + template: templates/audit-logs-data-connection.bicep + parameters: configurations/audit-logs-data-connection.tmpl.bicepparam + deploymentLevel: ResourceGroup + variables: + - name: auditLogsEventHubId + input: + resourceGroup: auditLogs + step: auditLogsEventHub + name: auditLogsEventHubId +- name: auditLogs + # In most regions this will be the same as the regional RG, + # but in dev, we want to deploy the event hub to the shared RG + resourceGroup: '{{ .auditLogsEventHub.rg }}' + subscription: '{{ .svc.subscription.key }}' + steps: + - name: auditLogsEventHub + action: ARM + template: templates/audit-logs-eventhub.bicep + parameters: configurations/audit-logs-eventhub.tmpl.bicepparam + deploymentLevel: ResourceGroup + variables: + - name: kustoPrincipalId + input: + resourceGroup: kusto + step: output + name: kustoPrincipalId - name: regional resourceGroup: '{{ .regionRG }}' subscription: '{{ .svc.subscription.key }}' diff --git a/dev-infrastructure/scripts/migrate-cosmosdb.sh b/dev-infrastructure/scripts/migrate-cosmosdb.sh deleted file mode 100755 index 9056c47abc..0000000000 --- a/dev-infrastructure/scripts/migrate-cosmosdb.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash -# This script migrates a CosmosDB SQL container from manual throughput to autoscaling. -set -o errexit -set -o nounset -set -o pipefail - -if [ -z "${RESOURCE_GROUP}" ] || [ -z "${COSMOSDB_ACCOUNT_NAME}" ] || [ -z "${DATABASE_NAME}" ] || [ -z "${CONTAINER_NAME}" ]; then - echo "Error: RESOURCE_GROUP, COSMOSDB_ACCOUNT_NAME, DATABASE_NAME, and CONTAINER_NAME must be set" - exit 1 -fi - -echo "Checking throughput configuration for container: ${CONTAINER_NAME}" -echo " Account: ${COSMOSDB_ACCOUNT_NAME}" -echo " Database: ${DATABASE_NAME}" -echo " Resource Group: ${RESOURCE_GROUP}" - -# First check if rg and cosmosdb account exists -if ! az group exists --name "${RESOURCE_GROUP}" --output json; then - echo "Resource group '${RESOURCE_GROUP}' does not exist (yet?). Exiting." - exit 0 -fi - -if ! az cosmosdb show --name "${COSMOSDB_ACCOUNT_NAME}" --resource-group "${RESOURCE_GROUP}" --output json; then - echo "CosmosDB account '${COSMOSDB_ACCOUNT_NAME}' does not exist (yet?). Exiting." - exit 0 -fi - -# Get current throughput configuration -THROUGHPUT_CONFIG=$(az cosmosdb sql container throughput show \ - --account-name "${COSMOSDB_ACCOUNT_NAME}" \ - --resource-group "${RESOURCE_GROUP}" \ - --database-name "${DATABASE_NAME}" \ - --name "${CONTAINER_NAME}" \ - --output json) - -# Check if autoscaling is enabled -AUTOSCALE_MAX_THROUGHPUT=$(echo "${THROUGHPUT_CONFIG}" | jq -r '.resource.autoscaleSettings.maxThroughput // empty') - -if [ -n "${AUTOSCALE_MAX_THROUGHPUT}" ] && [ "${AUTOSCALE_MAX_THROUGHPUT}" != "null" ]; then - echo "✓ Container '${CONTAINER_NAME}' already has autoscaling enabled (max throughput: ${AUTOSCALE_MAX_THROUGHPUT})" - exit 0 -fi - -# Migrate to autoscaling -az cosmosdb sql container throughput migrate \ - --account-name "${COSMOSDB_ACCOUNT_NAME}" \ - --resource-group "${RESOURCE_GROUP}" \ - --database-name "${DATABASE_NAME}" \ - --name "${CONTAINER_NAME}" \ - --throughput-type autoscale - -echo "✓ Successfully migrated container '${CONTAINER_NAME}' to autoscaling" - -# Verify the migration -echo "Verifying migration..." -NEW_THROUGHPUT_CONFIG=$(az cosmosdb sql container throughput show \ - --account-name "${COSMOSDB_ACCOUNT_NAME}" \ - --resource-group "${RESOURCE_GROUP}" \ - --database-name "${DATABASE_NAME}" \ - --name "${CONTAINER_NAME}" \ - --output json) - -NEW_AUTOSCALE_MAX_THROUGHPUT=$(echo "${NEW_THROUGHPUT_CONFIG}" | jq -r '.resource.autoscaleSettings.maxThroughput // empty') - -if [ -n "${NEW_AUTOSCALE_MAX_THROUGHPUT}" ] && [ "${NEW_AUTOSCALE_MAX_THROUGHPUT}" != "null" ]; then - echo "✓ Migration verified: autoscaling enabled with max throughput: ${NEW_AUTOSCALE_MAX_THROUGHPUT}" -else - echo "Warning: Migration completed but autoscaling may not be fully enabled yet" - echo "Current configuration:" - echo "${NEW_THROUGHPUT_CONFIG}" | jq . -fi diff --git a/dev-infrastructure/svc-pipeline.yaml b/dev-infrastructure/svc-pipeline.yaml index ed7de22300..abd4d1963a 100644 --- a/dev-infrastructure/svc-pipeline.yaml +++ b/dev-infrastructure/svc-pipeline.yaml @@ -44,6 +44,16 @@ resourceGroups: parameters: configurations/output-region.tmpl.bicepparam deploymentLevel: ResourceGroup outputOnly: true +- name: auditLogs + resourceGroup: '{{ .auditLogsEventHub.rg }}' + subscription: '{{ .svc.subscription.key }}' + steps: + - name: output + action: ARM + template: templates/output-audit-logs-eventhub.bicep + parameters: configurations/output-audit-logs-eventhub.tmpl.bicepparam + deploymentLevel: ResourceGroup + outputOnly: true - name: kusto resourceGroup: '{{ .kusto.rg }}' subscription: '{{ .global.subscription.key }}' @@ -110,60 +120,6 @@ resourceGroups: name: svcKeyVaultUrl issuer: value: OneCertV2-PublicCA - - name: migrate-cosmosdb-billing - action: Shell - command: ./migrate-cosmosdb.sh - workingDir: ./scripts - variables: - - name: RESOURCE_GROUP - configRef: regionRG - - name: COSMOSDB_ACCOUNT_NAME - configRef: frontend.cosmosDB.name - - name: DATABASE_NAME - configRef: frontend.cosmosDB.name - - name: CONTAINER_NAME - value: Billing - shellIdentity: - input: - resourceGroup: global - step: output - name: globalMSIId - - name: migrate-cosmosdb-locks - action: Shell - command: ./migrate-cosmosdb.sh - workingDir: ./scripts - variables: - - name: RESOURCE_GROUP - configRef: regionRG - - name: COSMOSDB_ACCOUNT_NAME - configRef: frontend.cosmosDB.name - - name: DATABASE_NAME - configRef: frontend.cosmosDB.name - - name: CONTAINER_NAME - value: Locks - shellIdentity: - input: - resourceGroup: global - step: output - name: globalMSIId - - name: migrate-cosmosdb-resources - action: Shell - command: ./migrate-cosmosdb.sh - workingDir: ./scripts - variables: - - name: RESOURCE_GROUP - configRef: regionRG - - name: COSMOSDB_ACCOUNT_NAME - configRef: frontend.cosmosDB.name - - name: DATABASE_NAME - configRef: frontend.cosmosDB.name - - name: CONTAINER_NAME - value: Resources - shellIdentity: - input: - resourceGroup: global - step: output - name: globalMSIId # Create SVC cluster - name: cluster action: ARM @@ -198,7 +154,7 @@ resourceGroups: name: azureFrontDoorResourceId - name: auditLogsEventHubAuthRuleId input: - resourceGroup: kusto + resourceGroup: auditLogs step: output name: auditLogsEventHubAuthRuleId dependsOn: diff --git a/dev-infrastructure/templates/audit-logs-data-connection.bicep b/dev-infrastructure/templates/audit-logs-data-connection.bicep new file mode 100644 index 0000000000..e2de55d84a --- /dev/null +++ b/dev-infrastructure/templates/audit-logs-data-connection.bicep @@ -0,0 +1,35 @@ +@description('Name of the existing Kusto cluster where the data connection will be created') +param kustoName string + +@description('Consumer group name for Kusto data connection') +param auditLogsKustoConsumerGroupName string + +@description('ID of the Event Hub to connect to') +param auditLogsEventHubId string + +@description('Target Kusto database name') +param databaseName string + +@description('Kusto data connection resource name') +param kustoDataConnectionName string + +@description('Whether the arobit Kusto cluster is enabled in this region') +param kustoEnabled bool + +@description('When true, create resources managed by this deployment') +param manageInstance bool = true + +// Kusto Event Hub data connection for AKS audit logs +resource kustoDataConnection 'Microsoft.Kusto/clusters/databases/dataConnections@2024-04-13' = if (kustoEnabled && manageInstance) { + name: '${kustoName}/${databaseName}/${kustoDataConnectionName}' + location: resourceGroup().location + kind: 'EventHub' + properties: { + eventHubResourceId: auditLogsEventHubId + consumerGroup: auditLogsKustoConsumerGroupName + tableName: 'rawAksEvents' + dataFormat: 'JSON' + compression: 'None' + mappingRuleName: 'rawAksEventsMapping' + } +} diff --git a/dev-infrastructure/templates/audit-logs-eventhub.bicep b/dev-infrastructure/templates/audit-logs-eventhub.bicep new file mode 100644 index 0000000000..d9adb9ad6d --- /dev/null +++ b/dev-infrastructure/templates/audit-logs-eventhub.bicep @@ -0,0 +1,79 @@ +@description('Event Hub namespace name for AKS audit logs') +param auditLogsEventHubNamespaceName string + +@description('Event Hub name for AKS audit logs') +param auditLogsEventHubName string + +@description('Consumer group name for Kusto data connection') +param auditLogsKustoConsumerGroupName string + +@description('Diagnostic settings authorization rule name') +param auditLogsDiagnosticSettingsRuleName string + +@description('Principal ID of the Kusto cluster managed identity') +param kustoPrincipalId string + +@description('When true, deploy managed audit logs Event Hub resources') +param manageInstance bool = true + +// Event Hub namespace for AKS audit logs +resource eventHubNamespace 'Microsoft.EventHub/namespaces@2024-01-01' = if (manageInstance) { + name: auditLogsEventHubNamespaceName + location: resourceGroup().location + sku: { + name: 'Premium' + tier: 'Premium' + capacity: 1 + } + properties: { + minimumTlsVersion: '1.2' + publicNetworkAccess: 'Disabled' + } + + resource networkRuleSet 'networkRuleSets@2024-01-01' = { + name: 'default' + properties: { + defaultAction: 'Deny' + publicNetworkAccess: 'Disabled' + trustedServiceAccessEnabled: true + } + } + + // Authorization rule for diagnostic settings + resource diagnosticSettingsAuthRule 'authorizationRules@2024-01-01' = { + name: auditLogsDiagnosticSettingsRuleName + properties: { + rights: [ + 'Send' + ] + } + } + + // Event Hub for svc AKS audit logs + resource eventHub 'eventhubs@2024-01-01' = { + name: auditLogsEventHubName + properties: { + messageRetentionInDays: 7 + partitionCount: 2 + } + + // Consumer group for svc Kusto data connection + resource kustoConsumerGroup 'consumergroups@2024-01-01' = { + name: auditLogsKustoConsumerGroupName + } + } +} + +var eventHubDataReceiverRole = 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde' +resource eventHubDataReceiverRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (manageInstance && kustoPrincipalId != '') { + scope: eventHubNamespace::eventHub + name: guid(eventHubNamespace::eventHub.id, kustoPrincipalId, eventHubDataReceiverRole) + properties: { + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', eventHubDataReceiverRole) + principalId: kustoPrincipalId + principalType: 'ServicePrincipal' + } +} + +output auditLogsEventHubId string = manageInstance ? eventHubNamespace::eventHub.id : '' +output auditLogsEventHubAuthRuleId string = manageInstance ? eventHubNamespace::diagnosticSettingsAuthRule.id : '' diff --git a/dev-infrastructure/templates/kusto-lookup.bicep b/dev-infrastructure/templates/kusto-lookup.bicep index 1d5b39eb0e..b94cc6926a 100644 --- a/dev-infrastructure/templates/kusto-lookup.bicep +++ b/dev-infrastructure/templates/kusto-lookup.bicep @@ -4,35 +4,12 @@ param kustoName string @description('Toggle if instance is expected to exist') param kustoEnabled bool -@description('Event Hub name for AKS audit logs') -param auditLogsEventHubName string - -@description('Event Hub namespace for AKS audit logs') -param auditLogsEventHubNamespaceName string - -@description('Name of the event hub authorization rule for AKS audit logs') -param auditLogsEventHubAuthRuleName string - resource kusto 'Microsoft.Kusto/clusters@2024-04-13' existing = if (kustoEnabled) { name: kustoName } -resource auditLogsEventHubNamespace 'Microsoft.EventHub/namespaces@2024-01-01' existing = if (kustoEnabled) { - name: auditLogsEventHubNamespaceName - - resource eventHub 'eventhubs@2024-01-01' existing = { - name: auditLogsEventHubName - } - - resource diagnosticSettingsAuthRule 'authorizationRules@2024-01-01' existing = { - name: auditLogsEventHubAuthRuleName - } -} - output kustoResourceId string = kustoEnabled ? kusto.id : '' output kustoUri string = kustoEnabled ? kusto.properties.uri : '' output kustoDataIngestionUri string = kustoEnabled ? kusto.properties.dataIngestionUri : '' -output auditLogsEventHubAuthRuleId string = kustoEnabled - ? auditLogsEventHubNamespace::diagnosticSettingsAuthRule.id - : '' +output kustoPrincipalId string = kustoEnabled ? kusto.identity.principalId : '' output kustoRegion string = kustoEnabled ? kusto.location : '' diff --git a/dev-infrastructure/templates/kusto.bicep b/dev-infrastructure/templates/kusto.bicep index 86c6568e3a..fb8e3ce4c7 100644 --- a/dev-infrastructure/templates/kusto.bicep +++ b/dev-infrastructure/templates/kusto.bicep @@ -34,18 +34,6 @@ param autoScaleMax int @description('Toggle if autoscale should be enabled') param enableAutoScale bool -@description('Event Hub namespace name for AKS audit logs') -param auditLogsEventHubNamespaceName string - -@description('Event Hub name for AKS audit logs') -param auditLogsEventHubName string - -@description('Consumer group name for Kusto data connection') -param auditLogsKustoConsumerGroupName string - -@description('Diagnostic settings authorization rule name') -param auditLogsDiagnosticSettingsRuleName string - module kusto '../modules/logs/kusto/main.bicep' = if (manageInstance) { name: 'kusto-${location}' params: { @@ -60,9 +48,5 @@ module kusto '../modules/logs/kusto/main.bicep' = if (manageInstance) { autoScaleMin: autoScaleMin autoScaleMax: autoScaleMax enableAutoScale: enableAutoScale - auditLogsEventHubNamespaceName: auditLogsEventHubNamespaceName - auditLogsEventHubName: auditLogsEventHubName - auditLogsKustoConsumerGroupName: auditLogsKustoConsumerGroupName - auditLogsDiagnosticSettingsRuleName: auditLogsDiagnosticSettingsRuleName } } diff --git a/dev-infrastructure/templates/mgmt-cluster.bicep b/dev-infrastructure/templates/mgmt-cluster.bicep index e0be376090..f434a89228 100644 --- a/dev-infrastructure/templates/mgmt-cluster.bicep +++ b/dev-infrastructure/templates/mgmt-cluster.bicep @@ -554,15 +554,15 @@ module hcpBackupsRbac '../modules/hcp-backups/storage-rbac.bicep' = { // // A K S D I A G N O S T I C S E T T I N G S // -// jboll, needs to disable, cause stage deployment fails -// module diagnosticSetting '../modules/aks/diagnostic-setting.bicep' = if (auditLogsEventHubAuthRuleId != '') { -// name: 'aks-diagnostic-setting' -// dependsOn: [ -// mgmtCluster -// ] -// params: { -// aksClusterName: aksClusterName -// auditLogsEventHubName: auditLogsEventHubName -// auditLogsEventHubAuthRuleId: auditLogsEventHubAuthRuleId -// } -// } + +module diagnosticSetting '../modules/aks/diagnostic-setting.bicep' = if (auditLogsEventHubAuthRuleId != '') { + name: 'aks-diagnostic-setting' + dependsOn: [ + mgmtCluster + ] + params: { + aksClusterName: aksClusterName + auditLogsEventHubName: auditLogsEventHubName + auditLogsEventHubAuthRuleId: auditLogsEventHubAuthRuleId + } +} diff --git a/dev-infrastructure/templates/mock-identities.bicep b/dev-infrastructure/templates/mock-identities.bicep index ee7f243ec4..83594c1e08 100644 --- a/dev-infrastructure/templates/mock-identities.bicep +++ b/dev-infrastructure/templates/mock-identities.bicep @@ -133,22 +133,29 @@ resource msiCustomRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' = { permissions: [ { actions: [ - 'Microsoft.Network/virtualNetworks/read' - 'Microsoft.Network/virtualNetworks/join/action' - 'Microsoft.Network/virtualNetworks/subnets/read' - 'Microsoft.Network/virtualNetworks/subnets/write' - 'Microsoft.Network/virtualNetworks/subnets/join/action' - 'Microsoft.Network/routeTables/read' - 'Microsoft.Network/routeTables/join/action' - 'Microsoft.Network/natGateways/join/action' - 'Microsoft.Network/natGateways/read' - 'Microsoft.Network/networkSecurityGroups/read' - 'Microsoft.Network/networkSecurityGroups/write' - 'Microsoft.Network/networkSecurityGroups/join/action' - 'Microsoft.ManagedIdentity/userAssignedIdentities/read' + 'Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/delete' 'Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/read' 'Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/write' - 'Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/delete' + 'Microsoft.ManagedIdentity/userAssignedIdentities/read' + 'Microsoft.Network/loadBalancers/backendAddressPools/read' // read backend address pools of LB to check if the backend address pool already exists + 'Microsoft.Network/loadBalancers/backendAddressPools/write' // write backend address pools to LB + 'Microsoft.Network/loadBalancers/read' // to check if LB exists or not before writing to it + 'Microsoft.Network/loadBalancers/write' // create LB if it doesn't exist + 'Microsoft.Network/natGateways/join/action' // subnet/write needs /join/action on nat gateway if present in request + 'Microsoft.Network/natGateways/read' + 'Microsoft.Network/networkSecurityGroups/join/action' // subnet/write needs /join/action on NSG if present in request + 'Microsoft.Network/networkSecurityGroups/read' // validate NSG + 'Microsoft.Network/networkSecurityGroups/write' + 'Microsoft.Network/privateDnsZones/virtualNetworkLinks/read' // read existing links between private DNS zone and virtual network + 'Microsoft.Network/privateDnsZones/virtualNetworkLinks/write' // attach private DNS zone to virtual network + 'Microsoft.Network/routeTables/join/action' // subnet/write needs /join/action on nat route table if present in request + 'Microsoft.Network/routeTables/read' + 'Microsoft.Network/virtualNetworks/join/action' // attach private DNS zone + 'Microsoft.Network/virtualNetworks/joinLoadBalancer/action' // add private IP addresses to LB backend + 'Microsoft.Network/virtualNetworks/read' // validate CIDR & existance + 'Microsoft.Network/virtualNetworks/subnets/join/action' // create private load balancer and join to subnet + 'Microsoft.Network/virtualNetworks/subnets/read' // validate CIDR & existance + 'Microsoft.Network/virtualNetworks/subnets/write' // attach the NSG to subnet ] notActions: [] } diff --git a/dev-infrastructure/templates/output-audit-logs-eventhub.bicep b/dev-infrastructure/templates/output-audit-logs-eventhub.bicep new file mode 100644 index 0000000000..9ea2bca118 --- /dev/null +++ b/dev-infrastructure/templates/output-audit-logs-eventhub.bicep @@ -0,0 +1,20 @@ +@description('Toggle if instance is expected to exist') +param kustoEnabled bool + +@description('Event Hub namespace for AKS audit logs') +param auditLogsEventHubNamespaceName string + +@description('Name of the event hub authorization rule for AKS audit logs') +param auditLogsEventHubAuthRuleName string + +resource auditLogsEventHubNamespace 'Microsoft.EventHub/namespaces@2024-01-01' existing = if (kustoEnabled) { + name: auditLogsEventHubNamespaceName + + resource diagnosticSettingsAuthRule 'authorizationRules@2024-01-01' existing = { + name: auditLogsEventHubAuthRuleName + } +} + +output auditLogsEventHubAuthRuleId string = kustoEnabled + ? auditLogsEventHubNamespace::diagnosticSettingsAuthRule.id + : '' diff --git a/dev-infrastructure/templates/svc-cluster.bicep b/dev-infrastructure/templates/svc-cluster.bicep index 7c77313b58..bd898804be 100644 --- a/dev-infrastructure/templates/svc-cluster.bicep +++ b/dev-infrastructure/templates/svc-cluster.bicep @@ -1192,15 +1192,14 @@ module svcKVNSPProfile '../modules/network/nsp-profile.bicep' = if (serviceKeyVa // A K S D I A G N O S T I C S E T T I N G S // -// jboll, needs to disable, cause stage deployment fails -// module diagnosticSetting '../modules/aks/diagnostic-setting.bicep' = if (auditLogsEventHubAuthRuleId != '') { -// name: 'aks-diagnostic-setting' -// dependsOn: [ -// svcCluster -// ] -// params: { -// aksClusterName: aksClusterName -// auditLogsEventHubName: auditLogsEventHubName -// auditLogsEventHubAuthRuleId: auditLogsEventHubAuthRuleId -// } -// } +module diagnosticSetting '../modules/aks/diagnostic-setting.bicep' = if (auditLogsEventHubAuthRuleId != '') { + name: 'aks-diagnostic-setting' + dependsOn: [ + svcCluster + ] + params: { + aksClusterName: aksClusterName + auditLogsEventHubName: auditLogsEventHubName + auditLogsEventHubAuthRuleId: auditLogsEventHubAuthRuleId + } +} diff --git a/dev-infrastructure/zz_fixture_TestHelmTemplate_dev_westus3_mgmt_1_arobit.yaml b/dev-infrastructure/zz_fixture_TestHelmTemplate_dev_westus3_mgmt_1_arobit.yaml index 565299979c..1bcd17cfde 100644 --- a/dev-infrastructure/zz_fixture_TestHelmTemplate_dev_westus3_mgmt_1_arobit.yaml +++ b/dev-infrastructure/zz_fixture_TestHelmTemplate_dev_westus3_mgmt_1_arobit.yaml @@ -50,17 +50,6 @@ data: HC_Retry_Failure_Count 5 HC_Period 60 parsers_custom.conf: | - # Previously, docker parser would parse the container log as record["log"]. - # With the default cri parser, the container log will be parsed as record["message"]. - # For backward compat with docker implementation, use the following parser. - [PARSER] - Name cri-o - Format regex - Regex ^(?