diff --git a/auth0/provider.go b/auth0/provider.go index 99b0549a..e881da68 100644 --- a/auth0/provider.go +++ b/auth0/provider.go @@ -62,6 +62,7 @@ func init() { "auth0_role": newRole(), "auth0_log_stream": newLogStream(), "auth0_branding": newBranding(), + "auth0_guardian": newGuardian(), }, ConfigureFunc: Configure, } diff --git a/auth0/resource_auth0_guardian.go b/auth0/resource_auth0_guardian.go new file mode 100644 index 00000000..45b3a65c --- /dev/null +++ b/auth0/resource_auth0_guardian.go @@ -0,0 +1,328 @@ +package auth0 + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "gopkg.in/auth0.v5/management" +) + +func newGuardian() *schema.Resource { + return &schema.Resource{ + + Create: createGuardian, + Read: readGuardian, + Update: updateGuardian, + Delete: deleteGuardian, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "policy": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "all-applications", + "confidence-score", + "never", + }, false), + }, + "phone": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + MinItems: 0, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "provider": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "auth0", + "twilio", + "phone-message-hook", + }, false), + }, + "message_types": { + Type: schema.TypeList, + Required: true, + + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "options": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + MinItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enrollment_message": { + Type: schema.TypeString, + Optional: true, + }, + "verification_message": { + Type: schema.TypeString, + Optional: true, + }, + "from": { + Type: schema.TypeString, + Optional: true, + }, + "messaging_service_sid": { + Type: schema.TypeString, + Optional: true, + }, + "auth_token": { + Type: schema.TypeString, + Sensitive: true, + Optional: true, + }, + "sid": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + }, + } +} +func createGuardian(d *schema.ResourceData, m interface{}) error { + d.SetId(resource.UniqueId()) + return updateGuardian(d, m) +} + +func deleteGuardian(d *schema.ResourceData, m interface{}) error { + api := m.(*management.Management) + api.Guardian.MultiFactor.Phone.Enable(false) + d.SetId("") + return nil +} +func updateGuardian(d *schema.ResourceData, m interface{}) (err error) { + api := m.(*management.Management) + + if d.HasChange("policy") { + p := d.Get("policy").(string) + if p == "never" { + //Passing empty array to set it to the "never" policy. + err = api.Guardian.MultiFactor.UpdatePolicy(&management.MultiFactorPolicies{}) + } else { + err = api.Guardian.MultiFactor.UpdatePolicy(&management.MultiFactorPolicies{p}) + } + } + //TODO: Extend for other MFA types + ok, err := factorShouldBeUpdated(d, "phone") + if err != nil { + return err + } + if ok { + api.Guardian.MultiFactor.Phone.Enable(true) + if err := configurePhone(d, api); err != nil { + return err + } + } else { + api.Guardian.MultiFactor.Phone.Enable(false) + } + return readGuardian(d, m) +} + +func configurePhone(d *schema.ResourceData, api *management.Management) (err error) { + + md := make(MapData) + List(d, "phone").Elem(func(d ResourceData) { + md.Set("provider", String(d, "provider", HasChange())) + md.Set("message_types", Slice(d, "message_types", HasChange())) + md.Set("options", List(d, "options")) + switch *String(d, "provider") { + case "twilio": + err = updateTwilioOptions(md["options"].(Iterator), api) + case "auth0": + err = updateAuth0Options(md["options"].(Iterator), api) + } + }) + + if s, ok := md.GetOk("provider"); ok { + if err := api.Guardian.MultiFactor.Phone.UpdateProvider(&management.MultiFactorProvider{Provider: s.(*string)}); err != nil { + return err + } + } + + mtypes := typeAssertToStringArray(Slice(md, "message_types")) + if mtypes != nil { + if err := api.Guardian.MultiFactor.Phone.UpdateMessageTypes(&management.PhoneMessageTypes{MessageTypes: mtypes}); err != nil { + return err + } + } + + return err +} + +func updateAuth0Options(opts Iterator, api *management.Management) (err error) { + opts.Elem(func(d ResourceData) { + err = api.Guardian.MultiFactor.SMS.UpdateTemplate(&management.MultiFactorSMSTemplate{ + EnrollmentMessage: String(d, "enrollment_message"), + VerificationMessage: String(d, "verification_message"), + }) + }) + if err != nil { + return err + } + return nil +} + +func updateTwilioOptions(opts Iterator, api *management.Management) error { + md := make(map[string]*string) + opts.Elem(func(d ResourceData) { + md["sid"] = String(d, "sid") + md["auth_token"] = String(d, "auth_token") + md["from"] = String(d, "from") + md["messaging_service_sid"] = String(d, "messaging_service_sid") + md["enrollment_message"] = String(d, "enrollment_message") + md["verification_message"] = String(d, "verification_message") + }) + + err := api.Guardian.MultiFactor.SMS.UpdateTwilio(&management.MultiFactorProviderTwilio{ + From: md["from"], + MessagingServiceSid: md["messaging_service_sid"], + AuthToken: md["auth_token"], + SID: md["sid"], + }) + if err != nil { + return err + } + err = api.Guardian.MultiFactor.SMS.UpdateTemplate(&management.MultiFactorSMSTemplate{ + EnrollmentMessage: md["enrollment_message"], + VerificationMessage: md["verification_message"], + }) + if err != nil { + return err + } + return nil +} + +func readGuardian(d *schema.ResourceData, m interface{}) error { + api := m.(*management.Management) + mt, err := api.Guardian.MultiFactor.Phone.MessageTypes() + if err != nil { + return err + } + phoneData := make(map[string]interface{}) + phoneData["message_types"] = mt.MessageTypes + prv, err := api.Guardian.MultiFactor.Phone.Provider() + if err != nil { + return err + } + phoneData["provider"] = prv.Provider + + p, err := api.Guardian.MultiFactor.Policy() + if err != nil { + return err + } + if len(*p) == 0 { + d.Set("policy", "never") + } else { + err = d.Set("policy", (*p)[0]) + } + var md map[string]interface{} + switch *prv.Provider { + case "twilio": + md, err = flattenTwilioOptions(api) + case "auth0": + md, err = flattenAuth0Options(api) + } + if err != nil { + return err + } + ok, err := factorShouldBeUpdated(d, "phone") + if err != nil { + return err + } + if ok { + phoneData["options"] = []interface{}{md} + err = d.Set("phone", []interface{}{phoneData}) + } else { + d.Set("phone", nil) + } + if err != nil { + return err + } + return nil +} + +func hasBlockPresentInNewState(d *schema.ResourceData, factor string) bool { + if ok := d.HasChange(factor); ok { + _, n := d.GetChange(factor) + newState := n.([]interface{}) + return len(newState) > 0 + } + return false +} + +func flattenAuth0Options(api *management.Management) (map[string]interface{}, error) { + md := make(map[string]interface{}) + t, err := api.Guardian.MultiFactor.SMS.Template() + if err != nil { + return nil, err + } + md["enrollment_message"] = t.EnrollmentMessage + md["verification_message"] = t.VerificationMessage + return md, nil +} + +func flattenTwilioOptions(api *management.Management) (map[string]interface{}, error) { + md := make(map[string]interface{}) + t, err := api.Guardian.MultiFactor.SMS.Template() + if err != nil { + return nil, err + } + md["enrollment_message"] = t.EnrollmentMessage + md["verification_message"] = t.VerificationMessage + tw, err := api.Guardian.MultiFactor.SMS.Twilio() + if err != nil { + return nil, err + } + md["auth_token"] = tw.AuthToken + md["from"] = tw.From + md["messaging_service_sid"] = tw.MessagingServiceSid + md["sid"] = tw.SID + return md, nil +} + +func typeAssertToStringArray(from []interface{}) *[]string { + length := len(from) + if length < 1 { + return nil + } + stringArray := make([]string, length) + for i, v := range from { + stringArray[i] = v.(string) + } + return &stringArray +} + +func isFactorEnabled(factor string, api *management.Management) (*bool, error) { + mfs, err := api.Guardian.MultiFactor.List() + if err != nil { + return nil, err + } + for _, mf := range mfs { + if *mf.Name == factor { + return mf.Enabled, nil + } + } + return nil, fmt.Errorf("factor %s is not among the possible factors", factor) +} + +// Determines if the factor should be updated. This depends on if it is in the state, if it is about to be added to the state. +func factorShouldBeUpdated(d *schema.ResourceData, factor string) (bool, error) { + _, ok := d.GetOk(factor) + return ok || hasBlockPresentInNewState(d, factor), nil +} diff --git a/auth0/resource_auth0_guardian_test.go b/auth0/resource_auth0_guardian_test.go new file mode 100644 index 00000000..25705c34 --- /dev/null +++ b/auth0/resource_auth0_guardian_test.go @@ -0,0 +1,163 @@ +package auth0 + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "testing" +) + +func TestAccGuardian(t *testing.T) { + + resource.Test(t, resource.TestCase{ + Providers: map[string]terraform.ResourceProvider{ + "auth0": Provider(), + }, + Steps: []resource.TestStep{ + { + Config: testAccConfigureTwilio, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("auth0_guardian.foo", "policy", "all-applications"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.message_types.0", "sms"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.provider", "twilio"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.options.0.enrollment_message", "enroll foo"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.options.0.verification_message", "verify foo"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.options.0.from", "from bar"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.options.0.messaging_service_sid", "foo"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.options.0.auth_token", "bar"), + ), + }, + { + Config: testAccConfigureTwilioUpdate, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("auth0_guardian.foo", "policy", "all-applications"), + resource.TestCheckNoResourceAttr("auth0_guardian.foo", "phone"), + ), + }, + + { + Config: testAccConfigureTwilio, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("auth0_guardian.foo", "policy", "all-applications"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.message_types.0", "sms"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.provider", "twilio"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.options.0.enrollment_message", "enroll foo"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.options.0.verification_message", "verify foo"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.options.0.from", "from bar"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.options.0.messaging_service_sid", "foo"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.options.0.auth_token", "bar"), + ), + }, + + { + Config: testAccConfigureCustomPhone, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("auth0_guardian.foo", "policy", "all-applications"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.message_types.0", "sms"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.provider", "phone-message-hook"), + ), + }, + + { + Config: testAccConfigureAuth0Custom, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("auth0_guardian.foo", "policy", "all-applications"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.message_types.0", "voice"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.provider", "auth0"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.options.0.enrollment_message", "enroll foo"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.options.0.verification_message", "verify foo"), + ), + }, + + { + Config: testAccConfigureAuth0, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("auth0_guardian.foo", "policy", "all-applications"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.message_types.0", "voice"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.provider", "auth0"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.options.0.enrollment_message", "enroll foo"), + resource.TestCheckResourceAttr("auth0_guardian.foo", "phone.0.options.0.verification_message", "verify foo"), + ), + }, + + { + Config: testAccConfigureNoPhone, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("auth0_guardian.foo", "policy", "all-applications"), + resource.TestCheckNoResourceAttr("auth0_guardian.foo", "phone"), + ), + }, + }, + }) +} + +const testAccConfigureAuth0Custom = ` +resource "auth0_guardian" "foo" { + policy = "all-applications" + phone { + provider = "auth0" + message_types = ["voice"] + options { + enrollment_message = "enroll foo" + verification_message = "verify foo" + } + } +} +` + +const testAccConfigureCustomPhone = ` + +resource "auth0_guardian" "foo" { + policy = "all-applications" + phone { + provider = "phone-message-hook" + message_types = ["sms"] + options{ + } + } +} +` +const testAccConfigureTwilio = ` + +resource "auth0_guardian" "foo" { + policy = "all-applications" + phone { + provider = "twilio" + message_types = ["sms"] + options { + enrollment_message = "enroll foo" + verification_message = "verify foo" + from = "from bar" + messaging_service_sid = "foo" + auth_token = "bar" + sid = "foo" + } +} +} +` +const testAccConfigureTwilioUpdate = ` + +resource "auth0_guardian" "foo" { + policy = "all-applications" +} +` + +const testAccConfigureAuth0 = ` + +resource "auth0_guardian" "foo" { + policy = "all-applications" + phone { + provider = "auth0" + message_types = ["voice"] + options { + enrollment_message = "enroll foo" + verification_message = "verify foo" + } +} +} +` +const testAccConfigureNoPhone = ` + +resource "auth0_guardian" "foo" { + policy = "all-applications" +} +` diff --git a/docs/resources/guardian.md b/docs/resources/guardian.md new file mode 100644 index 00000000..48076ba1 --- /dev/null +++ b/docs/resources/guardian.md @@ -0,0 +1,61 @@ +--- +layout: "auth0" +page_title: "Auth0: auth0_guardian" +description: |- + With this reasource, you can configure some of the MFA options +--- + +# auth0_guardian + +Multi-factor Authentication works by requiring additional factors during the login process to prevent unauthorized access. With this resource you can configure some of +the options available for MFA. + +## Example Usage + +```hcl +resource "auth0_guardian" "default" { + policy = "all-applications" + phone { + provider = "auth0" + message_types = ["sms"] + options { + enrollment_message = "{{code}}} is your verification code for {{tenant.friendly_name}}. Please enter this code to verify your enrollment" + verification_message = "{{code}} is your verification code for {{tenant.friendly_name}}" + } + } +} +``` + +## Argument Reference + +Arguments accepted by this resource include: + +* `policy` - (Required) String. Policy to use. Available options are `never`, `all-applications` and `confidence-score. The option `confidence-score` means the trigger of MFA will be adaptive. See [Auth0 docs](https://auth0.com/docs/mfa/adaptive-mfa) +* `phone` - (Optional) List(Resource). Configuration settings for the phone MFA. For details, see [Phone](#phone). + +### Phone + +`phone` supports the following arguments: + +* `provider` - (Required) String, Case-sensitive. Provider to use, one of `auth0`, `twilio` or `phone-message-hook`. +* `message_types` - (Required) List(String). Message types to use, array of `phone` and or `voice`. Adding both to array should enable the user to choose. +* `secret_access_key` - (Optional) String, Case-sensitive. AWS Secret Key. Will always be encrypted in our database. Used only for AWS. +* `options`- (Required) List(Resource). Options for the various providers. See [Options](#options). + +### Options +`options` supports different arguments depending on the provider specificed in [Phone](#phone). + +### Auth0 +* `enrollment_message` (Optional) String. This message will be sent whenever a user enrolls a new device for the first time using MFA. Supports liquid syntax, see [Auth0 docs](https://auth0.com/docs/mfa/customize-sms-or-voice-messages). +* `verification_message` (Optional) String. This message will be sent whenever a user logs in after the enrollment. Supports liquid syntax, see [Auth0 docs](https://auth0.com/docs/mfa/customize-sms-or-voice-messages). + +### Twilio +* `enrollment_message` (Optional) String. This message will be sent whenever a user enrolls a new device for the first time using MFA. Supports liquid syntax, see [Auth0 docs](https://auth0.com/docs/mfa/customize-sms-or-voice-messages). +* `verification_message` (Optional) String. This message will be sent whenever a user logs in after the enrollment. Supports liquid syntax, see [Auth0 docs](https://auth0.com/docs/mfa/customize-sms-or-voice-messages). +* `sid`(Optional) String. +* `auth_token`(Optional) String. +* `from` (Optional) String. +* `messaging_service_sid`(Optional) String. + +### Phone message hook +Options has to be empty. Custom code has to be written in a phone message hook. See [phone message hook docs](https://auth0.com/docs/hooks/extensibility-points/send-phone-message). diff --git a/go.mod b/go.mod index 1f4b0dac..5ee2b49a 100644 --- a/go.mod +++ b/go.mod @@ -5,5 +5,5 @@ go 1.15 require ( github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/terraform-plugin-sdk v1.16.1 - gopkg.in/auth0.v5 v5.14.0 + gopkg.in/auth0.v5 v5.15.0 ) diff --git a/go.sum b/go.sum index 7eab85f5..dc239c91 100644 --- a/go.sum +++ b/go.sum @@ -145,6 +145,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -229,6 +230,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= @@ -322,6 +325,7 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= +github.com/zclconf/go-cty v1.2.1 h1:vGMsygfmeCl4Xb6OA5U5XVAaQZ69FvoG7X2jUtQujb8= github.com/zclconf/go-cty v1.2.1/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= github.com/zclconf/go-cty v1.7.1 h1:AvsC01GMhMLFL8CgEYdHGM+yLnnDOwhPAYcgTkeF0Gw= github.com/zclconf/go-cty v1.7.1/go.mod h1:VDR4+I79ubFBGm1uJac1226K5yANQFHeauxPBoP54+o= @@ -402,6 +406,7 @@ golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= @@ -450,6 +455,7 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 h1:B6caxRw+hozq68X2MY7jEpZh/cr4/aHLv9xU8Kkadrw= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= @@ -502,6 +508,7 @@ golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d h1:W07d4xkoAUSNOkOzdzXCdFGxT7o2rW4q8M34tB2i//k= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201028111035-eafbe7b904eb h1:KVWk3RW1AZlxWum4tYqegLgwJHb5oouozcGM8HfNQaw= @@ -526,6 +533,7 @@ google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0 h1:yfrXXP61wVuLb0vBcG6qaOoIoqYEzOQS8jum51jkv2w= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/api v0.34.0 h1:k40adF3uR+6x/+hO5Dh4ZFUqFp67vxvbpafFiJxl10A= google.golang.org/api v0.34.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= @@ -565,6 +573,7 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d h1:92D1fum1bJLKSdr11OJ+54YeCMCGYIygTA7R/YZxH5M= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -580,6 +589,7 @@ google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1 h1:SfXqXS5hkufcdZ/mHtYCh53P2b+92WQq/DZcKLgsFRs= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= @@ -594,8 +604,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -gopkg.in/auth0.v5 v5.14.0 h1:xgyw6nW3AyXzOiF2tkp1DtLo26DwUK2tAcydfqYUbdY= -gopkg.in/auth0.v5 v5.14.0/go.mod h1:WwEEBRaU1v8K4cpgbGOI7WogKhE7j/5dqfAtZvc79SI= +gopkg.in/auth0.v5 v5.15.0 h1:kHBw8OdNPPnlqKhOBMDcYoNWlLMsFFrpagmhcMo+bHs= +gopkg.in/auth0.v5 v5.15.0/go.mod h1:ZUc29HB1p9iYkA1ti2uz/kVL3I9vg+Hs+qFjHKub9SM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=