Skip to content

Commit 5cc17eb

Browse files
authored
Merge pull request #1260 from ninjarobot/issue445
Add Service Bus topic authorization rules
2 parents 9dfbb10 + de21e2d commit 5cc17eb

5 files changed

Lines changed: 83 additions & 0 deletions

File tree

‎RELEASE_NOTES.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ Release Notes
22
=============
33
## 1.9.31
44
* Communication Services: Update `Microsoft.Communication/communicationServices` to the stable `2020-08-20` ARM API version instead of the retired preview API.
5+
* Service Bus: Add topic-level authorization rules with `add_authorization_rule` on the `topic` builder.
56

67
## 1.9.29
78
* Container Apps: Add support for setting Dapr protocol.

‎docs/content/api-overview/resources/service-bus.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ The Service Bus builder creates service bus namespaces and their associated queu
4747
| Topic | max_message_size | The maximum size of the message payload that can be accepted by the topic in Kilobytes e.g `1024<Kb>`. **Requires Premium SKU.** |
4848
| Topic | max_topic_size | Maximum size for the topic in Megabytes e.g. `1024<Mb>`. |
4949
| Topic | message_ttl | Time To Live (TTL) value for messages expressed as a TimeSpan or a TimeSpan string, such as '01:30:00' 1 hour, 30 minutes, or as an integer days e.g. `4<Days>`. |
50+
| Topic | add_authorization_rule | Adds an authorization rule to the topic. |
5051
| Topic | link_to_unmanaged_namespace | Instead of creating or modifying a namespace, configure this topic to point to another unmanaged namespace instance. |
5152
| Namespace | sku | The ServiceBusNamespaceSku e.g. Standard |
5253
| Namespace | namespace_name | The name of the namespace that holds the queue. |

‎src/Farmer/Arm/ServiceBus.fs‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ let namespaces =
2222
let queueAuthorizationRules =
2323
ResourceType("Microsoft.ServiceBus/namespaces/queues/authorizationRules", "2022-01-01-preview")
2424

25+
let topicAuthorizationRules =
26+
ResourceType("Microsoft.ServiceBus/namespaces/topics/authorizationRules", "2022-01-01-preview")
27+
2528
let namespaceAuthorizationRules =
2629
ResourceType("Microsoft.ServiceBus/namespaces/AuthorizationRules", "2022-01-01-preview")
2730

@@ -153,6 +156,23 @@ module Namespaces =
153156
|}
154157
|}
155158

159+
type TopicAuthorizationRule = {
160+
Name: ResourceName
161+
Location: Location
162+
Dependencies: ResourceId list
163+
Rights: AuthorizationRuleRight Set
164+
} with
165+
166+
interface IArmResource with
167+
member this.ResourceId = topicAuthorizationRules.resourceId this.Name
168+
169+
member this.JsonModel = {|
170+
topicAuthorizationRules.Create(this.Name, this.Location, this.Dependencies) with
171+
properties = {|
172+
rights = this.Rights |> Set.map string |> Set.toList
173+
|}
174+
|}
175+
156176
type NamespaceAuthorizationRule = {
157177
Name: ResourceName
158178
Location: Location

‎src/Farmer/Builders/Builders.ServiceBus.fs‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ type ServiceBusTopicConfig = {
325325
MaxMessageSizeInKilobytes: int<Kb> option
326326
MaxSizeInMegabytes: int<Mb> option
327327
Subscriptions: Map<ResourceName, ServiceBusSubscriptionConfig>
328+
AuthorizationRules: Map<ResourceName, AuthorizationRuleRight Set>
328329
} with
329330

330331
member this.ResourceId = topics.resourceId (this.Namespace.Name, this.Name)
@@ -352,6 +353,17 @@ type ServiceBusTopicConfig = {
352353
MaxMessageSizeInKilobytes = this.MaxMessageSizeInKilobytes
353354
MaxSizeInMegabytes = this.MaxSizeInMegabytes
354355
}
356+
for rule in this.AuthorizationRules do
357+
{
358+
TopicAuthorizationRule.Name =
359+
rule.Key.Map(fun name -> $"{this.Namespace.Name.Value}/{this.Name.Value}/%s{name}")
360+
Location = location
361+
Dependencies = [
362+
namespaces.resourceId this.Namespace.Name
363+
topics.resourceId (this.Namespace.Name, this.Name)
364+
]
365+
Rights = rule.Value
366+
}
355367
for subscription in this.Subscriptions do
356368
let subscription =
357369
{
@@ -373,6 +385,7 @@ type ServiceBusTopicBuilder() =
373385
MaxMessageSizeInKilobytes = None
374386
MaxSizeInMegabytes = None
375387
Subscriptions = Map.empty
388+
AuthorizationRules = Map.empty
376389
}
377390

378391
/// The name of the queue.
@@ -446,6 +459,13 @@ type ServiceBusTopicBuilder() =
446459
state.Add(subscription.Name, subscription))
447460
}
448461

462+
/// Add authorization rule on the topic.
463+
[<CustomOperation "add_authorization_rule">]
464+
member _.AddAuthorizationRule(state: ServiceBusTopicConfig, name, rights) = {
465+
state with
466+
AuthorizationRules = state.AuthorizationRules.Add(ResourceName name, Set rights)
467+
}
468+
449469
/// Instead of creating or modifying a namespace, configure this topic to point to another unmanaged namespace instance.
450470
[<CustomOperation "link_to_unmanaged_namespace">]
451471
member this.LinkToUnmanagedNamespace(state: ServiceBusTopicConfig, namespaceName: ResourceName) = {

‎src/Tests/ServiceBus.fs‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,47 @@ let tests =
579579
Expect.equal topic.Name "my-bus/my-topic" "Name not set"
580580
Expect.equal topic.MaxSizeInMegabytes (Nullable 10240) "Max size not set"
581581
}
582+
test "Topic authorization rule should not be present by default" {
583+
let sbAuthorizationRules =
584+
arm {
585+
add_resource (
586+
serviceBus {
587+
name "serviceBus"
588+
sku Standard
589+
add_topics [ topic { name "my-topic" } ]
590+
}
591+
)
592+
}
593+
|> findAzureResources<SBAuthorizationRule> dummyClient.SerializationSettings
594+
|> List.filter (fun x -> (=) x.Type topicAuthorizationRules.Type)
595+
596+
Expect.equal sbAuthorizationRules.Length 0 "Topic authorization rule should not be present"
597+
}
598+
test "Topic authorization rule should write correct ARM template" {
599+
let sbAuthorizationRule =
600+
arm {
601+
add_resource (
602+
serviceBus {
603+
name "serviceBus"
604+
sku Standard
605+
606+
add_topics [
607+
topic {
608+
name "my-topic"
609+
add_authorization_rule "my-rule" [ Manage ]
610+
}
611+
]
612+
}
613+
)
614+
}
615+
|> findAzureResources<SBAuthorizationRule> dummyClient.SerializationSettings
616+
|> List.filter (fun x -> (=) x.Type topicAuthorizationRules.Type)
617+
|> List.head
618+
619+
Expect.equal sbAuthorizationRule.Name "serviceBus/my-topic/my-rule" "Name is wrong"
620+
Expect.equal sbAuthorizationRule.Rights.Count 1 "Wrong number of rights"
621+
Expect.equal sbAuthorizationRule.Rights.[0] AccessRights.Manage "Wrong rights"
622+
}
582623
test "Can create a basic subscription" {
583624
let sub: SBSubscription =
584625
serviceBus {

0 commit comments

Comments
 (0)