Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turn on System Identity by default. #592

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ Release Notes
* Container Groups: Support for liveliness and readiness probes on containers.
* Container Groups: Connect network profile to an existing virtual network.
* Container Groups: Bugfix for outputs.
* Container Groups: System Identity now on by default.
* AKS: System Identity now on by default.
* Event Grid: Ensure destination Queues are created as a dependency
* Event Grid: Add ServiceBus Queue and Topic as supported destinations
* Functions: System Identity now on by default.
* Functions: Support for 64 bits.
* Functions: Add option to use managed Key Vault
* KeyVault: Fix an issue with adding tags on main KeyVault builder.
* ServiceBus: update namespace validation rules to follow [Microsoft documentation](https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/resource-name-rules#microsoftservicebus)
* Storage: Add support for tables
* Web App: Disables the automatic addition of the logging site extension when `docker_image` is used
* Web App: Add dotnet 5.0 runtime option
* Web App: System Identity now on by default.

* Framework: Updated DeterministicGuid for RFC 4122 compatibility
* Framework: Add support for NET5, upgrade to F#5.
Expand Down
2 changes: 1 addition & 1 deletion docs/content/api-overview/resources/aks-cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The AKS Builder constructs AKS clusters.
| add_agent_pools | Adds agent pools to the AKS cluster. |
| add_agent_pool | Adds an agent pool to the AKS cluster. |
| add_identity | Adds a managed identity to the the AKS cluster. |
| system_identity | Activates the system identity of the AKS cluster. |
| system_identity | Turns the system identity of the AKS cluster on or off (on by default). |
| network_profile | Sets the network profile for the AKS cluster. |
| linux_profile | Sets the linux profile for the AKS cluster. |
| service_principal_client_id | Sets the client id of the service principal for the AKS cluster. |
Expand Down
2 changes: 1 addition & 1 deletion docs/content/api-overview/resources/container-group.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ The Container Group builder is used to create Azure Container Group instances.
| containerGroup | private_ip | Indicates the container should use a system-assigned private IP address for use in a virtual network. |
| containerGroup | network_profile | Name of a network profile resource for the subnet in a virtual network where the container group will attach. |
| containerGroup | add_identity | Adds a managed identity to the the container group. |
| containerGroup | system_identity | Activates the system identity of the container group. |
| containerGroup | system_identity | Turns the system identity of the container group on or off (on by default). |
| containerGroup | add_registry_credentials | Adds a container image registry credential with a secure parameter for the password. |
| containerGroup | add_tcp_port | Adds a TCP port to be externally accessible. |
| containerGroup | add_udp_port | Adds a UDP port to be externally accessible. |
Expand Down
2 changes: 1 addition & 1 deletion docs/content/api-overview/resources/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ The Functions builder is used to create Azure Functions accounts. It abstracts t
| enable_cors | Enables CORS support for the app. Either specify AllOrigins or a list of valid URIs. |
| enable_cors_credentials | Allows CORS requests with credentials. |
| add_identity | Adds a managed identity to the the Function App. |
| system_identity | Activates the system identity of the Function App. |
| system_identity | Turns the system identity of the functions app on or off (on by default). |
| always_on | Stops the app from sleeping if idle for a few minutes of inactivity. |
| worker_process | Specifies whether to set the app to 32 or 64 Bitness. |

Expand Down
1 change: 0 additions & 1 deletion docs/content/api-overview/resources/managed-identity.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ open Farmer.Builders

let wa = webApp {
name "myApp"
system_identity // turn on the system identity of the web app
}

let vault = keyVault {
Expand Down
5 changes: 2 additions & 3 deletions docs/content/api-overview/resources/web-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ The Web App builder is used to create Azure App Service accounts. It abstracts t
| Web App | docker_ci | Turns on continuous integration of the web app from the Docker source repository using a webhook.
| Web App | docker_use_azure_registry | Uses the supplied Azure Container Registry name as the source of the Docker image, instead of Docker Hub. You do not need to specify the full url, but just the name of the registry itself.
| Web App | add_identity | Adds a managed identity to the the Web App. Farmer will automatically set the AZURE_CLIENT_ID application setting to the Client Id of the supplied identity. |
| Web App | system_identity | Activates the system identity of the Web App. |
| Web App | system_identity | Turns the system identity of the web app on or off (on by default). |
| Web App | enable_cors | Enables CORS support for the app. Either specify `WebApp.AllOrigins` or a list of valid URIs as strings. |
| Web App | enable_cors_credentials | Allows CORS requests with credentials. |
| Web App | source_control | Given a github repository URI and branch name, configures the web app to automatically deploy those files to the web app |
Expand Down Expand Up @@ -74,7 +74,7 @@ The Web App builder contains special commands that are executed *after* the ARM
| PublishingPassword | Gets the ARM expression path to the publishing password of this web app. |
| ServicePlan | Gets the Resource Name of the service plan for this web app. |
| AppInsights | Gets the Resource Name of the service plan for the AI resource linked to this web app. |
| SystemIdentity | Gets the system-created managed principal for the web app. It must have been enabled using the system_identity keyword. |
| SystemIdentity | Gets the system-created managed principal for the web app. |

#### Key Vault integration
The Web App builder comes with special integration into KeyVault. By activating KeyVault integration, the web app builder can automatically link to, or even create, a full KeyVault instance. All Secret or ARM Expression-based Settings (e.g. a setting that links to the Key of a Storage Account) will automatically be redirected to KeyVault. The value will be stored in KeyVault and the system identity will be activated and provided into the KeyVault with GET permissions. Lastly, Web App app settings will remain in place, using the Azure App Service built-in KeyVault redirection capabilities.
Expand Down Expand Up @@ -106,7 +106,6 @@ let myWebApp = webApp {
worker_size Medium
number_of_workers 3
run_from_package
system_identity
}
```

Expand Down
5 changes: 0 additions & 5 deletions docs/content/tutorials/web-storage-keyvault.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ let secretsvault = keyVault {
Now we have KeyVault grant permission to the web app:

```fsharp
let webapplication = webApp {
...
system_identity
}

let secretsvault = keyVault {
...
add_access_policy (AccessPolicy.create webapplication.SystemIdentity)
Expand Down
1 change: 0 additions & 1 deletion samples/scripts/tutorials/webapp-keyvault.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ let datastore = storageAccount {

let webapplication = webApp {
name "isaacsuperweb"
system_identity
link_to_keyvault (ResourceName vaultName)
secret_setting secretName
}
Expand Down
4 changes: 2 additions & 2 deletions src/Farmer/Builders/Builders.ContainerGroups.fs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ type ContainerGroupBuilder() =
{ Name = ResourceName.Empty
OperatingSystem = Linux
RestartPolicy = AlwaysRestart
Identity = ManagedIdentity.Empty
Identity = ManagedIdentity.AssignedOnly
ImageRegistryCredentials = []
InitContainers = []
IpAddress = None
Expand Down Expand Up @@ -239,7 +239,7 @@ type ContainerGroupBuilder() =
member _.AddIdentity(state:ContainerGroupConfig, identity:UserAssignedIdentity) = { state with Identity = state.Identity + identity }
member this.AddIdentity(state, identity:UserAssignedIdentityConfig) = this.AddIdentity(state, identity.UserAssignedIdentity)
[<CustomOperation "system_identity">]
member _.SystemIdentity(state:ContainerGroupConfig) = { state with Identity = { state.Identity with SystemAssigned = Enabled } }
member _.SystemIdentity(state:ContainerGroupConfig, on) = { state with Identity = { state.Identity with SystemAssigned = FeatureFlag.ofBool on } }
interface ITaggable<ContainerGroupConfig> with member _.Add state tags = { state with Tags = state.Tags |> Map.merge tags }

/// Creates an image registry credential with a generated SecureParameter for the password.
Expand Down
4 changes: 3 additions & 1 deletion src/Farmer/Builders/Builders.ContainerService.fs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ type AksBuilder() =
AgentPools = []
DnsPrefix = ""
EnableRBAC = false
Identity = ManagedIdentity.Empty
Identity = ManagedIdentity.AssignedOnly
LinuxProfile = None
NetworkProfile = None
ServicePrincipalClientID = None
Expand All @@ -181,6 +181,8 @@ type AksBuilder() =
[<CustomOperation "add_identity">]
member _.AddIdentity(state:AksConfig, identity:UserAssignedIdentity) = { state with Identity = state.Identity + identity }
member this.AddIdentity(state, identity:UserAssignedIdentityConfig) = this.AddIdentity(state, identity.UserAssignedIdentity)
[<CustomOperation "system_identity">]
member _.SystemIdentity(state:AksConfig, on) = { state with Identity = { state.Identity with SystemAssigned = FeatureFlag.ofBool on } }
/// Adds agent pools to the AKS cluster.
[<CustomOperation "add_agent_pools">]
member _.AddAgentPools(state:AksConfig, pools) = { state with AgentPools = state.AgentPools @ pools }
Expand Down
2 changes: 1 addition & 1 deletion src/Farmer/Builders/Builders.Functions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ type FunctionsBuilder() =
OperatingSystem = Windows
Settings = Map.empty
Dependencies = Set.empty
Identity = ManagedIdentity.Empty
Identity = ManagedIdentity.AssignedOnly
SecretStore = AppService
Tags = Map.empty
ZipDeployPath = None
Expand Down
7 changes: 4 additions & 3 deletions src/Farmer/Builders/Builders.WebApp.fs
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ type WebAppBuilder() =
ServicePlan = derived (fun name -> serverFarms.resourceId (name-"farm"))
AppInsights = Some (derived (fun name -> components.resourceId (name-"ai")))
Settings = Map.empty
Identity = ManagedIdentity.Empty
Identity = ManagedIdentity.AssignedOnly
Cors = None
OperatingSystem = Windows
ZipDeployPath = None
Expand Down Expand Up @@ -630,9 +630,10 @@ module Extensions =
|> this.Wrap state
member this.AddIdentity (state, identity:UserAssignedIdentityConfig) = this.AddIdentity(state, identity.UserAssignedIdentity)
[<CustomOperation "system_identity">]
member this.SystemIdentity (state:'T) =
member this.SystemIdentity (state:'T, on) =
let current = this.Get state
{ current with Identity = { current.Identity with SystemAssigned = Enabled } }
{ current with
Identity = { current.Identity with SystemAssigned = FeatureFlag.OfBoolean on } }
|> this.Wrap state
/// sets the list of origins that should be allowed to make cross-origin calls. Use AllOrigins to allow all.
[<CustomOperation "enable_cors">]
Expand Down
1 change: 1 addition & 0 deletions src/Farmer/Common.fs
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,7 @@ module Identity =
UserAssigned : UserAssignedIdentity list }
member this.Dependencies = this.UserAssigned |> List.map(fun u -> u.ResourceId)
static member Empty = { SystemAssigned = Disabled; UserAssigned = [] }
static member AssignedOnly = { ManagedIdentity.Empty with SystemAssigned = Enabled }
static member (+) (a, b) =
{ SystemAssigned = (a.SystemAssigned.AsBoolean || b.SystemAssigned.AsBoolean) |> FeatureFlag.ofBool
UserAssigned = a.UserAssigned @ b.UserAssigned |> List.distinct }
Expand Down
1 change: 1 addition & 0 deletions src/Farmer/Types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ module ResourceRef =
type FeatureFlag =
| Enabled | Disabled
member this.AsBoolean = match this with Enabled -> true | Disabled -> false
static member OfBoolean = function true -> Enabled | false -> Disabled
member this.ArmValue = match this with Enabled -> "Enabled" | Disabled -> "Disabled"

module FeatureFlag =
Expand Down
3 changes: 1 addition & 2 deletions src/Tests/ContainerGroup.fs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,6 @@ let tests = testList "Container Group" [
containerGroup {
name "myapp"
add_instances [ nginx ]
system_identity
} |> asAzureResource

Expect.isTrue group.Identity.Type.HasValue "Expecting an assigned identity."
Expand Down Expand Up @@ -420,7 +419,7 @@ let tests = testList "Container Group" [
let jobj = Newtonsoft.Json.Linq.JObject.Parse(json)
let subnetId = jobj.SelectToken("..subnet.id") |> string
let expectedSubnetId = "[resourceId('other-res-group', 'Microsoft.Network/virtualNetworks/subnets', 'containerNet', 'ContainerSubnet')]"
Expect.equal subnetId expectedSubnetId "Generated incorrect subnet ID."
Expect.equal subnetId expectedSubnetId "Generated incorrect subnet ID."
}
test "Can link a network profile directly to a container group" {
let profile = networkProfile { name "netprofile" }
Expand Down
6 changes: 3 additions & 3 deletions src/Tests/Functions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ let tests = testList "Functions tests" [
Expect.stringContains site.AppSettings.["AzureWebJobsDashboard"].Value "foo" "Web Jobs Dashboard setting should have storage account name"
}
test "Handles identity correctly" {
let f : Site = functions { name "" } |> getResourceAtIndex 0
let f : Site = functions { system_identity false } |> getResourceAtIndex 0
Expect.equal f.Identity.Type (Nullable ManagedServiceIdentityType.None) "Incorrect default managed identity"
Expect.isNull f.Identity.UserAssignedIdentities "Incorrect default managed identity"

let f : Site = functions { system_identity } |> getResourceAtIndex 0
let f : Site = functions { name "" } |> getResourceAtIndex 0
Expect.equal f.Identity.Type (Nullable ManagedServiceIdentityType.SystemAssigned) "Should have system identity"
Expect.isNull f.Identity.UserAssignedIdentities "Should have no user assigned identities"

let f : Site = functions { system_identity; add_identity (createUserAssignedIdentity "test"); add_identity (createUserAssignedIdentity "test2") } |> getResourceAtIndex 0
let f : Site = functions { name ""; add_identity (createUserAssignedIdentity "test"); add_identity (createUserAssignedIdentity "test2") } |> getResourceAtIndex 0
Expect.equal f.Identity.Type (Nullable ManagedServiceIdentityType.SystemAssignedUserAssigned) "Should have system identity"
Expect.sequenceEqual (f.Identity.UserAssignedIdentities |> Seq.map(fun r -> r.Key)) [ "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'test2')]"; "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'test')]" ] "Should have two user assigned identities"

Expand Down
6 changes: 3 additions & 3 deletions src/Tests/WebApp.fs
Original file line number Diff line number Diff line change
Expand Up @@ -203,15 +203,15 @@ let tests = testList "Web App Tests" [
}

test "Handles identity correctly" {
let wa : Site = webApp { name "" } |> getResourceAtIndex 0
let wa : Site = webApp { system_identity false } |> getResourceAtIndex 0
Expect.equal wa.Identity.Type (Nullable ManagedServiceIdentityType.None) "Incorrect default managed identity"
Expect.isNull wa.Identity.UserAssignedIdentities "Should be no user assigned identities"

let wa : Site = webApp { system_identity } |> getResourceAtIndex 0
let wa : Site = webApp { name "" } |> getResourceAtIndex 0
Expect.equal wa.Identity.Type (Nullable ManagedServiceIdentityType.SystemAssigned) "Should have system identity"
Expect.isNull wa.Identity.UserAssignedIdentities "Should have no user assigned identities"

let wa : Site = webApp { system_identity; add_identity (createUserAssignedIdentity "test"); add_identity (createUserAssignedIdentity "test2") } |> getResourceAtIndex 0
let wa : Site = webApp { name ""; add_identity (createUserAssignedIdentity "test"); add_identity (createUserAssignedIdentity "test2") } |> getResourceAtIndex 0
Expect.equal wa.Identity.Type (Nullable ManagedServiceIdentityType.SystemAssignedUserAssigned) "Should have system identity"
Expect.sequenceEqual (wa.Identity.UserAssignedIdentities |> Seq.map(fun r -> r.Key)) [ "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'test2')]"; "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'test')]" ] "Should have two user assigned identities"
Expect.contains (wa.SiteConfig.AppSettings |> Seq.map(fun s -> s.Name, s.Value)) ("AZURE_CLIENT_ID", "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'test2')).clientId]") "Missing AZURE_CLIENT_ID"
Expand Down
2 changes: 1 addition & 1 deletion src/Tests/test-data/diagnostics.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"[resourceId('Microsoft.Web/serverfarms', 'isaacdiagsuperweb-farm')]"
],
"identity": {
"type": "None"
"type": "SystemAssigned"
},
"kind": "app",
"location": "northeurope",
Expand Down
6 changes: 3 additions & 3 deletions src/Tests/test-data/lots-of-resources.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
"[resourceId('Microsoft.Web/serverfarms', 'farmerwebapp1979-farm')]"
],
"identity": {
"type": "None"
"type": "SystemAssigned"
},
"kind": "app",
"location": "northeurope",
Expand Down Expand Up @@ -211,7 +211,7 @@
"[resourceId('Microsoft.Web/serverfarms', 'farmerfuncs1979-farm')]"
],
"identity": {
"type": "None"
"type": "SystemAssigned"
},
"kind": "functionapp",
"location": "northeurope",
Expand Down Expand Up @@ -395,7 +395,7 @@
"apiVersion": "2019-12-01",
"dependsOn": [],
"identity": {
"type": "None"
"type": "SystemAssigned"
},
"location": "northeurope",
"name": "farmeraci1979",
Expand Down