Skip to content
2 changes: 2 additions & 0 deletions docs/examples/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ The following provides a list of examples of how to use Terraform to integrate P

## "Ready to run" Github Examples

* [Setting up SSO to PingDirectory from PingOne](https://github.com/pingidentity/terraform-docs/tree/main/examples/sso-to-pingdirectory-from-pingone)
* [Configuring PingOne for Windows Passwordless Login](https://github.com/pingidentity/terraform-docs/tree/main/examples/pingone-workforce-windows-passwordless-login)
* [Configuring PingOne Custom Domain with Cloudflare DNS](https://github.com/pingidentity/terraform-docs/tree/main/examples/pingone-custom-domain-with-cloudflare-dns)
* [Using Postman's "OAuth 2.0" authorization type with PingOne](https://github.com/pingidentity/terraform-docs/tree/main/examples/pingone-postman-oauth2-integration)
* [PingOne Neo - Getting Started](https://github.com/pingidentity/terraform-docs/tree/main/examples/pingone-neo-getting-started)

5 changes: 5 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Terraform Examples

## PingOne and PingDirectory

* [Setting up SSO to PingDirectory from PingOne](./sso-to-pingdirectory-from-pingone)

## PingOne

* [Windows Passwordless Login](./pingone-workforce-windows-passwordless-login)
* [Custom Domain with Cloudflare DNS](./pingone-custom-domain-with-cloudflare-dns)
* [PingOne Neo - Getting Started](./pingone-neo-getting-started)
* [Using Postman's "OAuth 2.0" authorization type with PingOne](./pingone-postman-oauth2-integration)

60 changes: 60 additions & 0 deletions examples/sso-to-pingdirectory-from-pingone/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Setting up SSO to PingDirectory from PingOne

Reference: [Setting up SSO to PingDirectory from PingOne](https://docs.pingidentity.com/r/en-us/pingone/pd_ds_set_up_sso_pingdir_pingone)

## Before you begin

* A PingDirectory server configured for Terraform access. This server will host the admin console that is being configured for SSO. For more information, see [Getting Started - PingDirectory](https://terraform.pingidentity.com/getting-started/pingdirectory/)
* A PingOne account configured for Terraform access. For more information, see [Getting Started - PingOne](https://terraform.pingidentity.com/getting-started/pingone/)

## Setting Connection Details
The following environment variables should be set prior to running the example. For more information, see the registry documentation for each provider.

| Variable name | Schema Documentation | Required/Optional |
|-------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|-------------------|
| `PINGDIRECTORY_PROVIDER_USERNAME` | [PingDirectory - username](https://registry.terraform.io/providers/pingidentity/pingdirectory/latest/docs#username) | Required |
| `PINGDIRECTORY_PROVIDER_PASSWORD` | [PingDirectory - password](https://registry.terraform.io/providers/pingidentity/pingdirectory/latest/docs#password) | Required |
| `PINGDIRECTORY_PROVIDER_HTTPS_HOST` | [PingDirectory - http_host](https://registry.terraform.io/providers/pingidentity/pingdirectory/latest/docs#https_host) | Required |
| `PINGDIRECTORY_PROVIDER_INSECURE_TRUST_ALL_TLS` | [PingDirectory - insecure_trust_all_tls](https://registry.terraform.io/providers/pingidentity/pingdirectory/latest/docs#insecure_trust_all_tls) | Optional |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose since it is just an example it is fine to recommend this, but maybe we could mention that this is just for testing and you should use actual cert configuration (https://registry.terraform.io/providers/pingidentity/pingdirectory/latest/docs#ca_certificate_pem_files) in production

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point - I'll add that in to the next draft

| `PINGONE_CLIENT_ID` | [PingOne - client_id](https://registry.terraform.io/providers/pingidentity/pingone/latest/docs#client_id) | Required |
| `PINGONE_CLIENT_SECRET` | [PingOne - client_secret](https://registry.terraform.io/providers/pingidentity/pingone/latest/docs#client_secret) | Required |
| `PINGONE_ENVIRONMENT_ID` | [PingOne - environment_id](https://registry.terraform.io/providers/pingidentity/pingone/latest/docs#environment_id) | Required |
| `PINGONE_REGION` | [PingOne - region](https://registry.terraform.io/providers/pingidentity/pingone/latest/docs#region) | Required |


## Setting Variables
The following variables can be set prior to running the example:

| Variable name | Required | Data Type | Default Value | Example Value | Description |
|--------------------------------------|----------|-----------|---------------|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
| `pingdirectory_console_base_url` | No | String | `https://localhost:8443` | `https://my-directory-host:8443` | The PingDirectory Console's base URL, used when forming the console sign-on link and the OpenID Connect callback URL |
| `pingdirectory_ldap_host` | No | String | *no default* | `my-directory-host` | The LDAP hostname of the PingDirectory server. If set, this is appended to the PingDirectory Console link as the default server to manage. |
| `pingdirectory_ldaps_port` | No | Number | *no default* | `6636` | The LDAPS port of the PingDirectory server. If set, this is appended to the PingDirectory Console link as the default server to manage. |
| `pingone_environment_license_id` | Yes | String | *no default* | | A valid license UUID to apply to the new environment. See [Finding Required IDs](https://terraform.pingidentity.com/getting-started/pingone/#license-id-organization-id-and-organization-name) for instructions on how to retrieve the `pingone_environment_license_id` value from the PingOne console. |
| `pingone_environment_name` | No | String | `Terraform Example - Setting up SSO to PingDirectory from PingOne` | `My Environment` | A string that represents the name of the PingOne customer environment to create and manage with Terraform. |
| `append_date_to_environment_name` | No | Boolean | `true` | `true` | A boolean that determines whether to append the current date to the pingone_environment_name value. |

## Outputs
The following outputs are returned from the example:

| Variable name | Data Type | Sensitive Value | Description |
|-----------------------------------------------------------|-----------|-----------------|------------------------------------------------------------------------------------------------------------------|
| `pingone_environment_name` | String | No | The environment name created by the example |

## Running the Example
Use the following to run the example:

```shell
terraform plan -out infra.tfout
```

```shell
terraform apply "infra.tfout"
```

## Clean up resources
Use the following to clean up the environment:

```shell
terraform destroy
```
134 changes: 134 additions & 0 deletions examples/sso-to-pingdirectory-from-pingone/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
###########################################
# Setting up SSO to PingDirectory from PingOne
#
# This example shows how to set up SSO to PingDirectory from PingOne.
# Reference: https://docs.pingidentity.com/r/en-us/pingone/pd_ds_set_up_sso_pingdir_pingone
###########################################

locals {
pingdirectory_login_path = var.pingdirectory_ldap_host != null && var.pingdirectory_ldap_host != "" && var.pingdirectory_ldaps_port != null ? format("?ldap-hostname=%s&ldaps-port=%s", var.pingdirectory_ldap_host, var.pingdirectory_ldaps_port) : format("/login")
pingdirectory_console_url = format("%s/console%s", var.pingdirectory_console_base_url, local.pingdirectory_login_path)
}

# Create the environment
# Ref: https://docs.pingidentity.com/r/en-us/pingone/pingone_t_create_pingone_environment
# Ref: https://docs.pingidentity.com/r/en-us/pingone/pingone_add_pingdirectory_to_the_environment
# Ref: https://docs.pingidentity.com/r/en-us/pingone/pingone_link_pingone_to_pingdirectory
resource "pingone_environment" "my_environment" {
name = local.pingone_environment_name
description = "This environment was created by Terraform as an example of how to set up SSO to PingDirectory from PingOne."
type = "SANDBOX"
license_id = var.pingone_environment_license_id

default_population {}

service {
type = "SSO"
}

service {
type = "PingDirectory"
console_url = local.pingdirectory_console_url
}
}

resource "pingone_population" "pingdirectory_admins" {
environment_id = pingone_environment.my_environment.id

name = "PingDirectory Demo Admins"
}

# Create a demo user and map it to the PingDirectory root DN user
# Ref: https://docs.pingidentity.com/r/en-us/pingone/pingone_configure_matching_administrator_accounts
resource "pingone_user" "demo_admin" {
environment_id = pingone_environment.my_environment.id

population_id = pingone_population.pingdirectory_admins.id

username = "demouser1"
email = "foouser@pingidentity.com"

name = {
family = "User1"
given = "Demo"
}
}

resource "pingdirectory_root_dn_user" "demo_admin" {
name = pingone_user.demo_admin.username
email_address = [pingone_user.demo_admin.email]
first_name = [pingone_user.demo_admin.name.given]
last_name = [pingone_user.demo_admin.name.family]

inherit_default_root_privileges = true
search_result_entry_limit = 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these attribute required for SSO?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be confirmed - once we have the remaining pieces in the PD provider then I'll do a full end-to-end test and if they're optional I'll likely remove them

time_limit_seconds = 0
look_through_entry_limit = 0
idle_time_limit_seconds = 0
password_policy = "Root Password Policy"
require_secure_authentication = false
require_secure_connections = false
}

# Create an application for the PingDirectory Administrative Console
# Ref: https://docs.pingidentity.com/r/en-us/pingone/pingone_add_the_oidc_application
resource "pingone_application" "pingdirectory_admin_console" {
environment_id = pingone_environment.my_environment.id
name = "PingDirectory Administrative Console"
description = "Application for the PingDirectory Administrative Console"
enabled = true

oidc_options {
type = "WEB_APP"
grant_types = ["AUTHORIZATION_CODE"]
response_types = ["CODE"]
token_endpoint_authn_method = "CLIENT_SECRET_BASIC"
redirect_uris = [format("%s/console/oidc/cb", var.pingdirectory_console_base_url)]
}
}

resource "pingone_application_attribute_mapping" "username_mapping" {
environment_id = pingone_environment.my_environment.id
application_id = pingone_application.pingdirectory_admin_console.id

name = "sub"
value = "$${user.username}"

required = true
}

# Configure the PingDirectory administrator console with PingOne details
# Ref: https://docs.pingidentity.com/r/en-us/pingone/pingone_configure_the_application_in_pingdirectory
resource "pingdirectory_id_token_validator" "pingone_token_validator" {
name = "PingOne ID Token Validator"
type = "ping-one"
issuer_url = module.pingone_utils.pingone_environment_issuer
enabled = true
identity_mapper = "All Admin Users"
evaluation_order_index = 1
}

resource "pingdirectory_sasl_mechanism_handler" "oauth_bearer_sasl_mechanism_handler" {
name = "OAUTHBEARER"
type = "oauth-bearer"
enabled = true

id_token_validator = [pingdirectory_id_token_validator.pingone_token_validator.name]
require_both_access_token_and_id_token = false
}

resource "pingdirectory_default_web_application_extension" "console_web_application_extension" {
name = "Console"
description = "The Administrative Console"
base_context_path = "/console"
war_file = "webapps/console.war"

ldap_server = "ldaps://0d7334259c96:1636"
log_file = "logs/webapps/console.log"
complexity = "advanced"

sso_enabled = true
oidc_client_id = pingone_application.pingdirectory_admin_console.oidc_options[0].client_id
oidc_client_secret = pingone_application.pingdirectory_admin_console.oidc_options[0].client_secret
oidc_issuer_url = module.pingone_utils.pingone_environment_issuer
}
8 changes: 8 additions & 0 deletions examples/sso-to-pingdirectory-from-pingone/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
output "pingdirectory_console_sign_on_url" {
value = local.pingdirectory_console_url
}

output "pingone_environment_name" {
description = "The environment name created by the example"
value = pingone_environment.my_environment.name
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
locals {
pingone_environment_name = var.append_date_to_environment_name ? format("%s %s", var.pingone_environment_name, formatdate("YYYY-MMM-DD hhmm", time_static.current.id)) : var.pingone_environment_name
}

module "pingone_utils" {
source = "pingidentity/utils/pingone"
version = "0.0.7"

region = pingone_environment.my_environment.region
environment_id = pingone_environment.my_environment.id
}

resource "time_static" "current" {}
36 changes: 36 additions & 0 deletions examples/sso-to-pingdirectory-from-pingone/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
variable "pingdirectory_console_base_url" {
type = string
default = "https://localhost:8443"
}

variable "pingdirectory_ldap_host" {
type = string
default = null
}

variable "pingdirectory_ldaps_port" {
type = number
default = null
}

variable "pingone_environment_license_id" {
description = "The license ID to use for the PingOne environment. For more information about finding the license ID, see https://terraform.pingidentity.com/getting-started/pingone/#finding-required-ids"
type = string

validation {
condition = var.pingone_environment_license_id != null && can(regex("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", var.pingone_environment_license_id))
error_message = "The pingone_environment_license_id value must be a valid PingOne resource ID, which is a UUID format."
}
}

variable "pingone_environment_name" {
description = "A string that represents the name of the PingOne customer environment to create and manage with Terraform."
type = string
default = "Terraform Example - Setting up SSO to PingDirectory from PingOne"
}

variable "append_date_to_environment_name" {
description = "A boolean that determines whether to append the current date to the pingone_environment_name value."
type = bool
default = true
}
26 changes: 26 additions & 0 deletions examples/sso-to-pingdirectory-from-pingone/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
terraform {
required_version = ">= 1.2.0"

required_providers {
pingdirectory = {
source = "pingidentity/pingdirectory"
version = ">= 1.0.0, < 2.0.0"
}
pingone = {
source = "pingidentity/pingone"
version = ">= 0.21.0, < 1.0.0"
}
time = {
source = "hashicorp/time"
version = ">= 0.9.1, < 1.0.0"
}
}
}

provider "pingdirectory" {
product_version = "9.3.0.0"
}

provider "pingone" {}

provider "time" {}