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

Feature/apigateway authorization scopes #4533

Merged
merged 3 commits into from
Jun 4, 2018
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
41 changes: 41 additions & 0 deletions aws/resource_aws_api_gateway_method.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ func resourceAwsApiGatewayMethod() *schema.Resource {
Optional: true,
},

"authorization_scopes": &schema.Schema{
Type: schema.TypeSet,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
Optional: true,
},

"api_key_required": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Expand Down Expand Up @@ -126,6 +133,10 @@ func resourceAwsApiGatewayMethodCreate(d *schema.ResourceData, meta interface{})
input.AuthorizerId = aws.String(v.(string))
}

if v, ok := d.GetOk("authorization_scopes"); ok {
input.AuthorizationScopes = expandStringList(v.(*schema.Set).List())
}

if v, ok := d.GetOk("request_validator_id"); ok {
input.RequestValidatorId = aws.String(v.(string))
}
Expand Down Expand Up @@ -168,6 +179,10 @@ func resourceAwsApiGatewayMethodRead(d *schema.ResourceData, meta interface{}) e
d.Set("request_models", aws.StringValueMap(out.RequestModels))
d.Set("request_validator_id", out.RequestValidatorId)

if err := d.Set("authorization_scopes", flattenStringList(out.AuthorizationScopes)); err != nil {
return fmt.Errorf("error setting authorization_scopes: %s", err)
}

return nil
}

Expand Down Expand Up @@ -229,6 +244,32 @@ func resourceAwsApiGatewayMethodUpdate(d *schema.ResourceData, meta interface{})
})
}

if d.HasChange("authorization_scopes") {
old, new := d.GetChange("authorization_scopes")
path := "/authorizationScopes"

os := old.(*schema.Set)
ns := new.(*schema.Set)

additionList := ns.Difference(os)
for _, v := range additionList.List() {
operations = append(operations, &apigateway.PatchOperation{
Op: aws.String("add"),
Path: aws.String(path),
Value: aws.String(v.(string)),
})
}

removalList := os.Difference(ns)
for _, v := range removalList.List() {
operations = append(operations, &apigateway.PatchOperation{
Op: aws.String("remove"),
Path: aws.String(path),
Value: aws.String(v.(string)),
})
}
}

if d.HasChange("api_key_required") {
operations = append(operations, &apigateway.PatchOperation{
Op: aws.String("replace"),
Expand Down
213 changes: 212 additions & 1 deletion aws/resource_aws_api_gateway_method_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,52 @@ func TestAccAWSAPIGatewayMethod_customauthorizer(t *testing.T) {
})
}

func TestAccAWSAPIGatewayMethod_cognitoauthorizer(t *testing.T) {
var conf apigateway.Method
rInt := acctest.RandInt()

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSAPIGatewayMethodDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSAPIGatewayMethodConfigWithCognitoAuthorizer(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSAPIGatewayMethodExists("aws_api_gateway_method.test", &conf),
testAccCheckAWSAPIGatewayMethodAttributes(&conf),
resource.TestCheckResourceAttr(
"aws_api_gateway_method.test", "http_method", "GET"),
resource.TestCheckResourceAttr(
"aws_api_gateway_method.test", "authorization", "COGNITO_USER_POOLS"),
resource.TestMatchResourceAttr(
"aws_api_gateway_method.test", "authorizer_id", regexp.MustCompile("^[a-z0-9]{6}$")),
resource.TestCheckResourceAttr(
"aws_api_gateway_method.test", "request_models.application/json", "Error"),
resource.TestCheckResourceAttr(
"aws_api_gateway_method.test", "authorization_scopes.#", "2"),
),
},

{
Config: testAccAWSAPIGatewayMethodConfigWithCognitoAuthorizerUpdate(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSAPIGatewayMethodExists("aws_api_gateway_method.test", &conf),
testAccCheckAWSAPIGatewayMethodAttributesUpdate(&conf),
resource.TestCheckResourceAttr(
"aws_api_gateway_method.test", "authorization", "COGNITO_USER_POOLS"),
resource.TestMatchResourceAttr(
"aws_api_gateway_method.test", "authorizer_id", regexp.MustCompile("^[a-z0-9]{6}$")),
resource.TestCheckResourceAttr(
"aws_api_gateway_method.test", "request_models.application/json", "Error"),
resource.TestCheckResourceAttr(
"aws_api_gateway_method.test", "authorization_scopes.#", "3"),
),
},
},
})
}

func TestAccAWSAPIGatewayMethod_customrequestvalidator(t *testing.T) {
var conf apigateway.Method
rInt := acctest.RandInt()
Expand Down Expand Up @@ -130,7 +176,7 @@ func testAccCheckAWSAPIGatewayMethodAttributes(conf *apigateway.Method) resource
if *conf.HttpMethod != "GET" {
return fmt.Errorf("Wrong HttpMethod: %q", *conf.HttpMethod)
}
if *conf.AuthorizationType != "NONE" && *conf.AuthorizationType != "CUSTOM" {
if *conf.AuthorizationType != "NONE" && *conf.AuthorizationType != "CUSTOM" && *conf.AuthorizationType != "COGNITO_USER_POOLS" {
return fmt.Errorf("Wrong Authorization: %q", *conf.AuthorizationType)
}

Expand Down Expand Up @@ -337,6 +383,171 @@ resource "aws_api_gateway_method" "test" {
}`, rInt, rInt, rInt, rInt, rInt)
}

func testAccAWSAPIGatewayMethodConfigWithCognitoAuthorizer(rInt int) string {
return fmt.Sprintf(`
resource "aws_api_gateway_rest_api" "test" {
name = "tf-acc-test-cognito-auth-%d"
}

resource "aws_iam_role" "invocation_role" {
name = "tf_acc_api_gateway_auth_invocation_role-%d"
path = "/"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}

resource "aws_iam_role" "iam_for_lambda" {
name = "tf_acc_iam_for_lambda_api_gateway_authorizer-%d"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}

resource "aws_cognito_user_pool" "pool" {
name = "tf-acc-test-cognito-pool-%d"
}


resource "aws_api_gateway_authorizer" "test" {
name = "tf-acc-test-cognito-authorizer"
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
identity_source = "method.request.header.Authorization"
provider_arns = ["${aws_cognito_user_pool.pool.arn}"]
type = "COGNITO_USER_POOLS"
}

resource "aws_api_gateway_resource" "test" {
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
parent_id = "${aws_api_gateway_rest_api.test.root_resource_id}"
path_part = "test"
}

resource "aws_api_gateway_method" "test" {
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
resource_id = "${aws_api_gateway_resource.test.id}"
http_method = "GET"
authorization = "COGNITO_USER_POOLS"
authorizer_id = "${aws_api_gateway_authorizer.test.id}"
authorization_scopes = ["test.read", "test.write"]

request_models = {
"application/json" = "Error"
}

request_parameters = {
"method.request.header.Content-Type" = false
"method.request.querystring.page" = true
}
}`, rInt, rInt, rInt, rInt)
}

func testAccAWSAPIGatewayMethodConfigWithCognitoAuthorizerUpdate(rInt int) string {
return fmt.Sprintf(`
resource "aws_api_gateway_rest_api" "test" {
name = "tf-acc-test-cognito-auth-%d"
}

resource "aws_iam_role" "invocation_role" {
name = "tf_acc_api_gateway_auth_invocation_role-%d"
path = "/"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}

resource "aws_iam_role" "iam_for_lambda" {
name = "tf_acc_iam_for_lambda_api_gateway_authorizer-%d"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}

resource "aws_cognito_user_pool" "pool" {
name = "tf-acc-test-cognito-pool-%d"
}


resource "aws_api_gateway_authorizer" "test" {
name = "tf-acc-test-cognito-authorizer"
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
identity_source = "method.request.header.Authorization"
provider_arns = ["${aws_cognito_user_pool.pool.arn}"]
type = "COGNITO_USER_POOLS"
}

resource "aws_api_gateway_resource" "test" {
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
parent_id = "${aws_api_gateway_rest_api.test.root_resource_id}"
path_part = "test"
}

resource "aws_api_gateway_method" "test" {
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
resource_id = "${aws_api_gateway_resource.test.id}"
http_method = "GET"
authorization = "COGNITO_USER_POOLS"
authorizer_id = "${aws_api_gateway_authorizer.test.id}"
authorization_scopes = ["test.read", "test.write", "test.delete"]

request_models = {
"application/json" = "Error"
}

request_parameters = {
"method.request.querystring.page" = false
}
}`, rInt, rInt, rInt, rInt)
}

func testAccAWSAPIGatewayMethodConfig(rInt int) string {
return fmt.Sprintf(`
resource "aws_api_gateway_rest_api" "test" {
Expand Down
5 changes: 3 additions & 2 deletions website/docs/r/api_gateway_method.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,15 @@ The following arguments are supported:
* `rest_api_id` - (Required) The ID of the associated REST API
* `resource_id` - (Required) The API resource ID
* `http_method` - (Required) The HTTP Method (`GET`, `POST`, `PUT`, `DELETE`, `HEAD`, `OPTIONS`, `ANY`)
* `authorization` - (Required) The type of authorization used for the method (`NONE`, `CUSTOM`, `AWS_IAM`)
* `authorizer_id` - (Optional) The authorizer id to be used when the authorization is `CUSTOM`
* `authorization` - (Required) The type of authorization used for the method (`NONE`, `CUSTOM`, `AWS_IAM`, `COGNITO_USER_POOLS`)
* `authorizer_id` - (Optional) The authorizer id to be used when the authorization is `CUSTOM` or `COGNITO_USER_POOLS`
* `api_key_required` - (Optional) Specify if the method requires an API key
* `request_models` - (Optional) A map of the API models used for the request's content type
where key is the content type (e.g. `application/json`)
and value is either `Error`, `Empty` (built-in models) or `aws_api_gateway_model`'s `name`.
* `request_validator_id` - (Optional) The ID of a `aws_api_gateway_request_validator`
* `request_parameters` - (Optional) A map of request query string parameters and headers that should be passed to the integration.
* `authorization_scopes` - (Optional) The authorization scopes used when the authorization is `COGNITO_USER_POOLS`
For example:
```hcl
request_parameters = {
Expand Down