diff --git a/google-beta/resource_monitoring_notification_channel.go b/google-beta/resource_monitoring_notification_channel.go index 23538b7501e..2ce554c69e1 100644 --- a/google-beta/resource_monitoring_notification_channel.go +++ b/google-beta/resource_monitoring_notification_channel.go @@ -313,8 +313,53 @@ func resourceMonitoringNotificationChannelImport(d *schema.ResourceData, meta in return []*schema.ResourceData{d}, nil } +// Some labels are obfuscated for monitoring channels +// e.g. if the value is "SECRET", the server will return "**CRET" +// This method checks to see if the value read from the server looks like +// the obfuscated version of the state value. If so, it will just use the state +// value to avoid permadiff. func flattenMonitoringNotificationChannelLabels(v interface{}, d *schema.ResourceData) interface{} { - return v + if v == nil { + return v + } + readLabels := v.(map[string]interface{}) + + stateLabelsRaw, ok := d.GetOk("labels") + if !ok { + return v + } + stateLabels := stateLabelsRaw.(map[string]interface{}) + + for k, serverV := range readLabels { + stateV, ok := stateLabels[k] + if !ok { + continue + } + useStateV := isMonitoringNotificationChannelLabelsObfuscated(serverV.(string), stateV.(string)) + if useStateV { + readLabels[k] = stateV.(string) + } + } + return readLabels +} + +func isMonitoringNotificationChannelLabelsObfuscated(serverLabel, stateLabel string) bool { + if stateLabel == serverLabel { + return false + } + + if len(stateLabel) != len(serverLabel) { + return false + } + + // Check if value read from GCP has either the same character or replaced + // it with '*'. + for i := 0; i < len(stateLabel); i++ { + if serverLabel[i] != '*' && stateLabel[i] != serverLabel[i] { + return false + } + } + return true } func flattenMonitoringNotificationChannelName(v interface{}, d *schema.ResourceData) interface{} { diff --git a/google-beta/resource_monitoring_notification_channel_test.go b/google-beta/resource_monitoring_notification_channel_test.go index 3d26c8cb7af..9bbf366ba04 100644 --- a/google-beta/resource_monitoring_notification_channel_test.go +++ b/google-beta/resource_monitoring_notification_channel_test.go @@ -7,6 +7,27 @@ import ( "github.com/hashicorp/terraform/helper/resource" ) +func TestMonitoringNotificationChannel_labelsObfuscated(t *testing.T) { + testCases := map[string]struct { + serverV string + expected bool + }{ + "": {"", false}, + "foo": {"foo", false}, + "value": {"diffValue", false}, + "charcnt8": {"****diff", false}, + "foobar": {"***bar", true}, + "SECRET": {"**CRET", true}, + } + + for stateV, testCase := range testCases { + result := isMonitoringNotificationChannelLabelsObfuscated(testCase.serverV, stateV) + if result != testCase.expected { + t.Errorf("expected state value %q and server value %q to return obfuscated=%t, got %t", stateV, testCase.serverV, testCase.expected, result) + } + } +} + func TestAccMonitoringNotificationChannel_update(t *testing.T) { t.Parallel() diff --git a/website/docs/r/monitoring_notification_channel.html.markdown b/website/docs/r/monitoring_notification_channel.html.markdown index 913f3c1aa83..6f1fae3f185 100644 --- a/website/docs/r/monitoring_notification_channel.html.markdown +++ b/website/docs/r/monitoring_notification_channel.html.markdown @@ -71,7 +71,18 @@ The following arguments are supported: * `labels` - (Optional) - Configuration fields that define the channel and its behavior. The permissible and required labels are specified in the NotificationChannelDescriptor.labels of the NotificationChannelDescriptor corresponding to the type field. + Configuration fields that define the channel and its behavior. The + permissible and required labels are specified in the + NotificationChannelDescriptor corresponding to the type field. + **Note**: Some NotificationChannelDescriptor labels are + sensitive and the API will return an partially-obfuscated value. + For example, for `"type": "slack"` channels, an `auth_token` + label with value "SECRET" will be obfuscated as "**CRET". In order + to avoid a diff, Terraform will use the state value if it appears + that the obfuscated value matches the state value in + length/unobfuscated characters. However, Terraform will not detect a + a diff if the obfuscated portion of the value was changed outside of + Terraform. * `user_labels` - (Optional)