diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..88cb251 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,30 @@ +# EditorConfig is awesome: http://EditorConfig.org +# Uses editorconfig to maintain consistent coding styles + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +max_line_length = 80 +trim_trailing_whitespace = true + +[*.{tf,tfvars}] +indent_size = 2 +indent_style = space + +[*.md] +max_line_length = 0 +trim_trailing_whitespace = false + +[Makefile] +tab_width = 2 +indent_style = tab + +[COMMIT_EDITMSG] +max_line_length = 0 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ffe75e0..70a33a6 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,17 +1,10 @@ # Use this file to define individuals or teams that are responsible for code in a repository. # Read more: # -# Order is important: the last matching pattern takes the most precedence +# Order is important: the last matching pattern has the highest precedence # These owners will be the default owners for everything -* @clouddrove/engineering @clouddrove/contributors +* @clouddrove/approvers @clouddrove/contributors -# Cloud Posse must review any changes to Makefiles -**/Makefile @clouddrove/engineering -**/Makefile.* @clouddrove/engineering - -# Cloud Posse must review any changes to GitHub actions -.github/* @clouddrove/engineering - -# Cloud Posse must review any changes to standard context definition -**/context.tf @clouddrove/engineering +# Admins must review all changes to CODEOWNERS or the mergify configuration +.github/CODEOWNERS @anmolnagpal diff --git a/.github/auto-release.yml b/.github/auto-release.yml deleted file mode 100644 index b1e5c5c..0000000 --- a/.github/auto-release.yml +++ /dev/null @@ -1,38 +0,0 @@ -name-template: 'v$RESOLVED_VERSION' -tag-template: '$RESOLVED_VERSION' -version-template: '$MAJOR.$MINOR.$PATCH' -version-resolver: - major: - labels: - - 'major' - minor: - labels: - - 'minor' - - 'enhancement' - patch: - labels: - - 'patch' - - 'fix' - - 'bugfix' - - 'bug' - - 'hotfix' - default: 'minor' - -categories: - - title: '🚀 Enhancements' - labels: - - 'enhancement' - - title: '🐛 Bug Fixes' - labels: - - 'fix' - - 'bugfix' - - 'bug' - - 'hotfix' - -change-template: | -
- $TITLE @$AUTHOR (#$NUMBER) - $BODY -
-template: | - $CHANGES diff --git a/.github/workflows/ansible.yml b/.github/workflows/ansible.yml deleted file mode 100644 index fb71ebf..0000000 --- a/.github/workflows/ansible.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: 'Ansible deploy' -on: - workflow_dispatch: - inputs: - filename: - description: 'Please enter ansible filename [deployment.yml]' - required: true - default: 'deployment.yml' - tags: - description: 'Please enter tagname [basic, nginx]' - required: true - default: 'basic' - -jobs: - anisble-deploy: - name: 'Ansible Deploy' - runs-on: ubuntu-latest - steps: - - name: 'Checkout' - uses: actions/checkout@master - - - name: Creating .ssh folder and permitting it with 777 - run: | - sudo mkdir -p /home/runner/.ssh - cd /home/runner && sudo ls -a - sudo chmod 777 /home/runner/.ssh - cd /home/runner - pwd - cd /home/runner/.ssh && touch id_rsa - sudo chmod 777 id_rsa - - name: Copy the key data from secrets to id_rsa file - run: | - cd /home/runner/.ssh - echo "${{secrets.PEM_KEY}}" > id_rsa - cat id_rsa && sudo chmod 600 /home/runner/.ssh/id_rsa - - name: check ansible connectivity - run: ansible all -m ping - - name: fetch ansible roles - run: make ansible-galaxy - - name: Ansible deployment for ${{ github.event.inputs.filename }} - id: ansible - run: | - cd deployment/ - ansible-playbook ${{ github.event.inputs.filename }} --tags=${{ github.event.inputs.tags }} \ No newline at end of file diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml deleted file mode 100644 index 7e789da..0000000 --- a/.github/workflows/auto-release.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: auto-release - -on: - push: - branches: - - master - -jobs: - semver: - runs-on: ubuntu-latest - steps: - # Drafts your next Release notes as Pull Requests are merged into "master" - - uses: release-drafter/release-drafter@v5 - with: - publish: true - prerelease: false - config-name: auto-release.yml - env: - GITHUB_TOKEN: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 9608007..0000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: 'Terraform manual deploy' -on: - workflow_dispatch: - inputs: - environment: - description: 'Please enter environment [dev,ops,prod]' - required: true - default: 'dev' - region: - description: 'Please enter region [ca-central-1, eu-west-1] ' - required: true - default: 'ca-central-1' - workspace: - description: 'Please enter workspace [base, common]' - required: true - default: 'common' - -jobs: - terraform-deploy: - name: 'Terraform- Deploy (Apply)' - runs-on: ubuntu-latest - steps: - - name: 'Checkout' - uses: actions/checkout@master - - - name: 'Terraform apply' - run: | - cd terraform/_tools - unset AWS_ACCESS_KEY_ID && unset AWS_SECRET_ACCESS_KEY && unset AWS_DEFAULT_REGION - export AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY }} && export AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} - sudo chmod +x apply.sh - ./apply.sh ${{ github.event.inputs.environment }} ${{ github.event.inputs.region }} ${{ github.event.inputs.workspace }} ${{ secrets.ROLE_ARN }} \ No newline at end of file diff --git a/.github/workflows/readme.yml b/.github/workflows/readme.yml new file mode 100644 index 0000000..083c63e --- /dev/null +++ b/.github/workflows/readme.yml @@ -0,0 +1,54 @@ +name: 'Create README.md file' +on: + push: + branches: + - master + +jobs: + readme-create: + name: 'readme-create' + runs-on: ubuntu-latest + steps: + - name: 'Checkout' + uses: actions/checkout@master + + - name: 'Set up Python 3.7' + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: 'create readme' + uses: 'clouddrove/github-actions@v9.0.1' + with: + actions_subcommand: 'readme' + github_token: '${{ secrets.GITHUB }}' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + + - name: 'pre-commit check errors' + uses: pre-commit/action@v2.0.0 + continue-on-error: true + + - name: 'pre-commit fix erros' + uses: pre-commit/action@v2.0.0 + continue-on-error: true + + - name: 'push readme' + uses: 'clouddrove/github-actions@v9.0.1' + continue-on-error: true + with: + actions_subcommand: 'push' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: 'Slack Notification' + uses: clouddrove/action-slack@v2 + with: + status: ${{ job.status }} + fields: repo,author + author_name: 'CloudDrove' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # required + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_TERRAFORM }} # required + if: always() diff --git a/.github/workflows/semantic-releaser.yml b/.github/workflows/semantic-releaser.yml new file mode 100644 index 0000000..6e685a0 --- /dev/null +++ b/.github/workflows/semantic-releaser.yml @@ -0,0 +1,30 @@ +name: Release + +on: + push: + branches: + - main + paths: + - '**.tf' + - '!examples/**.tf' + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: 14 + + - name: Release + env: + GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} + run: npx semantic-release diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml new file mode 100644 index 0000000..d65e3d7 --- /dev/null +++ b/.github/workflows/static-checks.yml @@ -0,0 +1,73 @@ +name: static-checks + +on: + pull_request: + +jobs: + versionExtract: + name: Get min/max versions + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Terraform min/max versions + id: minMax + uses: clowdhaus/terraform-min-max@main + outputs: + minVersion: ${{ steps.minMax.outputs.minVersion }} + maxVersion: ${{ steps.minMax.outputs.maxVersion }} + + versionEvaluate: + name: Evaluate Terraform versions + runs-on: ubuntu-latest + needs: versionExtract + strategy: + fail-fast: false + matrix: + version: + - ${{ needs.versionExtract.outputs.minVersion }} + - ${{ needs.versionExtract.outputs.maxVersion }} + directory: + - _example/ + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install Terraform v${{ matrix.version }} + uses: hashicorp/setup-terraform@v1 + with: + terraform_version: ${{ matrix.version }} + + - name: Init & validate v${{ matrix.version }} + run: | + cd ${{ matrix.directory }} + terraform init + terraform validate + - name: tflint + uses: reviewdog/action-tflint@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + working_directory: ${{ matrix.directory }} + fail_on_error: 'true' + filter_mode: 'nofilter' + flags: '--module' + + format: + name: Check code format + runs-on: ubuntu-latest + needs: versionExtract + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install Terraform v${{ needs.versionExtract.outputs.maxVersion }} + uses: hashicorp/setup-terraform@v1 + with: + terraform_version: ${{ needs.versionExtract.outputs.maxVersion }} + + - name: Check Terraform format changes + run: terraform fmt --recursive -check=true diff --git a/.github/workflows/terraform.yml b/.github/workflows/terraform.yml deleted file mode 100644 index eaa4802..0000000 --- a/.github/workflows/terraform.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: 'Terraform manual plan' -on: - workflow_dispatch: - inputs: - environment: - description: 'Please enter environment [dev,ops,prod]' - required: true - default: 'dev' - region: - description: 'Please enter region [ca-central-1, eu-west-1]' - required: true - default: 'ca-central-1' - workspace: - description: 'Please enter workspace [base, common]' - required: true - default: 'common' - -jobs: - terraform-pull-request: - name: 'Terraform- Fmt, Init, validate and Plan' - runs-on: ubuntu-latest - steps: - - name: 'Checkout' - uses: actions/checkout@master - - - name: 'Install dependancies' - run: | - sudo apt-get install jq awscli -y - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'" - - name: 'Terraform Format fmt' - run: | - cd terraform/${{ github.event.inputs.region }}/${{ github.event.inputs.workspace }} - terraform fmt --diff - - - name: 'Terraform validate' - run: | - cd terraform/_tools - sudo chmod +x validate.sh - unset AWS_ACCESS_KEY_ID && unset AWS_SECRET_ACCESS_KEY && unset AWS_DEFAULT_REGION - export AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY }} && export AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} - ./validate.sh ${{ github.event.inputs.environment }} ${{ github.event.inputs.region }} ${{ github.event.inputs.workspace }} ${{ secrets.ROLE_ARN }} - - - name: 'Infra Cost' - run: | - cd terraform/_tools - sudo chmod +x infracost.sh - curl -s -L https://github.com/infracost/infracost/releases/latest/download/infracost-linux-amd64.tar.gz | tar xz -C /tmp - sudo mv /tmp/infracost-linux-amd64 /usr/local/bin/infracost - export INFRACOST_API_KEY=${{ secrets.INFRACOST_API_KEY }} - unset AWS_ACCESS_KEY_ID && unset AWS_SECRET_ACCESS_KEY && unset AWS_DEFAULT_REGION - export AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY }} && export AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} - ./infracost.sh ${{ github.event.inputs.environment }} ${{ github.event.inputs.region }} ${{ github.event.inputs.workspace }} ${{ secrets.ROLE_ARN }} - - - name: 'Terraform plan' - run: | - cd terraform/_tools - sudo chmod +x plan.sh - unset AWS_ACCESS_KEY_ID && unset AWS_SECRET_ACCESS_KEY && unset AWS_DEFAULT_REGION - export AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY }} && export AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} - ./plan.sh ${{ github.event.inputs.environment }} ${{ github.event.inputs.region }} ${{ github.event.inputs.workspace }} ${{ secrets.ROLE_ARN }} $PLAN $JSON_PLAN_FILE ${convert_report} - env: - PLAN: plan.tfplan - JSON_PLAN_FILE: tfplan.json \ No newline at end of file diff --git a/.gitignore b/.gitignore index 785a42c..1813948 100644 --- a/.gitignore +++ b/.gitignore @@ -1,202 +1,41 @@ -### Linux template -*~ +# Local .terraform directories +**/.terraform/* -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* +# .tfstate files +*.tfstate +*.tfstate.* -# KDE directory preferences -.directory +# Crash log files +crash.log -# Linux trash folder which might appear on any partition or disk -.Trash-* +# Ignore any .tfvars files that are generated automatically for each Terraform run. Most +# .tfvars files are managed as part of configuration and so should be included in +# version control. +# +# example.tfvars -# .nfs files are created when an open file is removed but is still being accessed -.nfs* -### Eclipse template +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json +# Include override files you do wish to add to version control using negated pattern +# +# !example_override.tf -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.settings/ -.loadpath -.recommenders +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* -# External tool builders -.externalToolBuilders/ -# Locally stored "Eclipse launch configurations" -*.launch -# PyDev specific (Python IDE for Eclipse) -*.pydevproject -# CDT-specific (C/C++ Development Tooling) -.cproject - -# Java annotation processor (APT) -.factorypath - -# PDT-specific (PHP Development Tools) -.buildpath - -# sbteclipse plugin -.target - -# Tern plugin -.tern-project - -# TeXlipse plugin -.texlipse - -# STS (Spring Tool Suite) -.springBeans - -# Code Recommenders -.recommenders/ - -# Scala IDE specific (Scala & Java development for Eclipse) -.cache-main -.scala_dependencies -.worksheet -### Windows template -# Windows thumbnail cache files -Thumbs.db -ehthumbs.db -ehthumbs_vista.db - -# Dump file -*.stackdump - -# Folder config file -[Dd]esktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk -### Ansible template -*.retry -### macOS template -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk -### Archives template -# It's better to unpack these files and commit the raw source because -# git has its own built in compression methods. -*.7z -*.jar -*.rar -*.zip -*.gz -*.tgz -*.bzip -*.bz2 -*.xz -*.lzma -*.cab - -# Packing-only formats -*.iso -*.tar - -# Package management formats -*.dmg -*.xpi -*.gem -*.egg -*.deb -*.rpm -*.msi -*.msm -*.msp -### JetBrains template -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -/.idea/ -# User-specific stuff: -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/dictionaries - -# Sensitive or high-churn files: -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.xml -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml - -# Gradle: -.idea/**/gradle.xml -.idea/**/libraries - -# CMake -cmake-build-debug/ - -# Mongo Explorer plugin: -.idea/**/mongoSettings.xml - -## File-based project format: -*.iws - -## Plugin-specific files: - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ -# User-specific stuff: -.idea/* -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# CloudDrove stuff: -deployment/_logs/ansible-log.json -deployment/_logs/facts/* -deployment/_logs/retry/* -ansible-log.json +# ignored files +*.tfstate +*.tfstate.backup .terraform -deployment/roles/* -!deployment/roles/requirements.yml -.genie \ No newline at end of file +.idea +*.iml +_example/.terraform.tfstate.lock.info +.terraform.lock.hcl diff --git a/.meta b/.meta deleted file mode 100644 index ada179a..0000000 --- a/.meta +++ /dev/null @@ -1,5 +0,0 @@ -{ - "projects": { - ".genie": "git@github.com:clouddrove/genie.git" - } -} \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6db03ac..9e713a5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,23 +1,21 @@ repos: -- repo: git://github.com/antonbabenko/pre-commit-terraform - rev: v1.45.0 # Use the ref you want to point at - hooks: - - id: terraform_fmt - - id: terraform_validate -- repo: git://github.com/pre-commit/pre-commit-hooks - rev: v3.4.0 # Use the ref you want to point at - hooks: - - id: end-of-file-fixer - - id: trailing-whitespace - - id: mixed-line-ending - - id: check-byte-order-marker - - id: check-executables-have-shebangs - - id: check-merge-conflict - - id: debug-statements - - id: check-yaml - - id: check-added-large-files -- repo: https://github.com/ansible/ansible-lint.git - rev: v5.0.0a0 - hooks: - - id: ansible-lint - files: \.(yaml|yml)$ + + - repo: https://github.com/gruntwork-io/pre-commit + rev: v0.1.12 # Get the latest from: https://github.com/gruntwork-io/pre-commit/releases + hooks: + - id: terraform-fmt + - id: shellcheck + - id: tflint + + - repo: git://github.com/pre-commit/pre-commit-hooks + rev: v4.0.1 # Use the ref you want to point at + hooks: + - id: end-of-file-fixer + - id: trailing-whitespace + - id: mixed-line-ending + - id: check-byte-order-marker + - id: check-executables-have-shebangs + - id: check-merge-conflict + - id: debug-statements + - id: check-yaml + - id: check-added-large-files diff --git a/.releaserc.json b/.releaserc.json new file mode 100644 index 0000000..548e644 --- /dev/null +++ b/.releaserc.json @@ -0,0 +1,10 @@ +{ + "branches": [ + "main" + ], + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + "@semantic-release/github" + ] +} diff --git a/LICENSE b/LICENSE index da19d2f..9579323 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,201 @@ -MIT License - -Copyright (c) 2021 CloudDrove Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall 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. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2021 CloudDrove Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Makefile b/Makefile index a2c6d35..18e2f51 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,2 @@ -export GENIE_PATH ?= $(shell 'pwd')/.genie -export client ?= "client" +export GENIE_PATH ?= $(shell 'pwd')/../../../genie include $(GENIE_PATH)/Makefile \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 86f9d7a..0000000 --- a/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# reference-architectures - -This is our base repo structure to help set up actual client infra as code structure for deploy terraform, ansible and other. - -## How to set up client repo - -Through our internal Genie tool we can easily make client repo - -```hcl -make wrapper project="client-name" -``` -## How to set up terraform github action - -For run github action we have to change some values and save secret in repo - -- Change profile name in all .sh files in _tools folder, it's an optional -- Save secret 'ROLE_ARN' in repo secret, In this we have to save switch role arn to connect with AWS account - -## How to set up ansible github action - -For run ansible github action need to add secret in repo - -- Save secret 'PEM_KEY' in repo secret, In this we have to save our ssh key to connect to server via ansible - -## How to run github action - -For run github action go to Actions tab in github and follow below steps - -- Select workflow which you want to execute -- After that choose options and run manually job - -**Note:** Please run "Terraform Manual Plan" job first to verify, once verification done after thar run "Terraform Manual Deploy" Job. diff --git a/README.yaml b/README.yaml new file mode 100644 index 0000000..edb864a --- /dev/null +++ b/README.yaml @@ -0,0 +1,69 @@ +--- +# +# This is the canonical configuration for the `README.md` +# Run `make readme` to rebuild the `README.md` +# + + +# Name of this project +name: Terraform AZURE NETWORK SECURITY GROUP + +# License of this project +license: "APACHE" + +# Canonical GitHub repo +github_repo: clouddrove/terraform-azure-network-security-group + +# Badges to display +badges: + - name: "Terraform" + image: "https://img.shields.io/badge/Terraform-v1.0.0-green" + url: "https://www.terraform.io" + - name: "Licence" + image: "https://img.shields.io/badge/License-APACHE-blue.svg" + url: "LICENSE" + +# description of this project +description: |- + Terraform module to create NETWORK SECURITY GROUP resource on AZURE. + +# extra content +include: + - "terraform.md" + +# How to use this project +# yamllint disable rule:line-length +usage: |- + ### Simple Example + Here is an example of how you can use this module in your inventory structure: + ```hcl + module "security_group" { + source = "clouddrove/network-security-group/azure" + version = "1.0.0" + name = "example" + environment = "test" + label_order = ["name","environment"] + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + custom_port = [{ + name = "ssh" + protocol = "Tcp" + source_port_range = "*" + destination_port_ranges = ["22"] + source_address_prefixes = ["67.23.123.234/32"] + destination_address_prefixes = ["0.0.0.0/0"] + access = "Allow" + priority = 1002 + }, + { + name = "http-https" + protocol = "Tcp" + source_port_range = "*" + destination_port_ranges = ["80","443"] + source_address_prefixes = ["0.0.0.0/0"] + destination_address_prefixes = ["0.0.0.0/0"] + access = "Allow" + priority = 1003 + }] + } + ``` diff --git a/_docs/.gitkeep b/_docs/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/_example/README.md b/_example/README.md new file mode 100644 index 0000000..6a83ed9 --- /dev/null +++ b/_example/README.md @@ -0,0 +1,15 @@ +# Network-security-group example + +The root folder of this repo shows an example of how to create a network-security-group module, and create new Network-security-group resource. + +After this example you should have a new resource group. + +## How do you run this example? + +To run this example, apply the Terraform templates: + +1. Install [Terraform](https://www.terraform.io/), minimum version: `1.0.0`. +1. Set the environment variables specified at the top of the file, and fill in any other variables + that don't have a default. +1. Run `terraform init`. +1. Run `terraform apply`. diff --git a/_example/example.tf b/_example/example.tf new file mode 100644 index 0000000..fdfcb38 --- /dev/null +++ b/_example/example.tf @@ -0,0 +1,49 @@ +provider "azurerm" { + features {} +} + +module "resource_group" { + source = "clouddrove/resource-group/azure" + version = "1.0.0" + environment = "test" + label_order = ["name", "environment"] + + name = "example" + location = "North Europe" +} + +module "security_group" { + source = "../" + + ## Tags + name = "example" + environment = "test" + label_order = ["name", "environment"] + + ## Security Group + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + + ##Security Group rule for Custom port. + custom_port = [{ + name = "ssh" + protocol = "Tcp" + source_port_range = "*" + destination_port_ranges = ["22"] + source_address_prefixes = ["67.23.123.234/32"] + destination_address_prefixes = ["0.0.0.0/0"] + access = "Allow" + priority = 1002 + }, + { + name = "http-https" + protocol = "Tcp" + source_port_range = "*" + destination_port_ranges = ["80", "443"] + source_address_prefixes = ["0.0.0.0/0"] + destination_address_prefixes = ["0.0.0.0/0"] + access = "Allow" + priority = 1003 + } + ] +} diff --git a/_example/outputs.tf b/_example/outputs.tf new file mode 100644 index 0000000..79288db --- /dev/null +++ b/_example/outputs.tf @@ -0,0 +1,24 @@ +output "security_group_id" { + value = module.security_group.security_group_id + description = "The Name of the Network Security Group." +} + +output "security_group_name" { + value = module.security_group.security_group_name + description = "The Name of the Network Security Group." +} + +output "outbound_rule_name" { + value = module.security_group.outbound_rule_name + description = "The Name of the Outbound Network Security Rule." +} + +output "inbound_rule_name" { + value = module.security_group.inbound_custom_rule_name + description = "The Name of the Inbound Network Security Rule." +} + +output "tags" { + value = module.security_group.tags + description = "The tags associated to resources." +} diff --git a/app/docker/.gitkeep b/app/docker/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/k8s/charts/.gitkeep b/app/k8s/charts/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/k8s/kubectl/.gitkeep b/app/k8s/kubectl/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/packer/.gitkeep b/app/packer/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/deployment/_logs/.gitkeep b/deployment/_logs/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/deployment/_ssh/base/anmol.pub b/deployment/_ssh/base/anmol.pub deleted file mode 100644 index a6d1d8b..0000000 --- a/deployment/_ssh/base/anmol.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDWitszRT5hc+G9ZG6TFoBZabE2VzqtkvfsTubAjaocQ1JgQxFX1D+G39wKzHHn6xB8jafbdVViSYciqLyYocv5p/B2Bnzx6ztdz6WQZVd4lWMl9fsdxFL6Y79m5dG258pgREEZOQQB3OfG0uejmWRDusR5WwntXpWw4656GB7lI0vWDyaYfeccH802cISbQD0cCfEF3D929TS63xNrTtaIdoUnaSY8NwhcfE+2KBe9M7sqW5Co8+mO0shjgJiIC2mOAa0TKOuViw8pKDzxfy3ACKIjRtCJ/zZtDuCAsKkATg/15XZT742ULES+6582h7L2itYkj/8c3qAEeyQDrq3H \ No newline at end of file diff --git a/deployment/_ssh/base/nikita.pub b/deployment/_ssh/base/nikita.pub deleted file mode 100644 index 2e1c3a6..0000000 --- a/deployment/_ssh/base/nikita.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCyAc7Y0aDsLkkm8UrmXGb6068G+r3Q9PXtTs42tv1KoKxahY5vDo57RsPN+sQGPIVDclN6PbRm4c9guBwLBYFVQL4PvBOSYHrapXjbheebTQDQoyPV7SM7LK57J0BC8oEfcrTgCIdy9mIWAYFIeTWfj0Xw/c9thxNtSse9XTAH6e+Sucn0XNRwxzM2yOuXqiBWjU+bMDLfQ+QV6gd2k/ZXvURmg5uAzimLFi7kF0tDRd8PNw4i+mvBnJkvnBv0wf22s9meldRPZcIO6HfjbbDEk0Oyo66KI70034tVgvAN0mdq/1OwQez2xwRH548tnp7XMcQ9nqemlDkmZeM4gB6B \ No newline at end of file diff --git a/deployment/_ssh/dev/anmol.pub b/deployment/_ssh/dev/anmol.pub deleted file mode 100644 index a6d1d8b..0000000 --- a/deployment/_ssh/dev/anmol.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDWitszRT5hc+G9ZG6TFoBZabE2VzqtkvfsTubAjaocQ1JgQxFX1D+G39wKzHHn6xB8jafbdVViSYciqLyYocv5p/B2Bnzx6ztdz6WQZVd4lWMl9fsdxFL6Y79m5dG258pgREEZOQQB3OfG0uejmWRDusR5WwntXpWw4656GB7lI0vWDyaYfeccH802cISbQD0cCfEF3D929TS63xNrTtaIdoUnaSY8NwhcfE+2KBe9M7sqW5Co8+mO0shjgJiIC2mOAa0TKOuViw8pKDzxfy3ACKIjRtCJ/zZtDuCAsKkATg/15XZT742ULES+6582h7L2itYkj/8c3qAEeyQDrq3H \ No newline at end of file diff --git a/deployment/_ssh/dev/nikita.pub b/deployment/_ssh/dev/nikita.pub deleted file mode 100644 index 2e1c3a6..0000000 --- a/deployment/_ssh/dev/nikita.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCyAc7Y0aDsLkkm8UrmXGb6068G+r3Q9PXtTs42tv1KoKxahY5vDo57RsPN+sQGPIVDclN6PbRm4c9guBwLBYFVQL4PvBOSYHrapXjbheebTQDQoyPV7SM7LK57J0BC8oEfcrTgCIdy9mIWAYFIeTWfj0Xw/c9thxNtSse9XTAH6e+Sucn0XNRwxzM2yOuXqiBWjU+bMDLfQ+QV6gd2k/ZXvURmg5uAzimLFi7kF0tDRd8PNw4i+mvBnJkvnBv0wf22s9meldRPZcIO6HfjbbDEk0Oyo66KI70034tVgvAN0mdq/1OwQez2xwRH548tnp7XMcQ9nqemlDkmZeM4gB6B \ No newline at end of file diff --git a/deployment/_ssh/live/anmol.pub b/deployment/_ssh/live/anmol.pub deleted file mode 100644 index a6d1d8b..0000000 --- a/deployment/_ssh/live/anmol.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDWitszRT5hc+G9ZG6TFoBZabE2VzqtkvfsTubAjaocQ1JgQxFX1D+G39wKzHHn6xB8jafbdVViSYciqLyYocv5p/B2Bnzx6ztdz6WQZVd4lWMl9fsdxFL6Y79m5dG258pgREEZOQQB3OfG0uejmWRDusR5WwntXpWw4656GB7lI0vWDyaYfeccH802cISbQD0cCfEF3D929TS63xNrTtaIdoUnaSY8NwhcfE+2KBe9M7sqW5Co8+mO0shjgJiIC2mOAa0TKOuViw8pKDzxfy3ACKIjRtCJ/zZtDuCAsKkATg/15XZT742ULES+6582h7L2itYkj/8c3qAEeyQDrq3H \ No newline at end of file diff --git a/deployment/_ssh/live/nikita.pub b/deployment/_ssh/live/nikita.pub deleted file mode 100644 index 2e1c3a6..0000000 --- a/deployment/_ssh/live/nikita.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCyAc7Y0aDsLkkm8UrmXGb6068G+r3Q9PXtTs42tv1KoKxahY5vDo57RsPN+sQGPIVDclN6PbRm4c9guBwLBYFVQL4PvBOSYHrapXjbheebTQDQoyPV7SM7LK57J0BC8oEfcrTgCIdy9mIWAYFIeTWfj0Xw/c9thxNtSse9XTAH6e+Sucn0XNRwxzM2yOuXqiBWjU+bMDLfQ+QV6gd2k/ZXvURmg5uAzimLFi7kF0tDRd8PNw4i+mvBnJkvnBv0wf22s9meldRPZcIO6HfjbbDEk0Oyo66KI70034tVgvAN0mdq/1OwQez2xwRH548tnp7XMcQ9nqemlDkmZeM4gB6B \ No newline at end of file diff --git a/deployment/_ssh/web.ssh.config b/deployment/_ssh/web.ssh.config deleted file mode 100644 index e7520a1..0000000 --- a/deployment/_ssh/web.ssh.config +++ /dev/null @@ -1,43 +0,0 @@ -Host * -LogLevel QUIET -StrictHostKeyChecking no -UserKnownHostsFile /dev/null -ControlMaster auto -ControlPersist 10m -ControlPath ~/.ssh/instance_socket-%r@%h:%p -ForwardAgent yes - - -#Common -Host * -IdentityFile ~/.ssh/client/aws.pem - -#vpn -Host 0.0.0.0 -IdentityFile ~/.ssh/client/aws.pem - -# dmz-vpc-prv-ip -Host 10.1.* -ProxyCommand ssh -i ~/.ssh/client/dmz-main.pem -W %h:%p ubuntu@0.0.0.0 -User ubuntu -IdentityFile ~/.ssh/client/aws.pem - -#vpn -Host 0.0.0.0 -IdentityFile ~/.ssh/client/aws.pem - -# prod-vpc-prv-ip -Host 10.20.* -ProxyCommand ssh -i ~/.ssh/client/aws.pem -W %h:%p ubuntu@0.0.0.0 -User ubuntu -IdentityFile ~/.ssh/client/aws.pem - -#vpn -Host 0.0.0.0 -IdentityFile ~/.ssh/client/aws.pem - -# stage-vpc-prv-ip -Host 10.21.* -ProxyCommand ssh -i ~/.ssh/client/aws.pem -W %h:%p ubuntu@0.0.0.0 -User ubuntu -IdentityFile ~/.ssh/aws.pem diff --git a/deployment/_ssl/.gitkeep b/deployment/_ssl/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/deployment/ansible.cfg b/deployment/ansible.cfg deleted file mode 100644 index d7130f0..0000000 --- a/deployment/ansible.cfg +++ /dev/null @@ -1,204 +0,0 @@ -# config file for ansible -- https://ansible.com/ -# =============================================== - -# nearly all parameters can be overridden in ansible-playbook -# or with command line flags. ansible will read ANSIBLE_CONFIG, -# ansible.cfg in the current working directory, .ansible.cfg in -# the home directory or /etc/ansible/ansible.cfg, whichever it -# finds first - -[defaults] - -inventory = ./inventory/hosts.ini -transport = smart -forks = 50 -poll_interval = 15 - - -# smart - gather by default, but don't regather if already gathered -# implicit - gather by default, turn off with gather_facts: False -# explicit - do not gather by default, must say gather_facts: True -#gathering = implicit -gathering = smart - - - -# uncomment this to disable SSH key host checking -#host_key_checking = Falsenmol -host_key_checking = False - -# enable callback plugins, they can output to stdout but cannot be 'stdout' type. -#callback_whitelist = timer, mail -callback_whitelist = profile_tasks - - -# What flags to pass to sudo -# WARNING: leaving out the defaults might create unexpected behaviours -#sudo_flags = -H -S -n -sudo_flags = -H -S -n - -# SSH timeout -#timeout = 10 -timeout=20 - - -# logging is off by default unless this path is defined -# if so defined, consider logrotate -#log_path = /var/log/ansible.log -log_path=./_logs/ansible-log.json - - -# If set, configures the path to the Vault password file as an alternative to -# specifying --vault-password-file on the command line. -#vault_password_file = /path/to/vault_password_file - -# If set, configures the path to the Vault password file as an alternative to -# specifying --vault-password-file on the command line. -#vault_password_file = /path/to/vault_password_file - -# format of string {{ ansible_managed }} available within Jinja2 -# templates indicates to users editing templates files will be replaced. -# replacing {file}, {host} and {uid} and strftime codes with proper values. -#ansible_managed = Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host} -# {file}, {host}, {uid}, and the timestamp can all interfere with idempotence -# in some situations so the default is a static string: -#ansible_managed = Ansible managed -ansible_managed = Ansible managed: This file. is managed by CloudDrove Inc. Please do not change this file manually, else next deployment will overright it. - -# by default callbacks are not loaded for /bin/ansible, enable this if you -# want, for example, a notification or logging callback to also apply to -# /bin/ansible runs -#bin_ansible_callbacks = False -bin_ansible_callbacks = True - -# don't like colors either? -# set to 1 if you don't want colors, or export ANSIBLE_NOCOLOR=1 -#nocolor = 1 -force_color = 1 - -# if set to a persistent type (not 'memory', for example 'redis') fact values -# from previous runs in Ansible will be stored. This may be useful when -# wanting to use, for example, IP information from one group of servers -# without having to talk to them in the same playbook run to get their -# current IP information. -#fact_caching = memory - -fact_caching = jsonfile -fact_caching_connection = ./_logs/facts/ -fact_caching_timeout = 10000 - - -# retry files -# When a playbook fails by default a .retry file will be created in ~/ -# You can disable this feature by setting retry_files_enabled to False -# and you can change the location of the files by setting retry_files_save_path -#retry_files_enabled = False -#retry_files_save_path = ~/.ansible-retry -retry_files_enabled = True -retry_files_save_path = ./_logs/retry/ - - -# squash actions -# Ansible can optimise actions that call modules with list parameters -# when looping. Instead of calling the module once per with_ item, the -# module is called once with all items at once. Currently this only works -# under limited circumstances, and only with parameters named 'name'. -#squash_actions = apk,apt,dnf,homebrew,pacman,pkgng,yum,zypper -squash_actions = apk,apt,dnf,homebrew,pacman,pkgng,yum,zypper,template,file,copy - -# controls the compression level of variables sent to -# worker processes. At the default of 0, no compression -# is used. This value must be an integer from 0 to 9. -#var_compression_level = 9 -var_compression_level = 0 - -# controls what compression method is used for new-style ansible modules when -# they are sent to the remote system. The compression types depend on having -# support compiled into both the controller's python and the client's python. -# The names should match with the python Zipfile compression types: -# * ZIP_STORED (no compression. available everywhere) -# * ZIP_DEFLATED (uses zlib, the default) -# These values may be set per host via the ansible_module_compression inventory -# variable -#module_compression = 'ZIP_DEFLATED' -module_compression = 'ZIP_DEFLATED' - -# This controls how ansible handles multiple --tags and --skip-tags arguments -# on the CLI. If this is True then multiple arguments are merged together. If -# it is False, then the last specified argument is used and the others are ignored. -# This option will be removed in 2.8. -#merge_multiple_cli_flags = True - -# Controls showing custom stats at the end, off by default -#show_custom_stats = True -show_custom_stats = True - -[ssh_connection] - -# ssh arguments to use -# Leaving off ControlPersist will result in poor performance, so use -# paramiko on older platforms rather than removing it, -C controls compression use -#ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s -ssh_args = -C -F _ssh/web.ssh.config -q - - -[paramiko_connection] - -# uncomment this line to cause the paramiko connection plugin to not record new host -# keys encountered. Increases performance on new host additions. Setting works independently of the -# host key checking setting above. -record_host_keys=False - -# by default, Ansible requests a pseudo-terminal for commands executed under sudo. Uncomment this -# line to disable this behaviour. -pty=False - -# When using persistent connections with Paramiko, the connection runs in a -# background process. If the host doesn't already have a valid SSH key, by -# default Ansible will prompt to add the host key. This will cause connections -# running in background processes to fail. Uncomment this line to have -# Paramiko automatically add host keys. -host_key_auto_add = True - -# The path to use for the ControlPath sockets. This defaults to a hashed string of the hostname, -# port and username (empty string in the config). The hash mitigates a common problem users -# found with long hostames and the conventional %(directory)s/ansible-ssh-%%h-%%p-%%r format. -# In those cases, a "too long for Unix domain socket" ssh error would occur. -# -# Example: -# control_path = %(directory)s/%%h-%%r -control_path = %(directory)s/%%h-%%r - -# Enabling pipelining reduces the number of SSH operations required to -# execute a module on the remote server. This can result in a significant -# performance improvement when enabled, however when using "sudo:" you must -# first disable 'requiretty' in /etc/sudoers -# -# By default, this option is disabled to preserve compatibility with -# sudoers configurations that have requiretty (the default on many distros). -# -#pipelining = False -pipelining = True - -# Control the mechanism for transferring files (old) -# * smart = try sftp and then try scp [default] -# * True = use scp only -# * False = use sftp only -scp_if_ssh = smart - -# Control the mechanism for transferring files (new) -# If set, this will override the scp_if_ssh option -# * sftp = use sftp to transfer files -# * scp = use scp to transfer files -# * piped = use 'dd' over SSH to transfer files -# * smart = try sftp, scp, and piped, in that order [default] -transfer_method = smart - -[persistent_connection] - -# Configures the persistent connection timeout value in seconds. This value is -# how long the persistent connection will remain idle before it is destroyed. -# If the connection doesn't receive a request before the timeout value -# expires, the connection is shutdown. The default value is 30 seconds. -#connect_timeout = 30 -connect_timeout = 30 diff --git a/deployment/group_vars/all/global.yml b/deployment/group_vars/all/global.yml deleted file mode 100644 index e69de29..0000000 diff --git a/deployment/inventory/hosts.ini b/deployment/inventory/hosts.ini deleted file mode 100644 index e69de29..0000000 diff --git a/deployment/roles/.gitkeep b/deployment/roles/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/deployment/roles/requirements.yml b/deployment/roles/requirements.yml deleted file mode 100644 index 0b68d48..0000000 --- a/deployment/roles/requirements.yml +++ /dev/null @@ -1,3 +0,0 @@ -#From Ansible Galaxy -- src: clouddrove.ansible_role_common - name: common \ No newline at end of file diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..de36580 --- /dev/null +++ b/main.tf @@ -0,0 +1,87 @@ +## Managed By : CloudDrove +## Copyright @ CloudDrove. All Right Reserved. + +#Module : labels +#Description : Terraform module to create consistent naming for multiple names. +module "labels" { + source = "clouddrove/labels/azure" + version = "1.0.0" + + name = var.name + environment = var.environment + managedby = var.managedby + label_order = var.label_order + repository = var.repository +} + +locals { + custom_port = var.enabled && length(var.custom_port) > 0 ? { for cp in flatten(var.custom_port) : cp.name => cp } : {} +} + +#Module : SECURITY GROUP +#Description : Terraform resource for security group. +resource "azurerm_network_security_group" "default" { + count = var.enabled ? 1 : 0 + name = format("%s-%s-nsg", var.name, var.environment) + resource_group_name = var.resource_group_name + location = var.location + tags = module.labels.tags + timeouts { + create = var.create + update = var.update + read = var.read + delete = var.delete + } +} + +#Module : SECURITY GROUP RULE FOR EGRESS +#Description : Provides a security group rule resource. Represents a single egress +# group rule, which can be added to external Security Groups. +resource "azurerm_network_security_rule" "outbound" { + count = var.enabled ? 1 : 0 + name = format("%s-outbound-rule", module.labels.id) + resource_group_name = var.resource_group_name + network_security_group_name = join("", azurerm_network_security_group.default.*.name) + description = "Outbound traffic." + protocol = "*" + source_port_range = "*" + destination_port_range = "*" + source_address_prefix = "*" + source_application_security_group_ids = var.source_application_security_group_ids + destination_address_prefix = "*" + destination_application_security_group_ids = var.destination_application_security_group_ids + access = var.access + priority = var.priority + direction = "Outbound" + timeouts { + create = var.create + update = var.update + read = var.read + delete = var.delete + } +} + +resource "azurerm_network_security_rule" "inbound_custom" { + for_each = local.custom_port + name = format("%s-%s", module.labels.id, each.value.name) + resource_group_name = var.resource_group_name + network_security_group_name = join("", azurerm_network_security_group.default.*.name) + description = lookup(each.value, "description", "Inbound traffic") + protocol = lookup(each.value, "protocol", null) + source_port_range = lookup(each.value, "source_port_range", null) + destination_port_ranges = lookup(each.value, "destination_port_ranges", null) + source_address_prefixes = lookup(each.value, "source_address_prefixes", null) + source_application_security_group_ids = lookup(each.value, "source_application_security_group_ids", null) + destination_address_prefixes = lookup(each.value, "destination_address_prefixes", null) + destination_address_prefix = lookup(each.value, "destination_address_prefix", null) + destination_application_security_group_ids = lookup(each.value, "destination_application_security_group_ids", null) + access = lookup(each.value, "access", "Allow") + priority = lookup(each.value, "priority", null) + direction = lookup(each.value, "direction", "Inbound") + timeouts { + create = var.create + update = var.update + read = var.read + delete = var.delete + } +} diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..434a2f4 --- /dev/null +++ b/outputs.tf @@ -0,0 +1,24 @@ +output "security_group_id" { + value = join("", azurerm_network_security_group.default.*.id) + description = "The Name of the Network Security Group." +} + +output "security_group_name" { + value = join("", azurerm_network_security_group.default.*.name) + description = "The Name of the Network Security Group." +} + +output "outbound_rule_name" { + value = join("", azurerm_network_security_rule.outbound.*.name) + description = "The Name of the Outbound Network Security Rule." +} + +output "inbound_custom_rule_name" { + value = { for cp in flatten(var.custom_port) : cp.name => cp } + description = "The Name of the Inbound Network Security Rule." +} + +output "tags" { + value = module.labels.tags + description = "The tags associated to resources." +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..d34507c --- /dev/null +++ b/readme.md @@ -0,0 +1,2 @@ +# terraform-azure-security-group +Terraform module for Azure security group. diff --git a/terraform/README.md b/terraform/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/terraform/development/ca-central-1/applications/main.tf b/terraform/development/ca-central-1/applications/main.tf deleted file mode 100644 index e69de29..0000000 diff --git a/terraform/development/ca-central-1/applications/outputs.tf b/terraform/development/ca-central-1/applications/outputs.tf deleted file mode 100644 index e69de29..0000000 diff --git a/terraform/development/ca-central-1/applications/variables.tf b/terraform/development/ca-central-1/applications/variables.tf deleted file mode 100644 index e69de29..0000000 diff --git a/terraform/development/ca-central-1/networking/main.tf b/terraform/development/ca-central-1/networking/main.tf deleted file mode 100644 index 7126a76..0000000 --- a/terraform/development/ca-central-1/networking/main.tf +++ /dev/null @@ -1,59 +0,0 @@ -provider "aws" { - region = "ca-central-1" -} - -terraform { - backend "s3" { - bucket = "" - key = "ca-central-1/development/networking.tfstate" - region = "ca-central-1" - } -} - -module "s3_bucket" { - source = "clouddrove/s3/aws" - version = "0.14.0" - - bucket_enabled = true - versioning = true - - name = "logs" - environment = var.environment - label_order = var.label_order - - acl = "private" -} - -module "vpc" { - source = "clouddrove/vpc/aws" - version = "0.14.0" - - vpc_enabled = true - enable_flow_log = true - - name = "vpc" - environment = var.environment - label_order = var.label_order - - cidr_block = "10.10.0.0/16" - s3_bucket_arn = module.s3_bucket.arn -} - - -module "subnets" { - source = "clouddrove/subnet/aws" - version = "0.14.0" - - nat_gateway_enabled = true - - name = "subnets" - environment = var.environment - label_order = var.label_order - - availability_zones = ["ca-central-1a", "ca-central-1b", "ca-central-1c"] - vpc_id = module.vpc.vpc_id - type = "public-private" - igw_id = module.vpc.igw_id - cidr_block = module.vpc.vpc_cidr_block - ipv6_cidr_block = module.vpc.ipv6_cidr_block -} diff --git a/terraform/development/ca-central-1/networking/outputs.tf b/terraform/development/ca-central-1/networking/outputs.tf deleted file mode 100644 index e69de29..0000000 diff --git a/terraform/development/ca-central-1/networking/variables.tf b/terraform/development/ca-central-1/networking/variables.tf deleted file mode 100644 index 91e66b1..0000000 --- a/terraform/development/ca-central-1/networking/variables.tf +++ /dev/null @@ -1,9 +0,0 @@ -variable "label_order" { - description = "" - default = ["environment", "name"] -} - -variable "environment" { - description = "" - default = "development" -} diff --git a/terraform/production/ca-central-1/applications/main.tf b/terraform/production/ca-central-1/applications/main.tf deleted file mode 100644 index e69de29..0000000 diff --git a/terraform/production/ca-central-1/applications/outputs.tf b/terraform/production/ca-central-1/applications/outputs.tf deleted file mode 100644 index e69de29..0000000 diff --git a/terraform/production/ca-central-1/applications/variables.tf b/terraform/production/ca-central-1/applications/variables.tf deleted file mode 100644 index e69de29..0000000 diff --git a/terraform/production/ca-central-1/networking/main.tf b/terraform/production/ca-central-1/networking/main.tf deleted file mode 100644 index e77f03d..0000000 --- a/terraform/production/ca-central-1/networking/main.tf +++ /dev/null @@ -1,59 +0,0 @@ -provider "aws" { - region = "ca-central-1" -} - -terraform { - backend "s3" { - bucket = "" - key = "ca-central-1/production/networking.tfstate" - region = "ca-central-1" - } -} - -module "s3_bucket" { - source = "clouddrove/s3/aws" - version = "0.14.0" - - bucket_enabled = true - versioning = true - - name = "logs" - environment = var.environment - label_order = var.label_order - - acl = "private" -} - -module "vpc" { - source = "clouddrove/vpc/aws" - version = "0.14.0" - - vpc_enabled = true - enable_flow_log = true - - name = "vpc" - environment = var.environment - label_order = var.label_order - - cidr_block = "10.20.0.0/16" - s3_bucket_arn = module.s3_bucket.arn -} - - -module "subnets" { - source = "clouddrove/subnet/aws" - version = "0.14.0" - - nat_gateway_enabled = true - - name = "subnets" - environment = var.environment - label_order = var.label_order - - availability_zones = ["ca-central-1a", "ca-central-1b", "ca-central-1c"] - vpc_id = module.vpc.vpc_id - type = "public-private" - igw_id = module.vpc.igw_id - cidr_block = module.vpc.vpc_cidr_block - ipv6_cidr_block = module.vpc.ipv6_cidr_block -} diff --git a/terraform/production/ca-central-1/networking/outputs.tf b/terraform/production/ca-central-1/networking/outputs.tf deleted file mode 100644 index e69de29..0000000 diff --git a/terraform/production/ca-central-1/networking/variables.tf b/terraform/production/ca-central-1/networking/variables.tf deleted file mode 100644 index de49f97..0000000 --- a/terraform/production/ca-central-1/networking/variables.tf +++ /dev/null @@ -1,9 +0,0 @@ -variable "label_order" { - description = "" - default = ["environment", "name"] -} - -variable "environment" { - description = "" - default = "production" -} diff --git a/terraform/sandbox/ca-central-1/.gitkeep b/terraform/sandbox/ca-central-1/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/terraform/security/ca-central-1/main.tf b/terraform/security/ca-central-1/main.tf deleted file mode 100644 index b97e947..0000000 --- a/terraform/security/ca-central-1/main.tf +++ /dev/null @@ -1,11 +0,0 @@ -provider "aws" { - region = "ca-central-1" -} - -terraform { - backend "s3" { - bucket = "" - key = "ca-central-1/security.tfstate" - region = "ca-central-1" - } -} diff --git a/terraform/shared/ca-central-1/networking/main.tf b/terraform/shared/ca-central-1/networking/main.tf deleted file mode 100644 index 09f5fc3..0000000 --- a/terraform/shared/ca-central-1/networking/main.tf +++ /dev/null @@ -1,59 +0,0 @@ -provider "aws" { - region = "ca-central-1" -} - -terraform { - backend "s3" { - bucket = "" - key = "ca-central-1/shared/networking.tfstate" - region = "ca-central-1" - } -} - -module "s3_bucket" { - source = "clouddrove/s3/aws" - version = "0.14.0" - - bucket_enabled = true - versioning = true - - name = "logs" - environment = var.environment - label_order = var.label_order - - acl = "private" -} - -module "vpc" { - source = "clouddrove/vpc/aws" - version = "0.14.0" - - vpc_enabled = true - enable_flow_log = true - - name = "vpc" - environment = var.environment - label_order = var.label_order - - cidr_block = "10.0.0.0/16" - s3_bucket_arn = module.s3_bucket.arn -} - - -module "subnets" { - source = "clouddrove/subnet/aws" - version = "0.14.0" - - nat_gateway_enabled = true - - name = "subnets" - environment = var.environment - label_order = var.label_order - - availability_zones = ["ca-central-1a", "ca-central-1b", "ca-central-1c"] - vpc_id = module.vpc.vpc_id - type = "public-private" - igw_id = module.vpc.igw_id - cidr_block = module.vpc.vpc_cidr_block - ipv6_cidr_block = module.vpc.ipv6_cidr_block -} diff --git a/terraform/shared/ca-central-1/networking/outputs.tf b/terraform/shared/ca-central-1/networking/outputs.tf deleted file mode 100644 index e69de29..0000000 diff --git a/terraform/shared/ca-central-1/networking/variables.tf b/terraform/shared/ca-central-1/networking/variables.tf deleted file mode 100644 index a22a2a6..0000000 --- a/terraform/shared/ca-central-1/networking/variables.tf +++ /dev/null @@ -1,9 +0,0 @@ -variable "label_order" { - description = "" - default = ["environment", "name"] -} - -variable "environment" { - description = "" - default = "shared" -} diff --git a/terraform/shared/ca-central-1/vpn/main.tf b/terraform/shared/ca-central-1/vpn/main.tf deleted file mode 100644 index 6723154..0000000 --- a/terraform/shared/ca-central-1/vpn/main.tf +++ /dev/null @@ -1,155 +0,0 @@ -provider "aws" { - region = "ca-central-1" -} - -terraform { - backend "s3" { - bucket = "" - key = "ca-central-1/shared/vpn.tfstate" - region = "ca-central-1" - } -} - - -module "http-https" { - source = "clouddrove/security-group/aws" - version = "0.14.0" - - name = "http-https" - environment = var.environment - label_order = var.label_order - - vpc_id = var.vpc_id - allowed_ports = [80, 443] - allowed_ip = [var.allowed_ip_external] - -} - -module "ssh" { - source = "clouddrove/security-group/aws" - version = "0.14.0" - - name = "ssh" - environment = var.environment - label_order = var.label_order - - vpc_id = var.vpc_id - allowed_ip = [var.allowed_ip_internal] - allowed_ports = [22] -} - -module "kms" { - source = "clouddrove/kms/aws" - version = "0.14.0" - - name = "kms" - environment = var.environment - label_order = var.label_order - - enable_key_rotation = true - - description = "KMS key for vpn" - deletion_window_in_days = 7 - alias = "alias/vpn" - policy = data.aws_iam_policy_document.kms.json -} - -data "aws_iam_policy_document" "kms" { - version = "2012-10-17" - statement { - sid = "Enable IAM User Permissions" - effect = "Allow" - principals { - type = "AWS" - identifiers = ["*"] - } - actions = ["kms:*"] - resources = ["*"] - } - -} - - -module "iam-role" { - source = "clouddrove/iam-role/aws" - version = "0.14.0" - - name = "iam-role" - environment = var.environment - label_order = var.label_order - assume_role_policy = data.aws_iam_policy_document.default.json - - policy_enabled = true - policy = data.aws_iam_policy_document.iam-policy.json -} - -data "aws_iam_policy_document" "default" { - statement { - effect = "Allow" - actions = ["sts:AssumeRole"] - principals { - type = "Service" - identifiers = ["ec2.amazonaws.com"] - } - } -} - -data "aws_iam_policy_document" "iam-policy" { - statement { - actions = [ - "ssm:UpdateInstanceInformation", - "ssmmessages:CreateControlChannel", - "ssmmessages:CreateDataChannel", - "ssmmessages:OpenControlChannel", - "ssmmessages:OpenDataChannel"] - effect = "Allow" - resources = ["*"] - } - statement { - actions = [ - "kms:CreateGrant"] - effect = "Allow" - resources = [module.kms.key_arn] - condition { - test = "Bool" - values = [true] - variable = "kms:GrantIsForAWSResource" - } - } -} - -module "ec2" { - source = "clouddrove/ec2/aws" - version = "0.14.0" - - name = "" - environment = var.environment - label_order = var.label_order - - monitoring = false - assign_eip_address = true - associate_public_ip_address = true - instance_profile_enabled = true - ebs_optimized = false - ebs_volume_enabled = true - encrypted = true - instance_tags = { "snapshot" = true } - - instance_count = 1 - ami = "ami-08d658f84a6d84a80" - instance_type = "t2.nano" - - tenancy = "default" - vpc_security_group_ids_list = [module.ssh.security_group_ids, module.http-https.security_group_ids] - subnet_ids = var.public_subnet_ids - - iam_instance_profile = module.iam-role.name - disk_size = 20 - - ebs_volume_type = "gp2" - ebs_volume_size = 30 - kms_key_id = module.kms.key_arn - - dns_zone_id = "Z1XJD7SSBKXLC1" - hostname = "ec2" -} diff --git a/terraform/shared/ca-central-1/vpn/outputs.tf b/terraform/shared/ca-central-1/vpn/outputs.tf deleted file mode 100644 index e69de29..0000000 diff --git a/terraform/shared/ca-central-1/vpn/variables.tf b/terraform/shared/ca-central-1/vpn/variables.tf deleted file mode 100644 index 5fbf7b8..0000000 --- a/terraform/shared/ca-central-1/vpn/variables.tf +++ /dev/null @@ -1,34 +0,0 @@ -variable "label_order" { - description = "" - default = ["environment", "name"] -} - -variable "environment" { - description = "" - default = "shared" -} - -variable "subnet_ids" { - description = "" - default = "" -} - -variable "allowed_ip_external" { - description = "" - default = "0.0.0.0/0" -} - -variable "allowed_ip_internal" { - description = "" - default = "10.0.0.0/16" -} - -variable "vpc_id" { - description = "" - default = "" -} - -variable "public_subnet_ids" { - description = "" - default = [""] -} diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..9fd9676 --- /dev/null +++ b/variables.tf @@ -0,0 +1,142 @@ +#Module : LABEL +#Description : Terraform label module variables. +variable "name" { + type = string + default = "" + description = "Name (e.g. `app` or `cluster`)." +} + +variable "repository" { + type = string + default = "https://github.com/clouddrove/terraform-azure-nsg" + description = "Terraform current module repo" + + validation { + # regex(...) fails if it cannot find a match + condition = can(regex("^https://", var.repository)) + error_message = "The module-repo value must be a valid Git repo link." + } +} + +variable "environment" { + type = string + default = "" + description = "Environment (e.g. `prod`, `dev`, `staging`)." +} + +variable "label_order" { + type = list(any) + default = [] + description = "Label order, e.g. `name`,`application`." +} + +variable "attributes" { + type = list(any) + default = [] + description = "Additional attributes (e.g. `1`)." +} + +variable "delimiter" { + type = string + default = "-" + description = "Delimiter to be used between `organization`, `environment`, `name` and `attributes`." +} + +variable "tags" { + type = map(any) + default = {} + description = "Additional tags (e.g. map(`BusinessUnit`,`XYZ`)." +} + +variable "managedby" { + type = string + default = "hello@clouddrove.com" + description = "ManagedBy, eg 'CloudDrove'." +} + +variable "enabled" { + type = bool + default = true + description = "Flag to control the module creation" +} + +## Virtual Network +variable "resource_group_name" { + type = string + default = "" + description = "The name of the resource group in which to create the virtual network." +} + +variable "location" { + type = string + default = "" + description = "Location where resource should be created." +} + +variable "create" { + type = string + default = "30m" + description = "Used when creating the Resource Group." +} + +variable "update" { + type = string + default = "30m" + description = "Used when updating the Resource Group." +} + +variable "read" { + type = string + default = "5m" + description = "Used when retrieving the Resource Group." +} + +variable "delete" { + type = string + default = "30m" + description = "Used when deleting the Resource Group." +} + +variable "source_application_security_group_ids" { + type = list(any) + default = [] + description = "A List of source Application Security Group ID's." +} + +variable "destination_application_security_group_ids" { + type = list(any) + default = [] + description = "A List of destination Application Security Group ID's." +} + +variable "access" { + type = string + default = "Allow" + description = "Specifies whether network traffic is allowed or denied. Possible values are Allow and Deny." +} + +variable "priority" { + type = number + default = 1001 + description = "Specifies the priority of the rule. The value can be between 100 and 4096." +} + +variable "custom_port" { + type = list(any) + description = <<-DOC + A list of maps of custom port. + name: + protocol: + source_port_range: + destination_port_ranges: + source_address_prefixes: + source_application_security_group_ids: + destination_address_prefixes: for list of ip address + destination_address_prefix : for all ip address(*) or Virtualnetwork + destination_application_security_group_ids: + access: + priority: + tags: + DOC + default = [] +} diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..55c5a8f --- /dev/null +++ b/versions.tf @@ -0,0 +1,13 @@ +# Terraform version +terraform { + required_version = ">= 1.0.0" +} + +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">=2.90.0" + } + } +}