<|start_filename|>tf-aws-s3/aws/iam.go<|end_filename|>
package aws

type Principal struct {
	AWS string `json:"AWS"`
}

type Statement struct {
	Sid       string    `json:"Sid"`
	Effect    string    `json:"Effect"`
	Principal Principal `json:"Principal"`
	Action    []string  `json:"Action"`
	Resource  []string  `json:"Resource"`
}

type Policy struct {
	Version   string      `json:"Version"`
	ID        string      `json:"Id"`
	Statement []Statement `json:"Statement"`
}


<|start_filename|>tf-azure-network/Makefile<|end_filename|>
TFPLAN = .tfplan

unit:
	conftest test -p test/unit/network.rego network.tf -i hcl

contract:
	terraform plan -out $(TFPLAN)
	terraform show -json $(TFPLAN) > $(TFPLAN).json
	rm -f $(TFPLAN)
	conftest test -p test/contract/conftest $(TFPLAN).json

terraform-cloud:
ifndef TF_CLOUD_TOKEN
	$(error TF_CLOUD_TOKEN is undefined)
endif
	echo 'credentials "app.terraform.io" {' > /root/.terraformrc
	@echo "  token = \"$(TF_CLOUD_TOKEN)\"" >> /root/.terraformrc
	echo "}" >> /root/.terraformrc

<|start_filename|>tf-aws-ec2/Makefile<|end_filename|>
TFPLAN = .tfplan

install:
	bundle install

unit:
	conftest test -p test/unit/vpc.rego vpc.tf
	conftest test -p test/unit/securitygroup.rego securitygroup.tf
	conftest test -p test/unit/gateway.rego gateway.tf
	conftest test -p test/unit/subnet.rego subnet.tf
	terraform validate
	terraform fmt

contract:
	terraform plan -out $(TFPLAN) -var-file=terraform.tfvars
	terraform show -json $(TFPLAN) > $(TFPLAN).json
	conftest test -p test/contract/logic.rego $(TFPLAN).json
	conftest test -p test/contract/instances.rego $(TFPLAN).json

apply:
	terraform apply

integration: apply
	kitchen test

clean-kitchen:
	kitchen destroy default-ubuntu || true

clean: clean-kitchen
	terraform destroy --force  || true
	rm $(TFPLAN) $(TFPLAN).json || true

<|start_filename|>tf-aws-s3/tests/contract/iam_test.go<|end_filename|>
package test

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"testing"

	"github.com/joatmon08/tdd-infrastructure/tf-aws-s3/aws"
	"github.com/stretchr/testify/assert"
)

const BucketPolicyFilePath = "../../policies/bucket.json"
const AccountID = "REDACTED"

func getIAMOutput(t *testing.T, resource string) string {
	target := fmt.Sprintf("-target=%s", resource)
	cmd := exec.Command("terraform", "plan", "-state=tests/contract/test.tfstate", "-var-file=test.tfvars", "-lock=false", target)
	cmd.Dir = "../.."
	var out bytes.Buffer
	cmd.Stdout = &out
	err := cmd.Run()
	if err != nil {
		t.Error(err)
	}
	return out.String()
}

func getBucketInput(t *testing.T, policyPath string) *aws.Policy {
	jsonFile, err := os.Open(policyPath)
	if err != nil {
		t.Error(err)
	}
	defer jsonFile.Close()

	policyByteValue, _ := ioutil.ReadAll(jsonFile)

	var policy aws.Policy
	json.Unmarshal(policyByteValue, &policy)
	return &policy
}

func TestIAMHasExpectedWriteUserAndPolicy(t *testing.T) {
	iamPolicyOutput := getIAMOutput(t, "aws_iam_user_policy.bucket_write_user")
	bucketPolicyInput := getBucketInput(t, BucketPolicyFilePath)
	user := strings.Split(bucketPolicyInput.Statement[0].Principal.AWS, "/")[1]
	assert.Contains(t, iamPolicyOutput, user)
	assert.Contains(t, iamPolicyOutput, bucketPolicyInput.Statement[0].Action[0])
}

func TestIAMHasExpectedReadUserAndPolicy(t *testing.T) {
	iamPolicyOutput := getIAMOutput(t, "aws_iam_user_policy.bucket_read_user")
	bucketPolicyInput := getBucketInput(t, BucketPolicyFilePath)
	user := strings.Split(bucketPolicyInput.Statement[1].Principal.AWS, "/")[1]
	assert.Contains(t, iamPolicyOutput, user)
	assert.Contains(t, iamPolicyOutput, bucketPolicyInput.Statement[1].Action[0])
}

func TestIAMHasExpectedAdminRoleAndPolicy(t *testing.T) {
	iamPolicyOutput := getIAMOutput(t, "aws_iam_role_policy_attachment.bucket_admin_role")
	bucketPolicyInput := getBucketInput(t, BucketPolicyFilePath)
	role := strings.Split(bucketPolicyInput.Statement[2].Principal.AWS, "/")[1]
	assert.Contains(t, iamPolicyOutput, role)
	assert.Contains(t, iamPolicyOutput, bucketPolicyInput.Statement[2].Action[0])
}


<|start_filename|>tf-aws-s3/Makefile<|end_filename|>
include local.env
export $(shell sed 's/=.*//' local.env)

install:
	bundle install
	dep ensure
	terraform init

unit:
	go test ./tests/unit/...

contract:
	go test ./tests/contract/...

integration:
	cd tests/integration && bundle exec rake spec

plan:
	terraform plan -var-file=test.tfvars -var 'pgp_key=${PGP_KEY}'

apply:
	terraform apply -var-file=test.tfvars -var 'pgp_key=${PGP_KEY}'

destroy:
	terraform destroy -var-file=test.tfvars -var 'pgp_key=${PGP_KEY}'

extract:
	terraform output bucket_read_user_access_id
	terraform output bucket_read_user_secret_key | base64 --decode | gpg -d
	terraform output bucket_write_user_access_id
	terraform output bucket_write_user_secret_key | base64 --decode | gpg -d
	terraform output bucket_admin_access_id
	terraform output bucket_admin_secret_key | base64 --decode | gpg -d

<|start_filename|>tf-aws-s3/tests/unit/policy_test.go<|end_filename|>
package test

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"testing"

	"github.com/joatmon08/tdd-infrastructure/tf-aws-s3/aws"
	"github.com/stretchr/testify/assert"
)

const BucketPolicyFilePath = "../../policies/bucket.json"
const AccountID = "REDACTED"

func setup(t *testing.T, policyPath string) *aws.Policy {
	jsonFile, err := os.Open(policyPath)
	if err != nil {
		t.Error(err)
	}
	defer jsonFile.Close()

	policyByteValue, _ := ioutil.ReadAll(jsonFile)

	var policy aws.Policy
	json.Unmarshal(policyByteValue, &policy)
	return &policy
}

func TestPolicyHasVersionAndID(t *testing.T) {
	policy := setup(t, BucketPolicyFilePath)
	assert.Equal(t, "2012-10-17", policy.Version)
	assert.Equal(t, "MyBucketPolicy", policy.ID)
	assert.Equal(t, 3, len(policy.Statement))
	assert.Equal(t, "AllowWriteUser", policy.Statement[0].Sid)
	assert.Equal(t, "AllowReadUser", policy.Statement[1].Sid)
	assert.Equal(t, "AllowAdminRole", policy.Statement[2].Sid)
}

func TestPolicyHasMyBucketWriteUserStatement(t *testing.T) {
	policy := setup(t, BucketPolicyFilePath)
	assert.Equal(t, "AllowWriteUser", policy.Statement[0].Sid)
	assert.Equal(t, "Allow", policy.Statement[0].Effect)
	assert.Contains(t, policy.Statement[0].Principal.AWS, fmt.Sprintf("arn:aws:iam::%s:user/MyBucketWriteUser", AccountID))
	assert.Equal(t, 1, len(policy.Statement[0].Action))
	assert.Contains(t, policy.Statement[0].Action, "s3:PutObject")
	assert.Contains(t, policy.Statement[0].Resource, "arn:aws:s3:::MyBucket/*")
}

func TestPolicyHasMyBucketReadUserStatement(t *testing.T) {
	policy := setup(t, BucketPolicyFilePath)
	assert.Equal(t, "AllowReadUser", policy.Statement[1].Sid)
	assert.Equal(t, "Allow", policy.Statement[1].Effect)
	assert.Contains(t, policy.Statement[1].Principal.AWS, fmt.Sprintf("arn:aws:iam::%s:user/MyBucketReadUser", AccountID))
	assert.Equal(t, 1, len(policy.Statement[1].Action))
	assert.Contains(t, policy.Statement[1].Action, "s3:GetObject")
	assert.Contains(t, policy.Statement[1].Resource, "arn:aws:s3:::MyBucket/*")
}

func TestPolicyHasMyBucketAdminRoleStatement(t *testing.T) {
	policy := setup(t, BucketPolicyFilePath)
	assert.Equal(t, "AllowAdminRole", policy.Statement[2].Sid)
	assert.Equal(t, "Allow", policy.Statement[2].Effect)
	assert.Contains(t, policy.Statement[2].Principal.AWS, fmt.Sprintf("arn:aws:iam::%s:role/MyBucketAdminRole", AccountID))
	assert.Equal(t, 1, len(policy.Statement[2].Action))
	assert.Contains(t, policy.Statement[2].Action, "s3:*")
	assert.Contains(t, policy.Statement[2].Resource, "arn:aws:s3:::MyBucket")
	assert.Contains(t, policy.Statement[2].Resource, "arn:aws:s3:::MyBucket/*")
}
