diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..237345fd --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +*.exe +.DS_Store + +*.log +*.bak +*.backup +*~ +.*.swp + +bin/ +modules-dev/ +pkg/ +vendor/ +__pycache__/ + +.idea +.vscode + +.env +./*.tfstate +.terraform +terraform.tfplan +terraform.tfstate +terraform.tfvars +.terraform.tfstate.lock.info + +.tfcache +**/.terraform.lock.hcl +**/tf_resources.json +**/var.tfvars diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..8c6eb2c2 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,86 @@ +# A pipeline is composed of independent jobs that run scripts, grouped into stages. +# Stages run in sequential order, but jobs within stages run in parallel. +# +# For more information, see: https://docs.gitlab.com/ee/ci/yaml/index.html#stages + +stages: # List of stages for jobs, and their order of execution + - test-unit + - TF-Plan-e2e + - TF-Apply-e2e + - TF-Destroy-e2e + + +.testing_pipeline: + before_script: + - export http_proxy=http://www-proxy-hqdc.us.oracle.com:80 + - export https_proxy=$http_proxy + - curl https://releases.hashicorp.com/terraform/1.2.2/terraform_1.2.2_linux_amd64.zip > terraform.zip + - unzip terraform.zip -d /bin + - terraform --version + - eval $(ssh-agent -s) + - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - + - mkdir -p ~/.ssh + - chmod 700 ~/.ssh + - ssh-add -l + - pip install -r test/requirements.txt + image: lab-runner + tags: [LZ] + +unit-test-job: # This job runs in the test stage. + extends: .testing_pipeline + stage: test-unit + script: + - pytest -m unit --junit-xml=pytest.xml test + # # Orahub's artifact upload seems broken. Possibly a config issue... + # artifacts: + # when: always + # paths: + # - pytest.xml + # reports: + # junit: pytest.xml + rules: + - if: $CI_PIPELINE_SOURCE == "schedule" + +e2e-full-plan-job: # This job runs terraform plan. + extends: .testing_pipeline + stage: TF-Plan-e2e + when: on_success + script: + - cd templates/enterprise-landing-zone + - ./BackEnd.sh + - cat backend.tf + - terraform init -backend-config="address=$REMOTE_STATE_BACKEND" -backend-config="update_method=PUT" + - terraform validate + - terraform plan -var-file=$ENV_TFVARS_FILE_NAME + rules: + - if: ($CI_COMMIT_BRANCH == "LANZ-Integration") + +e2e-full-deploy-job: # This job runs terraform apply. + extends: .testing_pipeline + stage: TF-Apply-e2e + when: on_success + script: + - cd templates/enterprise-landing-zone + - ./BackEnd.sh + - cat backend.tf + - terraform init -backend-config="address=$REMOTE_STATE_BACKEND" -backend-config="update_method=PUT" + - terraform validate + - terraform apply -var-file=$ENV_TFVARS_FILE_NAME -auto-approve #neeed to look at pasing a plan file but have to understan gitlab artifiacts issue + rules: + - if: ($CI_COMMIT_BRANCH == "LANZ-Integration") + retry: 1 + +e2e-full-destroy-job: # This job runs terraform destroy. + extends: .testing_pipeline + stage: TF-Destroy-e2e + when: manual + allow_failure: true + script: + - cd templates/enterprise-landing-zone + - ./BackEnd.sh + - cat backend.tf + - terraform init -backend-config="address=$REMOTE_STATE_BACKEND" -backend-config="update_method=PUT" + - terraform validate + - terraform destroy -var-file=$ENV_TFVARS_FILE_NAME -auto-approve #neeed to look at pasing a plan file but have to understand gitlab artifiacts issue + rules: + - if: ($CI_COMMIT_BRANCH == "LANZ-Integration") \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..57f60630 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,23 @@ +# Contributing to the project + +Oracle welcomes contributions to this repository from anyone. + +If you want to submit a pull request to fix a bug or enhance an existing +feature, please first open an issue and link to that issue when you +submit your pull request. + +If you have any questions about a possible submission, feel free to open +an issue too. + +## Pull request process + +1. Fork this repository +1. Create a branch in your fork to implement the changes. We recommend using +the issue number as part of your branch name, e.g. `1234-fixes` +1. Ensure that there is at least one test that would fail without the fix and +passes post fix +1. Submit the pull request. *Do not leave the pull request blank*. Explain exactly +what your changes are meant to do and provide simple steps on how to validate +your changes, ideally referencing the test. Ensure that you reference the issue +you created as well. We will assign the pull request to 1-2 people for review +before it is submitted internally and the PR is closed. diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..a80c2341 --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2022 Oracle and/or its affiliates. + +The Universal Permissive License (UPL), Version 1.0 + +Subject to the condition set forth below, permission is hereby granted to any person obtaining a copy of this +software, associated documentation and/or data (collectively the "Software"), free of charge and under any and +all copyright rights in the Software, and any and all patent rights owned or freely licensable by each licensor +hereunder covering either (i) the unmodified Software as contributed to or provided by such licensor, or +(ii) the Larger Works (as defined below), to deal in both + +(a) the Software, and +(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if one is included with the Software +(each a “Larger Work” to which the Software is contributed by such licensors), + +without restriction, including without limitation the rights to copy, create derivative works of, display, +perform, and distribute the Software and make, use, sell, offer for sale, import, export, have made, and have +sold the Software and the Larger Work(s), and to sublicense the foregoing rights on either these or other terms. + +This license is subject to the following condition: +The above copyright notice and either this complete permission notice or at a minimum a reference to the UPL must +be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..8aee433d --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# Landing Zones + +This repository contains different types of Landing Zones to deploy to the Oracle Cloud Infrastructure platform. The landing zones are assembled from modules and templates that users can use in their default configuration or fork this repo and customize for your own scenarios. + +## Enterprise Scale Baseline Landing Zone v2.0 (ESBLZ v2.0) + +The Enterprise Scale Baseline Landing Zone v2.0 (ESBLZ v2.0) deploys a typical architecture used by enterprise customers. The root template for this landing zone is located at [templates/enterprise-landing-zone](./templates/enterprise-landing-zone). Users can use the guides below to get strated with the Enterprise Scale Baseline Landing Zone v2.0 (ESBLZ v2.0). + +- [Architecture Guide](./templates/enterprise-landing-zone/Architecture_Guide.md) +- [Implementation Guide](./templates/enterprise-landing-zone/IMPLEMENTATION.md) +- [Configuration Guide](./templates/enterprise-landing-zone/CONFIGURATION.md) + +## The Team + +This repository is developed and supported by the Oracle OCI Landing Zones team. + +## How to Contribute + +Interested in contributing? See our contribution [guidelines](CONTRIBUTING.md) for details. + +## License + +This repository and its contents are licensed under [UPL 1.0](https://opensource.org/licenses/UPL). \ No newline at end of file diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 00000000..1f41eaa4 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,20 @@ +# Release Notes + +---- +## v2.0.0 - 2023-02-28 +- Initial Release of new version 2 codebase with Hub and Spoke Networking, Multi-Environment support and more modular architecture. see the [Architecture Guide](./templates/enterprise-landing-zone/Architecture_Guide.md) for details. +- CIS Security Benchmark Compliance: Enterprise Scale Baseline Landing Zone v2 was designed to include a foundational set of security controls from the Center for Internet Security (CIS). We are happy to share that this release of Landing Zones will support the recommended CIS 1.2 Level 1 controls. The security controls implemented by this Landing Zone are prescriptive and practical in nature with the primary focus to help provide best practices for security hardening of the technologies that are deployed in our customers' tenancies. +While many of the CIS Level 1 recommendations are included in the Landing Zone deployment, however, there are some that require administrators to configure manually. Please be advised that for recommendations # 1.5 - 1.13, 2.6 - 2.8 and 3.16, it will be the customer administrators' responsibility to implement and enforce. +For recommendation #1.7, we recommend that Multi-Factor Authentication (MFA) be fully tested before restricting access only to MFA-verified users. Please note each user must enable MFA for themselves and an administrator cannot enable MFA for another user. For more information, please see [OCI Managing Multi-Factor Authentication documentation][v2.0.0-1]. +For more information on the CIS Security Benchmark, please visit the official [Oracle Cloud CIS Benchmark site][v2.0.0-2]. +- Certain CIDR ranges should not be used when deploying ESBLZv2, as the can conflict with IP addresses reserved for special use. These are: + * 169.254.10.0-169.254.19.255 + * 169.254.100.0-169.254.109.255 + * 169.254.192.0-169.254.201.255 + * 100.64.0.0–100.127.255.255 (Used by Exadata X8M/X9M for the interconnect) +- Known Issues + * 400-InvalidParameter Error in CreateServiceConnector operation: This can occasionally happen due to logs taking longer than normal to create while setting up the logging infrastructure. This will correct itself when the logs finish creating. Later Apply jobs in ORM or invocations of `terraform apply` should succeed. + * 429-TooManyRequests Error: A tenancy making a large number of OCI API requests in rapid succession may be throttled by the API. The solution is to wait some period of time (a few minutes) and retry the terraform operation again. This is rarely seen on `apply` but may occasionally be seen on `destroy` runs, as the delete operations are much faster than create, and Terraform makes many API calls. + +[v2.0.0-1]: https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/usingmfa.htm +[v2.0.0-2]: https://www.cisecurity.org/benchmark/oracle_cloud \ No newline at end of file diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..58373ec6 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,3 @@ +# Sample configs + + diff --git a/images/LZ-v2.0.png b/images/LZ-v2.0.png new file mode 100644 index 00000000..5c251240 Binary files /dev/null and b/images/LZ-v2.0.png differ diff --git a/images/Sec-LZ.png b/images/Sec-LZ.png new file mode 100644 index 00000000..3e1c6e06 Binary files /dev/null and b/images/Sec-LZ.png differ diff --git a/images/h&s-vpn-fc.png b/images/h&s-vpn-fc.png new file mode 100644 index 00000000..b3fa276f Binary files /dev/null and b/images/h&s-vpn-fc.png differ diff --git a/images/h&s-vpn.png b/images/h&s-vpn.png new file mode 100644 index 00000000..651e644e Binary files /dev/null and b/images/h&s-vpn.png differ diff --git a/images/p1.png b/images/p1.png new file mode 100644 index 00000000..87a29a01 Binary files /dev/null and b/images/p1.png differ diff --git a/images/p2.png b/images/p2.png new file mode 100644 index 00000000..25b3907a Binary files /dev/null and b/images/p2.png differ diff --git a/modules/README.md b/modules/README.md new file mode 100644 index 00000000..5f524ee0 --- /dev/null +++ b/modules/README.md @@ -0,0 +1 @@ +# Terraform Modules diff --git a/modules/alarms/README.md b/modules/alarms/README.md new file mode 100644 index 00000000..6054bfb0 --- /dev/null +++ b/modules/alarms/README.md @@ -0,0 +1,37 @@ + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_monitoring_alarm.monitoring_alarm](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/monitoring_alarm) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [alarm\_map](#input\_alarm\_map) | display name: the display name for alarm;
metric compartment id: the OCID of the compartment containing the metric being evaluated by the alarm
namespace: the source service or application emitting the metric that is evaluated by the alarm
query: the Monitoring Query Language (MQL) expression to evaluate for the alarm
severity: the perceived type of response required when the alarm is in the "FIRING" state |
map(object({
display_name = string,
metric_compartment_id = string,
namespace = string,
query = string,
severity = string,
}))
| n/a | yes | +| [compartment\_id](#input\_compartment\_id) | The OCID of the compartment containing the alarm. | `string` | `""` | no | +| [is\_enabled](#input\_is\_enabled) | Alarms enabled or disabled. | `bool` | `false` | no | +| [message\_format](#input\_message\_format) | format of alarm message | `string` | `"ONS_OPTIMIZED"` | no | +| [metric\_compartment\_id\_in\_subtree](#input\_metric\_compartment\_id\_in\_subtree) | Only needed if metric\_compartment\_id = | `bool` | `false` | no | +| [notification\_topic\_id](#input\_notification\_topic\_id) | the OCID of notification topic. | `string` | n/a | yes | +| [pending\_duration](#input\_pending\_duration) | The period of time that the condition defined in the alarm must persist before the alarm state changes from 'OK' to 'FIRING'. | `string` | `"PT5M"` | no | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/modules/alarms/main.tf b/modules/alarms/main.tf new file mode 100644 index 00000000..d32f64e4 --- /dev/null +++ b/modules/alarms/main.tf @@ -0,0 +1,23 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_monitoring_alarm" "monitoring_alarm" { + for_each = var.alarm_map + compartment_id = var.compartment_id + destinations = [var.notification_topic_id] + display_name = each.value.display_name + is_enabled = var.is_enabled + metric_compartment_id = each.value.metric_compartment_id + namespace = each.value.namespace + query = each.value.query + severity = each.value.severity + + message_format = var.message_format + pending_duration = var.pending_duration + metric_compartment_id_in_subtree = var.metric_compartment_id_in_subtree +} diff --git a/modules/alarms/variables.tf b/modules/alarms/variables.tf new file mode 100644 index 00000000..3b68e207 --- /dev/null +++ b/modules/alarms/variables.tf @@ -0,0 +1,51 @@ +variable "compartment_id" { + type = string + description = "The OCID of the compartment containing the alarm." + default = "" +} + +variable "alarm_map" { + type = map(object({ + display_name = string, + metric_compartment_id = string, + namespace = string, + query = string, + severity = string, + })) + description = < +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_announcements_service_announcement_subscription.announcement_subscription](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/announcements_service_announcement_subscription) | resource | +| [oci_announcements_service_announcement_subscriptions_filter_group.announcement_subscriptions_filter_group](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/announcements_service_announcement_subscriptions_filter_group) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | The OCID of the compartment where you want to create the announcement subscription | `string` | n/a | yes | +| [filter\_groups](#input\_filter\_groups) | A list of filter groups for the announcement subscription. | `map(any)` | n/a | yes | +| [notification\_topic\_id](#input\_notification\_topic\_id) | The OCID of the Notifications service topic | `string` | n/a | yes | +| [subscription\_display\_name](#input\_subscription\_display\_name) | The display name of the subscription | `string` | n/a | yes | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/modules/announcement-subscription/main.tf b/modules/announcement-subscription/main.tf new file mode 100644 index 00000000..d2e10038 --- /dev/null +++ b/modules/announcement-subscription/main.tf @@ -0,0 +1,26 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_announcements_service_announcement_subscription" "announcement_subscription" { + compartment_id = var.compartment_id + display_name = var.subscription_display_name + ons_topic_id = var.notification_topic_id +} + +resource "oci_announcements_service_announcement_subscriptions_filter_group" "announcement_subscriptions_filter_group" { + for_each = var.filter_groups + announcement_subscription_id = oci_announcements_service_announcement_subscription.announcement_subscription.id + name = each.key + dynamic "filters" { + for_each = toset(each.value.filters_value) + content { + type = each.value.filters_type + value = filters.key + } + } +} diff --git a/modules/announcement-subscription/variables.tf b/modules/announcement-subscription/variables.tf new file mode 100644 index 00000000..f78ce2ed --- /dev/null +++ b/modules/announcement-subscription/variables.tf @@ -0,0 +1,19 @@ +variable "compartment_id" { + type = string + description = "The OCID of the compartment where you want to create the announcement subscription" +} + +variable "subscription_display_name" { + type = string + description = "The display name of the subscription" +} + +variable "notification_topic_id" { + type = string + description = "The OCID of the Notifications service topic" +} + +variable "filter_groups" { + type = map(any) + description = "A list of filter groups for the announcement subscription. " +} diff --git a/modules/authentication-policy/README.md b/modules/authentication-policy/README.md new file mode 100644 index 00000000..5372e17f --- /dev/null +++ b/modules/authentication-policy/README.md @@ -0,0 +1,37 @@ + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_authentication_policy.authentication_policy](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_authentication_policy) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [authentication\_policy\_password\_policy\_is\_lowercase\_characters\_required](#input\_authentication\_policy\_password\_policy\_is\_lowercase\_characters\_required) | n/a | `any` | n/a | yes | +| [authentication\_policy\_password\_policy\_is\_numeric\_characters\_required](#input\_authentication\_policy\_password\_policy\_is\_numeric\_characters\_required) | n/a | `any` | n/a | yes | +| [authentication\_policy\_password\_policy\_is\_special\_characters\_required](#input\_authentication\_policy\_password\_policy\_is\_special\_characters\_required) | n/a | `any` | n/a | yes | +| [authentication\_policy\_password\_policy\_is\_uppercase\_characters\_required](#input\_authentication\_policy\_password\_policy\_is\_uppercase\_characters\_required) | n/a | `any` | n/a | yes | +| [authentication\_policy\_password\_policy\_is\_username\_containment\_allowed](#input\_authentication\_policy\_password\_policy\_is\_username\_containment\_allowed) | n/a | `any` | n/a | yes | +| [authentication\_policy\_password\_policy\_minimum\_password\_length](#input\_authentication\_policy\_password\_policy\_minimum\_password\_length) | n/a | `any` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | n/a | `any` | n/a | yes | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/modules/authentication-policy/main.tf b/modules/authentication-policy/main.tf new file mode 100644 index 00000000..0f1792d7 --- /dev/null +++ b/modules/authentication-policy/main.tf @@ -0,0 +1,21 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_identity_authentication_policy" "authentication_policy" { + compartment_id = var.tenancy_ocid + + password_policy { + + is_lowercase_characters_required = var.authentication_policy_password_policy_is_lowercase_characters_required + is_numeric_characters_required = var.authentication_policy_password_policy_is_numeric_characters_required + is_special_characters_required = var.authentication_policy_password_policy_is_special_characters_required + is_uppercase_characters_required = var.authentication_policy_password_policy_is_uppercase_characters_required + is_username_containment_allowed = var.authentication_policy_password_policy_is_username_containment_allowed + minimum_password_length = var.authentication_policy_password_policy_minimum_password_length + } +} \ No newline at end of file diff --git a/modules/authentication-policy/variables.tf b/modules/authentication-policy/variables.tf new file mode 100644 index 00000000..b53f4aed --- /dev/null +++ b/modules/authentication-policy/variables.tf @@ -0,0 +1,13 @@ +variable "tenancy_ocid" {} + +variable "authentication_policy_password_policy_is_lowercase_characters_required" {} + +variable "authentication_policy_password_policy_is_numeric_characters_required" {} + +variable "authentication_policy_password_policy_is_special_characters_required" {} + +variable "authentication_policy_password_policy_is_uppercase_characters_required" {} + +variable "authentication_policy_password_policy_is_username_containment_allowed" {} + +variable "authentication_policy_password_policy_minimum_password_length" {} \ No newline at end of file diff --git a/modules/bastion/README.md b/modules/bastion/README.md new file mode 100644 index 00000000..80de22ff --- /dev/null +++ b/modules/bastion/README.md @@ -0,0 +1,41 @@ +## Summary +Terraform module for OCI Bastion service. +Provide restricted and time-limited secure access to resources +that don't have public endpoints and require strict resource access controls. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_bastion_bastion.bastion](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/bastion_bastion) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [bastion\_client\_cidr\_block\_allow\_list](#input\_bastion\_client\_cidr\_block\_allow\_list) | A list of address ranges in CIDR notation that you want to allow to connect to sessions hosted by this bastion. | `list(string)` | n/a | yes | +| [bastion\_name](#input\_bastion\_name) | The name of the bastion, which can't be changed after creation. | `string` | n/a | yes | +| [compartment\_id](#input\_compartment\_id) | The OCID of the compartment where the bastion is located | `string` | n/a | yes | +| [target\_subnet\_id](#input\_target\_subnet\_id) | The OCID of the subnet that the bastion connects to | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [bastion\_ocid](#output\_bastion\_ocid) | The OCID of the bastion created | + \ No newline at end of file diff --git a/modules/bastion/main.tf b/modules/bastion/main.tf new file mode 100644 index 00000000..a77139fc --- /dev/null +++ b/modules/bastion/main.tf @@ -0,0 +1,18 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_bastion_bastion" "bastion" { + #Required + bastion_type = "STANDARD" + compartment_id = var.compartment_id + target_subnet_id = var.target_subnet_id + + #Optional + client_cidr_block_allow_list = var.bastion_client_cidr_block_allow_list + name = var.bastion_name +} \ No newline at end of file diff --git a/modules/bastion/outputs.tf b/modules/bastion/outputs.tf new file mode 100644 index 00000000..34124675 --- /dev/null +++ b/modules/bastion/outputs.tf @@ -0,0 +1,4 @@ +output "bastion_ocid" { + value = oci_bastion_bastion.bastion.id + description = "The OCID of the bastion created " +} \ No newline at end of file diff --git a/modules/bastion/variables.tf b/modules/bastion/variables.tf new file mode 100644 index 00000000..f80d6117 --- /dev/null +++ b/modules/bastion/variables.tf @@ -0,0 +1,19 @@ +variable "compartment_id" { + type = string + description = "The OCID of the compartment where the bastion is located" +} + +variable "target_subnet_id" { + type = string + description = "The OCID of the subnet that the bastion connects to" +} + +variable "bastion_client_cidr_block_allow_list" { + type = list(string) + description = "A list of address ranges in CIDR notation that you want to allow to connect to sessions hosted by this bastion." +} + +variable "bastion_name" { + type = string + description = "The name of the bastion, which can't be changed after creation." +} diff --git a/modules/break_glass_user/README.md b/modules/break_glass_user/README.md new file mode 100644 index 00000000..58e635a5 --- /dev/null +++ b/modules/break_glass_user/README.md @@ -0,0 +1,40 @@ + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | +| [random](#provider\_random) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_user.break_glass_user](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_user) | resource | +| [oci_identity_user_group_membership.administrator_group_membership](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_user_group_membership) | resource | +| [random_id.user](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | +| [oci_identity_groups.administrator_group](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/identity_groups) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [administrator\_group\_name](#input\_administrator\_group\_name) | The name for the administrator group | `string` | `"Administrators"` | no | +| [break\_glass\_user\_email](#input\_break\_glass\_user\_email) | The email address of the break glass user | `string` | n/a | yes | +| [break\_glass\_user\_index](#input\_break\_glass\_user\_index) | the index of the break glass user | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [break\_glass\_user\_list](#output\_break\_glass\_user\_list) | n/a | + \ No newline at end of file diff --git a/modules/break_glass_user/datasources.tf b/modules/break_glass_user/datasources.tf new file mode 100644 index 00000000..a3ff0fb0 --- /dev/null +++ b/modules/break_glass_user/datasources.tf @@ -0,0 +1,4 @@ +data "oci_identity_groups" "administrator_group" { + compartment_id = var.tenancy_ocid + name = var.administrator_group_name +} diff --git a/modules/break_glass_user/main.tf b/modules/break_glass_user/main.tf new file mode 100644 index 00000000..c9365502 --- /dev/null +++ b/modules/break_glass_user/main.tf @@ -0,0 +1,26 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "random_id" "user" { + byte_length = 4 +} + +resource "oci_identity_user" "break_glass_user" { + compartment_id = var.tenancy_ocid + description = "Break glass user ${var.break_glass_user_index}" + name = "Break_Glass_User_${var.break_glass_user_index}_${random_id.user.hex}" + email = var.break_glass_user_email +} + +# --------------------------------------------------------------------------------------------------------------------- +# Break Glass User Admin Group Membership +# --------------------------------------------------------------------------------------------------------------------- +resource "oci_identity_user_group_membership" "administrator_group_membership" { + group_id = data.oci_identity_groups.administrator_group.groups[0].id + user_id = oci_identity_user.break_glass_user.id +} \ No newline at end of file diff --git a/modules/break_glass_user/outputs.tf b/modules/break_glass_user/outputs.tf new file mode 100644 index 00000000..bc90f943 --- /dev/null +++ b/modules/break_glass_user/outputs.tf @@ -0,0 +1,3 @@ +output "break_glass_user_list" { + value = oci_identity_user.break_glass_user +} \ No newline at end of file diff --git a/modules/break_glass_user/variables.tf b/modules/break_glass_user/variables.tf new file mode 100644 index 00000000..86cfd9d9 --- /dev/null +++ b/modules/break_glass_user/variables.tf @@ -0,0 +1,21 @@ +variable "tenancy_ocid" { + type = string + description = "The OCID of tenancy" +} + +variable "break_glass_user_index" { + type = string + description = "the index of the break glass user" +} + +variable "break_glass_user_email" { + type = string + description = "The email address of the break glass user" +} + +variable "administrator_group_name" { + type = string + description = "The name for the administrator group" + default = "Administrators" +} + diff --git a/modules/bucket/README.md b/modules/bucket/README.md new file mode 100644 index 00000000..be475e30 --- /dev/null +++ b/modules/bucket/README.md @@ -0,0 +1,46 @@ +## Summary +Terraform module for OCI bucket, a container for storing objects in a compartment +within an Object Storage namespace. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_objectstorage_bucket.bucket](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/objectstorage_bucket) | resource | +| [oci_objectstorage_namespace.ns](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/objectstorage_namespace) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | The OCID of the compartment in which to create the bucket. | `string` | n/a | yes | +| [kms\_key\_id](#input\_kms\_key\_id) | The OCID of a master encryption key. | `string` | n/a | yes | +| [name](#input\_name) | The name of the bucket. Must be unique within an Object Storage namespace. | `string` | n/a | yes | +| [namespace](#input\_namespace) | The namespace of object storage bucket | `string` | n/a | yes | +| [retention\_policy\_duration\_amount](#input\_retention\_policy\_duration\_amount) | The timeAmount is interpreted in units defined by the timeUnit parameter. | `string` | n/a | yes | +| [retention\_policy\_duration\_time\_unit](#input\_retention\_policy\_duration\_time\_unit) | The unit that should be used to interpret timeAmount. | `string` | n/a | yes | +| [retention\_rule\_display\_name](#input\_retention\_rule\_display\_name) | The display name of retention rule | `string` | n/a | yes | +| [storage\_tier](#input\_storage\_tier) | The type of storage tier of this bucket. | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [bucket](#output\_bucket) | n/a | + \ No newline at end of file diff --git a/modules/bucket/datasources.tf b/modules/bucket/datasources.tf new file mode 100644 index 00000000..eafabe96 --- /dev/null +++ b/modules/bucket/datasources.tf @@ -0,0 +1,3 @@ +data "oci_objectstorage_namespace" "ns" { + compartment_id = var.tenancy_ocid +} diff --git a/modules/bucket/main.tf b/modules/bucket/main.tf new file mode 100644 index 00000000..63c29d1a --- /dev/null +++ b/modules/bucket/main.tf @@ -0,0 +1,25 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_objectstorage_bucket" "bucket" { + compartment_id = var.compartment_id + name = var.name + namespace = var.namespace + access_type = "NoPublicAccess" + kms_key_id = var.kms_key_id + storage_tier = var.storage_tier + + retention_rules { + display_name = var.retention_rule_display_name + + duration { + time_amount = var.retention_policy_duration_amount + time_unit = var.retention_policy_duration_time_unit + } + } +} diff --git a/modules/bucket/outputs.tf b/modules/bucket/outputs.tf new file mode 100644 index 00000000..991dd7f7 --- /dev/null +++ b/modules/bucket/outputs.tf @@ -0,0 +1,3 @@ +output "bucket" { + value = oci_objectstorage_bucket.bucket +} \ No newline at end of file diff --git a/modules/bucket/variables.tf b/modules/bucket/variables.tf new file mode 100644 index 00000000..1e22c4de --- /dev/null +++ b/modules/bucket/variables.tf @@ -0,0 +1,43 @@ +variable "tenancy_ocid" { + type = string + description = "The OCID of tenancy" +} +variable "name" { + type = string + description = "The name of the bucket. Must be unique within an Object Storage namespace. " +} + +variable "compartment_id" { + type = string + description = "The OCID of the compartment in which to create the bucket." +} + +variable "kms_key_id" { + type = string + description = "The OCID of a master encryption key." +} + +variable "storage_tier" { + type = string + description = "The type of storage tier of this bucket. " +} + +variable "retention_rule_display_name" { + type = string + description = "The display name of retention rule" +} + +variable "retention_policy_duration_amount" { + type = string + description = "The timeAmount is interpreted in units defined by the timeUnit parameter." +} + +variable "retention_policy_duration_time_unit" { + type = string + description = "The unit that should be used to interpret timeAmount." +} + +variable "namespace" { + type = string + description = "The namespace of object storage bucket" +} \ No newline at end of file diff --git a/modules/budget/README.md b/modules/budget/README.md new file mode 100644 index 00000000..12303ac6 --- /dev/null +++ b/modules/budget/README.md @@ -0,0 +1,57 @@ +## Summary + +Terraform module for OCI Budget creation. +Created budget and budget alert rule for a target compartment. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_budget_alert_rule.oci_budget_rule](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/budget_alert_rule) | resource | +| [oci_budget_budget.oci_budget](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/budget_budget) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [budget\_alert\_rule\_display\_name](#input\_budget\_alert\_rule\_display\_name) | n/a | `string` | n/a | yes | +| [budget\_alert\_rule\_message](#input\_budget\_alert\_rule\_message) | The alert message for budget alerts. | `string` | n/a | yes | +| [budget\_alert\_rule\_recipients](#input\_budget\_alert\_rule\_recipients) | The type of alert for the budget | `string` | n/a | yes | +| [budget\_alert\_rule\_threshold](#input\_budget\_alert\_rule\_threshold) | The target for the budget | `number` | n/a | yes | +| [budget\_alert\_rule\_threshold\_type](#input\_budget\_alert\_rule\_threshold\_type) | The threshold type for the budget | `string` | `"ABSOLUTE"` | no | +| [budget\_alert\_rule\_type](#input\_budget\_alert\_rule\_type) | The type of alert for the budget | `string` | `"ACTUAL"` | no | +| [budget\_amount](#input\_budget\_amount) | The amount of the budget expressed as a whole number in the currency of the customer's rate card. | `string` | n/a | yes | +| [budget\_description](#input\_budget\_description) | n/a | `string` | n/a | yes | +| [budget\_display\_name](#input\_budget\_display\_name) | n/a | `string` | n/a | yes | +| [budget\_reset\_period](#input\_budget\_reset\_period) | The reset period for the budget. | `string` | `"MONTHLY"` | no | +| [budget\_target](#input\_budget\_target) | The compartment ocid for the budget | `string` | n/a | yes | +| [budget\_target\_type](#input\_budget\_target\_type) | The target type for the budget | `string` | `"COMPARTMENT"` | no | +| [compartment\_id](#input\_compartment\_id) | The ocid of compartment to provision resources | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [budget](#output\_budget) | ----------------------------------------------------------------------------- Budget Output ----------------------------------------------------------------------------- | +| [budget\_alert\_rule](#output\_budget\_alert\_rule) | n/a | +| [budget\_alert\_rule\_recipients](#output\_budget\_alert\_rule\_recipients) | n/a | +| [budget\_alert\_rule\_threshold](#output\_budget\_alert\_rule\_threshold) | n/a | +| [budget\_amount](#output\_budget\_amount) | n/a | +| [budget\_id](#output\_budget\_id) | n/a | +| [budget\_target\_name](#output\_budget\_target\_name) | n/a | + \ No newline at end of file diff --git a/modules/budget/main.tf b/modules/budget/main.tf new file mode 100644 index 00000000..e6a5a057 --- /dev/null +++ b/modules/budget/main.tf @@ -0,0 +1,30 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + configuration_aliases = [oci] + } + } +} + +resource "oci_budget_budget" "oci_budget" { + compartment_id = var.compartment_id + amount = var.budget_amount + reset_period = var.budget_reset_period + + description = var.budget_description + display_name = var.budget_display_name + target_type = var.budget_target_type + targets = [ var.budget_target ] +} + +resource "oci_budget_alert_rule" "oci_budget_rule" { + budget_id = oci_budget_budget.oci_budget.id + threshold = var.budget_alert_rule_threshold + threshold_type = var.budget_alert_rule_threshold_type + type = var.budget_alert_rule_type + + display_name = var.budget_alert_rule_display_name + message = var.budget_alert_rule_message + recipients = var.budget_alert_rule_recipients +} diff --git a/modules/budget/outputs.tf b/modules/budget/outputs.tf new file mode 100644 index 00000000..a7f8ad2d --- /dev/null +++ b/modules/budget/outputs.tf @@ -0,0 +1,30 @@ +# ----------------------------------------------------------------------------- +# Budget Output +# ----------------------------------------------------------------------------- +output "budget" { + value = oci_budget_budget.oci_budget +} + +output "budget_alert_rule" { + value = oci_budget_alert_rule.oci_budget_rule +} + +output "budget_id" { + value = oci_budget_alert_rule.oci_budget_rule.budget_id +} + +output "budget_target_name" { + value = oci_budget_budget.oci_budget.display_name +} + +output "budget_amount" { + value = oci_budget_budget.oci_budget.amount +} + +output "budget_alert_rule_threshold" { + value = oci_budget_alert_rule.oci_budget_rule.threshold +} + +output "budget_alert_rule_recipients" { + value = oci_budget_alert_rule.oci_budget_rule.recipients +} diff --git a/modules/budget/variables.tf b/modules/budget/variables.tf new file mode 100644 index 00000000..1a5fde21 --- /dev/null +++ b/modules/budget/variables.tf @@ -0,0 +1,74 @@ +# ----------------------------------------------------------------------------- +# Required inputs +# ----------------------------------------------------------------------------- +variable "compartment_id" { + type = string + description = "The ocid of compartment to provision resources" +} + +variable "budget_amount" { + description = "The amount of the budget expressed as a whole number in the currency of the customer's rate card." + type = string +} + +variable "budget_reset_period" { + description = "The reset period for the budget." + default = "MONTHLY" + type = string +} + +variable "budget_description" { + + type = string +} + +variable "budget_display_name" { + + type = string +} + +variable "budget_target_type" { + description = "The target type for the budget" + default = "COMPARTMENT" + type = string +} + +variable "budget_target" { + description = "The compartment ocid for the budget" + type = string +} + +# ----------------------------------------------------------------------------- +# Optional inputs and values to override +# ----------------------------------------------------------------------------- +variable "budget_alert_rule_threshold" { + description = "The target for the budget" + type = number +} + +variable "budget_alert_rule_threshold_type" { + description = "The threshold type for the budget" + default = "ABSOLUTE" + type = string +} + +variable "budget_alert_rule_type" { + description = "The type of alert for the budget" + default = "ACTUAL" + type = string +} + +variable "budget_alert_rule_display_name" { + + type = string +} + +variable "budget_alert_rule_message" { + description = "The alert message for budget alerts." + type = string +} + +variable "budget_alert_rule_recipients" { + description = "The type of alert for the budget" + type = string +} diff --git a/modules/cloud-guard/README.md b/modules/cloud-guard/README.md new file mode 100644 index 00000000..a24c9239 --- /dev/null +++ b/modules/cloud-guard/README.md @@ -0,0 +1,54 @@ +## Summary +Terraform module for OCI Cloud Guard service. +That detects misconfigured resources, insecure activity +across tenants/compartments, and malicious threat activities and +provides security administrators with the visibility to triage +and resolve cloud security issues. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci.home\_region](#provider\_oci.home\_region) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_cloud_guard_cloud_guard_configuration.cloud_guard_configuration](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/cloud_guard_cloud_guard_configuration) | resource | +| [oci_cloud_guard_target.cloud_guard_target](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/cloud_guard_target) | resource | +| [oci_cloud_guard_detector_recipes.activity_detector_recipe](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/cloud_guard_detector_recipes) | data source | +| [oci_cloud_guard_detector_recipes.configuration_detector_recipe](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/cloud_guard_detector_recipes) | data source | +| [oci_cloud_guard_detector_recipes.threat_detector_recipe](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/cloud_guard_detector_recipes) | data source | +| [oci_cloud_guard_responder_recipes.responder_recipe](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/cloud_guard_responder_recipes) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [activity\_detector\_recipe\_display\_name](#input\_activity\_detector\_recipe\_display\_name) | The display name of activity detector recipe. | `string` | n/a | yes | +| [compartment\_id](#input\_compartment\_id) | The OCID of the compartment in which to list resources. | `string` | n/a | yes | +| [configuration\_detector\_recipe\_display\_name](#input\_configuration\_detector\_recipe\_display\_name) | The display name of configuration detector recipe. | `string` | n/a | yes | +| [description](#input\_description) | The target description. | `string` | n/a | yes | +| [display\_name](#input\_display\_name) | The display name of cloud guard target | `string` | n/a | yes | +| [region](#input\_region) | The reporting region value. | `string` | n/a | yes | +| [responder\_recipe\_display\_name](#input\_responder\_recipe\_display\_name) | The display name of responder recipe. | `string` | n/a | yes | +| [status](#input\_status) | Status of Cloud Guard Tenant | `string` | n/a | yes | +| [target\_resource\_id](#input\_target\_resource\_id) | Resource ID which the target uses to monitor. | `string` | n/a | yes | +| [target\_resource\_type](#input\_target\_resource\_type) | The type of targets. | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | +| [threat\_detector\_recipe\_display\_name](#input\_threat\_detector\_recipe\_display\_name) | The display name of threat detector recipe. | `string` | n/a | yes | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/modules/cloud-guard/datasources.tf b/modules/cloud-guard/datasources.tf new file mode 100644 index 00000000..10d74a43 --- /dev/null +++ b/modules/cloud-guard/datasources.tf @@ -0,0 +1,23 @@ +data "oci_cloud_guard_detector_recipes" "configuration_detector_recipe" { + provider = oci.home_region + compartment_id = var.tenancy_ocid + display_name = var.configuration_detector_recipe_display_name +} + +data "oci_cloud_guard_detector_recipes" "activity_detector_recipe" { + provider = oci.home_region + compartment_id = var.tenancy_ocid + display_name = var.activity_detector_recipe_display_name +} + +data "oci_cloud_guard_detector_recipes" "threat_detector_recipe" { + provider = oci.home_region + compartment_id = var.tenancy_ocid + display_name = var.threat_detector_recipe_display_name +} + +data "oci_cloud_guard_responder_recipes" "responder_recipe" { + provider = oci.home_region + compartment_id = var.tenancy_ocid + display_name = var.responder_recipe_display_name +} \ No newline at end of file diff --git a/modules/cloud-guard/main.tf b/modules/cloud-guard/main.tf new file mode 100644 index 00000000..e08bf248 --- /dev/null +++ b/modules/cloud-guard/main.tf @@ -0,0 +1,43 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + configuration_aliases = [oci, oci.home_region] + } + } +} + + +resource "oci_cloud_guard_cloud_guard_configuration" "cloud_guard_configuration" { + provider = oci.home_region + compartment_id = var.tenancy_ocid + reporting_region = var.region + status = var.status +} + +resource "oci_cloud_guard_target" "cloud_guard_target" { + provider = oci.home_region + compartment_id = var.compartment_id + display_name = var.display_name + target_resource_id = var.target_resource_id + target_resource_type = var.target_resource_type + description = var.description + + target_detector_recipes { + detector_recipe_id = data.oci_cloud_guard_detector_recipes.configuration_detector_recipe.detector_recipe_collection.0.items.0.id + } + + target_detector_recipes { + detector_recipe_id = data.oci_cloud_guard_detector_recipes.activity_detector_recipe.detector_recipe_collection.0.items.0.id + } + + target_detector_recipes { + detector_recipe_id = data.oci_cloud_guard_detector_recipes.threat_detector_recipe.detector_recipe_collection.0.items.0.id + } + + target_responder_recipes { + responder_recipe_id = data.oci_cloud_guard_responder_recipes.responder_recipe.responder_recipe_collection.0.items.0.id + } + + depends_on = [oci_cloud_guard_cloud_guard_configuration.cloud_guard_configuration] +} \ No newline at end of file diff --git a/modules/cloud-guard/outputs.tf b/modules/cloud-guard/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/modules/cloud-guard/variables.tf b/modules/cloud-guard/variables.tf new file mode 100644 index 00000000..e2b0dae4 --- /dev/null +++ b/modules/cloud-guard/variables.tf @@ -0,0 +1,60 @@ +variable "tenancy_ocid" { + type = string + description = "The OCID of tenancy" +} + +variable "region" { + type = string + description = "The reporting region value." +} + +variable "status" { + type = string + description = "Status of Cloud Guard Tenant" +} + +variable "compartment_id" { + type = string + description = "The OCID of the compartment in which to list resources." +} + +variable "display_name" { + type = string + description = "The display name of cloud guard target" +} + +variable "target_resource_id" { + type = string + description = "Resource ID which the target uses to monitor." +} + +variable "target_resource_type" { + type = string + description = "The type of targets." +} + +variable "description" { + type = string + description = "The target description." +} + +variable "configuration_detector_recipe_display_name" { + type = string + description = "The display name of configuration detector recipe." +} + +variable "activity_detector_recipe_display_name" { + type = string + description = "The display name of activity detector recipe." +} + +variable "threat_detector_recipe_display_name" { + type = string + description = "The display name of threat detector recipe." +} + +variable "responder_recipe_display_name" { + type = string + description = "The display name of responder recipe." +} + diff --git a/modules/compartment/README.md b/modules/compartment/README.md new file mode 100644 index 00000000..19eaa94f --- /dev/null +++ b/modules/compartment/README.md @@ -0,0 +1,45 @@ +## Summary +Terraform module for OCI Compartment creation. + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | +| [time](#provider\_time) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_compartment.compartment](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_compartment) | resource | +| [time_sleep.compartment_replication_delay](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_description](#input\_compartment\_description) | Description of the compartment to create. | `string` | n/a | yes | +| [compartment\_name](#input\_compartment\_name) | Name of the compartment to create. | `string` | n/a | yes | +| [compartment\_parent\_id](#input\_compartment\_parent\_id) | OCID of the parent compartment. | `string` | n/a | yes | +| [enable\_compartment\_delete](#input\_enable\_compartment\_delete) | Allows the compartment to delete on terraform destroy. | `bool` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [compartment](#output\_compartment) | The full compartment resource including all attributes | +| [compartment\_id](#output\_compartment\_id) | The OCID of the compartment created | +| [compartment\_name](#output\_compartment\_name) | The name of the compartment created | + diff --git a/modules/compartment/main.tf b/modules/compartment/main.tf new file mode 100644 index 00000000..33f702f8 --- /dev/null +++ b/modules/compartment/main.tf @@ -0,0 +1,21 @@ +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_identity_compartment" "compartment" { + compartment_id = var.compartment_parent_id + description = var.compartment_description + name = var.compartment_name + enable_delete = var.enable_compartment_delete +} + +resource "time_sleep" "compartment_replication_delay" { + depends_on = [oci_identity_compartment.compartment] + create_duration = "90s" +} diff --git a/modules/compartment/outputs.tf b/modules/compartment/outputs.tf new file mode 100644 index 00000000..26370f45 --- /dev/null +++ b/modules/compartment/outputs.tf @@ -0,0 +1,14 @@ +output "compartment" { + value = oci_identity_compartment.compartment + description = "The full compartment resource including all attributes" +} + +output "compartment_id" { + value = oci_identity_compartment.compartment.id + description = "The OCID of the compartment created" +} + +output "compartment_name" { + value = oci_identity_compartment.compartment.name + description = "The name of the compartment created" +} diff --git a/modules/compartment/variables.tf b/modules/compartment/variables.tf new file mode 100644 index 00000000..6a93c4f8 --- /dev/null +++ b/modules/compartment/variables.tf @@ -0,0 +1,19 @@ +variable "compartment_parent_id" { + type = string + description = "OCID of the parent compartment." +} + +variable "compartment_name" { + type = string + description = "Name of the compartment to create." +} + +variable "compartment_description" { + type = string + description = "Description of the compartment to create." +} + +variable "enable_compartment_delete" { + type = bool + description = "Allows the compartment to delete on terraform destroy." +} diff --git a/modules/drg/README.md b/modules/drg/README.md new file mode 100644 index 00000000..b44cc2bf --- /dev/null +++ b/modules/drg/README.md @@ -0,0 +1,53 @@ +## Summary +Terraform module for managing a single Dynamic Routing Gateway +and associated routing resources - including drg, attachments, +route distributions, and drg route tables. + +## Dependencies +* VCN +* Route-Table + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_core_drg.drg](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_drg) | resource | +| [oci_core_drg_attachment.drg_vcn_attachment](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_drg_attachment) | resource | +| [oci_core_drg_route_distribution.route_distribution](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_drg_route_distribution) | resource | +| [oci_core_drg_route_distribution_statement.route_distribution_statement](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_drg_route_distribution_statement) | resource | +| [oci_core_drg_route_table.route_table](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_drg_route_table) | resource | +| [oci_core_drg_route_table_route_rule.drg_route_table_route_rule](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_drg_route_table_route_rule) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | compartment id where to create all resources | `string` | n/a | yes | +| [drg\_display\_name](#input\_drg\_display\_name) | (Updatable) Name of Dynamic Routing Gateway. Does not have to be unique. | `string` | n/a | yes | +| [drg\_route\_table\_map](#input\_drg\_route\_table\_map) | The route table used by the DRG attachment. | `map(any)` | `null` | no | +| [drg\_vcn\_attachments](#input\_drg\_vcn\_attachments) | The network resource attached to the DRG | `map(any)` | `null` | no | +| [route\_distribution\_map](#input\_route\_distribution\_map) | The route table used by the DRG attachment. | `map(any)` | `null` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [drg\_attachment\_all\_attributes](#output\_drg\_attachment\_all\_attributes) | all attributes related to drg attachment | +| [drg\_id](#output\_drg\_id) | id of drg if it is created | +| [drg\_route\_tables](#output\_drg\_route\_tables) | n/a | + \ No newline at end of file diff --git a/modules/drg/main.tf b/modules/drg/main.tf new file mode 100644 index 00000000..d6d7374e --- /dev/null +++ b/modules/drg/main.tf @@ -0,0 +1,114 @@ +# Reference: https://github.com/oracle-terraform-modules/terraform-oci-drg + +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +# ----------------------------------------------------------------------------- +# Create Dynamic Routing Gateway and Attachments +# ----------------------------------------------------------------------------- +locals { + drg_attachment_defaults = { + route_table_id = null + type = "VCN" + export_drg_route_distribution_id = null + remove_export_drg_route_distribution_trigger = false + } + + drg_attachments_normalized = { + for k, v in var.drg_vcn_attachments : + k => merge(local.drg_attachment_defaults, v) + } +} + +resource "oci_core_drg" "drg" { + compartment_id = var.compartment_id + display_name = var.drg_display_name +} + +resource "oci_core_drg_attachment" "drg_vcn_attachment" { + for_each = local.drg_attachments_normalized + drg_id = oci_core_drg.drg.id + display_name = each.value.display_name + + network_details { + id = each.value.vcn_id + route_table_id = each.value.route_table_id + type = each.value.type + } + + drg_route_table_id = each.value.drg_route_table_name != null ? oci_core_drg_route_table.route_table[each.value.drg_route_table_name].id : null +} + +# ----------------------------------------------------------------------------- +# Create Import Hub Distribution +# ----------------------------------------------------------------------------- +locals { + distribution_statements = merge( + flatten([ + for k, v in var.route_distribution_map : { + for k2, v2 in v.statements : k2 => { + drg_route_distribution_id = oci_core_drg_route_distribution.route_distribution[k].id + action = v2.action + match_type = v2.match_type + attachment_type = v2.attachment_type + drg_attachment_name = v2.drg_attachment_name + priority = v2.priority + } + }])...) +} + +resource "oci_core_drg_route_distribution" "route_distribution" { + for_each = var.route_distribution_map + distribution_type = each.value.distribution_type + drg_id = oci_core_drg.drg.id + display_name = each.value.distribution_display_name +} + +resource "oci_core_drg_route_distribution_statement" "route_distribution_statement" { + for_each = local.distribution_statements + drg_route_distribution_id = each.value.drg_route_distribution_id + action = each.value.action + priority = each.value.priority + + match_criteria { + match_type = each.value.match_type + attachment_type = each.value.attachment_type + drg_attachment_id = each.value.drg_attachment_name != "" ? oci_core_drg_attachment.drg_vcn_attachment[each.value.drg_attachment_name].id : null + } +} + +# ----------------------------------------------------------------------------- +# Create Route Tables and Rules +# ----------------------------------------------------------------------------- +locals { + route_rules = merge( + flatten([ + for route_table_name, route_table in var.drg_route_table_map : { + for route_rule_key, route_rule in route_table.rules : route_rule_key => { + drg_route_table_id = oci_core_drg_route_table.route_table[route_table_name].id + destination = route_rule.destination + destination_type = route_rule.destination_type + next_hop_drg_attachment_id = oci_core_drg_attachment.drg_vcn_attachment[route_rule.next_hop_attachment_name].id + } + }])...) +} + +resource "oci_core_drg_route_table" "route_table" { + for_each = var.drg_route_table_map + drg_id = oci_core_drg.drg.id + display_name = each.value.display_name + import_drg_route_distribution_id = each.value.route_distribution_name != null ? oci_core_drg_route_distribution.route_distribution[each.value.route_distribution_name].id : null +} + +resource "oci_core_drg_route_table_route_rule" "drg_route_table_route_rule" { + for_each = local.route_rules + drg_route_table_id = each.value.drg_route_table_id + destination = each.value.destination + destination_type = each.value.destination_type + next_hop_drg_attachment_id = each.value.next_hop_drg_attachment_id +} diff --git a/modules/drg/outputs.tf b/modules/drg/outputs.tf new file mode 100644 index 00000000..7e915045 --- /dev/null +++ b/modules/drg/outputs.tf @@ -0,0 +1,13 @@ +output "drg_id" { + description = "id of drg if it is created" + value = oci_core_drg.drg.id +} + +output "drg_attachment_all_attributes" { + description = "all attributes related to drg attachment" + value = { for k, v in oci_core_drg_attachment.drg_vcn_attachment : k => v } +} + +output "drg_route_tables" { + value = { for k, v in oci_core_drg_route_table.route_table: k => v } +} \ No newline at end of file diff --git a/modules/drg/variables.tf b/modules/drg/variables.tf new file mode 100644 index 00000000..61faf3ae --- /dev/null +++ b/modules/drg/variables.tf @@ -0,0 +1,32 @@ +variable "compartment_id" { + description = "compartment id where to create all resources" + type = string +} + +variable "drg_display_name" { + description = "(Updatable) Name of Dynamic Routing Gateway. Does not have to be unique." + type = string + validation { + condition = length(var.drg_display_name) > 0 + error_message = "The drg_display_name value cannot be an empty string." + } +} + +# @TODO add type definitions for maps/objects +variable "drg_vcn_attachments" { + description = "The network resource attached to the DRG" + type = map(any) + default = null +} + +variable "route_distribution_map" { + type = map(any) + default = null + description = "The route table used by the DRG attachment." +} + +variable "drg_route_table_map" { + type = map(any) + default = null + description = "The route table used by the DRG attachment." +} diff --git a/modules/dynamic-group/README.md b/modules/dynamic-group/README.md new file mode 100644 index 00000000..1227bd5b --- /dev/null +++ b/modules/dynamic-group/README.md @@ -0,0 +1,42 @@ +## Summary +Terraform module for dynamic groups, that +allow you to group Oracle Cloud Infrastructure +compute instances as "principal" actors (similar to user groups). + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_dynamic_group.dynamic_group](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_dynamic_group) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [description](#input\_description) | The description you assign to the Group. Does not have to be unique, and it's changeable. | `string` | n/a | yes | +| [matching\_rule](#input\_matching\_rule) | Define a matching rule or a set of matching rules to define the group members. | `string` | n/a | yes | +| [name](#input\_name) | The name you assign to the group during creation. The name must be unique across all compartments in the tenancy. | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of the tenancy. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [id](#output\_id) | The OCID of dynamic group created | +| [name](#output\_name) | The name of dynamic group created | + \ No newline at end of file diff --git a/modules/dynamic-group/main.tf b/modules/dynamic-group/main.tf new file mode 100644 index 00000000..46597052 --- /dev/null +++ b/modules/dynamic-group/main.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_identity_dynamic_group" "dynamic_group" { + compartment_id = var.tenancy_ocid + description = var.description + matching_rule = var.matching_rule + name = var.name +} diff --git a/modules/dynamic-group/outputs.tf b/modules/dynamic-group/outputs.tf new file mode 100644 index 00000000..efa17107 --- /dev/null +++ b/modules/dynamic-group/outputs.tf @@ -0,0 +1,10 @@ + +output "id" { + value = oci_identity_dynamic_group.dynamic_group.id + description = "The OCID of dynamic group created" +} + +output "name" { + value = oci_identity_dynamic_group.dynamic_group.name + description = "The name of dynamic group created" +} \ No newline at end of file diff --git a/modules/dynamic-group/variables.tf b/modules/dynamic-group/variables.tf new file mode 100644 index 00000000..021b7897 --- /dev/null +++ b/modules/dynamic-group/variables.tf @@ -0,0 +1,19 @@ +variable "tenancy_ocid" { + type = string + description = "The OCID of the tenancy." +} + +variable "name" { + type = string + description = "The name you assign to the group during creation. The name must be unique across all compartments in the tenancy. " +} + +variable "description" { + type = string + description = "The description you assign to the Group. Does not have to be unique, and it's changeable. " +} + +variable "matching_rule" { + type = string + description = "Define a matching rule or a set of matching rules to define the group members." +} \ No newline at end of file diff --git a/modules/fastconnect/README.md b/modules/fastconnect/README.md new file mode 100644 index 00000000..902ac372 --- /dev/null +++ b/modules/fastconnect/README.md @@ -0,0 +1,61 @@ +## Summary + +Terraform module for OCI FastConnect creation. + + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_core_drg_attachment_management.drg_vc_attachment_asn](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_drg_attachment_management) | resource | +| [oci_core_drg_attachment_management.drg_vc_attachment_azure](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_drg_attachment_management) | resource | +| [oci_core_drg_attachment_management.drg_vc_attachment_no_asn](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_drg_attachment_management) | resource | +| [oci_core_virtual_circuit.azure_fastconnect_virtual_circuit](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_virtual_circuit) | resource | +| [oci_core_virtual_circuit.fastconnect_asn_virtual_circuit](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_virtual_circuit) | resource | +| [oci_core_virtual_circuit.fastconnect_no_asn_virtual_circuit](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_virtual_circuit) | resource | +| [oci_core_fast_connect_provider_service.fast_connect_provider_service](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/core_fast_connect_provider_service) | data source | +| [oci_core_fast_connect_provider_services.fast_connect_provider_services](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/core_fast_connect_provider_services) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [bgp\_md5auth\_key](#input\_bgp\_md5auth\_key) | n/a | `string` | n/a | yes | +| [compartment\_ocid](#input\_compartment\_ocid) | n/a | `string` | n/a | yes | +| [customer\_primary\_bgp\_peering\_ip](#input\_customer\_primary\_bgp\_peering\_ip) | n/a | `string` | n/a | yes | +| [customer\_secondary\_bgp\_peering\_ip](#input\_customer\_secondary\_bgp\_peering\_ip) | n/a | `string` | n/a | yes | +| [drg\_id](#input\_drg\_id) | n/a | `string` | n/a | yes | +| [drg\_route\_table\_vc\_id](#input\_drg\_route\_table\_vc\_id) | n/a | `string` | n/a | yes | +| [fastconnect\_asn\_provider\_list](#input\_fastconnect\_asn\_provider\_list) | Providers that require customer asn | `string` | `"Megaport,QTS,C3ntro,Cologix,CoreSite,Digital Realty,EdgeConneX,Epsilon,Equinix,InterCloud,Lumen,Neutrona,OracleL2ItegDeployment,Zayo"` | no | +| [fastconnect\_no\_asn\_provider\_list](#input\_fastconnect\_no\_asn\_provider\_list) | Providers that don't require customer asn or peering ip | `string` | `"AT&T,Verizon,BT,OMCS,OracleL3ItegDeployment,Orange"` | no | +| [fastconnect\_provider](#input\_fastconnect\_provider) | n/a | `string` | n/a | yes | +| [fastconnect\_routing\_policy](#input\_fastconnect\_routing\_policy) | n/a | `list(string)` | n/a | yes | +| [oracle\_primary\_bgp\_peering\_ip](#input\_oracle\_primary\_bgp\_peering\_ip) | n/a | `string` | n/a | yes | +| [oracle\_secondary\_bgp\_peering\_ip](#input\_oracle\_secondary\_bgp\_peering\_ip) | n/a | `string` | n/a | yes | +| [provider\_service\_key\_name](#input\_provider\_service\_key\_name) | n/a | `string` | n/a | yes | +| [region\_key](#input\_region\_key) | n/a | `string` | n/a | yes | +| [virtual\_circuit\_bandwidth\_shape](#input\_virtual\_circuit\_bandwidth\_shape) | n/a | `string` | n/a | yes | +| [virtual\_circuit\_customer\_asn](#input\_virtual\_circuit\_customer\_asn) | n/a | `string` | n/a | yes | +| [virtual\_circuit\_display\_name](#input\_virtual\_circuit\_display\_name) | n/a | `string` | n/a | yes | +| [virtual\_circuit\_is\_bfd\_enabled](#input\_virtual\_circuit\_is\_bfd\_enabled) | n/a | `bool` | n/a | yes | +| [virtual\_circuit\_type](#input\_virtual\_circuit\_type) | n/a | `string` | n/a | yes | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/modules/fastconnect/datasources.tf b/modules/fastconnect/datasources.tf new file mode 100644 index 00000000..5b28c69d --- /dev/null +++ b/modules/fastconnect/datasources.tf @@ -0,0 +1,7 @@ +data "oci_core_fast_connect_provider_services" "fast_connect_provider_services" { + compartment_id = var.compartment_ocid +} + +data "oci_core_fast_connect_provider_service" "fast_connect_provider_service" { + provider_service_id = lookup(element(data.oci_core_fast_connect_provider_services.fast_connect_provider_services.fast_connect_provider_services, index(data.oci_core_fast_connect_provider_services.fast_connect_provider_services.fast_connect_provider_services.*.provider_name, var.fastconnect_provider)), "id") +} diff --git a/modules/fastconnect/main.tf b/modules/fastconnect/main.tf new file mode 100644 index 00000000..e5bb5c63 --- /dev/null +++ b/modules/fastconnect/main.tf @@ -0,0 +1,109 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} +locals { + fastconnect_asn_provider_list = split(",", var.fastconnect_asn_provider_list) + fastconnect_no_asn_provider_list = split(",", var.fastconnect_no_asn_provider_list) +} + +# ----------------------------------------------------------------------------- +# Create FastConnect virtual circuit for Azure ExpressRoute +# ----------------------------------------------------------------------------- +resource "oci_core_virtual_circuit" "azure_fastconnect_virtual_circuit" { + count = var.fastconnect_provider == "Azure" ? 1 : 0 + compartment_id = var.compartment_ocid + gateway_id = var.drg_id + bandwidth_shape_name = var.virtual_circuit_bandwidth_shape + display_name = var.virtual_circuit_display_name + provider_service_id = data.oci_core_fast_connect_provider_service.fast_connect_provider_service.id + provider_service_key_name = var.provider_service_key_name + region = var.region_key + routing_policy = var.fastconnect_routing_policy + type = var.virtual_circuit_type + is_bfd_enabled = var.virtual_circuit_is_bfd_enabled + cross_connect_mappings { + bgp_md5auth_key = var.bgp_md5auth_key + customer_bgp_peering_ip = var.customer_primary_bgp_peering_ip + oracle_bgp_peering_ip = var.oracle_primary_bgp_peering_ip + } + cross_connect_mappings { + bgp_md5auth_key = var.bgp_md5auth_key + customer_bgp_peering_ip = var.customer_secondary_bgp_peering_ip + oracle_bgp_peering_ip = var.oracle_secondary_bgp_peering_ip + } +} + +# ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +# Create FastConnect virtual circuit for Megaport/QTS/C3ntro/Cologix/CoreSite/Digital Realty/EdgeConneX/Epsilon/Equinix/InterCloud/Lumen/Neutrona/OracleL2ItegDeployment/Zayo +# ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +resource "oci_core_virtual_circuit" "fastconnect_asn_virtual_circuit" { + count = contains(local.fastconnect_asn_provider_list, var.fastconnect_provider) ? 1 : 0 + compartment_id = var.compartment_ocid + customer_asn = var.virtual_circuit_customer_asn + gateway_id = var.drg_id + bandwidth_shape_name = var.virtual_circuit_bandwidth_shape + display_name = var.virtual_circuit_display_name + provider_service_id = data.oci_core_fast_connect_provider_service.fast_connect_provider_service.id + region = var.region_key + routing_policy = var.fastconnect_routing_policy + type = var.virtual_circuit_type + is_bfd_enabled = var.virtual_circuit_is_bfd_enabled + cross_connect_mappings { + bgp_md5auth_key = var.bgp_md5auth_key + customer_bgp_peering_ip = var.customer_primary_bgp_peering_ip + oracle_bgp_peering_ip = var.oracle_primary_bgp_peering_ip + } +} + +# ----------------------------------------------------------------------------------------- +# Create FastConnect virtual circuit for AT&T/Verizon/BT/OMCS/OracleL3ItegDeployment/Orange +# ----------------------------------------------------------------------------------------- +resource "oci_core_virtual_circuit" "fastconnect_no_asn_virtual_circuit" { + count = contains(local.fastconnect_no_asn_provider_list, var.fastconnect_provider) ? 1 : 0 + compartment_id = var.compartment_ocid + gateway_id = var.drg_id + bandwidth_shape_name = var.virtual_circuit_bandwidth_shape + display_name = var.virtual_circuit_display_name + provider_service_id = data.oci_core_fast_connect_provider_service.fast_connect_provider_service.id + region = var.region_key + routing_policy = var.fastconnect_routing_policy + type = var.virtual_circuit_type + is_bfd_enabled = var.virtual_circuit_is_bfd_enabled +} + +# ----------------------------------------------------------------------------------------- +# Create Virtual Circuit DRG Attachment +# ----------------------------------------------------------------------------------------- +resource "oci_core_drg_attachment_management" "drg_vc_attachment_azure" { + count = var.fastconnect_provider == "Azure" ? 1 : 0 + attachment_type = "VIRTUAL_CIRCUIT" + compartment_id = var.compartment_ocid + network_id = oci_core_virtual_circuit.azure_fastconnect_virtual_circuit[0].id + drg_id = var.drg_id + display_name = "P-VC-Attachment" + drg_route_table_id = var.drg_route_table_vc_id +} + +resource "oci_core_drg_attachment_management" "drg_vc_attachment_asn" { + count = contains(local.fastconnect_asn_provider_list, var.fastconnect_provider) ? 1 : 0 + attachment_type = "VIRTUAL_CIRCUIT" + compartment_id = var.compartment_ocid + network_id = oci_core_virtual_circuit.fastconnect_asn_virtual_circuit[0].id + drg_id = var.drg_id + display_name = "P-VC-Attachment" + drg_route_table_id = var.drg_route_table_vc_id +} + +resource "oci_core_drg_attachment_management" "drg_vc_attachment_no_asn" { + count = contains(local.fastconnect_no_asn_provider_list, var.fastconnect_provider) ? 1 : 0 + attachment_type = "VIRTUAL_CIRCUIT" + compartment_id = var.compartment_ocid + network_id = oci_core_virtual_circuit.fastconnect_no_asn_virtual_circuit[0].id + drg_id = var.drg_id + display_name = "P-VC-Attachment" + drg_route_table_id = var.drg_route_table_vc_id +} \ No newline at end of file diff --git a/modules/fastconnect/variables.tf b/modules/fastconnect/variables.tf new file mode 100644 index 00000000..a66d0265 --- /dev/null +++ b/modules/fastconnect/variables.tf @@ -0,0 +1,79 @@ +variable "fastconnect_asn_provider_list" { + type = string + description = "Providers that require customer asn" + default = "Megaport,QTS,C3ntro,Cologix,CoreSite,Digital Realty,EdgeConneX,Epsilon,Equinix,InterCloud,Lumen,Neutrona,OracleL2ItegDeployment,Zayo" +} + +variable "fastconnect_no_asn_provider_list" { + type = string + description = "Providers that don't require customer asn or peering ip" + default = "AT&T,Verizon,BT,OMCS,OracleL3ItegDeployment,Orange" +} + +variable "fastconnect_provider" { + type = string +} + +variable "compartment_ocid" { + type = string +} + +variable "drg_id" { + type = string +} + +variable "region_key" { + type = string +} + +variable "virtual_circuit_bandwidth_shape" { + type = string +} + +variable "virtual_circuit_display_name" { + type = string +} + +variable "provider_service_key_name" { + type = string +} + +variable "fastconnect_routing_policy" { + type = list(string) +} + +variable "virtual_circuit_type" { + type = string +} + +variable "customer_primary_bgp_peering_ip" { + type = string +} + +variable "oracle_primary_bgp_peering_ip" { + type = string +} + +variable "customer_secondary_bgp_peering_ip" { + type = string +} + +variable "oracle_secondary_bgp_peering_ip" { + type = string +} + +variable "virtual_circuit_customer_asn" { + type = string +} + +variable "virtual_circuit_is_bfd_enabled" { + type = bool +} + +variable "bgp_md5auth_key" { + type = string +} + +variable "drg_route_table_vc_id" { + type = string +} \ No newline at end of file diff --git a/modules/identity-domain/README.md b/modules/identity-domain/README.md new file mode 100644 index 00000000..91566661 --- /dev/null +++ b/modules/identity-domain/README.md @@ -0,0 +1,55 @@ +## Summary +Terraform module for OCI Identity Domain. +A container for managing users and roles, federating and provisioning +of users, secure application integration through Oracle Single Sign-On (SSO) +configuration, and SAML/OAuth based Identity Provider administration. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [null](#provider\_null) | n/a | +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [null_resource.groups](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | +| [oci_identity_domain.domain](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_domain) | resource | +| [oci_identity_domain_replication_to_region.test_domain_replication_to_region](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_domain_replication_to_region) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | The OCID of the Compartment where domain is created | `string` | n/a | yes | +| [domain\_admin\_email](#input\_domain\_admin\_email) | The admin email address. | `string` | `null` | no | +| [domain\_admin\_first\_name](#input\_domain\_admin\_first\_name) | The admin email address. | `string` | `null` | no | +| [domain\_admin\_last\_name](#input\_domain\_admin\_last\_name) | The admin email address. | `string` | `null` | no | +| [domain\_admin\_user\_name](#input\_domain\_admin\_user\_name) | The admin email address. | `string` | `null` | no | +| [domain\_description](#input\_domain\_description) | Domain entity description. | `string` | n/a | yes | +| [domain\_display\_name](#input\_domain\_display\_name) | The mutable display name of the domain. | `string` | n/a | yes | +| [domain\_home\_region](#input\_domain\_home\_region) | The region's name. | `string` | n/a | yes | +| [domain\_is\_hidden\_on\_login](#input\_domain\_is\_hidden\_on\_login) | Indicates whether domain is hidden on login screen or not. | `bool` | `false` | no | +| [domain\_is\_notification\_bypassed](#input\_domain\_is\_notification\_bypassed) | Indicates if admin user created in IDCS stripe would like to receive notification like welcome email or not. | `bool` | `false` | no | +| [domain\_is\_primary\_email\_required](#input\_domain\_is\_primary\_email\_required) | Indicate whether users in the domain are required to have a primary email address or not. | `bool` | `true` | no | +| [domain\_license\_type](#input\_domain\_license\_type) | The license type of Domain | `string` | n/a | yes | +| [domain\_replica\_region](#input\_domain\_replica\_region) | A region for which domain replication is requested for. | `string` | `""` | no | +| [group\_names](#input\_group\_names) | The list of user group names. | `list(string)` | `[]` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [domain](#output\_domain) | n/a | + \ No newline at end of file diff --git a/modules/identity-domain/main.tf b/modules/identity-domain/main.tf new file mode 100644 index 00000000..8aed4193 --- /dev/null +++ b/modules/identity-domain/main.tf @@ -0,0 +1,49 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_identity_domain" "domain" { + compartment_id = var.compartment_id + description = var.domain_description + display_name = var.domain_display_name + home_region = var.domain_home_region + license_type = var.domain_license_type + admin_email = var.domain_admin_email + admin_first_name = var.domain_admin_first_name + admin_last_name = var.domain_admin_last_name + admin_user_name = var.domain_admin_user_name + is_hidden_on_login = var.domain_is_hidden_on_login + is_notification_bypassed = var.domain_is_notification_bypassed + is_primary_email_required = var.domain_is_primary_email_required +} + +resource "oci_identity_domain_replication_to_region" "test_domain_replication_to_region" { + count = var.domain_replica_region != "" ? 1 : 0 + domain_id = oci_identity_domain.domain.id + replica_region = var.domain_replica_region +} + +resource "null_resource" "groups" { + count = length(var.group_names) != 0 ? 1 : 0 + + triggers = { + domain_id = oci_identity_domain.domain.id + group_names = "${join(",", var.group_names)}" + } + + provisioner "local-exec" { + working_dir = path.module + command = "pip3 install -r scripts/requirements.txt" + on_failure = continue + } + + provisioner "local-exec" { + working_dir = path.module + command = "python3 scripts/manage_identity_domain.py -d ${oci_identity_domain.domain.id} -g ${join(" ", var.group_names)}" + on_failure = continue + } +} diff --git a/modules/identity-domain/outputs.tf b/modules/identity-domain/outputs.tf new file mode 100644 index 00000000..d3dd96c2 --- /dev/null +++ b/modules/identity-domain/outputs.tf @@ -0,0 +1,3 @@ +output "domain" { + value = oci_identity_domain.domain +} diff --git a/modules/identity-domain/scripts/manage_identity_domain.py b/modules/identity-domain/scripts/manage_identity_domain.py new file mode 100644 index 00000000..a2732d79 --- /dev/null +++ b/modules/identity-domain/scripts/manage_identity_domain.py @@ -0,0 +1,128 @@ +# Reference: +# https://docs.oracle.com/en-us/iaas/Content/API/Concepts/signingrequests.htm#seven__Python +# https://www.ateam-oracle.com/post/oracle-cloud-infrastructure-oci-rest-call-walkthrough-with-curl + +import argparse +import oci +import os +import json +import requests + + +class ManageIdentityDomain: + def __init__(self, domain_id, group_names): + self.config, self.auth = self.set_up_oci_config() + self.identity_client = oci.identity.IdentityClient(self.config) + + self.host = self.get_domain_url(domain_id) + self.group_endpoint = self.host + "/admin/v1/Groups" + self.group_names = group_names + + def set_up_oci_config(self): + ''' + check terraform environment variables, prefixed by TF_, so it can run in our pipeline + ''' + try: + config = oci.config.from_file() + auth = oci.Signer( + tenancy=config['tenancy'], + user=config['user'], + fingerprint=config['fingerprint'], + private_key_file_location=config['key_file'] + ) + except oci.exceptions.ConfigFileNotFound: + + tenancy = os.environ.get("TF_VAR_tenancy_ocid") + user = os.environ.get("TF_VAR_current_user_ocid") + fingerprint = os.environ.get("TF_VAR_api_fingerprint") + private_key_file = os.environ.get("TF_VAR_api_private_key") + region = os.environ.get("TF_VAR_region") + + config = { + "user": user, + "key_content": private_key_file, + "fingerprint": fingerprint, + "tenancy": tenancy, + "region": region, + } + auth = oci.Signer( + tenancy=config['tenancy'], + user=config['user'], + fingerprint=config['fingerprint'], + private_key_content=config["key_content"], + private_key_file_location=None + ) + + return config, auth + + def get_domain_url(self, domain_id): + print("Waiting for domain to enter ACTIVE state") + get_domain_response = self.identity_client.get_domain( + domain_id=domain_id) + wait_until_domain_available_response = oci.wait_until( + self.identity_client, get_domain_response, 'lifecycle_state', 'ACTIVE') + + print( + f"Got domain url {wait_until_domain_available_response.data.url}") + + return wait_until_domain_available_response.data.url + + def create_group(self, group_name): + body = { + "displayName": group_name, + "schemas": [ + "urn:ietf:params:scim:schemas:core:2.0:Group", + "urn:ietf:params:scim:schemas:oracle:idcs:extension:group:Group" + ] + } + + response = requests.post( + self.group_endpoint, json=body, auth=self.auth) + response.raise_for_status() + + print( + f"Display Name: {group_name} \tOCID: {json.loads(response.content)['ocid']}") + + def create_groups(self): + for group in self.group_names: + print(f"Provisioning group {group}") + try: + self.create_group(group) + except requests.HTTPError as e: + print(f"Error creating group {group}") + print(e) + + def delete_group(self, group_name): + # @TODO finish delete method and add destroy provisioner + return + # filter=displayName eq "john" + response = requests.delete( + self.group_endpoint + f"/", auth=self.auth) + response.raise_for_status() + + print(f"Display Name: {group_name} deleted") + + def delete_groups(self): + for group in self.group_names: + print(f"Deleting group {group}") + try: + self.delete_group(group) + except requests.HTTPError as e: + print(f"Error deleting group {group}") + print(e) + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser(description="Manage an Identity Domain") + parser.add_argument('-d', '--domain_id', + help=" Id of the domain to manage", + required=True) + parser.add_argument('-g', '--group_names', + nargs='+', + help=' Names of the groups to create (space seperated)', + required=True) + + args = parser.parse_args() + manage_id = ManageIdentityDomain(args.domain_id, args.group_names) + manage_id.create_groups() diff --git a/modules/identity-domain/scripts/requirements.txt b/modules/identity-domain/scripts/requirements.txt new file mode 100644 index 00000000..6d3dde48 --- /dev/null +++ b/modules/identity-domain/scripts/requirements.txt @@ -0,0 +1,2 @@ +oci +requests \ No newline at end of file diff --git a/modules/identity-domain/variables.tf b/modules/identity-domain/variables.tf new file mode 100644 index 00000000..a01bf0d6 --- /dev/null +++ b/modules/identity-domain/variables.tf @@ -0,0 +1,84 @@ +variable "compartment_id" { + type = string + description = "The OCID of the Compartment where domain is created" +} + +# ----------------------------------------------------------------------------- +# Domain Variables +# ----------------------------------------------------------------------------- +variable "domain_description" { + type = string + description = "Domain entity description." +} + +variable "domain_display_name" { + type = string + description = "The mutable display name of the domain." +} + +variable "domain_home_region" { + type = string + description = "The region's name." +} + +variable "domain_license_type" { + type = string + description = "The license type of Domain" +} + +variable "domain_admin_email" { + type = string + default = null + description = "The admin email address." +} + +variable "domain_admin_first_name" { + type = string + default = null + description = "The admin email address." +} + +variable "domain_admin_last_name" { + type = string + default = null + description = "The admin email address." +} + +variable "domain_admin_user_name" { + type = string + default = null + description = "The admin email address." +} + +variable "domain_is_hidden_on_login" { + type = bool + default = false + description = "Indicates whether domain is hidden on login screen or not." +} + +variable "domain_is_notification_bypassed" { + type = bool + default = false + description = "Indicates if admin user created in IDCS stripe would like to receive notification like welcome email or not." +} + +variable "domain_is_primary_email_required" { + type = bool + default = true + description = "Indicate whether users in the domain are required to have a primary email address or not." +} + +variable "domain_replica_region" { + type = string + default = "" + description = "A region for which domain replication is requested for." +} + +# ----------------------------------------------------------------------------- +# Group Variables +# ----------------------------------------------------------------------------- +variable "group_names" { + type = list(string) + default = [] + description = "The list of user group names." +} diff --git a/modules/internet-gateway/README.md b/modules/internet-gateway/README.md new file mode 100644 index 00000000..b3524e81 --- /dev/null +++ b/modules/internet-gateway/README.md @@ -0,0 +1,35 @@ + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_core_internet_gateway.OCI-ELZ-IGW-P-HUB](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_internet_gateway) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [internet\_gateway\_display\_name](#input\_internet\_gateway\_display\_name) | Internet Gateway Display Name. | `string` | n/a | yes | +| [network\_compartment\_id](#input\_network\_compartment\_id) | The OCID of the compartment to contain the VCN. | `string` | n/a | yes | +| [vcn\_id](#input\_vcn\_id) | The VCN OCID Value | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [internet\_gw\_id](#output\_internet\_gw\_id) | Internet Gateway Display Name. | + \ No newline at end of file diff --git a/modules/internet-gateway/main.tf b/modules/internet-gateway/main.tf new file mode 100644 index 00000000..d48cdb8e --- /dev/null +++ b/modules/internet-gateway/main.tf @@ -0,0 +1,17 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +# ----------------------------------------------------------------------------- +# Create Internet Gateway +# ----------------------------------------------------------------------------- +resource "oci_core_internet_gateway" "OCI-ELZ-IGW-P-HUB" { + compartment_id = var.network_compartment_id + vcn_id = var.vcn_id + display_name = var.internet_gateway_display_name +} + diff --git a/modules/internet-gateway/outputs.tf b/modules/internet-gateway/outputs.tf new file mode 100644 index 00000000..11faa434 --- /dev/null +++ b/modules/internet-gateway/outputs.tf @@ -0,0 +1,4 @@ +output "internet_gw_id" { + value = oci_core_internet_gateway.OCI-ELZ-IGW-P-HUB.id + description = "Internet Gateway Display Name." +} diff --git a/modules/internet-gateway/variables.tf b/modules/internet-gateway/variables.tf new file mode 100644 index 00000000..17f11bb2 --- /dev/null +++ b/modules/internet-gateway/variables.tf @@ -0,0 +1,14 @@ +variable "network_compartment_id" { + type = string + description = "The OCID of the compartment to contain the VCN." +} + +variable "vcn_id" { + type = string + description = "The VCN OCID Value" +} + +variable "internet_gateway_display_name" { + type = string + description = "Internet Gateway Display Name." +} \ No newline at end of file diff --git a/modules/ipsec/README.md b/modules/ipsec/README.md new file mode 100644 index 00000000..5c2964e6 --- /dev/null +++ b/modules/ipsec/README.md @@ -0,0 +1,57 @@ +## Summary + +Terraform module for OCI IPSec creation. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_core_cpe.oci-ipsec-cpe](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_cpe) | resource | +| [oci_core_ipsec.oci-ipsec-connection](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_ipsec) | resource | +| [oci_core_ipsec_connection_tunnel_management.oci-ipsec-connection-tunnel-management-a](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_ipsec_connection_tunnel_management) | resource | +| [oci_core_ipsec_connection_tunnel_management.oci-ipsec-connection-tunnel-management-b](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_ipsec_connection_tunnel_management) | resource | +| [oci_core_cpe_device_shape.oci-ipsec-cpe-device-shape](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/core_cpe_device_shape) | data source | +| [oci_core_cpe_device_shapes.cpe_device_shapes](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/core_cpe_device_shapes) | data source | +| [oci_core_ipsec_connection_tunnel.oci-ipsec-connection-tunnel-a](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/core_ipsec_connection_tunnel) | data source | +| [oci_core_ipsec_connection_tunnel.oci-ipsec-connection-tunnel-b](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/core_ipsec_connection_tunnel) | data source | +| [oci_core_ipsec_connection_tunnels.oci-ipsec-connection-tunnels](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/core_ipsec_connection_tunnels) | data source | +| [oci_core_ipsec_connections.oci-ipsec-connections](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/core_ipsec_connections) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [bgp\_cust\_tunnela\_ip](#input\_bgp\_cust\_tunnela\_ip) | n/a | `any` | n/a | yes | +| [bgp\_oci\_tunnela\_ip](#input\_bgp\_oci\_tunnela\_ip) | n/a | `any` | n/a | yes | +| [compartment\_ocid](#input\_compartment\_ocid) | n/a | `string` | n/a | yes | +| [cpe\_display\_name](#input\_cpe\_display\_name) | Customer Premises Equipment IP address | `string` | n/a | yes | +| [cpe\_ip\_address](#input\_cpe\_ip\_address) | Customer Premises Equipment IP address | `string` | n/a | yes | +| [cpe\_vendor](#input\_cpe\_vendor) | n/a | `number` | n/a | yes | +| [customer\_bgp\_asn](#input\_customer\_bgp\_asn) | n/a | `any` | n/a | yes | +| [drg\_id](#input\_drg\_id) | n/a | `string` | n/a | yes | +| [ipsec\_display\_name](#input\_ipsec\_display\_name) | n/a | `string` | n/a | yes | +| [routing](#input\_routing) | n/a | `string` | n/a | yes | +| [shared\_secret](#input\_shared\_secret) | n/a | `any` | n/a | yes | +| [static\_routes](#input\_static\_routes) | n/a | `list(string)` | n/a | yes | +| [tunnel\_a\_display\_name](#input\_tunnel\_a\_display\_name) | n/a | `any` | n/a | yes | +| [tunnel\_b\_display\_name](#input\_tunnel\_b\_display\_name) | n/a | `any` | n/a | yes | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/modules/ipsec/datasources.tf b/modules/ipsec/datasources.tf new file mode 100644 index 00000000..4f643a69 --- /dev/null +++ b/modules/ipsec/datasources.tf @@ -0,0 +1,25 @@ +data "oci_core_cpe_device_shapes" "cpe_device_shapes" { +} + +data "oci_core_cpe_device_shape" "oci-ipsec-cpe-device-shape" { + cpe_device_shape_id = data.oci_core_cpe_device_shapes.cpe_device_shapes.cpe_device_shapes[var.cpe_vendor].cpe_device_shape_id +} + +data "oci_core_ipsec_connections" "oci-ipsec-connections" { + compartment_id = var.compartment_ocid + cpe_id = oci_core_cpe.oci-ipsec-cpe.id +} + +data "oci_core_ipsec_connection_tunnels" "oci-ipsec-connection-tunnels" { + ipsec_id = oci_core_ipsec.oci-ipsec-connection.id +} + +data "oci_core_ipsec_connection_tunnel" "oci-ipsec-connection-tunnel-a" { + ipsec_id = oci_core_ipsec.oci-ipsec-connection.id + tunnel_id = data.oci_core_ipsec_connection_tunnels.oci-ipsec-connection-tunnels.ip_sec_connection_tunnels[0].id +} + +data "oci_core_ipsec_connection_tunnel" "oci-ipsec-connection-tunnel-b" { + ipsec_id = oci_core_ipsec.oci-ipsec-connection.id + tunnel_id = data.oci_core_ipsec_connection_tunnels.oci-ipsec-connection-tunnels.ip_sec_connection_tunnels[1].id +} diff --git a/modules/ipsec/main.tf b/modules/ipsec/main.tf new file mode 100644 index 00000000..57dc99fd --- /dev/null +++ b/modules/ipsec/main.tf @@ -0,0 +1,77 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + + +# ----------------------------------------------------------------------------- +# Create customer premises equipment object +# ----------------------------------------------------------------------------- +resource "oci_core_cpe" "oci-ipsec-cpe" { + compartment_id = var.compartment_ocid + ip_address = var.cpe_ip_address + cpe_device_shape_id = data.oci_core_cpe_device_shape.oci-ipsec-cpe-device-shape.id + display_name = var.cpe_display_name +} + +# ----------------------------------------------------------------------------- +# Create IPSec tunnel connection for site-to-site VPN +# ----------------------------------------------------------------------------- +resource "oci_core_ipsec" "oci-ipsec-connection" { + compartment_id = var.compartment_ocid + cpe_id = oci_core_cpe.oci-ipsec-cpe.id + drg_id = var.drg_id + display_name = var.ipsec_display_name + static_routes = var.static_routes +} + +# ----------------------------------------------------------------------------- +# Create IPSEC connection management for OCI VCN tunnel a +# ----------------------------------------------------------------------------- +resource "oci_core_ipsec_connection_tunnel_management" "oci-ipsec-connection-tunnel-management-a" { + ipsec_id = oci_core_ipsec.oci-ipsec-connection.id + tunnel_id = data.oci_core_ipsec_connection_tunnels.oci-ipsec-connection-tunnels.ip_sec_connection_tunnels[0].id + routing = var.routing + display_name = var.tunnel_a_display_name + + #Optional + bgp_session_info { + customer_bgp_asn = var.routing == "BGP" ? var.customer_bgp_asn : null + customer_interface_ip = var.routing == "BGP" ? var.bgp_cust_tunnela_ip : null + oracle_interface_ip = var.routing == "BGP" ? var.bgp_oci_tunnela_ip : null + } + + shared_secret = var.shared_secret + ike_version = "V1" + + depends_on = [data.oci_core_ipsec_connections.oci-ipsec-connections] +} + +# ----------------------------------------------------------------------------- +# Create IPSEC connection management for OCI VCN tunnel b +# ----------------------------------------------------------------------------- +resource "oci_core_ipsec_connection_tunnel_management" "oci-ipsec-connection-tunnel-management-b" { + ipsec_id = oci_core_ipsec.oci-ipsec-connection.id + tunnel_id = data.oci_core_ipsec_connection_tunnels.oci-ipsec-connection-tunnels.ip_sec_connection_tunnels[1].id + routing = var.routing + display_name = var.tunnel_b_display_name + + #Optional + bgp_session_info { + customer_bgp_asn = var.routing == "BGP" ? var.customer_bgp_asn : null + customer_interface_ip = var.routing == "BGP" ? var.bgp_cust_tunnela_ip : null + oracle_interface_ip = var.routing == "BGP" ? var.bgp_oci_tunnela_ip : null + } + + shared_secret = var.shared_secret + ike_version = "V1" + + depends_on = [data.oci_core_ipsec_connections.oci-ipsec-connections] +} + +# ----------------------------------------------------------------------------- +# TODO Update drg ipsec attachment with route tables for OCI VCN tunnels +# ----------------------------------------------------------------------------- diff --git a/modules/ipsec/variables.tf b/modules/ipsec/variables.tf new file mode 100644 index 00000000..8ada4b4c --- /dev/null +++ b/modules/ipsec/variables.tf @@ -0,0 +1,49 @@ +variable "compartment_ocid" { + type = string + description = "" +} + +variable "cpe_ip_address" { + type = string + description = "Customer Premises Equipment IP address" +} + +variable "cpe_display_name" { + type = string + description = "Customer Premises Equipment IP address" +} + +variable "ipsec_display_name" { + type = string + description = "" +} + +variable "drg_id" { + type = string + description = "" +} + +variable "static_routes" { + type = list(string) +} + +variable "cpe_vendor" { + type = number +} + +variable "routing" { + type = string + description = "" +} + +variable "tunnel_a_display_name" {} + +variable "customer_bgp_asn" {} + +variable "bgp_cust_tunnela_ip" {} + +variable "bgp_oci_tunnela_ip" {} + +variable "shared_secret" {} + +variable "tunnel_b_display_name" {} \ No newline at end of file diff --git a/modules/key/README.md b/modules/key/README.md new file mode 100644 index 00000000..8c0e2183 --- /dev/null +++ b/modules/key/README.md @@ -0,0 +1,42 @@ +## Summary +Terraform module for OCI master encryption keys. +The Key could be used for encryption and decryption of data while at rest or in transit. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_kms_key.key](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/kms_key) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_ocid](#input\_compartment\_ocid) | The OCID of the compartment where you want to create the master encryption key. | `string` | n/a | yes | +| [display\_name](#input\_display\_name) | The display name of key | `string` | n/a | yes | +| [management\_endpoint](#input\_management\_endpoint) | The service endpoint to perform management operations against. | `string` | n/a | yes | +| [protection\_mode](#input\_protection\_mode) | he key's protection mode indicates how the key persists and where cryptographic operations that use the key are performed. | `string` | n/a | yes | +| [shape\_algorithm](#input\_shape\_algorithm) | The algorithm used by a key's key versions to encrypt or decrypt. | `string` | n/a | yes | +| [shape\_length](#input\_shape\_length) | The length of the key in bytes, expressed as an integer. | `number` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [key\_ocid](#output\_key\_ocid) | The OCID of the key created | + \ No newline at end of file diff --git a/modules/key/main.tf b/modules/key/main.tf new file mode 100644 index 00000000..6bda88b6 --- /dev/null +++ b/modules/key/main.tf @@ -0,0 +1,19 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_kms_key" "key" { + compartment_id = var.compartment_ocid + display_name = var.display_name + + key_shape { + algorithm = var.shape_algorithm + length = var.shape_length + } + management_endpoint = var.management_endpoint + protection_mode = var.protection_mode +} diff --git a/modules/key/outputs.tf b/modules/key/outputs.tf new file mode 100644 index 00000000..c944353b --- /dev/null +++ b/modules/key/outputs.tf @@ -0,0 +1,4 @@ +output "key_ocid" { + value = oci_kms_key.key.id + description = "The OCID of the key created" +} \ No newline at end of file diff --git a/modules/key/variables.tf b/modules/key/variables.tf new file mode 100644 index 00000000..b86f5af6 --- /dev/null +++ b/modules/key/variables.tf @@ -0,0 +1,29 @@ +variable "compartment_ocid" { + type = string + description = "The OCID of the compartment where you want to create the master encryption key." +} + +variable "display_name" { + type = string + description = "The display name of key" +} + +variable "shape_algorithm" { + type = string + description = "The algorithm used by a key's key versions to encrypt or decrypt." +} + +variable "shape_length" { + type = number + description = "The length of the key in bytes, expressed as an integer." +} + +variable "management_endpoint" { + type = string + description = "The service endpoint to perform management operations against." +} + +variable "protection_mode" { + type = string + description = "he key's protection mode indicates how the key persists and where cryptographic operations that use the key are performed." +} \ No newline at end of file diff --git a/modules/log-analytics-namespace/README.md b/modules/log-analytics-namespace/README.md new file mode 100644 index 00000000..3c696ca1 --- /dev/null +++ b/modules/log-analytics-namespace/README.md @@ -0,0 +1,45 @@ +## Summary +Terraform module for Logging Analytic, a cloud solution in +Oracle Cloud Infrastructure that lets you index, enrich, +aggregate, explore, search, analyze, correlate, visualize and monitor +all log data from your applications and system infrastructure. + + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | +| [time](#provider\_time) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_policy.policy](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_policy) | resource | +| [oci_log_analytics_namespace.namespace](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/log_analytics_namespace) | resource | +| [time_sleep.policy_propagation_delay](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [oci_log_analytics_namespaces.logging_analytics_namespaces](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/log_analytics_namespaces) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | The OCID of the root compartment. | `string` | n/a | yes | +| [is\_onboarded](#input\_is\_onboarded) | Use true if tenancy is to be onboarded to logging analytics and false if tenancy is to be offboarded. | `bool` | n/a | yes | +| [resource\_label](#input\_resource\_label) | n/a | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/modules/log-analytics-namespace/datasources.tf b/modules/log-analytics-namespace/datasources.tf new file mode 100644 index 00000000..f46be2ff --- /dev/null +++ b/modules/log-analytics-namespace/datasources.tf @@ -0,0 +1,3 @@ +data "oci_log_analytics_namespaces" "logging_analytics_namespaces" { + compartment_id = var.tenancy_ocid +} \ No newline at end of file diff --git a/modules/log-analytics-namespace/main.tf b/modules/log-analytics-namespace/main.tf new file mode 100644 index 00000000..c88cfe1c --- /dev/null +++ b/modules/log-analytics-namespace/main.tf @@ -0,0 +1,44 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_log_analytics_namespace" "namespace" { + compartment_id = var.compartment_id + is_onboarded = var.is_onboarded + namespace = data.oci_log_analytics_namespaces.logging_analytics_namespaces.namespace_collection[0].items[0].namespace + + depends_on = [ + time_sleep.policy_propagation_delay + ] +} + +locals { + la_root_policy = { + name = "${var.resource_label}-OCI-ELZ-LA-Policy" + description = "OCI Landing Zone Landing Zone Logging Analytics Service Policy" + + statements = [ + "define tenancy sampledata as ocid1.tenancy.oc1..aaaaaaaabmtv54v5bg45j7zd2eeat4df2bwfqkmxe2yy6ecdfrc36wloe4ia", + "endorse group Administrators to read loganalytics-features-family in tenancy sampledata", + "endorse group Administrators to read loganalytics-resources-family in tenancy sampledata", + "endorse group Administrators to read compartments in tenancy sampledata", + "allow service loganalytics to READ loganalytics-features-family in tenancy", + "allow service loganalytics to READ compartments in tenancy", + ] + } +} +resource "oci_identity_policy" "policy" { + compartment_id = var.tenancy_ocid + description = local.la_root_policy.description + name = local.la_root_policy.name + statements = local.la_root_policy.statements +} + +resource "time_sleep" "policy_propagation_delay" { + depends_on = [oci_identity_policy.policy] + create_duration = "90s" +} diff --git a/modules/log-analytics-namespace/variables.tf b/modules/log-analytics-namespace/variables.tf new file mode 100644 index 00000000..667fdab7 --- /dev/null +++ b/modules/log-analytics-namespace/variables.tf @@ -0,0 +1,18 @@ +variable "tenancy_ocid" { + type = string + description = "The OCID of tenancy" +} + +variable "compartment_id" { + type = string + description = "The OCID of the root compartment." +} + +variable "is_onboarded" { + type = bool + description = "Use true if tenancy is to be onboarded to logging analytics and false if tenancy is to be offboarded." +} + +variable "resource_label" { + type = string +} diff --git a/modules/log-analytics/README.md b/modules/log-analytics/README.md new file mode 100644 index 00000000..31cccb57 --- /dev/null +++ b/modules/log-analytics/README.md @@ -0,0 +1,44 @@ + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_policy.policy](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_policy) | resource | +| [oci_log_analytics_log_analytics_log_group.log_analytics_log_group](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/log_analytics_log_analytics_log_group) | resource | +| [oci_sch_service_connector.service_connector](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/sch_service_connector) | resource | +| [oci_log_analytics_namespaces.logging_analytics_namespaces](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/log_analytics_namespaces) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | The id of the compartment to place the resources. | `string` | n/a | yes | +| [log\_group\_description](#input\_log\_group\_description) | The description of log group | `string` | n/a | yes | +| [log\_group\_display\_name](#input\_log\_group\_display\_name) | The display name of log group | `string` | n/a | yes | +| [service\_connector\_display\_name](#input\_service\_connector\_display\_name) | The display name of the logging analytics service connector | `string` | n/a | yes | +| [service\_connector\_source\_compartment\_id](#input\_service\_connector\_source\_compartment\_id) | The compartment of the source log group for the logging analytics service connector | `string` | n/a | yes | +| [service\_connector\_source\_kind](#input\_service\_connector\_source\_kind) | The kind of log source for the logging analytics service connector | `string` | n/a | yes | +| [service\_connector\_source\_log\_group\_id](#input\_service\_connector\_source\_log\_group\_id) | The log group id for the logging analytics service connector | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | n/a | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [log\_group\_id](#output\_log\_group\_id) | The OCID of log group created | +| [service\_connector\_id](#output\_service\_connector\_id) | n/a | + \ No newline at end of file diff --git a/modules/log-analytics/datasources.tf b/modules/log-analytics/datasources.tf new file mode 100644 index 00000000..f46be2ff --- /dev/null +++ b/modules/log-analytics/datasources.tf @@ -0,0 +1,3 @@ +data "oci_log_analytics_namespaces" "logging_analytics_namespaces" { + compartment_id = var.tenancy_ocid +} \ No newline at end of file diff --git a/modules/log-analytics/main.tf b/modules/log-analytics/main.tf new file mode 100644 index 00000000..b99cb8c1 --- /dev/null +++ b/modules/log-analytics/main.tf @@ -0,0 +1,60 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_log_analytics_log_analytics_log_group" "log_analytics_log_group" { + compartment_id = var.compartment_id + display_name = var.log_group_display_name + namespace = data.oci_log_analytics_namespaces.logging_analytics_namespaces.namespace_collection[0].items[0].namespace + description = var.log_group_description +} + +locals { + service_connector = { + target_kind = "loggingAnalytics" + } +} +resource "oci_sch_service_connector" "service_connector" { + compartment_id = var.compartment_id + display_name = var.service_connector_display_name + + source { + kind = var.service_connector_source_kind + log_sources { + compartment_id = var.service_connector_source_compartment_id + log_group_id = var.service_connector_source_log_group_id + } + } + + target { + kind = local.service_connector.target_kind + log_group_id = oci_log_analytics_log_analytics_log_group.log_analytics_log_group.id + } +} + +locals { + policy = { + name = "lzSchPolicy${var.log_group_display_name}" + description = "Policy allowing log upload to service connectors in security compartment." + statements = [ + < +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_logging_log_group.log_group](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/logging_log_group) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | The OCID of the compartment that the resource belongs to. | `string` | n/a | yes | +| [description](#input\_description) | Description for log group | `string` | n/a | yes | +| [display\_name](#input\_display\_name) | The display name of log group | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [log\_group\_id](#output\_log\_group\_id) | The OCID of the log group created | + diff --git a/modules/log-group/main.tf b/modules/log-group/main.tf new file mode 100644 index 00000000..2546cab6 --- /dev/null +++ b/modules/log-group/main.tf @@ -0,0 +1,13 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_logging_log_group" "log_group" { + compartment_id = var.compartment_id + display_name = var.display_name + description = var.description +} diff --git a/modules/log-group/outputs.tf b/modules/log-group/outputs.tf new file mode 100644 index 00000000..9aaf1d50 --- /dev/null +++ b/modules/log-group/outputs.tf @@ -0,0 +1,4 @@ +output "log_group_id" { + value = oci_logging_log_group.log_group.id + description = "The OCID of the log group created" +} diff --git a/modules/log-group/variables.tf b/modules/log-group/variables.tf new file mode 100644 index 00000000..c67a7443 --- /dev/null +++ b/modules/log-group/variables.tf @@ -0,0 +1,14 @@ +variable "compartment_id" { + type = string + description = " The OCID of the compartment that the resource belongs to." +} + +variable "display_name" { + type = string + description = "The display name of log group" +} + +variable "description" { + type = string + description = "Description for log group" +} \ No newline at end of file diff --git a/modules/nat-gateway/README.md b/modules/nat-gateway/README.md new file mode 100644 index 00000000..af50799a --- /dev/null +++ b/modules/nat-gateway/README.md @@ -0,0 +1,35 @@ + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_core_nat_gateway.OCI-ELZ-NGW-P-HUB](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_nat_gateway) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [nat\_gateway\_display\_name](#input\_nat\_gateway\_display\_name) | NAT Gateway Display Name. | `string` | n/a | yes | +| [network\_compartment\_id](#input\_network\_compartment\_id) | The OCID of the compartment to contain the VCN. | `string` | n/a | yes | +| [vcn\_id](#input\_vcn\_id) | The VCN OCID Value | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [nat\_gw\_id](#output\_nat\_gw\_id) | NAT Gateway OCID. | + \ No newline at end of file diff --git a/modules/nat-gateway/main.tf b/modules/nat-gateway/main.tf new file mode 100644 index 00000000..28cac328 --- /dev/null +++ b/modules/nat-gateway/main.tf @@ -0,0 +1,17 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +# ----------------------------------------------------------------------------- +# Create NAT Gateway +# ----------------------------------------------------------------------------- +resource "oci_core_nat_gateway" "OCI-ELZ-NGW-P-HUB" { + compartment_id = var.network_compartment_id + vcn_id = var.vcn_id + display_name = var.nat_gateway_display_name +} + diff --git a/modules/nat-gateway/outputs.tf b/modules/nat-gateway/outputs.tf new file mode 100644 index 00000000..e8a45842 --- /dev/null +++ b/modules/nat-gateway/outputs.tf @@ -0,0 +1,4 @@ +output "nat_gw_id" { + value = oci_core_nat_gateway.OCI-ELZ-NGW-P-HUB.id + description = "NAT Gateway OCID." +} diff --git a/modules/nat-gateway/variables.tf b/modules/nat-gateway/variables.tf new file mode 100644 index 00000000..872cc7e0 --- /dev/null +++ b/modules/nat-gateway/variables.tf @@ -0,0 +1,14 @@ +variable "network_compartment_id" { + type = string + description = "The OCID of the compartment to contain the VCN." +} + +variable "vcn_id" { + type = string + description = "The VCN OCID Value" +} + +variable "nat_gateway_display_name" { + type = string + description = "NAT Gateway Display Name." +} \ No newline at end of file diff --git a/modules/notification-topic/README.md b/modules/notification-topic/README.md new file mode 100644 index 00000000..0fa2e719 --- /dev/null +++ b/modules/notification-topic/README.md @@ -0,0 +1,45 @@ +## Summary +Terraform module for OCI Topic service, including topic creation, subscription, and event rules. +A topic is a communication channel for sending messages to its subscriptions. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_events_rule.event_rule](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/events_rule) | resource | +| [oci_ons_notification_topic.topic_service](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/ons_notification_topic) | resource | +| [oci_ons_subscription.subscription_service](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/ons_subscription) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | The OCID of the compartment to create the topic in. | `string` | n/a | yes | +| [event\_rules](#input\_event\_rules) | n/a | `map(any)` | `{}` | no | +| [subscription\_endpoint](#input\_subscription\_endpoint) | A locator that corresponds to the subscription protocol. | `list(string)` | n/a | yes | +| [subscription\_protocol](#input\_subscription\_protocol) | Valid values: CUSTOM\_HTTPS, EMAIL, ORACLE\_FUNCTIONS, PAGERDUTY, SLACK, SMS | `string` | n/a | yes | +| [topic\_description](#input\_topic\_description) | The description of the topic being created | `string` | n/a | yes | +| [topic\_name](#input\_topic\_name) | The name of the topic being created. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [subscription\_id](#output\_subscription\_id) | The subscriptions, indexed by ID. | +| [topic\_id](#output\_topic\_id) | The OCID of the topic created | + \ No newline at end of file diff --git a/modules/notification-topic/main.tf b/modules/notification-topic/main.tf new file mode 100644 index 00000000..0e9f851c --- /dev/null +++ b/modules/notification-topic/main.tf @@ -0,0 +1,40 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_ons_notification_topic" "topic_service" { + compartment_id = var.compartment_id + name = var.topic_name + description = var.topic_description +} + +resource "oci_ons_subscription" "subscription_service" { + for_each = toset(var.subscription_endpoint) + compartment_id = var.compartment_id + endpoint = each.key + protocol = var.subscription_protocol + topic_id = oci_ons_notification_topic.topic_service.id +} + +resource "oci_events_rule" "event_rule" { + for_each = var.event_rules + compartment_id = var.compartment_id + condition = each.value.rule_condition + display_name = each.value.rule_display_name + is_enabled = each.value.rule_is_enabled + description = each.value.rule_description + + actions { + actions { + action_type = "ONS" #FAAS ONS OSS + is_enabled = true + # function_id = oci_functions_function.test_function.id + # stream_id = oci_streaming_stream.test_stream.id + topic_id = oci_ons_notification_topic.topic_service.id + } + } +} diff --git a/modules/notification-topic/outputs.tf b/modules/notification-topic/outputs.tf new file mode 100644 index 00000000..c51f642f --- /dev/null +++ b/modules/notification-topic/outputs.tf @@ -0,0 +1,9 @@ +output "topic_id" { + value = oci_ons_notification_topic.topic_service.id + description = "The OCID of the topic created" +} + +output "subscription_id" { + description = "The subscriptions, indexed by ID." + value = { for sub in oci_ons_subscription.subscription_service : sub.id => sub } +} diff --git a/modules/notification-topic/variables.tf b/modules/notification-topic/variables.tf new file mode 100644 index 00000000..682fc8af --- /dev/null +++ b/modules/notification-topic/variables.tf @@ -0,0 +1,30 @@ +variable "compartment_id" { + type = string + description = "The OCID of the compartment to create the topic in." +} + +variable "topic_name" { + type = string + description = "The name of the topic being created." +} + +variable "topic_description" { + type = string + description = "The description of the topic being created" +} + +variable "subscription_endpoint" { + type = list(string) + description = "A locator that corresponds to the subscription protocol." +} + +variable "subscription_protocol" { + type = string + description = "Valid values: CUSTOM_HTTPS, EMAIL, ORACLE_FUNCTIONS, PAGERDUTY, SLACK, SMS" +} + +variable "event_rules" { + type = map(any) + default = {} + description = "" +} diff --git a/modules/policies/README.md b/modules/policies/README.md new file mode 100644 index 00000000..0ab8dd0e --- /dev/null +++ b/modules/policies/README.md @@ -0,0 +1,41 @@ +## Summary +Terraform module for OCI Policy creation. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | +| [time](#provider\_time) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_policy.policy](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_policy) | resource | +| [time_sleep.policy_propagation_delay](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_ocid](#input\_compartment\_ocid) | The OCID of the compartment containing the policy. | `string` | n/a | yes | +| [description](#input\_description) | The description of policy | `string` | n/a | yes | +| [policy\_name](#input\_policy\_name) | The name of policy. | `string` | n/a | yes | +| [statements](#input\_statements) | An array of policy statements written in the policy language. | `list(string)` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [policy](#output\_policy) | n/a | + \ No newline at end of file diff --git a/modules/policies/main.tf b/modules/policies/main.tf new file mode 100644 index 00000000..1ac8194f --- /dev/null +++ b/modules/policies/main.tf @@ -0,0 +1,19 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_identity_policy" "policy" { + compartment_id = var.compartment_ocid + description = var.description + name = var.policy_name + statements = var.statements +} + +resource "time_sleep" "policy_propagation_delay" { + depends_on = [oci_identity_policy.policy] + create_duration = "90s" +} diff --git a/modules/policies/outputs.tf b/modules/policies/outputs.tf new file mode 100644 index 00000000..7fed20cd --- /dev/null +++ b/modules/policies/outputs.tf @@ -0,0 +1,3 @@ +output "policy" { + value = oci_identity_policy.policy +} diff --git a/modules/policies/variables.tf b/modules/policies/variables.tf new file mode 100644 index 00000000..9476bd25 --- /dev/null +++ b/modules/policies/variables.tf @@ -0,0 +1,19 @@ +variable "compartment_ocid" { + type = string + description = "The OCID of the compartment containing the policy." +} + +variable "description" { + type = string + description = "The description of policy" +} + +variable "policy_name" { + type = string + description = "The name of policy." +} + +variable "statements" { + type = list(string) + description = "An array of policy statements written in the policy language." +} \ No newline at end of file diff --git a/modules/route-table/README.md b/modules/route-table/README.md new file mode 100644 index 00000000..c2668909 --- /dev/null +++ b/modules/route-table/README.md @@ -0,0 +1,47 @@ +## Summary +Terraform module for Route Table creation. + +## Dependencies +* VCN + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_core_route_table.route_table](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_route_table) | resource | +| [oci_core_route_table_attachment.oci_core_route_table_attachment](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_route_table_attachment) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | The OCID of the compartment to contain the route table. | `string` | n/a | yes | +| [default\_route\_table\_id](#input\_default\_route\_table\_id) | n/a | `string` | `"The OCID of default route table"` | no | +| [is\_default](#input\_is\_default) | Option use default route table | `bool` | `false` | no | +| [route\_rules](#input\_route\_rules) | The collection of rules for routing destination IPs to network devices. | `map(any)` | n/a | yes | +| [route\_table\_display\_name](#input\_route\_table\_display\_name) | The display name of route table | `string` | n/a | yes | +| [subnet\_id](#input\_subnet\_id) | The OCID of the subnet. | `string` | `""` | no | +| [subnet\_name](#input\_subnet\_name) | The name of the subnet. | `string` | `""` | no | +| [vcn\_id](#input\_vcn\_id) | The OCID of the VCN the route table belongs to. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [id](#output\_id) | The OCID of the route table | + \ No newline at end of file diff --git a/modules/route-table/main.tf b/modules/route-table/main.tf new file mode 100644 index 00000000..d97d063d --- /dev/null +++ b/modules/route-table/main.tf @@ -0,0 +1,52 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +# ----------------------------------------------------------------------------- +# Create Route Tables and Attachment +# ----------------------------------------------------------------------------- +resource "oci_core_route_table" "route_table" { + count = var.is_default == false ? 1 : 0 + compartment_id = var.compartment_id + vcn_id = var.vcn_id + display_name = var.route_table_display_name + dynamic "route_rules" { + for_each = var.route_rules + content { + description = route_rules.key + network_entity_id = route_rules.value.network_entity_id + destination = route_rules.value.destination + destination_type = route_rules.value.destination_type + } + } +} + +resource "oci_core_route_table_attachment" "oci_core_route_table_attachment" { + count = var.subnet_name != "" ? 1 : 0 + #count = var.is_default == false ? 1 : 0 + subnet_id = var.subnet_id + route_table_id = oci_core_route_table.route_table[0].id +} + +# ----------------------------------------------------------------------------- +# Create Default Route Table Public Subnet Route Table +# ----------------------------------------------------------------------------- +/* +resource "oci_core_default_route_table" "defaultRouteTable" { + count = var.is_default == true ? 1 : 0 + manage_default_resource_id = var.default_route_table_id + dynamic "route_rules" { + for_each = var.route_rules + content { + description = route_rules.key + network_entity_id = route_rules.value.network_entity_id + destination = route_rules.value.destination + destination_type = route_rules.value.destination_type + } + } +}*/ + diff --git a/modules/route-table/outputs.tf b/modules/route-table/outputs.tf new file mode 100644 index 00000000..44895d69 --- /dev/null +++ b/modules/route-table/outputs.tf @@ -0,0 +1,4 @@ +output "id" { + value = oci_core_route_table.route_table[0].id + description = "The OCID of the route table" +} diff --git a/modules/route-table/variables.tf b/modules/route-table/variables.tf new file mode 100644 index 00000000..0838fd48 --- /dev/null +++ b/modules/route-table/variables.tf @@ -0,0 +1,43 @@ +variable "compartment_id" { + type = string + description = "The OCID of the compartment to contain the route table." +} + +variable "vcn_id" { + type = string + description = "The OCID of the VCN the route table belongs to." +} + +variable "route_table_display_name" { + type = string + description = "The display name of route table" +} + +variable "route_rules" { + type = map(any) + description = "The collection of rules for routing destination IPs to network devices." +} + +variable "subnet_id" { + type = string + description = "The OCID of the subnet." + default = "" +} + +variable "subnet_name" { + type = string + description = "The name of the subnet." + default = "" +} + + +variable "is_default" { + type = bool + default = false + description = "Option use default route table" +} + +variable "default_route_table_id" { + type = string + default = "The OCID of default route table" +} diff --git a/modules/security-list/README.md b/modules/security-list/README.md new file mode 100644 index 00000000..90b96c54 --- /dev/null +++ b/modules/security-list/README.md @@ -0,0 +1,40 @@ + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_core_security_list.test_security_list](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_security_list) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | Compartment OCID ID | `string` | n/a | yes | +| [security\_list\_egress\_security\_rules\_description](#input\_security\_list\_egress\_security\_rules\_description) | Egress: Security List Rule Description | `string` | n/a | yes | +| [security\_list\_egress\_security\_rules\_destination](#input\_security\_list\_egress\_security\_rules\_destination) | Egress: Security List Rule Description | `string` | n/a | yes | +| [security\_list\_egress\_security\_rules\_destination\_type](#input\_security\_list\_egress\_security\_rules\_destination\_type) | Egress: Security List Rule Destination Type | `string` | n/a | yes | +| [security\_list\_egress\_security\_rules\_protocol](#input\_security\_list\_egress\_security\_rules\_protocol) | Egress: Security List Rule Protocol | `string` | n/a | yes | +| [security\_list\_ingress\_security\_rules\_description](#input\_security\_list\_ingress\_security\_rules\_description) | Ingress: Security List Rule Description | `string` | n/a | yes | +| [security\_list\_ingress\_security\_rules\_protocol](#input\_security\_list\_ingress\_security\_rules\_protocol) | Egress: Security List Protocol | `string` | n/a | yes | +| [security\_list\_ingress\_security\_rules\_source](#input\_security\_list\_ingress\_security\_rules\_source) | Ingress: Security List Protocol | `string` | n/a | yes | +| [security\_list\_ingress\_security\_rules\_source\_type](#input\_security\_list\_ingress\_security\_rules\_source\_type) | Ingress: Security List Rule Source Type | `string` | n/a | yes | +| [vcn\_id](#input\_vcn\_id) | VCN OCID ID | `string` | n/a | yes | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/modules/security-list/main.tf b/modules/security-list/main.tf new file mode 100644 index 00000000..bccbd866 --- /dev/null +++ b/modules/security-list/main.tf @@ -0,0 +1,33 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +# ----------------------------------------------------------------------------- +# Create Internet Gateway +# ----------------------------------------------------------------------------- +resource "oci_core_security_list" "test_security_list" { + compartment_id = var.compartment_id + vcn_id = var.vcn_id + display_name = var.security_list_display_name + + egress_security_rules { + destination = var.security_list_egress_security_rules_destination + protocol = var.security_list_egress_security_rules_protocol + description = var.security_list_egress_security_rules_description + destination_type = var.security_list_egress_security_rules_destination_type + } + ingress_security_rules { + #Required + protocol = var.security_list_ingress_security_rules_protocol + source = var.security_list_ingress_security_rules_source + + #Optional + description = var.security_list_ingress_security_rules_description + source_type = var.security_list_ingress_security_rules_source_type + } +} + diff --git a/modules/security-list/variables.tf b/modules/security-list/variables.tf new file mode 100644 index 00000000..51702030 --- /dev/null +++ b/modules/security-list/variables.tf @@ -0,0 +1,47 @@ +variable "security_list_ingress_security_rules_protocol" { + type = string + description = "Egress: Security List Protocol" +} + +variable "security_list_ingress_security_rules_source" { + type = string + description = "Ingress: Security List Protocol" +} + +variable "security_list_ingress_security_rules_description" { + type = string + description = "Ingress: Security List Rule Description" +} + +variable "security_list_ingress_security_rules_source_type" { + type = string + description = "Ingress: Security List Rule Source Type" +} + +variable "security_list_egress_security_rules_destination" { + type = string + description = "Egress: Security List Rule Description" +} + +variable "security_list_egress_security_rules_protocol" { + type = string + description = "Egress: Security List Rule Protocol" +} + +variable "security_list_egress_security_rules_description" { + type = string + description = "Egress: Security List Rule Description" +} + +variable "security_list_egress_security_rules_destination_type" { + type = string + description = "Egress: Security List Rule Destination Type" +} +variable "compartment_id" { + type = string + description = "Compartment OCID ID" +} +variable "vcn_id" { + type = string + description = "VCN OCID ID" +} \ No newline at end of file diff --git a/modules/service-connector/README.md b/modules/service-connector/README.md new file mode 100644 index 00000000..303ed319 --- /dev/null +++ b/modules/service-connector/README.md @@ -0,0 +1,49 @@ +## Summary +Terraform module for Service Connector. +Service Connector Hub is a cloud message bus +platform that offers a single pane of glass for describing, +executing, and monitoring interactions when moving data between +Oracle Cloud Infrastructure services. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_sch_service_connector.service_connector](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/sch_service_connector) | resource | +| [oci_objectstorage_namespace.ns](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/objectstorage_namespace) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | The OCID of the comparment to create the service connector in. | `string` | n/a | yes | +| [cursor\_kind](#input\_cursor\_kind) | The cursor type discriminator. | `string` | `""` | no | +| [display\_name](#input\_display\_name) | The display name of service connector created | `string` | n/a | yes | +| [log\_group\_id](#input\_log\_group\_id) | The OCID of the log group. | `string` | `""` | no | +| [source\_compartment\_id](#input\_source\_compartment\_id) | The OCID of the compartment containing the log source. | `string` | n/a | yes | +| [source\_kind](#input\_source\_kind) | The source type discriminator. | `string` | n/a | yes | +| [stream\_id](#input\_stream\_id) | The OCID of the stream. | `string` | `""` | no | +| [target\_bucket](#input\_target\_bucket) | The name of the target bucket. | `string` | n/a | yes | +| [target\_kind](#input\_target\_kind) | The target type discriminator. | `string` | `"objectStorage"` | no | +| [target\_namespace](#input\_target\_namespace) | The namespace of target bucket | `string` | `""` | no | +| [tenancy\_ocid](#input\_tenancy\_ocid) | Tenancy LZ is created in. | `string` | n/a | yes | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/modules/service-connector/datasources.tf b/modules/service-connector/datasources.tf new file mode 100644 index 00000000..5fdd2d69 --- /dev/null +++ b/modules/service-connector/datasources.tf @@ -0,0 +1,3 @@ +data "oci_objectstorage_namespace" "ns" { + compartment_id = var.tenancy_ocid +} \ No newline at end of file diff --git a/modules/service-connector/main.tf b/modules/service-connector/main.tf new file mode 100644 index 00000000..be557e6d --- /dev/null +++ b/modules/service-connector/main.tf @@ -0,0 +1,31 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_sch_service_connector" "service_connector" { + compartment_id = var.compartment_id + display_name = var.display_name + source { + kind = var.source_kind + + log_sources { + compartment_id = var.source_compartment_id + log_group_id = var.log_group_id + } + cursor { + kind = var.cursor_kind + } + + stream_id = var.stream_id + + } + target { + kind = var.target_kind + bucket = var.target_bucket + namespace = data.oci_objectstorage_namespace.ns.namespace + } +} \ No newline at end of file diff --git a/modules/service-connector/variables.tf b/modules/service-connector/variables.tf new file mode 100644 index 00000000..971b3870 --- /dev/null +++ b/modules/service-connector/variables.tf @@ -0,0 +1,59 @@ +variable "tenancy_ocid" { + type = string + description = "Tenancy LZ is created in." +} + +variable "compartment_id" { + type = string + description = "The OCID of the comparment to create the service connector in." +} + +variable "source_compartment_id" { + type = string + description = "The OCID of the compartment containing the log source." +} + +variable "display_name" { + type = string + description = "The display name of service connector created" +} + +variable "source_kind" { + type = string + description = "The source type discriminator." +} + +variable "target_kind" { + type = string + default = "objectStorage" + description = "The target type discriminator." +} + +variable "log_group_id" { + type = string + default = "" + description = "The OCID of the log group." +} + +variable "stream_id" { + type = string + default = "" + description = "The OCID of the stream." +} + +variable "cursor_kind" { + type = string + default = "" + description = "The cursor type discriminator." +} + +variable "target_bucket" { + type = string + description = "The name of the target bucket." +} + +variable "target_namespace" { + type = string + default = "" + description = "The namespace of target bucket" +} \ No newline at end of file diff --git a/modules/service-gateway/README.md b/modules/service-gateway/README.md new file mode 100644 index 00000000..de3cdccf --- /dev/null +++ b/modules/service-gateway/README.md @@ -0,0 +1,36 @@ + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_core_service_gateway.service_gateway_all_svcs](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_service_gateway) | resource | +| [oci_core_services.service_gateway_all_oci_services](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/core_services) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [network\_compartment\_id](#input\_network\_compartment\_id) | The OCID of the compartment to contain the VCN. | `string` | n/a | yes | +| [service\_gateway\_display\_name](#input\_service\_gateway\_display\_name) | Service Gateway Display Name. | `string` | n/a | yes | +| [vcn\_id](#input\_vcn\_id) | The VCN OCID Value | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [service\_gw\_id](#output\_service\_gw\_id) | Service Gateway OCID. | + \ No newline at end of file diff --git a/modules/service-gateway/main.tf b/modules/service-gateway/main.tf new file mode 100644 index 00000000..d4db44bb --- /dev/null +++ b/modules/service-gateway/main.tf @@ -0,0 +1,30 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +# ----------------------------------------------------------------------------- +# Create Service Gateway +# ----------------------------------------------------------------------------- + +data "oci_core_services" "service_gateway_all_oci_services" { + filter { + name = "name" + values = ["All .* Services In Oracle Services Network"] + regex = true + } +} + + +resource "oci_core_service_gateway" "service_gateway_all_svcs" { + compartment_id = var.network_compartment_id + vcn_id = var.vcn_id + services { + service_id = lookup(data.oci_core_services.service_gateway_all_oci_services.services[0], "id") + } + display_name = var.service_gateway_display_name +} + diff --git a/modules/service-gateway/outputs.tf b/modules/service-gateway/outputs.tf new file mode 100644 index 00000000..ef72da1b --- /dev/null +++ b/modules/service-gateway/outputs.tf @@ -0,0 +1,4 @@ +output "service_gw_id" { + value = oci_core_service_gateway.service_gateway_all_svcs.id + description = "Service Gateway OCID." +} diff --git a/modules/service-gateway/variables.tf b/modules/service-gateway/variables.tf new file mode 100644 index 00000000..510594ab --- /dev/null +++ b/modules/service-gateway/variables.tf @@ -0,0 +1,14 @@ +variable "network_compartment_id" { + type = string + description = "The OCID of the compartment to contain the VCN." +} + +variable "vcn_id" { + type = string + description = "The VCN OCID Value" +} + +variable "service_gateway_display_name" { + type = string + description = "Service Gateway Display Name." +} \ No newline at end of file diff --git a/modules/service-log/README.md b/modules/service-log/README.md new file mode 100644 index 00000000..b55dc5a8 --- /dev/null +++ b/modules/service-log/README.md @@ -0,0 +1,37 @@ + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_logging_log.service_log](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/logging_log) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [log\_display\_name](#input\_log\_display\_name) | The display name of service log | `string` | n/a | yes | +| [log\_group\_id](#input\_log\_group\_id) | The OCID of a log group to work with. | `string` | n/a | yes | +| [log\_source\_category](#input\_log\_source\_category) | Log object category. | `string` | n/a | yes | +| [log\_source\_service](#input\_log\_source\_service) | Service generating log. | `string` | n/a | yes | +| [log\_source\_type](#input\_log\_source\_type) | The log source type. | `string` | n/a | yes | +| [log\_type](#input\_log\_type) | The logType that the log object is for, whether custom or service. | `string` | n/a | yes | +| [service\_log\_map](#input\_service\_log\_map) | n/a | `map(string)` | n/a | yes | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/modules/service-log/main.tf b/modules/service-log/main.tf new file mode 100644 index 00000000..34a7beb4 --- /dev/null +++ b/modules/service-log/main.tf @@ -0,0 +1,23 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_logging_log" "service_log" { + for_each = var.service_log_map + display_name = "${var.log_display_name}-${each.key}" + log_group_id = var.log_group_id + log_type = var.log_type + + configuration { + source { + category = var.log_source_category + resource = each.value + service = var.log_source_service + source_type = var.log_source_type + } + } +} diff --git a/modules/service-log/variables.tf b/modules/service-log/variables.tf new file mode 100644 index 00000000..e161f401 --- /dev/null +++ b/modules/service-log/variables.tf @@ -0,0 +1,34 @@ +variable "service_log_map" { + type = map(string) + description = "" +} + +variable "log_display_name" { + type = string + description = "The display name of service log" +} + +variable "log_type" { + type = string + description = "The logType that the log object is for, whether custom or service." +} + +variable "log_group_id" { + type = string + description = "The OCID of a log group to work with." +} + +variable "log_source_category" { + type = string + description = "Log object category." +} + +variable "log_source_service" { + type = string + description = "Service generating log." +} + +variable "log_source_type" { + type = string + description = "The log source type." +} diff --git a/modules/stream/README.md b/modules/stream/README.md new file mode 100644 index 00000000..dc1faf58 --- /dev/null +++ b/modules/stream/README.md @@ -0,0 +1,51 @@ +## Summary +Terraform module for Stream service and event rule. +It provides a fully managed, scalable, and durable solution for ingesting +and consuming high-volume data streams in real-time. Use Streaming for any +use case in which data is produced and processed continually and sequentially +in a publish-subscribe messaging model. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_events_rule.rule](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/events_rule) | resource | +| [oci_streaming_stream.stream](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/streaming_stream) | resource | +| [oci_streaming_stream_pool.stream_pool](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/streaming_stream_pool) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | The OCID of the compartment that contains the stream. | `string` | n/a | yes | +| [kms\_key\_id](#input\_kms\_key\_id) | Custom Encryption Key (Master Key) ocid. | `string` | n/a | yes | +| [rule\_action\_is\_enabled](#input\_rule\_action\_is\_enabled) | Option to enable rule action | `bool` | n/a | yes | +| [rule\_action\_type](#input\_rule\_action\_type) | The action to perform if the condition in the rule matches an event.(ONS, OSS, FAAS) | `string` | n/a | yes | +| [rule\_condition](#input\_rule\_condition) | A filter that specifies the event that will trigger actions associated with this rule. | `string` | n/a | yes | +| [rule\_display\_name](#input\_rule\_display\_name) | The display name of the rule | `string` | n/a | yes | +| [rule\_is\_enabled](#input\_rule\_is\_enabled) | Option to enable rule | `bool` | n/a | yes | +| [stream\_name](#input\_stream\_name) | The name of the stream. | `string` | n/a | yes | +| [stream\_partitions](#input\_stream\_partitions) | The number of partitions in the stream. | `number` | n/a | yes | +| [stream\_pool\_name](#input\_stream\_pool\_name) | The name of stream pool | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [stream\_id](#output\_stream\_id) | The OCID of the stream created | + \ No newline at end of file diff --git a/modules/stream/main.tf b/modules/stream/main.tf new file mode 100644 index 00000000..491d178d --- /dev/null +++ b/modules/stream/main.tf @@ -0,0 +1,37 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_streaming_stream_pool" "stream_pool" { + compartment_id = var.compartment_id + name = var.stream_pool_name + +# custom_encryption_key { +# kms_key_id = var.kms_key_id +# } +} + +resource "oci_streaming_stream" "stream" { + name = var.stream_name + partitions = var.stream_partitions + stream_pool_id = oci_streaming_stream_pool.stream_pool.id +} + +resource "oci_events_rule" "rule" { + actions { + actions { + action_type = var.rule_action_type + is_enabled = var.rule_action_is_enabled + + stream_id = oci_streaming_stream.stream.id + } + } + compartment_id = var.compartment_id + condition = var.rule_condition + display_name = var.rule_display_name + is_enabled = var.rule_is_enabled +} diff --git a/modules/stream/outputs.tf b/modules/stream/outputs.tf new file mode 100644 index 00000000..e9a68cdc --- /dev/null +++ b/modules/stream/outputs.tf @@ -0,0 +1,4 @@ +output "stream_id" { + value = oci_streaming_stream.stream.id + description = "The OCID of the stream created" +} \ No newline at end of file diff --git a/modules/stream/variables.tf b/modules/stream/variables.tf new file mode 100644 index 00000000..8cf132bd --- /dev/null +++ b/modules/stream/variables.tf @@ -0,0 +1,52 @@ +variable "compartment_id" { + type = string + description = "The OCID of the compartment that contains the stream." +} + +variable "stream_pool_name" { + type = string + description = "The name of stream pool" +} + +variable "kms_key_id" { + type = string + description = "Custom Encryption Key (Master Key) ocid." +} + +variable "stream_name" { + type = string + description = "The name of the stream." +} + +variable "stream_partitions" { + type = number + description = "The number of partitions in the stream." +} + +variable "rule_action_type" { + type = string + description = "The action to perform if the condition in the rule matches an event.(ONS, OSS, FAAS)" +} + +variable "rule_action_is_enabled" { + type = bool + description = "Option to enable rule action" +} + +variable "rule_condition" { + type = string + description = "A filter that specifies the event that will trigger actions associated with this rule." +} + +variable "rule_display_name" { + type = string + description = "The display name of the rule" +} + +variable "rule_is_enabled" { + type = bool + description = "Option to enable rule" +} + + + diff --git a/modules/subnet/README.md b/modules/subnet/README.md new file mode 100644 index 00000000..840d2b22 --- /dev/null +++ b/modules/subnet/README.md @@ -0,0 +1,43 @@ +## Summary +Terraform module for Virtual Cloud Network, subnets, and default security list. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_core_subnet.subnet](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_subnet) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [enable\_ipv6](#input\_enable\_ipv6) | Option to enable ipv6 | `bool` | `false` | no | +| [network\_compartment\_id](#input\_network\_compartment\_id) | the OCID of the compartment where the environment will be created. In general, this should be the Landing zone parent compartment. | `string` | n/a | yes | +| [security\_list\_ids](#input\_security\_list\_ids) | Security List OCID Value. | `string` | n/a | yes | +| [subnet\_map](#input\_subnet\_map) | The map of subnets including subnet name, description, dns label, subnet cidr block. |
map(object({
name = string,
description = string,
dns_label = string,
cidr_block = string,
prohibit_public_ip_on_vnic = bool
}))
| n/a | yes | +| [vcn\_cidr\_block](#input\_vcn\_cidr\_block) | The CIDR block of VCN | `string` | n/a | yes | +| [vcn\_display\_name](#input\_vcn\_display\_name) | The display name of VCN | `string` | n/a | yes | +| [vcn\_dns\_label](#input\_vcn\_dns\_label) | The DNS label of VCN | `string` | n/a | yes | +| [vcn\_id](#input\_vcn\_id) | VCN OCID Value | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [subnets](#output\_subnets) | The subnet OCID | + \ No newline at end of file diff --git a/modules/subnet/main.tf b/modules/subnet/main.tf new file mode 100644 index 00000000..a0a63d57 --- /dev/null +++ b/modules/subnet/main.tf @@ -0,0 +1,22 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +# ----------------------------------------------------------------------------- +# Create Subnets +# ----------------------------------------------------------------------------- +resource "oci_core_subnet" "subnet" { + for_each = var.subnet_map + cidr_block = each.value.cidr_block + display_name = each.value.name + dns_label = each.value.dns_label + compartment_id = var.network_compartment_id + prohibit_public_ip_on_vnic = each.value.prohibit_public_ip_on_vnic + vcn_id = var.vcn_id + #route_table_id = each.value.route_table_id + security_list_ids = var.subnet_security_list_ids +} diff --git a/modules/subnet/outputs.tf b/modules/subnet/outputs.tf new file mode 100644 index 00000000..b135a849 --- /dev/null +++ b/modules/subnet/outputs.tf @@ -0,0 +1,7 @@ +output "subnets" { + value = { for subnet in oci_core_subnet.subnet : + subnet.display_name => subnet.id + } + description = "The subnet OCID" +} + diff --git a/modules/subnet/variables.tf b/modules/subnet/variables.tf new file mode 100644 index 00000000..cc9dbc7a --- /dev/null +++ b/modules/subnet/variables.tf @@ -0,0 +1,50 @@ +#variable "compartment_id" { +# type = string +# description = "The OCID of the compartment to contain the VCN." +#} + +variable "vcn_cidr_block" { + type = string + description = "The CIDR block of VCN" +} + +variable "vcn_display_name" { + type = string + description = "The display name of VCN" +} + +variable "vcn_dns_label" { + type = string + description = "The DNS label of VCN" +} + +variable "enable_ipv6" { + type = bool + default = false + description = "Option to enable ipv6" +} + +variable "vcn_id" { + type = string + description = "VCN OCID Value" +} + +variable "network_compartment_id" { + type = string + description = "the OCID of the compartment where the environment will be created. In general, this should be the Landing zone parent compartment." +} + +variable "subnet_map" { + type = map(object({ + name = string, + description = string, + dns_label = string, + cidr_block = string, + prohibit_public_ip_on_vnic = bool + })) + description = "The map of subnets including subnet name, description, dns label, subnet cidr block." +} +variable "security_list_ids" { + type = string + description = "Security List OCID Value." +} diff --git a/modules/tag/README.md b/modules/tag/README.md new file mode 100644 index 00000000..d67e1b75 --- /dev/null +++ b/modules/tag/README.md @@ -0,0 +1,42 @@ + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_tag.tag](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_tag) | resource | +| [oci_identity_tag_default.tag_default](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_tag_default) | resource | +| [oci_identity_tag_namespace.tag_namespace](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_tag_namespace) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | The OCID of the compartment. | `string` | n/a | yes | +| [is\_namespace\_retired](#input\_is\_namespace\_retired) | Whether the tag namespace is retired. | `bool` | `false` | no | +| [tag\_default\_map](#input\_tag\_default\_map) | n/a | `any` | n/a | yes | +| [tag\_map](#input\_tag\_map) | n/a | `any` | n/a | yes | +| [tag\_namespace\_description](#input\_tag\_namespace\_description) | The description of the tag namespace. | `string` | n/a | yes | +| [tag\_namespace\_name](#input\_tag\_namespace\_name) | The name of the tag namespace | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [namespace\_id](#output\_namespace\_id) | Tag NameSpace OCID | +| [tag](#output\_tag) | Tag Values | +| [tag\_default](#output\_tag\_default) | Tag Default Values | + \ No newline at end of file diff --git a/modules/tag/main.tf b/modules/tag/main.tf new file mode 100644 index 00000000..f1f2e3dc --- /dev/null +++ b/modules/tag/main.tf @@ -0,0 +1,49 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_identity_tag_namespace" "tag_namespace" { + compartment_id = var.compartment_id + description = var.tag_namespace_description + name = var.tag_namespace_name + is_retired = var.is_namespace_retired +} + +resource "oci_identity_tag" "tag" { + for_each = var.tag_map + name = each.value.name + description = each.value.description + tag_namespace_id = oci_identity_tag_namespace.tag_namespace.id + is_cost_tracking = each.value.is_cost_tracking + is_retired = each.value.is_retired + + dynamic "validator" { + # validator block is optional for this resource but can not be left empty + for_each = lookup(each.value, "validator_type", null) != null ? ["optional_block"] : [] + content { + validator_type = each.value.validator_type + values = each.value.validator_values + } + } +} + +resource "time_sleep" "tag_creation_delay" { + depends_on = [oci_identity_tag.tag] + create_duration = "90s" +} + +resource "oci_identity_tag_default" "tag_default" { + for_each = var.tag_default_map + compartment_id = each.value.compartment_id + tag_definition_id = oci_identity_tag.tag[each.value.tag_definition_name].id + value = each.value.value + is_required = each.value.is_required + + depends_on = [ + time_sleep.tag_creation_delay + ] +} diff --git a/modules/tag/outputs.tf b/modules/tag/outputs.tf new file mode 100644 index 00000000..b5a4126f --- /dev/null +++ b/modules/tag/outputs.tf @@ -0,0 +1,14 @@ +output "namespace_id" { + value = oci_identity_tag_namespace.tag_namespace.id + description = "Tag NameSpace OCID" +} + +output "tag" { + value = oci_identity_tag.tag + description = "Tag Values" +} + +output "tag_default" { + value = oci_identity_tag_default.tag_default + description = "Tag Default Values" +} diff --git a/modules/tag/variables.tf b/modules/tag/variables.tf new file mode 100644 index 00000000..8f4df760 --- /dev/null +++ b/modules/tag/variables.tf @@ -0,0 +1,28 @@ +variable "compartment_id" { + type = string + description = "The OCID of the compartment." +} + +variable "tag_namespace_description" { + type = string + description = "The description of the tag namespace." +} + +variable "tag_namespace_name" { + type = string + description = "The name of the tag namespace" +} + +variable "is_namespace_retired" { + type = bool + default = false + description = "Whether the tag namespace is retired." +} + +variable "tag_map" { + +} + +variable "tag_default_map" { + +} diff --git a/modules/vault/README.md b/modules/vault/README.md new file mode 100644 index 00000000..c2268187 --- /dev/null +++ b/modules/vault/README.md @@ -0,0 +1,42 @@ +## Summary +Terraform module for Vault. It is a key management service that +stores and manages master encryption keys and secrets for secure access to resources. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_kms_vault.vault](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/kms_vault) | resource | +| [oci_kms_vault_replication.replication](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/kms_vault_replication) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | The OCID of the compartment where you want to create this vault. | `string` | n/a | yes | +| [display\_name](#input\_display\_name) | The display name of the vault | `string` | n/a | yes | +| [enable\_replication](#input\_enable\_replication) | Option to enable vault replication | `bool` | n/a | yes | +| [replica\_region](#input\_replica\_region) | the region to be created replica to. | `string` | n/a | yes | +| [vault\_type](#input\_vault\_type) | The type of vault to create. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [management\_endpoint](#output\_management\_endpoint) | The endpoint OCID of the valut | + \ No newline at end of file diff --git a/modules/vault/main.tf b/modules/vault/main.tf new file mode 100644 index 00000000..adebaada --- /dev/null +++ b/modules/vault/main.tf @@ -0,0 +1,19 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_kms_vault" "vault" { + compartment_id = var.compartment_id + display_name = var.display_name + vault_type = var.vault_type +} + +resource "oci_kms_vault_replication" "replication" { + count = var.enable_replication ? 1 : 0 + vault_id = oci_kms_vault.vault.id + replica_region = var.replica_region +} diff --git a/modules/vault/outputs.tf b/modules/vault/outputs.tf new file mode 100644 index 00000000..16bdff17 --- /dev/null +++ b/modules/vault/outputs.tf @@ -0,0 +1,4 @@ +output "management_endpoint" { + value = oci_kms_vault.vault.management_endpoint + description = "The endpoint OCID of the valut" +} \ No newline at end of file diff --git a/modules/vault/variables.tf b/modules/vault/variables.tf new file mode 100644 index 00000000..892a973a --- /dev/null +++ b/modules/vault/variables.tf @@ -0,0 +1,24 @@ +variable "compartment_id" { + type = string + description = "The OCID of the compartment where you want to create this vault." +} + +variable "display_name" { + type = string + description = "The display name of the vault" +} + +variable "vault_type" { + type = string + description = "The type of vault to create. " +} + +variable "replica_region" { + type = string + description = "the region to be created replica to." +} + +variable "enable_replication" { + type = bool + description = "Option to enable vault replication" +} diff --git a/modules/vcn-gateways/README.md b/modules/vcn-gateways/README.md new file mode 100644 index 00000000..db550268 --- /dev/null +++ b/modules/vcn-gateways/README.md @@ -0,0 +1,43 @@ +## Summary +Terraform module for Service Gateways and route table. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_core_route_table.route_table](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_route_table) | resource | +| [oci_core_service_gateway.sgw](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_service_gateway) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [compartment\_id](#input\_compartment\_id) | The OCID of the compartment to contain the service gateway. | `string` | n/a | yes | +| [route\_rules](#input\_route\_rules) | Route Rules. | `map(any)` | n/a | yes | +| [route\_table\_display\_name](#input\_route\_table\_display\_name) | The display name of route table. | `string` | n/a | yes | +| [service\_id](#input\_service\_id) | The OCID of the Service. | `string` | n/a | yes | +| [sgw\_display\_name](#input\_sgw\_display\_name) | The display name of service gateway | `string` | n/a | yes | +| [vcn\_id](#input\_vcn\_id) | The OCID of the VCN | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [route\_table\_id](#output\_route\_table\_id) | The OCID of the route table | +| [sgw\_id](#output\_sgw\_id) | The OCID of the service gateway | + \ No newline at end of file diff --git a/modules/vcn-gateways/main.tf b/modules/vcn-gateways/main.tf new file mode 100644 index 00000000..341cbf35 --- /dev/null +++ b/modules/vcn-gateways/main.tf @@ -0,0 +1,37 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +# ----------------------------------------------------------------------------- +# Create Service Gateway and Route Table +# ----------------------------------------------------------------------------- +resource "oci_core_service_gateway" "sgw" { + compartment_id = var.compartment_id + display_name = var.sgw_display_name + vcn_id = var.vcn_id + route_table_id = oci_core_route_table.route_table.id + + services { + service_id = var.service_id#lookup(data.oci_core_services.service_gateway_all_oci_services.services[0], "id") + } +} + +resource "oci_core_route_table" "route_table" { + compartment_id = var.compartment_id + vcn_id = var.vcn_id + display_name = var.route_table_display_name + + dynamic "route_rules" { + for_each = var.route_rules + content { + description = var.route_table_display_name + network_entity_id = route_rules.value.network_entity_id + destination = route_rules.value.destination + destination_type = route_rules.value.destination_type + } + } +} diff --git a/modules/vcn-gateways/outputs.tf b/modules/vcn-gateways/outputs.tf new file mode 100644 index 00000000..69f20ecf --- /dev/null +++ b/modules/vcn-gateways/outputs.tf @@ -0,0 +1,9 @@ +output "route_table_id" { + value = oci_core_route_table.route_table.id + description = "The OCID of the route table" +} + +output "sgw_id" { + value = oci_core_service_gateway.sgw.id + description = "The OCID of the service gateway" +} diff --git a/modules/vcn-gateways/variables.tf b/modules/vcn-gateways/variables.tf new file mode 100644 index 00000000..dca9a350 --- /dev/null +++ b/modules/vcn-gateways/variables.tf @@ -0,0 +1,29 @@ +variable "compartment_id" { + type = string + description = "The OCID of the compartment to contain the service gateway." +} + +variable "sgw_display_name" { + type = string + description = "The display name of service gateway" +} + +variable "vcn_id" { + type = string + description = "The OCID of the VCN" +} + +variable "service_id" { + type = string + description = "The OCID of the Service." +} + +variable "route_table_display_name" { + type = string + description = "The display name of route table." +} + +variable "route_rules" { + type = map(any) + description = "Route Rules." +} diff --git a/modules/vcn/README.md b/modules/vcn/README.md new file mode 100644 index 00000000..bcb1d77d --- /dev/null +++ b/modules/vcn/README.md @@ -0,0 +1,41 @@ +## Summary +Terraform module for Virtual Cloud Network, subnets, and default security list. + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_core_vcn.vcn](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/core_vcn) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [enable\_ipv6](#input\_enable\_ipv6) | Compartment : Option to enable ipv6 | `bool` | `false` | no | +| [network\_compartment\_id](#input\_network\_compartment\_id) | the OCID of the compartment where the environment will be created. | `string` | n/a | yes | +| [vcn\_cidr\_block](#input\_vcn\_cidr\_block) | The CIDR block of VCN | `string` | n/a | yes | +| [vcn\_display\_name](#input\_vcn\_display\_name) | The display name of VCN | `string` | n/a | yes | +| [vcn\_dns\_label](#input\_vcn\_dns\_label) | The DNS label of VCN | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [vcn](#output\_vcn) | n/a | +| [vcn\_id](#output\_vcn\_id) | The OCID of the VCN created | + \ No newline at end of file diff --git a/modules/vcn/main.tf b/modules/vcn/main.tf new file mode 100644 index 00000000..1942b350 --- /dev/null +++ b/modules/vcn/main.tf @@ -0,0 +1,20 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +# ----------------------------------------------------------------------------- +# Create VCN +# ----------------------------------------------------------------------------- +resource "oci_core_vcn" "vcn" { + cidr_blocks = [var.vcn_cidr_block] + compartment_id = var.network_compartment_id + display_name = var.vcn_display_name + dns_label = var.vcn_dns_label + is_ipv6enabled = var.enable_ipv6 +} + + diff --git a/modules/vcn/outputs.tf b/modules/vcn/outputs.tf new file mode 100644 index 00000000..baee8032 --- /dev/null +++ b/modules/vcn/outputs.tf @@ -0,0 +1,9 @@ +output "vcn_id" { + value = oci_core_vcn.vcn.id + description = "The OCID of the VCN created" +} + +output "vcn" { + value = oci_core_vcn.vcn +} + diff --git a/modules/vcn/variables.tf b/modules/vcn/variables.tf new file mode 100644 index 00000000..44790879 --- /dev/null +++ b/modules/vcn/variables.tf @@ -0,0 +1,30 @@ +#variable "compartment_id" { +# type = string +# description = "The OCID of the compartment to contain the VCN." +#} + +variable "vcn_cidr_block" { + type = string + description = "The CIDR block of VCN" +} + +variable "vcn_display_name" { + type = string + description = "The display name of VCN" +} + +variable "vcn_dns_label" { + type = string + description = "The DNS label of VCN" +} + +variable "enable_ipv6" { + type = bool + default = false + description = "Compartment : Option to enable ipv6" +} +variable "network_compartment_id" { + type = string + description = "the OCID of the compartment where the environment will be created." +} + diff --git a/modules/vss/README.md b/modules/vss/README.md new file mode 100644 index 00000000..2ca866f0 --- /dev/null +++ b/modules/vss/README.md @@ -0,0 +1,41 @@ + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_vulnerability_scanning_host_scan_recipe.vss_host_scan_recipe](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/vulnerability_scanning_host_scan_recipe) | resource | +| [oci_vulnerability_scanning_host_scan_target.vss_host_scan_target](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/vulnerability_scanning_host_scan_target) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [agent\_cis\_benchmark\_settings\_scan\_level](#input\_agent\_cis\_benchmark\_settings\_scan\_level) | Agent benchmarking settings scan level | `string` | n/a | yes | +| [host\_scan\_recipe\_agent\_settings\_agent\_configuration\_vendor](#input\_host\_scan\_recipe\_agent\_settings\_agent\_configuration\_vendor) | Vulnerability scanning service agent vendor | `string` | `"OCI"` | no | +| [host\_scan\_recipe\_agent\_settings\_scan\_level](#input\_host\_scan\_recipe\_agent\_settings\_scan\_level) | Vulnerability scanning service agent scan level | `string` | n/a | yes | +| [host\_scan\_recipe\_display\_name](#input\_host\_scan\_recipe\_display\_name) | Vulnerability scanning service display name | `string` | n/a | yes | +| [host\_scan\_recipe\_port\_settings\_scan\_level](#input\_host\_scan\_recipe\_port\_settings\_scan\_level) | Vulnerability scanning service port scan level | `string` | n/a | yes | +| [host\_scan\_target\_description](#input\_host\_scan\_target\_description) | Vulnerability scanning service target description | `string` | `"Vulnerability scanning service scan target"` | no | +| [host\_scan\_target\_display\_name](#input\_host\_scan\_target\_display\_name) | Vulnerability scanning service target display name | `string` | n/a | yes | +| [recipe\_compartment\_ocid](#input\_recipe\_compartment\_ocid) | the compartment ocid | `string` | n/a | yes | +| [target\_compartment\_ocid](#input\_target\_compartment\_ocid) | the compartment ocid of the vss target | `string` | n/a | yes | +| [vss\_scan\_schedule](#input\_vss\_scan\_schedule) | Vulnerability scanning service scan schedule | `string` | n/a | yes | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/modules/vss/main.tf b/modules/vss/main.tf new file mode 100644 index 00000000..34b23ca9 --- /dev/null +++ b/modules/vss/main.tf @@ -0,0 +1,41 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_vulnerability_scanning_host_scan_recipe" "vss_host_scan_recipe" { + compartment_id = var.recipe_compartment_ocid + display_name = var.host_scan_recipe_display_name + + agent_settings { + scan_level = var.host_scan_recipe_agent_settings_scan_level + + agent_configuration { + vendor = var.host_scan_recipe_agent_settings_agent_configuration_vendor + cis_benchmark_settings { + scan_level = var.agent_cis_benchmark_settings_scan_level + } + } + } + + port_settings { + scan_level = var.host_scan_recipe_port_settings_scan_level + } + + schedule { + type = var.vss_scan_schedule + } +} + +resource "oci_vulnerability_scanning_host_scan_target" "vss_host_scan_target" { + compartment_id = var.target_compartment_ocid + host_scan_recipe_id = oci_vulnerability_scanning_host_scan_recipe.vss_host_scan_recipe.id + target_compartment_id = var.target_compartment_ocid + description = var.host_scan_target_description + display_name = var.host_scan_target_display_name + + depends_on = [oci_vulnerability_scanning_host_scan_target.vss_host_scan_target] +} \ No newline at end of file diff --git a/modules/vss/variables.tf b/modules/vss/variables.tf new file mode 100644 index 00000000..a8781551 --- /dev/null +++ b/modules/vss/variables.tf @@ -0,0 +1,57 @@ +# ----------------------------------------------------------------------------- +# Common Variables +# ----------------------------------------------------------------------------- +variable "recipe_compartment_ocid" { + type = string + description = "the compartment ocid" +} + +# ----------------------------------------------------------------------------- +# VSS Host Scan Recipe Variables +# ----------------------------------------------------------------------------- +variable "host_scan_recipe_display_name" { + type = string + description = "Vulnerability scanning service display name" +} + +variable "host_scan_recipe_agent_settings_scan_level" { + type = string + description = "Vulnerability scanning service agent scan level" +} + +variable "host_scan_recipe_agent_settings_agent_configuration_vendor" { + type = string + description = "Vulnerability scanning service agent vendor" + default = "OCI" +} + +variable "host_scan_recipe_port_settings_scan_level" { + type = string + description = "Vulnerability scanning service port scan level" +} + +variable "vss_scan_schedule" { + type = string + description = "Vulnerability scanning service scan schedule" +} + +variable "agent_cis_benchmark_settings_scan_level" { + type = string + description = "Agent benchmarking settings scan level" +} + +variable "target_compartment_ocid" { + type = string + description = "the compartment ocid of the vss target" +} + +variable "host_scan_target_display_name" { + type = string + description = "Vulnerability scanning service target display name" +} + +variable "host_scan_target_description" { + type = string + description = "Vulnerability scanning service target description" + default = "Vulnerability scanning service scan target" +} \ No newline at end of file diff --git a/templates/README.md b/templates/README.md new file mode 100644 index 00000000..c2a2ea3f --- /dev/null +++ b/templates/README.md @@ -0,0 +1,4 @@ +# Templates for each Landing Zone + +This directory contains the top-level templates for each landing zone. + diff --git a/templates/elz-budget/README.md b/templates/elz-budget/README.md new file mode 100644 index 00000000..3e10210e --- /dev/null +++ b/templates/elz-budget/README.md @@ -0,0 +1,49 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [oci](#requirement\_oci) | 4.96.0 | + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | 4.96.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [budget](#module\_budget) | ../../modules/budget | n/a | + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_region_subscriptions.regions](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/identity_region_subscriptions) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [budget\_alert\_rule\_message](#input\_budget\_alert\_rule\_message) | The alert message for budget alerts. | `string` | n/a | yes | +| [budget\_alert\_rule\_recipients](#input\_budget\_alert\_rule\_recipients) | The delimited list of email addresses to receive the alert when it triggers. Delimiter characters can be a comma, space, TAB, or semicolon | `string` | n/a | yes | +| [budget\_alert\_rule\_threshold](#input\_budget\_alert\_rule\_threshold) | The target for the budget | `string` | n/a | yes | +| [budget\_amount](#input\_budget\_amount) | The amount of the budget expressed as a whole number in the currency of the customer's rate card. | `string` | n/a | yes | +| [budget\_compartment\_id](#input\_budget\_compartment\_id) | The ocid of compartment to provision resources | `string` | n/a | yes | +| [budget\_description](#input\_budget\_description) | n/a | `string` | n/a | yes | +| [budget\_display\_name](#input\_budget\_display\_name) | n/a | `string` | n/a | yes | +| [budget\_target](#input\_budget\_target) | The compartment ocid for the budget | `string` | n/a | yes | +| [environment\_prefix](#input\_environment\_prefix) | the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U | `string` | n/a | yes | +| [region](#input\_region) | The OCI region | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [budget](#output\_budget) | n/a | +| [budget\_alert\_rule](#output\_budget\_alert\_rule) | n/a | + \ No newline at end of file diff --git a/templates/elz-budget/datasources.tf b/templates/elz-budget/datasources.tf new file mode 100644 index 00000000..3e483838 --- /dev/null +++ b/templates/elz-budget/datasources.tf @@ -0,0 +1,12 @@ +# ----------------------------------------------------------------------------- +# Support for multi-region deployments +# ----------------------------------------------------------------------------- +locals { + region_subscriptions = data.oci_identity_region_subscriptions.regions.region_subscriptions + home_region = [for region in local.region_subscriptions : region.region_name if region.is_home_region == true] + region_key = [for region in local.region_subscriptions : region.region_key if region.region_name == var.region] +} + +data "oci_identity_region_subscriptions" "regions" { + tenancy_id = var.tenancy_ocid +} diff --git a/templates/elz-budget/main.tf b/templates/elz-budget/main.tf new file mode 100644 index 00000000..bdd855ab --- /dev/null +++ b/templates/elz-budget/main.tf @@ -0,0 +1,24 @@ +locals { + budget = { + budget_alert_rule_display_name = "${var.budget_display_name}_rule" + } +} + +module "budget" { + source = "../../modules/budget" + + compartment_id = var.budget_compartment_id + budget_amount = var.budget_amount + budget_display_name = var.budget_display_name + budget_description = var.budget_description + budget_target = var.budget_target + + budget_alert_rule_display_name = local.budget.budget_alert_rule_display_name + budget_alert_rule_threshold = var.budget_alert_rule_threshold + budget_alert_rule_message = var.budget_alert_rule_message + budget_alert_rule_recipients = var.budget_alert_rule_recipients + + providers = { + oci = oci + } +} diff --git a/templates/elz-budget/outputs.tf b/templates/elz-budget/outputs.tf new file mode 100644 index 00000000..3b567cbc --- /dev/null +++ b/templates/elz-budget/outputs.tf @@ -0,0 +1,7 @@ +output "budget" { + value = module.budget.budget +} + +output "budget_alert_rule" { + value = module.budget.budget_alert_rule +} diff --git a/templates/elz-budget/provider.tf b/templates/elz-budget/provider.tf new file mode 100644 index 00000000..2bbda84d --- /dev/null +++ b/templates/elz-budget/provider.tf @@ -0,0 +1,72 @@ +# ----------------------------------------------------------------------------- +# Provider Requirements if using stack as a module +# ----------------------------------------------------------------------------- +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + version = "4.96.0" # October 05, 2022 Release + configuration_aliases = [oci, oci.home_region] + } + } +} + +# # ----------------------------------------------------------------------------- +# # WARNING! +# # UNCOMMENT EVERYTHING BELOW AND COMMENT EVERYTHING ABOVE IF YOU WISH TO USE THIS +# # STACK AS A STANDALONE - DO NOT TOUCH IF USING THIS STACK IN A MODULE CALL +# # Provider Requirements if using stack as standalone +# # ----------------------------------------------------------------------------- +# terraform { +# required_version = ">= 1.0.0" + +# required_providers { +# oci = { +# source = "oracle/oci" +# version = "4.96.0" # October 05, 2022 Release +# } +# } +# } + +# # ----------------------------------------------------------------------------- +# # Provider blocks for home region and alternate region(s) +# # ----------------------------------------------------------------------------- +# provider "oci" { +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = var.region +# } + +# provider "oci" { +# alias = "home_region" +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = local.home_region[0] +# } + +# # ----------------------------------------------------------------------------- +# # Provider Variables +# # ----------------------------------------------------------------------------- +# variable "current_user_ocid" { +# type = string +# description = "The OCID of the current user" +# default = "" +# } + +# variable "api_fingerprint" { +# type = string +# description = "The fingerprint of API" +# default = "" +# } + +# variable "api_private_key_path" { +# type = string +# description = "The local path to the API private key" +# default = "" +# } diff --git a/templates/elz-budget/variables.tf b/templates/elz-budget/variables.tf new file mode 100644 index 00000000..b9af71c1 --- /dev/null +++ b/templates/elz-budget/variables.tf @@ -0,0 +1,63 @@ +# ----------------------------------------------------------------------------- +# Common Variables +# ----------------------------------------------------------------------------- +variable "tenancy_ocid" { + type = string + description = "The OCID of tenancy" +} + +variable "region" { + type = string + description = "The OCI region" +} + +variable "environment_prefix" { + type = string + description = "the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U" +} + +# ----------------------------------------------------------------------------- +# +# ----------------------------------------------------------------------------- +variable "budget_compartment_id" { + type = string + description = "The ocid of compartment to provision resources" +} + +variable "budget_amount" { + description = "The amount of the budget expressed as a whole number in the currency of the customer's rate card." + type = string +} + +variable "budget_description" { + + type = string +} + +variable "budget_display_name" { + + type = string +} + +variable "budget_target" { + description = "The compartment ocid for the budget" + type = string +} + +# ----------------------------------------------------------------------------- +# Optional inputs and values to override +# ----------------------------------------------------------------------------- +variable "budget_alert_rule_threshold" { + description = "The target for the budget" + type = string +} + +variable "budget_alert_rule_message" { + description = "The alert message for budget alerts." + type = string +} + +variable "budget_alert_rule_recipients" { + description = "The delimited list of email addresses to receive the alert when it triggers. Delimiter characters can be a comma, space, TAB, or semicolon" + type = string +} diff --git a/templates/elz-compartment/README.md b/templates/elz-compartment/README.md new file mode 100644 index 00000000..019eb446 --- /dev/null +++ b/templates/elz-compartment/README.md @@ -0,0 +1,52 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [oci](#requirement\_oci) | 4.96.0 | + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | 4.96.0 | +| [time](#provider\_time) | n/a | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [backup\_compartment](#module\_backup\_compartment) | ../../modules/compartment | n/a | +| [environment\_compartment](#module\_environment\_compartment) | ../../modules/compartment | n/a | +| [logging\_compartment](#module\_logging\_compartment) | ../../modules/compartment | n/a | +| [network\_compartment](#module\_network\_compartment) | ../../modules/compartment | n/a | +| [security\_compartment](#module\_security\_compartment) | ../../modules/compartment | n/a | +| [shared\_infra\_compartment](#module\_shared\_infra\_compartment) | ../../modules/compartment | n/a | + +## Resources + +| Name | Type | +|------|------| +| [time_sleep.compartment_replication_delay](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [oci_identity_region_subscriptions.regions](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/identity_region_subscriptions) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [enable\_compartment\_delete](#input\_enable\_compartment\_delete) | Set to true to allow the compartments to delete on terraform destroy. | `bool` | `true` | no | +| [enable\_logging](#input\_enable\_logging) | Set to true to enable logging compartment which stores the configuration information that landing zones is setting up for the customer. | `bool` | `false` | no | +| [enable\_tf\_state\_backup](#input\_enable\_tf\_state\_backup) | Set to true to enable logging compartment which contains the bucket for the log files. | `bool` | `false` | no | +| [environment\_compartment\_name](#input\_environment\_compartment\_name) | The name of the compartment that acts as the main compartment for the environment. Resources related to this environment will be created under this compartment. | `string` | `""` | no | +| [environment\_prefix](#input\_environment\_prefix) | the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U | `string` | n/a | yes | +| [home\_compartment\_id](#input\_home\_compartment\_id) | the OCID of the compartment where the environment will be created. In general, this should be the Landing zone parent compartment. | `string` | n/a | yes | +| [region](#input\_region) | The OCI region | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [compartments](#output\_compartments) | n/a | + \ No newline at end of file diff --git a/templates/elz-compartment/compartment.tf b/templates/elz-compartment/compartment.tf new file mode 100644 index 00000000..a929a383 --- /dev/null +++ b/templates/elz-compartment/compartment.tf @@ -0,0 +1,122 @@ +# ----------------------------------------------------------------------------- +# Compartment Resources +# ----------------------------------------------------------------------------- +locals { + environment_compartment = { + name = var.environment_compartment_name != "" ? var.environment_compartment_name : "OCI-ELZ-${var.environment_prefix}-CMP" + description = "Environment Compartment" + } + + shared_infra_compartment = { + name = "OCI-ELZ-${var.environment_prefix}-SRD-CMP-${local.region_key[0]}" + description = "Shared environment Resources Compartment" + } + + network_compartment = { + name = "OCI-ELZ-${var.environment_prefix}-SRD-NET" + description = "Network Compartment" + } + + security_compartment = { + name = "OCI-ELZ-${var.environment_prefix}-SRD-SEC" + description = "Security Compartment" + } + + logging_compartment = { + name = "OCI-ELZ-${var.environment_prefix}-LOG-${local.region_key[0]}" + description = "Logging Compartment" + } + + backup_compartment = { + name = "OCI-ELZ-${var.environment_prefix}-BAC-TF-${local.region_key[0]}" + description = "Backup Compartment" + } +} + +module "environment_compartment" { + source = "../../modules/compartment" + + compartment_parent_id = var.home_compartment_id + compartment_name = local.environment_compartment.name + compartment_description = local.environment_compartment.description + enable_compartment_delete = var.enable_compartment_delete + + providers = { + oci = oci.home_region + } +} + +module "shared_infra_compartment" { + source = "../../modules/compartment" + + compartment_parent_id = module.environment_compartment.compartment_id + compartment_name = local.shared_infra_compartment.name + compartment_description = local.shared_infra_compartment.description + enable_compartment_delete = var.enable_compartment_delete + + providers = { + oci = oci.home_region + } +} + +module "network_compartment" { + source = "../../modules/compartment" + + compartment_parent_id = module.shared_infra_compartment.compartment_id + compartment_name = local.network_compartment.name + compartment_description = local.network_compartment.description + enable_compartment_delete = var.enable_compartment_delete + + providers = { + oci = oci.home_region + } +} + +module "security_compartment" { + source = "../../modules/compartment" + + compartment_parent_id = module.shared_infra_compartment.compartment_id + compartment_name = local.security_compartment.name + compartment_description = local.security_compartment.description + enable_compartment_delete = var.enable_compartment_delete + + providers = { + oci = oci.home_region + } +} + +module "logging_compartment" { + source = "../../modules/compartment" + + count = var.enable_logging ? 1 : 0 + compartment_parent_id = module.environment_compartment.compartment_id + compartment_name = local.logging_compartment.name + compartment_description = local.logging_compartment.description + enable_compartment_delete = var.enable_compartment_delete + + providers = { + oci = oci.home_region + } +} + +module "backup_compartment" { + source = "../../modules/compartment" + + count = var.enable_tf_state_backup ? 1 : 0 + compartment_parent_id = module.environment_compartment.compartment_id + compartment_name = local.backup_compartment.name + compartment_description = local.backup_compartment.description + enable_compartment_delete = var.enable_compartment_delete + + providers = { + oci = oci.home_region + } +} + +# @TODO copied from scca not sure if necessary here or for any others +# - it seems the compartment technical module also has a delay so is this necessary? +resource "time_sleep" "compartment_replication_delay" { + depends_on = [module.backup_compartment] + + create_duration = "90s" +} diff --git a/templates/elz-compartment/datasources.tf b/templates/elz-compartment/datasources.tf new file mode 100644 index 00000000..3e483838 --- /dev/null +++ b/templates/elz-compartment/datasources.tf @@ -0,0 +1,12 @@ +# ----------------------------------------------------------------------------- +# Support for multi-region deployments +# ----------------------------------------------------------------------------- +locals { + region_subscriptions = data.oci_identity_region_subscriptions.regions.region_subscriptions + home_region = [for region in local.region_subscriptions : region.region_name if region.is_home_region == true] + region_key = [for region in local.region_subscriptions : region.region_key if region.region_name == var.region] +} + +data "oci_identity_region_subscriptions" "regions" { + tenancy_id = var.tenancy_ocid +} diff --git a/templates/elz-compartment/outputs.tf b/templates/elz-compartment/outputs.tf new file mode 100644 index 00000000..f5904596 --- /dev/null +++ b/templates/elz-compartment/outputs.tf @@ -0,0 +1,15 @@ +locals { + compartments_map = merge({ + "environment" : module.environment_compartment.compartment, + "shared" : module.shared_infra_compartment.compartment, + "network" : module.network_compartment.compartment, + "security" : module.security_compartment.compartment, + }, + var.enable_logging == true ? { "logging" : module.logging_compartment[0].compartment } : {}, + var.enable_tf_state_backup == true ? { "backup" : module.backup_compartment[0].compartment } : {}, + ) +} + +output "compartments" { + value = local.compartments_map +} diff --git a/templates/elz-compartment/provider.tf b/templates/elz-compartment/provider.tf new file mode 100644 index 00000000..2bbda84d --- /dev/null +++ b/templates/elz-compartment/provider.tf @@ -0,0 +1,72 @@ +# ----------------------------------------------------------------------------- +# Provider Requirements if using stack as a module +# ----------------------------------------------------------------------------- +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + version = "4.96.0" # October 05, 2022 Release + configuration_aliases = [oci, oci.home_region] + } + } +} + +# # ----------------------------------------------------------------------------- +# # WARNING! +# # UNCOMMENT EVERYTHING BELOW AND COMMENT EVERYTHING ABOVE IF YOU WISH TO USE THIS +# # STACK AS A STANDALONE - DO NOT TOUCH IF USING THIS STACK IN A MODULE CALL +# # Provider Requirements if using stack as standalone +# # ----------------------------------------------------------------------------- +# terraform { +# required_version = ">= 1.0.0" + +# required_providers { +# oci = { +# source = "oracle/oci" +# version = "4.96.0" # October 05, 2022 Release +# } +# } +# } + +# # ----------------------------------------------------------------------------- +# # Provider blocks for home region and alternate region(s) +# # ----------------------------------------------------------------------------- +# provider "oci" { +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = var.region +# } + +# provider "oci" { +# alias = "home_region" +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = local.home_region[0] +# } + +# # ----------------------------------------------------------------------------- +# # Provider Variables +# # ----------------------------------------------------------------------------- +# variable "current_user_ocid" { +# type = string +# description = "The OCID of the current user" +# default = "" +# } + +# variable "api_fingerprint" { +# type = string +# description = "The fingerprint of API" +# default = "" +# } + +# variable "api_private_key_path" { +# type = string +# description = "The local path to the API private key" +# default = "" +# } diff --git a/templates/elz-compartment/variables.tf b/templates/elz-compartment/variables.tf new file mode 100644 index 00000000..0446b5b5 --- /dev/null +++ b/templates/elz-compartment/variables.tf @@ -0,0 +1,49 @@ +# ----------------------------------------------------------------------------- +# Common Variables +# ----------------------------------------------------------------------------- +variable "tenancy_ocid" { + type = string + description = "The OCID of tenancy" +} + +variable "region" { + type = string + description = "The OCI region" +} + +variable "environment_prefix" { + type = string + description = "the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U" +} + +# ----------------------------------------------------------------------------- +# Compartment Variables +# ----------------------------------------------------------------------------- +variable "enable_compartment_delete" { + type = bool + description = "Set to true to allow the compartments to delete on terraform destroy." + default = true +} + +variable "home_compartment_id" { + type = string + description = "the OCID of the compartment where the environment will be created. In general, this should be the Landing zone parent compartment." +} + +variable "environment_compartment_name" { + type = string + description = "The name of the compartment that acts as the main compartment for the environment. Resources related to this environment will be created under this compartment. " + default = "" +} + +variable "enable_tf_state_backup" { + type = bool + description = "Set to true to enable logging compartment which contains the bucket for the log files." + default = false +} + +variable "enable_logging" { + type = bool + description = "Set to true to enable logging compartment which stores the configuration information that landing zones is setting up for the customer." + default = false +} diff --git a/templates/elz-environment/CONFIGURATION.md b/templates/elz-environment/CONFIGURATION.md new file mode 100644 index 00000000..e71b1196 --- /dev/null +++ b/templates/elz-environment/CONFIGURATION.md @@ -0,0 +1,20 @@ +## Configuration Guide (DO NOT UPDATE) + +### Compartment +For the Environment stack, we have the below compartment architecture: +* Environment Compartment + * Shared Infrastructure + * Network + * Security + * Logging + * Backup + +To configure the compartment the required user inputs are: +* **environment_compartment_name**: the name of the top level environment compartment +* **environment_prefix**: the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U +* **home_compartment_id**: the OCID of the compartment that the environment compartment build on. + +Note that: +* The default value of **enable_logging** and **enable_tf_state_backup** which control the creation of +the Logging Compartment and the Backup Compartment are set to false. Those two variables need to be true +to create the Logging Compartment and the Backup Compartment. diff --git a/templates/elz-environment/README.md b/templates/elz-environment/README.md new file mode 100644 index 00000000..239bf33b --- /dev/null +++ b/templates/elz-environment/README.md @@ -0,0 +1,150 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [oci](#requirement\_oci) | 4.96.0 | + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | 4.96.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [budget](#module\_budget) | ../elz-budget | n/a | +| [compartment](#module\_compartment) | ../elz-compartment | n/a | +| [identity](#module\_identity) | ../elz-identity | n/a | +| [logging](#module\_logging) | ../elz-logging | n/a | +| [monitoring](#module\_monitoring) | ../elz-monitoring | n/a | +| [network](#module\_network) | ../elz-network | n/a | +| [network-extension](#module\_network-extension) | ../elz-network-extension | n/a | +| [security](#module\_security) | ../elz-security | n/a | +| [tagging](#module\_tagging) | ../elz-tagging | n/a | +| [workload](#module\_workload) | ../elz-workload | n/a | + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_region_subscriptions.regions](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/identity_region_subscriptions) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [application\_admin\_group\_name](#input\_application\_admin\_group\_name) | The group name for the OCI Application Administrators Group | `string` | `""` | no | +| [bastion\_client\_cidr\_block\_allow\_list](#input\_bastion\_client\_cidr\_block\_allow\_list) | A list of address ranges in CIDR notation that you want to allow to connect to sessions hosted by this bastion. | `list(string)` | n/a | yes | +| [bgp\_cust\_tunnela\_ip](#input\_bgp\_cust\_tunnela\_ip) | n/a | `any` | n/a | yes | +| [bgp\_md5auth\_key](#input\_bgp\_md5auth\_key) | n/a | `string` | n/a | yes | +| [bgp\_oci\_tunnela\_ip](#input\_bgp\_oci\_tunnela\_ip) | n/a | `any` | n/a | yes | +| [budget\_alert\_rule\_message](#input\_budget\_alert\_rule\_message) | The alert message for budget alerts. | `string` | `""` | no | +| [budget\_alert\_rule\_recipients](#input\_budget\_alert\_rule\_recipients) | The delimited list of email addresses to receive the alert when it triggers. Delimiter characters can be a comma, space, TAB, or semicolon | `string` | `""` | no | +| [budget\_alert\_rule\_threshold](#input\_budget\_alert\_rule\_threshold) | The threshold for the budget alert. | `string` | `""` | no | +| [budget\_amount](#input\_budget\_amount) | The amount of the budget expressed as a whole number in the currency of the customer's rate card. | `string` | `""` | no | +| [cloud\_guard\_target\_tenancy](#input\_cloud\_guard\_target\_tenancy) | true if cloud guard targets to tenancy, false if cloud guard targets to Landing Zone home compartment | `bool` | n/a | yes | +| [cost\_center\_tagging](#input\_cost\_center\_tagging) | Cost Center Varible | `string` | n/a | yes | +| [cpe\_display\_name](#input\_cpe\_display\_name) | n/a | `string` | n/a | yes | +| [cpe\_ip\_address](#input\_cpe\_ip\_address) | Customer Premises Equipment (CPE) IP address | `string` | n/a | yes | +| [cpe\_vendor](#input\_cpe\_vendor) | n/a | `number` | n/a | yes | +| [create\_master\_encryption\_key](#input\_create\_master\_encryption\_key) | Option create master encryption key | `bool` | n/a | yes | +| [customer\_bgp\_asn](#input\_customer\_bgp\_asn) | n/a | `any` | n/a | yes | +| [customer\_onprem\_ip\_cidr](#input\_customer\_onprem\_ip\_cidr) | n/a | `list(string)` | `[]` | no | +| [customer\_primary\_bgp\_peering\_ip](#input\_customer\_primary\_bgp\_peering\_ip) | n/a | `string` | n/a | yes | +| [customer\_secondary\_bgp\_peering\_ip](#input\_customer\_secondary\_bgp\_peering\_ip) | n/a | `string` | n/a | yes | +| [database\_admin\_group\_name](#input\_database\_admin\_group\_name) | The group name for the OCI Database Logging Administrators Group | `string` | `""` | no | +| [domain\_admin\_email](#input\_domain\_admin\_email) | The email address for the identity domain admin. | `string` | n/a | yes | +| [enable\_bastion](#input\_enable\_bastion) | Option to enable bastion service | `bool` | n/a | yes | +| [enable\_budget](#input\_enable\_budget) | ----------------------------------------------------------------------------- Budget Variables ----------------------------------------------------------------------------- | `bool` | n/a | yes | +| [enable\_cloud\_guard](#input\_enable\_cloud\_guard) | true if you don't have cloud guard enabled, false if you've already have cloud guard enabled. | `bool` | n/a | yes | +| [enable\_compartment\_delete](#input\_enable\_compartment\_delete) | Set to true to allow the compartments to delete on terraform destroy. | `bool` | `true` | no | +| [enable\_fastconnect\_on\_environment](#input\_enable\_fastconnect\_on\_environment) | n/a | `bool` | n/a | yes | +| [enable\_internet\_gateway\_hub](#input\_enable\_internet\_gateway\_hub) | Option to enable true and Disable false. | `string` | n/a | yes | +| [enable\_logging](#input\_enable\_logging) | Set to true to enable logging compartment which stores the configuration information that landing zones is setting up for the customer. | `bool` | `false` | no | +| [enable\_nat\_gateway\_hub](#input\_enable\_nat\_gateway\_hub) | Option to enable true and Disable false. | `string` | n/a | yes | +| [enable\_nat\_gateway\_spoke](#input\_enable\_nat\_gateway\_spoke) | Option to enable true and Disable false. | `string` | n/a | yes | +| [enable\_network\_monitoring\_alarms](#input\_enable\_network\_monitoring\_alarms) | Enable Network Monitoring Alarms in Network Compartment | `bool` | n/a | yes | +| [enable\_security\_monitoring\_alarms](#input\_enable\_security\_monitoring\_alarms) | Enable Security Monitoring Alarms in Security Compartment | `bool` | n/a | yes | +| [enable\_service\_gateway\_hub](#input\_enable\_service\_gateway\_hub) | Option to enable true and Disable false. | `string` | n/a | yes | +| [enable\_service\_gateway\_spoke](#input\_enable\_service\_gateway\_spoke) | Option to enable true and Disable false. | `string` | n/a | yes | +| [enable\_tagging](#input\_enable\_tagging) | Set to true to enable Tagging. | `bool` | `false` | no | +| [enable\_tf\_state\_backup](#input\_enable\_tf\_state\_backup) | Set to true to enable logging compartment which contains the bucket for the log files. | `bool` | `false` | no | +| [enable\_vault\_replication](#input\_enable\_vault\_replication) | Option to enable vault replication | `bool` | n/a | yes | +| [enable\_vpn\_on\_environment](#input\_enable\_vpn\_on\_environment) | n/a | `bool` | n/a | yes | +| [enable\_vpn\_or\_fastconnect](#input\_enable\_vpn\_or\_fastconnect) | Option to enable VPN or FASTCONNECT service. Options are NONE, VPN, FASTCONNECT. | `string` | n/a | yes | +| [enable\_workload\_monitoring\_alarms](#input\_enable\_workload\_monitoring\_alarms) | Enable Workload Monitoring Alarms in Workload Compartment | `bool` | n/a | yes | +| [environment\_compartment\_name](#input\_environment\_compartment\_name) | The name of the compartment that acts as the main compartment for the environment. Resources related to this environment will be created under this compartment. | `string` | `""` | no | +| [environment\_prefix](#input\_environment\_prefix) | the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U | `string` | n/a | yes | +| [fastconnect\_provider](#input\_fastconnect\_provider) | Fastconnect Variables | `string` | n/a | yes | +| [fastconnect\_routing\_policy](#input\_fastconnect\_routing\_policy) | n/a | `list(string)` | n/a | yes | +| [geo\_location\_tagging](#input\_geo\_location\_tagging) | Geo Location. | `string` | n/a | yes | +| [home\_compartment\_id](#input\_home\_compartment\_id) | the OCID of the compartment where the environment will be created. In general, this should be the Landing zone parent compartment. | `string` | n/a | yes | +| [home\_compartment\_name](#input\_home\_compartment\_name) | the OCID of the compartment where the environment will be created. In general, this should be the Landing zone parent compartment. | `string` | n/a | yes | +| [iam\_admin\_group\_name](#input\_iam\_admin\_group\_name) | The group name for the OCI Landing Zone IAM Administrators Group | `string` | `""` | no | +| [identity\_topic\_endpoints](#input\_identity\_topic\_endpoints) | List of email addresses for Identity notifications. | `list(string)` | `[]` | no | +| [igw\_hub\_check](#input\_igw\_hub\_check) | n/a | `list(string)` | n/a | yes | +| [ipsec\_connection\_static\_routes](#input\_ipsec\_connection\_static\_routes) | n/a | `list(string)` | n/a | yes | +| [ipsec\_display\_name](#input\_ipsec\_display\_name) | n/a | `string` | n/a | yes | +| [nat\_gw\_hub\_check](#input\_nat\_gw\_hub\_check) | n/a | `list(string)` | n/a | yes | +| [nat\_gw\_spoke\_check](#input\_nat\_gw\_spoke\_check) | n/a | `list(string)` | n/a | yes | +| [network\_admin\_group\_name](#input\_network\_admin\_group\_name) | The group name for the OCI Landing Zone Network Administrators Group | `string` | `""` | no | +| [network\_topic\_endpoints](#input\_network\_topic\_endpoints) | List of email addresses for Network Warning and Critical notifications. | `list(string)` | `[]` | no | +| [ops\_admin\_group\_name](#input\_ops\_admin\_group\_name) | The group name for the OCI Landing Zone Ops Administrators Group | `string` | `""` | no | +| [oracle\_primary\_bgp\_peering\_ip](#input\_oracle\_primary\_bgp\_peering\_ip) | n/a | `string` | n/a | yes | +| [oracle\_secondary\_bgp\_peering\_ip](#input\_oracle\_secondary\_bgp\_peering\_ip) | n/a | `string` | n/a | yes | +| [platform\_admin\_group\_name](#input\_platform\_admin\_group\_name) | The group name for the OCI Landing Zone Platform Administrators Group | `string` | `""` | no | +| [platform\_topic\_endpoints](#input\_platform\_topic\_endpoints) | List of email addresses for Platform notifications. | `list(string)` | `[]` | no | +| [private\_spoke\_subnet\_app\_cidr\_block](#input\_private\_spoke\_subnet\_app\_cidr\_block) | Spoke App Subnet CIDR Block. | `string` | n/a | yes | +| [private\_spoke\_subnet\_db\_cidr\_block](#input\_private\_spoke\_subnet\_db\_cidr\_block) | Spoke DB Subnet CIDR Block. | `string` | n/a | yes | +| [private\_spoke\_subnet\_web\_cidr\_block](#input\_private\_spoke\_subnet\_web\_cidr\_block) | Spoke Web Subnet CIDR Block. | `string` | n/a | yes | +| [private\_subnet\_cidr\_block](#input\_private\_subnet\_cidr\_block) | Hub Private Subnet CIDR Block. | `string` | n/a | yes | +| [provider\_service\_key\_name](#input\_provider\_service\_key\_name) | n/a | `string` | n/a | yes | +| [public\_subnet\_cidr\_block](#input\_public\_subnet\_cidr\_block) | Hub Public Subnet CIDR Block. | `string` | n/a | yes | +| [region](#input\_region) | The OCI region | `string` | n/a | yes | +| [region\_key](#input\_region\_key) | n/a | `string` | n/a | yes | +| [remote\_peering\_connection\_peer\_id](#input\_remote\_peering\_connection\_peer\_id) | n/a | `string` | `null` | no | +| [remote\_peering\_connection\_peer\_region\_name](#input\_remote\_peering\_connection\_peer\_region\_name) | n/a | `string` | `null` | no | +| [resource\_label](#input\_resource\_label) | Prefix used to avoid naming conflict | `string` | n/a | yes | +| [retention\_policy\_duration\_amount](#input\_retention\_policy\_duration\_amount) | The timeAmount is interpreted in units defined by the timeUnit parameter, and is calculated in relation to each object's Last-Modified timestamp. | `string` | n/a | yes | +| [retention\_policy\_duration\_time\_unit](#input\_retention\_policy\_duration\_time\_unit) | The unit that should be used to interpret timeAmount. | `string` | n/a | yes | +| [routing](#input\_routing) | n/a | `string` | n/a | yes | +| [secops\_topic\_endpoints](#input\_secops\_topic\_endpoints) | List of email addresses for Secops Warning and Critical notifications. | `list(string)` | `[]` | no | +| [security\_admin\_group\_name](#input\_security\_admin\_group\_name) | The group name for the OCI Landing Zone Security Administrators Group | `string` | `""` | no | +| [service\_gw\_hub\_check](#input\_service\_gw\_hub\_check) | n/a | `list(string)` | n/a | yes | +| [service\_gw\_spoke\_check](#input\_service\_gw\_spoke\_check) | n/a | `list(string)` | n/a | yes | +| [shared\_secret](#input\_shared\_secret) | n/a | `any` | n/a | yes | +| [spoke\_vcn\_cidr](#input\_spoke\_vcn\_cidr) | Spoke VCN CIDR Block. | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | +| [tunnel\_a\_display\_name](#input\_tunnel\_a\_display\_name) | n/a | `any` | n/a | yes | +| [tunnel\_b\_display\_name](#input\_tunnel\_b\_display\_name) | n/a | `any` | n/a | yes | +| [vault\_replica\_region](#input\_vault\_replica\_region) | the region to be created replica to. | `string` | n/a | yes | +| [vault\_type](#input\_vault\_type) | The type of vault to create. | `string` | n/a | yes | +| [vcn\_cidr\_block](#input\_vcn\_cidr\_block) | Hub VCN CIDR Block. | `string` | n/a | yes | +| [virtual\_circuit\_bandwidth\_shape](#input\_virtual\_circuit\_bandwidth\_shape) | n/a | `string` | n/a | yes | +| [virtual\_circuit\_customer\_asn](#input\_virtual\_circuit\_customer\_asn) | n/a | `string` | n/a | yes | +| [virtual\_circuit\_display\_name](#input\_virtual\_circuit\_display\_name) | n/a | `string` | n/a | yes | +| [virtual\_circuit\_is\_bfd\_enabled](#input\_virtual\_circuit\_is\_bfd\_enabled) | n/a | `bool` | n/a | yes | +| [virtual\_circuit\_type](#input\_virtual\_circuit\_type) | n/a | `string` | n/a | yes | +| [workload\_admin\_group\_name](#input\_workload\_admin\_group\_name) | The group name for the OCI Workload Administrators Group | `string` | `""` | no | +| [workload\_topic\_endpoints](#input\_workload\_topic\_endpoints) | List of email addresses for Workload notifications. | `list(string)` | `[]` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [bucket](#output\_bucket) | n/a | +| [compartment](#output\_compartment) | n/a | +| [default\_group\_id](#output\_default\_group\_id) | n/a | +| [key\_id](#output\_key\_id) | n/a | +| [rpc\_id](#output\_rpc\_id) | n/a | +| [spoke\_web\_subnet\_ocid](#output\_spoke\_web\_subnet\_ocid) | n/a | +| [stream\_id](#output\_stream\_id) | n/a | +| [subnets](#output\_subnets) | The subnet OCID | +| [vault\_id](#output\_vault\_id) | n/a | +| [vcn](#output\_vcn) | n/a | +| [workload\_compartment\_id](#output\_workload\_compartment\_id) | n/a | + diff --git a/templates/elz-environment/datasources.tf b/templates/elz-environment/datasources.tf new file mode 100644 index 00000000..3e483838 --- /dev/null +++ b/templates/elz-environment/datasources.tf @@ -0,0 +1,12 @@ +# ----------------------------------------------------------------------------- +# Support for multi-region deployments +# ----------------------------------------------------------------------------- +locals { + region_subscriptions = data.oci_identity_region_subscriptions.regions.region_subscriptions + home_region = [for region in local.region_subscriptions : region.region_name if region.is_home_region == true] + region_key = [for region in local.region_subscriptions : region.region_key if region.region_name == var.region] +} + +data "oci_identity_region_subscriptions" "regions" { + tenancy_id = var.tenancy_ocid +} diff --git a/templates/elz-environment/logging-variables.tf b/templates/elz-environment/logging-variables.tf new file mode 100644 index 00000000..2a3b467e --- /dev/null +++ b/templates/elz-environment/logging-variables.tf @@ -0,0 +1,9 @@ +variable "retention_policy_duration_amount" { + type = string + description = "The timeAmount is interpreted in units defined by the timeUnit parameter, and is calculated in relation to each object's Last-Modified timestamp." +} + +variable "retention_policy_duration_time_unit" { + type = string + description = "The unit that should be used to interpret timeAmount." +} diff --git a/templates/elz-environment/logging.tf b/templates/elz-environment/logging.tf new file mode 100644 index 00000000..3dfc11ff --- /dev/null +++ b/templates/elz-environment/logging.tf @@ -0,0 +1,22 @@ +module "logging" { + source = "../elz-logging" + region = var.region + environment_prefix = var.environment_prefix + tenancy_ocid = var.tenancy_ocid + home_compartment_id = var.home_compartment_id + home_compartment_name = var.home_compartment_name + security_compartment_id = module.compartment.compartments.security.id + master_encryption_key = module.security.key_id + logging_compartment_id = module.compartment.compartments.logging.id + resource_label = var.resource_label + retention_policy_duration_amount = var.retention_policy_duration_amount + retention_policy_duration_time_unit = var.retention_policy_duration_time_unit + subnets_map = module.network.subnets + + depends_on = [ module.network ] + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} \ No newline at end of file diff --git a/templates/elz-environment/main.tf b/templates/elz-environment/main.tf new file mode 100644 index 00000000..b735d9f2 --- /dev/null +++ b/templates/elz-environment/main.tf @@ -0,0 +1,199 @@ +module "compartment" { + source = "../elz-compartment" + tenancy_ocid = var.tenancy_ocid + region = var.region + environment_prefix = var.environment_prefix + enable_compartment_delete = var.enable_compartment_delete + home_compartment_id = var.home_compartment_id + environment_compartment_name = var.environment_compartment_name + enable_tf_state_backup = var.enable_tf_state_backup + enable_logging = var.enable_logging + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} + +module "identity" { + source = "../elz-identity" + tenancy_ocid = var.tenancy_ocid + region = var.region + environment_prefix = var.environment_prefix + environment_compartment_id = module.compartment.compartments.environment.id + environment_compartment_name = module.compartment.compartments.environment.name + security_compartment_id = module.compartment.compartments.security.id + security_compartment_name = module.compartment.compartments.security.name + network_compartment_id = module.compartment.compartments.network.id + network_compartment_name = module.compartment.compartments.network.name + domain_admin_email = var.domain_admin_email + network_admin_group_name = var.network_admin_group_name + security_admin_group_name = var.security_admin_group_name + iam_admin_group_name = var.iam_admin_group_name + platform_admin_group_name = var.platform_admin_group_name + ops_admin_group_name = var.ops_admin_group_name + workload_admin_group_name = var.workload_admin_group_name + application_admin_group_name = var.application_admin_group_name + database_admin_group_name = var.database_admin_group_name + workload_compartment_id = module.workload.compartment_id + workload_compartment_name = module.workload.compartment_name + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} + +locals { + budget = { + budget_description = "Budget targeting ${var.environment_prefix} enviroment compartment" + budget_display_name = "OCI-ELZ-BGT-${var.environment_prefix}" + } +} + +module "budget" { + count = var.enable_budget ? 1 : 0 + source = "../elz-budget" + tenancy_ocid = var.tenancy_ocid + region = var.region + environment_prefix = var.environment_prefix + + budget_compartment_id = var.tenancy_ocid + budget_description = local.budget.budget_description + budget_display_name = local.budget.budget_display_name + budget_target = module.compartment.compartments.environment.id + budget_amount = var.budget_amount + budget_alert_rule_threshold = var.budget_alert_rule_threshold + budget_alert_rule_message = var.budget_alert_rule_message + budget_alert_rule_recipients = var.budget_alert_rule_recipients + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} + +module "security" { + source = "../elz-security" + enable_cloud_guard = var.enable_cloud_guard + resource_label = var.resource_label + home_compartment_id = var.home_compartment_id + cloud_guard_target_tenancy = var.cloud_guard_target_tenancy + tenancy_ocid = var.tenancy_ocid + environment_prefix = var.environment_prefix + home_compartment_name = var.home_compartment_name + region = var.region + environment_compartment_id = module.compartment.compartments.environment.id + security_compartment_id = module.compartment.compartments.security.id + enable_bastion = var.enable_bastion + bastion_target_subnet_id = module.network.spoke_web_subnet_ocid + bastion_client_cidr_block_allow_list = var.bastion_client_cidr_block_allow_list + vault_type = var.vault_type + replica_region = var.vault_replica_region + enable_replication = var.enable_vault_replication + create_master_encryption_key = var.create_master_encryption_key + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} + +locals { + network = { + vcn_description = "VCN targeting ${var.environment_prefix} enviroment compartment" + vcn_display_name = "OCI-ELZ-VCN-${var.environment_prefix}-HUB-${local.region_key[0]}" + } +} + +module "network" { + source = "../elz-network" + tenancy_ocid = var.tenancy_ocid + environment_prefix = var.environment_prefix + region = var.region + network_compartment_id = module.compartment.compartments.network.id + + enable_internet_gateway_hub = var.enable_internet_gateway_hub + enable_nat_gateway_hub = var.enable_nat_gateway_hub + enable_service_gateway_hub = var.enable_service_gateway_hub + enable_nat_gateway_spoke = var.enable_nat_gateway_spoke + enable_service_gateway_spoke = var.enable_service_gateway_spoke + + igw_hub_check = var.igw_hub_check + nat_gw_hub_check = var.nat_gw_hub_check + service_gw_hub_check = var.service_gw_hub_check + nat_gw_spoke_check = var.nat_gw_spoke_check + service_gw_spoke_check = var.service_gw_spoke_check + network_admin_group_name = var.network_admin_group_name + workload_compartment_id = module.workload.compartment_id + workload_compartment_name = module.workload.compartment_name + network_compartment_name = module.compartment.compartments.network.name + + vcn_cidr_block = var.vcn_cidr_block + public_subnet_cidr_block = var.public_subnet_cidr_block + private_subnet_cidr_block = var.private_subnet_cidr_block + private_spoke_subnet_web_cidr_block = var.private_spoke_subnet_web_cidr_block + private_spoke_subnet_app_cidr_block = var.private_spoke_subnet_app_cidr_block + private_spoke_subnet_db_cidr_block = var.private_spoke_subnet_db_cidr_block + spoke_vcn_cidr = var.spoke_vcn_cidr + ipsec_connection_static_routes = var.ipsec_connection_static_routes + enable_vpn_or_fastconnect = var.enable_vpn_or_fastconnect + enable_vpn_on_environment = var.enable_vpn_on_environment + enable_fastconnect_on_environment = var.enable_fastconnect_on_environment + customer_onprem_ip_cidr = var.customer_onprem_ip_cidr + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} + +module "tagging" { + + source = "../elz-tagging" + + region = var.region + environment_compartment_id = module.compartment.compartments.environment.id + environment_compartment_name = var.environment_compartment_name + enable_tagging = var.enable_tagging + environment_prefix = var.environment_prefix + tenancy_ocid = var.tenancy_ocid + cost_center_tagging = var.cost_center_tagging + geo_location_tagging = var.geo_location_tagging + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} + +module "monitoring" { + source = "../elz-monitoring" + + tenancy_ocid = var.tenancy_ocid + region = var.region + environment_prefix = var.environment_prefix + resource_label = var.resource_label + + environment_compartment_id = module.compartment.compartments.environment.id + security_compartment_id = module.compartment.compartments.security.id + network_compartment_id = module.compartment.compartments.network.id + workload_compartment_id = module.workload.compartment_id + + network_topic_endpoints = var.network_topic_endpoints + secops_topic_endpoints = var.secops_topic_endpoints + platform_topic_endpoints = var.platform_topic_endpoints + identity_topic_endpoints = var.identity_topic_endpoints + default_log_group_id = module.logging.log_group_id + + workload_topic_endpoints = var.workload_topic_endpoints + + enable_security_monitoring_alarms = var.enable_security_monitoring_alarms + enable_network_monitoring_alarms = var.enable_network_monitoring_alarms + enable_workload_monitoring_alarms = var.enable_workload_monitoring_alarms + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} diff --git a/templates/elz-environment/network-extension-variables.tf b/templates/elz-environment/network-extension-variables.tf new file mode 100644 index 00000000..a821c6cd --- /dev/null +++ b/templates/elz-environment/network-extension-variables.tf @@ -0,0 +1,122 @@ +variable "enable_vpn_or_fastconnect" { + type = string + description = "Option to enable VPN or FASTCONNECT service. Options are NONE, VPN, FASTCONNECT." +} + +variable "cpe_ip_address" { + type = string + description = "Customer Premises Equipment (CPE) IP address" +} + +variable "ipsec_connection_static_routes" { + type = list(string) +} + +variable "enable_vpn_on_environment" { + type = bool +} + +variable "cpe_display_name" { + type = string +} + +variable "ipsec_display_name" { + type = string +} + +variable "cpe_vendor" { + type = number +} + +variable "routing" { + type = string + description = "" +} + +variable "tunnel_a_display_name" {} + +variable "customer_bgp_asn" {} + +variable "bgp_cust_tunnela_ip" {} + +variable "bgp_oci_tunnela_ip" {} + +variable "shared_secret" {} + +variable "tunnel_b_display_name" {} + +# Fastconnect Variables +variable "fastconnect_provider" { + type = string +} + +variable "region_key" { + type = string +} + +variable "virtual_circuit_bandwidth_shape" { + type = string +} + +variable "virtual_circuit_display_name" { + type = string +} + +variable "provider_service_key_name" { + type = string +} + +variable "fastconnect_routing_policy" { + type = list(string) +} + +variable "virtual_circuit_type" { + type = string +} + +variable "customer_primary_bgp_peering_ip" { + type = string +} + +variable "oracle_primary_bgp_peering_ip" { + type = string +} + +variable "customer_secondary_bgp_peering_ip" { + type = string +} + +variable "oracle_secondary_bgp_peering_ip" { + type = string +} + +variable "virtual_circuit_customer_asn" { + type = string +} + +variable "virtual_circuit_is_bfd_enabled" { + type = bool +} + +variable "bgp_md5auth_key" { + type = string +} + +variable "enable_fastconnect_on_environment" { + type = bool +} + +variable "remote_peering_connection_peer_id" { + type = string + default = null +} + +variable "remote_peering_connection_peer_region_name" { + type = string + default = null +} + +variable "customer_onprem_ip_cidr" { + type = list(string) + default = [] +} diff --git a/templates/elz-environment/network-extension.tf b/templates/elz-environment/network-extension.tf new file mode 100644 index 00000000..82e990ae --- /dev/null +++ b/templates/elz-environment/network-extension.tf @@ -0,0 +1,47 @@ +module "network-extension" { + source = "../elz-network-extension" + tenancy_ocid = var.tenancy_ocid + region = var.region + environment_prefix = var.environment_prefix + + network_compartment_id = module.compartment.compartments.network.id + cpe_ip_address = var.cpe_ip_address + enable_vpn_or_fastconnect = var.enable_vpn_or_fastconnect + ipsec_connection_static_routes = var.ipsec_connection_static_routes + enable_vpn_on_environment = var.enable_vpn_on_environment + cpe_display_name = var.cpe_display_name + ipsec_display_name = var.ipsec_display_name + drg_id = module.network.drg_id + cpe_vendor = var.cpe_vendor + routing = var.routing + tunnel_a_display_name = var.tunnel_a_display_name + customer_bgp_asn = var.customer_bgp_asn + bgp_cust_tunnela_ip = var.bgp_cust_tunnela_ip + bgp_oci_tunnela_ip = var.bgp_oci_tunnela_ip + shared_secret = var.shared_secret + tunnel_b_display_name = var.tunnel_b_display_name + fastconnect_provider = var.fastconnect_provider + region_key = var.region_key + virtual_circuit_bandwidth_shape = var.virtual_circuit_bandwidth_shape + virtual_circuit_display_name = var.virtual_circuit_display_name + provider_service_key_name = var.provider_service_key_name + fastconnect_routing_policy = var.fastconnect_routing_policy + virtual_circuit_type = var.virtual_circuit_type + customer_primary_bgp_peering_ip = var.customer_primary_bgp_peering_ip + oracle_primary_bgp_peering_ip = var.oracle_primary_bgp_peering_ip + customer_secondary_bgp_peering_ip = var.customer_secondary_bgp_peering_ip + oracle_secondary_bgp_peering_ip = var.oracle_secondary_bgp_peering_ip + virtual_circuit_customer_asn = var.virtual_circuit_customer_asn + virtual_circuit_is_bfd_enabled = var.virtual_circuit_is_bfd_enabled + bgp_md5auth_key = var.bgp_md5auth_key + enable_fastconnect_on_environment = var.enable_fastconnect_on_environment + remote_peering_connection_peer_id = var.remote_peering_connection_peer_id + remote_peering_connection_peer_region_name = var.remote_peering_connection_peer_region_name + drg_route_table_rpc_id = var.enable_vpn_or_fastconnect == "FASTCONNECT" && var.enable_fastconnect_on_environment ? module.network.drg_route_tables.RT-RPC.id : null + drg_route_table_vc_id = var.enable_vpn_or_fastconnect == "FASTCONNECT" && var.enable_fastconnect_on_environment ? module.network.drg_route_tables.RT-Onprem.id : null + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} diff --git a/templates/elz-environment/outputs.tf b/templates/elz-environment/outputs.tf new file mode 100644 index 00000000..f482a83f --- /dev/null +++ b/templates/elz-environment/outputs.tf @@ -0,0 +1,45 @@ +output "compartment" { + value = module.compartment.compartments +} + +output "subnets" { + value = module.network.subnets + description = "The subnet OCID" +} + +output "vcn" { + value = module.network.vcn +} + +output "spoke_web_subnet_ocid" { + value = module.network.spoke_web_subnet_ocid +} + +output "workload_compartment_id" { + value = module.workload.compartment_id +} + +output "stream_id" { + value = module.logging.stream_id +} + +output "key_id" { + value = module.security.key_id +} + +output "bucket" { + value = module.logging.bucket +} + +output "default_group_id" { + value = module.logging.log_group_id +} + +output "vault_id" { + value = module.security.vault_id +} + +output "rpc_id" { + value = module.network-extension.rpc_id +} + diff --git a/templates/elz-environment/provider.tf b/templates/elz-environment/provider.tf new file mode 100644 index 00000000..2bbda84d --- /dev/null +++ b/templates/elz-environment/provider.tf @@ -0,0 +1,72 @@ +# ----------------------------------------------------------------------------- +# Provider Requirements if using stack as a module +# ----------------------------------------------------------------------------- +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + version = "4.96.0" # October 05, 2022 Release + configuration_aliases = [oci, oci.home_region] + } + } +} + +# # ----------------------------------------------------------------------------- +# # WARNING! +# # UNCOMMENT EVERYTHING BELOW AND COMMENT EVERYTHING ABOVE IF YOU WISH TO USE THIS +# # STACK AS A STANDALONE - DO NOT TOUCH IF USING THIS STACK IN A MODULE CALL +# # Provider Requirements if using stack as standalone +# # ----------------------------------------------------------------------------- +# terraform { +# required_version = ">= 1.0.0" + +# required_providers { +# oci = { +# source = "oracle/oci" +# version = "4.96.0" # October 05, 2022 Release +# } +# } +# } + +# # ----------------------------------------------------------------------------- +# # Provider blocks for home region and alternate region(s) +# # ----------------------------------------------------------------------------- +# provider "oci" { +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = var.region +# } + +# provider "oci" { +# alias = "home_region" +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = local.home_region[0] +# } + +# # ----------------------------------------------------------------------------- +# # Provider Variables +# # ----------------------------------------------------------------------------- +# variable "current_user_ocid" { +# type = string +# description = "The OCID of the current user" +# default = "" +# } + +# variable "api_fingerprint" { +# type = string +# description = "The fingerprint of API" +# default = "" +# } + +# variable "api_private_key_path" { +# type = string +# description = "The local path to the API private key" +# default = "" +# } diff --git a/templates/elz-environment/variables.tf b/templates/elz-environment/variables.tf new file mode 100644 index 00000000..2e6dd2e9 --- /dev/null +++ b/templates/elz-environment/variables.tf @@ -0,0 +1,368 @@ +# ----------------------------------------------------------------------------- +# Common Variables +# ----------------------------------------------------------------------------- +variable "tenancy_ocid" { + type = string + description = "The OCID of tenancy" +} + +variable "region" { + type = string + description = "The OCI region" +} + +variable "environment_prefix" { + type = string + description = "the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U" +} + +variable "resource_label" { + type = string + description = "Prefix used to avoid naming conflict" +} + +# ----------------------------------------------------------------------------- +# Compartment Variables +# ----------------------------------------------------------------------------- +variable "enable_compartment_delete" { + type = bool + description = "Set to true to allow the compartments to delete on terraform destroy." + default = true +} + +variable "home_compartment_id" { + type = string + description = "the OCID of the compartment where the environment will be created. In general, this should be the Landing zone parent compartment." +} +#home_compartment_name + +variable "home_compartment_name" { + type = string + description = "the OCID of the compartment where the environment will be created. In general, this should be the Landing zone parent compartment." +} + +variable "environment_compartment_name" { + type = string + description = "The name of the compartment that acts as the main compartment for the environment. Resources related to this environment will be created under this compartment. " + default = "" +} + +variable "enable_tf_state_backup" { + type = bool + description = "Set to true to enable logging compartment which contains the bucket for the log files." + default = false +} + +variable "enable_logging" { + type = bool + description = "Set to true to enable logging compartment which stores the configuration information that landing zones is setting up for the customer." + default = false +} + +# ----------------------------------------------------------------------------- +# IAM Variables +# ----------------------------------------------------------------------------- +variable "domain_admin_email" { + type = string + description = "The email address for the identity domain admin." +} + +variable "network_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Landing Zone Network Administrators Group" +} + +variable "security_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Landing Zone Security Administrators Group" +} + +variable "iam_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Landing Zone IAM Administrators Group" +} + +variable "platform_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Landing Zone Platform Administrators Group" +} + +variable "ops_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Landing Zone Ops Administrators Group" +} + +variable "workload_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Workload Administrators Group" +} +variable "application_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Application Administrators Group" +} +variable "database_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Database Logging Administrators Group" +} + +# ----------------------------------------------------------------------------- +# Budget Variables +# ----------------------------------------------------------------------------- +variable "enable_budget" { + + type = bool +} + +variable "budget_amount" { + description = "The amount of the budget expressed as a whole number in the currency of the customer's rate card." + type = string + default = "" +} + +variable "budget_alert_rule_threshold" { + description = "The threshold for the budget alert." + type = string + default = "" +} + +variable "budget_alert_rule_message" { + description = "The alert message for budget alerts." + type = string + default = "" +} + +variable "budget_alert_rule_recipients" { + description = "The delimited list of email addresses to receive the alert when it triggers. Delimiter characters can be a comma, space, TAB, or semicolon" + type = string + default = "" +} + +# ----------------------------------------------------------------------------- +# Security Variables +# ----------------------------------------------------------------------------- +variable "enable_cloud_guard" { + type = bool + description = "true if you don't have cloud guard enabled, false if you've already have cloud guard enabled." +} + +variable "cloud_guard_target_tenancy" { + type = bool + description = "true if cloud guard targets to tenancy, false if cloud guard targets to Landing Zone home compartment" +} + +# ----------------------------------------------------------------------------- +# Tagging Variables +# ----------------------------------------------------------------------------- + +variable "enable_tagging" { + type = bool + description = "Set to true to enable Tagging." + default = false +} + +variable "cost_center_tagging" { + type = string + description = "Cost Center Varible" +} + +variable "geo_location_tagging" { + type = string + description = "Geo Location." +} + +variable "enable_bastion" { + type = bool + description = "Option to enable bastion service" +} + +variable "bastion_client_cidr_block_allow_list" { + type = list(string) + description = "A list of address ranges in CIDR notation that you want to allow to connect to sessions hosted by this bastion." +} + +variable "vault_type" { + type = string + description = "The type of vault to create. " +} + +variable "vault_replica_region" { + type = string + description = "the region to be created replica to." +} + +variable "enable_vault_replication" { + type = bool + description = "Option to enable vault replication" +} + +variable "create_master_encryption_key" { + type = bool + description = "Option create master encryption key" +} + +# ----------------------------------------------------------------------------- +# Network Variables +# ----------------------------------------------------------------------------- + +variable "enable_internet_gateway_hub" { + type = string + description = "Option to enable true and Disable false." +} +variable "enable_nat_gateway_hub" { + type = string + description = "Option to enable true and Disable false." +} + +variable "enable_service_gateway_hub" { + type = string + description = "Option to enable true and Disable false." +} + +variable "enable_nat_gateway_spoke" { + type = string + description = "Option to enable true and Disable false." +} + +variable "enable_service_gateway_spoke" { + type = string + description = "Option to enable true and Disable false." +} + +variable "igw_hub_check" { + type = list(string) +} +variable "nat_gw_hub_check" { + type = list(string) +} +variable "service_gw_hub_check" { + type = list(string) +} + +variable "nat_gw_spoke_check" { + type = list(string) +} + +variable "service_gw_spoke_check" { + type = list(string) +} + +variable "vcn_cidr_block" { + type = string + description = "Hub VCN CIDR Block." +} + +variable "public_subnet_cidr_block" { + type = string + description = "Hub Public Subnet CIDR Block." +} + +variable "private_subnet_cidr_block" { + type = string + description = "Hub Private Subnet CIDR Block." +} + +variable "private_spoke_subnet_web_cidr_block" { + type = string + description = "Spoke Web Subnet CIDR Block." +} +variable "private_spoke_subnet_app_cidr_block" { + type = string + description = "Spoke App Subnet CIDR Block." +} +variable "private_spoke_subnet_db_cidr_block" { + type = string + description = "Spoke DB Subnet CIDR Block." +} +variable "spoke_vcn_cidr" { + type = string + description = "Spoke VCN CIDR Block." +} + +# ----------------------------------------------------------------------------- +# Monitoring Variables +# ----------------------------------------------------------------------------- +variable "network_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Network Warning and Critical notifications." + validation { + condition = length( + [for e in var.network_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.network_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "secops_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Secops Warning and Critical notifications." + validation { + condition = length( + [for e in var.secops_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.secops_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "platform_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Platform notifications." + validation { + condition = length( + [for e in var.platform_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.platform_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "identity_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Identity notifications." + validation { + condition = length( + [for e in var.identity_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.identity_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "workload_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Workload notifications." + validation { + condition = length( + [for e in var.workload_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.workload_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "enable_security_monitoring_alarms" { + type = bool + description = "Enable Security Monitoring Alarms in Security Compartment" +} +variable "enable_network_monitoring_alarms" { + type = bool + description = "Enable Network Monitoring Alarms in Network Compartment" +} +variable "enable_workload_monitoring_alarms" { + type = bool + description = "Enable Workload Monitoring Alarms in Workload Compartment" +} diff --git a/templates/elz-environment/workload.tf b/templates/elz-environment/workload.tf new file mode 100644 index 00000000..ad73ca2e --- /dev/null +++ b/templates/elz-environment/workload.tf @@ -0,0 +1,33 @@ +# ----------------------------------------------------------------------------- +# Workload Resources +# ----------------------------------------------------------------------------- +locals { + workload = { + workload_name = "Workload1" + enable_compartment_delete = true + } +} + +module "workload" { + source = "../elz-workload" + + tenancy_ocid = var.tenancy_ocid + region = var.region + workload_name = local.workload.workload_name + enable_compartment_delete = local.workload.enable_compartment_delete + + environment_prefix = var.environment_prefix + environment_compartment_id = module.compartment.compartments.environment.id + security_compartment_id = module.compartment.compartments.security.id + network_compartment_id = module.compartment.compartments.network.id + workload_compartment_id = module.workload.compartment_id + + enable_security_monitoring_alarms = var.enable_security_monitoring_alarms + enable_network_monitoring_alarms = var.enable_network_monitoring_alarms + enable_workload_monitoring_alarms = var.enable_workload_monitoring_alarms + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} diff --git a/templates/elz-identity/README.md b/templates/elz-identity/README.md new file mode 100644 index 00000000..7c712e12 --- /dev/null +++ b/templates/elz-identity/README.md @@ -0,0 +1,70 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [oci](#requirement\_oci) | 4.96.0 | + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | 4.96.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [application\_admin\_policy](#module\_application\_admin\_policy) | ../../modules/policies | n/a | +| [db\_admin\_policy](#module\_db\_admin\_policy) | ../../modules/policies | n/a | +| [iam\_admin\_policy](#module\_iam\_admin\_policy) | ../../modules/policies | n/a | +| [iam\_admin\_root\_policy](#module\_iam\_admin\_root\_policy) | ../../modules/policies | n/a | +| [identity\_domain](#module\_identity\_domain) | ../../modules/identity-domain | n/a | +| [network\_admin\_policy](#module\_network\_admin\_policy) | ../../modules/policies | n/a | +| [ops\_admin\_policy](#module\_ops\_admin\_policy) | ../../modules/policies | n/a | +| [platform\_admin\_policy](#module\_platform\_admin\_policy) | ../../modules/policies | n/a | +| [platform\_admin\_root\_policy](#module\_platform\_admin\_root\_policy) | ../../modules/policies | n/a | +| [security\_admin\_net\_policy](#module\_security\_admin\_net\_policy) | ../../modules/policies | n/a | +| [security\_admin\_policy](#module\_security\_admin\_policy) | ../../modules/policies | n/a | +| [security\_admin\_root\_policy](#module\_security\_admin\_root\_policy) | ../../modules/policies | n/a | +| [security\_admin\_sec\_policy](#module\_security\_admin\_sec\_policy) | ../../modules/policies | n/a | +| [workload\_admin\_policy](#module\_workload\_admin\_policy) | ../../modules/policies | n/a | + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_region_subscriptions.regions](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/identity_region_subscriptions) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [application\_admin\_group\_name](#input\_application\_admin\_group\_name) | The group name for the OCI Application Administrators Group | `string` | `""` | no | +| [database\_admin\_group\_name](#input\_database\_admin\_group\_name) | The group name for the OCI Database Logging Administrators Group | `string` | `""` | no | +| [domain\_admin\_email](#input\_domain\_admin\_email) | The email address for the identity domain admin. | `string` | n/a | yes | +| [environment\_compartment\_id](#input\_environment\_compartment\_id) | n/a | `string` | n/a | yes | +| [environment\_compartment\_name](#input\_environment\_compartment\_name) | n/a | `string` | n/a | yes | +| [environment\_prefix](#input\_environment\_prefix) | the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U | `string` | n/a | yes | +| [iam\_admin\_group\_name](#input\_iam\_admin\_group\_name) | The group name for the OCI Landing Zone IAM Administrators Group | `string` | `""` | no | +| [network\_admin\_group\_name](#input\_network\_admin\_group\_name) | The group name for the OCI Landing Zone Network Administrators Group | `string` | `""` | no | +| [network\_compartment\_id](#input\_network\_compartment\_id) | n/a | `string` | n/a | yes | +| [network\_compartment\_name](#input\_network\_compartment\_name) | n/a | `string` | n/a | yes | +| [ops\_admin\_group\_name](#input\_ops\_admin\_group\_name) | The group name for the OCI Landing Zone Ops Administrators Group | `string` | `""` | no | +| [platform\_admin\_group\_name](#input\_platform\_admin\_group\_name) | The group name for the OCI Landing Zone Platform Administrators Group | `string` | `""` | no | +| [region](#input\_region) | The OCI region | `string` | n/a | yes | +| [security\_admin\_group\_name](#input\_security\_admin\_group\_name) | The group name for the OCI Landing Zone Security Administrators Group | `string` | `""` | no | +| [security\_compartment\_id](#input\_security\_compartment\_id) | n/a | `string` | n/a | yes | +| [security\_compartment\_name](#input\_security\_compartment\_name) | n/a | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | +| [workload\_admin\_group\_name](#input\_workload\_admin\_group\_name) | The group name for the OCI Workload Administrators Group | `string` | `""` | no | +| [workload\_compartment\_id](#input\_workload\_compartment\_id) | n/a | `string` | n/a | yes | +| [workload\_compartment\_name](#input\_workload\_compartment\_name) | The name of the workload compartment by default OCI-ELZ--. | `string` | `""` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [domain](#output\_domain) | n/a | + \ No newline at end of file diff --git a/templates/elz-identity/datasources.tf b/templates/elz-identity/datasources.tf new file mode 100644 index 00000000..3e483838 --- /dev/null +++ b/templates/elz-identity/datasources.tf @@ -0,0 +1,12 @@ +# ----------------------------------------------------------------------------- +# Support for multi-region deployments +# ----------------------------------------------------------------------------- +locals { + region_subscriptions = data.oci_identity_region_subscriptions.regions.region_subscriptions + home_region = [for region in local.region_subscriptions : region.region_name if region.is_home_region == true] + region_key = [for region in local.region_subscriptions : region.region_key if region.region_name == var.region] +} + +data "oci_identity_region_subscriptions" "regions" { + tenancy_id = var.tenancy_ocid +} diff --git a/templates/elz-identity/iam.tf b/templates/elz-identity/iam.tf new file mode 100644 index 00000000..31b8d7ad --- /dev/null +++ b/templates/elz-identity/iam.tf @@ -0,0 +1,330 @@ +# ----------------------------------------------------------------------------- +# Identity Domain Resources +# ----------------------------------------------------------------------------- +locals { + identity_domain = { + domain_display_name = "OCI-ELZ-${var.environment_prefix}-IDT" + domain_description = "OCI Landing Zone ${var.environment_prefix} Identity Domain" + domain_license_type = "PREMIUM" + domain_admin_user_name = "domainadmin" + domain_admin_first_name = "domain" + domain_admin_last_name = "admin" + domain_is_hidden_on_login = false + group_names = values(local.group_names) + } + + group_names = { + network_admin_group_name : var.network_admin_group_name != "" ? var.network_admin_group_name : "OCI-ELZ-UGP-${var.environment_prefix}-NET-ADMIN", + iam_admin_group_name : var.iam_admin_group_name != "" ? var.iam_admin_group_name : "OCI-ELZ-UGP-${var.environment_prefix}-IDP-ADMIN", + platform_admin_group_name : var.platform_admin_group_name != "" ? var.platform_admin_group_name : "OCI-ELZ-UGP-${var.environment_prefix}-PLT-ADMIN", + ops_admin_group_name : var.ops_admin_group_name != "" ? var.ops_admin_group_name : "OCI-ELZ-UGP-${var.environment_prefix}-OPS-ADMIN", + security_admin_group_name : var.security_admin_group_name != "" ? var.security_admin_group_name : "OCI-ELZ-UGP-${var.environment_prefix}-SEC-ADMIN", + workload_admin_group_name : var.workload_admin_group_name != "" ? var.workload_admin_group_name : "OCI-ELZ-UGP-${var.environment_prefix}-WRK-ADMIN", + application_admin_group_name : var.application_admin_group_name != "" ? var.application_admin_group_name : "OCI-ELZ-UGP-${var.environment_prefix}-APP-ADMIN", + database_admin_group_name : var.database_admin_group_name != "" ? var.database_admin_group_name : "OCI-ELZ-UGP-${var.environment_prefix}-DB-ADMIN", + } + + network_admin_policy = { + name = "OCI-ELZ-UGP-${var.environment_prefix}-NET-ADMIN-POLICY" + description = "OCI Landing Zone Network Administrators Group - manages all network resources" + + statements = [ + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["network_admin_group_name"]} to manage virtual-network-family in compartment ${var.network_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["network_admin_group_name"]} to manage load-balancers in compartment ${var.network_compartment_name}", + ] + } + + iam_admin_root_policy = { + name = "OCI-ELZ-UGP-${var.environment_prefix}-IDP-ADMIN-ROOT-POLICY" + description = "OCI Landing Zone IAM Group" + + statements = [ + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to manage tag-defaults in tenancy", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to manage tag-namespaces in tenancy", + ] + } + + iam_admin_policy = { + name = "OCI-ELZ-UGP-${var.environment_prefix}-IDP-ADMIN-POLICY" + description = "OCI Landing Zone IAM Group" + + statements = [ + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to inspect users in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to inspect groups in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to read policies in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to manage groups in compartment ${var.environment_compartment_name} where all {target.group.name != 'Administrators'}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to inspect identity-providers in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to manage identity-providers in compartment ${var.environment_compartment_name} where any {request.operation = 'AddIdpGroupMapping', request.operation = 'DeleteIdpGroupMapping'}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to manage dynamic-groups in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to manage authentication-policies in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to manage network-sources in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to manage quota in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to read audit-events in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to use cloud-shell in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to manage tag-defaults in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to manage tag-namespaces in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to manage users in compartment ${var.environment_compartment_name} where any {request.operation = 'ListApiKeys',request.operation = 'ListAuthTokens',request.operation = 'ListCustomerSecretKeys',request.operation = 'UploadApiKey',request.operation = 'DeleteApiKey',request.operation = 'UpdateAuthToken',request.operation = 'CreateAuthToken',request.operation = 'DeleteAuthToken',request.operation = 'CreateSecretKey',request.operation = 'UpdateCustomerSecretKey',request.operation = 'DeleteCustomerSecretKey',request.operation = 'UpdateUserCapabilities'}", + ] + } + + platform_admin_root_policy = { + name = "OCI-ELZ-UGP-${var.environment_prefix}-PLT-ADMIN-ROOT-POLICY" + description = "OCI Landing Zone Platform Admin Root Group" + + statements = [ + "Define tenancy usage-report as ocid1.tenancy.oc1..aaaaaaaaned4fkpkisbwjlr56u7cj63lf3wffbilvqknstgtvzub7vhqkggq", + "Endorse group ${local.identity_domain.domain_display_name}/${local.group_names["platform_admin_group_name"]} to read objects in tenancy usage-report", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["platform_admin_group_name"]} to manage usage-report in tenancy" + ] + } + + platform_admin_policy = { + name = "OCI-ELZ-UGP-${var.environment_prefix}-PLT-ADMIN-POLICY" + description = "OCI Landing Zone Platform Admin Group" + + statements = [ + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["platform_admin_group_name"]} to manage usage-report in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["platform_admin_group_name"]} to manage usage-budgets in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["platform_admin_group_name"]} to manage accountmanagement-family in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["platform_admin_group_name"]} to manage tickets in compartment ${var.environment_compartment_name}", + ] + } + + ops_admin_policy = { + name = "OCI-ELZ-UGP-${var.environment_prefix}-OPS-ADMIN-POLICY" + description = "OCI Landing Zone Ops Admin Group" + + statements = [ + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["ops_admin_group_name"]} to read metrics in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["ops_admin_group_name"]} to manage alarms in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["ops_admin_group_name"]} to manage ons-topics in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["ops_admin_group_name"]} to manage ons-subscriptions in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["ops_admin_group_name"]} to read announcements in compartment ${var.environment_compartment_name}", + ] + } + + security_admin_sec_policy = { + name = "OCI-ELZ-UGP-${var.environment_prefix}-SEC-ADMIN-SEC-POLICY" + description = "OCI Landing Zone Security Admin Group Security Compartment" + + statements = [ + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to use key-delegate in compartment ${var.security_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to manage vaults in compartment ${var.security_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to manage secret-family in compartment ${var.security_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to manage keys in compartment ${var.security_compartment_name}", + "Allow service blockstorage, objectstorage-${var.region}, FssOc1Prod, oke, streaming to use keys in compartment ${var.security_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to manage bastion in compartment ${var.security_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to manage bastion-session in compartment ${var.security_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to read vaults in compartment ${var.security_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to inspect keys in compartment ${var.security_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to read vss-family in compartment ${var.security_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to use bastion in compartment ${var.security_compartment_name}", + ] + } + + security_admin_net_policy = { + name = "OCI-ELZ-UGP-${var.environment_prefix}-SEC-ADMIN-NET-POLICY" + description = "OCI Landing Zone Security Admin Group Network Compartment" + + statements = [ + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to read virtual-network-family in compartment ${var.network_compartment_name}", + ] + } + + security_admin_policy = { + name = "OCI-ELZ-UGP-${var.environment_prefix}-SEC-ADMIN-POLICY" + description = "OCI Landing Zone Security Admin Group Environment Compartment" + + statements = [ + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to read instance-family in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to read instance-agent-plugins in compartment ${var.environment_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to inspect work-requests in compartment ${var.environment_compartment_name}", + ] + } + + security_admin_root_policy = { + name = "OCI-ELZ-UGP-${var.environment_prefix}-SEC-ADMIN-ROOT-POLICY" + description = "OCI Landing Zone Security Admin Group Root Compartment" + + statements = [ + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to manage vss-family in tenancy", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]} to manage cloud-guard-family in tenancy", + ] + } + + workload_admin_policy = { + name = "OCI-ELZ-UGP-${var.environment_prefix}-WRK-ADMIN-POLICY" + description = "OCI Landing Zone Workload Administrators Group" + + statements = [ + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["workload_admin_group_name"]} to read metrics in compartment ${var.workload_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["workload_admin_group_name"]} to manage alarms in compartment ${var.workload_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["workload_admin_group_name"]} to manage ons-topics in compartment ${var.workload_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["workload_admin_group_name"]} to manage ons-subscriptions in compartment ${var.workload_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["workload_admin_group_name"]} to read announcements in compartment ${var.workload_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["workload_admin_group_name"]} to manage logging-family in compartment ${var.workload_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["workload_admin_group_name"]} to manage streams in compartment ${var.workload_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["workload_admin_group_name"]} to read audit-events in compartment ${var.workload_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["workload_admin_group_name"]} to manage logging-family in compartment ${var.workload_compartment_name}", + ] + } + + application_admin_policy = { + name = "OCI-ELZ-UGP-${var.environment_prefix}-APP-ADMIN-POLICY" + description = "OCI Landing Zone Workload Application Group" + + statements = [ + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["application_admin_group_name"]} to manage load-balancers in compartment ${var.workload_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["application_admin_group_name"]} to manage volume-family in compartment ${var.workload_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["application_admin_group_name"]} to manage object-family in compartment ${var.workload_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["application_admin_group_name"]} to manage file-family in compartment ${var.workload_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["application_admin_group_name"]} to manage instance-family in compartment ${var.workload_compartment_name}", + ] + } + + database_admin_policy = { + name = "OCI-ELZ-UGP-${var.environment_prefix}-DB-ADMIN-POLICY" + description = "OCI Landing Zone Workload Database Group" + + statements = [ + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["database_admin_group_name"]} to read autonomous-database-family in compartment ${var.workload_compartment_name}", + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["database_admin_group_name"]} to read database-family in compartment ${var.workload_compartment_name}", + ] + } + + announcement_subscription_policy = { + name = "OCI-ELZ-UGP-${var.environment_prefix}-ANNOUNCEMENT-POLICY" + description = "OCI Landing Zone Announcement Permission Policy" + + statements = [ + "Allow group ${local.identity_domain.domain_display_name}/${local.group_names["network_admin_group_name"]}, ${local.identity_domain.domain_display_name}/${local.group_names["security_admin_group_name"]}, ${local.identity_domain.domain_display_name}/${local.group_names["platform_admin_group_name"]}, ${local.identity_domain.domain_display_name}/${local.group_names["iam_admin_group_name"]} to manage announcement-subscriptions in compartment ${var.environment_compartment_name}" + ] + } +} + +module "identity_domain" { + source = "../../modules/identity-domain" + compartment_id = var.security_compartment_id + domain_description = local.identity_domain.domain_description + domain_display_name = local.identity_domain.domain_display_name + domain_home_region = var.region + domain_license_type = local.identity_domain.domain_license_type + domain_admin_email = var.domain_admin_email + domain_admin_user_name = local.identity_domain.domain_admin_user_name + domain_admin_first_name = local.identity_domain.domain_admin_first_name + domain_admin_last_name = local.identity_domain.domain_admin_last_name + domain_is_hidden_on_login = local.identity_domain.domain_is_hidden_on_login + group_names = local.identity_domain.group_names +} + +module "network_admin_policy" { + source = "../../modules/policies" + compartment_ocid = var.network_compartment_id + policy_name = local.network_admin_policy.name + description = local.network_admin_policy.description + statements = local.network_admin_policy.statements +} + +module "iam_admin_policy" { + source = "../../modules/policies" + compartment_ocid = var.environment_compartment_id + policy_name = local.iam_admin_policy.name + description = local.iam_admin_policy.description + statements = local.iam_admin_policy.statements +} + +module "iam_admin_root_policy" { + source = "../../modules/policies" + compartment_ocid = var.tenancy_ocid + policy_name = local.iam_admin_root_policy.name + description = local.iam_admin_root_policy.description + statements = local.iam_admin_root_policy.statements +} + +module "platform_admin_policy" { + source = "../../modules/policies" + compartment_ocid = var.environment_compartment_id + policy_name = local.platform_admin_policy.name + description = local.platform_admin_policy.description + statements = local.platform_admin_policy.statements +} + +module "platform_admin_root_policy" { + source = "../../modules/policies" + compartment_ocid = var.tenancy_ocid + policy_name = local.platform_admin_root_policy.name + description = local.platform_admin_root_policy.description + statements = local.platform_admin_root_policy.statements +} + +module "ops_admin_policy" { + source = "../../modules/policies" + compartment_ocid = var.environment_compartment_id + policy_name = local.ops_admin_policy.name + description = local.ops_admin_policy.description + statements = local.ops_admin_policy.statements +} + +module "security_admin_sec_policy" { + source = "../../modules/policies" + compartment_ocid = var.security_compartment_id + policy_name = local.security_admin_sec_policy.name + description = local.security_admin_sec_policy.description + statements = local.security_admin_sec_policy.statements +} + +module "security_admin_net_policy" { + source = "../../modules/policies" + compartment_ocid = var.network_compartment_id + policy_name = local.security_admin_net_policy.name + description = local.security_admin_net_policy.description + statements = local.security_admin_net_policy.statements +} + +module "security_admin_policy" { + source = "../../modules/policies" + compartment_ocid = var.environment_compartment_id + policy_name = local.security_admin_policy.name + description = local.security_admin_policy.description + statements = local.security_admin_policy.statements +} + +module "security_admin_root_policy" { + source = "../../modules/policies" + compartment_ocid = var.tenancy_ocid + policy_name = local.security_admin_root_policy.name + description = local.security_admin_root_policy.description + statements = local.security_admin_root_policy.statements +} + +module "workload_admin_policy" { + source = "../../modules/policies" + compartment_ocid = var.workload_compartment_id + policy_name = local.workload_admin_policy.name + description = local.workload_admin_policy.description + statements = local.workload_admin_policy.statements +} + +module "application_admin_policy" { + source = "../../modules/policies" + compartment_ocid = var.workload_compartment_id + policy_name = local.application_admin_policy.name + description = local.application_admin_policy.description + statements = local.application_admin_policy.statements +} + +module "db_admin_policy" { + source = "../../modules/policies" + compartment_ocid = var.workload_compartment_id + policy_name = local.database_admin_policy.name + description = local.database_admin_policy.description + statements = local.database_admin_policy.statements +} + +# module "announcement_subscription_policy" { +# source = "../../modules/policies" +# compartment_ocid = var.environment_compartment_id +# policy_name = local.announcement_subscription_policy.name +# description = local.announcement_subscription_policy.description +# statements = local.announcement_subscription_policy.statements +# } diff --git a/templates/elz-identity/outputs.tf b/templates/elz-identity/outputs.tf new file mode 100644 index 00000000..d105cbca --- /dev/null +++ b/templates/elz-identity/outputs.tf @@ -0,0 +1,3 @@ +output "domain" { + value = module.identity_domain.domain +} diff --git a/templates/elz-identity/provider.tf b/templates/elz-identity/provider.tf new file mode 100644 index 00000000..2bbda84d --- /dev/null +++ b/templates/elz-identity/provider.tf @@ -0,0 +1,72 @@ +# ----------------------------------------------------------------------------- +# Provider Requirements if using stack as a module +# ----------------------------------------------------------------------------- +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + version = "4.96.0" # October 05, 2022 Release + configuration_aliases = [oci, oci.home_region] + } + } +} + +# # ----------------------------------------------------------------------------- +# # WARNING! +# # UNCOMMENT EVERYTHING BELOW AND COMMENT EVERYTHING ABOVE IF YOU WISH TO USE THIS +# # STACK AS A STANDALONE - DO NOT TOUCH IF USING THIS STACK IN A MODULE CALL +# # Provider Requirements if using stack as standalone +# # ----------------------------------------------------------------------------- +# terraform { +# required_version = ">= 1.0.0" + +# required_providers { +# oci = { +# source = "oracle/oci" +# version = "4.96.0" # October 05, 2022 Release +# } +# } +# } + +# # ----------------------------------------------------------------------------- +# # Provider blocks for home region and alternate region(s) +# # ----------------------------------------------------------------------------- +# provider "oci" { +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = var.region +# } + +# provider "oci" { +# alias = "home_region" +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = local.home_region[0] +# } + +# # ----------------------------------------------------------------------------- +# # Provider Variables +# # ----------------------------------------------------------------------------- +# variable "current_user_ocid" { +# type = string +# description = "The OCID of the current user" +# default = "" +# } + +# variable "api_fingerprint" { +# type = string +# description = "The fingerprint of API" +# default = "" +# } + +# variable "api_private_key_path" { +# type = string +# description = "The local path to the API private key" +# default = "" +# } diff --git a/templates/elz-identity/variables.tf b/templates/elz-identity/variables.tf new file mode 100644 index 00000000..33af6cc6 --- /dev/null +++ b/templates/elz-identity/variables.tf @@ -0,0 +1,112 @@ +# ----------------------------------------------------------------------------- +# Common Variables +# ----------------------------------------------------------------------------- +variable "tenancy_ocid" { + type = string + description = "The OCID of tenancy" +} + +variable "region" { + type = string + description = "The OCI region" +} + +variable "environment_prefix" { + type = string + description = "the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U" +} + +# ----------------------------------------------------------------------------- +# Policy Variables +# ----------------------------------------------------------------------------- +variable "domain_admin_email" { + type = string + description = "The email address for the identity domain admin." +} + +variable "environment_compartment_name" { + type = string + +} + +variable "environment_compartment_id" { + type = string + +} + +variable "network_compartment_id" { + type = string + +} + +variable "network_compartment_name" { + type = string + +} + +variable "network_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Landing Zone Network Administrators Group" +} + +variable "security_compartment_id" { + type = string + +} +variable "workload_compartment_id" { + type = string + +} +variable "security_compartment_name" { + type = string + +} + +variable "security_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Landing Zone Security Administrators Group" +} + +variable "iam_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Landing Zone IAM Administrators Group" +} + +variable "platform_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Landing Zone Platform Administrators Group" +} + +variable "ops_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Landing Zone Ops Administrators Group" +} + +variable "workload_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Workload Administrators Group" +} + +variable "application_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Application Administrators Group" +} + +variable "database_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Database Logging Administrators Group" +} + +variable "workload_compartment_name" { + type = string + description = "The name of the workload compartment by default OCI-ELZ--." + default = "" +} diff --git a/templates/elz-logging/README.md b/templates/elz-logging/README.md new file mode 100644 index 00000000..27eb3dfb --- /dev/null +++ b/templates/elz-logging/README.md @@ -0,0 +1,66 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [oci](#requirement\_oci) | 4.96.0 | + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | 4.96.0 | +| [time](#provider\_time) | n/a | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [audit\_log\_bucket](#module\_audit\_log\_bucket) | ../../modules/bucket | n/a | +| [audit\_log\_service\_connector](#module\_audit\_log\_service\_connector) | ../../modules/service-connector | n/a | +| [default\_log\_bucket](#module\_default\_log\_bucket) | ../../modules/bucket | n/a | +| [default\_log\_group](#module\_default\_log\_group) | ../../modules/log-group | n/a | +| [default\_log\_service\_connector](#module\_default\_log\_service\_connector) | ../../modules/service-connector | n/a | +| [event\_log](#module\_event\_log) | ../../modules/service-log | n/a | +| [os\_read\_log](#module\_os\_read\_log) | ../../modules/service-log | n/a | +| [os\_write\_log](#module\_os\_write\_log) | ../../modules/service-log | n/a | +| [service\_event\_log\_bucket](#module\_service\_event\_log\_bucket) | ../../modules/bucket | n/a | +| [service\_event\_stream](#module\_service\_event\_stream) | ../../modules/stream | n/a | +| [service\_events\_service\_connector](#module\_service\_events\_service\_connector) | ../../modules/service-connector | n/a | +| [vcn\_flow\_log](#module\_vcn\_flow\_log) | ../../modules/service-log | n/a | + +## Resources + +| Name | Type | +|------|------| +| [time_sleep.first_log_delay](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [oci_events_rules.security_event_rules](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/events_rules) | data source | +| [oci_identity_region_subscriptions.regions](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/identity_region_subscriptions) | data source | +| [oci_objectstorage_namespace.ns](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/objectstorage_namespace) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [environment\_prefix](#input\_environment\_prefix) | the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U | `string` | n/a | yes | +| [home\_compartment\_id](#input\_home\_compartment\_id) | The id of the home compartment. | `string` | n/a | yes | +| [home\_compartment\_name](#input\_home\_compartment\_name) | The name of the home compartment. | `string` | n/a | yes | +| [logging\_compartment\_id](#input\_logging\_compartment\_id) | The ocid of the logging compartment. | `string` | n/a | yes | +| [master\_encryption\_key](#input\_master\_encryption\_key) | The ocid of master encryption key | `string` | n/a | yes | +| [region](#input\_region) | The OCI region | `string` | n/a | yes | +| [resource\_label](#input\_resource\_label) | Prefix used to avoid naming conflict | `string` | n/a | yes | +| [retention\_policy\_duration\_amount](#input\_retention\_policy\_duration\_amount) | The timeAmount is interpreted in units defined by the timeUnit parameter, and is calculated in relation to each object's Last-Modified timestamp. | `string` | n/a | yes | +| [retention\_policy\_duration\_time\_unit](#input\_retention\_policy\_duration\_time\_unit) | The unit that should be used to interpret timeAmount. | `string` | n/a | yes | +| [security\_compartment\_id](#input\_security\_compartment\_id) | The ocid of the security compartment. | `string` | n/a | yes | +| [subnets\_map](#input\_subnets\_map) | n/a | `map(string)` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [bucket](#output\_bucket) | n/a | +| [log\_group\_id](#output\_log\_group\_id) | n/a | +| [stream\_id](#output\_stream\_id) | n/a | + \ No newline at end of file diff --git a/templates/elz-logging/datasources.tf b/templates/elz-logging/datasources.tf new file mode 100644 index 00000000..dd76e547 --- /dev/null +++ b/templates/elz-logging/datasources.tf @@ -0,0 +1,23 @@ +# ----------------------------------------------------------------------------- +# Support for multi-region deployments +# ----------------------------------------------------------------------------- +locals { + region_subscriptions = data.oci_identity_region_subscriptions.regions.region_subscriptions + home_region = [for region in local.region_subscriptions : region.region_name if region.is_home_region == true] + region_key = [for region in local.region_subscriptions : region.region_key if region.region_name == var.region] +} + +data "oci_identity_region_subscriptions" "regions" { + tenancy_id = var.tenancy_ocid +} + +data "oci_events_rules" "security_event_rules" { + compartment_id = var.security_compartment_id + + depends_on = [ module.default_log_group, module.service_event_stream ] +} + +data "oci_objectstorage_namespace" "ns" { + compartment_id = var.tenancy_ocid +} + diff --git a/templates/elz-logging/main.tf b/templates/elz-logging/main.tf new file mode 100644 index 00000000..963b1f9a --- /dev/null +++ b/templates/elz-logging/main.tf @@ -0,0 +1,281 @@ +locals { + default_log_group = { + name = "Default_Group" + description = "Default log group for ${var.home_compartment_name}" + } + + service_event_stream = { + stream_pool_name = "services-events-pool" + stream_name = "serviceEvents" + stream_partitions = 1 + rule_action_type = "OSS" + rule_action_is_enabled = true + rule_condition = "{ }" // MATCH ALL EVENTS IN THIS COMPARTMENT HIERARCHY + rule_display_name = "All events in ${var.home_compartment_name}" + rule_is_enabled = true + } + + audit_log_bucket = { + name = "${var.resource_label}_${var.environment_prefix}_auditLogs_standard" + description = "Audit Log bucket" + retention_rule_display_name = "audit log bucket retention rule" + retention_policy_duration_amount = var.retention_policy_duration_amount + retention_policy_duration_time_unit = var.retention_policy_duration_time_unit + bucket_storage_tier = "Standard" + } + + default_log_bucket = { + name = "${var.resource_label}_${var.environment_prefix}_defaultLogs_standard" + description = "Default Log bucket" + retention_rule_display_name = "default log bucket retention rule" + retention_policy_duration_amount = var.retention_policy_duration_amount + retention_policy_duration_time_unit = var.retention_policy_duration_time_unit + bucket_storage_tier = "Standard" + } + + service_event_log_bucket = { + name = "${var.resource_label}_${var.environment_prefix}_serviceEvents_standard" + description = "Service Events Log bucket" + retention_rule_display_name = "service events log bucket retention rule" + retention_policy_duration_amount = var.retention_policy_duration_amount + retention_policy_duration_time_unit = var.retention_policy_duration_time_unit + bucket_storage_tier = "Standard" + } + + audit_log_service_connector = { + display_name = "${var.resource_label}_schAuditLog_standard_${var.environment_prefix}" + source_kind = "logging" + target_kind = "objectStorage" + log_group_id = "_Audit_Include_Subcompartment" + target_bucket = local.audit_log_bucket.name + } + + default_log_service_connector = { + display_name = "${var.resource_label}_schDefaultLog_standard_${var.environment_prefix}" + source_kind = "logging" + target_kind = "objectStorage" + target_bucket = local.default_log_bucket.name + } + + service_events_service_connector = { + display_name = "${var.resource_label}_schServiceEvents_standard_${var.environment_prefix}" + source_kind = "streaming" + target_kind = "objectStorage" + target_bucket = local.service_event_log_bucket.name + cursor_kind = "TRIM_HORIZON" + } + + buckets_map = { + DEFAULT : "${var.resource_label}_${var.environment_prefix}_defaultLogs_standard", + AUDIT: "${var.resource_label}_${var.environment_prefix}_auditLogs_standard", + SERVICE_EVENT: "${var.resource_label}_${var.environment_prefix}_serviceEvents_standard" + } + + os_read_log = { + log_display_name = "${var.resource_label}-OCI-ELZ-OS-READ-LOG-${var.environment_prefix}" + log_type = "SERVICE" + log_source_category = "read" + log_source_service = "objectstorage" + log_source_type = "OCISERVICE" + } + + os_write_log = { + log_display_name = "${var.resource_label}-OCI-ELZ-OS-WRITE-LOG-${var.environment_prefix}" + log_type = "SERVICE" + log_source_category = "write" + log_source_service = "objectstorage" + log_source_type = "OCISERVICE" + } + + subnets_map = { + HUB1: var.subnets_map["OCI-ELZ-SUB-${var.environment_prefix}-HUB-${local.region_key[0]}001"] + HUB2: var.subnets_map["OCI-ELZ-SUB-${var.environment_prefix}-HUB-${local.region_key[0]}002"] + SKP1: var.subnets_map["OCI-ELZ-SUB-${var.environment_prefix}-SPK-${local.region_key[0]}001"] + SKP2: var.subnets_map["OCI-ELZ-SUB-${var.environment_prefix}-SPK-${local.region_key[0]}002"] + SKP3: var.subnets_map["OCI-ELZ-SUB-${var.environment_prefix}-SPK-${local.region_key[0]}003"] + } + + vcn_flow_log = { + log_display_name = "${var.resource_label}-OCI-ELZ-VCN-FLOW-LOG-${var.environment_prefix}" + log_type = "SERVICE" + log_source_category = "all" + log_source_service = "flowlogs" + log_source_type = "OCISERVICE" + } + + events_map = { + security : data.oci_events_rules.security_event_rules.rules[0].id # All event in the LZ home compartment + } + + event_log = { + log_display_name = "${var.resource_label}-OCI-ELZ-EVENT-LOG-${var.environment_prefix}" + log_type = "SERVICE" + log_source_category = "ruleexecutionlog" + log_source_service = "cloudevents" + log_source_type = "OCISERVICE" + } + +} + +module "default_log_group" { + source = "../../modules/log-group" + compartment_id = var.security_compartment_id + display_name = local.default_log_group.name + description = local.default_log_group.description +} + +module "service_event_stream" { + source = "../../modules/stream" + compartment_id = var.security_compartment_id + stream_pool_name = local.service_event_stream.stream_pool_name + stream_name = local.service_event_stream.stream_name + kms_key_id = var.master_encryption_key + stream_partitions = local.service_event_stream.stream_partitions + rule_action_type = local.service_event_stream.rule_action_type + rule_action_is_enabled = local.service_event_stream.rule_action_is_enabled + rule_condition = local.service_event_stream.rule_condition + rule_display_name = local.service_event_stream.rule_display_name + rule_is_enabled = local.service_event_stream.rule_is_enabled +} + +module "audit_log_bucket" { + source = "../../modules/bucket" + tenancy_ocid = var.tenancy_ocid + compartment_id = var.logging_compartment_id + name = local.audit_log_bucket.name + kms_key_id = var.master_encryption_key + storage_tier = local.audit_log_bucket.bucket_storage_tier + retention_rule_display_name = local.audit_log_bucket.retention_rule_display_name + retention_policy_duration_amount = local.audit_log_bucket.retention_policy_duration_amount + retention_policy_duration_time_unit = local.audit_log_bucket.retention_policy_duration_time_unit + namespace = data.oci_objectstorage_namespace.ns.namespace +} + +module "default_log_bucket" { + source = "../../modules/bucket" + tenancy_ocid = var.tenancy_ocid + compartment_id = var.logging_compartment_id + name = local.default_log_bucket.name + kms_key_id = var.master_encryption_key + storage_tier = local.default_log_bucket.bucket_storage_tier + retention_rule_display_name = local.default_log_bucket.retention_rule_display_name + retention_policy_duration_amount = local.default_log_bucket.retention_policy_duration_amount + retention_policy_duration_time_unit = local.default_log_bucket.retention_policy_duration_time_unit + namespace = data.oci_objectstorage_namespace.ns.namespace +} + +module "service_event_log_bucket" { + source = "../../modules/bucket" + tenancy_ocid = var.tenancy_ocid + compartment_id = var.logging_compartment_id + name = local.service_event_log_bucket.name + kms_key_id = var.master_encryption_key + storage_tier = local.service_event_log_bucket.bucket_storage_tier + retention_rule_display_name = local.service_event_log_bucket.retention_rule_display_name + retention_policy_duration_amount = local.service_event_log_bucket.retention_policy_duration_amount + retention_policy_duration_time_unit = local.service_event_log_bucket.retention_policy_duration_time_unit + namespace = data.oci_objectstorage_namespace.ns.namespace +} + +module "audit_log_service_connector" { + source = "../../modules/service-connector" + tenancy_ocid = var.tenancy_ocid + compartment_id = var.security_compartment_id + source_compartment_id = var.home_compartment_id + display_name = local.audit_log_service_connector.display_name + source_kind = local.audit_log_service_connector.source_kind + target_kind = local.audit_log_service_connector.target_kind + log_group_id = local.audit_log_service_connector.log_group_id + target_bucket = local.audit_log_service_connector.target_bucket + + depends_on = [module.audit_log_bucket] +} + +module "default_log_service_connector" { + source = "../../modules/service-connector" + tenancy_ocid = var.tenancy_ocid + compartment_id = var.security_compartment_id + source_compartment_id = var.security_compartment_id + display_name = local.default_log_service_connector.display_name + source_kind = local.default_log_service_connector.source_kind + target_kind = local.default_log_service_connector.target_kind + log_group_id = module.default_log_group.log_group_id + target_bucket = local.default_log_service_connector.target_bucket + # Service connector needs at least one log on the log group, or it errors. + # Also it takes time for it to recognize this. + depends_on = [module.default_log_bucket, module.default_log_group, time_sleep.first_log_delay] +} + + +module "service_events_service_connector" { + source = "../../modules/service-connector" + tenancy_ocid = var.tenancy_ocid + compartment_id = var.security_compartment_id + source_compartment_id = var.security_compartment_id + display_name = local.service_events_service_connector.display_name + source_kind = local.service_events_service_connector.source_kind + target_kind = local.service_events_service_connector.target_kind + stream_id = module.service_event_stream.stream_id + cursor_kind = local.service_events_service_connector.cursor_kind + target_bucket = local.service_events_service_connector.target_bucket + + depends_on = [module.service_event_log_bucket] +} + +resource "time_sleep" "first_log_delay" { + create_duration = "600s" +} + +module "os_read_log" { + source = "../../modules/service-log" + + service_log_map = local.buckets_map + log_display_name = local.os_read_log.log_display_name + log_type = local.os_read_log.log_type + log_group_id = module.default_log_group.log_group_id + log_source_category = local.os_read_log.log_source_category + log_source_service = local.os_read_log.log_source_service + log_source_type = local.os_read_log.log_source_type + + depends_on = [ module.audit_log_bucket, module.default_log_bucket, module.service_event_log_bucket, module.default_log_group ] +} + +module "os_write_log" { + source = "../../modules/service-log" + + service_log_map = local.buckets_map + log_display_name = local.os_write_log.log_display_name + log_type = local.os_write_log.log_type + log_group_id = module.default_log_group.log_group_id + log_source_category = local.os_write_log.log_source_category + log_source_service = local.os_write_log.log_source_service + log_source_type = local.os_write_log.log_source_type + + depends_on = [ module.audit_log_bucket, module.default_log_bucket, module.service_event_log_bucket, module.default_log_group ] +} + + +module "vcn_flow_log" { + source = "../../modules/service-log" + + service_log_map = local.subnets_map + log_display_name = local.vcn_flow_log.log_display_name + log_type = local.vcn_flow_log.log_type + log_group_id = module.default_log_group.log_group_id + log_source_category = local.vcn_flow_log.log_source_category + log_source_service = local.vcn_flow_log.log_source_service + log_source_type = local.vcn_flow_log.log_source_type +} + +module "event_log" { + source = "../../modules/service-log" + + service_log_map = local.events_map + log_display_name = local.event_log.log_display_name + log_type = local.event_log.log_type + log_group_id = module.default_log_group.log_group_id + log_source_category = local.event_log.log_source_category + log_source_service = local.event_log.log_source_service + log_source_type = local.event_log.log_source_type +} + diff --git a/templates/elz-logging/outputs.tf b/templates/elz-logging/outputs.tf new file mode 100644 index 00000000..ed83e89d --- /dev/null +++ b/templates/elz-logging/outputs.tf @@ -0,0 +1,19 @@ +output "log_group_id" { + value = module.default_log_group.log_group_id +} + +output "stream_id" { + value = module.service_event_stream.stream_id +} + +locals { + standard_buckets_map = { + "audit" : module.audit_log_bucket + "default": module.default_log_bucket + "service_event": module.service_event_log_bucket + } +} + +output "bucket" { + value = local.standard_buckets_map +} diff --git a/templates/elz-logging/providers.tf b/templates/elz-logging/providers.tf new file mode 100644 index 00000000..2bbda84d --- /dev/null +++ b/templates/elz-logging/providers.tf @@ -0,0 +1,72 @@ +# ----------------------------------------------------------------------------- +# Provider Requirements if using stack as a module +# ----------------------------------------------------------------------------- +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + version = "4.96.0" # October 05, 2022 Release + configuration_aliases = [oci, oci.home_region] + } + } +} + +# # ----------------------------------------------------------------------------- +# # WARNING! +# # UNCOMMENT EVERYTHING BELOW AND COMMENT EVERYTHING ABOVE IF YOU WISH TO USE THIS +# # STACK AS A STANDALONE - DO NOT TOUCH IF USING THIS STACK IN A MODULE CALL +# # Provider Requirements if using stack as standalone +# # ----------------------------------------------------------------------------- +# terraform { +# required_version = ">= 1.0.0" + +# required_providers { +# oci = { +# source = "oracle/oci" +# version = "4.96.0" # October 05, 2022 Release +# } +# } +# } + +# # ----------------------------------------------------------------------------- +# # Provider blocks for home region and alternate region(s) +# # ----------------------------------------------------------------------------- +# provider "oci" { +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = var.region +# } + +# provider "oci" { +# alias = "home_region" +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = local.home_region[0] +# } + +# # ----------------------------------------------------------------------------- +# # Provider Variables +# # ----------------------------------------------------------------------------- +# variable "current_user_ocid" { +# type = string +# description = "The OCID of the current user" +# default = "" +# } + +# variable "api_fingerprint" { +# type = string +# description = "The fingerprint of API" +# default = "" +# } + +# variable "api_private_key_path" { +# type = string +# description = "The local path to the API private key" +# default = "" +# } diff --git a/templates/elz-logging/variables.tf b/templates/elz-logging/variables.tf new file mode 100644 index 00000000..9de4e7be --- /dev/null +++ b/templates/elz-logging/variables.tf @@ -0,0 +1,59 @@ +variable "region" { + type = string + description = "The OCI region" +} + +variable "environment_prefix" { + type = string + description = "the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U" +} + +variable "security_compartment_id" { + type = string + description = " The ocid of the security compartment." +} + +variable "home_compartment_name" { + type = string + description = " The name of the home compartment." +} + +variable "home_compartment_id" { + type = string + description = " The id of the home compartment." +} + +variable "master_encryption_key" { + type = string + description = "The ocid of master encryption key" +} + +variable "logging_compartment_id" { + type = string + description = " The ocid of the logging compartment." +} + +variable "tenancy_ocid" { + type = string + description = "The OCID of tenancy" +} + +variable "resource_label" { + type = string + description = "Prefix used to avoid naming conflict" +} + +variable "retention_policy_duration_amount" { + type = string + description = "The timeAmount is interpreted in units defined by the timeUnit parameter, and is calculated in relation to each object's Last-Modified timestamp." +} + +variable "retention_policy_duration_time_unit" { + type = string + description = "The unit that should be used to interpret timeAmount." +} + +variable "subnets_map" { + type = map(string) + description = "" +} diff --git a/templates/elz-monitoring/README.md b/templates/elz-monitoring/README.md new file mode 100644 index 00000000..0e747d3f --- /dev/null +++ b/templates/elz-monitoring/README.md @@ -0,0 +1,69 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [oci](#requirement\_oci) | 4.96.0 | + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | 4.96.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [alarm\_policy](#module\_alarm\_policy) | ../../modules/policies | n/a | +| [announcement\_subscription](#module\_announcement\_subscription) | ../../modules/announcement-subscription | n/a | +| [budget\_warning\_topic](#module\_budget\_warning\_topic) | ../../modules/notification-topic | n/a | +| [iam\_warning\_topic](#module\_iam\_warning\_topic) | ../../modules/notification-topic | n/a | +| [logging\_analytics\_audit](#module\_logging\_analytics\_audit) | ../../modules/log-analytics | n/a | +| [logging\_analytics\_default](#module\_logging\_analytics\_default) | ../../modules/log-analytics | n/a | +| [network\_alarms\_critical](#module\_network\_alarms\_critical) | ../../modules/alarms | n/a | +| [network\_alarms\_warning](#module\_network\_alarms\_warning) | ../../modules/alarms | n/a | +| [network\_critical\_topic](#module\_network\_critical\_topic) | ../../modules/notification-topic | n/a | +| [network\_warning\_topic](#module\_network\_warning\_topic) | ../../modules/notification-topic | n/a | +| [security\_alarms\_critical](#module\_security\_alarms\_critical) | ../../modules/alarms | n/a | +| [security\_alarms\_warning](#module\_security\_alarms\_warning) | ../../modules/alarms | n/a | +| [security\_critical\_topic](#module\_security\_critical\_topic) | ../../modules/notification-topic | n/a | +| [security\_warning\_topic](#module\_security\_warning\_topic) | ../../modules/notification-topic | n/a | +| [workload\_alarms\_critical](#module\_workload\_alarms\_critical) | ../../modules/alarms | n/a | +| [workload\_alarms\_warning](#module\_workload\_alarms\_warning) | ../../modules/alarms | n/a | +| [workload\_critical\_topic](#module\_workload\_critical\_topic) | ../../modules/notification-topic | n/a | +| [workload\_warning\_topic](#module\_workload\_warning\_topic) | ../../modules/notification-topic | n/a | + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_region_subscriptions.regions](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/identity_region_subscriptions) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [default\_log\_group\_id](#input\_default\_log\_group\_id) | n/a | `string` | n/a | yes | +| [enable\_network\_monitoring\_alarms](#input\_enable\_network\_monitoring\_alarms) | Enable Network Monitoring Alarms in Network Compartment | `bool` | n/a | yes | +| [enable\_security\_monitoring\_alarms](#input\_enable\_security\_monitoring\_alarms) | Enable Security Monitoring Alarms in Security Compartment | `bool` | n/a | yes | +| [enable\_workload\_monitoring\_alarms](#input\_enable\_workload\_monitoring\_alarms) | Enable Workload Monitoring Alarms in Workload Compartment | `bool` | n/a | yes | +| [environment\_compartment\_id](#input\_environment\_compartment\_id) | ----------------------------------------------------------------------------- Common Variables ----------------------------------------------------------------------------- | `string` | n/a | yes | +| [environment\_prefix](#input\_environment\_prefix) | the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U | `string` | n/a | yes | +| [identity\_topic\_endpoints](#input\_identity\_topic\_endpoints) | List of email addresses for Identity notifications. | `list(string)` | `[]` | no | +| [network\_compartment\_id](#input\_network\_compartment\_id) | n/a | `string` | n/a | yes | +| [network\_topic\_endpoints](#input\_network\_topic\_endpoints) | List of email addresses for Network Warning and Critical notifications. | `list(string)` | `[]` | no | +| [platform\_topic\_endpoints](#input\_platform\_topic\_endpoints) | List of email addresses for Platform notifications. | `list(string)` | `[]` | no | +| [region](#input\_region) | The OCI region | `string` | n/a | yes | +| [resource\_label](#input\_resource\_label) | Prefix used to avoid naming conflict | `string` | n/a | yes | +| [secops\_topic\_endpoints](#input\_secops\_topic\_endpoints) | List of email addresses for Secops Warning and Critical notifications. | `list(string)` | `[]` | no | +| [security\_compartment\_id](#input\_security\_compartment\_id) | n/a | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | +| [workload\_compartment\_id](#input\_workload\_compartment\_id) | n/a | `string` | n/a | yes | +| [workload\_topic\_endpoints](#input\_workload\_topic\_endpoints) | List of email addresses for Workload notifications. | `list(string)` | `[]` | no | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/templates/elz-monitoring/datasources.tf b/templates/elz-monitoring/datasources.tf new file mode 100644 index 00000000..3e483838 --- /dev/null +++ b/templates/elz-monitoring/datasources.tf @@ -0,0 +1,12 @@ +# ----------------------------------------------------------------------------- +# Support for multi-region deployments +# ----------------------------------------------------------------------------- +locals { + region_subscriptions = data.oci_identity_region_subscriptions.regions.region_subscriptions + home_region = [for region in local.region_subscriptions : region.region_name if region.is_home_region == true] + region_key = [for region in local.region_subscriptions : region.region_key if region.region_name == var.region] +} + +data "oci_identity_region_subscriptions" "regions" { + tenancy_id = var.tenancy_ocid +} diff --git a/templates/elz-monitoring/main.tf b/templates/elz-monitoring/main.tf new file mode 100644 index 00000000..509201b4 --- /dev/null +++ b/templates/elz-monitoring/main.tf @@ -0,0 +1,718 @@ +locals { + network_critical_topic = { + topic_name = "${var.environment_prefix}-Network-Critical-${var.resource_label}" + topic_description = "OCI Landing Zone Critical Network Topic" + subscription_protocol = "EMAIL" + } + + network_warning_topic = { + topic_name = "${var.environment_prefix}-Network-Warning-${var.resource_label}" + topic_description = "OCI Landing Zone Warning Network Topic" + subscription_protocol = "EMAIL" + event_rules = { + lzNetWarning = { + rule_condition = < 0] + ) == length(var.network_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "secops_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Secops Warning and Critical notifications." + validation { + condition = length( + [for e in var.secops_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.secops_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "platform_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Platform notifications." + validation { + condition = length( + [for e in var.platform_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.platform_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "identity_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Identity notifications." + validation { + condition = length( + [for e in var.identity_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.identity_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "default_log_group_id" { + type = string +} + +variable "workload_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Workload notifications." + validation { + condition = length( + [for e in var.workload_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.workload_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "enable_security_monitoring_alarms" { + type = bool + description = "Enable Security Monitoring Alarms in Security Compartment" +} +variable "enable_network_monitoring_alarms" { + type = bool + description = "Enable Network Monitoring Alarms in Network Compartment" +} +variable "enable_workload_monitoring_alarms" { + type = bool + description = "Enable Workload Monitoring Alarms in Workload Compartment" +} \ No newline at end of file diff --git a/templates/elz-network-extension/README.md b/templates/elz-network-extension/README.md new file mode 100644 index 00000000..42dfab9b --- /dev/null +++ b/templates/elz-network-extension/README.md @@ -0,0 +1,79 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [oci](#requirement\_oci) | 4.96.0 | + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | 4.96.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [fastconnect](#module\_fastconnect) | ../../modules/fastconnect | n/a | +| [ipsec](#module\_ipsec) | ../../modules/ipsec | n/a | + +## Resources + +| Name | Type | +|------|------| +| [oci_core_drg_attachment_management.drg_rpc_attachment_nonprod](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_drg_attachment_management) | resource | +| [oci_core_drg_attachment_management.drg_rpc_attachment_prod](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_drg_attachment_management) | resource | +| [oci_core_remote_peering_connection.remote_peering_connection](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_remote_peering_connection) | resource | +| [oci_identity_region_subscriptions.regions](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/identity_region_subscriptions) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [bgp\_cust\_tunnela\_ip](#input\_bgp\_cust\_tunnela\_ip) | n/a | `string` | n/a | yes | +| [bgp\_md5auth\_key](#input\_bgp\_md5auth\_key) | n/a | `string` | n/a | yes | +| [bgp\_oci\_tunnela\_ip](#input\_bgp\_oci\_tunnela\_ip) | n/a | `string` | n/a | yes | +| [cpe\_display\_name](#input\_cpe\_display\_name) | n/a | `string` | n/a | yes | +| [cpe\_ip\_address](#input\_cpe\_ip\_address) | Customer Premises Equipment (CPE) IP address | `string` | n/a | yes | +| [cpe\_vendor](#input\_cpe\_vendor) | n/a | `number` | n/a | yes | +| [customer\_bgp\_asn](#input\_customer\_bgp\_asn) | n/a | `string` | n/a | yes | +| [customer\_primary\_bgp\_peering\_ip](#input\_customer\_primary\_bgp\_peering\_ip) | n/a | `string` | n/a | yes | +| [customer\_secondary\_bgp\_peering\_ip](#input\_customer\_secondary\_bgp\_peering\_ip) | n/a | `string` | n/a | yes | +| [drg\_id](#input\_drg\_id) | n/a | `string` | n/a | yes | +| [drg\_route\_table\_rpc\_id](#input\_drg\_route\_table\_rpc\_id) | n/a | `string` | n/a | yes | +| [drg\_route\_table\_vc\_id](#input\_drg\_route\_table\_vc\_id) | n/a | `string` | n/a | yes | +| [enable\_fastconnect\_on\_environment](#input\_enable\_fastconnect\_on\_environment) | n/a | `bool` | n/a | yes | +| [enable\_vpn\_on\_environment](#input\_enable\_vpn\_on\_environment) | VPN Variables | `bool` | n/a | yes | +| [enable\_vpn\_or\_fastconnect](#input\_enable\_vpn\_or\_fastconnect) | Option to enable VPN or FASTCONNECT service. Options are NONE, VPN, FASTCONNECT. | `string` | n/a | yes | +| [environment\_prefix](#input\_environment\_prefix) | n/a | `string` | n/a | yes | +| [fastconnect\_provider](#input\_fastconnect\_provider) | Fastconnect Variables | `string` | n/a | yes | +| [fastconnect\_routing\_policy](#input\_fastconnect\_routing\_policy) | n/a | `list(string)` | n/a | yes | +| [ipsec\_connection\_static\_routes](#input\_ipsec\_connection\_static\_routes) | n/a | `list(string)` | n/a | yes | +| [ipsec\_display\_name](#input\_ipsec\_display\_name) | n/a | `string` | n/a | yes | +| [network\_compartment\_id](#input\_network\_compartment\_id) | n/a | `string` | n/a | yes | +| [oracle\_primary\_bgp\_peering\_ip](#input\_oracle\_primary\_bgp\_peering\_ip) | n/a | `string` | n/a | yes | +| [oracle\_secondary\_bgp\_peering\_ip](#input\_oracle\_secondary\_bgp\_peering\_ip) | n/a | `string` | n/a | yes | +| [provider\_service\_key\_name](#input\_provider\_service\_key\_name) | n/a | `string` | n/a | yes | +| [region](#input\_region) | The OCI region | `string` | n/a | yes | +| [region\_key](#input\_region\_key) | n/a | `string` | n/a | yes | +| [remote\_peering\_connection\_peer\_id](#input\_remote\_peering\_connection\_peer\_id) | n/a | `string` | `null` | no | +| [remote\_peering\_connection\_peer\_region\_name](#input\_remote\_peering\_connection\_peer\_region\_name) | n/a | `string` | `null` | no | +| [routing](#input\_routing) | n/a | `string` | n/a | yes | +| [shared\_secret](#input\_shared\_secret) | n/a | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | +| [tunnel\_a\_display\_name](#input\_tunnel\_a\_display\_name) | n/a | `string` | n/a | yes | +| [tunnel\_b\_display\_name](#input\_tunnel\_b\_display\_name) | n/a | `string` | n/a | yes | +| [virtual\_circuit\_bandwidth\_shape](#input\_virtual\_circuit\_bandwidth\_shape) | n/a | `string` | n/a | yes | +| [virtual\_circuit\_customer\_asn](#input\_virtual\_circuit\_customer\_asn) | n/a | `string` | n/a | yes | +| [virtual\_circuit\_display\_name](#input\_virtual\_circuit\_display\_name) | n/a | `string` | n/a | yes | +| [virtual\_circuit\_is\_bfd\_enabled](#input\_virtual\_circuit\_is\_bfd\_enabled) | n/a | `bool` | n/a | yes | +| [virtual\_circuit\_type](#input\_virtual\_circuit\_type) | n/a | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [rpc\_id](#output\_rpc\_id) | n/a | + \ No newline at end of file diff --git a/templates/elz-network-extension/datasources.tf b/templates/elz-network-extension/datasources.tf new file mode 100644 index 00000000..3e483838 --- /dev/null +++ b/templates/elz-network-extension/datasources.tf @@ -0,0 +1,12 @@ +# ----------------------------------------------------------------------------- +# Support for multi-region deployments +# ----------------------------------------------------------------------------- +locals { + region_subscriptions = data.oci_identity_region_subscriptions.regions.region_subscriptions + home_region = [for region in local.region_subscriptions : region.region_name if region.is_home_region == true] + region_key = [for region in local.region_subscriptions : region.region_key if region.region_name == var.region] +} + +data "oci_identity_region_subscriptions" "regions" { + tenancy_id = var.tenancy_ocid +} diff --git a/templates/elz-network-extension/main.tf b/templates/elz-network-extension/main.tf new file mode 100644 index 00000000..fba25f37 --- /dev/null +++ b/templates/elz-network-extension/main.tf @@ -0,0 +1,81 @@ +module "ipsec" { + count = var.enable_vpn_or_fastconnect == "VPN" && var.enable_vpn_on_environment ? 1 : 0 + source = "../../modules/ipsec" + compartment_ocid = var.network_compartment_id + cpe_ip_address = var.cpe_ip_address + cpe_display_name = var.cpe_display_name + drg_id = var.drg_id + ipsec_display_name = var.ipsec_display_name + static_routes = var.ipsec_connection_static_routes + cpe_vendor = var.cpe_vendor + routing = var.routing + tunnel_a_display_name = var.tunnel_a_display_name + customer_bgp_asn = var.customer_bgp_asn + bgp_cust_tunnela_ip = var.bgp_cust_tunnela_ip + bgp_oci_tunnela_ip = var.bgp_oci_tunnela_ip + shared_secret = var.shared_secret + tunnel_b_display_name = var.tunnel_b_display_name +} + +module "fastconnect" { + count = var.enable_vpn_or_fastconnect == "FASTCONNECT" && var.enable_fastconnect_on_environment ? 1 : 0 + source = "../../modules/fastconnect" + compartment_ocid = var.network_compartment_id + virtual_circuit_bandwidth_shape = var.virtual_circuit_bandwidth_shape + virtual_circuit_display_name = var.virtual_circuit_display_name + fastconnect_provider = var.fastconnect_provider + bgp_md5auth_key = var.bgp_md5auth_key + provider_service_key_name = var.provider_service_key_name + fastconnect_routing_policy = var.fastconnect_routing_policy + virtual_circuit_type = var.virtual_circuit_type + customer_primary_bgp_peering_ip = var.customer_primary_bgp_peering_ip + oracle_primary_bgp_peering_ip = var.oracle_primary_bgp_peering_ip + customer_secondary_bgp_peering_ip = var.customer_secondary_bgp_peering_ip + oracle_secondary_bgp_peering_ip = var.oracle_secondary_bgp_peering_ip + virtual_circuit_customer_asn = var.virtual_circuit_customer_asn + virtual_circuit_is_bfd_enabled = var.virtual_circuit_is_bfd_enabled + drg_id = var.drg_id + region_key = var.region_key + drg_route_table_vc_id = var.drg_route_table_vc_id +} + +# ----------------------------------------------------------------------------------------- +# Create RPC connection +# ----------------------------------------------------------------------------------------- +locals { + fastconnect = { + remote_peering_connection_display_name = "RPC-${var.environment_prefix}" + } + drg_rpc_attachment = { + display_name = "${var.environment_prefix}-RPC-Attachment" + } +} + +resource "oci_core_remote_peering_connection" "remote_peering_connection" { + count = var.enable_vpn_or_fastconnect == "FASTCONNECT" ? 1 : 0 + compartment_id = var.network_compartment_id + drg_id = var.drg_id + display_name = local.fastconnect.remote_peering_connection_display_name + peer_id = var.remote_peering_connection_peer_id != null ? var.remote_peering_connection_peer_id : null + peer_region_name = var.remote_peering_connection_peer_region_name != null ? var.remote_peering_connection_peer_region_name : null +} + +resource "oci_core_drg_attachment_management" "drg_rpc_attachment_nonprod" { + count = var.enable_vpn_or_fastconnect == "FASTCONNECT" && !var.enable_fastconnect_on_environment ? 1 : 0 + attachment_type = "REMOTE_PEERING_CONNECTION" + compartment_id = var.network_compartment_id + network_id = oci_core_remote_peering_connection.remote_peering_connection[0].id + drg_id = var.drg_id + display_name = local.drg_rpc_attachment.display_name + # drg_route_table_id = oci_core_drg_route_table.test_drg_route_table.id +} + +resource "oci_core_drg_attachment_management" "drg_rpc_attachment_prod" { + count = var.enable_vpn_or_fastconnect == "FASTCONNECT" && var.enable_fastconnect_on_environment ? 1 : 0 + attachment_type = "REMOTE_PEERING_CONNECTION" + compartment_id = var.network_compartment_id + network_id = oci_core_remote_peering_connection.remote_peering_connection[0].id + drg_id = var.drg_id + display_name = local.drg_rpc_attachment.display_name + drg_route_table_id = var.drg_route_table_rpc_id +} \ No newline at end of file diff --git a/templates/elz-network-extension/outputs.tf b/templates/elz-network-extension/outputs.tf new file mode 100644 index 00000000..57b77503 --- /dev/null +++ b/templates/elz-network-extension/outputs.tf @@ -0,0 +1,3 @@ +output "rpc_id" { + value = var.enable_vpn_or_fastconnect == "FASTCONNECT" ? oci_core_remote_peering_connection.remote_peering_connection[0].id : null +} \ No newline at end of file diff --git a/templates/elz-network-extension/provider.tf b/templates/elz-network-extension/provider.tf new file mode 100644 index 00000000..23554840 --- /dev/null +++ b/templates/elz-network-extension/provider.tf @@ -0,0 +1,72 @@ +# ----------------------------------------------------------------------------- +# Provider Requirements if using stack as a module +# ----------------------------------------------------------------------------- +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + version = "4.96.0" # October 05, 2022 Release + configuration_aliases = [oci, oci.home_region] + } + } +} + +# # ----------------------------------------------------------------------------- +# # WARNING! +# # UNCOMMENT EVERYTHING BELOW AND COMMENT EVERYTHING ABOVE IF YOU WISH TO USE THIS +# # STACK AS A STANDALONE - DO NOT TOUCH IF USING THIS STACK IN A MODULE CALL +# # Provider Requirements if using stack as standalone +# # ----------------------------------------------------------------------------- +# terraform { +# required_version = ">= 1.0.0" + +# required_providers { +# oci = { +# source = "oracle/oci" +# version = "4.96.0" # October 05, 2022 Release +# } +# } +# } + +# # ----------------------------------------------------------------------------- +# # Provider blocks for home region and alternate region(s) +# # ----------------------------------------------------------------------------- +# provider "oci" { +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = var.region +# } + +# provider "oci" { +# alias = "home_region" +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = local.home_region[0] +# } + +# # ----------------------------------------------------------------------------- +# # Provider Variables +# # ----------------------------------------------------------------------------- +# variable "current_user_ocid" { +# type = string +# description = "The OCID of the current user" +# default = "" +# } + +# variable "api_fingerprint" { +# type = string +# description = "The fingerprint of API" +# default = "" +# } + +# variable "api_private_key_path" { +# type = string +# description = "The local path to the API private key" +# default = "" +# } diff --git a/templates/elz-network-extension/variables.tf b/templates/elz-network-extension/variables.tf new file mode 100644 index 00000000..ed978def --- /dev/null +++ b/templates/elz-network-extension/variables.tf @@ -0,0 +1,162 @@ +# Common Variables +variable "tenancy_ocid" { + type = string + description = "The OCID of tenancy" +} + +variable "region" { + type = string + description = "The OCI region" +} + +variable "environment_prefix" { + type = string + description = "" +} + +variable "enable_vpn_or_fastconnect" { + type = string + description = "Option to enable VPN or FASTCONNECT service. Options are NONE, VPN, FASTCONNECT." +} + +# VPN Variables +variable "enable_vpn_on_environment" { + type = bool +} + +variable "cpe_display_name" { + type = string +} + +variable "cpe_ip_address" { + type = string + description = "Customer Premises Equipment (CPE) IP address" +} + +variable "network_compartment_id" { + type = string +} + +variable "ipsec_connection_static_routes" { + type = list(string) +} + +variable "ipsec_display_name" { + type = string +} + +variable "drg_id" { + type = string +} + +variable "cpe_vendor" { + type = number +} + +variable "routing" { + type = string + description = "" +} + +variable "tunnel_a_display_name" { + type = string +} + +variable "customer_bgp_asn" { + type = string +} + +variable "bgp_cust_tunnela_ip" { + type = string +} + +variable "bgp_oci_tunnela_ip" { + type = string +} + +variable "shared_secret" { + type = string +} + +variable "tunnel_b_display_name" { + type = string +} + +# Fastconnect Variables +variable "fastconnect_provider" { + type = string +} + +variable "region_key" { + type = string +} + +variable "virtual_circuit_bandwidth_shape" { + type = string +} + +variable "virtual_circuit_display_name" { + type = string +} + +variable "provider_service_key_name" { + type = string +} + +variable "fastconnect_routing_policy" { + type = list(string) +} + +variable "virtual_circuit_type" { + type = string +} + +variable "customer_primary_bgp_peering_ip" { + type = string +} + +variable "oracle_primary_bgp_peering_ip" { + type = string +} + +variable "customer_secondary_bgp_peering_ip" { + type = string +} + +variable "oracle_secondary_bgp_peering_ip" { + type = string +} + +variable "virtual_circuit_customer_asn" { + type = string +} + +variable "virtual_circuit_is_bfd_enabled" { + type = bool +} + +variable "bgp_md5auth_key" { + type = string +} + +variable "enable_fastconnect_on_environment" { + type = bool +} + +variable "remote_peering_connection_peer_id" { + type = string + default = null +} + +variable "remote_peering_connection_peer_region_name" { + type = string + default = null +} + +variable "drg_route_table_rpc_id" { + type = string +} + +variable "drg_route_table_vc_id" { + type = string +} diff --git a/templates/elz-network/README.md b/templates/elz-network/README.md new file mode 100644 index 00000000..44e3d11e --- /dev/null +++ b/templates/elz-network/README.md @@ -0,0 +1,95 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [oci](#requirement\_oci) | 4.96.0 | + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | 4.96.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [drg](#module\_drg) | ../../modules/drg | n/a | +| [hub\_internet\_gateway](#module\_hub\_internet\_gateway) | ../../modules/internet-gateway | n/a | +| [nat-gateway-hub](#module\_nat-gateway-hub) | ../../modules/nat-gateway | n/a | +| [nat-gateway-spoke](#module\_nat-gateway-spoke) | ../../modules/nat-gateway | n/a | +| [network\_default\_policy](#module\_network\_default\_policy) | ../../modules/policies | n/a | +| [service-gateway-hub](#module\_service-gateway-hub) | ../../modules/service-gateway | n/a | +| [service-gateway-spoke](#module\_service-gateway-spoke) | ../../modules/service-gateway | n/a | +| [workload\_default\_policy](#module\_workload\_default\_policy) | ../../modules/policies | n/a | + +## Resources + +| Name | Type | +|------|------| +| [oci_core_default_security_list.hub_default_security_list_locked_down](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_default_security_list) | resource | +| [oci_core_default_security_list.spoke_default_security_list_locked_down](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_default_security_list) | resource | +| [oci_core_route_table.hub_private_route_table](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_route_table) | resource | +| [oci_core_route_table.hub_public_route_table](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_route_table) | resource | +| [oci_core_route_table.spoke_route_table](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_route_table) | resource | +| [oci_core_security_list.security_list_hub](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_security_list) | resource | +| [oci_core_security_list.security_list_spoke](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_security_list) | resource | +| [oci_core_subnet.hub_private_subnet](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_subnet) | resource | +| [oci_core_subnet.hub_public_subnet](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_subnet) | resource | +| [oci_core_subnet.spoke_app_subnet](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_subnet) | resource | +| [oci_core_subnet.spoke_db_subnet](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_subnet) | resource | +| [oci_core_subnet.spoke_web_subnet](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_subnet) | resource | +| [oci_core_vcn.vcn_hub_network](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_vcn) | resource | +| [oci_core_vcn.vcn_spoke_network](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/resources/core_vcn) | resource | +| [oci_core_services.service_gateway](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/core_services) | data source | +| [oci_core_subnets.subnets](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/core_subnets) | data source | +| [oci_identity_region_subscriptions.regions](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/identity_region_subscriptions) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [add\_ssh\_to\_security\_list](#input\_add\_ssh\_to\_security\_list) | Add SSH tcpp port to Hub security list | `bool` | `false` | no | +| [customer\_onprem\_ip\_cidr](#input\_customer\_onprem\_ip\_cidr) | n/a | `list(string)` | n/a | yes | +| [enable\_fastconnect\_on\_environment](#input\_enable\_fastconnect\_on\_environment) | n/a | `bool` | n/a | yes | +| [enable\_internet\_gateway\_hub](#input\_enable\_internet\_gateway\_hub) | Option to enable true and Disable false. | `string` | `"false"` | no | +| [enable\_nat\_gateway\_hub](#input\_enable\_nat\_gateway\_hub) | Option to enable true and Disable false. | `string` | `"false"` | no | +| [enable\_nat\_gateway\_spoke](#input\_enable\_nat\_gateway\_spoke) | Option to enable true and Disable false. | `string` | `"false"` | no | +| [enable\_service\_gateway\_hub](#input\_enable\_service\_gateway\_hub) | Option to enable true and Disable false. | `string` | `"false"` | no | +| [enable\_service\_gateway\_spoke](#input\_enable\_service\_gateway\_spoke) | Option to enable true and Disable false. | `string` | `"false"` | no | +| [enable\_vpn\_on\_environment](#input\_enable\_vpn\_on\_environment) | n/a | `bool` | n/a | yes | +| [enable\_vpn\_or\_fastconnect](#input\_enable\_vpn\_or\_fastconnect) | Option to enable VPN or FASTCONNECT service. Options are NONE, VPN, FASTCONNECT. | `string` | n/a | yes | +| [environment\_prefix](#input\_environment\_prefix) | the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U | `string` | n/a | yes | +| [igw\_hub\_check](#input\_igw\_hub\_check) | n/a | `list(string)` | n/a | yes | +| [ipsec\_connection\_static\_routes](#input\_ipsec\_connection\_static\_routes) | ----------------------------------------------------------------------------- VPN Variables ----------------------------------------------------------------------------- | `list(string)` | n/a | yes | +| [nat\_gw\_hub\_check](#input\_nat\_gw\_hub\_check) | n/a | `list(string)` | n/a | yes | +| [nat\_gw\_spoke\_check](#input\_nat\_gw\_spoke\_check) | n/a | `list(string)` | n/a | yes | +| [network\_admin\_group\_name](#input\_network\_admin\_group\_name) | The group name for the OCI Landing Zone Network Administrators Group | `string` | `""` | no | +| [network\_compartment\_id](#input\_network\_compartment\_id) | Network Compartment OCID | `string` | n/a | yes | +| [network\_compartment\_name](#input\_network\_compartment\_name) | Network Compartment Name | `string` | n/a | yes | +| [private\_spoke\_subnet\_app\_cidr\_block](#input\_private\_spoke\_subnet\_app\_cidr\_block) | Spoke: Private Subnet App CIDR Block-1. | `string` | n/a | yes | +| [private\_spoke\_subnet\_db\_cidr\_block](#input\_private\_spoke\_subnet\_db\_cidr\_block) | Spoke: Private Subnet DB CIDR Block-1. | `string` | n/a | yes | +| [private\_spoke\_subnet\_web\_cidr\_block](#input\_private\_spoke\_subnet\_web\_cidr\_block) | Spoke: Private Subnet Web CIDR Block. | `string` | n/a | yes | +| [private\_subnet\_cidr\_block](#input\_private\_subnet\_cidr\_block) | Hub: Private Subnet CIDR Block. | `string` | n/a | yes | +| [public\_subnet\_cidr\_block](#input\_public\_subnet\_cidr\_block) | Hub: Public Subnet CIDR Block. | `string` | n/a | yes | +| [region](#input\_region) | The OCI region | `string` | n/a | yes | +| [service\_gw\_hub\_check](#input\_service\_gw\_hub\_check) | n/a | `list(string)` | n/a | yes | +| [service\_gw\_spoke\_check](#input\_service\_gw\_spoke\_check) | n/a | `list(string)` | n/a | yes | +| [spoke\_vcn\_cidr](#input\_spoke\_vcn\_cidr) | Spoke:VCN CIDR Block. | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | +| [vcn\_cidr\_block](#input\_vcn\_cidr\_block) | VCN CIDR Block. | `string` | n/a | yes | +| [workload\_compartment\_id](#input\_workload\_compartment\_id) | WorkLoad Compartment OCID | `string` | n/a | yes | +| [workload\_compartment\_name](#input\_workload\_compartment\_name) | WorkLoad Compartment Name | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [drg\_id](#output\_drg\_id) | n/a | +| [drg\_route\_tables](#output\_drg\_route\_tables) | n/a | +| [spoke\_web\_subnet\_ocid](#output\_spoke\_web\_subnet\_ocid) | n/a | +| [subnets](#output\_subnets) | The subnet OCID | +| [vcn](#output\_vcn) | n/a | + \ No newline at end of file diff --git a/templates/elz-network/datasources.tf b/templates/elz-network/datasources.tf new file mode 100644 index 00000000..3e483838 --- /dev/null +++ b/templates/elz-network/datasources.tf @@ -0,0 +1,12 @@ +# ----------------------------------------------------------------------------- +# Support for multi-region deployments +# ----------------------------------------------------------------------------- +locals { + region_subscriptions = data.oci_identity_region_subscriptions.regions.region_subscriptions + home_region = [for region in local.region_subscriptions : region.region_name if region.is_home_region == true] + region_key = [for region in local.region_subscriptions : region.region_key if region.region_name == var.region] +} + +data "oci_identity_region_subscriptions" "regions" { + tenancy_id = var.tenancy_ocid +} diff --git a/templates/elz-network/main.tf b/templates/elz-network/main.tf new file mode 100644 index 00000000..12d71fb1 --- /dev/null +++ b/templates/elz-network/main.tf @@ -0,0 +1,613 @@ +############################################################################## +########### CREATE VCN ########## +############################################################################## +locals { + vcn_hub_network = { + name = "OCI-ELZ-VCN-${var.environment_prefix}-HUB-${local.region_key[0]}" + } + vcn_internet_gateway = { + internet_gateway_diplay_name = "OCI-ELZ-IGW-${var.environment_prefix}-HUB" + } + internet_gateway = { + internet_gateway_display_name = "OCI-ELZ-IGW-${var.environment_prefix}-HUB" + } + nat_gateway = { + nat_gateway_display_name = "OCI-ELZ-NGW-${var.environment_prefix}-HUB" + } + vcn_spoke = { + name = "OCI-ELZ-VCN-${var.environment_prefix}-SPK-${local.region_key[0]}001" + } + + ipsec_connection_static_routes = var.enable_vpn_or_fastconnect == "VPN" && var.enable_vpn_on_environment ? var.ipsec_connection_static_routes : [] + customer_onprem_ip_cidr = var.enable_vpn_or_fastconnect == "FASTCONNECT" ? var.customer_onprem_ip_cidr : [] + + igw_hub_check = var.enable_internet_gateway_hub == "true" ? var.igw_hub_check : [] + nat_gw_hub_check = var.enable_nat_gateway_hub == "true" ? var.nat_gw_hub_check : [] + service_gw_hub_check = var.enable_service_gateway_hub == "true" ? var.service_gw_hub_check : [] + nat_gw_spoke_check = var.enable_nat_gateway_spoke == "true" ? var.nat_gw_spoke_check : [] + service_gw_spoke_check = var.enable_service_gateway_spoke == "true" ? var.service_gw_spoke_check : [] + + hub_public_route_rules_options = { + route_rules_default = { + "hub-to-web-traffic" = { + network_entity_id = module.drg.drg_id + destination = var.private_spoke_subnet_web_cidr_block + destination_type = "CIDR_BLOCK" + } + "hub-to-app-traffic" = { + network_entity_id = module.drg.drg_id + destination = var.private_spoke_subnet_app_cidr_block + destination_type = "CIDR_BLOCK" + } + "hub-to-db-traffic" = { + network_entity_id = module.drg.drg_id + destination = var.private_spoke_subnet_db_cidr_block + destination_type = "CIDR_BLOCK" + } + } + route_rules_igw = { + for index, route in local.igw_hub_check : "igw-rule-${index}" => { + network_entity_id = module.hub_internet_gateway[0].internet_gw_id + destination = "0.0.0.0/0" + destination_type = "CIDR_BLOCK" + } + } + route_rules_vpn = { + for index, route in local.ipsec_connection_static_routes : "cpe-rule-${index}" => { + network_entity_id = module.drg.drg_id + destination = route + destination_type = "CIDR_BLOCK" + } + } + route_rules_fastconnect = { + for index, route in local.customer_onprem_ip_cidr : "fc-rule-${index}" => { + network_entity_id = module.drg.drg_id + destination = route + destination_type = "CIDR_BLOCK" + } + } + } + + hub_public_route_rules = { + route_table_display_name = "OCI-ELZ-RTPUB-${var.environment_prefix}-HUB001" + route_rules = merge(local.hub_public_route_rules_options.route_rules_default, local.hub_public_route_rules_options.route_rules_igw, local.hub_public_route_rules_options.route_rules_vpn, local.hub_public_route_rules_options.route_rules_fastconnect) + } + + hub_private_route_rules_options = { + route_rules_default = { + "pri-hub-to-web-traffic" = { + network_entity_id = module.drg.drg_id + destination = var.private_spoke_subnet_web_cidr_block + destination_type = "CIDR_BLOCK" + } + "pri-hub-to-app-traffic" = { + network_entity_id = module.drg.drg_id + destination = var.private_spoke_subnet_app_cidr_block + destination_type = "CIDR_BLOCK" + } + "pri-hub-to-db-traffic" = { + network_entity_id = module.drg.drg_id + destination = var.private_spoke_subnet_db_cidr_block + destination_type = "CIDR_BLOCK" + } + } + route_rules_nat = { + for index, route in local.nat_gw_hub_check : "nat-gw-rule-${index}" => { + network_entity_id = module.nat-gateway-hub[0].nat_gw_id + destination = "0.0.0.0/0" + destination_type = "CIDR_BLOCK" + } + } + route_rules_srvc_gw = { + for index, route in local.service_gw_hub_check : "service-gw-rule-${index}" => { + network_entity_id = module.service-gateway-hub[0].service_gw_id + destination = data.oci_core_services.service_gateway.services[0]["cidr_block"] + destination_type = "SERVICE_CIDR_BLOCK" + } + } + route_rules_vpn = { + for index, route in local.ipsec_connection_static_routes : "cpe-rule-${index}" => { + network_entity_id = module.drg.drg_id + destination = route + destination_type = "CIDR_BLOCK" + } + } + route_rules_fastconnect = { + for index, route in local.customer_onprem_ip_cidr : "fc-rule-${index}" => { + network_entity_id = module.drg.drg_id + destination = route + destination_type = "CIDR_BLOCK" + } + } + } + hub_private_route_rules = { + route_table_display_name = "OCI-ELZ-RTPRV-${var.environment_prefix}-HUB002" + route_rules = merge(local.hub_private_route_rules_options.route_rules_default,local.hub_private_route_rules_options.route_rules_nat,local.hub_private_route_rules_options.route_rules_srvc_gw, local.hub_private_route_rules_options.route_rules_vpn, local.hub_private_route_rules_options.route_rules_fastconnect) + } + + spoke_route_rules_options = { + route_rules_default = { + "spoke-public-subnet" = { + network_entity_id = module.drg.drg_id + destination = var.public_subnet_cidr_block + destination_type = "CIDR_BLOCK" + } + "spoke-private-subnet" = { + network_entity_id = module.drg.drg_id + destination = var.private_subnet_cidr_block + destination_type = "CIDR_BLOCK" + } + "spoke-route-target" = { + network_entity_id = module.drg.drg_id + destination = var.spoke_vcn_cidr + destination_type = "CIDR_BLOCK" + } + } + route_rules_nat_spoke = { + for index, route in local.nat_gw_spoke_check : "nat-gw-rule-${index}" => { + network_entity_id = module.nat-gateway-spoke[0].nat_gw_id + destination = "0.0.0.0/0" + destination_type = "CIDR_BLOCK" + } + } + route_rules_srvc_gw_spoke = { + for index, route in local.service_gw_spoke_check : "service-gw-rule-${index}" => { + network_entity_id = module.service-gateway-spoke[0].service_gw_id + destination = data.oci_core_services.service_gateway.services[0]["cidr_block"] + destination_type = "SERVICE_CIDR_BLOCK" + } + } + route_rules_vpn = { + for index, route in local.ipsec_connection_static_routes : "cpe-rule-${index}" => { + network_entity_id = module.drg.drg_id + destination = route + destination_type = "CIDR_BLOCK" + } + } + route_rules_fastconnect = { + for index, route in local.customer_onprem_ip_cidr : "fc-rule-${index}" => { + network_entity_id = module.drg.drg_id + destination = route + destination_type = "CIDR_BLOCK" + } + } + } + spoke_route_rules = { + route_table_display_name = "OCI-ELZ-RTPRV-${var.environment_prefix}-SPK001" + route_rules = merge(local.spoke_route_rules_options.route_rules_default,local.spoke_route_rules_options.route_rules_nat_spoke,local.spoke_route_rules_options.route_rules_srvc_gw_spoke,local.spoke_route_rules_options.route_rules_vpn, local.spoke_route_rules_options.route_rules_fastconnect) + } +} +data "oci_core_services" "service_gateway" { + filter { + name = "name" + values = [".*Object.*Storage"] + regex = true + } +} +############################################################################## +########### CREATE HUB ########## +############################################################################## +resource "oci_core_vcn" "vcn_hub_network" { + cidr_blocks = [var.vcn_cidr_block] + compartment_id = var.network_compartment_id + display_name = local.vcn_hub_network.name + dns_label = "hublabel" + is_ipv6enabled = false +} + +resource "oci_core_default_security_list" "hub_default_security_list_locked_down" { + manage_default_resource_id = oci_core_vcn.vcn_hub_network.default_security_list_id +} + +locals { + list_info = { + hub_display_name = "OCI-ELZ-${var.environment_prefix}-Hub-Security-List" + spoke_display_name = "OCI-ELZ-${var.environment_prefix}-Spk-Security-List" + } + ip_protocols = { + ICMP = "1" + TCP = "6" + UDP = "17" + ICMPv6 = "58" + } + security_list_ingress = { + protocol = local.ip_protocols.ICMP + source = "0.0.0.0/0" + description = "All ICMP Taffic" + source_type = "CIDR_BLOCK" + } + security_list_ingress_ssh = { + protocol = local.ip_protocols.TCP + source = "0.0.0.0/0" + description = "SSH Traffic" + source_type = "CIDR_BLOCK" + tcp_port = 22 + } + security_list_egress = { + destination = "0.0.0.0/0" + protocol = "all" + description = "All Traffic For All Port" + destination_type = "CIDR_BLOCK" + } +} + +#Create the HUB VCN Security Rule + +resource "oci_core_security_list" "security_list_hub" { + compartment_id = var.network_compartment_id + vcn_id = oci_core_vcn.vcn_hub_network.id + display_name = local.list_info.hub_display_name + + egress_security_rules { + destination = local.security_list_egress.destination + protocol = local.security_list_egress.protocol + description = local.security_list_egress.description + destination_type = local.security_list_egress.destination_type + } + ingress_security_rules { + protocol = local.security_list_ingress.protocol + source = local.security_list_ingress.source + description = local.security_list_ingress.description + source_type = local.security_list_ingress.source_type + } + dynamic "ingress_security_rules" { + for_each = var.add_ssh_to_security_list ? [1] : [] + content { + protocol = local.security_list_ingress_ssh.protocol + source = local.security_list_ingress_ssh.source + description = local.security_list_ingress_ssh.description + source_type = local.security_list_ingress_ssh.source_type + tcp_options { + max = local.security_list_ingress_ssh.tcp_port + min = local.security_list_ingress_ssh.tcp_port + } + } + } +} + +# Private Subnet and route table +resource "oci_core_subnet" "hub_private_subnet" { + cidr_block = var.private_subnet_cidr_block + display_name = "OCI-ELZ-SUB-${var.environment_prefix}-HUB-${local.region_key[0]}002" + dns_label = "prisublabel" + compartment_id = var.network_compartment_id + prohibit_public_ip_on_vnic = true + vcn_id = oci_core_vcn.vcn_hub_network.id + route_table_id = oci_core_route_table.hub_private_route_table.id + security_list_ids = toset([oci_core_security_list.security_list_hub.id]) +} +resource "oci_core_route_table" "hub_private_route_table" { + compartment_id = var.network_compartment_id + vcn_id = oci_core_vcn.vcn_hub_network.id + display_name = local.hub_private_route_rules.route_table_display_name + dynamic "route_rules" { + for_each = local.hub_private_route_rules.route_rules + content { + description = route_rules.key + network_entity_id = route_rules.value.network_entity_id + destination = route_rules.value.destination + destination_type = route_rules.value.destination_type + } + } +} + +#Public Subnet and route table +resource "oci_core_subnet" "hub_public_subnet" { + cidr_block = var.public_subnet_cidr_block + display_name = "OCI-ELZ-SUB-${var.environment_prefix}-HUB-${local.region_key[0]}001" + dns_label = "pubsublabel" + compartment_id = var.network_compartment_id + prohibit_public_ip_on_vnic = false + vcn_id = oci_core_vcn.vcn_hub_network.id + route_table_id = oci_core_route_table.hub_public_route_table.id + security_list_ids = toset([oci_core_security_list.security_list_hub.id]) +} + +resource "oci_core_route_table" "hub_public_route_table" { + compartment_id = var.network_compartment_id + vcn_id = oci_core_vcn.vcn_hub_network.id + display_name = local.hub_public_route_rules.route_table_display_name + dynamic "route_rules" { + for_each = local.hub_public_route_rules.route_rules + content { + description = route_rules.key + network_entity_id = route_rules.value.network_entity_id + destination = route_rules.value.destination + destination_type = route_rules.value.destination_type + } + } +} + +############################################################################## +########### CREATE SPOKE ########## +############################################################################## +resource "oci_core_vcn" "vcn_spoke_network" { + cidr_blocks = [var.spoke_vcn_cidr] + compartment_id = var.workload_compartment_id + display_name = local.vcn_spoke.name + dns_label = "spokelabel" + is_ipv6enabled = false +} + +resource "oci_core_default_security_list" "spoke_default_security_list_locked_down" { + manage_default_resource_id = oci_core_vcn.vcn_spoke_network.default_security_list_id +} + +#Create the HUB VCN Security Rule +resource "oci_core_security_list" "security_list_spoke" { + compartment_id = var.workload_compartment_id + vcn_id = oci_core_vcn.vcn_spoke_network.id + display_name = local.list_info.spoke_display_name + + egress_security_rules { + destination = local.security_list_egress.destination + protocol = local.security_list_egress.protocol + description = local.security_list_egress.description + destination_type = local.security_list_egress.destination_type + } + ingress_security_rules { + protocol = local.security_list_ingress.protocol + source = local.security_list_ingress.source + description = local.security_list_ingress.description + source_type = local.security_list_ingress.source_type + } +} + +#Web App and DB Subnet and route table +resource "oci_core_subnet" "spoke_web_subnet" { + cidr_block = var.private_spoke_subnet_web_cidr_block + display_name = "OCI-ELZ-SUB-${var.environment_prefix}-SPK-${local.region_key[0]}001" + dns_label = "webdnslabel" + compartment_id = var.workload_compartment_id + prohibit_public_ip_on_vnic = true + vcn_id = oci_core_vcn.vcn_spoke_network.id + route_table_id = oci_core_route_table.spoke_route_table.id + security_list_ids = toset([oci_core_security_list.security_list_spoke.id]) +} +resource "oci_core_subnet" "spoke_app_subnet" { + cidr_block = var.private_spoke_subnet_app_cidr_block + display_name = "OCI-ELZ-SUB-${var.environment_prefix}-SPK-${local.region_key[0]}002" + dns_label = "appdnslabel" + compartment_id = var.workload_compartment_id + prohibit_public_ip_on_vnic = true + vcn_id = oci_core_vcn.vcn_spoke_network.id + route_table_id = oci_core_route_table.spoke_route_table.id + security_list_ids = toset([oci_core_security_list.security_list_spoke.id]) +} +resource "oci_core_subnet" "spoke_db_subnet" { + cidr_block = var.private_spoke_subnet_db_cidr_block + display_name = "OCI-ELZ-SUB-${var.environment_prefix}-SPK-${local.region_key[0]}003" + dns_label = "dbdnslabel" + compartment_id = var.workload_compartment_id + prohibit_public_ip_on_vnic = true + vcn_id = oci_core_vcn.vcn_spoke_network.id + route_table_id = oci_core_route_table.spoke_route_table.id + security_list_ids = toset([oci_core_security_list.security_list_spoke.id]) +} + +resource "oci_core_route_table" "spoke_route_table" { + compartment_id = var.workload_compartment_id + vcn_id = oci_core_vcn.vcn_spoke_network.id + display_name = local.spoke_route_rules.route_table_display_name + dynamic "route_rules" { + for_each = local.spoke_route_rules.route_rules + content { + description = route_rules.key + network_entity_id = route_rules.value.network_entity_id + destination = route_rules.value.destination + destination_type = route_rules.value.destination_type + } + } +} + +#TODO Need to format this with the connectivity tests +#TODO Need to add ICMP security allow for tests + +data "oci_core_subnets" "subnets" { + compartment_id = var.network_compartment_id +} +########################################################################################################### +########### CREATE INTERNET GATEWAY, NAT GATEWAY AND SERVICE GATEWAY ########## +########################################################################################################### +locals { + hub_internet_gateway = { + vcn_id = oci_core_vcn.vcn_hub_network.id + internet_gateway_display_name = "OCI-ELZ-IGW-${var.environment_prefix}-HUB" + } + hub_nat_gateway = { + vcn_id = oci_core_vcn.vcn_hub_network.id + nat_gateway_display_name = "OCI-ELZ-NGW-${var.environment_prefix}-HUB" + } + + spoke_nat_gateway = { + vcn_id = oci_core_vcn.vcn_spoke_network.id + nat_gateway_display_name = "OCI-ELZ-NGW-${var.environment_prefix}-SPK" + } + service_gateway_hub = { + service_gateway_display_name = "OCI-ELZ-SGW-${var.environment_prefix}-HUB" + vcn_id = oci_core_vcn.vcn_hub_network.id + } + service_gateway_spoke = { + service_gateway_display_name = "OCI-ELZ-SGW-${var.environment_prefix}-SPK" + vcn_id = oci_core_vcn.vcn_spoke_network.id + } +} + +module "hub_internet_gateway" { + source = "../../modules/internet-gateway" + + count = var.enable_internet_gateway_hub == "true" ? 1 : 0 + network_compartment_id = var.network_compartment_id + vcn_id = local.hub_internet_gateway.vcn_id + internet_gateway_display_name = local.hub_internet_gateway.internet_gateway_display_name +} + +module "nat-gateway-hub" { + source = "../../modules/nat-gateway" + + count = var.enable_nat_gateway_hub == "true" ? 1 : 0 + network_compartment_id = var.network_compartment_id + vcn_id = local.hub_nat_gateway.vcn_id + nat_gateway_display_name = local.hub_nat_gateway.nat_gateway_display_name +} + +module "nat-gateway-spoke" { + source = "../../modules/nat-gateway" + + count = var.enable_nat_gateway_spoke == "true" ? 1 : 0 + network_compartment_id = var.workload_compartment_id + vcn_id = local.spoke_nat_gateway.vcn_id + nat_gateway_display_name = local.spoke_nat_gateway.nat_gateway_display_name +} + +module "service-gateway-hub" { + source = "../../modules/service-gateway" + + count = var.enable_service_gateway_hub == "true" ? 1 : 0 + network_compartment_id = var.network_compartment_id + vcn_id = local.service_gateway_hub.vcn_id + service_gateway_display_name = local.service_gateway_hub.service_gateway_display_name +} + +module "service-gateway-spoke" { + source = "../../modules/service-gateway" + + count = var.enable_service_gateway_spoke == "true" ? 1 : 0 + network_compartment_id = var.workload_compartment_id + vcn_id = local.service_gateway_spoke.vcn_id + service_gateway_display_name = local.service_gateway_spoke.service_gateway_display_name +} + +############################################################################################## +########### CREATE DRG AND DEFAULT POLICY ########## +############################################################################################## +locals { + drg_route_table_options = { + default = {} + virtual_circuit = var.enable_vpn_or_fastconnect == "FASTCONNECT" && var.enable_fastconnect_on_environment ? { + RT-Onprem = { + display_name = "RT-Onprem" + route_distribution_name = "Import_Onprem" + rules = { + + } + } + RT-RPC = { + display_name = "RT-RPC" + route_distribution_name = "Import_RPC" + rules = { + + } + } + } : {} + } + drg_route_distribution_options = { + default = {} + virtual_circuit = var.enable_vpn_or_fastconnect == "FASTCONNECT" && var.enable_fastconnect_on_environment ? { + Import_Onprem = { + distribution_display_name = "Import_Onprem" + distribution_type = "IMPORT" + statements = { + "statement-1" = { + action = "ACCEPT" + match_type = "DRG_ATTACHMENT_TYPE" # DRG_ATTACHMENT_ID DRG_ATTACHMENT_TYPE MATCH_ALL + attachment_type = "REMOTE_PEERING_CONNECTION" + drg_attachment_name = "" + priority = 1 + } + "statement-2" = { + action = "ACCEPT" + match_type = "DRG_ATTACHMENT_TYPE" # DRG_ATTACHMENT_ID DRG_ATTACHMENT_TYPE MATCH_ALL + attachment_type = "VCN" + drg_attachment_name = "" + priority = 2 + } + } + } + Import_RPC = { + distribution_display_name = "Import_RPC" + distribution_type = "IMPORT" + statements = { + "statement-3" = { + action = "ACCEPT" + match_type = "DRG_ATTACHMENT_TYPE" # DRG_ATTACHMENT_ID DRG_ATTACHMENT_TYPE MATCH_ALL + attachment_type = "VIRTUAL_CIRCUIT" + drg_attachment_name = "" + priority = 1 + } + } + } + } : {} + + } + drg = { + drg_display_name = "OCI-ELZ-DRG-${var.environment_prefix}-HUB" + drg_route_table_display_name = "Hub-Vcn-Drg-Route-Table-${var.environment_prefix}" + drg_vcn_attachments = { + "Hub-VCN-Attachment" = { + display_name = "Hub-Vcn-Drg-${var.environment_prefix}-Attachment" + vcn_id = oci_core_vcn.vcn_hub_network.id + route_table_id = "" + drg_route_table_name = null + } + "Spoke-VCN-Attachment" = { + display_name = "Workload001-${var.environment_prefix}-VCN-Attachment" + vcn_id = oci_core_vcn.vcn_spoke_network.id + route_table_id = "" + drg_route_table_name = null + } + } + drg_route_table_map = merge(local.drg_route_table_options.default, local.drg_route_table_options.virtual_circuit) + route_distribution_map = merge(local.drg_route_distribution_options.default, local.drg_route_distribution_options.virtual_circuit) + } + group_names = { + network_admin_group_name : var.network_admin_group_name != "" ? var.network_admin_group_name : "OCI-ELZ-UGP-${var.environment_prefix}-NET-ADMIN", + } + network_default_policy = { + name = "OCI-ELZ-${var.environment_prefix}-SRD-NET-DEFAULT-POLICY" + description = "OCI Network Default Policy" + + statements = [ + "Allow group OCI-ELZ-${var.environment_prefix}-IDT/${local.group_names["network_admin_group_name"]} to manage vcns in compartment ${var.network_compartment_name}", + "Allow group OCI-ELZ-${var.environment_prefix}-IDT/${local.group_names["network_admin_group_name"]} to manage drgs in compartment ${var.network_compartment_name}", + "Allow group OCI-ELZ-${var.environment_prefix}-IDT/${local.group_names["network_admin_group_name"]} to manage remote-peering-from in compartment ${var.network_compartment_name}", + "Allow group OCI-ELZ-${var.environment_prefix}-IDT/${local.group_names["network_admin_group_name"]} to manage remote-peering-to in compartment ${var.network_compartment_name}", + "Allow group OCI-ELZ-${var.environment_prefix}-IDT/${local.group_names["network_admin_group_name"]} to manage remote-peering-from in compartment ${var.network_compartment_name}", + "Allow group OCI-ELZ-${var.environment_prefix}-IDT/${local.group_names["network_admin_group_name"]} to manage virtual-network-family in compartment ${var.network_compartment_name}", + "Allow group OCI-ELZ-${var.environment_prefix}-IDT/${local.group_names["network_admin_group_name"]} to manage load-balancers in compartment ${var.network_compartment_name}", + ] + } + workload_default_policy = { + name = "OCI-ELZ-${var.environment_prefix}-SRD-NET-WRK-DEFAULT-POLICY" + description = "OCI Workload Default Policy" + + statements = [ + "Allow group OCI-ELZ-${var.environment_prefix}-IDT/${local.group_names["network_admin_group_name"]} to manage vcns in compartment ${var.workload_compartment_name}", + ] + } +} + +module "drg" { + source = "../../modules/drg" + + compartment_id = var.network_compartment_id + drg_display_name = local.drg.drg_display_name + drg_vcn_attachments = local.drg.drg_vcn_attachments + drg_route_table_map = local.drg.drg_route_table_map + route_distribution_map = local.drg.route_distribution_map +} + +module "network_default_policy" { + source = "../../modules/policies" + compartment_ocid = var.network_compartment_id + policy_name = local.network_default_policy.name + description = local.network_default_policy.description + statements = local.network_default_policy.statements +} +module "workload_default_policy" { + source = "../../modules/policies" + compartment_ocid = var.workload_compartment_id + policy_name = local.workload_default_policy.name + description = local.workload_default_policy.description + statements = local.workload_default_policy.statements +} diff --git a/templates/elz-network/outputs.tf b/templates/elz-network/outputs.tf new file mode 100644 index 00000000..3c94198d --- /dev/null +++ b/templates/elz-network/outputs.tf @@ -0,0 +1,25 @@ +output "subnets" { + value = { + (oci_core_subnet.hub_public_subnet.display_name) = oci_core_subnet.hub_public_subnet.id + (oci_core_subnet.hub_private_subnet.display_name) = oci_core_subnet.hub_private_subnet.id + (oci_core_subnet.spoke_app_subnet.display_name) = oci_core_subnet.spoke_app_subnet.id + (oci_core_subnet.spoke_web_subnet.display_name) = oci_core_subnet.spoke_web_subnet.id + (oci_core_subnet.spoke_db_subnet.display_name) = oci_core_subnet.spoke_db_subnet.id + } + description = "The subnet OCID" +} +output "vcn" { + value = oci_core_vcn.vcn_hub_network +} + +output "spoke_web_subnet_ocid" { + value = oci_core_subnet.spoke_web_subnet.id +} + +output "drg_id" { + value = module.drg.drg_id +} + +output "drg_route_tables" { + value = module.drg.drg_route_tables +} \ No newline at end of file diff --git a/templates/elz-network/provider.tf b/templates/elz-network/provider.tf new file mode 100644 index 00000000..2bbda84d --- /dev/null +++ b/templates/elz-network/provider.tf @@ -0,0 +1,72 @@ +# ----------------------------------------------------------------------------- +# Provider Requirements if using stack as a module +# ----------------------------------------------------------------------------- +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + version = "4.96.0" # October 05, 2022 Release + configuration_aliases = [oci, oci.home_region] + } + } +} + +# # ----------------------------------------------------------------------------- +# # WARNING! +# # UNCOMMENT EVERYTHING BELOW AND COMMENT EVERYTHING ABOVE IF YOU WISH TO USE THIS +# # STACK AS A STANDALONE - DO NOT TOUCH IF USING THIS STACK IN A MODULE CALL +# # Provider Requirements if using stack as standalone +# # ----------------------------------------------------------------------------- +# terraform { +# required_version = ">= 1.0.0" + +# required_providers { +# oci = { +# source = "oracle/oci" +# version = "4.96.0" # October 05, 2022 Release +# } +# } +# } + +# # ----------------------------------------------------------------------------- +# # Provider blocks for home region and alternate region(s) +# # ----------------------------------------------------------------------------- +# provider "oci" { +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = var.region +# } + +# provider "oci" { +# alias = "home_region" +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = local.home_region[0] +# } + +# # ----------------------------------------------------------------------------- +# # Provider Variables +# # ----------------------------------------------------------------------------- +# variable "current_user_ocid" { +# type = string +# description = "The OCID of the current user" +# default = "" +# } + +# variable "api_fingerprint" { +# type = string +# description = "The fingerprint of API" +# default = "" +# } + +# variable "api_private_key_path" { +# type = string +# description = "The local path to the API private key" +# default = "" +# } diff --git a/templates/elz-network/variables.tf b/templates/elz-network/variables.tf new file mode 100644 index 00000000..bb2e075a --- /dev/null +++ b/templates/elz-network/variables.tf @@ -0,0 +1,155 @@ +# ----------------------------------------------------------------------------- +# Common Variables +# ----------------------------------------------------------------------------- +variable "tenancy_ocid" { + type = string + description = "The OCID of tenancy" +} + +variable "region" { + type = string + description = "The OCI region" +} + +variable "environment_prefix" { + type = string + description = "the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U" +} + +# ----------------------------------------------------------------------------- +# Network Variables +# ----------------------------------------------------------------------------- + +variable "enable_internet_gateway_hub" { + type = string + default = "false" + description = "Option to enable true and Disable false." +} +variable "enable_nat_gateway_hub" { + type = string + default = "false" + description = "Option to enable true and Disable false." +} + +variable "enable_service_gateway_hub" { + type = string + default = "false" + description = "Option to enable true and Disable false." +} + +variable "enable_nat_gateway_spoke" { + type = string + default = "false" + description = "Option to enable true and Disable false." +} + +variable "enable_service_gateway_spoke" { + type = string + default = "false" + description = "Option to enable true and Disable false." +} +variable "igw_hub_check" { + type = list(string) +} +variable "nat_gw_hub_check" { + type = list(string) +} +variable "service_gw_hub_check" { + type = list(string) +} + +variable "nat_gw_spoke_check" { + type = list(string) +} + +variable "service_gw_spoke_check" { + type = list(string) +} + +variable "network_compartment_id" { + type = string + description = "Network Compartment OCID" +} + +variable "workload_compartment_id" { + type = string + description = "WorkLoad Compartment OCID" +} + +variable "workload_compartment_name" { + type = string + description = "WorkLoad Compartment Name" +} +variable "network_compartment_name" { + type = string + description = "Network Compartment Name" +} +variable "network_admin_group_name" { + type = string + default = "" + description = "The group name for the OCI Landing Zone Network Administrators Group" +} +variable "vcn_cidr_block" { + type = string + description = "VCN CIDR Block." +} + +variable "public_subnet_cidr_block" { + type = string + description = "Hub: Public Subnet CIDR Block." +} + +variable "private_subnet_cidr_block" { + type = string + description = "Hub: Private Subnet CIDR Block." +} + +variable "private_spoke_subnet_web_cidr_block" { + type = string + description = "Spoke: Private Subnet Web CIDR Block." +} + +variable "private_spoke_subnet_app_cidr_block" { + type = string + description = "Spoke: Private Subnet App CIDR Block-1." +} + +variable "private_spoke_subnet_db_cidr_block" { + type = string + description = "Spoke: Private Subnet DB CIDR Block-1." +} + +variable "spoke_vcn_cidr" { + type = string + description = "Spoke:VCN CIDR Block." +} + +variable "add_ssh_to_security_list" { + type = bool + description = "Add SSH tcpp port to Hub security list" + default = false +} + +# ----------------------------------------------------------------------------- +# VPN Variables +# ----------------------------------------------------------------------------- +variable "ipsec_connection_static_routes" { + type = list(string) +} + +variable "enable_vpn_or_fastconnect" { + type = string + description = "Option to enable VPN or FASTCONNECT service. Options are NONE, VPN, FASTCONNECT." +} + +variable "enable_vpn_on_environment" { + type = bool +} + +variable "enable_fastconnect_on_environment" { + type = bool +} + +variable "customer_onprem_ip_cidr" { + type = list(string) +} diff --git a/templates/elz-security/README.md b/templates/elz-security/README.md new file mode 100644 index 00000000..581f0566 --- /dev/null +++ b/templates/elz-security/README.md @@ -0,0 +1,61 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [oci](#requirement\_oci) | 4.96.0 | + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | 4.96.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [bastion](#module\_bastion) | ../../modules/bastion | n/a | +| [cloud\_guard](#module\_cloud\_guard) | ../../modules/cloud-guard | n/a | +| [key](#module\_key) | ../../modules/key | n/a | +| [key\_policy](#module\_key\_policy) | ../../modules/policies | n/a | +| [vault](#module\_vault) | ../../modules/vault | n/a | +| [vss](#module\_vss) | ../../modules/vss | n/a | + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_region_subscriptions.regions](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/identity_region_subscriptions) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [bastion\_client\_cidr\_block\_allow\_list](#input\_bastion\_client\_cidr\_block\_allow\_list) | A list of address ranges in CIDR notation that you want to allow to connect to sessions hosted by this bastion. | `list(string)` | n/a | yes | +| [bastion\_target\_subnet\_id](#input\_bastion\_target\_subnet\_id) | The OCID of the subnet that the bastion connects to | `string` | n/a | yes | +| [cloud\_guard\_target\_tenancy](#input\_cloud\_guard\_target\_tenancy) | true if cloud guard targets to tenancy, false if cloud guard targets to Landing Zone home compartment | `bool` | n/a | yes | +| [create\_master\_encryption\_key](#input\_create\_master\_encryption\_key) | Option create master encryption key | `bool` | n/a | yes | +| [enable\_bastion](#input\_enable\_bastion) | Option to enable bastion service | `bool` | n/a | yes | +| [enable\_cloud\_guard](#input\_enable\_cloud\_guard) | true if you don't have cloud guard enabled, false if you've already have cloud guard enabled. | `bool` | n/a | yes | +| [enable\_replication](#input\_enable\_replication) | Option to enable vault replication | `bool` | n/a | yes | +| [environment\_compartment\_id](#input\_environment\_compartment\_id) | The OCID of environment compartment | `string` | n/a | yes | +| [environment\_prefix](#input\_environment\_prefix) | the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U | `string` | n/a | yes | +| [home\_compartment\_id](#input\_home\_compartment\_id) | the OCID of the compartment where the environment will be created. In general, this should be the Landing zone parent compartment. | `string` | n/a | yes | +| [home\_compartment\_name](#input\_home\_compartment\_name) | Landing Zone home compartment name | `string` | n/a | yes | +| [region](#input\_region) | The OCI region | `string` | n/a | yes | +| [replica\_region](#input\_replica\_region) | the region to be created replica to. | `string` | n/a | yes | +| [resource\_label](#input\_resource\_label) | Prefix used to avoid naming conflict | `string` | n/a | yes | +| [security\_compartment\_id](#input\_security\_compartment\_id) | The OCID of security compartment | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | +| [vault\_type](#input\_vault\_type) | The type of vault to create. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [bastion\_id](#output\_bastion\_id) | n/a | +| [key\_id](#output\_key\_id) | n/a | +| [vault\_id](#output\_vault\_id) | n/a | + \ No newline at end of file diff --git a/templates/elz-security/datasources.tf b/templates/elz-security/datasources.tf new file mode 100644 index 00000000..3e483838 --- /dev/null +++ b/templates/elz-security/datasources.tf @@ -0,0 +1,12 @@ +# ----------------------------------------------------------------------------- +# Support for multi-region deployments +# ----------------------------------------------------------------------------- +locals { + region_subscriptions = data.oci_identity_region_subscriptions.regions.region_subscriptions + home_region = [for region in local.region_subscriptions : region.region_name if region.is_home_region == true] + region_key = [for region in local.region_subscriptions : region.region_key if region.region_name == var.region] +} + +data "oci_identity_region_subscriptions" "regions" { + tenancy_id = var.tenancy_ocid +} diff --git a/templates/elz-security/main.tf b/templates/elz-security/main.tf new file mode 100644 index 00000000..0e707af7 --- /dev/null +++ b/templates/elz-security/main.tf @@ -0,0 +1,127 @@ +locals { + cloud_guard = { + display_name = "${var.resource_label}-OCI-ELZ-CG-${var.environment_prefix}" + status = "ENABLED" + target_resource_type = "COMPARTMENT" + description = "OCI LZ Cloud Guard Target" + configuration_detector_recipe_display_name = "OCI Configuration Detector Recipe" + activity_detector_recipe_display_name = "OCI Activity Detector Recipe" + threat_detector_recipe_display_name = "OCI Threat Detector Recipe" + responder_recipe_display_name = "OCI Responder Recipe" + compartment_id = var.cloud_guard_target_tenancy ? var.tenancy_ocid : var.environment_compartment_id + target_resource_id = var.cloud_guard_target_tenancy ? var.tenancy_ocid : var.environment_compartment_id + } + + vss = { + host_scan_recipe_display_name = "${var.resource_label}-OCI-ELZ-VSS-${var.environment_prefix}" + host_scan_target_display_name = "${var.resource_label}-OCI-ELZ-VSS-Target-${var.environment_prefix}" + host_scan_recipe_agent_settings_scan_level = "STANDARD" + host_scan_recipe_port_settings_scan_level = "STANDARD" + agent_cis_benchmark_settings_scan_level = "STRICT" + vss_scan_schedule = "DAILY" + } + + bastion = { + name = "${var.resource_label}-OCI-ELZ-BAS-${var.environment_prefix}" + } + + vault = { + name = "${var.resource_label}-OCI-ELZ-VAL-${var.environment_prefix}" + } + + key = { + name = "${var.resource_label}-OCI-ELZ-KEY-${var.environment_prefix}" + shape_algorithm = "AES" + shape_length = 32 + protection_mode = "SOFTWARE" + } + + create_key = var.vault_type != "NONE" && var.create_master_encryption_key + + key_policy = { + name = "${var.resource_label}-OCI-ELZ-KEY-Policy-${var.environment_prefix}" + description = "OCI Enterprise Landing Zone Key Policy" + + statements = local.create_key ? [ + "Allow service objectstorage-${var.region} to use keys in compartment id ${var.security_compartment_id} where target.key.id = ${module.key[0].key_ocid}", + "Allow service blockstorage,FssOc1Prod, OKE, streaming to use keys in compartment id ${var.security_compartment_id} where target.key.id = ${module.key[0].key_ocid}" + ] : [] + } + +} + +module "cloud_guard" { + source = "../../modules/cloud-guard" + count = var.enable_cloud_guard ? 1 : 0 + tenancy_ocid = var.tenancy_ocid + region = var.region + status = local.cloud_guard.status + compartment_id = local.cloud_guard.compartment_id + display_name = local.cloud_guard.display_name + target_resource_id = local.cloud_guard.target_resource_id + target_resource_type = local.cloud_guard.target_resource_type + description = local.cloud_guard.description + configuration_detector_recipe_display_name = local.cloud_guard.configuration_detector_recipe_display_name + activity_detector_recipe_display_name = local.cloud_guard.activity_detector_recipe_display_name + threat_detector_recipe_display_name = local.cloud_guard.threat_detector_recipe_display_name + responder_recipe_display_name = local.cloud_guard.responder_recipe_display_name + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} + +module "vss" { + source = "../../modules/vss" + recipe_compartment_ocid = var.security_compartment_id + target_compartment_ocid = var.environment_compartment_id + host_scan_recipe_agent_settings_scan_level = local.vss.host_scan_recipe_agent_settings_scan_level + host_scan_recipe_port_settings_scan_level = local.vss.host_scan_recipe_port_settings_scan_level + agent_cis_benchmark_settings_scan_level = local.vss.agent_cis_benchmark_settings_scan_level + vss_scan_schedule = local.vss.vss_scan_schedule + host_scan_recipe_display_name = local.vss.host_scan_recipe_display_name + host_scan_target_display_name = local.vss.host_scan_target_display_name +} + +module "bastion" { + source = "../../modules/bastion" + count = var.enable_bastion ? 1 : 0 + target_subnet_id = var.bastion_target_subnet_id + bastion_client_cidr_block_allow_list = var.bastion_client_cidr_block_allow_list + bastion_name = local.bastion.name + compartment_id = var.security_compartment_id +} + +module "vault" { + source = "../../modules/vault" + # vault_type = "NONE" is used for testing. + count = var.vault_type != "NONE" ? 1 : 0 + compartment_id = var.security_compartment_id + display_name = local.vault.name + vault_type = var.vault_type + replica_region = var.replica_region + enable_replication = var.enable_replication +} + +module "key" { + source = "../../modules/key" + count = local.create_key ? 1 : 0 + compartment_ocid = var.security_compartment_id + display_name = local.key.name + shape_algorithm = local.key.shape_algorithm + shape_length = local.key.shape_length + protection_mode = local.key.protection_mode + management_endpoint = module.vault[0].management_endpoint + + depends_on = [module.vault] +} + +module "key_policy" { + source = "../../modules/policies" + count = local.create_key ? 1 : 0 + compartment_ocid = var.home_compartment_id + description = local.key_policy.description + policy_name = local.key_policy.name + statements = local.key_policy.statements +} \ No newline at end of file diff --git a/templates/elz-security/outputs.tf b/templates/elz-security/outputs.tf new file mode 100644 index 00000000..88c754e0 --- /dev/null +++ b/templates/elz-security/outputs.tf @@ -0,0 +1,11 @@ +output "key_id" { + value = local.create_key ? module.key[0].key_ocid : null +} + +output "bastion_id" { + value = var.enable_bastion ? module.bastion[0].bastion_ocid : null +} + +output "vault_id" { + value = var.vault_type != "NONE" ? module.vault[0].management_endpoint : null +} \ No newline at end of file diff --git a/templates/elz-security/provider.tf b/templates/elz-security/provider.tf new file mode 100644 index 00000000..23554840 --- /dev/null +++ b/templates/elz-security/provider.tf @@ -0,0 +1,72 @@ +# ----------------------------------------------------------------------------- +# Provider Requirements if using stack as a module +# ----------------------------------------------------------------------------- +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + version = "4.96.0" # October 05, 2022 Release + configuration_aliases = [oci, oci.home_region] + } + } +} + +# # ----------------------------------------------------------------------------- +# # WARNING! +# # UNCOMMENT EVERYTHING BELOW AND COMMENT EVERYTHING ABOVE IF YOU WISH TO USE THIS +# # STACK AS A STANDALONE - DO NOT TOUCH IF USING THIS STACK IN A MODULE CALL +# # Provider Requirements if using stack as standalone +# # ----------------------------------------------------------------------------- +# terraform { +# required_version = ">= 1.0.0" + +# required_providers { +# oci = { +# source = "oracle/oci" +# version = "4.96.0" # October 05, 2022 Release +# } +# } +# } + +# # ----------------------------------------------------------------------------- +# # Provider blocks for home region and alternate region(s) +# # ----------------------------------------------------------------------------- +# provider "oci" { +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = var.region +# } + +# provider "oci" { +# alias = "home_region" +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = local.home_region[0] +# } + +# # ----------------------------------------------------------------------------- +# # Provider Variables +# # ----------------------------------------------------------------------------- +# variable "current_user_ocid" { +# type = string +# description = "The OCID of the current user" +# default = "" +# } + +# variable "api_fingerprint" { +# type = string +# description = "The fingerprint of API" +# default = "" +# } + +# variable "api_private_key_path" { +# type = string +# description = "The local path to the API private key" +# default = "" +# } diff --git a/templates/elz-security/variables.tf b/templates/elz-security/variables.tf new file mode 100644 index 00000000..d5138f49 --- /dev/null +++ b/templates/elz-security/variables.tf @@ -0,0 +1,86 @@ +variable "home_compartment_id" { + type = string + description = "the OCID of the compartment where the environment will be created. In general, this should be the Landing zone parent compartment." +} + +variable "home_compartment_name" { + type = string + description = "Landing Zone home compartment name" +} + +variable "resource_label" { + type = string + description = "Prefix used to avoid naming conflict" +} + +variable "enable_cloud_guard" { + type = bool + description = "true if you don't have cloud guard enabled, false if you've already have cloud guard enabled." +} + +variable "environment_prefix" { + type = string + description = "the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U" +} + +variable "tenancy_ocid" { + type = string + description = "The OCID of tenancy" +} + +variable "cloud_guard_target_tenancy" { + type = bool + description = "true if cloud guard targets to tenancy, false if cloud guard targets to Landing Zone home compartment" +} + +variable "region" { + type = string + description = "The OCI region" +} + +variable "security_compartment_id" { + type = string + description = "The OCID of security compartment" +} + +variable "environment_compartment_id" { + type = string + description = "The OCID of environment compartment" +} + +// Bastion Variables +variable "bastion_target_subnet_id" { + type = string + description = "The OCID of the subnet that the bastion connects to" +} + +variable "bastion_client_cidr_block_allow_list" { + type = list(string) + description = "A list of address ranges in CIDR notation that you want to allow to connect to sessions hosted by this bastion." +} + +variable "enable_bastion" { + type = bool + description = "Option to enable bastion service" +} + +// Vault & Key Variables +variable "vault_type" { + type = string + description = "The type of vault to create. " +} + +variable "replica_region" { + type = string + description = "the region to be created replica to." +} + +variable "enable_replication" { + type = bool + description = "Option to enable vault replication" +} + +variable "create_master_encryption_key" { + type = bool + description = "Option create master encryption key" +} \ No newline at end of file diff --git a/templates/elz-tagging/README.md b/templates/elz-tagging/README.md new file mode 100644 index 00000000..93ffaa13 --- /dev/null +++ b/templates/elz-tagging/README.md @@ -0,0 +1,43 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [oci](#requirement\_oci) | 4.96.0 | + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | 4.96.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [elz\_tagging](#module\_elz\_tagging) | ../../modules/tag | n/a | + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_region_subscriptions.regions](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/identity_region_subscriptions) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [cost\_center\_tagging](#input\_cost\_center\_tagging) | Compartment Cost Center Tag. | `string` | n/a | yes | +| [enable\_tagging](#input\_enable\_tagging) | Set to true to enable Tagging. | `bool` | n/a | yes | +| [environment\_compartment\_id](#input\_environment\_compartment\_id) | The OCID of the compartment. | `string` | n/a | yes | +| [environment\_compartment\_name](#input\_environment\_compartment\_name) | The OCID of the compartment. | `string` | n/a | yes | +| [environment\_prefix](#input\_environment\_prefix) | the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U | `string` | n/a | yes | +| [geo\_location\_tagging](#input\_geo\_location\_tagging) | Compartment Geo Location Tag. | `string` | n/a | yes | +| [region](#input\_region) | The OCI region | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | Set to true to enable Tagging. | `string` | n/a | yes | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/templates/elz-tagging/datasources.tf b/templates/elz-tagging/datasources.tf new file mode 100644 index 00000000..3e483838 --- /dev/null +++ b/templates/elz-tagging/datasources.tf @@ -0,0 +1,12 @@ +# ----------------------------------------------------------------------------- +# Support for multi-region deployments +# ----------------------------------------------------------------------------- +locals { + region_subscriptions = data.oci_identity_region_subscriptions.regions.region_subscriptions + home_region = [for region in local.region_subscriptions : region.region_name if region.is_home_region == true] + region_key = [for region in local.region_subscriptions : region.region_key if region.region_name == var.region] +} + +data "oci_identity_region_subscriptions" "regions" { + tenancy_id = var.tenancy_ocid +} diff --git a/templates/elz-tagging/main.tf b/templates/elz-tagging/main.tf new file mode 100644 index 00000000..2d2cc581 --- /dev/null +++ b/templates/elz-tagging/main.tf @@ -0,0 +1,58 @@ +locals { + elz_tagging = { + tag_namespace_description = "Tenancy Level Tag" + tag_namespace_name = "ELZ-${var.environment_prefix}-Namespace" + is_namespace_retired = false + tag_map = { + cost_center = { + description = "Cost Center" + name = "Cost_Center" + is_cost_tracking = false + is_retired = false + } + geo_location = { + description = "Geo Location" + name = "Geo_Location" + is_cost_tracking = false + is_retired = false + } + environment_prefix = { + description = "Environment" + name = "Environment_Prefix" + is_cost_tracking = false + is_retired = false + } + } + tag_default_map = { + cost_center_tag = { + compartment_id = var.environment_compartment_id + tag_definition_name = "cost_center" + value = var.cost_center_tagging + is_required = false + } + geo_location = { + compartment_id = var.environment_compartment_id + tag_definition_name = "geo_location" + value = var.geo_location_tagging + is_required = false + } + environment_prefix = { + compartment_id = var.environment_compartment_id + tag_definition_name = "environment_prefix" + value = var.environment_prefix + is_required = false + } + } + } +} + +module "elz_tagging" { + count = var.enable_tagging ? 1 : 0 + source = "../../modules/tag" + compartment_id = var.tenancy_ocid + tag_namespace_description = local.elz_tagging.tag_namespace_description + tag_namespace_name = local.elz_tagging.tag_namespace_name + is_namespace_retired = local.elz_tagging.is_namespace_retired + tag_map = local.elz_tagging.tag_map + tag_default_map = local.elz_tagging.tag_default_map +} diff --git a/templates/elz-tagging/provider.tf b/templates/elz-tagging/provider.tf new file mode 100644 index 00000000..2bbda84d --- /dev/null +++ b/templates/elz-tagging/provider.tf @@ -0,0 +1,72 @@ +# ----------------------------------------------------------------------------- +# Provider Requirements if using stack as a module +# ----------------------------------------------------------------------------- +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + version = "4.96.0" # October 05, 2022 Release + configuration_aliases = [oci, oci.home_region] + } + } +} + +# # ----------------------------------------------------------------------------- +# # WARNING! +# # UNCOMMENT EVERYTHING BELOW AND COMMENT EVERYTHING ABOVE IF YOU WISH TO USE THIS +# # STACK AS A STANDALONE - DO NOT TOUCH IF USING THIS STACK IN A MODULE CALL +# # Provider Requirements if using stack as standalone +# # ----------------------------------------------------------------------------- +# terraform { +# required_version = ">= 1.0.0" + +# required_providers { +# oci = { +# source = "oracle/oci" +# version = "4.96.0" # October 05, 2022 Release +# } +# } +# } + +# # ----------------------------------------------------------------------------- +# # Provider blocks for home region and alternate region(s) +# # ----------------------------------------------------------------------------- +# provider "oci" { +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = var.region +# } + +# provider "oci" { +# alias = "home_region" +# tenancy_ocid = var.tenancy_ocid +# user_ocid = var.current_user_ocid +# fingerprint = var.api_fingerprint +# private_key_path = var.api_private_key_path +# region = local.home_region[0] +# } + +# # ----------------------------------------------------------------------------- +# # Provider Variables +# # ----------------------------------------------------------------------------- +# variable "current_user_ocid" { +# type = string +# description = "The OCID of the current user" +# default = "" +# } + +# variable "api_fingerprint" { +# type = string +# description = "The fingerprint of API" +# default = "" +# } + +# variable "api_private_key_path" { +# type = string +# description = "The local path to the API private key" +# default = "" +# } diff --git a/templates/elz-tagging/variables.tf b/templates/elz-tagging/variables.tf new file mode 100644 index 00000000..b2b1fe4e --- /dev/null +++ b/templates/elz-tagging/variables.tf @@ -0,0 +1,37 @@ +variable "environment_compartment_id" { + type = string + description = "The OCID of the compartment." +} + +variable "environment_compartment_name" { + type = string + description = "The OCID of the compartment." +} + +variable "cost_center_tagging" { + type = string + description = "Compartment Cost Center Tag." +} + +variable "geo_location_tagging" { + type = string + description = "Compartment Geo Location Tag." +} + +variable "enable_tagging" { + type = bool + description = "Set to true to enable Tagging." +} + +variable "environment_prefix" { + type = string + description = "the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U" +} +variable "tenancy_ocid" { + type = string + description = "Set to true to enable Tagging." +} +variable "region" { + type = string + description = "The OCI region" +} \ No newline at end of file diff --git a/templates/elz-workload/CONFIGURATION.md b/templates/elz-workload/CONFIGURATION.md new file mode 100644 index 00000000..055342f9 --- /dev/null +++ b/templates/elz-workload/CONFIGURATION.md @@ -0,0 +1,12 @@ +## Configuration Guide (DO NOT UPDATE) + +### Compartment +For the Workload stack, we have the below compartment architecture: +* Workload + +To configure the compartment the required user inputs are: +* **enviroment_compartment_id**: the OCID of the higher level environment compartment +* **workload_compartment_name**: the name of workload compartment, by default OCI-ELZ-- +* **workload_name**: the name of the workload +* **home_compartment_id**: the OCID of the compartment that the environment compartment build on. + diff --git a/templates/elz-workload/README.md b/templates/elz-workload/README.md new file mode 100644 index 00000000..fe3c9146 --- /dev/null +++ b/templates/elz-workload/README.md @@ -0,0 +1,56 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [oci](#requirement\_oci) | 4.96.0 | + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | 4.96.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [workload\_compartment](#module\_workload\_compartment) | ../../modules/compartment | n/a | +| [workload\_critical\_topic](#module\_workload\_critical\_topic) | ../../modules/notification-topic | n/a | +| [workload\_warning\_topic](#module\_workload\_warning\_topic) | ../../modules/notification-topic | n/a | + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_region_subscriptions.regions](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/identity_region_subscriptions) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [enable\_compartment\_delete](#input\_enable\_compartment\_delete) | Set to true to allow the compartments to delete on terraform destroy. | `bool` | `true` | no | +| [enable\_network\_monitoring\_alarms](#input\_enable\_network\_monitoring\_alarms) | Enable Network Monitoring Alarms in Network Compartment | `bool` | n/a | yes | +| [enable\_security\_monitoring\_alarms](#input\_enable\_security\_monitoring\_alarms) | Enable Security Monitoring Alarms in Security Compartment | `bool` | n/a | yes | +| [enable\_workload\_monitoring\_alarms](#input\_enable\_workload\_monitoring\_alarms) | Enable Workload Monitoring Alarms in Workload Compartment | `bool` | n/a | yes | +| [environment\_compartment\_id](#input\_environment\_compartment\_id) | n/a | `string` | n/a | yes | +| [environment\_prefix](#input\_environment\_prefix) | the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U | `string` | n/a | yes | +| [network\_compartment\_id](#input\_network\_compartment\_id) | the OCID of the compartment where the environment will be created. In general, this should be the Landing zone parent compartment. | `string` | n/a | yes | +| [network\_topic\_endpoints](#input\_network\_topic\_endpoints) | List of email addresses for Network Warning and Critical notifications. | `list(string)` | `[]` | no | +| [region](#input\_region) | The OCI region | `string` | n/a | yes | +| [secops\_topic\_endpoints](#input\_secops\_topic\_endpoints) | List of email addresses for Secops Warning and Critical notifications. | `list(string)` | `[]` | no | +| [security\_compartment\_id](#input\_security\_compartment\_id) | the OCID of the compartment where the environment will be created. In general, this should be the Landing zone parent compartment. | `string` | n/a | yes | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | +| [workload\_compartment\_id](#input\_workload\_compartment\_id) | the OCID of the compartment where the environment will be created. In general, this should be the Landing zone parent compartment. | `string` | `""` | no | +| [workload\_compartment\_name](#input\_workload\_compartment\_name) | The name of the workload compartment by default OCI-ELZ--. | `string` | `""` | no | +| [workload\_name](#input\_workload\_name) | The name of the workload. | `string` | n/a | yes | +| [workload\_topic\_endpoints](#input\_workload\_topic\_endpoints) | List of email addresses for Workload notifications. | `list(string)` | `[]` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [compartment\_id](#output\_compartment\_id) | The ocid of workload compartment | +| [compartment\_name](#output\_compartment\_name) | The Workload Compartment Name | + \ No newline at end of file diff --git a/templates/elz-workload/datasources.tf b/templates/elz-workload/datasources.tf new file mode 100644 index 00000000..3e483838 --- /dev/null +++ b/templates/elz-workload/datasources.tf @@ -0,0 +1,12 @@ +# ----------------------------------------------------------------------------- +# Support for multi-region deployments +# ----------------------------------------------------------------------------- +locals { + region_subscriptions = data.oci_identity_region_subscriptions.regions.region_subscriptions + home_region = [for region in local.region_subscriptions : region.region_name if region.is_home_region == true] + region_key = [for region in local.region_subscriptions : region.region_key if region.region_name == var.region] +} + +data "oci_identity_region_subscriptions" "regions" { + tenancy_id = var.tenancy_ocid +} diff --git a/templates/elz-workload/iam.tf b/templates/elz-workload/iam.tf new file mode 100644 index 00000000..df2fdf97 --- /dev/null +++ b/templates/elz-workload/iam.tf @@ -0,0 +1,22 @@ +# ----------------------------------------------------------------------------- +# Compartment Resources +# ----------------------------------------------------------------------------- +locals { + workload_compartment = { + name = var.workload_compartment_name != "" ? var.workload_compartment_name : "OCI-ELZ-${var.environment_prefix}-${var.workload_name}-${local.region_key[0]}" + description = "Workload Compartment" + } +} + +module "workload_compartment" { + source = "../../modules/compartment" + + compartment_parent_id = var.environment_compartment_id + compartment_name = local.workload_compartment.name + compartment_description = local.workload_compartment.description + enable_compartment_delete = var.enable_compartment_delete + + providers = { + oci = oci.home_region + } +} diff --git a/templates/elz-workload/monitoring.tf b/templates/elz-workload/monitoring.tf new file mode 100644 index 00000000..8848c642 --- /dev/null +++ b/templates/elz-workload/monitoring.tf @@ -0,0 +1,217 @@ +########################################################################### +####### WORKLOAD MONITORING ALARMS DEFINITION ######## +########################################################################### + +locals { + workload_critical_topic = { + topic_name = "${var.environment_prefix}-Workload-Critical" + topic_description = "OCI Landing Zone Critical Workload Topic" + subscription_protocol = "EMAIL" + } + workload_warning_topic = { + topic_name = "${var.environment_prefix}-Workload-Warning" + topic_description = "OCI Landing Zone Warning Workload Topic" + subscription_protocol = "EMAIL" + } + alarm_policy = { + name = "${var.environment_prefix}-Policy" + description = "OCI Alarm Policy" + + statements = [ + < 0] + ) == length(var.workload_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} +variable "network_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Network Warning and Critical notifications." + validation { + condition = length( + [for e in var.network_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.network_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "secops_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Secops Warning and Critical notifications." + validation { + condition = length( + [for e in var.secops_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.secops_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "enable_security_monitoring_alarms" { + type = bool + description = "Enable Security Monitoring Alarms in Security Compartment" +} +variable "enable_network_monitoring_alarms" { + type = bool + description = "Enable Network Monitoring Alarms in Network Compartment" +} +variable "enable_workload_monitoring_alarms" { + type = bool + description = "Enable Workload Monitoring Alarms in Workload Compartment" +} +variable "environment_compartment_id" { + type = string +} \ No newline at end of file diff --git a/templates/enterprise-landing-zone/.module-tf-docs.yml b/templates/enterprise-landing-zone/.module-tf-docs.yml new file mode 100644 index 00000000..c8339416 --- /dev/null +++ b/templates/enterprise-landing-zone/.module-tf-docs.yml @@ -0,0 +1,13 @@ +formatter: "markdown table" + +recursive: + enabled: true + path: ../../modules + +output: + file: "README.md" + mode: insert + template: |- + + {{ .Content }} + diff --git a/templates/enterprise-landing-zone/.terraform-docs.yml b/templates/enterprise-landing-zone/.terraform-docs.yml new file mode 100644 index 00000000..904d9026 --- /dev/null +++ b/templates/enterprise-landing-zone/.terraform-docs.yml @@ -0,0 +1,13 @@ +formatter: "markdown table" + +recursive: + enabled: true + path: ../ + +output: + file: "README.md" + mode: insert + template: |- + + {{ .Content }} + diff --git a/templates/enterprise-landing-zone/Architecture_Guide.md b/templates/enterprise-landing-zone/Architecture_Guide.md new file mode 100644 index 00000000..efadfc84 --- /dev/null +++ b/templates/enterprise-landing-zone/Architecture_Guide.md @@ -0,0 +1,433 @@ +# Architectural Guide + +# **Intro** + +As described in the previous version of the Enterprise Landing Zone v1, the new Oracle Enterprise Scale Baseline Landing Zone v2.0 (ESBLZ v2.0) is a set of foundational services and components that are deployed in a customer's OCI tenancy to establish a secure and scalable network foundation for running enterprise workloads. + +The new version of Oracle Cloud Infrastructure (OCI) Enterprise Scale Baseline Landing Zone is a set of Terraform modules that are designed to make it easy to set up a secure and compliant multi-account infrastructure on OCI. Some common use cases for OCI Enterprise Scale Baseline Landing Zone include: + +- Multi-cloud architectures: The ESBLZv2 can be used to create a landing zone for connecting to other clouds, such as Azure, for a hybrid cloud architecture. +- Governance and compliance: The ESBLZv2 provides a set of pre-built policies and guardrails that help ensure that your OCI environment is compliant with industry standards, such as ISO27001 and PCI DSS (these and other compliance standards will be part of ongoing releases). +- Automation and scalability: The Landing Zone can be used to automate the creation of new accounts, users, and resources on OCI, making it easy to scale your infrastructure as your organization grows. + +# **Primary Objectives** + +The primary objectives of the ESBLZv2 zone include the following items: + +- Reduce time-to-start and deploy. +- Provide an architecturally strong foundation. +- Maintain the flexibility to customize and evolve the implementation to your organization's needs. + +# **Key Design Principles** + +Key design principles for resiliency and security ensure that the ESBLZv2 zone deploys a strong foundation for your cloud environment. + +## **_Resiliency_** + +A resilient cloud architecture helps you to avoid single points of failure for your cloud-based workloads. + +At the infrastructure level, OCI provides physical and logical resources to help you design for resiliency, such as [regions, availability domains, and fault domains](https://docs.oracle.com/iaas/Content/General/Concepts/regions.htm). + +Resiliency depends on the nature, architecture, and implementation of the workloads that you plan to deploy on OCI. For best practices, see [Resilience and Continuous Availability of Oracle Cloud Infrastructure Services and Platform FAQ](https://www.oracle.com/cloud/iaas/faq.html) and [Best practices for designing reliable and resilient cloud topologies](https://docs.oracle.com/en/solutions/oci-best-practices-resilience/reliable-and-resilient-cloud-topology-practices1.html). + +## **_Security_** + +The Enterprise Scale Baseline Landing Zone follows best practices for security design principles. + +- Design for attackers + - Limit permissions based on requirements + - Enforce network segmentation +- Leverage native controls +- Use identity as primary access control +- Accountability +- Embrace automation +- Focus on information protection +- Design for resilience + - Ongoing vigilance + - Defense in depth + - Defense at edge + - Least privilege +- Assume zero trust + +For more information, see the security design principles in [Best practices framework for Oracle Cloud Infrastructure](https://docs.oracle.com/en/solutions/oci-best-practices/effective-strategies-security-and-compliance1.html#GUID-68F2BA09-96CE-48A4-B92E-8F928EE86F13). + +# **Architecture Overview** + +The ESBLZv2 creates an architectural framework that's ready for you to launch new projects and workloads on OCI. + +- [Compartments](https://docs.oracle.com/en-us/iaas/Content/cloud-adoption-framework/landing-zone.htm#compartments): Use compartments to organize and isolate your resources to make it easier to manage and secure access to them. +- [Tags](https://docs.oracle.com/en-us/iaas/Content/cloud-adoption-framework/landing-zone.htm#tags): Use tags to organize and list resources based on your business needs. +- [Budgets and alerts](https://docs.oracle.com/en-us/iaas/Content/cloud-adoption-framework/landing-zone.htm#budgets-alerts): Use [budgets](https://docs.oracle.com/iaas/Content/Billing/Concepts/budgetsoverview.htm) to set soft limits on your OCI spending, and use alerts to let you know when you might exceed your budget. +- [Oracle Cloud Infrastructure Identity and Access Management (IAM)](https://docs.oracle.com/en-us/iaas/Content/cloud-adoption-framework/landing-zone.htm#iam): Use IAM to control access to your cloud resources on OCI. +- [Networking and connectivity](https://docs.oracle.com/en-us/iaas/Content/cloud-adoption-framework/landing-zone.htm#networking-connectivity): Create a virtual cloud network (VCN), subnets, and other networking and connectivity resources that are required to run your workloads and connect to the internet or your on-premises network. +- [Security](https://docs.oracle.com/en-us/iaas/Content/cloud-adoption-framework/landing-zone.htm#security): Enable a strong security posture by enabling OCI security services such as Oracle Cloud Guard, Oracle Vulnerability Scanning Service, and Oracle Cloud Infrastructure Bastion. + +The following diagram illustrates the ESBLZv2.0 reference architecture. + +![](./images/enterprise-landing-zone-v2.svg) + +## **_Network and Connectivity_** + +One of the key components of the Enterprise Scale Baseline Landing Zone v2.0 (ESBLZ v2.0) is the network architecture and its segmentation. With the adoption of the ESBLZ v2.0, you can have a highly segregated, functional environment to securely deploy your workloads. One of the key components of the network architecture is the use of the Hub & Spoke architecture the ESBLZ v2.0 will provide two distinct Hub & Spoke architectures (one for the Production environment and one for non-Production environments) that are segregated from each other. + +In Oracle Cloud Infrastructure (OCI), the [Hub & Spoke architecture](https://docs.oracle.com/en/solutions/hub-spoke-network-drg/index.html#GUID-FB5990CB-A23B-482D-80F4-AE4A548DEC9C) is a network design pattern in which a central hub network is connected to multiple spoke networks. The hub network is typically used for shared resources, such as security appliances and core services, while the spoke networks are used for individual workloads or applications. + +The Hub & Spoke architecture deployed within the ESBLZ can provide several benefits, including: + +1. Isolation: Each spoke is its own compartment, which provides an additional layer of isolation and security for resources. This allows for better management and control over access to resources and limits the blast radius of any security incident. +2. Scalability: Spokes can be added or removed as needed to support different use cases or teams. This allows for a flexible and scalable architecture that can adapt to changing business needs. +3. Networking: A hub provides a central point for all network traffic to flow through, which simplifies the overall network architecture and improves security. Resources in different spokes can communicate with each other over the hub-spoke network without having to traverse the internet. +4. Resource Management: Each spoke can be managed and administered independently, which allows for better resource allocation and more efficient use of resources. It also allows for different teams or business units to manage their own resources, with the ability to have different access to control and management. +5. Cost Optimization: By centralizing certain resources, like VPN gateways and load balancers, in the hub, it can be more cost-effective to manage them. +6. Governance: By having a central hub it becomes much more easier to apply governance rules and policies across the whole infrastructure and have a clear view of all the resources and activity going on in your enterprise. + +It's important to notice that this architecture is really flexible, so some of the components in the hub, like load balancer, could be moved to the Spoke, depending on the use case or need. + +In ESBLZ v2.0 OCI, the hub network is created using a Virtual Cloud Network (VCN) in the Network Shared Infrastructure compartment in each environment, and the spoke networks are created in each Application compartment, using VCN Attachment through a [Dynamic Routing Gateway (DRG)](https://docs.oracle.com/en-us/iaas/Content/Network/Tasks/managingDRGs.htm). This allows the spoke networks to access the shared resources in the hub network while maintaining their isolation from each other. + +Overall, the Hub & Spoke architecture is a flexible and scalable design pattern that can be used to build complex network architectures in OCI and this is one of the main reasons why ESBLZ v2.0 will allow you to have a pre-configured environment ready to use within minutes. + +For more information on the network architecture components, please refer to the sections of the modules that compose it. + +## **_Logging and Monitoring_** + +Two other key components of the ESBLZ are the monitoring and logging of the resources that will be part of it. These two areas are particularly important within the IT Governance and Operations of each enterprise. + +[Monitoring](https://docs.oracle.com/en-us/iaas/Content/Monitoring/Concepts/monitoringoverview.htm) and [logging](https://docs.oracle.com/en-us/iaas/Content/Logging/Concepts/loggingoverview.htm) are important in the ESBLZ v2.0 because they help you to understand the performance and availability of your cloud resources and applications. They can also help you to identify and troubleshoot issues and maintain compliance with regulatory requirements. + +By monitoring your resources, you can ensure that they are performing as expected and that they have sufficient capacity to meet the demands of your applications. This can help you optimize your cloud environment's performance and cost efficiency. + +Logging lets you record events and activities in your cloud environment. This can be useful for a variety of purposes, such as auditing, debugging, and analysing trends. + +Overall, monitoring and logging are critical for the operation, maintenance, and security of your OCI cloud environment. + +For more information on the monitoring and logging components, please refer to the sections of the modules that compose them. + +## **_Multi environment_** + +In order to support multiple environments, the landing zone deploys two isolated environments: + +- Production Environment for your production workloads +- Non-production environment for your development or other workloads. + +Both of these environments are isolated from each other in different ways: + +- Each environment has a separate identity domain, so users are isolated on a single environment and non-production users won't have access to production resources. +- Each environment has its own hub and spoke network. +- Each environment has its own Cloud Guard target +- Each environment has a separate logging and monitoring configuration + +This separation of environments allows you to secure deploy production workloads and non-production workloads without having to worry about resources being able to access resources from a different environment. + +In addition to the two default environments, the Environments module allows you to deploy additional environments if you require one. These additional environments will have the same isolation to the other environment as described above. + +## **_Identity_** + +Use Oracle Cloud Infrastructure Identity and Access Management (IAM) to control access to your cloud resources on OCI. + +The Landing Zone creates IAM groups and policies that control access to the resources created by the Landing Zone. Optionally, you can federate with your organization's Microsoft Active Directory implementation. + +We recommend that you create one or more [break-glass users](https://docs.oracle.com/en-us/iaas/Content/cloud-adoption-framework/deploy-landing-zone.htm#emergency-access-accounts) during your deployment, especially if you are using federation. Break-glass users are administrators who have emergency access to all Oracle Cloud Infrastructure services and resources in the tenancy. + +**Federating with Microsoft Active Directory** + +With the ESBLZv2, you can optionally federate with Microsoft Active Directory. + +Use the same group names in Oracle Cloud Infrastructure as you use for Active Directory. To do this, pass the Active Directory group names as variables to the ESBLZv2 Terraform module. The groups will be created by the landing zone and mapped to your Active Directory groups. + +For more information about federating with Active Directory, see [Federating with Microsoft Active Directory](https://docs.oracle.com/iaas/Content/Identity/Tasks/federatingADFS.htm). + +## _Compliance_ + +ESBLZv2 includes a set of pre-built policies and guardrails that help ensure that your OCI environment has a strong security foundation to help your organization achieve your security compliance goals. The security controls that have been implemented in ESBLZv2 include recommendations that help our customers attain [CIS 1.2](https://www.cisecurity.org/benchmark/oracle_cloud) compliance Level 1. + +The Center for Internet Security, Inc. (CIS®) is a community-driven non-profit, responsible for the CIS Controls® and CIS Benchmarks™, globally recognized best practices for securing IT systems and data. The goal of CIS is to prevent and mitigate new cyber threats that are identified in the industry today. For many OCI customers, this has been a go-to benchmark that guides their architecture to help them secure their workloads in Oracle Cloud Infrastructure (OCI). Recognizing the importance of adhering to best practice guidance from both OCI teams and the industry, OCI Landing Zones continues to implement support for CIS Benchmarks today. + +For more information, please refer to ["CIS 1.2 Level 1"](./images/CIS1.2Level1.xlsx) for a list of security controls that are included in ESBLZv2. + +# **Functional Modules** + +The ESBLZ is comprised out of different functional modules. Each of these modules is a set of terraform scripts that groups a functional area of the landing zone. + These modules have been designed so they can be customized and run independently. This makes the ESBLZv2 more flexible and allows the customers to tweak it to their needs. + +Below is a detailed description of the different modules + +## **ESBLZ _Landing Zone Module_** + +The Landing Zone Module is the module that brings everything together. It creates the entire Landing Zone by invoking the other modules. + The ESBLZv2 deploys two isolated environments as depicted on the diagram above. + This module invokes the environment module twice, each for a distinct isolated environment: + +- Environment Module to create the production environment +- Environment Module to create the non-Production environment + +This module is also responsible for creating the Landing Zone parent compartment but apart from that, it doesn't deploy any other resources and relies on the environment module for the deployment of an environment. + +## **_Environment Module_** + +The Environment Module is a module that aggregates the other modules into a single environment. It uses the following modules to compose an isolated environment in the Landing Zone: + +- Compartment Module +- Budget and Tagging Module +- Identity Module +- Network Module +- Security Module +- Monitoring Module +- Logging Module + +The module in its own doesn't create any additional resources. It only aggregates the other functional modules. + +## **_Budgets and Tagging Module_** + +Budget & Tagging are another two key components to achieve strong Governance within the ESBLZ v2.0. + +Budgeting and tagging are important in the Oracle Cloud Infrastructure (OCI) ESBLZ v2.0 because they help you to manage and optimize the cost of your cloud resources. + +Budgeting allows you to set limits on your cloud spending, and to receive notifications when your usage approaches or exceeds those limits. This can help you to avoid unexpected charges and to better control your cloud costs. + +Tagging allows you to assign metadata to your cloud resources, such as tags that represent the purpose, owner, or environment of those resources. You can then use tags to organize and manage your resources and to track your cloud costs by tag. For example, you might use tags to track the costs of different projects or departments or to identify resources that are eligible for discounts or credits. + +Overall, budgeting and tagging can help you to better understand your cloud usage and costs and to manage your resources more effectively in OCI. + +The customer will have the opportunity during deployment to enable or disable Budget and Tag for each environment. For more information about the Tagging Best Practice please refer to [Best Practices for Using Tags to Manage Costs, Operations, and Governance (oracle.com)](https://blogs.oracle.com/cloud-infrastructure/post/best-practices-for-using-tags-to-manage-costs-operations-and-governance) and [FinOps best practices for Oracle Cloud Infrastructure | CloudWorld 2022 - YouTube](https://www.youtube.com/watch?v=0ia5wMwrAuI). + +The main components that the Budget module will have been as follows: + +- 1 Budget per environment [Optional] + - If feature is enable - Budget scope: **L2- Environment compartment** + +The main components that the Tagging module will have been as follows: + +- 1 Tag namespace per environment [Optional] create in **L2- Environment compartment** + - If feature is enabled: + - Tag Environment + - Tag Cost Center + - Tag Geo Location + +## **_Compartments Module_** + +You use compartments to organize and isolate your resources to make it easier to manage and secure access to them. + +The ESBLZv2 creates a compartment structure for your organization. You control access to compartment by creating policies that specify what actions groups of users can take on the resources in those compartments. The following diagram shows the compartment structure that is created by the landing zone: + +![](./images/Compartment.png) + +The compartments module only creates the compartment structure for a single environment which include the following compartments: + +- **L2 - Environment:** The encapsulating compartment for an environment +- **L3 - Shared infrastructure** : compartment containing the shared infrastructure: + - **L4: Network** : The compartment that will hold the Hub component of the network + - **L4 Security** : The compartment holding the security and identity components +- **L3 - Workload** compartment that will hold a spoke connecting to the hub +- **L3 Logging** : Compartment that will hold a bucket to store the log files from the environment +- **L3 Backup** : A backup compartment that will contain the configuration and state file + +## **_Identity Module_** + +The identity module creates and configures an identity domain in an environment in the landing zone. + +In order to isolate access between resources, groups are created together with policies in order to restrict access to certain resources. + +- **Network Admin: ** User group that have access to the network resources inside your environment +- **SecOps Admin: ** User group that have access to the security related resources inside your environment +- **Identity Admin: ** User group that can manage the identity related resources +- **Platform Admin: ** User group that have access to usage reports and can manage budgets +- **Ops Admin: ** User group that have access to the metrics, events and alerts in your environment +- **Log Admin: ** User group that have access to the logs of your environment + +## **_Logging Module_** + +The Logging Module implemented by ESBLZv2 will use the below services to help your organization meet your Security Policy and Compliance requirements. + +- Vault (Key Management) +- Log Archiving Storage Bucket +- Default Log Group +- Streams & Events +- Service Connector + +**Log Archiving Storage Bucket (optional)** + +An optional immutable storage bucket will be deployed by default for the purposes of archiving logs and events within the defined retention period according to user input. The ESBLZv2 is deployed with a 1 day retention duration to facilitate environment clean up and this should be revised accordingly to comply with the retention requirements of your organization's security policies. + +**Default Log Group** + +OCI generates service logs for supported services and accordingly, users can enable or disable logging for each supported service. TheESBLZ default setting is to enable and store all service logs. For more information regarding [Service Logs](https://docs.oracle.com/en-us/iaas/Content/Logging/Concepts/service_logs.htm). + +**Streams & Events** + +OCI Streaming service is used for real-time ingestion of high-volume data streams. It can be used where data is continually produced and published sequentially such as with log events. The ESBLZv2 will utilize the OCI Streaming Service in conjunction with OCI events. OCI services generate _events_ that provide notifications when there are any resource changes in your environment. + +Please refer to [Services Event Types](https://docs.oracle.com/en-us/iaas/Content/Events/Reference/eventsproducers.htm#Services_that_Produce_Events) for a full list and refer to these links for more information regarding [Streaming](https://docs.oracle.com/en-us/iaas/Content/Streaming/home.htm) and [Events](https://docs.oracle.com/en-us/iaas/Content/Events/home.htm). + +**Service Connector Hub** + +Many organizations' security policies will stipulate a common archiving system should be made available for the purposes of storing systems, applications, security, and event logging. The Service Connector service will be used to ship all audit logs, service logs, and service events to object storage so that it can be made available for operational review. + +For more details regarding [Service Connector Hub](https://docs.oracle.com/en-us/iaas/Content/service-connector-hub/archivelogs.htm#Scenario_Archive_Log) + +## **_Monitoring Module_** + +The following module will allow the customer to be able to monitor their resources and receive the correct alerts in case of malfunctioning ESBLZ v2.0 components/ OCI tenancy. + +It provides a starting point that administrators can tweak according to their operational model. + +Services inside OCI provide metrics and events that can be monitored through the metrics dashboard. In addition to this, alerts can be created based on certain queries of these metrics and events. To organize these alerts, topics are created that will group certain alerts. In the landing zone, these topics are defined per the severity of the alert (critical and warning). Different topics are also created per compartment and environment (ex, PRD-Network, NPRD-Security and PRD-workload, etc.). Please refer to the next sub-paragraph for a detailed overview of these topics. + Each of these topics will have different monitoring rules assigned to them for each environment. + +To avoid excessive costs and a lot of messages, the ESBLZ v2.0 deployment will have all these alerts disabled by default. Based on your operational model, you can enable the relevant alerts from the OCI console. + +The monitoring structure contains following elements: + +- Monitor Alert Channels - Create Notification Topics (e.g. PRD-Network-Critical, NPRD-Security-Warning) and subscription (i.e. email) +- Monitor OCI service incidents and action required from OCI maintenance by subscribing to Console Announcements +- Monitor Cloud Guard status (e.g. problemthresholdreached) by subscribing Cloud Guard events +- Monitor VSS and Cloud Guard detected problem by subscribing Cloud Guard events +- Enable metrics-based monitoring of Network, Security, Logging and Workload compartments by creating sample alarm rules for the deployed service metrics namespaces + +Enable Logging Analytics for reporting via Log Explorer and Dashboards + +- Enable Logging Analytics at tenancy level +- Ingest logs (i.e. Default Log Group and Audit Logs) into Log Analytics via service connectors + +![](./images/Monitoring.png) + + **Operational Model** + +In order to organize alerts in meaningful groups, multiple alerts are grouped together for a compartment admin to subscribe to. + +- Workload X admin of a specific environment: receives alerts for the specific workload. +- Security admin of a specific environment: receives alerts for all resources in the Security compartment (Bastion, VSS, ... ) as well as security related notifications from Cloud Guard. +- Network admin of a specific environment: receives alerts for all resources in the Network compartment (Network HUB, DRG, Fast Connect). +- Identity admin of a specific environment: receives alerts related IAM +- Platform admin of a specific environment: receives alerts related Budgets + +In addition to this, messages are grouped into [Notification Topics](https://docs.oracle.com/en-us/iaas/Content/Notification/Tasks/managingtopicsandsubscriptions.htm) per severity (Critical and Warning) for each environment and compartment (Network, Security and Workload). + +| **#** | [**compartment\_id**](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/ons_notification_topic#compartment_id) | **name** | +| --- | --- | --- | +| 1 | \ | PRD-Network-Critical and NPRD-Network-Critical | +| 2 | \ | PRD-Network-Warning and NPRD-Network-Warning | +| 3 | \ | PRD-Security-Critical and NPRD-Security-Critical | +| 4 | \ | PRD-Security-Warning and PRD-Security-Warning | +| 5 | \< L3 -Workload X Compartment ID\> | \-Critical [part of Workload Expansion Module] | +| 6 | \< L3 -Workload X Compartment ID\> | \-Warning [part of Workload Expansion Module] | +| 7 | \ | PRD-Budget-Warning and NPRD-Budget-Warning | +| 8 | \ | PRD-IAM-Warning and NPRD-IAM-Warning | + +Admins of each compartment are able to subscribe to these topics so they will receive an email when an alert occurs. By default, a single E-Mail address will be used for all alert groups, however it is possible to overwrite these values in the console so each notification topic can be send to a different E-Mail address. + +**Monitoring Rules** + +The ESBLZ v2.0 will create many monitoring rules that can trigger alerts. These are disabled by default. You can enable the rules that apply to your operational needs from the OCI Console. + +For a complete list of events/alerts refer to the **ESBLZ v2.0 Deployment guide/ User Guide.** + +## **_Network Module_** + +The network module includes two main Functional Modules, the first will deploy a type of network called "Hub & Spoke" (H&P) that will allow the various workloads to interconnect with each other. The second one called "Network Extension Module" will extend connectivity with the on-premises network as well using the H&P created previously. +By default, the ESBLZ v2.0 will deploy the H&P module within the " **L2 - OCI-ELZ-\**" compartment (for **PROD** and **NO-PROD** ). Also, the Network Extension Module will be an optional module and it will only be allowed to be deployed in the production environment. As a result, it will be shared between the two environments prod and non-prod. + +The main components that the Hub module will have been as follows: + +- A **VCN** which will host the different subnets of the HUB deployed in the **L4 - Network compartment** +- A **public subnet** to host all internet-facing servers and resources, including load balancers, Web Servers...This subnet must be secured with the correct Cloud Guard recipes and other security features, as described in [Security paragraph](#ArchitecturalGuide-security)[.](#ArchitecturalGuide-securitymodule) +- A **private subnet** to host all common or shared services that your environment uses such as Network Virtual Appliance, Internal Jump Box Server. +- A **DRG** which will enable routing between the VNC Hub and other application VCNs (spokes), deployed in the **L4 - Network compartment** +- A **Internet Gateways** [Optional] which allows traffic between the public subnets in a VCN and the public internet, deployed in the **L4 - Network compartment** +- A **NAT Gateways** [Optional] which enables private resources in a VCN to access hosts on the internet, without exposing those resources to incoming internet connections, deployed in the **L4 - Network compartment** +- A **Service gateway** [Optional] which provides access from a VCN to other services, such as Oracle Cloud Infrastructure Object Storage. The traffic from the VCN to the Oracle service travels over the Oracle network fabric and never traverses the internet, deployed in the **L4 - Network compartment.** + +The main components that the Spoke module will have are as follows: + +- A **VCN** which will host the different subnets of the Spoke deployed in the **L3 - Workload compartment** +- Three **private subnets** to host all components of your application using different tier such as Web, App and DB. +- A **VCN Attachments** which will be connected to the DRG of the HUB. +- A **NAT Gateways** [Optional] which enables private resources in a VCN to access hosts on the internet, without exposing those resources to incoming internet connections, deployed in the **L3 - Workload compartment** +- A **Service gateway** [Optional] which provides access from a VCN to other services, such as Oracle Cloud Infrastructure Object Storage. The traffic from the VCN to the Oracle service travels over the Oracle network fabric and never traverses the internet, deployed in the **L3 - Workload compartment.** + +**NOTE :** In a scenario in which the customer wishes to publish its Web Servers using the ESBLZ v2.0, an Public Load Balancer must be deployed within the public subnet in the HUB ( **L4 - Network Compartment** ), which will have as endpoints the Web Servers present in the subnet that will be part of the **L3 - Workload compartment.** Since connectivity is already configured via the Hub & Spoke architecture, all that needs to be done is to change the Security Lists associated with the subnets to enable traffic between the Load Balancer and the endpoints. + +The Network extension module consists of two sub-modules that will allow the customer to decide whether to deploy a Site-to-Site VPN in each environment rather than share Fast Connect between environments. + +The main components that the VPN module will have are as follows: + +- A **Customer Premises Equipment (CPE)** deployed in the **L4 - Network compartment** , so traffic can flow between your on-premises network and virtual cloud network (VCN). +- An **IPsec Connection.** + +See these related topics: + +- + - [Networking](https://docs.oracle.com/en-us/iaas/Content/Network/Concepts/landing.htm#top): For general information about the parts of a VCN + - [Site-to-Site VPN](https://docs.oracle.com/en-us/iaas/Content/Network/Tasks/managingIPsec.htm#VPN_Connect): For various topics about IPsec VPNs + - [Verified CPE Devices](https://docs.oracle.com/en-us/iaas/Content/Network/Reference/CPElist.htm#Verified_CPE_Devices): For a list of CPE devices Oracle has verified. + +Using this module, you can decide during deployment to create a Site-to-Site VPN for each environment so that you can continue to have segregated traffic + +The main components that the Fast Connect module will have been as follows: + +- A **Fast Connect circuit** dedicated, private connection between your data center and Oracle Cloud Infrastructure, using your choice of Oracle partners deployed in the **L4 - Network compartment ** +- A **Remote Peering Connections (RPC) attachment** which will peer the DRGs of the two environments created during the ESBLZ v2.0 deployment. + +Using this module, the customer can decide whether or not to deploy a Fast Connect circuit by sharing it between environments. This decision was made because the Fast Connect service is generally more expensive than a Site-to-Site VPN. + +After deployment, if it is necessary to have other Fast Connect circuits, the customer will be able to create more but will have to change the Route Table set during deployment. While enabling this module, environments will continue to be segregated as traffic will be allowed or denied by the security lists applied to each subnet. + +. While enabling this module, environments will continue to be segregated as traffic will be allowed or denied by the security lists applied to each subnet. + +The security lists implemented during the ESBLZ v2.0 deployment are CIS 1.2.0 compliant, so all incoming traffic will be blocked except the ICMP protocol. For more information please refer to the CIS Benchmark 1.2.0 for Oracle Cloud Infrastructure: [CIS Oracle Cloud Infrastructure Benchmarks (cisecurity.org)](https://www.cisecurity.org/benchmark/oracle_cloud) + +## **_Security Module_** + +Oracle Cloud Infrastructure (OCI) is a Security-first Cloud Service that helps organizations reduce the risk of security threats for cloud workloads by putting our customers' Data Security and Privacy first. This is achieved via the automation of security operations with simple, prescriptive, and integrated cloud-native security capabilities built into the OCI platform. Oracle helps customers easily adopt OIC services and secure their cloud infrastructure, data, and applications. + +The ESBLZv2 further supports Oracle's Security-First Cloud strategy tenets: + +- Security should be simple—easy to use, deploy, and operate +- Security tools should offer guidance to help customers achieve strong security more easily +- Security should be integrated and automated, reducing manual security tasks and human errors +- Cloud security should be economically attractive, improving the cost of securing cloud workloads + +The following OCI cloud-native services will be implemented by ESBLZv2 to help your organization meet your Security Policy and Compliance requirements. + +- Cloud Guard +- Vulnerability Scanning Service (VSS) +- Vault (Key Management) +- Bastion + +**Cloud Guard** + +Cloud Guard is the OCI native security service that helps our customers monitor, identify threats/configuration issues, achieve a strong security posture and maintain compliance with their security policies. When issues are detected, Cloud Guard can recommend, assist or execute corrective actions based on how you configure Cloud Guard to respond. The ESBLZv2 will enable Cloud Guard services by default, and it will use your organization's tenancy home region as its reporting region. Cloud Guard is used in conjunction with VSS detector recipes. The following default Oracle Managed Detector Recipes will be enabled to provide a strong secure baseline for your organization's OCI environment: + +- Configuration Detector Recipe - Set of rules designed specifically to detect resource configuration settings that could pose a security problem. +- Threat Detector Recipe - Set of rules designed to specifically to detect rogue user activity and high-risk activity based on our Threat Intelligence Service. +- Activity Detector Recipe - Set of rules designed specifically to detect actions on resources that could pose a security problem + +These recipes can be used as the default Oracle-managed versions, or you can clone these recipes and use them to provide a strong baseline and further customize the recipes based on your requirements. + +It is not recommended to enable the Responder Recipe due to changes made during pre-production activities. The Responder Recipe should be enabled after completing a thorough review and testing. + +- Responder Recipe - Defines the action or set of actions to take in response to a problem that a detector has identified. + +If required, Cloud Guard findings can be pushed to 3rd Party SIEM, e.g. [Splunk HTTP Event Collector (HEC) via OCI SDK](https://blogs.oracle.com/cloudsecurity/post/push-cloud-guard-findings-to-splunk-hec). + +For more details, please refer to the official [OCI Cloud Guard documentation](https://docs.oracle.com/en-us/iaas/cloud-guard/home.htm). + +**Vulnerability Scanning Service (VSS)** + +OCI Vulnerability Scanning Service (VSS) can be scheduled to check hosts, detect open ports and container images for vulnerabilities. The default Oracle Detector Recipes will be used for scanning compute resources and the public port. These default recipes provide a foundational security posture baseline based on Oracle and industry security best practices. + +Please note that the Oracle Vulnerability Scanning Service is not compliant with PCI DSS requirements. OCI supports the use of Qualys agents which can be integrated with OCI VSS. + +For additional detail, please refer to our [Vulnerability Scanning Service (VSS)](https://docs.oracle.com/en-us/iaas/scanning/home.htm) documentation. + +**Vault (Key Management)** + +OCI Vault is our cloud-native encryption management service that will be used in this Landing Zone to store and manage Master Encryption Keys and Secrets that are used to secure your OCI resources and will be used to encrypt your logs. This ESBLZv2 landing zone will default to VIRTUAL. A Master Encryption Key (MEK) AES 256 will be generated by default as part of your Landing Zone deployment. This MEK will be used to encrypt your log object storage buckets. Customers can choose to "bring your own key" (BYOK) and import key material from your on-premises or 3rd-party cloud environments. In addition, OCI can provide a Hardware Security Module (HSM) dedicated vault service as an option. + +Please refer to [Vault (Key Management)](https://docs.oracle.com/en-us/iaas/Content/KeyManagement/Concepts/keyoverview.htm) for more details. + +**Bastion** + +OCI Bastions provides restricted and time-limited access to target resources that don't have public endpoints, letting authorized users connect from specific IP addresses to target resources using Secure Shell (SSH) sessions. This Landing Zone deployment will also include the OCI Bastion service which allows privileged users to connect from specified IP Addresses to target resources over Secure Shell (SSH). When connected via Bastion, users can interact with the target OCI resource by using any software or protocol supported by SSH. For example, you can use the Remote Desktop Protocol (RDP) to connect to a Windows host or use Oracle Net Services to connect to a database. The Bastion Service is associated with a single VCN and there is a limit of 5 Bastions per region. + +For more information, please see [OCI Bastion](https://docs.oracle.com/en-us/iaas/Content/Bastion/Concepts/bastionoverview.htm). \ No newline at end of file diff --git a/templates/enterprise-landing-zone/BackEnd.sh b/templates/enterprise-landing-zone/BackEnd.sh new file mode 100755 index 00000000..d7609ece --- /dev/null +++ b/templates/enterprise-landing-zone/BackEnd.sh @@ -0,0 +1,7 @@ +#! /bin/bash + +cat <> backend.tf +terraform { + backend "http" {} +} +EOT \ No newline at end of file diff --git a/templates/enterprise-landing-zone/CONFIGURATION.md b/templates/enterprise-landing-zone/CONFIGURATION.md new file mode 100644 index 00000000..77ae3612 --- /dev/null +++ b/templates/enterprise-landing-zone/CONFIGURATION.md @@ -0,0 +1,651 @@ +## Enterprise Scale Baseline Landing Zone Configuration Guide + +This configuration guide will detail the required and available configurations needed to deploy an Enterprise Scale Baseline Landing Zone(ESBLZ) on Oracle Cloud Infrastructure. + +## Prerequisites + +The Enterprise Scale Baseline Landing Zone is designed to be deployed to a tenancy owned by the individual Tenancy Administrator. The user deploying the ESBLZ must be a member of the Administrators group for the tenancy. The tenancy must have the required Resource Limits and have the Logging Analytics feature turned on. Detailed information on these prerequisites, and how to check that your tenancy meets them, and enable needed features can be found in the [Implementation Document](Implementation.md) + + +## Minimum Required Configuration + +Deployment of the ESBLZ is controlled by several Terraform [input variables](README.md#inputs), however most of these have sensible default values. Here are the minimum required configurations to deploy a ESBLZ: + +### Basic Terraform Connection Information +The required provider variables for the ESBLZ: + +| Name | Description | Type | Default | Required | +| ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | -------- | ------- | :------: | +| [current\_user\_ocid](#input\_current\_user\_ocid) | The ID of user to deploy the ESBLZ. | `string` | `""` | no | +| [api\_fingerprint](#input\_api\_fingerprint) | The API fingerprint which can be retrieved from the console. | `string` | `""` | no | +| [api\_private\_key](#input\_api\_private\_key) | The API private key | `string` | `""` | no | +| [api\_private\_key\_path](#input\_api\_private\_key\_path) | The local path to the API private key | `string` | `""` | no | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The ID of tenancy | `string` | n/a | yes | +| [region](#input\_region) | The OCI region to deploy the ESBLZ resources to. | `string` | n/a | yes | +| [resource\_label](#input\_resource\_label) | The prefix used to avoid naming conflict | `string` | n/a | no | + + +## Compartment Module + +This architecture diagram illustrates the compartments Enterprise LZ deploys. + +![Architecture](<../../images/LZ-v2.0.png> "Architecture") + +The ESBLZ Home Compartment would be created in enterprise-landing-zone. The other +compartments would be created in elz-environment and in elz-workload. + +The required arguments for ESBLZ Home Compartment: +* **compartment_parent_id**: the OCID of compartment/tenancy that you create the ESBLZ in +* **compartment_name**: the name of ESBLZ home compartment +* **compartment_description**: the description of ESBLZ home compartment +* **enable_compartment_delete**: unless enable_delete is explicitly set to true, Terraform will not delete compartments on destroy + +To configure the compartment the required user inputs are: + +| Name | Description | Type | Default | Required | +| ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -------- | -------------------- | :------: | +| [enable\_compartment\_delete](#input\_enable\_compartment\_delete) | Set to true to allow the compartments to delete on terraform destroy. | `bool` | `true` | no | +| [home\_compartment\_name](#input\_home\_compartment\_name) | The name of the home compartment under which all ESBLZ resources will be deployed. | `string` | `"OCI-ELZ-CMP-HOME"` | no | + +## Identity Module +Each environment will have its own identity domain. The identity domain applies to all resources under the environment compartment. +ESBLZ will only support the new identity domains in OCI(Henosis) and not the old IDCS domains. + +Required attributes: +* Display Name: The display name of Identity Domain. Default: OCI-ELZ--IDT +* Description: The description of Identity Domain. Default: OCI ESBLZ Identity Domain +* Domain Type: Premium +* Domain Admin: Email address for the domain admin +* Compartment: OCID for the compartment where the domain will be stored. This should be the L4-Security compartment +* Tags: Optional freeform tags + +### Identity Domain Configurations + +* **Required Arguments/Parameters for Identity Domain**: + + | Name | Description | Type | Default | Required | + | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------- | :------: | + | [nonprod\_domain\_admin\_email](#input\_nonprod\_domain\_admin\_email) | The email address for the non prod identity domain admin. | `string` | n/a | yes | + | [prod\_domain\_admin\_email](#input\_prod\_domain\_admin\_email) | The email address for the prod identity domain admin. | `string` | n/a | yes | + | [break\_glass\_user\_email\_list](#input\_break\_glass\_user\_email\_list) | Unique list of break glass user email addresses that do not exist in the tenancy. These users are added to the Administrator group. | `list(string)` | `[]` | no | + + +## Groups and Policies + +For control over users and user groups, a federate-able Identity Domain is created in the L4-Security Compartment for each environment. +To do so, the user deploying the ESBLZ will need set up federation after the ESBLZ has been deployed. + +The ESBLZ also will create 6 different User Groups, meant for managing individual deployed environments(by default 2, prod and non-prod). + +* **Network Admin** : OCI ESBLZ Network Administrators Group - manages all network resources +* **SecOps Admin**: OCI ESBLZ Security Administrators Group +* **IAM Admin**: OCI ESBLZ IAM Group +* **Ops Admin**: OCI ESBLZ Ops Admin Group +* **Platform Admin**: OCI ESBLZ Platform Admin Group + +While creating these user-groups the user inputs will be optional as there will be default value with group name, however if customer who want to setup federation, they will need to update the user-groups with the names as how those exist in their federated domain. + +* **Required Arguments/Parameters for Groups**: + + 1. Prod Environment + + | Name | Description | Type | Default | Required | + | ------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------- | -------- | ------------------------------- | :------: | + | [prod\_network\_admin\_group\_name](#input\_prod\_network\_admin\_group\_name) | The group name for the OCI ESBLZ Network Administrators Group | `string` | `"OCI-ELZ-UGP--NET-ADMIN"` | no | + | [prod\_ops\_admin\_group\_name](#input\_prod\_ops\_admin\_group\_name) | The group name for the OCI ESBLZ Ops Administrators Group | `string` | `"OCI-ELZ-UGP--OPS-ADMIN"` | no | + | [prod\_iam\_admin\_group\_name](#input\_prod\_iam\_admin\_group\_name) | The group name for the OCI ESBLZ IAM Administrators Group | `string` | `"OCI-ELZ-UGP--IAM-ADMIN"` | no | + | [prod\_security\_admin\_group\_name](#input\_prod\_security\_admin\_group\_name) | The group name for the OCI ESBLZ Security Administrators Group | `string` | `"OCI-ELZ-UGP--SEC-ADMIN"` | no | + | [prod\_platform\_admin\_group\_name](#input\_prod\_platform\_admin\_group\_name) | The group name for the OCI ESBLZ Platform Administrators Group | `string` | `"OCI-ELZ-UGP--PLT-ADMIN"` | no | + + 2. NonProd Environment + + | Name | Description | Type | Default | Required | + | --------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | -------- | ------------------------------- | :------: | + | [nonprod\_network\_admin\_group\_name](#input\_nonprod\_network\_admin\_group\_name) | The group name for the OCI ESBLZ Network Administrators Group | `string` | `"OCI-ELZ-UGP--NET-ADMIN"` | no | + | [nonprod\_ops\_admin\_group\_name](#input\_nonprod\_ops\_admin\_group\_name) | The group name for the OCI ESBLZ Ops Administrators Group | `string` | `"OCI-ELZ-UGP--OPS-ADMIN"` | no | + | [nonprod\_iam\_admin\_group\_name](#input\_nonprod\_iam\_admin\_group\_name) | The group name for the OCI ESBLZ IAM Administrators Group | `string` | `"OCI-ELZ-UGP--IAM-ADMIN"` | no | + | [nonprod\_security\_admin\_group\_name](#input\_nonprod\_security\_admin\_group\_name) | The group name for the OCI ESBLZ Security Administrators Group | `string` | `"OCI-ELZ-UGP--SEC-ADMIN"` | no | + | [nonprod\_platform\_admin\_group\_name](#input\_nonprod\_platform\_admin\_group\_name) | The group name for the OCI ESBLZ Platform Administrators Group | `string` | `"OCI-ELZ-UGP--PLT-ADMIN"` | no | + +The ESBLZ deploys policies that will grant administrative privileges to members of each of those groups over resources in their respective compartments. + +## Budget and Tagging Module + +The budget and tagging modules will give the ability to enable or disable budgets and tags in individual environments during the deployment as well as after the deployment without impacting the operation of LZ. +The deployment mode of the modules will be the same for each additional environment the client wants to create. + +## Budget Module + +The budgets module is responsible for deploying the budget component in a single environment. +The ESBLZ should create following components: + +* 1 Budget per environment + * **Budget scope**: Environment (Prod/Non-Prod) + +* **Required Arguments/Parameters for Budget Module**: + + * **Option on enabling or disabling Budget**: + + + | Name | Description | Type | Default | Required | + | ----------------------------------------------------------------------------------------------------- | ----------- | ------ | ------- | :------: | + | [nonprod\_enable\_budget](#input\_nonprod\_enable\_budget) | n/a | `bool` | n/a | yes | + | [prod\_enable\_budget](#input\_prod\_enable\_budget) | n/a | `bool` | n/a | yes | + + + 1. Prod Environment + + | Name | Description | Type | Default | Required | + | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- | -------- | ------- | :------: | + | [prod\_budget\_amount](#input\_prod\_budget\_amount) | The amount of the budget expressed as a whole number in the currency of the customer's rate card. | `string` | `""` | no | + | [prod\_budget\_alert\_rule\_threshold](#input\_prod\_budget\_alert\_rule\_threshold) | The threshold for the budget alert. | `string` | `""` | no | + | [prod\_domain\_admin\_email](#input\_prod\_domain\_admin\_email) | The email address for the prod identity domain admin. | `string` | n/a | yes | + | [prod\_budget\_alert\_rule\_message](#input\_prod\_budget\_alert\_rule\_message) | The alert message for budget alerts. | `string` | `""` | no | + + + 2. Non-Prod Environment + + | Name | Description | Type | Default | Required | + | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | ------- | :------: | + | [nonprod\_budget\_amount](#input\_nonprod\_budget\_amount) | The amount of the budget expressed as a whole number in the currency of the customer's rate card. | `string` | `""` | no | + | [nonprod\_budget\_alert\_rule\_threshold](#input\_nonprod\_budget\_alert\_rule\_threshold) | The threshold for the budget alert. | `string` | `""` | no | + | [nonprod\_domain\_admin\_email](#input\_nonprod\_domain\_admin\_email) | The email address for the non prod identity domain admin. | `string` | n/a | yes | + | [nonprod\_budget\_alert\_rule\_message](#input\_nonprod\_budget\_alert\_rule\_message) | The alert message for budget alerts. | `string` | `""` | no | + + +## Tagging Module + +The tags module is responsible for deploying Tags within the L2 Environment compartment. + +The ESBLZ should create following components: + + +* Tag namespace per environment containing the following defined tags and tag defaults + * **Cost Center** + * **Geo Location** + * **Environment Prefix** + +* **Required Arguments/Parameters for Tagging Module**: + + + 1. Prod Environment + + | Name | Description | Type | Default | Required | + | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | -------- | ------- | :------: | + | [prod\_enable\_tagging](#input\_prod\_enable\_tagging) | Option to enable Tagging gateway in Production environment | `bool` | `false` | no | + | [prod\_cost\_center\_tagging](#input\_prod\_cost\_center\_tagging) | Production Cost Center. | `string` | n/a | yes | + | [prod\_geo\_location\_tagging](#input\_prod\_geo\_location\_tagging) | Production Geo Center. | `string` | n/a | yes | + + 2. Non-Prod Environment + + | Name | Description | Type | Default | Required | + | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | -------- | ------- | :------: | + | [nonprod\_enable\_tagging](#input\_nonprod\_enable\_tagging) | Option to enable Tagging gateway in Non-Production environment | `bool` | `false` | no | + | [nonprod\_cost\_center\_tagging](#input\_nonprod\_cost\_center\_tagging) | Non-ProductionGeo Location. | `string` | n/a | yes | + | [nonprod\_geo\_location\_tagging](#input\_nonprod\_geo\_location\_tagging) | Non-Production Geo Location. | `string` | n/a | yes | + + +# Monitoring Module + +The monitoring module will enable you to actively and passively monitor resources using the Metrics and Alarms features. By Default the monitoring module will create all the components in each environment but alerts are disabled. + +## Monitoring Module Known Limitation +1. Monitoring Module will configure at least 100 Alarms, so make sure tenancy have proper service limit. + +## Required Arguments/Parameters for Monitoring Module +**Production Environment** + +| Variable | Description | Default Value | Usage | +| :------------------------------------- | --------------------------------------- | ------------- | ------------- | +| prod_enable_security_monitoring_alarms | Enable Security Monitoring Alarms | false (bool) | Set to true | +| prod_enable_network_monitoring_alarms | Enable Network Monitoring Alarms | false (bool) | Set to true | +| prod_enable_workload_monitoring_alarms | Enable Workload Monitoring Alarms | false (bool) | Set to true | +| prod_network_topic_endpoints | Enable Network Notifications Topic | empty (list) | Email Address | +| prod_secops_topic_endpoints | Enable Security OPS Notifications Topic | empty (list) | Email Address | +| prod_platform_topic_endpoints | Enable Platform Notifications Topic | empty (list) | Email Address | +| prod_identity_topic_endpoints | Enable Identity Notifications Topic | empty (list) | Email Address | + +**Non-Production Environment** + +| Variable | Description | Default Value | Usage | +| :---------------------------------------- | --------------------------------------- | ------------- | ------------- | +| nonprod_enable_security_monitoring_alarms | Enable Security Monitoring Alarms | false (bool) | Set to true | +| nonprod_enable_network_monitoring_alarms | Enable Network Monitoring Alarms | false (bool) | Set to true | +| nonprod_enable_workload_monitoring_alarms | Enable Workload Monitoring Alarms | false (bool) | Set to true | +| nonprod_network_topic_endpoints | Enable Network Notifications Topic | empty (list) | Email Address | +| nonprod_secops_topic_endpoints | Enable Security OPS Notifications Topic | empty (list) | Email Address | +| nonprod_platform_topic_endpoints | Enable Platform Notifications Topic | empty (list) | Email Address | +| nonprod_identity_topic_endpoints | Enable Identity Notifications Topic | empty (list) | Email Address | + + +## Networking Module + +Network Module will deploy Hub and Spoke distribution paradigm, VPN and Fastconnect on the LZ Environment. + +## Network Module Known Limitation +* CIDR ranges which can't be used during the ESBLZ deployment: + * 169.254.10.0-169.254.19.255 + * 169.254.100.0-169.254.109.255 + * 169.254.192.0-169.254.201.255 + * 100.64.0.0–100.127.255.255 (Used by Exadata X8M/X9M for the interconnect) + +## Required Arguments/Parameters for Network Module + +**Production Environment Variable** + +1. Hub Related Variable + +| Variable | Description | Default Value | Usage | +| :------------------------------- | ------------------------------ | ---------------- | ----------------------- | +| prod_hub_vcn_cidr_block | HUB VCN CIDR Block | "" (string) | Provide CIDR IP | +| prod_enable_internet_gateway_hub | Enable Internet Gateway In Hub | "false" (string) | To Enable Set to "true" | +| prod_enable_service_gateway_hub | Enable Service Gateway In Hub | "false" (string) | To Enable Set to "true" | +| prod_enable_nat_gateway_hub | Enable NAT Gateway In Hub | "false" (string) | To Enable Set to "true" | + + +2. Spoke Related Variable + +| Variable | Description | Default Value | Usage | +| :-------------------------------- | ------------------------------- | ---------------- | ----------------------- | +| prod_spoke_vcn_cidr | Spoke VCN CIDR Block | "" (string) | Provide CIDR IP | +| prod_enable_service_gateway_spoke | Enable Service Gateway In Spoke | "false" (string) | To Enable Set to "true" | +| prod_enable_nat_gateway_spoke | Enable NAT Gateway In Spoke | "false" (string) | To Enable Set to "true" | +| prod_spoke_subnet_web_cidr_block | Spoke Web CIDR Block | "" (string) | Provide CIDR IP | +| prod_spoke_subnet_app_cidr_block | Spoke App CIDR Block | "" (string) | Provide CIDR IP | +| prod_spoke_subnet_db_cidr_block | Spoke DB CIDR Block | "" (string) | Provide CIDR IP | + +3. VPN Related Variable + +| Variable | Description | Default Value | Usage | +| :---------------------------------- | --------------------------------- | ----------------------------- | ------------------------------- | +| enable_vpn_or_fastconnect | Enable VPN or Fastconnect Service | "VPN \| FASTCONNECT" (string) | Set to "VPN" or "FASTCONNECT" | +| prod_enable_vpn | Enable VPN on Environment | false (bool) | Set to true | +| prod_cpe_ip_address | VPN CPE IP Address | "" (string) | CPE Public IP Address | +| prod_cpe_display_name | VPN CPE Display Name | "" (string) | CPE Display Name | +| prod_cpe_vendor | VPN CPE Vender | 0 (number) | Follow CPE Vendor List | +| prod_ipsec_connection_static_routes | Ipsec Static Route | [""] (list) | Onpremise IPsec Static Route | +| prod_shared_secret | Shared Key for IPSec Tunnel | "EXAMPLE" (string) | Provide IpSec Tunnel Shared Key | +| prod_ipsec_routing_type | Ipsec Routing Type | "STATIC" (string) | Set to "STATIC" or "BGP" to use | +| prod_customer_bgp_asn | BGP ASN(IF BGP Selected) | "" (string) | Provide BGP ASN | +| prod_bgp_cust_tunnela_ip | CPE Side Tunnel End IP Address | "" (string) | Provide IP Address | +| prod_customer_bgp_asn | OCI Side Tunnel End IP Address | "" (string) | Provide IP Address | + + +4. FastConnect Related Variable (By Design FastConnect will be deployed only on Production Environment) + +| Variable | Description | Default Value | Usage | +| :------------------------------ | ------------------------------------- | ----------------------------- | --------------------------------- | +| enable_vpn_or_fastconnect | Enable VPN or Fastconnect Service | "VPN \| FASTCONNECT" (string) | Set to "VPN" or "FASTCONNECT" | +| fastconnect_provider | Enable VPN on Environment | "" (string) | Follow FastConnect List | +| virtual_circuit_bandwidth_shape | Provisioned Bandwidth | "1500" (string) | Provide Bandwidth | +| virtual_circuit_display_name | Provisioned VC Name | ""(string) | VC Display Name | +| fastconnect_routing_policy | Fastconnect Routing Policy | [""] (list) | Follow Fastconnect Routing Policy | +| virtual_circuit_type | VC IP Address Type | "PRIVATE \| PUBLIC" (string) | Provide VC Type | +| customer_primary_bgp_peering_ip | Customer End BGP Peering IPv4 Address | "" (string) | Provide IP Address | +| oracle_primary_bgp_peering_ip | Oracle End BGP Peering IPv4 Address | "" (string) | Provide IP Address | +| virtual_circuit_customer_asn | VC BGP ASN | ""(string) | VC BGP ASN | +| customer_onprem_ip_cidr | On Premise IP CIDR | [""] (list) | On Premise IP CIDR | +| bgp_md5auth_key | Optional : BGP Authentication MD5 | ""(string) | Provide Key | +| virtual_circuit_is_bfd_enabled | Optional : Enable BFD on VC | false(bool) | To Enable Set to true | + +> FastConnect Provider List +> +| FastConnect Provider | +| :--------------------- | +| AT&T | +| Azure | +| Megaport | +| QTS | +| CEintro | +| Cologix | +| CoreSite | +| Digitial Realty | +| EdgeConneX | +| Epsilon | +| Equinix | +| InterCloud | +| Lumen | +| Neutrona | +| OMCS | +| OracleL2ItegDeployment | +| OracleL3ItegDeployment | +| Orange | +| Verizon | +| Zayo | + + +> FastConnect Routing Policy +> +| FastConnect Routing Policy | +| :------------------------- | +| ORACLE_SERVICE_NETWORK | +| REGIONAL | +| MARKET_LEVEL | +| GLOBAL | + + + +**Non Production Environment Variable** + +1. Hub Related Variable + +| Variable | Description | Default Value | Usage | +| :---------------------------------- | ------------------------------ | ---------------- | ----------------------- | +| nonprod_hub_vcn_cidr_block | HUB VCN CIDR Block | "" (string) | Provide IP Address | +| nonprod_enable_internet_gateway_hub | Enable Internet Gateway In Hub | "false" (string) | To Enable Set to "true" | +| nonprod_enable_service_gateway_hub | Enable Service Gateway In Hub | "false" (string) | To Enable Set to "true" | +| nonprod_enable_nat_gateway_hub | Enable NAT Gateway In Hub | "false" (string) | To Enable Set to "true" | + +3. Spoke Related Variable + +| Variable | Description | Default Value | Usage | +| :----------------------------------- | ------------------------------- | ---------------- | ----------------------- | +| nonprod_spoke_vcn_cidr | Spoke VCN CIDR Block | "" (string) | Provide IP Address | +| nonprod_enable_service_gateway_spoke | Enable Service Gateway In Spoke | "false" (string) | To Enable Set to "true" | +| nonprod_enable_nat_gateway_spoke | Enable NAT Gateway In Spoke | "false" (string) | To Enable Set to "true" | +| nonprod_spoke_subnet_web_cidr_block | Spoke Web CIDR Block | "" (string) | Provide IP Address | +| nonprod_spoke_subnet_app_cidr_block | Spoke App CIDR Block | "" (string) | Provide IP Address | +| nonprod_spoke_subnet_db_cidr_block | Spoke DB CIDR Block | "" (string) | Provide IP Address | + +3. VPN Related Variable + +| Variable | Description | Default Value | Usage | +| :------------------------------------- | --------------------------------- | ----------------------------- | ------------------------------- | +| enable_vpn_or_fastconnect | Enable VPN or Fastconnect Service | "VPN \| FASTCONNECT" (string) | Set to "VPN" or "FASTCONNECT" | +| nonprod_enable_vpn | Enable VPN on Environment | false (bool) | Set to true | +| nonprod_cpe_ip_address | VPN CPE IP Address | "" (string) | CPE Public IP Address | +| nonprod_cpe_display_name | VPN CPE Display Name | "" (string) | CPE Display Name | +| nonprod_cpe_vendor | VPN CPE Vender | 0 (number) | Follow CPE Vendor List | +| nonprod_ipsec_connection_static_routes | Ipsec Static Route | [""] (list) | IPsec Static Route | +| nonprod_shared_secret | Shared Key for IPSec Tunnel | "EXAMPLE" (string) | Provide IpSec Tunnel Shared Key | +| nonprod_ipsec_routing_type | Ipsec Routing Type | "STATIC" (string) | Set to "STATIC" or "BGP" to use | +| nonprod_customer_bgp_asn | BGP ASN(IF BGP Selected) | "" (string) | Provide BGP ASN | +| nonprod_bgp_cust_tunnela_ip | CPE Side Tunnel End IP Address | "" (string) | Provide IP Address | +| nonprod_customer_bgp_asn | OCI Side Tunnel End IP Address | "" (string) | Provide IP Address | + +> CPE Vendor List +> +| Number | CPE Vendor | +| :----- | -------------------- | +| 0 | Yamaha-RTX1210 | +| 1 | Other | +| 2 | Cisco-9.7.1-or-later | +| 3 | Yamaha-RTX830 | +| 4 | Libreswan | +| 5 | Fortinet | +| 6 | NEC | +| 7 | Cisco-8.5+ | +| 8 | Cisco-IOS | +| 9 | WatchGuard | +| 10 | Juniper-MX | +| 11 | Juniper-SRX | +| 12 | Furukawa | +| 13 | Check_Point | +| 14 | Palo_Alto | + + +## Hub and Spoke Network + +Hub and Spoke distribution paradigm will allow workload to interconnect with each other. Hub instance will configured on shared network compartment and spoke instance will be deployed on workload compartment. + +***HUB Module*** + +1. **Naming Convention** + +| Resource | Deployed Name | +| :--------------------------- | --------------------------------------------- | +| Hub VCN Name | OCI-ELZ-VCN-\-HUB-\ | +| Hub Public Subnet Name | OCI-ELZ-VCN-\-HUB-\001 | +| Hub Private Subnet Name | OCI-ELZ-VCN-\-HUB-\002 | +| Hub Internet Gateway Name* | OCI-ELZ-IGW-\-HUB | +| Hub Service Gateway Name | OCI-ELZ-SGW-\-HUB | +| Hub NAT Gateway Name | OCI-ELZ-NGW-\-HUB | +| Hub Public Route Table Name | OCI-ELZ-RTPUB-\-HUB001 | +| Hub Private Route Table Name | OCI-ELZ-RTPRV-\-HUB002 | + +2. **Route Rule** + >Public Route Table Information + 1. If Internet Gateway is enabled, it will act as default gateway. + 2. All Spoke Subnet destination will be forwarded to DRG. + + >Private Route Table Information + 1. If NAT Gateway is enabled, it will act as default gateway. + 2. If Service Gateway is enabled , all OCI services can access Hub resources. + 3. All Spoke Subnet destination will be forwarded to DRG. + +3. **Security Rule** + 1. Ingress Rule : Allow All ICMP Traffic + 2. Egress Rule : Allow All Protocol Traffic + +***Spoke Module*** + +1. **Naming Convention** + +| Resource | Deployed Name | +| :------------------------- | --------------------------------------------- | +| Spoke VCN Name | OCI-ELZ-VCN-\-SPK-\ | +| Spoke Web Subnet Name | OCI-ELZ-VCN-\-SPK-\001 | +| Spoke App Subnet Name | OCI-ELZ-VCN-\-SPK-\002 | +| Spoke DB Subnet Name | OCI-ELZ-VCN-\-SPK-\003 | +| Spoke Service Gateway Name | OCI-ELZ-SGW-\-SPK | +| Spoke NAT Gateway Name | OCI-ELZ-NGW-\-SPK | +| Spoke Route Table | OCI-ELZ-RTPRV-\-SPK001 | + +2. **Route Rule** + >Public Route Table Information + 1. If NAT Gateway is enabled, it will act as default gateway. + 2. If Service Gateway is enabled , all OCI services can access Spoke resources. + 3. All Hub Subnet destination will be forwarded to DRG. + 4. All Spoke Subnet destination will be forwarded to DRG. + +3. **Security Rule** + 1. Ingress Rule : Allow All ICMP Traffic + 2. Egress Rule : Allow All Protocol Traffic + +## VPN Module + +VPN Module will be deployed under Shared Infrasturture Network Compartment. IPsec connection will be deployed using Static or BGP connection. + +1. **Naming Convention** + +| Resource | Deployed Name | +| :-------------------- | ------------------------------------------- | +| CPE Name | OCI-ELZ-CPE-\-HUB-[REGION]001 | +| IPsec Connection Name | OCI-ELZ-IPC-\-HUB-[REGION]001 | + +2. **Route Rule** + > Route Table Information OCI-ELZ-RTPUB-\-HUB001 Route Will be Updated + 1. On Premise IPSec static route will be forwarded to DRG. + + > Route Table Information OCI-ELZ-RTPRV-\-HUB001 Route Will be Updated + 1. On Premise IPSec static route will be forwarded to DRG. + + > Route Table Information OCI-ELZ-RTPRV-\-SPK001 Route Will be Updated + 1. On Premise IPSec static route will be forwarded to DRG. + + +## FastConnect Module + +1. **Naming Convention** + +| Resource | Deployed Name | +| :----------------------- | ------------------------------------------- | +| FastConnect Circuit Name | OCI-ELZ-FCN-\-HUB-[REGION]001 | + +2. **Route Rule** + > Route Table Information : OCI-ELZ-RTPUB-\-HUB001 Route Table Will be Updated + 1. On Premise IP CIDR Route will be forwarded to DRG. + + > Route Table Information : OCI-ELZ-RTPRV-\-HUB001 Route Table Will be Updated + 2. On Premise IP CIDR Route will be forwarded to DRG. + + > Route Table Information : OCI-ELZ-RTPRV-\-SPK001 Route Table Will be Updated + 3. On Premise IP CIDR Route will be forwarded to DRG.
+ +3. **RPC Attachment**
+On Premise Subnet route will not propagate over the RPC connection to the second Hub & Spoke, and vice versa. In order to accomplish this, we will create two separate route tables in on the DRG called "OCI-ELZ-DRG-P-HUB", one for the IPSec/VC attachment and the other for the RPC attachment and we will be specific on what types of routes to import. + > Update DRG OCI-ELZ-DRG-\-HUB + 1. Create Import Route Distribution for On Prem + 2. Create Import Route Distribution for RPC + 3. Create Route Table for On Prem + 4. Create Route Table for RPC + 5. Apply the new Route Tables to the Attachments + + +## Security + +To provide for a secure environment, the ESBLZ deploys several Oracle security services, such as CloudGuard to monitor for insecure cloud resource deployments, Vulnerability Scanning Service to scan compute instances for open ports and known vulnerabilities, and OS Management Service to manage updates and patches. + +To provide secure storage and key management, the ESBLZ deploys a Vault and a creates a Master Encryption Key stored in that vault, which can be used to encrypt data in Object Storage. + +For secure storage and future analysis of logging data, the ESBLZ directs all logging data, including general log data, service events, and audit logs, to secure storage. This can be secure object storage buckets created by the ESBLZ, and encrypted with the Master Encryption Key stored in the central Vault. + +For secure access to workload resources, the ESBLZ deploys a Bastion in the L4 Security Compartment. + + +### Security Services + +The ESBLZ deploys configurations for multiple security services. VSS (Vulnerability Scanning Service) will scan compute instances deployed in the ESBLZ (i.e. as part of workloads) for open ports, and known security vulnerabilities. OSMS (OS Management Service) works with operating systems on deployed compute instances (such as Oracle Autonomous Linux) to manage patches and updates to ensure a secure environment. + +### Cloud Guard Sub Module + +CloudGuard can monitor for a multitude of security conditions. The ESBLZ configures CloudGuard with several Oracle-managed security recipes for up-to-date best practice security monitoring. + +By default, CloudGuard is configured to monitor just the resources deployed in the ESBLZ Home compartment, and compartments within that. An option is for CloudGuard to monitor the entire tenancy is there and it is controlled by the [cloud_guard_target_tenancy](cloud_guard_target_tenancy) variable. This is a Boolean variable that defaults to `false`. If it is set to `true` CloudGuard will be configured to monitor the entire tenancy, instead of just the ESBLZ Home compartment. + +Cloud Guard Target will be deployed in base compartment of both L2-Prod and L2-Non-Prod environments along with related IAM policies. All Oracle managed responder recipes will reside in L4 Security compartment of each environment. + +The **target_detector_recipes** which are Oracle managed: + +* OCI Config Detector Recipes +* OCI Threat Detector Recipes +* OCI Activity Detector Recipe + +The **target_responder_recipes**: OCI Responder Recipe (enabling CloudGuard events and other responds) + +For further details on CloudGuard, see the [Cloud Guard documentation](https://docs.oracle.com/en-us/iaas/cloud-guard/home.htm). + +* **Required Arguments/Parameters Under Cloud Guard Module**: + + | Name | Description | Type | Default | Required | + | ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------ | ------- | :------: | + | [enable\_cloud\_guard](#input\_enable\_cloud\_guard) | true if you don't have cloud guard enabled, false if you've already have cloud guard enabled. | `bool` | `true` | no | + | [cloud\_guard\_target\_tenancy](#input\_cloud\_guard\_target\_tenancy) | true if cloud guard targets to tenancy, false if cloud guard targets to ESBLZ home compartment | `bool` | `false` | no | + +### Bastion Sub Module + +Bastion service is created in the L4 Security Compartment within the L2 prod Compartment and second one in the L4 Security Compartment within the L2 non-Prod Compartment as depicted in the Security Architecture shown above. It allows secure access to compute resources in the respective environments. CIDR Block provided will give the address range of all the resources for which Bastion Service can host sessions for. + +* **Required Arguments/Parameters Under Bastion Module**: + + 1. Prod Environment + + | Name | Description | Type | Default | Required | + | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | -------------- | ------- | :------: | + | [prod\_enable\_bastion](#input\_prod\_enable\_bastion) | Option to enable bastion service | `bool` | n/a | yes | + | [prod\_bastion\_client\_cidr\_block\_allow\_list](#input\_prod\_bastion\_client\_cidr\_block\_allow\_list) | A list of address ranges in CIDR notation that you want to allow to connect to sessions hosted by this bastion. | `list(string)` | n/a | yes | + + 2. Non-Prod Environment + + | Name | Description | Type | Default | Required | + | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | -------------- | ------- | :------: | + | [nonprod\_enable\_bastion](#input\_nonprod\_enable\_bastion) | Option to enable bastion service | `bool` | n/a | yes | + | [nonprod\_bastion\_client\_cidr\_block\_allow\_list](#input\_nonprod\_bastion\_client\_cidr\_block\_allow\_list) | A list of address ranges in CIDR notation that you want to allow to connect to sessions hosted by this bastion. | `list(string)` | n/a | yes | + +### VSS Sub Module + +VSS (Vulnerability Scanning Service) is part of many security services deployed under ESBLZ. It scans compute instances deployed in the ESBLZ (i.e. as part of workloads) for open ports, and other known security vulnerabilities. + +**Key Features**: + +* VSS Recipes are created in L4-Security Compartment in both prod/nonprod environments to manage instances, read components and VNICs. +* Network and agent based scanning in enabled by default +* Scans are configured with "Daily" Schedule +* Qualys integration allows to run reports on Qualys Dashboard instead of CloudGuard. This feature might be available on later releases, as it is not currently on Terraform Code Support. + +**No Input Parameters Required for VSS Module** + +### OSMS Sub Module + +OSMS (OS Management Service) works with operating systems on deployed compute instances (such as Oracle Autonomous Linux) to manage patches and updates to ensure a secure environment. + +**Key Features**: + +* IAM Policy is created at Tenancy Level for OSMS service to emit metrics for instances in Tenancy +* Dynamic Group is created, name: ${var.resource_label}-"OCI-ELZ-DG" +* Matching Rules are created with compartment OCIDs (where instances reside), eg: L4-Security, Logging, Network, Workload and Base Compartment OCIDs +* IAM Policy for Dynamic Group is created in LZ home compartment + +**No Input Parameters Required for OSMS Module** + +### Vault and Key Management Sub Module + +OCI Vault service is a key management service that stores and manages master encryption keys and secrets for secure access to resources. + +**Key Features**: + +* A Virtual Vault is created for secure storage of cryptographic keys within L4-Security Compartment of both Prod and NonProd Environments +* A user-manageable Master Encryption Key is also created, stored in the Vault, and is usable for encryption of data in OCI Storage Services +* Vault does support BYOK scenario and can store all user keys as well +* IAM Policy for Storage Services to use keys are created in LZ Base Compartment + +* **Required Arguments/Parameters for Vault and Key Management Module**: + + 1. Prod Environment + + | Name | Description | Type | Default | Required | + | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | -------- | ----------- | :------: | + | [prod\_vault\_type](#input\_prod\_vault\_type) | The type of vault to create. | `string` | `"DEFAULT"` | no | + | [prod\_vault\_replica\_region](#input\_prod\_vault\_replica\_region) | the region to be created replica to. | `string` | `""` | no | + | [prod\_enable\_vault\_replication](#input\_prod\_enable\_vault\_replication) | Option to enable vault replication | `bool` | `false` | no | + | [prod\_create\_master\_encryption\_key](#input\_prod\_create\_master\_encryption\_key) | Option create master encryption key | `bool` | `true` | no | + + + 2. Non-Prod Environment + + | Name | Description | Type | Default | Required | + | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------ | -------- | ----------- | :------: | + | [nonprod\_vault\_type](#input\_nonprod\_vault\_type) | The type of vault to create. | `string` | `"DEFAULT"` | no | + | [nonprod\_vault\_replica\_region](#input\_nonprod\_vault\_replica\_region) | the region to be created replica to. | `string` | `""` | no | + | [nonprod\_enable\_vault\_replication](#input\_nonprod\_enable\_vault\_replication) | Option to enable vault replication | `bool` | `false` | no | + | [nonprod\_create\_master\_encryption\_key](#input\_nonprod\_create\_master\_encryption\_key) | Option create master encryption key | `bool` | `true` | no | + + +### Logging + +The ESBLZ sets up secure storage of all log data generated by resources and services in the ESBLZ. For both environments in L2-Prod and L2-NonProd compartment a logging compartment **“L3-Logging Compartment”** is created. This compartment hosts the below listed 3 immutable storage buckets: + +* **AuditLogs_standard** (for audit logs) +* **DefaultLogs_standard** (for general logging) +* **ServiceEvents_standard** (for service events) + +These buckets are encrypted with the Master Encryption Key(MEK) stored in the vault. Retention policies are also applied to these buckets to manage data retention, disallowing deletion, or modifications of data for a configurable time-period. + +Default Log group (Name: Default_Group) is created is L4-Security compartment and service logs for all supported services (VCN Flow logs, Object Storage etc.) are enabled and stored in L3-Logging compartment. + +All the events in ESBLZ environment are streamed to standard object storage. The Stream Pool is created in L4-Security compartment and encrypted with MEK and the service evens are stored in standard Object storage bucket in Logging compartment. + +Service connector is used to ship all the audit, service logs and events in ESBLZ to these buckets in logging compartment. All IAM Policies for Service Connector are created in the L2 level Home compartment of each environment. + +* **Required Arguments/Parameters for Bucket Retention Policies**: + + 1. Prod Environment + + | Name | Description | Type | Default | Required | + | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------- | :------: | + | [prod\_retention\_policy\_duration\_amount](#input\_prod\_retention\_policy\_duration\_amount) | The timeAmount is interpreted in units defined by the timeUnit parameter, and is calculated in relation to each object's Last-Modified timestamp. | `string` | `"1"` | no | + | [prod\_retention\_policy\_duration\_time\_unit](#input\_prod\_retention\_policy\_duration\_time\_unit) | The unit that should be used to interpret timeAmount. | `string` | `"DAYS"` | no | + + 2. Non-Prod Environment + + | Name | Description | Type | Default | Required | + | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------- | :------: | + | [nonprod\_retention\_policy\_duration\_amount](#input\_nonprod\_retention\_policy\_duration\_amount) | The timeAmount is interpreted in units defined by the timeUnit parameter, and is calculated in relation to each object's Last-Modified timestamp. | `string` | `"1"` | no | + | [nonprod\_retention\_policy\_duration\_time\_unit](#input\_nonprod\_retention\_policy\_duration\_time\_unit) | The unit that should be used to interpret timeAmount. | `string` | `"DAYS"` | no | + + 3. Archive Log + + | Name | Description | Type | Default | Required | + | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------- | :------: | + | [archive\_log\_retention\_policy\_duration\_amount](#input\_archive\_log\_retention\_policy\_duration\_amount) | The timeAmount is interpreted in units defined by the timeUnit parameter, and is calculated in relation to each object's Last-Modified timestamp. | `string` | `"1"` | no | + | [archive\_log\_retention\_policy\_duration\_time\_unit](#input\_archive\_log\_retention\_policy\_duration\_time\_unit) | The unit that should be used to interpret timeAmount. | `string` | `"DAYS"` | no | diff --git a/templates/enterprise-landing-zone/IMPLEMENTATION.md b/templates/enterprise-landing-zone/IMPLEMENTATION.md new file mode 100644 index 00000000..f23d9d13 --- /dev/null +++ b/templates/enterprise-landing-zone/IMPLEMENTATION.md @@ -0,0 +1,293 @@ +# Enterprise Scale Baseline Landing Zone + +## Prerequisites + +To deploy the Enterprise Scale Baseline Landing Zone from the terraform cli you will need the following prerequisites. +- [Latest Version of Terrafom](https://developer.hashicorp.com/terraform/downloads) +- [OCI Terraform provider](https://registry.terraform.io/providers/oracle/oci/latest/docs) v4.109.0 or later +- [oci - cli](https://github.com/oracle/oci-cli) + +## User + +The Enterprise Scale Baseline Landing Zone should be deployed by a user who is a member of the Administrators group for the tenancy. This user need to have an api key entry defined as decribed [here](https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/terraformproviderconfiguration.htm). Once the user and API Key are defined your oci-cli config should resemble. + +```text +[DEFAULT] +user=ocid1.xxxxxx.xxxxxx.xxxxxx..... #ocid of the user +fingerprint=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx #user api key fingerprint +tenancy=ocid1.xxxxxx.xxxxxx.xxxxxx..... #tenancy ocid +region=us-phoenix-1 #or desired region +key_file= # TODO +``` + +## Region + +The Enterprise Scale Baseline Landing Zone should be deployed to the tenancy's Home Region. + +## Tenancy + +The tenancy you intend to deploy the Enterprise Scale Baseline Landing Zone to. + +### Logging Analytics + +The Logging Analytics service should be enabled for the tenancy. +To check the current status of Logging Analytics for a tenancy, visit the [Logging Analytics home page][1]. +There will be a dark grey box at the top of the page. On the right hand side of that box, if Logging analytics has *not* been enabled, there will be a notice that Logging Analytics has not been enabled for the tenancy, and a blue button to enable it. To enable it, click the blue button, and wait for the 3 onboarding steps to complete. No further action will be required, as the Enterprise Scale Baseline Landing Zone will configure the needed datasources. + +### Resource Limits + +Most of the initial resource limits a new tenancy comes with should be sufficient to deploy 1 Enterprise Scale Baseline Landing Zone, with 2 environments and 1 workload each. + +However, there are some resource limits that will need to be increased in order to deploy the Enterprise Scale Baseline Landing Zone. Below is a table listing the Terraform OCI resource names and numbers deployed please ensure your tenancy has sufficient limts before deploying the Enterprise Scale Baseline Landing Zone: +|OCI Terraform Resource Name | Count | +| ---------------------------- | ------- | +|oci_announcements_service_announcement_subscription| 2| +|oci_announcements_service_announcement_subscriptions_filter_group| 4| +|oci_bastion_bastion| 2| +|oci_budget_alert_rule| 2| +|oci_budget_budget| 2| +|oci_cloud_guard_cloud_guard_configuration| 2| +|oci_cloud_guard_target| 2| +|oci_core_cpe| 1| +|oci_core_default_security_list| 4| +|oci_core_drg| 2| +|oci_core_drg_attachment| 4| +|oci_core_internet_gateway| 2| +|oci_core_ipsec| 1| +|oci_core_ipsec_connection_tunnel_management| 2| +|oci_core_nat_gateway| 4| +|oci_core_route_table| 6| +|oci_core_security_list| 4| +|oci_core_service_gateway| 4| +|oci_core_subnet| 10| +|oci_core_vcn| 4| +|oci_events_rule| 12| +|oci_identity_authentication_policy| 1| +|oci_identity_compartment| 13| +|oci_identity_domain| 2| +|oci_identity_dynamic_group| 1| +|oci_identity_policy| 49| +|oci_identity_tag| 7| +|oci_identity_tag_default| 7| +|oci_identity_tag_namespace| 3| +|oci_kms_key| 3| +|oci_kms_vault| 2| +|oci_log_analytics_log_analytics_log_group| 4| +|oci_logging_log| 18| +|oci_logging_log_group| 2| +|oci_monitoring_alarm| 68| +|oci_objectstorage_bucket| 7| +|oci_ons_notification_topic| 20| +|oci_sch_service_connector| 16| +|oci_streaming_stream| 2| +|oci_streaming_stream_pool| 2| +|oci_vulnerability_scanning_host_scan_recipe| 2| +|oci_vulnerability_scanning_host_scan_target| 2| + +Example to check the limits in tenancy: + +1. Login to OCI Console and click on the left top corner burger menu. +2. Scroll down and click on Governance and Administration +3. Under Tenancy Management click on Limits, Quotas and Usage Option + +![ScreenShot1]( "ScreenShot1") + +4. Under Service option select Service Connector Hub and it will show how much is the limit, used and available. + +![ScreenShot2]( "ScreenShot2") + +Also, this link can provide all the details on limits, quotas and usage as to how use, request increase etc. + +https://docs.oracle.com/en-us/iaas/Content/General/Concepts/servicelimits.htm + +Requests to raise these limits can be done through the [request a service limit increase][2] page. + +[1]: https://cloud.oracle.com/loganalytics/home "Logging Analytics Home page." +[2]: https://cloud.oracle.com/support/create?type=limit "Request a service Limit Increase." + +## Enterprise Scale Baseline Landing Zone Compartment Architecture + +--- +![Architecture](<../../images/LZ-v2.0.png> "Architecture") + +This architecture diagram illustrates the compartments Enterprise LZ deployments + +### Compartment Structure + +For the Enterprise Scale Baseline Landing Zone, we have the below compartment architecture: + +* Enterprise Scale Baseline Landing Zone Home Compartment + * Prod + * Shared Infrastructure + * Network + * Security + * Workload + * Logging + * Backup + * Non Prod + * Shared Infrastructure + * Network + * Security + * Workload + * Logging + * Backup + +## Environments + +--- +Environments are each full infrastructure deployments with their own hub-and-spoke network, Identity domain, user groups, etc. + +They are designed to ensure isolation between each environment. They can each contain multiple Workloads. + +The Enterprise Scale Baseline Landing Zone will initially set up two Environments: `Prod` and `Nonprod`. Infrastructure resources within each Environment will have a single letter abbreviation (such as `N` or `P`) to indicate which environment they are part of. + +In the future, the `elz-environment` template will allow you to easily add new Environments to an existing Enterprise Scale Baseline Landing Zone. + +## Workloads + +--- +Workloads are the "shell" for you to deploy an application or service into. They provide infrastructure such as a compartment you can place application resources in, user groups to manage the application, network and logging infrastructure, etc. + +Workloads exist within Environments. + +The Enterprise Scale Baseline Landing Zone will set up one initial workload configuration in each Environment. In the future, the `elz-workload` template will allow you to easily add additional workloads to a deployed Environment within the Enterprise Scale Baseline Landing Zone. + +Note that Workload compartments and networks all contain a user provided *workload_name* suffix in their names. This allows multiple workloads, each with their own separate compartment and networks, to be deployed. + +## Identity Domain + +--- +Each environment will have its own identity domain. This lives in the Security compartment of each environment. The identity domain applies to all resources under the environment compartment. +Enterprise Scale Baseline Landing Zone will only support the new identity domains in OCI(Henosis) and not the old IDCS domains. + +Each domain has it's own users and groups, and can be federated and configured separately. + +## Networking + +--- +Each environment will have it's own independent network configuration. The network architecture is a "Hub and Spoke" design. It is built around OCI's Dynamic Routing Gateway (DRG), which acts as central router. It can connect together multiple virtual networks, as well as VPN or FastConnect links to on-premises networks. + +Each environment will have one Hub virtual network (VCN) that hosts network infrastructure shared between all workloads, such as load balancers and firewalls. This will have one Public and one Private subnet. + +For *each* workload deployed in an environment, there will be one Spoke network. This will have three private subnets, one each for Web, DB and Application resources. + +The `elz-network-extension` template can add VPN or FastConnect links between an environment's DRG and an on-prem network. + +## Deployment of The Enterprise Scale Baseline Landing Zone + +## For customers who already have Infrastructure in OCI + +If you already have infrastructure deployed in OCI and are looking to explore a best-practices infrastructure architecture with Enterprise Scale Baseline Landing Zone, you may want to create a new [Child Tenancy](https://docs.oracle.com/en-us/iaas/Content/General/Concepts/organization_management_overview.htm) to deploy the Enterprise Scale Baseline Landing Zone in. This will guarantee there are no conflicts with existing infrastructure. + +Note that child tenancies have their own [resource limits](#resource-limits), which should be checked to confirm the Enterprise Scale Baseline Landing Zone can be deployed. + +## How to Deploy + +--- +The Enterprise Scale Baseline Landing Zone can be launched through Oracle Resource Manager or from the Terraform CLI. + +## Terraform CLI + +1. Have Terraform installed on the system you will deploy from. The Enterprise Scale Baseline Landing Zone should work with any version of Terraform greater than 1.0.0, including the latest version (currently 1.3.9). If you do not have Terraform already installed, the [Terraform Download page](https://developer.hashicorp.com/terraform/downloads) will have links for the proper package for your system, and installation instructions. + +2. Set up API keys to work with your OCI account. Follow the instructions [here](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm). + +3. Visit the [GitHub page](https://github.com/oracle-quickstart/oci-landing-zones) to clone the Terraform template. + +4. In the repository, cd to the `templates/enterprise-landing-zone/` directory. This is the main template for the Enterprise Scale Baseline Landing Zone. (the other templates will allow you to deploy other components, such as additional Environments or Workloads, or to deploy pieces of the Enterprise Scale Baseline Landing Zone architecture for use in your own custom infrastructure designs.) + +5. Create a terraform.tfvars file in the directory and populate it with the required variables or override existing variables. +**For reference on the configuration variable values read the [Configuration Guide](CONFIGURATION.md). For a full list of all available configuration variables see the [Input Variables Reference in the README](README.md#inputs)** + + Note: An example tfvars file is included for reference. Using this file is the preferred way to run the stack from the CLI, because of the large number of variables to manage. + +6. From the root of the module run the following commands to deploy the terraform. + * `terraform init` + * `terraform plan` + * `terraform apply` + +7. Terraform will provision your resources and provide outputs once it completes. + +### For more information + +- [Deploy to OCI using Terraform tutorials](https://docs.oracle.com/en-us/iaas/developer-tutorials/tutorials/tf-provider/01-summary.htm). + +- [OCI provider documentation](https://registry.terraform.io/providers/oracle/oci/latest/docs). + +## Resource Manager + +To deploy using Resource Manager, the stack must be imported into the console in one of 2 ways: + +Use the `Deploy to Oracle Cloud` button which will take you directly to OCI Resource Manager if you are logged in. You can skip to step 11 if you use this. +Or you can select the stack manually through the console starting from step 1. + +1. From the console home page, navigate to `Developer Services -> Resource Manager -> Stacks` +2. Select the compartment you want to create the stack in and select `Create stack`. +3. Select `Source code control system` for the Terraform source. +4. In the `Stack Configuration` box, under `Source Code Management Type`, select `GitHub`. +5. Under `Configuration source provider`, if you have a provider set up for public GitHub, you can select it, then skip to step 9. Otherwise select `Create configuration source provider`. +6. If you do not already have a Personal Access Token for your GitHub account, log in to GitHub and create one. The option can be found under `Settings -> Developer settings -> Personal access tokens -> Tokens (classic)` on the [GitHub site](https://github.com). The token must have the `repo` scope. +7. To create the configuration provider for GitHub in OCI, fill in the "Create configuration source provider" form as follows: + * Name: GitHub + * Description: (optional) Public Github Repositories + * Select the `Public Endpoint` option + * Type: GitHub + * Server URL: https://github.com/ + * Personal Access Token: #Your Personal Access Token# +8. Click `Create` to create the config provider +9. For Repository select `oci-landing-zones` +10. For Branch select `main` +11. for Working directory, select `templates/enterprise-landing-zone` + +12. For Name, give the stack a name or accept the default. +13. For the Create in Compartment dropdown, select the compartment to store the Stack. +14. For Terraform Version dropdown, make sure to select 1.0.x at least. Lower Terraform versions are not supported. + +After completing the Stack Creation Wizard, the subsequent step prompts for variables values. **For reference on the configuration variable values read the [Configuration Guide](CONFIGURATION.md). For a full list of all available configuration variables see the [Input Variables Reference in the README](README.md#inputs)** + +After filling in the required input variables, click next to review the stack values and create the stack. + +In the Stack page use the appropriate buttons to plan/apply/destroy your stack. + +### For more information + +- [Resource Manager Overview](https://docs.oracle.com/en-us/iaas/Content/ResourceManager/Concepts/resourcemanager.htm) + +## Teardown and destroy of an Enterprise Scale Baseline Landing Zone stack + +If you wish to delete an entire Enterprise Scale Baseline Landing Zone stack, there are a few resources that will require some manual intervention due to dependancies or conditions that are outside of Terraform's knowledge. + +The steps to clean up these resources is as follows: + +1. Bucket Removal (For each Environment) + * Navigate to the audit bucket, default bucket, and service event bucket in the logging compartment, and archive bucket in the home compartment. + * For each bucket: + * Delete the retention rules: on the bucket page, navigate to Resource → Retention Rules. + * Delete all the objects in the bucket: on the bucket page, navigate to Resource → Objects. + * Delete the bucket. + +2. Identity Domain (For each Environment) + + * Deactivate the identity domain created in the security compartment for each env: on the Identity Domain page, navigate to More actions → Deactivate. + * Delete the identity domain. + +3. Vault/Key (For each Environment) + + * The vault cannot be deleted right away. Vaults have a minimum 7-Day waiting period before deletion. This is because once the Vault is deleted, all data encrypted with keys in that Vault becomes unreadable. + * You can move the vault and the Master Encryption Key to another compartment outside the Enterprise Scale Baseline Landing Zone home before deleting it in order to delete the landing zone. + * Or you can schedule a deletion for the key and the vault, and then wait to delete the Enterprise Scale Baseline Landing Zone when the Vault and key have been deleted. + +4. Logging Analytics + + * Purge the log: navigate to the Administration page of Logging Analytics → click the storage under the Resources section → Purge Logs + * (Optional) Delete the Logging Analytics group. + +Once these resources have been removed, you will be able to use Terraform to delete the rest of the Enterprise Scale Baseline Landing Zone. If using terraform CLI: run `terraform destroy` to remove other resources. If using ORM: navigate to the corresponding stack created and click `Destroy`. + +## Known Issues + +--- +These are some known temporary issues that can occur while deploying the Enterprise Scale Baseline Landing Zone. + +* 400-InvalidParameter Error in CreateServiceConnector operation: This can occasionally happen due to logs taking longer than normal to create while setting up the logging infrastructure. This will correct itself when the logs finish creating. Later Apply jobs in ORM or invocations of `terraform apply` should succeed. +* 429-TooManyRequests Error: A tenancy making a large number of OCI API requests in rapid succession may be throttled by the API. The solution is to wait some period of time (a few minutes) and retry the terraform operation again. This is rarely seen on `apply` but may occasionally be seen on `destroy` runs, as the delete operations are much faster than create, and Terraform makes many API calls. \ No newline at end of file diff --git a/templates/enterprise-landing-zone/README.md b/templates/enterprise-landing-zone/README.md new file mode 100644 index 00000000..957f1b08 --- /dev/null +++ b/templates/enterprise-landing-zone/README.md @@ -0,0 +1,226 @@ +# Enterprise Scale Baseline Landing Zone + +Version 2 of Enterprise Scale Baseline Landing Zone + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [oci](#requirement\_oci) | 4.96.0 | + +## Providers + +| Name | Version | +|------|---------| +| [oci](#provider\_oci) | 4.96.0 | +| [random](#provider\_random) | 3.4.3 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [architecture\_tag](#module\_architecture\_tag) | ../../modules/tag | n/a | +| [archive\_bucket](#module\_archive\_bucket) | ../../modules/bucket | n/a | +| [archive\_key](#module\_archive\_key) | ../../modules/key | n/a | +| [authentication\_policy](#module\_authentication\_policy) | ../../modules/authentication-policy | n/a | +| [break\_glass\_users](#module\_break\_glass\_users) | ../../modules/break_glass_user | n/a | +| [cloud\_guard\_root\_policy](#module\_cloud\_guard\_root\_policy) | ../../modules/policies | n/a | +| [cloud\_guard\_target\_policy](#module\_cloud\_guard\_target\_policy) | ../../modules/policies | n/a | +| [home\_compartment](#module\_home\_compartment) | ../../modules/compartment | n/a | +| [key\_archive\_policy](#module\_key\_archive\_policy) | ../../modules/policies | n/a | +| [logging\_analytics\_namespace](#module\_logging\_analytics\_namespace) | ../../modules/log-analytics-namespace | n/a | +| [nonprod\_archive\_audit\_log\_service\_connector](#module\_nonprod\_archive\_audit\_log\_service\_connector) | ../../modules/service-connector | n/a | +| [nonprod\_archive\_default\_log\_service\_connector](#module\_nonprod\_archive\_default\_log\_service\_connector) | ../../modules/service-connector | n/a | +| [nonprod\_archive\_service\_events\_service\_connector](#module\_nonprod\_archive\_service\_events\_service\_connector) | ../../modules/service-connector | n/a | +| [nonprod\_environment](#module\_nonprod\_environment) | ../elz-environment | n/a | +| [nonprod\_platform\_admin\_policy](#module\_nonprod\_platform\_admin\_policy) | ../../modules/policies | n/a | +| [osms\_dg\_policy](#module\_osms\_dg\_policy) | ../../modules/policies | n/a | +| [osms\_dynamic\_group](#module\_osms\_dynamic\_group) | ../../modules/dynamic-group | n/a | +| [osms\_policy](#module\_osms\_policy) | ../../modules/policies | n/a | +| [prod\_archive\_audit\_log\_service\_connector](#module\_prod\_archive\_audit\_log\_service\_connector) | ../../modules/service-connector | n/a | +| [prod\_archive\_default\_log\_service\_connector](#module\_prod\_archive\_default\_log\_service\_connector) | ../../modules/service-connector | n/a | +| [prod\_archive\_service\_events\_service\_connector](#module\_prod\_archive\_service\_events\_service\_connector) | ../../modules/service-connector | n/a | +| [prod\_environment](#module\_prod\_environment) | ../elz-environment | n/a | +| [prod\_platform\_admin\_policy](#module\_prod\_platform\_admin\_policy) | ../../modules/policies | n/a | +| [service\_connector\_archive\_policy](#module\_service\_connector\_archive\_policy) | ../../modules/policies | n/a | +| [service\_connector\_policy](#module\_service\_connector\_policy) | ../../modules/policies | n/a | +| [vault\_policy](#module\_vault\_policy) | ../../modules/policies | n/a | +| [vss\_policy](#module\_vss\_policy) | ../../modules/policies | n/a | + +## Resources + +| Name | Type | +|------|------| +| [random_id.tag](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | +| [oci_identity_region_subscriptions.regions](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/identity_region_subscriptions) | data source | +| [oci_objectstorage_namespace.ns](https://registry.terraform.io/providers/oracle/oci/4.96.0/docs/data-sources/objectstorage_namespace) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [api\_fingerprint](#input\_api\_fingerprint) | The fingerprint of API | `string` | `""` | no | +| [api\_private\_key](#input\_api\_private\_key) | The API private key | `string` | `""` | no | +| [api\_private\_key\_path](#input\_api\_private\_key\_path) | The local path to the API private key | `string` | `""` | no | +| [archive\_log\_retention\_policy\_duration\_amount](#input\_archive\_log\_retention\_policy\_duration\_amount) | The timeAmount is interpreted in units defined by the timeUnit parameter, and is calculated in relation to each object's Last-Modified timestamp. | `string` | `"1"` | no | +| [archive\_log\_retention\_policy\_duration\_time\_unit](#input\_archive\_log\_retention\_policy\_duration\_time\_unit) | The unit that should be used to interpret timeAmount. | `string` | `"DAYS"` | no | +| [bgp\_md5auth\_key](#input\_bgp\_md5auth\_key) | The key for BGP MD5 authentication. Only applicable if your system requires MD5 authentication | `string` | `""` | no | +| [break\_glass\_user\_email\_list](#input\_break\_glass\_user\_email\_list) | Unique list of break glass user email addresses that do not exist in the tenancy. These users are added to the Administrator group. | `list(string)` | `[]` | no | +| [cloud\_guard\_target\_tenancy](#input\_cloud\_guard\_target\_tenancy) | true if cloud guard targets to tenancy, false if cloud guard targets to Landing Zone home compartment | `bool` | `false` | no | +| [current\_user\_ocid](#input\_current\_user\_ocid) | The OCID of the current user | `string` | `""` | no | +| [customer\_onprem\_ip\_cidr](#input\_customer\_onprem\_ip\_cidr) | n/a | `list(string)` | `[]` | no | +| [customer\_primary\_bgp\_peering\_ip](#input\_customer\_primary\_bgp\_peering\_ip) | The primary BGP IPv4 address of the customer's router | `string` | `""` | no | +| [customer\_secondary\_bgp\_peering\_ip](#input\_customer\_secondary\_bgp\_peering\_ip) | [Optional] The secondary BGP IPv4 address of the customer's router | `string` | `""` | no | +| [enable\_cloud\_guard](#input\_enable\_cloud\_guard) | true if you don't have cloud guard enabled, false if you've already have cloud guard enabled. | `bool` | `true` | no | +| [enable\_compartment\_delete](#input\_enable\_compartment\_delete) | Set to true to allow the compartments to delete on terraform destroy. | `bool` | `true` | no | +| [enable\_vpn\_or\_fastconnect](#input\_enable\_vpn\_or\_fastconnect) | Option to enable VPN or FASTCONNECT service. Options are NONE, VPN, FASTCONNECT. | `string` | `"NONE"` | no | +| [fastconnect\_provider](#input\_fastconnect\_provider) | Fastconnect provider. Please choose from: AT&T, Azure, Megaport, QTS, CEintro, Cologix, CoreSite, Digitial Realty, EdgeConneX, Epsilon, Equinix, InterCloud, Lumen, Neutrona, OMCS, OracleL2ItegDeployment, OracleL3ItegDeployment, Orange, Verizon, Zayo | `string` | `""` | no | +| [fastconnect\_routing\_policy](#input\_fastconnect\_routing\_policy) | Available FastConnect routing policies: ORACLE\_SERVICE\_NETWORK, REGIONAL, MARKET\_LEVEL, GLOBAL | `list(string)` | `[]` | no | +| [home\_compartment\_name](#input\_home\_compartment\_name) | The name of the Landing Zone home compartment. | `string` | `"OCI-ELZ-CMP-HOME"` | no | +| [igw\_hub\_check](#input\_igw\_hub\_check) | n/a | `list(string)` |
[
""
]
| no | +| [nat\_gw\_hub\_check](#input\_nat\_gw\_hub\_check) | n/a | `list(string)` |
[
""
]
| no | +| [nat\_gw\_spoke\_check](#input\_nat\_gw\_spoke\_check) | n/a | `list(string)` |
[
""
]
| no | +| [nonprod\_application\_admin\_group\_name](#input\_nonprod\_application\_admin\_group\_name) | The group name for the OCI Application Administrators Group. Defaults to OCI-ELZ-UGP-N-APP-ADMIN if blank or not provided. | `string` | `""` | no | +| [nonprod\_bastion\_client\_cidr\_block\_allow\_list](#input\_nonprod\_bastion\_client\_cidr\_block\_allow\_list) | A list of address ranges in CIDR notation that you want to allow to connect to sessions hosted by this bastion. | `list(string)` | n/a | yes | +| [nonprod\_bgp\_cust\_tunnela\_ip](#input\_nonprod\_bgp\_cust\_tunnela\_ip) | The IP address for the CPE end of the inside tunnel interface. | `string` | `""` | no | +| [nonprod\_bgp\_oci\_tunnela\_ip](#input\_nonprod\_bgp\_oci\_tunnela\_ip) | The IP address for the Oracle end of the inside tunnel interface. | `string` | `""` | no | +| [nonprod\_budget\_alert\_rule\_message](#input\_nonprod\_budget\_alert\_rule\_message) | The alert message for budget alerts. Required *if* nonprod\_enable\_budget is true. | `string` | `""` | no | +| [nonprod\_budget\_alert\_rule\_recipients](#input\_nonprod\_budget\_alert\_rule\_recipients) | The delimited list of email addresses to receive the alert when it triggers. Delimiter characters can be a comma, space, TAB, or semicolon. Required *if* nonprod\_enable\_budget is true. | `string` | `""` | no | +| [nonprod\_budget\_alert\_rule\_threshold](#input\_nonprod\_budget\_alert\_rule\_threshold) | The threshold for the budget alert. Required *if* nonprod\_enable\_budget is true. | `string` | `""` | no | +| [nonprod\_budget\_amount](#input\_nonprod\_budget\_amount) | The amount of the budget expressed as a whole number in the currency of the customer's rate card. Required *if* nonprod\_enable\_budget is true. | `string` | `""` | no | +| [nonprod\_cost\_center\_tagging](#input\_nonprod\_cost\_center\_tagging) | Non-ProductionGeo Location. | `string` | n/a | yes | +| [nonprod\_cpe\_display\_name](#input\_nonprod\_cpe\_display\_name) | Customer Premises Equipment name. Recommendation: OCI-ELZ-CPE-[Environment]-HUB-[Region] 001 | `string` | `""` | no | +| [nonprod\_cpe\_ip\_address](#input\_nonprod\_cpe\_ip\_address) | Customer Premises Equipment (CPE) IP address | `string` | `""` | no | +| [nonprod\_cpe\_vendor](#input\_nonprod\_cpe\_vendor) | Type corresponding number as your CPE vendor: Yamaha-RTX1210 0, Other 1, Cisco-9.7.1-or-later 2, Yamaha-RTX830 3, Libreswan 4, Fortinet 5, NEC 6, Cisco-8.5+ 7, Cisco-IOS 8, WatchGuard 9, Juniper-MX 10, Juniper-SRX 11, Furukawa 12, Check\_Point 13, Palo\_Alto 14 | `number` | `0` | no | +| [nonprod\_create\_master\_encryption\_key](#input\_nonprod\_create\_master\_encryption\_key) | Option create master encryption key | `bool` | `true` | no | +| [nonprod\_customer\_bgp\_asn](#input\_nonprod\_customer\_bgp\_asn) | ASN is required and used for the tunnel's BGP session | `string` | `""` | no | +| [nonprod\_database\_admin\_group\_name](#input\_nonprod\_database\_admin\_group\_name) | The group name for the OCI Database Logging Administrators Group. Defaults to OCI-ELZ-UGP-N-DB-ADMIN if blank or not provided. | `string` | `""` | no | +| [nonprod\_domain\_admin\_email](#input\_nonprod\_domain\_admin\_email) | The email address for the non prod identity domain admin. | `string` | n/a | yes | +| [nonprod\_enable\_bastion](#input\_nonprod\_enable\_bastion) | Option to enable bastion service | `bool` | n/a | yes | +| [nonprod\_enable\_budget](#input\_nonprod\_enable\_budget) | n/a | `bool` | n/a | yes | +| [nonprod\_enable\_fastconnect](#input\_nonprod\_enable\_fastconnect) | [Please don't change this value] Enable fastconnect in non prod environment. | `bool` | `false` | no | +| [nonprod\_enable\_internet\_gateway\_hub](#input\_nonprod\_enable\_internet\_gateway\_hub) | Option to enable TRUE and Disable false. | `string` | `"false"` | no | +| [nonprod\_enable\_nat\_gateway\_hub](#input\_nonprod\_enable\_nat\_gateway\_hub) | Option to enable TRUE and Disable false. | `string` | `"false"` | no | +| [nonprod\_enable\_nat\_gateway\_spoke](#input\_nonprod\_enable\_nat\_gateway\_spoke) | Option to enable TRUE and Disable false. | `string` | `"false"` | no | +| [nonprod\_enable\_network\_monitoring\_alarms](#input\_nonprod\_enable\_network\_monitoring\_alarms) | Enable Network Monitoring Alarms in Non-Production Network Compartment | `bool` | `false` | no | +| [nonprod\_enable\_security\_monitoring\_alarms](#input\_nonprod\_enable\_security\_monitoring\_alarms) | Enable Security Monitoring Alarms in Non-Production Security Compartment | `bool` | `false` | no | +| [nonprod\_enable\_service\_gateway\_hub](#input\_nonprod\_enable\_service\_gateway\_hub) | Option to enable TRUE and Disable false. | `string` | `"false"` | no | +| [nonprod\_enable\_service\_gateway\_spoke](#input\_nonprod\_enable\_service\_gateway\_spoke) | Option to enable TRUE and Disable false. | `string` | `"false"` | no | +| [nonprod\_enable\_tagging](#input\_nonprod\_enable\_tagging) | Option to enable Tagging gateway in Non-Production environment | `bool` | `false` | no | +| [nonprod\_enable\_vault\_replication](#input\_nonprod\_enable\_vault\_replication) | Option to enable vault replication | `bool` | `false` | no | +| [nonprod\_enable\_vpn](#input\_nonprod\_enable\_vpn) | Enable VPN in non prod environment | `bool` | n/a | yes | +| [nonprod\_enable\_workload\_monitoring\_alarms](#input\_nonprod\_enable\_workload\_monitoring\_alarms) | Enable Workload Monitoring Alarms in Non-Production Workload Compartment | `bool` | `false` | no | +| [nonprod\_geo\_location\_tagging](#input\_nonprod\_geo\_location\_tagging) | Non-Production Geo Location. | `string` | n/a | yes | +| [nonprod\_hub\_private\_subnet\_cidr\_block](#input\_nonprod\_hub\_private\_subnet\_cidr\_block) | Non-Production Enivornment HUB Private Subnet CIDR Block. | `string` | n/a | yes | +| [nonprod\_hub\_public\_subnet\_cidr\_block](#input\_nonprod\_hub\_public\_subnet\_cidr\_block) | Non-Production Enivornment HUB Public Subnet CIDR Block. | `string` | n/a | yes | +| [nonprod\_hub\_vcn\_cidr\_block](#input\_nonprod\_hub\_vcn\_cidr\_block) | Non-Production Enivornment HUB VCN CIDR Block. | `string` | n/a | yes | +| [nonprod\_iam\_admin\_group\_name](#input\_nonprod\_iam\_admin\_group\_name) | The group name for the OCI Landing Zone IAM Administrators Group. Defaults to OCI-ELZ-UGP-N-IDP-ADMIN if blank or not provided. | `string` | `""` | no | +| [nonprod\_identity\_topic\_endpoints](#input\_nonprod\_identity\_topic\_endpoints) | List of email addresses for Identity notifications. | `list(string)` | `[]` | no | +| [nonprod\_ipsec\_connection\_static\_routes](#input\_nonprod\_ipsec\_connection\_static\_routes) | n/a | `list(string)` |
[
""
]
| no | +| [nonprod\_ipsec\_display\_name](#input\_nonprod\_ipsec\_display\_name) | IPsec display name. Recommendation: OCI-ELZ-IPS-[Environment]-HUB-[Region] 001 | `string` | `""` | no | +| [nonprod\_ipsec\_routing\_type](#input\_nonprod\_ipsec\_routing\_type) | BGP dynamic routing, STATIC routing. Type BGP or STATIC | `string` | `"STATIC"` | no | +| [nonprod\_network\_admin\_group\_name](#input\_nonprod\_network\_admin\_group\_name) | The group name for the OCI Landing Zone Network Administrators Group. Defaults to OCI-ELZ-UGP-N-NET-ADMIN if blank or not provided. | `string` | `""` | no | +| [nonprod\_network\_topic\_endpoints](#input\_nonprod\_network\_topic\_endpoints) | List of email addresses for Network Warning and Critical notifications. | `list(string)` | `[]` | no | +| [nonprod\_ops\_admin\_group\_name](#input\_nonprod\_ops\_admin\_group\_name) | The group name for the OCI Landing Zone Ops Administrators Group. Defaults to OCI-ELZ-UGP-N-OPS-ADMIN if blank or not provided. | `string` | `""` | no | +| [nonprod\_platform\_admin\_group\_name](#input\_nonprod\_platform\_admin\_group\_name) | The group name for the OCI Landing Zone Platform Administrators Group. Defaults to OCI-ELZ-UGP-N-PLT-ADMIN if blank or not provided. | `string` | `""` | no | +| [nonprod\_platform\_topic\_endpoints](#input\_nonprod\_platform\_topic\_endpoints) | List of email addresses for Platform notifications. | `list(string)` | `[]` | no | +| [nonprod\_retention\_policy\_duration\_amount](#input\_nonprod\_retention\_policy\_duration\_amount) | The timeAmount is interpreted in units defined by the timeUnit parameter, and is calculated in relation to each object's Last-Modified timestamp. | `string` | `"1"` | no | +| [nonprod\_retention\_policy\_duration\_time\_unit](#input\_nonprod\_retention\_policy\_duration\_time\_unit) | The unit that should be used to interpret timeAmount. | `string` | `"DAYS"` | no | +| [nonprod\_secops\_topic\_endpoints](#input\_nonprod\_secops\_topic\_endpoints) | List of email addresses for Secops Warning and Critical notifications. | `list(string)` | `[]` | no | +| [nonprod\_security\_admin\_group\_name](#input\_nonprod\_security\_admin\_group\_name) | The group name for the OCI Landing Zone Security Administrators Group. Defaults to OCI-ELZ-UGP-N-SEC-ADMIN if blank or not provided. | `string` | `""` | no | +| [nonprod\_shared\_secret](#input\_nonprod\_shared\_secret) | The shared secret (pre-shared key) to use for the IPSec tunnel | `string` | `"example"` | no | +| [nonprod\_spoke\_subnet\_app\_cidr\_block](#input\_nonprod\_spoke\_subnet\_app\_cidr\_block) | Non-Production Enivornment Spoke App Subnet CIDR Block. | `string` | n/a | yes | +| [nonprod\_spoke\_subnet\_db\_cidr\_block](#input\_nonprod\_spoke\_subnet\_db\_cidr\_block) | Non-Production Enivornment Spoke DB Subnet CIDR Block. | `string` | n/a | yes | +| [nonprod\_spoke\_subnet\_web\_cidr\_block](#input\_nonprod\_spoke\_subnet\_web\_cidr\_block) | Non-Production Enivornment Spoke Web Subnet CIDR Block. | `string` | n/a | yes | +| [nonprod\_spoke\_vcn\_cidr](#input\_nonprod\_spoke\_vcn\_cidr) | Non-Production Enivornment Spoke VCN CIDR Block. | `string` | n/a | yes | +| [nonprod\_tunnel\_a\_display\_name](#input\_nonprod\_tunnel\_a\_display\_name) | Tunnel A display name. Recommendation: | `string` | `""` | no | +| [nonprod\_tunnel\_b\_display\_name](#input\_nonprod\_tunnel\_b\_display\_name) | Tunnel B display name. Recommendation: | `string` | `""` | no | +| [nonprod\_vault\_replica\_region](#input\_nonprod\_vault\_replica\_region) | the region to be created replica to. Required *if* nonprod\_enable\_vault\_replication is true. | `string` | `""` | no | +| [nonprod\_vault\_type](#input\_nonprod\_vault\_type) | The type of vault to create. | `string` | `"DEFAULT"` | no | +| [nonprod\_workload\_admin\_group\_name](#input\_nonprod\_workload\_admin\_group\_name) | The group name for the OCI Workload Administrators Group. Defaults to OCI-ELZ-UGP-N-WRK-ADMIN if blank or not provided. | `string` | `""` | no | +| [nonprod\_workload\_topic\_endpoints](#input\_nonprod\_workload\_topic\_endpoints) | List of email addresses for Non Prod Workload notifications. | `list(string)` | `[]` | no | +| [onboard\_log\_analytics](#input\_onboard\_log\_analytics) | Set to true to onboard the tenancy to logging analytics. | `bool` | `true` | no | +| [oracle\_primary\_bgp\_peering\_ip](#input\_oracle\_primary\_bgp\_peering\_ip) | The primary BGP IPv4 address for Oracle's end of the BGP session | `string` | `""` | no | +| [oracle\_secondary\_bgp\_peering\_ip](#input\_oracle\_secondary\_bgp\_peering\_ip) | [Optional] Secondary IPv4 address for Oracle's end of the BGP session | `string` | `""` | no | +| [prod\_application\_admin\_group\_name](#input\_prod\_application\_admin\_group\_name) | The group name for the OCI Application Administrators Group. Defaults to OCI-ELZ-UGP-P-APP-ADMIN if blank or not provided. | `string` | `""` | no | +| [prod\_bastion\_client\_cidr\_block\_allow\_list](#input\_prod\_bastion\_client\_cidr\_block\_allow\_list) | A list of address ranges in CIDR notation that you want to allow to connect to sessions hosted by this bastion. | `list(string)` | n/a | yes | +| [prod\_bgp\_cust\_tunnela\_ip](#input\_prod\_bgp\_cust\_tunnela\_ip) | The IP address for the CPE end of the inside tunnel interface. | `string` | `""` | no | +| [prod\_bgp\_oci\_tunnela\_ip](#input\_prod\_bgp\_oci\_tunnela\_ip) | The IP address for the Oracle end of the inside tunnel interface. | `string` | `""` | no | +| [prod\_budget\_alert\_rule\_message](#input\_prod\_budget\_alert\_rule\_message) | The alert message for budget alerts. Required *if* prod\_enable\_budget is true. | `string` | `""` | no | +| [prod\_budget\_alert\_rule\_recipients](#input\_prod\_budget\_alert\_rule\_recipients) | The delimited list of email addresses to receive the alert when it triggers. Delimiter characters can be a comma, space, TAB, or semicolon. Required *if* prod\_enable\_budget is true. | `string` | `""` | no | +| [prod\_budget\_alert\_rule\_threshold](#input\_prod\_budget\_alert\_rule\_threshold) | The threshold for the budget alert. Required *if* prod\_enable\_budget is true. | `string` | `""` | no | +| [prod\_budget\_amount](#input\_prod\_budget\_amount) | The amount of the budget expressed as a whole number in the currency of the customer's rate card. Required *if* prod\_enable\_budget is true. | `string` | `""` | no | +| [prod\_cost\_center\_tagging](#input\_prod\_cost\_center\_tagging) | Production Cost Center. | `string` | n/a | yes | +| [prod\_cpe\_display\_name](#input\_prod\_cpe\_display\_name) | Customer Premises Equipment name. Recommendation: OCI-ELZ-CPE-[Environment]-HUB-[Region] 001 | `string` | `""` | no | +| [prod\_cpe\_ip\_address](#input\_prod\_cpe\_ip\_address) | Customer Premises Equipment (CPE) IP address | `string` | `""` | no | +| [prod\_cpe\_vendor](#input\_prod\_cpe\_vendor) | Type corresponding number as your CPE vendor: Yamaha-RTX1210 0, Other 1, Cisco-9.7.1-or-later 2, Yamaha-RTX830 3, Libreswan 4, Fortinet 5, NEC 6, Cisco-8.5+ 7, Cisco-IOS 8, WatchGuard 9, Juniper-MX 10, Juniper-SRX 11, Furukawa 12, Check\_Point 13, Palo\_Alto 14 | `number` | `0` | no | +| [prod\_create\_master\_encryption\_key](#input\_prod\_create\_master\_encryption\_key) | Option create master encryption key | `bool` | `true` | no | +| [prod\_customer\_bgp\_asn](#input\_prod\_customer\_bgp\_asn) | ASN is required and used for the tunnel's BGP session | `string` | `""` | no | +| [prod\_database\_admin\_group\_name](#input\_prod\_database\_admin\_group\_name) | The group name for the OCI Database Logging Administrators Group. Defaults to OCI-ELZ-UGP-P-DB-ADMIN if blank or not provided. | `string` | `""` | no | +| [prod\_domain\_admin\_email](#input\_prod\_domain\_admin\_email) | The email address for the prod identity domain admin. | `string` | n/a | yes | +| [prod\_enable\_bastion](#input\_prod\_enable\_bastion) | Option to enable bastion service | `bool` | n/a | yes | +| [prod\_enable\_budget](#input\_prod\_enable\_budget) | n/a | `bool` | n/a | yes | +| [prod\_enable\_fastconnect](#input\_prod\_enable\_fastconnect) | [Please don't change this value] Enable fastconnect in prod environment. | `bool` | `true` | no | +| [prod\_enable\_internet\_gateway\_hub](#input\_prod\_enable\_internet\_gateway\_hub) | Option to enable TRUE and Disable false. | `string` | `"false"` | no | +| [prod\_enable\_nat\_gateway\_hub](#input\_prod\_enable\_nat\_gateway\_hub) | Option to enable TRUE and Disable false. | `string` | `"false"` | no | +| [prod\_enable\_nat\_gateway\_spoke](#input\_prod\_enable\_nat\_gateway\_spoke) | Option to enable TRUE and Disable false. | `string` | `"false"` | no | +| [prod\_enable\_network\_monitoring\_alarms](#input\_prod\_enable\_network\_monitoring\_alarms) | Enable Network Monitoring Alarms in Production Network Compartment | `bool` | `false` | no | +| [prod\_enable\_security\_monitoring\_alarms](#input\_prod\_enable\_security\_monitoring\_alarms) | Enable Security Monitoring Alarms in Production Security Compartment | `bool` | `false` | no | +| [prod\_enable\_service\_gateway\_hub](#input\_prod\_enable\_service\_gateway\_hub) | Option to enable TRUE and Disable false. | `string` | `"false"` | no | +| [prod\_enable\_service\_gateway\_spoke](#input\_prod\_enable\_service\_gateway\_spoke) | Option to enable TRUE and Disable false. | `string` | `"false"` | no | +| [prod\_enable\_tagging](#input\_prod\_enable\_tagging) | Option to enable Tagging gateway in Production environment | `bool` | `false` | no | +| [prod\_enable\_vault\_replication](#input\_prod\_enable\_vault\_replication) | Option to enable vault replication | `bool` | `false` | no | +| [prod\_enable\_vpn](#input\_prod\_enable\_vpn) | Enable VPN in prod environment | `bool` | n/a | yes | +| [prod\_enable\_workload\_monitoring\_alarms](#input\_prod\_enable\_workload\_monitoring\_alarms) | Enable Workload Monitoring Alarms in Production Workload Compartment | `bool` | `false` | no | +| [prod\_geo\_location\_tagging](#input\_prod\_geo\_location\_tagging) | Production Geo Center. | `string` | n/a | yes | +| [prod\_hub\_private\_subnet\_cidr\_block](#input\_prod\_hub\_private\_subnet\_cidr\_block) | Production Enivornment HUB Private Subnet CIDR Block. | `string` | n/a | yes | +| [prod\_hub\_public\_subnet\_cidr\_block](#input\_prod\_hub\_public\_subnet\_cidr\_block) | Production Enivornment HUB Public Subnet CIDR Block. | `string` | n/a | yes | +| [prod\_hub\_vcn\_cidr\_block](#input\_prod\_hub\_vcn\_cidr\_block) | Production Enivornment HUB VCN CIDR Block. | `string` | n/a | yes | +| [prod\_iam\_admin\_group\_name](#input\_prod\_iam\_admin\_group\_name) | The group name for the OCI Landing Zone IAM Administrators Group. Defaults to OCI-ELZ-UGP-P-IDP-ADMIN if blank or not provided. | `string` | `""` | no | +| [prod\_identity\_topic\_endpoints](#input\_prod\_identity\_topic\_endpoints) | List of email addresses for Identity notifications. | `list(string)` | `[]` | no | +| [prod\_ipsec\_connection\_static\_routes](#input\_prod\_ipsec\_connection\_static\_routes) | n/a | `list(string)` |
[
""
]
| no | +| [prod\_ipsec\_display\_name](#input\_prod\_ipsec\_display\_name) | IPsec display name. Recommendation: OCI-ELZ-IPS-[Environment]-HUB-[Region] 001 | `string` | `""` | no | +| [prod\_ipsec\_routing\_type](#input\_prod\_ipsec\_routing\_type) | BGP dynamic routing, STATIC routing. Type BGP or STATIC | `string` | `"STATIC"` | no | +| [prod\_network\_admin\_group\_name](#input\_prod\_network\_admin\_group\_name) | The group name for the OCI Landing Zone Network Administrators Group. Defaults to OCI-ELZ-UGP-P-NET-ADMIN if blank or not provided. | `string` | `""` | no | +| [prod\_network\_topic\_endpoints](#input\_prod\_network\_topic\_endpoints) | List of email addresses for Network Warning and Critical notifications. | `list(string)` | `[]` | no | +| [prod\_ops\_admin\_group\_name](#input\_prod\_ops\_admin\_group\_name) | The group name for the OCI Landing Zone Ops Administrators Group. Defaults to OCI-ELZ-UGP-P-OPS-ADMIN if blank or not provided. | `string` | `""` | no | +| [prod\_platform\_admin\_group\_name](#input\_prod\_platform\_admin\_group\_name) | The group name for the OCI Landing Zone Platform Administrators Group. Defaults to OCI-ELZ-UGP-P-PLT-ADMIN if blank or not provided. | `string` | `""` | no | +| [prod\_platform\_topic\_endpoints](#input\_prod\_platform\_topic\_endpoints) | List of email addresses for Platform notifications. | `list(string)` | `[]` | no | +| [prod\_retention\_policy\_duration\_amount](#input\_prod\_retention\_policy\_duration\_amount) | The timeAmount is interpreted in units defined by the timeUnit parameter, and is calculated in relation to each object's Last-Modified timestamp. | `string` | `"1"` | no | +| [prod\_retention\_policy\_duration\_time\_unit](#input\_prod\_retention\_policy\_duration\_time\_unit) | The unit that should be used to interpret timeAmount. | `string` | `"DAYS"` | no | +| [prod\_secops\_topic\_endpoints](#input\_prod\_secops\_topic\_endpoints) | List of email addresses for Secops Warning and Critical notifications. | `list(string)` | `[]` | no | +| [prod\_security\_admin\_group\_name](#input\_prod\_security\_admin\_group\_name) | The group name for the OCI Landing Zone Security Administrators Group. Defaults to OCI-ELZ-UGP-P-SEC-ADMIN if blank or not provided. | `string` | `""` | no | +| [prod\_shared\_secret](#input\_prod\_shared\_secret) | The shared secret (pre-shared key) to use for the IPSec tunnel | `string` | `"example"` | no | +| [prod\_spoke\_subnet\_app\_cidr\_block](#input\_prod\_spoke\_subnet\_app\_cidr\_block) | Production Enivornment Spoke App Subnet CIDR Block. | `string` | n/a | yes | +| [prod\_spoke\_subnet\_db\_cidr\_block](#input\_prod\_spoke\_subnet\_db\_cidr\_block) | Production Enivornment Spoke DB Subnet CIDR Block. | `string` | n/a | yes | +| [prod\_spoke\_subnet\_web\_cidr\_block](#input\_prod\_spoke\_subnet\_web\_cidr\_block) | Production Enivornment Spoke Web Subnet CIDR Block. | `string` | n/a | yes | +| [prod\_spoke\_vcn\_cidr](#input\_prod\_spoke\_vcn\_cidr) | Production Enivornment Spoke VCN CIDR Block. | `string` | n/a | yes | +| [prod\_tunnel\_a\_display\_name](#input\_prod\_tunnel\_a\_display\_name) | Tunnel A display name. Recommendation: | `string` | `""` | no | +| [prod\_tunnel\_b\_display\_name](#input\_prod\_tunnel\_b\_display\_name) | Tunnel B display name. Recommendation: | `string` | `""` | no | +| [prod\_vault\_replica\_region](#input\_prod\_vault\_replica\_region) | the region to be created replica to. Required *if* prod\_enable\_vault\_replication is true. | `string` | `""` | no | +| [prod\_vault\_type](#input\_prod\_vault\_type) | The type of vault to create. | `string` | `"DEFAULT"` | no | +| [prod\_workload\_admin\_group\_name](#input\_prod\_workload\_admin\_group\_name) | The group name for the OCI Workload Administrators Group. Defaults to OCI-ELZ-UGP-P-WRK-ADMIN if blank or not provided. | `string` | `""` | no | +| [prod\_workload\_topic\_endpoints](#input\_prod\_workload\_topic\_endpoints) | List of email addresses for Prod Workload notifications. | `list(string)` | `[]` | no | +| [provider\_service\_key\_name](#input\_provider\_service\_key\_name) | The provider service key that the provider gives you when you set up a virtual circuit connection from the provider to OCI | `string` | `""` | no | +| [region](#input\_region) | The OCI region | `string` | n/a | yes | +| [resource\_label](#input\_resource\_label) | A prefix used to avoid naming conflicts if multiple Landing Zones are deployed. | `string` | `""` | no | +| [service\_gw\_hub\_check](#input\_service\_gw\_hub\_check) | n/a | `list(string)` |
[
""
]
| no | +| [service\_gw\_spoke\_check](#input\_service\_gw\_spoke\_check) | n/a | `list(string)` |
[
""
]
| no | +| [tenancy\_ocid](#input\_tenancy\_ocid) | The OCID of tenancy | `string` | n/a | yes | +| [virtual\_circuit\_bandwidth\_shape](#input\_virtual\_circuit\_bandwidth\_shape) | The provisioned data rate of the connection | `string` | `"1500"` | no | +| [virtual\_circuit\_customer\_asn](#input\_virtual\_circuit\_customer\_asn) | The BGP ASN of the network at the other end of the BGP session from Oracle | `string` | `0` | no | +| [virtual\_circuit\_display\_name](#input\_virtual\_circuit\_display\_name) | The display name of this virtual circuit. Recommendation: OCI-ELZ-FCN-P-HUB-[REGION] 001 | `string` | `""` | no | +| [virtual\_circuit\_is\_bfd\_enabled](#input\_virtual\_circuit\_is\_bfd\_enabled) | Set to true to enable BFD for IPv4 BGP peering, or set to false to disable BFD | `bool` | `false` | no | +| [virtual\_circuit\_type](#input\_virtual\_circuit\_type) | The type of IP addresses used in this virtual circuit. PRIVATE or PUBLIC | `string` | `""` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [dynamic\_group\_detail](#output\_dynamic\_group\_detail) | n/a | +| [subnets](#output\_subnets) | The subnet OCID | +| [vcn](#output\_vcn) | n/a | +| [workload\_compartment\_id](#output\_workload\_compartment\_id) | n/a | + \ No newline at end of file diff --git a/templates/enterprise-landing-zone/backend.tf b/templates/enterprise-landing-zone/backend.tf new file mode 100644 index 00000000..e69de29b diff --git a/templates/enterprise-landing-zone/datasources.tf b/templates/enterprise-landing-zone/datasources.tf new file mode 100644 index 00000000..3131c438 --- /dev/null +++ b/templates/enterprise-landing-zone/datasources.tf @@ -0,0 +1,18 @@ +# ----------------------------------------------------------------------------- +# Support for multi-region deployments +# ----------------------------------------------------------------------------- + +locals { + region_subscriptions = data.oci_identity_region_subscriptions.regions.region_subscriptions + home_region = [for region in local.region_subscriptions : region.region_name if region.is_home_region == true] + region_key = [for region in local.region_subscriptions : region.region_key if region.region_name == var.region] +} + +data "oci_identity_region_subscriptions" "regions" { + tenancy_id = var.tenancy_ocid +} + +data "oci_objectstorage_namespace" "ns" { + compartment_id = var.tenancy_ocid +} + diff --git a/templates/enterprise-landing-zone/environment.tf b/templates/enterprise-landing-zone/environment.tf new file mode 100644 index 00000000..9d986585 --- /dev/null +++ b/templates/enterprise-landing-zone/environment.tf @@ -0,0 +1,266 @@ +# ----------------------------------------------------------------------------- +# Prod Enviroment Resources +# ----------------------------------------------------------------------------- +locals { + prod_environment = { + environment_prefix = "P" + enable_tf_state_backup = false + enable_logging = true + } +} + +module "prod_environment" { + source = "../elz-environment" + + tenancy_ocid = var.tenancy_ocid + region = var.region + resource_label = var.resource_label + + home_compartment_id = module.home_compartment.compartment_id + environment_prefix = local.prod_environment.environment_prefix + enable_tf_state_backup = local.prod_environment.enable_tf_state_backup + enable_logging = local.prod_environment.enable_logging + domain_admin_email = var.prod_domain_admin_email + network_admin_group_name = var.prod_network_admin_group_name + iam_admin_group_name = var.prod_iam_admin_group_name + platform_admin_group_name = var.prod_platform_admin_group_name + ops_admin_group_name = var.prod_ops_admin_group_name + security_admin_group_name = var.prod_security_admin_group_name + + workload_admin_group_name = var.prod_workload_admin_group_name + application_admin_group_name = var.prod_application_admin_group_name + database_admin_group_name = var.prod_database_admin_group_name + + enable_budget = var.prod_enable_budget + budget_amount = var.prod_budget_amount + budget_alert_rule_threshold = var.prod_budget_alert_rule_threshold + budget_alert_rule_message = var.prod_budget_alert_rule_message + budget_alert_rule_recipients = var.prod_budget_alert_rule_recipients + enable_cloud_guard = var.enable_cloud_guard + cloud_guard_target_tenancy = var.cloud_guard_target_tenancy + home_compartment_name = var.home_compartment_name + enable_vpn_or_fastconnect = var.enable_vpn_or_fastconnect + cpe_ip_address = var.prod_cpe_ip_address + ipsec_connection_static_routes = var.prod_ipsec_connection_static_routes + enable_vpn_on_environment = var.prod_enable_vpn + cpe_display_name = var.prod_cpe_display_name + ipsec_display_name = var.prod_ipsec_display_name + cpe_vendor = var.prod_cpe_vendor + routing = var.prod_ipsec_routing_type + tunnel_a_display_name = var.prod_tunnel_a_display_name + customer_bgp_asn = var.prod_customer_bgp_asn + bgp_cust_tunnela_ip = var.prod_bgp_cust_tunnela_ip + bgp_oci_tunnela_ip = var.prod_bgp_oci_tunnela_ip + shared_secret = var.prod_shared_secret + tunnel_b_display_name = var.prod_tunnel_b_display_name + fastconnect_provider = var.fastconnect_provider + region_key = local.region_key[0] + virtual_circuit_bandwidth_shape = format("%s %s", var.virtual_circuit_bandwidth_shape, "Gbps") + virtual_circuit_display_name = var.virtual_circuit_display_name + provider_service_key_name = var.provider_service_key_name + fastconnect_routing_policy = var.fastconnect_routing_policy + virtual_circuit_type = var.virtual_circuit_type + customer_primary_bgp_peering_ip = var.customer_primary_bgp_peering_ip + oracle_primary_bgp_peering_ip = var.oracle_primary_bgp_peering_ip + customer_secondary_bgp_peering_ip = var.customer_secondary_bgp_peering_ip + oracle_secondary_bgp_peering_ip = var.oracle_secondary_bgp_peering_ip + virtual_circuit_customer_asn = var.virtual_circuit_customer_asn + virtual_circuit_is_bfd_enabled = var.virtual_circuit_is_bfd_enabled + bgp_md5auth_key = var.bgp_md5auth_key + enable_fastconnect_on_environment = var.prod_enable_fastconnect + customer_onprem_ip_cidr = var.customer_onprem_ip_cidr + + enable_internet_gateway_hub = var.prod_enable_internet_gateway_hub + enable_nat_gateway_hub = var.prod_enable_nat_gateway_hub + enable_service_gateway_hub = var.prod_enable_service_gateway_hub + enable_nat_gateway_spoke = var.prod_enable_nat_gateway_spoke + enable_service_gateway_spoke = var.prod_enable_service_gateway_spoke + + igw_hub_check = var.igw_hub_check + nat_gw_hub_check = var.nat_gw_hub_check + service_gw_hub_check = var.service_gw_hub_check + nat_gw_spoke_check = var.nat_gw_spoke_check + service_gw_spoke_check = var.service_gw_spoke_check + + vcn_cidr_block = var.prod_hub_vcn_cidr_block + public_subnet_cidr_block = var.prod_hub_public_subnet_cidr_block + private_subnet_cidr_block = var.prod_hub_private_subnet_cidr_block + + spoke_vcn_cidr = var.prod_spoke_vcn_cidr + private_spoke_subnet_web_cidr_block = var.prod_spoke_subnet_web_cidr_block + private_spoke_subnet_app_cidr_block = var.prod_spoke_subnet_app_cidr_block + private_spoke_subnet_db_cidr_block = var.prod_spoke_subnet_db_cidr_block + + enable_bastion = var.prod_enable_bastion + bastion_client_cidr_block_allow_list = var.prod_bastion_client_cidr_block_allow_list + vault_type = var.prod_vault_type + vault_replica_region = var.prod_vault_replica_region + enable_vault_replication = var.prod_enable_vault_replication + create_master_encryption_key = var.prod_create_master_encryption_key + + retention_policy_duration_amount = var.prod_retention_policy_duration_amount + retention_policy_duration_time_unit = var.prod_retention_policy_duration_time_unit + + enable_tagging = var.prod_enable_tagging + cost_center_tagging = var.prod_cost_center_tagging + geo_location_tagging = var.prod_geo_location_tagging + + network_topic_endpoints = var.prod_network_topic_endpoints + secops_topic_endpoints = var.prod_secops_topic_endpoints + platform_topic_endpoints = var.prod_platform_topic_endpoints + identity_topic_endpoints = var.prod_identity_topic_endpoints + + workload_topic_endpoints = var.prod_workload_topic_endpoints + enable_security_monitoring_alarms = var.prod_enable_security_monitoring_alarms + enable_network_monitoring_alarms = var.prod_enable_network_monitoring_alarms + enable_workload_monitoring_alarms = var.prod_enable_workload_monitoring_alarms + + + providers = { + oci = oci + oci.home_region = oci.home_region + } + + depends_on = [ + module.cloud_guard_root_policy, + module.cloud_guard_target_policy, + module.vss_policy, + module.home_compartment + ] +} + +# ----------------------------------------------------------------------------- +# Prod Enviroment Resources +# ----------------------------------------------------------------------------- +locals { + nonprod_environment = { + environment_prefix = "N" + enable_tf_state_backup = false + enable_logging = true + } +} + +module "nonprod_environment" { + source = "../elz-environment" + + tenancy_ocid = var.tenancy_ocid + region = var.region + resource_label = var.resource_label + + home_compartment_id = module.home_compartment.compartment_id + environment_prefix = local.nonprod_environment.environment_prefix + enable_tf_state_backup = local.nonprod_environment.enable_tf_state_backup + enable_logging = local.nonprod_environment.enable_logging + domain_admin_email = var.nonprod_domain_admin_email + network_admin_group_name = var.nonprod_network_admin_group_name + iam_admin_group_name = var.nonprod_iam_admin_group_name + platform_admin_group_name = var.nonprod_platform_admin_group_name + ops_admin_group_name = var.nonprod_ops_admin_group_name + security_admin_group_name = var.nonprod_security_admin_group_name + + workload_admin_group_name = var.nonprod_workload_admin_group_name + application_admin_group_name = var.nonprod_application_admin_group_name + database_admin_group_name = var.nonprod_database_admin_group_name + + enable_budget = var.nonprod_enable_budget + budget_amount = var.nonprod_budget_amount + budget_alert_rule_threshold = var.nonprod_budget_alert_rule_threshold + budget_alert_rule_message = var.nonprod_budget_alert_rule_message + budget_alert_rule_recipients = var.nonprod_budget_alert_rule_recipients + enable_cloud_guard = var.enable_cloud_guard + cloud_guard_target_tenancy = var.cloud_guard_target_tenancy + home_compartment_name = var.home_compartment_name + enable_vpn_or_fastconnect = var.enable_vpn_or_fastconnect + cpe_ip_address = var.nonprod_cpe_ip_address + ipsec_connection_static_routes = var.nonprod_ipsec_connection_static_routes + enable_vpn_on_environment = var.nonprod_enable_vpn + cpe_display_name = var.nonprod_cpe_display_name + ipsec_display_name = var.nonprod_ipsec_display_name + cpe_vendor = var.nonprod_cpe_vendor + routing = var.nonprod_ipsec_routing_type + tunnel_a_display_name = var.nonprod_tunnel_a_display_name + customer_bgp_asn = var.nonprod_customer_bgp_asn + bgp_cust_tunnela_ip = var.nonprod_bgp_cust_tunnela_ip + bgp_oci_tunnela_ip = var.nonprod_bgp_oci_tunnela_ip + shared_secret = var.nonprod_shared_secret + tunnel_b_display_name = var.nonprod_tunnel_b_display_name + fastconnect_provider = var.fastconnect_provider + region_key = local.region_key[0] + virtual_circuit_bandwidth_shape = format("%s %s", var.virtual_circuit_bandwidth_shape, "Gbps") + virtual_circuit_display_name = var.virtual_circuit_display_name + provider_service_key_name = var.provider_service_key_name + fastconnect_routing_policy = var.fastconnect_routing_policy + virtual_circuit_type = var.virtual_circuit_type + customer_primary_bgp_peering_ip = var.customer_primary_bgp_peering_ip + oracle_primary_bgp_peering_ip = var.oracle_primary_bgp_peering_ip + customer_secondary_bgp_peering_ip = var.customer_secondary_bgp_peering_ip + oracle_secondary_bgp_peering_ip = var.oracle_secondary_bgp_peering_ip + virtual_circuit_customer_asn = var.virtual_circuit_customer_asn + virtual_circuit_is_bfd_enabled = var.virtual_circuit_is_bfd_enabled + bgp_md5auth_key = var.bgp_md5auth_key + enable_fastconnect_on_environment = var.nonprod_enable_fastconnect + customer_onprem_ip_cidr = var.customer_onprem_ip_cidr + + enable_internet_gateway_hub = var.nonprod_enable_internet_gateway_hub + enable_nat_gateway_hub = var.nonprod_enable_nat_gateway_hub + enable_service_gateway_hub = var.nonprod_enable_service_gateway_hub + enable_nat_gateway_spoke = var.nonprod_enable_nat_gateway_spoke + enable_service_gateway_spoke = var.nonprod_enable_service_gateway_spoke + + igw_hub_check = var.igw_hub_check + nat_gw_hub_check = var.nat_gw_hub_check + service_gw_hub_check = var.service_gw_hub_check + nat_gw_spoke_check = var.nat_gw_spoke_check + service_gw_spoke_check = var.service_gw_spoke_check + + vcn_cidr_block = var.nonprod_hub_vcn_cidr_block + public_subnet_cidr_block = var.nonprod_hub_public_subnet_cidr_block + private_subnet_cidr_block = var.nonprod_hub_private_subnet_cidr_block + + spoke_vcn_cidr = var.nonprod_spoke_vcn_cidr + private_spoke_subnet_web_cidr_block = var.nonprod_spoke_subnet_web_cidr_block + private_spoke_subnet_app_cidr_block = var.nonprod_spoke_subnet_app_cidr_block + private_spoke_subnet_db_cidr_block = var.nonprod_spoke_subnet_db_cidr_block + + enable_bastion = var.nonprod_enable_bastion + bastion_client_cidr_block_allow_list = var.nonprod_bastion_client_cidr_block_allow_list + vault_type = var.nonprod_vault_type + vault_replica_region = var.nonprod_vault_replica_region + enable_vault_replication = var.nonprod_enable_vault_replication + create_master_encryption_key = var.nonprod_create_master_encryption_key + + retention_policy_duration_amount = var.nonprod_retention_policy_duration_amount + retention_policy_duration_time_unit = var.nonprod_retention_policy_duration_time_unit + + enable_tagging = var.nonprod_enable_tagging + cost_center_tagging = var.nonprod_cost_center_tagging + geo_location_tagging = var.nonprod_geo_location_tagging + + + network_topic_endpoints = var.nonprod_network_topic_endpoints + secops_topic_endpoints = var.nonprod_secops_topic_endpoints + platform_topic_endpoints = var.nonprod_platform_topic_endpoints + identity_topic_endpoints = var.nonprod_identity_topic_endpoints + + workload_topic_endpoints = var.nonprod_workload_topic_endpoints + enable_security_monitoring_alarms = var.nonprod_enable_security_monitoring_alarms + enable_network_monitoring_alarms = var.nonprod_enable_network_monitoring_alarms + enable_workload_monitoring_alarms = var.nonprod_enable_workload_monitoring_alarms + + #workload_compartment_id = module.nonprod_environment.workload_compartment_id + + remote_peering_connection_peer_id = var.enable_vpn_or_fastconnect == "FASTCONNECT" ? module.prod_environment.rpc_id : null + remote_peering_connection_peer_region_name = var.region + + providers = { + oci = oci + oci.home_region = oci.home_region + } + + depends_on = [ + module.cloud_guard_root_policy, + module.cloud_guard_target_policy, + module.vss_policy, + module.home_compartment + ] +} diff --git a/templates/enterprise-landing-zone/example.tfvars b/templates/enterprise-landing-zone/example.tfvars new file mode 100644 index 00000000..843d1ea4 --- /dev/null +++ b/templates/enterprise-landing-zone/example.tfvars @@ -0,0 +1,94 @@ +# Provider +current_user_ocid = "## YOUR USER OCID ##" +region = "## OCI REGION TO DEPLOY TO" +tenancy_ocid = "## YOUR TENANCY OCID ##" +api_fingerprint = "## YOUR OCI API KEY FINGERPRINT ##" +api_private_key_path = "## YOUR OCI API PRIVATE KEY FILE ##" + +# iam +resource_label = "DEMO" +prod_domain_admin_email = "an-example-email-address@oracle.com" +nonprod_domain_admin_email = "an-example-email-address@oracle.com" +enable_compartment_delete = false + +# security +enable_cloud_guard = true +cloud_guard_target_tenancy = false +nonprod_enable_bastion = true +prod_enable_bastion = true +prod_bastion_client_cidr_block_allow_list = ["10.0.0.0/16", "10.0.0.0/24"] +nonprod_bastion_client_cidr_block_allow_list = ["10.0.0.0/16", "10.0.0.0/24"] + +# budget +nonprod_enable_budget = true +prod_enable_budget = true +nonprod_budget_alert_rule_message = "test" +nonprod_budget_alert_rule_recipients = "an-example-email-address@oracle.com" +nonprod_budget_alert_rule_threshold = 1000000 +nonprod_budget_amount = 10000000 +prod_budget_alert_rule_message = "test" +prod_budget_alert_rule_recipients = "an-example-email-address@oracle.com" +prod_budget_alert_rule_threshold = 1000000 +prod_budget_amount = 10000000 + +# network extension +enable_vpn_or_fastconnect = "NONE" +prod_enable_vpn = true +prod_cpe_ip_address = "10.0.0.0" +prod_cpe_display_name = "OCI-ELZ-CPE-P-HUB-001" +prod_cpe_vendor = 4 +prod_ipsec_connection_static_routes = ["10.0.0.0/16", "11.0.0.0/16"] +nonprod_enable_vpn = false + +# network +prod_enable_internet_gateway_hub = "true" +prod_enable_nat_gateway_hub = "true" +prod_enable_service_gateway_hub = "true" +prod_enable_nat_gateway_spoke = "true" +prod_enable_service_gateway_spoke = "true" + +nonprod_enable_internet_gateway_hub = "true" +nonprod_enable_nat_gateway_hub = "true" +nonprod_enable_service_gateway_hub = "true" +nonprod_enable_nat_gateway_spoke = "true" +nonprod_enable_service_gateway_spoke = "true" + +prod_hub_vcn_cidr_block = "10.1.0.0/16" +prod_hub_public_subnet_cidr_block = "10.1.1.0/24" +prod_hub_private_subnet_cidr_block = "10.1.2.0/24" + +prod_spoke_vcn_cidr = "10.2.0.0/16" +prod_spoke_subnet_web_cidr_block = "10.2.1.0/24" +prod_spoke_subnet_app_cidr_block = "10.2.2.0/24" +prod_spoke_subnet_db_cidr_block = "10.2.3.0/24" + +nonprod_hub_vcn_cidr_block = "10.3.0.0/16" +nonprod_hub_public_subnet_cidr_block = "10.3.1.0/24" +nonprod_hub_private_subnet_cidr_block = "10.3.2.0/24" + +nonprod_spoke_vcn_cidr = "10.4.0.0/16" +nonprod_spoke_subnet_web_cidr_block = "10.4.1.0/24" +nonprod_spoke_subnet_app_cidr_block = "10.4.2.0/24" +nonprod_spoke_subnet_db_cidr_block = "10.4.3.0/24" + +# Tagging +prod_enable_tagging = true +nonprod_enable_tagging = true +nonprod_cost_center_tagging = "n_cost_tag" +nonprod_geo_location_tagging = "n_geo_tag" +prod_cost_center_tagging = "p_cost_tag" +prod_geo_location_tagging = "p_geo_tag" +onboard_log_analytics = false + +# Monitoring (Optional) +prod_network_topic_endpoints = [] +prod_secops_topic_endpoints = [] +prod_platform_topic_endpoints = [] +prod_identity_topic_endpoints = [] +prod_workload_topic_endpoints = [] +nonprod_network_topic_endpoints = [] +nonprod_secops_topic_endpoints = [] +nonprod_platform_topic_endpoints = [] +nonprod_identity_topic_endpoints = [] +nonprod_workload_topic_endpoints = [] + diff --git a/templates/enterprise-landing-zone/iam.tf b/templates/enterprise-landing-zone/iam.tf new file mode 100644 index 00000000..17943508 --- /dev/null +++ b/templates/enterprise-landing-zone/iam.tf @@ -0,0 +1,59 @@ +# ----------------------------------------------------------------------------- +# Compartment Resources +# ----------------------------------------------------------------------------- +locals { + home_compartment = { + description = "Enterprise Landing Zone Home Compartment" + } +} + +module "home_compartment" { + source = "../../modules/compartment" + + compartment_parent_id = var.tenancy_ocid + compartment_name = var.home_compartment_name + compartment_description = local.home_compartment.description + enable_compartment_delete = var.enable_compartment_delete + + providers = { + oci = oci.home_region + } +} + +module "break_glass_users" { + for_each = { for index, email in var.break_glass_user_email_list : index => email } + source = "../../modules/break_glass_user" + tenancy_ocid = var.tenancy_ocid + + break_glass_user_index = each.key + break_glass_user_email = each.value + + providers = { + oci = oci.home_region + } +} + +# ----------------------------------------------------------------------------- +# Authentication Policy +# ----------------------------------------------------------------------------- +locals { + authentication_policy = { + authentication_policy_password_policy_is_lowercase_characters_required = true + authentication_policy_password_policy_is_numeric_characters_required = true + authentication_policy_password_policy_is_special_characters_required = true + authentication_policy_password_policy_is_uppercase_characters_required = true + authentication_policy_password_policy_is_username_containment_allowed = false + authentication_policy_password_policy_minimum_password_length = 14 + } +} + +module "authentication_policy" { + source = "../../modules/authentication-policy" + tenancy_ocid = var.tenancy_ocid + authentication_policy_password_policy_is_lowercase_characters_required = local.authentication_policy.authentication_policy_password_policy_is_lowercase_characters_required + authentication_policy_password_policy_is_numeric_characters_required = local.authentication_policy.authentication_policy_password_policy_is_numeric_characters_required + authentication_policy_password_policy_is_special_characters_required = local.authentication_policy.authentication_policy_password_policy_is_special_characters_required + authentication_policy_password_policy_is_uppercase_characters_required = local.authentication_policy.authentication_policy_password_policy_is_uppercase_characters_required + authentication_policy_password_policy_is_username_containment_allowed = local.authentication_policy.authentication_policy_password_policy_is_username_containment_allowed + authentication_policy_password_policy_minimum_password_length = local.authentication_policy.authentication_policy_password_policy_minimum_password_length +} diff --git a/templates/enterprise-landing-zone/images/CIS1.2Level1.xlsx b/templates/enterprise-landing-zone/images/CIS1.2Level1.xlsx new file mode 100644 index 00000000..1baacdcb Binary files /dev/null and b/templates/enterprise-landing-zone/images/CIS1.2Level1.xlsx differ diff --git a/templates/enterprise-landing-zone/images/Compartment.png b/templates/enterprise-landing-zone/images/Compartment.png new file mode 100644 index 00000000..8811e62c Binary files /dev/null and b/templates/enterprise-landing-zone/images/Compartment.png differ diff --git a/templates/enterprise-landing-zone/images/Monitoring.png b/templates/enterprise-landing-zone/images/Monitoring.png new file mode 100644 index 00000000..7f66ce64 Binary files /dev/null and b/templates/enterprise-landing-zone/images/Monitoring.png differ diff --git a/templates/enterprise-landing-zone/images/enterprise-landing-zone-v2.svg b/templates/enterprise-landing-zone/images/enterprise-landing-zone-v2.svg new file mode 100644 index 00000000..922c5265 --- /dev/null +++ b/templates/enterprise-landing-zone/images/enterprise-landing-zone-v2.svg @@ -0,0 +1,1802 @@ + + + + + +L1 - Landing Zone Home + + + +L2 - Production + + + +L2 - Non-Prod + + + +L3 - Workload + + + +L3 - Workload + + + +L3 - Logging + + + +L3 - Logging + + + +L3 - Backup + + + +L3 - Backup + + + +L3 - Shared + + + +L3 - Shared + + + +L4 - Network + + + +L4 - Network + + + +L4 - Security + + + +L4 - Security + + + + + + + + + + + + + +HUB-VCN + + + + + + + + + + + + +HUB-VCN + + +Private Subnet + + + +Private Subnet + + + +Web Subnet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Web Subnet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +App Subnet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +App Subnet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +DB Subnet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +DB Subnet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Public Subnet + + + +Public Subnet + + + + + + + + + + + + + + + + + + + + + + + + + + +ENV Level +IAM Policies + + + + + + + + + + + + + + + + + + + + + + + + + + +ENV Level +IAM Policies + + + + + + + + + + + + + + + + + + + + + + + + + + +Policies + + + +Oracle Services Network + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Object Storage + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Object Storage +(Standard, +Immutable) + + + + + + + + + + + + + + + + + + +IAM Groups + + + + + + + + + + + + + + + + + + +IAM Groups + + + + + + + + + + + + + + + +VSS Recipes + + + + + + + + + + + + + + + +VSS Recipes + + + + + + + + + + + + + + + +VSS Target + + + + + + + + + + + + + + + +VSS Target + + + + + + + + + + + + + + + + + + + + + + + +Auditing + + + + + + + + + + + + + + + + + + + + + + + +Auditing + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Logging + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Logging + + + + + + + + + + + + + + + +Events + + + + + + + + + + + + + + + +Events + + + + + + + + + + + + + + + + + + +Key +Management + + + + + + + + + + + + + + + + + + +Key +Management + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Streaming + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Streaming + + + + + + + + + + + + + + + +Service +Connector +Hub + + + + + + + + + + + + + + + +Service +Connector +Hub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Bastion + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Bastion + + + + + + + + + + + + + + + + + + + +Vault + + + + + + + + + + + + + + + + + + + +Vault + + + + + + + + + + + + + + + + + +Load +Balancer + + + + + + + + + + + + + + + + + + + + + +On-Premise +Networks + + + + + + + + + + + + + + + + +Internet + + + + + + + + + + + + + + + + +IAM +Domain +(L2_PROD) + + + + + + + + + + + + + + + + +IAM Domain +(Default) + + + + + + + + + + + + + + + + +IAM +Domain +(L2_PROD) + + + + + + + + + + + + +Cloud Guard +Target + + + + + + + + + + + + +Cloud Guard +Target + + + + + + + + + + + + +Cloud Guard + + + + + + + + + + + + +Cloud Guard +Enablement + + + + + + + + + + + + +Cloud Guard + + + + + + + + + + + + + + + + +NAT +Gateway + + + + + + + + + + + + + + + + + +NAT +Gateway + + + + + + + + + + + + + + + + + +NAT +Gateway + + + + + + + + + + + + + + + + + +NAT +Gateway + + + + + + + + + + + + + + + + + + +Service +Gateway + + + + + + + + + + + + + + + + + + +Service +Gateway + + + + + + + + + + + + + + + + + + +Service +Gateway + + + + + + + + + + + + + + + + + + +Service +Gateway + + + + + + + + + + + + + + + + + + + + +Internet +Gateway + + + + + + + + + + + + + + + + + + + + +Internet +Gateway + + + + + + + + + + + + + + + +DRG + + + + + + + + + + + + + + + +DRG + + + + + + + + + + + + + + + + + + + + + + + + +Compute + + + + + + + + + + + + + + + + + + + + + + + +Compute + + + + + + + + + + + +Server + + + + + + + + + + + +Server + + + + + + + + + + + +Server + + + + + + + + + + + +Server + + + + + + + + + + + +Server + + + + + + + + + + + +Server + + + + + + + + + + + + + + + + + + + + + + + +Compute + + + + + + + + + + + + + + + + + + + + + + + +Compute + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +DRG VCN Attachment + + + + + + + +DRG VCN Attachment + + + + +RPC Attachment + + + + + + + + + + + + + + + + + + + diff --git a/templates/enterprise-landing-zone/integration.tfvars b/templates/enterprise-landing-zone/integration.tfvars new file mode 100644 index 00000000..743715ee --- /dev/null +++ b/templates/enterprise-landing-zone/integration.tfvars @@ -0,0 +1,74 @@ +#tfvars file for the ci pipline +# iam +resource_label = "INTEGRATION" +enable_compartment_delete = false + +# security +enable_cloud_guard = true +cloud_guard_target_tenancy = false +nonprod_enable_bastion = true +prod_enable_bastion = true +prod_bastion_client_cidr_block_allow_list = ["0.0.0.0/0"] +nonprod_bastion_client_cidr_block_allow_list = ["0.0.0.0/0"] + +# budget +nonprod_budget_alert_rule_message = "test" +nonprod_budget_alert_rule_threshold = 1000000 +nonprod_budget_amount = 10000000 +prod_budget_alert_rule_message = "test" +prod_budget_alert_rule_threshold = 1000000 +prod_budget_amount = 10000000 +nonprod_enable_budget = true +prod_enable_budget = true + +# network extension +enable_vpn_or_fastconnect = "VPN" +prod_enable_vpn = true +prod_cpe_ip_address = "129.146.57.36" +prod_cpe_display_name = "OCI-ELZ-CPE-P-HUB-001" +prod_cpe_vendor = 4 +prod_ipsec_connection_static_routes = ["172.16.0.0/16"] +nonprod_enable_vpn = false + +# Network + +prod_enable_internet_gateway_hub = "true" +prod_enable_nat_gateway_hub = "true" +prod_enable_service_gateway_hub = "true" +prod_enable_nat_gateway_spoke = "true" +prod_enable_service_gateway_spoke = "true" + +nonprod_enable_internet_gateway_hub = "true" +nonprod_enable_nat_gateway_hub = "true" +nonprod_enable_service_gateway_hub = "true" +nonprod_enable_nat_gateway_spoke = "true" +nonprod_enable_service_gateway_spoke = "true" + +prod_hub_vcn_cidr_block = "10.1.0.0/16" +prod_hub_public_subnet_cidr_block = "10.1.1.0/24" +prod_hub_private_subnet_cidr_block = "10.1.2.0/24" + +prod_spoke_vcn_cidr = "10.2.0.0/16" +prod_spoke_subnet_web_cidr_block = "10.2.1.0/24" +prod_spoke_subnet_app_cidr_block = "10.2.2.0/24" +prod_spoke_subnet_db_cidr_block = "10.2.3.0/24" + +nonprod_hub_vcn_cidr_block = "10.3.0.0/16" +nonprod_hub_public_subnet_cidr_block = "10.3.1.0/24" +nonprod_hub_private_subnet_cidr_block = "10.3.2.0/24" + +nonprod_spoke_vcn_cidr = "10.4.0.0/16" +nonprod_spoke_subnet_web_cidr_block = "10.4.1.0/24" +nonprod_spoke_subnet_app_cidr_block = "10.4.2.0/24" +nonprod_spoke_subnet_db_cidr_block = "10.4.3.0/24" + +#tagging +nonprod_cost_center_tagging = "n_cost_tag" +nonprod_geo_location_tagging = "n_geo_tag" +prod_cost_center_tagging = "p_cost_tag" +prod_geo_location_tagging = "p_geo_tag" +prod_enable_tagging = true +nonprod_enable_tagging = true + +# logging +onboard_log_analytics = false \ No newline at end of file diff --git a/templates/enterprise-landing-zone/logging-variables.tf b/templates/enterprise-landing-zone/logging-variables.tf new file mode 100644 index 00000000..aab4a19d --- /dev/null +++ b/templates/enterprise-landing-zone/logging-variables.tf @@ -0,0 +1,35 @@ +variable "prod_retention_policy_duration_amount" { + type = string + description = "The timeAmount is interpreted in units defined by the timeUnit parameter, and is calculated in relation to each object's Last-Modified timestamp." + default = "1" +} + +variable "prod_retention_policy_duration_time_unit" { + type = string + description = "The unit that should be used to interpret timeAmount." + default = "DAYS" +} + +variable "nonprod_retention_policy_duration_amount" { + type = string + description = "The timeAmount is interpreted in units defined by the timeUnit parameter, and is calculated in relation to each object's Last-Modified timestamp." + default = "1" +} + +variable "nonprod_retention_policy_duration_time_unit" { + type = string + description = "The unit that should be used to interpret timeAmount." + default = "DAYS" +} + +variable "archive_log_retention_policy_duration_amount" { + type = string + description = "The timeAmount is interpreted in units defined by the timeUnit parameter, and is calculated in relation to each object's Last-Modified timestamp." + default = "1" +} + +variable "archive_log_retention_policy_duration_time_unit" { + type = string + description = "The unit that should be used to interpret timeAmount." + default = "DAYS" +} \ No newline at end of file diff --git a/templates/enterprise-landing-zone/logging.tf b/templates/enterprise-landing-zone/logging.tf new file mode 100644 index 00000000..f0804cbb --- /dev/null +++ b/templates/enterprise-landing-zone/logging.tf @@ -0,0 +1,288 @@ +locals { + service_connector_policy = { + name = "${var.resource_label}-OCI-ELZ-SC-Policy" + description = "OCI ELZ Service Connector Policy" + statements = [ + "Allow any-user to read log-content in compartment id ${module.home_compartment.compartment_id} where all {request.principal.type='serviceconnector'}", + "Allow any-user to read log-groups in compartment id ${module.home_compartment.compartment_id} where all {request.principal.type='serviceconnector'}", + "Allow any-user to {STREAM_READ, STREAM_CONSUME} in compartment id ${module.prod_environment.compartment.security.id} where all {request.principal.type='serviceconnector', target.stream.id='${module.prod_environment.stream_id}', request.principal.compartment.id='${module.prod_environment.compartment.security.id}'}", + "Allow any-user to {STREAM_READ, STREAM_CONSUME} in compartment id ${module.nonprod_environment.compartment.security.id} where all {request.principal.type='serviceconnector', target.stream.id='${module.nonprod_environment.stream_id}', request.principal.compartment.id='${module.nonprod_environment.compartment.security.id}'}", + "Allow any-user to manage objects in compartment id ${module.prod_environment.compartment.logging.id} where all {request.principal.type='serviceconnector', target.bucket.name='*_standard', request.principal.compartment.id='${module.prod_environment.compartment.security.id}'}", + "Allow any-user to manage objects in compartment id ${module.nonprod_environment.compartment.logging.id} where all {request.principal.type='serviceconnector', target.bucket.name='*_standard', request.principal.compartment.id='${module.nonprod_environment.compartment.security.id}'}", + "Allow any-user to manage objects in compartment id ${module.prod_environment.compartment.logging.id} where all {request.principal.type='serviceconnector', any{target.bucket.name='${var.resource_label}_${local.prod_environment.environment_prefix}_auditLogs_standard', target.bucket.name='${var.resource_label}_${local.prod_environment.environment_prefix}_defaultLogs_standard', target.bucket.name='${var.resource_label}_${local.prod_environment.environment_prefix}_serviceEvents_standard'}, request.principal.compartment.id='${module.prod_environment.compartment.security.id}'}", + "Allow any-user to manage objects in compartment id ${module.nonprod_environment.compartment.logging.id} where all {request.principal.type='serviceconnector', any{target.bucket.name='${var.resource_label}_${local.nonprod_environment.environment_prefix}_auditLogs_standard', target.bucket.name='${var.resource_label}_${local.nonprod_environment.environment_prefix}_defaultLogs_standard', target.bucket.name='${var.resource_label}_${local.nonprod_environment.environment_prefix}_serviceEvents_standard'}, request.principal.compartment.id='${module.nonprod_environment.compartment.security.id}'}" + ] + } + + service_connector_archive_policy = { + name = "${var.resource_label}-OCI-ELZ-SC-ARC-Policy" + description = "OCI ELZ Service Connector Policy For Archive" + statements = [ + "Allow any-user to read log-content in compartment id ${module.home_compartment.compartment_id} where all {request.principal.type='serviceconnector'}", + "Allow any-user to read log-groups in compartment id ${module.home_compartment.compartment_id} where all {request.principal.type='serviceconnector'}", + "Allow any-user to {STREAM_READ, STREAM_CONSUME} in compartment id ${module.home_compartment.compartment_id} where all {request.principal.type='serviceconnector'}", + "Allow any-user to manage objects in compartment id ${module.home_compartment.compartment_id} where all {request.principal.type='serviceconnector', target.bucket.name='${local.archive_log_bucket.name}'}" + ] + } + + key_archive_policy = { + name = "${var.resource_label}-OCI-ELZ-KEY-ARC-Policy" + description = "OCI Enterprise Landing Zone Key Policy For Archive" + + statements = [ + "Allow service objectstorage-${var.region} to use keys in compartment id ${module.prod_environment.compartment.security.id}", + "Allow service blockstorage,FssOc1Prod, OKE, streaming to use keys in compartment id ${module.prod_environment.compartment.security.id}" + ] + } + + archive_log_bucket = { + name = "${var.resource_label}_logs_archive" + description = "Archive Log bucket" + retention_rule_display_name = "archive log bucket retention rule" + retention_policy_duration_amount = var.archive_log_retention_policy_duration_amount + retention_policy_duration_time_unit = var.archive_log_retention_policy_duration_time_unit + bucket_storage_tier = "Archive" + } + + prod_archive_audit_log_service_connector = { + display_name = "${var.resource_label}_schAuditLog_archive_${local.prod_environment.environment_prefix}" + source_kind = "logging" + target_kind = "objectStorage" + log_group_id = "_Audit_Include_Subcompartment" + target_bucket = module.archive_bucket.bucket.name + } + + nonprod_archive_audit_log_service_connector = { + display_name = "${var.resource_label}_schAuditLog_archive_${local.nonprod_environment.environment_prefix}" + source_kind = "logging" + target_kind = "objectStorage" + log_group_id = "_Audit_Include_Subcompartment" + target_bucket = module.archive_bucket.bucket.name + } + + prod_archive_default_log_service_connector = { + display_name = "${var.resource_label}_schDefaultLog_archive_${local.prod_environment.environment_prefix}" + source_kind = "logging" + target_kind = "objectStorage" + target_bucket = module.archive_bucket.bucket.name + } + + nonprod_archive_default_log_service_connector = { + display_name = "${var.resource_label}_schDefaultLog_archive_${local.nonprod_environment.environment_prefix}" + source_kind = "logging" + target_kind = "objectStorage" + target_bucket = module.archive_bucket.bucket.name + } + + prod_archive_service_events_service_connector = { + display_name = "${var.resource_label}_schServiceEvents_archive_${local.prod_environment.environment_prefix}" + source_kind = "streaming" + target_kind = "objectStorage" + target_bucket = module.archive_bucket.bucket.name + cursor_kind = "TRIM_HORIZON" + } + + nonprod_archive_service_events_service_connector = { + display_name = "${var.resource_label}_schServiceEvents_archive_${local.nonprod_environment.environment_prefix}" + source_kind = "streaming" + target_kind = "objectStorage" + target_bucket = module.archive_bucket.bucket.name + cursor_kind = "TRIM_HORIZON" + } + + archive_key = { + name = "${var.resource_label}-OCI-ELZ-ARC-KEY-${local.prod_environment.environment_prefix}" + shape_algorithm = "AES" + shape_length = 32 + protection_mode = "SOFTWARE" + } + + group_names = { + prod_platform_admin_group_name : var.prod_platform_admin_group_name != "" ? var.prod_platform_admin_group_name : "OCI-ELZ-UGP-${local.prod_environment.environment_prefix}-PLT-ADMIN", + nonprod_platform_admin_group_name : var.nonprod_platform_admin_group_name != "" ? var.nonprod_platform_admin_group_name : "OCI-ELZ-UGP-${local.prod_environment.environment_prefix}-PLT-ADMIN", + } + + prod_platform_admin_policy = { + name = "OCI-ELZ-UGP-${local.prod_environment.environment_prefix}-PLT-ADMIN-POLICY-ARCHIVE" + description = "OCI Landing Zone Platform Admin Group Policy To Manage Archive Bucket" + + statements = [ + "Allow group ${local.group_names["prod_platform_admin_group_name"]} to manage buckets in compartment ${module.home_compartment.compartment_name}", + "Allow group ${local.group_names["prod_platform_admin_group_name"]} to manage objects in compartment ${module.home_compartment.compartment_name}" + ] + } + + nonprod_platform_admin_policy = { + name = "OCI-ELZ-UGP-${local.nonprod_environment.environment_prefix}-PLT-ADMIN-POLICY-ARCHIVE" + description = "OCI Landing Zone Platform Admin Group Policy To Manage Archive Bucket" + + statements = [ + "Allow group ${local.group_names["nonprod_platform_admin_group_name"]} to manage buckets in compartment ${module.home_compartment.compartment_name}", + "Allow group ${local.group_names["nonprod_platform_admin_group_name"]} to manage objects in compartment ${module.home_compartment.compartment_name}" + ] + } +} + +module "service_connector_policy" { + source = "../../modules/policies" + compartment_ocid = module.home_compartment.compartment_id + policy_name = local.service_connector_policy.name + description = local.service_connector_policy.description + statements = local.service_connector_policy.statements + + depends_on = [module.prod_environment, module.nonprod_environment, module.home_compartment] +} + +module "service_connector_archive_policy" { + source = "../../modules/policies" + compartment_ocid = module.home_compartment.compartment_id + policy_name = local.service_connector_archive_policy.name + description = local.service_connector_archive_policy.description + statements = local.service_connector_archive_policy.statements + + depends_on = [module.prod_environment, module.nonprod_environment, module.home_compartment] +} + +module "archive_key" { + source = "../../modules/key" + compartment_ocid = module.prod_environment.compartment.security.id + display_name = local.archive_key.name + shape_algorithm = local.archive_key.shape_algorithm + shape_length = local.archive_key.shape_length + protection_mode = local.archive_key.protection_mode + management_endpoint = module.prod_environment.vault_id + + depends_on = [module.prod_environment, module.home_compartment] +} + +module "key_archive_policy" { + source = "../../modules/policies" + compartment_ocid = module.home_compartment.compartment_id + policy_name = local.key_archive_policy.name + description = local.key_archive_policy.description + statements = local.key_archive_policy.statements + + depends_on = [module.prod_environment, module.nonprod_environment, module.home_compartment] +} + +module "archive_bucket" { + source = "../../modules/bucket" + tenancy_ocid = var.tenancy_ocid + compartment_id = module.home_compartment.compartment_id + name = local.archive_log_bucket.name + kms_key_id = module.archive_key.key_ocid + storage_tier = local.archive_log_bucket.bucket_storage_tier + retention_rule_display_name = local.archive_log_bucket.retention_rule_display_name + retention_policy_duration_amount = local.archive_log_bucket.retention_policy_duration_amount + retention_policy_duration_time_unit = local.archive_log_bucket.retention_policy_duration_time_unit + namespace = data.oci_objectstorage_namespace.ns.namespace + + depends_on = [module.prod_environment, module.nonprod_environment, module.home_compartment, module.archive_key, module.key_archive_policy] +} + +module "prod_archive_audit_log_service_connector" { + source = "../../modules/service-connector" + tenancy_ocid = var.tenancy_ocid + compartment_id = module.prod_environment.compartment.security.id + source_compartment_id = module.home_compartment.compartment_id + display_name = local.prod_archive_audit_log_service_connector.display_name + source_kind = local.prod_archive_audit_log_service_connector.source_kind + target_kind = local.prod_archive_audit_log_service_connector.target_kind + log_group_id = local.prod_archive_audit_log_service_connector.log_group_id + target_bucket = local.prod_archive_audit_log_service_connector.target_bucket + + depends_on = [module.archive_bucket, module.service_connector_archive_policy] +} + +module "nonprod_archive_audit_log_service_connector" { + source = "../../modules/service-connector" + tenancy_ocid = var.tenancy_ocid + compartment_id = module.nonprod_environment.compartment.security.id + source_compartment_id = module.home_compartment.compartment_id + display_name = local.nonprod_archive_audit_log_service_connector.display_name + source_kind = local.nonprod_archive_audit_log_service_connector.source_kind + target_kind = local.nonprod_archive_audit_log_service_connector.target_kind + log_group_id = local.nonprod_archive_audit_log_service_connector.log_group_id + target_bucket = local.nonprod_archive_audit_log_service_connector.target_bucket + + depends_on = [module.archive_bucket, module.service_connector_archive_policy] +} + +module "prod_archive_default_log_service_connector" { + source = "../../modules/service-connector" + tenancy_ocid = var.tenancy_ocid + compartment_id = module.prod_environment.compartment.security.id + source_compartment_id = module.prod_environment.compartment.security.id + display_name = local.prod_archive_default_log_service_connector.display_name + source_kind = local.prod_archive_default_log_service_connector.source_kind + target_kind = local.prod_archive_default_log_service_connector.target_kind + log_group_id = module.prod_environment.default_group_id + target_bucket = local.prod_archive_default_log_service_connector.target_bucket + + depends_on = [module.archive_bucket, module.service_connector_archive_policy] +} + +module "nonprod_archive_default_log_service_connector" { + source = "../../modules/service-connector" + tenancy_ocid = var.tenancy_ocid + compartment_id = module.nonprod_environment.compartment.security.id + source_compartment_id = module.nonprod_environment.compartment.security.id + display_name = local.nonprod_archive_default_log_service_connector.display_name + source_kind = local.nonprod_archive_default_log_service_connector.source_kind + target_kind = local.nonprod_archive_default_log_service_connector.target_kind + log_group_id = module.nonprod_environment.default_group_id + target_bucket = local.nonprod_archive_default_log_service_connector.target_bucket + + depends_on = [module.archive_bucket, module.service_connector_archive_policy] +} + +module "prod_archive_service_events_service_connector" { + source = "../../modules/service-connector" + tenancy_ocid = var.tenancy_ocid + compartment_id = module.prod_environment.compartment.security.id + source_compartment_id = module.prod_environment.compartment.security.id + display_name = local.prod_archive_service_events_service_connector.display_name + source_kind = local.prod_archive_service_events_service_connector.source_kind + target_kind = local.prod_archive_service_events_service_connector.target_kind + stream_id = module.prod_environment.stream_id + cursor_kind = local.prod_archive_service_events_service_connector.cursor_kind + target_bucket = local.prod_archive_service_events_service_connector.target_bucket + + depends_on = [module.archive_bucket, module.service_connector_archive_policy] +} + +module "nonprod_archive_service_events_service_connector" { + source = "../../modules/service-connector" + tenancy_ocid = var.tenancy_ocid + compartment_id = module.nonprod_environment.compartment.security.id + source_compartment_id = module.nonprod_environment.compartment.security.id + display_name = local.nonprod_archive_service_events_service_connector.display_name + source_kind = local.nonprod_archive_service_events_service_connector.source_kind + target_kind = local.nonprod_archive_service_events_service_connector.target_kind + stream_id = module.nonprod_environment.stream_id + cursor_kind = local.nonprod_archive_service_events_service_connector.cursor_kind + target_bucket = local.nonprod_archive_service_events_service_connector.target_bucket + + depends_on = [module.archive_bucket, module.service_connector_archive_policy] +} + +module "prod_platform_admin_policy" { + source = "../../modules/policies" + compartment_ocid = module.home_compartment.compartment_id + policy_name = local.prod_platform_admin_policy.name + description = local.prod_platform_admin_policy.description + statements = local.prod_platform_admin_policy.statements + + depends_on = [module.home_compartment] +} + +module "nonprod_platform_admin_policy" { + source = "../../modules/policies" + compartment_ocid = module.home_compartment.compartment_id + policy_name = local.nonprod_platform_admin_policy.name + description = local.nonprod_platform_admin_policy.description + statements = local.nonprod_platform_admin_policy.statements + + depends_on = [module.home_compartment] +} + diff --git a/templates/enterprise-landing-zone/monitoring.tf b/templates/enterprise-landing-zone/monitoring.tf new file mode 100644 index 00000000..8edd59b6 --- /dev/null +++ b/templates/enterprise-landing-zone/monitoring.tf @@ -0,0 +1,14 @@ +locals { + logging_analytics = { + is_onboarded = true + } +} + +module "logging_analytics_namespace" { + count = var.onboard_log_analytics ? 1 : 0 + source = "../../modules/log-analytics-namespace" + compartment_id = var.tenancy_ocid + is_onboarded = local.logging_analytics.is_onboarded + tenancy_ocid = var.tenancy_ocid + resource_label = var.resource_label +} diff --git a/templates/enterprise-landing-zone/network-extension-variables.tf b/templates/enterprise-landing-zone/network-extension-variables.tf new file mode 100644 index 00000000..38176958 --- /dev/null +++ b/templates/enterprise-landing-zone/network-extension-variables.tf @@ -0,0 +1,259 @@ +variable "enable_vpn_or_fastconnect" { + type = string + description = "Option to enable VPN or FASTCONNECT service. Options are NONE, VPN, FASTCONNECT." + default = "NONE" +} + +variable "prod_enable_vpn" { + type = bool + description = "Enable VPN in prod environment" +} + +variable "nonprod_enable_vpn" { + type = bool + description = "Enable VPN in non prod environment" +} + +variable "prod_cpe_display_name" { + type = string + description = "Customer Premises Equipment name. Recommendation: OCI-ELZ-CPE-[Environment]-HUB-[Region] 001" + default = "" +} + +variable "nonprod_cpe_display_name" { + type = string + description = "Customer Premises Equipment name. Recommendation: OCI-ELZ-CPE-[Environment]-HUB-[Region] 001" + default = "" +} + +variable "prod_cpe_ip_address" { + type = string + description = "Customer Premises Equipment (CPE) IP address" + default = "" +} + +variable "nonprod_cpe_ip_address" { + type = string + description = "Customer Premises Equipment (CPE) IP address" + default = "" +} + +variable "prod_ipsec_display_name" { + type = string + description = "IPsec display name. Recommendation: OCI-ELZ-IPS-[Environment]-HUB-[Region] 001" + default = "" +} + +variable "nonprod_ipsec_display_name" { + type = string + description = "IPsec display name. Recommendation: OCI-ELZ-IPS-[Environment]-HUB-[Region] 001" + default = "" +} + +variable "prod_ipsec_connection_static_routes" { + type = list(string) + description = "" + default = [""] +} + +variable "nonprod_ipsec_connection_static_routes" { + type = list(string) + description = "" + default = [""] +} + +variable "prod_cpe_vendor" { + type = number + description = "Type corresponding number as your CPE vendor: Yamaha-RTX1210 0, Other 1, Cisco-9.7.1-or-later 2, Yamaha-RTX830 3, Libreswan 4, Fortinet 5, NEC 6, Cisco-8.5+ 7, Cisco-IOS 8, WatchGuard 9, Juniper-MX 10, Juniper-SRX 11, Furukawa 12, Check_Point 13, Palo_Alto 14" + default = 0 +} + +variable "nonprod_cpe_vendor" { + type = number + description = "Type corresponding number as your CPE vendor: Yamaha-RTX1210 0, Other 1, Cisco-9.7.1-or-later 2, Yamaha-RTX830 3, Libreswan 4, Fortinet 5, NEC 6, Cisco-8.5+ 7, Cisco-IOS 8, WatchGuard 9, Juniper-MX 10, Juniper-SRX 11, Furukawa 12, Check_Point 13, Palo_Alto 14" + default = 0 +} + +variable "prod_ipsec_routing_type" { + type = string + description = "BGP dynamic routing, STATIC routing. Type BGP or STATIC" + default = "STATIC" +} + +variable "prod_tunnel_a_display_name" { + type = string + description = "Tunnel A display name. Recommendation: " + default = "" +} + +variable "prod_customer_bgp_asn" { + type = string + description = "ASN is required and used for the tunnel's BGP session" + default = "" +} + +variable "prod_bgp_cust_tunnela_ip" { + type = string + description = "The IP address for the CPE end of the inside tunnel interface." + default = "" +} + +variable "prod_bgp_oci_tunnela_ip" { + type = string + description = "The IP address for the Oracle end of the inside tunnel interface." + default = "" + +} + +variable "prod_shared_secret" { + type = string + description = "The shared secret (pre-shared key) to use for the IPSec tunnel" + default = "example" + +} + +variable "prod_tunnel_b_display_name" { + type = string + description = "Tunnel B display name. Recommendation: " + default = "" +} + +variable "nonprod_ipsec_routing_type" { + type = string + description = "BGP dynamic routing, STATIC routing. Type BGP or STATIC" + default = "STATIC" +} + +variable "nonprod_tunnel_a_display_name" { + type = string + description = "Tunnel A display name. Recommendation: " + default = "" +} + +variable "nonprod_customer_bgp_asn" { + type = string + description = "ASN is required and used for the tunnel's BGP session" + default = "" +} + +variable "nonprod_bgp_cust_tunnela_ip" { + type = string + description = "The IP address for the CPE end of the inside tunnel interface." + default = "" +} + +variable "nonprod_bgp_oci_tunnela_ip" { + type = string + description = "The IP address for the Oracle end of the inside tunnel interface." + default = "" +} + +variable "nonprod_shared_secret" { + type = string + description = "The shared secret (pre-shared key) to use for the IPSec tunnel" + default = "example" +} + +variable "nonprod_tunnel_b_display_name" { + type = string + description = "Tunnel B display name. Recommendation: " + default = "" +} + +# Fastconnect Variables +variable "fastconnect_provider" { + type = string + description = "Fastconnect provider. Please choose from: AT&T, Azure, Megaport, QTS, CEintro, Cologix, CoreSite, Digitial Realty, EdgeConneX, Epsilon, Equinix, InterCloud, Lumen, Neutrona, OMCS, OracleL2ItegDeployment, OracleL3ItegDeployment, Orange, Verizon, Zayo" + default = "" +} + + +variable "virtual_circuit_bandwidth_shape" { + type = string + description = "The provisioned data rate of the connection" + default = "1500" +} + +variable "virtual_circuit_display_name" { + type = string + description = "The display name of this virtual circuit. Recommendation: OCI-ELZ-FCN-P-HUB-[REGION] 001" + default = "" +} + +variable "provider_service_key_name" { + type = string + description = "The provider service key that the provider gives you when you set up a virtual circuit connection from the provider to OCI" + default = "" +} + +variable "fastconnect_routing_policy" { + type = list(string) + description = "Available FastConnect routing policies: ORACLE_SERVICE_NETWORK, REGIONAL, MARKET_LEVEL, GLOBAL" + default = [] +} + +variable "virtual_circuit_type" { + type = string + description = "The type of IP addresses used in this virtual circuit. PRIVATE or PUBLIC" + default = "" +} + +variable "customer_primary_bgp_peering_ip" { + type = string + description = "The primary BGP IPv4 address of the customer's router" + default = "" + +} + +variable "oracle_primary_bgp_peering_ip" { + type = string + description = "The primary BGP IPv4 address for Oracle's end of the BGP session" + default = "" +} + +variable "customer_secondary_bgp_peering_ip" { + type = string + description = "[Optional] The secondary BGP IPv4 address of the customer's router" + default = "" +} + +variable "oracle_secondary_bgp_peering_ip" { + type = string + description = "[Optional] Secondary IPv4 address for Oracle's end of the BGP session" + default = "" +} + +variable "virtual_circuit_customer_asn" { + type = string + description = "The BGP ASN of the network at the other end of the BGP session from Oracle" + default = 0 +} + +variable "virtual_circuit_is_bfd_enabled" { + type = bool + description = "Set to true to enable BFD for IPv4 BGP peering, or set to false to disable BFD" + default = false +} + +variable "bgp_md5auth_key" { + type = string + description = "The key for BGP MD5 authentication. Only applicable if your system requires MD5 authentication" + default = "" +} + +variable "prod_enable_fastconnect" { + type = bool + default = true + description = "[Please don't change this value] Enable fastconnect in prod environment." +} + +variable "nonprod_enable_fastconnect" { + type = bool + default = false + description = "[Please don't change this value] Enable fastconnect in non prod environment." +} + +variable "customer_onprem_ip_cidr" { + type = list(string) + default = [] +} diff --git a/templates/enterprise-landing-zone/outputs.tf b/templates/enterprise-landing-zone/outputs.tf new file mode 100644 index 00000000..0d548592 --- /dev/null +++ b/templates/enterprise-landing-zone/outputs.tf @@ -0,0 +1,16 @@ +output "subnets" { + value = module.prod_environment.subnets + description = "The subnet OCID" +} + +output "vcn" { + value = module.prod_environment.vcn +} + +output "dynamic_group_detail" { + value = module.osms_dynamic_group +} + +output "workload_compartment_id" { + value = module.prod_environment.workload_compartment_id +} \ No newline at end of file diff --git a/templates/enterprise-landing-zone/provider.tf b/templates/enterprise-landing-zone/provider.tf new file mode 100644 index 00000000..d9301434 --- /dev/null +++ b/templates/enterprise-landing-zone/provider.tf @@ -0,0 +1,81 @@ +# # ----------------------------------------------------------------------------- +# # Provider Requirements if using stack as a module +# # ----------------------------------------------------------------------------- +# terraform { +# required_version = ">= 1.0.0" + +# required_providers { +# oci = { +# source = "oracle/oci" +# version = "4.96.0" # October 05, 2022 Release +# configuration_aliases = [oci, oci.home_region] +# } +# } +# } + +# ----------------------------------------------------------------------------- +# WARNING! +# UNCOMMENT EVERYTHING BELOW AND COMMENT EVERYTHING ABOVE IF YOU WISH TO USE THIS +# STACK AS A STANDALONE - DO NOT TOUCH IF USING THIS STACK IN A MODULE CALL +# Provider Requirements if using stack as standalone +# ----------------------------------------------------------------------------- +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + version = "4.96.0" # October 05, 2022 Release + } + } +} + + +# ----------------------------------------------------------------------------- +# Provider blocks for home region and alternate region(s) +# ----------------------------------------------------------------------------- +provider "oci" { + tenancy_ocid = var.tenancy_ocid + user_ocid = var.current_user_ocid + fingerprint = var.api_fingerprint + private_key = var.api_private_key # if both set this takes precidence + private_key_path = var.api_private_key_path + region = var.region +} + +provider "oci" { + alias = "home_region" + tenancy_ocid = var.tenancy_ocid + user_ocid = var.current_user_ocid + fingerprint = var.api_fingerprint + private_key = var.api_private_key # if both set this takes precidence + private_key_path = var.api_private_key_path + region = local.home_region[0] +} + +# ----------------------------------------------------------------------------- +# Provider Variables +# ----------------------------------------------------------------------------- +variable "current_user_ocid" { + type = string + description = "The OCID of the current user" + default = "" +} + +variable "api_fingerprint" { + type = string + description = "The fingerprint of API" + default = "" +} + +variable "api_private_key_path" { + type = string + description = "The local path to the API private key" + default = "" +} + +variable "api_private_key" { + type = string + description = "The API private key" + default = "" +} \ No newline at end of file diff --git a/templates/enterprise-landing-zone/regenerate_docs.sh b/templates/enterprise-landing-zone/regenerate_docs.sh new file mode 100755 index 00000000..30d3de60 --- /dev/null +++ b/templates/enterprise-landing-zone/regenerate_docs.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +########################################################### +## This will update all our autogenerated README.md files. +## +## The autogenerated content is placed between: +## +## ... and ... +## +## tags in the README.md files. DO NOT edit those sections +## manually! Any changes there will be lost! +## +## Note: this script actually generates the main +## enterprise-landing-zone/README.md twice, +## which is unavoidable due to our directory layout. +## We may need to revisit this if ve decide to use +## different documentation parameters in modules/ +## and templates/ folders. +########################################################### + +terraform-docs . +terraform-docs -c .module-tf-docs.yml . + diff --git a/templates/enterprise-landing-zone/security.tf b/templates/enterprise-landing-zone/security.tf new file mode 100644 index 00000000..12d48fca --- /dev/null +++ b/templates/enterprise-landing-zone/security.tf @@ -0,0 +1,177 @@ +locals { + cloud_guard_policy = { + name = "${var.resource_label}-OCI-ELZ-CG-Policy" + description = "OCI Enterprise Landing Zone Cloud Guard Policy" + + statements = [ + "Allow service cloudguard to read vaults in tenancy", + "Allow service cloudguard to read keys in tenancy", + "Allow service cloudguard to read compartments in tenancy", + "Allow service cloudguard to read tenancies in tenancy", + "Allow service cloudguard to read audit-events in tenancy", + "Allow service cloudguard to read compute-management-family in tenancy", + "Allow service cloudguard to read instance-family in tenancy", + "Allow service cloudguard to read virtual-network-family in tenancy", + "Allow service cloudguard to read volume-family in tenancy", + "Allow service cloudguard to read database-family in tenancy", + "Allow service cloudguard to read object-family in tenancy", + "Allow service cloudguard to read load-balancers in tenancy", + "Allow service cloudguard to read users in tenancy", + "Allow service cloudguard to read groups in tenancy", + "Allow service cloudguard to read policies in tenancy", + "Allow service cloudguard to read dynamic-groups in tenancy", + "Allow service cloudguard to read authentication-policies in tenancy", + "Allow service cloudguard to use network-security-groups in tenancy", + "Allow service cloudguard to read data-safe-family in tenancy", + "Allow service cloudguard to read autonomous-database-family in tenancy", + "Allow service cloudguard to manage cloudevents-rules in tenancy where target.rule.type='managed'" + ] + } + + cloud_guard_target_policy = { + name = "${var.resource_label}-OCI-ELZ-CGTarget-Policy" + description = "OCI Enterprise Landing Zone Cloud Guard Target Policy" + + statements = var.cloud_guard_target_tenancy ? [ + "Allow service cloudguard to manage instance-family in tenancy", + "Allow service cloudguard to manage object-family in tenancy", + "Allow service cloudguard to manage buckets in tenancy", + "Allow service cloudguard to manage users in tenancy", + "Allow service cloudguard to manage policies in tenancy", + "Allow service cloudguard to manage keys in tenancy" + ] : [ + "Allow service cloudguard to manage instance-family in compartment ${var.home_compartment_name}", + "Allow service cloudguard to manage object-family in compartment ${var.home_compartment_name}", + "Allow service cloudguard to manage buckets in compartment ${var.home_compartment_name}", + "Allow service cloudguard to manage users in compartment ${var.home_compartment_name}", + "Allow service cloudguard to manage policies in compartment ${var.home_compartment_name}", + "Allow service cloudguard to manage keys in compartment ${var.home_compartment_name}" + ] + } + + vss_policy = { + name = "${var.resource_label}-OCI-ELZ-VSS-Policy" + description = "OCI Enterprise Landing Zone VSS Policy" + + statements = [ + "Allow service vulnerability-scanning-service to manage instances in compartment ${var.home_compartment_name}", + "Allow service vulnerability-scanning-service to read compartments in compartment ${var.home_compartment_name}", + "Allow service vulnerability-scanning-service to read vnics in compartment ${var.home_compartment_name}", + "Allow service vulnerability-scanning-service to read vnic-attachments in compartment ${var.home_compartment_name}" + ] + } + + vault_policy = { + name = "${var.resource_label}-OCI-ELZ-Vault-Policy" + description = "OCI Enterprise Landing Zone Vault Policy" + statements = [ + "Allow service keymanagementservice to manage vaults in compartment ${var.home_compartment_name}" + ] + } + + osms_dynamic_group = { + dynamic_group_name = "${var.resource_label}-OCI-ELZ-DG" + dynamic_group_description = "OCI ELZ Dynamic Group" + + general_matching_rule = < 0] + ) == length(var.prod_network_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "prod_secops_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Secops Warning and Critical notifications." + validation { + condition = length( + [for e in var.prod_secops_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.prod_secops_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "prod_platform_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Platform notifications." + validation { + condition = length( + [for e in var.prod_platform_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.prod_platform_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "prod_identity_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Identity notifications." + validation { + condition = length( + [for e in var.prod_identity_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.prod_identity_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} +variable "nonprod_network_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Network Warning and Critical notifications." + validation { + condition = length( + [for e in var.nonprod_network_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.nonprod_network_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "nonprod_secops_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Secops Warning and Critical notifications." + validation { + condition = length( + [for e in var.nonprod_secops_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.nonprod_secops_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "nonprod_platform_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Platform notifications." + validation { + condition = length( + [for e in var.nonprod_platform_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.nonprod_platform_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "nonprod_identity_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Identity notifications." + validation { + condition = length( + [for e in var.nonprod_identity_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.nonprod_identity_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "prod_workload_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Prod Workload notifications." + validation { + condition = length( + [for e in var.prod_workload_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.prod_workload_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "nonprod_workload_topic_endpoints" { + type = list(string) + default = [] + description = "List of email addresses for Non Prod Workload notifications." + validation { + condition = length( + [for e in var.nonprod_workload_topic_endpoints : + e if length(regexall("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", e)) > 0] + ) == length(var.nonprod_workload_topic_endpoints) + error_message = "Validation failed: invalid email address." + } +} + +variable "prod_enable_security_monitoring_alarms" { + type = bool + default = false + description = "Enable Security Monitoring Alarms in Production Security Compartment" +} +variable "prod_enable_network_monitoring_alarms" { + type = bool + default = false + description = "Enable Network Monitoring Alarms in Production Network Compartment" +} +variable "prod_enable_workload_monitoring_alarms" { + type = bool + default = false + description = "Enable Workload Monitoring Alarms in Production Workload Compartment" +} +variable "nonprod_enable_security_monitoring_alarms" { + type = bool + default = false + description = "Enable Security Monitoring Alarms in Non-Production Security Compartment" +} +variable "nonprod_enable_network_monitoring_alarms" { + type = bool + default = false + description = "Enable Network Monitoring Alarms in Non-Production Network Compartment" +} +variable "nonprod_enable_workload_monitoring_alarms" { + type = bool + default = false + description = "Enable Workload Monitoring Alarms in Non-Production Workload Compartment" +} diff --git a/test/README.md b/test/README.md new file mode 100644 index 00000000..f75469ce --- /dev/null +++ b/test/README.md @@ -0,0 +1,39 @@ +# Testing Code + +Unit and functional test code goes here. + +## Testing Locally +install the dependencies in a virtual environment +```bash +python -m venv lz-venv +. lz-venv/bin/activate +pip install -r test/requirements.txt +``` + +Edit and source the test_vars.example file +``` +source test_vars +``` + +Run the tests +``` +pytest test +``` + +Run a specific test script +``` +pytest --tf-mod-dir=test/terraform/budget test/test_budget.py +``` + +Run all unit tests +``` +pytest -m unit test +``` + +To see the output of Terraform as it runs (for debugging), +you can use the `--capture=tee-sys` flag like so: + +``` +pytest --capture=tee-sys --tf-mod-dir=test/terraform/budget test/test_budget.py +``` +You can also add the `--pdb` flag to pytest to drop into the python debugger within a failed test. \ No newline at end of file diff --git a/test/TestCompartmentModule1.py b/test/TestCompartmentModule1.py new file mode 100755 index 00000000..3c307047 --- /dev/null +++ b/test/TestCompartmentModule1.py @@ -0,0 +1,162 @@ +import oci +from oci.config import from_file +import pytest +import sys + +# Get Ocid From the Compartment Name +def getOcidFromCompName (compartmentName, compartmentData): + thiscompartment=[comp for comp in compartmentData if comp.name==compartmentName][0] + return thiscompartment.id + +# Get all the Children Compartment Inside the Compartment +def getCompTree (compartmentId): + list_compartments_response = identity_client.list_compartments( + compartment_id=compartmentId, + compartment_id_in_subtree=True) + return list_compartments_response.data + +# Check the Compartment Name Exist the Compartment Tree +def checkCompInData (compartmentName, compartmentData): + thiscompartment=[comp for comp in compartmentData if comp.name==compartmentName][0] + return "True" if thiscompartment else "False" + +# Create Compartment +def createCompartment (rootCompartmentOcid, compartmentName, compartmentDescription): + createCompartmentOcidResponse = identity_client.CreateCompartmentDetails( + compartment_id = rootCompartmentOcid, + name = compartmentName, + description = compartmentDescription + ) + return createCompartmentOcidResponse.data.id + +# Delete Compartment +def deleteCompartment (compartmentOcid): + deleteCompartmentOcidResponse = identity_client.delete_compartment( + compartment_id=compartmentId + ) + +def checkL1CompName: + compartmentlist = getCompTree(rootCompId) + returnFlag = checkCompInData("L1CompName", compartmentlist) + if returnFlag: + print ("Found L1 Compartment Inside the Root compartment") + else: + print ("Not Found L1 Compartment Inside the Root compartment") + sys.exit() + +def checkL2ProdCompName: + compartmentlist = getCompTree(l1OcidValue) + returnFlag = checkCompInData("L2CompProdName", compartmentlist) + if returnFlag: + print ("Found L2 Prod Compartment Inside the L1 compartment") + else: + print ("Not Found L2 Prod Compartment Inside the L1 compartment") + sys.exit() + +def checkL2NonProdCompName: + compartmentlist = getCompTree(l1OcidValue) + returnFlag = checkCompInData("L2CompNonProdName", compartmentlist) + if returnFlag: + print ("Found L2 Non Prod Compartment Inside the L1 compartment") + else: + print ("Not Found L2 Non Prod Compartment Inside the L1 compartment") + sys.exit() + +def checkL2Prodcheck(compartmentName): + compartmentlist = getCompTree(l2ProdOcidValue) + returnFlag = checkCompInData(compartmentName, compartmentlist) + if returnFlag: + print ("Found New L3 Network Compartment Inside the L2 Prod compartment") + else: + print ("Not Found New L3 Network Compartment Inside the L2 Prod compartment") + sys.exit() + +def checkCompInsideProdEnv: + compartmentlist = getCompTree(l2ProdOcidValue) + returnFlag = checkCompInData("L3CompNameProd", compartmentlist) + if returnFlag: + print ("Found L3 Compartment Inside the L2 Prod compartment") + else: + print ("Not Found L3 Compartment Inside the L2 Prod compartment") + sys.exit() + + returnFlag = checkCompInData("L4CompNameProd", compartmentlist) + if returnFlag: + print ("Found L4 Compartment Inside the L2 Prod compartment") + else: + print ("Not Found L4 Compartment Inside the L2 Prod compartment") + sys.exit() + +def checkCompInsideNonProdEnv: + compartmentlist = getCompTree(l2NonProdOcidValue) + returnFlag = checkCompInData("L3CompNameNonProd", compartmentlist) + if returnFlag: + print ("Found L3 Compartment Inside the L2 Non Prod compartment") + else: + print ("Not Found L3 Compartment Inside the L2 Non Prod compartment") + sys.exit() + + returnFlag = checkCompInData("L4CompNameNonProd", compartmentlist) + + if returnFlag: + print ("Found L4 Compartment Inside the L2 Non Prod compartment") + else: + print ("Not Found L4 Compartment Inside the L2 Non Prod compartment") + sys.exit() + +# Config file is read from user's home location i.e., ~/.oci/config +config = from_file() + +rootCompId="ocid1.tenancy.oc1..aaaaaaaaxbchsnzhdxyoewmoqiqzvltba2ri7gijhbd2z5ybpgorv7yhxeeq" # root compartment OCID + +#L1CompName = +#L2CompProdName = +#L2CompNonProdName +#L3CompNameProdSharedInfra= +#L4CompNameProdNetwork = +#L4CompNameProdSecurity = +#L3CompNameNonProd = +#L4CompNameNonProdNetwork = +#L4CompNameNonProdSecurity = + +# Please fill up the following Information +#config_with_key_file = { +# "user": , +# "key_file": , +# "fingerprint": , +# "tenancy": , +# "region": +#} + +oci.config.validate_config(config_with_key_file) +identity_client = oci.identity.IdentityClient(config) + +# Get the list of compartments including child compartments except root compartment +compartmentlist = getCompTree(rootCompId) + +# Get the OCID From the Compartment Name +l1OcidValue = getOcidFromCompName(L1CompName) +l2ProdOcidValue = getOcidFromCompName(L2CompProdName) + +l2NonProdOcidValue = getOcidFromCompName(L2CompNonProdName) +l4ProdNetworkOcid = getOcidFromCompName(L4CompNameProdNetwork) +l2ProdSharedInfraOcid = getOcidFromCompName(L3CompNameProdSharedInfra) + +# Check the Compartment Module Usecase +checkL1CompName() +checkL2ProdCompName() +checkL2NonProdCompName() +checkCompInsideProdEnv() +checkCompInsideNonProdEnv() + +# LANZ-902 : Delete the previous compartment and create new with different Name + +deleteCompartment(l4ProdNetworkOcid) +newL3NetworkCompName = "L3ProdSharedNetwork" +newl4ProdNetworkOcid = createCompartment(l2ProdSharedInfraOcid, newL3NetworkCompName, "L3 Prod Shared Network Compartment") +checkL2Prodcheck(newL3NetworkCompName) + + + + + diff --git a/test/conftest.py b/test/conftest.py new file mode 100644 index 00000000..cb45081b --- /dev/null +++ b/test/conftest.py @@ -0,0 +1,20 @@ +from glob import glob +import os +import pytest +import shutil + +@pytest.fixture(scope='session', autouse=True) +def session_setup_teardown(): + # setup code goes here if needed + # copy common files to ./terraform/ subfolders then cleanup common files + cwd = os.path.abspath(os.path.dirname(__file__)) + src = cwd + "/provider.tf" + dsts = glob(cwd + "/terraform/*/") + + for dst in dsts: + shutil.copy(src, dst) + + yield + + for dst in dsts: + os.remove(dst + "provider.tf") diff --git a/test/identityModuleTest.py b/test/identityModuleTest.py new file mode 100755 index 00000000..3d37891b --- /dev/null +++ b/test/identityModuleTest.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python + +import oci +from oci.config import from_file +import pytest +import sys + +REGION = 'us-ashburn-1' + +def get_config(): + if REGION != '': + return {"region": REGION} + return {} + + +def getAllUserCompartment(compartmentId): + getUserTree = identity_client.list_users(compartment_id=compartmentId) + return getUserTree.data + +def checkUserInData (userOcid, allUserData): + thisUser=[user for user in allUserData if user.id==userOcid][0] + return "True" if thisUser else "False" + +def findUserOcid(userName, allUserData): + thisUser=[user for user in allUserData if user.name==userName][0] + return thisUser.id + +def getGroupMembershipIdComp(compartmentId,userId): + getUserGroup = identity_client.list_user_group_memberships( + compartment_id=compartmentId, + user_id=userId + ) + print (getUserGroup.data) + return getUserGroup.data[0].group_id + +def createUserComp(compartmentId,userName,userDesc,userEmail): + create_user_response = identity_client.create_user( + create_user_details=oci.identity.models.CreateUserDetails( + compartment_id=compartmentId, + name=userName, + description=userDesc, + email=userEmail + )) + return create_user_response.data.id + +def deleteUser(userOcid): + deleteUserData = identity_client.delete_user(user_id=userOcid) + print (deleteUserData.data) + #return getUserTree.data + +def getGroupInfo(userDomainId): + getGroupInfo = identity_client.get_group( + group_id=userDomainId + ) + print (getGroupInfo.data) + +def getDomainInfoFromGroup(groupId): + getDomainInfo = identity_client.get_domain( + domain_id=groupId, + opc_request_id="VK8CHLJIWPURR3FHDDIB" + ) + print (getDomainInfo.data) + +def listGroupCompartmentInfo(compartmentOcid): + getGroupInfo = identity_client.list_groups(compartment_id = compartmentOcid) + return getGroupInfo.data + +def getGroupOcidFromName (groupName, groupData): + groupInfo=[grp for grp in groupData if grp.name==groupName][0] + return groupInfo.id + +def listPolicyInCompartment(compartmentOcid): + getPolicyInfo = identity_client.list_policies(compartment_id = compartmentOcid) + return getPolicyInfo.data + +def getPolicyOcidFromData(policyName, policyData): + policyInfo = [ policy for policy in policyData if policy.name==policyName][0] + return policyInfo.id + +def policyInfoFromOcid(policyOcid): + getPolicyInfo = identity_client.get_policy(policy_id = policyOcid) + return getPolicyInfo.data.statements + +def listUserCompartment(compartmentOcid): + listUserData = identity_client.list_users( + compartment_id = compartmentOcid + ) + return listUserData.data + +def getUserDetails (userOcid): + getUserDetail = identity_client.get_user( + user_id = userOcid + ) + print (getUserDetail.data) + +def getTenancyInfo(compartmentOcid): + getUserDetail = identity_client.get_tenancy( + tenancy_id = compartmentOcid + ) + print (getUserDetail.data) + + +config = from_file() + +rootCompId="ocid1.tenancy.oc1..aaaaaaaaxbchsnzhdxyoewmoqiqzvltba2ri7gijhbd2z5ybpgorv7yhxeeq" # root compartment OCID + + +#config_with_key_file = { +# "user": , +# "key_file": , +# "fingerprint": , +# "tenancy": , +# "region": +#} + +oci.config.validate_config(config_with_key_file) +identity_client = oci.identity.IdentityClient(config) + + +# Identity Varible +""" +networkProdCompartmentName = +networkProdGroupName = +networkProdPolicyName = +securityProdCompartmentName = +securityProdGroupName = +securityProdPolicyName = +networkNonProdCompartmentName = +networkNonProdGroupName = +securityNonProdCompartmentName = +securityNonProdGroupName = +breakUserName = +""" + +#Network Admin Test +getGroupInfoData = listGroupCompartmentInfo(rootCompId) +groupOcidNetworkProd = getGroupOcidFromName(networkProdGroupName,getGroupInfoData) +getGroupInfo(groupOcidNetworkProd) +#Verify the Policy +policyDataProd = listPolicyInCompartment(rootCompId) +policyOcidProd = getPolicyOcidFromData(networkProdPolicyName,policyData) +policyStatementProd = policyInfoFromOcid(policyOcid) +verfiyNetworkPolicy(policyStatementProd) + +#Create the User Inside Network Compartment and Verify it Accessiblity to other Compartment +l4ProdNetworkOcid = getOcidFromCompName(networkProdCompartmentName) +l4ProdSecurityOcid = getOcidFromCompName(securityProdCompartmentName) +newUserNetworkOcid = createUserComp(l4ProdNetworkOcid,"UserApiNetwork","Network User Created By OCI API", "abc@email.com") +allUserSecurityUser = getAllUserCompartment(securityProdCompartmentName) +returnFlag = checkUserInData(l4ProdNetworkOcid,allUserSecurityUser) +if returnFlag == "True": + deleteUser(newUserNetworkOcid) + sys.exit("Error::Created user Inside Network Compartment has access to security Comp") +deleteUser(newUserNetworkOcid) + + +#Security Admin Test +groupOcidSecurityProd = getGroupOcidFromName(securityProdGroupName,getGroupInfoData) +getGroupInfo(groupOcidSecurityProd) + +#Verify the Policy +policyOcidProdSecurity = getPolicyOcidFromData(securityProdPolicyName,policyData) +policyStatementProdSecurity = policyInfoFromOcid(policyOcid) +verfiySecurityPolicy(policyStatementProd) + +#Create the User Inside Security Compartment and Verify it Accessiblity to other Compartment + +newUserSecurityOcid = createUserComp(l4ProdSecurityOcid,"UserApiSecurity","Security User Created By OCI API", "abc@email.com") +allUserNetworkUser = getAllUserCompartment(networkProdCompartmentName) +returnFlag = checkUserInData(newUserSecurityOcid,allUserNetworkUser) +if returnFlag == "True": + deleteUser(newUserSecurityOcid) + sys.exit("Error::Created user Inside Security Compartment has access to Network Comp") +deleteUser(newUserSecurityOcid) + + +#Verify Break User Name + +allUserData = listUserCompartment(rootCompId) +breakUserOcid = findUserOcid(breakUserName, allUserData) +getUserDetails(breakUserOcid) + diff --git a/test/provider.tf b/test/provider.tf new file mode 100644 index 00000000..0abf6909 --- /dev/null +++ b/test/provider.tf @@ -0,0 +1,79 @@ +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + version = "4.96.0" # October 05, 2022 Release + configuration_aliases = [oci, oci.home_region] + } + } +} + +# ----------------------------------------------------------------------------- +# Support for multi-region deployments +# ----------------------------------------------------------------------------- +data "oci_identity_region_subscriptions" "regions" { + tenancy_id = var.tenancy_ocid +} + +locals { + region_subscriptions = data.oci_identity_region_subscriptions.regions.region_subscriptions + home_region = [for region in local.region_subscriptions : region.region_name if region.is_home_region == true] + region_key = [for region in local.region_subscriptions : region.region_key if region.region_name == var.region] +} + +# ----------------------------------------------------------------------------- +# Provider blocks for home region and alternate region(s) +# ----------------------------------------------------------------------------- +provider "oci" { + tenancy_ocid = var.tenancy_ocid + user_ocid = var.current_user_ocid + fingerprint = var.api_fingerprint + private_key = var.api_private_key # if both set this takes precidence + private_key_path = var.api_private_key_path + region = var.region +} + +provider "oci" { + alias = "home_region" + tenancy_ocid = var.tenancy_ocid + user_ocid = var.current_user_ocid + fingerprint = var.api_fingerprint + private_key = var.api_private_key # if both set this takes precidence + private_key_path = var.api_private_key_path + region = local.home_region[0] +} + +variable "region" { + type = string + description = "the OCI region" +} + +variable "tenancy_ocid" { + type = string + description = "The OCID of tenancy" +} + +variable "current_user_ocid" { + type = string + description = "OCID of the current user" +} + +variable "api_fingerprint" { + type = string + description = "The fingerprint of API" + default = "" +} + +variable "api_private_key_path" { + type = string + description = "The local path to the API private key" + default = "" +} + +variable "api_private_key" { + type = string + description = "The API private key" + default = "" +} \ No newline at end of file diff --git a/test/pytest.ini b/test/pytest.ini new file mode 100644 index 00000000..e5e5a28e --- /dev/null +++ b/test/pytest.ini @@ -0,0 +1,7 @@ +[pytest] +addopts = --strict-markers -ra -v +markers = + unit: unit tests + integration: integration tests + tf: terraform + slow: slow tests diff --git a/test/requirements.txt b/test/requirements.txt new file mode 100644 index 00000000..14918dda --- /dev/null +++ b/test/requirements.txt @@ -0,0 +1,6 @@ +pytest +pytest_terraform +python-hcl2 +paramiko +oci + diff --git a/test/terraform/budget/main.tf b/test/terraform/budget/main.tf new file mode 100644 index 00000000..3d0c22e5 --- /dev/null +++ b/test/terraform/budget/main.tf @@ -0,0 +1,28 @@ +locals { + budget = { + budget_description = "Budget targeting ${var.environment_prefix} enviroment compartment" + budget_display_name = "OCI-ELZ-BGT-${var.environment_prefix}" + } +} + +module "budget" { + count = var.enable_budget ? 1 : 0 + source = "../../../templates/elz-budget" #MODIFIED + tenancy_ocid = var.tenancy_ocid + region = var.region + environment_prefix = var.environment_prefix + + budget_compartment_id = var.tenancy_ocid + budget_description = local.budget.budget_description + budget_display_name = local.budget.budget_display_name + budget_target = var.tenancy_ocid #MODIFIED + budget_amount = var.budget_amount + budget_alert_rule_threshold = var.budget_alert_rule_threshold + budget_alert_rule_message = var.budget_alert_rule_message + budget_alert_rule_recipients = var.budget_alert_rule_recipients + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} diff --git a/test/terraform/budget/terraform.tfvars.example b/test/terraform/budget/terraform.tfvars.example new file mode 100644 index 00000000..38e4ad2f --- /dev/null +++ b/test/terraform/budget/terraform.tfvars.example @@ -0,0 +1,6 @@ +environment_prefix = "P" +enable_budget = true +budget_amount = "10000" +budget_alert_rule_threshold = "100" +budget_alert_rule_message = "testing prod" +budget_alert_rule_recipients = "example@example.com" diff --git a/test/terraform/budget/variables.tf b/test/terraform/budget/variables.tf new file mode 100644 index 00000000..2f0b4343 --- /dev/null +++ b/test/terraform/budget/variables.tf @@ -0,0 +1,34 @@ +variable "environment_prefix" { + type = string + description = "the 1 character string representing the environment eg. P (prod), N (non-prod), D, T, U" + default = "P" +} + +variable "enable_budget" { + type = bool + default = true +} + +variable "budget_amount" { + description = "The amount of the budget expressed as a whole number in the currency of the customer's rate card." + type = string + default = "10000" +} + +variable "budget_alert_rule_threshold" { + description = "The threshold for the budget alert." + type = string + default = "100" +} + +variable "budget_alert_rule_message" { + description = "The alert message for budget alerts." + type = string + default = "testing prod" +} + +variable "budget_alert_rule_recipients" { + description = "The delimited list of email addresses to receive the alert when it triggers. Delimiter characters can be a comma, space, TAB, or semicolon" + type = string + default = "example@example.com" +} diff --git a/test/terraform/network/datasources.tf b/test/terraform/network/datasources.tf new file mode 100644 index 00000000..03ab5fb4 --- /dev/null +++ b/test/terraform/network/datasources.tf @@ -0,0 +1,16 @@ +# --------------------------------------------------------------------------------------------------------------------- +# Get the image id of Oracle Linux +# --------------------------------------------------------------------------------------------------------------------- +data "oci_core_images" "ol_images" { + compartment_id = var.tenancy_ocid + + operating_system = "Oracle Linux" + operating_system_version = "8" + shape = var.test_instance_shape + sort_by = "TIMECREATED" + sort_order = "DESC" +} + +data "oci_identity_availability_domains" "ad" { + compartment_id = var.tenancy_ocid +} diff --git a/test/terraform/network/main.tf b/test/terraform/network/main.tf new file mode 100644 index 00000000..8cce39b3 --- /dev/null +++ b/test/terraform/network/main.tf @@ -0,0 +1,95 @@ +locals { + availability_domains = data.oci_identity_availability_domains.ad.availability_domains + test_compartment_ocid = var.compartment_ocid != "" ? var.compartment_ocid : var.tenancy_ocid +} + +# --------------------------------------------------------------------------------------------------------------------- +# Call network module to set up hub and spoke network here: +# --------------------------------------------------------------------------------------------------------------------- +# +module "network" { + source = "../../../templates/elz-network" + + tenancy_ocid = var.tenancy_ocid + region = var.region + environment_prefix = var.environment_prefix + enable_internet_gateway = true + enable_nat_gateway = true + enable_service_gateway = true + + network_compartment_id = local.test_compartment_ocid + + vcn_cidr_block = var.vcn_cidr_block + public_subnet_cidr_block = var.public_subnet_cidr_block + private_subnet_cidr_block = var.private_subnet_cidr_block + + private_spoke_subnet_web_cidr_block = var.private_spoke_subnet_web_cidr_block + private_spoke_subnet_app_cidr_block = var.private_spoke_subnet_app_cidr_block + private_spoke_subnet_db_cidr_block = var.private_spoke_subnet_db_cidr_block + spoke_vcn_cidr = var.spoke_vcn_cidr + + add_ssh_to_security_list = true + + customer_onprem_ip_cidr = [] + ipsec_connection_static_routes = [""] + enable_vpn_or_fastconnect = "NONE" + enable_vpn_on_environment = false + enable_fastconnect_on_environment = false + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} + +# +# ======== +# Fetch public hub subnet and 3 private workload subnets +# from network module. Module will need to utput those values. +# ======== +locals { + pub_subnet = module.network.subnets["OCI-ELZ-SUB-${var.environment_prefix}-HUB-${local.region_key[0]}001"] + priv_subnets = [ + module.network.subnets["OCI-ELZ-SUB-${var.environment_prefix}-SPK-${local.region_key[0]}001"], + module.network.subnets["OCI-ELZ-SUB-${var.environment_prefix}-SPK-${local.region_key[0]}002"], + module.network.subnets["OCI-ELZ-SUB-${var.environment_prefix}-SPK-${local.region_key[0]}003"], + ] +} + +# --------------------------------------------------------------------------------------------------------------------- +# Create Bastion +# --------------------------------------------------------------------------------------------------------------------- +module "bastion" { + source = "./test_instance" + compartment_ocid = local.test_compartment_ocid + hostname = "hub-bastion" + ssh_public_keys = join("\n", var.ssh_public_key_list) + subnet_id = local.pub_subnet + needs_public_ip = true + instance_shape = var.test_instance_shape + image_id = data.oci_core_images.ol_images.images.0.id + availability_domain = lookup(local.availability_domains[0], "name") +} + +# --------------------------------------------------------------------------------------------------------------------- +# Create private test instances +# --------------------------------------------------------------------------------------------------------------------- +module "test_nodes" { + source = "./test_instance" + count = length(local.priv_subnets) + compartment_ocid = local.test_compartment_ocid + + hostname = "spoke-${count.index + 1}-test" + ssh_public_keys = join("\n", var.ssh_public_key_list) + subnet_id = local.priv_subnets[count.index] + needs_public_ip = false + + instance_shape = var.test_instance_shape + image_id = data.oci_core_images.ol_images.images.0.id + availability_domain = lookup(local.availability_domains[0], "name") +} + +resource "time_sleep" "sshd_start_delay" { + depends_on = [module.bastion, module.test_nodes] + create_duration = "60s" +} \ No newline at end of file diff --git a/test/terraform/network/outputs.tf b/test/terraform/network/outputs.tf new file mode 100644 index 00000000..46ffb3b0 --- /dev/null +++ b/test/terraform/network/outputs.tf @@ -0,0 +1,17 @@ +output "bastion_ip" { + value = module.bastion.public_ip +} + +output "private_test_node_ips" { + value = module.test_nodes[*].private_ip +} + +# used in subnet names. +output "region_key" { + value = local.region_key[0] +} + +# used in subnet names. +output "environmant_prefix"{ + value = var.environment_prefix +} \ No newline at end of file diff --git a/test/terraform/network/terraform.tfvars.example b/test/terraform/network/terraform.tfvars.example new file mode 100644 index 00000000..b1d35718 --- /dev/null +++ b/test/terraform/network/terraform.tfvars.example @@ -0,0 +1,9 @@ +# ======= Network test values. + +# compartment_ocid = "comapartment OCID here..." # defaults to tenancy root +# test_instance_shape = "VM.Standard.E4.Flex" + +# environment_prefix = "P" +# vcn_cidr_block = "10.0.0.0/16" +# public_subnet_cidr_block = "10.0.0.0/24" +# private_subnet_cidr_block = "10.0.1.0/24" \ No newline at end of file diff --git a/test/terraform/network/test_instance/main.tf b/test/terraform/network/test_instance/main.tf new file mode 100644 index 00000000..96fa88a4 --- /dev/null +++ b/test/terraform/network/test_instance/main.tf @@ -0,0 +1,54 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +# --------------------------------------------------------------------------------------------------------------------- +# Create single test instance +# --------------------------------------------------------------------------------------------------------------------- +resource "oci_core_instance" "test_instance" { + compartment_id = var.compartment_ocid + availability_domain = var.availability_domain + shape = var.instance_shape + is_pv_encryption_in_transit_enabled = true + display_name = var.hostname + + freeform_tags = { + "Description" = "Network Test host" + "Function" = "Test Network connectivity." + } + + create_vnic_details { + assign_public_ip = var.needs_public_ip + display_name = "${var.hostname}-vnic" + hostname_label = var.hostname + subnet_id = var.subnet_id + } + + shape_config { + memory_in_gbs = var.instance_shape_config_memory_in_gbs + ocpus = var.instance_shape_config_ocpus + baseline_ocpu_utilization = "BASELINE_1_1" + } + + metadata = { + ssh_authorized_keys = var.ssh_public_keys + } + + source_details { + source_type = "image" + source_id = var.image_id + } + + launch_options { + is_pv_encryption_in_transit_enabled = true + network_type = "PARAVIRTUALIZED" + } + + timeouts { + create = "10m" + } +} diff --git a/test/terraform/network/test_instance/outputs.tf b/test/terraform/network/test_instance/outputs.tf new file mode 100644 index 00000000..2c318037 --- /dev/null +++ b/test/terraform/network/test_instance/outputs.tf @@ -0,0 +1,10 @@ +# --------------------------------------------------------------------------------------------------------------------- +# Return the public IP address +# --------------------------------------------------------------------------------------------------------------------- +output "public_ip" { + value = oci_core_instance.test_instance.public_ip +} + +output "private_ip" { + value = oci_core_instance.test_instance.private_ip +} \ No newline at end of file diff --git a/test/terraform/network/test_instance/variables.tf b/test/terraform/network/test_instance/variables.tf new file mode 100644 index 00000000..1e276455 --- /dev/null +++ b/test/terraform/network/test_instance/variables.tf @@ -0,0 +1,58 @@ +# --------------------------------------------------------------------------------------------------------------------- +# Required inputs +# --------------------------------------------------------------------------------------------------------------------- +variable "compartment_ocid" { + type = string + description = "The OCID of the compartment" +} +variable "ssh_public_keys" { + type = string + description = "The ssh public keys" +} + +variable "subnet_id" { + type = string + description = "[Subnet] The subnet ID the instance should be connected to" +} + +variable "image_id" { + type = string +} + +variable "availability_domain" { + type = string +} + +variable "hostname" { + type = string +} + +variable needs_public_ip { + type = bool +} + +# --------------------------------------------------------------------------------------------------------------------- +# Test instance inputs +# --------------------------------------------------------------------------------------------------------------------- +variable "instance_shape" { + type = string + description = "Bastion Instance Shape" +} + +variable "instance_shape_config_ocpus" { + type = number + description = "Number of OCPUs per instance" + default = 1 +} + +variable "instance_shape_config_memory_in_gbs" { + type = number + description = "Memory in GB per instance" + default = 8 +} + +variable "instance_operating_system_version" { + description = "the version of Oracle Linux" + type = string + default = "8" +} diff --git a/test/terraform/network/variables.tf b/test/terraform/network/variables.tf new file mode 100644 index 00000000..5063fdf2 --- /dev/null +++ b/test/terraform/network/variables.tf @@ -0,0 +1,73 @@ +# ============ Provider variables. +#variable "tenancy_ocid" { +# type = string +# description = "the ocid of tenancy" +#} +# =================================== + +variable "compartment_ocid" { + type = string + description = "the ocid of the compartment instances will live in. Defaults to tenancy root." + default = "" +} + +variable "ssh_public_key_list" { + type = list(string) + description = "The list of ssh public keys" +} + +variable "test_instance_shape" { + type = string + description = "Test Instance Shape" + default = "VM.Standard.E4.Flex" +} + +# ====== Network Module test parameters. +variable "environment_prefix" { + type = string + description = "1 char env prefix" + default = "P" +} + +variable "vcn_cidr_block" { + type = string + description = "Hub vcn CIDR" + default = "10.0.0.0/16" +} + +variable "public_subnet_cidr_block" { + type = string + description = "Hub public subnet CIDR" + default = "10.0.0.0/24" + +} + +variable "private_subnet_cidr_block" { + type = string + description = "Hub private subnet CIDR" + default = "10.0.1.0/24" +} + + +variable "private_spoke_subnet_web_cidr_block" { + type = string + default = "10.1.1.0/24" + +} + +variable "private_spoke_subnet_app_cidr_block" { + type = string + default = "10.1.2.0/24" + +} + +variable "private_spoke_subnet_db_cidr_block" { + type = string + default = "10.1.3.0/24" + +} + +variable "spoke_vcn_cidr" { + type = string + default = "10.1.0.0/16" +} \ No newline at end of file diff --git a/test/terraform/security_bastion/compartment/main.tf b/test/terraform/security_bastion/compartment/main.tf new file mode 100644 index 00000000..61feba76 --- /dev/null +++ b/test/terraform/security_bastion/compartment/main.tf @@ -0,0 +1,21 @@ +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_identity_compartment" "compartment" { + compartment_id = var.compartment_parent_id + description = var.compartment_description + name = var.compartment_name + enable_delete = var.enable_compartment_delete +} + +resource "time_sleep" "compartment_replication_delay" { + depends_on = [oci_identity_compartment.compartment] + create_duration = var.compartment_replication_delay +} diff --git a/test/terraform/security_bastion/compartment/outputs.tf b/test/terraform/security_bastion/compartment/outputs.tf new file mode 100644 index 00000000..43fd128a --- /dev/null +++ b/test/terraform/security_bastion/compartment/outputs.tf @@ -0,0 +1,8 @@ +output "compartment_id" { + value = oci_identity_compartment.compartment.id + description = "The OCID of the compartment created" + depends_on = [ + time_sleep.compartment_replication_delay + ] +} + diff --git a/test/terraform/security_bastion/compartment/variables.tf b/test/terraform/security_bastion/compartment/variables.tf new file mode 100644 index 00000000..02e245d1 --- /dev/null +++ b/test/terraform/security_bastion/compartment/variables.tf @@ -0,0 +1,26 @@ +variable "compartment_parent_id" { + type = string + description = "OCID of the parent compartment." +} + +variable "compartment_name" { + type = string + description = "Name of the compartment to create." +} + +variable "compartment_description" { + type = string + description = "Description of the compartment to create." +} + +variable "enable_compartment_delete" { + type = bool + description = "Allows the compartment to delete on terraform destroy." + default = false +} + +variable "compartment_replication_delay" { + type = string + description = "delay to allow compartments to replicate" + default = "90s" +} \ No newline at end of file diff --git a/test/terraform/security_bastion/main.tf b/test/terraform/security_bastion/main.tf new file mode 100644 index 00000000..4c50bfb2 --- /dev/null +++ b/test/terraform/security_bastion/main.tf @@ -0,0 +1,117 @@ +locals { + test_compartment_name = "Test_sec_bast_home_compartment" +} + +##### Test Compartments + +module "home_compartment" { + source = "./compartment" + + compartment_parent_id = var.tenancy_ocid + compartment_name = local.test_compartment_name + compartment_description = "Test Home comaprtment for Bastion tests" + compartment_replication_delay = var.compartment_replication_delay + + providers = { + oci = oci.home_region + } +} + +module "environment_compartment" { + source = "./compartment" + + compartment_parent_id = module.home_compartment.compartment_id + compartment_name = "Test_sec_bast_env_compartment" + compartment_description = "Test environment comaprtment for Bastion tests" + compartment_replication_delay = var.compartment_replication_delay + + providers = { + oci = oci.home_region + } +} + +module "shared_infra_compartment" { + source = "./compartment" + + compartment_parent_id = module.environment_compartment.compartment_id + compartment_name = "Test_sec_bast_si_compartment" + compartment_description = "Test Shared Infra comaprtment for Bastion tests" + compartment_replication_delay = var.compartment_replication_delay + + providers = { + oci = oci.home_region + } +} + +module "security_compartment" { + source = "./compartment" + + compartment_parent_id = module.shared_infra_compartment.compartment_id + compartment_name = "Test_sec_bast_sec_compartment" + compartment_description = "Test Security comaprtment for Bastion tests" + compartment_replication_delay = var.compartment_replication_delay + + providers = { + oci = oci.home_region + } +} + +module "network_compartment" { + source = "./compartment" + + compartment_parent_id = module.shared_infra_compartment.compartment_id + compartment_name = "Test_sec_bast_net_sec_compartment" + compartment_description = "Test Security comaprtment for Bastion tests" + compartment_replication_delay = var.compartment_replication_delay + + providers = { + oci = oci.home_region + } +} + +##### Test Network + +resource "oci_core_vcn" "vcn_test_network" { + cidr_blocks = [var.vcn_cidr_block] + compartment_id = module.network_compartment.compartment_id + display_name = "bastiontestnet" + dns_label = "basttestlabel" + is_ipv6enabled = false +} + +resource "oci_core_subnet" "test_subnet" { + cidr_block = var.test_subnet_cidr_block + display_name = "Test_sec_bast_subnet" + dns_label = "testbastsub" + compartment_id = module.network_compartment.compartment_id + prohibit_public_ip_on_vnic = false + vcn_id = oci_core_vcn.vcn_test_network.id +} + +##### Create Security module to test + +module "security" { + source = "../../../templates/elz-security" + enable_cloud_guard = false + resource_label = var.resource_label + home_compartment_id = module.home_compartment.compartment_id + cloud_guard_target_tenancy = false + tenancy_ocid = var.tenancy_ocid + environment_prefix = var.environment_prefix + home_compartment_name = "Test Home" + region = var.region + environment_compartment_id = module.environment_compartment.compartment_id + security_compartment_id = module.security_compartment.compartment_id + enable_bastion = true + bastion_target_subnet_id = oci_core_subnet.test_subnet.id + bastion_client_cidr_block_allow_list = ["0.0.0.0/0"] + vault_type = "NONE" + replica_region = "" + enable_replication = false + create_master_encryption_key = false + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} diff --git a/test/terraform/security_bastion/outputs.tf b/test/terraform/security_bastion/outputs.tf new file mode 100644 index 00000000..c9e974c4 --- /dev/null +++ b/test/terraform/security_bastion/outputs.tf @@ -0,0 +1,19 @@ +output "environment_compartment_id" { + value = module.environment_compartment.compartment_id + description = "The OCID of the test environment compartment" +} + +output "security_compartment_id" { + value = module.security_compartment.compartment_id + description = "The OCID of the test security compartment" +} + +output "test_subnet_id" { + value = oci_core_subnet.test_subnet.id + description = "OCID of test subnet" +} + +output "bastion_id" { + value = module.security.bastion_id + description = "OCID of the created bastion" +} \ No newline at end of file diff --git a/test/terraform/security_bastion/variables.tf b/test/terraform/security_bastion/variables.tf new file mode 100644 index 00000000..d229bfef --- /dev/null +++ b/test/terraform/security_bastion/variables.tf @@ -0,0 +1,34 @@ +variable "compartment_replication_delay" { + type = string + description = "delay to allow compartments to replicate" + default = "90s" +} + +variable "compartment_ocid" { + type = string + description = "the ocid of the compartment instances will live in. Defaults to tenancy root." + default = "" +} +variable "environment_prefix" { + type = string + description = "1 char env prefix" + default = "P" +} + +variable "resource_label" { + type = string + description = "Prefix used to avoid naming conflict" + default = "TSTBAST" +} + +variable "vcn_cidr_block" { + type = string + description = "Test VCN CIDR" + default = "10.0.0.0/16" +} + +variable "test_subnet_cidr_block" { + type = string + description = "Hub public subnet CIDR" + default = "10.0.0.0/24" +} \ No newline at end of file diff --git a/test/terraform/security_cloudguard/compartment/main.tf b/test/terraform/security_cloudguard/compartment/main.tf new file mode 100644 index 00000000..61feba76 --- /dev/null +++ b/test/terraform/security_cloudguard/compartment/main.tf @@ -0,0 +1,21 @@ +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_identity_compartment" "compartment" { + compartment_id = var.compartment_parent_id + description = var.compartment_description + name = var.compartment_name + enable_delete = var.enable_compartment_delete +} + +resource "time_sleep" "compartment_replication_delay" { + depends_on = [oci_identity_compartment.compartment] + create_duration = var.compartment_replication_delay +} diff --git a/test/terraform/security_cloudguard/compartment/outputs.tf b/test/terraform/security_cloudguard/compartment/outputs.tf new file mode 100644 index 00000000..43fd128a --- /dev/null +++ b/test/terraform/security_cloudguard/compartment/outputs.tf @@ -0,0 +1,8 @@ +output "compartment_id" { + value = oci_identity_compartment.compartment.id + description = "The OCID of the compartment created" + depends_on = [ + time_sleep.compartment_replication_delay + ] +} + diff --git a/test/terraform/security_cloudguard/compartment/variables.tf b/test/terraform/security_cloudguard/compartment/variables.tf new file mode 100644 index 00000000..02e245d1 --- /dev/null +++ b/test/terraform/security_cloudguard/compartment/variables.tf @@ -0,0 +1,26 @@ +variable "compartment_parent_id" { + type = string + description = "OCID of the parent compartment." +} + +variable "compartment_name" { + type = string + description = "Name of the compartment to create." +} + +variable "compartment_description" { + type = string + description = "Description of the compartment to create." +} + +variable "enable_compartment_delete" { + type = bool + description = "Allows the compartment to delete on terraform destroy." + default = false +} + +variable "compartment_replication_delay" { + type = string + description = "delay to allow compartments to replicate" + default = "90s" +} \ No newline at end of file diff --git a/test/terraform/security_cloudguard/main.tf b/test/terraform/security_cloudguard/main.tf new file mode 100644 index 00000000..1267ff67 --- /dev/null +++ b/test/terraform/security_cloudguard/main.tf @@ -0,0 +1,157 @@ +locals { + test_compartment_name = "Test_sec_cg_home_compartment" + + cloud_guard_policy = { + name = "${var.resource_label}-OCI-ELZ-CG-Policy" + description = "OCI Enterprise Landing Zone Cloud Guard Policy" + + statements = [ + "Allow service cloudguard to read vaults in tenancy", + "Allow service cloudguard to read keys in tenancy", + "Allow service cloudguard to read compartments in tenancy", + "Allow service cloudguard to read tenancies in tenancy", + "Allow service cloudguard to read audit-events in tenancy", + "Allow service cloudguard to read compute-management-family in tenancy", + "Allow service cloudguard to read instance-family in tenancy", + "Allow service cloudguard to read virtual-network-family in tenancy", + "Allow service cloudguard to read volume-family in tenancy", + "Allow service cloudguard to read database-family in tenancy", + "Allow service cloudguard to read object-family in tenancy", + "Allow service cloudguard to read load-balancers in tenancy", + "Allow service cloudguard to read users in tenancy", + "Allow service cloudguard to read groups in tenancy", + "Allow service cloudguard to read policies in tenancy", + "Allow service cloudguard to read dynamic-groups in tenancy", + "Allow service cloudguard to read authentication-policies in tenancy", + "Allow service cloudguard to use network-security-groups in tenancy", + "Allow service cloudguard to read data-safe-family in tenancy", + "Allow service cloudguard to read autonomous-database-family in tenancy", + "Allow service cloudguard to manage cloudevents-rules in tenancy where target.rule.type='managed'" + ] + } + + cloud_guard_target_policy = { + name = "${var.resource_label}-OCI-ELZ-CGTarget-Policy" + description = "OCI Enterprise Landing Zone Cloud Guard Target Policy" + + statements = [ + "Allow service cloudguard to manage instance-family in compartment ${local.test_compartment_name}", + "Allow service cloudguard to manage object-family in compartment ${local.test_compartment_name}", + "Allow service cloudguard to manage buckets in compartment ${local.test_compartment_name}", + "Allow service cloudguard to manage users in compartment ${local.test_compartment_name}", + "Allow service cloudguard to manage policies in compartment ${local.test_compartment_name}", + "Allow service cloudguard to manage keys in compartment ${local.test_compartment_name}" + ] + } +} + +##### Test Compartments + +module "home_compartment" { + source = "./compartment" + + compartment_parent_id = var.tenancy_ocid + compartment_name = local.test_compartment_name + compartment_description = "Test Home comaprtment for CG tests" + compartment_replication_delay = var.compartment_replication_delay + + providers = { + oci = oci.home_region + } +} + +module "environment_compartment" { + source = "./compartment" + + compartment_parent_id = module.home_compartment.compartment_id + compartment_name = "Test_sec_cg_env_compartment" + compartment_description = "Test environment comaprtment for CG tests" + compartment_replication_delay = var.compartment_replication_delay + + providers = { + oci = oci.home_region + } +} + +module "shared_infra_compartment" { + source = "./compartment" + + compartment_parent_id = module.environment_compartment.compartment_id + compartment_name = "Test_sec_cg_si_compartment" + compartment_description = "Test Shared Infra comaprtment for CG tests" + compartment_replication_delay = var.compartment_replication_delay + + providers = { + oci = oci.home_region + } +} + +module "security_compartment" { + source = "./compartment" + + compartment_parent_id = module.shared_infra_compartment.compartment_id + compartment_name = "Test_sec_cg_sec_compartment" + compartment_description = "Test Security comaprtment for CG tests" + compartment_replication_delay = var.compartment_replication_delay + + providers = { + oci = oci.home_region + } +} + +##### Policies + +############################################################################### +## Note: I don't like that we have to create these policies here to test. +## It would be better to test the policy creation along with the +## cloudguard resource creation, But the security module is not +## self-contained, these policies are created in the top-level +## "enterprise-landing-zone" template, and thus can't be instantiated +## separately. +############################################################################### + +module "cloud_guard_root_policy" { + source = "./policies" + compartment_ocid = var.tenancy_ocid + policy_name = local.cloud_guard_policy.name + description = local.cloud_guard_policy.description + statements = local.cloud_guard_policy.statements +} + +module "cloud_guard_target_policy" { + source = "./policies" + compartment_ocid = module.home_compartment.compartment_id + policy_name = local.cloud_guard_target_policy.name + description = local.cloud_guard_target_policy.description + statements = local.cloud_guard_target_policy.statements + + depends_on = [module.home_compartment] +} + +##### Create Security module to test + +module "security" { + source = "../../../templates/elz-security" + enable_cloud_guard = true + resource_label = var.resource_label + home_compartment_id = module.home_compartment.compartment_id + cloud_guard_target_tenancy = false + tenancy_ocid = var.tenancy_ocid + environment_prefix = var.environment_prefix + home_compartment_name = local.test_compartment_name + region = var.region + environment_compartment_id = module.environment_compartment.compartment_id + security_compartment_id = module.security_compartment.compartment_id + enable_bastion = false + bastion_target_subnet_id = "" + bastion_client_cidr_block_allow_list = ["0.0.0.0/0"] + vault_type = "NONE" + replica_region = "" + enable_replication = false + create_master_encryption_key = false + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} diff --git a/test/terraform/security_cloudguard/outputs.tf b/test/terraform/security_cloudguard/outputs.tf new file mode 100644 index 00000000..b4f4072f --- /dev/null +++ b/test/terraform/security_cloudguard/outputs.tf @@ -0,0 +1,9 @@ +output "environment_compartment_id" { + value = module.environment_compartment.compartment_id + description = "The OCID of the test environment compartment" +} + +output "security_compartment_id" { + value = module.security_compartment.compartment_id + description = "The OCID of the test security compartment" +} diff --git a/test/terraform/security_cloudguard/policies/main.tf b/test/terraform/security_cloudguard/policies/main.tf new file mode 100644 index 00000000..1ac8194f --- /dev/null +++ b/test/terraform/security_cloudguard/policies/main.tf @@ -0,0 +1,19 @@ +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_identity_policy" "policy" { + compartment_id = var.compartment_ocid + description = var.description + name = var.policy_name + statements = var.statements +} + +resource "time_sleep" "policy_propagation_delay" { + depends_on = [oci_identity_policy.policy] + create_duration = "90s" +} diff --git a/test/terraform/security_cloudguard/policies/outputs.tf b/test/terraform/security_cloudguard/policies/outputs.tf new file mode 100644 index 00000000..7fed20cd --- /dev/null +++ b/test/terraform/security_cloudguard/policies/outputs.tf @@ -0,0 +1,3 @@ +output "policy" { + value = oci_identity_policy.policy +} diff --git a/test/terraform/security_cloudguard/policies/variables.tf b/test/terraform/security_cloudguard/policies/variables.tf new file mode 100644 index 00000000..9476bd25 --- /dev/null +++ b/test/terraform/security_cloudguard/policies/variables.tf @@ -0,0 +1,19 @@ +variable "compartment_ocid" { + type = string + description = "The OCID of the compartment containing the policy." +} + +variable "description" { + type = string + description = "The description of policy" +} + +variable "policy_name" { + type = string + description = "The name of policy." +} + +variable "statements" { + type = list(string) + description = "An array of policy statements written in the policy language." +} \ No newline at end of file diff --git a/test/terraform/security_cloudguard/variables.tf b/test/terraform/security_cloudguard/variables.tf new file mode 100644 index 00000000..d7d864d8 --- /dev/null +++ b/test/terraform/security_cloudguard/variables.tf @@ -0,0 +1,23 @@ +variable "compartment_replication_delay" { + type = string + description = "delay to allow compartments to replicate" + default = "90s" +} + +variable "compartment_ocid" { + type = string + description = "the ocid of the compartment test resources will live in. Defaults to tenancy root." + default = "" +} + +variable "environment_prefix" { + type = string + description = "1 char env prefix" + default = "P" +} + +variable "resource_label" { + type = string + description = "Prefix used to avoid naming conflict" + default = "TSTCG" +} diff --git a/test/terraform/security_vault/compartment/main.tf b/test/terraform/security_vault/compartment/main.tf new file mode 100644 index 00000000..61feba76 --- /dev/null +++ b/test/terraform/security_vault/compartment/main.tf @@ -0,0 +1,21 @@ +terraform { + required_version = ">= 1.0.0" + + required_providers { + oci = { + source = "oracle/oci" + } + } +} + +resource "oci_identity_compartment" "compartment" { + compartment_id = var.compartment_parent_id + description = var.compartment_description + name = var.compartment_name + enable_delete = var.enable_compartment_delete +} + +resource "time_sleep" "compartment_replication_delay" { + depends_on = [oci_identity_compartment.compartment] + create_duration = var.compartment_replication_delay +} diff --git a/test/terraform/security_vault/compartment/outputs.tf b/test/terraform/security_vault/compartment/outputs.tf new file mode 100644 index 00000000..43fd128a --- /dev/null +++ b/test/terraform/security_vault/compartment/outputs.tf @@ -0,0 +1,8 @@ +output "compartment_id" { + value = oci_identity_compartment.compartment.id + description = "The OCID of the compartment created" + depends_on = [ + time_sleep.compartment_replication_delay + ] +} + diff --git a/test/terraform/security_vault/compartment/variables.tf b/test/terraform/security_vault/compartment/variables.tf new file mode 100644 index 00000000..02e245d1 --- /dev/null +++ b/test/terraform/security_vault/compartment/variables.tf @@ -0,0 +1,26 @@ +variable "compartment_parent_id" { + type = string + description = "OCID of the parent compartment." +} + +variable "compartment_name" { + type = string + description = "Name of the compartment to create." +} + +variable "compartment_description" { + type = string + description = "Description of the compartment to create." +} + +variable "enable_compartment_delete" { + type = bool + description = "Allows the compartment to delete on terraform destroy." + default = false +} + +variable "compartment_replication_delay" { + type = string + description = "delay to allow compartments to replicate" + default = "90s" +} \ No newline at end of file diff --git a/test/terraform/security_vault/main.tf b/test/terraform/security_vault/main.tf new file mode 100644 index 00000000..fcf87e38 --- /dev/null +++ b/test/terraform/security_vault/main.tf @@ -0,0 +1,89 @@ +locals { + test_compartment_name = "Test_sec_vault_home_${random_id.home_suffix.hex}" +} + +resource "random_id" "home_suffix" { + byte_length = 4 +} + +##### Test Compartments + +module "home_compartment" { + source = "./compartment" + + compartment_parent_id = var.tenancy_ocid + compartment_name = local.test_compartment_name + compartment_description = "Test Home comaprtment for vault tests" + compartment_replication_delay = var.compartment_replication_delay + + providers = { + oci = oci.home_region + } +} + +module "environment_compartment" { + source = "./compartment" + + compartment_parent_id = module.home_compartment.compartment_id + compartment_name = "Test_sec_vault_env_compartment" + compartment_description = "Test environment comaprtment for vault tests" + compartment_replication_delay = var.compartment_replication_delay + + providers = { + oci = oci.home_region + } +} + +module "shared_infra_compartment" { + source = "./compartment" + + compartment_parent_id = module.environment_compartment.compartment_id + compartment_name = "Test_sec_vault_si_compartment" + compartment_description = "Test Shared Infra comaprtment for Vault tests" + compartment_replication_delay = var.compartment_replication_delay + + providers = { + oci = oci.home_region + } +} + +module "security_compartment" { + source = "./compartment" + + compartment_parent_id = module.shared_infra_compartment.compartment_id + compartment_name = "Test_sec_vault_sec_compartment" + compartment_description = "Test Security comaprtment for Vault tests" + compartment_replication_delay = var.compartment_replication_delay + + providers = { + oci = oci.home_region + } +} + +##### Create Security module to test + +module "security" { + source = "../../../templates/elz-security" + enable_cloud_guard = false + resource_label = var.resource_label + home_compartment_id = module.home_compartment.compartment_id + cloud_guard_target_tenancy = false + tenancy_ocid = var.tenancy_ocid + environment_prefix = var.environment_prefix + home_compartment_name = local.test_compartment_name + region = var.region + environment_compartment_id = module.environment_compartment.compartment_id + security_compartment_id = module.security_compartment.compartment_id + enable_bastion = false + bastion_target_subnet_id = "" + bastion_client_cidr_block_allow_list = ["0.0.0.0/0"] + vault_type = "DEFAULT" + replica_region = "" + enable_replication = false + create_master_encryption_key = true + + providers = { + oci = oci + oci.home_region = oci.home_region + } +} diff --git a/test/terraform/security_vault/outputs.tf b/test/terraform/security_vault/outputs.tf new file mode 100644 index 00000000..f3557cf9 --- /dev/null +++ b/test/terraform/security_vault/outputs.tf @@ -0,0 +1,14 @@ +output "environment_compartment_id" { + value = module.environment_compartment.compartment_id + description = "The OCID of the test environment compartment" +} + +output "security_compartment_id" { + value = module.security_compartment.compartment_id + description = "The OCID of the test security compartment" +} + +output "key_id" { + value = module.security.key_id + description = "OCID of Master Encryption Key." +} \ No newline at end of file diff --git a/test/terraform/security_vault/variables.tf b/test/terraform/security_vault/variables.tf new file mode 100644 index 00000000..d7d864d8 --- /dev/null +++ b/test/terraform/security_vault/variables.tf @@ -0,0 +1,23 @@ +variable "compartment_replication_delay" { + type = string + description = "delay to allow compartments to replicate" + default = "90s" +} + +variable "compartment_ocid" { + type = string + description = "the ocid of the compartment test resources will live in. Defaults to tenancy root." + default = "" +} + +variable "environment_prefix" { + type = string + description = "1 char env prefix" + default = "P" +} + +variable "resource_label" { + type = string + description = "Prefix used to avoid naming conflict" + default = "TSTCG" +} diff --git a/test/test_budget.py b/test/test_budget.py new file mode 100644 index 00000000..fbbd6c06 --- /dev/null +++ b/test/test_budget.py @@ -0,0 +1,33 @@ +from pytest_terraform import terraform +import pytest + +#unit tests for budget module +@pytest.mark.skip(reason="Budget tests currently broken, due to 404 error. We need to fix this.") +@pytest.mark.unit +@terraform("budget", scope="session") +def test_oci_budget_target_name(budget): + print(budget) + # actual_budget_target_name = budget["oci_budget_budget.oci_budget.display_name"] + # expected_budget_target_name = "budget-test-target-name-budget" + # assert actual_budget_target_name == expected_budget_target_name + +# @pytest.mark.unit +# @terraform("budget", scope="session") +# def test_oci_budget_amount(budget): +# actual_budget_amount = budget["oci_budget_budget.oci_budget.amount"] +# expected_budget_amount = 100000 +# assert actual_budget_amount == expected_budget_amount + +# @pytest.mark.unit +# @terraform("budget", scope="session") +# def test_oci_budget_alert_rule_threshold(budget): +# actual_budget_alert_rule_threshold = budget["oci_budget_alert_rule.oci_budget_rule.threshold"] +# expected_budget_alert_rule_threshold = 100 +# assert actual_budget_alert_rule_threshold == expected_budget_alert_rule_threshold + +# @pytest.mark.unit +# @terraform("budget", scope="session") +# def test_oci_budget_alert_rule_recipients(budget): +# actual_budget_alert_rule_recipients = budget["oci_budget_alert_rule.oci_budget_rule.recipients"] +# expected_budget_alert_rule_recipients = "example@test.com" +# assert actual_budget_alert_rule_recipients == expected_budget_alert_rule_recipients diff --git a/test/test_helpers/__init__.py b/test/test_helpers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/test_helpers/network/__init__.py b/test/test_helpers/network/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/test_helpers/network/nettest.py b/test/test_helpers/network/nettest.py new file mode 100644 index 00000000..a32c90b2 --- /dev/null +++ b/test/test_helpers/network/nettest.py @@ -0,0 +1,57 @@ +import socket +import paramiko + +from .proxssh import ProxySSH + +class NetTest: + + def __init__(self, bastion_ip): + self.bastion_ip = bastion_ip + + def check_ssh_connection(self, server_ip=None): + """Check ssh connection to server. + If server_ip is not specified, check connection to bastion""" + p = ProxySSH(self.bastion_ip, server_ip=server_ip) + #try: + p.exec_command_no_print("hostname") + # except paramiko.SSHException: + # return False + # except socket.timeout: + # return False + return True + + def ping_server(self, destination_ip, source_ip=None): + """Ping destination from source. + If no source specified, use bastion""" + p = ProxySSH(self.bastion_ip, server_ip=source_ip) + #try: + cmd = f"ping -c 3 {destination_ip} ; echo $?" + res = p.exec_command_no_print(cmd) + errcode = res.splitlines()[-1] + # except paramiko.SSHException: + # return False + # except socket.timeout: + # return False + return errcode == "0" + + +if __name__ == "__main__": + n = NetTest("150.136.166.192") + + #n = NetTest("129.80.237.242") + + print("Checking Bastion SSH connection (port 22)...") + assert n.check_ssh_connection() + print(" Ok.") + + print("Pinging Server 1...") + assert n.ping_server("10.0.1.54") + print(" Ok.") + + print("Pinging Server 2...") + assert n.ping_server("10.0.2.45") + print(" Ok.") + + print("Pinging Server 3...") + assert n.ping_server("10.0.3.117") + print(" Ok.") diff --git a/test/test_helpers/network/proxssh.py b/test/test_helpers/network/proxssh.py new file mode 100644 index 00000000..067b7d6b --- /dev/null +++ b/test/test_helpers/network/proxssh.py @@ -0,0 +1,86 @@ +import paramiko + + +class ProxySSH: + + def __init__(self, bastion_ip, server_ip=None, timeout=60): + if server_ip is None: + server_ip = bastion_ip + + self.server_ip = server_ip + self.connect_timeout = timeout + + if bastion_ip == server_ip: + self.bastion_ip = None + else: + self.bastion_ip = bastion_ip + + self._bastion_client = None + self._server_client = None + + def open_client(self): + server_client = paramiko.SSHClient() + server_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + if self.bastion_ip is None: + self._bastion_client = None + server_client.connect(self.server_ip, + username='opc', + timeout=self.connect_timeout) + else: + bastion_client = paramiko.SSHClient() + bastion_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + bastion_client.connect(self.bastion_ip, + username='opc', + timeout=self.connect_timeout) + self._bastion_client = bastion_client + + bastion_clienttransport = bastion_client.get_transport() + bastion_clientchannel = bastion_clienttransport.open_channel("direct-tcpip", + (self.server_ip, 22), + (self.bastion_ip, 22)) + + server_client.connect(self.server_ip, + username='opc', + timeout=self.connect_timeout, + sock=bastion_clientchannel) + + self._server_client = server_client + return server_client + + @property + def server_client(self): + if self._server_client is None: + self.open_client() + return self._server_client + + def close(self): + if self._server_client is not None: + self._server_client.close() + self._server_client = None + if self._bastion_client is not None: + self._bastion_client.close() + self._bastion_client = None + + @property + def file_xfer(self): + return self.server_client.open_sftp() + + def exec_command(self, cmd, display=True): + if display: + print("===== Running on {} =======".format(self.server_ip)) + print(" {}".format(cmd)) + stdin, stdout, stderr = self.server_client.exec_command(cmd) + if display: + print("-------- output -----------") + stdout_return = stdout.read().decode('UTF-8') + if display: + print(stdout_return) + print("-------- errors -----------") + + print(stderr.read().decode("UTF-8")) + print("---------------------------") + return stdout_return + + def exec_command_no_print(self, cmd): + return self.exec_command(cmd, display=False) \ No newline at end of file diff --git a/test/test_helpers/oci.py b/test/test_helpers/oci.py new file mode 100644 index 00000000..5a2d1420 --- /dev/null +++ b/test/test_helpers/oci.py @@ -0,0 +1,15 @@ +import oci +import os + + +def get_test_config(): + conf = { + "user" : os.environ["TF_VAR_current_user_ocid"], + "tenancy" : os.environ["TF_VAR_tenancy_ocid"], + "fingerprint" : os.environ["TF_VAR_api_fingerprint"], + "key_file" : os.environ["TF_VAR_api_private_key_path"], + "region" : os.environ["TF_VAR_region"], + } + oci.config.validate_config(conf) + return conf + diff --git a/test/test_network.py b/test/test_network.py new file mode 100644 index 00000000..06bd2608 --- /dev/null +++ b/test/test_network.py @@ -0,0 +1,44 @@ +from pytest_terraform import terraform +import pytest + +from test_helpers.network.nettest import NetTest + +#unit tests for network module +@pytest.mark.unit +@terraform("network", scope="session") +def test_hub_internet(network): + bastion_ip = network.outputs['bastion_ip']['value'] + + n = NetTest(bastion_ip) + print(f"Checking SSH Connection to bastion {bastion_ip}") + assert n.check_ssh_connection() + +@pytest.mark.unit +def test_hub_to_spoke_subnet001_ping(network): + bastion_ip = network.outputs['bastion_ip']['value'] + private_test_node_ips = network.outputs['private_test_node_ips']['value'] + + n = NetTest(bastion_ip) + ip = private_test_node_ips[0] + print(f"Pinging {ip} from bastion {bastion_ip}") + assert n.ping_server(ip) + +@pytest.mark.unit +def test_hub_to_spoke_subnet002_ping(network): + bastion_ip = network.outputs['bastion_ip']['value'] + private_test_node_ips = network.outputs['private_test_node_ips']['value'] + + n = NetTest(bastion_ip) + ip = private_test_node_ips[1] + print(f"Pinging {ip} from bastion {bastion_ip}") + assert n.ping_server(ip) + +@pytest.mark.unit +def test_hub_to_spoke_subnet003_ping(network): + bastion_ip = network.outputs['bastion_ip']['value'] + private_test_node_ips = network.outputs['private_test_node_ips']['value'] + + n = NetTest(bastion_ip) + ip = private_test_node_ips[2] + print(f"Pinging {ip} from bastion {bastion_ip}") + assert n.ping_server(ip) diff --git a/test/test_osms.py b/test/test_osms.py new file mode 100755 index 00000000..22c9e0a6 --- /dev/null +++ b/test/test_osms.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +import oci +import sys +import pytest +from pytest_terraform import terraform + +from test_helpers.oci import get_test_config + + +def listAllManaged(compartmentId): + list_module_stream_profiles_on_managed_instance_response = osms_client.list_module_stream_profiles_on_managed_instance( + compartment_id=compartmentId + ) + return list_module_stream_profiles_on_managed_instance_response.data +def listAllManagedCompartment(compartmentId): + list_managed_instance_groups_response = osms_client.list_managed_instance_groups( + compartment_id=compartmentId + ) + return list_managed_instance_groups_response.data + +def list_dynamic_group(compartmentId): + list_dynamic_groups_response = identity_client.list_dynamic_groups( + compartment_id=compartmentId + ) + return list_dynamic_groups_response.data + +def find_dynamic_group_ocid (dg_data, dg_name): + + dg_name_data = [ dg for dg in dg_data if dg.name==dg_name][0] + if dg_name_data: + return dg_name_data.id + else: + print ("Not Found the Dynamic Group OCID") + sys.exit() + +def get_dynamic_info(dynamicId, identity_client): + get_dynamic_group_response = identity_client.get_dynamic_group( + + dynamic_group_id=dynamicId + ) + return get_dynamic_group_response.data + +def check_dg_lifecycle_state(dg_data, state): + if dg_data.lifecycle_state == state: + return True + else: + return False + +# TODO: Remove this `skip` to enable test once everything is working. +@pytest.mark.skip(reason="Waiting for Terraform test harness code to make this work.") +@pytest.mark.unit +@terraform("osms_detail", scope="session") +def test_osms_unit_test_case(osms_detail): + config = get_test_config() + osms_client = oci.os_management.OsManagementClient(config) + identity_client = oci.identity.IdentityClient(config) + dynamic_group_id = osms_detail.outputs["dynamic_group_detail"]['id'] + dynamic_group_name = osms_detail.outputs["dynamic_group_detail"]['name'] + dg_data = get_dynamic_info(dynamic_group_id, identity_client) + expected_state = "ACTIVE" + actual_state = dg_data.lifecycle_state + assert expected_state == actual_state + + diff --git a/test/test_security_bastion.py b/test/test_security_bastion.py new file mode 100644 index 00000000..c844bd86 --- /dev/null +++ b/test/test_security_bastion.py @@ -0,0 +1,78 @@ +from pytest_terraform import terraform +import pytest +import oci + + +#from test_helpers.network.nettest import NetTest +from test_helpers.oci import get_test_config + +#unit tests for bastion portion of the security module +@pytest.mark.unit +@terraform("security_bastion", scope="session") +def test_bastion_create(security_bastion): + conf = get_test_config() + bastion_client = oci.bastion.BastionClient(conf) + + tf_bast = security_bastion["oci_bastion_bastion.bastion"] + bast_id = tf_bast['id'] + + # Did terraform output right id? + out_bast_id = security_bastion.outputs["bastion_id"]['value'] + assert bast_id == out_bast_id + + #can we get the bastion? + api_bast_resp = bastion_client.get_bastion(bastion_id=bast_id) + api_bast = api_bast_resp.data + + assert api_bast.id == bast_id + +@pytest.mark.unit +def test_bastion_active(security_bastion): + conf = get_test_config() + bastion_client = oci.bastion.BastionClient(conf) + + bast_id = security_bastion.outputs["bastion_id"]['value'] + + api_bast_resp = bastion_client.get_bastion(bastion_id=bast_id) + api_bast = api_bast_resp.data + + api_bast_resp = bastion_client.get_bastion(bastion_id=bast_id) + api_bast = api_bast_resp.data + + # is it active ? + assert api_bast.lifecycle_state == "ACTIVE" + +@pytest.mark.unit +def test_bastion_compartment(security_bastion): + conf = get_test_config() + bastion_client = oci.bastion.BastionClient(conf) + + bast_id = security_bastion.outputs["bastion_id"]['value'] + + api_bast_resp = bastion_client.get_bastion(bastion_id=bast_id) + api_bast = api_bast_resp.data + + api_bast_resp = bastion_client.get_bastion(bastion_id=bast_id) + api_bast = api_bast_resp.data + + # is it in the right compartment ? + sec_comp = security_bastion.outputs["security_compartment_id"]['value'] + assert api_bast.compartment_id == sec_comp + +@pytest.mark.unit +def test_bastion_subnet(security_bastion): + conf = get_test_config() + bastion_client = oci.bastion.BastionClient(conf) + + bast_id = security_bastion.outputs["bastion_id"]['value'] + + api_bast_resp = bastion_client.get_bastion(bastion_id=bast_id) + api_bast = api_bast_resp.data + + api_bast_resp = bastion_client.get_bastion(bastion_id=bast_id) + api_bast = api_bast_resp.data + + # is it on the right subnet? + subnet_id = security_bastion.outputs["test_subnet_id"]['value'] + assert api_bast.target_subnet_id == subnet_id + diff --git a/test/test_security_cloudguard.py b/test/test_security_cloudguard.py new file mode 100644 index 00000000..b3fbf063 --- /dev/null +++ b/test/test_security_cloudguard.py @@ -0,0 +1,79 @@ +from pytest_terraform import terraform +import pytest +import oci + + +from test_helpers.oci import get_test_config + +#unit tests for cloudguard portion of the security module +@pytest.mark.unit +@terraform("security_cloudguard", scope="session") +def test_cloudguard_target_created(security_cloudguard): + conf = get_test_config() + cloud_guard_client = oci.cloud_guard.CloudGuardClient(conf) + + env_comp_ocid = security_cloudguard.outputs["environment_compartment_id"]['value'] + cg_target = security_cloudguard['oci_cloud_guard_target.cloud_guard_target'] + + target = cloud_guard_client.get_target(target_id=cg_target['id']).data + + assert target.lifecycle_state == 'ACTIVE' + assert target.compartment_id == env_comp_ocid + assert target.target_resource_type == 'COMPARTMENT' + + +@pytest.mark.unit +def test_cloudguard_target_responder_recipe(security_cloudguard): + conf = get_test_config() + cloud_guard_client = oci.cloud_guard.CloudGuardClient(conf) + + cg_target = security_cloudguard['oci_cloud_guard_target.cloud_guard_target'] + + target = cloud_guard_client.get_target(target_id=cg_target['id']).data + found = False + for trr in target.target_responder_recipes: + if trr.display_name == 'OCI Responder Recipe' and trr.owner == "ORACLE": + found = True + assert found + +@pytest.mark.unit +def test_cloudguard_target_config_detector_recipe(security_cloudguard): + conf = get_test_config() + cloud_guard_client = oci.cloud_guard.CloudGuardClient(conf) + + cg_target = security_cloudguard['oci_cloud_guard_target.cloud_guard_target'] + + target = cloud_guard_client.get_target(target_id=cg_target['id']).data + found = False + for tdr in target.target_detector_recipes: + if tdr.display_name == 'OCI Configuration Detector Recipe' and tdr.owner == "ORACLE": + found = True + assert found + +@pytest.mark.unit +def test_cloudguard_target_threat_detector_recipe(security_cloudguard): + conf = get_test_config() + cloud_guard_client = oci.cloud_guard.CloudGuardClient(conf) + + cg_target = security_cloudguard['oci_cloud_guard_target.cloud_guard_target'] + + target = cloud_guard_client.get_target(target_id=cg_target['id']).data + found = False + for tdr in target.target_detector_recipes: + if tdr.display_name == 'OCI Threat Detector Recipe' and tdr.owner == "ORACLE": + found = True + assert found + +@pytest.mark.unit +def test_cloudguard_target_activity_detector_recipe(security_cloudguard): + conf = get_test_config() + cloud_guard_client = oci.cloud_guard.CloudGuardClient(conf) + + cg_target = security_cloudguard['oci_cloud_guard_target.cloud_guard_target'] + + target = cloud_guard_client.get_target(target_id=cg_target['id']).data + found = False + for tdr in target.target_detector_recipes: + if tdr.display_name == 'OCI Activity Detector Recipe' and tdr.owner == "ORACLE": + found = True + assert found diff --git a/test/test_security_vault.py b/test/test_security_vault.py new file mode 100644 index 00000000..0a8e666b --- /dev/null +++ b/test/test_security_vault.py @@ -0,0 +1,27 @@ +from pytest_terraform import terraform +import pytest +import oci + + +from test_helpers.oci import get_test_config + +#unit tests for vault/key portion of the security module +@pytest.mark.skip(reason="Skipped until we can better deal with vault cleanup. ") +@pytest.mark.unit +@terraform("security_vault", scope="session") +def test_master_encryption_key_created(security_vault): + conf = get_test_config() + #oci.key_management.KmsVaultClient(conf) + + vault = security_vault["oci_kms_vault.vault"] + mgmt_url = vault["management_endpoint"] + + assert key_id is not None + + key_client = oci.key_management.KmsManagementClient(conf, mgmt_url) + key_id = security_vault.outputs["key_id"] + k = key_client.get_key(key_id).data + kv = key_client.get_key_version(key_id, k["current_key_version"]).data + + assert kv['lifecycle_state'] == "ACTIVE" + diff --git a/test/test_vars.example b/test/test_vars.example new file mode 100644 index 00000000..f7540d8c --- /dev/null +++ b/test/test_vars.example @@ -0,0 +1,13 @@ + +# To run tests manually, you should edit and _source_ this file. + +# Change if using different region. +export TF_VAR_region="us-ashburn-1" + +export TF_VAR_tenancy_ocid="... your tenancy OCID ..." +export TF_VAR_current_user_ocid="... your user OCID ... " +export TF_VAR_api_fingerprint="... your OCI API key fingerprint ... " +export TF_VAR_api_private_key_path="... location of your OCI API key file ... " + +# Change if your ssh pubkey has a different filenane. +export TF_VAR_ssh_public_key_list="[\"$(cat ~/.ssh/id_rsa.pub)\"]"