Skip to content

Commit

Permalink
maestro support onecert client certificates (#1298)
Browse files Browse the repository at this point in the history
* support onecert signed  certificates for maestro eventgrid auth

https://issues.redhat.com/browse/ARO-7825

Signed-off-by: Gerd Oberlechner <goberlec@redhat.com>

* Update dev-infrastructure/templates/mgmt-cluster.bicep

Co-authored-by: Jean-Francois Chevrette <jchevret@redhat.com>

* Update dev-infrastructure/templates/svc-cluster.bicep

Co-authored-by: Jean-Francois Chevrette <jchevret@redhat.com>

---------

Signed-off-by: Gerd Oberlechner <goberlec@redhat.com>
Co-authored-by: Jean-Francois Chevrette <jchevret@redhat.com>
  • Loading branch information
geoberle and jfchevrette authored Feb 11, 2025
1 parent 8eabdcc commit 92d2f37
Show file tree
Hide file tree
Showing 20 changed files with 158 additions and 35 deletions.
2 changes: 1 addition & 1 deletion config/config.msft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ defaults:
name: arohcp-maestro-{{ .ctx.regionShort }}
maxClientSessionsPerAuthName: 4
private: false
certDomain: 'selfsigned.maestro.keyvault.azure.com'
certIssuer: OneCertV2-PrivateCA
postgres:
name: arohcp-maestro-{{ .ctx.regionShort }}
serverVersion: '15'
Expand Down
23 changes: 15 additions & 8 deletions config/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@
"keyColonValueCSV": {
"type": "string",
"pattern": "^$|^[\\w-\\.]+:[\\w\\/-]+(,[\\w-\\.]+:[\\w\\/-]+)*$"
},
"certificateIssuer": {
"type": "string",
"enum": [
"Self",
"OneCertV2-PublicCA",
"OneCertV2-PrivateCA"
]
}
},
"properties": {
Expand Down Expand Up @@ -367,12 +375,7 @@
"type": "string"
},
"issuer": {
"type": "string",
"enum": [
"Self",
"OneCertV2-PublicCA",
"OneCertV2-PrivateCA"
]
"$ref": "#/definitions/certificateIssuer"
}
},
"additionalProperties": false,
Expand Down Expand Up @@ -550,7 +553,11 @@
"type": "object",
"properties": {
"certDomain": {
"type": "string"
"type": "string",
"description": "Optional SAN base domain for Maestro Eventgrid certificates. If missing, defaults to maestro.${dns.regionalSubdomain}.${dns.svcParentZoneName}"
},
"certIssuer": {
"$ref": "#/definitions/certificateIssuer"
},
"consumerName": {
"type": "string"
Expand Down Expand Up @@ -668,7 +675,7 @@
},
"additionalProperties": false,
"required": [
"certDomain",
"certIssuer",
"consumerName",
"server",
"eventGrid",
Expand Down
3 changes: 2 additions & 1 deletion config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ defaults:
name: arohcp-maestro-{{ .ctx.regionShort }}
maxClientSessionsPerAuthName: 6
private: false
certDomain: 'selfsigned.maestro.keyvault.azure.com'
certDomain: selfsigned.maestro.keyvault.azure.com
certIssuer: Self
postgres:
name: arohcp-maestro-{{ .ctx.regionShort }}
serverVersion: '15'
Expand Down
1 change: 1 addition & 0 deletions config/public-cloud-cs-pr.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
"imageTag": "1.25"
},
"certDomain": "selfsigned.maestro.keyvault.azure.com",
"certIssuer": "Self",
"consumerName": "hcp-underlay-cspr-mgmt-1",
"eventGrid": {
"maxClientSessionsPerAuthName": 6,
Expand Down
1 change: 1 addition & 0 deletions config/public-cloud-dev.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
"imageTag": "1.25"
},
"certDomain": "selfsigned.maestro.keyvault.azure.com",
"certIssuer": "Self",
"consumerName": "hcp-underlay-dev-mgmt-1",
"eventGrid": {
"maxClientSessionsPerAuthName": 6,
Expand Down
2 changes: 1 addition & 1 deletion config/public-cloud-msft-int.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
"imageBase": "mcr.microsoft.com/azurelinux/base/nginx",
"imageTag": "1.25"
},
"certDomain": "selfsigned.maestro.keyvault.azure.com",
"certIssuer": "OneCertV2-PrivateCA",
"consumerName": "hcp-underlay-int-mgmt-1",
"eventGrid": {
"maxClientSessionsPerAuthName": 4,
Expand Down
1 change: 1 addition & 0 deletions config/public-cloud-personal-dev.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
"imageTag": "1.25"
},
"certDomain": "selfsigned.maestro.keyvault.azure.com",
"certIssuer": "Self",
"consumerName": "hcp-underlay-usw3tst-mgmt-1",
"eventGrid": {
"maxClientSessionsPerAuthName": 6,
Expand Down
31 changes: 31 additions & 0 deletions dev-infrastructure/ca/AMEROOT_ameroot.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFVjCCAz6gAwIBAgIQJdrLVcnGd4FAnlaUgt5N/jANBgkqhkiG9w0BAQsFADA8
MRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRAwDgYD
VQQDEwdhbWVyb290MB4XDTE2MDUyNDIyNTI1NFoXDTI2MDUyNDIyNTcwM1owPDET
MBEGCgmSJomT8ixkARkWA0dCTDETMBEGCgmSJomT8ixkARkWA0FNRTEQMA4GA1UE
AxMHYW1lcm9vdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALv4uChY
oVuO+bxBOcn8v4FajoGkxo0YgVwEqEPDVPI6vzmnEqHVhQ1GMVeDyiRrgQT1vCk1
HMMzo9LlWowPrzbXOwjOTFbXc36+UU41yNN2GeNa49RXbAkfbzKE/SYLfbqOD0dN
ZLwvOhgIb25oA1eAxW/DI/hvJLLKh2SscvkIyd3o2BUeFm7NtyYG/buCKJh8lOq8
0iBwRoEoInb0vhorHaswSMmqY1g+AJndY/M7uGUqkhDGBhLu53bU9wbUPHsEI+wa
q6WypCijZYT+C4BS5GJrEPZ2O92pztd+ULqhzNRoPj5RuElUww7+z5RnbCaupyBY
OmmJMH30EiRSq8dK/irixXXwJraSywR5kyfmAkv6GYWlRlxFUiK3/co47JLA3TDK
N0wfutbpqxdZQYyGfO2nZrr5JbKfSU0sMtOZDkK6hlafV++hfkVSvFfNHE5B5uN1
MK6agl1dzi28HfJT9aO7cmjGxl1SJ5qoCvcwZNQ2SPHFdrslcwXEFOMDaEzVOA3V
7j3+6lrT8sHXg0sErkcd8lrBImfzhLxM/Wh8CgOUNeUu3flUoxmFv3el+QWalSNy
2SXs2NgWuYE5Iog7CHD/xCnoEnZwwjqLkrro4hYWE4Xj3VlA2Eq+VxqJOgdyFl3m
ckSZ08OcwLeprY4+2GEvCXNGNdXUmNNgk2PvAgMBAAGjVDBSMAsGA1UdDwQEAwIB
hjASBgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBQpXlFeZK40ueusnA2njHUB
0QkLKDAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0BAQsFAAOCAgEAcznFDnJx
sXaazFY1DuIPvUaiWS7ELxAVXMGZ7ROjLrDq1FNYVewL4emDqyEIEMFncec8rqyk
VBvLQA5YqMCxQWJpL0SlgRSknzLh9ZVcQw1TshC49/XV2N/CLOuyInEQwS//46so
T20Cf8UGUiOK472LZlvM4KchyDR3FTNtmMg0B/LKVjevpX9sk5MiyjjLUj3jtPIP
7jpsfZDd/BNsg/89kpsIF5O64I7iYFj3MHu9o4UJcEX0hRt7OzUxqa9THTssvzE5
VkWo8Rtou2T5TobKV6Rr5Ob9wchLXqVtCyZF16voEKheBnalhGUvErI/6VtBwLb7
13C0JkKLBNMen+HClNliicVIaubnpY2g+AqxOgKBHiZnzq2HhE1qqEUf4VfqahNU
iaXtbtyo54f2dCf9UL9uG9dllN3nxBE/Y/aWF6E1M8Bslj1aYAtfUQ/xlhEXCly6
zohw697i3XFUt76RwvfW8quvqdH9Mx0PBpYo4wJJRwAecSJQNy6wIJhAuDgOemXJ
YViBi/bDnhPcFEVQxsypQSw91BUw7Mxh+W59H5MC25SAIw9fLMT9LRqSYpPyasNp
4nACjR+bv/6cI+ICOrGmD2mrk2c4dNnYpDx96FfX/Y158RV0wotqIglACk6m1qyo
yTra6P0Kvo6xz4KaVm8F7VDzUP+heAAhPAs=
-----END CERTIFICATE-----
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ param aksClusterOutboundIPAddressIPTags = '{{ .mgmt.aks.clusterOutboundIPAddress
param maestroConsumerName = '{{ .maestro.consumerName }}'
param maestroEventGridNamespaceId = '__maestroEventGridNamespaceId__'
param maestroCertDomain = '{{ .maestro.certDomain }}'
param maestroCertIssuer = '{{ .maestro.certIssuer }}'
param regionalSvcDNSZoneName = '{{ .dns.regionalSubdomain }}.{{ .dns.svcParentZoneName }}'


// ACR
param ocpAcrResourceId = '__ocpAcrResourceId__'
Expand Down
1 change: 1 addition & 0 deletions dev-infrastructure/configurations/region.tmpl.bicepparam
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ param regionalDNSSubdomain = '{{ .dns.regionalSubdomain }}'
param maestroEventGridNamespacesName = '{{ .maestro.eventGrid.name }}'
param maestroEventGridMaxClientSessionsPerAuthName = {{ .maestro.eventGrid.maxClientSessionsPerAuthName }}
param maestroEventGridPrivate = {{ .maestro.eventGrid.private }}
param maestroCertificateIssuer = '{{ .maestro.certIssuer }}'
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ param maestroNamespace = '{{ .maestro.server.k8s.namespace }}'
param maestroServiceAccountName = '{{ .maestro.server.k8s.serviceAccountName }}'
param maestroEventGridNamespacesName = '{{ .maestro.eventGrid.name }}'
param maestroServerMqttClientName = '{{ .maestro.server.mqttClientName }}'
param maestroCertDomain = '{{ .maestro.certDomain}}'
param maestroCertDomain = '{{ .maestro.certDomain }}'
param maestroCertIssuer = '{{ .maestro.certIssuer }}'
param maestroPostgresServerName = '{{ .maestro.postgres.name }}'
param maestroPostgresServerMinTLSVersion = '{{ .maestro.postgres.minTLSVersion }}'
param maestroPostgresServerVersion = '{{ .maestro.postgres.serverVersion }}'
Expand Down
12 changes: 12 additions & 0 deletions dev-infrastructure/mgmt-pipeline.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,17 @@ resourceGroups:
provider:
name: provider
value: OneCertV2-PrivateCA
- name: mgmt-oncert-public-kv-issuer
action: SetCertificateIssuer
dependsOn:
- mgmt-infra
vaultBaseUrl:
input:
name: mgmtKeyVaultUrl
step: mgmt-infra
provider:
name: provider
value: OneCertV2-PublicCA
# Build the MC
- name: mgmt-cluster
action: ARM
Expand All @@ -93,6 +104,7 @@ resourceGroups:
dependsOn:
- cx-oncert-public-kv-issuer
- mgmt-oncert-private-kv-issuer
- mgmt-oncert-public-kv-issuer
- global-output
- region-output
- name: {{ .mgmt.rg }}
Expand Down
4 changes: 2 additions & 2 deletions dev-infrastructure/modules/maestro/maestro-access-cert.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ param clientName string
param keyVaultCertificateName string

@description('The issuer of the certificate.')
param certificateIssuer string = 'Self'
param certificateIssuer string

@description('Grant this managed identity access to the certificate in Key Vault.')
param certificateAccessManagedIdentityPrincipalId string
Expand All @@ -41,7 +41,7 @@ module clientCertificate '../keyvault/key-vault-cert.bicep' = {
name: '${clientName}-client-cert'
params: {
keyVaultName: keyVaultName
subjectName: 'CN=${clientName}'
subjectName: 'CN=${clientAuthenticationName}'
certName: keyVaultCertificateName
keyVaultManagedIdentityId: kvCertOfficerManagedIdentityResourceId
dnsNames: [
Expand Down
3 changes: 3 additions & 0 deletions dev-infrastructure/modules/maestro/maestro-consumer.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ param maestroEventGridNamespaceId string
param certKeyVaultName string
param keyVaultOfficerManagedIdentityName string
param maestroCertificateDomain string
param maestroCertificateIssuer string

module eventGridClientCert 'maestro-access-cert.bicep' = {
name: '${deployment().name}-eg-crt-${uniqueString(maestroConsumerName)}'
params: {
keyVaultName: certKeyVaultName
kvCertOfficerManagedIdentityResourceId: keyVaultOfficerManagedIdentityName
certDomain: maestroCertificateDomain
certificateIssuer: maestroCertificateIssuer
clientName: maestroConsumerName
keyVaultCertificateName: maestroConsumerName
certificateAccessManagedIdentityPrincipalId: maestroAgentManagedIdentityPrincipalId
Expand All @@ -40,5 +42,6 @@ module evengGridAccess 'maestro-eventgrid-access.bicep' = {
clientRole: 'consumer'
certificateThumbprint: eventGridClientCert.outputs.certificateThumbprint
certificateSAN: eventGridClientCert.outputs.certificateSAN
certificateIssuer: maestroCertificateIssuer
}
}
41 changes: 33 additions & 8 deletions dev-infrastructure/modules/maestro/maestro-eventgrid-access.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ param clientName string
param clientRole string

@description('The issuer of the certificate.')
param certificateIssuer string = 'Self'
param certificateIssuer string

@description('The thumbprint of the certificate that should get access. Dont use in production')
param certificateThumbprint string
Expand All @@ -37,11 +37,15 @@ resource eventGridNamespace 'Microsoft.EventGrid/namespaces@2023-12-15-preview'
name: eventGridNamespaceName
}

// D O N ' T U S E T H U M B P R I N T I N P R O D U C T I O N
// eventgrid MQTT client trusting the certificate by thumbprint if
// Key Vault self-signed certificates are used. trusting self-signed certificates
// as CAs is not supported in EventGrid
resource mqttClient 'Microsoft.EventGrid/namespaces/clients@2023-12-15-preview' = if (certificateIssuer == 'Self') {
//
// T H U M B P R I N T V A L I D A T I O N S C H E M E
// D O N ' T U S E I N P R O D U C T I O N
//
// With this scheme, eventgrid MQTT trusts client certificates by thumbprint. For self-signed
// certificates, this is the only secure option. But it comes at the price of updating the
// thumbprints in the eventgrid namespace every time a new certificate is issued.
//
resource selfSignedCertMqttClient 'Microsoft.EventGrid/namespaces/clients@2023-12-15-preview' = if (certificateIssuer == 'Self') {
name: clientName
parent: eventGridNamespace
properties: {
Expand All @@ -60,5 +64,26 @@ resource mqttClient 'Microsoft.EventGrid/namespaces/clients@2023-12-15-preview'
}
}

// TODO - implement issuer CA registration with EventGrid + register the mqtt client with
// the DnsMatchesAuthenticationName authentication validation scheme
//
// D N S V A L I D A T I O N S C H E M E
//
// This is the scheme we want to use for production. It allows us to trust CA signed
// certificates by validating the certificate SAN against the authentication name.
// This way certificates can be rotated without updating the eventgrid MQTT client
// configuration.
//
resource certMqttClient 'Microsoft.EventGrid/namespaces/clients@2023-12-15-preview' = if (certificateIssuer != 'Self') {
name: clientName
parent: eventGridNamespace
properties: {
authenticationName: certificateSAN
attributes: {
role: clientRole
consumer_name: clientName
}
clientCertificateAuthentication: {
validationScheme: 'DnsMatchesAuthenticationName'
}
state: 'Enabled'
}
}
Loading

0 comments on commit 92d2f37

Please sign in to comment.