Skip to content

Commit

Permalink
Merge pull request #1131 from ninjarobot/aks-fips-and-workload-identity
Browse files Browse the repository at this point in the history
Managed Clusters (AKS): Support for workload identity, OIDC issuer, image cleaner, and Defender.
  • Loading branch information
ninjarobot authored Aug 8, 2024
2 parents c397361 + 862a73b commit 55f08f6
Show file tree
Hide file tree
Showing 9 changed files with 340 additions and 47 deletions.
5 changes: 5 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Release Notes
=============

## 1.9.1
* Managed Clusters (AKS): Support for workload identity, OIDC issuer, image cleaner, and Defender.
* Managed Clusters (AKS): Default to use MSI for the service principal profile to align with CLI and Portal.
* User Assigned Identities: Support for `depends_on`.

## 1.9.0
* PostgreSQL: Support for Flexible Servers.
* Virtual Machines: Includes Ubuntu 24.04 LTS images.
Expand Down
69 changes: 39 additions & 30 deletions docs/content/api-overview/resources/aks-cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,39 +13,48 @@ The AKS Cluster builder is used to create AKS clusters.
#### AKS Builder Keywords
The AKS builder (`aks`) constructs AKS clusters.

| Keyword | Purpose |
|-|-|
| name | Sets the name of the AKS cluster. |
| dns_prefix | Sets the DNS prefix of the AKS cluster. |
| enable_private_cluster | Restricts the cluster's Kubernetes API to only be accessible from private networks. |
| enable_rbac | Enable Kubernetes Role-Based Access Control. |
| 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. |
| kubelet_identity | Assigns a user assigned identity to the kubelet user that pulls container images. |
| 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. |
| service_principal_use_msi | Enables the AKS cluster to use the managed identity service principal instead of an external client secret. |
| windows_username | Sets the windows admin username for the AKS cluster. |
| add_api_server_authorized_ip_ranges | Adds IP address CIDR ranges to be allowed Kubernetes API access. |
| addon | A list with the configuration of all addons on the cluster (AciConnectorLinux, HttpApplicationRouting, KubeDashboard, IngressApplicationGateway, OmsAgent). |
| Keyword | Purpose |
|-------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|
| name | Sets the name of the AKS cluster. |
| dns_prefix | Sets the DNS prefix of the AKS cluster. |
| enable_defender | Enables Defender for the containers running in the cluster. |
| enable_image_cleaner | Enables a service to periodically purge images that are no longer used. |
| enable_private_cluster | Restricts the cluster's Kubernetes API to only be accessible from private networks. |
| enable_rbac | Enable Kubernetes Role-Based Access Control. |
| enable_workload_identity | Enables workload identity to assign a pod to a managed identity. Requires OIDC, so enables that as well. |
| oidc_issuer | Enables or disables the OIDC issuer service for issuing tokens for federated identity. |
| 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. |
| kubelet_identity | Assigns a user assigned identity to the kubelet user that pulls container images. |
| 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. |
| service_principal_use_msi | Enables the AKS cluster to use the managed identity service principal instead of an external client secret. |
| windows_username | Sets the windows admin username for the AKS cluster. |
| add_api_server_authorized_ip_ranges | Adds IP address CIDR ranges to be allowed Kubernetes API access. |
| addon | A list with the configuration of all addons on the cluster (AciConnectorLinux, HttpApplicationRouting, KubeDashboard, IngressApplicationGateway, OmsAgent). |

##### Configuration Members

* `OidcIssuerUrl` - the configuration built by the `aks` builder uses this property to provide an ARM expression to reference the OIDC Issuer URL on the managed cluster, if enabled.

#### Agent Pool Builder keywords
The Agent Pool builder (`agentPool`) constructs agent pools in the AKS cluster.

| Keyword | Purpose |
|-|-|
| name | Sets the name of the agent pool. |
| count | Sets the count of VM's in the agent pool. |
| user_mode | Sets the agent pool to user mode. |
| disk_size | Sets the disk size for the VM's in the agent pool. |
| max_pods | Sets the maximum number of pods in the agent pool. |
| os_type | Sets the OS type of the VM's in the agent pool. |
| subnet | Sets the name of a virtual network subnet where this AKS cluster should be attached. |
| vm_size | Sets the size of the VM's in the agent pool. |
| vnet | Sets the name of a virtual network in the same region where this AKS cluster should be attached. |
| Keyword | Purpose |
|-------------|--------------------------------------------------------------------------------------------------|
| name | Sets the name of the agent pool. |
| count | Sets the count of VM's in the agent pool. |
| user_mode | Sets the agent pool to user mode. |
| disk_size | Sets the disk size for the VM's in the agent pool. |
| enable_fips | Uses a FIPS compliant OS image for VM's in the agent pool. |
| max_pods | Sets the maximum number of pods in the agent pool. |
| os_type | Sets the OS type of the VM's in the agent pool. |
| subnet | Sets the name of a virtual network subnet where this AKS cluster should be attached. |
| vm_size | Sets the size of the VM's in the agent pool. |
| vnet | Sets the name of a virtual network in the same region where this AKS cluster should be attached. |

#### Kubenet Builder
The Kubenet builder (`kubenetNetworkProfile`) creates Kubenet network profiles on the AKS cluster.
Expand All @@ -66,7 +75,7 @@ The CNI builder (`azureCniNetworkProfile`) creates Azure CNI network profiles on

#### Basic Example

The simplest cluster uses a system assigned managed identity and
The simplest cluster uses a system assigned managed identity and
default settings for the node pool (size of 3).

```fsharp
Expand Down
63 changes: 62 additions & 1 deletion src/Farmer/Arm/ContainerService.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ open Farmer.Identity
open Farmer.Vm

let managedClusters =
ResourceType("Microsoft.ContainerService/managedClusters", "2021-03-01")
ResourceType("Microsoft.ContainerService/managedClusters", "2024-02-01")

module AddonProfiles =
type AciConnectorLinux = {
Expand Down Expand Up @@ -137,6 +137,29 @@ type ManagedClusterIdentityProfile = {

member internal this.Dependencies = [ this.KubeletIdentity ] |> List.choose id

type OidcIssuerProfile = { Enabled: FeatureFlag }

type SecurityProfileSettings = {
Defender:
{|
SecurityMonitoring: FeatureFlag
LogAnalyticsResourceId: ResourceId option
|} option
// intervalHours: minimum 24 hours, default one week, maximum 3 months
ImageCleanerSettings:
{|
Enabled: FeatureFlag
Interval: System.TimeSpan
|} option
WorkloadIdentity: FeatureFlag option
} with

static member Default = {
Defender = None
ImageCleanerSettings = None
WorkloadIdentity = None
}

type ManagedCluster = {
Name: ResourceName
Location: Location
Expand All @@ -148,6 +171,7 @@ type ManagedCluster = {
{|
Name: ResourceName
Count: int
EnableFIPS: FeatureFlag option
MaxPods: int option
Mode: AgentPoolMode
OsDiskSize: int<Gb>
Expand Down Expand Up @@ -178,6 +202,8 @@ type ManagedCluster = {
LoadBalancerSku: LoadBalancer.Sku option
ServiceCidr: IPAddressCidr option
|} option
OidcIssuerProfile: OidcIssuerProfile option
SecurityProfile: SecurityProfileSettings option
WindowsProfile:
{|
AdminUserName: string
Expand Down Expand Up @@ -248,6 +274,7 @@ type ManagedCluster = {
else
agent.Name.Value.ToLowerInvariant()
count = agent.Count
enableFIPS = agent.EnableFIPS |> Option.mapBoxed _.AsBoolean
maxPods = agent.MaxPods |> Option.toNullable
mode = agent.Mode |> string
osDiskSizeGB = agent.OsDiskSize
Expand Down Expand Up @@ -301,6 +328,40 @@ type ManagedCluster = {
networkProfile.ServiceCidr |> Option.map IPAddressCidr.format |> Option.toObj
|}
| None -> Unchecked.defaultof<_>
oidcIssuerProfile =
match this.OidcIssuerProfile with
| None -> Unchecked.defaultof<_>
| Some oidc -> {| enabled = oidc.Enabled.AsBoolean |}
securityProfile =
match this.SecurityProfile with
| None -> Unchecked.defaultof<_>
| Some profile -> {|
defender =
profile.Defender
|> Option.map (fun defender -> {|
logAnalyticsWorkspaceResourceId =
defender.LogAnalyticsResourceId
|> Option.map (_.ArmExpression.Eval())
|> Option.toObj
securityMonitoring = {|
enabled = defender.SecurityMonitoring.AsBoolean
|}
|})
|> Option.defaultValue Unchecked.defaultof<_>
imageCleaner =
profile.ImageCleanerSettings
|> Option.map (fun imageCleaner -> {|
enabled = imageCleaner.Enabled.AsBoolean
intervalHours = imageCleaner.Interval.TotalHours
|})
|> Option.defaultValue Unchecked.defaultof<_>
workloadIdentity =
profile.WorkloadIdentity
|> Option.map (fun workloadIdentity -> {|
enabled = workloadIdentity.AsBoolean
|})
|> Option.defaultValue Unchecked.defaultof<_>
|}
servicePrincipalProfile = {|
clientId = this.ServicePrincipalProfile.ClientId
secret =
Expand Down
3 changes: 2 additions & 1 deletion src/Farmer/Arm/ManagedIdentity.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ let federatedIdentityCredentials =

type UserAssignedIdentity = {
Name: ResourceName
Dependencies: ResourceId Set
Location: Location
Tags: Map<string, string>
} with
Expand All @@ -20,7 +21,7 @@ type UserAssignedIdentity = {
member this.ResourceId = userAssignedIdentities.resourceId this.Name

member this.JsonModel =
userAssignedIdentities.Create(this.Name, this.Location, [], this.Tags)
userAssignedIdentities.Create(this.Name, this.Location, this.Dependencies, this.Tags)

/// A federated identity credential from an OpenId Connect issuer.
type FederatedIdentityCredential = {
Expand Down
Loading

0 comments on commit 55f08f6

Please sign in to comment.