44# --------------------------------------------------------------------------------------------
55
66import ast
7+ import base64
78import threading
89import time
910import re
@@ -6736,7 +6737,7 @@ def _get_log(url, headers, log_file=None):
67366737def upload_ssl_cert(cmd, resource_group_name,
67376738 name, certificate_password,
67386739 certificate_file, slot=None,
6739- certificate_name=None):
6740+ certificate_name=None, load_to_code=None ):
67406741 Certificate = cmd.get_models('Certificate')
67416742 client = web_client_factory(cmd.cli_ctx)
67426743 webapp = _generic_site_operation(cmd.cli_ctx, resource_group_name, name, 'get', slot)
@@ -6757,6 +6758,32 @@ def upload_ssl_cert(cmd, resource_group_name,
67576758 webapp.location, resource_group_name)
67586759 cert = Certificate(password=certificate_password, pfx_blob=cert_contents,
67596760 location=webapp.location, server_farm_id=get_site_server_farm_id(webapp))
6761+
6762+ # Check if this is a Flex Consumption function app
6763+ is_flex = is_flex_functionapp(cmd.cli_ctx, resource_group_name, name)
6764+
6765+ # For Flex Consumption apps, use the site-scoped certificates endpoint (slots not supported)
6766+ if is_flex:
6767+ # Build certificate envelope as dict to include loadCertificateToWebsitesSettings
6768+ # (not in SDK model yet)
6769+ cert_envelope = {
6770+ "location": webapp.location,
6771+ "properties": {
6772+ "password": certificate_password,
6773+ "pfxBlob": base64.b64encode(cert_contents).decode('utf-8'),
6774+ "serverFarmId": get_site_server_farm_id(webapp)
6775+ }
6776+ }
6777+ if load_to_code is not None:
6778+ cert_envelope["properties"]["loadCertificateToWebsitesSettings"] = {
6779+ "loadToWebsite": load_to_code
6780+ }
6781+ return client.site_certificates.create_or_update(
6782+ resource_group_name=resource_group_name,
6783+ name=name,
6784+ certificate_name=cert_name,
6785+ certificate_envelope=cert_envelope
6786+ )
67606787 return client.certificates.create_or_update(resource_group_name, cert_name, cert)
67616788
67626789
@@ -6774,26 +6801,52 @@ def _get_cert(certificate_password, certificate_file):
67746801 return thumbprint
67756802
67766803
6777- def list_ssl_certs(cmd, resource_group_name):
6804+ def list_ssl_certs(cmd, resource_group_name, name=None ):
67786805 client = web_client_factory(cmd.cli_ctx)
6806+
6807+ # Check if this is a Flex Consumption function app
6808+ if name and is_flex_functionapp(cmd.cli_ctx, resource_group_name, name):
6809+ return client.site_certificates.list(resource_group_name=resource_group_name, name=name)
67796810 return client.certificates.list_by_resource_group(resource_group_name)
67806811
67816812
6782- def show_ssl_cert(cmd, resource_group_name, certificate_name):
6813+ def show_ssl_cert(cmd, resource_group_name, certificate_name, name=None ):
67836814 client = web_client_factory(cmd.cli_ctx)
6815+
6816+ # Check if this is a Flex Consumption function app
6817+ if name and is_flex_functionapp(cmd.cli_ctx, resource_group_name, name):
6818+ return client.site_certificates.get(
6819+ resource_group_name=resource_group_name,
6820+ name=name,
6821+ certificate_name=certificate_name
6822+ )
67846823 return client.certificates.get(resource_group_name, certificate_name)
67856824
67866825
6787- def delete_ssl_cert(cmd, resource_group_name, certificate_thumbprint):
6826+ def delete_ssl_cert(cmd, resource_group_name, certificate_thumbprint, name=None ):
67886827 client = web_client_factory(cmd.cli_ctx)
6828+
6829+ # Check if this is a Flex Consumption function app
6830+ if name and is_flex_functionapp(cmd.cli_ctx, resource_group_name, name):
6831+ site_certs = client.site_certificates.list(resource_group_name=resource_group_name, name=name)
6832+ for site_cert in site_certs:
6833+ if site_cert.thumbprint == certificate_thumbprint:
6834+ return client.site_certificates.delete(
6835+ resource_group_name=resource_group_name,
6836+ name=name,
6837+ certificate_name=site_cert.name
6838+ )
6839+ raise ResourceNotFoundError("Certificate for thumbprint '{}' not found".format(certificate_thumbprint))
6840+
67896841 webapp_certs = client.certificates.list_by_resource_group(resource_group_name)
67906842 for webapp_cert in webapp_certs:
67916843 if webapp_cert.thumbprint == certificate_thumbprint:
67926844 return client.certificates.delete(resource_group_name, webapp_cert.name)
67936845 raise ResourceNotFoundError("Certificate for thumbprint '{}' not found".format(certificate_thumbprint))
67946846
67956847
6796- def import_ssl_cert(cmd, resource_group_name, key_vault, key_vault_certificate_name, name=None, certificate_name=None):
6848+ def import_ssl_cert(cmd, resource_group_name, key_vault, key_vault_certificate_name, name=None, certificate_name=None,
6849+ load_to_code=None, enable_using_msi=None):
67976850 Certificate = cmd.get_models('Certificate')
67986851 client = web_client_factory(cmd.cli_ctx)
67996852
@@ -6841,17 +6894,20 @@ def import_ssl_cert(cmd, resource_group_name, key_vault, key_vault_certificate_n
68416894 from azure.cli.core.commands.client_factory import get_subscription_id
68426895 subscription_id = get_subscription_id(cmd.cli_ctx)
68436896 if cloud_type.lower() == PUBLIC_CLOUD.lower():
6897+ # Check if app_service_certificate_orders operation group is available in the SDK
68446898 if kv_subscription.lower() != subscription_id.lower():
68456899 diff_subscription_client = get_mgmt_service_client(cmd.cli_ctx, ResourceType.MGMT_APPSERVICE,
68466900 subscription_id=kv_subscription)
6847- ascs = diff_subscription_client.app_service_certificate_orders.list(api_version=VERSION_2022_09_01)
6901+ cert_orders_client = diff_subscription_client
68486902 else:
6849- ascs = client.app_service_certificate_orders.list(api_version=VERSION_2022_09_01)
6903+ cert_orders_client = client
68506904
6851- kv_secret_name = None
6852- for asc in ascs:
6853- if asc.name == key_vault_certificate_name:
6854- kv_secret_name = asc.certificates[key_vault_certificate_name].key_vault_secret_name
6905+ if hasattr(cert_orders_client, 'app_service_certificate_orders'):
6906+ ascs = cert_orders_client.app_service_certificate_orders.list(api_version=VERSION_2022_09_01)
6907+ for asc in ascs:
6908+ if asc.name == key_vault_certificate_name:
6909+ kv_secret_name = asc.certificates[key_vault_certificate_name].key_vault_secret_name
6910+ break
68556911
68566912 # if kv_secret_name is not populated, it is not an appservice certificate, proceed for KV certificates
68576913 if not kv_secret_name:
@@ -6872,6 +6928,31 @@ def import_ssl_cert(cmd, resource_group_name, key_vault, key_vault_certificate_n
68726928 kv_cert_def = Certificate(location=location, key_vault_id=kv_id, password='',
68736929 key_vault_secret_name=kv_secret_name)
68746930
6931+ # Check if this is a Flex Consumption function app
6932+ if name and is_flex_functionapp(cmd.cli_ctx, resource_group_name, name):
6933+ # Build certificate envelope as dict to include loadCertificateToWebsitesSettings
6934+ # (not in SDK model yet)
6935+ cert_envelope = {
6936+ "location": location,
6937+ "properties": {
6938+ "keyVaultId": kv_id,
6939+ "password": "",
6940+ "keyVaultSecretName": kv_secret_name
6941+ }
6942+ }
6943+ if load_to_code is not None:
6944+ cert_envelope["properties"]["loadCertificateToWebsitesSettings"] = {
6945+ "loadToWebsite": load_to_code
6946+ }
6947+ if enable_using_msi is not None:
6948+ cert_envelope["properties"]["enableKeyVaultAccessUsingMSI"] = enable_using_msi
6949+ return client.site_certificates.create_or_update(
6950+ resource_group_name=resource_group_name,
6951+ name=name,
6952+ certificate_name=cert_name,
6953+ certificate_envelope=cert_envelope
6954+ )
6955+
68756956 return client.certificates.create_or_update(name=cert_name, resource_group_name=resource_group_name,
68766957 certificate_envelope=kv_cert_def)
68776958
@@ -6903,9 +6984,23 @@ def create_managed_ssl_cert(cmd, resource_group_name, name, hostname, slot=None,
69036984 easy_cert_def = Certificate(location=location, canonical_name=hostname,
69046985 server_farm_id=server_farm_id, password='')
69056986
6987+ # Check if this is a Flex Consumption function app
6988+ is_flex = is_flex_functionapp(cmd.cli_ctx, resource_group_name, name)
6989+
6990+ # Default certificate_name to hostname if not provided
6991+ if not certificate_name:
6992+ certificate_name = hostname
6993+
69066994 # TODO: Update manual polling to use LongRunningOperation once backend API & new SDK supports polling
69076995 try:
6908- certificate_name = hostname if not certificate_name else certificate_name
6996+ # For Flex Consumption apps, use the site-scoped certificates endpoint (slots not supported)
6997+ if is_flex:
6998+ return client.site_certificates.create_or_update(
6999+ resource_group_name=resource_group_name,
7000+ name=name,
7001+ certificate_name=certificate_name,
7002+ certificate_envelope=easy_cert_def
7003+ )
69097004 return client.certificates.create_or_update(name=certificate_name, resource_group_name=resource_group_name,
69107005 certificate_envelope=easy_cert_def)
69117006 except Exception as ex:
@@ -6973,24 +7068,37 @@ def _update_ssl_binding(cmd, resource_group_name, name, certificate_thumbprint,
69737068 if not webapp:
69747069 raise ResourceNotFoundError("'{}' app doesn't exist".format(name))
69757070
6976- cert_resource_group_name = parse_resource_id(get_site_server_farm_id(webapp))['resource_group']
6977- webapp_certs = client.certificates.list_by_resource_group(cert_resource_group_name )
7071+ # Check if this is a Flex Consumption function app
7072+ is_flex = is_flex_functionapp(cmd.cli_ctx, resource_group_name, name )
69787073
69797074 found_cert = None
6980- # search for a cert that matches in the app service plan's RG
6981- for webapp_cert in webapp_certs:
6982- if webapp_cert.thumbprint == certificate_thumbprint:
6983- found_cert = webapp_cert
6984- # search for a cert that matches in the webapp's RG
6985- if not found_cert:
6986- webapp_certs = client.certificates.list_by_resource_group(resource_group_name)
7075+
7076+ # For Flex Consumption apps, search in site-scoped certificates
7077+ if is_flex:
7078+ site_certs = client.site_certificates.list(resource_group_name=resource_group_name, name=name)
7079+ for site_cert in site_certs:
7080+ if site_cert.thumbprint == certificate_thumbprint:
7081+ found_cert = site_cert
7082+ break
7083+ # If not a Flex app, search in regular certificates
7084+ else:
7085+ cert_resource_group_name = parse_resource_id(get_site_server_farm_id(webapp))['resource_group']
7086+ webapp_certs = client.certificates.list_by_resource_group(cert_resource_group_name)
7087+ # search for a cert that matches in the app service plan's RG
69877088 for webapp_cert in webapp_certs:
69887089 if webapp_cert.thumbprint == certificate_thumbprint:
69897090 found_cert = webapp_cert
6990- # search for a cert that matches in the subscription, filtering on the serverfarm
6991- if not found_cert:
6992- sub_certs = client.certificates.list(filter=f"ServerFarmId eq '{get_site_server_farm_id(webapp)}'")
6993- found_cert = next(iter([c for c in sub_certs if c.thumbprint == certificate_thumbprint]), None)
7091+ # search for a cert that matches in the webapp's RG
7092+ if not found_cert:
7093+ webapp_certs = client.certificates.list_by_resource_group(resource_group_name)
7094+ for webapp_cert in webapp_certs:
7095+ if webapp_cert.thumbprint == certificate_thumbprint:
7096+ found_cert = webapp_cert
7097+ # search for a cert that matches in the subscription, filtering on the serverfarm
7098+ if not found_cert:
7099+ sub_certs = client.certificates.list(filter=f"ServerFarmId eq '{get_site_server_farm_id(webapp)}'")
7100+ found_cert = next(iter([c for c in sub_certs if c.thumbprint == certificate_thumbprint]), None)
7101+
69947102 if found_cert:
69957103 if not hostname:
69967104 if len(found_cert.host_names) == 1 and not found_cert.host_names[0].startswith('*'):
0 commit comments