Repository: amp-labs/connectors
Pull request #1612 (2025-04-30 21:21:35)

chore(deps): bump github.com/getkin/kin-openapi from 0.131.0 to 0.132.0
Bumps [github.com/getkin/kin-openapi](https://github.com/getkin/kin-openapi) from 0.131.0 to 0.132.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/getkin/kin-openapi/releases">github.com/getkin/kin-openapi's releases</a>.</em></p>
<blockquote>
<h2>v0.132.0</h2>
<h2>What's Changed</h2>
<ul>
<li>style: Use fmt.Sprint without formating by <a href="https://github.com/gaiaz-iusipov"><code>@​gaiaz-iusipov</code></a> in <a href="https://redirect.github.com/getkin/kin-openapi/pull/1061">getkin/kin-openapi#1061</a></li>
<li>openapi3filter: don't consume request body in <code>AuthenticatorFunc</code> by <a href="https://github.com/jamietanna"><code>@​jamietanna</code></a> in <a href="https://redirect.github.com/getkin/kin-openapi/pull/1064">getkin/kin-openapi#1064</a></li>
<li>openapi2conv: fix for refs on items within additional properties by <a href="https://github.com/roberth1988"><code>@​roberth1988</code></a> in <a href="https://redirect.github.com/getkin/kin-openapi/pull/1067">getkin/kin-openapi#1067</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/gaiaz-iusipov"><code>@​gaiaz-iusipov</code></a> made their first contribution in <a href="https://redirect.github.com/getkin/kin-openapi/pull/1061">getkin/kin-openapi#1061</a></li>
<li><a href="https://github.com/roberth1988"><code>@​roberth1988</code></a> made their first contribution in <a href="https://redirect.github.com/getkin/kin-openapi/pull/1067">getkin/kin-openapi#1067</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/getkin/kin-openapi/compare/v0.131.0...v0.132.0">https://github.com/getkin/kin-openapi/compare/v0.131.0...v0.132.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/getkin/kin-openapi/commit/72b5d5177d5993bbbc8c863e36ef036850558658"><code>72b5d51</code></a> openapi2conv: fix for refs on items within additional properties (<a href="https://redirect.github.com/getkin/kin-openapi/issues/1067">#1067</a>)</li>
<li><a href="https://github.com/getkin/kin-openapi/commit/75e2cc5ad8729cf119ad0274ea0678e2e360c731"><code>75e2cc5</code></a> openapi3filter: don't consume request body in <code>AuthenticatorFunc</code> (<a href="https://redirect.github.com/getkin/kin-openapi/issues/1064">#1064</a>)</li>
<li><a href="https://github.com/getkin/kin-openapi/commit/3cf8f7dad86555f6ad46c5972cc1bfb517afb148"><code>3cf8f7d</code></a> style: Use fmt.Sprint without formating (<a href="https://redirect.github.com/getkin/kin-openapi/issues/1061">#1061</a>)</li>
<li>See full diff in <a href="https://github.com/getkin/kin-openapi/compare/v0.131.0...v0.132.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/getkin/kin-openapi&package-manager=go_modules&previous-version=0.131.0&new-version=0.132.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/go.mod b/go.mod
index 38113968..add93e76 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,7 @@ require (
 	github.com/chromedp/chromedp v0.13.6
 	github.com/deiu/linkparser v0.0.0-20170608193052-9b6849e15168
 	github.com/gertd/go-pluralize v0.2.1
-	github.com/getkin/kin-openapi v0.131.0
+	github.com/getkin/kin-openapi v0.132.0
 	github.com/go-playground/validator v9.31.0+incompatible
 	github.com/go-test/deep v1.1.1
 	github.com/gobwas/glob v0.2.3
diff --git a/go.sum b/go.sum
index 09f0ecf2..1d96f03d 100644
--- a/go.sum
+++ b/go.sum
@@ -53,8 +53,8 @@ github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/
 github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
 github.com/gertd/go-pluralize v0.2.1 h1:M3uASbVjMnTsPb0PNqg+E/24Vwigyo/tvyMTtAlLgiA=
 github.com/gertd/go-pluralize v0.2.1/go.mod h1:rbYaKDbsXxmRfr8uygAEKhOWsjyrrqrkHVpZvoOp8zk=
-github.com/getkin/kin-openapi v0.131.0 h1:NO2UeHnFKRYhZ8wg6Nyh5Cq7dHk4suQQr72a4pMrDxE=
-github.com/getkin/kin-openapi v0.131.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58=
+github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk=
+github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58=
 github.com/go-json-experiment/json v0.0.0-20250211171154-1ae217ad3535 h1:yE7argOs92u+sSCRgqqe6eF+cDaVhSPlioy1UkA0p/w=
 github.com/go-json-experiment/json v0.0.0-20250211171154-1ae217ad3535/go.mod h1:BWmvoE1Xia34f3l/ibJweyhrT+aROb/FQ6d+37F0e2s=
 github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
diff --git a/providers/aws/internal/awscore/commands.go b/providers/aws/internal/core/commands.go
similarity index 95%
rename from providers/aws/internal/awscore/commands.go
rename to providers/aws/internal/core/commands.go
index 71f399ce..d838f0ff 100644
--- a/providers/aws/internal/awscore/commands.go
+++ b/providers/aws/internal/core/commands.go
@@ -1,4 +1,4 @@
-package awscore
+package core
 
 import "github.com/amp-labs/connectors/internal/datautils"
 
diff --git a/providers/aws/internal/awscore/requests.go b/providers/aws/internal/core/requests.go
similarity index 99%
rename from providers/aws/internal/awscore/requests.go
rename to providers/aws/internal/core/requests.go
index 09acee7e..413c708d 100644
--- a/providers/aws/internal/awscore/requests.go
+++ b/providers/aws/internal/core/requests.go
@@ -1,4 +1,4 @@
-package awscore
+package core
 
 import (
 	"bytes"
diff --git a/providers/aws/internal/identitystore/metadata.go b/providers/aws/internal/identitystore/metadata.go
new file mode 100644
index 00000000..76bdd552
--- /dev/null
+++ b/providers/aws/internal/identitystore/metadata.go
@@ -0,0 +1,20 @@
+package identitystore
+
+import (
+	_ "embed"
+
+	"github.com/amp-labs/connectors/internal/staticschema"
+	"github.com/amp-labs/connectors/tools/fileconv"
+	"github.com/amp-labs/connectors/tools/scrapper"
+)
+
+var (
+	//go:embed schemas.json
+	schemas []byte
+
+	FileManager = scrapper.NewMetadataFileManager[staticschema.FieldMetadataMapV1]( // nolint:gochecknoglobals
+		schemas, fileconv.NewSiblingFileLocator())
+
+	// Schemas is cached Object schemas.
+	Schemas = FileManager.MustLoadSchemas() // nolint:gochecknoglobals
+)
diff --git a/providers/aws/internal/identitystore/schemas.json b/providers/aws/internal/identitystore/schemas.json
new file mode 100644
index 00000000..e0091c85
--- /dev/null
+++ b/providers/aws/internal/identitystore/schemas.json
@@ -0,0 +1,51 @@
+{
+  "modules": {
+    "aws-identity-center": {
+      "objects": {
+        "Groups": {
+          "displayName": "Groups",
+          "responseKey": "Groups",
+          "fields": {
+            "GroupId": "Group Id",
+            "IdentityStoreId": "Identity Store Id",
+            "Description": "Description",
+            "DisplayName": "Display Name",
+            "ExternalIds": "External Ids"
+          }
+        },
+        "Users": {
+          "displayName": "Users",
+          "responseKey": "Users",
+          "fields": {
+            "IdentityStoreId": "Identity Store Id",
+            "UserId": "User Id",
+            "Addresses": "Addresses",
+            "DisplayName": "Display Name",
+            "Emails": "Emails",
+            "ExternalIds": "External Ids",
+            "Locale": "Locale",
+            "Name": "Name",
+            "NickName": "NickName",
+            "PhoneNumbers": "Phone Numbers",
+            "PreferredLanguage": "Preferred Language",
+            "ProfileUrl": "Profile URL",
+            "Timezone": "Timezone",
+            "Title": "Title",
+            "UserName": "User Name",
+            "UserType": "User Type"
+          }
+        },
+        "GroupMemberships": {
+          "displayName": "Group Memberships",
+          "responseKey": "GroupMemberships",
+          "fields": {
+            "IdentityStoreId": "Identity Store Id",
+            "GroupId": "Group Id",
+            "MemberId": "Member Id",
+            "MembershipId": "Membership Id"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/providers/aws/internal/ssoadmin/metadata.go b/providers/aws/internal/ssoadmin/metadata.go
new file mode 100644
index 00000000..d584ddfe
--- /dev/null
+++ b/providers/aws/internal/ssoadmin/metadata.go
@@ -0,0 +1,20 @@
+package ssoadmin
+
+import (
+	_ "embed"
+
+	"github.com/amp-labs/connectors/internal/staticschema"
+	"github.com/amp-labs/connectors/tools/fileconv"
+	"github.com/amp-labs/connectors/tools/scrapper"
+)
+
+var (
+	//go:embed schemas.json
+	schemas []byte
+
+	FileManager = scrapper.NewMetadataFileManager[staticschema.FieldMetadataMapV1]( // nolint:gochecknoglobals
+		schemas, fileconv.NewSiblingFileLocator())
+
+	// Schemas is cached Object schemas.
+	Schemas = FileManager.MustLoadSchemas() // nolint:gochecknoglobals
+)
diff --git a/providers/aws/internal/ssoadmin/schemas.json b/providers/aws/internal/ssoadmin/schemas.json
new file mode 100644
index 00000000..f8ca30cd
--- /dev/null
+++ b/providers/aws/internal/ssoadmin/schemas.json
@@ -0,0 +1,81 @@
+{
+  "modules": {
+    "aws-identity-center": {
+      "objects": {
+        "Instances": {
+          "displayName": "Instances",
+          "responseKey": "Instances",
+          "fields": {
+            "CreatedDate": "Created Date",
+            "IdentityStoreId": "Identity Store Id",
+            "InstanceArn": "Instance Arn",
+            "Name": "Name",
+            "OwnerAccountId": "Owner Account Id",
+            "Status": "Status"
+          }
+        },
+        "Applications": {
+          "displayName": "Applications",
+          "responseKey": "Applications",
+          "fields": {
+            "ApplicationAccount": "Application Account",
+            "ApplicationArn": "Application Arn",
+            "ApplicationProviderArn": "Application Provider Arn",
+            "CreatedDate": "Created Date",
+            "Description": "Description",
+            "InstanceArn": "Instance Arn",
+            "Name": "Name",
+            "PortalOptions": "Portal Options",
+            "Status": "Status"
+          }
+        },
+        "ApplicationProviders": {
+          "displayName": "Application Providers",
+          "responseKey": "ApplicationProviders",
+          "fields": {
+            "ApplicationProviderArn": "Application Provider Arn",
+            "DisplayData": "Display Data",
+            "FederationProtocol": "Federation Protocol",
+            "ResourceServerConfig": "Resource Server Config"
+          }
+        },
+        "AccountAssignmentsCreationStatus": {
+          "displayName": "Account Assignments Creation Status",
+          "responseKey": "AccountAssignmentsCreationStatus",
+          "fields": {
+            "CreatedDate": "Created Date",
+            "RequestId": "Request Id",
+            "Status": "Status"
+          }
+        },
+        "AccountAssignmentsDeletionStatus": {
+          "displayName": "Account Assignments Deletion Status",
+          "responseKey": "AccountAssignmentsDeletionStatus",
+          "fields": {
+            "CreatedDate": "Created Date",
+            "RequestId": "Request Id",
+            "Status": "Status"
+          }
+        },
+        "PermissionSetsProvisioningStatus": {
+          "displayName": "Permission Sets Provisioning Status",
+          "responseKey": "PermissionSetsProvisioningStatus",
+          "fields": {
+            "CreatedDate": "Created Date",
+            "RequestId": "Request Id",
+            "Status": "Status"
+          }
+        },
+        "TrustedTokenIssuers": {
+          "displayName": "Trusted Token Issuers",
+          "responseKey": "TrustedTokenIssuers",
+          "fields": {
+            "Name": "Name",
+            "TrustedTokenIssuerArn": "Trusted Token Issuer Arn",
+            "TrustedTokenIssuerType": "Trusted Token Issuer Type"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/providers/aws/metadata.go b/providers/aws/metadata.go
new file mode 100644
index 00000000..2e63254d
--- /dev/null
+++ b/providers/aws/metadata.go
@@ -0,0 +1,46 @@
+package aws
+
+import (
+	"context"
+
+	"github.com/amp-labs/connectors"
+	"github.com/amp-labs/connectors/common"
+	"github.com/amp-labs/connectors/providers"
+	"github.com/amp-labs/connectors/providers/aws/internal/identitystore"
+	"github.com/amp-labs/connectors/providers/aws/internal/ssoadmin"
+)
+
+func (c *Connector) ListObjectMetadata(
+	ctx context.Context, objectNames []string,
+) (*connectors.ListObjectMetadataResult, error) {
+	if len(objectNames) == 0 {
+		return nil, common.ErrMissingObjects
+	}
+
+	result := common.NewListObjectMetadataResult()
+
+	for _, name := range objectNames {
+		if data, ok := findObjectMetadata(name); ok {
+			result.Result[name] = *data
+		} else {
+			result.Errors[name] = common.ErrObjectNotSupported
+		}
+	}
+
+	return result, nil
+}
+
+// Try locating metadata for an object across AWS services.
+func findObjectMetadata(objectName string) (*common.ObjectMetadata, bool) {
+	data, err := identitystore.Schemas.SelectOne(providers.ModuleAWSIdentityCenter, objectName)
+	if err == nil {
+		return data, true
+	}
+
+	data, err = ssoadmin.Schemas.SelectOne(providers.ModuleAWSIdentityCenter, objectName)
+	if err == nil {
+		return data, true
+	}
+
+	return nil, false
+}


Test patch:
diff --git a/providers/aws/metadata_test.go b/providers/aws/metadata_test.go
new file mode 100644
index 00000000..6f8f9f34
--- /dev/null
+++ b/providers/aws/metadata_test.go
@@ -0,0 +1,115 @@
+package aws
+
+import (
+	"net/http"
+	"testing"
+
+	"github.com/amp-labs/connectors"
+	"github.com/amp-labs/connectors/common"
+	"github.com/amp-labs/connectors/providers"
+	"github.com/amp-labs/connectors/test/utils/mockutils/mockserver"
+	"github.com/amp-labs/connectors/test/utils/testroutines"
+)
+
+func TestListObjectMetadata(t *testing.T) { // nolint:funlen,gocognit,cyclop
+	t.Parallel()
+
+	tests := []testroutines.Metadata{
+		{
+			Name:         "At least one object name must be queried",
+			Input:        nil,
+			Server:       mockserver.Dummy(),
+			ExpectedErrs: []error{common.ErrMissingObjects},
+		},
+		{
+			Name:       "Unknown object requested",
+			Input:      []string{"butterflies"},
+			Server:     mockserver.Dummy(),
+			Comparator: testroutines.ComparatorSubsetMetadata,
+			Expected: &common.ListObjectMetadataResult{
+				Errors: map[string]error{
+					"butterflies": common.ErrObjectNotSupported,
+				},
+			},
+		},
+		{
+			Name:       "Metadata for objects across AWS Services",
+			Input:      []string{"Users", "Applications", "Helicopters"},
+			Server:     mockserver.Dummy(),
+			Comparator: testroutines.ComparatorSubsetMetadata,
+			Expected: &common.ListObjectMetadataResult{
+				Result: map[string]common.ObjectMetadata{
+					"Users": {
+						DisplayName: "Users",
+						FieldsMap: map[string]string{
+							"IdentityStoreId":   "Identity Store Id",
+							"UserId":            "User Id",
+							"Addresses":         "Addresses",
+							"DisplayName":       "Display Name",
+							"Emails":            "Emails",
+							"ExternalIds":       "External Ids",
+							"Locale":            "Locale",
+							"Name":              "Name",
+							"NickName":          "NickName",
+							"PhoneNumbers":      "Phone Numbers",
+							"PreferredLanguage": "Preferred Language",
+							"ProfileUrl":        "Profile URL",
+							"Timezone":          "Timezone",
+							"Title":             "Title",
+							"UserName":          "User Name",
+							"UserType":          "User Type",
+						},
+					},
+					"Applications": {
+						DisplayName: "Applications",
+						FieldsMap: map[string]string{
+							"ApplicationAccount":     "Application Account",
+							"ApplicationArn":         "Application Arn",
+							"ApplicationProviderArn": "Application Provider Arn",
+							"CreatedDate":            "Created Date",
+							"Description":            "Description",
+							"InstanceArn":            "Instance Arn",
+							"Name":                   "Name",
+							"PortalOptions":          "Portal Options",
+							"Status":                 "Status",
+						},
+					},
+				},
+				Errors: map[string]error{
+					"Helicopters": common.ErrObjectNotSupported,
+				},
+			},
+			ExpectedErrs: nil,
+		},
+	}
+
+	for _, tt := range tests {
+		// nolint:varnamelen
+		t.Run(tt.Name, func(t *testing.T) {
+			t.Parallel()
+
+			tt.Run(t, func() (connectors.ObjectMetadataConnector, error) {
+				return constructTestConnector(tt.Server.URL)
+			})
+		})
+	}
+}
+
+func constructTestConnector(serverURL string) (*Connector, error) {
+	connector, err := NewConnector(common.Parameters{
+		Module:              providers.ModuleAWSIdentityCenter,
+		AuthenticatedClient: http.DefaultClient,
+		Metadata: map[string]string{
+			"region":          "test-region",
+			"identityStoreID": "test-identity-store-id",
+			"instanceArn":     "test-instance-arn",
+		},
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	connector.SetBaseURL(serverURL)
+
+	return connector, nil
+}
diff --git a/test/aws/metadata/main.go b/test/aws/metadata/main.go
new file mode 100644
index 00000000..1d7756d3
--- /dev/null
+++ b/test/aws/metadata/main.go
@@ -0,0 +1,34 @@
+package main
+
+import (
+	"context"
+	"fmt"
+	"os"
+	"os/signal"
+	"syscall"
+
+	"github.com/amp-labs/connectors/providers"
+	connTest "github.com/amp-labs/connectors/test/aws"
+	"github.com/amp-labs/connectors/test/utils"
+)
+
+func main() {
+	// Handle Ctrl-C gracefully.
+	ctx, done := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
+	defer done()
+
+	// Set up slog logging.
+	utils.SetupLogging()
+
+	conn := connTest.GetAWSConnector(ctx, providers.ModuleAWSIdentityCenter)
+
+	metadata, err := conn.ListObjectMetadata(ctx, []string{
+		"Users", "Applications",
+	})
+	if err != nil {
+		utils.Fail("error listing metadata", "error", err)
+	}
+
+	fmt.Println("Metadata...")
+	utils.DumpJSON(metadata, os.Stdout)
+}