diff --git a/.github/workflows/push-e2e-test.yml b/.github/workflows/push-e2e-test.yml index 66cbb89..a78cafa 100644 --- a/.github/workflows/push-e2e-test.yml +++ b/.github/workflows/push-e2e-test.yml @@ -26,5 +26,4 @@ jobs: TF_VAR_BTP_KYMA_PLAN: ${{ secrets.kyma_plan }} TF_VAR_BTP_KYMA_REGION: ${{ secrets.kyma_region }} TF_VAR_BTP_CUSTOM_IAS_TENANT: ${{ secrets.ias_tenant }} - TF_VAR_BTP_CUSTOM_IAS_DOMAIN: ${{ secrets.ias_domain }} TF_VAR_BTP_BACKEND_URL: ${{ secrets.btp_api_url }} diff --git a/README.md b/README.md index 2a708a0..4fb3e36 100644 --- a/README.md +++ b/README.md @@ -8,20 +8,17 @@ Terraform module that creates kyma runtime in SAP BTP platform. -![image](./assets/sequence.png) +![image](./assets/sequence.drawio.svg) ### Input Variables (TF vars) | NAME | MANDATORY | DEFAULT VALUE | DESCRIPTION | |----------------------------|-----------|---------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------| | BTP_GLOBAL_ACCOUNT | true | | UUID of SAP BTP Global Account | -| BTP_BOT_USER | true | | Email of the technical user (shared mailbox) | -| BTP_BOT_PASSWORD | true | | Password of the techniacal user (created when inviting shared mailbox into custom SAP IAS tenant) | | BTP_USE_SUBACCOUNT_ID | false | | Provide an UUID of existing SAP BTP Subaccount to be used. Should not be combined with `BTP_NEW_SUBACCOUNT_*` inputs. | | BTP_NEW_SUBACCOUNT_NAME | false | | Provide a name for a new SAP BTP Subaccount to be created. Should not be combined with `BTP_USE_SUBACCOUNT_ID` input. | | BTP_NEW_SUBACCOUNT_REGION | false | | Provide a region for a new SAP BTP Subaccount to be created. Should not be combined with `BTP_USE_SUBACCOUNT_ID` input. | | BTP_CUSTOM_IAS_TENANT | true | | Provide the name of the custom SAP IAS tenant that is an authentication provider for the technical user. | -| BTP_CUSTOM_IAS_DOMAIN | false | accounts.ondemand.com | Domain of the identity provider (on canary and staging environments this has to be set to `accounts400.ondemand.com`) | | BTP_BACKEND_URL | false | https://cli.btp.cloud.sap | URL of the BTP backend API (on canary environment this has to be set to `https://cpcli.cf.sap.hana.ondemand.com`). | | BTP_KYMA_PLAN | false | azure | Use one of a valid kyma plans that you are entitled to use (One of: `azure`, `gcp`, `aws`,`sap-converged-cloud`) | | BTP_KYMA_REGION | false | westeurope | Use a valid kyma region that matches your selected kyma plan | @@ -32,6 +29,7 @@ Terraform module for Kyma uses the following terraform [providers](provider.tf), - `SAP/btp` - `massdriver-cloud/jq` - `hashicorp/http` + - `salrashid123/http-full` ### Outputs @@ -61,7 +59,7 @@ Terraform module for Kyma uses the following terraform [providers](provider.tf), | +-- .tfvars ``` -2. In the `.tfvars` file, provide [input parameters](#input-variables-tf-vars). Refer to the [template](examples/kyma-on-btp-new-sa/.tfvars-template) file. +2. In the `.tfvars` file, provide values that are necessary for the `kyma` child module (kyma module's [input parameters](#input-variables-tf-vars)) and the `sap/btp` provider. For example: ```tf @@ -70,7 +68,6 @@ BTP_BOT_PASSWORD = "..." BTP_GLOBAL_ACCOUNT = "..." BTP_BACKEND_URL = "https://cpcli.cf.sap.hana.ondemand.com" BTP_CUSTOM_IAS_TENANT = "my-tenant" -BTP_CUSTOM_IAS_DOMAIN = "accounts400.ondemand.com" BTP_NEW_SUBACCOUNT_NAME = "kyma-runtime-subaccount" BTP_NEW_SUBACCOUNT_REGION = "eu21" BTP_KYMA_PLAN = "azure" @@ -94,12 +91,8 @@ provider "btp" { module "kyma" { source = "git::https://github.com/kyma-project/terraform-module.git?ref=v0.2.0" BTP_KYMA_PLAN = var.BTP_KYMA_PLAN - BTP_NEW_SUBACCOUNT_NAME = var.BTP_NEW_SUBACCOUNT_NAME - BTP_CUSTOM_IAS_TENANT = var.BTP_CUSTOM_IAS_TENANT - BTP_CUSTOM_IAS_DOMAIN = var.BTP_CUSTOM_IAS_DOMAIN BTP_KYMA_REGION = var.BTP_KYMA_REGION - BTP_BOT_USER = var.BTP_BOT_USER - BTP_BOT_PASSWORD = var.BTP_BOT_PASSWORD + BTP_NEW_SUBACCOUNT_NAME = var.BTP_NEW_SUBACCOUNT_NAME BTP_NEW_SUBACCOUNT_REGION = var.BTP_NEW_SUBACCOUNT_REGION } diff --git a/assets/sequence.drawio b/assets/sequence.drawio new file mode 100644 index 0000000..c010e16 --- /dev/null +++ b/assets/sequence.drawio @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/sequence.drawio.svg b/assets/sequence.drawio.svg new file mode 100644 index 0000000..cff68b7 --- /dev/null +++ b/assets/sequence.drawio.svg @@ -0,0 +1,4 @@ + + + +
technical user credentials
Vault
CI workflow
read BTP credentials
kubeconfig
dispatch (new commit in app repository)
BTP CLI API
SAP BTP TERRAFORM PROVIDER

create SAP BTP KYMA runtime
(input: BTP GA, BTP credentials {technical user}, IAS tenant name )

ready (output: kubeconfig)
create resources
ready (instanceId)
BTP Resources (i.e subaccount, entitlements, kyma environment, oidc app)
Kyma Runtime
create resources
ready
push app to kyma and run tests (using kubeconfig)
done
tear down resourcesĀ 
return
delete all from tf state
return
Ā 
YAML
deprovision btp resources
CIS (local)
PUTĀ /provisioning/v1/environments/{instance_id}/bindings
\ No newline at end of file diff --git a/assets/sequence.png b/assets/sequence.png deleted file mode 100644 index 9f5cd5b..0000000 Binary files a/assets/sequence.png and /dev/null differ diff --git a/examples/kyma-on-btp-new-sa/.tfvars-template b/examples/kyma-on-btp-new-sa/.tfvars-template index 72f82b6..b20bab8 100644 --- a/examples/kyma-on-btp-new-sa/.tfvars-template +++ b/examples/kyma-on-btp-new-sa/.tfvars-template @@ -14,10 +14,11 @@ BTP_BACKEND_URL = "" # Mandatory BTP_CUSTOM_IAS_TENANT = "" -# Optional. Defaults to `accounts.ondemand.com`. For Canary landscape use `accounts400.ondemand.com` -BTP_CUSTOM_IAS_DOMAIN = "" # Optional. defaults to `azure`; One of: `azure`, `sap-converged-cloud`, `aws`, `gcp` BTP_KYMA_PLAN = "" # Must match options for given plan; i.e `westeurope` is a valid kyma region for kyma plan `azure` BTP_KYMA_REGION = "" + +# Optional +BTP_KYMA_CUSTOM_ADMINISTRATORS= "" \ No newline at end of file diff --git a/examples/kyma-on-btp-new-sa/main.tf b/examples/kyma-on-btp-new-sa/main.tf index 2d8ec1c..6faf0c7 100644 --- a/examples/kyma-on-btp-new-sa/main.tf +++ b/examples/kyma-on-btp-new-sa/main.tf @@ -2,21 +2,27 @@ terraform { required_providers { btp = { source = "SAP/btp" - version = "1.8.0" } jq = { source = "massdriver-cloud/jq" } http = { source = "hashicorp/http" - version = "3.4.5" } + http-full = { + source = "salrashid123/http-full" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.32.0" + } } } provider "jq" {} provider "http" {} +provider "http-full" {} provider "btp" { globalaccount = var.BTP_GLOBAL_ACCOUNT @@ -26,17 +32,25 @@ provider "btp" { password = var.BTP_BOT_PASSWORD } +# this shows how to configure kubernetes terraform provider with the output from terraform module for kyma +locals { + kubeconfig = module.kyma.kubeconfig +} + +provider "kubernetes" { + cluster_ca_certificate = base64decode(local.kubeconfig.clusters.0.cluster.certificate-authority-data) + host = local.kubeconfig.clusters.0.cluster.server + token = local.kubeconfig.users.0.user.token +} + module "kyma" { source = "../.." BTP_KYMA_PLAN = var.BTP_KYMA_PLAN BTP_NEW_SUBACCOUNT_NAME = var.BTP_NEW_SUBACCOUNT_NAME - BTP_CUSTOM_IAS_TENANT = var.BTP_CUSTOM_IAS_TENANT - BTP_CUSTOM_IAS_DOMAIN = var.BTP_CUSTOM_IAS_DOMAIN BTP_KYMA_REGION = var.BTP_KYMA_REGION - BTP_BOT_USER = var.BTP_BOT_USER - BTP_BOT_PASSWORD = var.BTP_BOT_PASSWORD BTP_NEW_SUBACCOUNT_REGION = var.BTP_NEW_SUBACCOUNT_REGION BTP_KYMA_MODULES = var.BTP_KYMA_MODULES + BTP_KYMA_CUSTOM_ADMINISTRATORS = var.BTP_KYMA_CUSTOM_ADMINISTRATORS } output "subaccount_id" { @@ -54,3 +68,13 @@ output "cluster_id" { output "domain" { value = module.kyma.domain } + +# this shows how to use kubernetes terraform provider to read data from k8s cluster +data "kubernetes_namespace" "default" { + depends_on = [ + module.kyma.kubeconfig + ] + metadata { + name = "default" + } +} \ No newline at end of file diff --git a/examples/kyma-on-btp-new-sa/variables.tf b/examples/kyma-on-btp-new-sa/variables.tf index 5f4c001..dcd4f1f 100644 --- a/examples/kyma-on-btp-new-sa/variables.tf +++ b/examples/kyma-on-btp-new-sa/variables.tf @@ -47,13 +47,7 @@ variable "BTP_KYMA_PLAN" { variable "BTP_CUSTOM_IAS_TENANT" { type = string description = "Custom IAS tenant" - default = "custon-tenant" -} - -variable "BTP_CUSTOM_IAS_DOMAIN" { - type = string - description = "Custom IAS domain" - default = "accounts.ondemand.com" + default = "custom-tenant" } variable "BTP_KYMA_REGION" { @@ -83,3 +77,7 @@ variable "BTP_KYMA_MODULES" { ] description = "The list of kyma modules to install" } + +variable "BTP_KYMA_CUSTOM_ADMINISTRATORS" { + type = list(string) +} diff --git a/examples/kyma-on-btp-reuse-sa/.tfvars-template b/examples/kyma-on-btp-reuse-sa/.tfvars-template index ac52eee..a56ef6d 100644 --- a/examples/kyma-on-btp-reuse-sa/.tfvars-template +++ b/examples/kyma-on-btp-reuse-sa/.tfvars-template @@ -11,10 +11,11 @@ BTP_BACKEND_URL = "" # Mandatory BTP_CUSTOM_IAS_TENANT = "" -# Optional. Defaults to `accounts.ondemand.com`. For Canary landscape use `accounts400.ondemand.com` -BTP_CUSTOM_IAS_DOMAIN = "" # Optional. defaults to `azure`; One of: `azure`, `sap-converged-cloud`, `aws`, `gcp` BTP_KYMA_PLAN = "" # Must match options for given plan; i.e `westeurope` is a valid kyma region for kyma plan `azure` BTP_KYMA_REGION = "" + +# Optional +BTP_KYMA_CUSTOM_ADMINISTRATORS= "" \ No newline at end of file diff --git a/examples/kyma-on-btp-reuse-sa/main.tf b/examples/kyma-on-btp-reuse-sa/main.tf index ecb4539..cf75d13 100644 --- a/examples/kyma-on-btp-reuse-sa/main.tf +++ b/examples/kyma-on-btp-reuse-sa/main.tf @@ -2,14 +2,15 @@ terraform { required_providers { btp = { source = "SAP/btp" - version = "1.8.0" } jq = { source = "massdriver-cloud/jq" } http = { source = "hashicorp/http" - version = "3.4.5" + } + http-full = { + source = "salrashid123/http-full" } } } @@ -17,6 +18,7 @@ terraform { provider "jq" {} provider "http" {} +provider "http-full" {} provider "btp" { globalaccount = var.BTP_GLOBAL_ACCOUNT @@ -29,11 +31,7 @@ provider "btp" { module "kyma" { source = "../.." BTP_KYMA_PLAN = var.BTP_KYMA_PLAN - BTP_CUSTOM_IAS_TENANT = var.BTP_CUSTOM_IAS_TENANT - BTP_CUSTOM_IAS_DOMAIN = var.BTP_CUSTOM_IAS_DOMAIN BTP_KYMA_REGION = var.BTP_KYMA_REGION - BTP_BOT_USER = var.BTP_BOT_USER - BTP_BOT_PASSWORD = var.BTP_BOT_PASSWORD BTP_USE_SUBACCOUNT_ID = var.BTP_USE_SUBACCOUNT_ID } diff --git a/examples/kyma-on-btp-reuse-sa/variables.tf b/examples/kyma-on-btp-reuse-sa/variables.tf index bf9e9ea..53aa3bb 100644 --- a/examples/kyma-on-btp-reuse-sa/variables.tf +++ b/examples/kyma-on-btp-reuse-sa/variables.tf @@ -55,3 +55,6 @@ variable "BTP_KYMA_REGION" { default = "westeurope" } +variable "BTP_KYMA_CUSTOM_ADMINISTRATORS" { + type = list(string) +} diff --git a/examples/kyma-on-btp-with-custom-oidc/README.md b/examples/kyma-on-btp-with-custom-oidc/README.md new file mode 100644 index 0000000..426fc42 --- /dev/null +++ b/examples/kyma-on-btp-with-custom-oidc/README.md @@ -0,0 +1,50 @@ +## Prerequisites + +### Ensure CLI tools +Ensure you have opentofu (or terraform CLI installed). +The sample scripts relly on `tofu` command, but its 100% compatible with `terraform` CLI. + +Ensure the tofu CLI is installed by calling: +```sh +brew install opentofu +``` + +### Ensure Input parameters + +Save a new version of the template file `examples/kyma-on-btp-with-custom-oidc/local-template.tfvars` as `examples/kyma-on-btp-with-custom-oidc/local.tfvars`. Provide values for input variables. + +``` +BTP_NEW_SUBACCOUNT_NAME = "new-test-sa" +BTP_NEW_SUBACCOUNT_REGION = "..." +BTP_BOT_USER = "{my-technical-user}@sap.com" +BTP_BOT_PASSWORD = "..." +BTP_GLOBAL_ACCOUNT = "..." +BTP_CUSTOM_IAS_TENANT = "..." +``` + +### Ensure technical user access + +In this example a new subaccount is created automatically. Please ensure the following + - make sure that your custom SAP IAS tenant is trusted on global account level, + - make sure that technical user (bot user) is added to the global account and is assigned a global account administrator role collection, + - make sure the technical user is added to your custom SAP IAS tenant. + +## Run +Run the example: + +```sh +tofu init +tofu apply -var-file="local.tfvars" -auto-approve +``` + +As a result, a new `kubeconfig.yaml` file was created that you can use to access the newly provisioned kyma runtime on SAP BTP. + +```sh +kubectl get nodes --kubeconfig kubeconfig.yaml +``` + +Last but not least, deprovision all resources via: + +```sh +tofu destroy -var-file="local.tfvars" -auto-approve +``` \ No newline at end of file diff --git a/examples/kyma-on-btp-with-custom-oidc/main.tf b/examples/kyma-on-btp-with-custom-oidc/main.tf new file mode 100644 index 0000000..845bc76 --- /dev/null +++ b/examples/kyma-on-btp-with-custom-oidc/main.tf @@ -0,0 +1,181 @@ +terraform { + required_providers { + btp = { + source = "SAP/btp" + } + jq = { + source = "massdriver-cloud/jq" + } + http = { + source = "hashicorp/http" + } + http-full = { + source = "salrashid123/http-full" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.32.0" + } + } +} + + +provider "jq" {} +provider "http" {} +provider "http-full" {} + +provider "btp" { + globalaccount = var.BTP_GLOBAL_ACCOUNT + cli_server_url = var.BTP_BACKEND_URL + idp = var.BTP_CUSTOM_IAS_TENANT + username = var.BTP_BOT_USER + password = var.BTP_BOT_PASSWORD +} + +# this shows how to configure kubernetes terraform provider with the output from terraform module for kyma +locals { + kubeconfig = module.kyma.kubeconfig + subaccount_id = var.BTP_USE_SUBACCOUNT_ID + subaccount_name = data.btp_subaccount.target_subaccount.name + oidc_config = { + groupsClaim = "groups" + signingAlgs = ["RS256"] + usernameClaim = "sub" + usernamePrefix = "-" + clientID = jsondecode(btp_subaccount_service_binding.identity_application_binding.credentials).clientid + issuerURL = "https://${var.BTP_CUSTOM_IAS_TENANT}.${var.BTP_CUSTOM_IAS_DOMAIN}" + } +} + +provider "kubernetes" { + cluster_ca_certificate = base64decode(local.kubeconfig.clusters.0.cluster.certificate-authority-data) + host = local.kubeconfig.clusters.0.cluster.server + token = local.kubeconfig.users.0.user.token +} + +data "btp_subaccount" "target_subaccount" { + id = local.subaccount_id +} + +# custom idp setup +resource "btp_subaccount_entitlement" "identity" { + subaccount_id = local.subaccount_id + service_name = "identity" + plan_name = "application" +} + +data "btp_subaccount_service_plan" "identity_application" { + depends_on = [btp_subaccount_entitlement.identity] + subaccount_id = local.subaccount_id + offering_name = "identity" + name = "application" +} + + +resource "btp_subaccount_trust_configuration" "custom_idp" { + subaccount_id = var.BTP_USE_SUBACCOUNT_ID + identity_provider = "${var.BTP_CUSTOM_IAS_TENANT}.${var.BTP_CUSTOM_IAS_DOMAIN}" + name = "${local.subaccount_name}-${var.BTP_CUSTOM_IAS_TENANT}" +} + +resource "btp_subaccount_service_instance" "identity_application" { + depends_on = [btp_subaccount_trust_configuration.custom_idp] + subaccount_id = local.subaccount_id + name = "${local.subaccount_name}-${var.BTP_CUSTOM_IAS_TENANT}-oidc-app" + serviceplan_id = data.btp_subaccount_service_plan.identity_application.id + parameters = jsonencode({ + user-access = "public" + oauth2-configuration = { + grant-types = [ + "authorization_code", + "authorization_code_pkce_s256", + "refresh_token" + ], + token-policy = { + token-validity = 3600, + refresh-validity = 15552000, + refresh-usage-after-renewal = "off", + refresh-parallel = 3, + access-token-format = "default" + }, + public-client = true, + redirect-uris = [ + "https://dashboard.kyma.cloud.sap", + "https://dashboard.dev.kyma.cloud.sap", + "https://dashboard.stage.kyma.cloud.sap", + "http://localhost:8000" + ] + }, + subject-name-identifier = { + attribute = "mail", + fallback-attribute = "none" + }, + default-attributes = null, + assertion-attributes = { + email = "mail", + groups = "companyGroups", + first_name = "firstName", + last_name = "lastName", + login_name = "loginName", + mail = "mail", + scope = "companyGroups", + user_uuid = "userUuid", + locale = "language" + }, + name = "${local.subaccount_name}-${var.BTP_CUSTOM_IAS_TENANT}-oidc-app", + display-name = "${local.subaccount_name}-${var.BTP_CUSTOM_IAS_TENANT}-oidc-app" + }) +} + +resource "btp_subaccount_service_binding" "identity_application_binding" { + subaccount_id = local.subaccount_id + name = "${local.subaccount_name}-${var.BTP_CUSTOM_IAS_TENANT}-oidc-app-binding" + service_instance_id = btp_subaccount_service_instance.identity_application.id + parameters = jsonencode({ + credential-type = "X509_GENERATED" + key-length = 4096 + validity = 1 + validity-type = "DAYS" + app-identifier = "kymaruntime" + }) +} + + +module "kyma" { + depends_on = [ + btp_subaccount_service_binding.identity_application_binding + ] + source = "../.." + BTP_KYMA_PLAN = var.BTP_KYMA_PLAN + BTP_USE_SUBACCOUNT_ID = var.BTP_USE_SUBACCOUNT_ID + BTP_KYMA_CUSTOM_OIDC = local.oidc_config + BTP_KYMA_CUSTOM_ADMINISTRATORS = var.BTP_KYMA_CUSTOM_ADMINISTRATORS + BTP_KYMA_REGION = var.BTP_KYMA_REGION + BTP_KYMA_MODULES = var.BTP_KYMA_MODULES +} + +output "subaccount_id" { + value = module.kyma.subaccount_id +} + +output "service_instance_id" { + value = module.kyma.service_instance_id +} + +output "cluster_id" { + value = module.kyma.cluster_id +} + +output "domain" { + value = module.kyma.domain +} + +# this shows how to use kubernetes terraform provider to read data from k8s cluster +data "kubernetes_namespace" "default" { + depends_on = [ + module.kyma.kubeconfig + ] + metadata { + name = "default" + } +} \ No newline at end of file diff --git a/examples/kyma-on-btp-with-custom-oidc/variables.tf b/examples/kyma-on-btp-with-custom-oidc/variables.tf new file mode 100644 index 0000000..a706cfb --- /dev/null +++ b/examples/kyma-on-btp-with-custom-oidc/variables.tf @@ -0,0 +1,83 @@ +# we're using uppercase variable names, since in some cases (e.g Azure DevOps) the system variables are forced to be uppercase +# TF allows providing variable values as env variables of name name, case sensitive + +variable "BTP_GLOBAL_ACCOUNT" { + type = string + description = "Global account name" + default = "global-account-guid" +} + +variable "BTP_BOT_USER" { + type = string + description = "Bot account name" + default = "email@domain.com" +} + +variable "BTP_BOT_PASSWORD" { + type = string + description = "Bot account password" + default = "password" + sensitive = true +} + +variable "BTP_BACKEND_URL" { + type = string + description = "BTP backend URL" + default = "https://cli.btp.cloud.sap" +} + +variable "BTP_USE_SUBACCOUNT_ID" { + type = string + description = "Subaccount name" + default = null +} + +variable "BTP_KYMA_PLAN" { + type = string + description = "Plan name" + default = "azure" +} + +variable "BTP_CUSTOM_IAS_TENANT" { + type = string + description = "Custom IAS tenant" + default = "custom-tenant" +} + +variable "BTP_CUSTOM_IAS_DOMAIN" { + type = string + description = "Custom IAS domain" + default = "accounts.ondemand.com" +} + +variable "BTP_KYMA_CUSTOM_ADMINISTRATORS" { + type = list(string) +} + +variable "BTP_KYMA_REGION" { + type = string + description = "Kyma region" + default = "westeurope" +} + +variable "BTP_KYMA_MODULES" { + type = list(object({ + name = string + channel = string + })) + default = [ + { + name = "istio" + channel = "fast" + }, + { + name = "api-gateway" + channel = "fast" + }, + { + name = "btp-operator" + channel = "fast" + } + ] + description = "The list of kyma modules to install" +} diff --git a/main.tf b/main.tf index 465b0a7..f8ef6b2 100644 --- a/main.tf +++ b/main.tf @@ -22,19 +22,10 @@ resource "btp_subaccount_environment_instance" "kyma" { modules = { list = var.BTP_KYMA_MODULES } - oidc = { - groupsClaim = "groups" - signingAlgs = ["RS256"] - usernameClaim = "sub" - usernamePrefix = "-" - clientID = jsondecode(btp_subaccount_service_binding.identity_application_binding.credentials).clientid - issuerURL = "https://${var.BTP_CUSTOM_IAS_TENANT}.${var.BTP_CUSTOM_IAS_DOMAIN}" - } + oidc = var.BTP_KYMA_CUSTOM_OIDC name = "${local.subaccount_name}-kyma" region = var.BTP_KYMA_REGION - administrators = [ - var.BTP_BOT_USER - ] + administrators = var.BTP_KYMA_CUSTOM_ADMINISTRATORS }) timeouts = { create = "60m" @@ -43,43 +34,10 @@ resource "btp_subaccount_environment_instance" "kyma" { } } -data "btp_subaccount_environment_instance" "kyma-instance" { - depends_on = [ - btp_subaccount_environment_instance.kyma - ] - subaccount_id = local.subaccount_id - id = btp_subaccount_environment_instance.kyma.id -} - - -data "http" "kubeconfig" { - url = jsondecode(btp_subaccount_environment_instance.kyma.labels).KubeconfigURL - retry { - attempts = 2 - max_delay_ms = 2000 - min_delay_ms = 1000 - } - lifecycle { - postcondition { - condition = can(regex("kind: Config",self.response_body)) - error_message = "Invalid content of downloaded kubeconfig" - } - } -} - -locals { - id_token = jsondecode(data.http.token.response_body).id_token - kubeconfig_oidc = yamldecode(data.http.kubeconfig.response_body) -} - -data "jq_query" "kubeconfig" { - data = jsonencode(yamldecode(data.http.kubeconfig.response_body)) - query = "del(.users[] | .user | .exec) | .users[] |= . + { user: { token: ${jsonencode(local.id_token)} } }" -} resource "local_sensitive_file" "kubeconfig-yaml" { filename = "kubeconfig.yaml" - content = yamlencode(jsondecode(data.jq_query.kubeconfig.result) ) + content = jsondecode(data.http.kymaruntime_bindings.response_body).credentials.kubeconfig } # wait for kyma readiness @@ -122,114 +80,89 @@ data "local_file" "domain" { filename = "domain.txt" } -#"oidc.tf" +locals { + cisCredentials = jsondecode(btp_subaccount_service_binding.cis-local-binding.credentials) + instance_id = btp_subaccount_environment_instance.kyma.id + cisBasicAuth = base64encode("${local.cisCredentials.uaa.clientid}:${local.cisCredentials.uaa.clientsecret}") +} -resource "btp_subaccount_entitlement" "identity" { - subaccount_id = local.subaccount_id - service_name = "identity" - plan_name = "application" + +#"subaccount.tf" +data "btp_subaccount" "reuse_subaccount" { + count = var.BTP_USE_SUBACCOUNT_ID != null && var.BTP_NEW_SUBACCOUNT_NAME == null ? 1 : 0 + id = var.BTP_USE_SUBACCOUNT_ID +} + +resource "btp_subaccount" "subaccount" { + count = var.BTP_NEW_SUBACCOUNT_NAME != null && var.BTP_USE_SUBACCOUNT_ID == null ? 1 : 0 + name = var.BTP_NEW_SUBACCOUNT_NAME + region = var.BTP_NEW_SUBACCOUNT_REGION + subdomain = var.BTP_NEW_SUBACCOUNT_NAME } -# custom idp -resource "btp_subaccount_trust_configuration" "custom_idp" { - subaccount_id = local.subaccount_id - identity_provider = "${var.BTP_CUSTOM_IAS_TENANT}.${var.BTP_CUSTOM_IAS_DOMAIN}" - name = "${local.subaccount_name}-${var.BTP_CUSTOM_IAS_TENANT}" +# cis +resource "btp_subaccount_entitlement" "cis" { + subaccount_id = local.subaccount_id + service_name = "cis" + plan_name = "local" } -data "btp_subaccount_service_plan" "identity_application" { - depends_on = [btp_subaccount_entitlement.identity] +data "btp_subaccount_service_plan" "cis" { + depends_on = [btp_subaccount_entitlement.cis] subaccount_id = local.subaccount_id - offering_name = "identity" - name = "application" + offering_name = "cis" + name = "local" } -resource "btp_subaccount_service_instance" "identity_application" { - depends_on = [btp_subaccount_trust_configuration.custom_idp] +resource "btp_subaccount_service_instance" "cis-local" { + depends_on = [btp_subaccount_entitlement.cis] subaccount_id = local.subaccount_id - name = "${local.subaccount_name}-${var.BTP_CUSTOM_IAS_TENANT}-oidc-app" - serviceplan_id = data.btp_subaccount_service_plan.identity_application.id + name = "cis-local" + serviceplan_id = data.btp_subaccount_service_plan.cis.id parameters = jsonencode({ - user-access = "public" - oauth2-configuration = { - grant-types = [ - "authorization_code", - "authorization_code_pkce_s256", - "password", - "refresh_token" - ], - token-policy = { - token-validity = 3600, - refresh-validity = 15552000, - refresh-usage-after-renewal = "off", - refresh-parallel = 3, - access-token-format = "default" - }, - public-client = true, - redirect-uris = [ - "https://dashboard.kyma.cloud.sap", - "https://dashboard.dev.kyma.cloud.sap", - "https://dashboard.stage.kyma.cloud.sap", - "http://localhost:8000" - ] - }, - subject-name-identifier = { - attribute = "mail", - fallback-attribute = "none" - }, - default-attributes = null, - assertion-attributes = { - email = "mail", - groups = "companyGroups", - first_name = "firstName", - last_name = "lastName", - login_name = "loginName", - mail = "mail", - scope = "companyGroups", - user_uuid = "userUuid", - locale = "language" - }, - name = "${local.subaccount_name}-${var.BTP_CUSTOM_IAS_TENANT}-oidc-app", - display-name = "${local.subaccount_name}-${var.BTP_CUSTOM_IAS_TENANT}-oidc-app" + "grantType": "clientCredentials" }) } -resource "btp_subaccount_service_binding" "identity_application_binding" { +resource "btp_subaccount_service_binding" "cis-local-binding" { + depends_on = [btp_subaccount_service_instance.cis-local] subaccount_id = local.subaccount_id - name = "${local.subaccount_name}-${var.BTP_CUSTOM_IAS_TENANT}-oidc-app-binding" - service_instance_id = btp_subaccount_service_instance.identity_application.id - parameters = jsonencode({ - credential-type = "X509_GENERATED" - key-length = 4096 - validity = 1 - validity-type = "DAYS" - app-identifier = "kymaruntime" - }) -} - -locals { - idp = jsondecode(btp_subaccount_service_binding.identity_application_binding.credentials) + name = "cis-local-binding" + service_instance_id = btp_subaccount_service_instance.cis-local.id } -data "http" "token" { - url = "${local.idp.url}/oauth2/token" +# fetch token for hana admin API using client-credential service binding +data "http" "cis-api-token" { + depends_on = [ + btp_subaccount_service_binding.cis-local-binding + ] + url = "${local.cisCredentials.uaa.url}/oauth/token?grant_type=client_credentials" method = "POST" request_headers = { - Content-Type = "application/x-www-form-urlencoded" + Authorization = "Basic ${local.cisBasicAuth}" } - request_body = "grant_type=password&username=${var.BTP_BOT_USER}&password=${var.BTP_BOT_PASSWORD}&client_id=${local.idp.clientid}&scope=groups,email" } -#"subaccount.tf" -data "btp_subaccount" "reuse_subaccount" { - count = var.BTP_USE_SUBACCOUNT_ID != null && var.BTP_NEW_SUBACCOUNT_NAME == null ? 1 : 0 - id = var.BTP_USE_SUBACCOUNT_ID -} +# create kyma binding via provisioning API +data "http" "kymaruntime_bindings" { + depends_on = [ + data.http.cis-api-token, + local.instance_id + ] -resource "btp_subaccount" "subaccount" { - count = var.BTP_NEW_SUBACCOUNT_NAME != null && var.BTP_USE_SUBACCOUNT_ID == null ? 1 : 0 - name = var.BTP_NEW_SUBACCOUNT_NAME - region = var.BTP_NEW_SUBACCOUNT_REGION - subdomain = var.BTP_NEW_SUBACCOUNT_NAME -} + provider = http-full + url = "${local.cisCredentials.endpoints.provisioning_service_url}/provisioning/v1/environments/${local.instance_id}/bindings" + method = "PUT" + request_headers = { + Authorization = "Bearer ${jsondecode(data.http.cis-api-token.response_body).access_token}" + Accept = "application/json" + content-type = "application/json" + } + + request_body = jsonencode({ + "parameters": { + "expiration_seconds": 7200, + } + }) +} diff --git a/output.tf b/output.tf index 24a1d3f..912d200 100644 --- a/output.tf +++ b/output.tf @@ -1,5 +1,5 @@ output "kubeconfig" { - value = yamlencode(jsondecode(data.jq_query.kubeconfig.result) ) + value = yamldecode(jsondecode(data.http.kymaruntime_bindings.response_body).credentials.kubeconfig) } output "subaccount_id" { diff --git a/provider.tf b/provider.tf index 4c747d2..0b9b8e9 100644 --- a/provider.tf +++ b/provider.tf @@ -2,14 +2,17 @@ terraform { required_providers { btp = { source = "SAP/btp" - version = "1.8.0" + version = ">= 1.6.0" } jq = { source = "massdriver-cloud/jq" } http = { source = "hashicorp/http" - version = "3.4.5" + version = ">= 3.4.5" } + http-full = { + source = "salrashid123/http-full" + } } } diff --git a/variables.tf b/variables.tf index 53c8248..0b3fce1 100644 --- a/variables.tf +++ b/variables.tf @@ -26,16 +26,22 @@ variable "BTP_NEW_SUBACCOUNT_REGION" { default = "eu20" } -variable "BTP_CUSTOM_IAS_TENANT" { - type = string - description = "Custom IAS tenant" - default = "custon-tenant" +variable "BTP_KYMA_CUSTOM_OIDC" { + type = object({ + clientID = string + issuerURL = string + usernameClaim = string + usernamePrefix = string + groupsClaim = string + signingAlgs = list(string) + }) + default = null } -variable "BTP_CUSTOM_IAS_DOMAIN" { - type = string - description = "Custom IAS domain" - default = "accounts.ondemand.com" +variable "BTP_KYMA_CUSTOM_ADMINISTRATORS" { + type = list(string) + description = "List of users (sub) of the custom OIDC that should become cluster-admins" + default = [] } variable "BTP_KYMA_REGION" { @@ -44,19 +50,6 @@ variable "BTP_KYMA_REGION" { default = "westeurope" } -variable "BTP_BOT_USER" { - type = string - description = "Bot account name" - default = "email@domain.com" -} - -variable "BTP_BOT_PASSWORD" { - type = string - description = "Bot account password" - default = "password" - sensitive = true -} - variable "BTP_BACKEND_URL" { type = string description = "Backend URL for BTP API; defaults to https://cli.btp.cloud.sap"