Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions examples/complete/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
##############################################################################

locals {
secret_manager_guid = var.existing_secret_manager_instance_guid == null ? module.secrets_manager[0].secrets_manager_guid : var.existing_secret_manager_instance_guid
secret_manager_region = var.existing_secret_manager_instance_region == null ? var.region : var.existing_secret_manager_instance_region
secrets_manager_guid = var.existing_secrets_manager_instance_guid == null ? module.secrets_manager[0].secrets_manager_guid : var.existing_secrets_manager_instance_guid
secrets_manager_region = var.existing_secrets_manager_instance_region == null ? var.region : var.existing_secrets_manager_instance_region
service_credential_names = {
"es_admin" : "Administrator",
"es_operator" : "Operator",
Expand Down Expand Up @@ -131,7 +131,7 @@ module "icd_mongodb" {

# Create Secrets Manager Instance (if not using existing one)
module "secrets_manager" {
count = var.existing_secret_manager_instance_guid == null ? 1 : 0
count = var.existing_secrets_manager_instance_guid == null ? 1 : 0
source = "terraform-ibm-modules/secrets-manager/ibm"
version = "2.2.6"
resource_group_id = module.resource_group.resource_group_id
Expand All @@ -146,8 +146,8 @@ module "secrets_manager" {
module "secrets_manager_secrets_group" {
source = "terraform-ibm-modules/secrets-manager-secret-group/ibm"
version = "1.3.4"
region = local.secret_manager_region
secrets_manager_guid = local.secret_manager_guid
region = local.secrets_manager_region
secrets_manager_guid = local.secrets_manager_guid
#tfsec:ignore:general-secrets-no-plaintext-exposure
secret_group_name = "${var.prefix}-es-secrets"
secret_group_description = "service secret-group" #tfsec:ignore:general-secrets-no-plaintext-exposure
Expand All @@ -158,8 +158,8 @@ module "secrets_manager_service_credentials_user_pass" {
source = "terraform-ibm-modules/secrets-manager-secret/ibm"
version = "1.7.0"
for_each = local.service_credential_names
region = local.secret_manager_region
secrets_manager_guid = local.secret_manager_guid
region = local.secrets_manager_region
secrets_manager_guid = local.secrets_manager_guid
secret_group_id = module.secrets_manager_secrets_group.secret_group_id
secret_name = "${var.prefix}-${each.key}-credentials"
secret_description = "MongoDB Service Credentials for ${each.key}"
Expand All @@ -172,8 +172,8 @@ module "secrets_manager_service_credentials_user_pass" {
module "secrets_manager_service_credentials_cert" {
source = "terraform-ibm-modules/secrets-manager-secret/ibm"
version = "1.7.0"
region = local.secret_manager_region
secrets_manager_guid = local.secret_manager_guid
region = local.secrets_manager_region
secrets_manager_guid = local.secrets_manager_guid
secret_group_id = module.secrets_manager_secrets_group.secret_group_id
secret_name = "${var.prefix}-es-cert"
secret_description = "MongoDB Service Credential Certificate"
Expand Down
6 changes: 3 additions & 3 deletions examples/complete/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ variable "plan" {
default = "enterprise"
}

variable "existing_secret_manager_instance_guid" {
variable "existing_secrets_manager_instance_guid" {
type = string
description = "Existing Secrets Manager GUID. If not provided an new instance will be provisioned"
default = null
}

variable "existing_secret_manager_instance_region" {
variable "existing_secrets_manager_instance_region" {
type = string
description = "Required if value is passed into var.existing_secret_manager_instance_guid"
description = "Required if value is passed into var.existing_secrets_manager_instance_guid"
default = null
}

Expand Down
8 changes: 4 additions & 4 deletions ibm_catalog.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,16 +226,16 @@
"key": "admin_pass"
},
{
"key": "admin_pass_secret_manager_secret_group"
"key": "admin_pass_secrets_manager_secret_group"
},
{
"key": "admin_pass_secret_manager_secret_name"
"key": "admin_pass_secrets_manager_secret_name"
},
{
"key": "existing_mongodb_instance_crn"
},
{
"key": "use_existing_admin_pass_secret_manager_secret_group"
"key": "use_existing_admin_pass_secrets_manager_secret_group"
},
{
"key": "users"
Expand Down Expand Up @@ -292,7 +292,7 @@
"key": "service_credential_secrets"
},
{
"key": "skip_mongodb_secret_manager_auth_policy"
"key": "skip_mongodb_secrets_manager_auth_policy"
}
]
}
Expand Down
28 changes: 11 additions & 17 deletions solutions/standard/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@ module "resource_group" {
existing_resource_group_name = var.use_existing_resource_group == true ? var.resource_group_name : null
}


#######################################################################################################################
# KMS encryption key
#######################################################################################################################

locals {
create_new_kms_key = var.existing_mongodb_instance_crn == null && !var.use_ibm_owned_encryption_key && var.existing_kms_key_crn == null ? 1 : 0 # no need to create any KMS resources if passing an existing key, or using IBM owned keys
create_new_kms_key = var.existing_mongodb_instance_crn == null && !var.use_ibm_owned_encryption_key && var.existing_kms_key_crn == null ? true : false # no need to create any KMS resources if passing an existing key, or using IBM owned keys
mongodb_key_name = var.prefix != null ? "${var.prefix}-${var.key_name}" : var.key_name
mongodb_key_ring_name = var.prefix != null ? "${var.prefix}-${var.key_ring_name}" : var.key_ring_name
}
Expand All @@ -24,7 +23,7 @@ module "kms" {
providers = {
ibm = ibm.kms
}
count = local.create_new_kms_key
count = local.create_new_kms_key ? 1 : 0
source = "terraform-ibm-modules/kms-all-inclusive/ibm"
version = "5.0.2"
create_key_protect_instance = false
Expand Down Expand Up @@ -89,7 +88,6 @@ locals {
create_cross_account_kms_auth_policy = var.existing_mongodb_instance_crn == null && var.ibmcloud_kms_api_key != null && !var.use_ibm_owned_encryption_key
create_cross_account_backup_kms_auth_policy = var.existing_mongodb_instance_crn == null && var.ibmcloud_kms_api_key != null && !var.use_ibm_owned_encryption_key && var.existing_backup_kms_key_crn != null


# If KMS encryption enabled (and existing ES instance is not being passed), parse details from the existing key if being passed, otherwise get it from the key that the DA creates
kms_account_id = var.existing_mongodb_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].account_id : module.kms_instance_crn_parser[0].account_id
kms_service = var.existing_mongodb_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].service_name : module.kms_instance_crn_parser[0].service_name
Expand All @@ -98,7 +96,6 @@ locals {
kms_key_id = var.existing_mongodb_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].resource : module.kms[0].keys[format("%s.%s", local.mongodb_key_ring_name, local.mongodb_key_name)].key_id
kms_region = var.existing_mongodb_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].region : module.kms_instance_crn_parser[0].region


# If creating KMS cross account policy for backups, parse backup key details from passed in key CRN
backup_kms_account_id = local.create_cross_account_backup_kms_auth_policy ? module.kms_backup_key_crn_parser[0].account_id : local.kms_account_id
backup_kms_service = local.create_cross_account_backup_kms_auth_policy ? module.kms_backup_key_crn_parser[0].service_name : local.kms_service
Expand Down Expand Up @@ -223,8 +220,6 @@ locals {
# elseif _ replace first char with K
# else use asis
generated_admin_password = startswith(random_password.admin_password[0].result, "-") ? "J${substr(random_password.admin_password[0].result, 1, -1)}" : startswith(random_password.admin_password[0].result, "_") ? "K${substr(random_password.admin_password[0].result, 1, -1)}" : random_password.admin_password[0].result


# admin password to use
admin_pass = var.admin_pass == null ? local.generated_admin_password : var.admin_pass
}
Expand Down Expand Up @@ -315,21 +310,20 @@ locals {
#######################################################################################################################

locals {
create_secret_manager_auth_policy = var.skip_mongodb_secret_manager_auth_policy || var.existing_secrets_manager_instance_crn == null ? 0 : 1
create_secrets_manager_auth_policy = var.skip_mongodb_secrets_manager_auth_policy || var.existing_secrets_manager_instance_crn == null ? 0 : 1
}

# Parse the Secrets Manager CRN
module "secret_manager_instance_crn_parser" {
module "secrets_manager_instance_crn_parser" {
count = var.existing_secrets_manager_instance_crn != null ? 1 : 0
source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser"
version = "1.1.0"
crn = var.existing_secrets_manager_instance_crn
}


# create a service authorization between Secrets Manager and the target service (Databases for MongoDB)
resource "ibm_iam_authorization_policy" "secrets_manager_key_manager" {
count = local.create_secret_manager_auth_policy
count = local.create_secrets_manager_auth_policy
depends_on = [module.mongodb]
source_service_name = "secrets-manager"
source_resource_instance_id = local.existing_secrets_manager_instance_guid
Expand All @@ -341,7 +335,7 @@ resource "ibm_iam_authorization_policy" "secrets_manager_key_manager" {

# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478
resource "time_sleep" "wait_for_mongodb_authorization_policy" {
count = local.create_secret_manager_auth_policy
count = local.create_secrets_manager_auth_policy
depends_on = [ibm_iam_authorization_policy.secrets_manager_key_manager]
create_duration = "30s"
}
Expand Down Expand Up @@ -371,10 +365,10 @@ locals {

# Build the structure of the arbitrary credential type secret for admin password
admin_pass_secret = [{
secret_group_name = (var.prefix != null && var.prefix != "") && var.admin_pass_secret_manager_secret_group != null ? "${var.prefix}-${var.admin_pass_secret_manager_secret_group}" : var.admin_pass_secret_manager_secret_group
existing_secret_group = var.use_existing_admin_pass_secret_manager_secret_group
secret_group_name = (var.prefix != null && var.prefix != "") && var.admin_pass_secrets_manager_secret_group != null ? "${var.prefix}-${var.admin_pass_secrets_manager_secret_group}" : var.admin_pass_secrets_manager_secret_group
existing_secret_group = var.use_existing_admin_pass_secrets_manager_secret_group
secrets = [{
secret_name = (var.prefix != null && var.prefix != "") && var.admin_pass_secret_manager_secret_name != null ? "${var.prefix}-${var.admin_pass_secret_manager_secret_name}" : var.admin_pass_secret_manager_secret_name
secret_name = (var.prefix != null && var.prefix != "") && var.admin_pass_secrets_manager_secret_name != null ? "${var.prefix}-${var.admin_pass_secrets_manager_secret_name}" : var.admin_pass_secrets_manager_secret_name
secret_type = "arbitrary"
secret_payload_password = local.admin_pass
}
Expand All @@ -384,8 +378,8 @@ locals {
# Concatinate into 1 secrets object
secrets = concat(local.service_credential_secrets, local.admin_pass_secret)
# Parse Secrets Manager details from the CRN
existing_secrets_manager_instance_guid = var.existing_secrets_manager_instance_crn != null ? module.secret_manager_instance_crn_parser[0].service_instance : null
existing_secrets_manager_instance_region = var.existing_secrets_manager_instance_crn != null ? module.secret_manager_instance_crn_parser[0].region : null
existing_secrets_manager_instance_guid = var.existing_secrets_manager_instance_crn != null ? module.secrets_manager_instance_crn_parser[0].service_instance : null
existing_secrets_manager_instance_region = var.existing_secrets_manager_instance_crn != null ? module.secrets_manager_instance_crn_parser[0].region : null
}

module "secrets_manager_service_credentials" {
Expand Down
19 changes: 11 additions & 8 deletions solutions/standard/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ variable "kms_endpoint_type" {
type = string
description = "The type of endpoint to use for communicating with the Key Protect or Hyper Protect Crypto Services instance. Possible values: `public`, `private`. Applies only if `existing_kms_key_crn` is not specified."
default = "private"

validation {
condition = can(regex("public|private", var.kms_endpoint_type))
error_message = "The kms_endpoint_type value must be 'public' or 'private'."
Expand Down Expand Up @@ -304,6 +305,7 @@ variable "existing_secrets_manager_endpoint_type" {
type = string
description = "The endpoint type to use if `existing_secrets_manager_instance_crn` is specified. Possible values: public, private."
default = "private"

validation {
condition = contains(["public", "private"], var.existing_secrets_manager_endpoint_type)
error_message = "Only \"public\" and \"private\" are allowed values for 'existing_secrets_endpoint_type'."
Expand Down Expand Up @@ -350,41 +352,42 @@ variable "service_credential_secrets" {
}
}

variable "skip_mongodb_secret_manager_auth_policy" {
variable "skip_mongodb_secrets_manager_auth_policy" {
type = bool
description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Databases for MongoDB. If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the MongoDB instance created by the Deployable Architecture. Set to `true` to use an existing policy. The value of this is ignored if any value for 'existing_secrets_manager_instance_crn' is not passed."
default = false
}

variable "admin_pass_secret_manager_secret_group" {
variable "admin_pass_secrets_manager_secret_group" {
type = string
description = "The name of a new or existing secrets manager secret group for admin password. To use existing secret group, `use_existing_admin_pass_secrets_manager_secret_group` must be set to `true`. If a prefix input variable is specified, the prefix is added to the name in the `<prefix>-<name>` format."
default = "mongodb-secrets"

validation {
condition = (
var.existing_secrets_manager_instance_crn == null ||
var.admin_pass_secret_manager_secret_group != null
var.admin_pass_secrets_manager_secret_group != null
)
error_message = "`admin_pass_secret_manager_secret_group` is required when `existing_secrets_manager_instance_crn` is set."
error_message = "`admin_pass_secrets_manager_secret_group` is required when `existing_secrets_manager_instance_crn` is set."
}
}

variable "use_existing_admin_pass_secret_manager_secret_group" {
variable "use_existing_admin_pass_secrets_manager_secret_group" {
type = bool
description = "Whether to use an existing secrets manager secret group for admin password."
default = false
}

variable "admin_pass_secret_manager_secret_name" {
variable "admin_pass_secrets_manager_secret_name" {
type = string
description = "The name of a new mongodb administrator secret. If a prefix input variable is specified, the prefix is added to the name in the `<prefix>-<name>` format."
default = "mongodb-admin-password"

validation {
condition = (
var.existing_secrets_manager_instance_crn == null ||
var.admin_pass_secret_manager_secret_name != null
var.admin_pass_secrets_manager_secret_name != null
)
error_message = "`admin_pass_secret_manager_secret_name` is required when `existing_secrets_manager_instance_crn` is set."
error_message = "`admin_pass_secrets_manager_secret_name` is required when `existing_secrets_manager_instance_crn` is set."
}
}
41 changes: 41 additions & 0 deletions tests/other_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
package test

import (
"crypto/rand"
"encoding/base64"
"fmt"

"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testhelper"
)

Expand Down Expand Up @@ -55,3 +58,41 @@ func TestRunRestoredDBExample(t *testing.T) {
assert.Nil(t, err, "This should not have errored")
assert.NotNil(t, output, "Expected some output")
}

func TestRunCompleteExample(t *testing.T) {
t.Parallel()

options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{
Testing: t,
TerraformDir: "examples/complete",
Prefix: "mongodb-upg",
BestRegionYAMLPath: regionSelectionPath,
ResourceGroup: resourceGroup,
TerraformVars: map[string]interface{}{
"mongodb_version": "6.0", // Always lock to the lowest supported MongoDB version
"plan": "standard",
"users": []map[string]interface{}{
{
"name": "testuser",
"password": GetRandomAdminPassword(t),
"type": "database",
},
},
"admin_pass": GetRandomAdminPassword(t),
},
CloudInfoService: sharedInfoSvc,
})

output, err := options.RunTestConsistency()
assert.Nil(t, err, "This should not have errored")
assert.NotNil(t, output, "Expected some output")
}

func GetRandomAdminPassword(t *testing.T) string {
// Generate a 15 char long random string for the admin_pass
randomBytes := make([]byte, 13)
_, randErr := rand.Read(randomBytes)
require.Nil(t, randErr) // do not proceed if we can't gen a random password
randomPass := "A1" + base64.URLEncoding.EncodeToString(randomBytes)[:13]
return randomPass
}
4 changes: 2 additions & 2 deletions tests/pr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ func TestRunStandardSolutionSchematics(t *testing.T) {
{Name: "service_credential_names", Value: "{\"admin_test\": \"Administrator\", \"editor_test\": \"Editor\"}", DataType: "map(string)"},
{Name: "existing_secrets_manager_instance_crn", Value: permanentResources["secretsManagerCRN"], DataType: "string"},
{Name: "service_credential_secrets", Value: serviceCredentialSecrets, DataType: "list(object)"},
{Name: "admin_pass_secret_manager_secret_group", Value: options.Prefix, DataType: "string"},
{Name: "admin_pass_secret_manager_secret_name", Value: options.Prefix, DataType: "string"},
{Name: "admin_pass_secrets_manager_secret_group", Value: options.Prefix, DataType: "string"},
{Name: "admin_pass_secrets_manager_secret_name", Value: options.Prefix, DataType: "string"},
{Name: "provider_visibility", Value: "private", DataType: "string"},
{Name: "prefix", Value: options.Prefix, DataType: "string"},
}
Expand Down