Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

INTMDB 186 - Added authorization resource to split the cloud access provider config #420

Merged
merged 21 commits into from
Apr 14, 2021
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions examples/atlas-cloud-provider-access/aws/aws-roles.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
resource "aws_iam_role_policy" "test_policy" {
name = "mongo_setup_policy"
role = aws_iam_role.test_role.id

policy = <<-EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
EOF
}

resource "aws_iam_role" "test_role" {
name = "mongo_setup_test_role"

assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "${mongodbatlas_cloud_provider_access_setup.setup_only.aws.atlas_aws_account_arn}"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "${mongodbatlas_cloud_provider_access_setup.setup_only.aws.atlas_assumed_role_external_id}"
}
}
}
]
}
EOF
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appears a linter error about not newline at the end of file

13 changes: 13 additions & 0 deletions examples/atlas-cloud-provider-access/aws/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
resource "mongodbatlas_cloud_provider_access_setup" "setup_only" {
project_id = var.project_id
provider_name = var.cloud_provider_access_name
}

resource "mongodbatlas_cloud_provider_access_authorization" "auth_role" {
project_id = var.project_id
role_id = mongodbatlas_cloud_provider_access_setup.setup_only.role_id

aws = {
iam_assumed_role_arn = aws_iam_role.test_role.arn
}
}
9 changes: 9 additions & 0 deletions examples/atlas-cloud-provider-access/aws/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
provider "mongodbatlas" {
public_key = var.public_key
private_key = var.private_key
}
provider "aws" {
access_key = var.access_key
secret_key = var.secret_key
region = var.aws_region
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as before about linter error

25 changes: 25 additions & 0 deletions examples/atlas-cloud-provider-access/aws/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// mongo
variable project_id {
type = string
}
variable cloud_provider_access_name {
type = string
default = "AWS"
}
variable public_key {
type = string
}
variable private_key {
type = string
}

// aws
variable access_key {
type = string
}
variable secret_key {
type = string
}
variable aws_region {
type = string
}
8 changes: 8 additions & 0 deletions examples/atlas-cloud-provider-access/aws/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
required_providers {
mongodbatlas = {
source = "mongodb/mongodbatlas"
}
}
required_version = ">= 0.13"
}
21 changes: 21 additions & 0 deletions integration-testing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
### Integration tests

The integration tests required extra credentials, like aws, azure.
In order to execute the complete terra cycle (init, apply, destroy)
themantissa marked this conversation as resolved.
Show resolved Hide resolved

For all the testing it needs the common environment variables
```
MONGODB_ATLAS_PROJECT_ID
MONGODB_ATLAS_PUBLIC_KEY
MONGODB_ATLAS_PRIVATE_KEY
```

For especific aws related interactions
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
For especific aws related interactions
For specific aws related interactions

```
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_REGION

AWS_CUSTOMER_MASTER_KEY_ID (only cloud at rest)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
AWS_CUSTOMER_MASTER_KEY_ID (only cloud at rest)
AWS_CUSTOMER_MASTER_KEY_ID (only required for encryption at rest with customer managed keys)


```
themantissa marked this conversation as resolved.
Show resolved Hide resolved
33 changes: 33 additions & 0 deletions integration-testing/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package integration_testing

import "os"

type MongoDBCredentials struct {
ProjectID string
PublicKey string
PrivateKey string
}

type AWSCredentials struct {
AccessKey string
SecretKey string
CustomerMasterKey string
AwsRegion string
}

func GetCredentialsFromEnv() MongoDBCredentials {
return MongoDBCredentials{
ProjectID: os.Getenv("MONGODB_ATLAS_PROJECT_ID"),
PublicKey: os.Getenv("MONGODB_ATLAS_PUBLIC_KEY"),
PrivateKey: os.Getenv("MONGODB_ATLAS_PRIVATE_KEY"),
}
}

func GetAWSCredentialsFromEnv() AWSCredentials {
return AWSCredentials{
AccessKey: os.Getenv("AWS_ACCESS_KEY_ID"),
SecretKey: os.Getenv("AWS_SECRET_ACCESS_KEY"),
CustomerMasterKey: os.Getenv("AWS_CUSTOMER_MASTER_KEY_ID"),
AwsRegion: os.Getenv("AWS_REGION"),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package integration_testing

import (
"os"
"testing"

"github.com/gruntwork-io/terratest/modules/terraform"
)

const (
defaultTerratestFilesCPA = "../examples/atlas-cloud-provider-access/aws/"
)

func TestTerraformResourceMongoDBAtlasCloudProviderAccess_basicAWS(t *testing.T) {
SkipTestExtCred(t)
t.Parallel()

mongoSecrets := GetCredentialsFromEnv()
awsSecrets := GetAWSCredentialsFromEnv()

testFiles := os.Getenv("TERRATEST_CLOUD_PROVIDER_ACCESS_AWS")
if testFiles == "" {
testFiles = defaultTerratestFilesCPA
}

terraformOptions := &terraform.Options{
TerraformDir: testFiles,
Vars: map[string]interface{}{
"project_id": mongoSecrets.ProjectID,
"cloud_provider_access_name": "AWS",
"public_key": mongoSecrets.PublicKey,
"private_key": mongoSecrets.PrivateKey,
"access_key": awsSecrets.AccessKey,
"secret_key": awsSecrets.SecretKey,
"aws_region": awsSecrets.AwsRegion,
},
}

terraformTest := terraform.WithDefaultRetryableErrors(t, terraformOptions)

defer terraform.Destroy(t, terraformTest)
terraform.InitAndApply(t, terraformTest)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,22 @@ func TestTerraformResourceMongoDBAtlasEncryptionAtRestWithRole_basicAWS(t *testi
SkipTestExtCred(t)
t.Parallel()

var (
projectID = os.Getenv("MONGODB_ATLAS_PROJECT_ID")
accessKey = os.Getenv("AWS_ACCESS_KEY_ID")
secretKey = os.Getenv("AWS_SECRET_ACCESS_KEY")
customerKey = os.Getenv("AWS_CUSTOMER_MASTER_KEY_ID")
awsRegion = os.Getenv("AWS_REGION")
publicKey = os.Getenv("MONGODB_ATLAS_PUBLIC_KEY")
privateKey = os.Getenv("MONGODB_ATLAS_PRIVATE_KEY")
)
mongoSecrets := GetCredentialsFromEnv()
awsSecrets := GetAWSCredentialsFromEnv()

// Construct the terraform options with default retryable errors to handle the most common
// retryable errors in terraform testing.
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
// The path to where our Terraform code is located
TerraformDir: "../examples/atlas-encryptionAtRest-roles",
Vars: map[string]interface{}{
"access_key": accessKey,
"secret_key": secretKey,
"customer_master_key": customerKey,
"atlas_region": awsRegion,
"project_id": projectID,
"public_key": publicKey,
"private_key": privateKey,
"access_key": awsSecrets.AccessKey,
"secret_key": awsSecrets.SecretKey,
"customer_master_key": awsSecrets.CustomerMasterKey,
"atlas_region": awsSecrets.AwsRegion,
"project_id": mongoSecrets.ProjectID,
"public_key": mongoSecrets.PublicKey,
"private_key": mongoSecrets.PrivateKey,
},
})

Expand All @@ -53,20 +47,20 @@ func TestTerraformResourceMongoDBAtlasEncryptionAtRestWithRole_basicAWS(t *testi
awsRoleARN := terraform.Output(t, terraformOptions, "aws_iam_role_arn")
cpaRoleID := terraform.Output(t, terraformOptions, "cpa_role_id")

fmt.Println(fmt.Sprintf("awsRoleARN : %s", awsRoleARN))
fmt.Println(fmt.Sprintf("cpaRoleID : %s", cpaRoleID))
fmt.Printf("awsRoleARN : %s", awsRoleARN)
fmt.Printf("cpaRoleID : %s", cpaRoleID)

terraformOptionsUpdated := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
// The path to where our Terraform code is located
TerraformDir: "../examples/atlas-encryptionAtRest-roles",
Vars: map[string]interface{}{
"access_key": accessKey,
"secret_key": secretKey,
"customer_master_key": customerKey,
"atlas_region": awsRegion,
"project_id": projectID,
"public_key": publicKey,
"private_key": privateKey,
"access_key": awsSecrets.AccessKey,
"secret_key": awsSecrets.SecretKey,
"customer_master_key": awsSecrets.CustomerMasterKey,
"atlas_region": awsSecrets.AwsRegion,
"project_id": mongoSecrets.ProjectID,
"public_key": mongoSecrets.PublicKey,
"private_key": mongoSecrets.PrivateKey,
"aws_iam_role_arn": awsRoleARN,
},
})
Expand All @@ -77,11 +71,11 @@ func TestTerraformResourceMongoDBAtlasEncryptionAtRestWithRole_basicAWS(t *testi
// The path to where our Terraform code is located
TerraformDir: "../examples/atlas-encryptionAtRest-roles/second_step",
Vars: map[string]interface{}{
"customer_master_key": customerKey,
"atlas_region": awsRegion,
"project_id": projectID,
"public_key": publicKey,
"private_key": privateKey,
"customer_master_key": awsSecrets.CustomerMasterKey,
"atlas_region": awsSecrets.AwsRegion,
"project_id": mongoSecrets.ProjectID,
"public_key": mongoSecrets.PublicKey,
"private_key": mongoSecrets.PrivateKey,
"cpa_role_id": cpaRoleID,
},
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package mongodbatlas

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
matlas "go.mongodb.org/atlas/mongodbatlas"
)

func dataSourceMongoDBAtlasCloudProviderAccessSetup() *schema.Resource {
return &schema.Resource{
Read: dataSourceMongoDBAtlasCloudProviderAccessSetupRead,
Schema: map[string]*schema.Schema{
"project_id": {
Type: schema.TypeString,
Required: true,
},
"provider_name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"AWS"}, false),
},
"role_id": {
Type: schema.TypeString,
Required: true,
},
"aws": {
Type: schema.TypeMap,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"atlas_aws_account_arn": {
Type: schema.TypeString,
Computed: true,
},
"atlas_assumed_role_external_id": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"created_date": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceMongoDBAtlasCloudProviderAccessSetupRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*matlas.Client)
projectID := d.Get("project_id").(string)
providerName := d.Get("provider_name").(string)
roleID := d.Get("role_id").(string)

roles, _, err := conn.CloudProviderAccess.ListRoles(context.Background(), projectID)

if err != nil {
return fmt.Errorf(errorGetRead, err)
}

// aws specific
if providerName == "AWS" {
var targetRole matlas.AWSIAMRole
// searching in roles
for i := range roles.AWSIAMRoles {
role := &(roles.AWSIAMRoles[i])
if role.RoleID == roleID && role.ProviderName == providerName {
targetRole = *role
}
}
// Not Found
if targetRole.RoleID == "" && !d.IsNewResource() {
d.SetId("")
return nil
}

roleSchema := roleToSchemaSetup(&targetRole)

for key, val := range roleSchema {
if err := d.Set(key, val); err != nil {
return fmt.Errorf(errorGetRead, err)
}
}
} else {
// planning for the future multiple providers
return fmt.Errorf(errorGetRead,
fmt.Sprintf("unsopported provider type %s", providerName))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fmt.Sprintf("unsopported provider type %s", providerName))
fmt.Sprintf("unsupported provider type %s", providerName))

}

d.SetId(resource.UniqueId())

return nil
}
Loading