Skip to content

Commit

Permalink
Support for Azure RBAC for key vault data plane access. (#609)
Browse files Browse the repository at this point in the history
  • Loading branch information
ninjarobot authored Apr 23, 2021
1 parent 7994724 commit 9ddd87c
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 4 deletions.
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Release Notes
* Functions: Add option to use managed Key Vault
* Functions: Add support for dotnet-isolated runtime (NET5)
* KeyVault: Fix an issue with adding tags on main KeyVault builder.
* KeyVault: Support Azure RBAC for data plane access.
* 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
Expand Down
2 changes: 2 additions & 0 deletions docs/content/api-overview/resources/keyvault.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ The Key Vault builder contains access policies, secrets, and configuration infor
| disable_resource_manager_access | Disallows Resource Manager access to the vault. |
| enable_disk_encryption_access | Allows Azure Disk Encyption service access to the vault. |
| disable_disk_encryption_access | Disallows Azure Disk Encyption service access to the vault. |
| enable_rbac | Enables Azure role based access control for data access.
| disable_rbac | Disables Azure role based access control for data access.
| enable_soft_delete | Enables VM access to the vault. |
| enable_soft_delete_with_purge_protection | Disables VM access to the vault. |
| uri | Sets the URI of the vault. |
Expand Down
6 changes: 4 additions & 2 deletions src/Farmer/Arm/KeyVault.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ open Farmer
open Farmer.KeyVault
open System

let secrets = ResourceType ("Microsoft.KeyVault/vaults/secrets", "2018-02-14")
let vaults = ResourceType ("Microsoft.KeyVault/vaults", "2018-02-14")
let secrets = ResourceType ("Microsoft.KeyVault/vaults/secrets", "2019-09-01")
let vaults = ResourceType ("Microsoft.KeyVault/vaults", "2019-09-01")

module Vaults =
type Secret =
Expand Down Expand Up @@ -50,6 +50,7 @@ type Vault =
Uri : Uri option
Deployment : FeatureFlag option
DiskEncryption : FeatureFlag option
RbacAuthorization : FeatureFlag option
TemplateDeployment : FeatureFlag option
SoftDelete : SoftDeletionMode option
CreateMode : CreateMode option
Expand Down Expand Up @@ -89,6 +90,7 @@ type Vault =
enabledForDeployment = this.Deployment |> Option.map(fun f -> f.AsBoolean) |> Option.toNullable
enabledForDiskEncryption = this.DiskEncryption |> Option.map(fun f -> f.AsBoolean) |> Option.toNullable
enabledForTemplateDeployment = this.TemplateDeployment |> Option.map(fun f -> f.AsBoolean) |> Option.toNullable
enableRbacAuthorization = this.RbacAuthorization |> Option.map(fun f -> f.AsBoolean) |> Option.toNullable
enableSoftDelete =
match this.SoftDelete with
| None ->
Expand Down
19 changes: 17 additions & 2 deletions src/Farmer/Builders/Builders.KeyVault.fs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ type KeyVaultConfigSettings =
/// Specifies whether Azure Disk Encryption is permitted to retrieve secrets from the vault and unwrap keys.
AzureDiskEncryptionAccess : FeatureFlag option
/// Specifies whether Soft Deletion is enabled for the vault
SoftDelete : SoftDeletionMode option }
SoftDelete : SoftDeletionMode option
/// Specifies whether Azure role based authorization is used for data retrieval instead of any access policies on the key vault.
RbacAuthorization : FeatureFlag option }

type NetworkAcl =
{ IpRules : string list
Expand Down Expand Up @@ -105,6 +107,7 @@ type KeyVaultConfig =
TemplateDeployment = this.Access.ResourceManagerAccess
DiskEncryption = this.Access.AzureDiskEncryptionAccess
Deployment = this.Access.VirtualMachineAccess
RbacAuthorization = this.Access.RbacAuthorization
SoftDelete = this.Access.SoftDelete
CreateMode =
match this.Policies with
Expand Down Expand Up @@ -219,7 +222,13 @@ type KeyVaultBuilder() =
member __.Yield (_:unit) =
{ Name = ResourceName.Empty
TenantId = Subscription.TenantId
Access = { VirtualMachineAccess = None; ResourceManagerAccess = Some Enabled; AzureDiskEncryptionAccess = None; SoftDelete = None }
Access = {
VirtualMachineAccess = None
RbacAuthorization = None
ResourceManagerAccess = Some Enabled
AzureDiskEncryptionAccess = None
SoftDelete = None
}
Sku = Standard
NetworkAcl = { IpRules = []; VnetRules = []; Bypass = None; DefaultAction = None }
Policies = []
Expand Down Expand Up @@ -273,6 +282,12 @@ type KeyVaultBuilder() =
/// Disallows Azure Disk Encyption service access to the vault.
[<CustomOperation "disable_disk_encryption_access">]
member __.DisableDiskEncryptionAccess(state:KeyVaultBuilderState) = { state with Access = { state.Access with AzureDiskEncryptionAccess = Some Disabled } }
/// Enables Azure role based authentication for access to key vault data.
[<CustomOperation "enable_rbac">]
member __.EnableRbacAuthorization(state:KeyVaultBuilderState) = { state with Access = { state.Access with RbacAuthorization = Some Enabled } }
/// Disables Azure role based authentication for access to key vault data.
[<CustomOperation "disable_rbac">]
member __.DisableRbacAuthorization(state:KeyVaultBuilderState) = { state with Access = { state.Access with RbacAuthorization = Some Disabled } }
/// Enables VM access to the vault.
[<CustomOperation "enable_soft_delete">]
member __.EnableSoftDeletion(state:KeyVaultBuilderState) = { state with Access = { state.Access with SoftDelete = Some SoftDeletionOnly } }
Expand Down
46 changes: 46 additions & 0 deletions src/Tests/KeyVault.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ module KeyVault
open Expecto
open Farmer.Builders
open Farmer.KeyVault
open Farmer.Arm.RoleAssignment
open System
open Farmer
open Newtonsoft.Json.Linq

let tests = testList "KeyVault" [
test "Can create secrets without popping" {
Expand Down Expand Up @@ -66,4 +68,48 @@ let tests = testList "KeyVault" [
let vault = v.BuildResources Location.NorthEurope |> List.head :?> Farmer.Arm.KeyVault.Vault
Expect.sequenceEqual vault.Dependencies [ ResourceId.create(Arm.Web.sites, a.Name) ] "Web App dependency"
}

test "Create a basic key vault" {
let kv = keyVault {
name "my-test-kv-9876abcd"
}
let json =
let template =
arm {
add_resource kv
}
template.Template |> Writer.toJson
let jobj = JObject.Parse(json)
let kvName = jobj.SelectToken("resources[0].name")
Expect.equal kvName (JValue.CreateString "my-test-kv-9876abcd" :> JToken) "Incorrect name set on key vault"
}

test "Create a key vault with RBAC enabled" {
let kv = keyVault {
name "my-test-kv-9876rbac"
enable_rbac
}
let msi = createUserAssignedIdentity "kvUser"
let roleAssignment =
{ Name =
ArmExpression.create($"guid(concat(resourceGroup().id, '{Roles.KeyVaultReader.Id}'))")
.Eval()
|> ResourceName
RoleDefinitionId = Roles.KeyVaultReader
PrincipalId = msi.PrincipalId
PrincipalType = PrincipalType.ServicePrincipal
Scope = ResourceGroup
Dependencies = Set.empty }
let json =
let template =
arm {
add_resource kv
add_resource msi
add_resource roleAssignment
}
template.Template |> Writer.toJson
let jobj = JObject.Parse(json)
let enableRbac = jobj.SelectToken("resources[0].properties.enableRbacAuthorization")
Expect.isTrue (enableRbac.Value<bool>()) "RBAC was not enabled on the key vault"
}
]

0 comments on commit 9ddd87c

Please sign in to comment.