hashicorp / terraform-provider-azurerm

Terraform provider for Azure Resource Manager
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
Mozilla Public License 2.0
4.53k stars 4.61k forks source link

Enable just-in-time network access policies for VMs #3661

Open javisst opened 5 years ago

javisst commented 5 years ago

Community Note

Description

Just in time access is available to enable time-based access to dedicated virtual machines on configurable ports.

When just-in-time is enabled, Security Center locks down inbound traffic to your Azure VMs by creating an NSG rule. You select the ports on the VM to which inbound traffic will be locked down. These ports are controlled by the just-in-time solution. See https://docs.microsoft.com/en-us/azure/security-center/security-center-just-in-time.

I am not sure if this should be part of network security rules (or network security groups) or the virtual machine as this is deeply linked to both resources. As Set-AzJitNetworkAccessPolicy is attached to the VM this might be more suitable as JIT policy attached directly to a virtual machine instead of network group.

See Set-AzJitNetworkAccessPolicy https://docs.microsoft.com/en-us/powershell/module/az.security/set-azjitnetworkaccesspolicy?view=azps-2.2.0.

New or Affected Resource(s)

New:

Might be affected:

Potential Terraform Configuration

resource "azurerm_virtual_machine" "test" {
  name                  = "${var.prefix}-vm"
  location              = "${azurerm_resource_group.main.location}"
  resource_group_name   = "${azurerm_resource_group.main.name}"
  network_interface_ids = ["${azurerm_network_interface.main.id}"]
  vm_size               = "Standard_DS1_v2"
}

resource "azurerm_virtual_machine_jit_network_access_policy" "test" {
  name                 = "default"
  location             = azurerm_resource_group.main.location
  resource_group_name  = azurerm_resource_group.main.name
  virtual_machine_name = azurerm_virtual_machine.test.name
  kind                 = "Basic"

  jit_policy {
    port                        = 22
    protocol                    = "*"
    source_address_prefix       = "*"
    max_request_access_duration = "PT3H"
  }

  jit_policy {
    port                        = 3389
    protocol                    = "*"
    source_address_prefix       = "*"
    max_request_access_duration = "PT3H"
  }
}

References

tombuildsstuff commented 4 years ago

API reference: https://docs.microsoft.com/en-us/rest/api/securitycenter/jitnetworkaccesspolicies/createorupdate

egorchabala commented 4 years ago

Any chance to pick up this in upcoming releases?

riemers commented 2 years ago

There is an option to use the rest-api with the AzApi provider.

data "azapi_resource" "policy_data" {
  name      = "default"
  parent_id = "${var.resource_group_id}/providers/Microsoft.Security/locations/westeurope"
  type      = "Microsoft.Security/locations/jitNetworkAccessPolicies@2020-01-01"
}

Then making a new one:

resource "azapi_resource" "policy" {
  name      = "default"
  parent_id = "${var.resource_group_id}/providers/Microsoft.Security/locations/westeurope"
  type      = "Microsoft.Security/locations/jitNetworkAccessPolicies@2020-01-01"
  schema_validation_enabled = false
  body = local.body_jit_encoded_json
  depends_on = [
    data.azapi_resource.policy_data
  ]
}

Then you have to create the new json with the old one.

  body_jit_encoded_json = jsonencode({
    "name": "default"
    "location": "${var.location}"
    "properties": {
      "requests": jsondecode(data.azapi_resource.policy_data[0].output).properties.requests
      "virtualMachines":  concat([{
        "id": "/subscriptions/${var.arm_subscription_id}/resourceGroups/murex01-${var.short}-rg/providers/Microsoft.Compute/virtualMachines/${var.name}",
        "ports": [
          {
            "number": "22",
            "protocol": "TCP",
            "allowedSourceAddressPrefix": "10.0.0.0/8",
            "maxRequestAccessDuration": "PT3H"
          },
          {
            "number": "3389",
            "protocol": "TCP",
            "allowedSourceAddressPrefix": "10.0.0.0/8",
            "maxRequestAccessDuration": "PT3H"
          }
        ]
      }],jsondecode(data.azapi_resource.policy_data[0].output).properties.virtualMachines)

    }
  })

This does work, only my problem now if I do multiple servers at the same time it will grab the list of servers add the server to it and does so for the next server. So the first one will work but the second one will have duplicates. So i should not build this in the module but at the highest level after all the vm's are deployed. Since there is no option to add a single VM to the jit policy with overwriting everything. At this point I am stuck, almost there but stuck at the multiple servers issues. Perhaps someone knows a better call.

EliiseS commented 2 years ago

I ran into a few issues with @riemers code sample, since my resource group doesn't have a 'default' JIT policy in it without having previously created a JIT policy in that RG via the portal. The API also complained about a missing required type property (the docs do say it's not required though).

After some troubleshooting, I managed to apply JIT access policy to my new VM on azapi: v0.5.0 with:

resource "azapi_resource" "policy" {
  name      = "iot-edge-just-in-time-policy"
  parent_id = "${var.resource_group_id}/providers/Microsoft.Security/locations/${var.location}"
  type      = "Microsoft.Security/locations/jitNetworkAccessPolicies@2020-01-01"
  schema_validation_enabled = false
  body = jsonencode({
    "kind": "Basic"
    "properties": {
      "virtualMachines":  [{
        "id": "/subscriptions/${data.azurerm_subscription.current.subscription_id}/resourceGroups/${var.resource_group_name}/providers/Microsoft.Compute/virtualMachines/${var.edge_vm_name}",
        "ports": [
          {
            "number": "22",
            "protocol": "TCP",
            "allowedSourceAddressPrefix": "10.0.0.0/8",
            "maxRequestAccessDuration": "PT3H"
          },
          {
            "number": "3389",
            "protocol": "TCP",
            "allowedSourceAddressPrefix": "10.0.0.0/8",
            "maxRequestAccessDuration": "PT3H"
          }
        ]
      }]
    }
  })
}
jakeprice-me commented 1 year ago

I ran into a few issues with @riemers code sample, since my resource group doesn't have a 'default' JIT policy in it without having previously created a JIT policy in that RG via the portal. The API also complained about a missing required type property (the docs do say it's not required though).

After some troubleshooting, I managed to apply JIT access policy to my new VM on azapi: v0.5.0 with:

resource "azapi_resource" "policy" {
  name      = "iot-edge-just-in-time-policy"
  parent_id = "${var.resource_group_id}/providers/Microsoft.Security/locations/${var.location}"
  type      = "Microsoft.Security/locations/jitNetworkAccessPolicies@2020-01-01"
  schema_validation_enabled = false
  body = jsonencode({
    "kind": "Basic"
    "properties": {
      "virtualMachines":  [{
        "id": "/subscriptions/${data.azurerm_subscription.current.subscription_id}/resourceGroups/${var.resource_group_name}/providers/Microsoft.Compute/virtualMachines/${var.edge_vm_name}",
        "ports": [
          {
            "number": "22",
            "protocol": "TCP",
            "allowedSourceAddressPrefix": "10.0.0.0/8",
            "maxRequestAccessDuration": "PT3H"
          },
          {
            "number": "3389",
            "protocol": "TCP",
            "allowedSourceAddressPrefix": "10.0.0.0/8",
            "maxRequestAccessDuration": "PT3H"
          }
        ]
      }]
    }
  })
}

This works great, but I had to remove the quotes around the port number 22, to stop Terraform wanting to update in place on each apply šŸ‘

resource "azapi_resource" "policy" {
  name      = "main-vm-just-in-time-policy"
  parent_id = "${azurerm_resource_group.main.id}/providers/Microsoft.Security/locations/${azurerm_resource_group.main.location}"
  type      = "Microsoft.Security/locations/jitNetworkAccessPolicies@2020-01-01"
  schema_validation_enabled = false
  body = jsonencode({
    "kind": "Basic"
    "properties": {
      "virtualMachines":  [{
        "id": "/subscriptions/${var.subscription_id}/resourceGroups/${azurerm_resource_group.main.name}/providers/Microsoft.Compute/virtualMachines/${azurerm_linux_virtual_machine.main.name}",
        "ports": [
          {
            "number": 22,
            "protocol": "TCP",
            "allowedSourceAddressPrefix": "10.0.0.0/8",
            "maxRequestAccessDuration": "PT3H"
          }
        ]
      }]
    }
  })
}

Also, if you don't have any idea what the P3TH value means for maxRequestAccessDuration this section on Wikipedia about ISO8601 should make it clearer.

aristosvo commented 1 year ago

@njuCZ Have you had a proper follow-up with the Network/Networking API team based on https://github.com/hashicorp/terraform-provider-azurerm/pull/10326#issuecomment-795011684 / https://github.com/hashicorp/terraform-provider-azurerm/pull/10326#issuecomment-796387665?

I was wondering if we could move implemetation a bit forward :)

825i commented 7 months ago

I am not sure if this should be part of network security rules (or network security groups) or the virtual machine as this is deeply linked to both resources. As Set-AzJitNetworkAccessPolicy is attached to the VM this might be more suitable as JIT policy attached directly to a virtual machine instead of network group.

See Set-AzJitNetworkAccessPolicy https://docs.microsoft.com/en-us/powershell/module/az.security/set-azjitnetworkaccesspolicy?view=azps-2.2.0.

New or Affected Resource(s)

New:

  • azurerm_virtual_machine_jit_network_access_policy

Might be affected:

  • azurerm_virtual_machine
  • azurerm_network_security_group
  • azurerm_network_security_rule

Potential Terraform Configuration

resource "azurerm_virtual_machine" "test" {
  name                  = "${var.prefix}-vm"
  location              = "${azurerm_resource_group.main.location}"
  resource_group_name   = "${azurerm_resource_group.main.name}"
  network_interface_ids = ["${azurerm_network_interface.main.id}"]
  vm_size               = "Standard_DS1_v2"
}

resource "azurerm_virtual_machine_jit_network_access_policy" "test" {
  name                 = "default"
  location             = azurerm_resource_group.main.location
  resource_group_name  = azurerm_resource_group.main.name
  virtual_machine_name = azurerm_virtual_machine.test.name
  kind                 = "Basic"

  jit_policy {
    port                        = 22
    protocol                    = "*"
    source_address_prefix       = "*"
    max_request_access_duration = "PT3H"
  }

  jit_policy {
    port                        = 3389
    protocol                    = "*"
    source_address_prefix       = "*"
    max_request_access_duration = "PT3H"
  }
}

References

So this doesn't work. GPT hallucinated based on this ticket that the function has been added. Here's the output I got via Terraform cloud. It would be really nice if this was pushed along as it seems there is an api for this.

Error: Invalid resource type
on vm_sql.tf line 8, in resource "azurerm_security_center_just_in_time_vm_access_policy" "sql_jit_policy":
resource "azurerm_security_center_just_in_time_vm_access_policy" "sql_jit_policy" {
The provider hashicorp/azurerm does not support resource type "azurerm_security_center_just_in_time_vm_access_policy".

When trying to add this policy for a SQL VM.