From 030d3aa750d107a78c20c1d16921bb014c014bfe Mon Sep 17 00:00:00 2001 From: yoctoalex Date: Thu, 2 Nov 2023 19:58:03 +0100 Subject: [PATCH] Initial commit --- .gitignore | 35 ++ LICENSE | 201 ++++++++++++ README.md | 46 +++ examples/aws-existing-account/README.md | 13 + examples/aws-existing-account/main.tf | 18 + examples/aws-existing-account/outputs.tf | 25 ++ examples/aws-existing-account/var.tf | 24 ++ examples/aws-existing-account/versions.tf | 15 + examples/aws-new-account/README.md | 13 + examples/aws-new-account/main.tf | 19 ++ examples/aws-new-account/outputs.tf | 60 ++++ examples/aws-new-account/var.tf | 24 ++ examples/aws-new-account/versions.tf | 15 + main.tf | 383 ++++++++++++++++++++++ outputs.tf | 70 ++++ variables.tf | 36 ++ versions.tf | 14 + 17 files changed, 1011 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 examples/aws-existing-account/README.md create mode 100644 examples/aws-existing-account/main.tf create mode 100644 examples/aws-existing-account/outputs.tf create mode 100644 examples/aws-existing-account/var.tf create mode 100644 examples/aws-existing-account/versions.tf create mode 100644 examples/aws-new-account/README.md create mode 100644 examples/aws-new-account/main.tf create mode 100644 examples/aws-new-account/outputs.tf create mode 100644 examples/aws-new-account/var.tf create mode 100644 examples/aws-new-account/versions.tf create mode 100644 main.tf create mode 100644 outputs.tf create mode 100644 variables.tf create mode 100644 versions.tf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..791ad1c --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +.DS_Store + +# Local .terraform directories +**/.terraform/* + +# Terraform lockfile +.terraform.lock.hcl + +# .tfstate files +*.tfstate +*.tfstate.* +*.tfplan + +# Crash log files +crash.log + +# Exclude all .tfvars files, which are likely to contain sentitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars + +# 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 + +# Ignore CLI configuration files +.terraformrc +terraform.rc + +# Ignore XC Cloud Certificates +*.p12 \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + 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 [yyyy] [name of copyright owner] + + 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/README.md b/README.md new file mode 100644 index 0000000..b735eb8 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# AWS Cloud Credentials for F5 Distributed Cloud (XC) Terraform module + +This Terraform module provisions AWS Cloud Credentials in F5 Distributed Cloud (XC). It creates an IAM User, IAM Policy, Access Key, and Access Secret in AWS Cloud, along with a Cloud Credentials object in XC Cloud. + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](https://github.com/hashicorp/terraform) | >= 1.0 | +| [aws](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) | >= 5.0 | +| [volterra](https://registry.terraform.io/providers/volterraedge/volterra/latest) | >= 0.11.26 | + +## Usage + + +To use this module and leverage your existing credentials without provisioning any resources on AWS Cloud, include the following code in your Terraform configuration: + +```hcl +module "aws_cloud_credentials" { + source = "f5devcentral/aws-cloud-credentials/volterra" + + name = "aws-tf-demo-creds" + aws_access_key = "your_aws_access_key" + aws_secret_key = "your_aws_secret_key" +} +``` + + +If you want to create a new AWS IAM User + +```hcl +module "aws_cloud_credentials" { + source = "f5devcentral/aws-cloud-credentials/volterra" + + name = "aws-tf-demo-creds" +} +`````` + + +## Contributing + +Contributions to this module are welcome! Please see the contribution guidelines for more information. + +## License + +This module is licensed under the Apache 2.0 License. \ No newline at end of file diff --git a/examples/aws-existing-account/README.md b/examples/aws-existing-account/README.md new file mode 100644 index 0000000..02e4ac7 --- /dev/null +++ b/examples/aws-existing-account/README.md @@ -0,0 +1,13 @@ +# AWS Existing Account + +The following example will create an F5 XC Cloud Credentials object without provisioning any resources in the AWS Cloud + +```hcl +module "aws_creds" { + source = "f5devcentral/aws-cloud-credentials/volterra" + version = "0.0.3" + + name = "aws-tf-demo-creds" + aws_access_key = "your_existing_aws_access_key" + aws_secret_key = "your_existing_aws_secret_key" +``` \ No newline at end of file diff --git a/examples/aws-existing-account/main.tf b/examples/aws-existing-account/main.tf new file mode 100644 index 0000000..5737fbf --- /dev/null +++ b/examples/aws-existing-account/main.tf @@ -0,0 +1,18 @@ +provider "volterra" { + api_p12_file = var.xc_api_p12_file + url = var.xc_api_url +} + +provider "aws" { + access_key = var.aws_access_key + secret_key = var.aws_secret_key + region = "us-east-1" +} + +module "aws_creds" { + source = "../.." + + name = "aws-tf-demo-creds" + aws_access_key = var.aws_access_key + aws_secret_key = var.aws_secret_key +} diff --git a/examples/aws-existing-account/outputs.tf b/examples/aws-existing-account/outputs.tf new file mode 100644 index 0000000..b94cc32 --- /dev/null +++ b/examples/aws-existing-account/outputs.tf @@ -0,0 +1,25 @@ +output "access_key" { + description = "AWS Access Key" + value = module.aws_creds.aws_access_key +} + +output "secret_key" { + description = "AWS Secret Key" + sensitive = true + value = module.aws_creds.aws_secret_key +} + +output "name" { + description = "XC Cloud Credentials Name" + value = module.aws_creds.name +} + +output "namespace" { + description = "XC Cloud Credentials Namespace" + value = module.aws_creds.namespace +} + +output "id" { + description = "XC Cloud Credentials ID" + value = module.aws_creds.id +} \ No newline at end of file diff --git a/examples/aws-existing-account/var.tf b/examples/aws-existing-account/var.tf new file mode 100644 index 0000000..a46500b --- /dev/null +++ b/examples/aws-existing-account/var.tf @@ -0,0 +1,24 @@ +variable "xc_api_url" { + description = "XC Cloud API URL" + type = string + default = "https://your_xc-cloud_api_url.console.ves.volterra.io/api" +} + +variable "xc_api_p12_file" { + description = "Path to XC Cloud API certificate" + type = string + default = "./api-certificate.p12" +} + +variable "aws_access_key" { + description = "AWS Access Key" + type = string + default = "your_aws_access_key" +} + +variable "aws_secret_key" { + description = "AWS Secret Key" + type = string + sensitive = true + default = "your_aws_secret_key" +} \ No newline at end of file diff --git a/examples/aws-existing-account/versions.tf b/examples/aws-existing-account/versions.tf new file mode 100644 index 0000000..9efc91a --- /dev/null +++ b/examples/aws-existing-account/versions.tf @@ -0,0 +1,15 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + volterra = { + source = "volterraedge/volterra" + version = ">=0.11.26" + } + + aws = { + source = "hashicorp/aws" + version = ">=5.0" + } + } +} diff --git a/examples/aws-new-account/README.md b/examples/aws-new-account/README.md new file mode 100644 index 0000000..d5610f9 --- /dev/null +++ b/examples/aws-new-account/README.md @@ -0,0 +1,13 @@ +# AWS New Account + +The following example will create F5 XC Cloud Credentials, an AWS IAM User, an Access Key, a Secret Key, and the required AWS IAM Policies for AWS TGW Site deployment with DirectConnect. + +```hcl +module "aws_creds" { + source = "f5devcentral/aws-cloud-credentials/volterra" + version = "0.0.3" + + create_aws_tgw_iam = true + create_direct_connect_iam = true +} +``` \ No newline at end of file diff --git a/examples/aws-new-account/main.tf b/examples/aws-new-account/main.tf new file mode 100644 index 0000000..c94c83e --- /dev/null +++ b/examples/aws-new-account/main.tf @@ -0,0 +1,19 @@ +provider "volterra" { + api_p12_file = var.xc_api_p12_file + url = var.xc_api_url +} + +provider "aws" { + access_key = var.aws_access_key + secret_key = var.aws_secret_key + region = "us-east-1" +} + +module "aws_creds" { + source = "../.." + name = "aws-tf-demo-creds" + + create_aws_tgw_iam = true + create_direct_connect_iam = true +} + diff --git a/examples/aws-new-account/outputs.tf b/examples/aws-new-account/outputs.tf new file mode 100644 index 0000000..f3822be --- /dev/null +++ b/examples/aws-new-account/outputs.tf @@ -0,0 +1,60 @@ +output "access_key" { + description = "AWS Access Key" + value = module.aws_creds.aws_access_key +} + +output "secret_key" { + description = "AWS Secret Key" + sensitive = true + value = module.aws_creds.aws_secret_key +} + +output "user" { + description = "AWS IAM user name" + value = module.aws_creds.aws_iam_user_name +} + +output "aws_iam_vpc_site_policy_arn" { + value = module.aws_creds.aws_iam_vpc_site_policy_arn + description = "Created AWS IAM VPC Site Policy arn" +} + +output "aws_iam_tgw_site_policy_arn" { + value = module.aws_creds.aws_iam_tgw_site_policy_arn + description = "Created AWS IAM TGW Site Policy arn" +} + +output "aws_iam_directconnect_policy_arn" { + value = module.aws_creds.aws_iam_directconnect_policy_arn + description = "Created AWS IAM DirectConnect Policy arn" +} + +output "aws_iam_vpc_site_policy_name" { + value = module.aws_creds.aws_iam_vpc_site_policy_name + description = "Created AWS IAM VPC Site Policy name" +} + +output "aws_iam_tgw_site_policy_name" { + value = module.aws_creds.aws_iam_tgw_site_policy_name + description = "Created AWS IAM TGW Site Policy name" +} + +output "aws_iam_directconnect_policy_name" { + value = module.aws_creds.aws_iam_directconnect_policy_name + description = "Created AWS IAM DirectConnect Policy name" +} + +output "name" { + description = "XC Cloud Credentials Name" + value = module.aws_creds.name +} + +output "namespace" { + description = "XC Cloud Credentials Namespace" + value = module.aws_creds.namespace +} + +output "id" { + description = "XC Cloud Credentials ID" + value = module.aws_creds.id +} \ No newline at end of file diff --git a/examples/aws-new-account/var.tf b/examples/aws-new-account/var.tf new file mode 100644 index 0000000..7dd267a --- /dev/null +++ b/examples/aws-new-account/var.tf @@ -0,0 +1,24 @@ +variable "xc_api_url" { + description = "XC Cloud API URL" + type = string + default = "https://your_xc-cloud_api_url.console.ves.volterra.io/api" +} + +variable "xc_api_p12_file" { + description = "Path to XC Cloud API certificate" + type = string + default = "./api-certificate.p12" +} + +variable "aws_access_key" { + description = "AWS Access Key" + type = string + default = "" +} + +variable "aws_secret_key" { + description = "AWS Secret Key" + type = string + sensitive = true + default = "" +} \ No newline at end of file diff --git a/examples/aws-new-account/versions.tf b/examples/aws-new-account/versions.tf new file mode 100644 index 0000000..9efc91a --- /dev/null +++ b/examples/aws-new-account/versions.tf @@ -0,0 +1,15 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + volterra = { + source = "volterraedge/volterra" + version = ">=0.11.26" + } + + aws = { + source = "hashicorp/aws" + version = ">=5.0" + } + } +} diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..b9946e0 --- /dev/null +++ b/main.tf @@ -0,0 +1,383 @@ +locals { + create_iam_user = var.aws_access_key == null || var.aws_secret_key == null +} + +resource "aws_iam_user" "this" { + count = local.create_iam_user ? 1 : 0 + + name = var.name + tags = var.tags +} + +resource "aws_iam_access_key" "this" { + count = local.create_iam_user ? 1 : 0 + + user = local.create_iam_user ? aws_iam_user.this[0].name : null + depends_on = [ + aws_iam_user.this[0] + ] +} + +resource "aws_iam_policy" "tgw_site" { + count = local.create_iam_user && var.create_aws_tgw_iam ? 1 : 0 + + name = "${var.name}-tgw-site-policy" + description = "F5 XC Cloud AWS TGW Site policy" + policy = data.aws_iam_policy_document.tgw_site.json + + tags = var.tags + + depends_on = [ + aws_iam_user.this[0] + ] +} + +resource "aws_iam_user_policy_attachment" "tgw_site" { + count = local.create_iam_user && var.create_aws_tgw_iam ? 1 : 0 + + user = local.create_iam_user ? aws_iam_user.this[0].name : null + policy_arn = aws_iam_policy.tgw_site[0].arn + + depends_on = [ + aws_iam_policy.tgw_site[0] + ] +} + +data "aws_iam_policy_document" "tgw_site" { + version = "2012-10-17" + statement { + sid = "EC2TGWPermissions" + effect = "Allow" + actions = [ + "ec2:AcceptTransitGatewayVpcAttachment", + "ec2:AssociateTransitGatewayRouteTable", + "ec2:CreateTransitGateway", + "ec2:CreateTransitGatewayConnect", + "ec2:CreateTransitGatewayConnectPeer", + "ec2:CreateTransitGatewayPeeringAttachment", + "ec2:CreateTransitGatewayPolicyTable", + "ec2:CreateTransitGatewayPrefixListReference", + "ec2:CreateTransitGatewayRoute", + "ec2:CreateTransitGatewayRouteTable", + "ec2:CreateTransitGatewayRouteTableAnnouncement", + "ec2:CreateTransitGatewayVpcAttachment", + "ec2:DeleteTransitGateway", + "ec2:DeleteTransitGatewayRoute", + "ec2:DeleteTransitGatewayRouteTable", + "ec2:DeleteTransitGatewayVpcAttachment", + "ec2:DescribeTransitGatewayAttachments", + "ec2:DescribeTransitGatewayPeeringAttachments", + "ec2:DescribeTransitGatewayRouteTables", + "ec2:DescribeTransitGatewayVpcAttachments", + "ec2:DescribeTransitGateways", + "ec2:DisableTransitGatewayRouteTablePropagation", + "ec2:DisassociateTransitGatewayRouteTable", + "ec2:EnableTransitGatewayRouteTablePropagation", + "ec2:GetTransitGatewayRouteTableAssociations", + "ec2:GetTransitGatewayRouteTablePropagations", + "ec2:ModifyTransitGatewayVpcAttachment", + "ec2:SearchTransitGatewayRoutes" + ] + resources = ["*"] + } +} + +resource "aws_iam_policy" "directconnect" { + count = local.create_iam_user && var.create_direct_connect_iam ? 1 : 0 + + name = "${var.name}-directconnect-policy" + description = "F5 XC Cloud AWS DirectConnect policy" + policy = data.aws_iam_policy_document.directconnect.json + + tags = var.tags + + depends_on = [ + aws_iam_user.this[0] + ] +} + +resource "aws_iam_user_policy_attachment" "directconnect" { + count = local.create_iam_user && var.create_direct_connect_iam ? 1 : 0 + + user = local.create_iam_user ? aws_iam_user.this[0].name : null + policy_arn = aws_iam_policy.directconnect[0].arn + + depends_on = [ + aws_iam_policy.directconnect[0] + ] +} + +data "aws_iam_policy_document" "directconnect" { + version = "2012-10-17" + statement { + sid = "DirectConnectPermissions" + effect = "Allow" + actions = [ + "directconnect:AllocateHostedConnection", + "directconnect:AllocatePrivateVirtualInterface", + "directconnect:AllocatePublicVirtualInterface", + "directconnect:AssociateHostedConnection", + "directconnect:AssociateVirtualInterface", + "directconnect:ConfirmConnection", + "directconnect:ConfirmPrivateVirtualInterface", + "directconnect:ConfirmPublicVirtualInterface", + "directconnect:CreateConnection", + "directconnect:CreateDirectConnectGateway", + "directconnect:CreateDirectConnectGatewayAssociation", + "directconnect:CreatePrivateVirtualInterface", + "directconnect:CreatePublicVirtualInterface", + "directconnect:DeleteConnection", + "directconnect:DeleteDirectConnectGateway", + "directconnect:DeleteDirectConnectGatewayAssociation", + "directconnect:DeleteVirtualInterface", + "directconnect:DescribeConnections", + "directconnect:DescribeDirectConnectGatewayAssociations", + "directconnect:DescribeDirectConnectGatewayAttachments", + "directconnect:DescribeDirectConnectGateways", + "directconnect:DescribeHostedConnections", + "directconnect:DescribeTags", + "directconnect:DescribeVirtualGateways", + "directconnect:DescribeVirtualInterfaces", + "directconnect:TagResource", + "directconnect:UntagResource", + "directconnect:UpdateConnection", + "directconnect:UpdateDirectConnectGatewayAssociation" + ] + resources = ["*"] + } +} + +resource "aws_iam_user_policy_attachment" "vpc_site" { + count = local.create_iam_user ? 1 : 0 + + user = local.create_iam_user ? aws_iam_user.this[0].name : null + policy_arn = aws_iam_policy.vpc_site[0].arn + + depends_on = [ + aws_iam_policy.vpc_site[0] + ] +} + +resource "aws_iam_policy" "vpc_site" { + count = local.create_iam_user ? 1 : 0 + + name = "${var.name}-vpc-site-policy" + description = "F5 XC Cloud AWS VPC Site policy" + policy = data.aws_iam_policy_document.vpc_site.json + + tags = var.tags + + depends_on = [ + aws_iam_user.this[0] + ] +} + +data "aws_iam_policy_document" "vpc_site" { + version = "2012-10-17" + statement { + sid = "AutoScalingPermissions" + effect = "Allow" + actions = [ + "autoscaling:AttachLoadBalancerTargetGroups", + "autoscaling:AttachLoadBalancers", + "autoscaling:CreateAutoScalingGroup", + "autoscaling:CreateLaunchConfiguration", + "autoscaling:DeleteAutoScalingGroup", + "autoscaling:DeleteLaunchConfiguration", + "autoscaling:DescribeAutoScalingGroups", + "autoscaling:DescribeLaunchConfigurations", + "autoscaling:DescribeLoadBalancerTargetGroups", + "autoscaling:DescribeLoadBalancers", + "autoscaling:DetachLoadBalancerTargetGroups", + "autoscaling:DetachLoadBalancers", + "autoscaling:DisableMetricsCollection", + "autoscaling:EnableMetricsCollection", + "autoscaling:ResumeProcesses", + "autoscaling:SuspendProcesses", + "autoscaling:UpdateAutoScalingGroup", + ] + resources = ["*"] + } + statement { + sid = "EC2Permissions" + effect = "Allow" + actions = [ + "ec2:AllocateAddress", + "ec2:AssignPrivateIpAddresses", + "ec2:AssociateAddress", + "ec2:AssociateIamInstanceProfile", + "ec2:AssociateRouteTable", + "ec2:AssociateSubnetCidrBlock", + "ec2:AssociateVpcCidrBlock", + "ec2:AttachInternetGateway", + "ec2:AttachNetworkInterface", + "ec2:AttachVpnGateway", + "ec2:AuthorizeSecurityGroupEgress", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateCustomerGateway", + "ec2:CreateInternetGateway", + "ec2:CreateNetworkInterface", + "ec2:CreateRoute", + "ec2:CreateRouteTable", + "ec2:CreateSecurityGroup", + "ec2:CreateSubnet", + "ec2:CreateTags", + "ec2:CreateVpc", + "ec2:CreateVpnConnection", + "ec2:CreateVpnConnectionRoute", + "ec2:CreateVpnGateway", + "ec2:DeleteClientVpnEndpoint", + "ec2:DeleteClientVpnRoute", + "ec2:DeleteCustomerGateway", + "ec2:DeleteInternetGateway", + "ec2:DeleteNetworkInterface", + "ec2:DeleteRoute", + "ec2:DeleteRouteTable", + "ec2:DeleteSecurityGroup", + "ec2:DeleteSubnet", + "ec2:DeleteTags", + "ec2:DeleteVpc", + "ec2:DeleteVpnConnection", + "ec2:DeleteVpnGateway", + "ec2:DescribeAccountAttributes", + "ec2:DescribeAddresses", + "ec2:DescribeClientVpnConnections", + "ec2:DescribeClientVpnEndpoints", + "ec2:DescribeCustomerGateways", + "ec2:DescribeIamInstanceProfileAssociations", + "ec2:DescribeImages", + "ec2:DescribeInstanceAttribute", + "ec2:DescribeInstanceCreditSpecifications", + "ec2:DescribeInstanceTypes", + "ec2:DescribeInstances", + "ec2:DescribeInternetGateways", + "ec2:DescribeNetworkAcls", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeTags", + "ec2:DescribeVolumes", + "ec2:DescribeVolumesModifications", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcClassicLink", + "ec2:DescribeVpcClassicLinkDnsSupport", + "ec2:DescribeVpcs", + "ec2:DescribeVpnConnections", + "ec2:DescribeVpnGateways", + "ec2:DetachInternetGateway", + "ec2:DetachNetworkInterface", + "ec2:DetachVpnGateway", + "ec2:DisableVgwRoutePropagation", + "ec2:DisassociateAddress", + "ec2:DisassociateIamInstanceProfile", + "ec2:DisassociateRouteTable", + "ec2:DisassociateSubnetCidrBlock", + "ec2:DisassociateVpcCidrBlock", + "ec2:EnableVgwRoutePropagation", + "ec2:GetPasswordData", + "ec2:ModifyInstanceAttribute", + "ec2:ModifyInstanceCreditSpecification", + "ec2:ModifyInstanceMetadataOptions", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:ModifySubnetAttribute", + "ec2:ModifyVolume", + "ec2:ModifyVpcAttribute", + "ec2:ModifyVpnConnection", + "ec2:ModifyVpnConnectionOptions", + "ec2:MonitorInstances", + "ec2:ReleaseAddress", + "ec2:ReplaceIamInstanceProfileAssociation", + "ec2:ReplaceRoute", + "ec2:ReplaceRouteTableAssociation", + "ec2:RevokeSecurityGroupEgress", + "ec2:RevokeSecurityGroupIngress", + "ec2:RunInstances", + "ec2:StartInstances", + "ec2:StopInstances", + "ec2:TerminateInstances", + "ec2:UnassignPrivateIpAddresses", + "ec2:UnmonitorInstances" + ] + resources = ["*"] + } + + statement { + sid = "ELBPermissions" + effect = "Allow" + actions = [ + "elasticloadbalancing:AddTags", + "elasticloadbalancing:CreateListener", + "elasticloadbalancing:CreateLoadBalancer", + "elasticloadbalancing:CreateTargetGroup", + "elasticloadbalancing:DeleteListener", + "elasticloadbalancing:DeleteLoadBalancer", + "elasticloadbalancing:DeleteTargetGroup", + "elasticloadbalancing:DeregisterTargets", + "elasticloadbalancing:DescribeInstanceHealth", + "elasticloadbalancing:DescribeListeners", + "elasticloadbalancing:DescribeLoadBalancerAttributes", + "elasticloadbalancing:DescribeLoadBalancers", + "elasticloadbalancing:DescribeTags", + "elasticloadbalancing:DescribeTargetGroupAttributes", + "elasticloadbalancing:DescribeTargetGroups", + "elasticloadbalancing:DescribeTargetHealth", + "elasticloadbalancing:ModifyListener", + "elasticloadbalancing:ModifyLoadBalancerAttributes", + "elasticloadbalancing:ModifyTargetGroup", + "elasticloadbalancing:ModifyTargetGroupAttributes", + "elasticloadbalancing:RegisterTargets", + "elasticloadbalancing:RemoveTags", + ] + resources = ["*"] + } + statement { + sid = "IAMPermissions" + effect = "Allow" + actions = [ + "iam:AddRoleToInstanceProfile", + "iam:AttachRolePolicy", + "iam:CreateInstanceProfile", + "iam:CreatePolicy", + "iam:CreatePolicyVersion", + "iam:CreateRole", + "iam:CreateServiceLinkedRole", + "iam:DeleteInstanceProfile", + "iam:DeletePolicy", + "iam:DeletePolicyVersion", + "iam:DeleteRole", + "iam:DeleteRolePermissionsBoundary", + "iam:DeleteRolePolicy", + "iam:DetachRolePolicy", + "iam:GetInstanceProfile", + "iam:GetPolicy", + "iam:GetPolicyVersion", + "iam:GetRole", + "iam:ListAttachedRolePolicies", + "iam:ListInstanceProfilesForRole", + "iam:ListPolicyVersions", + "iam:ListRolePolicies", + "iam:PassRole", + "iam:PutRolePermissionsBoundary", + "iam:RemoveRoleFromInstanceProfile", + "iam:TagRole", + "iam:UpdateAssumeRolePolicy", + "iam:UpdateRole", + "iam:UpdateRoleDescription" + ] + resources = ["*"] + } +} + +resource "volterra_cloud_credentials" "this" { + name = var.name + namespace = "system" + aws_secret_key { + access_key = local.create_iam_user ? aws_iam_access_key.this[0].id : var.aws_access_key + secret_key { + clear_secret_info { + url = "string:///${base64encode(local.create_iam_user ? aws_iam_access_key.this[0].secret : var.aws_secret_key)}" + } + } + } +} diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..551fe62 --- /dev/null +++ b/outputs.tf @@ -0,0 +1,70 @@ +output "aws_access_key" { + value = local.create_iam_user ? aws_iam_access_key.this[0].id : var.aws_access_key + description = "AWS Access Key" +} + +output "aws_secret_key" { + value = local.create_iam_user ? aws_iam_access_key.this[0].secret : var.aws_secret_key + sensitive = true + description = "AWS Secret Key" +} + +output "aws_iam_user_name" { + value = local.create_iam_user ? aws_iam_user.this[0].name : "" + description = "Created AWS User name" +} + +output "aws_iam_user_arn" { + value = local.create_iam_user ? aws_iam_user.this[0].arn : "" + description = "The ARN assigned by AWS for the created IAM User" +} + +output "aws_iam_user_id" { + value = local.create_iam_user ? aws_iam_user.this[0].unique_id : "" + description = "The ID assigned by AWS for the created IAM User" +} + +output "aws_iam_vpc_site_policy_arn" { + value = local.create_iam_user ? aws_iam_policy.vpc_site[0].arn : "" + description = "Created AWS IAM VPC Site Policy arn" +} + +output "aws_iam_tgw_site_policy_arn" { + value = local.create_iam_user && var.create_aws_tgw_iam ? aws_iam_policy.tgw_site[0].arn : "" + description = "Created AWS IAM TGW Site Policy arn" +} + +output "aws_iam_directconnect_policy_arn" { + value = local.create_iam_user && var.create_direct_connect_iam ? aws_iam_policy.directconnect[0].arn : "" + description = "Created AWS IAM DirectConnect Policy arn" +} + +output "aws_iam_vpc_site_policy_name" { + value = local.create_iam_user ? aws_iam_policy.vpc_site[0].name : "" + description = "Created AWS IAM VPC Site Policy name" +} + +output "aws_iam_tgw_site_policy_name" { + value = local.create_iam_user && var.create_aws_tgw_iam ? aws_iam_policy.tgw_site[0].name : "" + description = "Created AWS IAM TGW Site Policy name" +} + +output "aws_iam_directconnect_policy_name" { + value = local.create_iam_user && var.create_direct_connect_iam ? aws_iam_policy.directconnect[0].name : "" + description = "Created AWS IAM DirectConnect Policy name" +} + +output "name" { + value = volterra_cloud_credentials.this.name + description = "Created XC Cloud Credentials name" +} + +output "namespace" { + value = volterra_cloud_credentials.this.namespace + description = "The namespace in which the XC Cloud Credentials is created" +} + +output "id" { + value = volterra_cloud_credentials.this.id + description = "ID of the XC Cloud Credentials" +} \ No newline at end of file diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..1083fd4 --- /dev/null +++ b/variables.tf @@ -0,0 +1,36 @@ +variable "tags" { + description = "A map of tags to add to all resources" + type = map(string) + default = {} +} + +variable "name" { + description = "Cloud Credentials name" + type = string + default = "" +} + +variable "aws_access_key" { + description = "Existing AWS Access Key ID" + type = string + default = null +} + +variable "aws_secret_key" { + description = "Existing AWS Secret Access Key" + type = string + sensitive = true + default = null +} + +variable "create_direct_connect_iam" { + description = "Create IAM permissions for Direct Connect" + type = bool + default = false +} + +variable "create_aws_tgw_iam" { + description = "Create IAM permissions for AWS TGW" + type = bool + default = false +} \ No newline at end of file diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..629c8d8 --- /dev/null +++ b/versions.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + volterra = { + source = "volterraedge/volterra" + version = ">=0.11.26" + } + aws = { + source = "hashicorp/aws" + version = ">=5.0" + } + } +} \ No newline at end of file