# CIS Compliant Images

# Overview



# Requirements Definition

# Organization Core

# Checklist

### Compliance

#### Repositories &amp; Workflow Overview

- [ ] create source control elements 
    - [ ] create 01-01-Compliance Base Infrastructure repository 
        - [ ] workflow to run terraform on merge into main
    - [ ] create 01-02-Build Infrastructure repository 
        - [ ] workflow to run when new build requested
        - [ ] build infrastructure persists for fixed period
        - [ ] scheduled workflow checks whether to destroy
    - [ ] create 01-03-Definitions repository  
        
        - [ ] PR validates sources
        - [ ] PR test build
        - [ ] workflow run on updates to main

Base Infrastructure

- [ ] Subscription 
    - [ ] Service Principal
    - [ ] Resource Group 
        - [ ] Key Vault
        - [ ] Storage Account
        - [ ] Image Gallery

<details id="bkmrk-image-gallery-%C2%A0-terr"><summary>Image Gallery</summary>

```
terraform {
    backend "azurerm" {
        subscription_id = "625b66d7-5b11-40fb-99ab-ba303c13ea88"
        resource_group_name = "tf_state"
        storage_account_name = "continobakerytfstate"
        container_name = "example"
        key = "secops-infrastructure.tfstate"
    }
}
```

```
locals {
    ## details for creating rhe new additional shared image gallery in a new resource group (f enabled)
    location = "uksouth"
    shared_image_gallery_name = "secops_base_images"
    shared_image_gallery_resource_group_name = "secops_base_images-rg"
    shared_image_gallery_resource_group_create = true
    contributor_role_create = false
    reader_role_create = false
    managed_image_resource_group_name = "secops_base_images-rg"
}
```

```
data "azurerm_client_config" "current" {}

resource "azurerm_resource_group" "shared_image_gallery" {
  count = var.shared_image_gallery_resource_group_create == true ? 1 : 0
  
  name     = var.shared_image_gallery_resource_group_name
  location = var.location
}

data "azurerm_resource_group" "shared_image_gallery" {  
  name     = var.shared_image_gallery_resource_group_name

  depends_on = [ azurerm_resource_group.shared_image_gallery]
}

resource "azurerm_shared_image_gallery" "shared_image_gallery" {
  name                = var.shared_image_gallery_name
  resource_group_name = data.azurerm_resource_group.shared_image_gallery.name
  location            = data.azurerm_resource_group.shared_image_gallery.location
  description         = "Shared Images Gallery to store VMSS deployment images"

  lifecycle { ignore_changes = [ tags, ] }
}
```

</details>Build Infrastructure

- [ ] Build Resource Group 
    - [ ] vNet
    - [ ] Subnet
    - [ ] NSG
    - [ ] Storage Account

<details id="bkmrk-packer-build-persist"><summary>Packer Build Persisten Resources</summary>

```
## Build Image Factory Setup
## this variable file has been populated with all possible variables that could be required by any configuration
## ity is intended to take use input varaiables and use logic with locals to determine either a user set name or 
## programatically created variable names - depending on the direction we take
variable "location" { default = "uksouth" }
variable "packer_build_resource_group_name" {}
variable "packer_build_resource_group_create" { default = true }
variable "packer_build_vnet_name" { }
variable "packer_build_vnet_address_space" { default = [ "10.0.0.0/16", ]  }
variable "packer_build_vnet_create" { default = true }
variable "packer_build_subnet_name" { default = "packer_build" }
variable "packer_build_subnet_addresses" { default = [ "10.0.1.0/24", ] }
variable "packer_build_subnet_create" { default = true }
```

```
resource "azurerm_resource_group" "packer_build" {
  #ts:skip=accurics.azure.NS.272 Nolock is required as resources will be temporary
  count = var.packer_build_resource_group_create == true ? 1 : 0

  name     = var.packer_build_resource_group_name
  location = var.location
}


resource "azurerm_virtual_network" "packer_build" {
  count = var.packer_build_vnet_create == true ? 1 : 0

  name                = var.packer_build_vnet_name
  address_space       = var.packer_build_vnet_address_space
  location            = var.location
  resource_group_name = var.packer_build_resource_group_name

  depends_on = [ azurerm_resource_group.packer_build, data.azurerm_resource_group.packer_build]

}

data "azurerm_resource_group" "packer_build" {
  name     = var.packer_build_resource_group_name
  depends_on  = [ azurerm_resource_group.packer_build ]
}


data "azurerm_virtual_network" "packer_build" {
  name                = var.packer_build_vnet_name
  resource_group_name = var.packer_build_resource_group_name
  depends_on  = [ azurerm_virtual_network.packer_build ]

}

locals { 
  subnets = data.azurerm_virtual_network.packer_build.subnets
}

resource "azurerm_subnet" "packer_build" {
  count = var.packer_build_subnet_create == true ? 1 : 0

  name                 = var.packer_build_subnet_name
  resource_group_name  = data.azurerm_virtual_network.packer_build.resource_group_name
  virtual_network_name = data.azurerm_virtual_network.packer_build.name
  address_prefixes     = var.packer_build_subnet_addresses

  depends_on = [ azurerm_virtual_network.packer_build]

}


resource "azurerm_network_security_group" "packer_build" {
  count = var.packer_build_subnet_create == true ? 1 : 0

	# checkov:skip=BC_AZR_NETWORKING_57: ADD REASON
	# checkov:skip=BC_AZR_NETWORKING_2: ADD REASON
	# checkov:skip=BC_AZR_NETWORKING_3: ADD REASON
  name                = "packer_nsg"
  location            = data.azurerm_resource_group.packer_build.location
  resource_group_name = data.azurerm_resource_group.packer_build.name


  security_rule {
    name                       = "inallow"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "*"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }

}


resource "azurerm_subnet_network_security_group_association" "packer_build" {
  count = var.packer_build_subnet_create == true ? 1 : 0

  subnet_id                 = azurerm_subnet.packer_build.0.id
  network_security_group_id = azurerm_network_security_group.packer_build.0.id
}


resource "azurerm_network_security_rule" "packer_build_inbound" {
  count = var.packer_build_subnet_create == true ? 1 : 0

  name                        = "sshin"
  priority                    = 110
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "22"
  source_address_prefix       = "*"
  destination_address_prefix  = "*"
  resource_group_name         = azurerm_network_security_group.packer_build.0.resource_group_name
  network_security_group_name = azurerm_network_security_group.packer_build.0.name
}


resource "azurerm_network_security_rule" "packer_build_out" {
  name                        = "allout"
  priority                    = 110
  direction                   = "Outbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "*"
  source_address_prefix       = "*"
  destination_address_prefix  = "*"
  resource_group_name         = azurerm_network_security_group.packer_build.0.resource_group_name
  network_security_group_name = azurerm_network_security_group.packer_build.0.name
}
```

</details>

# Roles & Responsibilities

Business

- Define Approved Vendors and Products for BAU use

Compliance

- Validates Products and Versions for BAU use
- Validates CIS guidance and roles to secure images
- Select the provider catalogue image to obtain 
    - Publisher
    - Offer
    - SKU
- Creates definition for OS and CIS components

```
[
    {
      "comment": "OS Definition"
    },
    {
      "Azure OS Image Publisher": "",
      "Azure OS Image Offer": "",
      "Azure OS Image SKU": "",
      "Azure OS Image Gen": "",
      "Azure OS Image Size": "",
      "Image Versions": [
        "2.4.20240817",
        "2.7",
        "3"
      ],
      "CIS Hardening Role": "",
      "CIS Hardening Link": "",
      "auto_rebuild": true,
      "updates": {
        "version": "date",
        "version": "date"
      },
      "Destination Gallery RG": "",
      "Destination Gallery": "",
      "Destination Publisher": "",
      "Destination SKU": "",
      "Comment": "Auto Generated"
    }
]
```

and adds into repo

- new branch for OS
- manual verify
- When PR is created a full validation of the OS and Hardening is done

Platform