-
Notifications
You must be signed in to change notification settings - Fork 393
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
Added AWS IAM data helpers #255
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
package access | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
) | ||
|
||
type awsIamPolicy struct { | ||
Version string `json:"Version,omitempty"` | ||
ID string `json:"Id,omitempty"` | ||
Statements []*awsIamPolicyStatement `json:"Statement"` | ||
} | ||
|
||
type awsIamPolicyStatement struct { | ||
Sid string `json:"Sid,omitempty"` | ||
Effect string `json:"Effect,omitempty"` | ||
Actions interface{} `json:"Action,omitempty"` | ||
NotActions interface{} `json:"NotAction,omitempty"` | ||
Resources interface{} `json:"Resource,omitempty"` | ||
NotResources interface{} `json:"NotResource,omitempty"` | ||
Principal map[string]string `json:"Principal,omitempty"` | ||
Condition map[string]map[string]string `json:"Condition,omitempty"` | ||
} | ||
|
||
func DataAwsCrossAccountRolicy() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: func(d *schema.ResourceData, m interface{}) error { | ||
policy := awsIamPolicy{ | ||
Statements: []*awsIamPolicyStatement{ | ||
{ | ||
Effect: "Allow", | ||
Actions: []string{ | ||
"ec2:AssociateDhcpOptions", | ||
"ec2:AssociateIamInstanceProfile", | ||
"ec2:AssociateRouteTable", | ||
"ec2:AttachInternetGateway", | ||
"ec2:AttachVolume", | ||
"ec2:AuthorizeSecurityGroupEgress", | ||
"ec2:AuthorizeSecurityGroupIngress", | ||
"ec2:CancelSpotInstanceRequests", | ||
"ec2:CreateDhcpOptions", | ||
"ec2:CreateInternetGateway", | ||
"ec2:CreateKeyPair", | ||
"ec2:CreateRoute", | ||
"ec2:CreateSecurityGroup", | ||
"ec2:CreateSubnet", | ||
"ec2:CreateTags", | ||
"ec2:CreateVolume", | ||
"ec2:CreateVpc", | ||
"ec2:DeleteInternetGateway", | ||
"ec2:DeleteKeyPair", | ||
"ec2:DeleteRoute", | ||
"ec2:DeleteRouteTable", | ||
"ec2:DeleteSecurityGroup", | ||
"ec2:DeleteSubnet", | ||
"ec2:DeleteTags", | ||
"ec2:DeleteVolume", | ||
"ec2:DeleteVpc", | ||
"ec2:DescribeAvailabilityZones", | ||
"ec2:DescribeNetworkAcls", | ||
"ec2:DescribeInternetGateways", | ||
"ec2:DescribeVpcAttribute", | ||
"ec2:DescribeIamInstanceProfileAssociations", | ||
"ec2:DescribeInstanceStatus", | ||
"ec2:DescribeInstances", | ||
"ec2:DescribePrefixLists", | ||
"ec2:DescribeReservedInstancesOfferings", | ||
"ec2:DescribeRouteTables", | ||
"ec2:DescribeSecurityGroups", | ||
"ec2:DescribeSpotInstanceRequests", | ||
"ec2:DescribeSpotPriceHistory", | ||
"ec2:DescribeSubnets", | ||
"ec2:DescribeVolumes", | ||
"ec2:DescribeVpcs", | ||
"ec2:DetachInternetGateway", | ||
"ec2:DisassociateIamInstanceProfile", | ||
"ec2:ModifyVpcAttribute", | ||
"ec2:ReplaceIamInstanceProfileAssociation", | ||
"ec2:RequestSpotInstances", | ||
"ec2:RevokeSecurityGroupEgress", | ||
"ec2:RevokeSecurityGroupIngress", | ||
"ec2:RunInstances", | ||
"ec2:TerminateInstances", | ||
"ec2:CreatePlacementGroup", | ||
"ec2:DeletePlacementGroup", | ||
"ec2:DescribePlacementGroups", | ||
}, | ||
Resources: "*", | ||
}, | ||
{ | ||
Effect: "Allow", | ||
Actions: []string{ | ||
"iam:CreateServiceLinkedRole", | ||
"iam:PutRolePolicy", | ||
}, | ||
Resources: "arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot", | ||
Condition: map[string]map[string]string{ | ||
"StringLike": { | ||
"iam:AWSServiceName": "spot.amazonaws.com", | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
if passRoleARNs, ok := d.GetOk("pass_role_arns"); ok { | ||
policy.Statements = append(policy.Statements, &awsIamPolicyStatement{ | ||
Effect: "Allow", | ||
Actions: "iam:PassRole", | ||
Resources: passRoleARNs, | ||
}) | ||
} | ||
policyJSON, err := json.MarshalIndent(policy, "", " ") | ||
if err != nil { | ||
return err | ||
} | ||
return d.Set("json", string(policyJSON)) | ||
}, | ||
Schema: map[string]*schema.Schema{ | ||
"pass_role_arns": { | ||
Type: schema.TypeList, | ||
Elem: schema.TypeString, | ||
Optional: true, | ||
}, | ||
"json": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func DataAwsAssumeRolePolicy() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: func(d *schema.ResourceData, m interface{}) error { | ||
policyJSON, err := json.MarshalIndent(awsIamPolicy{ | ||
Statements: []*awsIamPolicyStatement{ | ||
{ | ||
Effect: "Allow", | ||
Actions: "sts:AssumeRole", | ||
Condition: map[string]map[string]string{ | ||
"StringEquals": { | ||
"sts:ExternalId": d.Get("external_id").(string), | ||
}, | ||
}, | ||
Principal: map[string]string{ | ||
"AWS": fmt.Sprintf("arn:aws:iam::%s:root", d.Get("databricks_account_id").(string)), | ||
}, | ||
}, | ||
}, | ||
}, "", " ") | ||
if err != nil { | ||
return err | ||
} | ||
return d.Set("json", string(policyJSON)) | ||
}, | ||
Schema: map[string]*schema.Schema{ | ||
"databricks_account_id": { | ||
Type: schema.TypeString, | ||
Default: "414351767826", | ||
Optional: true, | ||
}, | ||
"external_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
"json": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func DataAwsBucketPolicy() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: func(d *schema.ResourceData, m interface{}) error { | ||
policyJSON, err := json.MarshalIndent(awsIamPolicy{ | ||
Statements: []*awsIamPolicyStatement{ | ||
{ | ||
Effect: "Allow", | ||
Actions: []string{ | ||
"s3:GetObject", | ||
"s3:GetObjectVersion", | ||
"s3:PutObject", | ||
"s3:DeleteObject", | ||
"s3:ListBucket", | ||
"s3:GetBucketLocation", | ||
}, | ||
Resources: []string{ | ||
fmt.Sprintf("arn:aws:s3:::%s/*", d.Get("bucket_name").(string)), | ||
fmt.Sprintf("arn:aws:s3:::%s", d.Get("bucket_name").(string)), | ||
}, | ||
Principal: map[string]string{ | ||
"AWS": fmt.Sprintf("arn:aws:iam::%s:root", d.Get("databricks_account_id").(string)), | ||
}, | ||
}, | ||
}, | ||
}, "", " ") | ||
if err != nil { | ||
return err | ||
} | ||
return d.Set("json", string(policyJSON)) | ||
}, | ||
Schema: map[string]*schema.Schema{ | ||
"databricks_account_id": { | ||
Type: schema.TypeString, | ||
Default: "414351767826", | ||
Optional: true, | ||
}, | ||
"bucket_name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
"json": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# databricks_aws_assume_role_policy Data Source | ||
|
||
This data source constructs necessary AWS STS assume role policy for you. | ||
|
||
## Example Usage | ||
|
||
End-to-end example of provisioning Cross-account IAM role: | ||
|
||
```hcl | ||
variable "account_id" { | ||
type = string | ||
description = "External ID you find on https://accounts.cloud.databricks.com/#aws" | ||
} | ||
|
||
data "databricks_aws_crossaccount_policy" "this" {} | ||
|
||
resource "aws_iam_policy" "cross_account_policy" { | ||
name = "${var.prefix}-crossaccount-iam-policy" | ||
policy = data.databricks_aws_crossaccount_policy.this.json | ||
} | ||
|
||
data "databricks_aws_assume_role_policy" "this" { | ||
external_id = var.account_id | ||
} | ||
|
||
resource "aws_iam_role" "cross_account" { | ||
name = "${var.prefix}-crossaccount-iam-role" | ||
assume_role_policy = data.databricks_aws_assume_role_policy.this.json | ||
description = "Grants Databricks full access to VPC resources" | ||
} | ||
|
||
resource "aws_iam_role_policy_attachment" "cross_account" { | ||
policy_arn = aws_iam_policy.cross_account_policy.arn | ||
role = aws_iam_role.cross_account.name | ||
} | ||
|
||
// required only in case of multiworkspace setup | ||
resource "databricks_mws_credentials" "this" { | ||
provider = databricks.mws | ||
account_id = var.account_id | ||
credentials_name = "${var.prefix}-creds" | ||
role_arn = aws_iam_role.cross_account.arn | ||
} | ||
``` | ||
|
||
## Attribute Reference | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All the other docs in the repo make a clear distinction between attribute and argument. Argument should be user inputs where attributes are outputs/read only values computed by the resource/datasource. This should use the naming convention Argument reference
Attribute reference
|
||
|
||
This data source takes `external_id` argument, which is your master account id, which you can find as External ID on https://accounts.cloud.databricks.com/#aws. AWS IAM Policy JSON documents are available in `json` property that is exported from this data source. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# databricks_aws_bucket_policy Data Source | ||
|
||
This datasource configures simple access policy for AWS S3 buckets, so that Databricks can access data in it. | ||
|
||
## Example Usage | ||
|
||
```hcl | ||
resource "aws_s3_bucket" "this" { | ||
bucket = "things" | ||
region = "eu-west-1" | ||
acl = "private" | ||
force_destroy = true | ||
} | ||
|
||
data "databricks_aws_bucket_policy" "stuff" { | ||
bucket_name = aws_s3_bucket.this.bucket | ||
} | ||
|
||
resource "aws_s3_bucket_policy" "this" { | ||
bucket = aws_s3_bucket.this.id | ||
policy = data.databricks_aws_bucket_policy.this.json | ||
} | ||
``` | ||
## Argument Reference | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All the other docs in the repo make a clear distinction between attribute and argument. Argument should be user inputs where attributes are outputs/read only values computed by the resource/datasource. The bucket_name should be an argument where the json is an attribute. This should use the naming convention Argument reference
Attribute reference
|
||
|
||
* `bucket_name` - (Required) AWS S3 Bucket name for which to generate policy document. | ||
* `json` - (Read-only) AWS IAM Policy JSON document to grand Databricks full access to bucket. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs a docs page