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

Added oidcToken to pubsub api. #1265

Merged
merged 1 commit into from
Oct 23, 2019
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
83 changes: 83 additions & 0 deletions google-beta/resource_pubsub_subscription.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,23 @@ func resourcePubsubSubscription() *schema.Resource {
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"oidc_token": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"service_account_email": {
Type: schema.TypeString,
Required: true,
},
"audience": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
},
},
},
Expand Down Expand Up @@ -449,12 +466,37 @@ func flattenPubsubSubscriptionPushConfig(v interface{}, d *schema.ResourceData)
return nil
}
transformed := make(map[string]interface{})
transformed["oidc_token"] =
flattenPubsubSubscriptionPushConfigOidcToken(original["oidcToken"], d)
transformed["push_endpoint"] =
flattenPubsubSubscriptionPushConfigPushEndpoint(original["pushEndpoint"], d)
transformed["attributes"] =
flattenPubsubSubscriptionPushConfigAttributes(original["attributes"], d)
return []interface{}{transformed}
}
func flattenPubsubSubscriptionPushConfigOidcToken(v interface{}, d *schema.ResourceData) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["service_account_email"] =
flattenPubsubSubscriptionPushConfigOidcTokenServiceAccountEmail(original["serviceAccountEmail"], d)
transformed["audience"] =
flattenPubsubSubscriptionPushConfigOidcTokenAudience(original["audience"], d)
return []interface{}{transformed}
}
func flattenPubsubSubscriptionPushConfigOidcTokenServiceAccountEmail(v interface{}, d *schema.ResourceData) interface{} {
return v
}

func flattenPubsubSubscriptionPushConfigOidcTokenAudience(v interface{}, d *schema.ResourceData) interface{} {
return v
}

func flattenPubsubSubscriptionPushConfigPushEndpoint(v interface{}, d *schema.ResourceData) interface{} {
return v
}
Expand Down Expand Up @@ -558,6 +600,13 @@ func expandPubsubSubscriptionPushConfig(v interface{}, d TerraformResourceData,
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedOidcToken, err := expandPubsubSubscriptionPushConfigOidcToken(original["oidc_token"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedOidcToken); val.IsValid() && !isEmptyValue(val) {
transformed["oidcToken"] = transformedOidcToken
}

transformedPushEndpoint, err := expandPubsubSubscriptionPushConfigPushEndpoint(original["push_endpoint"], d, config)
if err != nil {
return nil, err
Expand All @@ -575,6 +624,40 @@ func expandPubsubSubscriptionPushConfig(v interface{}, d TerraformResourceData,
return transformed, nil
}

func expandPubsubSubscriptionPushConfigOidcToken(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedServiceAccountEmail, err := expandPubsubSubscriptionPushConfigOidcTokenServiceAccountEmail(original["service_account_email"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedServiceAccountEmail); val.IsValid() && !isEmptyValue(val) {
transformed["serviceAccountEmail"] = transformedServiceAccountEmail
}

transformedAudience, err := expandPubsubSubscriptionPushConfigOidcTokenAudience(original["audience"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedAudience); val.IsValid() && !isEmptyValue(val) {
transformed["audience"] = transformedAudience
}

return transformed, nil
}

func expandPubsubSubscriptionPushConfigOidcTokenServiceAccountEmail(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandPubsubSubscriptionPushConfigOidcTokenAudience(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandPubsubSubscriptionPushConfigPushEndpoint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}
Expand Down
71 changes: 59 additions & 12 deletions google-beta/resource_pubsub_subscription_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,30 @@ func TestAccPubsubSubscription_update(t *testing.T) {
})
}

func TestAccPubsubSubscription_push(t *testing.T) {
t.Parallel()

topicFoo := fmt.Sprintf("tf-test-topic-foo-%s", acctest.RandString(10))
subscription := fmt.Sprintf("projects/%s/subscriptions/tf-test-topic-foo-%s", getTestProjectFromEnv(), acctest.RandString(10))

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckPubsubSubscriptionDestroy,
Steps: []resource.TestStep{
{
Config: testAccPubsubSubscription_push(topicFoo, subscription),
},
{
ResourceName: "google_pubsub_subscription.foo",
ImportStateId: subscription,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccPubsubSubscription_emptyTTL(topic, subscription string) string {
return fmt.Sprintf(`
resource "google_pubsub_topic" "foo" {
Expand All @@ -123,18 +147,41 @@ resource "google_pubsub_subscription" "foo" {
`, topic, subscription)
}

// TODO: Add acceptance test for push delivery.
//
// Testing push endpoints is tricky for the following reason:
// - You need a publicly accessible HTTPS server to handle POST requests in order to receive push messages.
// - The server must present a valid SSL certificate signed by a certificate authority
// - The server must be routable by DNS.
// - You also need to validate that you own the domain (or have equivalent access to the endpoint).
// - Finally, you must register the endpoint domain with the GCP project.
//
// An easy way to test this would be to create an App Engine Hello World app. With AppEngine, SSL certificate, DNS and domain registry is handled for us.
// App Engine is not yet supported by Terraform but once it is, it will provide an easy path to testing push configs.
// Another option would be to use Cloud Functions once Terraform support is added.
func testAccPubsubSubscription_push(topicFoo string, subscription string) string {
return fmt.Sprintf(`
data "google_project" "project" {}

resource "google_service_account" "pub_sub_service_account" {
account_id = "my-super-service"
}

data "google_iam_policy" "admin" {
binding {
role = "roles/projects.topics.publish"

members = [
"serviceAccount:${google_service_account.pub_sub_service_account.email}",
]
}
}

resource "google_pubsub_topic" "foo" {
name = "%s"
}

resource "google_pubsub_subscription" "foo" {
name = "%s"
topic = "${google_pubsub_topic.foo.name}"
ack_deadline_seconds = 10
push_config {
push_endpoint = "https://${data.google_project.project.project_id}.appspot.com"
oidc_token {
service_account_email = "${google_service_account.pub_sub_service_account.email}"
}
}
}
`, topicFoo, subscription)
}

func testAccPubsubSubscription_fullName(topic, subscription, label string, deadline int) string {
return fmt.Sprintf(`
Expand Down
24 changes: 24 additions & 0 deletions website/docs/r/pubsub_subscription.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,11 @@ The following arguments are supported:

The `push_config` block supports:

* `oidc_token` -
(Optional)
If specified, Pub/Sub will generate and attach an OIDC JWT token as
an Authorization header in the HTTP request for every pushed message. Structure is documented below.

* `push_endpoint` -
(Required)
A URL locating the endpoint to which messages should be pushed.
Expand Down Expand Up @@ -212,6 +217,25 @@ The `push_config` block supports:
- v1beta1: uses the push format defined in the v1beta1 Pub/Sub API.
- v1 or v1beta2: uses the push format defined in the v1 Pub/Sub API.


The `oidc_token` block supports:

* `service_account_email` -
(Required)
Service account email to be used for generating the OIDC token.
The caller (for subscriptions.create, subscriptions.patch, and
subscriptions.modifyPushConfig RPCs) must have the
iam.serviceAccounts.actAs permission for the service account.

* `audience` -
(Optional)
Audience to be used when generating OIDC token. The audience claim
identifies the recipients that the JWT is intended for. The audience
value is a single case-sensitive string. Having multiple values (array)
for the audience field is not supported. More info about the OIDC JWT
token audience here: https://tools.ietf.org/html/rfc7519#section-4.1.3
Note: if not specified, the Push endpoint URL will be used.

The `expiration_policy` block supports:

* `ttl` -
Expand Down