Skip to content

Commit fe729c5

Browse files
[Stream Analytics] Fix #9708: Policy isn't triggered when creating a stream analytics input (#9734)
* Update test case version * Fix authentication mode bug * Added test case and recording for this development * Added log and update version * Update test case and re-record test case * Update test case recording version
1 parent cec56d3 commit fe729c5

File tree

10 files changed

+575
-15
lines changed

10 files changed

+575
-15
lines changed

src/stream-analytics/HISTORY.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
Release History
44
===============
55

6+
1.0.2
7+
+++++++++++++++
8+
* Fix creating stream analytics input not triggering policy bug
9+
610
1.0.1
711
+++++++++++++++
812
* Supports stream-analytics output type: Microsoft.AzureFunction

src/stream-analytics/azext_stream_analytics/tests/latest/recordings/test_input_create_policy_violation.yaml

Lines changed: 425 additions & 0 deletions
Large diffs are not rendered by default.

src/stream-analytics/azext_stream_analytics/tests/latest/recordings/test_input_crud.yaml

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

src/stream-analytics/azext_stream_analytics/tests/latest/recordings/test_job_scale.yaml

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

src/stream-analytics/azext_stream_analytics/tests/latest/recordings/test_output_crud.yaml

Lines changed: 6 additions & 6 deletions
Large diffs are not rendered by default.

src/stream-analytics/azext_stream_analytics/tests/latest/recordings/test_private_endpoint_crud.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2935,7 +2935,7 @@ interactions:
29352935
User-Agent:
29362936
- AZURECLI/2.77.0 azsdk-python-core/1.35.0 Python/3.12.10 (Windows-11-10.0.26100-SP0)
29372937
method: GET
2938-
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_stream_analytics_000001/providers/Microsoft.Storage/storageAccounts/pl000002?api-version=2024-01-01
2938+
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_stream_analytics_000001/providers/Microsoft.Storage/storageAccounts/pl000002?api-version=2025-06-01
29392939
response:
29402940
body:
29412941
string: '{"sku":{"name":"Standard_LRS","tier":"Standard"},"kind":"StorageV2","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_stream_analytics_000001/providers/Microsoft.Storage/storageAccounts/pl000002","name":"pl000002","type":"Microsoft.Storage/storageAccounts","location":"westus","tags":{},"properties":{"keyCreationTime":{"key1":"2025-09-19T03:45:19.3246476Z","key2":"2025-09-19T03:45:19.3246476Z"},"allowCrossTenantReplication":false,"privateEndpointConnections":[],"minimumTlsVersion":"TLS1_0","allowBlobPublicAccess":false,"networkAcls":{"ipv6Rules":[],"bypass":"AzureServices","virtualNetworkRules":[],"ipRules":[],"defaultAction":"Allow"},"supportsHttpsTrafficOnly":true,"encryption":{"services":{"file":{"keyType":"Account","enabled":true,"lastEnabledTime":"2025-09-19T03:45:19.3402678Z"},"blob":{"keyType":"Account","enabled":true,"lastEnabledTime":"2025-09-19T03:45:19.3402678Z"}},"keySource":"Microsoft.Storage"},"accessTier":"Hot","provisioningState":"Succeeded","creationTime":"2025-09-19T03:45:19.1840227Z","primaryEndpoints":{"dfs":"https://pl000002.dfs.core.windows.net/","web":"https://pl000002.z22.web.core.windows.net/","blob":"https://pl000002.blob.core.windows.net/","queue":"https://pl000002.queue.core.windows.net/","table":"https://pl000002.table.core.windows.net/","file":"https://pl000002.file.core.windows.net/"},"primaryLocation":"westus","statusOfPrimary":"available"}}'
@@ -2981,7 +2981,7 @@ interactions:
29812981
User-Agent:
29822982
- AZURECLI/2.77.0 azsdk-python-core/1.35.0 Python/3.12.10 (Windows-11-10.0.26100-SP0)
29832983
method: GET
2984-
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_stream_analytics_000001/providers/Microsoft.Storage/storageAccounts/pl000002/privateLinkResources?api-version=2024-01-01
2984+
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_stream_analytics_000001/providers/Microsoft.Storage/storageAccounts/pl000002/privateLinkResources?api-version=2025-06-01
29852985
response:
29862986
body:
29872987
string: '{"value":[{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_stream_analytics_000001/providers/Microsoft.Storage/storageAccounts/pl000002/privateLinkResources/blob","name":"blob","type":"Microsoft.Storage/storageAccounts/privateLinkResources","properties":{"groupId":"blob","requiredMembers":["blob"],"requiredZoneNames":["privatelink.blob.core.windows.net"]}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_stream_analytics_000001/providers/Microsoft.Storage/storageAccounts/pl000002/privateLinkResources/table","name":"table","type":"Microsoft.Storage/storageAccounts/privateLinkResources","properties":{"groupId":"table","requiredMembers":["table"],"requiredZoneNames":["privatelink.table.core.windows.net"]}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_stream_analytics_000001/providers/Microsoft.Storage/storageAccounts/pl000002/privateLinkResources/queue","name":"queue","type":"Microsoft.Storage/storageAccounts/privateLinkResources","properties":{"groupId":"queue","requiredMembers":["queue"],"requiredZoneNames":["privatelink.queue.core.windows.net"]}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_stream_analytics_000001/providers/Microsoft.Storage/storageAccounts/pl000002/privateLinkResources/file","name":"file","type":"Microsoft.Storage/storageAccounts/privateLinkResources","properties":{"groupId":"file","requiredMembers":["file"],"requiredZoneNames":["privatelink.file.core.windows.net"]}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_stream_analytics_000001/providers/Microsoft.Storage/storageAccounts/pl000002/privateLinkResources/web","name":"web","type":"Microsoft.Storage/storageAccounts/privateLinkResources","properties":{"groupId":"web","requiredMembers":["web"],"requiredZoneNames":["privatelink.web.core.windows.net"]}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_stream_analytics_000001/providers/Microsoft.Storage/storageAccounts/pl000002/privateLinkResources/dfs","name":"dfs","type":"Microsoft.Storage/storageAccounts/privateLinkResources","properties":{"groupId":"dfs","requiredMembers":["dfs"],"requiredZoneNames":["privatelink.dfs.core.windows.net"]}}]}'

src/stream-analytics/azext_stream_analytics/tests/latest/test_stream_analytics_commands.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,85 @@ def test_input_crud(self, storage_account):
188188
# delete an input
189189
self.cmd("stream-analytics input delete -n {input_name} -g {rg} --job-name {job_name} --yes")
190190

191+
@ResourceGroupPreparer(name_prefix="cli_test_stream_analytics_")
192+
@StorageAccountPreparer(parameter_name="storage_account")
193+
def test_input_create_policy_violation(self, storage_account):
194+
self.kwargs.update({
195+
"job_name": "job",
196+
"input_name": "input",
197+
"locale": "en-US",
198+
"account": storage_account,
199+
"container": "container"
200+
})
201+
202+
policy_param = {
203+
"effect": {
204+
"value": "Deny"
205+
}
206+
}
207+
self.kwargs["policy_param"] = json.dumps(policy_param)
208+
self.cmd(
209+
"policy assignment create --name deny-asa-mi --display-name 'Deny ASA non-MI authentication' \
210+
--policy ea6c4923-510a-4346-be26-1894919a5b97 \
211+
--params '{policy_param}'"
212+
)
213+
214+
# create a streaming job
215+
self.cmd(
216+
"stream-analytics job create -n {job_name} -g {rg} \
217+
--data-locale {locale} \
218+
--output-error-policy Drop --out-of-order-policy Drop \
219+
--order-max-delay 0 --arrival-max-delay 5"
220+
)
221+
222+
# prepare storage account
223+
self.kwargs["key"] = self.cmd(
224+
"storage account keys list --account-name {account}"
225+
).get_output_in_json()[0]["value"]
226+
self.cmd(
227+
"storage container create -n {container} \
228+
--account-name {account} --account-key {key}"
229+
)
230+
231+
# create/test an input
232+
props = {
233+
"type": "Stream",
234+
"datasource": {
235+
"type": "Microsoft.Storage/Blob",
236+
"properties": {
237+
"container": self.kwargs["container"],
238+
"dateFormat": "yyyy/MM/dd",
239+
"pathPattern": "{date}/{time}",
240+
"storageAccounts": [{
241+
"accountName": self.kwargs["account"],
242+
"accountKey": self.kwargs["key"]
243+
}],
244+
"timeFormat": "HH",
245+
"authenticationMode": "ConnectionString"
246+
}
247+
},
248+
"serialization": {
249+
"type": "Csv",
250+
"properties": {
251+
"encoding": "UTF8",
252+
"fieldDelimiter": ","
253+
}
254+
}
255+
}
256+
self.kwargs["properties"] = json.dumps(props)
257+
258+
# Make sure it raises an exception error and the error is correct
259+
from azure.core.exceptions import HttpResponseError
260+
with self.assertRaises(HttpResponseError) as cm:
261+
self.cmd(
262+
"stream-analytics input create -n {input_name} -g {rg} \
263+
--job-name {job_name} \
264+
--properties '{properties}'"
265+
)
266+
267+
self.assertIn("RequestDisallowedByPolicy", str(cm.exception))
268+
269+
191270
@AllowLargeResponse()
192271
@ResourceGroupPreparer(name_prefix="cli_test_stream_analytics_", location="westus")
193272
@StorageAccountPreparer(parameter_name="storage_account")

src/stream-analytics/azext_stream_analytics/vendored_sdks/streamanalytics/models/_models.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,9 @@ class BlobDataSourceProperties(msrest.serialization.Model):
10001000
:param time_format: The time format. Wherever {time} appears in pathPattern, the value of this
10011001
property is used as the time format instead.
10021002
:type time_format: str
1003+
:param authentication_mode: Authentication Mode. Possible values include: "Msi", "UserToken",
1004+
"ConnectionString".
1005+
:type authentication_mode: str or ~stream_analytics_management_client.models.AuthenticationMode
10031006
"""
10041007

10051008
_attribute_map = {
@@ -1008,6 +1011,7 @@ class BlobDataSourceProperties(msrest.serialization.Model):
10081011
'path_pattern': {'key': 'pathPattern', 'type': 'str'},
10091012
'date_format': {'key': 'dateFormat', 'type': 'str'},
10101013
'time_format': {'key': 'timeFormat', 'type': 'str'},
1014+
'authentication_mode': {'key': 'authenticationMode', 'type': 'str'},
10111015
}
10121016

10131017
def __init__(
@@ -1020,6 +1024,7 @@ def __init__(
10201024
self.path_pattern = kwargs.get('path_pattern', None)
10211025
self.date_format = kwargs.get('date_format', None)
10221026
self.time_format = kwargs.get('time_format', None)
1027+
self.authentication_mode = kwargs.get('authentication_mode', None)
10231028

10241029

10251030
class BlobOutputDataSource(OutputDataSource):
@@ -1156,6 +1161,9 @@ class BlobReferenceInputDataSource(ReferenceInputDataSource):
11561161
:param time_format: The time format. Wherever {time} appears in pathPattern, the value of this
11571162
property is used as the time format instead.
11581163
:type time_format: str
1164+
:param authentication_mode: Authentication Mode. Possible values include: "Msi", "UserToken",
1165+
"ConnectionString".
1166+
:type authentication_mode: str or ~stream_analytics_management_client.models.AuthenticationMode
11591167
"""
11601168

11611169
_validation = {
@@ -1169,6 +1177,7 @@ class BlobReferenceInputDataSource(ReferenceInputDataSource):
11691177
'path_pattern': {'key': 'properties.pathPattern', 'type': 'str'},
11701178
'date_format': {'key': 'properties.dateFormat', 'type': 'str'},
11711179
'time_format': {'key': 'properties.timeFormat', 'type': 'str'},
1180+
'authentication_mode': {'key': 'properties.authenticationMode', 'type': 'str'},
11721181
}
11731182

11741183
def __init__(
@@ -1182,6 +1191,7 @@ def __init__(
11821191
self.path_pattern = kwargs.get('path_pattern', None)
11831192
self.date_format = kwargs.get('date_format', None)
11841193
self.time_format = kwargs.get('time_format', None)
1194+
self.authentication_mode = kwargs.get('authentication_mode', None)
11851195

11861196

11871197
class BlobReferenceInputDataSourceProperties(BlobDataSourceProperties):
@@ -1207,6 +1217,9 @@ class BlobReferenceInputDataSourceProperties(BlobDataSourceProperties):
12071217
:param time_format: The time format. Wherever {time} appears in pathPattern, the value of this
12081218
property is used as the time format instead.
12091219
:type time_format: str
1220+
:param authentication_mode: Authentication Mode. Possible values include: "Msi", "UserToken",
1221+
"ConnectionString".
1222+
:type authentication_mode: str or ~stream_analytics_management_client.models.AuthenticationMode
12101223
"""
12111224

12121225
_attribute_map = {
@@ -1215,6 +1228,7 @@ class BlobReferenceInputDataSourceProperties(BlobDataSourceProperties):
12151228
'path_pattern': {'key': 'pathPattern', 'type': 'str'},
12161229
'date_format': {'key': 'dateFormat', 'type': 'str'},
12171230
'time_format': {'key': 'timeFormat', 'type': 'str'},
1231+
'authentication_mode': {'key': 'authenticationMode', 'type': 'str'},
12181232
}
12191233

12201234
def __init__(
@@ -1288,6 +1302,9 @@ class BlobStreamInputDataSource(StreamInputDataSource):
12881302
:param source_partition_count: The partition count of the blob input data source. Range 1 -
12891303
256.
12901304
:type source_partition_count: int
1305+
:param authentication_mode: Authentication Mode. Possible values include: "Msi", "UserToken",
1306+
"ConnectionString".
1307+
:type authentication_mode: str or ~stream_analytics_management_client.models.AuthenticationMode
12911308
"""
12921309

12931310
_validation = {
@@ -1302,6 +1319,7 @@ class BlobStreamInputDataSource(StreamInputDataSource):
13021319
'date_format': {'key': 'properties.dateFormat', 'type': 'str'},
13031320
'time_format': {'key': 'properties.timeFormat', 'type': 'str'},
13041321
'source_partition_count': {'key': 'properties.sourcePartitionCount', 'type': 'int'},
1322+
'authentication_mode': {'key': 'properties.authenticationMode', 'type': 'str'},
13051323
}
13061324

13071325
def __init__(
@@ -1316,6 +1334,7 @@ def __init__(
13161334
self.date_format = kwargs.get('date_format', None)
13171335
self.time_format = kwargs.get('time_format', None)
13181336
self.source_partition_count = kwargs.get('source_partition_count', None)
1337+
self.authentication_mode = kwargs.get('authentication_mode', None)
13191338

13201339

13211340
class BlobStreamInputDataSourceProperties(BlobDataSourceProperties):
@@ -1344,6 +1363,9 @@ class BlobStreamInputDataSourceProperties(BlobDataSourceProperties):
13441363
:param source_partition_count: The partition count of the blob input data source. Range 1 -
13451364
256.
13461365
:type source_partition_count: int
1366+
:param authentication_mode: Authentication Mode. Possible values include: "Msi", "UserToken",
1367+
"ConnectionString".
1368+
:type authentication_mode: str or ~stream_analytics_management_client.models.AuthenticationMode
13471369
"""
13481370

13491371
_attribute_map = {
@@ -1353,6 +1375,7 @@ class BlobStreamInputDataSourceProperties(BlobDataSourceProperties):
13531375
'date_format': {'key': 'dateFormat', 'type': 'str'},
13541376
'time_format': {'key': 'timeFormat', 'type': 'str'},
13551377
'source_partition_count': {'key': 'sourcePartitionCount', 'type': 'int'},
1378+
'authentication_mode': {'key': 'authenticationMode', 'type': 'str'},
13561379
}
13571380

13581381
def __init__(
@@ -1361,6 +1384,7 @@ def __init__(
13611384
):
13621385
super(BlobStreamInputDataSourceProperties, self).__init__(**kwargs)
13631386
self.source_partition_count = kwargs.get('source_partition_count', None)
1387+
self.authentication_mode = kwargs.get('authentication_mode', None)
13641388

13651389

13661390
class Resource(msrest.serialization.Model):

0 commit comments

Comments
 (0)