Repository: getmoto/moto (python)

Issue:
IAM - create_policy returns bad tags
Hi, Thank you for this great library!

I just noticed a small bug in IAM implementation. Using latest moto version with python mocks. 
The function create_policy returns the policy tags with this format: 
`[{"tag_key": {"tag_key": "tag_value"}},...]` instead of `[{"tag_key": "tag_value"}]`

I took a quick look at the code and seems like the function `policy.get_tag()` that does the conversion is never called and instead the response template use the `tags` attribute from the `Policy` class which is in the wrong format.

So an easy fix would be to do like `get_policy` response template and use get_tags() (in `create_policy` response template). Replacing:

```jinja
{% for tag_key, tag_value in policy.tags.items() %}
``` 
by
```jinja
{% for tag_key, tag_value in policy.get_tags().items() %}
``` 

There might be more like this in IAM looking at the templates but I did not dig further.

Pull request description:
IAM: create_policy() should return tags in correct format
Fixes #7724

Patch:
diff --git a/moto/iam/responses.py b/moto/iam/responses.py
index 562dd2b1e..cb20c45fd 100644
--- a/moto/iam/responses.py
+++ b/moto/iam/responses.py
@@ -1239,14 +1239,16 @@ CREATE_POLICY_TEMPLATE = """<CreatePolicyResponse>
       <PolicyId>{{ policy.id }}</PolicyId>
       <PolicyName>{{ policy.name }}</PolicyName>
       <UpdateDate>{{ policy.updated_iso_8601 }}</UpdateDate>
+      {% if policy.tags %}
       <Tags>
-        {% for tag_key, tag_value in policy.tags.items() %}
+        {% for tag in policy.get_tags() %}
         <member>
-          <Key>{{ tag_key }}</Key>
-          <Value>{{ tag_value }}</Value>
+            <Key>{{ tag['Key'] }}</Key>
+            <Value>{{ tag['Value'] }}</Value>
         </member>
         {% endfor %}
       </Tags>
+      {% endif %}
     </Policy>
   </CreatePolicyResult>
   <ResponseMetadata>
diff --git a/other_langs/terraform/iam/iam.tf b/other_langs/terraform/iam/iam.tf
new file mode 100644
index 000000000..1a7710d9e
--- /dev/null
+++ b/other_langs/terraform/iam/iam.tf
@@ -0,0 +1,24 @@
+resource "aws_iam_policy" "policy" {
+  name        = "test_policy"
+  path        = "/"
+  description = "My test policy"
+
+  # Terraform's "jsonencode" function converts a
+  # Terraform expression result to valid JSON syntax.
+  policy = jsonencode({
+    Version = "2012-10-17"
+    Statement = [
+      {
+        Action = [
+          "ec2:Describe*",
+        ]
+        Effect   = "Allow"
+        Resource = "*"
+      },
+    ]
+  })
+
+  tags = {
+    t1 = "v1"
+  }
+}
\ No newline at end of file
diff --git a/other_langs/terraform/iam/providers.tf b/other_langs/terraform/iam/providers.tf
new file mode 100644
index 000000000..3e11097e7
--- /dev/null
+++ b/other_langs/terraform/iam/providers.tf
@@ -0,0 +1,14 @@
+provider "aws" {
+  region                      = "us-east-1"
+  s3_use_path_style           = true
+  skip_credentials_validation = true
+  skip_metadata_api_check     = true
+  skip_requesting_account_id  = true
+
+  endpoints {
+    iam = "http://localhost:5000"
+  }
+
+  access_key = "my-access-key"
+  secret_key = "my-secret-key"
+}


Test patch:
diff --git a/.github/workflows/tests_terraform_examples.yml b/.github/workflows/tests_terraform_examples.yml
index 8dfa291b9..fee7afa17 100644
--- a/.github/workflows/tests_terraform_examples.yml
+++ b/.github/workflows/tests_terraform_examples.yml
@@ -11,7 +11,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        service: ["acm", "awslambda", "cloudfront", "elb", "route53", "sqs"]
+        service: ["acm", "awslambda", "cloudfront", "elb", "iam", "route53", "sqs"]
 
     steps:
     - uses: actions/checkout@v4
diff --git a/tests/test_iam/test_iam.py b/tests/test_iam/test_iam.py
index 9b00a7dbe..507377bc3 100644
--- a/tests/test_iam/test_iam.py
+++ b/tests/test_iam/test_iam.py
@@ -858,25 +858,24 @@ def test_delete_default_policy_version():
 @mock_aws()
 def test_create_policy_with_tags():
     conn = boto3.client("iam", region_name="us-east-1")
-    conn.create_policy(
+    tag1 = {"Key": "somekey", "Value": "somevalue"}
+    tag2 = {"Key": "someotherkey", "Value": "someothervalue"}
+    create = conn.create_policy(
         PolicyName="TestCreatePolicyWithTags1",
         PolicyDocument=MOCK_POLICY,
-        Tags=[
-            {"Key": "somekey", "Value": "somevalue"},
-            {"Key": "someotherkey", "Value": "someothervalue"},
-        ],
+        Tags=[tag1, tag2],
         Description="testing",
-    )
+    )["Policy"]
+    assert tag1 in create["Tags"]
+    assert tag2 in create["Tags"]
 
     # Get policy:
     policy = conn.get_policy(
         PolicyArn=f"arn:aws:iam::{ACCOUNT_ID}:policy/TestCreatePolicyWithTags1"
     )["Policy"]
     assert len(policy["Tags"]) == 2
-    assert policy["Tags"][0]["Key"] == "somekey"
-    assert policy["Tags"][0]["Value"] == "somevalue"
-    assert policy["Tags"][1]["Key"] == "someotherkey"
-    assert policy["Tags"][1]["Value"] == "someothervalue"
+    assert tag1 in policy["Tags"]
+    assert tag2 in policy["Tags"]
     assert policy["Description"] == "testing"