Skip to content

Commit 5c510fe

Browse files
committed
Commit for secure meta data extract from id
1 parent 7d8ba33 commit 5c510fe

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+513
-5017
lines changed

security/security-design/shared-assets/oci-security-health-check-forensics/LICENSE renamed to security/security-design/shared-assets/iam-saml-metadata-from-identity-domain/LICENSE

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
Copyright (c) 2025 Oracle and/or its affiliates.
1+
2+
Copyright (c) 2025 Oracle and/or its affiliates.
23

34
The Universal Permissive License (UPL), Version 1.0
45

@@ -32,4 +33,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
3233
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3334
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3435
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35-
SOFTWARE.
36+
SOFTWARE.
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Automating SAML Metadata Retrieval in OCI Identity Domains
2+
3+
This solution provisions an **OCI Identity Domain** with Terraform and securely retrieves its **SAML metadata** for integration with external identity providers.
4+
5+
Instead of making the SAML metadata publicly accessible by enabling the *“Configure client access”* option under *Access Signing Certificate*, this approach uses a **temporary confidential OAuth client** to authenticate and download the metadata.
6+
7+
The workflow is:
8+
9+
1. **Provisioning with Terraform (Optional)**
10+
11+
* Deploy the OCI Identity Domain.
12+
* Trigger a shell script via `null_resource` provisioner after domain creation.
13+
14+
2. **Automated Metadata Retrieval via Shell Script**
15+
16+
* Register a **temporary confidential application** that supports the *client credentials* grant type via OCI CLI.
17+
* Request an `access_token` from the Identity Domain OAuth endpoint using the app's credentials.
18+
* Call the `/fed/v1/metadata` endpoint with `Authorization: Bearer` header.
19+
* Download and save the SAML metadata XML to a local file (`oci_idcs_metadata.xml`).
20+
* Deactivate and delete the temporary confidential app (cleanup).
21+
* Print the `client_id` and masked `client_secret` to stdout (not stored in Terraform state).
22+
23+
3. **Security Benefits**
24+
25+
* **No Public Exposure**: The SAML metadata endpoint remains private and is never exposed to the internet.
26+
* **Authenticated Access**: Only the temporary, authenticated client can retrieve the metadata.
27+
* **Ephemeral Credentials**: The OAuth client is destroyed immediately after use, minimizing the attack surface.
28+
* **State-Free Secrets**: The client credentials are never written to the Terraform state file.
29+
30+
This method provides both **automation** and **security**, ensuring SAML metadata can be retrieved programmatically without compromising the confidentiality of signing certificates.
31+
32+
33+
## Resources Created
34+
35+
### By Terraform (Optional):
36+
1. **OCI Identity Domain** (`oci_identity_domain.identity_domain`) - A managed identity domain in OCI with specified compartment, display name, description, license type, and home region
37+
2. **Null Resource** (`null_resource.configure_idcs_app`) - Triggers the shell script after domain creation
38+
3. The **OCI Identity Domain** is not destroyed after creation. The SAML metadate would then be invalid.
39+
40+
### By Shell Script (`create_confidential_app_and_get_saml_meta_data.sh`):
41+
1. **Confidential OAuth Client App** - Created in the new identity domain with:
42+
- Client credentials grant type
43+
- Confidential client type
44+
- Custom web app template
45+
2. **SAML Metadata XML File** (`oci_idcs_metadata.xml`) - Downloaded to local filesystem
46+
3. **Cleanup** - By default, the script deactivates and deletes the confidential app after downloading metadata (unless `KEEP_APP=true`)
47+
48+
## Prerequisites
49+
50+
### Required Tools:
51+
- **OCI CLI** with Identity Domains commands
52+
- **jq** (JSON processor)
53+
- **curl**
54+
- **python3**
55+
- **Terraform** ≥ 1.5.0
56+
57+
### Required Configuration:
58+
1. **OCI CLI configured** with valid profile (default: `DEFAULT`)
59+
2. **terraform.tfvars** populated with:
60+
- `compartment_id` (OCID of the enclosing compartment)
61+
- `region`
62+
- `domain_display_name`
63+
- `domain_description`
64+
- `license_type`
65+
- `tenancy_ocid`
66+
- `oci_profile`
67+
68+
### Optional (for cleanup):
69+
- `ADMIN_ACCESS_TOKEN` or
70+
- `ADMIN_CLIENT_ID` + `ADMIN_CLIENT_SECRET` (for proper app cleanup with admin privileges)
71+
72+
## How to Run
73+
74+
1. **Initialize**: `terraform init`
75+
2. **Plan**: `terraform plan -out tfplan`
76+
3. **Apply**: `terraform apply tfplan`
77+
78+
### Environment Variables (optional):
79+
- `APP_NAME` - Custom app name (default: `saml-metadata-client`)
80+
- `SCOPE` - OAuth scope (default: `urn:opc:idm:__myscopes__`)
81+
- `OUT_XML` - Output file path (default: `oci_idcs_metadata.xml`)
82+
- `KEEP_APP` - Set to `true` to prevent app deletion
83+
84+
The script automatically receives `IDCS_ENDPOINT` and `PROFILE` from Terraform.
85+
86+
## Terraform Flow
87+
88+
During `apply`, the configuration creates the OCI Identity Domain. After the domain exists, Terraform triggers `scripts/create_confidential_app_and_get_saml_meta_data.sh`, which:
89+
90+
- provisions a confidential OAuth client against the new domain via the OCI CLI,
91+
- regenerates the client secret if necessary,
92+
- retrieves a client-credentials token, and
93+
- downloads the SAML metadata document to `oci_idcs_metadata.xml` (override via `OUT_XML`).
94+
95+
The script prints the confidential app ID, client ID, and a masked client secret—store the full secret securely outside of Terraform state.
96+
97+
## Running the Script Standalone
98+
99+
If an identity domain already exists, you can run the script directly without Terraform:
100+
101+
```bash
102+
IDCS_ENDPOINT="https://idcs-<hash>.identity.oraclecloud.com" \
103+
PROFILE="oci_profile_name" \
104+
bash scripts/create_confidential_app_and_get_saml_meta_data.sh
105+
```
106+
107+
### Optional Environment Variables:
108+
- `APP_NAME` - Custom app name (default: `saml-metadata-client`)
109+
- `SCOPE` - OAuth scope (default: `urn:opc:idm:__myscopes__`)
110+
- `OUT_XML` - Output file path (default: `oci_idcs_metadata.xml`)
111+
- `KEEP_APP` - Set to `true` to prevent app deletion after metadata retrieval
112+
- `ADMIN_ACCESS_TOKEN` - Bearer token with Identity Domain Administrator rights (preferred for cleanup)
113+
- `ADMIN_CLIENT_ID` / `ADMIN_CLIENT_SECRET` - Admin confidential app credentials (alternative for cleanup)
114+
- `ADMIN_SCOPE` - Admin scope (default: `urn:opc:idm:__myscopes__`)
115+
116+
### Example with custom settings:
117+
```bash
118+
IDCS_ENDPOINT="https://idcs-abc123.identity.oraclecloud.com" \
119+
PROFILE="my-oci-profile" \
120+
APP_NAME="my-metadata-app" \
121+
OUT_XML="custom_metadata.xml" \
122+
KEEP_APP="false" \
123+
bash scripts/create_confidential_app_and_get_saml_meta_data.sh
124+
```
125+
126+
This is useful when you need to retrieve SAML metadata from an existing identity domain without provisioning a new one. When you want to keep the confidential application, set the variable KEEP_APP to false.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
terraform {
2+
required_version = ">= 1.5.0"
3+
4+
required_providers {
5+
oci = {
6+
source = "hashicorp/oci"
7+
}
8+
null = {
9+
source = "hashicorp/null"
10+
}
11+
}
12+
}
13+
14+
resource "oci_identity_domain" "identity_domain" {
15+
compartment_id = var.compartment_id
16+
display_name = var.domain_display_name
17+
description = var.domain_description
18+
is_hidden_on_login = var.is_hidden_on_login
19+
license_type = var.license_type
20+
home_region = var.region
21+
}
22+
23+
# Wait until the thing exists.
24+
resource "null_resource" "configure_idcs_app" {
25+
depends_on = [oci_identity_domain.identity_domain]
26+
27+
triggers = {
28+
identity_domain_id = oci_identity_domain.identity_domain.id
29+
}
30+
31+
provisioner "local-exec" {
32+
when = create
33+
command = "${path.module}/scripts/create_confidential_app_and_get_saml_meta_data.sh"
34+
environment = {
35+
IDCS_ENDPOINT = oci_identity_domain.identity_domain.url
36+
PROFILE = var.oci_profile
37+
}
38+
}
39+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
output "identity_domain_id" {
3+
description = "The OCID of the created identity domain."
4+
value = oci_identity_domain.identity_domain.id
5+
}
6+
7+
output "identity_domain_url" {
8+
description = "The URL of the created identity domain."
9+
value = oci_identity_domain.identity_domain.url
10+
}
11+
12+
output "identity_domain_home_region_url" {
13+
description = "The home region URL of the created identity domain."
14+
value = oci_identity_domain.identity_domain.home_region_url
15+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
provider "oci" {
2+
# Uses ~/.oci/config by default; select profile via var.oci_profile
3+
config_file_profile = var.oci_profile
4+
}

0 commit comments

Comments
 (0)