From 950afbdd23103c973f55bb23a03dfd9a10ea338c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Antonio=20Reyes?= Date: Fri, 8 Sep 2023 16:01:13 -0300 Subject: [PATCH] update README with docs regarding App Oauth token usage --- README.md | 16 ++- pagerduty/config.go | 2 +- pagerduty/provider.go | 4 +- pagerduty/provider_test.go | 185 +++++++++++++++++++++++++++---- website/docs/index.html.markdown | 56 +++++++++- 5 files changed, 229 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 4d54a0c62..e6f18c501 100644 --- a/README.md +++ b/README.md @@ -201,14 +201,12 @@ PAGERDUTY_ACC_SERVICE_INTEGRATION_GENERIC_EMAIL_NO_FILTERS="user@.p PAGERDUTY_ACC_INCIDENT_CUSTOM_FIELDS=1 make testacc TESTARGS="-run PagerDutyIncidentCustomField" PAGERDUTY_ACC_LICENSE_NAME="Full User" make testacc TESTARGS="-run DataSourcePagerDutyLicense_Basic" PAGERDUTY_ACC_SCHEDULE_USED_BY_EP_W_1_LAYER=1 make testacc TESTARGS="-run PagerDutyScheduleWithTeams_EscalationPolicyDependantWithOneLayer" -PAGERDUTY_ACC_PROVIDER_SCOPED_OAUTH=1 make testacc TESTARGS="-run PagerDutyProviderScopedOauthTokenAuthentication_Basic" ``` -| Variable Name | Feature Set | -|--------------------------------------------------------------|--------------------------------------| -| `PAGERDUTY_ACC_INCIDENT_WORKFLOWS` | Incident Workflows | -| `PAGERDUTY_ACC_SERVICE_INTEGRATION_GENERIC_EMAIL_NO_FILTERS` | Service Integration | -| `PAGERDUTY_ACC_INCIDENT_CUSTOM_FIELDS` | Custom Fields | -| `PAGERDUTY_ACC_LICENSE_NAME` | Licenses | -| `PAGERDUTY_ACC_SCHEDULE_USED_BY_EP_W_1_LAYER` | Schedule | -| `PAGERDUTY_ACC_PROVIDER_SCOPED_OAUTH` | Provider Scoped Oauth Authentication | +| Variable Name | Feature Set | +|--------------------------------------------------------------|---------------------| +| `PAGERDUTY_ACC_INCIDENT_WORKFLOWS` | Incident Workflows | +| `PAGERDUTY_ACC_SERVICE_INTEGRATION_GENERIC_EMAIL_NO_FILTERS` | Service Integration | +| `PAGERDUTY_ACC_INCIDENT_CUSTOM_FIELDS` | Custom Fields | +| `PAGERDUTY_ACC_LICENSE_NAME` | Licenses | +| `PAGERDUTY_ACC_SCHEDULE_USED_BY_EP_W_1_LAYER` | Schedule | diff --git a/pagerduty/config.go b/pagerduty/config.go index 089c05043..4dfc3454a 100644 --- a/pagerduty/config.go +++ b/pagerduty/config.go @@ -64,7 +64,7 @@ func (c *Config) Client() (*pagerduty.Client, error) { } // Validate that the PagerDuty token is set - if c.Token == "" && *c.APITokenType == pagerduty.AuthTokenTypeAPIToken { + if c.Token == "" && c.APITokenType != nil && *c.APITokenType == pagerduty.AuthTokenTypeAPIToken { return nil, fmt.Errorf(invalidCreds) } diff --git a/pagerduty/provider.go b/pagerduty/provider.go index 34c16b7fc..ef6b53fb2 100644 --- a/pagerduty/provider.go +++ b/pagerduty/provider.go @@ -251,12 +251,14 @@ func expandAppOauthTokenParams(v interface{}) *persistentconfig.AppOauthScopedTo return aotp } +var validationAuthMethodConfigWarning = "PagerDuty Provider has been set to authenticate API calls utilizing API token and App Oauth token at same time, in this scenario the use of App Oauth token is prioritised over API token authentication configuration. It is recommended to explicitely set just one authentication method.\nWe also suggest you to check your environment variables in case `token` being automatically read by Provider configuration through `PAGERDUTY_TOKEN` environment variable." + func validateAuthMethodConfig(data *schema.ResourceData) error { _, isSetAPIToken := data.GetOk("token") _, isSetUseAppOauthScopedToken := data.GetOk("use_app_oauth_scoped_token") if isSetUseAppOauthScopedToken && isSetAPIToken { - return fmt.Errorf("PagerDuty Provider has been set to authenticate API calls utilizing API token and App Oauth token at same time, in this scenario the use of App Oauth token is prioritised over API token authentication configuration. It is recommended to explicitely set just one authentication method.\nWe also suggest you to check your environment variables in case `token` being automatically read by Provider configuration through `PAGERDUTY_TOKEN` environment variable.") + return fmt.Errorf(validationAuthMethodConfigWarning) } return nil diff --git a/pagerduty/provider_test.go b/pagerduty/provider_test.go index 16e7b72ae..985e78a68 100644 --- a/pagerduty/provider_test.go +++ b/pagerduty/provider_test.go @@ -40,44 +40,197 @@ func TestProviderImpl(t *testing.T) { var _ *schema.Provider = Provider() } -func TestAccPagerDutyProviderScopedOauthTokenAuthentication_Basic(t *testing.T) { - team := fmt.Sprintf("tf-%s", acctest.RandString(5)) +func TestAccPagerDutyProviderAuthMethods_Basic(t *testing.T) { + username := fmt.Sprintf("tf-%s", acctest.RandString(5)) + email := fmt.Sprintf("%s@foo.test", username) + escalationPolicy := fmt.Sprintf("tf-%s", acctest.RandString(5)) + service := fmt.Sprintf("tf-%s", acctest.RandString(5)) + serviceUpdated := fmt.Sprintf("tf-%s", acctest.RandString(5)) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) - testAccPreCheckProviderScopedOauthTokenAuthentication(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckPagerDutyTeamDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckPagerDutyProviderAuthenticationConfig(team, "scoped_oauth_token"), + Config: testAccCheckPagerDutyProviderAuthWithAPITokenConfig(username, email, escalationPolicy, service), Check: resource.ComposeTestCheckFunc( - testAccCheckPagerDutyTeamExists("pagerduty_team.foo"), + testAccCheckPagerDutyServiceExists("pagerduty_service.foo"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "name", service), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "description", "foo"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "auto_resolve_timeout", "1800"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "acknowledgement_timeout", "1800"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "alert_creation", "create_incidents"), + resource.TestCheckNoResourceAttr( + "pagerduty_service.foo", "alert_grouping"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "alert_grouping_timeout", "null"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "incident_urgency_rule.#", "1"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "incident_urgency_rule.0.urgency", "high"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "incident_urgency_rule.0.type", "constant"), + resource.TestCheckResourceAttrSet( + "pagerduty_service.foo", "html_url"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "type", "service"), ), }, { - Config: testAccCheckPagerDutyProviderAuthenticationConfig(team, "use_app_credentials"), + Config: testAccCheckPagerDutyProviderAuthWithAppOauthScopedTokenConfig(username, email, escalationPolicy, serviceUpdated), Check: resource.ComposeTestCheckFunc( - testAccCheckPagerDutyTeamExists("pagerduty_team.foo"), + testAccCheckPagerDutyServiceExists("pagerduty_service.foo"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "name", serviceUpdated), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "description", "bar"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "auto_resolve_timeout", "3600"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "acknowledgement_timeout", "3600"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "alert_creation", "create_incidents"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "incident_urgency_rule.#", "1"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "incident_urgency_rule.0.urgency", "high"), + resource.TestCheckResourceAttr( + "pagerduty_service.foo", "incident_urgency_rule.0.type", "constant"), ), }, }, }) } -func testAccCheckPagerDutyProviderAuthenticationConfig(team, apiTokenType string) string { +func testAccCheckPagerDutyProviderAuthWithAPITokenConfig(username, email, escalationPolicy, service string) string { return fmt.Sprintf(` +resource "pagerduty_user" "foo" { + name = "%s" + email = "%s" + color = "green" + role = "user" + job_title = "foo" + description = "foo" +} + +resource "pagerduty_escalation_policy" "foo" { + name = "%s" + description = "bar" + num_loops = 2 + rule { + escalation_delay_in_minutes = 10 + target { + type = "user_reference" + id = pagerduty_user.foo.id + } + } +} +resource "pagerduty_service" "foo" { + name = "%s" + description = "foo" + auto_resolve_timeout = 1800 + acknowledgement_timeout = 1800 + escalation_policy = pagerduty_escalation_policy.foo.id + alert_creation = "create_incidents" +} +`, username, email, escalationPolicy, service) +} + +func testAccCheckPagerDutyProviderAuthWithAppOauthScopedTokenConfig(username, email, escalationPolicy, service string) string { + return fmt.Sprintf(` provider "pagerduty" { - api_token_type = "%[2]s" + token = "" + use_app_oauth_scoped_token {} } -resource "pagerduty_team" "foo" { - name = "%[1]s" - description = "foo created with api token type of %[2]s" -}`, team, apiTokenType) +resource "pagerduty_user" "foo" { + name = "%s" + email = "%s" + color = "green" + role = "user" + job_title = "foo" + description = "foo" +} + +resource "pagerduty_escalation_policy" "foo" { + name = "%s" + description = "bar" + num_loops = 2 + + rule { + escalation_delay_in_minutes = 10 + target { + type = "user_reference" + id = pagerduty_user.foo.id + } + } +} + +resource "pagerduty_service" "foo" { + name = "%s" + description = "bar" + auto_resolve_timeout = 3600 + acknowledgement_timeout = 3600 + + escalation_policy = pagerduty_escalation_policy.foo.id + incident_urgency_rule { + type = "constant" + urgency = "high" + } +} +`, username, email, escalationPolicy, service) +} +func testAccCheckPagerDutyProviderAuthWithMultipleMethodsConfig(username, email, escalationPolicy, service string) string { + return fmt.Sprintf(` +provider "pagerduty" { + use_app_oauth_scoped_token {} +} + +resource "pagerduty_user" "foo" { + name = "%s" + email = "%s" + color = "green" + role = "user" + job_title = "foo" + description = "foo" +} + +resource "pagerduty_escalation_policy" "foo" { + name = "%s" + description = "bar" + num_loops = 2 + + rule { + escalation_delay_in_minutes = 10 + target { + type = "user_reference" + id = pagerduty_user.foo.id + } + } +} + +resource "pagerduty_service" "foo" { + name = "%s" + description = "bar" + auto_resolve_timeout = 3600 + acknowledgement_timeout = 3600 + + escalation_policy = pagerduty_escalation_policy.foo.id + incident_urgency_rule { + type = "constant" + urgency = "high" + } +} +`, username, email, escalationPolicy, service) } func testAccPreCheck(t *testing.T) { @@ -94,12 +247,6 @@ func testAccPreCheck(t *testing.T) { } } -func testAccPreCheckProviderScopedOauthTokenAuthentication(t *testing.T) { - if v := os.Getenv("PAGERDUTY_ACC_PROVIDER_SCOPED_OAUTH"); v == "" { - t.Skip("PAGERDUTY_ACC_PROVIDER_SCOPED_OAUTH not set. Skipping Provider Scoped Oauth-related test") - } -} - // timeNowInLoc returns the current time in the given location. // If an error occurs when trying to load the location, we just return the current local time. func timeNowInLoc(name string) time.Time { diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index 805b5069b..b98bc3fb4 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -20,7 +20,7 @@ terraform { required_providers { pagerduty = { source = "pagerduty/pagerduty" - version = "2.2.1" + version = ">= 2.2.1" } } } @@ -52,12 +52,60 @@ resource "pagerduty_team_membership" "earline_engineering" { The following arguments are supported: -* `token` - (Required) The v2 authorization token. It can also be sourced from the PAGERDUTY_TOKEN environment variable. See [API Documentation](https://developer.pagerduty.com/docs/ZG9jOjExMDI5NTUx-authentication)for more information. -* `user_token` - (Optional) The v2 user level authorization token. It can also be sourced from the PAGERDUTY_USER_TOKEN environment variable. See [API Documentation](https://developer.pagerduty.com/docs/ZG9jOjExMDI5NTUx-authentication) for more information. +* `token` - (Optional) The v2 authorization token. It can also be sourced from the `PAGERDUTY_TOKEN` environment variable. See [API Documentation](https://developer.pagerduty.com/docs/ZG9jOjExMDI5NTUx-authentication)for more information. +* `user_token` - (Optional) The v2 user level authorization token. It can also be sourced from the `PAGERDUTY_USER_TOKEN` environment variable. See [API Documentation](https://developer.pagerduty.com/docs/ZG9jOjExMDI5NTUx-authentication) for more information. +* `use_app_oauth_scoped_token` - (Optional) Defines the configuration needed for making use of [App Oauth Scoped API token](https://developer.pagerduty.com/docs/e518101fde5f3-obtaining-an-app-o-auth-token) for authenticating API calls. * `skip_credentials_validation` - (Optional) Skip validation of the token against the PagerDuty API. -* `service_region` - (Optional) The PagerDuty service region to use. Default to empty (uses US region). Supported value: `eu`. +* `service_region` - (Optional) The PagerDuty service region to use. Default to empty (uses US region). Supported value: `eu`. This setting also affects configuration of `use_app_oauth_scoped_token` for setting Region of *App Oauth token credentials*. * `api_url_override` - (Optional) It can be used to set a custom proxy endpoint as PagerDuty client api url overriding `service_region` setup. +The `use_app_oauth_scoped_token` block contains the following arguments: + +* `pd_client_id` - (Required) An identifier issued when the Scoped OAuth client was added to a PagerDuty App. It can also be sourced from the `PAGERDUTY_CLIENT_ID` environment variable. +* `pd_client_secret` - (Required) A secret issued when the Scoped OAuth client was added to a PagerDuty App. It can also be sourced from the `PAGERDUTY_CLIENT_SECRET` environment variable. +* `pd_subdomain` - (Required) Your PagerDuty account subdomain; i.e: If the *URL* shown by the Browser when you are in your PagerDuty account is some like: https://acme.pagerudty.com, then your PagerDuty subdomain is `acme`. It can also be sourced from the `PAGERDUTY_SUBDOMAIN` environment variable. + +## Example using App Oauth scoped token + +```hcl +# Configure the PagerDuty provider +terraform { + required_providers { + pagerduty = { + source = "pagerduty/pagerduty" + version = ">= 3.0.0" # Mind the supported Provider version + } + } +} + +provider "pagerduty" { + # Configure use of App Oauth scoped token + use_app_oauth_scoped_token { + pd_client_id = var.pd_client_id + pd_client_secret = var.pd_client_secret + pd_subdomain = var.pd_subdomain + } +} + +# Create a PagerDuty team +resource "pagerduty_team" "engineering" { + name = "Engineering" + description = "All engineering" +} + +# Create a PagerDuty user +resource "pagerduty_user" "earline" { + name = "Earline Greenholt" + email = "125.greenholt.earline@graham.name" +} + +# Create a team membership +resource "pagerduty_team_membership" "earline_engineering" { + user_id = pagerduty_user.earline.id + team_id = pagerduty_team.engineering.id +} +``` + ## Debugging Provider Output Using Logs In addition to the [log levels provided by Terraform](https://developer.hashicorp.com/terraform/internals/debugging), namely `TRACE`, `DEBUG`, `INFO`, `WARN`, and `ERROR` (in descending order of verbosity), the PagerDuty Provider introduces an extra level called `SECURE`. This level offers verbosity similar to Terraform's debug logging level, specifically for the output of API calls and HTTP request/response logs. The key difference is that API keys within the request's Authorization header will be obfuscated, revealing only the last four characters. An example is provided below: