diff --git a/released/discovery_center/mission_4172/README.md b/released/discovery_center/mission_4172/README.md deleted file mode 100644 index aaf708d9..00000000 --- a/released/discovery_center/mission_4172/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Discovery Center Mission: Build Events-to-Business Actions Apps with SAP BTP and MS Azure/AWS (4172) - -## Overview - -This sample shows how to create a landscape for the Discovery Center Mission - [Build Events-to-Business Actions Apps with SAP BTP and MS Azure/AWS](https://discovery-center.cloud.sap/missiondetail/4172/) - -## Content of setup - -The setup comprises the following resources: - -- Creation of the SAP BTP subaccount -- Entitlements of services -- Subscriptions to applications -- Role collection assignments to users -- Creation of CF environments -- Management of users and roles on org and space level - -## Deploying the resources - -To deploy the resources you must: - -1. Export environment variables BTP_USERNAME, BTP_PASSWORD, CF_USER, and CF_PASSWORD with your username and password for the custom IdP of your global account. - -2. Change the variables in the `samples.tfvars` file in the main folder to meet your requirements - - > ⚠ NOTE: You should pay attention **specifically** to the users defined in the samples.tfvars whether they already exist in your SAP BTP accounts. Otherwise you might get error messages like e.g. `Error: The user could not be found: jane.doe@test.com`. - -3. Execute the apply.sh script. - -4. Verify e.g., in BTP cockpit that a new subaccount with a integration suite, SAP Business Application Studio, CF environment instance and a CF space have been created. - -5. Clean up by running the destroy.sh script. \ No newline at end of file diff --git a/released/discovery_center/mission_4172/apply.sh b/released/discovery_center/mission_4172/apply.sh deleted file mode 100755 index fb333585..00000000 --- a/released/discovery_center/mission_4172/apply.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -cd step1 - -terraform init -terraform apply -var-file='../samples.tfvars' -auto-approve -terraform output > ../step2/step1vars.tfvars - -cd ../step2 - -terraform init -terraform apply -var-file=step1vars.tfvars -var-file='../samples.tfvars' -auto-approve - -cd .. \ No newline at end of file diff --git a/released/discovery_center/mission_4172/destroy.sh b/released/discovery_center/mission_4172/destroy.sh deleted file mode 100755 index c149b746..00000000 --- a/released/discovery_center/mission_4172/destroy.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -cd step2 - -terraform destroy -var-file=step1vars.tfvars -var-file='../samples.tfvars' -auto-approve -rm step1vars.tfvars - -cd ../step1 - -terraform destroy -var-file='../samples.tfvars' -auto-approve - -cd .. \ No newline at end of file diff --git a/released/discovery_center/mission_4172/step1/README.md b/released/discovery_center/mission_4172/step1/README.md new file mode 100644 index 00000000..b49a91be --- /dev/null +++ b/released/discovery_center/mission_4172/step1/README.md @@ -0,0 +1,62 @@ +# Discovery Center Mission: Build Events-to-Business Actions Apps with SAP BTP and MS Azure/AWS (4172) - Step 1 + +## Overview + +This sample shows how to create a landscape for the Discovery Center Mission - [Build Events-to-Business Actions Apps with SAP BTP and MS Azure/AWS](https://discovery-center.cloud.sap/missiondetail/4172/) + +## Content of setup + +The setup comprises the following resources: + +- Creation of the SAP BTP subaccount +- Entitlements of services +- Subscriptions to applications +- Role collection assignments to users +- Creation of CF environments +- Management of users and roles on org and space level + +## Deploying the resources + +To deploy the resources you must: + +1. Set your credentials as environment variables + + ```bash + export BTP_USERNAME ='' + export BTP_PASSWORD ='' + export CF_USER ='' + export CF_PASSWORD ='' + ``` + +2. Change the variables in the `sample.tfvars` file in the main folder to meet your requirements + + > The minimal set of parameters you should specify (besides user_email and password) is global account (i.e. its subdomain) and the used custom_idp and all user assignments + + > ⚠ NOTE: You should pay attention **specifically** to the users defined in the sample.tfvars whether they already exist in your SAP BTP accounts. Otherwise, you might get error messages like, e.g., `Error: The user could not be found: jane.doe@test.com`. + + +3. Initialize your workspace: + + ```bash + terraform init + ``` + +4. You can check what Terraform plans to apply based on your configuration: + + ```bash + terraform plan -var-file="sample.tfvars" + ``` + +5. Apply your configuration to provision the resources: + + ```bash + terraform apply -var-file="sample.tfvars" + ``` + +## In the end + +You probably want to remove the assets after trying them out to avoid unnecessary costs. To do so execute the following command: + +```bash +terraform destroy -var-file="sample.tfvars" +``` \ No newline at end of file diff --git a/released/discovery_center/mission_4172/step1/locals.tf b/released/discovery_center/mission_4172/step1/locals.tf deleted file mode 100644 index 00e26833..00000000 --- a/released/discovery_center/mission_4172/step1/locals.tf +++ /dev/null @@ -1,5 +0,0 @@ -locals { - service__sap_business_app_studio = "sapappstudio" - service_name__hana_cloud_tools = "hana-cloud-tools" - service_name__sap_process_automation = "process-automation" -} \ No newline at end of file diff --git a/released/discovery_center/mission_4172/step1/main.tf b/released/discovery_center/mission_4172/step1/main.tf index caa94721..4a55f9ba 100644 --- a/released/discovery_center/mission_4172/step1/main.tf +++ b/released/discovery_center/mission_4172/step1/main.tf @@ -1,55 +1,80 @@ -############################################################################################### +# ------------------------------------------------------------------------------------------------------ # Setup of names in accordance to naming convention -############################################################################################### +# ------------------------------------------------------------------------------------------------------ resource "random_uuid" "uuid" {} locals { - random_uuid = random_uuid.uuid.result - project_subaccount_domain = lower(replace("mission-4172-${local.random_uuid}", "_", "-")) - project_subaccount_cf_org = substr(replace("${local.project_subaccount_domain}", "-", ""), 0, 32) + random_uuid = random_uuid.uuid.result + subaccount_domain = lower(replace("mission-4172-${local.random_uuid}", "_", "-")) + subaccount_cf_org = substr(replace("${local.subaccount_domain}", "-", ""), 0, 32) +} + +locals { + service__sap_business_app_studio = "sapappstudio" + service_name__hana_cloud_tools = "hana-cloud-tools" + service_name__sap_process_automation = "process-automation" } -############################################################################################### +# ------------------------------------------------------------------------------------------------------ # Creation of subaccount -############################################################################################### -resource "btp_subaccount" "project" { +# ------------------------------------------------------------------------------------------------------ +resource "btp_subaccount" "dc_mission" { count = var.subaccount_id == "" ? 1 : 0 name = var.subaccount_name - subdomain = local.project_subaccount_domain + subdomain = local.subaccount_domain region = lower(var.region) usage = "USED_FOR_PRODUCTION" } -data "btp_subaccount" "project" { - id = var.subaccount_id != "" ? var.subaccount_id : btp_subaccount.project[0].id +data "btp_subaccount" "dc_mission" { + id = var.subaccount_id != "" ? var.subaccount_id : btp_subaccount.dc_mission[0].id +} + + +# ------------------------------------------------------------------------------------------------------ +# Assign custom IDP to sub account (if custom_idp is set) +# ------------------------------------------------------------------------------------------------------ +resource "btp_subaccount_trust_configuration" "fully_customized" { + # Only create trust configuration if custom_idp has been set + count = var.custom_idp == "" ? 0 : 1 + subaccount_id = data.btp_subaccount.dc_mission.id + identity_provider = var.custom_idp +} + +locals { + custom_idp_tenant = var.custom_idp != "" ? element(split(".", var.custom_idp), 0) : "" + origin_key = local.custom_idp_tenant != "" ? "${local.custom_idp_tenant}-platform" : "sap.default" + origin_key_app_users = var.custom_idp != "" ? var.custom_idp_apps_origin_key : "sap.default" } -############################################################################################### +# ------------------------------------------------------------------------------------------------------ # Assignment of users as sub account administrators -############################################################################################### +# ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_role_collection_assignment" "subaccount-admins" { - for_each = toset("${var.subaccount_admins}") - subaccount_id = data.btp_subaccount.project.id + for_each = toset(var.subaccount_admins) + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Subaccount Administrator" + origin = local.origin_key user_name = each.value } -############################################################################################### +# ------------------------------------------------------------------------------------------------------ # Assignment of users as sub account service administrators -############################################################################################### +# ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_role_collection_assignment" "subaccount-service-admins" { - for_each = toset("${var.subaccount_service_admins}") - subaccount_id = data.btp_subaccount.project.id + for_each = toset(var.subaccount_service_admins) + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Subaccount Service Administrator" + origin = local.origin_key user_name = each.value } -###################################################################### +# ------------------------------------------------------------------------------------------------------ # Extract list of CF landscape labels from environments -###################################################################### +# ------------------------------------------------------------------------------------------------------ data "btp_subaccount_environments" "all" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id } # Take the landscape label from the first CF environment if no environment label is provided @@ -57,47 +82,34 @@ resource "terraform_data" "cf_landscape_label" { input = length(var.cf_landscape_label) > 0 ? var.cf_landscape_label : [for env in data.btp_subaccount_environments.all.values : env if env.service_name == "cloudfoundry" && env.environment_type == "cloudfoundry"][0].landscape_label } -###################################################################### +# ------------------------------------------------------------------------------------------------------ # Creation of Cloud Foundry environment -###################################################################### +# ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_environment_instance" "cloudfoundry" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id name = var.cf_org_name environment_type = "cloudfoundry" service_name = "cloudfoundry" plan_name = "standard" landscape_label = terraform_data.cf_landscape_label.output parameters = jsonencode({ - instance_name = local.project_subaccount_cf_org + instance_name = local.subaccount_cf_org }) } -###################################################################### -# Entitlement of all general services -###################################################################### -resource "btp_subaccount_entitlement" "genentitlements" { - for_each = { - for index, entitlement in var.entitlements : - index => entitlement - } - subaccount_id = data.btp_subaccount.project.id - service_name = each.value.service_name - plan_name = each.value.plan_name -} - -# ###################################################################### +# # ------------------------------------------------------------------------------------------------------ # # Create app subscription to SAP Business APplication Studio -# ###################################################################### +# # ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "bas" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = local.service__sap_business_app_studio plan_name = var.service_plan__sap_business_app_studio } # Create app subscription to busineass applicaiton stuido resource "btp_subaccount_subscription" "bas" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id app_name = local.service__sap_business_app_studio plan_name = var.service_plan__sap_business_app_studio depends_on = [btp_subaccount_entitlement.bas] @@ -106,36 +118,18 @@ resource "btp_subaccount_subscription" "bas" { resource "btp_subaccount_role_collection_assignment" "bas_dev" { depends_on = [btp_subaccount_subscription.bas] for_each = toset(var.appstudio_developers) - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Business_Application_Studio_Developer" + origin = local.origin_key_app_users user_name = each.value } resource "btp_subaccount_role_collection_assignment" "bas_admn" { depends_on = [btp_subaccount_subscription.bas] for_each = toset(var.appstudio_admins) - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Business_Application_Studio_Administrator" - user_name = each.value -} - -###################################################################### -# Assign other Role Collection -###################################################################### - -resource "btp_subaccount_role_collection_assignment" "cloud_conn_admn" { - depends_on = [btp_subaccount_entitlement.genentitlements] - for_each = toset(var.cloudconnector_admins) - subaccount_id = data.btp_subaccount.project.id - role_collection_name = "Cloud Connector Administrator" - user_name = each.value -} - -resource "btp_subaccount_role_collection_assignment" "conn_dest_admn" { - depends_on = [btp_subaccount_entitlement.genentitlements] - for_each = toset(var.conn_dest_admins) - subaccount_id = data.btp_subaccount.project.id - role_collection_name = "Connectivity and Destination Administrator" + origin = local.origin_key_app_users user_name = each.value } @@ -143,13 +137,13 @@ resource "btp_subaccount_role_collection_assignment" "conn_dest_admn" { # Entitle subaccount for usage of SAP HANA Cloud tools # ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "hana_cloud_tools" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = local.service_name__hana_cloud_tools plan_name = "tools" } resource "btp_subaccount_subscription" "hana_cloud_tools" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id app_name = local.service_name__hana_cloud_tools plan_name = "tools" depends_on = [btp_subaccount_entitlement.hana_cloud_tools] @@ -157,10 +151,10 @@ resource "btp_subaccount_subscription" "hana_cloud_tools" { # Assign users to Role Collection: SAP HANA Cloud Administrator resource "btp_subaccount_role_collection_assignment" "hana_cloud_admin" { - for_each = toset(var.hana_cloud_admins) - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "SAP HANA Cloud Administrator" - user_name = each.value + user_name = var.hana_system_admin + origin = local.origin_key_app_users depends_on = [btp_subaccount_subscription.hana_cloud_tools] } @@ -168,21 +162,21 @@ resource "btp_subaccount_role_collection_assignment" "hana_cloud_admin" { # Entitle subaccount for usage of SAP HANA Cloud # ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "hana_cloud" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = "hana-cloud" plan_name = "hana" } # Get plan for SAP HANA Cloud data "btp_subaccount_service_plan" "hana_cloud" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id offering_name = "hana-cloud" name = "hana" depends_on = [btp_subaccount_entitlement.hana_cloud] } resource "btp_subaccount_service_instance" "hana_cloud" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id serviceplan_id = data.btp_subaccount_service_plan.hana_cloud.id name = "my-hana-cloud-instance" depends_on = [btp_subaccount_entitlement.hana_cloud] @@ -217,24 +211,24 @@ resource "btp_subaccount_service_instance" "hana_cloud" { # Create service binding to SAP HANA Cloud service resource "btp_subaccount_service_binding" "hana_cloud" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id service_instance_id = btp_subaccount_service_instance.hana_cloud.id name = "hana-cloud-key" } -# ###################################################################### +# # ------------------------------------------------------------------------------------------------------ # # Create app subscription to SAP Build Process Automation -# ###################################################################### +# # ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "build_process_automation" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = local.service_name__sap_process_automation plan_name = var.service_plan__sap_process_automation } -# Create app subscription to SAP Build Workzone, standard edition (depends on entitlement) +# Create app subscription to SAP Build Process Automation (depends on entitlement) resource "btp_subaccount_subscription" "build_process_automation" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id app_name = local.service_name__sap_process_automation plan_name = var.service_plan__sap_process_automation depends_on = [btp_subaccount_entitlement.build_process_automation] @@ -243,61 +237,96 @@ resource "btp_subaccount_subscription" "build_process_automation" { resource "btp_subaccount_role_collection_assignment" "sbpa_admin" { depends_on = [btp_subaccount_subscription.build_process_automation] for_each = toset(var.process_automation_admins) - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "ProcessAutomationAdmin" + origin = local.origin_key_app_users user_name = each.value } resource "btp_subaccount_role_collection_assignment" "sbpa_dev" { depends_on = [btp_subaccount_subscription.build_process_automation] for_each = toset(var.process_automation_developers) - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "ProcessAutomationDeveloper" + origin = local.origin_key_app_users user_name = each.value } resource "btp_subaccount_role_collection_assignment" "sbpa_part" { depends_on = [btp_subaccount_subscription.build_process_automation] for_each = toset(var.process_automation_participants) - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "ProcessAutomationParticipant" + origin = local.origin_key_app_users user_name = each.value } -###################################################################### +# ------------------------------------------------------------------------------------------------------ # Event Mesh -###################################################################### +# ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "event_mesh" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = "enterprise-messaging" plan_name = "default" } resource "btp_subaccount_entitlement" "event_mesh_application" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = "enterprise-messaging-hub" plan_name = "standard" } resource "btp_subaccount_subscription" "event_mesh_application" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id app_name = "enterprise-messaging-hub" plan_name = "standard" depends_on = [btp_subaccount_entitlement.event_mesh_application] } resource "btp_subaccount_role_collection_assignment" "event_mesh_admin" { - depends_on = [btp_subaccount_entitlement.event_mesh_application] + depends_on = [btp_subaccount_subscription.event_mesh_application] for_each = toset(var.event_mesh_admins) - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Enterprise Messaging Administrator" + origin = local.origin_key_app_users user_name = each.value } resource "btp_subaccount_role_collection_assignment" "event_mesh_developer" { - depends_on = [btp_subaccount_entitlement.event_mesh_application] + depends_on = [btp_subaccount_subscription.event_mesh_application] for_each = toset(var.event_mesh_developers) - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Enterprise Messaging Developer" + origin = local.origin_key_app_users user_name = each.value } + + +# ------------------------------------------------------------------------------------------------------ +# Create tfvars file for step 2 (if variable `create_tfvars_file_for_step2` is set to true) +# ------------------------------------------------------------------------------------------------------ +resource "local_file" "output_vars_step1" { + count = var.create_tfvars_file_for_step2 ? 1 : 0 + content = <<-EOT + globalaccount = "${var.globalaccount}" + cli_server_url = ${jsonencode(var.cli_server_url)} + custom_idp = ${jsonencode(var.custom_idp)} + + subaccount_id = "${data.btp_subaccount.dc_mission.id}" + + cf_api_url = "${jsondecode(btp_subaccount_environment_instance.cloudfoundry.labels)["API Endpoint"]}" + + cf_org_id = "${jsondecode(btp_subaccount_environment_instance.cloudfoundry.labels)["Org ID"]}" + cf_org_name = "${jsondecode(btp_subaccount_environment_instance.cloudfoundry.labels)["Org Name"]}" + + cf_space_name = "${var.cf_space_name}" + + cf_org_users = ${jsonencode(var.cf_org_users)} + cf_org_admins = ${jsonencode(var.cf_org_admins)} + cf_space_developers = ${jsonencode(var.cf_space_developers)} + cf_space_managers = ${jsonencode(var.cf_space_managers)} + + + EOT + filename = "../step2/terraform.tfvars" +} \ No newline at end of file diff --git a/released/discovery_center/mission_4172/step1/outputs.tf b/released/discovery_center/mission_4172/step1/outputs.tf index 56f90f7b..5f893f04 100644 --- a/released/discovery_center/mission_4172/step1/outputs.tf +++ b/released/discovery_center/mission_4172/step1/outputs.tf @@ -11,5 +11,21 @@ output "cf_org_id" { } output "subaccount_id" { - value = data.btp_subaccount.project.id + value = data.btp_subaccount.dc_mission.id +} + +output "bas_url" { + value = btp_subaccount_subscription.bas.subscription_url +} + +output "hana_cloud_tools_url" { + value = btp_subaccount_subscription.hana_cloud_tools.subscription_url +} + +output "event_mesh_application_url" { + value = btp_subaccount_subscription.event_mesh_application.subscription_url +} + +output "build_process_automation_url" { + value = btp_subaccount_subscription.build_process_automation.subscription_url } \ No newline at end of file diff --git a/released/discovery_center/mission_4172/samples.tfvars b/released/discovery_center/mission_4172/step1/sample.tfvars similarity index 73% rename from released/discovery_center/mission_4172/samples.tfvars rename to released/discovery_center/mission_4172/step1/sample.tfvars index adf8e887..0766ca39 100644 --- a/released/discovery_center/mission_4172/samples.tfvars +++ b/released/discovery_center/mission_4172/step1/sample.tfvars @@ -1,15 +1,13 @@ globalaccount = "myglobalaccount" region = "us10" subaccount_name = "Discovery Center mission - Build Events-to-Business actions" -cf_org_name = "cf-environment" +custom_idp = ".accounts.ondemand.com" subaccount_admins = ["john.doe@sap.com"] subaccount_service_admins = ["john.doe@sap.com"] -appstudio_developers = ["john.doe@sap.com"] -appstudio_admins = ["john.doe@sap.com"] -cloudconnector_admins = ["john.doe@sap.com"] -conn_dest_admins = ["john.doe@sap.com"] +appstudio_developers = ["john.doe@sap.com"] +appstudio_admins = ["john.doe@sap.com"] cf_space_developers = ["john.doe@sap.com"] cf_space_managers = ["john.doe@sap.com"] @@ -17,7 +15,7 @@ cf_org_admins = ["john.doe@sap.com"] cf_org_users = ["john.doe@sap.com"] hana_system_password = "Abc12345" -hana_cloud_admins = ["john.doe@sap.com"] +hana_system_admin = "john.doe@sap.com" process_automation_admins = ["john.doe@sap.com"] process_automation_developers = ["john.doe@sap.com"] diff --git a/released/discovery_center/mission_4172/step1/variables.tf b/released/discovery_center/mission_4172/step1/variables.tf index 3027e9e0..5bab453c 100644 --- a/released/discovery_center/mission_4172/step1/variables.tf +++ b/released/discovery_center/mission_4172/step1/variables.tf @@ -49,27 +49,42 @@ variable "cli_server_url" { default = "https://cli.btp.cloud.sap" } +variable "custom_idp" { + type = string + description = "The custom identity provider for the subaccount." + default = "" +} + +variable "custom_idp_apps_origin_key" { + type = string + description = "The custom identity provider for the subaccount." + default = "sap.custom" +} + +variable "origin" { + type = string + description = "Defines the origin key of the identity provider" + default = "sap.ids" + # The value for the origin_key can be defined + # but are normally set to "sap.ids", "sap.default" or "sap.custom" +} + +variable "origin_key" { + type = string + description = "Defines the origin key of the identity provider" + default = "" + # The value for the origin_key can be defined, set to "sap.ids", "sap.default" or "sap.custom" +} + # subaccount variables variable "subaccount_admins" { type = list(string) description = "Defines the colleagues who are added to each subaccount as subaccount administrators." - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if admins contains a list of valid email addresses - validation { - condition = length([for email in var.subaccount_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) - error_message = "Please enter a valid email address for the Subaccount Admins." - } } variable "subaccount_service_admins" { type = list(string) description = "Defines the colleagues who are added to each subaccount as subaccount service administrators." - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if admins contains a list of valid email addresses - validation { - condition = length([for email in var.subaccount_service_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_service_admins) - error_message = "Please enter a valid email address for the Subaccount service Admins." - } } variable "service_plan__sap_business_app_studio" { @@ -82,94 +97,19 @@ variable "service_plan__sap_business_app_studio" { } } -### -# Entitlements -### -variable "entitlements" { - type = list(object({ - service_name = string - plan_name = string - type = string - })) - description = "The list of entitlements that shall be added to the subaccount." - default = [ - { - service_name = "connectivity" - plan_name = "lite", - type = "service" - }, - { - service_name = "destination" - plan_name = "lite", - type = "service" - }, - { - service_name = "html5-apps-repo" - plan_name = "app-host", - type = "service" - }, - { - service_name = "xsuaa" - plan_name = "application", - type = "service" - } - ] -} - variable "appstudio_developers" { type = list(string) description = "Business Application Studio Developers" - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if Business Application Studio Developers contains a list of valid email addresses - validation { - condition = length([for email in var.appstudio_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.appstudio_developers) - error_message = "Please enter a valid email address for the Business Application Studio Developers" - } } variable "appstudio_admins" { type = list(string) description = "Business Application Studio Administrators" - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if Business Application Studio Administrators contains a list of valid email addresses - validation { - condition = length([for email in var.appstudio_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.appstudio_admins) - error_message = "Please enter a valid email address for the Business Application Studio Administrators." - } -} - -variable "cloudconnector_admins" { - type = list(string) - description = "Cloud Connector Administrators" - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if Cloud Connector Administrators contains a list of valid email addresses - validation { - condition = length([for email in var.cloudconnector_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cloudconnector_admins) - error_message = "Please enter a valid email address for the Cloud Connector Administrators." - } -} - -variable "conn_dest_admins" { - type = list(string) - description = "Connectivity and Destination Administrators" - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if Connectivity and Destination Administrators contains a list of valid email addresses - validation { - condition = length([for email in var.conn_dest_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.conn_dest_admins) - error_message = "Please enter a valid email address for the Connectivity and Destination Administrators." - } } -variable "hana_cloud_admins" { - type = list(string) - description = "Defines the colleagues who are added as admins to access the instance of SAP HANA Cloud." - default = ["jane.doe@test.com", "john.doe@test.com"] - - # add validation to check if admins contains a list of valid email addresses - validation { - condition = length([for email in var.hana_cloud_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.hana_cloud_admins) - error_message = "Please enter a valid email address for the admins of SAP HANA Cloud instance." - } +variable "hana_system_admin" { + type = string + description = "Defines the colleague who is added as an admin to access the instance of SAP HANA Cloud." } @@ -224,56 +164,67 @@ variable "service_plan__sap_process_automation" { variable "process_automation_admins" { type = list(string) description = "SAP Build Process Automation Administrators" - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if SAP Build Process Automation Administrators contains a list of valid email addresses - validation { - condition = length([for email in var.process_automation_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.process_automation_admins) - error_message = "Please enter a valid email address for the SAP Build Process Automation Administrators." - } } variable "process_automation_developers" { type = list(string) description = "SAP Build Process Automation Developers" - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if SAP Build Process Automation Developers contains a list of valid email addresses - validation { - condition = length([for email in var.process_automation_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.process_automation_developers) - error_message = "Please enter a valid email address for the SAP Build Process Automation Developers." - } } variable "process_automation_participants" { type = list(string) description = "SAP Build Process Automation Participants" - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if SAP Build Process Automation Participants contains a list of valid email addresses - validation { - condition = length([for email in var.process_automation_participants : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.process_automation_participants) - error_message = "Please enter a valid email address for the SAP Build Process Automation Participants." - } } variable "event_mesh_admins" { type = list(string) description = "Enterprise Messaging Administrators" - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if admins contains a list of valid email addresses - validation { - condition = length([for email in var.event_mesh_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.event_mesh_admins) - error_message = "Please enter a valid email address for the Enterprise Messaging Administrators." - } } variable "event_mesh_developers" { type = list(string) description = "Enterprise Messaging Developers" - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if Enterprise Messaging Developers contains a list of valid email addresses +} + +# ------------------------------------------------------------------------------------------------------ +# Switch for creating tfvars for step 2 +# ------------------------------------------------------------------------------------------------------ +variable "create_tfvars_file_for_step2" { + type = bool + description = "Switch to enable the creation of the tfvars file for step 2." + default = true +} + +variable "cf_space_name" { + type = string + description = "Name of the Cloud Foundry space." + default = "dev" + validation { - condition = length([for email in var.event_mesh_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.event_mesh_developers) - error_message = "Please enter a valid email address for the Enterprise Messaging Developers." + condition = can(regex("^.{1,255}$", var.cf_space_name)) + error_message = "The Cloud Foundry space name must not be emtpy and not exceed 255 characters." } } +variable "cf_org_admins" { + type = list(string) + description = "List of users to set as Cloudfoundry org administrators." +} + +variable "cf_org_users" { + type = list(string) + description = "List of users to set as Cloudfoundry org users." +} + +variable "cf_space_managers" { + type = list(string) + description = "Defines the colleagues who are added to a CF space as space manager." +} + +variable "cf_space_developers" { + type = list(string) + description = "Defines the colleagues who are added to a CF space as space developer." +} + + diff --git a/released/discovery_center/mission_4172/step2/README.md b/released/discovery_center/mission_4172/step2/README.md new file mode 100644 index 00000000..35ad8763 --- /dev/null +++ b/released/discovery_center/mission_4172/step2/README.md @@ -0,0 +1,38 @@ +# Discovery Center Mission: Build Events-to-Business Actions Apps with SAP BTP and MS Azure/AWS (4172) - Step 2 + +## Overview + +This script shows how to create a SAP BTP subaccount forDiscovery Center Mission: Build Events-to-Business Actions Apps with SAP BTP and MS Azure/AWS (4172). Step 2 comprises all activities that depend on the step 1 completion. + +## Deploying the resources + +To deploy the resources you must: + + +1. If you did not create a `tfvars` file in step 1 (via the variable `create_tfvars_file_for_step2`) you must manually Take the output of step 1 and transfer it in a `tfvars` file e.g. `sample.tfvars` file to meet your requirements. Of course you can also further adjust the generated `tfvars` file from step 1. + +2. If not already done in step 1, initialize your workspace: + + ```bash + terraform init + ``` + +3. You can check what Terraform plans to apply based on your configuration. If you use the generated `tfvars` file from step 1 you do not need need to explicitly add the filename to the command: + + ```bash + terraform plan -var-file="terraform.tfvars" + ``` + +4. According to the variants of step 3. apply your configuration to provision the resources either via: + + ```bash + terraform apply -var-file="terraform.tfvars" + ``` + +## In the end + +You probably want to remove the assets after trying them out to avoid unnecessary costs. To do so execute the command fitting your setup: + +```bash +terraform destroy -var-file="terraform.tfvars" +``` diff --git a/released/discovery_center/mission_4172/step2/main.tf b/released/discovery_center/mission_4172/step2/main.tf index b4812ee4..239624be 100644 --- a/released/discovery_center/mission_4172/step2/main.tf +++ b/released/discovery_center/mission_4172/step2/main.tf @@ -1,26 +1,65 @@ -###################################################################### +# ------------------------------------------------------------------------------------------------------ +# Import custom trust config and disable for user login +# ------------------------------------------------------------------------------------------------------ +locals { + available_for_user_logon = var.custom_idp != "" ? false : true +} + +import { + to = btp_subaccount_trust_configuration.default + id = "${var.subaccount_id},sap.default" +} + +resource "btp_subaccount_trust_configuration" "default" { + subaccount_id = var.subaccount_id + identity_provider = "" + auto_create_shadow_users = false + available_for_user_logon = local.available_for_user_logon +} + +# ------------------------------------------------------------------------------------------------------ # Create space using CF provider -###################################################################### +# ------------------------------------------------------------------------------------------------------ resource "cloudfoundry_space" "dev" { - name = "DEV" + name = var.cf_space_name org = var.cf_org_id } -###################################################################### +# ------------------------------------------------------------------------------------------------------ +# SETUP ALL SERVICES FOR CF USAGE +# ------------------------------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------------------------------ +# USERS AND ROLES +# ------------------------------------------------------------------------------------------------------ +data "btp_whoami" "me" {} + +locals { + # Remove current user if issuer (idp) of logged in user is not same as used custom idp + cf_org_admins = data.btp_whoami.me.issuer != var.custom_idp ? var.cf_org_admins : setsubtract(toset(var.cf_org_admins), [data.btp_whoami.me.email]) + cf_org_users = data.btp_whoami.me.issuer != var.custom_idp ? var.cf_org_admins : setsubtract(toset(var.cf_org_users), [data.btp_whoami.me.email]) + + # get origin_key from custom.idp + custom_idp_tenant = var.custom_idp != "" ? element(split(".", var.custom_idp), 0) : "" + origin_key = local.custom_idp_tenant != "" ? "${local.custom_idp_tenant}-platform" : "sap.ids" +} + +# ------------------------------------------------------------------------------------------------------ # add org and space users and managers -###################################################################### +# ------------------------------------------------------------------------------------------------------ resource "cloudfoundry_org_role" "organization_user" { - for_each = toset(var.cf_org_users) + for_each = toset(local.cf_org_users) username = each.value type = "organization_user" org = var.cf_org_id + origin = local.origin_key } resource "cloudfoundry_org_role" "organization_manager" { - for_each = toset(var.cf_org_admins) + for_each = toset(local.cf_org_admins) username = each.value type = "organization_manager" org = var.cf_org_id + origin = local.origin_key } resource "cloudfoundry_space_role" "space_developer" { @@ -28,6 +67,7 @@ resource "cloudfoundry_space_role" "space_developer" { username = each.value type = "space_developer" space = cloudfoundry_space.dev.id + origin = local.origin_key depends_on = [cloudfoundry_org_role.organization_user, cloudfoundry_org_role.organization_manager] } @@ -36,5 +76,6 @@ resource "cloudfoundry_space_role" "space_manager" { username = each.value type = "space_manager" space = cloudfoundry_space.dev.id + origin = local.origin_key depends_on = [cloudfoundry_org_role.organization_user, cloudfoundry_org_role.organization_manager] } \ No newline at end of file diff --git a/released/discovery_center/mission_4172/step2/outputs.tf b/released/discovery_center/mission_4172/step2/outputs.tf deleted file mode 100644 index ad4178cd..00000000 --- a/released/discovery_center/mission_4172/step2/outputs.tf +++ /dev/null @@ -1,19 +0,0 @@ -output "subaccount_id" { - value = var.subaccount_id -} - -output "cf_landscape_label" { - value = var.cf_landscape_label -} - -output "cf_org_id" { - value = var.cf_org_id -} - -output "cf_api_url" { - value = var.cf_api_url -} - -output "cf_space_name" { - value = cloudfoundry_space.dev.name -} \ No newline at end of file diff --git a/released/discovery_center/mission_4172/step2/provider.tf b/released/discovery_center/mission_4172/step2/provider.tf index b58d086e..7d04ed08 100644 --- a/released/discovery_center/mission_4172/step2/provider.tf +++ b/released/discovery_center/mission_4172/step2/provider.tf @@ -4,13 +4,19 @@ terraform { source = "SAP/cloudfoundry" version = "1.0.0-rc1" } + btp = { + source = "SAP/btp" + version = "~> 1.5.0" + } } } -###################################################################### -# Configure CF provider -###################################################################### +provider "btp" { + globalaccount = var.globalaccount + cli_server_url = var.cli_server_url +} + + provider "cloudfoundry" { - # resolve API URL from environment instance api_url = var.cf_api_url -} \ No newline at end of file +} diff --git a/released/discovery_center/mission_4172/step2/variables.tf b/released/discovery_center/mission_4172/step2/variables.tf index 0b435101..443fdd19 100644 --- a/released/discovery_center/mission_4172/step2/variables.tf +++ b/released/discovery_center/mission_4172/step2/variables.tf @@ -1,8 +1,23 @@ -variable "cf_api_url" { - type = string +variable "globalaccount" { + type = string + description = "The globalaccount subdomain where the sub account shall be created." +} + +# The BTP CLI server URL +variable "cli_server_url" { + type = string + description = "The BTP CLI server URL." + default = "https://cli.btp.cloud.sap" } -variable "cf_landscape_label" { +# The CF Org name from the Cloud Foundry environment instance +variable "cf_org_name" { + type = string + description = "The Cloud Foundry Org name from the Cloud Foundry environment instance." + +} + +variable "cf_api_url" { type = string } @@ -17,43 +32,37 @@ variable "subaccount_id" { variable "cf_space_developers" { type = list(string) description = "CF Space developers" - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if CF Space developers contains a list of valid email addresses - validation { - condition = length([for email in var.cf_space_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_space_developers) - error_message = "Please enter a valid email address for the CF Space developers." - } } variable "cf_space_managers" { type = list(string) description = "CF Space managers" - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if CF Space managers contains a list of valid email addresses - validation { - condition = length([for email in var.cf_space_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_space_managers) - error_message = "Please enter a valid email address for the Cloud Connector Administrators." - } } variable "cf_org_admins" { type = list(string) description = "CF Org Admins" - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if CF Org Admins contains a list of valid email addresses - validation { - condition = length([for email in var.cf_org_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_admins) - error_message = "Please enter a valid email address for the CF Org Admins." - } } variable "cf_org_users" { type = list(string) description = "CF Org Users" - default = ["jane.doe@test.com", "john.doe@test.com"] - # add validation to check if CF Org Users contains a list of valid email addresses +} + + +variable "custom_idp" { + type = string + description = "Defines the custom IDP to be used for the subaccount" + default = "" +} + +variable "cf_space_name" { + type = string + description = "Name of the Cloud Foundry space." + default = "dev" + validation { - condition = length([for email in var.cf_org_users : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_users) - error_message = "Please enter a valid email address for the CF Org Users." + condition = can(regex("^.{1,255}$", var.cf_space_name)) + error_message = "The Cloud Foundry space name must not be emtpy and not exceed 255 characters." } -} +} \ No newline at end of file