├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── aws_ec2.tf ├── aws_s3.tf ├── aws_sql.tf ├── aws_sql.tf.bkp ├── boundary_dynamic_aws.tf.bkp ├── boundary_okta.tf ├── boundary_postgres.tf ├── boundary_postgres.tf.bkp ├── boundary_session_recording.tf ├── boundary_windows.tf ├── dev ├── .terraform.lock.hcl ├── Makefile ├── backend.tf ├── main.tf └── outputs.tf ├── generic_test.tf ├── hcp-boundary-worker.nomad ├── main.tf ├── nomad_job_ssh.tf ├── nomad_workers.tf ├── okta_boundary.tf ├── outputs.tf ├── pki_test.tf ├── provider.tf ├── terraform.tfvars ├── to_team.tf.bkp ├── variables.tf ├── vault_aws.tf.bkp ├── vault_boundary.tf ├── vault_consul.tf ├── vault_postgres.tf ├── vault_postgres.tf.bkp ├── vault_ssh.tf └── vault_windows.tf /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # Crash log files 9 | crash.log 10 | 11 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 12 | # .tfvars files are managed as part of configuration and so should be included in 13 | # version control. 14 | # 15 | *.tfvars 16 | */dev/*.tfvars 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # 27 | # !example_override.tf 28 | 29 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 30 | # example: *tfplan* 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: login init demostack apply 2 | .PHONY: all doormat_creds doormat_aws deploy destroy console 3 | TFC_ORG = emea-se-playground-2019 4 | WORKSPACE_DEMOSTACK = Guy-AWS-Demostack 5 | DOORMAT_AWS_ACCOUNT = aws_guy_test 6 | login: 7 | doormat login 8 | init: 9 | terraform init 10 | demostack: 11 | doormat aws export --account $(DOORMAT_AWS_ACCOUNT) 12 | apply: 13 | terraform init 14 | terraform plan 15 | terraform apply 16 | destroy: 17 | terraform destroy -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # terraform-boundary-config 2 | a module for a demostack configuration of bounday 3 | -------------------------------------------------------------------------------- /aws_ec2.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS Provider 2 | provider "aws" { 3 | region = var.region 4 | } 5 | 6 | 7 | data "aws_instances" "servers" { 8 | 9 | 10 | filter { 11 | name = "instance-state-name" 12 | values = ["running"] 13 | } 14 | 15 | instance_tags = { 16 | # owner = var.owner_tag 17 | Function = "worker" 18 | Purpose = var.application_name 19 | } 20 | 21 | } 22 | 23 | data "aws_instance" "windows" { 24 | 25 | filter { 26 | name = "instance-state-name" 27 | values = ["running"] 28 | } 29 | 30 | instance_tags = { 31 | Function = "Windows" 32 | Purpose = var.application_name 33 | #owner = var.owner_tag 34 | } 35 | 36 | get_password_data = true 37 | } -------------------------------------------------------------------------------- /aws_s3.tf: -------------------------------------------------------------------------------- 1 | resource "aws_s3_bucket" "boundary_session_recording" { 2 | bucket = var.s3_bucket_name 3 | force_destroy = true 4 | tags = { 5 | Name = var.s3_bucket_name_tags 6 | Environment = var.s3_bucket_env_tags 7 | Terraform = "true" 8 | } 9 | } 10 | 11 | resource "aws_s3_bucket_versioning" "versioning_demo" { 12 | bucket = aws_s3_bucket.boundary_session_recording.id 13 | versioning_configuration { 14 | status = "Enabled" 15 | } 16 | } 17 | 18 | resource "aws_s3_bucket_metric" "demo-bucket-metric" { 19 | bucket = aws_s3_bucket.boundary_session_recording.id 20 | name = "EntireBucket" 21 | } -------------------------------------------------------------------------------- /aws_sql.tf: -------------------------------------------------------------------------------- 1 | data "aws_db_instance" "mysql" { 2 | db_instance_identifier = "${var.application_name}-mysql" 3 | } 4 | 5 | 6 | data "aws_db_instance" "postgres" { 7 | db_instance_identifier = "${var.application_name}-postgres" 8 | } -------------------------------------------------------------------------------- /aws_sql.tf.bkp: -------------------------------------------------------------------------------- 1 | 2 | resource "aws_db_subnet_group" "databases" { 3 | name = "databases" 4 | subnet_ids = aws_subnet.demostack.*.id 5 | 6 | } 7 | 8 | resource "aws_db_instance" "mysql" { 9 | identifier = "${var.namespace}-mysql" 10 | allocated_storage = 10 11 | engine = "mysql" 12 | engine_version = "5.7" 13 | instance_class = "db.t3.micro" 14 | db_name = "mydb" 15 | username = "foo" 16 | password = "foobarbaz" 17 | parameter_group_name = "default.mysql5.7" 18 | db_subnet_group_name = aws_db_subnet_group.databases.id 19 | vpc_security_group_ids =[aws_security_group.demostack.id] 20 | skip_final_snapshot = true 21 | timeouts { 22 | create = "10m" 23 | delete = "10m" 24 | } 25 | } 26 | 27 | # https://github.com/terraform-aws-modules/terraform-aws-rds/tree/master/examples/complete-postgres 28 | resource "aws_db_instance" "postgres" { 29 | identifier = "${var.namespace}-postgres" 30 | engine = "postgres" 31 | engine_version = "13.1" 32 | instance_class = "db.t3.micro" 33 | 34 | allocated_storage = 5 35 | storage_encrypted = true 36 | 37 | db_name = "postgress" 38 | username = "postgresql" 39 | password = "YourPwdShouldBeLongAndSecure!" 40 | port = 5432 41 | db_subnet_group_name = aws_db_subnet_group.databases.id 42 | vpc_security_group_ids =[aws_security_group.demostack.id] 43 | skip_final_snapshot = true 44 | timeouts { 45 | create = "10m" 46 | delete = "10m" 47 | } 48 | } -------------------------------------------------------------------------------- /boundary_dynamic_aws.tf.bkp: -------------------------------------------------------------------------------- 1 | 2 | data "aws_iam_access_key" "boundary_dynamic_host_catalog" { 3 | user_name = "${var.namespace}-bdhc" 4 | } 5 | 6 | resource "boundary_host_catalog_plugin" "aws_ec2" { 7 | name = "AWS Sandbox" 8 | description = "Host catalog in AWS Sandbox" 9 | scope_id = boundary_scope.project.id 10 | plugin_name = "aws" 11 | attributes_json = jsonencode({ "region" = data.aws_region.current.name }) 12 | secrets_json = jsonencode({ 13 | "access_key_id" = data.aws_iam_access_key.boundary_dynamic_host_catalog.id 14 | "secret_access_key" = data.aws_iam_access_key.boundary_dynamic_host_catalog.secret 15 | }) 16 | } -------------------------------------------------------------------------------- /boundary_okta.tf: -------------------------------------------------------------------------------- 1 | resource "boundary_auth_method_oidc" "provider" { 2 | name = "Okta" 3 | description = "OIDC auth method for Okta" 4 | scope_id = "global" 5 | issuer = okta_auth_server.boundary.issuer 6 | client_id = okta_app_oauth.boundary.client_id 7 | client_secret = okta_app_oauth.boundary.client_secret 8 | signing_algorithms = ["RS256"] 9 | api_url_prefix = var.boundary_address 10 | is_primary_for_scope = true 11 | state = "active-public" 12 | max_age = 0 13 | } 14 | 15 | resource "boundary_account_oidc" "oidc_user" { 16 | name = "guy-hashicorp" 17 | description = "OIDC account for guy-HashiCorp" 18 | auth_method_id = boundary_auth_method_oidc.provider.id 19 | issuer = okta_auth_server.boundary.issuer 20 | subject = okta_app_oauth.boundary.client_id 21 | } 22 | 23 | resource "boundary_managed_group" "oidc_managed_group" { 24 | name = "okta-managed-group" 25 | description = "Okta Managed Group" 26 | auth_method_id = boundary_auth_method_oidc.provider.id 27 | filter = "\"okta.com\" in \"/token/iss\"" 28 | } 29 | 30 | resource "boundary_role" "oidc_admin_role" { 31 | name = "Admin Role" 32 | description = "admin role" 33 | principal_ids = [boundary_managed_group.oidc_managed_group.id] 34 | grant_strings = ["id=*;type=*;actions=*"] 35 | scope_id = "global" 36 | } 37 | 38 | 39 | resource "boundary_role" "oidc_user_role" { 40 | name = "User Role" 41 | description = "user role org" 42 | principal_ids = [boundary_managed_group.oidc_managed_group.id] 43 | grant_strings = ["id=*;type=*;actions=*"] 44 | scope_id = boundary_scope.app.id 45 | } 46 | 47 | 48 | 49 | resource "boundary_role" "oidc_user_role_project" { 50 | name = "User Role" 51 | description = "user role project" 52 | principal_ids = [boundary_managed_group.oidc_managed_group.id] 53 | grant_strings = ["id=*;type=*;actions=*"] 54 | scope_id = boundary_scope.app_infra.id 55 | } 56 | -------------------------------------------------------------------------------- /boundary_postgres.tf: -------------------------------------------------------------------------------- 1 | 2 | 3 | resource "boundary_credential_library_vault" "postgres" { 4 | name = "postgres_creds" 5 | description = "postgres dynamic creds" 6 | credential_type = "username_password" 7 | credential_store_id = boundary_credential_store_vault.app_vault.id 8 | path = "postgres/creds/postgres-role" # change to Vault backend path 9 | http_method = "GET" 10 | } 11 | 12 | 13 | resource "boundary_host_catalog_static" "postgres_catalog" { 14 | name = "postgres_consul_servers" 15 | description = "Postgres servers host catalog" 16 | scope_id = boundary_scope.app_infra.id 17 | } 18 | 19 | resource "boundary_host_static" "postgres_host" { 20 | type = "static" 21 | name = "postgres_server" 22 | description = "Postgres server host" 23 | address = data.aws_db_instance.postgres.address 24 | host_catalog_id = boundary_host_catalog_static.postgres_catalog.id 25 | } 26 | 27 | resource "boundary_host_set_static" "postgres_set" { 28 | type = "static" 29 | name = "postgres_set" 30 | description = "Host set for postgres servers" 31 | host_catalog_id = boundary_host_catalog_static.postgres_catalog.id 32 | host_ids = [boundary_host_static.postgres_host.id] 33 | } 34 | 35 | resource "boundary_target" "postgres" { 36 | type = "tcp" 37 | name = "postgres servers" 38 | description = "Postgres target" 39 | scope_id = boundary_scope.app_infra.id 40 | default_port = data.aws_db_instance.postgres.port 41 | session_connection_limit = -1 42 | egress_worker_filter = " \"demostack\" in \"/tags/type\" " 43 | 44 | host_source_ids = [ 45 | boundary_host_set_static.postgres_set.id 46 | ] 47 | 48 | brokered_credential_source_ids = [ 49 | boundary_credential_library_vault.postgres.id 50 | ] 51 | } 52 | 53 | -------------------------------------------------------------------------------- /boundary_postgres.tf.bkp: -------------------------------------------------------------------------------- 1 | 2 | 3 | resource "boundary_credential_library_vault" "postgres" { 4 | name = "postgres_creds" 5 | description = "postgres dynamic creds" 6 | credential_store_id = boundary_credential_store_vault.app_vault.id 7 | path = "postgres/creds/postgres-role" # change to Vault backend path 8 | http_method = "GET" 9 | } 10 | 11 | 12 | resource "boundary_host_catalog_static" "postgres_catalog" { 13 | name = "postgres_consul_servers" 14 | description = "Postgres servers host catalog" 15 | scope_id = boundary_scope.app_infra.id 16 | } 17 | 18 | resource "boundary_host" "postgres_host" { 19 | type = "static" 20 | name = "postgres_server" 21 | description = "Postgres server host" 22 | address = var.postgres_hostname 23 | host_catalog_id = boundary_host_catalog_static.postgres_catalog.id 24 | } 25 | 26 | resource "boundary_host_set" "postgres_set" { 27 | type = "static" 28 | name = "postgres_set" 29 | description = "Host set for postgres servers" 30 | host_catalog_id = boundary_host_catalog_static.postgres_catalog.id 31 | host_ids = [boundary_host.postgres_host.id] 32 | } 33 | 34 | resource "boundary_target" "postgres" { 35 | type = "tcp" 36 | name = "postgres servers" 37 | description = "Postgres target" 38 | scope_id = boundary_scope.app_infra.id 39 | default_port = var.postgres_port 40 | session_connection_limit = -1 41 | # worker_filter = "demostack in /tags/type" 42 | 43 | host_source_ids = [ 44 | boundary_host_set.postgres_set.id 45 | ] 46 | 47 | injected_application_credential_source_ids = [ 48 | boundary_credential_library_vault.postgres.id 49 | ] 50 | } -------------------------------------------------------------------------------- /boundary_session_recording.tf: -------------------------------------------------------------------------------- 1 | # Grab some information about and from the current AWS account. 2 | data "aws_caller_identity" "current" {} 3 | 4 | data "aws_iam_policy" "demo_user_permissions_boundary" { 5 | name = "DemoUser" 6 | } 7 | 8 | locals { 9 | my_email = split("/", data.aws_caller_identity.current.arn)[2] 10 | } 11 | 12 | # Create the user to be used in Boundary for session recording. Then attach the policy to the user. 13 | resource "aws_iam_user" "boundary_session_recording" { 14 | name = "demo-${local.my_email}-bsr" 15 | permissions_boundary = data.aws_iam_policy.demo_user_permissions_boundary.arn 16 | force_destroy = true 17 | } 18 | 19 | resource "aws_iam_user_policy_attachment" "boundary_session_recording" { 20 | user = aws_iam_user.boundary_session_recording.name 21 | policy_arn = data.aws_iam_policy.demo_user_permissions_boundary.arn 22 | } 23 | 24 | data "aws_iam_policy_document" "boundary_user_policy" { 25 | statement { 26 | sid = "InteractWithS3" 27 | actions = [ 28 | "s3:PutObject", 29 | "s3:GetObject", 30 | "s3:GetObjectAttributes", 31 | ] 32 | resources = ["arn:aws:s3:::${var.s3_bucket_name}/*"] 33 | } 34 | statement { 35 | actions = [ 36 | "iam:DeleteAccessKey", 37 | "iam:GetUser", 38 | "iam:CreateAccessKey" 39 | ] 40 | resources = [aws_iam_user.boundary_session_recording.arn] 41 | } 42 | } 43 | 44 | resource "aws_iam_policy" "boundary_user_policy" { 45 | name = "demo-${local.my_email}-bsr-policy" 46 | path = "/" 47 | description = "Managed policy for the Boundary user recorder" 48 | policy = data.aws_iam_policy_document.boundary_user_policy.json 49 | } 50 | 51 | 52 | resource "aws_iam_user_policy_attachment" "boundary_user_policy" { 53 | user = aws_iam_user.boundary_session_recording.name 54 | policy_arn = aws_iam_policy.boundary_user_policy.arn 55 | } 56 | 57 | # Generate some secrets to pass in to the Boundary configuration. 58 | # WARNING: These secrets are not encrypted in the state file. Ensure that you do not commit your state file! 59 | resource "aws_iam_access_key" "boundary_session_recording" { 60 | user = aws_iam_user.boundary_session_recording.name 61 | depends_on = [aws_iam_user_policy_attachment.boundary_session_recording] 62 | } 63 | 64 | # AWS is eventually-consistent when creating IAM Users. Introduce a wait 65 | # before handing credentails off to boundary. 66 | resource "time_sleep" "boundary_session_recording_user_ready" { 67 | create_duration = "1m" 68 | 69 | depends_on = [aws_iam_access_key.boundary_session_recording,nomad_job.nomad_boundary_workers] 70 | } 71 | 72 | # NOTE: Be advised, at this time there is no way to delete a storage bucket with the provider or inside of Boundary GUI 73 | # The only way to delete the storage bucket is to delete the cluster at the moment. As such, you could leverage the below 74 | # to provision a storage bucket with this demo, or you can manage this in your Boundary Cluster Configuration 75 | 76 | 77 | resource "boundary_storage_bucket" "doormat_example" { 78 | depends_on = [ nomad_job.nomad_boundary_workers,aws_iam_user.boundary_session_recording,time_sleep.boundary_session_recording_user_ready ] 79 | name = "Demo BSR Bucket" 80 | description = "Demo Boundary Session Recording Bucket" 81 | #scope_id = boundary_scope.app.id 82 | scope_id = "global" 83 | plugin_name = "aws" 84 | bucket_name = var.s3_bucket_name 85 | attributes_json = jsonencode({ "region" = var.region, "disable_credential_rotation" = var.disable_credential_rotation }) 86 | 87 | secrets_json = jsonencode({ 88 | "access_key_id" = aws_iam_access_key.boundary_session_recording.id, 89 | "secret_access_key" = aws_iam_access_key.boundary_session_recording.secret 90 | }) 91 | worker_filter = " \"demostack\" in \"/tags/type\" " 92 | } 93 | -------------------------------------------------------------------------------- /boundary_windows.tf: -------------------------------------------------------------------------------- 1 | 2 | 3 | resource "boundary_credential_library_vault" "windows" { 4 | name = "windows_creds" 5 | description = "windows dynamic creds" 6 | credential_type = "username_password" 7 | credential_store_id = boundary_credential_store_vault.app_vault.id 8 | path = "boundary_creds/data/windows" # change to Vault backend path 9 | http_method = "GET" 10 | } 11 | 12 | 13 | resource "boundary_host_catalog_static" "windows_catalog" { 14 | name = "windows_consul_servers" 15 | description = "windows servers host catalog" 16 | scope_id = boundary_scope.app_infra.id 17 | } 18 | 19 | resource "boundary_host_static" "windows_host" { 20 | type = "static" 21 | name = "windows_server" 22 | description = "windows server host" 23 | address = data.aws_instance.windows.private_ip 24 | host_catalog_id = boundary_host_catalog_static.windows_catalog.id 25 | } 26 | 27 | resource "boundary_host_set_static" "windows_set" { 28 | type = "static" 29 | name = "windows_set" 30 | description = "Host set for windows servers" 31 | host_catalog_id = boundary_host_catalog_static.windows_catalog.id 32 | host_ids = [boundary_host_static.windows_host.id] 33 | } 34 | 35 | resource "boundary_target" "windows" { 36 | type = "tcp" 37 | name = "windows servers" 38 | description = "windows target" 39 | scope_id = boundary_scope.app_infra.id 40 | default_port = var.windows_port 41 | session_connection_limit = -1 42 | egress_worker_filter = " \"demostack\" in \"/tags/type\" " 43 | 44 | host_source_ids = [ 45 | boundary_host_set_static.windows_set.id 46 | ] 47 | 48 | brokered_credential_source_ids = [ 49 | boundary_credential_library_vault.windows.id 50 | ] 51 | } -------------------------------------------------------------------------------- /dev/.terraform.lock.hcl: -------------------------------------------------------------------------------- 1 | # This file is maintained automatically by "terraform init". 2 | # Manual edits may be lost in future updates. 3 | 4 | provider "registry.terraform.io/hashicorp/aws" { 5 | version = "5.10.0" 6 | hashes = [ 7 | "h1:ll2mC5mMF+Tm/+tmDQ6p6h3oAFpMSbZsA54STMZegwI=", 8 | "zh:24f8b40ba25521ec809906623ce1387542f3da848952167bc960663583a7b2c7", 9 | "zh:3c12afbda4e8ed44ab8315d16bbba4329ef3f18ffe3c0d5ea456dd05472fa610", 10 | "zh:4da2de97535c7fb51ede8ef9b6bd45c790005aec36daac4317a6175d2ff632fd", 11 | "zh:5631fd3c02c5abe5e51a73bd77ddeaaf97b2d508845ea03bc1e5955b52d94706", 12 | "zh:5bdef27b4e5b2dcd0661125fcc1e70826d545903b1e19bb8d28d2a0c812468d5", 13 | "zh:7b7f6b3e00ad4b7bfaa9872388f7b8014d8c9a1fe5c3f9f57865535865727633", 14 | "zh:935f7a599a3f55f69052b096491262d59787625ce5d52f729080328e5088e823", 15 | "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", 16 | "zh:a451a24f6675f8ad643a9b218cdb54c2af75a53d6a712daff46f64b81ec61032", 17 | "zh:a5bcf820baefdc9f455222878f276a7f406a1092ac7b4c0cdbd6e588bff84847", 18 | "zh:c9ab7b838a75bbcacc298658c1a04d1f0ee5935a928d821afcbe08c98cca7c5f", 19 | "zh:d83855b6d66aaa03b1e66e03b7d0a4d1c9f992fce06f00011edde2a6ad6d91d6", 20 | "zh:f1793e9a1e3ced98ca301ef1a294f46c06f77f6eb10f4d67ffef87ea60835421", 21 | "zh:f366c99ddb16d75e07a687a60c015e8e2e0cdb593dea902385629571bd604859", 22 | "zh:fb3ec60ea72144f480f495634c6d3e7a7638d7061a77c228a30768c1ae0b91f6", 23 | ] 24 | } 25 | 26 | provider "registry.terraform.io/hashicorp/boundary" { 27 | version = "1.1.9" 28 | hashes = [ 29 | "h1:0CVDjVvwGP61jrm9EoS3LPFDNXsMw9A4ePGl4N/yjVk=", 30 | "zh:04ba8085e722d61e553337882b4f6b5ee2c1eff21dbb2422eed329fbdfe6e95d", 31 | "zh:1fe6b90fc0e2c91ae8d94236554ec3939f98b989b86c4d5452845b803bcd3af6", 32 | "zh:3a211c794760b2842b1d90ff5f373ad5e3b1112e436d0318a4056dda80e35ee2", 33 | "zh:3aa2ad8aaf57984186c202dbc0f376025d0e7e6b605115a94e3c9f5ca302ab75", 34 | "zh:3bdd9b8bc7df69908310864e9beae161aba00cbb1ffa468535982d7f5b37e716", 35 | "zh:3df06331ed139f911c1af05ad4d29279e2bc6d862bf8c80fa2423ffafc7b41b9", 36 | "zh:44829f169ca8647f742bb42ffe19f8521684bf43e2f435747c8fee280546eeac", 37 | "zh:45ec983fbbca68a6bfa429f7beb9593f802d1f17b27f84f86e1bc794bfd8c4d0", 38 | "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", 39 | "zh:790b8e405057afb8ae16169116de18bfdf0134452601ed084afbf2e5ee810548", 40 | "zh:d7a399d5d54b109ce08b3a20e5b13cfa4488d19c54db7e5cb8c9bf962a9bafbc", 41 | "zh:f25c62b4de4bcaa6b878dfa6098a49ad5f9bd9fbe9fe46d94646351df274befc", 42 | ] 43 | } 44 | 45 | provider "registry.terraform.io/hashicorp/nomad" { 46 | version = "1.4.20" 47 | hashes = [ 48 | "h1:4IKRa9RKAwJ55lLQjgkOkXLnm+KV4T0bCH+ldNhRR14=", 49 | "zh:02989edcebe724fc0aa873b22176fd20074c4f46295e728010711a8fc5dfa72c", 50 | "zh:089ba7d19bcf5c6bab3f8b8c5920eb6d78c52cf79bb0c5dfeb411c600e7efcba", 51 | "zh:235865a2182ca372bcbf440201a8b8cc0715ad5dbc4de893d99b6f32b5be53ab", 52 | "zh:67ea718764f3f344ecc6e027d20c1327b86353c8064aa90da3ec12cec4a88954", 53 | "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", 54 | "zh:8c68c540f0df4980568bdd688c2adec86eda62eb2de154e3db215b16de0a7ae0", 55 | "zh:911969c63a69a733be57b96d54c5966c9424e1abec8d5f20038c8cef3a504c65", 56 | "zh:a673c92ddc9d47e8d53dcb9b376f1adcb4543488202fc83a3e7eab8677530684", 57 | "zh:a94a73eae89fd8c8ebf872013079be41161d3f293f4026c92d45c4c5667dd613", 58 | "zh:db6b89f8b696040c0344f00928e4cf6e0a75034421ba14cdcd8a4d23bc865dce", 59 | "zh:e512c0b1239e3d66b60d22c2b4de19fea288e492cde90dff9277cc475fd9dbbf", 60 | "zh:ef6eccecbdef3bb8ce629cabfb5550c1db5c3e952943dda1786ef6cb470a8c23", 61 | ] 62 | } 63 | 64 | provider "registry.terraform.io/hashicorp/time" { 65 | version = "0.9.1" 66 | hashes = [ 67 | "h1:VxyoYYOCaJGDmLz4TruZQTSfQhvwEcMxvcKclWdnpbs=", 68 | "zh:00a1476ecf18c735cc08e27bfa835c33f8ac8fa6fa746b01cd3bcbad8ca84f7f", 69 | "zh:3007f8fc4a4f8614c43e8ef1d4b0c773a5de1dcac50e701d8abc9fdc8fcb6bf5", 70 | "zh:5f79d0730fdec8cb148b277de3f00485eff3e9cf1ff47fb715b1c969e5bbd9d4", 71 | "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", 72 | "zh:8c8094689a2bed4bb597d24a418bbbf846e15507f08be447d0a5acea67c2265a", 73 | "zh:a6d9206e95d5681229429b406bc7a9ba4b2d9b67470bda7df88fa161508ace57", 74 | "zh:aa299ec058f23ebe68976c7581017de50da6204883950de228ed9246f309e7f1", 75 | "zh:b129f00f45fba1991db0aa954a6ba48d90f64a738629119bfb8e9a844b66e80b", 76 | "zh:ef6cecf5f50cda971c1b215847938ced4cb4a30a18095509c068643b14030b00", 77 | "zh:f1f46a4f6c65886d2dd27b66d92632232adc64f92145bf8403fe64d5ffa5caea", 78 | "zh:f79d6155cda7d559c60d74883a24879a01c4d5f6fd7e8d1e3250f3cd215fb904", 79 | "zh:fd59fa73074805c3575f08cd627eef7acda14ab6dac2c135a66e7a38d262201c", 80 | ] 81 | } 82 | 83 | provider "registry.terraform.io/hashicorp/vault" { 84 | version = "3.18.0" 85 | hashes = [ 86 | "h1:dAfEObrH5Qs81VDfaFcdwfPDx4BgRG/CLaj7ybm3RCs=", 87 | "zh:0e898f977d2dbd0b2ffeb25520f6f3aaa0a078f654bf312dc12fefc327313204", 88 | "zh:11899fb3e6d2ce6215047cc37c4e1cbdc01334242103600d79009bcdda2cccd9", 89 | "zh:19c57f433f014f6275d1461dd190c50b1fbd2b1217718de6d2eb64e6a9bcea5c", 90 | "zh:4e2aa164ffd13080dc10d5de4256b684108126e1082c2613854e26a398831389", 91 | "zh:77abbf9d90d085677194305cf192f7890408881bbedc77e97c5146cef3e27a7c", 92 | "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", 93 | "zh:790758438efe4389fdb0cabfb6f5118dad13869946665a72ba79a2f1102ff153", 94 | "zh:b9f3f1ba160a41545c4a8cb3a0d91fb37e194cfd6879ac7f358321851242ff78", 95 | "zh:bf19d8380e93a8a6ea8735cc015d4d04c6c588b233bb7cbb2bc3c277b7973f9a", 96 | "zh:de096c2afc87052e4848661ae5fc87528468399ae1a3ef242f1d6738504c79fc", 97 | "zh:eb4dce6a7bc10fa836cd379161bb5fad698d3288099e6ce0fa92ca3183acf242", 98 | "zh:f1c150dc13d6597ee08b83904fdd97a6702a106d3f524d60f048f2bd5c492f51", 99 | ] 100 | } 101 | -------------------------------------------------------------------------------- /dev/Makefile: -------------------------------------------------------------------------------- 1 | all: login init demostack apply 2 | .PHONY: all doormat_creds doormat_aws deploy destroy console 3 | TFC_ORG = emea-se-playground-2019 4 | WORKSPACE_DEMOSTACK = Guy-AWS-Demostack 5 | DOORMAT_AWS_ACCOUNT = aws_guy_test 6 | login: 7 | doormat login 8 | init: 9 | terraform init 10 | demostack: 11 | doormat aws export --account $(DOORMAT_AWS_ACCOUNT) 12 | apply: 13 | terraform init 14 | terraform plan 15 | terraform apply 16 | destroy: 17 | terraform destroy -------------------------------------------------------------------------------- /dev/backend.tf: -------------------------------------------------------------------------------- 1 | # Using a single workspace: 2 | 3 | terraform { 4 | backend "remote" { 5 | hostname = "app.terraform.io" 6 | organization = "emea-se-playground-2019" 7 | workspaces { 8 | name = "GUY-HCP-Boundary-Config" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /dev/main.tf: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | // Variables 3 | variable "config_boundary_auth_method_id" {} 4 | variable "config_boundary_address" {} 5 | variable "config_boundary_password" {} 6 | variable "config_boundary_username" {} 7 | variable "config_vault_address" {} 8 | variable "config_vault_namespace" {} 9 | variable "config_vault_token" {} 10 | variable "config_nomad_address" {} 11 | variable "config_nomad_token" {} 12 | variable "config_path_to_private_key" {} 13 | variable "config_path_to_public_key" {} 14 | variable "config_application_name" {} 15 | 16 | //-------------------------------------------------------------------- 17 | // Modules 18 | module "config" { 19 | # source = "app.terraform.io/emea-se-playground-2019/config/boundary" 20 | source = "github.com/GuyBarros/terraform-boundary-config" 21 | 22 | application_name = var.config_application_name 23 | boundary_auth_method_id = var.config_boundary_auth_method_id 24 | boundary_address = var.config_boundary_address 25 | boundary_password = var.config_boundary_password 26 | boundary_username = var.config_boundary_username 27 | postgres_password = "YourPwdShouldBeLongAndSecure!" 28 | vault_address = var.config_vault_address 29 | vault_namespace = var.config_vault_namespace 30 | vault_token = var.config_vault_token 31 | nomad_address = var.config_nomad_address 32 | nomad_token = var.config_nomad_token 33 | windows_port = 3389 34 | path_to_private_key = var.config_path_to_private_key 35 | path_to_public_key = var.config_path_to_public_key 36 | } -------------------------------------------------------------------------------- /dev/outputs.tf: -------------------------------------------------------------------------------- 1 | 2 | output "A_Welcome_Message" { 3 | value = < /etc/ssh/trusted-user-ca-keys.pem 47 | 48 | # Setting up /etc/ssh/sshd_config 49 | grep -qxF 'TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem' /etc/ssh/sshd_config || sudo echo 'TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem' >> /etc/ssh/sshd_config 50 | 51 | # This is what your sshd config looks like now: 52 | cat /etc/ssh/sshd_config 53 | 54 | # restarting SSHD 55 | sudo systemctl restart sshd 56 | 57 | # remove your authorised_keys, if any. 58 | if [ -f /home/ubuntu/.ssh/authorized_keys ]; then 59 | mv /home/ubuntu/.ssh/authorized_keys /home/ubuntu/.ssh/backup 60 | fi 61 | 62 | # Uncomment the line below if you run into issues 63 | # mv /home/ubuntu/.ssh/backup /home/ubuntu/.ssh/authorized_keys 64 | 65 | exit 0 66 | EOH 67 | 68 | destination = "script.sh" 69 | perms = "755" 70 | } 71 | 72 | config { 73 | command = "bash" 74 | args = ["script.sh"] 75 | } 76 | } 77 | 78 | }#Group 79 | } # Job 80 | 81 | 82 | 83 | 84 | EOT 85 | } -------------------------------------------------------------------------------- /nomad_workers.tf: -------------------------------------------------------------------------------- 1 | resource "boundary_worker" "controller_led" { 2 | count = var.boundary_ingress_worker_count 3 | scope_id = "global" 4 | name = "${var.application_name} ingress worker ${count.index}" 5 | description = "self managed worker with controller led auth" 6 | } 7 | 8 | resource "nomad_job" "nomad_boundary_workers" { 9 | count = var.boundary_ingress_worker_count 10 | hcl2 { 11 | enabled = true 12 | vars = { 13 | boundary_auth_token = boundary_worker.controller_led[count.index].controller_generated_activation_token 14 | #boundary_auth_token = boundary_worker.controller_led[0].controller_generated_activation_token 15 | boundary_ingress_worker_count = var.boundary_ingress_worker_count 16 | hcp_boundary_cluster_id = substr(var.boundary_address, 8, 36) 17 | } 18 | } 19 | jobspec = <