diff --git a/config/sns/config.go b/config/sns/config.go index aaf80d56d5..3913cd0103 100644 --- a/config/sns/config.go +++ b/config/sns/config.go @@ -6,6 +6,10 @@ package sns import ( "github.com/crossplane/upjet/pkg/config" + awspolicy "github.com/hashicorp/awspolicyequivalence" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" "github.com/upbound/provider-aws/config/common" ) @@ -26,5 +30,42 @@ func Configure(p *config.Provider) { // If the topic policy is unset on the Topic resource, don't late initialize it, to avoid conflicts with the // policy managed by a TopicPolicy resource. r.LateInitializer.IgnoredFields = append(r.LateInitializer.IgnoredFields, "policy") + r.TerraformCustomDiff = func(diff *terraform.InstanceDiff, _ *terraform.InstanceState, _ *terraform.ResourceConfig) (*terraform.InstanceDiff, error) { + if diff == nil || diff.Attributes["policy"] == nil || diff.Attributes["policy"].Old == "" || diff.Attributes["policy"].New == "" { + return diff, nil + } + + vOld, err := removePolicyVersion(diff.Attributes["policy"].Old) + if err != nil { + return nil, errors.Wrap(err, "failed to remove Version from the old AWS policy document") + } + vNew, err := removePolicyVersion(diff.Attributes["policy"].New) + if err != nil { + return nil, errors.Wrap(err, "failed to remove Version from the new AWS policy document") + } + + ok, err := awspolicy.PoliciesAreEquivalent(vOld, vNew) + if err != nil { + return nil, errors.Wrap(err, "failed to compare the old and the new AWS policy documents") + } + if ok { + delete(diff.Attributes, "policy") + } + return diff, nil + } }) } + +func removePolicyVersion(p string) (string, error) { + var policy any + if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal([]byte(p), &policy); err != nil { + return "", errors.Wrap(err, "failed to unmarshal the policy from JSON") + } + m, ok := policy.(map[string]any) + if !ok { + return p, nil + } + delete(m, "Version") + r, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(m) + return string(r), errors.Wrap(err, "failed to marshal the policy map as JSON") +} diff --git a/examples/sns/v1beta1/topic-with-policy.yaml b/examples/sns/v1beta1/topic-with-policy.yaml index b5272f1579..d78e68f941 100644 --- a/examples/sns/v1beta1/topic-with-policy.yaml +++ b/examples/sns/v1beta1/topic-with-policy.yaml @@ -5,6 +5,8 @@ apiVersion: sns.aws.upbound.io/v1beta1 kind: Topic metadata: + annotations: + meta.upbound.io/example-id: sns/v1beta1/topic name: example-topic-${Rand.RFC1123Subdomain} labels: testing.upbound.io/example-name: sns @@ -19,7 +21,7 @@ spec: "Effect": "Allow", "Principal": { "AWS": [ - "arn:aws:iam::123456789110:role/test/project/test/principal1" + "arn:aws:iam::153891904029:role/sample-role" ] }, "Action": "sns:Publish", @@ -30,7 +32,7 @@ spec: "Effect": "Allow", "Principal": { "AWS": [ - "arn:aws:iam::123456789110:role/test/project/test/principal1" + "arn:aws:iam::153891904029:role/sample-role" ] }, "Action": "sns:GetTopicAttributes", @@ -41,7 +43,7 @@ spec: "Effect": "Allow", "Principal": { "AWS": [ - "arn:aws:iam::123456789110:role/test/project/test/principal1" + "arn:aws:iam::153891904029:role/sample-role" ] }, "Action": "sns:ListSubscriptionsByTopic", @@ -49,3 +51,29 @@ spec: } ] } + +--- + +apiVersion: iam.aws.upbound.io/v1beta1 +kind: Role +metadata: + annotations: + meta.upbound.io/example-id: sns/v1beta1/topic + labels: + testing.upbound.io/example-name: role + name: sample-role +spec: + forProvider: + assumeRolePolicy: | + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "eks.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] + } diff --git a/go.mod b/go.mod index 2a37c79d5e..80d6258f20 100644 --- a/go.mod +++ b/go.mod @@ -23,10 +23,12 @@ require ( github.com/crossplane/upjet v1.4.1 github.com/go-ini/ini v1.46.0 github.com/google/go-cmp v0.6.0 + github.com/hashicorp/awspolicyequivalence v1.6.0 github.com/hashicorp/terraform-json v0.21.0 github.com/hashicorp/terraform-plugin-framework v1.8.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 github.com/hashicorp/terraform-provider-aws v0.0.0-00010101000000-000000000000 + github.com/json-iterator/go v1.1.12 github.com/pkg/errors v0.9.1 gopkg.in/alecthomas/kingpin.v2 v2.2.6 gopkg.in/yaml.v3 v3.0.1 @@ -259,7 +261,6 @@ require ( github.com/hashicorp/aws-cloudformation-resource-schema-sdk-go v0.22.0 // indirect github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.53 // indirect github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2 v2.0.0-beta.54 // indirect - github.com/hashicorp/awspolicyequivalence v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -289,7 +290,6 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattbaird/jsonpatch v0.0.0-20230413205102-771768614e91 // indirect github.com/mattn/go-colorable v0.1.13 // indirect