Repository: kubernetes/cloud-provider-aws (go)

Issue:
Allow `ecr-credential-provider` to generate credentials for any registry
<!-- Please only use this template for submitting enhancement requests -->

**What would you like to be added**: Allow `ecr-credential-provider` to generate credentials for any registry (only base restrictions on `CredentialProviderConfig`)

**Why is this needed**:
Today `ecr-credential-provider`, is limited to `public.ecr.aws` , and registry url compliant with [ecrPattern](https://github.com/kubernetes/cloud-provider-aws/blob/master/cmd/ecr-credential-provider/main.go#L45). 

In order to achieve this functionality we need to remove this restriction.

**End user use case** : 
Using an EKS Cluster, we need to mirror public registry where SLA aren't garrantee or with some IP Rate limits restrictions. 

In order to achieve that, I've setuped the followings : 
- ECR Pull through cache to `public.ecr.aws` , `quay.io` and `registry.k8s.io`
- Containerd configured to mirror `public.ecr.aws` , `quay.io` and `registry.k8s.io` to my private ECR registry
- Private registry is hosted on another account (cross account scenario), on the same aws region
- aws-ecr-credential-provider configured to generate credentials for : `public.ecr.aws` , `quay.io` and `registry.k8s.io` with a config file like : 
  ```json
  {
    "apiVersion": "kubelet.config.k8s.io/v1alpha1",
    "kind": "CredentialProviderConfig",
    "providers": [
      {
        "name": "ecr-credential-provider",
        "matchImages": [
          "*.dkr.ecr.*.amazonaws.com",
          "*.dkr.ecr.*.amazonaws.com/*",
          "*.dkr.ecr.*.amazonaws.com.cn",
          "*.dkr.ecr-fips.*.amazonaws.com",
          "*.dkr.ecr.*.c2s.ic.gov",
          "*.dkr.ecr.*.sc2s.sgov.gov",
          "quay.io",
          "public.ecr.aws",
          "registry.k8s.io"
        ],
        "defaultCacheDuration": "12h",
        "apiVersion": "credentialprovider.kubelet.k8s.io/v1alpha1"
      }
    ]
   }
  ```

* Current status : No credentials has been generated, and pull through cache aren't use 
* Expected status : Credentials should be generated (for the current node , on the same aws region, or an explicit configuration on `CredentialProviderConfig`) , to allow my node to use my private registry mirror for public registry.


**Potential solution**:

I wonder if it's really needed to _generate an error here_ and not relying on SDK region behavior (and potential user configuration in provider configuration - `AWS_REGION` env variable in `CredentialProviderConfig` for exemple).

By removing program error [here](https://github.com/kubernetes/cloud-provider-aws/pull/667/files#diff-61e97abee8e39e3bb484acf33a377325f9514a670e1a541c15a8a61eb9343f79R232) , with something like : 
```suggestion
if len(splitHost) != 6 {
  return "", nil
}
```
(further code updates will be probably needed ;-) ) 
this provider will rely on AWS SDK default behaviour, and let opportunity to users to handle more uses cases.
Relying on SDK default behavior will still throw an error when no region are configured (Eg. : `E0922 13:04:35.558288   57050 main.go:255] Error running credential provider plugin: MissingRegion: could not find region configuration` ) 

Ref.: https://github.com/kubernetes/cloud-provider-aws/pull/667#discussion_r1334174043

Sample working code modification : https://github.com/jBouyoud/cloud-provider-aws/commit/5a167d0ae233981db3a992dd767b1ff1f60fdcda

I'll be glad to help on this topic, please let me known how.
Regards

<!-- DO NOT EDIT BELOW THIS LINE -->
/kind feature

Pull request:
Remove ecr pattern restriction
<!--  Thanks for sending a pull request!  Here are some tips for you:

1. If this is your first time, please read our contributor guidelines: https://git.k8s.io/community/contributors/guide#your-first-contribution and developer guide https://git.k8s.io/community/contributors/devel/development.md#development-guide
2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. For reference on required PR/issue labels, read here:
https://git.k8s.io/community/contributors/devel/sig-release/release.md#issue-kind-label
3. Ensure you have added or ran the appropriate tests for your PR: https://git.k8s.io/community/contributors/devel/sig-testing/testing.md
4. If you want *faster* PR reviews, read how: https://git.k8s.io/community/contributors/guide/pull-requests.md#best-practices-for-faster-reviews
5. Follow the instructions for writing a release note: https://git.k8s.io/community/contributors/guide/release-notes.md
6. If the PR is unfinished, see how to mark it: https://git.k8s.io/community/contributors/guide/pull-requests.md#marking-unfinished-pull-requests
-->

**What type of PR is this?**
> Uncomment only one, leave it on its own line:
>
> /kind api-change
> /kind bug
> /kind cleanup
> /kind design
> /kind documentation
> /kind failing-test

/kind feature

> /kind flake

**What this PR does / why we need it**:

Remove ecr pattern restriction and forward region responsability to AWS SDK default behavior. This allow users to use this binary with any registries even they configure properly their AWS SDK (`AWS_REGION` environment variable or any other configuration handled in AWS SDK)  

**Which issue(s) this PR fixes**:
<!-- 
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
_If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_*
-->
Fixes #668

**Special notes for your reviewer**:

**Does this PR introduce a user-facing change?**:
<!--  
If no, just write "NONE".
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".
2. 
-->
```release-note
[ecr-credential-provider] An ECR token is returned for the default AWS region when the specified image reference doesn't match a known ECR pattern.
```


Patch:
diff --git a/cmd/ecr-credential-provider/main.go b/cmd/ecr-credential-provider/main.go
index eb2bcde..428d4a0 100644
--- a/cmd/ecr-credential-provider/main.go
+++ b/cmd/ecr-credential-provider/main.go
@@ -60,8 +60,13 @@ type ecrPlugin struct {
 }
 
 func defaultECRProvider(region string) (*ecr.ECR, error) {
+	cfg := aws.Config{}
+	if region != "" {
+		klog.Warningf("No region found in the image reference, the default region will be used. Please refer to AWS SDK documentation for configuration purpose.")
+		cfg.Region = aws.String(region)
+	}
 	sess, err := session.NewSessionWithOptions(session.Options{
-		Config:            aws.Config{Region: aws.String(region)},
+		Config:            cfg,
 		SharedConfigState: session.SharedConfigEnable,
 	})
 	if err != nil {
@@ -122,11 +127,10 @@ func (e *ecrPlugin) getPublicCredsData() (*credsData, error) {
 
 func (e *ecrPlugin) getPrivateCredsData(imageHost string, image string) (*credsData, error) {
 	klog.Infof("Getting creds for private image %s", image)
-	region, err := parseRegionFromECRPrivateHost(imageHost)
-	if err != nil {
-		return nil, err
-	}
+	var err error
+
 	if e.ecr == nil {
+		region := parseRegionFromECRPrivateHost(imageHost)
 		e.ecr, err = defaultECRProvider(region)
 		if err != nil {
 			return nil, err
@@ -227,12 +231,12 @@ func parseHostFromImageReference(image string) (string, error) {
 	return parsed.Hostname(), nil
 }
 
-func parseRegionFromECRPrivateHost(host string) (string, error) {
+func parseRegionFromECRPrivateHost(host string) string {
 	splitHost := ecrPrivateHostPattern.FindStringSubmatch(host)
 	if len(splitHost) != 6 {
-		return "", fmt.Errorf("invalid private ECR host: %s", host)
+		return ""
 	}
-	return splitHost[3], nil
+	return splitHost[3]
 }
 
 func main() {


Test patch:
diff --git a/cmd/ecr-credential-provider/main_test.go b/cmd/ecr-credential-provider/main_test.go
index f403388..0ddb64d 100644
--- a/cmd/ecr-credential-provider/main_test.go
+++ b/cmd/ecr-credential-provider/main_test.go
@@ -86,6 +86,12 @@ func Test_GetCredentials_Private(t *testing.T) {
 			getAuthorizationTokenOutput: generatePrivateGetAuthorizationTokenOutput("user", "pass", "", nil),
 			response:                    generateResponse("123456789123.dkr.ecr.us-west-2.amazonaws.com", "user", "pass"),
 		},
+		{
+			name:                        "non ECR host",
+			image:                       "registry.k8s.io/foo:latest",
+			getAuthorizationTokenOutput: generatePrivateGetAuthorizationTokenOutput("user", "pass", "", nil),
+			response:                    generateResponse("registry.k8s.io", "user", "pass"),
+		},
 		{
 			name:                        "empty authorization data",
 			image:                       "123456789123.dkr.ecr.us-west-2.amazonaws.com",
@@ -304,35 +310,22 @@ func Test_parseRegionFromECRPrivateHost(t *testing.T) {
 		name   string
 		host   string
 		region string
-		err    error
 	}{
 		{
 			name:   "success",
 			host:   "123456789123.dkr.ecr.us-west-2.amazonaws.com",
 			region: "us-west-2",
-			err:    nil,
 		},
 		{
 			name:   "invalid registry",
 			host:   "foobar",
 			region: "",
-			err:    errors.New("invalid private ECR host: foobar"),
-		},
-		{
-			name:   "invalid host",
-			host:   "foobar ",
-			region: "",
-			err:    errors.New("invalid private ECR host: foobar "),
 		},
 	}
 
 	for _, testcase := range testcases {
 		t.Run(testcase.name, func(t *testing.T) {
-			region, err := parseRegionFromECRPrivateHost(testcase.host)
-
-			if testcase.err != nil && (testcase.err.Error() != err.Error()) {
-				t.Fatalf("expected error %s, got %s", testcase.err, err)
-			}
+			region := parseRegionFromECRPrivateHost(testcase.host)
 
 			if region != testcase.region {
 				t.Fatalf("region mismatch. Expected %s, got %s", testcase.region, region)