Skip to content

Commit

Permalink
add function to retrieve latest version of a policy document
Browse files Browse the repository at this point in the history
  • Loading branch information
james03160927 committed Dec 12, 2024
1 parent a70a955 commit 1a65c12
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 0 deletions.
53 changes: 53 additions & 0 deletions modules/aws/iam.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package aws

import (
"context"
"fmt"
"net/url"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
Expand Down Expand Up @@ -59,6 +61,57 @@ func GetIamCurrentUserArnE(t testing.TestingT) (string, error) {
return *resp.User.Arn, nil
}

// GetIamPolicyDocument gets the most recent policy (JSON) document for an IAM policy.
func GetIamPolicyDocument(t testing.TestingT, region string, policyARN string) string {
out, err := GetIamPolicyDocumentE(t, region, policyARN)
if err != nil {
t.Fatal(err)
}
return out
}

// GetIamPolicyDocumentE gets the most recent policy (JSON) document for an IAM policy.
func GetIamPolicyDocumentE(t testing.TestingT, region string, policyARN string) (string, error) {
iamClient, err := NewIamClientE(t, region)
if err != nil {
return "", err
}

versions, err := iamClient.ListPolicyVersions(context.Background(), &iam.ListPolicyVersionsInput{
PolicyArn: &policyARN,
})
if err != nil {
return "", err
}

var defaultVersion string
for _, version := range versions.Versions {
if version.IsDefaultVersion == true {
defaultVersion = *version.VersionId
}
}

document, err := iamClient.GetPolicyVersion(context.Background(), &iam.GetPolicyVersionInput{
PolicyArn: aws.String(policyARN),
VersionId: aws.String(defaultVersion),
})
if err != nil {
return "", err
}

unescapedDocument := document.PolicyVersion.Document
if unescapedDocument == nil {
return "", fmt.Errorf("no policy document found for policy %s", policyARN)
}

escapedDocument, err := url.QueryUnescape(*unescapedDocument)
if err != nil {
return "", err
}

return escapedDocument, nil
}

// CreateMfaDevice creates an MFA device using the given IAM client.
func CreateMfaDevice(t testing.TestingT, iamClient *iam.Client, deviceName string) *types.VirtualMFADevice {
mfaDevice, err := CreateMfaDeviceE(t, iamClient, deviceName)
Expand Down
52 changes: 52 additions & 0 deletions modules/aws/iam_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package aws

import (
"context"
"strings"
"testing"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/iam"
"github.com/gruntwork-io/terratest/modules/random"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestGetIamCurrentUserName(t *testing.T) {
Expand All @@ -19,3 +25,49 @@ func TestGetIamCurrentUserArn(t *testing.T) {
username := GetIamCurrentUserArn(t)
assert.Regexp(t, "^arn:aws:iam::[0-9]{12}:user/.+$", username)
}

func TestGetIAMPolicyDocument(t *testing.T) {
t.Parallel()

region := GetRandomRegion(t, nil, nil)

t.Run("Exists", func(t *testing.T) {
iamClient, err := NewIamClientE(t, region)
require.NoError(t, err)

policyDocument := `{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1530709892083",
"Action": "*",
"Effect": "Allow",
"Resource": "*"
}
]
}`
input := &iam.CreatePolicyInput{
PolicyName: aws.String(strings.ToLower(random.UniqueId())),
PolicyDocument: aws.String(policyDocument),
}
policy, err := iamClient.CreatePolicy(context.Background(), input)
require.NoError(t, err)

t.Cleanup(func() {
t.Log("Deleting IAM Policy Document")
_, err := iamClient.DeletePolicy(context.Background(), &iam.DeletePolicyInput{
PolicyArn: policy.Policy.Arn,
})
require.NoError(t, err)
})

p := GetIamPolicyDocument(t, region, *policy.Policy.Arn)
t.Log("Retrieved Policy Document:", p)
assert.JSONEq(t, policyDocument, p)
})

t.Run("DoesNotExist", func(t *testing.T) {
_, err := GetIamPolicyDocumentE(t, region, "arn:aws:iam::1234567890:policy/does-not-exist")
require.Error(t, err)
})
}

0 comments on commit 1a65c12

Please sign in to comment.