Repository: aws-cloudformation/cfn-lint

Issue:
Outputs on AWS::ServiceCatalog::CloudFormationProvisionedProduct causing errors
### CloudFormation Lint Version

cfn-lint 1.5.0

### What operating system are you using?

Amazon Linux

### Describe the bug

Dynamic values under `Outputs` on `AWS::ServiceCatalog::CloudFormationProvisionedProduct` resource types cause errors.

I tried testing with the vanilla example template from AWS CloudFormation [docs page](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-servicecatalog-cloudformationprovisionedproduct.html#aws-resource-servicecatalog-cloudformationprovisionedproduct--examples) on `AWS::ServiceCatalog::CloudFormationProvisionedProduct`

Running this command:
```
pipenv run cfn-lint --template ./test/success/sc-product.yaml
```

Against the reproduction template gives this error
```
E1010 'Outputs.SCLambdaArn' is not one of ['RecordId', 'CloudformationStackArn', 'Outputs', 'ProvisionedProductId']
test/success/sc-product.yaml:17:41
```

### Expected behavior

!GetAtt on dynamic `Outputs` values should work and not cause E1010 errors.

### Reproduction template

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Serverless Stack
Resources:
  SimpleLambda:
    Type: AWS::ServiceCatalog::CloudFormationProvisionedProduct
    Properties:
      ProductName: Basic Lambda
      ProvisioningArtifactName: '1.0'
            
  SimpleApiGateway:
    Type: AWS::ServiceCatalog::CloudFormationProvisionedProduct
    Properties:
      ProductName: API Gateway
      ProvisioningArtifactName: '1.0'
      ProvisioningParameters:
        - Key: LambdaArn
          Value: !GetAtt [SimpleLambda, Outputs.SCLambdaArn]
```


Discussion:
Should have a fix in shortly.  We do this for CloudFormation nested stacks, custom resources, just need to enable this for `AWS::ServiceCatalog::CloudFormationProvisionedProduct` as well.
I'm going to put in a workaround for this but need to figure out a better long term solution.
Thanks @kddejong !



Patch:
diff --git a/src/cfnlint/rules/functions/GetAtt.py b/src/cfnlint/rules/functions/GetAtt.py
index 03e2020464..006bf1922c 100644
--- a/src/cfnlint/rules/functions/GetAtt.py
+++ b/src/cfnlint/rules/functions/GetAtt.py
@@ -102,10 +102,6 @@ def _resolve_getatt(
                         yield err
                         continue
 
-                    # because of the complexities of schemas ($ref, anyOf, allOf, etc.)
-                    # we will simplify the validator to just have a type check
-                    # then we will provide a simple value to represent the type from the
-                    # getAtt
                     evolved = validator.evolve(schema=s)  # type: ignore
                     evolved.validators = {  # type: ignore
                         "type": validator.validators.get("type"),  # type: ignore
@@ -124,7 +120,6 @@ def _resolve_getatt(
                         t, validator.context.regions
                     ):
                         getatt_schema = schema.resolver.resolve_cfn_pointer(pointer)
-
                         if not getatt_schema.get("type") or not s.get("type"):
                             continue
 
diff --git a/src/cfnlint/schema/_getatts.py b/src/cfnlint/schema/_getatts.py
index 22343251fd..7bf89339d1 100644
--- a/src/cfnlint/schema/_getatts.py
+++ b/src/cfnlint/schema/_getatts.py
@@ -253,6 +253,14 @@ def __init__(self, schema: "Schema") -> None:
             self._attrs["Outputs\\..*"] = "/properties/CfnLintStringType"
             return
 
+        if schema.type_name == "AWS::ServiceCatalog::CloudFormationProvisionedProduct":
+            for ro_attr in schema.schema.get("readOnlyProperties", []):
+                if ro_attr == "/properties/Outputs":
+                    self._attrs["Outputs\\..*"] = "/properties/CfnLintStringType"
+                else:
+                    self._attrs[self._pointer_to_attr(ro_attr)] = ro_attr
+            return
+
         for unnamed_type in _unnamed_unknown_types:
             if schema.type_name.startswith(unnamed_type):
                 self._attrs[".*"] = "/properties/CfnLintAllTypes"


Test patch:
diff --git a/test/unit/module/schema/test_schema.py b/test/unit/module/schema/test_schema.py
index 94d3bbbff1..10a10c8baa 100644
--- a/test/unit/module/schema/test_schema.py
+++ b/test/unit/module/schema/test_schema.py
@@ -142,7 +142,6 @@ def resource_vpc_schema():
 
 
 def test_vpc_schema(resource_vpc_schema):
-
     schema = Schema(schema=resource_vpc_schema)
     assert list(schema.get_atts.keys()) == [
         "CidrBlock",
@@ -161,3 +160,155 @@ def test_vpc_schema(resource_vpc_schema):
     assert schema.get_atts["VpcId"] == "/properties/VpcId"
     assert schema.get_atts["CidrBlock"] == "/properties/CidrBlock"
     assert schema.get_atts["Ipv6CidrBlocks"] == "/properties/Ipv6CidrBlocks"
+
+
+@pytest.fixture
+def resource_servicecatalog_schema():
+    return {
+        "additionalProperties": False,
+        "createOnlyProperties": [
+            "/properties/NotificationArns",
+            "/properties/ProvisionedProductName",
+        ],
+        "definitions": {
+            "OutputType": {"type": "string"},
+            "ProvisioningParameter": {
+                "additionalProperties": False,
+                "properties": {
+                    "Key": {"maxLength": 1000, "minLength": 1, "type": "string"},
+                    "Value": {"maxLength": 4096, "type": "string"},
+                },
+                "required": ["Key", "Value"],
+                "type": "object",
+            },
+            "ProvisioningPreferences": {
+                "additionalProperties": False,
+                "properties": {
+                    "StackSetAccounts": {
+                        "items": {"pattern": "^[0-9]{12}$", "type": "string"},
+                        "type": "array",
+                        "uniqueItems": True,
+                    },
+                    "StackSetFailureToleranceCount": {"minimum": 0, "type": "integer"},
+                    "StackSetFailureTolerancePercentage": {
+                        "maximum": 100,
+                        "minimum": 0,
+                        "type": "integer",
+                    },
+                    "StackSetMaxConcurrencyCount": {"minimum": 1, "type": "integer"},
+                    "StackSetMaxConcurrencyPercentage": {
+                        "maximum": 100,
+                        "minimum": 1,
+                        "type": "integer",
+                    },
+                    "StackSetOperationType": {
+                        "enum": ["CREATE", "UPDATE", "DELETE"],
+                        "type": "string",
+                    },
+                    "StackSetRegions": {
+                        "items": {
+                            "pattern": "^[a-z]{2}-([a-z]+-)+[1-9]",
+                            "type": "string",
+                        },
+                        "type": "array",
+                        "uniqueItems": True,
+                    },
+                },
+                "type": "object",
+            },
+            "Tag": {
+                "additionalProperties": False,
+                "properties": {
+                    "Key": {
+                        "maxLength": 128,
+                        "minLength": 1,
+                        "pattern": "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$",
+                        "type": "string",
+                    },
+                    "Value": {
+                        "maxLength": 256,
+                        "minLength": 1,
+                        "pattern": "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$",
+                        "type": "string",
+                    },
+                },
+                "required": ["Key", "Value"],
+                "type": "object",
+            },
+        },
+        "documentationUrl": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-servicecatalog-cloudformationprovisionedproduct.html",
+        "handlers": {
+            "create": {"permissions": ["*"], "timeoutInMinutes": 720},
+            "delete": {"permissions": ["*"]},
+            "read": {"permissions": ["*"]},
+            "update": {"permissions": ["*"], "timeoutInMinutes": 720},
+        },
+        "primaryIdentifier": ["/properties/ProvisionedProductId"],
+        "properties": {
+            "AcceptLanguage": {"enum": ["en", "jp", "zh"], "type": "string"},
+            "CloudformationStackArn": {
+                "maxLength": 256,
+                "minLength": 1,
+                "type": "string",
+            },
+            "NotificationArns": {
+                "items": {"type": "string"},
+                "maxItems": 5,
+                "type": "array",
+                "uniqueItems": True,
+            },
+            "Outputs": {
+                "additionalProperties": False,
+                "maxProperties": 100,
+                "patternProperties": {
+                    "^[A-Za-z0-9]{1,64}$": {"$ref": "#/definitions/OutputType"}
+                },
+                "type": "object",
+            },
+            "PathId": {"maxLength": 100, "minLength": 1, "type": "string"},
+            "PathName": {"maxLength": 100, "minLength": 1, "type": "string"},
+            "ProductId": {"maxLength": 100, "minLength": 1, "type": "string"},
+            "ProductName": {"maxLength": 128, "minLength": 1, "type": "string"},
+            "ProvisionedProductId": {"maxLength": 50, "minLength": 1, "type": "string"},
+            "ProvisionedProductName": {
+                "maxLength": 128,
+                "minLength": 1,
+                "type": "string",
+            },
+            "ProvisioningArtifactId": {
+                "maxLength": 100,
+                "minLength": 1,
+                "type": "string",
+            },
+            "ProvisioningArtifactName": {"type": "string"},
+            "ProvisioningParameters": {
+                "items": {"$ref": "#/definitions/ProvisioningParameter"},
+                "type": "array",
+            },
+            "ProvisioningPreferences": {
+                "$ref": "#/definitions/ProvisioningPreferences"
+            },
+            "RecordId": {"maxLength": 50, "minLength": 1, "type": "string"},
+            "Tags": {"items": {"$ref": "#/definitions/Tag"}, "type": "array"},
+        },
+        "readOnlyProperties": [
+            "/properties/RecordId",
+            "/properties/CloudformationStackArn",
+            "/properties/Outputs",
+            "/properties/ProvisionedProductId",
+        ],
+        "sourceUrl": "https://github.com/aws-cloudformation/aws-cloudformation-rpdk.git",
+        "typeName": "AWS::ServiceCatalog::CloudFormationProvisionedProduct",
+    }
+
+
+def test_servicecatalog_cloudformation_schema(resource_servicecatalog_schema):
+
+    schema = Schema(schema=resource_servicecatalog_schema)
+    assert list(schema.get_atts.keys()) == [
+        "RecordId",
+        "CloudformationStackArn",
+        "Outputs\\..*",
+        "ProvisionedProductId",
+    ]
+    assert schema.get_atts["Outputs.Example"] == "/properties/CfnLintStringType"