Skip to content

Commit

Permalink
Initial work for linking to an identity
Browse files Browse the repository at this point in the history
  • Loading branch information
aebaid committed Sep 26, 2022
1 parent 5733c56 commit b4e09e2
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/Farmer/Builders/Builders.DeploymentScript.fs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type DeploymentScriptConfig =

let identity =
this.CustomIdentity
|> Option.defaultValue (UserAssignedIdentity generatedIdentityId)
|> Option.defaultValue (UserAssignedIdentity (LinkedResource.Managed generatedIdentityId))

// Assignment
{
Expand Down
20 changes: 19 additions & 1 deletion src/Farmer/Builders/Builders.UserAssignedIdentity.fs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ type UserAssignedIdentityConfig =
]

member this.ResourceId = userAssignedIdentities.resourceId this.Name
member this.UserAssignedIdentity = UserAssignedIdentity this.ResourceId
member this.UserAssignedIdentity = UserAssignedIdentity (LinkedResource.Managed this.ResourceId)

member this.UnManagedUserAssignedIdentity = UserAssignedIdentity(LinkedResource.Unmanaged this.ResourceId)
member this.ClientId = this.UserAssignedIdentity.ClientId
member this.PrincipalId = this.UserAssignedIdentity.PrincipalId

Expand Down Expand Up @@ -64,6 +66,22 @@ module Extensions =

member this.AddIdentity(state, identity: UserAssignedIdentityConfig) =
this.AddIdentity(state, identity.UserAssignedIdentity)

member this.AddIdentity(state, resourceId: ResourceId) =
let linkedResource = (LinkedResource.Managed resourceId)
let userAssignedIdentity = (UserAssignedIdentity linkedResource)
this.Add state (fun current -> current + userAssignedIdentity)



[<CustomOperation "link_to_identity">]
member this.LinkToIdentity(state: 'TConfig, resourceId: ResourceId) =
let linkedResource = (LinkedResource.Unmanaged resourceId)
let userAssignedIdentity = (UserAssignedIdentity linkedResource)
this.Add state (fun current -> current + userAssignedIdentity)

member this.LinkToIdentity(state, identity: UserAssignedIdentityConfig) =
this.AddIdentity(state, identity.UnManagedUserAssignedIdentity)

[<CustomOperation "system_identity">]
member this.SystemIdentity(state: 'TConfig) =
Expand Down
34 changes: 26 additions & 8 deletions src/Farmer/Common.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1833,11 +1833,15 @@ module Identity =

/// Represents a User Assigned Identity, and the ability to create a Principal Id from it.
type UserAssignedIdentity =
| UserAssignedIdentity of ResourceId
| UserAssignedIdentity of LinkedResource

member private this.CreateExpression field =
let (UserAssignedIdentity resourceId) = this

let (UserAssignedIdentity linkedResource) = this
let resourceId =
match linkedResource with
| Managed rid -> rid
| Unmanaged rid -> rid

ArmExpression
.create($"reference({resourceId.ArmExpression.Value}).%s{field}")
.WithOwner(resourceId)
Expand All @@ -1847,7 +1851,10 @@ module Identity =

member this.ResourceId =
match this with
| UserAssignedIdentity r -> r
| UserAssignedIdentity lrid ->
match lrid with
| Managed rid -> rid
| Unmanaged rid -> rid

type SystemIdentity =
| SystemIdentity of ResourceId
Expand All @@ -1873,7 +1880,11 @@ module Identity =
UserAssigned: UserAssignedIdentity list
}

member this.Dependencies = this.UserAssigned |> List.map (fun u -> u.ResourceId)
member this.Dependencies = this.UserAssigned |> List.filter (fun u ->
let (UserAssignedIdentity linkedResourceId) = u
match linkedResourceId with
| Managed _ -> true
| Unmanaged _ -> false) |> List.map (fun u -> u.ResourceId)

static member Empty =
{
Expand All @@ -1888,9 +1899,16 @@ module Identity =
}

static member (+)(managedIdentity, userAssignedIdentity: UserAssignedIdentity) =
{ managedIdentity with
UserAssigned = userAssignedIdentity :: managedIdentity.UserAssigned
}
let (UserAssignedIdentity linkedResource) = userAssignedIdentity
match linkedResource with
| Managed rid ->
{ managedIdentity with
UserAssigned = userAssignedIdentity :: managedIdentity.UserAssigned
}
| Unmanaged rid ->
{ managedIdentity with
UserAssigned = userAssignedIdentity :: managedIdentity.UserAssigned
}

open Identity

Expand Down
20 changes: 18 additions & 2 deletions src/Farmer/IdentityExtensions.fs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace Farmer

open Farmer.Arm
open Identity
open Farmer.Arm.ManagedIdentity
open System
Expand All @@ -12,12 +13,27 @@ module ManagedIdentityExtensions =
static member create(resourceId: ResourceId) =
{
SystemAssigned = Disabled
UserAssigned = [ UserAssignedIdentity resourceId ]
UserAssigned = [ UserAssignedIdentity (LinkedResource.Managed resourceId) ]
}


static member create(linkedResource:LinkedResource) =
match linkedResource with
| Managed rid ->
{
SystemAssigned = Disabled
UserAssigned = [ UserAssignedIdentity (LinkedResource.Managed rid) ]
}
| Unmanaged rid ->
{
SystemAssigned = Disabled
UserAssigned = [ UserAssignedIdentity (LinkedResource.Unmanaged rid) ]
}

/// Creates a resource identity from a resource name
static member create(name: ResourceName) =
userAssignedIdentities.resourceId name |> ManagedIdentity.create



module Roles =
type RoleAssignment =
Expand Down
2 changes: 1 addition & 1 deletion src/Tests/ContainerApps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ let tests =
Expect.equal
containerApp.Identity.UserAssigned.[0]
(UserAssignedIdentity(
ResourceId.create (Arm.ManagedIdentity.userAssignedIdentities, ResourceName "appUser")
ResourceId.create (Arm.ManagedIdentity.userAssignedIdentities, ResourceName "appUser") |> LinkedResource.Managed
))
"Expected user identity named 'appUser'."
}
Expand Down
83 changes: 76 additions & 7 deletions src/Tests/ContainerGroup.fs
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,12 @@ let tests =
}

test "Container group with managed identity to private registry" {
let userAssignedIdentity =
ResourceId.create (Arm.ManagedIdentity.userAssignedIdentities, ResourceName "user", "resourceGroup")
|> UserAssignedIdentity
let resourceId = ResourceId.create (
ManagedIdentity.userAssignedIdentities,
ResourceName "user",
"resourceGroup"
)
let userAssignedIdentity = UserAssignedIdentity (LinkedResource.Managed resourceId)

let managedIdentity =
{ ManagedIdentity.Empty with
Expand All @@ -306,9 +309,7 @@ let tests =
ResourceName "user",
"resourceGroup"
)
|> UserAssignedIdentity
)

add_managed_identity_registry_credentials
[ registry "my-registry.azurecr.io" "user" managedIdentity ]
}
Expand Down Expand Up @@ -396,7 +397,6 @@ let tests =
ResourceName "user",
"resourceGroup"
)
|> UserAssignedIdentity
)
}
|> asAzureResource
Expand Down Expand Up @@ -431,7 +431,7 @@ let tests =
Expect.equal
containerGroup.Identity.UserAssigned.[0]
(UserAssignedIdentity(
ResourceId.create (Arm.ManagedIdentity.userAssignedIdentities, ResourceName "aciUser")
ResourceId.create (Arm.ManagedIdentity.userAssignedIdentities, ResourceName "aciUser") |> LinkedResource.Managed
))
"Expected user identity named 'aciUser'."
}
Expand Down Expand Up @@ -1220,4 +1220,73 @@ async {
Expect.sequenceEqual nameservers [ JValue "8.8.8.8"; JValue "1.1.1.1" ] "Incorrect nameservers."
Expect.equal searchDomains (JValue "example.com example.local") "Incorrect search domains."
}

// test "Specify DNS ahmed and search domains" {
// let resourceId = ResourceId.create (Arm.ManagedIdentity.userAssignedIdentities, ResourceName "user", "resourceGroup")
// let userAssignedIdentity =
// resourceId |> LinkedResource.Managed
// |> UserAssignedIdentity
//
// let managedIdentity:Identity.ManagedIdentity =
// { ManagedIdentity.Empty with
// UserAssigned = [ userAssignedIdentity ]
// }
//
// let myVnet =
// vnet {
// name "mynetwork"
// add_address_spaces [ "10.30.32.0/20" ]
//
// add_subnets
// [
// subnet {
// name "containers"
// prefix "10.30.41.0/24"
// add_delegations [ SubnetDelegationService.ContainerGroups ]
// }
// ]
// }
// let containerGroup =
// containerGroup {
// // name "container-group-with-custom-dns"
//
// add_identity userAssignedIdentity
// add_managed_identity_registry_credentials [ registry "my-registry.azurecr.io" "user" managedIdentity ]
//
//
// add_instances
// [
// containerInstance {
// name "httpserver"
// image "nginx:1.17.6-alpine"
// }
// ]
// link_to_vnet myVnet.ResourceId
// subnet "containers"
// }
//
//
//
// let deployment =
// arm {
// add_resources
// [
// containerGroup
//
// ]
// }
//
// System.Console.WriteLine(containerGroup.Dependencies)
//
// let jobj = deployment.Template |> Writer.toJson |> JObject.Parse
//
// let dnsConfig =
// jobj.SelectToken "resources[?(@.name=='container-group-with-custom-dns')].properties.dnsConfig"
//
// let nameservers = dnsConfig.SelectToken "nameServers"
// let searchDomains = dnsConfig.SelectToken "searchDomains"
// Expect.sequenceEqual nameservers [ JValue "8.8.8.8"; JValue "1.1.1.1" ] "Incorrect nameservers."
// Expect.equal searchDomains (JValue "example.com example.local") "Incorrect search domains."
// }

]
10 changes: 5 additions & 5 deletions src/Tests/Identity.fs
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,27 @@ let tests =

let userOnlyA =
{ ManagedIdentity.Empty with
UserAssigned = [ UserAssignedIdentity(userAssignedIdentities.resourceId "a") ]
UserAssigned = [ UserAssignedIdentity(LinkedResource.Managed (userAssignedIdentities.resourceId "a")) ]
}

let userOnlyB =
{ ManagedIdentity.Empty with
UserAssigned = [ UserAssignedIdentity(userAssignedIdentities.resourceId "b") ]
UserAssigned = [ UserAssignedIdentity(LinkedResource.Managed (userAssignedIdentities.resourceId "b")) ]
}

Expect.isTrue (userOnlyA + systemOnly).SystemAssigned.AsBoolean "Should have System Assigned on"

Expect.sequenceEqual
(userOnlyA + userOnlyB).UserAssigned
[
UserAssignedIdentity(userAssignedIdentities.resourceId "a")
UserAssignedIdentity(userAssignedIdentities.resourceId "b")
UserAssignedIdentity(LinkedResource.Managed (userAssignedIdentities.resourceId "a"))
UserAssignedIdentity(LinkedResource.Managed (userAssignedIdentities.resourceId "b"))
]
"User Assigned not added correctly"

Expect.sequenceEqual
(userOnlyA + userOnlyA).UserAssigned
[ UserAssignedIdentity(userAssignedIdentities.resourceId "a") ]
[ UserAssignedIdentity(LinkedResource.Managed (userAssignedIdentities.resourceId "a")) ]
"User Assigned duplicates exist"
}
test "Creates ARM JSON correctly" {
Expand Down

0 comments on commit b4e09e2

Please sign in to comment.