@@ -23,6 +23,14 @@ def _scope_to_resource(scope): # This is an experimental reasonable-effort appr
23
23
24
24
def _obtain_token (http_client , resource , client_id = None , object_id = None , mi_res_id = None ):
25
25
if "IDENTITY_ENDPOINT" in os .environ and "IDENTITY_HEADER" in os .environ :
26
+ if "IDENTITY_SERVER_THUMBPRINT" in os .environ :
27
+ if client_id or object_id or mi_res_id :
28
+ raise ValueError (
29
+ "Managed Identity in Service Fabric is configured in the cluster, not during runtime. "
30
+ "See also https://learn.microsoft.com/en-us/azure/service-fabric/configure-existing-cluster-enable-managed-identity-token-service" )
31
+ return _obtain_token_on_service_fabric (
32
+ http_client , os .environ ["IDENTITY_ENDPOINT" ], os .environ ["IDENTITY_HEADER" ],
33
+ os .environ ["IDENTITY_SERVER_THUMBPRINT" ], resource )
26
34
return _obtain_token_on_app_service (
27
35
http_client , os .environ ["IDENTITY_ENDPOINT" ], os .environ ["IDENTITY_HEADER" ],
28
36
resource , client_id = client_id , object_id = object_id , mi_res_id = mi_res_id )
@@ -69,7 +77,8 @@ def _obtain_token_on_app_service(http_client, endpoint, identity_header, resourc
69
77
client_id = None , object_id = None , mi_res_id = None ,
70
78
):
71
79
"""Obtains token for
72
- `App Service <https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Chttp#rest-endpoint-reference>`_
80
+ `App Service <https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Chttp#rest-endpoint-reference>`_,
81
+ Azure Functions, and Azure Automation.
73
82
"""
74
83
# Prerequisite: Create your app service https://docs.microsoft.com/en-us/azure/app-service/quickstart-python
75
84
# Assign it a managed identity https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Chttp
@@ -114,6 +123,41 @@ def _obtain_token_on_app_service(http_client, endpoint, identity_header, resourc
114
123
raise
115
124
116
125
126
+ def _obtain_token_on_service_fabric (
127
+ http_client , endpoint , identity_header , server_thumbprint , resource ,
128
+ ):
129
+ """Obtains token for
130
+ `Service Fabric <https://learn.microsoft.com/en-us/azure/service-fabric/>`_
131
+ """
132
+ # Deployment https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-get-started-containers-linux
133
+ # See also https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/identity/azure-identity/tests/managed-identity-live/service-fabric/service_fabric.md
134
+ # Protocol https://learn.microsoft.com/en-us/azure/service-fabric/how-to-managed-identity-service-fabric-app-code#acquiring-an-access-token-using-rest-api
135
+ logger .debug ("Obtaining token via managed identity on Azure Service Fabric" )
136
+ resp = http_client .get (
137
+ endpoint ,
138
+ params = {"api-version" : "2019-07-01-preview" , "resource" : resource },
139
+ headers = {"Secret" : identity_header },
140
+ )
141
+ try :
142
+ payload = json .loads (resp .text )
143
+ if payload .get ("access_token" ) and payload .get ("expires_on" ):
144
+ return { # Normalizing the payload into OAuth2 format
145
+ "access_token" : payload ["access_token" ],
146
+ "expires_in" : payload ["expires_on" ] - int (time .time ()),
147
+ "resource" : payload .get ("resource" ),
148
+ "token_type" : payload ["token_type" ],
149
+ }
150
+ return {
151
+ "error" : "invalid_scope" ,
152
+ "error_description" : "{}, {}" .format (
153
+ payload .get ("statusCode" ), payload .get ("message" )),
154
+ }
155
+ except ValueError :
156
+ logger .debug ("IMDS emits unexpected payload: %s" , resp .text )
157
+ raise
158
+
159
+
160
+
117
161
class ManagedIdentity (object ):
118
162
_instance , _tenant = socket .getfqdn (), "managed_identity" # Placeholders
119
163
0 commit comments