From 84ca607d0fc887372d293d287344dabe5d378136 Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Fri, 14 Apr 2023 09:32:33 -0400 Subject: [PATCH 01/11] initial commit of files and resource --- modules/azuread/group/README.md | 151 +++++++++++++++++++++++++++++ modules/azuread/group/main.tf | 34 +++++++ modules/azuread/group/outputs.tf | 0 modules/azuread/group/variables.tf | 0 4 files changed, 185 insertions(+) create mode 100755 modules/azuread/group/README.md create mode 100755 modules/azuread/group/main.tf create mode 100755 modules/azuread/group/outputs.tf create mode 100755 modules/azuread/group/variables.tf diff --git a/modules/azuread/group/README.md b/modules/azuread/group/README.md new file mode 100755 index 00000000..5942d8f4 --- /dev/null +++ b/modules/azuread/group/README.md @@ -0,0 +1,151 @@ + + + + + + + +[![Contributors][contributors-shield]][contributors-url] +[![Forks][forks-shield]][forks-url] +[![Stargazers][stars-shield]][stars-url] +[![Issues][issues-shield]][issues-url] +[![MIT License][license-shield]][license-url] +[![LinkedIn][linkedin-shield]][linkedin-url] + + + +
+
+ + Logo + + +

module_name

+

+ module_description +
+ Explore the docs » +
+
+ Zachary Hill + · + Report Bug + · + Request Feature +

+
+ + + +
+ Table of Contents +
    +
  1. Usage
  2. +
  3. Requirements
  4. +
  5. Providers
  6. +
  7. Modules
  8. +
  9. Resources
  10. +
  11. Inputs
  12. +
  13. Outputs
  14. +
  15. License
  16. +
  17. Contact
  18. +
  19. Acknowledgments
  20. +
+
+ + + +## Usage +### Simple Example +``` +module test { + source = + + variable = +} +``` + +_For more examples, please refer to the [Documentation](https://github.com/zachreborn/terraform-modules)_ + +

(back to top)

+ + + + +## Requirements + +No requirements. + +## Providers + +No providers. + +## Modules + +No modules. + +## Resources + +No resources. + +## Inputs + +No inputs. + +## Outputs + +No outputs. + + + +## License + +Distributed under the MIT License. See `LICENSE.txt` for more information. + +

(back to top)

+ + + + +## Contact + +Zachary Hill - [![LinkedIn][linkedin-shield]][linkedin-url] - zhill@zacharyhill.co + +Project Link: [https://github.com/zachreborn/terraform-modules](https://github.com/zachreborn/terraform-modules) + +

(back to top)

+ + + + +## Acknowledgments + +* [Zachary Hill](https://zacharyhill.co) +* [Jake Jones](https://github.com/jakeasarus) + +

(back to top)

+ + + + +[contributors-shield]: https://img.shields.io/github/contributors/zachreborn/terraform-modules.svg?style=for-the-badge +[contributors-url]: https://github.com/zachreborn/terraform-modules/graphs/contributors +[forks-shield]: https://img.shields.io/github/forks/zachreborn/terraform-modules.svg?style=for-the-badge +[forks-url]: https://github.com/zachreborn/terraform-modules/network/members +[stars-shield]: https://img.shields.io/github/stars/zachreborn/terraform-modules.svg?style=for-the-badge +[stars-url]: https://github.com/zachreborn/terraform-modules/stargazers +[issues-shield]: https://img.shields.io/github/issues/zachreborn/terraform-modules.svg?style=for-the-badge +[issues-url]: https://github.com/zachreborn/terraform-modules/issues +[license-shield]: https://img.shields.io/github/license/zachreborn/terraform-modules.svg?style=for-the-badge +[license-url]: https://github.com/zachreborn/terraform-modules/blob/master/LICENSE.txt +[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555 +[linkedin-url]: https://www.linkedin.com/in/zachary-hill-5524257a/ +[product-screenshot]: /images/screenshot.webp +[Terraform.io]: https://img.shields.io/badge/Terraform-7B42BC?style=for-the-badge&logo=terraform +[Terraform-url]: https://terraform.io \ No newline at end of file diff --git a/modules/azuread/group/main.tf b/modules/azuread/group/main.tf new file mode 100755 index 00000000..9b7738ce --- /dev/null +++ b/modules/azuread/group/main.tf @@ -0,0 +1,34 @@ +############################ +# Data Sources +############################ + +data "azuread_client_config" "current" {} + +############################ +# Azure AD Group +############################ + +resource "azuread_group" "this" { + auto_subscribe_new_members = var.auto_subscribe_new_members + description = var.description + display_name = var.display_name + external_senders_allowed = var.external_senders_allowed + hide_from_address_lists = var.hide_from_address_lists + hide_from_outlook_clients = var.hide_from_outlook_clients + mail_enabled = var.mail_enabled + mail_nickname = var.mail_nickname + prevent_duplicate_names = var.prevent_duplicate_names + provisioning_options = var.provisioning_options + security_enabled = var.security_enabled + types = var.types + owners = var.owners + visibility = var.visibility + + dynamic "dynamic_membership" { + for_each = var.dynamic_membership + content { + enabled = dynamic_membership.value.enabled + rule = dynamic_membership.value.rule + } + } +} diff --git a/modules/azuread/group/outputs.tf b/modules/azuread/group/outputs.tf new file mode 100755 index 00000000..e69de29b diff --git a/modules/azuread/group/variables.tf b/modules/azuread/group/variables.tf new file mode 100755 index 00000000..e69de29b From ea14f3b0a777d11c6637beac9854a61263b47a20 Mon Sep 17 00:00:00 2001 From: zachreborn Date: Fri, 14 Apr 2023 13:34:18 +0000 Subject: [PATCH 02/11] Continuous Integration - terraform fmt and terraform-docs --- modules/azuread/group/README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/azuread/group/README.md b/modules/azuread/group/README.md index 5942d8f4..1b1436ac 100755 --- a/modules/azuread/group/README.md +++ b/modules/azuread/group/README.md @@ -84,7 +84,9 @@ No requirements. ## Providers -No providers. +| Name | Version | +|------|---------| +| [azuread](#provider\_azuread) | n/a | ## Modules @@ -92,7 +94,10 @@ No modules. ## Resources -No resources. +| Name | Type | +|------|------| +| [azuread_group.this](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/group) | resource | +| [azuread_client_config.current](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/data-sources/client_config) | data source | ## Inputs From b0f895f90adfb41633c43addc60bd180a47f581a Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Fri, 14 Apr 2023 11:23:39 -0400 Subject: [PATCH 03/11] added all variables --- modules/azuread/group/main.tf | 3 +- modules/azuread/group/variables.tf | 133 +++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 1 deletion(-) diff --git a/modules/azuread/group/main.tf b/modules/azuread/group/main.tf index 9b7738ce..24e96695 100755 --- a/modules/azuread/group/main.tf +++ b/modules/azuread/group/main.tf @@ -17,11 +17,12 @@ resource "azuread_group" "this" { hide_from_outlook_clients = var.hide_from_outlook_clients mail_enabled = var.mail_enabled mail_nickname = var.mail_nickname + members = var.members + owners = var.owners prevent_duplicate_names = var.prevent_duplicate_names provisioning_options = var.provisioning_options security_enabled = var.security_enabled types = var.types - owners = var.owners visibility = var.visibility dynamic "dynamic_membership" { diff --git a/modules/azuread/group/variables.tf b/modules/azuread/group/variables.tf index e69de29b..39dbb071 100755 --- a/modules/azuread/group/variables.tf +++ b/modules/azuread/group/variables.tf @@ -0,0 +1,133 @@ +############################ +# Azure AD Group Variables +############################ + +variable "auto_subscribe_new_members" { + type = bool + description = "(Optional) Indicates whether new members added to the group will be auto-subscribed to receive email notifications. Can only be set for Unified groups." + default = null + validation { + condition = can(regex("true|false|null", var.auto_subscribe_new_members)) + error_message = "The value of auto_subscribe_new_members must be true, false or null." + } +} + +variable "description" { + type = string + description = "(Optional) A description for the group." + default = null +} + +variable "display_name" { + type = string + description = "(Required) The display name for the group." +} + +variable "external_senders_allowed" { + type = bool + description = "(Optional) Indicates whether external senders can send messages to the group. Can only be set for Unified groups." + default = null + validation { + condition = can(regex("true|false|null", var.external_senders_allowed)) + error_message = "The value of external_senders_allowed must be true, false or null." + } +} + +variable "hide_from_address_lists" { + type = bool + description = "(Optional) Indicates whether the group is displayed in certain parts of the Outlook user interface: in the Address Book, in address lists for selecting message recipients, and in the Browse Groups dialog for searching groups. Can only be set for Unified groups." + default = null + validation { + condition = can(regex("true|false|null", var.hide_from_address_lists)) + error_message = "The value of hide_from_address_lists must be true, false or null." + } +} + +variable "hide_from_outlook_clients" { + type = bool + description = "(Optional) Indicates whether the group is displayed in Outlook clients, such as Outlook for Windows and Outlook on the web. Can only be set for Unified groups." + default = null + validation { + condition = can(regex("true|false|null", var.hide_from_outlook_clients)) + error_message = "The value of hide_from_outlook_clients must be true, false or null." + } +} + +variable "mail_enabled" { + type = bool + description = "(Optional) Whether the group is a mail enabled, with a shared group mailbox. At least one of mail_enabled or security_enabled must be specified. Only Microsoft 365 groups can be mail enabled (see the types property)." + default = null + validation { + condition = can(regex("true|false|null", var.mail_enabled)) + error_message = "The value of mail_enabled must be true, false or null." + } +} + +variable "mail_nickname" { + type = string + description = "(Optional) The mail alias for the group, unique in the organisation. Required for mail-enabled groups. Changing this forces a new resource to be created." + default = null +} + +variable "members" { + type = list(string) + description = "(Optional) A list of members who should be present in this group. Supported object types are Users, Groups or Service Principals. Cannot be used with the dynamic_membership block." + default = null +} + +variable "owners" { + type = list(string) + description = "(Optional) A set of object IDs of principals that will be granted ownership of the group. Supported object types are users or service principals. By default, the principal being used to execute Terraform is assigned as the sole owner. Groups cannot be created with no owners or have all their owners removed." + default = null +} + +variable "prevent_duplicate_names" { + type = bool + description = "(Optional) If true, will return an error if an existing group is found with the same name. Defaults to false." + default = null + validation { + condition = can(regex("true|false|null", var.prevent_duplicate_names)) + error_message = "The value of prevent_duplicate_names must be true, false or null." + } +} + +variable "provisioning_options" { + type = list(string) + description = "(Optional) A list of provisioning options for a Microsoft 365 group. The only supported value is Team. See official documentation for details. Changing this forces a new resource to be created." + default = null +} + +variable "security_enabled" { + type = bool + description = "(Optional) Whether the group is a security group for controlling access to in-app resources. At least one of security_enabled or mail_enabled must be specified. A Microsoft 365 group can be security enabled and mail enabled (see the types property)." + default = null + validation { + condition = can(regex("true|false|null", var.security_enabled)) + error_message = "The value of security_enabled must be true, false or null." + } +} + +variable "types" { + type = list(string) + description = "(Optional) A list of group types to configure for the group. Supported values are DynamicMembership, which denotes a group with dynamic membership, and Unified, which specifies a Microsoft 365 group. Required when mail_enabled is true. Changing this forces a new resource to be created." + default = null +} + +variable "visibility" { + type = string + description = "(Optional) The group join policy and group content visibility. Possible values are Private, Public, or Hiddenmembership. Only Microsoft 365 groups can have Hiddenmembership visibility and this value must be set when the group is created. By default, security groups will receive Private visibility and Microsoft 365 groups will receive Public visibility." + default = null + validation { + condition = can(regex("Private|Public|Hiddenmembership|null", var.visibility)) + error_message = "The value of visibility must be Private, Public, Hiddenmembership or null." + } +} + +variable "dynamic_membership" { + type = object({ + enabled = bool + rule = string + }) + description = "(Optional) A dynamic membership block. Cannot be used with the members property." + default = null +} From 5896a97a1d7dee9f370fa3e4874354748892a2f8 Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Fri, 14 Apr 2023 11:25:48 -0400 Subject: [PATCH 04/11] added the outputs --- modules/azuread/group/outputs.tf | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/modules/azuread/group/outputs.tf b/modules/azuread/group/outputs.tf index e69de29b..a88bf450 100755 --- a/modules/azuread/group/outputs.tf +++ b/modules/azuread/group/outputs.tf @@ -0,0 +1,14 @@ +output "mail" { + description = "The SMTP address for the group." + value = azuread_group.this.mail +} + +output "object_id" { + description = "The object ID of the Azure AD group." + value = azuread_group.this.object_id +} + +output "proxy_addresses" { + description = "The proxy addresses for the group." + value = azuread_group.this.proxy_addresses +} From 30c96c246e1530a3ac77c994389bd4166756ba84 Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Fri, 14 Apr 2023 11:28:55 -0400 Subject: [PATCH 05/11] updated all validation to account for null better --- modules/azuread/group/variables.tf | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/azuread/group/variables.tf b/modules/azuread/group/variables.tf index 39dbb071..edfb29f3 100755 --- a/modules/azuread/group/variables.tf +++ b/modules/azuread/group/variables.tf @@ -7,7 +7,7 @@ variable "auto_subscribe_new_members" { description = "(Optional) Indicates whether new members added to the group will be auto-subscribed to receive email notifications. Can only be set for Unified groups." default = null validation { - condition = can(regex("true|false|null", var.auto_subscribe_new_members)) + condition = var.auto_subscribe_new_members == null ? true : can(regex("true|false", var.auto_subscribe_new_members)) error_message = "The value of auto_subscribe_new_members must be true, false or null." } } @@ -28,7 +28,7 @@ variable "external_senders_allowed" { description = "(Optional) Indicates whether external senders can send messages to the group. Can only be set for Unified groups." default = null validation { - condition = can(regex("true|false|null", var.external_senders_allowed)) + condition = var.external_senders_allowed == null ? true : can(regex("true|false", var.external_senders_allowed)) error_message = "The value of external_senders_allowed must be true, false or null." } } @@ -38,7 +38,7 @@ variable "hide_from_address_lists" { description = "(Optional) Indicates whether the group is displayed in certain parts of the Outlook user interface: in the Address Book, in address lists for selecting message recipients, and in the Browse Groups dialog for searching groups. Can only be set for Unified groups." default = null validation { - condition = can(regex("true|false|null", var.hide_from_address_lists)) + condition = var.hide_from_address_lists == null ? true : can(regex("true|false", var.hide_from_address_lists)) error_message = "The value of hide_from_address_lists must be true, false or null." } } @@ -48,7 +48,7 @@ variable "hide_from_outlook_clients" { description = "(Optional) Indicates whether the group is displayed in Outlook clients, such as Outlook for Windows and Outlook on the web. Can only be set for Unified groups." default = null validation { - condition = can(regex("true|false|null", var.hide_from_outlook_clients)) + condition = var.hide_from_outlook_clients == null ? true : can(regex("true|false", var.hide_from_outlook_clients)) error_message = "The value of hide_from_outlook_clients must be true, false or null." } } @@ -58,7 +58,7 @@ variable "mail_enabled" { description = "(Optional) Whether the group is a mail enabled, with a shared group mailbox. At least one of mail_enabled or security_enabled must be specified. Only Microsoft 365 groups can be mail enabled (see the types property)." default = null validation { - condition = can(regex("true|false|null", var.mail_enabled)) + condition = var.mail_enabled == null ? true: can(regex("true|false", var.mail_enabled)) error_message = "The value of mail_enabled must be true, false or null." } } @@ -86,7 +86,7 @@ variable "prevent_duplicate_names" { description = "(Optional) If true, will return an error if an existing group is found with the same name. Defaults to false." default = null validation { - condition = can(regex("true|false|null", var.prevent_duplicate_names)) + condition = var.prevent_duplicate_names == null ? true : can(regex("true|false", var.prevent_duplicate_names)) error_message = "The value of prevent_duplicate_names must be true, false or null." } } @@ -102,7 +102,7 @@ variable "security_enabled" { description = "(Optional) Whether the group is a security group for controlling access to in-app resources. At least one of security_enabled or mail_enabled must be specified. A Microsoft 365 group can be security enabled and mail enabled (see the types property)." default = null validation { - condition = can(regex("true|false|null", var.security_enabled)) + condition = var.security_enabled == null ? true : can(regex("true|false", var.security_enabled)) error_message = "The value of security_enabled must be true, false or null." } } @@ -118,7 +118,7 @@ variable "visibility" { description = "(Optional) The group join policy and group content visibility. Possible values are Private, Public, or Hiddenmembership. Only Microsoft 365 groups can have Hiddenmembership visibility and this value must be set when the group is created. By default, security groups will receive Private visibility and Microsoft 365 groups will receive Public visibility." default = null validation { - condition = can(regex("Private|Public|Hiddenmembership|null", var.visibility)) + condition = var.visibility == null ? true : can(regex("Private|Public|Hiddenmembership", var.visibility)) error_message = "The value of visibility must be Private, Public, Hiddenmembership or null." } } From 2ff696072a8f4d7ac500da85f506613e4ee086bd Mon Sep 17 00:00:00 2001 From: zachreborn Date: Fri, 14 Apr 2023 15:30:06 +0000 Subject: [PATCH 06/11] Continuous Integration - terraform fmt and terraform-docs --- modules/azuread/group/README.md | 25 +++++++- modules/azuread/group/outputs.tf | 8 +-- modules/azuread/group/variables.tf | 92 +++++++++++++++--------------- 3 files changed, 73 insertions(+), 52 deletions(-) diff --git a/modules/azuread/group/README.md b/modules/azuread/group/README.md index 1b1436ac..79d79263 100755 --- a/modules/azuread/group/README.md +++ b/modules/azuread/group/README.md @@ -101,11 +101,32 @@ No modules. ## Inputs -No inputs. +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [auto\_subscribe\_new\_members](#input\_auto\_subscribe\_new\_members) | (Optional) Indicates whether new members added to the group will be auto-subscribed to receive email notifications. Can only be set for Unified groups. | `bool` | `null` | no | +| [description](#input\_description) | (Optional) A description for the group. | `string` | `null` | no | +| [display\_name](#input\_display\_name) | (Required) The display name for the group. | `string` | n/a | yes | +| [dynamic\_membership](#input\_dynamic\_membership) | (Optional) A dynamic membership block. Cannot be used with the members property. |
object({
enabled = bool
rule = string
})
| `null` | no | +| [external\_senders\_allowed](#input\_external\_senders\_allowed) | (Optional) Indicates whether external senders can send messages to the group. Can only be set for Unified groups. | `bool` | `null` | no | +| [hide\_from\_address\_lists](#input\_hide\_from\_address\_lists) | (Optional) Indicates whether the group is displayed in certain parts of the Outlook user interface: in the Address Book, in address lists for selecting message recipients, and in the Browse Groups dialog for searching groups. Can only be set for Unified groups. | `bool` | `null` | no | +| [hide\_from\_outlook\_clients](#input\_hide\_from\_outlook\_clients) | (Optional) Indicates whether the group is displayed in Outlook clients, such as Outlook for Windows and Outlook on the web. Can only be set for Unified groups. | `bool` | `null` | no | +| [mail\_enabled](#input\_mail\_enabled) | (Optional) Whether the group is a mail enabled, with a shared group mailbox. At least one of mail\_enabled or security\_enabled must be specified. Only Microsoft 365 groups can be mail enabled (see the types property). | `bool` | `null` | no | +| [mail\_nickname](#input\_mail\_nickname) | (Optional) The mail alias for the group, unique in the organisation. Required for mail-enabled groups. Changing this forces a new resource to be created. | `string` | `null` | no | +| [members](#input\_members) | (Optional) A list of members who should be present in this group. Supported object types are Users, Groups or Service Principals. Cannot be used with the dynamic\_membership block. | `list(string)` | `null` | no | +| [owners](#input\_owners) | (Optional) A set of object IDs of principals that will be granted ownership of the group. Supported object types are users or service principals. By default, the principal being used to execute Terraform is assigned as the sole owner. Groups cannot be created with no owners or have all their owners removed. | `list(string)` | `null` | no | +| [prevent\_duplicate\_names](#input\_prevent\_duplicate\_names) | (Optional) If true, will return an error if an existing group is found with the same name. Defaults to false. | `bool` | `null` | no | +| [provisioning\_options](#input\_provisioning\_options) | (Optional) A list of provisioning options for a Microsoft 365 group. The only supported value is Team. See official documentation for details. Changing this forces a new resource to be created. | `list(string)` | `null` | no | +| [security\_enabled](#input\_security\_enabled) | (Optional) Whether the group is a security group for controlling access to in-app resources. At least one of security\_enabled or mail\_enabled must be specified. A Microsoft 365 group can be security enabled and mail enabled (see the types property). | `bool` | `null` | no | +| [types](#input\_types) | (Optional) A list of group types to configure for the group. Supported values are DynamicMembership, which denotes a group with dynamic membership, and Unified, which specifies a Microsoft 365 group. Required when mail\_enabled is true. Changing this forces a new resource to be created. | `list(string)` | `null` | no | +| [visibility](#input\_visibility) | (Optional) The group join policy and group content visibility. Possible values are Private, Public, or Hiddenmembership. Only Microsoft 365 groups can have Hiddenmembership visibility and this value must be set when the group is created. By default, security groups will receive Private visibility and Microsoft 365 groups will receive Public visibility. | `string` | `null` | no | ## Outputs -No outputs. +| Name | Description | +|------|-------------| +| [mail](#output\_mail) | The SMTP address for the group. | +| [object\_id](#output\_object\_id) | The object ID of the Azure AD group. | +| [proxy\_addresses](#output\_proxy\_addresses) | The proxy addresses for the group. | diff --git a/modules/azuread/group/outputs.tf b/modules/azuread/group/outputs.tf index a88bf450..cbbb8672 100755 --- a/modules/azuread/group/outputs.tf +++ b/modules/azuread/group/outputs.tf @@ -1,6 +1,6 @@ output "mail" { - description = "The SMTP address for the group." - value = azuread_group.this.mail + description = "The SMTP address for the group." + value = azuread_group.this.mail } output "object_id" { @@ -9,6 +9,6 @@ output "object_id" { } output "proxy_addresses" { - description = "The proxy addresses for the group." - value = azuread_group.this.proxy_addresses + description = "The proxy addresses for the group." + value = azuread_group.this.proxy_addresses } diff --git a/modules/azuread/group/variables.tf b/modules/azuread/group/variables.tf index edfb29f3..5159ba1b 100755 --- a/modules/azuread/group/variables.tf +++ b/modules/azuread/group/variables.tf @@ -7,20 +7,20 @@ variable "auto_subscribe_new_members" { description = "(Optional) Indicates whether new members added to the group will be auto-subscribed to receive email notifications. Can only be set for Unified groups." default = null validation { - condition = var.auto_subscribe_new_members == null ? true : can(regex("true|false", var.auto_subscribe_new_members)) + condition = var.auto_subscribe_new_members == null ? true : can(regex("true|false", var.auto_subscribe_new_members)) error_message = "The value of auto_subscribe_new_members must be true, false or null." } } variable "description" { - type = string - description = "(Optional) A description for the group." - default = null + type = string + description = "(Optional) A description for the group." + default = null } variable "display_name" { - type = string - description = "(Required) The display name for the group." + type = string + description = "(Required) The display name for the group." } variable "external_senders_allowed" { @@ -28,7 +28,7 @@ variable "external_senders_allowed" { description = "(Optional) Indicates whether external senders can send messages to the group. Can only be set for Unified groups." default = null validation { - condition = var.external_senders_allowed == null ? true : can(regex("true|false", var.external_senders_allowed)) + condition = var.external_senders_allowed == null ? true : can(regex("true|false", var.external_senders_allowed)) error_message = "The value of external_senders_allowed must be true, false or null." } } @@ -38,7 +38,7 @@ variable "hide_from_address_lists" { description = "(Optional) Indicates whether the group is displayed in certain parts of the Outlook user interface: in the Address Book, in address lists for selecting message recipients, and in the Browse Groups dialog for searching groups. Can only be set for Unified groups." default = null validation { - condition = var.hide_from_address_lists == null ? true : can(regex("true|false", var.hide_from_address_lists)) + condition = var.hide_from_address_lists == null ? true : can(regex("true|false", var.hide_from_address_lists)) error_message = "The value of hide_from_address_lists must be true, false or null." } } @@ -48,7 +48,7 @@ variable "hide_from_outlook_clients" { description = "(Optional) Indicates whether the group is displayed in Outlook clients, such as Outlook for Windows and Outlook on the web. Can only be set for Unified groups." default = null validation { - condition = var.hide_from_outlook_clients == null ? true : can(regex("true|false", var.hide_from_outlook_clients)) + condition = var.hide_from_outlook_clients == null ? true : can(regex("true|false", var.hide_from_outlook_clients)) error_message = "The value of hide_from_outlook_clients must be true, false or null." } } @@ -58,27 +58,27 @@ variable "mail_enabled" { description = "(Optional) Whether the group is a mail enabled, with a shared group mailbox. At least one of mail_enabled or security_enabled must be specified. Only Microsoft 365 groups can be mail enabled (see the types property)." default = null validation { - condition = var.mail_enabled == null ? true: can(regex("true|false", var.mail_enabled)) + condition = var.mail_enabled == null ? true : can(regex("true|false", var.mail_enabled)) error_message = "The value of mail_enabled must be true, false or null." } } variable "mail_nickname" { - type = string - description = "(Optional) The mail alias for the group, unique in the organisation. Required for mail-enabled groups. Changing this forces a new resource to be created." - default = null + type = string + description = "(Optional) The mail alias for the group, unique in the organisation. Required for mail-enabled groups. Changing this forces a new resource to be created." + default = null } variable "members" { - type = list(string) - description = "(Optional) A list of members who should be present in this group. Supported object types are Users, Groups or Service Principals. Cannot be used with the dynamic_membership block." - default = null + type = list(string) + description = "(Optional) A list of members who should be present in this group. Supported object types are Users, Groups or Service Principals. Cannot be used with the dynamic_membership block." + default = null } variable "owners" { - type = list(string) - description = "(Optional) A set of object IDs of principals that will be granted ownership of the group. Supported object types are users or service principals. By default, the principal being used to execute Terraform is assigned as the sole owner. Groups cannot be created with no owners or have all their owners removed." - default = null + type = list(string) + description = "(Optional) A set of object IDs of principals that will be granted ownership of the group. Supported object types are users or service principals. By default, the principal being used to execute Terraform is assigned as the sole owner. Groups cannot be created with no owners or have all their owners removed." + default = null } variable "prevent_duplicate_names" { @@ -86,48 +86,48 @@ variable "prevent_duplicate_names" { description = "(Optional) If true, will return an error if an existing group is found with the same name. Defaults to false." default = null validation { - condition = var.prevent_duplicate_names == null ? true : can(regex("true|false", var.prevent_duplicate_names)) + condition = var.prevent_duplicate_names == null ? true : can(regex("true|false", var.prevent_duplicate_names)) error_message = "The value of prevent_duplicate_names must be true, false or null." } } variable "provisioning_options" { - type = list(string) - description = "(Optional) A list of provisioning options for a Microsoft 365 group. The only supported value is Team. See official documentation for details. Changing this forces a new resource to be created." - default = null + type = list(string) + description = "(Optional) A list of provisioning options for a Microsoft 365 group. The only supported value is Team. See official documentation for details. Changing this forces a new resource to be created." + default = null } variable "security_enabled" { - type = bool - description = "(Optional) Whether the group is a security group for controlling access to in-app resources. At least one of security_enabled or mail_enabled must be specified. A Microsoft 365 group can be security enabled and mail enabled (see the types property)." - default = null - validation { - condition = var.security_enabled == null ? true : can(regex("true|false", var.security_enabled)) - error_message = "The value of security_enabled must be true, false or null." - } + type = bool + description = "(Optional) Whether the group is a security group for controlling access to in-app resources. At least one of security_enabled or mail_enabled must be specified. A Microsoft 365 group can be security enabled and mail enabled (see the types property)." + default = null + validation { + condition = var.security_enabled == null ? true : can(regex("true|false", var.security_enabled)) + error_message = "The value of security_enabled must be true, false or null." + } } variable "types" { - type = list(string) - description = "(Optional) A list of group types to configure for the group. Supported values are DynamicMembership, which denotes a group with dynamic membership, and Unified, which specifies a Microsoft 365 group. Required when mail_enabled is true. Changing this forces a new resource to be created." - default = null + type = list(string) + description = "(Optional) A list of group types to configure for the group. Supported values are DynamicMembership, which denotes a group with dynamic membership, and Unified, which specifies a Microsoft 365 group. Required when mail_enabled is true. Changing this forces a new resource to be created." + default = null } variable "visibility" { - type = string - description = "(Optional) The group join policy and group content visibility. Possible values are Private, Public, or Hiddenmembership. Only Microsoft 365 groups can have Hiddenmembership visibility and this value must be set when the group is created. By default, security groups will receive Private visibility and Microsoft 365 groups will receive Public visibility." - default = null - validation { - condition = var.visibility == null ? true : can(regex("Private|Public|Hiddenmembership", var.visibility)) - error_message = "The value of visibility must be Private, Public, Hiddenmembership or null." - } + type = string + description = "(Optional) The group join policy and group content visibility. Possible values are Private, Public, or Hiddenmembership. Only Microsoft 365 groups can have Hiddenmembership visibility and this value must be set when the group is created. By default, security groups will receive Private visibility and Microsoft 365 groups will receive Public visibility." + default = null + validation { + condition = var.visibility == null ? true : can(regex("Private|Public|Hiddenmembership", var.visibility)) + error_message = "The value of visibility must be Private, Public, Hiddenmembership or null." + } } variable "dynamic_membership" { - type = object({ - enabled = bool - rule = string - }) - description = "(Optional) A dynamic membership block. Cannot be used with the members property." - default = null + type = object({ + enabled = bool + rule = string + }) + description = "(Optional) A dynamic membership block. Cannot be used with the members property." + default = null } From 3be14919be2e72ef016829d04af35036efc63aa7 Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Fri, 14 Apr 2023 11:37:49 -0400 Subject: [PATCH 07/11] added better handling of the dynamic dynamic_membership block --- modules/azuread/group/README.md | 22 +++++++++++++++------- modules/azuread/group/main.tf | 6 +++--- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/modules/azuread/group/README.md b/modules/azuread/group/README.md index 79d79263..81ce7b27 100755 --- a/modules/azuread/group/README.md +++ b/modules/azuread/group/README.md @@ -26,9 +26,9 @@ Logo -

module_name

+

Azure AD Group Module

- module_description + This module creates and manages Azure AD group resources.
Explore the docs »
@@ -62,12 +62,20 @@ ## Usage -### Simple Example +### Dynamic Membership Group Example +This group utilizes dynamic membership rules to manage group membership. ``` -module test { - source = - - variable = +module group_app_terraform { + source = "github.com/zachreborn/terraform-modules//modules/azuread/group" + display_name = "app_terraform" + owners = [admin.objectid] + security_enabled = true + types = ["DynamicMembership"] + + dynamic_membership = { + enabled = true + rule = "user.department -eq \"DevOps\"" + } } ``` diff --git a/modules/azuread/group/main.tf b/modules/azuread/group/main.tf index 24e96695..14349d63 100755 --- a/modules/azuread/group/main.tf +++ b/modules/azuread/group/main.tf @@ -26,10 +26,10 @@ resource "azuread_group" "this" { visibility = var.visibility dynamic "dynamic_membership" { - for_each = var.dynamic_membership + for_each = var.dynamic_membership == null ? [] : [var.dynamic_membership] content { - enabled = dynamic_membership.value.enabled - rule = dynamic_membership.value.rule + enabled = try(dynamic_membership.value.enabled, null) + rule = try(dynamic_membership.value.rule, null) } } } From ad5135bf43b60781222f5db7bbd7e6acefc1e9ab Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Fri, 14 Apr 2023 12:16:21 -0400 Subject: [PATCH 08/11] Added terraform and provider requirements --- modules/azuread/group/main.tf | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/modules/azuread/group/main.tf b/modules/azuread/group/main.tf index 14349d63..f1c172fa 100755 --- a/modules/azuread/group/main.tf +++ b/modules/azuread/group/main.tf @@ -1,8 +1,12 @@ -############################ -# Data Sources -############################ - -data "azuread_client_config" "current" {} +terraform { + required_version = ">= 1.0.0" + required_providers { + azuread = { + source = "hashicorp/azuread" + version = ">= 2.36.0" + } + } +} ############################ # Azure AD Group From 088df1bda5b194f32b174ae5c3d7b5fc488cc11c Mon Sep 17 00:00:00 2001 From: zachreborn Date: Fri, 14 Apr 2023 16:17:26 +0000 Subject: [PATCH 09/11] Continuous Integration - terraform fmt and terraform-docs --- modules/azuread/group/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/azuread/group/README.md b/modules/azuread/group/README.md index 81ce7b27..b65e752c 100755 --- a/modules/azuread/group/README.md +++ b/modules/azuread/group/README.md @@ -88,13 +88,16 @@ _For more examples, please refer to the [Documentation](https://github.com/zachr ## Requirements -No requirements. +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [azuread](#requirement\_azuread) | >= 2.36.0 | ## Providers | Name | Version | |------|---------| -| [azuread](#provider\_azuread) | n/a | +| [azuread](#provider\_azuread) | >= 2.36.0 | ## Modules @@ -105,7 +108,6 @@ No modules. | Name | Type | |------|------| | [azuread_group.this](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/group) | resource | -| [azuread_client_config.current](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/data-sources/client_config) | data source | ## Inputs From a0fb1091b3f2acc57c98dabd1545839b6b2af2f3 Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Fri, 14 Apr 2023 12:20:27 -0400 Subject: [PATCH 10/11] updated readme for more context --- modules/azuread/group/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/azuread/group/README.md b/modules/azuread/group/README.md index b65e752c..a3397d66 100755 --- a/modules/azuread/group/README.md +++ b/modules/azuread/group/README.md @@ -63,7 +63,7 @@ ## Usage ### Dynamic Membership Group Example -This group utilizes dynamic membership rules to manage group membership. +This configures an Azure AD security group which utilizes dynamic membership rules to manage group membership. ``` module group_app_terraform { source = "github.com/zachreborn/terraform-modules//modules/azuread/group" From a5452647819631f519aebfbc985926accd459545 Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Fri, 14 Apr 2023 12:29:07 -0400 Subject: [PATCH 11/11] added two additional examples --- modules/azuread/group/README.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/modules/azuread/group/README.md b/modules/azuread/group/README.md index a3397d66..3db57e7c 100755 --- a/modules/azuread/group/README.md +++ b/modules/azuread/group/README.md @@ -62,11 +62,32 @@ ## Usage +### Simple Example +``` +module group_simple_example { + source = "github.com/zachreborn/terraform-modules//modules/azuread/group" + display_name = "example" + owners = [admin.objectid] + security_enabled = true +} +``` +### Microsoft 365 Group Example +``` +module group_365_example { + source = "github.com/zachreborn/terraform-modules//modules/azuread/group" + display_name = "example" + mail_enabled = true + mail_nickname = "ExampleGroup" + owners = [admin.objectid] + security_enabled = true + types = ["Unified"] +} +``` ### Dynamic Membership Group Example This configures an Azure AD security group which utilizes dynamic membership rules to manage group membership. ``` module group_app_terraform { - source = "github.com/zachreborn/terraform-modules//modules/azuread/group" + source = "github.com/zachreborn/terraform-modules//modules/azuread/group" display_name = "app_terraform" owners = [admin.objectid] security_enabled = true