Skip to content

resource: Expand PingOne SSO export coverage - #143

Open
samir-gandhi wants to merge 21 commits into
mainfrom
pingone-core-resources
Open

resource: Expand PingOne SSO export coverage#143
samir-gandhi wants to merge 21 commits into
mainfrom
pingone-core-resources

Conversation

@samir-gandhi

Copy link
Copy Markdown
Contributor

Summary

Expands PingOne SSO export coverage with the application-family and supporting resource batches, plus fixes surfaced by live UAT exports.

Resource coverage

  • Adds export support for the application family, sign-on policy, resource scope family, and related child resources.
  • Adds pingone_password_policy, pingone_group_nesting, pingone_resource_secret, pingone_population_default, and pingone_population_default_identity_provider.
  • Intentionally excludes user and user-assignment resources because individual end-user identities are not promotable environment configuration.

Export correctness

  • Resolves UUIDs embedded in plain SCIM filter strings, including pingone_group.user_filter.
  • Filters CORE/PREDEFINED resource attributes that have no exportable API value.
  • Filters built-in PingOne API scopes that the provider schema cannot manage.
  • Silently skips deterministic PingOne system applications and other deterministic bootstrap objects.
  • Deduplicates actionable warning messages.
  • Documents system-managed/bootstrap resource analysis for future resource work.

Verification

  • go build ./...
  • go vet ./...
  • gofmt -l .
  • go test ./... -count=1
  • go run ./tools/validate-definitions definitions/
  • Live UAT export completed successfully.
  • Generated UAT configuration passed terraform validate.

One pre-existing intermittent map-iteration test (TestResolveEmbeddedReferences_DisambiguatedName_StableAcrossEnvironments) may fail nondeterministically; reruns pass and the failure is unrelated to this change.

🤖 Generated with Claude Code

samir-gandhi and others added 21 commits July 24, 2026 15:34
…sources

pingone-go-client only covers DaVinci, Environments, Connectors, and
ConfigurationManagement APIs, so the ~92 open Platform/SSO/Authorize/MFA/
Protect/Verify export-support issues cannot be implemented against it.
Add patrickcping/pingone-go-sdk-v2/management (the SDK terraform-provider-
pingone itself uses) as a second client on Client, built lazily since it
performs an OAuth exchange at construction time rather than on first
request.
The go:embed directive listed pingone/base and pingone/davinci explicitly,
so every new resource category (sso, platform, mfa, ...) would require
editing this file — violating the "new resource requires zero edits to
existing files" invariant. A single pingone/*/*.yaml wildcard covers any
category subdirectory automatically.
Adds a schema-driven definition and Go handler for pingone_group,
covering name, description, population_id (referencing
pingone_population), user_filter, external_id, and custom_data
(jsonencode_raw). Uses the pingone-go-sdk-v2/management SDK via
Client.management(), following the list-then-iterate pagination
pattern documented in the new-resource-pingone skill.

Also bumps the hardcoded definition-count assertions in
internal/schema/integration_test.go and the sorted resource-type
list in internal/platform/pingone/dispatch_test.go, both of which
track the total number of registered definitions/resources and
needed updating for the new pingone_group entry.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds the pingone_population YAML definition and Go handler using the
management SDK's list-then-paginate/get pattern, per issue #81. Both
password_policy.id and theme.id nested references degrade gracefully
to Terraform variable fallbacks since pingone_password_policy and
pingone_branding_theme are not yet exported by this tool; resolution
auto-promotes once those resource types land, with no changes needed
here.

Updates dispatch_test.go and schema integration_test.go resource-count
assertions to account for the new registered type, and flips the
pingone_population row in RESOURCE_COVERAGE.md to supported.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds Terraform export support for pingone_resource (OAuth 2.0 custom
resources) via the management SDK. Built-in resources (OPENID_CONNECT,
PINGONE_API) are filtered out of the list since only CUSTOM resources
are manageable through the pingone_resource Terraform resource.

Closes #84.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a schema-driven definition and Go handler for pingone_application,
covering OIDC, SAML, External Link, and WS-Fed application types (the
four the pingone_application Terraform resource schema actually supports).
The management SDK's ReadOneApplication200Response is a discriminated
union with 7 possible variants; a custom handler unwraps it via
GetActualInstance() and projects the result into a flat struct with one
nilable field per supported variant, letting the generic object/
nested_attributes engine emit exactly one *_options block per resource.

The 3 built-in PingOne system application types (Admin Console, Portal,
Self Service) have no corresponding schema block in the provider and are
skipped with a warning (c.AddWarning) rather than exported incorrectly.

Also bumps the hardcoded definition-count assertions in
internal/schema/integration_test.go and the sorted resource-type list in
internal/platform/pingone/dispatch_test.go, both of which track the total
number of registered definitions/resources and needed updating for the
new pingone_application entry.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…olaris/pilot-combined-manual-test

# Conflicts:
#	internal/platform/pingone/dispatch_test.go
…aris/pilot-combined-manual-test

# Conflicts:
#	internal/platform/pingone/dispatch_test.go
#	internal/schema/integration_test.go
…polaris/pilot-combined-manual-test

# Conflicts:
#	internal/schema/integration_test.go
Merging the group/population/resource pilot branches together surfaced
a symbol collision: three independent agents each wrote an identically
named test helper for building a fake management.APIClient. Renamed
each to be resource-specific so all three test files can coexist.
…branch

Flips enabled: true on definitions/pingone/base/environment.yaml so the
resource participates in export alongside the pilot resources. This was
deliberately disabled in commit 9eb4335 ("not ready for publish") and
re-enabling it changes environment_id from a variable reference to a
real resource reference across every other exported resource -- a
breaking change for existing users, confirmed via make regression-local.
Not intended to ship; local manual-testing branch only.
Resolves the fallback-variable case for pingone_population.theme and
the DaVinci flow showForm theme reference (resource_flow.go), both of
which previously fell back to a Terraform variable because
pingone_branding_theme had no exported resource type.
pingone-go-client only covers DaVinci/Environments/Connectors; the
patrickcping/pingone-go-sdk-v2/management SDK added for the Platform/
SSO/Authorize backlog (issue #119) was undocumented outside a local,
gitignored skill file. Records which SDK backs which resource category,
why the management client is built lazily, and the shape differences
that affect handler code.
…source_scope family, application children)

Completes the application-family batch of PingOne SSO resource export
support: pingone_sign_on_policy (new base resource), pingone_resource_scope,
pingone_resource_scope_openid, pingone_resource_scope_pingone_api (children
of pingone_resource / built-in resources), and pingone_application_secret,
pingone_application_attribute_mapping, pingone_application_resource,
pingone_application_flow_policy_assignment,
pingone_application_sign_on_policy_assignment, and
pingone_application_resource_grant (children of pingone_application).

pingone_sign_on_policy and the resource_scope family were added ahead of
their dependents (application_sign_on_policy_assignment,
application_attribute_mapping's oidc_scopes, application_resource_grant's
scopes) so those references resolve to real resources instead of fallback
variables.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Three bugs surfaced by exporting against a real environment:

- resource/pingone_application_attribute_mapping: mapping names (e.g. the
  reserved "sub"/"saml_subject" core mappings) are only unique within a
  single application, not across the environment, causing duplicate-label
  export failures whenever multiple applications shared a core mapping name.
  Added label_fields: [name, application_id].

- resource/pingone_resource_scope, resource/pingone_application_resource:
  import_id_format used "{resource_id}", which the import generator treats
  as a reserved placeholder for the resource's own ID (data.ID), not as a
  reference to the "resource_id" *attribute*. This silently duplicated the
  scope/app-resource's own ID into both UUID segments of the import ID
  instead of including the parent resource's ID. Added a distinctly-named
  shadow attribute (parent_resource_id_for_import) for the import path.

- resource/pingone_application_resource_grant: SAML/external-link/WS-Fed
  applications have no resource-grants endpoint and return 404, aborting
  the whole export. Grants only apply to OIDC applications, so non-OIDC
  applications are now skipped without attempting the call.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ute CORE/PREDEFINED bug

Adds pingone_password_policy, pingone_group_nesting, pingone_resource_secret,
pingone_population_default, and pingone_population_default_identity_provider.
password_policy resolves the fallback-variable placeholder left on
pingone_population.password_policy.id from the prior batch.

Also fixes pingone_resource_attribute to export only user-authored (Type ==
CUSTOM) attributes — CORE/PREDEFINED attributes (e.g. "sub", "given_name")
exist on every resource automatically with no real API-returned value, which
was surfacing as spurious "required field value is missing" errors.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…up.user_filter

pingone_group.user_filter is a SCIM filter string (e.g. population.id eq
"<uuid>") rather than a jsonencode(...) JSON blob, so the existing
EmbeddedReferenceRule machinery (which walks JSON structures) couldn't reach
the embedded population UUID, and it was exported as a raw, environment-
specific ID.

Adds EmbeddedReferenceRule.PlainStringPattern: a single-capture-group regex
that locates a UUID inside an ordinary string attribute and resolves it via
the dependency graph exactly like the JSON-blob path (same Strategy
semantics), producing a new core.InterpolatedString type. Both formatters
render it correctly — HCL escapes everything except the embedded "${...}"
expression (avoiding the "$${...}" double-escaping that cty.StringVal would
otherwise produce), and tfjson passes it through as-is.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Silently skip PingOne system applications and built-in API scopes that the Terraform provider cannot manage. Deduplicate actionable warnings, document the exclusions, and add guidance for identifying system-managed resources during new resource analysis.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Regression Test Results

Matrix Entry Status Breaking Acceptable

✅ No regressions detected

All export configurations produced compatible output.


Generated by regression workflow • View run

1 similar comment
@github-actions

Copy link
Copy Markdown

Regression Test Results

Matrix Entry Status Breaking Acceptable

✅ No regressions detected

All export configurations produced compatible output.


Generated by regression workflow • View run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant