Skip to content
This repository has been archived by the owner on Jul 3, 2023. It is now read-only.

Commit

Permalink
handle signed metadata_url urls
Browse files Browse the repository at this point in the history
  • Loading branch information
iwarapter committed Apr 29, 2023
1 parent c167b35 commit c40d62f
Show file tree
Hide file tree
Showing 20 changed files with 460 additions and 68 deletions.
6 changes: 3 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ services:
depends_on:
- ldap
environment:
- OPERATIONAL_MODE=CLUSTERED_CONSOLE
- CLUSTER_BIND_ADDRESS=LINK_LOCAL
- CLUSTER_NAME=COMPOSE_PF_CLUSTER
- OPERATIONAL_MODE=STANDALONE
# - CLUSTER_BIND_ADDRESS=LINK_LOCAL
# - CLUSTER_NAME=COMPOSE_PF_CLUSTER
- DNS_QUERY_LOCATION=pingfederate-admin
- DNS_RECORD_TYPE=A
- PF_LOG_LEVEL=DEBUG
Expand Down
33 changes: 18 additions & 15 deletions docs/resources/metadata_url.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,31 @@ resource "pingfederate_metadata_url" "test" {

### Optional

- `cert_view` (Attributes) The Signature Verification Certificate details. This property is read-only and is always ignored on a POST or PUT. (see [below for nested schema](#nestedatt--cert_view))
- `id` (String) The persistent, unique ID for the Metadata Url. It can be any combination of [a-z0-9._-]. This property is system-assigned if not specified.
- `validate_signature` (Boolean) Perform Metadata Signature Validation. The default value is TRUE.
- `x509file` (Attributes) Data of the Signature Verification Certificate for the Metadata URL. (see [below for nested schema](#nestedatt--x509file))

### Read-Only

- `cert_view` (Attributes) The Signature Verification Certificate details. This property is read-only and is always ignored on a POST or PUT. (see [below for nested schema](#nestedatt--cert_view))

<a id="nestedatt--x509file"></a>
### Nested Schema for `x509file`

Required:

- `file_data` (String) The certificate data in PEM format. New line characters should be omitted or encoded in this value.

Optional:

- `crypto_provider` (String) Cryptographic Provider. This is only applicable if Hybrid HSM mode is true.
- `id` (String) The persistent, unique ID for the certificate. It can be any combination of [a-z0-9._-]. This property is system-assigned if not specified.


<a id="nestedatt--cert_view"></a>
### Nested Schema for `cert_view`

Optional:
Read-Only:

- `crypto_provider` (String) Cryptographic Provider. This is only applicable if Hybrid HSM mode is true.
- `expires` (String) The end date up until which the item is valid, in ISO 8601 format (UTC).
Expand All @@ -56,19 +72,6 @@ Optional:
- `valid_from` (String) The start date from which the item is valid, in ISO 8601 format (UTC).
- `version` (Number) The X.509 version to which the item conforms.


<a id="nestedatt--x509file"></a>
### Nested Schema for `x509file`

Required:

- `file_data` (String) The certificate data in PEM format. New line characters should be omitted or encoded in this value.

Optional:

- `crypto_provider` (String) Cryptographic Provider. This is only applicable if Hybrid HSM mode is true.
- `id` (String) The persistent, unique ID for the certificate. It can be any combination of [a-z0-9._-]. This property is system-assigned if not specified.

## Import

Import is supported using the following syntax:
Expand Down
26 changes: 13 additions & 13 deletions docs/resources/sp_idp_connection.md
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,6 @@ Optional:
Required:

- `idp_identity_mapping` (String) Defines the process in which users authenticated by the IdP are associated with user accounts local to the SP.
- `oauth_authentication_policy_contract_ref` (Block List, Min: 1, Max: 1) The Authentication policy contract to map into for OAuth. The policy contract can subsequently be mapped into the OAuth persistent grant. (see [below for nested schema](#nestedblock--idp_browser_sso--oauth_authentication_policy_contract_ref))
- `protocol` (String) The browser-based SSO protocol to use.

Optional:
Expand All @@ -413,25 +412,14 @@ Optional:
- `enabled_profiles` (List of String) The profiles that are enabled for browser-based SSO. SAML 2.0 supports all profiles whereas SAML 1.x IdP connections support both IdP and SP (non-standard) initiated SSO. This is required for SAMLx.x Connections.
- `incoming_bindings` (List of String) The SAML bindings that are enabled for browser-based SSO. This is required for SAML 2.0 connections when the enabled profiles contain the SP-initiated SSO profile or either SLO profile. For SAML 1.x based connections, it is not used for SP Connections and it is optional for IdP Connections.
- `message_customizations` (Block List) The message customizations for browser-based SSO. Depending on server settings, connection type, and protocol this may or may not be supported. (see [below for nested schema](#nestedblock--idp_browser_sso--message_customizations))
- `oauth_authentication_policy_contract_ref` (Block List, Max: 1) The Authentication policy contract to map into for OAuth. The policy contract can subsequently be mapped into the OAuth persistent grant. (see [below for nested schema](#nestedblock--idp_browser_sso--oauth_authentication_policy_contract_ref))
- `oidc_provider_settings` (Block List) The OpenID Provider configuration settings. Required for an OIDC connection. (see [below for nested schema](#nestedblock--idp_browser_sso--oidc_provider_settings))
- `sign_authn_requests` (Boolean) Determines whether SAML authentication requests should be signed.
- `slo_service_endpoints` (Block List) A list of possible endpoints to send SLO requests and responses. (see [below for nested schema](#nestedblock--idp_browser_sso--slo_service_endpoints))
- `sso_o_auth_mapping` (Block List) Direct mapping from the IdP connection to the OAuth persistent grant. (see [below for nested schema](#nestedblock--idp_browser_sso--sso_o_auth_mapping))
- `sso_service_endpoints` (Block List) The IdP SSO endpoints that define where to send your authentication requests. Only required for SP initiated SSO. This is required for SAML x.x and WS-FED Connections. (see [below for nested schema](#nestedblock--idp_browser_sso--sso_service_endpoints))
- `url_whitelist_entries` (Block List) For WS-Federation connections, a whitelist of additional allowed domains and paths used to validate wreply for SLO, if enabled. (see [below for nested schema](#nestedblock--idp_browser_sso--url_whitelist_entries))

<a id="nestedblock--idp_browser_sso--oauth_authentication_policy_contract_ref"></a>
### Nested Schema for `idp_browser_sso.oauth_authentication_policy_contract_ref`

Required:

- `id` (String) The ID of the resource.

Read-Only:

- `location` (String) A read-only URL that references the resource. If the resource is not currently URL-accessible, this property will be null.


<a id="nestedblock--idp_browser_sso--adapter_mappings"></a>
### Nested Schema for `idp_browser_sso.adapter_mappings`

Expand Down Expand Up @@ -1229,6 +1217,18 @@ Optional:
- `message_expression` (String)


<a id="nestedblock--idp_browser_sso--oauth_authentication_policy_contract_ref"></a>
### Nested Schema for `idp_browser_sso.oauth_authentication_policy_contract_ref`

Required:

- `id` (String) The ID of the resource.

Read-Only:

- `location` (String) A read-only URL that references the resource. If the resource is not currently URL-accessible, this property will be null.


<a id="nestedblock--idp_browser_sso--oidc_provider_settings"></a>
### Nested Schema for `idp_browser_sso.oidc_provider_settings`

Expand Down
24 changes: 24 additions & 0 deletions internal/framework/attribute_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package framework

import (
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"
)

var certViewAttrTypes = map[string]attr.Type{
"crypto_provider": types.StringType,
"expires": types.StringType,
"id": types.StringType,
"issuer_dn": types.StringType,
"key_algorithm": types.StringType,
"key_size": types.NumberType,
"serial_number": types.StringType,
"sha1fingerprint": types.StringType,
"sha256fingerprint": types.StringType,
"signature_algorithm": types.StringType,
"status": types.StringType,
"subject_alternative_names": types.ListType{ElemType: types.StringType},
"subject_dn": types.StringType,
"valid_from": types.StringType,
"version": types.NumberType,
}
6 changes: 4 additions & 2 deletions internal/framework/expander.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package framework
import (
"context"

"github.com/hashicorp/terraform-plugin-framework/types/basetypes"

"github.com/hashicorp/terraform-plugin-framework/types"
pf "github.com/iwarapter/pingfederate-sdk-go/pingfederate/models"
)
Expand Down Expand Up @@ -336,8 +338,8 @@ func expandGlobalAuthenticationSessionPolicy(in GlobalAuthenticationSessionPolic

func expandMetadataUrl(in MetadataUrlData) *pf.MetadataUrl {
var result pf.MetadataUrl
if in.CertView != nil {
result.CertView = expandCertView(*in.CertView)
if !in.CertView.IsUnknown() && !in.CertView.IsNull() {
in.CertView.As(context.Background(), &result.CertView, basetypes.ObjectAsOptions{})
}
if !in.Id.IsUnknown() && !in.Id.IsNull() {
result.Id = String(in.Id.ValueString())
Expand Down
6 changes: 5 additions & 1 deletion internal/framework/flattener.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package framework

import (
"context"
"math/big"

"github.com/hashicorp/terraform-plugin-framework/attr"
Expand Down Expand Up @@ -653,7 +654,10 @@ func flattenGlobalAuthenticationSessionPolicy(in *pf.GlobalAuthenticationSession
func flattenMetadataUrl(in *pf.MetadataUrl) *MetadataUrlData {
result := MetadataUrlData{}
if in.CertView != nil {
result.CertView = flattenCertView(in.CertView)
flat := flattenCertView(in.CertView)
result.CertView, _ = types.ObjectValueFrom(context.Background(), certViewAttrTypes, *flat)
} else {
result.CertView = types.ObjectNull(certViewAttrTypes)
}
if in.Id != nil {
result.Id = types.StringValue(*in.Id)
Expand Down
139 changes: 134 additions & 5 deletions internal/framework/pingfederate_metadata_url_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func TestAccPingFederateMetadataUrlResource(t *testing.T) {
CheckDestroy: testAccCheckPingFederateMetadataUrlResourceDestroy,
Steps: []resource.TestStep{
{
Config: testAccPingFederateMetadataUrlResourceConfig("true"),
Config: testAccPingFederateMetadataUrlResourceConfig("acc_test_one"),
Check: resource.ComposeTestCheckFunc(
testAccCheckPingFederateMetadataUrlResourceExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "name", "acc_test_one"),
Expand All @@ -54,10 +54,10 @@ func TestAccPingFederateMetadataUrlResource(t *testing.T) {
),
},
{
Config: testAccPingFederateMetadataUrlResourceConfig("false"),
Config: testAccPingFederateMetadataUrlResourceConfig("acc_test_one_changed"),
Check: resource.ComposeTestCheckFunc(
testAccCheckPingFederateMetadataUrlResourceExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "name", "acc_test_one"),
resource.TestCheckResourceAttr(resourceName, "name", "acc_test_one_changed"),
resource.TestCheckResourceAttr(resourceName, "url", "https://sptest.iamshowcase.com/testsp_metadata.xml"),
resource.TestCheckResourceAttr(resourceName, "validate_signature", "false"),
),
Expand All @@ -71,6 +71,39 @@ func TestAccPingFederateMetadataUrlResource(t *testing.T) {
})
}

func TestAccPingFederateMetadataUrlResource_SignedMetadata(t *testing.T) {
resourceName := "pingfederate_metadata_url.demo"
resource.ParallelTest(t, resource.TestCase{
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
CheckDestroy: testAccCheckPingFederateMetadataUrlResourceDestroy,
Steps: []resource.TestStep{
{
Config: testAccPingFederateMetadataUrlResourceSignedMetadataConfig("acc_test_two"),
Check: resource.ComposeTestCheckFunc(
testAccCheckPingFederateMetadataUrlResourceExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "name", "acc_test_two"),
resource.TestCheckResourceAttr(resourceName, "url", "https://localhost:9031/pf/federation_metadata.ping?PartnerIdpId=foobar"),
resource.TestCheckResourceAttr(resourceName, "validate_signature", "true"),
),
},
{
Config: testAccPingFederateMetadataUrlResourceSignedMetadataConfig("acc_test_two_changed"),
Check: resource.ComposeTestCheckFunc(
testAccCheckPingFederateMetadataUrlResourceExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "name", "acc_test_two_changed"),
resource.TestCheckResourceAttr(resourceName, "url", "https://localhost:9031/pf/federation_metadata.ping?PartnerIdpId=foobar"),
resource.TestCheckResourceAttr(resourceName, "validate_signature", "true"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckPingFederateMetadataUrlResourceDestroy(s *terraform.State) error {
return nil
}
Expand All @@ -79,9 +112,105 @@ func testAccPingFederateMetadataUrlResourceConfig(configUpdate string) string {
return fmt.Sprintf(`
resource "pingfederate_metadata_url" "demo" {
id = "acc_test_one"
name = "acc_test_one"
name = "%s"
url = "https://sptest.iamshowcase.com/testsp_metadata.xml"
validate_signature = %s
validate_signature = true
}`, configUpdate)
}

func testAccPingFederateMetadataUrlResourceSignedMetadataConfig(configUpdate string) string {
return fmt.Sprintf(`
resource "pingfederate_sp_idp_connection" "test" {
active = true
base_url = "https://localhost:9031"
entity_id = "foobar"
error_page_msg_id = "errorDetail.spSsoFailure"
logging_mode = "STANDARD"
name = "foobar"
virtual_entity_ids = []
credentials {
certs {
active_verification_cert = true
encryption_cert = false
primary_verification_cert = true
secondary_verification_cert = false
x509_file {
file_data = <<-EOT
-----BEGIN CERTIFICATE-----
MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQK
EwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYwMDAwWjASMRAwDgYDVQQKEwdB
Y21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDU
U4rvwCUg/CNaJ2PT5xLD4N1Vcb8rbFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rla
jEX2D73faWJekD0UaUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJa
RI6PYfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61XyelukPOGKBV/q
6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZuh7AXF5+4nJS4AAt0n1lN
Y7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggrBgEFBQcD
ATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREE
JzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOC
AQEAxWGI5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsvcxv3
HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2+tK/tKHRP1Y/Ra0R
iDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3Bgrw/ZQTTIVjjh4JBSW3WyWgNo/ik
C1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lH
Ja6I5leHUNOHahRbpbWeOfs/WkBKOclmOV2xlTVuPw==
-----END CERTIFICATE-----
EOT
id = "example"
}
}
}
idp_browser_sso {
assertions_signed = false
enabled_profiles = ["IDP_INITIATED_SSO"]
idp_identity_mapping = "NONE"
incoming_bindings = ["POST"]
protocol = "SAML20"
sign_authn_requests = false
attribute_contract {
core_attributes {
masked = false
name = "SAML_SUBJECT"
}
}
decryption_policy {
assertion_encrypted = false
attributes_encrypted = false
slo_encrypt_subject_name_id = false
slo_subject_name_id_encrypted = false
subject_name_id_encrypted = false
}
}
}
resource "pingfederate_metadata_url" "demo" {
name = "%s"
url = "https://localhost:9031/pf/federation_metadata.ping?PartnerIdpId=${pingfederate_sp_idp_connection.test.entity_id}"
validate_signature = true
x509file = {
file_data = <<-EOT
-----BEGIN CERTIFICATE-----
MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQK
EwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYwMDAwWjASMRAwDgYDVQQKEwdB
Y21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDU
U4rvwCUg/CNaJ2PT5xLD4N1Vcb8rbFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rla
jEX2D73faWJekD0UaUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJa
RI6PYfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61XyelukPOGKBV/q
6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZuh7AXF5+4nJS4AAt0n1lN
Y7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggrBgEFBQcD
ATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREE
JzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOC
AQEAxWGI5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsvcxv3
HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2+tK/tKHRP1Y/Ra0R
iDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3Bgrw/ZQTTIVjjh4JBSW3WyWgNo/ik
C1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lH
Ja6I5leHUNOHahRbpbWeOfs/WkBKOclmOV2xlTVuPw==
-----END CERTIFICATE-----
EOT
}
}`, configUpdate)
}

Expand Down
24 changes: 24 additions & 0 deletions internal/framework/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import (
"os"
"testing"

"github.com/iwarapter/pingfederate-sdk-go/services/certificatesCa"
"github.com/iwarapter/pingfederate-sdk-go/services/keyPairsSslServer"

"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"

"github.com/hashicorp/terraform-plugin-mux/tf5to6server"
Expand Down Expand Up @@ -105,6 +108,27 @@ func requiredVersionTestCheckFunc(major, minor int, f resource.TestCheckFunc) re
}

func dataSetup() error {
sslPairs, _, err := pfc.KeyPairsSslServer.GetKeyPairs()
if err != nil {
for _, view := range *sslPairs.Items {
if *view.SubjectDN == "CN=ping, O=ping, C=GB" {
pfc.KeyPairsSslServer.UpdateSettings(&keyPairsSslServer.UpdateSettingsInput{
Body: pf.SslServerSettings{
ActiveAdminConsoleCerts: &[]*pf.ResourceLink{{Id: view.Id}},
ActiveRuntimeServerCerts: &[]*pf.ResourceLink{{Id: view.Id}},
AdminConsoleCertRef: &pf.ResourceLink{Id: view.Id},
RuntimeServerCertRef: &pf.ResourceLink{Id: view.Id},
},
})
cert, _, _ := pfc.KeyPairsSslServer.ExportCertificateFile(&keyPairsSslServer.ExportCertificateFileInput{
Id: *view.Id,
})
pfc.CertificatesCa.ImportTrustedCA(&certificatesCa.ImportTrustedCAInput{
Body: pf.X509File{Id: String("testing"), FileData: cert},
})
}
}
}
pcv := pfc.PasswordCredentialValidators
if _, _, err := pcv.GetPasswordCredentialValidator(&passwordCredentialValidators.GetPasswordCredentialValidatorInput{Id: "pcvtestme"}); err != nil {
if _, _, err := pcv.CreatePasswordCredentialValidator(&passwordCredentialValidators.CreatePasswordCredentialValidatorInput{
Expand Down

0 comments on commit c40d62f

Please sign in to comment.