Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
38 changes: 24 additions & 14 deletions mongodbatlas/cloud_provider_access.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ const cloudProviderAccessPath = "api/atlas/v1.0/groups/%s/cloudProviderAccess"
// See more: https://www.mongodb.com/docs/atlas/reference/api-resources-spec/v2/#tag/Cloud-Provider-Access
type CloudProviderAccessService interface {
ListRoles(context.Context, string) (*CloudProviderAccessRoles, *Response, error)
GetRole(context.Context, string, string) (*AWSIAMRole, *Response, error)
CreateRole(context.Context, string, *CloudProviderAccessRoleRequest) (*AWSIAMRole, *Response, error)
AuthorizeRole(context.Context, string, string, *CloudProviderAuthorizationRequest) (*AWSIAMRole, *Response, error)
GetRole(context.Context, string, string) (*CloudProviderAccessRole, *Response, error)
CreateRole(context.Context, string, *CloudProviderAccessRoleRequest) (*CloudProviderAccessRole, *Response, error)
AuthorizeRole(context.Context, string, string, *CloudProviderAuthorizationRequest) (*CloudProviderAccessRole, *Response, error)
DeauthorizeRole(context.Context, *CloudProviderDeauthorizationRequest) (*Response, error)
}

Expand All @@ -40,19 +40,24 @@ var _ CloudProviderAccessService = &CloudProviderAccessServiceOp{}

// CloudProviderAccessRoles an array of awsIamRoles objects.
type CloudProviderAccessRoles struct {
AWSIAMRoles []AWSIAMRole `json:"awsIamRoles,omitempty"` // Unique identifier of AWS security group in this access list entry.
AWSIAMRoles []CloudProviderAccessRole `json:"awsIamRoles,omitempty"` // Unique identifier of AWS security group in this access list entry.
}

// AWSIAMRole is the response from the CloudProviderAccessService.ListRoles.
type AWSIAMRole struct {
// CloudProviderAccessRole is the response from the CloudProviderAccessService.ListRoles.
type CloudProviderAccessRole struct {
AtlasAWSAccountARN string `json:"atlasAWSAccountArn,omitempty"` // ARN associated with the Atlas AWS account used to assume IAM roles in your AWS account.
AtlasAssumedRoleExternalID string `json:"atlasAssumedRoleExternalId,omitempty"` // Unique external ID Atlas uses when assuming the IAM role in your AWS account.
AuthorizedDate string `json:"authorizedDate,omitempty"` // Date on which this role was authorized.
CreatedDate string `json:"createdDate,omitempty"` // Date on which this role was created.
FeatureUsages []*FeatureUsage `json:"featureUsages,omitempty"` // Atlas features this AWS IAM role is linked to.
IAMAssumedRoleARN string `json:"iamAssumedRoleArn,omitempty"` // ARN of the IAM Role that Atlas assumes when accessing resources in your AWS account.
ProviderName string `json:"providerName,omitempty"` // Name of the cloud provider. Currently limited to AWS.
RoleID string `json:"roleId,omitempty"` // Unique ID of this role.
RoleID string `json:"roleId,omitempty"` // Unique 24-hexadecimal digit string that identifies the role.
AzureID *string `json:"_id,omitempty"` // Unique 24-hexadecimal digit string that identifies the Azure Service Principal in Atlas.
AtlasAzureAppID *string `json:"atlasAzureAppId,omitempty"` // Azure Active Directory Application ID of Atlas.
Copy link
Member

@wtrocki wtrocki Jul 21, 2023

Choose a reason for hiding this comment

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

Nit: Can we change the order of properties to make it easier to understand what comes from which polymorphic type? For example: Putting ID as first property or adding an Azure prefix in the comments

Copy link
Collaborator Author

@andreaangiolillo andreaangiolillo Jul 21, 2023

Choose a reason for hiding this comment

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

Just to make sure I understood the suggestion here: you are proposing to update the description of each field and add Azure:desciption or AWS: description? What about the fields that are needed with both? Azure|AWS:description?

Copy link
Member

Choose a reason for hiding this comment

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

I have no strong opinion on this.
My suggestion was to add prefixes to Azure: specific properties. Adding AWS ones could be a bonus.
Otherwise no description update is needed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

updated

LastUpdatedDate string `json:"lastUpdatedDate,omitempty"` // UUID string that identifies the Azure Service Principal.
AzureServicePrincipalID *string `json:"servicePrincipalId,omitempty"` // Unique ID of this role.
AzureTenantID *string `json:"tenantId,omitempty"` // UUID String that identifies the Azure Active Directory Tenant ID.
}

// FeatureUsage represents where the role sis being used.
Expand All @@ -63,7 +68,12 @@ type FeatureUsage struct {

// CloudProviderAccessRoleRequest represent a new role creation.
type CloudProviderAccessRoleRequest struct {
ProviderName string `json:"providerName"`
ProviderName string `json:"providerName"` // Human-readable label that identifies the cloud provider of the role.
IamAssumedRoleArn *string `json:"iamAssumedRoleArn,omitempty"` // Amazon Resource Name (ARN) that identifies the Amazon Web Services (AWS) Identity and Access Management (IAM) role that MongoDB Cloud assumes when it accesses resources in your AWS account.
AtlasAzureAppID *string `json:"atlasAzureAppId,omitempty"` // Date and time when this Azure Service Principal was last updated. This parameter expresses its value in the ISO 8601 timestamp format in UTC.
AzureServicePrincipalID *string `json:"servicePrincipalId,omitempty"` // Unique AzureID of this role.
AzureTenantID *string `json:"tenantId,omitempty"` // UUID String that identifies the Azure Active Directory Tenant AzureID.

}

// CloudProviderAuthorizationRequest represents an authorization request.
Expand All @@ -83,7 +93,7 @@ type CloudProviderDeauthorizationRequest struct {
// with the specified id and with access to the specified project.
//
// See more: https://www.mongodb.com/docs/atlas/reference/api-resources-spec/v2/#tag/Cloud-Provider-Access/operation/getCloudProviderAccessRole
func (s *CloudProviderAccessServiceOp) GetRole(ctx context.Context, groupID, roleID string) (*AWSIAMRole, *Response, error) {
func (s *CloudProviderAccessServiceOp) GetRole(ctx context.Context, groupID, roleID string) (*CloudProviderAccessRole, *Response, error) {
if groupID == "" {
return nil, nil, NewArgError("groupId", "must be set")
}
Expand All @@ -98,7 +108,7 @@ func (s *CloudProviderAccessServiceOp) GetRole(ctx context.Context, groupID, rol
return nil, nil, err
}

root := new(AWSIAMRole)
root := new(CloudProviderAccessRole)
resp, err := s.Client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
Expand Down Expand Up @@ -130,7 +140,7 @@ func (s *CloudProviderAccessServiceOp) ListRoles(ctx context.Context, groupID st
// CreateRole creates an AWS IAM role.
//
// See more: https://www.mongodb.com/docs/atlas/reference/api-resources-spec/v2/#tag/Cloud-Provider-Access/operation/createCloudProviderAccessRole
func (s *CloudProviderAccessServiceOp) CreateRole(ctx context.Context, groupID string, request *CloudProviderAccessRoleRequest) (*AWSIAMRole, *Response, error) {
func (s *CloudProviderAccessServiceOp) CreateRole(ctx context.Context, groupID string, request *CloudProviderAccessRoleRequest) (*CloudProviderAccessRole, *Response, error) {
if request == nil {
return nil, nil, NewArgError("request", "must be set")
}
Expand All @@ -142,7 +152,7 @@ func (s *CloudProviderAccessServiceOp) CreateRole(ctx context.Context, groupID s
return nil, nil, err
}

root := new(AWSIAMRole)
root := new(CloudProviderAccessRole)
resp, err := s.Client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
Expand All @@ -154,7 +164,7 @@ func (s *CloudProviderAccessServiceOp) CreateRole(ctx context.Context, groupID s
// AuthorizeRole authorizes and configure an AWS Assumed IAM role.
//
// See more: https://www.mongodb.com/docs/atlas/reference/api-resources-spec/v2/#tag/Cloud-Provider-Access/operation/authorizeCloudProviderAccessRole
func (s *CloudProviderAccessServiceOp) AuthorizeRole(ctx context.Context, groupID, roleID string, request *CloudProviderAuthorizationRequest) (*AWSIAMRole, *Response, error) {
func (s *CloudProviderAccessServiceOp) AuthorizeRole(ctx context.Context, groupID, roleID string, request *CloudProviderAuthorizationRequest) (*CloudProviderAccessRole, *Response, error) {
if roleID == "" {
return nil, nil, NewArgError("roleID", "must be set")
}
Expand All @@ -171,7 +181,7 @@ func (s *CloudProviderAccessServiceOp) AuthorizeRole(ctx context.Context, groupI
return nil, nil, err
}

root := new(AWSIAMRole)
root := new(CloudProviderAccessRole)
resp, err := s.Client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
Expand Down
130 changes: 121 additions & 9 deletions mongodbatlas/cloud_provider_access_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestCloudProviderAccessServiceOp_ListRoles(t *testing.T) {
}

expected := &CloudProviderAccessRoles{
AWSIAMRoles: []AWSIAMRole{
AWSIAMRoles: []CloudProviderAccessRole{
{
AtlasAWSAccountARN: "arn:aws:iam::123456789012:root",
AtlasAssumedRoleExternalID: "3192be49-6e76-4b7d-a7b8-b486a8fc4483",
Expand All @@ -67,7 +67,7 @@ func TestCloudProviderAccessServiceOp_ListRoles(t *testing.T) {
}
}

func TestCloudProviderAccessServiceOp_GetRole(t *testing.T) {
func TestCloudProviderAccessServiceOp_GetRoleAWS(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
roleID := "1"
Expand All @@ -90,7 +90,7 @@ func TestCloudProviderAccessServiceOp_GetRole(t *testing.T) {
t.Fatalf("CloudProviderAccess.GetRole returned error: %v", err)
}

expected := &AWSIAMRole{
expected := &CloudProviderAccessRole{
AtlasAWSAccountARN: "arn:aws:iam::123456789012:root",
AtlasAssumedRoleExternalID: "3192be49-6e76-4b7d-a7b8-b486a8fc4483",
AuthorizedDate: "2020-08-03T20:42:49Z",
Expand All @@ -105,17 +105,128 @@ func TestCloudProviderAccessServiceOp_GetRole(t *testing.T) {
}
}

func TestCloudProviderAccessServiceOp_CreateRole(t *testing.T) {
func TestCloudProviderAccessServiceOp_GetRoleAzure(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
roleID := "1"
mux.HandleFunc(fmt.Sprintf("/api/atlas/v1.0/groups/1/cloudProviderAccess/%s", roleID), func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{
"providerName": "AZURE",
"atlasAssumedRoleExternalId": "test",
"createdDate": "2019-08-24T14:15:22Z",
"iamAssumedRoleArn": "arn:aws:iam::123456789012:root",
"roleId": "32b6e34b3d91647abb20e7b8",
"_id": "32b6e34b3d91647abb20e7b8",
"atlasAzureAppId": "test",
"lastUpdatedDate": "2019-08-24T14:15:22Z",
"servicePrincipalId": "test",
"tenantId": "test"
}`)
})

roles, _, err := client.CloudProviderAccess.GetRole(ctx, groupID, roleID)
if err != nil {
t.Fatalf("CloudProviderAccess.GetRole returned error: %v", err)
}

expected := &CloudProviderAccessRole{
AtlasAssumedRoleExternalID: "test",
IAMAssumedRoleARN: "arn:aws:iam::123456789012:root",
CreatedDate: "2019-08-24T14:15:22Z",
LastUpdatedDate: "2019-08-24T14:15:22Z",
AtlasAzureAppID: pointer("test"),
AzureServicePrincipalID: pointer("test"),
AzureTenantID: pointer("test"),
ProviderName: "AZURE",
RoleID: "32b6e34b3d91647abb20e7b8",
AzureID: pointer("32b6e34b3d91647abb20e7b8"),
}
if diff := deep.Equal(roles, expected); diff != nil {
t.Error(diff)
}
}

func TestCloudProviderAccessServiceOp_CreateRoleAzure(t *testing.T) {
client, mux, teardown := setup()
defer teardown()

createRequest := &CloudProviderAccessRoleRequest{
ProviderName: "AWS",
ProviderName: "AZURE",
AtlasAzureAppID: pointer("test"),
AzureServicePrincipalID: pointer("test"),
AzureTenantID: pointer("test"),
}

mux.HandleFunc("/api/atlas/v1.0/groups/1/cloudProviderAccess", func(w http.ResponseWriter, r *http.Request) {
expected := map[string]interface{}{
"providerName": "AWS",
"providerName": "AZURE",
"atlasAzureAppId": "test",
"servicePrincipalId": "test",
"tenantId": "test",
}

jsonBlob := `{
"providerName": "AZURE",
"atlasAssumedRoleExternalId": "test",
"createdDate": "2019-08-24T14:15:22Z",
"iamAssumedRoleArn": "arn:aws:iam::123456789012:root",
"roleId": "32b6e34b3d91647abb20e7b8",
"_id": "32b6e34b3d91647abb20e7b8",
"atlasAzureAppId": "test",
"lastUpdatedDate": "2019-08-24T14:15:22Z",
"servicePrincipalId": "test",
"tenantId": "test"
}`

var v map[string]interface{}
err := json.NewDecoder(r.Body).Decode(&v)
if err != nil {
t.Fatalf("decode json: %v", err)
}

if diff := deep.Equal(v, expected); diff != nil {
t.Error(diff)
}

fmt.Fprint(w, jsonBlob)
})

role, _, err := client.CloudProviderAccess.CreateRole(ctx, "1", createRequest)
if err != nil {
t.Fatalf("CloudProviderAccess.CreateRole returned error: %v", err)
}

expected := &CloudProviderAccessRole{
AtlasAssumedRoleExternalID: "test",
IAMAssumedRoleARN: "arn:aws:iam::123456789012:root",
CreatedDate: "2019-08-24T14:15:22Z",
LastUpdatedDate: "2019-08-24T14:15:22Z",
AtlasAzureAppID: pointer("test"),
AzureServicePrincipalID: pointer("test"),
AzureTenantID: pointer("test"),
ProviderName: "AZURE",
RoleID: "32b6e34b3d91647abb20e7b8",
AzureID: pointer("32b6e34b3d91647abb20e7b8"),
}
if diff := deep.Equal(role, expected); diff != nil {
t.Error(diff)
}
}

func TestCloudProviderAccessServiceOp_CreateRoleAWS(t *testing.T) {
client, mux, teardown := setup()
defer teardown()

createRequest := &CloudProviderAccessRoleRequest{
ProviderName: "AWS",
IamAssumedRoleArn: pointer("test"),
}

mux.HandleFunc("/api/atlas/v1.0/groups/1/cloudProviderAccess", func(w http.ResponseWriter, r *http.Request) {
expected := map[string]interface{}{
"providerName": "AWS",
"iamAssumedRoleArn": "test",
}

jsonBlob := `{
Expand All @@ -124,7 +235,7 @@ func TestCloudProviderAccessServiceOp_CreateRole(t *testing.T) {
"authorizedDate": null,
"createdDate": "2020-07-30T20:20:36Z",
"featureUsages": [],
"iamAssumedRoleArn": null,
"iamAssumedRoleArn": "test",
"providerName": "AWS",
"roleId": "5f232b94af0a6b41747bcc2d"
}`
Expand All @@ -147,9 +258,10 @@ func TestCloudProviderAccessServiceOp_CreateRole(t *testing.T) {
t.Fatalf("CloudProviderAccess.CreateRole returned error: %v", err)
}

expected := &AWSIAMRole{
expected := &CloudProviderAccessRole{
AtlasAWSAccountARN: "arn:aws:iam::123456789012:root",
AtlasAssumedRoleExternalID: "3192be49-6e76-4b7d-a7b8-b486a8fc4483",
IAMAssumedRoleARN: "test",
CreatedDate: "2020-07-30T20:20:36Z",
FeatureUsages: []*FeatureUsage{},
ProviderName: "AWS",
Expand Down Expand Up @@ -206,7 +318,7 @@ func TestCloudProviderAccessServiceOp_AuthorizeRole(t *testing.T) {
t.Fatalf("CloudProviderAccess.AuthorizeRole returned error: %v", err)
}

expected := &AWSIAMRole{
expected := &CloudProviderAccessRole{
AtlasAWSAccountARN: "arn:aws:iam::123456789012:user/test.user",
AtlasAssumedRoleExternalID: "3192be49-6e76-4b7d-a7b8-b486a8fc4483",
AuthorizedDate: "2020-07-30T22:17:09Z",
Expand Down