diff --git a/api/agent.go b/api/agent.go index 168580239..8132ff798 100644 --- a/api/agent.go +++ b/api/agent.go @@ -363,7 +363,7 @@ func NewControllerWrapper(config *loadtest.Config, controllerConfig interface{}, creds, err := getUserCredentials(config.UsersConfiguration.UsersFilePath, config) if err != nil { - return nil, err + return nil, fmt.Errorf("error getting user credentials from file: %w", err) } modAdmins := 0 @@ -373,7 +373,7 @@ func NewControllerWrapper(config *loadtest.Config, controllerConfig interface{}, err = createCustomEmoji(config) if err != nil { - return nil, err + return nil, fmt.Errorf("error creating custom emoji from config: %w", err) } mlog.Info("Custom emoji created") @@ -383,6 +383,7 @@ func NewControllerWrapper(config *loadtest.Config, controllerConfig interface{}, username := fmt.Sprintf("%s-%d", namePrefix, id) email := fmt.Sprintf("%s-%d@example.com", namePrefix, id) password := "testPass123$" + authenticationType := userentity.AuthenticationTypeMattermost if modAdmins > 0 && id%modAdmins == 0 { username = "" @@ -395,15 +396,31 @@ func NewControllerWrapper(config *loadtest.Config, controllerConfig interface{}, username = creds[id].username email = creds[id].email password = creds[id].password + + // Check if the user has a custom authentication type. Custom authentication types are + // specified by prepending the username with the authentication type followed by a colon. + // Example: "openid:user1@test.mattermost.com user1password" + // TODO: Move to util function + if usernameParts := strings.Split(username, ":"); len(usernameParts) > 1 { + authenticationType = usernameParts[0] + username = usernameParts[1] + + // Fix the email as well + if emailParts := strings.Split(email, ":"); len(emailParts) > 1 { + email = emailParts[1] + } + } } ueConfig := userentity.Config{ - ServerURL: config.ConnectionConfiguration.ServerURL, - WebSocketURL: config.ConnectionConfiguration.WebSocketURL, - Username: username, - Email: email, - Password: password, + ServerURL: config.ConnectionConfiguration.ServerURL, + WebSocketURL: config.ConnectionConfiguration.WebSocketURL, + AuthenticationType: authenticationType, + Username: username, + Email: email, + Password: password, } + store, err := memstore.New(&memstore.Config{ MaxStoredPosts: 250, MaxStoredUsers: 500, @@ -413,11 +430,11 @@ func NewControllerWrapper(config *loadtest.Config, controllerConfig interface{}, MaxStoredReactions: 10, }) if err != nil { - return nil, err + return nil, fmt.Errorf("error creating memory store: %w", err) } if err := store.SetServerVersion(serverVersion); err != nil { - return nil, err + return nil, fmt.Errorf("error setting server version: %w", err) } ueSetup := userentity.Setup{ @@ -527,7 +544,7 @@ func createCustomEmoji(config *loadtest.Config) error { } sysadmin := createSysAdmin(adminStore, config) if err := sysadmin.Login(); err != nil { - return err + return fmt.Errorf("error login as sysadmin: %w", err) } emoji := &model.Emoji{ diff --git a/config/deployer.sample.json b/config/deployer.sample.json index 5eb16b518..fb257fb47 100644 --- a/config/deployer.sample.json +++ b/config/deployer.sample.json @@ -56,6 +56,14 @@ "AmazonS3SignV2": false, "AmazonS3SSE": false }, + "ExternalAuthProviderSettings": { + "Enabled": false, + "KeycloakAdminUser": "mmadmin", + "KeycloakAdminPassword": "mmpass", + "KeycloakRealmFilePath": "", + "KeycloakDBDumpURI": "", + "GenerateUsersCount": 0 + }, "MattermostDownloadURL": "https://latest.mattermost.com/mattermost-enterprise-linux", "MattermostLicenseFile": "", "MattermostConfigPatchFile": "", diff --git a/deployment/config.go b/deployment/config.go index d3af9ef3a..7175eba84 100644 --- a/deployment/config.go +++ b/deployment/config.go @@ -51,6 +51,8 @@ type Config struct { ExternalDBSettings ExternalDBSettings // External bucket connection settings. ExternalBucketSettings ExternalBucketSettings + // ExternalAuthProviderSettings contains the settings for configuring an external auth provider. + ExternalAuthProviderSettings ExternalAuthProviderSettings // URL from where to download Mattermost release. // This can also point to a local binary path if the user wants to run loadtest // on a custom build. The path should be prefixed with "file://". In that case, @@ -87,6 +89,11 @@ type Config struct { // This can also point to a local file if prefixed with "file://". // In such case, the dump file will be uploaded to the app servers. DBDumpURI string `default:""` + // DBExtraSQL are optional URIs to SQL files containing SQL statements to be applied + // to the Mattermost database. + // The file is expected to be gzip compressed. + // This can also point to a local file if prefixed with "file://". + DBExtraSQL []string `default:"[]"` // An optional host name that will: // - Override the SiteUrl // - Point to the proxy IP via a new entry in the server's /etc/hosts file @@ -114,6 +121,8 @@ type StorageSizes struct { Job int `default:"50"` // Size, in GiB, for the storage of the elasticsearch instances ElasticSearch int `default:"20"` + // Size, in GiB, for the storage of the keycloak instances + KeyCloak int `default:"10"` } // PyroscopeSettings contains flags to enable/disable the profiling @@ -179,6 +188,43 @@ type ExternalBucketSettings struct { AmazonS3SSE bool `default:"false"` } +// ExternalAuthProviderSettings contains the necessary data +// to configure an external auth provider. +type ExternalAuthProviderSettings struct { + // Enabled is set to true if the external auth provider should be enabled. + Enabled bool `default:"false"` + // DevelopmentMode is set to true if the keycloak instance should be started in development mode. + DevelopmentMode bool `default:"true"` + // KeycloakVersion is the version of keycloak to deploy. + KeycloakVersion string `default:"24.0.2"` + // KeycloakInstanceType is the type of the EC2 instance for keycloak. + InstanceType string `default:"c7i.xlarge"` + // KeycloakAdminUser is the username of the keycloak admin interface (admin on the master realm) + KeycloakAdminUser string `default:"mmuser" validate:"notempty"` + // KeycloakAdminPassword is the password of the keycloak admin interface (admin on the master realm) + KeycloakAdminPassword string `default:"mmpass" validate:"notempty"` + // KeycloakRealmFilePath is the path to the realm file to be uploaded to the keycloak instance. + // If empty, a default realm file will be used. + KeycloakRealmFilePath string `default:""` + // KeycloakDBDumpURI + // An optional URI to a keycloak database dump file to be uploaded on environment + // creation. + // The file is expected to be gzip compressed. + // This can also point to a local file if prefixed with "file://". + KeycloakDBDumpURI string `default:""` + // GenerateUsersCount is the number of users to generate in the keycloak instance. + GenerateUsersCount int `default:"0" validate:"range:[0,)"` + // KeycloakRealmName is the name of the realm to be used in Mattermost. Must exist in the keycloak instance. + // It is used when creating users and to properly set the OpenID configuration in Mattermost. + KeycloakRealmName string `default:"mattermost"` + // KeycloakClientID is the client id to be used in Mattermost from the above realm. + // Must exist in the keycloak instance + KeycloakClientID string `default:"mattermost-openid"` + // KeycloakClientSecret is the client secret from the above realm to be used in Mattermost. + // Must exist in the keycloak instance + KeycloakClientSecret string `default:"qbdUj4dacwfa5sIARIiXZxbsBFoopTyf"` +} + // ElasticSearchSettings contains the necessary data // to configure an ElasticSearch instance to be deployed // and provisioned. diff --git a/deployment/terraform/agent.go b/deployment/terraform/agent.go index 70f9ce9b7..6347b648a 100644 --- a/deployment/terraform/agent.go +++ b/deployment/terraform/agent.go @@ -23,10 +23,8 @@ func (t *Terraform) generateLoadtestAgentConfig() (*loadtest.Config, error) { if err != nil { return nil, err } - url := t.output.Instances[0].PrivateIP + ":8065" - if t.output.HasProxy() { - url = t.output.Proxy.PrivateIP - } + + url := getServerURL(t.output, t.config) cfg.ConnectionConfiguration.ServerURL = "http://" + url cfg.ConnectionConfiguration.WebSocketURL = "ws://" + url @@ -129,6 +127,27 @@ func (t *Terraform) configureAndRunAgents(extAgent *ssh.ExtAgent) error { batch = append(batch, uploadInfo{srcData: strings.Join(splitFiles[i], "\n"), dstPath: dstUsersFilePath, msg: "Uploading list of users credentials"}) } + // If SiteURL is set, update /etc/hosts to point to the correct IP + if t.config.SiteURL != "" { + output, err := t.Output() + if err != nil { + return err + } + + // The new entry in /etc/hosts will make SiteURL point to: + // - The first instance's IP if there's a single node + // - The proxy's IP if there's more than one node + ip := output.Instances[0].PrivateIP + if output.HasProxy() { + ip = output.Proxy.PrivateIP + } + + proxyHost := fmt.Sprintf("%s %s\n", ip, t.config.SiteURL) + appHostsFile := fmt.Sprintf(appHosts, proxyHost) + + batch = append(batch, uploadInfo{srcData: appHostsFile, dstPath: "/etc/hosts", msg: "Updating /etc/hosts to point to the correct IP"}) + } + if err := uploadBatch(sshc, batch); err != nil { return fmt.Errorf("batch upload failed: %w", err) } diff --git a/deployment/terraform/assets/bindata.go b/deployment/terraform/assets/bindata.go index ad29e3ecc..65cf00745 100644 --- a/deployment/terraform/assets/bindata.go +++ b/deployment/terraform/assets/bindata.go @@ -1,15 +1,17 @@ // Code generated by go-bindata. DO NOT EDIT. // sources: // .terraform.lock.hcl (4.546kB) -// cluster.tf (20.735kB) +// cluster.tf (22.868kB) // coordinator_dashboard_tmpl.json (3.38kB) // dashboard.yaml (231B) // dashboard_data.json (40.142kB) // datasource.yaml (296B) // elasticsearch.tf (3.697kB) // es_dashboard_data.json (8.51kB) -// outputs.tf (740B) -// variables.tf (1.776kB) +// keycloak-database.sql (141B) +// mattermost-realm.json (115.155kB) +// outputs.tf (801B) +// variables.tf (2.113kB) package assets @@ -98,7 +100,7 @@ func TerraformLockHcl() (*asset, error) { return a, nil } -var _clusterTf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x3c\xfd\x93\xdb\xb6\x95\xbf\xeb\xaf\x78\x65\x3c\xb5\x7d\x63\x92\xda\xd5\x26\x71\xb6\xdd\x64\x5c\x5f\x7b\x73\x33\x49\x93\xb9\xde\x5d\xe7\x66\xbd\xc3\x01\xc1\x27\x09\x5e\x92\x40\x00\x50\x5a\xd9\xdd\xfb\xdb\x3b\x00\xc1\x0f\x51\xa4\x44\x69\x37\xfe\xe8\xd8\x9d\x6e\x24\xbc\x0f\x3c\x3c\xbc\x4f\x10\x94\x46\x29\xc9\x9c\xcb\x0c\xde\x4f\x00\x24\xfe\x5a\x30\x89\x49\x24\x24\x5f\xb1\x04\xa5\xb2\xc3\x00\x64\xad\xe0\xca\x7d\x06\x50\xbc\x90\x14\x01\xae\xc0\x5b\x12\xb5\x64\x94\x4b\x11\x92\xb5\xf2\x1c\x7c\x85\x52\x31\x9e\x1b\xf8\xff\x7f\x0f\x5f\x07\xb3\xef\x4a\xc8\xfd\xc4\xfc\xff\x7e\x32\xa9\xd8\x83\x67\xa8\xdc\xd4\x0b\x43\x02\x57\xb0\x22\x32\x20\x6b\x15\x95\x23\x13\x00\x21\xf9\x9c\xa5\xd8\x02\xb9\x11\xc3\x2a\x21\x9a\x58\x36\x0e\xdf\x03\x8f\x16\x52\x62\xae\x3d\x78\xbf\x05\xa7\x24\x4d\x51\x46\x2c\xc1\x5c\x33\xbd\xe9\x47\x5c\x6a\x2d\x3c\xf0\xb2\x4d\x24\x8a\x38\x65\x34\x62\xa2\x94\xaf\x90\xa9\x5d\xaf\xd6\x42\x5d\x86\x21\x5d\x22\xbd\x65\x22\x20\x19\x79\xc7\x73\xb2\x56\x01\xe5\x99\xd7\x08\x84\x77\x1a\x65\x4e\x52\x0f\x3c\x21\xd9\x8a\x68\xac\x39\x09\xc9\x17\x92\x64\x70\x05\xd7\x9e\x5a\x7a\x2f\xc0\xf3\xa9\xf9\x8b\x74\xc9\xe1\xfd\x9b\x37\x6f\x3c\x26\xcc\xdf\x4b\xf3\xe7\xc9\xb3\x25\x57\x3a\x27\x19\x82\xcf\x9e\x9b\x91\x7b\xef\xc6\x4c\x93\x72\x4a\xd2\x72\x7b\x6a\x49\x8d\xf6\xe8\x92\x67\xe2\x99\x11\x22\x30\xb2\x06\xed\x95\x04\x12\x95\xe0\xb9\xc2\x28\xe6\xc9\xe6\xb9\x95\xa5\x92\x0d\xae\xc0\x12\x55\x82\x07\x0d\xc8\x90\x15\xa9\x0e\x98\xd8\x56\xb8\x2a\xe2\x1c\xb5\xf2\xc0\x53\x98\x22\xd5\x98\x94\x0b\x9c\xb3\x54\xa3\x74\xd6\x62\x45\xb7\xa6\xb2\x12\xd4\x67\x49\x69\x09\x2b\x92\x16\x68\x4c\xea\xda\x6c\x29\xaa\x68\x25\xe8\x4d\x65\x1d\x12\x9d\x81\xd9\x59\x6e\x71\x13\x09\xc2\xa4\x07\xde\x2d\x6e\xca\x19\xcc\x58\xc3\xf8\xc9\x7b\xc3\x84\xa6\x85\xd2\x28\xed\xf8\xbd\x7f\x8b\x1b\x4b\xd4\xa8\xe7\x16\x37\x70\x65\x64\xc3\x67\x06\x5d\xa9\x65\xd4\x40\x9e\xef\xce\xcb\x72\xa5\x49\x4e\xd1\x03\x8f\x08\x11\x29\x94\x2b\x94\xe5\xf4\x9a\x2c\x1a\x77\xf8\xab\x91\x63\x40\x0a\x22\x84\xff\xe4\x3d\xe5\x45\xae\x03\x96\x27\x78\x77\xef\xd9\x45\x4e\x00\x28\xcf\x73\xa4\xda\xd8\x7c\xc9\xe7\x2b\xf8\xef\x25\x42\x82\x73\x52\xa4\x1a\x0a\x65\x76\x21\x43\x98\x73\x09\xbc\x90\xf0\xea\xa7\xff\xb4\x68\x7a\x23\xec\x74\x4a\x2d\x4b\x55\x1a\x4c\x33\x50\xc4\x45\xae\x8b\x72\xcc\xd8\x0c\x5c\x81\xc2\x74\x1e\xd4\xbb\x5f\xcd\x4c\x32\x06\xcd\xbf\xc6\xa9\x48\xc6\x26\x00\xd5\xb2\x23\x37\x91\x85\x0a\x11\x6d\x8d\x6f\x6f\x81\xe5\xd2\xde\xaa\xe0\x16\x37\x01\x4b\xec\x2a\x8b\x5c\x77\xe7\x6a\x73\xb3\x08\x13\x80\x95\xa0\x91\x42\x5a\x48\xa6\x37\xd1\x42\xf2\x42\x44\x2c\xb1\x06\x52\xc5\x9f\x0e\xd8\xb0\xb9\x9e\xde\x04\x2c\x79\xb1\x07\x23\x5a\x70\xa5\x98\x43\x9c\x00\xdc\x18\x05\x48\xce\x75\x14\xa7\x9c\xde\x46\x09\xae\x18\x45\xb7\x03\x2b\x9e\x16\x19\x46\x8a\xbd\xab\x16\xde\x46\xb2\xe3\x2a\x22\x42\xb4\x91\x5b\x5a\xda\x42\x76\x5a\xb2\x0a\xb7\xd1\xce\x04\x44\x13\xf0\x8c\x01\x7a\x6e\xc2\x2a\x8e\x36\xba\xc9\x88\xd6\x28\x33\xae\x74\x94\x32\x8a\xc6\x55\x6d\xa0\x33\x18\x09\x2a\xcd\x72\xa2\x5d\x64\x0d\x97\x3c\xc3\xb0\xdc\xf5\xb0\xa1\x6b\xb1\xf0\x1d\x0b\xaf\x57\x10\x89\x19\xd7\xe8\xe3\x1d\xd2\x4a\x1e\x96\xa7\x2c\xc7\x5a\xe9\x60\x1c\x5b\x83\xcf\x01\xa5\xc4\x3b\xa6\xbd\x17\xd5\xf8\x7a\x69\x02\xf2\x35\xfc\x0e\xfc\x39\x84\x2b\x22\xc3\x94\xc5\x21\x4d\x79\x91\x84\xd5\xde\x86\x31\xe7\xda\x9f\xb3\x9c\xa9\x25\x26\x70\xf3\x07\x48\x38\xd8\x20\xf7\xf4\xef\x84\x69\x96\x2f\xac\x71\x5b\x22\x9f\xe5\x4c\x07\x41\xf0\xf4\x0f\xa0\x52\x44\x01\x67\x06\x3b\xc7\x66\xc6\x92\x50\x53\x11\xc5\xb1\x7c\x0a\xff\x00\x55\x24\x1c\x34\x22\xf8\x04\x42\xd4\x34\xcc\x78\x52\xa4\xa8\x1a\x12\x8b\x91\xf1\x44\x48\x1e\x23\x38\xd2\xd6\x1a\x16\x66\x71\xbf\xfe\x0c\x3e\x54\x51\x7d\xbd\x5e\x07\x82\x2b\xbd\x90\xa8\x7e\x4d\x03\x2e\x17\x61\x86\x09\x23\xe1\x2d\x6e\x54\xf8\xea\xf5\xeb\xd7\x17\xaf\xff\xf2\x32\x20\x8a\xc2\x3f\x60\x21\x16\xe0\xfb\x09\x12\x99\x71\xd9\x16\x28\x2c\x94\x0c\xd5\x92\x48\x34\x74\x92\xe5\x0b\x15\x56\x5c\x7d\x22\xe9\x92\xad\xd0\x77\x90\x60\x21\x16\x1d\x89\xd5\x12\x7c\x0a\x4f\xed\x82\xdf\x78\x09\xc6\x70\xad\xd8\x22\xc7\xc4\x8f\x37\x57\xc7\xf2\xbe\xb1\x6b\xbb\x0c\x43\x22\x74\x77\x69\xa2\x88\x43\x89\x82\x2b\x03\x84\x27\xcf\x52\x15\x47\x12\x53\x24\x0a\xc1\xa7\xea\xb9\x2f\x16\xc9\x02\x32\xc2\xf2\x37\x1e\x7c\x5f\x2a\x99\x08\x1d\x96\x66\xab\x82\x94\x29\x1d\x24\xa1\xc1\xb2\x9f\x9f\x76\x16\x42\x84\xf6\xad\x8e\x37\x50\x88\x84\x68\x1c\x80\x5b\x83\x49\x53\x83\x97\x6d\xd4\xaf\xa9\x4f\x53\x86\xb9\xf6\x5f\x06\xd3\xc3\x14\xcd\x9a\x2a\xb2\xb3\xb3\x11\x54\x92\x67\xa8\x97\x58\x28\x3f\xe7\x89\xf1\x02\xc1\xa5\x46\x79\x98\x32\x2f\x32\x42\x75\x0a\x29\xcb\x8b\x3b\x5f\x73\x9e\x2a\xdf\x54\x47\x9d\xef\x7e\xaa\x95\x7f\x7e\x1e\x4c\x2f\xca\x88\x3c\x90\xdc\x5a\x49\x26\x43\x2d\x19\x55\xa7\x25\x1a\x47\xfc\xd9\x65\x17\x4f\xcf\x82\xbb\x94\xc8\x85\x0d\x52\xe3\xb2\x05\x7c\x0f\x53\xf8\x01\xce\xe0\x12\xa6\x23\x13\xd1\x49\x09\xc6\xe9\xb4\x49\x32\x0f\x4f\x1e\x8e\xe5\x83\x12\xc8\x67\x16\xb7\x4f\x8d\x04\x8d\x87\x76\xc3\xe3\x46\x69\xcc\x8c\x0b\x62\x4e\xe2\x14\x87\x31\x7b\xb8\x92\x24\xb1\x16\x9d\xb2\x78\xce\x73\x4d\x79\x3e\x67\x8b\x33\xc8\x0a\x95\x76\x12\x43\x95\x12\x92\x34\x58\x48\x32\x27\x39\x31\x15\x7e\xc8\x95\x0a\x5d\x8c\x0c\xdd\x78\x74\x36\x0d\xce\x83\x59\x44\xb2\xe4\x9b\x8b\x20\xc1\xb8\x23\x46\x22\x6e\x17\xe0\x33\x38\x8c\xbe\x35\xf1\x82\xe9\x65\x11\xdb\x49\x59\x1e\x17\xf4\x16\x75\xf3\xc1\x89\xa0\xc2\x84\xaf\xf3\x94\x93\x24\x5c\x9d\x07\x67\xc1\xb4\xc6\x88\xec\xd7\xc8\x46\xa5\x83\x92\x8d\x25\x1a\x92\xef\x6d\xa1\xf4\x9a\x68\xba\x34\x5f\x30\x25\x4a\x33\xaa\xd0\x64\xa3\xa8\x0a\xac\x7d\x12\x9f\x59\x89\xfb\xf1\x7d\x0b\x0c\xca\xa8\x5a\x8a\xa2\x89\x0c\x16\xef\xba\xe9\xfd\x36\x61\x12\x42\x2e\xf4\x00\xa3\x0e\xbe\x26\x12\xfc\x77\x77\xab\x39\x1c\x39\x2f\xf8\xaf\xf7\x4d\x03\xbe\xaf\xb4\x64\xc2\xa7\x3c\x13\x3c\xc7\x5c\xab\xab\x6e\x1e\x6a\x2c\x37\x21\x98\xf1\xdc\x97\x68\x14\x71\xc8\xbe\x9d\xdd\xf8\x2e\x31\x74\xb0\x51\xda\x20\xb4\x8d\x04\x4a\x13\xa9\x0f\x31\xae\xb6\x7d\x80\x65\x05\xee\x32\xeb\xba\x87\xd8\x48\xae\x28\x17\x18\x30\x5e\xfb\x46\x3d\x18\x4d\x83\xd9\xb7\xc1\xf9\xa0\x0d\x76\x9d\x34\x18\x4f\xba\x1b\x09\x2a\xca\x4a\x57\x23\x53\xaf\x90\xfc\x6e\x73\x5a\xe2\xb5\xa4\x65\xda\xed\xe6\xbe\xed\x7f\xfb\x33\x61\x1f\x6e\x29\x55\xb7\xef\xda\xce\x91\xbd\x73\xf4\x65\xcc\xb3\x56\xc6\x24\x4a\x71\xca\x4c\x6f\x5f\x67\xef\x88\x24\x89\x44\x65\xd6\xac\x65\x81\x27\xe5\x4b\x2b\x6f\xab\xd3\x6a\xa5\xe6\xc1\xac\xfc\xa0\x6c\x6a\x27\x3c\x36\x97\x7e\xbc\xca\xe8\x73\xce\xe2\x1f\xa4\xfb\xca\x17\x2c\xbf\xb3\x9d\x89\x6d\xb7\xec\xd7\xc8\xb4\x3e\xa6\x97\xb9\xc5\xcd\xde\x9e\xab\x6a\x4e\xb4\x34\xee\x99\x98\xde\x27\x48\x1c\xcb\x51\x3d\x96\x09\xe7\x57\x36\xd4\xd4\x3d\x53\x23\x90\x20\xf4\x96\x2c\x50\x85\xa6\x1b\x32\xdb\x54\x35\xde\x3d\x6d\x13\x58\xb2\xbd\x2d\x53\xc9\xb8\xaf\x67\xda\x11\xcc\x57\x92\x3e\x96\x3c\xa7\x08\x74\x42\xe9\x66\x99\x7d\x5a\x3d\xd8\xa3\x24\xe2\xbe\x75\x95\xf5\x87\x2f\x4a\xcd\x5a\x8c\x50\xe5\x4c\x08\xd4\x3b\xbe\xd0\x87\xca\xb4\xe9\xdb\x57\x84\xa5\x66\x8a\xd1\x14\xa5\x44\x5d\x89\x65\x66\x03\xc2\x00\x72\xe8\x62\x5c\x87\x28\xcd\xc1\x9f\xab\x3d\x42\xb5\x0e\x97\x86\x79\x37\x38\xfb\x93\x2e\xc9\x22\x13\x38\x3d\xf0\xd4\xac\xfc\x60\x82\x5f\xd9\xbf\x0d\xa4\x58\x87\x58\xe7\xbe\xbd\x59\xee\xf7\xbf\xb7\x50\x35\x8b\xaa\x83\xec\xc8\xd5\xb6\x65\x22\xba\x02\xcf\xab\x53\x61\xaf\x78\x84\x52\x54\x36\x59\x59\x21\xeb\x33\x67\x1b\xef\x5d\x26\xab\x96\x11\x94\xb2\x99\xa4\x67\xd8\x7f\x08\x11\xd5\xcc\x61\x5b\xe9\xaa\x8f\x46\x40\x57\xad\xf5\x6b\x31\xa8\x71\x9b\x1a\xe2\xf1\xa4\x3c\xa2\x60\x6a\xcb\x61\xd3\xe2\x9c\x4b\x8a\x51\x82\x4a\x4b\xbe\xa9\xea\x8f\x41\xc3\x89\x04\x4f\x19\xdd\xd4\xf6\x53\x7d\x1d\x69\x45\x0e\xfd\xa3\x6d\xa7\x29\x03\xac\x08\x70\x05\x7f\xfc\xe3\x9f\x7f\xfe\xcb\xc4\x08\xee\xfd\x6f\xf9\xc0\xcc\xbb\x04\xef\x7c\x7a\x76\xee\x9f\x4d\xfd\xb3\x6f\xad\x9f\x7a\x7f\xd3\x44\x63\x86\xb9\xf6\x2e\xeb\xc2\xa0\x7a\x0e\x67\x9d\xf8\xcf\xf3\x39\x52\x03\xf5\x5e\xa5\x29\x5f\xd7\xde\x6d\x81\xaf\x6c\xa5\xd3\x22\xad\x21\x6a\x76\xf9\x23\x53\xfa\x4f\xdb\x1d\x40\x3f\xf8\xa7\x22\xd5\xec\x17\x22\xf5\xff\x08\x13\x27\x55\x2f\xfa\xbf\x63\x8a\x1a\xf7\xf0\xfb\x0f\x74\xec\x7e\xe4\xd4\x9e\x62\x7b\x2d\xa4\x9b\x2d\xb1\xff\xcb\xed\xbd\x59\x15\x91\xf9\x25\x59\xab\x4b\x35\xbb\xbc\xbc\x7c\xf2\x7e\xcb\x07\x6a\xab\x2e\xcb\xce\xfb\x8a\xe3\xfd\x8b\x3e\x4d\xed\x55\xc6\xab\x98\xcb\x72\xa1\xa2\x5e\xe8\xa0\x5a\x3a\x78\x46\x35\xfb\x94\xf2\x73\xfc\xd6\x6c\xd1\x80\x52\xc6\x40\x5f\xd1\xb4\x17\xe1\x97\x62\x1f\x79\x0d\x35\xe4\x83\xca\xde\x6b\x40\xa7\xee\x44\xf8\x6f\xf5\x5e\xd8\x66\xe0\x7e\x62\x8c\x7d\xc7\xad\x65\xa2\x22\xe7\xa7\x1e\x78\x49\xdc\x7c\x79\x3f\xd0\xeb\xec\x3d\x15\x74\xbe\x98\xc4\xfb\x81\x55\x64\x28\x1f\x05\xcf\x99\x29\xe4\x3b\xf1\xac\x07\xc5\x4d\xdd\x4f\xff\x3b\x47\xef\x79\x70\xd9\x1f\x80\x92\xd8\x68\x24\x21\x9a\xc4\x44\x61\xeb\xc8\x72\x20\x62\x95\xf8\x19\xb1\x23\x75\x5b\xd2\xa8\x20\x89\xeb\xd1\x06\x4f\x10\xa5\xd6\x5c\x26\xdb\x78\xd5\xe8\x04\x40\xdd\x32\x11\xcd\x99\x89\x52\x2a\x27\x42\x2d\xb9\x6e\x7a\x3e\x22\x44\xba\x89\x58\x66\x9f\x79\x68\x4c\x37\x96\x89\x03\xa2\x49\xfb\xd8\xb7\x19\x6d\x75\x97\x58\x35\x7a\x54\x5d\x05\xd8\x46\xdf\x06\x5e\xf7\x33\xb9\xd9\x7f\x6c\xdb\xd3\x81\x26\x71\x69\x7d\x37\x7b\x0d\xad\xdd\xf9\x77\x87\xd4\xb0\xe1\x8d\xb3\xc0\x1f\x06\x0c\xb0\xb4\xaa\xb6\x35\xf5\xf0\x1d\xb0\x9b\x9e\x47\xc8\x7d\xe6\xb9\xbb\x2b\x7b\xec\x74\x18\xe3\x12\x3a\xfa\x6a\xe1\xd5\xdd\x7d\xb3\xba\x94\x28\xd5\xab\xa0\x2d\x1d\x18\xac\x01\x1b\x1a\x63\x4c\x7d\x86\xd9\xa2\xab\xcc\xb7\xd0\x3c\xca\x58\xce\x65\x65\x59\x51\x21\x16\x92\x24\xe5\x3d\x81\x39\x49\x95\x41\x13\x28\xe7\x5c\x66\x76\x06\x96\x2b\xb6\x58\x6a\x15\xb9\x3a\xb6\x6d\xa2\x66\x20\xea\x43\x36\x6e\x6c\x9c\x4a\x92\x0c\x8d\xf2\x4a\xb3\x6c\x3f\x83\x48\x31\x5f\xe8\xe5\xb3\xda\xfd\x1c\xa6\x7a\xee\x6c\x64\x68\xa3\xc5\xc2\x86\x0f\x6f\xd7\x7e\x77\x27\x2c\xe3\xa5\x1d\x54\xd5\x48\x53\x05\xed\xb1\x26\xb1\x30\x16\x34\x27\x19\x4b\x37\x83\x4a\xb7\x01\x91\x14\x92\x4b\xe2\xdb\x87\x72\x36\xb8\xb5\x07\x5e\x06\x53\x2b\xac\x1b\x6b\x9e\xc3\x9d\xd9\x47\x5e\xc9\x26\x27\x19\xa3\xe0\xd5\x62\x57\xe7\x1c\x73\x2e\x23\x24\x74\xd9\x8e\x4f\x95\x82\x2c\x02\xe5\xb9\xc6\x5c\xd7\xc9\xbb\x15\x2a\xcd\xba\x6a\xec\xc0\xde\x22\xb9\xf6\x0c\xdc\xbb\xa9\xee\x1e\x99\xb1\x3d\xc8\xf6\x3f\x35\x76\x69\x58\xa6\x0d\xe5\x49\x1f\x76\x1b\xee\x88\xee\xfb\x3b\x9b\x76\x80\xc1\x3c\x11\x9c\xe5\xba\x15\x60\xaa\xa1\x11\x01\xa6\xc7\x7d\x46\x86\x97\x7d\x51\xe1\x03\x04\x85\xee\x5a\xb7\xf2\x6b\x97\x41\xbd\x82\x60\x27\x06\x5f\xb7\xa2\xdd\x4d\xb0\x96\x4c\xa3\x1c\x72\x9a\xb5\x1c\x4c\xb8\x32\xe9\x89\x9b\x85\xd2\x3c\x6b\x24\x6c\x1f\xbe\x5e\x81\xf7\xea\xaf\xff\xe7\x99\xac\xa3\x34\xd1\x8c\x46\x19\x66\x31\xca\x3a\xdb\x9c\x22\x7d\x6f\x32\x6a\x25\x20\x53\x3e\x6a\x54\x3a\x22\x8b\xf2\x26\xda\x51\xd7\x8b\x0c\xcd\xe8\x0b\x46\x8f\xfd\x6c\xb7\xcf\x6a\x8f\x39\xdf\xb6\xd2\x1f\xb8\x57\xd4\xa5\x1b\x73\xcb\x68\xc4\x5c\xd5\xad\xa3\xf2\x06\x5b\xc4\x92\x41\xc2\x4a\xe1\x35\xe6\xb8\xf3\xf3\x63\x2b\x17\x2b\x9f\x35\x96\x07\xdf\x4f\x32\x9c\xbe\x3c\x60\xfe\xb4\x8e\x1f\xf7\x1d\x89\x6d\x5b\x42\x79\xdb\x70\x37\x49\x8c\xbc\x0c\xd1\xf6\x9c\x3d\x77\x12\xab\x39\xfd\x72\xce\x89\xbd\x5c\x46\x25\x13\xd5\xe5\xb2\x57\x42\x40\x85\x04\x16\xc9\x6e\x49\x15\xad\xaa\x50\x0f\x3d\x13\xd8\x00\xca\xf2\x85\x75\x07\x97\xf1\x25\xcf\x22\xa3\x5d\x2b\xd5\xf9\x79\x19\x8e\x78\x35\xd4\x1a\x14\x92\x6b\x4e\x79\xea\xe4\xd7\x54\x94\xba\xa3\x2c\x91\xa5\x4b\x18\x0f\xb2\x77\x5f\x5b\x17\x54\xeb\x04\x76\xed\x3d\x79\xef\x80\x95\x67\xde\x87\xb3\x73\xef\x05\x34\x80\x9a\xca\x42\x6e\xe0\x72\x90\xea\xc6\x3d\xd6\xdb\xb7\x98\x97\xd3\x6f\xbe\xee\x59\x4e\x3d\x3c\x6e\x41\xd7\xde\x34\xb0\xff\x0b\xa7\x07\x67\xb5\xcc\xbf\xed\xcc\xd9\x1a\x6c\x66\x6c\xcf\xf7\x15\xfc\x44\x36\x31\x82\x44\xa5\x25\xa3\x1a\x78\x9e\x6e\x2c\x57\xf8\xa5\x76\x04\x70\x4f\x8f\x7f\x70\x24\x7f\x2a\x34\x2c\x49\x9e\x6c\xa0\x74\x6b\x4d\x6e\x8d\x73\xba\xdb\xd7\x0a\xd6\x4c\x2f\x79\xa1\x21\x23\x79\x41\xd2\x74\x03\x4a\x2d\x7d\x83\xc1\x72\xcd\x41\x2f\xd1\x31\x0c\x1e\xb8\xe4\xca\x9e\xbf\x3b\x9b\x4e\x77\x94\xdd\x01\xb5\x15\xde\x55\xfa\xb6\xab\x0d\xc5\xe2\xad\x7b\x3f\x95\x68\x38\x6c\x02\xbb\x22\x55\x63\x9d\xcd\xf7\xcf\xc6\xed\xfd\xa8\x10\xe1\x6e\xb6\x7e\xd8\x48\xe1\xbb\x49\x47\x07\x8c\x12\xff\x31\xe2\x46\xe5\x57\xdf\x5e\x0c\x58\x40\x0d\xea\xb1\x80\x22\x39\xca\x02\xea\xab\xc5\x63\x0d\xf3\x44\xb1\x8e\x34\xcc\x53\xc4\xda\x0d\x4e\x1d\xd0\xc7\xd1\xd6\x29\x62\x3d\x54\x5b\x1f\xd8\x85\x0f\xf9\x70\x12\xb7\x7d\xf7\x28\xaf\x1d\xee\xed\xbb\x89\x7d\xc4\x6e\xcc\x66\xd3\x6f\x06\x76\xa3\x06\x3d\xfa\x6e\x8c\x90\xeb\xeb\x8b\xd9\x6e\xa1\xd0\x01\x3d\xba\x5c\x23\x42\x6f\xd3\xa7\x8d\x09\xa1\xb6\x43\x3b\x58\x6e\xfd\x58\xc5\x47\x8b\x7f\x7a\xe5\x55\x76\x1d\x55\x3b\xb3\xdd\xc1\x94\x90\x43\x2b\x8c\x64\x91\x62\xb5\x4c\xdf\xb4\x8a\x65\x4b\xba\xd3\xc4\x5d\x81\xe7\x76\xd0\x9e\x26\x75\xb6\xaf\x2e\xe9\xba\x9b\x57\x03\xba\x5b\xd7\xde\xbc\xb6\x77\x55\xb0\x0f\x58\xf3\xed\x74\x6d\xae\xf1\x1c\xe8\xd9\x8e\x53\x29\x11\xec\x74\x95\x5e\x4c\x6d\x95\xd3\xa7\x54\x07\x3a\x56\xad\xdd\xd0\xf5\x9b\xae\xbd\x8c\xc0\x7b\x96\x8f\x7b\x57\x3f\xb4\xf4\xc1\x75\x97\xd1\xfa\xa3\x2f\xdb\x15\x94\xbe\xe6\x7e\xeb\xae\xf2\xfe\x73\xc0\x91\xf9\xa0\xe7\x70\x65\x9c\x2d\x1d\x36\xa9\xc3\x96\xb5\x63\x60\xbb\x5a\xac\x51\xf6\x29\xb3\x7a\x11\x6a\xf7\xb8\xa4\x9f\x70\xab\x40\x3f\x6e\x2b\xb6\x3b\xfd\x4f\x64\x0b\x5c\xef\xb2\x67\x0b\x1c\xc6\x67\xba\x05\xcd\xcb\x2d\x8f\x5d\xf1\x54\x9e\xd5\x4d\xb0\x23\x6d\xa2\x26\xaf\xd2\xdc\xae\x2d\x9c\x6c\x04\x5f\xf2\xe3\x49\x6e\x5a\x6d\xc9\xe1\x40\xf9\x1b\xee\xcc\x77\xd3\xef\x86\x72\x8d\x03\x7d\xa0\x34\xfb\x20\x15\xba\x57\x02\x3e\x82\xfe\x66\xc3\x65\xca\xec\x83\x96\x29\x0f\x33\xc1\xea\x6d\x82\x8f\xa0\xc1\x8b\xe9\xc5\x70\xa1\x77\xf1\xb9\x68\xb0\x5d\xef\x3d\xae\xfa\x3e\xf5\x42\xf1\xd8\xfc\xe8\x5e\x2a\x1a\xdd\x57\x3a\xfc\xc3\x9d\xe5\xdf\x76\x5b\x49\x47\x5b\x3f\xa1\x1b\x75\x4a\x70\x71\x31\x1b\x68\xc6\x2b\xc8\x23\xf6\xe2\x2f\x0e\xaa\xf4\xa6\x79\xca\xd9\xd4\x12\xa8\xf6\x59\xd2\xfd\x64\xf2\x15\xfc\x1d\x21\x47\x4c\x80\x80\x42\x41\x24\xd1\xd8\x6d\xb6\x8d\x09\x83\xe6\x20\x24\xae\x4c\x2f\x4e\x37\x34\x65\x14\x12\x14\x98\x27\x98\xd3\x0d\xc4\xa8\xd7\x88\xf9\xe4\x2b\x7b\xc2\x4d\x84\x70\x94\x24\x4f\xc0\x09\x59\x8e\x04\xe3\x0a\x53\x21\x4c\x67\x50\xbf\x8c\xf5\x89\x14\xa5\xe7\x5f\x1f\x2a\x4a\x1d\xc6\xa3\x17\xa5\xdb\xbe\x73\x6c\x65\x5a\x1b\xd1\x08\xaf\x2b\x5f\xde\x3a\xe6\x04\xfd\xec\xb8\x13\x74\x3b\xc1\x61\x27\xfd\xc5\xa0\xfd\x66\xcf\xdb\x5e\xf6\x9d\x6e\xbe\xec\x3d\xde\x1c\xfd\x78\xea\x5f\xeb\x11\xdf\xa7\xfc\xe8\xe9\x63\x3f\x7b\x6a\xdd\x55\x79\xcb\xe3\xd3\x5e\x92\x7c\xcb\x63\xf7\x46\xe6\xbf\xc2\xaf\xe1\x34\x6a\x78\xc4\x1f\xc5\xe9\x63\xfa\x48\xbf\x8d\xf3\xf0\x3b\x25\x6f\x79\xfc\xa0\x1b\x25\x5f\x7e\xf3\xe6\xb4\xab\x2d\x5f\x7e\xa1\xe6\xcb\x2f\xd4\xec\x5c\x4f\x1a\xba\x4b\x94\x17\x69\x1a\x55\x5f\xed\xfb\x51\x51\x52\x64\x62\xfb\xc8\xed\xd9\xa8\x17\x99\xdc\xfb\x4b\x86\x3c\x2a\x24\x73\xb9\x77\xcc\x8b\x4e\xcf\xb7\xde\x74\x6a\xbb\x9e\xcd\xbe\x5b\x9e\x47\x79\x96\x99\x9a\xf9\xca\x26\x1a\xf0\xfd\xea\x77\xfe\xca\x14\xd2\xfa\x9d\xbf\x7b\x50\x33\xa0\xc2\x01\x76\x05\x34\xf0\xcb\x30\x3c\xf0\x4a\x0a\xf8\xbe\x34\x61\x52\xb1\x95\x0b\x0f\xf7\x93\x7f\x06\x00\x00\xff\xff\x09\x6e\x5f\xe8\xff\x50\x00\x00") +var _clusterTf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7c\xff\x73\xdb\xb8\xb1\xf8\xef\xfa\x2b\xb6\xbc\x4c\x93\x7c\x26\x24\xe5\x2f\x77\xc9\xb9\xf5\xdd\xa4\xf9\xb4\x6f\xde\xf4\xae\x77\xd3\xf6\xbd\xce\x1b\xc7\xc3\x01\xc9\x95\x84\x98\x24\x70\x00\x28\x59\x49\xfd\xfe\xf6\x37\x00\x01\x92\xa2\x48\x89\x92\x7d\x4e\x72\x13\x67\x62\x4b\xd8\x5d\x60\xb1\xd8\xaf\x00\x48\x85\x42\x90\x19\x13\x39\x7c\x98\x00\x08\xfc\xa5\xa4\x02\xd3\x88\x0b\xb6\xa4\x29\x0a\x69\x9a\x01\xc8\x4a\xc2\xa5\xfd\x0c\x20\x59\x29\x12\x04\xb8\x04\x6f\x41\xe4\x82\x26\x4c\xf0\x90\xac\xa4\x67\xe1\x4b\x14\x92\xb2\x42\xc3\xff\xf7\x3b\xf8\x3a\x38\xfb\xb6\x82\xdc\x4d\xf4\xff\xbb\xc9\xc4\x75\x0f\x9e\xa6\xb2\x43\xcf\x35\x09\x5c\xc2\x92\x88\x80\xac\x64\x54\xb5\x4c\x00\xb8\x60\x33\x9a\x61\x0b\x64\x5b\x74\x57\x29\x51\xc4\x74\x63\xf1\x3d\xf0\x92\x52\x08\x2c\x94\x07\x1f\x36\xe0\x09\xc9\x32\x14\x11\x4d\xb1\x50\x54\xad\xfb\x11\x17\x4a\x71\x0f\xbc\x7c\x1d\xf1\x32\xce\x68\x12\x51\x5e\xf1\x57\x8a\xcc\xcc\x57\x29\x2e\x2f\xc2\x30\x59\x60\x72\x43\x79\x40\x72\xf2\x9e\x15\x64\x25\x83\x84\xe5\x5e\xc3\x10\xde\x2a\x14\x05\xc9\x3c\xf0\xb8\xa0\x4b\xa2\xb0\xee\x89\x0b\x36\x17\x24\x87\x4b\xb8\xf2\xe4\xc2\x7b\x01\x9e\x9f\xe8\xdf\x98\x2c\x18\x7c\x78\xfb\xf6\xad\x47\xb9\xfe\x7d\xa1\x7f\x3d\x79\xb6\x60\x52\x15\x24\x47\xf0\xe9\x73\xdd\x72\xe7\x5d\xeb\x61\x32\x96\x90\xac\x5a\x9e\x9a\x53\x2d\xbd\x64\xc1\x72\xfe\x4c\x33\x11\x68\x5e\x83\xf6\x4c\x02\x81\x92\xb3\x42\x62\x14\xb3\x74\xfd\xdc\xf0\xe2\x78\x83\x4b\x30\x44\x8e\xf1\xa0\x01\x69\xb2\x32\x53\x01\xe5\x9b\x02\x97\x65\x5c\xa0\x92\x1e\x78\x12\x33\x4c\x14\xa6\xd5\x04\x67\x34\x53\x28\xac\xb6\x18\xd6\x8d\xaa\x2c\x79\xe2\xd3\xb4\xd2\x84\x25\xc9\x4a\xd4\x2a\x75\xa5\x97\x14\x65\xb4\xe4\xc9\xb5\xd3\x0e\x81\x56\xc1\xcc\x28\x37\xb8\x8e\x38\xa1\xc2\x03\xef\x06\xd7\xd5\x08\xba\xad\xe9\xf8\xc9\x07\xdd\x49\x92\x95\x52\xa1\x30\xed\x77\xfe\x0d\xae\x0d\x51\x23\x9e\x1b\x5c\xc3\xa5\xe6\x0d\x9f\x69\x74\x29\x17\x51\x03\x79\xbe\x3d\x2e\x2d\xa4\x22\x45\x82\x1e\x78\x84\xf3\x48\xa2\x58\xa2\xa8\x86\x57\x64\xde\x98\xc3\xdf\x34\x1f\x03\x5c\x10\xce\xfd\x27\x1f\x12\x56\x16\x2a\xa0\x45\x8a\xb7\x77\x9e\x99\xe4\x04\x20\x61\x45\x81\x89\xd2\x3a\x5f\xf5\xf3\x15\xfc\x73\x81\x90\xe2\x8c\x94\x99\x82\x52\xea\x55\xc8\x11\x66\x4c\x00\x2b\x05\xbc\xfe\xf1\x3f\x0d\x9a\x5a\x73\x33\x9c\x94\x8b\x4a\x94\x1a\x53\x37\x94\x71\x59\xa8\xb2\x6a\xd3\x3a\x03\x97\x20\x31\x9b\x05\xf5\xea\xbb\x91\x49\x4e\xa1\xf9\x69\x8c\x8a\xe4\x74\x02\xe0\xa6\x1d\xd9\x81\x0c\x94\xf3\x68\xa3\x7d\x73\x09\x4c\x2f\xed\xa5\x0a\x6e\x70\x1d\xd0\xd4\xcc\xb2\x2c\x54\x77\xac\x76\x6f\x06\x61\x02\xb0\xe4\x49\x24\x31\x29\x05\x55\xeb\x68\x2e\x58\xc9\x23\x9a\x1a\x05\x71\xfe\xa7\x03\xd6\xdd\x5c\x4d\xaf\x03\x9a\xbe\xd8\x81\x11\xcd\x99\x94\xd4\x22\x4e\x00\xae\xb5\x00\x04\x63\x2a\x8a\x33\x96\xdc\x44\x29\x2e\x69\x82\x76\x05\x96\x2c\x2b\x73\x8c\x24\x7d\xef\x26\xde\x46\x32\xed\x32\x22\x9c\xb7\x91\x5b\x52\xda\x40\xb6\x52\x32\x02\x37\xde\x4e\x3b\x44\xed\xf0\xb4\x02\x7a\x76\x40\xe7\x47\x1b\xd9\xe4\x44\x29\x14\x39\x93\x2a\xca\x68\x82\xda\x54\x8d\xa3\xd3\x18\x29\x4a\x45\x0b\xa2\xac\x67\x0d\x17\x2c\xc7\xb0\x5a\xf5\xb0\xa1\x6b\x75\xe1\xdb\x2e\xbc\x5e\x46\x04\xe6\x4c\xa1\x8f\xb7\x98\x38\x7e\x68\x91\xd1\x02\x6b\xa1\x83\x36\x6c\x05\x3e\x03\x14\x02\x6f\xa9\xf2\x5e\xb8\xf6\xd5\x42\x3b\xe4\x2b\xf8\x1d\xf8\x33\x08\x97\x44\x84\x19\x8d\xc3\x24\x63\x65\x1a\xba\xb5\x0d\x63\xc6\x94\x3f\xa3\x05\x95\x0b\x4c\xe1\xfa\x0f\x90\x32\x30\x4e\xee\xe9\xbf\x08\x55\xb4\x98\x1b\xe5\x36\x44\x3e\x2d\xa8\x0a\x82\xe0\xe9\x1f\x40\x66\x88\x1c\x4e\x34\x76\x81\xcd\x88\x15\xa1\x4a\x78\x14\xc7\xe2\x29\xfc\x1b\x64\x99\x32\x50\x88\xe0\x13\x08\x51\x25\x61\xce\xd2\x32\x43\xd9\x90\x18\x8c\x9c\xa5\x5c\xb0\x18\xc1\x92\xb6\xe6\x30\xd7\x93\xfb\xe5\x27\xf0\xc1\x79\xf5\xd5\x6a\x15\x70\x26\xd5\x5c\xa0\xfc\x25\x0b\x98\x98\x87\x39\xa6\x94\x84\x37\xb8\x96\xe1\xeb\x37\x6f\xde\x9c\xbf\xf9\xcb\xab\x80\xc8\x04\xfe\x0d\x73\x3e\x07\xdf\x4f\x91\x88\x9c\x89\x36\x43\x61\x29\x45\x28\x17\x44\xa0\xa6\x13\xb4\x98\xcb\xd0\xf5\xea\x13\x91\x2c\xe8\x12\x7d\x0b\x09\xe6\x7c\xde\xe1\x58\x2e\xc0\x4f\xe0\xa9\x99\xf0\x5b\x2f\xc5\x18\xae\x24\x9d\x17\x98\xfa\xf1\xfa\xf2\xd0\xbe\xaf\xcd\xdc\x2e\xc2\x90\x70\xd5\x9d\x1a\x2f\xe3\x50\x20\x67\x52\x03\xe1\xc9\xb3\x4c\xc6\x91\xc0\x0c\x89\x44\xf0\x13\xf9\xdc\xe7\xf3\x74\x0e\x39\xa1\xc5\x5b\x0f\xbe\xab\x84\x4c\xb8\x0a\x2b\xb5\x95\x41\x46\xa5\x0a\xd2\x50\x63\x99\xcf\x4f\x3b\x13\x21\x5c\xf9\x46\xc6\x6b\x28\x79\x4a\x14\x0e\xc0\x8d\xc2\x64\x99\xc6\xcb\xd7\xf2\x97\xcc\x4f\x32\x8a\x85\xf2\x5f\x05\xd3\xfd\x14\xcd\x9c\x1c\xd9\xc9\xc9\x08\x2a\xc1\x72\x54\x0b\x2c\xa5\x5f\xb0\x54\x5b\x01\x67\x42\xa1\xd8\x4f\x59\x94\x39\x49\x54\x06\x19\x2d\xca\x5b\x5f\x31\x96\x49\x5f\x67\x47\x9d\xef\x7e\xa6\xa4\x7f\x7a\x1a\x4c\xcf\x2b\x8f\x3c\x10\xdc\x5a\x41\x26\x47\x25\x68\x22\x8f\x0b\x34\x96\xf8\xb3\x8b\x2e\x9e\x3a\x0b\x6e\x33\x22\xe6\xc6\x49\x8d\x8b\x16\xf0\x1d\x4c\xe1\x7b\x38\x81\x0b\x98\x8e\x0c\x44\x47\x05\x18\x2b\xd3\x26\xc8\xdc\x3f\x78\xd8\x2e\xef\x15\x40\x3e\x33\xbf\x7d\xac\x27\x68\x2c\xb4\xeb\x1e\xd7\x52\x61\xae\x4d\x10\x0b\x12\x67\x38\x8c\xd9\xd3\x2b\x49\x53\xa3\xd1\x19\x8d\x67\xac\x50\x09\x2b\x66\x74\x7e\x02\x79\x29\xb3\x4e\x60\x70\x21\x21\xcd\x82\xb9\x20\x33\x52\x10\x9d\xe1\x87\x4c\xca\xd0\xfa\xc8\xd0\xb6\x47\x27\xd3\xe0\x34\x38\x8b\x48\x9e\x7e\x73\x1e\xa4\x18\x77\xd8\x48\xf9\xcd\x1c\x7c\x0a\xfb\xd1\x37\x06\x9e\x53\xb5\x28\x63\x33\x28\x2d\xe2\x32\xb9\x41\xd5\x7c\xb0\x2c\xc8\x30\x65\xab\x22\x63\x24\x0d\x97\xa7\xc1\x49\x30\xad\x31\x22\xf3\x35\x32\x5e\x69\x2f\x67\x63\x89\x86\xf8\x7b\x57\x4a\xb5\x22\x2a\x59\xe8\x2f\x98\x11\xa9\x68\x22\x51\x47\xa3\xc8\x39\xd6\x3e\x8e\x4f\x0c\xc7\xfd\xf8\xbe\x01\x06\x95\x57\xad\x58\x51\x44\x04\xf3\xf7\xdd\xf0\x7e\x93\x52\x01\x21\xe3\x6a\xa0\xa3\x0e\xbe\x22\x02\xfc\xf7\xb7\xcb\x19\x1c\x38\x2e\xf8\x6f\x76\x0d\x03\xbe\x2f\x95\xa0\xdc\x4f\x58\xce\x59\x81\x85\x92\x97\xdd\x38\xd4\x68\x6e\x4a\x30\x67\x85\x2f\x50\x0b\x62\x9f\x7e\x5b\xbd\xf1\x6d\x60\xe8\x60\xa3\x30\x4e\x68\x13\x09\xa4\x22\x42\xed\xeb\xd8\x2d\xfb\x40\x97\x0e\xdc\xed\xac\x6b\x1e\x7c\x2d\x98\x4c\x18\xc7\x80\xb2\xda\x36\xea\xc6\x68\x1a\x9c\xbd\x0c\x4e\x07\x75\xb0\x6b\xa4\xc1\x78\xd2\x6d\x4f\xe0\x28\x9d\xac\x46\x86\x5e\x2e\xd8\xed\xfa\xb8\xc0\x6b\x48\xab\xb0\xdb\x8d\x7d\x9b\x3f\xbb\x23\x61\x1f\x6e\xc5\x55\xb7\xee\xda\x8c\x91\xbd\x63\xf4\x45\xcc\x93\x56\xc4\x24\x52\xb2\x84\xea\xda\xbe\x8e\xde\x11\x49\x53\x81\x52\xcf\x59\x89\x12\x8f\x8a\x97\x86\xdf\x56\xa5\xd5\x0a\xcd\x83\x51\xf9\x5e\xd1\xd4\x0c\x78\x68\x2c\xfd\x78\x99\xd1\xe7\x1c\xc5\x1f\xa5\xfa\x2a\xe6\xb4\xb8\x35\x95\x89\x29\xb7\xcc\xd7\x48\x97\x3e\xba\x96\xb9\xc1\xf5\xce\x9a\xcb\x15\x27\x4a\x68\xf3\x4c\x75\xed\x13\xa4\xb6\xcb\x51\x35\x96\x76\xe7\x97\xc6\xd5\xd4\x35\x53\xc3\x10\x27\xc9\x0d\x99\xa3\x0c\x75\x35\xa4\x97\xc9\x15\xde\x3d\x65\x13\x18\xb2\x9d\x25\x53\xd5\x71\x5f\xcd\xb4\xc5\x98\x2f\x45\xf2\x50\xfc\x1c\xc3\xd0\x11\xa9\x9b\xe9\xec\xd3\xaa\xc1\x1e\x24\x10\xf7\xcd\xab\xca\x3f\x7c\x5e\x49\xd6\x60\x84\xb2\xa0\x9c\xa3\xda\xb2\x85\x3e\x54\xaa\x74\xdd\xbe\x24\x34\xd3\x43\x8c\xa6\xa8\x38\xea\x72\x2c\x72\xe3\x10\x06\x90\x43\xeb\xe3\x3a\x44\x59\x01\xfe\x4c\xee\x60\xaa\xb5\xb9\x34\xdc\x77\x83\xb3\x3b\xe8\x92\x3c\xd2\x8e\xd3\x03\x4f\x9e\x55\x1f\xb4\xf3\xab\xea\xb7\x81\x10\x6b\x11\xeb\xd8\xb7\x33\xca\xfd\xfe\xf7\x06\x2a\xcf\x22\xb7\x91\x1d\xd9\xdc\xb6\x0a\x44\x97\xe0\x79\x75\x28\xec\x65\x8f\x24\x09\x4a\x13\xac\x0c\x93\xf5\x9e\xb3\xf1\xf7\x36\x92\xb9\x69\x04\x15\x6f\x3a\xe8\xe9\xee\x1f\x83\x45\x79\x66\xb1\x0d\x77\xee\xa3\x66\xd0\x66\x6b\xfd\x52\x0c\x6a\xdc\x26\x87\x78\x38\x2e\x0f\x48\x98\xda\x7c\x98\xb0\x38\x63\x22\xc1\x28\x45\xa9\x04\x5b\xbb\xfc\x63\x50\x71\x22\xce\x32\x9a\xac\x6b\xfd\x71\x5f\x47\x6a\x91\x45\xff\x68\xcb\xa9\xd3\x00\xc3\x02\x5c\xc2\x1f\xff\xf8\xe7\x9f\xfe\x32\xd1\x8c\x7b\xff\x5d\x1d\x98\x79\x17\xe0\x9d\x4e\x4f\x4e\xfd\x93\xa9\x7f\xf2\xd2\xd8\xa9\xf7\x0f\x45\x14\xe6\x58\x28\xef\xa2\x4e\x0c\xdc\x39\x9c\x31\xe2\x3f\xcf\x66\x98\x68\xa8\xf7\x3a\xcb\xd8\xaa\xb6\x6e\x03\x7c\x6d\x32\x9d\x16\x69\x0d\x91\x67\x17\x3f\x50\xa9\xfe\xb4\x59\x01\xf4\x83\x7f\x2c\x33\x45\x7f\x26\x42\xfd\x17\xd7\x7e\x52\xf6\xa2\xff\x7f\xcc\x50\xe1\x8e\xfe\xfe\x03\x6d\x77\x3f\xb0\xc4\xec\x62\x7b\x2d\xa4\xeb\x0d\xb6\xff\x6e\xd7\x5e\xcf\x8a\x88\xe2\x82\xac\xe4\x85\x3c\xbb\xb8\xb8\x78\xf2\x61\xc3\x06\x6a\xad\xae\xd2\xce\x3b\xd7\xe3\xdd\x8b\x3e\x49\xed\x14\xc6\xeb\x98\x89\x6a\xa2\xbc\x9e\xe8\xa0\x58\x3a\x78\x5a\x34\xbb\x84\xf2\x53\xfc\x4e\x2f\xd1\x80\x50\xc6\x40\x5f\x27\x59\x2f\xc2\xcf\xe5\x2e\xf2\x1a\xaa\xc9\x07\x85\xbd\x53\x81\x8e\x5d\x89\xf0\xff\xd5\x6b\x61\x8a\x81\xbb\x89\x56\xf6\x2d\xb3\x16\xa9\x8c\xac\x9d\x7a\xe0\xa5\x71\xf3\xe5\xc3\x40\xad\xb3\x73\x57\xd0\xda\x62\x1a\xef\x06\x3a\xcf\x50\x1d\x05\xcf\xa8\x4e\xe4\x3b\xfe\xac\x07\xc5\x0e\xdd\x4f\xff\x3b\x4b\xef\x79\x70\xd1\xef\x80\xd2\x58\x4b\x24\x25\x8a\xc4\x44\x62\x6b\xcb\x72\xc0\x63\x55\xf8\x39\x31\x2d\x75\x59\xd2\x88\x20\x8d\xeb\xd6\x06\x8f\x13\x29\x57\x4c\xa4\x9b\x78\xae\x75\x02\x20\x6f\x28\x8f\x66\x54\x7b\x29\x59\x10\x2e\x17\x4c\x35\x35\x1f\xe1\x3c\x5b\x47\x34\x37\x67\x1e\x0a\xb3\xb5\xe9\xc4\x02\x51\x87\x7d\xec\x5b\x8c\xb6\xb8\x2b\xac\x1a\x3d\x72\x57\x01\x36\xd1\x37\x81\x57\xfd\x9d\x5c\xef\xde\xb6\xed\xa9\x40\xd3\xb8\xd2\xbe\xeb\x9d\x8a\xd6\xae\xfc\xbb\x4d\x72\x58\xf1\xc6\x69\xe0\xf7\x03\x0a\x58\x69\x55\x5b\x9b\x7a\xfa\x1d\xd0\x9b\x9e\x23\xe4\x3e\xf5\xdc\x5e\x95\x1d\x7a\x3a\x8c\x71\x01\x1d\x79\xb5\xf0\xea\xea\xbe\x99\x5d\x46\xa4\xec\x15\xd0\x86\x0c\x34\xd6\x80\x0e\x8d\x51\xa6\x3e\xc5\x6c\xd1\x39\xf5\x2d\x15\x8b\x72\x5a\x30\xe1\x34\x2b\x2a\xf9\x5c\x90\xb4\xba\x27\x30\x23\x99\xd4\x68\x1c\xc5\x8c\x89\xdc\x8c\x40\x0b\x49\xe7\x0b\x25\x23\x9b\xc7\xb6\x55\x54\x37\x44\x7d\xc8\xda\x8c\xb5\x51\x09\x92\xa3\x16\x5e\xa5\x96\xed\x33\x88\x0c\x8b\xb9\x5a\x3c\xab\xcd\xcf\x62\xca\xe7\x56\x47\x86\x16\x9a\xcf\x8d\xfb\xf0\xb6\xf5\x77\x7b\xc0\xca\x5f\x9a\x46\xe9\x5a\x9a\x2c\x68\x87\x36\xf1\xb9\xd6\xa0\x19\xc9\x69\xb6\x1e\x14\xba\x71\x88\xa4\x14\x4c\x10\xdf\x1c\xca\x19\xe7\xd6\x6e\x78\x15\x4c\x0d\xb3\xb6\xad\x39\x87\x3b\x31\x47\x5e\xe9\xba\x20\x39\x4d\xc0\xab\xd9\x76\xfb\x1c\x33\x26\x22\x24\xc9\xa2\xed\x9f\x9c\x80\x0c\x42\xc2\x0a\x85\x85\xaa\x83\x77\xcb\x55\xea\x79\xd5\xd8\x81\xb9\x45\x72\xe5\x69\xb8\x77\xed\xee\x1e\xe9\xb6\x1d\xc8\xe6\x4f\x8d\x5d\x29\x96\x2e\x43\x59\xda\x87\xdd\x86\x5b\xa2\xbb\xfe\xca\xa6\xed\x60\xb0\x48\x39\xa3\x85\x6a\x39\x18\xd7\x34\xc2\xc1\xf4\x98\xcf\x48\xf7\xb2\xcb\x2b\x3c\x82\x53\xe8\xce\x75\x23\xbe\x76\x3b\xa8\x67\x10\x6c\xf9\xe0\xab\x96\xb7\xbb\x0e\x56\x82\x2a\x14\x43\x46\xb3\x12\x83\x01\x57\xa4\x3d\x7e\xb3\x94\x8a\xe5\x0d\x87\xed\xcd\xd7\x4b\xf0\x5e\xff\xed\x7f\x3c\x1d\x75\xa4\x22\x8a\x26\x51\x8e\x79\x8c\xa2\x8e\x36\xc7\x70\xdf\x1b\x8c\x5a\x01\x48\xa7\x8f\x0a\xa5\x8a\xc8\xbc\xba\x89\x76\xd0\xf5\x22\x4d\x33\xfa\x82\xd1\x43\x9f\xed\xf6\x69\xed\x21\xfb\xdb\x86\xfb\x3d\xf7\x8a\xba\x74\x63\x6e\x19\x8d\x18\xcb\xdd\x3a\xaa\x6e\xb0\x45\x34\x1d\x24\x74\x02\xaf\x31\xc7\xed\x9f\x1f\x9a\xb9\x18\xfe\x8c\xb2\xdc\xfb\x7e\x92\xee\xe9\xcb\x01\xf3\xa7\xb5\xfd\xb8\x6b\x4b\x6c\x53\x13\xaa\xdb\x86\xdb\x41\x62\xe4\x65\x88\xb6\xe5\xec\xb8\x93\xe8\xc6\xf4\xab\x31\x27\xe6\x72\x59\x22\x28\x77\x97\xcb\x5e\x73\x0e\x0e\x09\x0c\x92\x59\x12\xe7\xad\x9c\xab\x87\x9e\x01\x8c\x03\xa5\xc5\xdc\x98\x83\x8d\xf8\x82\xe5\x91\x96\xae\xe1\xea\xf4\xb4\x72\x47\xcc\x35\xb5\x1a\xb9\x60\x8a\x25\x2c\xb3\xfc\xab\x84\x57\xb2\x4b\x68\x2a\x2a\x93\xd0\x16\x64\xee\xbe\xb6\x2e\xa8\xd6\x01\xec\xca\x7b\xf2\xc1\x02\x9d\x65\xde\x85\x67\xa7\xde\x0b\x68\x00\x35\x95\x81\x5c\xc3\xc5\x20\xd5\xb5\x3d\xd6\xdb\x35\x99\x57\xd3\x6f\xbe\xee\x99\x4e\xdd\x3c\x6e\x42\x57\xde\x34\x30\xff\xc2\xe9\xde\x51\x4d\xe7\x2f\x3b\x63\xb6\x1a\x9b\x11\xdb\xe3\x7d\x05\x3f\x92\x75\x8c\x20\x50\x2a\x41\x13\x05\xac\xc8\xd6\xa6\x57\xf8\xb9\x36\x04\xb0\xa7\xc7\xdf\x5b\x92\x3f\x95\x0a\x16\xa4\x48\xd7\x50\x99\xb5\x22\x37\xda\x38\xed\xed\x6b\x09\x2b\xaa\x16\xac\x54\x90\x93\xa2\x24\x59\xb6\x06\x29\x17\xbe\xc6\xa0\x85\x62\xa0\x16\x68\x3b\x0c\xee\x39\x65\xa7\xcf\xdf\x9e\x4c\xa7\x5b\xc2\xee\x80\xda\x02\xef\x0a\x7d\xd3\xd4\x86\x7c\xf1\xc6\xbd\x1f\xc7\x1a\x0e\xab\xc0\x36\x4b\xae\xad\xb3\xf8\xfe\xc9\xb8\xb5\x1f\xe5\x22\xec\xcd\xd6\xc7\xf5\x14\xbe\x1d\x74\xb4\xc3\xa8\xf0\x1f\xc2\x6f\x38\xbb\x7a\x79\x3e\xa0\x01\x35\xa8\x47\x03\xca\xf4\x20\x0d\xa8\xaf\x16\x8f\x55\xcc\x23\xd9\x3a\x50\x31\x8f\x61\x6b\xdb\x39\x75\x40\x1f\x47\x5a\xc7\xb0\x75\x5f\x69\x3d\xb2\x09\xef\xb3\xe1\x34\x6e\xdb\xee\x41\x56\x3b\x5c\xdb\x77\x03\xfb\x88\xd5\x38\x3b\x9b\x7e\x33\xb0\x1a\x35\xe8\xc1\x57\x63\x04\x5f\x5f\x9f\x9f\x6d\x27\x0a\x1d\xd0\x83\xf3\x35\xc2\xf5\x36\x75\xda\x18\x17\x6a\x2a\xb4\xbd\xe9\xd6\x0f\xce\x3f\x1a\xfc\xe3\x33\xaf\xaa\xea\x70\xe5\xcc\x66\x05\x53\x41\xf6\xcd\x30\x12\x65\x86\x6e\x9a\xbe\x2e\x15\xab\x92\x74\xab\x88\xbb\x04\xcf\xae\xa0\xd9\x4d\xea\x2c\x5f\x9d\xd2\x75\x17\xaf\x06\x74\x97\xae\xbd\x78\x6d\xeb\x72\xb0\x47\xcc\xf9\xb6\xaa\x36\x5b\x78\x0e\xd4\x6c\x87\x89\x94\x70\x7a\xbc\x48\xcf\xa7\x26\xcb\xe9\x13\xaa\x05\x1d\x2a\xd6\xae\xeb\xfa\x55\xe7\x5e\x79\xe0\x1d\xd3\xc7\x9d\xb3\x1f\x9a\xfa\xe0\xbc\x2b\x6f\xfd\xd1\xa7\x6d\x13\x4a\x5f\x31\xbf\x75\x57\x79\xf7\x3e\xe0\xc8\x78\xd0\xb3\xb9\x32\x4e\x97\xf6\xab\xd4\x7e\xcd\xda\x52\xb0\x6d\x29\xd6\x28\xbb\x84\xe9\x1e\x84\xda\xde\x2e\xe9\x27\xdc\x48\xd0\x0f\x5b\x8a\xcd\x4a\xff\x13\x59\x02\x5b\xbb\xec\x58\x02\x8b\xf1\x99\x2e\x41\xf3\x70\xcb\x43\x67\x3c\xce\xb2\xba\x01\x76\xa4\x4e\xd4\xe4\x2e\xcc\x6d\xeb\xc2\xd1\x4a\xf0\x25\x3e\x1e\x65\xa6\x6e\x49\xf6\x3b\xca\x5f\x71\x65\xbe\x9d\x7e\x3b\x14\x6b\x2c\xe8\x91\xc2\xec\xbd\x44\x68\x1f\x09\xf8\x08\xf2\x3b\x1b\x4e\x53\xce\x1e\x35\x4d\xb9\x9f\x0a\xba\xa7\x09\x3e\x82\x04\xcf\xa7\xe7\xc3\x89\xde\xf9\xe7\x22\xc1\x76\xbe\xf7\xb0\xe2\xfb\xd4\x13\xc5\x43\xe3\xa3\x7d\xa8\x68\x74\x5d\x69\xf1\xf7\x57\x96\xff\xd8\x2e\x25\x2d\x6d\x7d\x42\x37\x6a\x97\xe0\xfc\xfc\x6c\xa0\x18\x77\x90\x07\xac\xc5\x5f\xec\x15\xe9\x75\x73\xca\xd9\xe4\x12\x28\x77\x69\xd2\xdd\x64\xf2\x15\xfc\x0b\xa1\x40\x4c\x81\x80\x44\x4e\x04\x51\xd8\x2d\xb6\xb5\x0a\x83\x62\xc0\x05\x2e\x75\x2d\x9e\xac\x93\x8c\x26\x90\x22\xc7\x22\xc5\x22\x59\x43\x8c\x6a\x85\x58\x4c\xbe\x32\x3b\xdc\x84\x73\x4b\x49\x8a\x14\x2c\x93\x55\x4b\x30\x2e\x31\xe5\x5c\x57\x06\xf5\xc3\x58\x9f\x48\x52\x7a\xfa\xf5\xbe\xa4\xd4\x62\x3c\x78\x52\xba\x69\x3b\x87\x66\xa6\xb5\x12\x8d\xb0\xba\xea\xe1\xad\x43\x76\xd0\x4f\x0e\xdb\x41\x37\x03\xec\x37\xd2\x9f\x35\xda\xaf\x76\xde\xf6\xaa\x6f\x77\xf3\x55\xef\xf6\xe6\xe8\xe3\xa9\xdf\xd6\x11\xdf\xa7\x7c\xf4\xf4\xb1\xcf\x9e\x5a\x77\x55\xde\xb1\xf8\xb8\x87\x24\xdf\xb1\xd8\x3e\x91\xf9\x5b\x78\x1b\x4e\x23\x86\x07\x7c\x29\x4e\x5f\xa7\x0f\xf4\x6e\x9c\xfb\xdf\x29\x79\xc7\xe2\x7b\xdd\x28\xf9\xf2\xce\x9b\xe3\xae\xb6\x7c\x79\x43\xcd\x97\x37\xd4\x6c\x5d\x4f\x1a\xba\x4b\x54\x94\x59\x16\xb9\xaf\xe6\xf9\xa8\x28\x2d\x73\xbe\xb9\xe5\xf6\x6c\xd4\x83\x4c\xf6\xf9\x25\x4d\x1e\x95\x82\xda\xd8\x3b\xe6\x41\xa7\xe7\x1b\x4f\x3a\xb5\x4d\xcf\x44\xdf\x0d\xcb\x4b\x58\x9e\xeb\x9c\xf9\xd2\x04\x1a\xf0\x7d\xf7\x9e\xbf\x2a\x84\xb4\xde\xf3\x77\x07\xf2\x0c\x12\x6e\x01\xdb\x0c\x6a\xf8\x45\x18\xee\x79\x24\x05\x7c\x5f\x68\x37\x29\xe9\xd2\xba\x87\xbb\xc9\x24\x0c\xe1\xaf\xb8\x4e\x32\x46\x6e\x86\x03\xdf\x8d\xc5\x38\x30\xec\xd5\x64\x9f\x63\x94\x73\xcc\xef\x79\x01\x41\x07\xd9\x5d\xa3\x7f\x84\xd7\xf3\xb8\x31\x1f\x32\xd0\xb9\x3e\xbf\xdc\x9f\xdc\xe3\xa0\xca\xe2\x3d\xe5\xc0\x38\x16\xef\xd2\x1b\xff\xe4\xa5\xff\x4e\x60\xcb\xd1\x6d\xf8\x3c\x56\x28\x41\x63\xf0\xd7\x83\x4f\x37\x33\xae\xc2\xda\x58\x36\x91\x92\x52\x64\xe0\xff\x04\xfe\x0f\xe0\xfb\xac\x54\xbc\x54\x7e\xfd\xc6\x17\x47\xd3\xf7\x4e\x1a\x07\x6b\x3e\x6c\xbf\x81\xa6\x32\xda\x5a\x79\xed\x43\x23\x77\x35\x89\x3f\x80\x10\xbc\xa7\xbc\xc3\x67\x25\x90\x0d\xae\x46\x75\x03\x7e\xba\x73\xfe\xfd\x42\xda\xdb\x75\x98\x12\x45\x42\x9a\xeb\x98\xd1\x95\xe8\x82\xad\x0a\xf0\xff\x0e\x95\xf3\xb8\xa8\xfe\xf4\x32\x31\xf6\x4e\xc4\xa6\x7f\xdc\x2e\xa5\x77\xb8\x87\x11\x45\x74\x3d\xd7\xbd\x75\xf4\x5f\x71\xfd\xc6\xe8\xc3\x7d\x4a\xe9\xc7\xac\xb6\x7e\x73\x65\x74\x18\xc2\x3f\x19\x54\x8f\xd0\x43\xcb\x9b\xee\xdc\x9f\xe8\xdb\x5b\x6c\x35\xff\x4a\x7b\x14\xaf\xa6\x03\x1b\x23\xf7\xdc\x1a\xb9\x9b\xfc\x5f\x00\x00\x00\xff\xff\xd3\x80\x16\x08\x54\x59\x00\x00") func clusterTfBytes() ([]byte, error) { return bindataRead( @@ -114,7 +116,7 @@ func clusterTf() (*asset, error) { } info := bindataFileInfo{name: "cluster.tf", size: 0, mode: os.FileMode(0644), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5a, 0x53, 0x22, 0x5e, 0x57, 0x46, 0xc6, 0xd9, 0xf9, 0xff, 0x2d, 0x39, 0xc2, 0xa5, 0x5e, 0x3, 0xc7, 0xab, 0x93, 0x97, 0x16, 0x82, 0xb8, 0x34, 0xfd, 0xa4, 0x44, 0x99, 0x7c, 0xca, 0x17, 0xe8}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x79, 0xa9, 0xa8, 0xa2, 0x1a, 0x72, 0x1c, 0xa6, 0x32, 0xe0, 0x57, 0xbe, 0xb0, 0xbb, 0xa5, 0x66, 0x85, 0x81, 0xe6, 0xb7, 0xf3, 0xf9, 0xa9, 0xd1, 0x78, 0x35, 0x96, 0xdc, 0x3c, 0x63, 0xa4, 0xc8}} return a, nil } @@ -238,7 +240,47 @@ func es_dashboard_dataJson() (*asset, error) { return a, nil } -var _outputsTf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x92\x31\x6b\xfb\x30\x10\xc5\x77\x7f\x0a\x91\xf1\x3f\x68\xc9\xfc\x1f\x4a\x87\x0e\x85\x0e\xc9\x58\x8a\x38\x49\x47\xaa\x44\x91\xc4\xdd\x29\xad\x29\xfd\xee\xc5\x76\x52\x1c\xdb\xb8\x5a\x04\x7a\xf7\x7b\xf7\x4e\x5c\xae\x52\xaa\xa8\x4d\x48\x2c\x90\x1c\xf2\x46\x7d\x35\x4a\x5d\x20\x56\x54\xff\x15\x7c\xb0\xb9\x49\x1a\x4a\x31\x8c\x74\x41\x7a\xfd\xf7\xd6\x7c\x37\xcd\x0d\xf6\xf6\x31\x56\x16\xa4\x39\x4c\x9e\x8d\x1b\x44\x83\xc9\x97\x1c\x92\xe8\xe9\x03\x4f\xfc\xe0\x80\x49\xd6\x92\xc4\x0c\x5e\x90\xc5\xf4\x95\x13\xfa\x8c\x42\xc1\xf1\xbe\x4f\xba\x62\x72\xad\xbb\x8e\x34\x76\x28\x94\x3f\xdb\x15\xb2\xd7\x17\x38\x8c\xc0\x12\xdc\xbc\x73\x77\x06\x8f\x5c\x30\x31\x02\xb9\x77\xe3\xf3\x19\x42\xd2\xf8\x9b\x40\x29\xc6\xc4\x41\xc2\xa5\xeb\x28\x54\x71\xc1\x7c\x97\x23\x3e\xec\x5e\x16\xd2\xc1\xd9\x50\x8e\xd8\x19\xf6\x37\x50\x1a\xf3\xbc\xb5\xd5\x9d\x50\xe6\x24\x6f\xcd\x20\xe9\x5b\xcd\x3d\xf7\x8c\xed\xf2\x30\x5d\x4b\x70\x0e\x99\xcd\x09\x5b\xcd\xdb\x13\xb6\x7f\x4c\xe1\xed\x1e\x5d\xa5\x20\xed\x13\xe5\x5a\x16\xc2\x5c\x65\x73\xe8\x74\xed\xed\x98\x3e\x66\x3b\x7c\xee\xda\x72\x1c\xb3\xbd\x5f\xd3\x9f\x00\x00\x00\xff\xff\x2e\x33\x67\x1c\xe4\x02\x00\x00") +var _keycloakDatabaseSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x0e\x72\x75\x0c\x71\x55\x08\x0d\x76\x0d\x52\xc8\x4e\xad\x4c\xce\xc9\x4f\xcc\x56\x08\xf7\x0c\xf1\x50\x08\x70\x0c\x0e\x0e\xf7\x0f\x72\x51\x50\xcf\xcd\x2d\x48\x2c\x2e\x56\xb7\xe6\x82\x2a\x76\x71\x0c\x71\x74\x72\x0c\x76\x45\x68\xf0\x0f\xf7\x43\xd2\x6f\xcd\xe5\x1e\xe4\xe8\x17\xa2\xe0\xe8\xe3\xa3\x10\x10\xe4\x19\xe6\xe9\xe3\xea\xee\x1a\xac\xe0\xef\x87\x45\x67\x88\x3f\x92\x36\x40\x00\x00\x00\xff\xff\x90\x74\xbe\xbd\x8d\x00\x00\x00") + +func keycloakDatabaseSqlBytes() ([]byte, error) { + return bindataRead( + _keycloakDatabaseSql, + "keycloak-database.sql", + ) +} + +func keycloakDatabaseSql() (*asset, error) { + bytes, err := keycloakDatabaseSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "keycloak-database.sql", size: 0, mode: os.FileMode(0644), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6e, 0xd9, 0x59, 0xb7, 0xf0, 0x95, 0xfc, 0xc1, 0x6e, 0xb5, 0x5d, 0x98, 0x1b, 0x2a, 0xb4, 0x13, 0x2b, 0xc, 0x95, 0xd8, 0xc9, 0xea, 0x18, 0x84, 0x5, 0x50, 0x3a, 0xc9, 0x6, 0xf5, 0x1a, 0xe0}} + return a, nil +} + +var _mattermostRealmJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x79\x53\xeb\x3c\x93\x38\xfa\xff\x7c\x8a\x14\x77\xaa\xe6\xde\x1f\x8f\x40\x96\x64\x5b\x7a\x66\xde\xa9\x9b\x0d\x08\x24\x90\x85\x25\x30\x67\xea\x29\xad\x89\x13\xc7\x0e\xb6\xb3\xf1\xd6\xf3\xdd\x7f\x15\x27\x40\x02\xd9\xe0\x6c\x9c\xf3\x92\xaa\x53\xc5\xb1\x5b\xb2\xd4\xdd\xea\x4d\xad\xd6\x3f\xff\x2d\x93\xc9\x64\xf6\x3c\xb5\xf7\x67\x66\xaf\xc7\x93\x44\x47\xbd\x30\x4e\xf6\xfe\x98\x3d\x8f\x34\xf7\x7b\xab\x5f\x29\x2f\xee\xfb\x7c\x72\xce\x7b\x7a\x0a\x70\xa6\x27\xd2\x0f\x79\x77\xc5\xeb\x93\xa4\xe7\x4f\x41\xfe\x4b\x79\xc3\x8c\xf4\x79\x1c\xff\xe3\xcb\x5e\x57\x02\x3f\x6c\x85\x20\xd1\xe3\xe4\xcb\xde\x7f\xff\x57\xdc\xe7\xc1\x7f\x3f\x76\xf2\x5f\x87\xe9\x7f\xff\xeb\x50\x79\xc3\xff\x7e\xec\x31\x08\x93\x9c\x36\x61\x34\xfd\x1c\x7c\xfc\x8a\x36\x7c\xe0\x27\x0d\xaf\x15\xf0\x64\x10\xe9\xac\xdf\x0a\x23\x2f\x69\xa7\x63\xae\x37\x90\xed\x3c\xcf\x64\x18\x76\x75\x5d\x9b\x48\xc7\xed\xcb\xb0\xab\x83\xbd\x3f\x33\x86\xfb\xb1\x7e\x02\x78\x7e\x55\xe1\xe3\xba\x1e\xc4\x8b\x5f\xe2\x52\xea\x38\x4e\xdf\x96\x3d\xa3\xa7\xe3\xdb\xfb\x33\xe3\x6c\x78\x7d\x14\x46\xa5\x5e\xdf\xf7\xa4\x97\x1c\xf9\xe1\x68\xef\xcf\x0c\x83\x8f\xe0\x71\x1c\x36\x74\x1c\x7b\x61\x50\x52\xbe\xbe\xf4\x7a\x3a\x1c\x24\x7b\x7f\x66\x2c\xba\x02\xa4\xc2\xc7\x0b\x9f\xc4\x0e\xdc\xdc\x4d\x5d\xf7\x74\x4f\xe8\xa8\xb2\x38\xfc\x95\xbd\xad\x84\x0c\x8d\xf1\xbd\x40\xaf\x1c\x1e\xb2\x19\x7a\xfe\xfa\x32\xe4\x42\xbf\xc5\x80\x0b\x5f\xab\x17\x08\x5e\x0b\xbe\xf7\x67\xc6\xb6\x28\x79\xee\x58\xfa\x9e\x0e\x92\x95\x23\x58\x09\xb2\xdc\xd7\x32\xc8\xc5\x86\xe9\x6c\x82\x5c\xdd\xe7\x8c\xcc\xf9\x50\xe9\xf5\x4c\xb0\xf8\xf6\x2a\xd6\x51\x56\x26\x5e\x98\x52\x0e\xae\x07\x2c\x87\x2d\x2f\x58\x66\x00\x9e\xb6\x4b\x59\xea\x58\x07\x3a\xe2\x89\x56\xb9\x49\x56\xf5\xbc\x45\x0e\x24\x18\x6d\x69\x31\x1d\xc3\x22\xff\x3c\xd3\x8f\x0f\x92\x36\x2a\xe8\xa1\x27\xf5\xab\x29\xad\x02\xaa\x86\xbe\xef\x05\xad\x52\x90\xe8\x68\xc8\xa7\x6b\xda\x9e\x43\xe9\x27\x8a\x27\xd1\x40\x3f\xf1\x9c\x5f\xd7\xf7\x03\x2f\x4a\x5f\xec\x9d\x5f\x9c\x17\x9f\x57\x63\xcb\x8b\x93\x88\x4f\xc7\x9b\xf5\xfd\x70\xf4\x8a\x5b\x16\x21\x8a\x3d\xee\xf9\xd9\x78\x3a\x91\x60\x26\x6e\x96\x21\x17\xb8\x78\xf1\xc5\x50\x47\x9e\x99\xa4\x8d\x5f\xbc\xf1\xa7\xd8\xbe\xf1\x92\xf6\xac\xe7\xa7\x01\x2c\x0c\x5e\x0d\xa6\x4b\x97\x27\x3a\x05\x89\xd7\x0d\x32\xd6\x49\x95\xc7\xf1\x28\x8c\xd4\x6a\x10\xad\xbc\xe4\x71\xe0\x2b\x3f\x24\xa2\x41\xa2\x8f\xc2\x48\xea\x6a\x14\x26\x5a\x26\xaf\xba\xe8\xeb\xa8\xc7\x03\x1d\x24\xe5\x50\x76\x67\x9c\xbb\xf8\xba\xc7\xc7\x97\xba\xd7\x0f\x23\x1e\x4d\xe6\x10\xf1\x02\xcb\xf6\xf8\xf8\x88\x7b\xfe\x20\xd2\x37\xdc\x4b\x1a\x5a\x86\x81\x8a\x97\x84\x51\xcf\x0b\xbc\xde\xa0\x57\x1b\x78\xb2\x9b\xf2\xe1\x32\xe0\x13\x7b\x8f\xb8\x97\x94\x02\x39\xc5\x77\xb0\xea\xfd\xfd\x53\x07\xf9\xb6\x96\xdd\x8a\xe7\xfb\xde\x33\x98\xf5\xbc\xbe\x7b\x7c\x5c\xd0\x7e\xc2\xa7\x2b\xf1\x19\x60\x91\x93\xcd\x6c\xc4\x47\x5c\x26\x61\x94\x32\xed\x23\xc6\x43\x5f\x4f\x81\x67\x7a\x6b\x49\x47\xfd\xcf\xd3\xa3\xe9\xef\x9f\x4b\xff\x5b\x50\x72\x96\x03\x31\x87\xc4\x05\x52\x12\x09\x08\xb4\x39\xa0\x48\x3b\xc0\x61\x1a\x49\x87\x21\xd7\x75\xcc\x9c\x4d\x97\x5a\xcf\x39\xef\x51\x8c\xfd\x35\x5b\xc3\xab\x20\x95\x8e\x65\xe4\xf5\xe7\xab\x7e\xef\xdf\xff\x39\x1d\xf4\x5f\xf3\x76\x60\xd6\xee\xef\x55\x0d\x65\xd8\xeb\x87\xb1\x97\xbc\x60\xe4\x65\x98\x54\x56\xd5\x43\x7f\x23\x50\x18\x24\xdc\x0b\x74\x54\x5a\xad\xd7\x97\x80\x79\x92\x44\x9e\x18\x24\x33\xbc\xfe\xbd\x04\xf0\xf7\x1f\xbb\x21\x55\xba\x46\x49\xa5\x29\x70\xa9\xc1\x80\x20\xdb\x06\x42\x59\x0c\xb8\x92\x11\x9b\xda\x4c\x11\xb4\x11\xa9\x32\xd2\x3c\xd1\x60\x46\xca\x9d\x51\xba\xd8\xea\x37\x43\xa8\x50\x0a\x61\x46\x18\x40\x0c\x43\x40\x1c\x23\x00\x77\xb5\x06\xae\x8b\x31\xa4\xb6\x20\xc8\xc6\x9b\x10\x3a\x37\x8c\x40\xba\x5e\xc0\xe6\xf1\xae\x46\xee\x52\x0f\x5b\xb1\xfb\x2c\xd0\x56\x83\x2c\xaf\xd9\x25\x98\xd5\xeb\x77\x09\x64\xeb\x9a\x7b\x82\x1c\xf4\xf8\x5f\x53\x8d\x15\x46\xde\x43\xaa\x3b\xf6\x56\xc2\xfe\xef\xea\x2e\xe6\xcc\xb0\x76\xac\x99\xb9\xf2\x0e\x07\x29\xd0\xfa\x11\x67\x66\x62\x2e\xe0\xad\x74\xc1\xa7\xf0\xeb\x47\x9d\x42\x0f\x3d\x3d\x02\xfd\x28\x34\x9e\xaf\x57\x0f\x3a\x1d\xf8\xca\x37\x7f\xbf\x7a\xfa\xf7\x2f\xc3\xe9\xc4\xd2\xc8\x20\xa1\x80\x70\xb9\x05\x08\xb3\x14\x60\x52\x29\xa0\xa4\xcd\xb0\xc1\xca\x25\x74\x23\xa7\xbf\xa6\xf8\xce\x2c\xfe\xaa\xe9\x6f\x26\x44\xa8\xa3\x1c\xc5\x30\x02\xc4\xb1\x34\x20\xda\xb5\x01\x47\xda\x02\xd0\x68\x97\x51\x88\xb4\xc6\x62\x13\x6a\xf9\xd4\xd6\xdc\x1d\x9d\x29\xf8\x4f\x96\x14\x4b\x8a\xe4\x9b\x2f\xfd\x67\x92\x81\xed\x63\x49\x5b\x78\xbd\xbe\x8e\xe2\x30\x58\xc7\x99\x2f\xba\x4f\x05\xc6\x6c\x24\x9b\xc4\x5c\xe6\x49\x60\xe8\xe1\xce\xa0\xdb\x16\xc9\xeb\x16\xeb\xd4\xf1\x12\xe4\x1c\xe3\x73\xf4\xed\x36\xc3\x37\x0d\xe5\x7e\xa0\xa3\x09\x18\xc4\x3a\xda\x3a\xcf\x79\xf7\x9e\xd2\x41\xe2\x25\x93\xa9\x38\x1d\x7a\x6a\x87\x86\xe9\x74\x77\xfa\x44\x0a\xb9\x23\x85\xe6\xc3\xd9\xa9\xdf\xd9\x2c\xdf\xd6\xf1\x4e\xf4\x99\xc3\xbe\x81\x51\xde\x8e\xbe\xd9\xe0\xd3\xe1\xec\x08\xdb\x8a\xc2\x41\x3f\xfe\x2d\xf4\xdc\xd3\xff\x16\x24\xcb\x3a\x69\xb2\x9b\x04\x59\x23\xfe\xe6\x42\x9d\x19\xca\x18\xe3\x80\x0a\x1b\x03\xc2\x39\x05\x5c\x58\x06\x20\x8c\xa5\x85\x99\x4d\x38\xa5\x6b\x68\xf0\x24\xd8\x77\x91\x4a\x6b\x84\xfc\x52\xd3\x55\xc2\x3e\xb3\xa3\xce\xcc\xbc\x22\xd5\x6a\xcd\x90\x59\x41\x2d\xa6\x04\x96\x84\x3a\xc0\x52\x96\x02\x04\x43\x0e\x28\x51\x0c\x60\x48\x5c\x17\x2b\x26\x98\x70\xd6\x0d\x6d\x13\x2d\x33\xab\x39\x6a\x23\x3d\x04\xb2\x88\x22\x54\x02\x46\x0c\x05\xc4\x68\x0c\x84\xe6\x0c\x68\x8b\x28\xa9\xa0\xe2\x86\xae\x52\xb2\x99\x45\x7a\xec\x24\xf8\xd7\x10\x64\xb9\xed\x27\x45\x32\x7b\x9c\x51\xd7\x66\xd0\x05\x9a\x43\x1b\x10\x68\x10\x10\xae\xb1\x01\x32\xdc\x51\xdc\x75\x15\x33\x6a\x1b\x45\xb6\x2b\xd7\x35\xe4\x58\x68\xf8\x49\x8b\xcc\x9e\xc5\x95\x2d\x1c\xea\x00\xca\x1d\x08\x08\x15\x16\xa0\xda\x61\x40\x6b\x97\x2b\x64\x19\xa4\xed\xdd\x68\xb1\x8b\xc9\xb0\x89\x24\x5b\xed\xfc\xcc\xbf\x18\x65\x30\xc6\x54\x43\xa2\x80\xed\xd2\xa9\xdf\x25\x39\x10\xdc\x86\x40\xdb\x9a\x0b\x22\x10\x17\x46\xee\x44\x99\x4d\x56\xc8\x26\x8a\xac\x0d\xdb\x64\xfe\xc5\x28\x01\x1d\x4c\xb4\x92\x18\x40\x62\x23\x40\x5c\x62\x03\x21\x1c\x0a\x2c\xa1\xa8\x0d\xa9\xa0\x70\xa5\x9b\x96\x59\x11\x40\xdb\x68\x85\x6f\x8e\xa2\xcd\x9a\x7e\xd2\x23\xb3\xa7\x89\xb6\x88\xa5\x11\x70\x11\xa5\x80\x68\x82\x00\xc3\x92\x02\xed\x4a\x6c\xb0\xc3\x5c\xdb\xd9\x55\xa3\x7f\x85\xd4\x5a\xd5\xc3\x27\x75\x32\x7b\xd0\x08\xc7\x15\x8a\x01\xaa\x2d\x0c\x88\x71\x6d\xc0\x25\x37\xc0\xb5\xb5\x26\x36\xe3\x54\x38\x5b\xe5\xd6\x76\x97\x72\x0d\x51\x16\x1a\x7e\xd2\x22\xb3\xe7\x72\x63\x6c\xcb\xe1\xd3\x61\x38\x80\x08\x6e\x01\x86\xa4\x0b\xb8\xd6\x2e\xa6\xd8\xa1\x18\x59\x3b\xae\x94\x9d\x9d\xce\xcd\xcb\xe5\x75\x37\x9f\x74\xca\xec\xb9\xcc\xd1\x02\xba\x06\x70\xe8\x6a\x40\xb8\x84\x80\x53\x83\x00\x74\x98\xb4\x1d\xa9\x2d\xe2\xf2\x9d\x74\xfd\x3b\x96\xcc\x73\xbb\x9d\x28\xb1\x11\xc1\x5b\x43\x84\x99\x1d\x23\x79\x99\x77\x45\xf3\x32\x6f\x0b\x47\x65\x76\x0f\x77\x64\xd6\x86\x3c\x32\x2b\xc3\x1e\x99\xd5\x4c\x90\xf9\x4d\xf8\xd5\x21\x44\x6b\x8b\x69\xe0\xd8\xd4\x05\x44\x72\x05\x38\x54\x10\x50\x8e\xb5\xe5\xd8\x52\x52\xb5\x6a\x3b\x31\xb3\x42\xae\xbc\x83\x63\x17\x5b\x7e\x4a\x8f\xcc\x1e\xa1\x4a\x10\xa5\x0c\x50\x82\xe9\xa9\x0f\xc7\x00\xb5\x6c\x0a\x38\x31\x9c\x71\xee\x08\xc3\xf5\x4e\xd2\xe3\x5d\xf1\x8d\xc5\x96\xbf\x93\x04\x79\x44\xc6\xa7\x4c\x78\xfa\x6d\x8e\xb3\x49\xcc\x10\xb4\x05\x70\x08\xa3\x80\xb8\x06\x01\xc1\x2c\x04\xb8\x2b\x19\xe7\x42\xba\xda\xd9\xaa\xc3\x76\x88\x9b\x6f\x96\x09\x9f\x3e\xeb\xa3\x15\x8e\x2d\x4e\x2d\x9b\x01\xc4\x25\x03\xc4\xc5\x06\x50\x88\x2d\x80\xa1\x4b\x30\x66\xd0\x10\xb9\xd5\x47\xda\x65\xcb\x63\xa3\x1d\xfe\x19\xf3\x7c\xa2\x87\xb1\x11\x52\xc2\xd1\x00\x3a\x68\xea\x15\xd9\x0c\x50\xa6\x0d\xb0\x8d\x11\x5c\x31\x05\x31\xdc\xd5\x12\x7f\x4f\xd4\x73\xa9\xe9\x27\x3d\x32\x7b\xda\x95\x4c\x62\xe6\x02\x9b\xda\x1a\x10\xa5\x6d\x20\x1c\xa1\x80\x83\x5c\xce\x1d\x84\x04\x72\x77\x5c\x1f\x1b\x77\xd5\x36\x2e\x8f\x59\xcb\x4f\x6a\x64\xf6\x30\xe1\x82\x68\xe2\x02\xad\x20\x07\x04\xb9\x1a\x70\x8a\x1c\x40\xa9\xb0\x6d\x47\x60\x4d\xcc\xd6\xd5\xf1\xb6\xad\xd1\x4d\xc6\xcc\xa7\x8f\xba\xdc\x93\x37\x1f\x8b\xed\x5a\xd4\x62\x80\xbb\x18\x03\xa2\x09\x05\x42\x6b\x03\x1c\x4b\x2a\xc7\x50\xa9\x1d\x48\x76\x5b\x31\x73\x67\xeb\x1d\x2b\x66\xd6\xf2\xb7\xa4\xc6\xd2\x93\x17\x39\x30\x8b\x76\x6c\xcc\xd3\xc3\x1a\xff\xf3\x12\x24\x15\x26\x60\x26\xe7\x7b\x7a\x4d\xfa\xdb\xe6\x8d\x6b\xee\x1a\x2c\xb4\x00\xae\xb1\x6c\x40\x0c\x62\x40\x10\x81\x81\x63\xb9\xda\x96\x12\x69\x23\xff\x05\x83\x10\x3b\xe1\xf5\x55\xab\xdf\x35\x08\x21\x08\x63\xc8\x71\x6d\x20\xa1\x43\x01\x31\x4c\x02\x46\x98\x00\x46\x59\xcc\xd5\x5c\x1b\x68\xec\x1f\xe6\xf6\x72\x23\x91\xe4\x2e\x70\xe8\xd4\xe1\xa0\x02\x01\xe1\xba\x0c\x68\xc3\x14\x56\x52\x3b\x9c\x6c\xdd\xba\xfc\xd5\x4d\xdc\x8f\x44\x0f\x8a\x24\x46\x48\x0b\x80\x8d\x56\x80\x58\x52\x01\xe6\x40\x0b\x50\xae\xa0\xb2\xa5\xb6\xb4\xd8\x1a\x14\xfa\xd5\x13\x5f\x3e\x12\x3d\x04\x66\x4c\x52\xc6\x01\xc1\x8a\x00\x22\x5d\x02\xb8\x72\x2d\xa0\xb4\x52\x5a\x62\x0a\x0d\xfc\xed\xb7\x2d\x3f\x14\x3d\xa8\x14\xd2\x31\x0a\x50\x29\x0d\x20\x9c\x21\xc0\x6c\xa2\x00\xb3\xa0\x91\x0c\x59\x88\x33\xf8\xbb\xbb\x80\x1f\x89\x1e\x90\x53\xac\x99\x54\x40\x70\xa8\x01\xe1\xb6\x06\x5c\x32\x1b\x50\xc7\xb8\x9c\x09\x62\xa8\x5e\x6b\xce\xfd\x1e\x41\xec\x8f\x44\x0d\x23\x11\x33\x8a\x2b\x20\x66\x0e\x39\x47\x80\xd3\xa9\xf6\x70\x94\x2b\x1d\x68\x31\xbd\x6b\xc0\xea\x57\x75\xc8\x3f\x12\x35\xb8\xe2\x42\x21\xee\x00\x61\xa0\x01\x44\x42\x07\x08\x64\x18\xb0\xf0\xd4\xb8\xb2\x5d\x69\xb6\x6f\xe2\xcf\x2c\xe7\x75\x67\x14\x32\xeb\x89\xb1\xd0\xf0\xf7\xf0\x06\x76\xce\x5e\xcf\xbc\xde\x7e\xd8\xa1\xc1\x5b\xce\x30\xa4\x0d\xde\x72\x24\x20\x93\x79\x63\x8e\xfa\x62\x83\x37\xce\x79\xa7\x04\xf5\x4c\xe6\x2d\xc7\x1f\x32\xef\xf0\xc6\xde\x74\xcc\xe3\x79\x38\x6f\x39\x34\xf1\xdc\xea\xcd\x38\x7d\xdf\x67\xde\x30\x99\x1d\x82\x34\xab\xc6\xf5\xe6\x53\x09\x8b\x8d\x77\x26\xe5\xba\x28\xdf\xa7\xd3\xfc\xf4\xdb\x6c\x84\x5a\x2e\xe1\xcc\x76\x81\x91\x18\x01\x62\x14\x07\x94\xbb\x1a\x10\x06\x11\x25\x36\xe7\x4c\xed\xba\x4b\xf7\x0b\x67\xc3\x7f\x24\x8a\x10\x46\x2c\xa9\xb1\x0d\xb0\xab\xe5\x74\x2c\x36\xe0\x52\xbb\xc0\xe1\xd8\xb2\x1d\xed\x10\x24\x77\x0c\x63\xfc\x9a\xf9\x72\x1f\x89\x16\xd0\xb1\x2c\xcb\x42\x06\x38\x18\x5a\x80\x08\x09\x01\x13\x54\x02\xa1\x38\x57\x8a\x4a\xb6\x43\xee\xe2\xaf\x9b\x73\xfd\x91\x28\x41\x94\x74\x95\x03\x1d\x20\x8d\xb0\x01\xd1\xd2\x01\xc2\x35\x18\x30\x6c\x84\xeb\x6a\x8a\x6d\xb3\xd5\x59\xfe\x7d\xce\x25\x7c\x24\xca\x50\x28\x2d\x48\x0d\x07\x90\x49\x17\x10\x6d\x5b\x80\x53\x82\x00\x43\x2e\xb7\x15\x17\xb6\x31\x5b\x1d\xb5\x5f\xf9\xf4\xce\x47\xa2\x85\x34\x16\xb5\x99\x71\x80\x66\xc8\x06\xc4\x96\x18\x30\x4b\xb9\x80\xba\xd0\xa2\x5c\x0a\xec\xba\xab\xce\xe6\x67\x56\x68\xf3\xdf\x24\x13\xfe\x23\x51\x47\x43\x64\x38\xb4\x6c\xc0\x39\x62\x80\x38\x88\x02\x81\x20\x07\x84\x51\xcc\xb1\x45\x90\xdc\x1e\xf0\xfb\x3d\xf3\xf2\xbe\x66\x53\xed\x57\xc8\xcb\xfb\x48\x5c\x08\x89\xe1\x8a\x40\x04\x1c\x62\xb9\x80\xd8\x86\x02\x8e\xb5\x02\xd8\x75\x84\x32\x8e\x30\x0a\x6d\xe5\xc2\x5f\x7b\xdf\xfe\x23\x51\xc3\x08\xe1\xba\xca\xd6\xc0\xb5\xdc\xa9\x5d\x23\x1c\xc0\x05\x35\x40\x38\x16\x36\x86\x4b\x84\xec\x5d\x37\x01\x7e\xbb\x13\x19\x1f\x89\x4e\xb6\x45\xb1\x25\xb5\x03\x84\xa6\x2e\x20\x96\x23\x00\x43\xb6\x0b\x18\xa7\xc6\x40\x4e\x11\x22\xee\xef\x9d\xcd\xfa\x91\xa8\x41\x34\x63\xc6\x12\x1c\x30\x4a\xa7\x9a\xd4\x22\x40\x58\x0c\x03\x8e\x1d\x2e\x08\x64\xcc\x45\xec\x5f\x31\x3f\xec\xbb\xd2\x68\xe9\xc9\x86\x8c\xa4\xb0\xaf\x83\x94\x4c\xaf\x72\x92\x62\x2d\x07\xd1\x14\x51\x69\x2c\x1f\xc8\x30\x88\x67\x33\x7c\x05\x39\x07\xf0\xbd\x95\x2f\x67\x05\xba\x36\xb5\x17\x51\xd8\xd5\xd1\xdb\x73\x9e\x90\xc2\x96\x4d\x24\x07\x44\xa4\x07\xaf\x2c\x0b\x50\xc8\x04\x10\x94\x2b\x84\x1d\x88\x6d\xb3\xb5\x58\x47\xa4\xb9\x02\x49\x5a\xb1\xf6\xad\xdb\x1c\xf3\x76\x3f\x8b\x7d\x2c\x6e\x2b\x6a\x63\x0a\x30\x84\x04\x10\xca\x15\xe0\x4c\x73\xe0\x3a\xae\x26\x5c\x43\x26\x56\x16\xb1\xcb\x7c\x3d\xfb\x6c\xaa\xd1\xb6\xf9\xe4\x91\xcd\x94\xd2\xd4\x00\x69\x1b\x03\x88\x12\x08\x70\x9a\xee\x1a\x52\xe2\x32\x69\x69\xa4\x77\xd5\x9f\x9b\xeb\xbe\x6d\xf1\x75\x66\x6d\x3f\x9a\x5d\xbd\x6b\xe9\xbb\x4c\xe6\x55\xf9\x3b\xe0\x7b\x41\xf7\x63\x5b\xd5\xae\x86\x54\x4a\x82\x01\xd1\x0e\x04\x84\x43\x0d\x04\xc4\x1a\x10\xe5\x20\xe1\x30\x83\xac\xf5\xb1\xeb\x6f\x6e\x1f\x20\x61\x43\x47\x39\x00\x71\xed\x02\xc2\xb4\x0d\x84\x34\x1c\x50\x48\x88\x34\x06\x52\xce\x76\x4b\x96\x7c\x8f\x51\xbd\xd0\xf0\x67\x89\x8e\x8f\x44\x0b\x33\x45\xb8\x83\x1c\x80\x05\x75\x00\xd1\x8c\x02\x2e\x98\x0b\x1c\xc7\x51\x96\x90\xd8\xe6\x7c\xe7\x3d\x8d\x30\x88\xdf\x9c\xe9\xb4\xdc\xf6\x97\x96\x09\xb3\xa0\xc1\x1c\x09\x9f\xb2\xe0\xe9\xb7\x25\x0a\x87\x14\xe2\x9a\x02\x03\x15\x06\x84\xbb\x10\x70\xae\x2c\xe0\xba\x2e\x64\x02\x4d\x3d\x89\xad\x89\x44\xb3\x58\x73\x7f\x56\xd3\xda\x0b\x83\xf7\x48\x84\xc5\xe6\x9f\x72\x21\xb3\x27\x34\xd2\xc2\xc2\x04\x60\x8e\x6d\x40\x8c\xa0\x80\x62\x41\x80\x64\x96\x24\x1a\x52\x9b\x6d\xb7\x15\x94\xf6\x75\xf2\x4e\x5b\x61\xb9\xed\x27\x45\x32\x7b\x14\x62\x97\x49\xe4\x02\x43\x1d\x0b\x10\x61\x13\xc0\xb4\xb1\x00\x66\xcc\x28\x87\x5b\xae\xc1\x6f\xb4\xde\xe6\x66\xcb\x57\xd8\x70\xb3\x1e\x3e\xa9\x93\xd9\x73\x90\xad\x29\xe7\x18\x60\x41\x20\x20\xd8\xc6\x80\x5b\x92\x00\xe5\x28\xa6\xa8\x83\xa1\xd2\xbb\xed\xec\xbc\x4b\x8b\x2e\xb6\xfc\xa4\x46\x66\x8f\xba\xca\xb5\x25\x46\xc0\x82\x42\x02\xc2\xa6\xce\x99\x43\x35\xa0\x18\x11\xc4\x38\x55\x90\x6c\xdd\xdb\x59\xaa\x59\xfd\x76\x6a\xcc\x5b\xfe\x96\xd4\x58\x76\x4f\xff\x6d\xf9\xf9\x9c\x56\x7b\x73\xe3\xfc\x39\xe0\xf0\x58\xb7\x7d\x3e\x97\x85\x5b\x0e\xde\x55\x16\xfe\x2d\xe5\xe0\xdf\x5a\x06\x7e\x83\xbd\xb9\xb1\x02\xeb\x86\xca\xab\x4b\xb8\x89\xe6\x57\x87\xe4\x23\x9d\xc6\xc3\xb8\x1f\x2f\xd9\x98\x7b\xfd\xf9\xbd\x1b\xb3\x66\x8f\x08\x0c\x93\x7e\x35\xf4\x3d\x39\xb9\x9c\xf4\xd3\xa9\x27\x61\xd2\xdf\x7b\xf9\x72\xe9\x9e\xa0\x93\x1e\x97\x8d\x93\xac\xf5\x0a\xaa\x14\x78\xd3\xef\xe6\xa7\x62\x3c\x8d\xfe\xc0\x97\x10\x05\xaf\xe5\xa5\xb7\x6d\x38\x2f\xdf\x94\xc3\xb0\x9b\x6d\x6b\xae\x6e\xbc\x40\xa5\xb7\xff\x58\x2f\x41\xaa\x3a\xf2\x42\xb5\x78\xbb\xc5\xd3\xab\x7c\xa8\x74\x5d\x0f\x62\x2e\x5e\xa2\x70\x0a\xd3\x18\xf4\xfb\x61\x94\x68\x95\x5d\x34\xe8\x96\x90\x33\x9d\x75\xb6\xdf\x3f\x8a\xb4\xbe\xb8\xac\xa6\x97\x34\xfd\xf1\xea\xed\x71\x18\xb6\x7c\xbd\xe6\x65\xc5\x93\x51\x18\x87\x26\xc9\x0e\x92\xf6\x94\x00\x92\x27\x61\x94\x02\x2f\x21\xdc\x0f\x25\xf7\xe7\xbb\xb2\x97\x7a\x9c\xcc\x16\xc4\xfc\xe5\x48\x8b\x69\xf3\x60\x36\xab\x7a\xbf\x98\x06\x36\x1f\xef\x8c\xea\xbe\xb8\x33\x6a\x19\xfa\xf5\xa5\x4e\x2f\xe6\x58\x4c\xef\x77\x5a\x1a\xcc\xcb\xef\xcd\x58\x6c\x75\xff\xd9\x24\xd1\x71\x92\x8e\x3b\x1f\x06\x43\x3d\xe1\x81\xd4\xd5\x48\x1b\x1d\xe9\x40\xa6\x03\x0c\xc2\x24\x13\xf7\xb5\xf4\x8c\xa7\xd5\x9a\x5e\x16\xb1\x93\x4d\x12\x2e\xdb\xf3\x1d\xc7\x5d\x5a\xcf\xef\xc7\xa9\xeb\x38\x0d\xfa\x9e\xe9\xc9\x8e\x0d\xaf\x62\x1d\x5d\xeb\xc8\x33\x73\xf2\xcf\x3b\x7a\xc3\xa7\xf3\x69\x92\xee\xeb\xcb\x90\x5e\x4c\x6f\x18\x7a\xaa\xc1\x7b\x7a\x69\x9e\xf5\xf4\x72\x9e\x74\x49\x2c\xb2\xe6\x8b\xa6\x52\xea\x7e\x32\xe5\xe0\x2c\x6f\x0d\x3c\xb5\x24\xe7\x96\x41\x8b\xe3\x24\xe2\x17\x91\xd7\xf2\x82\x0d\x50\x8f\x17\xed\xf8\x3a\x8e\xdf\xc6\x4a\x8b\x2d\xbf\x9e\xad\x96\xc7\xb1\x89\xc5\x16\x21\xbf\x0d\xbb\x2d\xf5\xf8\x55\xac\xb7\x34\x8b\xf7\xb2\xe1\x62\x27\x5f\xcf\x92\x8b\xbd\xed\xc6\x9e\x4b\xe8\x78\x3f\xab\x2e\x75\xb3\x3b\xdb\x2e\x36\x5b\xc7\xc2\xb3\xa4\xc9\x45\x06\x7b\x51\x11\x7c\xa6\xd8\x15\x62\x8e\x43\xa5\x06\x48\x2b\x04\x08\xb3\x2c\x20\xb0\x2b\x80\xb4\x2d\xe3\xb8\x16\x81\x96\x7c\xb9\x03\x95\x76\x1d\xbc\xe0\xff\x34\xd7\x12\xbc\xaa\xf5\xb1\x67\xbc\x28\x4e\xd6\xdc\xd5\xf7\x04\xe4\xf3\x67\x98\x29\x35\x5f\xbe\xd7\xf3\xab\xb4\x9e\xbf\x06\xad\xff\x5f\xe9\xe1\xc1\xb3\x0e\x3f\x90\xe1\xcb\xbd\xc8\x59\xb3\x19\x67\xbc\xb8\xfc\xea\x09\x64\x76\x62\x40\x4d\xc9\x1d\x27\xbc\xd7\x9f\xaa\x4b\xd7\x82\xd4\xb1\x88\x0d\x1d\x84\x5f\xf6\xb8\xe2\xba\xb1\x25\xfd\xb5\xda\x60\x9c\x7e\x66\xa5\x2d\xb1\x9a\x34\x2f\x48\x84\x21\x36\x16\x86\x08\x70\xa5\x05\x20\x06\xdb\x80\x23\x87\x00\x81\x6d\x25\x5c\x89\x1d\x4b\xad\x2d\x50\x90\xcc\x8d\x91\x27\x9b\x65\x0d\xdc\x94\x7a\x65\x2e\x74\x8a\xe5\xca\x24\xb3\x0d\x7e\x8e\xb7\x02\x4f\xad\xb0\x47\x94\x39\x96\x6b\xbb\x6b\x5a\xc4\x5a\x46\x3a\x29\xf0\x84\x4f\x3f\xf1\xcf\x2f\x7b\x43\xee\x0f\xf4\x97\xbd\x3f\xbf\xec\x1d\xbb\x13\x74\x1d\x06\x95\xeb\xab\x41\xf7\x2a\xbe\x9c\x28\x5e\x8c\x4f\x54\xd6\x54\x74\xbd\x9e\xdd\xe7\xf5\xfc\x5d\xb3\x78\x3f\x4c\x1a\xa4\x11\xa9\x66\xbe\xc5\x6f\x3b\xe7\xcd\xf1\x65\xdb\xab\x36\xb2\xfe\x19\x12\xa7\xf2\x01\xf3\xeb\xf1\xa8\xd4\xbc\xc3\xa8\xd2\x2d\xd8\x54\x8c\xe4\x6d\xeb\x1f\xff\xf8\xb2\xf7\xc7\x97\xbd\x98\xfb\x49\xfa\x95\xe8\x66\x1c\xdf\x1d\xc6\x57\x95\x61\x25\xca\xee\xd7\x7b\xd7\xc1\xfd\xe0\xaa\x36\x87\xe2\x4a\x79\x53\xd9\xc1\xfd\x2a\x8f\x78\x4f\x27\x3a\x8a\xbf\xec\xfd\xf9\xcf\xbf\xd7\xfb\x08\x4f\x24\x5d\x98\x53\x9b\xc7\xed\x52\xa2\x67\xb7\xc7\x4d\x3b\x40\x16\x84\x10\x4e\x3f\xf0\x28\xf4\xd3\xb1\xf4\x45\x57\x19\x04\xe2\x36\xb7\x2d\xb4\x6d\x00\xdb\x6c\xfc\x17\xbc\xa6\xbc\xd4\x7a\x9b\xfe\x7b\x36\x61\xa7\x46\x69\xbc\xba\xbc\xc2\xcc\xda\x9d\x5d\x16\xb8\x06\x84\xfb\xbd\xfa\xfc\xfe\xb3\xd7\xbc\xbb\xde\xc6\xdf\x38\xcc\x15\xb7\x6a\x3e\xbd\x5b\x70\x4f\x9e\x1d\x98\x3f\x36\x0b\x32\x8c\x90\xd1\xd8\xc5\x00\x19\x8c\x00\xd1\x4a\x00\x41\x6d\x01\x08\x72\xb4\x22\x1c\x31\x1b\x6e\x14\x64\xbd\xde\x60\x9d\xe4\x59\x10\x21\x6b\x16\xf7\x2b\x19\x62\x33\xe4\x40\x6a\x43\x64\x91\x0f\x21\x43\x2c\x24\x28\x26\xd2\x00\x42\xb5\x0b\x88\xcd\x25\x60\x2e\xa3\xc0\x60\x89\xb5\x6d\x10\xa2\x36\xfa\x5a\x19\xf2\x42\x26\x3c\xa1\x00\x53\xf8\x76\x99\xa0\xf7\x8f\xe2\x87\x6c\xb7\x73\x75\xdf\x77\xab\xd7\x93\x16\x3e\x32\x37\xb8\x99\xe4\x38\x4a\x9a\x39\x4b\x0c\xfb\xe3\x82\x38\x3f\x69\x75\xcf\x6f\xda\x63\x4b\xb8\xb7\xe7\x9e\x65\x93\xdb\x61\xcf\x09\xea\x50\xf2\x0e\xf2\xc7\xcc\x3e\xbb\xf5\x8b\x7a\xe8\x05\x95\x33\x41\x8e\xef\xce\x7a\xf5\xda\x4b\x99\xe0\x07\xc1\x61\xb6\x1b\x5e\x5c\x58\x83\xea\xe9\xf1\x9d\x7d\x23\x46\x03\x2b\x85\xfa\xda\x75\xef\xda\x1b\x97\x3d\xb2\x9d\xe9\x37\x3e\xfa\xd2\xde\x7e\xe7\xe0\x4e\xb7\x60\xcd\xce\x4a\x6e\x9c\xda\xb3\xe7\xbe\x7a\x7b\x68\xeb\x76\xcf\x8e\xbb\xdf\x9b\x6f\x3b\x5b\xde\xfc\xf9\xfb\x6b\x45\xd6\x92\x2d\x1f\xcb\xb0\xaf\x2b\xbc\xdf\xf7\x82\xd6\x46\xc3\x6c\x7e\xc5\xec\x14\x7c\x6f\xdb\xbd\x8f\x4f\xf7\x52\x6e\x27\xde\xc6\xc0\xd0\xe3\x20\x17\xbe\xbd\x30\xd4\x85\x70\xd0\x3a\x32\xac\xa0\xd8\xd3\x46\xde\xab\x44\x97\x15\x2c\xb2\x7e\x1e\x99\x37\x12\x77\x5d\xb5\x99\x17\xb4\xfd\xb7\xe5\xe7\x7f\x2f\x21\x60\x07\xc3\xf9\x1d\x41\xbc\x79\xe7\x33\xc7\x6d\xf5\x54\x9e\x02\x67\xff\xfe\xcf\x19\xf0\x5f\x6b\x76\x59\xf6\xa2\x30\x4c\xae\x22\x7f\x06\x3b\x5d\x81\x39\x1e\xeb\xab\xc8\x7f\x05\x28\x66\xcf\xa7\x80\x87\xb3\x83\xa8\x87\xcf\x3a\xfa\x70\xde\xfd\xe1\xcb\x56\xf1\x20\x8a\xc2\x16\x4f\x52\xa7\x66\xe1\x36\xdd\x55\x9a\x69\xa3\x46\xe3\xfe\x88\x4f\xe2\xc2\xec\x56\xee\xd2\xd4\x05\x8d\xd7\x5e\x90\x34\x47\xd0\x92\x1f\xf5\x18\x4e\x9b\xbd\x02\x33\x95\xf1\x6a\xb4\xb3\xa7\x53\xb2\x20\x44\x15\x23\x0a\x08\x03\x11\x20\xc2\x56\x80\x0b\xc7\x02\xd0\xe5\xb6\x20\xca\xb5\x04\x7a\x69\x2c\xef\x45\x5a\x79\x91\x96\xc9\x55\xe4\xad\x59\x4a\x1b\x10\xf7\x7f\x36\xcb\xb5\x91\x16\xaf\x9d\xb3\x67\x6a\x6f\x90\x28\x42\xf3\x48\x47\x17\x81\x3f\x59\x87\xac\xd9\x9e\xc2\x16\xe2\xc4\x09\x0f\x14\x8f\xd4\x91\x1f\x8e\x8a\x9b\x08\xe5\x2d\xdc\x19\xbe\xf2\x22\xed\x27\xc8\x19\xb6\xb2\xa9\x58\x39\x8e\x78\x90\xc4\x9b\xe1\x63\x1d\x0d\x3d\xa9\xb3\x33\x8c\x6d\x01\xee\x0f\x84\xef\xc9\xfc\xa3\xec\x58\x05\x62\xa2\x30\x48\x64\x9b\x07\x81\xf6\xcb\x61\xeb\xd5\xcd\xc4\xcf\x7d\x45\x61\x12\xca\x30\xe5\xfd\x59\x36\xdf\x54\x04\x05\x5a\xbe\x62\xa0\xe5\xb0\xfa\x6b\x06\xe8\x4f\x5d\x4c\x3f\xfd\xd6\xc1\x23\xbb\x1c\x0c\x66\xfc\xb2\xb7\xbf\xb7\x51\x6d\xf0\x67\x76\xf6\xc2\x60\x8a\xde\x9c\x17\x28\x2f\x68\x5d\x0c\x75\x14\x79\x4a\x2f\x46\x2e\x9f\x27\x39\xf0\xfd\x54\x0e\xaf\xbc\xde\xf9\x09\x2c\x48\x03\xb6\xf5\x85\x4b\xab\x5f\x85\x2e\x9e\xe9\x36\x33\xd4\xf3\xcf\x32\x7e\x0d\xbb\x8f\xb4\x00\xe1\x9c\x6b\x57\xc8\xea\xf5\x1b\x2f\x73\x31\xbe\xe2\xc5\xcc\x85\xdf\xb8\x54\xc2\xfe\xcc\x01\xda\x3e\x3e\xae\x54\xb4\xc6\x1e\xe9\xb7\xc3\x60\xe5\xc8\xb6\x9b\x32\x3d\x4f\x46\xe1\x7c\x6e\xa0\x33\x7a\xe9\xbf\xec\xec\x89\x50\xcb\xe6\x96\x76\x05\x30\x2e\xd5\x80\x58\xd8\x00\x26\x09\x01\xc2\x26\x36\x53\x06\x6a\x28\x5f\x6e\x06\xaf\xd2\x0c\x6b\xb4\xe5\x5a\x0d\xf1\x08\xff\xa9\x29\x76\xd3\x14\x90\x40\x47\xba\x10\x02\x2a\xd0\x94\x4c\x0e\x06\x8c\x0b\x1b\xd8\x90\x59\x46\x19\xcb\xd6\xf6\xcb\x5d\xe1\x4f\x4d\x91\xf9\xb8\x9a\x62\xc5\x40\x3f\x9e\xa2\x58\x25\xb1\xba\x52\x1f\xc8\x50\xe9\x03\xd9\xe6\xbe\xaf\x83\x96\x3e\xe8\xe9\xa4\x9d\xee\xd0\xed\x3d\xef\x09\x3c\xfe\x3e\xac\x7a\x79\x44\xe2\xd4\x71\x78\x19\x7b\x7e\xfc\x6d\x0e\x52\x40\x97\x49\x6e\x04\x70\x2c\x86\x00\x81\x36\x03\x94\x58\x08\x40\xe3\x0a\x22\x30\x33\x06\x6f\x3d\xa5\xce\x07\xca\xd3\x81\xd4\x99\x48\xc7\xa1\x3f\x5c\x9b\x1d\xb0\x33\xc5\xd7\x4c\x2f\x6d\xe7\x29\x09\x1e\x3f\x08\xe6\x1f\x04\xbd\xd9\xfb\x75\xe1\x83\x5d\x96\xe2\x22\xb4\xf1\x5a\xef\x49\x44\xff\xd4\xf5\x3f\x46\xd7\x13\x4d\xa9\xeb\x10\x80\x2c\x49\x00\xc1\x1c\x02\x6a\x21\x0a\x6c\xc1\x29\x45\x9c\x43\xf6\xea\x28\xec\xb2\xae\x7f\x3a\x1f\xb2\x55\xcb\x3f\x42\xbe\x52\xdb\xbf\xaa\x02\x56\x1c\xb9\x16\x82\x18\x58\x14\x2a\x40\x2c\x8e\x01\x35\x36\x01\x16\x52\x94\x5b\x1c\x11\x24\x5e\x9e\x51\x79\xa5\x80\x7f\x11\x25\xba\x0a\xf2\xdb\x68\xd1\x15\x64\xfc\xed\x95\xe8\xaf\xa1\x0e\x3f\x25\xf0\x0f\x91\xc0\xef\x38\xeb\xb5\x24\x81\xe7\x27\xec\xb6\x89\xdf\x19\xd8\x6f\x23\x7b\x31\xa3\xc6\xb2\x1d\x0b\x08\x4d\x1d\x40\x14\xa4\x80\x5b\x06\x4f\xdd\x20\xa4\x84\x54\x50\xda\xaf\x76\xcb\x7e\x51\xd9\xfb\xcb\x38\x30\x9f\xa1\xae\x4f\xe1\xfb\xaa\xb3\x8f\x2d\x7c\x91\xc3\x88\xc5\x35\x03\xc6\x4d\x6b\x26\x71\x1b\x30\x17\x33\xe0\x62\x02\x05\xb4\x0d\xc2\xf8\x55\x46\xd0\xa2\xf0\x7d\x7d\xda\x7a\x8d\x1c\x7e\xf9\xfc\x45\xce\xf0\x86\x90\xd7\x2b\xf6\x9f\xda\xd1\x6b\xde\x2d\x04\xc0\x7e\x17\x41\x7f\x2f\xd4\x55\x87\x28\x2e\x47\x86\xdb\x71\x29\x5b\x2f\x79\xcd\xbb\xb1\x88\x73\x47\x61\xd8\xbf\x9c\xbc\x2c\x5c\xbf\x43\x84\xeb\x4d\x61\xac\x37\x37\xff\xfd\xd4\xc4\x37\xb6\xd0\x77\xd6\x12\x2b\xbe\xfb\xed\x94\x44\xe8\x29\x79\x20\x3d\xc1\x0f\x5a\xd3\xe9\x1e\x3c\xb3\xfc\x5e\x3a\xc0\x55\x42\x67\xc6\xb1\x07\x33\xde\x3c\x48\xb3\x45\xbc\x30\x38\x48\xbc\xd9\x12\x9f\x27\x91\x61\xba\xea\xf4\xc7\x9e\xe0\xb2\x3b\x9f\xe1\xa3\x72\x8a\x75\x1c\x4f\x3b\x88\x9e\xc9\xbd\x37\x9d\xf4\x4a\x59\xb9\x49\xa9\xfd\x9f\x95\x42\x74\xaa\xcb\xd0\x81\xd2\x53\x4a\x1d\x2c\xa5\x38\xbc\x61\xce\x6a\xb6\xce\x0f\xc2\xe0\x60\xce\x9c\x07\xb1\x8c\xb4\x0e\x36\xb6\x5a\x31\xd9\x48\x0f\xc3\xae\x3e\x98\x8b\xf6\x83\xb4\xbc\x42\xfc\xdc\xc9\x8f\xd1\xca\x2b\x58\x6a\x93\x52\x06\xd6\x77\xd2\xca\x5c\xae\x8a\xaf\x7d\x2a\xeb\xcd\xca\xfa\x1d\xd7\x3c\xad\x53\xd6\xab\x4a\xff\xbc\x57\x57\x6f\x52\xc8\xbf\x96\xd6\xfd\x41\x0e\xd2\xaa\x34\xe6\x8f\xa8\xf8\x3e\xfd\xa3\x0f\x23\x89\x3f\xdd\xa3\xc5\xde\x7f\x98\xc4\xb5\x91\xd1\x86\x71\x1b\x08\x82\x39\x20\xcc\x51\x40\x68\x4b\x01\x88\x88\x8d\x90\x45\x90\x4b\x36\xee\x0e\xbc\xbc\x1e\xef\x87\x3a\x47\xed\x24\xe9\xff\x79\x78\x98\x1e\xb3\x6b\x87\x71\xf2\x27\x85\x8e\x7d\xe8\x87\x2d\x2f\x38\x8c\xe3\xf0\x70\xd5\x88\x7e\x43\x07\x8a\x49\xa4\x95\x72\x09\x60\x1a\x41\x40\x6c\x92\xde\x73\x84\x00\x74\x2d\xa2\x09\x36\xb6\x71\x5f\xa5\x68\x6c\x77\xa2\x76\x42\xee\x1b\xfc\xac\xdf\xdf\x8d\xfa\x69\xda\x64\x8b\x1f\xb5\x6a\x19\x6c\x53\x21\xd3\x36\x07\x3c\x8e\x75\x94\xba\x13\xf1\xe3\xc9\xc0\x8d\x4e\x41\xda\xc8\x84\x91\xd4\x07\xa9\x0a\x12\x33\xcd\xb1\xc9\xeb\x49\x9b\xf4\x06\x7e\xe2\xa5\x89\xf5\xea\xe0\x31\xcb\x76\xcb\x57\x74\x20\xa3\x49\x3f\xd9\x08\xf8\xf6\x44\x87\xb4\xeb\x29\xc9\x74\xb4\x3c\xe5\x8d\xc3\x7f\xd9\xe0\xa0\xab\x27\x5e\x60\xc2\x03\x3d\xde\x3c\xc0\x59\x6b\xaf\x15\x78\x41\xeb\x40\x4e\x51\x9d\x1e\x10\x4c\xbf\x58\x29\x95\xf2\xf8\x21\x9f\xcf\x4a\x99\xcf\xb5\x8e\xda\x9a\xdf\xc7\x41\x21\x7b\x9e\x6b\x75\xef\xdb\x5d\xef\x98\x8d\x60\x2e\x5b\x8b\x8f\xb2\x85\xec\x43\xe5\xb2\x38\x2a\x8f\x6e\x0b\xd7\xb5\x5a\xa1\x90\x6f\x87\xea\xa4\x3e\x92\x0f\xe1\xb0\xfc\xa0\x3a\xe7\x97\xb5\x87\xf3\xcb\xda\xa4\xdc\xb3\x03\xd9\x63\x51\xb9\xe7\x0f\xcb\x68\x3c\xbc\x43\xfe\xa0\x8c\xcf\x1f\xc4\x84\x3d\xdc\xde\x58\x71\x25\x47\x9a\x85\xcb\x22\xa9\x14\x4a\xa3\x8b\xcb\x2c\xa9\x74\x2a\xa3\x8a\x15\x36\x0b\x97\xa5\x85\x67\x35\x58\xb1\xc2\x51\xe5\xa1\x38\xae\xe4\xe9\x71\xd6\xba\x2a\x66\x47\xa3\x90\x9f\xd4\xa1\x3c\xa9\x38\xe5\x09\xc5\xb7\x0f\x57\xb0\x32\xfd\xe7\xd9\x83\x3b\x7c\x3a\xe4\x13\xbb\x2f\x26\x2c\x16\x48\xf5\x85\xc7\x1e\x24\xa2\x43\x89\x8e\x12\x51\xc8\xe7\xb3\x8d\xd2\xa8\x50\xbb\x3d\x3d\x0b\xef\x4a\xed\xa1\x3c\xcf\xd6\x8a\xb9\x5c\x2d\x5b\x68\xb5\x8a\xd5\xec\xf4\x7d\x2d\xcc\xb7\x5a\xc5\x5c\xf6\xb4\x65\xe9\xfa\xfd\x2d\x6d\x12\x71\x7c\x79\x74\xda\x52\x26\xa9\x86\x35\xff\x7e\xc4\x63\xd3\xbb\x3b\x2d\x8c\xba\x55\x5f\xdc\xc4\xe7\x86\x34\x6b\x83\xee\xe8\xf6\xfe\x58\xf6\x0b\xb7\x67\x89\xca\x2a\xda\xeb\x95\xbb\xb7\x67\xd6\xa8\x59\xed\xd4\x87\xea\xee\xf2\x3c\x97\xc5\xc1\xa0\x72\x77\x7b\x2c\x4f\x3b\xcd\xca\x30\x77\x76\xdc\xb8\x7f\x60\xf7\x28\xa6\xfb\xa3\xc2\x3e\xbb\x3c\x93\x45\x87\x37\x2e\x1b\xee\xbe\xbe\x28\xb3\xe3\x4e\xfd\xa6\xa2\x8a\x76\x8b\x1c\xc7\xe5\xee\x45\xe7\xe1\x34\x74\x72\x98\x25\x81\x97\xcf\x9f\x9c\x64\xad\xc8\x37\x57\xad\x42\xf3\x28\x3b\x2c\xd4\x93\x86\x03\x27\xc9\x20\x1b\x74\x0b\xce\xed\xb1\xba\xc3\xbd\xf0\x2e\xe9\x6a\x1a\xc7\xc5\xbb\xce\xf8\xb4\x1e\x1c\x1b\x7c\x44\x8b\x56\xdd\xf0\x2a\xc9\x06\x2e\xa7\x05\xeb\xce\x9f\x0c\xcf\x03\x75\xd7\x2f\x27\xb9\xc3\xac\x37\xee\x94\x86\x3c\x3e\xed\x57\xa3\x5a\xd3\xbe\xba\x39\x2c\x74\x3b\x67\x47\xb5\xf1\xfe\xfe\xfe\xf1\x9d\x3a\xca\x0d\x8f\xef\x49\x6b\xc8\x49\xbf\x18\xf5\xee\xad\xba\x09\x4a\x61\x31\x39\x76\xaf\xdd\x42\xaf\xd5\xcf\x15\xc6\x56\x75\x68\x15\x27\xa7\x8e\x35\x0c\x47\xd7\xa3\xee\x55\xe1\x54\xa3\x81\xd7\xc3\xb1\xdb\xb6\x3d\x7e\x97\xd5\x85\x7b\xeb\xbc\x79\x9e\xbd\xad\x54\x0c\xcc\x67\x47\xc5\x6c\xf6\x72\x05\x4f\x65\x2f\xf2\xd9\x5a\x31\xdb\xce\x3a\x93\xce\x5d\xaf\x2b\x27\xb9\xd6\x95\xf1\x4c\xd4\x2e\xc8\x33\xd2\x24\xd5\x2b\x14\x25\x66\x7f\xc2\x86\xf7\x3e\xa2\xb7\xf7\x08\x97\x54\x28\xe1\x80\x5c\xf2\x61\x74\x27\x8a\x27\x5a\xb5\xb2\xf1\xe8\xc6\x2d\x60\x51\x08\x9a\xf8\x34\xab\xea\x59\x5c\x15\x13\x75\x1c\x64\x4f\xf4\x65\x55\xc5\x17\x43\x73\x78\x95\x0d\xfd\x6a\x27\x56\x87\xd2\xdd\x3f\xeb\x56\x44\xd4\xbf\x96\x87\x51\xe7\x98\x56\x8f\x92\xeb\x91\xb9\x2f\xe0\x6e\x2f\xbc\xea\x37\xef\xec\x4b\xeb\xe8\xf8\xe4\xc2\x3d\xeb\xf4\x0f\xe3\x2a\xf6\xcf\x9b\x7a\xd0\x0a\xfb\xe3\xb0\x4d\xfc\x06\xbe\xc9\xea\xee\xd9\x7d\x81\x16\x82\xb2\xef\x3b\x8d\xb8\x5f\xef\xd5\x22\xd5\xba\xab\x1d\x5e\x34\x8a\xbd\x71\xb3\xe2\x61\x72\xd4\x42\x0f\xdd\xbc\x3f\x38\xbc\xee\xdb\xac\x54\xc7\x93\xe1\xe9\xb8\x7b\xad\xac\xe4\xee\x4c\x35\x3c\x6b\xdc\x3d\xe1\x39\x55\x3e\x8c\x8f\x71\xd3\x29\x1c\x8e\x26\x0e\xed\xdf\xde\xe4\x1c\x72\x35\xa9\x42\x54\x3d\xe1\x45\x94\x9d\x24\x0f\xf7\xe5\x43\xbf\x77\x78\x78\x96\xef\x5c\xd1\x1b\x71\xbc\x7f\xcc\x94\x97\xaf\x9e\x9d\xf7\x9d\x81\x6a\x5a\xfe\xd1\x19\x39\x3c\x27\xad\x7e\x70\xd3\x28\xc5\x6d\xeb\xa8\xb8\x7f\xd8\x40\xa8\x18\xd9\x87\xb5\xce\x59\xe1\xb8\x3a\x39\x37\xd8\xae\x8e\xfe\xf1\x8f\xb5\xb2\x80\x4f\x45\x00\x97\x4f\x92\xf3\x60\x56\xef\xd4\x78\xb3\x6c\x9e\xcb\xa3\x6a\xae\x7c\x73\x42\x8f\xcf\x1f\x4e\xee\xea\x56\x3f\x51\xbd\xb0\xc5\xee\xc6\xed\x9b\xec\xee\x7d\xee\x26\x91\x66\x82\x8c\x2f\xd6\x82\xa8\x37\xb2\x7f\x35\x4e\xb2\xc8\x5e\x55\x51\x2b\x6d\xf9\x57\x2a\xfb\xff\x9a\x1a\x7d\x7f\x79\x6a\xfa\xbf\x1e\xdf\x41\x02\x3e\x46\xdd\x76\xd7\x31\x53\x27\x25\x88\x13\x9e\x3c\x1d\xa1\x5e\x27\xa0\xdf\x17\xdd\x5a\x12\xcc\xfd\xc8\x1b\xf2\x24\x95\xea\x73\xc1\x5c\xec\x67\x4b\xb9\x6c\xf6\x2c\x5d\x24\xbd\xc2\xb5\x7d\xdc\xef\x8c\x4d\x3b\xbe\xab\x5c\xf5\x72\xd6\x3e\xdc\x6f\xe7\x6f\xa2\xdc\xfd\x78\xff\xae\xdb\xad\xe6\x6b\xfb\xd7\x09\x1f\x59\x87\x6d\x95\x77\x2e\x73\x5e\x78\x37\xe9\x9e\xb7\xee\x2d\x98\xc3\x13\x7e\x3b\xa8\xb7\xa2\x66\x4e\xee\x9f\x1f\x33\xcb\xaf\xc0\x62\x41\x6b\x32\xf6\x5b\x77\xa3\xde\xb9\x9c\xd0\x62\x78\x77\x16\x55\x51\xc4\x1f\x1e\xdc\x6c\xd5\xb5\x2a\xfd\xd1\x65\xbf\x7f\x7a\x5e\x1e\xda\x84\x0c\x21\x3f\x3f\xba\x1d\xc3\xcb\x5e\xa1\xc5\x47\x83\x9a\x53\xad\xf4\x3a\xe1\x89\x41\x48\x97\x4a\x25\x29\x0b\x37\x83\x6b\xd6\xc8\x9e\xcb\xab\x3c\x3d\x3f\xb6\xca\xd1\xe5\x19\x22\x79\x5d\xab\xf6\x5b\x77\x56\xa0\x79\xbb\x87\xea\xee\x64\x32\xaa\xf7\xaa\x45\xff\x58\xde\x1d\xca\xe6\xe8\xf2\xfa\x88\x85\x87\xad\xbc\x49\xa2\x51\xf5\xba\xd7\x3c\xa3\x48\x59\xbd\xee\x00\x9e\xd0\x7c\xf9\xb8\xe2\xb1\xfb\x51\xaf\xbb\x9f\xe4\x8c\x5f\x17\xf4\xa2\x51\x09\xaf\x0b\x27\xae\x4b\xee\x7c\x78\x75\x4c\x79\xe4\xe5\x59\xe4\x75\x1b\x03\x1e\x5d\x1f\xed\x4b\xaf\xd5\x80\x22\x69\xc6\x17\x3c\xdf\x2d\x56\x4f\xae\xf6\x0f\xaf\x2e\x4b\x41\x74\xb3\xdf\xc9\x35\xf3\xf5\x5a\xc5\x77\xb9\x73\x26\xf4\xc3\xe0\xa4\x77\xda\xef\xe6\xc8\x45\x74\x65\x49\x98\x6b\x8d\xc6\x87\xb5\x52\x21\x5b\xcb\xe6\xb2\xe1\x14\xcf\xde\x3d\x49\x9c\x2b\x3c\x1a\x74\xae\x91\x89\x8e\x1d\x5c\x2c\x55\x28\xeb\xeb\x8b\xe6\xdd\x28\x29\x1e\xc9\x98\x5f\xe6\x5a\xa3\x1b\xbf\x9c\x43\x47\xbd\xe6\x31\x15\xd9\x8b\x4a\x2f\xca\x07\xea\xc1\xd4\xed\xc4\x2b\x68\xd6\xd0\x51\xa7\xd5\xab\x94\x4d\xdc\x3e\x3f\xbb\x26\x78\x58\xca\x96\xf6\x8f\x6a\xd5\xfd\xd3\xe6\x91\x3a\xac\xf4\xdd\x04\x96\xd4\xe1\xd9\xa4\xdb\x1e\x3e\x44\x56\x54\xa2\xad\xda\x61\xb1\x19\xbb\x7e\x78\x17\x4b\xef\xa4\xbc\x7f\x76\xe5\x0f\x2f\x26\x56\x69\x82\xae\xcf\x8e\xb3\x7e\x43\x1d\x86\xf9\x73\xe7\x8c\x66\x79\xd8\x7c\x68\x8c\xfa\x16\xc1\x57\x03\x6c\xe3\x38\x8e\x54\x87\x14\xfb\x51\x65\xe2\x9e\xc0\xbb\x0a\x2b\x54\x54\x9d\xc0\x70\xe8\x06\x51\xbb\xe0\x0c\xc6\x68\x98\x77\x8f\x8e\x7b\xe7\xb2\x7d\x36\xb0\x47\xed\xaa\x80\x4d\x9c\xbb\x77\xd0\x90\x14\xcf\xb5\x18\x38\x5d\xd6\x3e\xac\x9c\x43\xd2\xce\x17\xdb\x76\x29\xac\xe5\x86\x9d\xfb\x46\xc1\xe9\xc2\x9b\xd6\x7e\x2d\xaa\x84\xfb\x85\x93\xa3\xe8\x72\x98\x0c\xaa\x95\xe4\xea\xe2\xd6\x3b\x84\x34\x54\x63\xeb\x8e\x74\x6b\x98\x5c\xf7\xfb\xbd\xee\xfd\xb0\x16\x34\xcf\x86\x65\x18\xd7\x6d\x0f\x56\x2e\x06\xc3\x9b\xc3\x49\x82\xaf\x9a\x8e\xec\xf4\x2a\x45\xda\x0d\x4e\x4f\x78\xa1\x98\x6f\xdd\x16\xb3\x6e\xa1\x40\x26\xe3\x20\x7a\x38\x3a\x2b\xdd\x0a\x5d\x1c\xdd\x88\x4e\xf3\x66\x94\x1c\x97\xee\x49\x7b\x7c\xc2\x24\xf3\x5b\xa4\x59\x4b\x0e\xd9\x65\x70\x79\x53\xad\xf1\x93\x8b\x71\xef\xbe\xec\xc8\xbb\x56\x9f\xc0\xd2\x99\x31\xd7\x6d\x49\x46\xb9\xfa\x79\x30\x39\x41\xde\xd5\x1d\xbf\x08\x68\xf6\xaa\x7d\x61\xf4\x51\xe9\x78\x72\x8e\x6f\x27\x98\x17\x6e\xe2\x49\x81\x05\x47\xb4\x7a\x1f\x0d\xbb\xc5\x66\x2c\xea\xd9\xd3\x9b\x5b\xa7\x33\x3c\x4a\xc4\xcd\xad\x2a\x36\x0b\xa7\x63\xb7\x77\x39\xbe\x8e\x27\x8c\xeb\x73\xff\x7e\xff\xfc\xc4\x3d\x2f\xa3\x49\xe7\xd0\x5c\x3c\x48\x9f\x9d\x55\xfb\x71\x3a\xde\x7e\xd5\xf7\xf7\xc3\xc3\x89\x17\x57\x70\x8e\xd2\xac\xa4\x46\x9a\x7e\x83\x1e\xc5\x50\x04\x76\xdd\xc1\x7e\xa9\xcb\xc7\x67\xe7\x47\xd7\x27\xd9\x46\x37\xaa\xf0\xfc\x09\x69\xdd\x50\x1a\xa2\xfd\x41\x74\x7b\xd1\x47\x4a\x98\x8b\xee\x8d\x3c\x25\x93\xec\xa5\xf5\xd0\x1a\xb2\xda\xfe\x04\xaa\x51\xe7\xf2\x50\x57\x5a\xac\xee\xb7\x3d\xe4\x5f\x5c\x0d\x27\xb1\x3a\xb5\xfb\xb5\xc8\x41\xb7\x97\x95\x2b\x0e\xdb\x59\x32\x18\xd5\x6d\x33\x2c\xea\x91\x18\x89\x41\x47\xc6\xf5\x9b\xfe\xf1\xb0\x7b\x3d\xac\xe6\xa2\xc6\x7e\xbe\x59\xef\xe9\xc3\x7e\xff\xb4\xdf\x6a\xdc\x24\xb7\x77\x97\x50\xa6\xe3\x0d\xa2\xf1\xb1\x73\x5e\xa8\xbb\x37\x6e\xef\xd6\xc1\xc6\x92\x54\x95\x2f\x2b\x87\x3e\x31\xc2\x74\xcf\x1f\x68\xb1\xb0\x4f\x8e\x79\xfb\xce\xd6\xed\x30\x37\x56\xfb\xe8\xea\xfc\x21\x99\x94\xa3\xc0\x6e\xdc\x9e\x38\x25\xe7\x2c\xc7\x2f\x1f\xee\xcd\xc0\xad\x4c\xf2\x0f\xd5\x1a\xcc\x9e\x5e\x94\x82\x49\xf6\xb8\x51\xf2\xc9\xcd\xcd\x83\xf0\x13\x95\x3d\x54\x37\xa8\x1a\x44\xad\x6e\xfb\xea\x26\xdf\xbc\x13\xa3\x07\x4b\x67\x47\x8d\x46\xfb\xa4\xf0\x70\x3d\x1e\x36\x7a\x16\xbd\x70\x6f\x0a\xbd\xeb\x42\x15\xdf\xdf\x27\xed\xfd\xec\xa4\x1d\x25\xd7\xdd\x6a\xf9\x7a\x94\xc3\x6d\x38\xae\xe4\xfa\xaa\x92\x6f\xdd\xe6\x0a\xc1\x89\x9b\x73\xca\x51\xa1\xa1\xc7\xc5\xd1\xa1\x3d\x52\xb5\xde\xf5\x64\xd4\xed\x91\xf1\xbd\x3e\xba\x2c\xb6\x1d\xff\xb4\xd4\x23\xf7\x34\xac\x0d\x4a\xfd\x11\xac\xd8\x47\xf2\xb0\x59\x39\xf5\x2e\x6b\xb5\x01\xec\xdf\x9e\x59\x85\x16\x6f\xde\x47\x78\xd8\xeb\x8b\xa0\x10\xc0\xdc\x91\x75\x89\x8b\xe3\xf1\xdd\xa4\xbf\x5f\x72\x68\xbd\x4c\x8f\xe3\xeb\xb6\x85\x4b\xf7\xd5\x4b\x3c\x32\xd4\xe9\x1f\x5f\x17\x6f\xb2\xd1\x7e\x92\x2d\x75\xec\x2b\x34\x11\xce\xe4\xaa\x15\xc0\x4e\xb9\xda\xcf\xdd\x84\xa7\x0f\xe2\xf8\xaa\x38\x2a\x96\x1b\x17\xa3\x87\xf6\xf5\x6d\x0d\x7b\xb5\x61\x90\x87\x56\x6d\x74\x96\x6b\xd5\xf2\xdc\x15\x13\xc9\xaf\x27\xfa\xe2\x7c\xdf\x8c\x74\x3b\xfb\xe0\xdf\x74\x86\xe7\x83\xcb\x8b\x9b\xa1\xa7\x2f\xe2\xe4\xba\x55\xee\xd3\xe8\x64\x60\xfc\x0a\xbf\x42\xf9\x93\x9a\x73\x8c\x3b\xb2\x72\xc8\xe3\x31\xf3\x2d\xbb\x70\xb9\x1f\xdc\x57\x0d\x1b\x3b\x95\x18\x5d\xd5\xc6\xc1\x48\x1c\x35\xc8\xf8\x12\xdd\x9d\x34\xa3\xc1\x58\x8f\xdd\xf0\xe6\xbc\xda\xaa\xf1\x87\x8b\xee\x7e\x3b\x77\x74\xec\xe2\x63\x5a\x4d\xaa\x17\x85\xba\x46\x5e\x35\xcb\x24\x6e\x9d\x35\xbc\xc3\x09\xab\x50\xf8\x70\x74\x72\x7c\x9e\xcd\x0f\x26\xee\x91\xef\xf6\xcb\xcd\x6c\xfc\x60\xeb\x8b\xce\xb8\x74\x7d\x71\x7b\xd9\x5a\xaf\xf4\x57\xa8\xcb\xa7\x43\xdf\x6b\xf5\x9f\xef\x87\xa3\x03\x2d\xfb\x07\xc6\x4f\x0b\x28\x6d\x51\x65\x61\xa0\x13\xaf\xa7\x07\xb1\x9e\x6a\xc1\xd9\x31\xfe\xad\xad\xfe\x7a\x52\xc8\x7f\x49\x1e\x84\x81\xf7\x5c\xcc\xe8\xaf\xe7\xec\xef\x79\x98\x60\x34\x1a\x1d\x8c\xf0\x41\x18\xb5\x0e\x11\x84\xd6\xa1\x05\x0f\xc7\x3d\x1f\xe8\xb1\x04\xd2\x22\xc1\xff\xf3\x76\xe7\x69\xdc\xf3\x1b\x5e\xeb\x4c\x4f\x4a\x81\x09\xcf\x74\x5a\xce\xe6\x32\xe2\x41\x3c\xc5\xd3\xcc\x1e\x3a\xbf\x38\x2f\x7e\xcc\x68\xe6\xab\x7d\xa5\xaf\xce\x3c\x67\x52\x22\xa6\x8c\x04\xd4\x50\x0a\x08\x13\x10\x70\x9b\x2b\xe0\x40\x44\x2c\xc2\x2c\xa6\xd9\xd6\x4a\xa7\x4f\x45\x4c\xd6\xc0\x6d\x09\x1a\xac\x99\xcc\x23\xf4\xac\xbe\x4a\x3f\x0a\xfb\x3a\x4a\x26\xdf\x29\xc9\x7c\xe5\xfb\xcc\x52\x44\xe3\x60\x3a\xdd\xe7\xc5\x94\xe3\xb1\xb7\x2e\x27\x3f\x6d\x38\x1d\xf6\xc1\x53\xeb\x1d\xf0\x94\x99\x05\x62\x3c\x1d\x28\x7f\x72\xf0\x0a\xb9\x2b\xdb\x7c\x83\x8b\x18\x1c\xa9\x34\x72\x09\x70\x19\x45\x80\x38\x82\x03\x4e\x35\x02\x50\x52\x2c\xa9\x23\x21\x5f\xb9\x2d\x9d\x59\x64\x80\x0d\x82\x25\xf3\xc9\x00\xcf\x0c\xb0\x05\x4f\x99\x95\x0c\xf0\xd4\xe8\x3b\x31\x80\x45\x6d\x6a\x43\x4e\x01\xa3\x46\x01\x62\x2b\x09\x98\x46\x1c\x40\x29\xb5\x03\x25\x77\x99\x78\x99\xc9\xf4\xd4\xc3\xe3\x18\x0d\xef\x79\xfe\x24\xb3\x2b\x0f\x7c\xd5\xb1\x93\x29\x3e\x7a\xa1\xd2\xfe\xcf\x63\x89\xe9\x10\x52\x65\x92\x26\x23\x1c\x48\x9f\x7b\xbd\x0d\xde\xe2\x52\xbb\xb7\x8b\x04\x4f\xbd\xf5\x3b\xb3\xfd\x9d\xb7\xb6\x4a\x01\x0f\x96\x49\xfa\xd7\x36\x76\xed\xc4\x61\x70\x39\xe9\xeb\x03\xff\xb1\x86\x52\x23\x89\xbc\xa0\xf5\xbd\xb8\x95\x11\xc2\x15\xa6\x1a\x48\x57\x42\x40\x2c\xe6\x02\x66\x3b\x1a\x30\x26\x34\xc7\x86\x70\xee\x6e\xd5\x57\xcf\x95\xb9\x3e\xe5\xd5\x42\xc3\xd7\xdc\xb9\x0d\x51\x99\x95\x02\xeb\xb9\xd5\x77\xe2\x01\x1b\x6a\xc6\x89\xb0\x01\xc5\x76\x5a\x80\x42\x00\xe6\x4a\x17\x38\x52\x73\x62\x88\x25\x38\xdf\x7a\xbf\xee\x5b\x54\xd6\xa7\xb8\x7a\x8b\x02\xfb\x39\xe2\xaa\x9f\x96\x75\x8c\xb4\xfa\x6b\x97\x31\xfe\x68\xa9\x45\x0d\xb7\x94\x0d\x19\x70\x1d\x6e\x00\x21\x8e\x06\x94\x68\x38\x15\x62\xdc\x62\xca\xb8\x50\x6d\xbd\x7b\xac\x69\x43\x98\x99\xa5\x10\xfc\x2b\x89\xad\x41\x14\xfc\x19\xf2\xd8\x8b\xff\x9c\x3e\x8f\xff\x4c\xe4\x9f\x8d\x6c\xa5\xfc\x27\x3a\x80\x7f\x4e\xdb\x4c\x9f\x82\x19\xf8\x9f\x83\xe8\xe5\x69\xc2\xa5\x4f\xbc\xe6\xe7\x4d\xe8\xcc\xac\x14\x6e\x5b\x5b\x2c\xcf\xe3\x69\x06\x9e\xfa\xd3\x3a\x40\x07\x94\xc0\x03\xcb\xc2\x36\x61\x07\xd6\x01\x3b\xb0\xbe\x17\xc3\x09\x5b\x2a\x2a\x6c\x0c\x10\xb4\x2c\x40\x10\x67\x80\x0b\x8c\x81\x30\x82\x4a\x47\xbb\x96\x0b\xb7\xde\x82\xf5\xaf\xc7\x6b\xef\x50\x91\xef\xe0\x20\xf0\x76\x16\x5a\x91\x39\xf4\xf8\xfb\x06\x97\xda\x32\x86\x8c\xe0\x1a\xd8\x10\x21\x40\x0c\xe7\x80\x33\x2e\x01\x97\xc8\x72\x6d\x63\x41\x07\x6d\x35\xa9\x76\xe6\x95\x4f\x5d\xba\x33\xe7\xfc\x1c\x45\xba\x75\x58\x3f\x5a\x77\x6a\x61\x5b\x16\x75\x6d\xe0\x20\x97\x01\xa2\x2d\x67\x2a\xc5\x04\xe0\xb6\x30\x0e\xd1\x82\x71\xba\xb6\x08\xec\x93\x49\x3a\xf0\xfd\x1f\xe3\x9d\x4e\xbf\x04\x52\x9d\xf4\xa3\x39\xf3\x47\xb1\xcb\xc6\x15\xf0\xbd\xec\x27\x09\x05\xc4\x5c\x02\x87\x6a\x09\x88\xd0\x12\x30\x65\xd9\xc0\x81\xca\x46\x8e\xa4\xc8\xb0\xad\x41\xaa\x96\x37\xd4\xc1\x67\x88\xe2\xcd\x72\x6a\x27\x27\xf0\xe7\xc8\xaa\x94\xa4\x1f\x2e\x44\x41\x11\xd4\x70\x2a\xab\x1c\x6d\x13\x40\x5c\xea\x02\x06\x95\x02\x4a\x32\xc1\x28\xd6\xae\x42\x5b\x03\x6a\xaf\xce\x03\x3e\x41\x7c\x1a\x5e\xc9\x66\x0c\x65\x56\x5a\x5d\x9e\xfa\x6e\xd1\x08\x49\x18\xc6\x86\x03\xa5\x05\x9f\x9a\xda\x0a\x50\xca\x6c\x40\xa4\x70\xa9\x24\xdc\x41\x78\xeb\x5d\x85\x51\xe8\xeb\x8c\xef\xc5\x5b\x05\xcd\x3b\xa9\x3e\xed\x1f\x4c\xfb\xff\xe1\x14\x8f\xbd\xa0\xe5\x6f\x4c\xbd\x79\x02\x7d\x37\x73\xbc\xb6\x97\xd3\x7b\x70\xbe\x17\xbd\xb9\x60\x16\xb7\x24\x70\x99\x22\x80\x50\xac\x81\x50\x0e\x03\xc2\xa1\xc4\x68\x4d\x1c\x6c\x6d\x5d\xde\x81\x27\xbb\x9f\x1b\x26\x2f\x1b\xbe\x5e\xe4\x5b\xf0\x94\x59\xb9\xd4\xcf\x1f\x1b\xed\xca\x00\x4b\x4f\xde\x5d\x4e\x2a\xbd\xbb\x29\x5d\xc3\x1b\xfb\x5b\x77\xc2\x63\xf7\xb3\x15\xef\xb8\x22\x7c\xe9\x6c\x45\x7a\x84\x0d\xcc\xea\x0a\xf7\x5e\x5f\xea\xf6\xba\x02\xc8\xcb\x06\xbf\x78\x2d\x90\xcf\xc3\x6a\x1f\xe3\x78\xc1\xbf\xc0\x61\xb5\xef\x54\xcc\xe3\xdb\xcb\x14\x09\x21\x57\x10\x52\x20\x91\xc1\x80\x60\x65\x00\xc7\xca\x06\x48\xb8\x4c\x18\xca\x39\xb4\x37\xca\x94\x58\xcb\x41\xe4\x25\x13\x30\x2f\xd6\xb6\x63\x01\xd7\xd5\xcd\xb6\xd7\x71\xcd\xce\x4f\x6b\x6d\x2c\xe4\x9a\xf6\xb9\x58\x8e\x74\xde\xfd\x6f\x53\xc7\x55\x63\x63\x90\x46\x16\xc0\x8c\x18\x40\x6c\xec\x00\x06\xa5\x06\xe9\xdd\x9e\xcc\x55\x9c\x59\xef\xa8\x72\xb1\x1e\x6f\x5f\x59\xff\x62\xff\x5f\xad\xfe\xc5\x67\x9d\xd7\x79\x8b\xcf\x3a\xaf\x8f\x77\x8e\x41\x22\x21\x66\x18\x60\x8b\xbb\x80\x40\x68\x00\x73\x1c\x0d\x98\xc5\x84\xc5\xa8\xe3\x72\xb9\x75\x1f\x30\x3d\x39\xf9\x23\x63\x58\x4f\x0c\xf1\x0b\x07\xb1\x36\x22\x2d\xf3\xf3\x22\x58\xdb\xc7\xf5\xd5\xd1\xab\x6f\xe3\xdd\x7c\x1e\x87\xdf\x78\x1c\xfe\xdf\x32\xab\xaf\x92\xd9\xe5\x1e\x42\x0a\x99\xa3\x29\x04\x0a\x5a\x70\x6a\x7a\x49\xc0\x29\x45\x00\x31\x47\x60\x85\xb9\xcb\x5f\x5f\xdf\xb5\x69\xb3\xe6\xe5\x21\xf8\x8b\xbe\x0e\x4a\x85\x4c\x7e\x26\x05\x32\x62\xe0\xf9\x09\xf0\x82\x4c\x7a\x2b\xcf\x9f\x2b\x33\x0a\xbe\xa1\xb6\xf0\x02\xe9\x0f\x94\x3e\xf0\x82\xf9\x42\x89\x1f\x6f\xf7\x79\xd7\xd1\xaa\x75\x8d\x96\x21\x0f\x92\xf9\x11\xd9\x7f\xff\x67\x3a\xbd\x94\x14\xf9\x19\xc8\xa5\x1e\x27\x7f\x6f\xd6\x37\x5f\x2d\xe6\x85\xe3\x6a\xad\x88\x05\x6c\x5b\x63\x40\x0c\xe1\x80\x2a\xe3\x02\xe5\x18\x43\x5d\xc4\xb0\x80\x5b\xcb\x79\x7f\xee\xa8\x7e\xee\xa8\xee\x2a\xe2\xdf\x1a\xc1\x34\x1a\x43\x87\x13\x40\x0d\xe4\x80\x30\xd7\x00\x4e\x31\x02\xdc\x75\x05\x85\xca\x18\x6a\x76\x63\xcf\xcc\xf0\xf1\x7e\xc0\x4f\x3e\xdd\xd8\x6e\x05\x9f\x5e\x6f\x46\x5d\xe6\x27\xf3\xeb\x5f\x5b\x48\x9b\x59\xcd\xb8\x22\x0c\x7d\xcd\x83\x77\x1a\x27\x3b\x87\x2b\xb0\x24\x8e\x32\x82\x01\xe8\x50\x17\x10\x57\x20\xc0\x34\x11\x00\x3a\xae\x52\x8c\xb9\xc2\x26\xaf\x3c\xdf\xa7\x7b\x12\x5e\x95\x50\xdb\xa2\x31\x53\x8d\x95\x31\x61\x94\xe1\x4a\x65\xb8\x8c\x32\xff\xef\xb2\x47\x92\x91\x61\x30\xd5\x38\x19\xe9\xf3\x38\xce\x3c\x5d\x30\xfd\xff\x65\x92\x30\x93\xb4\x75\x26\x25\xc7\xcf\xd0\xb1\x5f\x53\x9d\xef\xfb\xaa\x48\xec\x58\x2e\xc6\x08\x02\x86\xb8\x02\x44\x5b\x1a\x30\x4a\x20\xd0\xd8\x66\x10\x29\x4d\x2c\xfc\xf2\x0e\x9a\x55\x94\xcc\xf8\x21\xcf\xf8\x7a\xa8\xbf\xbf\xaa\xe4\x32\xfa\x05\x72\x3a\xbc\x20\x89\xc2\xb8\xaf\xe5\xac\xc2\xe4\x2f\x93\x10\xf2\x4e\x41\xa0\x1c\xc8\x09\xb1\x38\x20\x8a\x71\x40\x6c\x8e\x00\x17\x54\x01\xcb\x71\x85\xd1\x46\xbb\xea\x95\x43\xfd\xc4\x3e\xab\xfc\x82\x37\x1a\xcf\x2b\xbb\xf8\x7d\x8c\xe7\x74\x7a\x3f\xda\x78\xd6\x9a\xb8\xc2\x75\x34\x70\xb1\x36\x80\xb8\x12\x03\xce\xa0\x0b\x90\xa6\x46\x3b\x0a\x5b\x2e\x79\xe9\x0f\x3d\xf5\xb0\x44\xda\x4c\x30\xe8\x89\xf5\xab\xf5\x33\x52\xb2\xd2\x38\x49\x51\x77\xbe\x09\x73\x99\x9f\x67\x9a\xa4\x83\xfb\x6b\x23\x5d\x33\x3f\xc5\xa2\xe6\xd4\x21\xc4\xb5\x01\xe6\x8a\x02\xa2\x99\x0d\xa8\x41\x10\xd8\xd8\xe1\x8e\xb6\x94\xb1\x5e\x5d\x2a\xf0\xd4\xc3\x2a\x9e\xfd\x19\x86\xf5\x6f\xc6\xbc\x1f\xd7\xbe\x5e\x64\xe2\x8f\x6d\x66\xdb\x8c\x39\x0e\x91\x18\x68\xdb\xb6\x01\x81\x2e\x04\xdc\x71\x6c\x20\x0c\xb6\x88\xcd\x34\x87\xfc\xd5\x45\x81\x4f\xb7\xca\xbf\x0c\x9d\x6d\x56\xb4\x95\x05\xf0\x0c\xc8\x9c\xde\x5c\xbe\x50\xb6\xbf\x8c\x96\xfd\x11\xd6\x33\x41\xd4\x31\xc8\x60\xc0\xb0\xb1\x01\x71\xa7\x76\xb4\x86\x1c\x38\x92\x09\xa9\xa5\xa4\x5a\xbd\xdc\xae\x7d\x45\xa0\x41\x7f\xd5\x8d\xe5\x6f\xc3\xed\x9a\x19\xfd\x9e\x6e\xfb\xc7\x3d\xfc\xb6\x9e\x94\x99\x9f\xa1\x0d\x99\x4d\xb9\x25\x1d\x09\x2c\x2d\x15\x20\xb6\x0d\x81\xe0\x42\x01\x6d\x23\x57\x29\xdb\xb8\x4c\xbf\xf4\xce\x9f\x7a\x78\x4a\xed\x9d\xdd\x65\xfe\xe3\x18\x74\x96\xe4\x94\x26\x4a\xfe\x68\x16\x5d\xa8\x53\xf9\xd5\xfe\xd6\x9b\x38\xda\x84\xe1\xc7\x63\xe6\x8d\x94\xcf\x7c\x87\x2d\xb1\x9d\xd5\xa1\x43\x2c\xa4\x19\x33\x80\xab\xa9\x3a\xd4\xb6\x04\x02\x31\x0a\x04\xa1\x14\x73\x8a\x10\x74\xd7\xaa\xc3\xd5\x1b\x64\x6f\x75\x37\x57\x77\xf2\x61\x55\xe1\xdb\x1d\xce\xd9\x04\x7f\xb4\xcb\x69\x53\x48\x94\xe1\x36\x10\x2e\x12\x80\x20\x48\x00\x85\x0a\x01\xe5\x08\x23\x28\x36\xae\x63\xd6\x6e\xb8\x7f\x1e\x28\xff\x3d\x75\xea\xc7\x3e\x50\x0e\x19\xb5\xa0\x23\x29\x50\x08\x4f\x0d\x40\xc8\xa7\x52\x08\x01\x4a\x88\x2b\x11\xb7\x30\x81\x5b\x39\xf6\xf3\x50\xdc\xaa\x16\xbf\xce\xa1\x38\xcb\x48\x84\xb0\xe0\x40\xd8\x08\x01\xe2\x50\x08\xa8\x41\x06\x08\xc6\xa8\x6b\x29\x2a\x1c\xfb\x9b\x1e\x44\xf8\x8c\x33\xbc\xe9\x5c\xc2\xcf\x11\x5b\xbb\x8c\xec\x47\x0b\x2b\x47\xd9\xd8\x60\x2d\x00\x56\xc8\x06\x64\xca\xb2\x8c\x2b\x03\x18\x76\x2c\x57\x0b\x26\x9d\x57\x61\x84\xa7\x1e\x1e\xe7\xf5\x10\x06\x7a\x4a\xbb\x4f\x46\x7d\x13\xa3\x6e\x41\x5b\xe6\xe7\x31\xea\x2e\x23\xfb\xd1\x8c\x6a\x5c\x97\xb9\x5a\x38\xc0\xc2\xdc\x01\x04\x11\x1b\x70\x86\x15\xd0\x9a\xda\x14\x72\x17\x3a\xee\xd6\xb0\xca\x48\x8b\xd8\x4b\x3e\x05\xea\xdb\xf8\x74\x33\xd6\x32\x3f\x8f\x4d\x77\x18\xd8\x0f\xdf\x6c\xb0\x2d\x24\x14\x71\x00\xb3\x5d\x08\x88\xb0\x05\x10\x16\x35\x80\xb8\x4c\x12\xd7\x35\xae\xd9\xae\xf7\x5b\x3a\x50\x9f\x5b\x63\x6f\x64\xd2\x8d\x48\xcb\xfc\xc4\x88\xc9\xd6\x71\xfd\x68\x16\x75\x35\xe4\x4c\x11\x08\xb4\xa5\x2c\x40\x28\x56\x40\x48\xdb\x01\xb6\x94\xc2\xd1\xb6\xe0\x96\xda\xaa\xf1\x7b\x9e\x52\xbe\xfe\xd1\x05\x1b\x7e\x07\x3e\x9d\x61\xee\x63\x96\x6c\x98\x8d\xed\xc3\xd5\x6c\x70\x84\xcb\x25\x14\x12\x70\x0a\x2d\x40\x94\x63\x01\x06\x11\x04\xca\x18\x84\x19\x16\x58\xa3\xad\x21\xeb\xf5\x39\xf0\x99\x4f\x66\x5d\x68\xf7\x62\xcb\x76\x23\xd6\x32\x3f\x33\x00\xb4\x75\x60\x3f\x9a\x4b\x91\x25\x85\x0d\x15\x05\x8a\x70\x08\x88\xc4\x04\x50\x8e\x2c\xc0\x6d\x65\x73\x6a\x11\x89\xc8\xd6\xaa\x6e\x9f\xc7\x87\x3e\x8f\x0f\x7d\x4f\x17\x8a\xdb\xae\xd2\x5c\x01\xa4\x39\x06\xc4\x66\x1c\x08\x66\x73\xe0\x5a\xda\x50\xae\x0c\x17\xd6\xd6\x6a\x28\x9f\xd5\xa4\x3f\xab\x49\xff\x18\x6e\x95\xae\xd4\x9a\x6b\x0e\xb0\x74\x08\x20\x74\xea\x54\x49\xe1\x02\xcb\xa5\x96\x32\xae\xb0\xb9\xda\x2a\x50\x3f\xeb\x8a\xbd\x73\xf3\xf9\xb3\xae\xd8\xdb\x98\x95\x48\xc9\xb5\x20\x08\x60\x64\x20\x20\x08\x0a\xc0\x08\xa4\xc0\x36\x4a\x50\xe9\x4a\xcc\xcd\x56\x1b\x55\x78\x51\xd2\x56\xfc\x33\x3e\xf5\x46\x66\xdd\x86\xb7\xcc\xcf\x63\xd6\x9d\x86\xf6\xc3\x79\x55\x73\xcd\x98\x83\x81\x8d\x8c\x02\x44\x58\x0a\x30\xc7\xb2\x80\x85\x6c\xe3\xba\xd8\xb5\x04\xdc\x1a\x00\xe8\x7b\x32\xbd\xb6\xef\x93\x53\xdf\xe4\x4f\x6d\xc4\x5a\xe6\x27\xfa\x53\xdb\x07\xf6\xc3\x77\xd1\x5d\x08\xa1\x74\x34\xb0\x88\x46\x80\x40\xe1\x00\xca\x39\x04\x12\x09\x88\x91\x31\x8c\xf2\xed\x79\x1f\xfd\xe9\xda\x53\x19\xbe\x53\xed\xbe\x4f\x46\x7d\x4e\xfd\x98\x21\x2e\xbb\x0e\x0b\x99\x9f\xc7\xaa\xf3\xa1\xfd\xb5\x96\xa6\x99\x6f\xc2\xad\x4b\x4f\x76\x4f\x43\x63\x0e\x24\x96\x65\x71\x60\x31\xa2\x01\x51\x6a\xea\x62\x21\x0d\x90\xb0\x5d\x86\x94\x84\x14\xbe\xac\xd7\xfd\x7c\x64\x6e\x65\x99\x84\x37\xa6\xa1\xad\xe9\xe4\xf7\x49\x43\x9b\x4f\xf0\x47\xa7\xa1\x49\x45\xa4\x36\xae\x02\x0a\x4e\xbd\x11\x89\x5d\x40\x21\xb3\x80\x43\x89\x6b\xdb\xae\x85\xf5\xf6\x9b\x98\xd6\xd7\xc1\xc8\x7c\x53\x59\x34\xff\xce\x4f\x91\x3f\xcf\x72\xe4\x60\x56\x5d\x32\x99\x25\xce\x3e\xff\x67\x67\x41\x74\x90\x96\x61\x8a\xd2\x1b\x78\x1f\xff\xdc\xbd\x71\x3f\x8c\x13\xee\xff\x25\x43\x35\xd3\x70\x0b\xff\xdd\xd2\xc9\xd7\x8b\xd0\x83\x38\x89\xf4\xac\x0e\xd8\xfc\xaf\x6f\x2a\x46\x5f\x7c\x2c\xd2\xad\xb9\x6c\x98\xff\xf5\xcd\x25\xf0\x8b\x0f\xa6\x91\x2d\x2f\x99\x3c\x45\xb9\xa6\x7f\x7f\x67\xc1\x8a\x1d\x5b\x28\x2d\x24\x80\x10\x0b\x40\xb0\xe5\x02\x8e\x38\x02\x54\x11\x4b\x22\x89\x95\xed\xbe\xac\x8b\xf0\xb4\xee\x36\xd6\x92\x79\xa3\x7c\xdd\xdc\xd7\xb7\x13\xb3\x6b\xe5\xdf\x7c\x00\xb3\xaa\x66\xaf\xa5\xe0\xbb\xe4\xef\xbf\xad\xa6\xd0\x36\x9a\x50\x24\x28\x72\xb0\x01\x8e\x46\x14\x10\x0c\x2d\x40\xb9\x65\x03\xc8\xb5\x31\x4c\x48\x57\xaa\x97\x32\x71\xa9\xaa\xf2\x5f\x2b\xaa\x2a\xbf\x24\x47\x23\x5b\x29\x67\xd6\x95\x60\xde\x56\x8b\xf7\xfd\x58\x9e\x76\x56\x0f\x7d\x5d\xf6\xe2\xe4\xbb\x20\xf9\x5b\xeb\x27\xca\x88\xad\x6d\xcb\x01\x04\x0b\x1b\x10\x6b\xaa\x9f\x0c\x27\xc0\x51\x0e\xc7\x14\x29\xe9\xda\x5b\x03\x10\x9f\x95\xae\x7f\x62\xa5\xeb\x77\xca\x45\xc2\x5c\xe2\x50\xed\x00\xd7\x48\x02\x08\x53\x12\x30\xec\xba\x40\x6a\x8b\x28\xe9\x62\x65\xc8\x5a\xb9\xb8\xaa\xfa\xd7\x9b\xea\x6d\x4c\xf5\x42\xba\x38\xe3\xc7\x6a\x1a\x33\xb1\xf8\xab\x15\xd5\x78\xb3\x11\x9a\xce\xf9\x47\x9b\xa0\xc4\x46\x9a\x43\x02\x81\xb1\x1c\x05\x88\x44\x1a\x30\xc7\x81\xc0\x76\x39\x35\x2e\x72\xa8\x22\x5b\x2f\x5b\xe1\x03\xe5\xe9\x40\xea\x4c\xa4\xe3\xd0\x1f\x7e\xff\x00\xce\xe3\x07\xc1\xfc\x83\xdf\x69\xe9\x7f\x83\xab\x6c\x2c\x69\xa8\x51\x1c\xd8\x8a\xc1\xe9\x42\xa2\x40\x58\x44\x01\x25\x2d\xa2\x2c\x6a\xb9\x5c\x6d\xbd\x69\x29\x3d\xa7\x96\x59\x57\x54\xef\xdb\x22\xf6\x43\x9c\x8e\x7b\xf3\xb1\xb5\x6f\x11\x01\x48\xe7\x3b\x37\xc0\x0e\x36\x21\x3b\xb3\x31\x12\xb0\xa1\xcd\xaa\x43\x7f\xdf\x2b\xcc\xe5\x40\x8c\x2c\xe1\x02\x29\xa1\x05\x08\x27\x10\x70\x2a\x21\x70\x2c\x68\x13\x83\x34\xb3\x9d\xad\x69\xad\xb3\x9a\x86\x3f\x9c\xef\xe6\x95\x90\xff\x95\x18\x2f\x0e\x07\x91\x7c\x34\xfe\x0f\x9e\x4a\x65\x7b\xea\xef\x8f\xc7\x88\xef\x34\x28\x24\xb3\x2c\xa5\x35\x01\x1a\x2a\x0c\x88\xc3\x0c\xe0\x16\x85\x80\x71\x2e\x18\xb2\xa4\x72\x5f\xa5\x07\x2e\xe6\x57\xaf\x29\x44\xfa\xb6\x32\x5e\xb3\xa2\xc0\x99\x91\x16\x99\x79\x77\xbf\xb6\x7d\xb1\xb6\xd5\x1a\x03\xe3\x3b\x1b\x12\x4c\x2a\x8a\xb4\x41\x00\x21\x46\x01\xd1\x58\x00\x61\x4b\x17\x20\x77\xea\x37\x30\xc9\xa0\xde\xba\xb3\xbe\x82\x46\xdf\xdf\x96\x98\x7d\xf3\x91\xc5\x7e\x9c\x29\xb1\x6e\x29\xa5\x7f\x3d\x56\x96\x9d\x97\xeb\x2d\x6c\xa9\xda\xbb\xd2\xf3\x5d\x91\xd0\xf6\xaa\x34\xe5\x2b\x73\x7d\xcd\x72\x4b\x8b\xe8\xad\x1a\xd9\xc5\xb6\x82\xbd\xeb\x03\x25\x2b\x42\x97\xaf\x4a\x74\xad\x29\xc8\xfb\x38\x08\x11\x85\xa3\x58\x47\x8d\xf9\xad\x02\x27\x9a\xab\x19\xf3\x3e\xb3\xea\x5e\x5a\xab\x2f\x48\x1e\x61\xaa\xa1\xef\xc9\x49\x5d\xf7\xc3\x28\x99\xd7\x97\xdf\x5b\xfc\xe0\x38\x3f\x83\x9f\x4a\xd5\xd9\xe4\xd2\x3a\xe7\x41\x18\x07\xde\xd2\x76\xfb\xde\xfc\xbc\x68\x34\xeb\x71\x06\x04\x1e\x1f\x2e\x75\x59\x0f\x45\x98\xc4\x97\xbc\x35\x03\x5a\x9e\xe1\xf8\x28\xe2\xbd\xc5\x4f\x35\xb2\x95\xe2\x45\xbd\x74\x5c\x3a\x5f\x04\x5b\x39\x8d\x54\x0e\x4c\x9b\x83\x38\x92\x99\xff\x88\xb5\x6f\xfe\xe3\x3f\x33\xb3\x27\x3c\x90\x3a\x4e\xc2\x28\x7e\x7a\x1e\x8a\x8e\x96\xc9\x0c\x74\x3a\x8a\xff\xf8\xcf\xa5\x71\x34\x1b\x8d\x6a\x14\x26\xb3\x4a\x72\xd3\x9e\xad\xff\xcc\x4c\x95\xf2\x3f\x84\x1f\xca\xee\x22\x68\x9c\x44\x9e\x4c\x2e\x23\x1e\xc4\x53\x34\x3e\x8e\x69\xda\xa6\xc7\xc7\x80\xb7\xf4\x3f\xb0\x65\x63\x07\x42\xf8\x9f\x99\xb9\xdc\x6b\x0c\x44\x21\xec\xf1\x29\x5b\xa5\x1d\xcd\x05\xd0\x5e\xdc\x4b\xfa\x0d\x1d\x0d\xd3\x25\xf9\x58\xd3\x7d\x4f\x0f\xf5\xba\x62\xf9\xf3\x77\x65\x2f\x4e\x74\xf0\x52\x54\xed\x75\x44\x18\xc7\xc0\x0f\x5b\xad\xa7\x8d\x99\x47\x66\x99\xdf\xe4\x50\x1c\xce\xa9\xbb\x78\xb3\xc6\x5e\x7a\x07\x42\x71\xc3\x57\x17\x00\x0a\x3a\xe1\x9e\xbf\x06\xce\x53\x3a\x48\xa6\x04\x8a\xc2\xa1\x37\xe7\xc6\xa7\xaf\xbc\x7c\xb9\x20\x6d\x9f\x6a\x49\x87\xbd\x7e\x18\x4c\x3f\xb3\xcc\xc6\x61\xd4\x3a\xe8\xea\x89\xf4\x43\xde\x3d\x98\x5f\x2a\x10\x1f\xcc\x6c\x85\x68\xa1\x98\xfd\x41\x3f\xe5\x8c\x83\xd9\x82\x5c\x2c\x73\xff\xc4\x32\xcb\x92\x7d\x95\xaa\x9a\x29\x6d\xaa\x18\xb2\x1d\x06\xb8\xe0\x18\x10\x89\x25\x60\xae\xab\x00\xc7\x36\xb3\x2d\x61\x0b\xb8\xf2\xd8\xc9\x93\x34\xbf\x8c\x06\x71\xa2\x55\xe6\x24\x8c\x93\x75\x35\xc4\x53\x2c\x94\x1e\xed\x90\x29\x38\x68\xaf\x03\x8f\x07\xe2\xf1\xbe\x0c\x1e\x84\xc1\xa4\x17\x0e\xd6\xc1\xe5\x97\x90\xb8\xc2\x7c\xde\x66\x0f\xee\x4d\x47\x01\x62\x9d\xde\x3a\x00\x16\xf1\x0b\x22\x7d\x3f\xd0\x71\x02\x7a\x83\x34\xe6\x94\xc8\xf6\x4a\x65\xf9\xd4\xd3\x7a\xfb\xea\x7f\xd7\xa9\x8d\x99\x0d\x3c\x88\xbc\xf8\x5b\x7c\x65\x8b\xea\x79\x81\x9d\xb5\xec\xc0\x8d\x84\x0e\xa7\x0e\x10\xc8\x48\x40\x6c\xd7\x06\x9c\x29\x07\x38\xd8\x71\x99\x6b\x41\x68\xdb\xab\xae\x32\x78\x62\x87\x0a\x1f\x67\x66\x4c\x19\x67\xca\x5e\xcf\x5b\xa5\xa8\x5f\xb0\xc4\x54\x98\xcc\x90\xf1\xf3\x19\x62\x71\x2c\x1b\x29\x81\x20\xfc\xbe\x84\x40\x18\x69\xa9\x84\x00\xca\xa6\x16\x20\xcc\x10\x40\x19\xb6\x81\x41\x4a\x21\x66\x14\x61\xaf\xb6\x83\x33\x8b\x84\x98\x5f\x8f\x31\x27\x46\x66\xae\xb3\xb7\x12\xe3\xd1\x50\x9a\x73\x67\xa2\x7b\x7d\x9f\x27\xab\x5b\x2e\x52\xe6\xb9\x72\xee\xca\x7d\xba\x6f\x43\x9d\x74\x70\x60\x6e\x93\x80\x78\xfd\xbd\x01\x4f\x2d\xbe\xff\x82\x31\xc6\xd5\x4c\xb9\x36\x70\x18\x46\x80\x48\x42\x01\x25\xae\x01\x92\x48\xc5\x84\x0b\x89\x76\x56\x65\x46\x3f\xd1\x69\x1e\x05\xcc\x3c\x19\x9b\x5b\x49\x34\xb7\x4e\x53\x11\xb5\xae\xc5\x77\x5a\x34\xef\x43\x11\xd3\x44\x33\x2a\x25\xd0\x38\x2d\x0a\x4c\x0d\xa0\x02\x31\x40\x18\xb4\xa5\x6d\x94\xcd\x57\x16\x26\xff\x59\xac\xfc\xdd\x85\xcc\x47\x64\x63\x5b\xbb\x9a\x42\x8a\x01\x26\x8e\x02\xc4\x55\x1c\x08\x04\x05\xe0\xc2\xa6\xc4\xb6\x5c\x57\x2a\xb4\x89\x46\x47\x03\xdf\x9f\x51\x26\x53\xf0\xe2\x99\xc9\xb4\x95\x42\xab\x2a\x00\x66\x3e\x1c\xfb\x4a\x29\xb0\x6b\x41\x17\xc0\x34\x41\x17\x13\x07\x50\x46\x5c\x20\x0c\x32\xb6\x45\x24\x92\x72\xa3\x85\xf4\xc8\xbe\xd5\xb9\x6b\x9a\x99\xd9\x83\x99\x99\x75\xba\x33\x1b\x3f\x7a\xb6\x73\xdf\xf5\x83\xb0\xf1\xeb\x81\x81\x64\xb2\x95\x9f\xdf\x95\xf6\xfe\xdc\x32\x6e\x73\x64\x3b\xa0\xcf\xbd\x68\xe4\xc5\x1a\xc4\x03\xb1\x43\xd3\xb7\x6c\x24\x3e\x37\x48\x2f\x5d\xdd\x31\x31\x6f\xd5\xdc\xde\xdc\x74\xc7\xaa\x3a\xcf\x0d\x76\xca\xd9\x79\x31\xa1\x97\x18\xff\xae\xb2\x45\x73\x4b\x10\x57\x21\x80\xa8\xe4\x80\x08\x8c\x00\x75\x98\x00\x42\x20\x57\x42\xee\x48\x68\xad\x94\x02\x3f\x79\x01\xfd\x38\x93\xe6\xa7\x2c\xa2\xdd\xd9\xe6\xcd\x6c\xf9\x15\x0b\xe7\x07\x2d\xed\xaf\x58\xa4\xdf\x7a\x11\x3d\xfd\x6f\xc1\x51\x5c\x8e\x03\x4c\x3f\x36\x0f\x8e\x1d\x5c\xc5\x3a\xaa\xce\xfe\x7e\x0c\x2f\xec\xee\xeb\x43\xc7\x42\x8c\x12\x1b\x18\x8e\x05\x20\x04\x21\x20\x1c\x63\x80\x46\xae\x30\xb6\x6b\x84\xa3\xe1\xf6\xf5\xa4\xb4\xf4\xf9\xd4\x4d\x1e\xea\x27\x3c\xac\xbb\x25\xec\x9b\xac\x91\xae\x4c\x51\x70\xf0\x88\x83\x27\xf8\x0d\x8b\xe3\x9f\x5f\x16\x42\xf5\x5f\xf6\xfe\xfc\x9f\x7f\x7e\x49\xe5\xc9\x97\xbd\x3f\xbf\x3c\x95\xa7\xfb\xb2\xf7\xc7\x97\xc7\xf0\xfb\xf9\xe3\xcb\x7f\xff\xe7\xe3\xeb\xbf\xd3\xf7\x43\xee\x7b\x2a\x0d\x0a\x4c\xfb\xf9\xe7\x97\x3d\x5f\x07\xad\xa4\x3d\xfb\xbb\xe7\x05\x5f\xf6\xfe\xc4\x7f\x7c\x99\x7a\x8e\x5f\xf6\xfe\x44\xb6\xfd\xf7\x1f\xcf\x1f\x98\xa2\xa6\xed\x09\x2f\x99\x9a\xa1\x6d\x1e\x71\x99\xe8\x28\xed\x26\x85\xea\x83\x27\xc0\x20\x4c\x80\xa7\x02\xd0\x0e\x7b\x61\x2b\xe2\xfd\xb4\xff\xbf\xa7\x50\x7d\x1d\xf5\xbc\x38\x7e\xfe\xfe\xd0\xd3\xa3\xe9\x8c\xbe\xcc\xa2\x55\xe9\x20\xa7\xfd\x7c\xd9\xfb\xdf\x3f\xbe\xec\x69\xe5\x25\x6b\xde\x4e\x7b\x5b\xd8\x16\xfa\xb2\xf7\x67\x1a\xd2\xfa\xfb\x8f\x45\xdc\xa4\xb1\xe3\x35\x88\x49\xdf\xad\xc1\xca\xbc\xdd\x6c\x66\x4b\x28\x7a\x42\xcc\xf4\xcd\xa3\xd3\x32\x7b\x97\xc6\xa5\x67\xa3\x5d\x18\xe3\x0f\x9e\xf1\xd3\x89\xb5\x35\xb3\x7e\x7a\xbf\x0b\x3f\x2c\x72\xc1\x54\xc9\x84\x01\xd8\xc2\x08\x1f\x14\x2b\x8f\x87\x4e\xd7\x20\xe5\xf1\xf5\xbf\x14\x4e\x1e\xab\xb0\xad\xc4\xc9\xf9\xe2\xcb\x17\x08\x99\xf6\xce\x83\x20\x4c\x96\x1f\xad\x1d\xfe\xca\xc1\xae\x1d\xe3\x14\x7a\x56\x5e\x77\x95\xa0\x03\x3d\x9d\x70\xc5\x13\xbe\x38\xea\xd9\x1e\x4a\x0a\x33\xd5\x28\x99\x55\x30\x85\xe7\x7d\xd7\x14\x30\xfb\x24\x4f\xff\xc8\x8c\xda\x9e\x6c\xcf\xae\x44\xca\x24\xe1\x2c\x9b\xeb\xb9\x8f\x74\x44\x83\x60\x76\xb5\xbc\x7a\x6a\x37\x0b\x4d\xa7\x7d\x15\xcf\xb3\xb9\x72\xb1\xf0\x65\xef\xef\xef\xa6\x35\xbb\x7a\x12\x1f\x9c\xe9\xc9\xdb\xd5\x24\xa2\x44\x21\x65\x51\x60\x98\x4b\x00\x11\xd0\x00\x41\x8c\x0d\xa0\x65\xdb\x2e\xb4\x90\xed\xaa\x55\xd9\x52\xcf\x1b\x9c\x3a\x06\x2d\x1d\xe8\x68\x9d\xe5\xf8\xc2\x3e\xdd\x06\xfe\x6d\x94\x68\x3a\xb7\x0d\x1a\xd3\xe1\xcc\x58\xd4\x45\x40\x08\x6a\x01\xe2\xd8\x16\x10\x92\x69\xe0\x5a\x5c\x08\x0b\x23\x17\x13\xf5\xb6\x08\xf7\xd3\x95\xd6\x1b\xbe\x5a\xf0\xae\xc2\x53\x28\x5b\x57\xd9\xf1\xd5\xa0\x76\x67\xc4\xd8\x77\x40\xf6\x6d\xdf\xe9\x47\x5e\x38\xdf\x99\xda\xf0\x25\xeb\x7b\x47\x6c\x2d\xa8\x38\xb3\x2d\x1b\x50\xad\x0d\x20\xd8\x70\xc0\x98\xb2\x01\x73\xb1\xc0\x16\x35\x0c\xd2\x8d\x6c\xd3\xee\x71\xf9\xcc\x08\xa0\x1d\xdb\xd6\xca\x90\xcb\x32\xf7\x2c\xb7\xfa\x79\xec\xa3\x2c\x5b\x73\xec\x48\x20\xb9\xe5\x02\x42\x2c\x08\x84\x14\x0c\x38\x90\xda\x8e\xc3\x5c\x2e\xe9\x3a\xfc\x7f\x05\xfb\xa8\xea\x5f\x67\x9e\x3e\xae\xb7\xb9\x0a\x2f\xae\xda\xb5\x4e\xb1\x71\x7f\xc1\xa8\x3c\x7e\x98\x5c\x0c\xef\xdb\x47\xad\xe3\x92\x53\xae\x8f\x4f\x93\x87\x66\xb6\x9d\x75\x8f\x0d\x7c\x08\x1e\x38\xbc\xe8\xe7\x8e\x45\xa1\xd4\xab\x17\xfd\x9b\xe1\xf8\xb6\x71\x0a\x72\x7f\x79\xa7\x56\xf7\xa1\x38\xbe\xf2\x7a\xe7\xc5\x71\x13\x95\x2b\x67\xed\x06\xa9\x80\x11\xe9\xd5\x0a\xb9\x3c\x94\x7e\xd0\x0c\x74\xde\xef\xc1\xc6\xc5\xc3\x43\x4e\xab\x76\x89\xb4\xc8\x59\x0f\x67\xdb\xad\x8e\xc1\x4d\x67\x72\xc5\xfc\xb8\x7b\xc4\x8f\xb3\xb5\x82\xb8\xb0\xbc\xb1\x5b\x92\xf5\x73\x1f\xf2\x89\x68\xfa\xd9\xce\x9a\xf3\x63\xdf\x8b\xa7\xd7\x74\xcb\xfd\xd6\xb4\xdb\x76\x6f\x73\xbf\x27\x8d\x29\xef\x7d\xd7\xd5\xc2\x1d\xee\x38\xca\x46\x80\x63\x4a\x00\x21\xd2\x06\x1c\x1a\x0a\x94\xb2\x5d\x06\xa1\xe1\x9a\xae\xe4\xe6\xa7\x8c\xaa\x98\xbf\x45\xc8\x6e\x05\xff\x26\xab\xa4\x1f\x79\x43\x9e\xe8\x33\xbd\x85\x6e\x95\x52\xa9\x18\x8e\x4a\xb9\x6c\xf6\x2c\x9f\xad\x15\xb3\x49\x5b\x8f\x82\xa1\x7f\x96\x8b\x50\xb7\x25\xc4\xfd\xc5\x71\xbd\x30\x2a\x86\xa3\x07\x5b\x45\x9d\xfc\x20\x9b\xc5\xa5\x11\x3e\x6c\x8c\x6e\xfc\x7a\xab\x5d\x1e\xde\x88\xf3\xd8\x6f\x1c\xef\x5f\xd4\xd5\x00\xf2\x71\xa1\x58\x88\xf9\xad\xea\xdf\xd7\xee\x26\xdd\xe2\x71\x68\xdf\xe5\x4b\xc9\x30\x9b\xad\xc5\x57\xe4\x28\x7a\x08\x65\x35\xae\x66\x0f\x7b\x83\xf0\x3c\xbe\xbf\xbd\x85\xc3\x52\x4d\xdf\x8e\x4e\x4a\xa7\x95\xf3\xd0\xce\x4d\xf2\xad\x26\xed\x9c\x12\x27\xbe\xb9\xba\x4d\x98\x5d\x1d\x38\xd9\xdb\x9b\xd6\xe4\xbe\x5c\x69\x45\x90\x34\xda\x43\x78\xec\xb4\x92\xa1\x3a\xc4\xa7\xe5\xd1\xcd\x75\xfe\xc6\x1b\x9f\xe5\xef\xf6\xcb\xe7\x27\xdd\xb3\xdc\xf9\x59\xf1\xa4\x7f\x44\xce\x8b\x7d\x4c\xa4\x9e\xf0\xd6\x59\x24\x9c\x07\xdf\x15\xd9\x6c\x6f\x5f\xa0\x71\xdb\xb3\x51\xe3\xe4\x76\x78\x15\x37\xf3\xa3\x51\x76\x60\xb7\x5d\xe2\x9f\x07\x17\xe3\x6e\xbe\x95\xf3\x1b\xce\xc5\xb1\x87\x4e\x1b\x77\xce\xe1\x31\x1d\x50\x2f\x97\x8b\xd0\x69\x9f\x8c\xa8\x3a\x54\x96\x39\xb2\x85\x17\xe2\xea\x68\x52\xae\xb4\x0b\x87\x97\x17\x79\xbb\x1b\x49\x78\x75\x79\x62\xce\x6b\x76\xaf\xd6\x09\xcf\x2b\xd4\x64\x8f\xac\xe6\x59\xaf\x16\xe5\x8a\x8d\x87\x08\xdb\xc2\x62\x37\x0f\x85\x8b\x43\x58\x16\x78\x54\x2a\x64\x6b\xd9\x5c\x36\x2c\xe5\xb2\xb9\xa2\x7f\xb3\xdf\x8d\x2f\x5a\x14\x89\xce\xed\x55\xe0\x25\xa6\x7c\x8b\xf7\xa3\x9e\x49\xa2\xf1\x61\x65\x58\x09\x6f\xea\x24\x30\xb9\x66\xab\xcc\xf6\x79\x90\x5c\x95\xe4\xf8\xc4\x85\x3d\xaf\xf9\x00\x1b\xa5\xc3\xc1\xe0\xee\xba\x3e\x30\xf1\xd1\x7e\x74\xf1\x30\x90\xaa\xda\x71\x27\x03\x2f\x70\x2f\xfa\xd6\xf1\x15\x4e\x02\xd6\x65\x27\x24\x7b\x2d\x6a\xfd\x87\xc1\xc3\x45\xef\x36\x87\x63\xae\xac\xeb\x1b\x82\xcb\xde\x4d\xf6\xde\x74\x1d\xca\xf6\x87\xe5\x66\xb5\x71\x21\x8e\x8f\x0a\x81\x86\x17\x27\x9c\x9e\xd9\x83\xc0\xb1\xab\x08\x31\xdb\x81\xa5\x61\x55\x9b\xb8\xd4\x1e\x54\xc2\x0a\xbc\x74\x4f\xcb\xc3\xa4\x5c\x2d\xe5\x5a\x37\xd1\xed\xe1\x55\xb3\x73\xe8\x1f\xdd\x55\x99\x21\x13\xbb\xe8\x34\xee\xdc\xb0\x53\x3b\x1a\x36\x4f\x9b\xed\x7b\x0e\x4b\x67\xfc\xda\x27\x91\x9a\xdc\x74\xce\xdc\x61\xab\x79\x5c\x3a\x41\xd9\x8b\xba\x15\x57\xbd\xda\x43\x77\xd2\x53\x0f\x58\x9e\x36\x51\x8d\xf0\xb1\x07\xef\x9b\xfb\xd5\xbb\x23\x54\xe2\x0f\x65\xda\x2d\xe8\x33\x5c\x29\x0c\x0b\x37\xee\x65\xf4\x10\x79\xad\xf6\x24\xaf\x68\x23\xee\x15\x6f\xae\xaf\x07\x47\xd9\x71\xb7\x50\xbe\x6c\x3b\xcd\xf2\x69\x74\x92\x10\xdd\x0f\x5b\x17\x0f\x75\x11\xee\x17\x0a\xf7\x97\x9e\xbd\x7f\x5a\xcc\xb7\x6e\x8b\x59\x6a\xdb\x2d\x75\xd8\x1a\xd8\x5d\xfb\xac\x3d\x22\x87\xc5\xf8\xfe\x74\xd2\xef\x5c\x96\x2e\x75\xfe\x28\x2e\x77\x4e\xfa\xb5\x4e\xcb\xab\xef\x3f\x54\xb8\x69\x8d\x65\x33\x10\xf7\x61\xe3\xbc\x73\x72\x28\xc7\xe6\xbe\xd2\xaa\xf9\x18\x1d\x0e\x0e\xcf\xe4\x45\xc9\x89\x47\x77\x67\x6e\xf6\x26\x97\x33\xc6\x2d\x3e\xd8\xc9\x08\x05\x4e\x23\x2e\x77\xce\x3b\xfd\x5b\x13\x5d\x37\xdc\x8b\xab\xfa\x39\x1e\x46\xf7\x67\xe5\x07\xef\xaa\xd9\x65\xdd\xa3\x0a\xbd\x38\x23\x2c\x68\xb5\xcc\x61\x4f\x1d\x0f\x06\x63\x66\x95\x72\xc7\xad\xdc\xf8\xe4\xec\x9c\x9e\xc6\x7d\x39\x70\xee\xc9\xe0\x5a\xb6\xbb\x25\x2d\xd3\xf1\x0e\xad\x4e\xe3\xb6\xde\x60\x9d\x7a\x5c\x72\xbb\xb7\xb4\x26\x9d\xfd\xe6\x43\x72\x38\xbc\xcd\x3d\x58\x0f\xf2\xc6\xc9\x56\x6e\x46\x30\xee\xe4\x3a\x8d\xdb\xc1\xcd\xa0\x50\x55\xb5\xbb\xf6\xa0\x0b\x5d\x69\x8f\xc9\xb1\x5b\x6f\xe7\x4b\xc7\x93\xab\x07\xfb\xd2\xc6\x87\xea\x2e\xe6\xae\x19\x8d\xf0\x69\x36\x36\x82\xf0\x51\xc9\x1f\xd7\xa8\x9f\xad\x76\xeb\x39\x15\x17\x2f\xc7\xc9\x65\x6c\xfb\x57\x35\xd7\xad\x1c\x8e\x5a\x38\x61\xa5\xce\x6d\xfe\xac\xfc\xc0\xc7\x7d\xe7\xb2\x30\xa8\x5e\xed\x1f\xf5\x95\xed\x78\x58\xdc\x49\xe7\x88\xc6\xcd\xb3\x73\x61\x86\x35\xdc\x38\x75\xd8\x29\xec\xa6\xe3\xb5\x0b\x03\x7d\x51\x13\xc5\x8b\xe6\x79\xa7\x3b\xdc\x37\x13\xe7\x2a\x7b\xe9\x5f\x38\x5e\xe5\xf6\xa2\x78\x58\xf0\xb3\x61\x99\xeb\xeb\x7a\xa7\x13\x77\x2f\xce\x9c\x21\x89\x5a\x77\xc3\x93\x6e\xb6\x1f\x55\xef\x4e\x2b\xc5\xfc\x40\xf7\x9d\x8b\x56\x21\x2b\x15\x6c\x15\xea\x75\xa7\x54\xca\x55\x3b\x6d\x3c\xf1\x2f\xc4\xe9\xa8\xa7\x4b\x08\xa3\x6b\xef\xb0\x9f\xe3\xad\xea\xe9\x7e\x74\x12\xe0\xab\xae\x75\x55\x08\x4e\x6f\x86\x17\xbd\x0b\x87\x5f\x8f\x4f\x59\xc1\x6f\x36\xee\x2e\x5b\x03\xd4\x90\xb9\xbc\x38\x36\xed\xf2\x51\xc1\xee\x5b\x85\xfb\x5a\xfd\xea\xb6\xef\xe4\xa7\x2e\x1c\xbd\x2e\x16\xaf\xf2\xad\xdb\x1c\xbf\xbf\xa1\x5d\xe7\x24\x6a\x9a\xf3\x6a\x5e\x7a\x0f\x1e\xbc\x76\xce\xce\xce\xa3\x76\x38\x56\xd9\x1c\x27\xe1\x24\x8f\xbb\xa4\xdf\xb1\x07\x6e\x58\xaf\x55\x06\x93\xdb\x7d\xaf\x2b\x9c\x72\x4d\xfb\x13\xaf\xed\xb3\xa0\xbe\xdf\x3a\xa9\xd5\xad\x61\x7b\xbf\xa8\x3b\xb9\xd8\x69\xda\xfb\xcd\x52\xcb\x9b\xf4\xf0\xd8\x56\xbc\xd9\xce\x1d\x91\xdb\xd2\xbd\xac\x3b\xcd\x93\xdc\xdd\x7e\x70\xd2\xa8\xb8\x76\x6b\xbf\x73\x3d\xbc\x1e\x2a\x7c\xd3\xd1\x0f\x11\x37\xe5\x72\x8e\xf5\xbb\xd1\xb1\xed\x44\xaa\x7c\x5f\xe8\xb6\x73\xfb\xa7\x8d\x9e\x3b\x68\xcb\x16\xb9\x1d\xdc\xee\x5b\xbe\x1e\xdf\xd6\xce\x72\xad\x63\x6b\xff\x66\x78\x7f\x5b\xf5\x4e\x8e\xb3\x49\xab\x6e\x9b\xab\xc2\x61\x81\x5f\xee\x53\xde\x94\x57\x61\x13\x0f\x8e\x26\x3d\x7c\x53\xa8\x9e\x04\xd1\xfd\x45\x05\xde\xdc\x58\xd0\xbb\x8d\x71\x59\x1f\x46\x67\xcd\xfd\xe3\xfd\xa3\xa8\x52\xb7\xa2\x4b\xaf\xcb\x60\xa9\x63\x15\x4f\xcf\x5a\x9d\xaa\x57\xb3\xec\xe6\x49\xc4\xf7\x7b\xa5\x56\xb5\x28\xaa\xc9\x75\xe7\xaa\x0d\x6f\xbd\xd3\x91\x3b\x1c\xfa\x56\xe3\x76\xe4\x47\xdd\xe1\x39\x3c\x24\xfd\x32\xb9\x3b\x3f\x2a\x16\x0a\xd2\xae\xee\x9b\xca\xf9\x09\xbc\x0f\x49\xe5\x1e\x7a\x4e\xdd\xca\xe7\xca\x95\xee\x6d\x21\x57\x56\x3a\x40\x4d\xdc\x39\x7c\x63\x76\x89\x8e\x12\xcf\xa4\xc1\xeb\xad\xaa\x28\xdf\x7b\xc8\xe7\xb3\xb7\x95\x7c\xae\x75\x34\x79\x48\xe0\xe0\xb2\x90\x3d\xcf\xb5\xba\xf7\xed\xae\x77\xcc\x46\x30\x97\xad\xc5\x47\xd9\x42\xb6\x5e\xa9\xd1\x51\xa1\x76\x5b\xb8\xae\xd5\x0a\x85\xec\x5d\x72\xdb\x3c\x87\x77\xcd\xd2\xe8\xa4\x2d\xcf\x2b\x9d\xec\xe8\xbc\x53\xb4\x2b\x9d\xca\xb8\xf2\x50\x1a\xdf\x4c\x9f\x3d\x3c\x3f\x3b\xbf\xcc\x8e\x6f\x3a\xeb\xfb\x68\xb5\x8a\x5e\x25\x0b\x8f\xf3\x8d\xfb\xe3\x46\x49\xe0\x42\xad\x98\xcb\xd6\xae\xb2\x59\x52\xca\x15\x46\xd9\xe9\xfb\xb3\x54\x94\xd7\xf2\xe8\xc8\xcd\xeb\xfd\xab\xf0\x78\xc8\x1b\xb9\x64\x10\x92\xbb\x62\x35\xdb\xe8\x14\xaa\x3e\x1a\x54\xce\x48\xb6\x20\x3b\x05\xc3\xca\x39\x7e\x7d\x9c\x2f\x0e\xd8\x5d\x8c\x26\xd7\x25\x41\xec\x23\xe4\xd6\xa3\x62\xa5\x76\x31\xee\xb7\x51\xaf\x9f\x0b\xce\x6a\x35\xde\xf1\xbb\x25\x0f\xd1\x6c\x2e\x3f\xbe\x6c\xdd\x0c\x2f\xda\xa3\xfd\x11\x2d\xec\x73\xa7\x85\x26\xfd\x76\xa7\x41\xdb\x39\xbb\x93\x95\xad\xee\x08\x75\xba\x27\xa5\xb3\x9c\x99\x54\x82\xce\xfd\xf8\xae\xee\x61\xdc\xdd\x77\xc3\x5c\x9b\x17\xce\xc2\x78\x92\x1f\x5e\xb6\xcf\x8e\x0f\x6b\xe2\x3e\x8f\x18\x3e\x94\xdd\x61\xee\xee\xea\x94\x97\x8b\xe1\x69\x40\x62\xa8\x6b\x61\x11\x86\x35\xdd\x6d\xb6\x60\x23\x30\xed\xb1\x7b\x7a\x9f\xbd\x4f\x86\xd1\x45\x33\x89\xb3\x79\x61\x0f\xc5\xf1\x71\x39\xb8\x2b\x29\x8f\x35\xc6\xb2\x5c\xc8\xe6\xdd\xde\xc9\xd0\xbb\x42\xd2\x3d\xae\x9d\x65\x8f\xaf\xcb\x21\xe1\xe5\x5b\xff\x34\x88\xa8\x98\xb8\x93\x52\xf1\x78\x78\xdb\x0b\x3a\x85\x31\x66\xf8\x9a\x36\xfd\xc1\x59\x47\x1e\x16\x4a\xf1\xa4\x58\x65\x15\x52\xee\x35\x92\x87\x7a\xbd\xa2\xa8\x55\xe8\xdd\xe5\x2f\x5a\xf0\x61\x4c\xb3\xcd\x6b\x79\x7f\x97\x8f\x8b\xf5\xf2\xc5\xd0\xf8\xc3\xa6\x25\x2a\x15\xf7\xb0\x96\x0c\x4d\xb6\x55\xc9\x65\xb3\xc5\x29\x6d\x4e\xcf\xc2\xbb\x52\x7b\x28\xcf\xb3\xb5\x62\x39\x57\xcb\x16\x5a\xad\x62\x2e\x7b\x92\x9f\x18\x77\x74\x79\x4b\xef\xa2\xaa\xbc\xbf\x19\xe4\x3a\xce\xa9\x29\x30\x6f\xb4\x4f\x6c\x75\x49\xee\x2e\xb2\x25\xbf\xda\x2c\xdb\xfb\xa3\xd1\xed\x83\xca\xba\xdd\x6e\xc3\x1c\xb9\xc7\xf9\x66\x79\x72\x5b\x80\x57\x4e\xad\x98\x43\x8d\x2c\xac\x1f\x55\x9b\x57\xc8\xbe\x31\xa5\xeb\x8a\x28\x54\xad\x8b\x49\x85\x84\x79\xf1\x50\xbc\xaf\x0d\xb3\xfa\xa6\x7b\x39\xd6\xb0\xba\x7f\x77\xd3\x2a\x5e\x99\xeb\x73\xd6\x69\x0d\xc9\x39\xf3\x0f\xc3\xab\xa6\x77\xd2\x1d\x4e\xee\x3c\x76\x66\x9d\x55\x68\x58\x3e\xc3\x1d\xeb\xf0\xb6\x91\xbd\xcf\x8d\x1d\x58\x75\xbc\x86\xc3\x38\x61\xd5\x68\x42\xb4\x70\xb8\xb0\x7b\x77\x93\xab\xc3\xcb\xbe\x5b\xf6\xdd\xd1\x65\x5f\x1d\xdd\x58\xe1\x61\xff\x96\x1d\xe7\x65\x93\xca\x62\xae\x6d\xfa\xfb\xa7\x3d\x14\x5f\x1f\xcb\x87\xd2\x11\x8c\x0f\xf9\xa9\xc3\xa2\x44\x9e\x59\x86\x8e\x7a\xcd\x8b\xd6\x2d\xba\x3e\x1b\x43\x5d\x83\x70\xd4\xb8\x48\xba\x27\x43\x59\xad\xde\x64\x7b\x77\x0f\x7e\xb7\x7f\xfb\xa0\xaa\x8d\x5e\xa5\xe3\x0f\x6e\xae\x07\x71\xd6\xba\x24\xb5\xea\x45\x87\x10\x35\xce\xed\x8f\x4b\x0e\xf2\x90\x9d\x3b\xbb\xf2\x6b\xfd\x9b\x4a\xef\x8c\xdf\x35\xc9\x9d\x70\x6a\x97\x57\xd9\xc9\xb0\x70\x37\x88\x27\x8d\x60\x54\x11\x11\x82\x5e\xa7\xf8\x8f\x5f\xd2\xd5\x95\x2e\x92\x58\x43\x0a\x04\x95\x0a\x10\xe1\x2a\x20\x88\xc1\x80\xd8\x82\x19\x9b\x52\x97\xe8\x55\x47\x4f\xd6\xb8\xba\xbf\x8e\x93\x4b\x29\xc7\x1c\x73\x08\x20\x99\x3a\x2d\x14\x4b\xc0\x6c\xcb\x02\x14\x5b\x2e\x63\x0e\x41\x2e\xb4\xbf\xbd\x93\x5b\x9b\x18\xeb\xae\x13\x8e\x83\x23\x7f\x00\x07\xa7\xd8\xc3\xad\x7c\x14\x06\x0f\xfc\x68\x70\x3c\xb9\xae\x64\x1b\xb8\x28\xf8\xb0\xea\x57\x94\x0f\x2e\xee\x2e\x4e\xb3\xfa\x2f\x15\xfa\x8a\x51\x31\xf6\xff\xea\xfa\xa7\xa5\x02\xb7\x3b\xe6\xaf\x63\x54\xb4\xc7\x0e\x03\xb4\x59\x2a\xb7\x49\x17\x88\x53\x5d\x2a\xdd\x9c\x51\xa7\x89\x9a\x63\x6e\x5a\x93\xe3\x73\xc0\xcd\xa0\xd3\x19\x4e\xf2\x0d\x57\xe0\x89\xb9\x2d\x3f\x20\x75\x1e\x0c\x78\xfd\xec\xfe\xe6\xde\x36\xb5\x86\x93\xaf\x51\xe3\x8e\x9b\x47\xc3\x56\x84\xe9\xd1\x51\xa5\x55\xbe\x71\xab\xa8\x4c\x8b\xca\xef\x07\x97\x6f\xf4\x46\x7f\xb6\x93\x8b\x6c\xe7\xab\xc3\x8f\xe9\x5f\x8f\x09\xcd\x5e\x90\xe8\x28\xe0\xb3\x64\x79\xef\x21\xfd\x63\x75\x02\x71\x3c\xe8\xf7\xc3\x28\xd1\xaa\x9c\xd6\xfa\x5c\xce\x52\x5e\xba\x86\xfe\xc8\x0f\x47\xcb\x3b\xc1\xab\x0f\xdf\x08\xac\x11\x72\x38\xb0\x95\x9b\x26\x59\x59\x80\x42\xaa\x01\xd1\x44\x1a\xa8\xa5\xd2\xec\xd5\x0d\x63\xdc\xf7\x78\x9a\x8c\x9e\x95\x69\x95\x8c\xf9\xfd\xb4\xf3\xeb\xef\xc3\x79\xb2\xfa\x8b\x46\x2f\x6f\xf8\xd4\x49\x3b\x54\x99\x91\x97\xb4\xe7\x51\xe1\x24\x4c\xfb\x49\x26\xe9\xb1\x1b\x3d\xf6\xe2\xc4\x0b\x5a\x19\x3e\xfb\xc6\x8a\xa3\x37\x0b\x0b\x5d\xf0\xd8\x93\xc0\xf8\xe1\xe8\x25\x5c\x12\xf6\xcb\xe9\x85\xf0\x2b\x0f\x63\xec\xa5\xc5\x16\x4a\xd3\x11\x25\xd1\xe0\xe5\xcb\x65\x84\x16\xc7\x5a\x0e\x1e\xf3\xf0\x77\x3e\xff\xb2\xd0\x47\x98\x9e\x2b\xf1\x54\x1f\xa4\x9b\x5e\x60\x11\x6b\xeb\x8e\x94\x2c\x35\x9f\x92\x74\xcb\xa1\x92\xf9\xee\x47\x4f\x07\xe9\xb1\x9e\x6c\xf9\xb2\x58\x3f\xcf\x5e\x96\xae\x8b\xeb\x4f\xbe\x3c\x2d\x26\x0b\x6e\x1a\xc5\xee\x83\x18\xa4\xa7\x2e\x92\x41\x7f\x9e\x81\xf1\x08\xfe\x7a\x75\xbc\xee\x60\x17\x34\xce\x87\xf0\x9a\x62\xdf\x06\x0d\xe8\x0d\x68\xd8\x30\x86\x29\x37\x66\x1f\x57\x4a\x7a\xff\xf0\x24\x53\x7c\xe4\xea\xc7\x95\x23\x26\x99\xba\x06\xcb\x8c\xb6\x6e\x88\xbb\xa3\x75\xe9\xc9\xee\x07\xf1\x0c\x21\x88\x10\x1b\x02\x57\xda\x1c\x10\x6e\x08\x10\x2e\x55\x00\xbb\x1a\x71\xc1\xa1\xc2\xaf\x2a\x0e\x3d\xcb\x82\xdc\xec\xb4\x4d\x06\x64\xf2\x61\xa0\xbc\x99\x2c\xcb\x5c\x5c\x56\xb7\x08\x82\x29\x22\xa7\x6b\x5f\xe9\x44\x47\x3d\x2f\xd0\x19\xcf\xa4\x12\xe0\xe2\xb2\x9a\xf1\xe2\xcc\xe3\x7e\x5e\x7a\x56\x2f\x3d\x90\xb7\x09\x59\xbf\xae\x5c\x90\xcf\x58\x9b\xa5\x47\xcc\xac\x8e\xc1\xea\x4c\xdd\xd7\x7d\xbc\x5d\x38\xd4\x8b\xb5\xab\x52\xbd\x58\xf8\x8d\x24\xc3\x63\x02\x16\x08\x93\x3e\x30\x61\xd4\xfb\xf9\xa8\x7b\x8b\x34\xf9\x36\xa8\x7b\xe7\xea\xd7\x16\x74\x90\x96\x16\x40\x86\x6b\x40\x5c\x6d\x01\xaa\x21\x06\xd8\xb5\x05\x47\x9a\x4b\x45\xf0\xda\xd5\x5f\xf0\x22\x2d\x93\xcc\x71\xc4\x83\xe4\x53\x04\xbc\xf8\x7d\x8a\x80\x05\xf0\x1f\x21\x02\x54\xca\x8d\xa0\x35\xe5\x46\x30\xcf\xa9\xd0\x53\x99\xf0\xf3\xd1\xf8\xcb\x88\x03\x28\x31\xb7\x84\x72\x80\xcd\x09\x02\xc4\x75\x6c\xc0\x89\x4d\x81\xc1\x58\x29\x0b\x53\xac\xcc\xcb\x03\x2a\xcf\xe2\xe0\xc8\x8b\xe2\x24\x23\xa2\xb0\xab\xa3\x8c\x1f\xb6\xbc\xe0\x53\x28\xbc\xf8\x7d\x0a\x85\x05\xf0\x4f\xbb\xe0\x07\xa0\xee\xbd\x5e\x81\x14\x96\xb6\x89\x00\x04\x62\x0e\x88\xb1\x6c\xc0\xa1\x43\x81\xb2\x25\x67\xc8\xc1\x94\x89\x97\xf9\x29\xcf\x82\xe0\x84\x07\xca\xd7\xaf\xfc\x9e\x2d\x6b\x7f\xde\x6a\xd4\xe6\x49\x2a\x02\xc2\xf9\xda\x8f\xf4\x74\xe5\xbf\x0c\x0d\xcc\x82\x08\x31\xef\xe9\x4c\xea\x58\x1f\x3e\x66\xc7\x66\x7c\xaf\xbb\x24\x17\xb4\xca\x3c\x1e\xb2\xce\x3c\x0a\x84\xdf\x46\x50\x78\xaa\x3f\x93\x0d\x51\x0f\xf8\x5e\xd0\xfd\xf9\x2c\xfe\xab\x48\x87\x37\xc7\x13\xbe\xd3\x32\xdf\x35\x98\xf0\x86\xb0\xdb\x3b\x70\xf8\x5e\x7b\xc1\xe1\x0e\x71\x0c\x05\xc6\x70\x0b\x10\x23\x10\xa0\x4c\x33\x00\x25\x77\x34\x35\x16\xa3\x0e\x5b\x2b\x26\xea\x3a\xd6\xdf\xd8\x6f\x88\xdb\xe1\xc0\x57\x19\x91\x16\x9e\xd3\x49\x26\x8c\x32\x41\x98\x1c\x64\x1a\x3a\x95\x29\x8f\x24\x9c\xfe\x6d\xc2\x48\xea\x83\xdf\x46\x10\x7c\x5a\x0c\x8b\xbf\xaf\xb0\x18\x52\xc6\xf9\x74\x1b\xde\x24\x06\x04\xc2\x4c\xd9\x44\x02\x6c\x31\x03\x08\xb4\x28\xe0\x2e\x44\x80\x6b\x4b\x28\x0b\x3b\x36\xe6\x2f\xcf\x0a\x3d\x8b\x81\x34\xa7\x5c\x46\x7a\x2e\xd1\xa2\xcc\x54\x8f\xbd\x2e\x58\xb6\x52\x0e\x3c\xba\x01\x8f\xd6\xc1\x61\x10\x06\xe0\xc9\x54\x48\x33\xcd\xb9\x3f\xdf\x66\x19\xbe\x2e\x42\xfa\x4b\xae\xf6\xfc\xe3\xc6\xe4\x5e\x8a\x34\x9d\x19\x04\xde\xfd\x40\xcf\x66\x3b\xdf\xb5\xdc\x85\x75\x9f\xcc\x87\xb4\x97\x99\xd0\xf0\x0c\x98\xf5\xf6\xb9\x35\x31\xff\xfd\xa6\x5b\x13\xbb\x99\xe8\xef\xc0\xe0\x3b\x25\x08\x71\xa4\xc1\x8a\xd9\x00\x3a\x26\x2d\x2e\xcd\x00\x15\x5c\x01\xcb\x70\xc2\xb5\x63\x13\xed\xae\x8f\x43\x7e\xc5\x3e\xcb\x4b\xa9\x52\xd7\xcb\xe0\x99\xd0\xfc\xde\xbb\x92\xcf\xa7\x0f\x79\x1c\x8f\xc2\x48\x7d\x10\x4f\xf9\xb7\x5d\xfb\xf9\x8b\xf3\x42\xe9\xb2\x74\x71\x9e\x2d\xff\xa4\xb5\xff\x8e\x38\xdd\x3b\xd0\xf9\x5e\x53\xc2\x25\x2e\x33\x94\x02\xcb\xb1\x20\x20\x46\xbb\x80\x39\xc4\x06\x0c\x5b\xb6\x10\x2e\x31\xce\xab\x02\x1a\xcf\x82\x60\x5e\xfc\x6f\xcb\x1a\x9f\x43\x65\x04\x8f\xb5\xfa\xf6\x11\xc4\x15\xab\xf7\xc7\x2f\xed\x34\xee\x25\xc3\xb0\xeb\x7d\xaa\xf2\x77\xe1\x2e\xee\x07\xba\xb5\xae\xd4\xef\xd7\xe2\xae\x50\x6a\xa4\x47\x1a\x3f\xa4\x0f\xf0\x7e\xc4\x3d\x86\xd9\xc0\xe3\xaa\x01\x91\x9e\xed\xca\x84\x6b\xcb\xa7\xfe\x50\x2e\x44\xf6\xaf\x81\xcc\xef\x6c\x50\xe2\xef\xa0\x54\xa6\x56\xc3\xcf\x8b\x43\x59\x50\x39\x0c\x41\x02\x1c\xe3\x72\x40\x6c\xd7\x02\x9c\x43\x0b\x58\x0c\x62\x57\x58\xd0\x55\xf6\xcb\x52\xc3\xcf\x5a\x63\x75\x3d\xc1\x97\x5a\x23\xc7\xe3\x97\xdb\x4d\xa9\xfb\xb9\xa6\xf5\x8b\x32\x6c\xb3\xb2\x62\xbf\x82\xe6\x98\x0f\x75\x9e\x6b\xfa\x11\x56\xed\xaf\xa4\x3b\xe6\xd8\xeb\x8c\x3e\x06\xea\x7e\x25\xed\xb1\xc4\x78\x1f\x06\x83\x6f\x91\x95\x1f\x04\x83\x63\x1b\xbe\x0c\xba\xff\x1c\xdc\x91\x5f\x25\x7e\xa9\x09\x15\x1a\x62\x0c\xa0\xd2\x02\x10\x6c\x2b\xc0\x1d\x5b\x00\xe4\x52\xac\x89\x26\x96\xb0\xd6\x3b\x1d\x33\x0b\x27\x93\xe6\x9d\x6c\xd1\x21\x2f\xae\x23\xa8\xcf\x2f\x7a\xc8\x5c\x8c\x02\x1d\xcd\xf2\xa8\x7e\x17\x07\x64\x75\x36\xce\x63\xb4\xe1\x33\xbe\xf0\xf5\xb8\x7c\x0c\xd8\xfc\x7c\x5c\xfe\x2a\x5a\xe6\x3b\xc7\x6a\xbe\x87\x59\xfd\xa6\x14\xcb\x77\x20\xf2\x9d\x02\xd3\x71\xb4\xed\x40\xc4\x00\x81\x94\x01\xc2\x5d\x01\x38\x23\x1c\x50\x68\x30\x87\x0e\xd5\x86\x6d\x10\x98\xa1\xec\xea\x28\xb5\xa5\xb7\xc8\xcb\xab\x58\xab\x8c\x98\x64\x0a\xb3\x16\x73\x53\x3b\x93\x84\x4b\xf9\x1d\x19\xde\xe2\x5e\x10\x27\xe9\x4e\x50\xa9\xf0\x6a\x03\xf9\x97\x15\xa1\xe9\xac\x41\x3b\x49\xfa\x60\x36\xea\x65\x90\x9f\xbe\xee\x7f\xbc\x0c\x7d\x27\xbb\xba\x88\x33\x26\x1c\x01\x2c\x07\x4a\x40\x1c\xd7\x05\xc2\x40\x03\xb0\xab\xa5\xd6\xdc\x68\xa2\x5e\x1e\x41\x7c\x66\x57\xf3\x2a\x5c\xba\x85\x6b\xb3\xe9\x75\x19\x71\x26\xe1\x5d\x1d\x64\xb8\x49\x74\x94\x79\xdd\xc9\x2c\x81\xe9\x55\x66\xd2\xe3\x26\xc3\x63\xd9\x2c\x2f\xce\x04\x61\x92\x99\xe8\x24\xdd\x17\xd5\x2a\xe5\xfe\x60\x92\x39\x9b\xd7\xae\xfa\x86\xbb\x12\x3f\x9d\xeb\x9f\xb7\x36\x23\x3d\xf4\xf4\x28\x33\xaf\xe2\xf8\x9e\x6d\xcd\x59\x0f\x1b\xea\x4d\xbe\x6e\xfa\x9b\x2d\x96\x1f\xa4\x24\x7f\x72\x5e\xd4\x8e\xe9\x03\xef\xc0\xdf\x7b\x9d\x09\x0d\x5d\x8d\x08\x06\x06\x32\x0e\x08\xb3\x30\x60\x5a\x52\x40\xa5\xc2\x18\x4e\x45\x0e\x7c\x75\xb3\x19\xdf\x14\x46\x5b\xa1\x15\x53\x23\xfa\x8f\xcc\xa3\x09\xf8\x47\x26\x4c\xfa\x19\x1e\xa8\x4c\x98\xb4\xe7\xaa\x35\x93\x76\xf5\xfb\x24\x38\xa5\x51\xf9\xcf\xdd\xca\xf9\xef\x63\x5a\xc0\xdf\x63\x7d\xef\x7a\xc4\xf0\x1d\x38\x7c\xe7\x02\xa7\x8c\x29\xad\x5c\x08\x5c\x2e\x19\x20\x94\x62\x20\x98\xb2\x81\x45\x1c\x9b\x5a\x5a\x32\x29\x5e\xde\x81\xfd\xbc\xc0\x17\x2f\x0e\xda\xb2\xce\x17\x41\x33\xab\xd6\xe8\xaf\xa8\xe2\x5f\x4e\x0c\xf4\x79\x4b\xbf\x79\x15\x7f\x17\xed\xf4\x96\x45\xbc\x2b\xf7\x2e\xd3\x70\xc3\x2c\xbf\x3b\xd7\xda\x5a\x13\x69\x6c\x03\x2c\xa6\x04\x20\x86\x42\xc0\xa8\xc1\x00\x52\x97\x59\x0e\xb3\x6c\x24\x5f\xde\x11\xb4\x9a\x6b\x57\x4d\x63\x33\xeb\xae\x80\x5f\x66\xdd\x29\xc4\xaf\xa1\x85\x96\x58\x77\x96\x67\x3b\x37\x3d\x7e\xbe\x12\xfa\x55\xc2\x30\x2b\x44\xc0\x5c\x99\x73\xf9\x31\x30\x69\xff\xaa\x98\x8c\xb4\xe4\xfd\x44\xb6\xf9\xf7\x45\xe5\x1b\xf2\x17\x9c\x5f\x25\x46\xa0\xb8\xad\xa9\x76\x0d\x80\x12\x0a\x40\x34\xc6\x80\x5b\x14\x01\xc7\xe5\x84\x3a\x8e\xd6\x16\x79\x79\x99\xdd\xa2\x7c\x8c\x75\x32\xf5\x42\x52\x77\x9e\xfb\xdb\x4c\xf8\xfa\x4b\xf8\xd9\xa5\xc4\xb3\x1c\xde\xd9\x79\x86\xc9\xf4\x51\x2b\x4c\xa3\x5a\x5e\xf4\x64\xea\x4f\x3d\x9c\x38\xec\xe9\xa4\xbd\x22\x45\xfa\xd7\x35\x08\x62\x9d\x80\x05\x74\x00\xd9\x0e\xc3\x78\xb6\x5f\xf0\xf3\xc5\xc1\xaf\x62\xdd\xaf\x42\x25\x78\x79\xbf\xef\x4f\xc2\xe1\xaf\xa5\x9c\xa6\x38\xfc\x38\xfb\x2b\xbf\xca\x1e\xf4\x77\xf6\x2e\xdf\xb2\x9d\xbc\xab\x7d\xbe\xdb\x19\xb4\x77\x60\xf0\x9d\x5a\xc8\x55\x82\x20\xcd\x29\xb0\xf5\xac\x32\x97\x03\x28\x65\x14\x60\xc1\x6d\xd7\xe5\x1a\xb9\x66\xbd\x16\x8a\x79\xcf\xcf\x68\xf9\xf2\xe4\xd2\x4b\xe5\xd3\xc8\x56\xca\x99\x62\xbe\x9a\x99\xdf\x0d\x94\xc9\x2e\x67\x35\x1d\xfd\x46\xae\xe6\xe7\xe6\xc9\xd3\x6f\xb7\xeb\xe5\x57\xc7\xe3\xb7\xd4\x93\x43\x4c\x68\x66\x18\x07\x5c\x61\x06\x08\x45\x0a\x50\xce\x24\xb0\x35\x84\xc8\xa2\x0e\xb6\xe9\xff\x65\xed\xda\x7a\xd3\x86\xa1\xf0\x7b\x7f\x45\xc5\x3b\x51\x60\x68\xa5\x7b\xa3\x10\xb6\x48\x50\x50\x08\x9d\xa6\x3d\x44\xb9\x1c\x5a\xab\x26\xc9\x92\x80\xba\x87\xfe\xf7\x29\x27\x76\x88\x1d\xc7\x20\xc6\x2b\xb5\xbf\xe6\x7c\xbe\x1d\xfb\xdc\x34\xee\x77\x17\x46\x31\xe9\x32\x32\xf2\x71\x30\xf8\xa6\x6d\x1c\xd2\xc8\x2f\xc0\x40\xeb\x8b\x21\x3c\xba\x94\xf7\xcd\x92\x20\x31\x9b\xdf\xe7\xc5\x4b\x34\x08\x61\x17\x8c\xa2\xb0\x3f\x7e\x18\x8f\xfa\xa3\x20\x30\xfb\x8f\x83\x2f\xe3\xfe\xc3\x6e\x30\x8e\x20\x78\x0c\x06\xad\xd2\x0d\x4d\x45\xf1\xbc\x5d\x43\x2b\x28\x93\x8b\x97\xb7\x4a\x62\x03\x4d\x4b\x46\x65\x98\xfa\x76\xdf\xc3\x22\x31\xf1\x6b\xa7\x74\xc2\x68\xf3\x7c\x1a\xcc\x64\xa5\x1b\xe9\x5a\x84\xe9\xea\x79\x6e\x7f\xdf\x3a\x96\xe7\x2a\xa2\x75\x1b\xa5\x6a\xab\xf0\x53\x55\x48\xaf\xb8\x9b\xe8\x01\xa1\x4e\x89\xa8\xd8\x33\x58\x5d\xd4\x09\x2f\x50\xaf\x7a\x24\xd0\xac\x39\x65\xb9\xcf\xee\xf1\xaf\x29\x70\x2d\x67\xb9\xf1\x26\xcf\x33\xaf\x3e\xc1\x36\x5d\x44\xb8\x90\xed\x73\x7c\x9b\xaf\xcf\x98\x33\xce\xa2\x97\xa0\x83\x2a\x51\xe4\xb5\xb4\xc8\xba\xd9\xb5\xb4\x6c\xd7\xb3\x89\x6b\x79\xeb\xc9\x66\xf3\x73\xe5\xc8\x9b\x60\xcd\xc8\x16\xa7\xf0\xfd\x5a\xad\x5f\x49\x64\x9c\xc1\xbc\xe5\xec\x90\xd5\xac\xff\xa5\xc1\x59\xcd\xed\x85\xec\x27\xd7\x62\x41\x69\x9f\xec\x20\x41\x8d\x78\x4b\x0e\x64\x1d\xeb\x5a\x0e\x5e\x2c\xc7\x9e\xff\xf2\xac\xe5\xc4\x96\x55\xbb\x9a\x01\x1e\xb6\xa7\xb8\xa0\x48\xf2\xeb\xd0\x6e\x29\xbd\xfc\xee\x73\xad\xf4\x11\x50\x28\xc0\xeb\xb0\xcc\x73\xf9\x67\xd8\xaa\x2b\x3b\x8a\x5c\x47\x51\x87\x78\xd3\xdd\x40\x7e\xb1\xb9\x96\x84\xea\xa4\xf2\xca\x03\xdd\xa3\x98\xb8\xf6\xcc\x52\x40\x4b\xee\x42\xd9\x52\x24\xe3\x3c\xf2\x6d\x0f\x0d\xf3\x22\x46\x84\x83\x95\xc5\x98\x31\xfd\x4d\x0a\x4c\x13\xde\xec\x78\x13\x85\x61\x88\x39\xfe\xa1\xf3\x17\x6f\xa6\xf0\x36\xad\xee\xab\xd3\xd3\xeb\xc9\x09\x52\xfd\x2a\xc5\x1c\x85\x45\xb5\x9f\x77\x12\xe3\x19\x98\x13\x92\xba\x69\xdb\x91\xab\x72\x96\x79\x42\x37\x97\x45\xa9\x91\xf0\xa6\x9d\x4e\x34\x8d\xca\x9b\x82\xc2\xd3\x0b\x49\xe0\x3f\xf9\xe1\x7b\xf8\xe6\xc7\x31\x50\x37\x79\x87\x78\x06\x94\x1c\x21\xfb\xbb\x4c\x22\x9c\x38\x69\x42\x9b\x3b\x07\xf6\xb1\x3e\x52\x92\x41\x8e\xb7\x8c\xde\x60\x68\xca\x7f\x2f\x45\x71\xe0\xcf\x01\xf2\x02\xa2\x72\xca\xfd\x20\x95\xee\x8e\x5f\xe5\xbd\x11\x61\x79\xf5\x92\x52\xba\xe1\x0c\x8e\x24\x84\x69\x12\xc1\x82\xec\x20\x4f\x7d\x44\xff\x6a\x8a\xe8\xc8\xdc\x6a\xb7\xa3\x24\x86\x0d\x60\xad\xbe\xa5\xff\xd1\xec\x61\x76\x41\xaf\x13\x4a\x49\xfc\x6a\xc7\x05\x64\x47\x9f\xa2\xc1\xa6\x8d\xcd\x40\xed\x88\x82\x4b\xf6\x90\x1c\x8a\x16\x68\xea\x67\x4c\xba\x6d\x46\xc4\x8f\xed\xc4\xd3\x7d\xa4\x4a\x28\xdd\xff\x2f\x29\xee\x94\x22\x03\x9f\xee\x1d\x38\x60\xcd\xf7\x55\x91\x4e\xd9\x38\x36\xf4\x71\x9e\x1d\x9b\x97\xe6\x7b\x81\x2c\x67\x5a\xfb\x70\x64\x98\x06\x77\x2b\xc4\x7b\xcf\x92\x15\x0d\x0c\x43\xc8\x73\xe9\xfe\x23\x4c\x75\x76\xca\x4a\x53\x2c\x3d\xfd\xfa\x5b\xcc\xcd\xcd\x7a\x25\x94\x84\xa4\xd5\xeb\xf4\x2b\xef\x75\xf7\x79\xf7\x2f\x00\x00\xff\xff\x9e\x90\x4d\xeb\xd3\xc1\x01\x00") + +func mattermostRealmJsonBytes() ([]byte, error) { + return bindataRead( + _mattermostRealmJson, + "mattermost-realm.json", + ) +} + +func mattermostRealmJson() (*asset, error) { + bytes, err := mattermostRealmJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "mattermost-realm.json", size: 0, mode: os.FileMode(0644), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x80, 0x99, 0x3b, 0xa8, 0x7b, 0xc1, 0xed, 0xc, 0x8a, 0xe4, 0xdd, 0xfc, 0xd0, 0xbe, 0x4c, 0x4a, 0xa3, 0x5f, 0xc7, 0x61, 0x74, 0xd6, 0xb7, 0xe2, 0xd8, 0xf4, 0x31, 0x7f, 0xdb, 0x16, 0x15, 0x6c}} + return a, nil +} + +var _outputsTf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x92\x31\x6b\xc3\x30\x10\x85\x77\xff\x0a\x91\xb1\x83\x97\xcc\x1d\x4a\x87\x0e\x85\x0e\xc9\x58\x8a\x38\x4b\x47\xaa\x58\x91\xc4\xdd\x29\xad\x28\xfd\xef\xc5\x76\x5c\x9c\xd8\x38\x5e\x0c\x7e\xf7\xbd\xf7\xce\x5c\xcc\x92\xb2\xa8\x8d\x0b\x2c\x10\x0c\xf2\x46\xfd\x54\x4a\x9d\xc1\x67\x54\x8f\x0a\xbe\x58\x8f\x52\x0d\x29\x69\x46\x3a\x23\xbd\x3f\x7c\x54\xbf\x55\x35\xc2\xb6\x79\xf6\x99\x05\x69\x0e\x93\x65\x6d\x06\x51\x63\xb0\x29\xba\x20\xf5\xed\x07\xbe\xf1\x83\x03\x06\x59\x6b\xe2\x23\x58\x41\x16\xdd\x4f\xde\xd0\x27\x14\x72\x86\xf7\x7d\xd3\x15\x93\xcb\xdc\x65\xa5\xa9\x43\x8b\xc5\xf8\x08\xed\x5d\x8b\x71\x70\x0a\x27\x8a\xdf\x65\x85\xe9\xf5\x85\x50\xf4\xc0\xe2\xcc\x3c\xb3\x7b\x06\x8f\x98\x30\x30\x02\x99\x4f\x6d\xe3\x09\x5c\xa8\xf1\xbf\xbe\x52\x8c\x81\x9d\xb8\x73\x97\x28\x94\x71\xc1\x7c\x17\x3d\x3e\xed\xde\x16\xda\xc1\x49\x53\xf4\xd8\x19\xf6\x6f\xa0\x30\xe5\x79\xdb\x64\xd3\xa2\xcc\x49\xde\xea\x41\xaa\xc7\x99\x6b\xee\x15\xcb\xf2\x32\x5d\x24\x18\x83\xcc\xba\xc5\x52\xf3\xb6\xc5\x72\x67\x0b\xdb\xec\xd1\x64\x72\x52\x5e\x28\xe6\xb4\x50\xe6\x22\xeb\x43\xa7\xd7\xb6\x99\xd2\xc7\xd8\x0c\x3f\x77\xed\xb2\x8e\xb1\xb9\xbe\xf1\xbf\x00\x00\x00\xff\xff\x27\x02\x90\xbc\x21\x03\x00\x00") func outputsTfBytes() ([]byte, error) { return bindataRead( @@ -254,11 +296,11 @@ func outputsTf() (*asset, error) { } info := bindataFileInfo{name: "outputs.tf", size: 0, mode: os.FileMode(0644), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe8, 0x3, 0x8b, 0x3b, 0x9f, 0x58, 0x9, 0xc5, 0xa6, 0x12, 0x88, 0x62, 0x3d, 0x6d, 0x4a, 0xfa, 0x1e, 0xc1, 0xb2, 0xa8, 0x18, 0xff, 0x1f, 0x1c, 0x8b, 0x50, 0xc9, 0x80, 0xfb, 0x1c, 0x7f, 0x69}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3e, 0x12, 0xe6, 0x68, 0xaf, 0xf0, 0xb8, 0x4d, 0x3d, 0x6e, 0xeb, 0xeb, 0x71, 0x4c, 0x19, 0x57, 0x62, 0xa5, 0x8f, 0xd2, 0xa1, 0x0, 0xb, 0x8b, 0x7e, 0x49, 0x98, 0x45, 0xd4, 0xf2, 0xc8, 0x96}} return a, nil } -var _variablesTf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x94\x4f\x6f\xdb\x3c\x0c\xc6\xef\xf9\x14\x82\xdf\x4b\x73\x78\x8d\xb4\x59\xb1\x5d\x72\xdc\xe7\x10\x68\x99\x71\xd4\xe8\xdf\x48\x2a\x6d\x36\xf4\xbb\x0f\x76\x1a\xc0\xae\xb5\xb8\x87\xe4\x14\x88\x0f\x7f\xa2\xe8\x87\x3c\x01\x59\x68\x1c\xaa\xca\xb8\xcc\x82\xa4\x03\x78\xac\xd4\x9f\xd5\xfb\x6a\x35\x0f\x9e\x92\xd1\xb6\xfd\x67\x98\x73\x13\x50\x4a\x0a\x48\x49\xdb\xc0\x02\xc1\xa0\x36\x31\x07\xb9\x2d\x91\x73\x9a\x57\x01\x1d\x06\x59\xc4\x4c\x45\x23\xd0\x7f\xea\xa7\x03\x16\x6b\x18\x81\xcc\x41\x5d\x73\x78\x9c\x8e\xbc\x74\xc1\x58\x51\x2c\x13\x59\x9f\x90\xd8\xc6\x50\x0c\x25\x53\x3a\x36\x84\x20\xa8\x29\xba\x22\x90\x03\x24\x3e\x44\xd1\x84\x29\xb2\x95\x48\xe7\x99\x2c\x51\x7c\x3b\x2f\xd4\xd6\x36\x4b\xcf\x1b\x2b\x30\x74\x36\x2c\x40\x1c\x30\x97\x14\x57\x4f\xd8\x16\x83\xd8\xbd\x45\x2a\xa9\x2e\x37\x8c\xfb\xa5\x54\x5f\xb8\xda\x29\x0f\xe9\x01\xc2\x79\xbd\x52\xaa\xc5\x3d\x64\x27\x6a\x37\xc4\x95\xaa\x20\x53\x24\xf8\xdf\x9f\xf9\x97\xab\xd4\xf0\xdb\xa9\xea\x47\xbd\xa9\x87\x23\x7d\x89\xd7\xdb\x7a\xf3\x5c\x3f\x55\x93\x9c\x14\x59\x3a\xc2\x21\x71\xa7\xaa\xc7\x6f\xf5\xf7\x5e\xf0\x3e\x2b\x2d\x33\x52\x71\x18\xda\x46\x27\x60\x7e\x8d\x34\xf7\xf9\xf0\xa4\xfe\xaf\x4e\x48\xfb\x48\x7e\x68\x92\x0d\x6c\xbb\x83\x14\xfb\x94\x80\xc0\xa3\x20\xf1\xe4\xf5\xce\xb2\x3c\xf4\x2d\x60\x21\x1b\xba\xf5\x7a\x9a\xc8\x7c\xd0\x29\x37\xce\x1a\x7d\xc4\xb9\x15\x3c\x88\x20\xf9\xc8\xa2\x9d\x35\x18\x18\xf5\xde\x16\x9c\xd5\xb8\x68\x8e\xba\xc5\x93\x1d\x19\xe6\xa3\x86\xa1\xa7\x97\xdb\x27\x9f\xa0\xea\xd2\xb6\xba\x81\x61\xfb\x1b\x59\x0f\x63\xf8\x99\x16\xb2\x6f\x90\x26\xb4\xc7\xcd\x22\x6a\xf0\xf5\x7d\x50\x90\xd2\x7d\x40\x1e\x85\xac\xe1\x2f\xc0\x9e\x97\x61\x2f\xb1\xb9\x0f\x08\xc7\xfb\xed\x0b\xc8\xa7\x4f\xc8\x97\xd8\x68\x46\x3a\xf5\x63\x7b\x7b\x4b\x94\x94\xc5\x85\xc3\x5b\xdd\x64\x73\x44\xd1\x6d\xf6\x49\x67\xb2\x25\x09\xbe\x49\x3f\x6c\xee\xaa\x2d\xce\x1d\xbc\x0e\x5e\x28\x1a\xb9\x8f\x11\x76\xa5\x9d\xdb\x87\xc0\x7f\x5c\xfb\x37\x00\x00\xff\xff\x7d\x77\x43\x95\xf0\x06\x00\x00") +var _variablesTf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x55\xcd\x6e\xdb\x3c\x10\xbc\xfb\x29\x08\xe5\x92\x1c\x3e\xc1\x89\x13\x7c\xbd\xf8\xd8\x4b\xfb\x10\xc4\x92\x5a\xcb\x8c\xf9\xd7\x5d\x4a\x89\x5a\xe4\xdd\x0b\xc9\x76\x21\x55\xb4\x15\x14\xf6\xc9\xd0\xcc\xce\x2e\x57\xc3\x51\x0b\x64\x40\x59\x14\x85\xb6\x0d\x27\x24\xe9\xc1\x61\x21\x7e\xad\x3e\x56\xab\x39\xd8\x46\x2d\x4d\x75\x11\xe6\x46\x79\x4c\x39\x06\xc4\x28\x8d\xe7\x04\x5e\xa3\xd4\xa1\xf1\xe9\x3a\x25\x75\x71\x3e\x05\xd4\xe8\xd3\xa2\xcc\x94\x34\x12\xba\x13\x5f\x2d\x70\x32\x9a\x11\x48\xef\xc5\xb9\x86\xc7\xe5\xc8\x4b\x0d\xc6\x8c\xec\x98\xc8\xb2\x45\x62\x13\x7c\x16\x8a\x3a\xf7\x58\x13\x42\x42\x49\xc1\x66\x05\xd9\x43\xe4\x7d\x48\x92\x30\x06\x36\x29\x50\x37\xa3\x45\x0a\xef\xdd\xc2\x6c\x95\x5a\x3a\xde\x98\x81\xbe\x36\x7e\x41\xc4\x02\x73\x8e\x71\xf6\x84\xa9\xd0\x27\xb3\x33\x48\x39\xd6\xb1\xc3\x78\x5f\x42\xf4\x83\x8b\xad\x70\x10\xef\xc1\x77\x0f\x2b\x21\x2a\xdc\x41\x63\x93\xd8\x0e\xb8\x10\x05\x34\x14\x08\xfe\x73\x1d\xff\xb0\x85\x18\x7e\x5b\x51\x7c\x29\xd7\xe5\xf0\x48\x1e\xf1\x72\x53\xae\x5f\xca\xa7\x62\x52\x13\x03\xa7\x9a\x70\x28\xdc\x8a\xe2\xf1\xb9\xfc\xbf\x27\x7c\xcc\x46\x6b\x18\x29\x7b\x19\x2a\x25\x23\x30\xbf\x05\x9a\xfb\x7c\x38\x52\xff\x57\x46\xa4\x5d\x20\x37\x2c\xc9\x78\x36\xf5\x3e\x65\xf7\x14\x81\xc0\x61\x42\xe2\xc9\xe9\xad\xe1\x74\xdf\xaf\x80\x13\x19\x5f\x3f\x3c\x4c\x0b\x99\xf7\x32\x36\xca\x1a\x2d\x0f\x38\xb7\x82\x83\x94\x90\x5c\xe0\x24\xad\xd1\xe8\x19\xe5\xce\x64\x9c\xa5\x6c\xd0\x07\x59\x61\x6b\x46\x86\x39\xcd\x30\xec\xf4\xd8\x7d\xf2\x0a\x8a\x3a\x6e\x8a\x2b\x32\x6c\x7e\x22\xcb\xe1\x1a\xfe\xad\xe6\x1b\xa7\x90\x26\x6a\x8f\xeb\x45\xa9\xc1\xd7\xb7\x91\x82\x18\x6f\x23\xe4\x30\x91\xd1\xfc\x09\xb1\x97\x65\xb1\xd7\xa0\x6e\x23\x84\xe3\x7c\xfb\x84\xe4\xd3\xfa\x98\x8b\xdf\xb1\xd3\x36\xc0\x61\x14\x89\x57\xfb\x1c\x4e\xfc\x7f\xd8\xe5\xb9\xf4\x74\x4d\xaa\x89\xe9\x55\x08\xf6\x02\xfd\x7a\xac\xfd\xa1\xcd\x83\xe4\xa2\x8d\x9f\x9e\xcb\x75\x1f\x0e\x79\xa1\x0a\x5b\xb4\x21\xba\xfe\x63\xe2\x42\x85\xd9\x39\xef\xc4\xb7\xa0\x04\x23\xb5\x48\xd9\xdd\xbd\x06\x25\x8f\xf0\x52\xec\xe6\x98\xd9\xa3\xf2\x46\xaa\x46\x1f\x30\xc9\xaa\x71\x51\x36\x64\x72\x14\x7c\x4f\x7d\x7a\xd9\x33\x37\x1b\x64\xf0\x36\x5c\xae\x6c\x32\xf4\x18\x61\x9d\xfb\x88\xf5\x10\xb8\x53\xdb\xdf\x01\x00\x00\xff\xff\xd3\x65\x0c\xd1\x41\x08\x00\x00") func variablesTfBytes() ([]byte, error) { return bindataRead( @@ -274,7 +316,7 @@ func variablesTf() (*asset, error) { } info := bindataFileInfo{name: "variables.tf", size: 0, mode: os.FileMode(0644), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5c, 0xc0, 0x10, 0xb7, 0x5, 0xb6, 0x50, 0xb1, 0x91, 0xf9, 0xba, 0x3f, 0xfe, 0xe9, 0x2f, 0x3e, 0x46, 0x57, 0x38, 0xac, 0x40, 0x9e, 0x88, 0x17, 0xe9, 0x52, 0x6a, 0x15, 0x44, 0x6e, 0x95, 0x2a}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc8, 0x39, 0x60, 0x63, 0xaf, 0x75, 0xaf, 0x61, 0x27, 0xdc, 0xe7, 0xfb, 0xaa, 0x23, 0x88, 0xc0, 0xfb, 0x7f, 0x89, 0xb2, 0x6b, 0x35, 0xba, 0xcf, 0xdf, 0xb3, 0x3d, 0x3, 0x4e, 0x36, 0xd5, 0x29}} return a, nil } @@ -377,6 +419,8 @@ var _bindata = map[string]func() (*asset, error){ "datasource.yaml": datasourceYaml, "elasticsearch.tf": elasticsearchTf, "es_dashboard_data.json": es_dashboard_dataJson, + "keycloak-database.sql": keycloakDatabaseSql, + "mattermost-realm.json": mattermostRealmJson, "outputs.tf": outputsTf, "variables.tf": variablesTf, } @@ -435,6 +479,8 @@ var _bintree = &bintree{nil, map[string]*bintree{ "datasource.yaml": {datasourceYaml, map[string]*bintree{}}, "elasticsearch.tf": {elasticsearchTf, map[string]*bintree{}}, "es_dashboard_data.json": {es_dashboard_dataJson, map[string]*bintree{}}, + "keycloak-database.sql": {keycloakDatabaseSql, map[string]*bintree{}}, + "mattermost-realm.json": {mattermostRealmJson, map[string]*bintree{}}, "outputs.tf": {outputsTf, map[string]*bintree{}}, "variables.tf": {variablesTf, map[string]*bintree{}}, }} diff --git a/deployment/terraform/assets/cluster.tf b/deployment/terraform/assets/cluster.tf index 4526282fe..96542eecb 100644 --- a/deployment/terraform/assets/cluster.tf +++ b/deployment/terraform/assets/cluster.tf @@ -647,3 +647,80 @@ resource "null_resource" "s3_dump" { command = "aws --profile ${var.aws_profile} s3 cp ${var.s3_bucket_dump_uri} s3://${aws_s3_bucket.s3bucket[0].id} --recursive" } } + +// Keycloak +resource "aws_instance" "keycloak" { + tags = { + Name = "${var.cluster_name}-keycloak" + } + + connection { + # The default username for our AMI + type = "ssh" + user = "ubuntu" + host = self.public_ip + } + + ami = var.aws_ami + instance_type = var.keycloak_instance_type + count = var.keycloak_enabled ? 1 : 0 + key_name = aws_key_pair.key.id + + vpc_security_group_ids = [ + aws_security_group.keycloak[0].id, + ] + + root_block_device { + volume_size = var.block_device_sizes_keycloak + volume_type = var.block_device_type + } + + provisioner "remote-exec" { + inline = [ + "set -o errexit", + "while [ ! -f /var/lib/cloud/instance/boot-finished ]; do echo 'Waiting for cloud-init...'; sleep 1; done", + "sudo apt-get -y update", + "sudo apt-get install unzip openjdk-17-jre postgresql postgresql-contrib -y", + "sudo mkdir -p /opt/keycloak", + "sudo curl -O -L --output-dir /opt/keycloak https://github.com/keycloak/keycloak/releases/download/${var.keycloak_version}/keycloak-${var.keycloak_version}.zip", + "sudo unzip /opt/keycloak/keycloak-${var.keycloak_version}.zip -d /opt/keycloak", + "sudo mkdir -p /opt/keycloak/keycloak-${var.keycloak_version}/data/import", + "sudo chown -R ubuntu:ubuntu /opt/keycloak", + ] + } +} + +resource "aws_security_group" "keycloak" { + count = var.keycloak_enabled ? 1 : 0 + name = "${var.cluster_name}-keycloak-security-group" + description = "KeyCloak security group for loadtest cluster ${var.cluster_name}" + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = local.private_ip != "" ? ["${local.public_ip}/32", "${local.private_ip}/32"] : ["${local.public_ip}/32"] + } + + // To access keycloak + ingress { + from_port = 8443 + to_port = 8443 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 8080 + to_port = 8080 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } +} diff --git a/deployment/terraform/assets/keycloak-database.sql b/deployment/terraform/assets/keycloak-database.sql new file mode 100644 index 000000000..006371bbb --- /dev/null +++ b/deployment/terraform/assets/keycloak-database.sql @@ -0,0 +1,3 @@ +CREATE USER keycloak WITH PASSWORD 'mmpass'; +CREATE DATABASE keycloak OWNER keycloak; +GRANT ALL PRIVILEGES ON DATABASE keycloak TO keycloak; diff --git a/deployment/terraform/assets/mattermost-realm.json b/deployment/terraform/assets/mattermost-realm.json new file mode 100644 index 000000000..bad498703 --- /dev/null +++ b/deployment/terraform/assets/mattermost-realm.json @@ -0,0 +1,2733 @@ +{ + "id": "mattermost", + "realm": "mattermost", + "displayName": "Keycloak", + "displayNameHtml": "
Keycloak
", + "notBefore": 0, + "defaultSignatureAlgorithm": "RS256", + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 60, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "oauth2DeviceCodeLifespan": 600, + "oauth2DevicePollingInterval": 5, + "enabled": true, + "sslRequired": "NONE", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": true, + "bruteForceProtected": false, + "permanentLockout": false, + "maxTemporaryLockouts": 0, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "1603a047-cc4c-405a-82e6-69e2c692776f", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "mattermost", + "attributes": {} + }, + { + "id": "c7fdcde8-78f3-4255-bd19-7c945859d42f", + "name": "create-realm", + "description": "${role_create-realm}", + "composite": false, + "clientRole": false, + "containerId": "mattermost", + "attributes": {} + }, + { + "id": "bdd23949-2930-46fb-a7ee-7733085b4253", + "name": "default-roles-mattermost", + "description": "${role_default-roles}", + "composite": true, + "composites": { + "realm": [ + "offline_access", + "uma_authorization" + ], + "client": { + "account": [ + "manage-account", + "view-profile" + ] + } + }, + "clientRole": false, + "containerId": "mattermost", + "attributes": {} + }, + { + "id": "41e2f2bd-b7a1-491d-9cdd-dc593f3d7483", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "mattermost", + "attributes": {} + }, + { + "id": "86d6d932-461e-4e75-a2e1-0fe79802ee3b", + "name": "admin", + "description": "${role_admin}", + "composite": true, + "composites": { + "realm": [ + "create-realm" + ], + "client": { + "mattermost-realm": [ + "impersonation", + "manage-clients", + "view-events", + "view-authorization", + "view-realm", + "create-client", + "manage-authorization", + "query-users", + "manage-identity-providers", + "view-users", + "view-clients", + "manage-users", + "query-clients", + "manage-realm", + "manage-events", + "view-identity-providers", + "query-realms", + "query-groups" + ] + } + }, + "clientRole": false, + "containerId": "mattermost", + "attributes": {} + } + ], + "client": { + "mattermost-realm": [ + { + "id": "89f8999a-8b53-4aa8-ab1f-233c13954a88", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "b214d48c-94f8-4fe3-bea9-e14dcd0daf8b", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "a9875907-ea05-40f2-b7f5-2fa6da77d9fd", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "1ad5b686-8a60-48b1-8e69-ee7ad21f2e5d", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "3338e04d-5781-49ca-ba50-e5eab4b2abfc", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "0634edc3-0452-4745-bb68-1bd8508b803b", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "e4e141e2-7288-4e42-93c8-e7c3f369756b", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "0fb67bd9-8e13-4f75-acaf-75ee459a8b6c", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "7aff516a-4306-4ba1-92c7-aee738368321", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "796eb07f-a07e-4ac0-a8f2-069c56ce147a", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "mattermost-realm": [ + "query-users", + "query-groups" + ] + } + }, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "644ee19e-6587-4cad-a0d0-8a3e165cc8df", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "48db4ddf-db9e-48b9-8158-a4fa9aa6bfae", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "mattermost-realm": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "bc39205b-6498-47f2-b912-a7c9aabc7e6a", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "031a8159-2ac9-473f-8031-30743390f4cb", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "f522db6e-0623-4f59-89ef-5ffbad9d0301", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "e7c9c397-585e-4de5-b6bd-627aa622b27b", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "34ab4e47-ed0a-427e-a826-88b556b3e4f1", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + }, + { + "id": "9d571819-a733-4e48-beef-61cd6f8ce604", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "attributes": {} + } + ], + "mattermost-saml": [], + "realm-management": [ + { + "id": "8a7f3beb-7f15-4f29-b4b3-617e5cc2efca", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-users", + "query-groups" + ] + } + }, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "4afc2ca7-6898-48b2-b779-ef9d3dce6a4d", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "82c322eb-3fed-41cd-9601-8ad0d5ce1ebf", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "b399c89a-43d4-4c74-ad71-deddec380f0b", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "b8cbc6fd-8ccf-4a92-954d-910fc9212a90", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "0a83e9cd-ba0e-4a5e-ac95-86f7a9b4f8e6", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "fc29fdad-b85e-4da2-a801-86d7c6019ecb", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "adabd2a6-bf0f-4c06-b2f9-13f9d357cf6c", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "view-users", + "query-clients", + "impersonation", + "create-client", + "manage-events", + "manage-users", + "query-realms", + "view-realm", + "query-users", + "manage-clients", + "view-authorization", + "view-events", + "manage-authorization", + "view-clients", + "query-groups", + "manage-identity-providers", + "manage-realm", + "view-identity-providers" + ] + } + }, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "b174a957-fc32-4fda-8a7e-4902845aa9da", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "4941ce35-37ec-4f95-ace7-6a3156e642cd", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "0611112f-6301-4bc0-9b8c-bdaadd8c9b6c", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "4dc7d606-cfb5-4ec6-b7f3-93fb77e835f0", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "80c108fa-09c7-4e51-a842-927a5dab5ffb", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "cf1859f6-e925-45c3-91d7-87018acb3773", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "e02fa015-aa29-4628-b20a-4983a3142c90", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "04fad402-6417-45f8-a3ed-376bdf6bfd20", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "fbb77d5e-7175-4eb6-ab8f-b613ffac2250", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "51831ce6-be87-416b-9257-9a8ff0a82247", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + }, + { + "id": "4e99f1ba-9889-4614-b193-a36ab4099729", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "attributes": {} + } + ], + "mattermost-openid": [], + "security-admin-console": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "2d3154ca-4b7e-4a11-809b-b8ad236035f8", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "1a5d8538-3004-48ad-a9ea-767e4ae09b53", + "attributes": {} + } + ], + "account": [ + { + "id": "659dde8f-c5ff-4db2-a8ad-b88479c1e2e0", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "7e08cc43-4e60-4a0e-b03e-4d62b69f21da", + "attributes": {} + }, + { + "id": "52b506d6-2ae7-49e5-bcfa-8044cff08a9a", + "name": "view-groups", + "description": "${role_view-groups}", + "composite": false, + "clientRole": true, + "containerId": "7e08cc43-4e60-4a0e-b03e-4d62b69f21da", + "attributes": {} + }, + { + "id": "fcff0626-3b86-4e98-ab97-666d1bc35aaa", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "7e08cc43-4e60-4a0e-b03e-4d62b69f21da", + "attributes": {} + }, + { + "id": "cf2d2ae8-f0d3-4a70-aad1-77709b218316", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "7e08cc43-4e60-4a0e-b03e-4d62b69f21da", + "attributes": {} + }, + { + "id": "be2eb134-3a35-4fb8-83b4-c91c4e0859e0", + "name": "delete-account", + "description": "${role_delete-account}", + "composite": false, + "clientRole": true, + "containerId": "7e08cc43-4e60-4a0e-b03e-4d62b69f21da", + "attributes": {} + }, + { + "id": "80379c27-f861-4b54-9ef1-399fd6a17f30", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "7e08cc43-4e60-4a0e-b03e-4d62b69f21da", + "attributes": {} + }, + { + "id": "625e8aa3-3b40-4353-a1c4-d6d9d8630deb", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "7e08cc43-4e60-4a0e-b03e-4d62b69f21da", + "attributes": {} + }, + { + "id": "87d75c32-10bc-49ad-a68e-832429a8d043", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "7e08cc43-4e60-4a0e-b03e-4d62b69f21da", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRole": { + "id": "bdd23949-2930-46fb-a7ee-7733085b4253", + "name": "default-roles-mattermost", + "description": "${role_default-roles}", + "composite": true, + "clientRole": false, + "containerId": "mattermost" + }, + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpPolicyCodeReusable": false, + "otpSupportedApplications": [ + "totpAppFreeOTPName", + "totpAppGoogleName", + "totpAppMicrosoftAuthenticatorName" + ], + "localizationTexts": {}, + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyExtraOrigins": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "webAuthnPolicyPasswordlessExtraOrigins": [], + "users": [ + { + "id": "d29668ce-2ed2-4911-b37b-c51f671401c9", + "username": "keycloak-user-01", + "firstName": "Keycloak", + "lastName": "User", + "email": "keycloak-01@dev.mattermost.com", + "emailVerified": true, + "createdTimestamp": 1710861450623, + "enabled": true, + "totp": false, + "credentials": [ + { + "id": "303f1302-adeb-4f35-a264-b35db7c361d4", + "type": "password", + "userLabel": "My password", + "createdDate": 1710861461757, + "secretData": "{\"value\":\"G7y2VonMVUukUsTydaEsHdAfMeRRA+aRCZXEqvtS4SrdXCgaYjNXxThiPSAlK2bJcz3aVxwIXZ32MkD58bwcYg==\",\"salt\":\"rWxsZ/sUMvMrA+RmVnquUQ==\",\"additionalParameters\":{}}", + "credentialData": "{\"hashIterations\":210000,\"algorithm\":\"pbkdf2-sha512\",\"additionalParameters\":{}}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "default-roles-mattermost" + ], + "notBefore": 0, + "groups": [] + }, + { + "id": "322fe373-2f32-4edb-b85b-426ed4a29509", + "username": "mmuser", + "emailVerified": false, + "createdTimestamp": 1592608502143, + "enabled": true, + "totp": false, + "credentials": [ + { + "id": "12b834cf-48e7-45ac-9798-f3c3e5f22852", + "type": "password", + "createdDate": 1592608502380, + "secretData": "{\"value\":\"e+FszAkjUqp7PVyg3FfW3XtBa2tXB1bvpxDbNHgkNWhx1b7YNi154Yvm6nR0caj2lx95KYlEevinMKb4GZKmRQ==\",\"salt\":\"lnn/AkoOO1uPJGZ5Wbwu1Q==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "offline_access", + "uma_authorization", + "admin" + ], + "clientRoles": { + "account": [ + "manage-account", + "view-profile" + ] + }, + "notBefore": 0, + "groups": [] + } + ], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account", + "view-groups" + ] + } + ] + }, + "clients": [ + { + "id": "7e08cc43-4e60-4a0e-b03e-4d62b69f21da", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/mattermost/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "7228d94d-bf02-4b5d-ab61-07a5b4d71b24", + "redirectUris": [ + "/realms/mattermost/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "815a1e7b-f78e-413f-9c44-b5459df0e0c0", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/mattermost/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "0406c700-8b2e-4163-9ab5-5091fdf15e5b", + "redirectUris": [ + "/realms/mattermost/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "1079cafb-6192-4059-8412-0f7b4b39ff3c", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "84e88764-21c4-43a0-8128-5ba882aa0990", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "da271203-180d-41a3-8f54-12d8a1a242b8", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "1a5d8538-3004-48ad-a9ea-767e4ae09b53", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "398f1561-be86-4d08-a1f3-4162dbcd0c59", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "26941ae9-f7c7-4ea5-9739-7340b05f2331", + "clientId": "mattermost-openid", + "name": "", + "description": "", + "rootUrl": "", + "adminUrl": "", + "baseUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "qbdUj4dacwfa5sIARIiXZxbsBFoopTyf", + "redirectUris": [ + "*" + ], + "webOrigins": [ + "*" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "oidc.ciba.grant.enabled": "false", + "client.secret.creation.time": "1710861383", + "backchannel.logout.session.required": "true", + "post.logout.redirect.uris": "*", + "oauth2.device.authorization.grant.enabled": "false", + "display.on.consent.screen": "false", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "9db3c486-1d1d-430a-84d9-304773d9b9b6", + "clientId": "mattermost-realm", + "name": "", + "description": "", + "adminUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "52fef9a5-b43a-496d-be1d-024522142740", + "clientId": "mattermost-saml", + "name": "", + "description": "", + "rootUrl": "", + "adminUrl": "http://localhost:8065/login/sso/saml", + "baseUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "9c2edd74-9e20-454d-8cc2-0714e43f5f7e", + "redirectUris": [ + "http://localhost:8065/login/sso/saml" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "saml", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "true", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "post.logout.redirect.uris": "+", + "saml.server.signature": "true", + "saml.server.signature.keyinfo.ext": "false", + "saml.signing.certificate": "MIIC3zCCAccCBgFheaqsnDANBgkqhkiG9w0BAQsFADAzMTEwLwYDVQQDDChodHRwczovLzdjNTQzNTQyLm5ncm9rLmlvL2xvZ2luL3Nzby9zYW1sMB4XDTE4MDIwOTA4MjMwM1oXDTI4MDIwOTA4MjQ0M1owMzExMC8GA1UEAwwoaHR0cHM6Ly83YzU0MzU0Mi5uZ3Jvay5pby9sb2dpbi9zc28vc2FtbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJg1eRqY8X4bGTFJgdftPoQlqwasfmZJDwkPlbWsNf4XQukwYqGcpDYKtdAd8mmLkYK1wXPjRvdZTNBA3nuMZYGcJjXMvBKGSqz9q2s8+wD+9TKcE6aSTS7+eOL9GjRWMdE5g4GsLkOjzJo6B39tniCCHHA1rlfUgDXFAvDRtS60ytuAnkD6YGdZ3moZtke8ssEZjxJRnGf3F8E1RfaP4An7a8D1ZlyvNndZpLtB/AixjIvasJpPrQX5UW/DkjKFQx+++GZdFBvGq4gva4pErmq1RfnIoEtG7V7DmgpBDx1Pv1EyJ61vowVwkUDJe2uim3s7h5iaZAeDq1NXNAYMMf0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAhA6yjZmkcyBgUfifrhDcK4X4PU2rtf+y9vql28Yq23Idoc0u4TavrZbEHedgAswW7D3bDnX3JAdRA3PbydGnAHeTPdsOvf/UAolPjsd/c7+KkMbrpVc/rjG8PFtVwfqD3kmoUpXZ5T1FGHO7Kjp/sP3lNXeugopxoh4lS3WAekKqD8DnLll6SspRmQrdgZQ/OSEmxXMi34Fg2zkClu/Vp59IR3yvJxkVd1tZKdSi1xkHaBdL/sG3X6D/wy68pYWB64UyP02PHaE2AytzqL/lm//KCjU8WbG+G9diCPKNp6udX1lFK4/N4gpnWSIsh1FE+/S22Er5/QjKDGPyNf35Pw==", + "saml.artifact.binding.identifier": "TFPBLWH8GNzHZR1ptdmog9ZxhWA=", + "saml.artifact.binding": "false", + "saml.signature.algorithm": "RSA_SHA256", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "saml.authnstatement": "true", + "display.on.consent.screen": "false", + "saml.signing.private.key": "MIIEpAIBAAKCAQEAmDV5GpjxfhsZMUmB1+0+hCWrBqx+ZkkPCQ+Vtaw1/hdC6TBioZykNgq10B3yaYuRgrXBc+NG91lM0EDee4xlgZwmNcy8EoZKrP2razz7AP71MpwTppJNLv544v0aNFYx0TmDgawuQ6PMmjoHf22eIIIccDWuV9SANcUC8NG1LrTK24CeQPpgZ1neahm2R7yywRmPElGcZ/cXwTVF9o/gCftrwPVmXK82d1mku0H8CLGMi9qwmk+tBflRb8OSMoVDH774Zl0UG8ariC9rikSuarVF+cigS0btXsOaCkEPHU+/UTInrW+jBXCRQMl7a6KbezuHmJpkB4OrU1c0Bgwx/QIDAQABAoIBAAiq4t6U3wujV2frG63EIM89peOXZwtEFcsaTBgwWlLB2FmXG8bAOMmrCndzfR5tiDe9SerjgmMLfshNKV43vIAI+FQP+JXFd/Mp7t0Id/Kykhvzr1rI8gQ/EXs7loZsciHL+KUlvOy1Iy2VKGAlSd/oCN6K8AaoXzSwp143Uu353ssrdj4EprMy7H0ZM9DMdR40ov7nrhD6ux2vC7FGmNchKu5whPb0X3Bq62v4ENebu6k9h/MN04hCEh5IoQBvjqSD6k0Wg+QrMo+DHFrTvtuPMtUOYi/08odx1Z4kQ34VppmkqvQnXKvL0sR5i0MOuvW/yt3UX6cjmME8knJHaDECgYEA7DD4yxnrzFKIYbeEwWbjXWwtGIq4hxH9c9lg4XQt/9TnTWPQaHOxmqL6cZgp40IKffVhc4wBRNnyH2iUZaOn8AUhOfeFIGyN3Yy3aDWsyD9nF8PqrvkEXsbRAJWY6jvFtbWYdEXDJx7mTxVsy9aeNlq+NH7NL2yj/fOzcl9KPpsCgYEApPll+o/yisM3B88Ac8fcfpS8Fs0bn5R63lIkaxKNFVHASkrMaCH4gW88o2+urYOp2dbfOkWcJ4yAT1zgv9Q+y0dwjT/eMg9Rlhi2lOUvysdJ5pQr62YTMUa0hA4uwR5fvEewbwbujcsRWpGvkVvPBrS+CXRme/ppJpgSWtYZT0cCgYEAnrxG6NDR7W7mY63f1c8dLTM/l4fbfkNz8ED+4GahZ5ehoBxd+2UNztyLrn5SYH6I6KBaTzqfu7MyCzPQ0AJOInyAGSIl4WWzbltdA/dW2PnrgkhUWCXZbwz1eAwSShHDzVxvSm18O7WDmVDP3qqth+AyhrtVkPLVwB3h0xMBpdMCgYBDnH7B6LrDSexEw/5wdQmVywkm4xqeFTEh6lJIm4q8oQuIpw0M5Fc/XMJiTQQu0pYK1DgaXqr3vmpbnDn0BF1T3ExxZyp+I68RL8GsVh13IqPT3wf86pGVEWAr+tAIj5U2yb6yUgn0jLPpBWoJzbGUEwELSOwzhVYQ3iQvnC01QwKBgQCa7bycaVyeON+fwehAzlWjvNuTOWvieOstVgLp8rHuflMaU2CHQ6G3jcM/asx9l15DT+nqPf9x6Ms2UQxnwbFS4xT2ZHXruxex7oWNPgQazOk+hBFG73G8PtPODRe2iPA9c3gKSi/y9M80zFHGNACuy7Fl7pLXAsz5eOjxIVOYTg==", + "saml_name_id_format": "username", + "saml.allow.ecp.flow": "false", + "saml.onetimeuse.condition": "false", + "saml_signature_canonicalization_method": "http://www.w3.org/2001/10/xml-exc-c14n#", + "saml.server.signature.keyinfo.xmlSigKeyInfoKeyNameTransformer": "NONE" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "9cc29dfc-8f88-49b0-a5ad-602414919e96", + "name": "lastName", + "protocol": "saml", + "protocolMapper": "saml-user-property-mapper", + "consentRequired": false, + "config": { + "attribute.nameformat": "Basic", + "user.attribute": "lastName", + "friendly.name": "lastName" + } + }, + { + "id": "46cde274-7982-46ba-a8e2-0c83c86c0a83", + "name": "username", + "protocol": "saml", + "protocolMapper": "saml-user-property-mapper", + "consentRequired": false, + "config": { + "attribute.nameformat": "Basic", + "user.attribute": "username", + "friendly.name": "username" + } + }, + { + "id": "185850a8-98fd-45dc-9e2a-0cce60ca79b1", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "944ad38e-c7c0-4197-956e-99bea3f4aa76", + "name": "firstName", + "protocol": "saml", + "protocolMapper": "saml-user-property-mapper", + "consentRequired": false, + "config": { + "attribute.nameformat": "Basic", + "user.attribute": "firstName", + "friendly.name": "firstName" + } + }, + { + "id": "50e9a4b5-8350-4a0b-97c7-6cea4f41baad", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "8fa1d509-76af-446e-84e0-c7ca19df70d7", + "name": "X500 email", + "protocol": "saml", + "protocolMapper": "saml-user-property-mapper", + "consentRequired": false, + "config": { + "attribute.nameformat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", + "user.attribute": "email", + "friendly.name": "email", + "attribute.name": "urn:oid:1.2.840.113549.1.9.1" + } + }, + { + "id": "b5cd8b53-2011-42a9-ab33-bfb8c6e71708", + "name": "email", + "protocol": "saml", + "protocolMapper": "saml-user-property-mapper", + "consentRequired": false, + "config": { + "attribute.nameformat": "Basic", + "user.attribute": "email", + "friendly.name": "e-mail", + "attribute.name": "email" + } + }, + { + "id": "e992fbae-5022-4faa-a9ac-ac2175f10626", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "eb511875-6279-4e16-bfbb-a5bf64eb9a84", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "8c0b03ac-68ec-4bec-9d15-60d526c82f93", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "820e0279-6e54-4787-90dd-dc9b983e7d21", + "name": "id", + "protocol": "saml", + "protocolMapper": "saml-user-property-mapper", + "consentRequired": false, + "config": { + "attribute.nameformat": "Basic", + "user.attribute": "id", + "friendly.name": "id" + } + }, + { + "id": "5c4933fa-deba-42ad-8895-4cb78c4a623a", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + }, + { + "id": "5ab91a1c-79d4-483e-bd69-b684fee46311", + "name": "nickname", + "protocol": "saml", + "protocolMapper": "saml-user-property-mapper", + "consentRequired": false, + "config": { + "attribute.nameformat": "Basic", + "user.attribute": "nickname", + "friendly.name": "Nickname" + } + } + ], + "defaultClientScopes": [ + "role_list" + ], + "optionalClientScopes": [] + }, + { + "id": "b4992675-c068-4f9c-949b-fd197eaef0f5", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [], + "optionalClientScopes": [] + }, + { + "id": "c00ad008-c2f3-43df-a3d5-2b79bf8aa055", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/mattermost/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "e3ff2e21-394f-4536-90ce-d9d8697da91f", + "redirectUris": [ + "/admin/mattermost/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "d04c0393-31a7-400f-966e-919b19867ac7", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "d8096e80-d010-43dc-a882-296b3d3a7a09", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "b67eed41-55e3-4f4a-8df7-d6ff87293b0c", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "5fe306a4-8f0a-497f-a832-a77b80dff8fc", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "3c46dfb9-0687-47b2-9e4b-067dd997b54f", + "name": "acr", + "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "36173320-92ad-4e1e-9840-e35902de413b", + "name": "acr loa level", + "protocol": "openid-connect", + "protocolMapper": "oidc-acr-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + } + ] + }, + { + "id": "d60a441a-4d9a-45a2-ab8d-167bfefe7dc7", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "ee47b76e-73ef-47c3-a907-2e8fe6d31749", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + }, + { + "id": "5a864475-3ad8-4e95-8f20-536a6e1df159", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "599664c3-e555-4070-a665-bf31459ea0ab", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "4286f2f3-93f5-4720-9e0a-6c9bcecc8ed5", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + }, + { + "id": "958a1c6c-1ecd-4550-babd-e527dd5f79ef", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "userinfo.token.claim": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "6412e99f-ad55-4e5c-b298-b4883a82207b", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "5804dfa5-b72b-4204-80d2-d6bfb83f76fe", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "098106c8-d235-470a-b482-8447c2a1340e", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "1fc223ba-b522-4680-8f2f-b99871d8b651", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "6d53f3eb-3d25-43ba-9adf-93617eb9c6ab", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "f7797eb6-13a6-4245-a93d-ee8580a70675", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "5512bd46-9570-4b5b-b18f-479c477f7f51", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "7e0a9d40-e1d1-483d-bc56-5ccb6e5ba1db", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "6b7ac0bc-a801-4d61-9020-dff2393b3e2f", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "21cb50d8-d4a0-4c34-8a21-a5d5a814c248", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "fa57dead-2ea3-459a-b95a-71ef8adfab1a", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "c7ceeaea-3c64-4846-9cb7-1781df7b5ad8", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "4ccaeb42-32f0-420b-9408-5fdb8c7c3aff", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "4eae9963-52fd-4b1d-9611-125f77371b0b", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "07000c6e-14e2-40b6-8aa0-c2b032ff98ae", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "9604111a-194e-4dda-b92e-2b5792dc0806", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "cd4cef7d-d064-4c37-8091-684755713eb1", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "365bdebc-003b-4317-a2a2-8d41c2c3d57c", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "82b8263f-6e28-4301-8a15-0aeff9bc7cd1", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "8945e516-43b5-4137-8fa4-6d6a382dc75f", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "497468e6-7fc4-49dc-9377-ce14dc73df4c", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "452ea040-f16d-4c2e-9660-57a8f7268d44", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + }, + { + "id": "e1cf8fda-5d90-49d8-b14d-dc14d1817ad6", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "060321b7-cc01-4a40-a8c0-61054f2e9565", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + } + ] + }, + { + "id": "c911dee4-e0d3-469f-a180-9aab921cd7db", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "9cd82ef2-2298-4e3b-b5c7-2741379c90e8", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "profile", + "email", + "roles", + "web-origins", + "acr" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "address", + "phone", + "microprofile-jwt" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "referrerPolicy": "no-referrer", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "identityProviders": [], + "identityProviderMappers": [], + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "c8d92569-aba3-4c3c-977d-a35951b5b051", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "afc06a86-b2fc-4575-a9d6-636797100557", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "id": "232ecdbb-d581-49f4-8935-f2dd29fd4906", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "ff7e9d75-6932-4c48-847f-c4cd9b704e6a", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "9e4e98cc-e3ad-4e8f-8b29-4905c5fd5afc", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "5e7e8083-346d-47da-b20b-ab5845177cd2", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "ccb37107-02f0-4346-8947-bf2f514c2cc1", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-usermodel-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-role-list-mapper", + "saml-user-attribute-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-full-name-mapper", + "oidc-address-mapper", + "saml-user-property-mapper" + ] + } + }, + { + "id": "ea1b47d2-28ca-4b32-869b-bb27c0a6c01e", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-usermodel-property-mapper", + "oidc-address-mapper", + "oidc-full-name-mapper", + "saml-user-attribute-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-role-list-mapper", + "oidc-usermodel-attribute-mapper", + "saml-user-property-mapper" + ] + } + } + ], + "org.keycloak.userprofile.UserProfileProvider": [ + { + "id": "06129845-fa3b-4422-b6ff-e27bf57fb6e0", + "providerId": "declarative-user-profile", + "subComponents": {}, + "config": { + "kc.user.profile.config": [ + "{\"attributes\":[{\"name\":\"username\",\"displayName\":\"${username}\",\"validations\":{\"length\":{\"min\":3,\"max\":255},\"username-prohibited-characters\":{},\"up-username-not-idn-homograph\":{}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"email\",\"displayName\":\"${email}\",\"validations\":{\"email\":{},\"length\":{\"max\":255}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"firstName\",\"displayName\":\"${firstName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"lastName\",\"displayName\":\"${lastName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"nickname\",\"displayName\":\"Nickname\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[],\"edit\":[\"admin\"]},\"multivalued\":false}],\"groups\":[{\"name\":\"user-metadata\",\"displayHeader\":\"User metadata\",\"displayDescription\":\"Attributes, which refer to user metadata\"}],\"unmanagedAttributePolicy\":\"ENABLED\"}" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "284d2d18-f974-4b0f-b4f5-0155701257d4", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "kid": [ + "6a9f1872-bb81-4651-bc9e-71abb132734d" + ], + "secret": [ + "DiUoJ0cgUAxUuQZfbxl6-A" + ], + "priority": [ + "100" + ] + } + }, + { + "id": "10da9515-8eef-43fa-99d5-973b318f9084", + "name": "hmac-generated-hs512", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "kid": [ + "d15ea36c-ca17-4410-bcb9-60856697ac80" + ], + "secret": [ + "dP_KieGRhadoOUhQjESqO98cGzyOvqhFgGI6LRxJtzXAhA7Gf0znza0OpBGbDImRElWvxYSJ-B_iJ1kzExUimNExX2LMKhS4M-w4mQDBC0clnXneClm0SOzzBedhI4g4Km3Ahgjf3X6yU9lskFaGAQDbO1ix7IcRNl0aybXlAjg" + ], + "priority": [ + "100" + ], + "algorithm": [ + "HS512" + ] + } + }, + { + "id": "a6a66d52-a384-44c5-a0f8-dd57900fae8d", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "privateKey": [ + "MIIEowIBAAKCAQEAthewnvlKBr2kgbbqOGRDwEowz5drjCuAA3Iw3/SwWlRghLvWbNslSG+ORdu0axDEDsaYdpqQZykEGo5ZCItvAAQsU4FrzocPsPA/muoNsqYY0vIQeYwHIJMNo5ByCgX8jJ46sWUYt95Pu6AYWgyqLMgr04Shv0G6gtvd/3JLwWVCWixKCZ+LNHkKBNKEHpF4NEp34ceyagKrb6zl7bAAm+b2xhi52SHYvUsXCwwAu5h74lNnOxkCgBlS6OGi2JSZ6/G8u8iBBr2Jp4w8d/d1fF5bio3PwyLMhD/TOC5krc0UTHfNQ5mQjoNM8fAF1XKmQrBESzr35b19WzDO/0Lb3wIDAQABAoIBABElW+ksOg82bjYUnitfLY3+rmftrx/MvMoWR4nfBXgL9+antUIcxH70miXz0SI/uuZVRufsF+rOzucdPj7yuin7Op1GU3tn9k9H4AVbQpzuzOmYB3sad1VW43LiWAqfk689+vLXPSObGFDne0OHa8K5un65P229560IvPefsIhuMoM0T7JLvtLPIBgWrY/UXj/lFZP9f4y5E6SZ7ojQFvXJXhqa0IKaVl4rdyWjK7vgXGIH2AOR1sPiQzkymdz3cJX2Q4axi0qX+PZF2IazL8kDeK3MDvDW7TrzrighyCd8SsmEWVVuFAxkDLTh6XLJrHt4epogOzRbo+DDqTi5+JECgYEA855gd/gu5k5Khw4/EsqJypjTITeCFsLjHpQjgiR+zMafgxcXnbqoSNjH/cxfqMgQl32/u/KcOI6swZK7AWBBff7Ez5tw2n6SsLjNjpYfrVS7OURN3vrqKLziUXk9kFM8OK49nggf/mdGuux91IBGgBxHKN8Jspcu6q4uVchkIecCgYEAv1jSYRS9jRsI7kY8Qc6+Xzt/vYBz1zcW6AMWw0sjBjSYuWuDPdQZhuk07c5x4G7RhCIGyUz5T53/dZsa7fww3JAsfb4awIlxQ8lAPkRBdsETxtTs5lUQ77M/wg3t9IjYCKLzaxp6TDuPU+Fpd56i3bZc6F8sXKNbfvQ3SJ69J0kCgYEA5DueOQbEOXNjkv+fy6UATlO6iMYOE/DlAoLaeVRjjskOK6v4rgZvHkAprPZJMECuep6OgDAcd0gDRR6IIBPjh3ylObJwmeI232Vi/pBagPJ+rHn3Uk1UDnJWvOmO6aVxJ9DlXSZTgu2ScBCbGfhLFD5p1DqQRUYp6Cbite8VEEUCgYBaqW8k6HrXfNPCcizi0V6KKNrhoxdABa4oyC3k4pj5u7oRQMuyY+ikb6LQelyihl9nR+gHQR1vh+EejBs6X5+XIgiym3x5daXhBF4YIqcR6XHBZ+nHSM75g+jVvVvd3WjezrafLLB9pkrG56rdLqDkhB+JSm7uhcg4YuY+1lexYQKBgG1+WvqYPiHGAtgR5fUD/DaT+8aXcUoX3uFym3WDPHnrqOM0WW10iYs3Le/rKX+G+FrMR1rTik90Ij1EJKgjPiQ15XHra+mIgPEbPtVjUh0YiJw7vvl1SYwlrkvN0/4pL4ZNFEDDc5P+fMNH0qo4Mq0i6R1CBLMkYDBLden2X3j/" + ], + "certificate": [ + "MIICmzCCAYMCBgFyzt0uTDANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjAwNjE5MjMxMzIxWhcNMzAwNjE5MjMxNTAxWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2F7Ce+UoGvaSBtuo4ZEPASjDPl2uMK4ADcjDf9LBaVGCEu9Zs2yVIb45F27RrEMQOxph2mpBnKQQajlkIi28ABCxTgWvOhw+w8D+a6g2yphjS8hB5jAcgkw2jkHIKBfyMnjqxZRi33k+7oBhaDKosyCvThKG/QbqC293/ckvBZUJaLEoJn4s0eQoE0oQekXg0Snfhx7JqAqtvrOXtsACb5vbGGLnZIdi9SxcLDAC7mHviU2c7GQKAGVLo4aLYlJnr8by7yIEGvYmnjDx393V8XluKjc/DIsyEP9M4LmStzRRMd81DmZCOg0zx8AXVcqZCsERLOvflvX1bMM7/QtvfAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAHCyf7wTY8ZrPcqWuBj6JfD9iw+45dT4ZOAIlPXL5+wwYzdA7kkSfF7GCXLyYD0U6QEB2SA0RFPXU25WfIVMbDP1OyM4oCbzEqQvAeWkTxe0P+ZWgEUfVN9jgv4N9l/oUXiHkvyZi9K1KM8oLK3j1/YSAqBx60P6iS69a49Pry4eb6ab5mZyU/Tp7Ll7wTpdFW1o/pY9GCcX8cEBhfp+Jm2sVGczIF0s/aJ69rtcK1f8wmXOgY2VKx0eQ00wSOtkHvcPPWAmZzlkpYzdPSmMjluWVusA1T4QPOj44dxB+xI62i25BKUlQpWMmKaZX4Zb6QTUAyvDZusySnwMbr20ijE=" + ], + "priority": [ + "100" + ] + } + }, + { + "id": "c72c3e08-b8cd-4b7d-b4f3-45b9f58874e5", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "kid": [ + "88a3a3a0-0484-483c-9511-831799642705" + ], + "secret": [ + "Qyf1ZjoxnFlu0uJ3i3gCronzaFuGyVMAS3EbavPlMdl-OZOJAe_dold98bxl_klJIDa5jf_G2E5x69-8XILh4k-bJeIIWK86X2XxafgyGN-afujjvyCS7b3yfYLz2dNnuaRKqWq5fQS6CQ8f7xXFvgr38FFMgLW7P2L8EdlpnT0" + ], + "priority": [ + "100" + ], + "algorithm": [ + "HS256" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "cb3e226a-5d7d-4e81-808e-4e4cf0ecde9e", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false + } + ] + }, + { + "id": "f4424450-7c5a-4af4-b78d-37e2aba0d3b1", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "e1062ec1-2fae-47e1-8e03-375ba2eacd43", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "0c3a1bd6-5a42-4765-a458-f33dd1383dfa", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "fcb1e54b-403a-4f15-a068-d5ca926389b4", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Account verification options", + "userSetupAllowed": false + } + ] + }, + { + "id": "06a646f8-ffa1-4fb2-89e9-0ca6e8f19869", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "b239d54c-319f-4018-a702-ae1bd13653a0", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false + } + ] + }, + { + "id": "46cf3d95-06f6-43b9-8bad-1fa4ae654e73", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "b7479f88-1610-4fe7-9645-9315bb74f6c1", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "identity-provider-redirector", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 25, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "forms", + "userSetupAllowed": false + } + ] + }, + { + "id": "10d69204-6f7a-4571-aa01-19037b107d58", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-secret-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-x509", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "e48be033-0deb-435d-a65b-2783e4e41b11", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "66e56029-4089-4a7b-a94a-80f3a068ef91", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "72a99b6b-160c-4677-bf0f-37eceeafe4d5", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "User creation or linking", + "userSetupAllowed": false + } + ] + }, + { + "id": "ee07e243-f09a-4913-9ec8-8cd33037ec0b", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "899ded70-7ac9-4883-b9d5-146581ec9cbf", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": true, + "flowAlias": "registration form", + "userSetupAllowed": false + } + ] + }, + { + "id": "5ee4cf5f-19db-4f80-98f3-0879169152c6", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-password-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 50, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-recaptcha-action", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 60, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "da5e8e7f-0c0b-4e33-a182-67a4866ee147", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-credential-email", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 40, + "autheticatorFlow": true, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "7db42ea8-5e7d-4e86-8898-3ba577ae27f7", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "29be9f9a-ad39-482d-8a9c-5e0021863588", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "bcefb4dc-8784-4bb0-9138-7f18deb9b184", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "TERMS_AND_CONDITIONS", + "name": "Terms and Conditions", + "providerId": "TERMS_AND_CONDITIONS", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "delete_account", + "name": "Delete Account", + "providerId": "delete_account", + "enabled": false, + "defaultAction": false, + "priority": 60, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "firstBrokerLoginFlow": "first broker login", + "attributes": { + "cibaBackchannelTokenDeliveryMode": "poll", + "cibaExpiresIn": "120", + "cibaAuthRequestedUserHint": "login_hint", + "oauth2DeviceCodeLifespan": "600", + "clientOfflineSessionMaxLifespan": "0", + "oauth2DevicePollingInterval": "5", + "clientSessionIdleTimeout": "0", + "parRequestUriLifespan": "60", + "clientSessionMaxLifespan": "0", + "clientOfflineSessionIdleTimeout": "0", + "cibaInterval": "5", + "realmReusableOtpCode": "false" + }, + "keycloakVersion": "24.0.1", + "userManagedAccessAllowed": false, + "clientProfiles": { + "profiles": [] + }, + "clientPolicies": { + "policies": [] + } +} diff --git a/deployment/terraform/assets/outputs.tf b/deployment/terraform/assets/outputs.tf index ec360370e..19a726553 100644 --- a/deployment/terraform/assets/outputs.tf +++ b/deployment/terraform/assets/outputs.tf @@ -14,6 +14,10 @@ output "metricsServer" { value = aws_instance.metrics_server } +output "keycloakServer" { + value = aws_instance.keycloak +} + output "proxy" { value = aws_instance.proxy_server } diff --git a/deployment/terraform/assets/variables.tf b/deployment/terraform/assets/variables.tf index f0f1e872e..bc366a722 100644 --- a/deployment/terraform/assets/variables.tf +++ b/deployment/terraform/assets/variables.tf @@ -116,6 +116,29 @@ variable "block_device_sizes_elasticsearch" { default = 20 } +# Keycloak variables +variable "block_device_sizes_keycloak" { + type = number + default = 10 +} + +variable "keycloak_enabled" { + type = bool +} + +variable "keycloak_instance_type" { +} + +variable "keycloak_version" { + type = string + default = "24.0.2" +} + +variable "keycloak_development_mode" { + type = bool +} + +# Job server variables variable "job_server_instance_count" { } diff --git a/deployment/terraform/create.go b/deployment/terraform/create.go index 79fe94c32..4efc1e5e8 100644 --- a/deployment/terraform/create.go +++ b/deployment/terraform/create.go @@ -188,6 +188,13 @@ func (t *Terraform) Create(initData bool) error { } } + if t.output.HasKeycloak() { + // Setting up keycloak. + if err := t.setupKeycloak(extAgent); err != nil { + return fmt.Errorf("error setting up keycloak server: %w", err) + } + } + if t.output.HasAppServers() { var siteURL string switch { @@ -263,6 +270,13 @@ func (t *Terraform) Create(initData bool) error { } } + if len(t.config.DBExtraSQL) > 0 { + // Run extra SQL commands if specified + if err := t.ExecuteCustomSQL(); err != nil { + errorsChan <- fmt.Errorf("failed to execute custom SQL: %w", err) + } + } + // Clear licenses data if err := t.ClearLicensesData(); err != nil { errorsChan <- fmt.Errorf("failed to clear old licenses data: %w", err) @@ -888,6 +902,19 @@ func (t *Terraform) updateAppConfig(siteURL string, sshc *ssh.Client, jobServerE } } + if t.output.HasKeycloak() { + keycloakScheme := "https" + if t.config.ExternalAuthProviderSettings.DevelopmentMode { + keycloakScheme = "http" + } + + cfg.OpenIdSettings.Enable = model.NewBool(true) + cfg.OpenIdSettings.ButtonText = model.NewString("Keycloak Login") + cfg.OpenIdSettings.DiscoveryEndpoint = model.NewString(keycloakScheme + "://" + t.output.KeycloakServer.PublicDNS + ":8080/realms/" + t.config.ExternalAuthProviderSettings.KeycloakRealmName + "/.well-known/openid-configuration") + cfg.OpenIdSettings.Id = model.NewString(t.config.ExternalAuthProviderSettings.KeycloakClientID) + cfg.OpenIdSettings.Secret = model.NewString(t.config.ExternalAuthProviderSettings.KeycloakClientSecret) + } + b, err := json.MarshalIndent(cfg, "", " ") if err != nil { return fmt.Errorf("error in marshalling config: %w", err) @@ -937,6 +964,7 @@ func (t *Terraform) init() error { assets.RestoreAssets(t.config.TerraformStateDir, "dashboard_data.json") assets.RestoreAssets(t.config.TerraformStateDir, "coordinator_dashboard_tmpl.json") assets.RestoreAssets(t.config.TerraformStateDir, "es_dashboard_data.json") + assets.RestoreAssets(t.config.TerraformStateDir, "keycloak.service") // We lock to make this call safe for concurrent use // since "terraform init" command can write to common files under diff --git a/deployment/terraform/dump.go b/deployment/terraform/dump.go index 25b224e0c..d3e2f0b4f 100644 --- a/deployment/terraform/dump.go +++ b/deployment/terraform/dump.go @@ -97,7 +97,7 @@ func (t *Terraform) IngestDump() error { return err } - if len(output.Instances) < 1 { + if len(t.output.Instances) < 1 { return fmt.Errorf("no app instances deployed") } @@ -118,17 +118,6 @@ func (t *Terraform) IngestDump() error { return err } - // stop - // reset - // load dump - // start - - stopCmd := deployment.Cmd{ - Msg: "Stopping app servers", - Value: "sudo systemctl stop mattermost", - Clients: appClients, - } - resetCmd, err := getResetCmd(t.config, output, appClients) if err != nil { return fmt.Errorf("error building reset cmd: %w", err) @@ -151,13 +140,122 @@ func (t *Terraform) IngestDump() error { } loadDBDumpCmd.Value = dbCmd - startCmd := deployment.Cmd{ + if err := t.executeDatabaseCommands([]deployment.Cmd{resetCmd, loadDBDumpCmd}); err != nil { + return fmt.Errorf("error ingesting db dump: %w", err) + } + + return nil +} + +// ExecuteCustomSQL executes provided custom SQL files in the app instances. +func (t *Terraform) ExecuteCustomSQL() error { + output, err := t.Output() + if err != nil { + return err + } + + extAgent, err := ssh.NewAgent() + if err != nil { + return err + } + + if len(output.Instances) < 1 { + return fmt.Errorf("no app instances deployed") + } + + client, err := extAgent.NewClient(output.Instances[0].PublicIP) + if err != nil { + return fmt.Errorf("error in getting ssh connection %w", err) + } + defer client.Close() + + var commands []deployment.Cmd + + for _, sqlURI := range t.config.DBExtraSQL { + fileName := filepath.Base(sqlURI) + mlog.Info("Provisioning SQL file", mlog.String("uri", sqlURI)) + if err := deployment.ProvisionURL(client, sqlURI, fileName); err != nil { + return err + } + + loadSQLFileCmd := deployment.Cmd{ + Msg: "Loading SQL file: " + fileName, + Clients: []*ssh.Client{client}, + } + + dbCmd, err := deployment.BuildLoadDBDumpCmd(fileName, deployment.DBSettings{ + UserName: t.config.TerraformDBSettings.UserName, + Password: t.config.TerraformDBSettings.Password, + DBName: t.config.DBName(), + Host: output.DBWriter(), + Engine: t.config.TerraformDBSettings.InstanceEngine, + }) + if err != nil { + return fmt.Errorf("error building command for loading DB dump: %w", err) + } + loadSQLFileCmd.Value = dbCmd + + commands = append(commands, loadSQLFileCmd) + } + + if err := t.executeDatabaseCommands(commands); err != nil { + return fmt.Errorf("error executing custom SQL files: %w", err) + } + + return nil +} + +// executeDatabaseCommands executes a series of commands stopping the mattermost service in the +// app instances then executing the provided commands and finally starting the mattermost service. +func (t *Terraform) executeDatabaseCommands(extraCommands []deployment.Cmd) error { + output, err := t.Output() + if err != nil { + return err + } + + extAgent, err := ssh.NewAgent() + if err != nil { + return err + } + + if len(output.Instances) < 1 { + return fmt.Errorf("no app instances deployed") + } + + appClients := make([]*ssh.Client, len(output.Instances)) + for i, instance := range output.Instances { + client, err := extAgent.NewClient(instance.PublicIP) + if err != nil { + return fmt.Errorf("error in getting ssh connection %w", err) + } + defer client.Close() + appClients[i] = client + } + + commands := []deployment.Cmd{{ + Msg: "Stopping app servers", + Value: "sudo systemctl stop mattermost", + Clients: appClients, + }} + + // Append provided commands + commands = append(commands, extraCommands...) + + commands = append(commands, deployment.Cmd{ Msg: "Restarting app server", Value: "sudo systemctl start mattermost && until $(curl -sSf http://localhost:8065 --output /dev/null); do sleep 1; done;", Clients: appClients, + }) + + if err := t.executeCommands(commands); err != nil { + return fmt.Errorf("error executing database commands: %w", err) } - for _, c := range []deployment.Cmd{stopCmd, resetCmd, loadDBDumpCmd, startCmd} { + return nil +} + +func (t *Terraform) executeCommands(commands []deployment.Cmd) error { + for _, c := range commands { mlog.Info(c.Msg) for _, client := range c.Clients { mlog.Debug("Running cmd", mlog.String("cmd", c.Value)) diff --git a/deployment/terraform/info.go b/deployment/terraform/info.go index 9118e8b4b..1e9644c58 100644 --- a/deployment/terraform/info.go +++ b/deployment/terraform/info.go @@ -56,6 +56,13 @@ func displayInfo(output *Output) { fmt.Println("Prometheus URL: http://" + output.MetricsServer.PublicIP + ":9090") fmt.Println("Pyroscope URL: http://" + output.MetricsServer.PublicIP + ":4040") } + if output.HasKeycloak() { + fmt.Println("Keycloak server IP: " + output.KeycloakServer.PublicIP) + fmt.Println("Keycloak URL: http://" + output.KeycloakServer.PublicDNS + ":8080/") + if len(output.KeycloakDatabaseCluster.Endpoints) > 0 { + fmt.Printf("Keycloak DB Cluster: %v\n", output.KeycloakDatabaseCluster.Endpoints[0]) + } + } if output.HasDB() { fmt.Println("DB Cluster Identifier: ", output.DBCluster.ClusterIdentifier) fmt.Println("DB writer endpoint: " + output.DBWriter()) diff --git a/deployment/terraform/keycloak.go b/deployment/terraform/keycloak.go new file mode 100644 index 000000000..8ede56786 --- /dev/null +++ b/deployment/terraform/keycloak.go @@ -0,0 +1,358 @@ +package terraform + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "net/http" + "os" + "path/filepath" + "strings" + "syscall" + "text/template" + "time" + + "github.com/mattermost/mattermost-load-test-ng/deployment" + "github.com/mattermost/mattermost-load-test-ng/deployment/terraform/assets" + "github.com/mattermost/mattermost-load-test-ng/deployment/terraform/ssh" + "github.com/mattermost/mattermost/server/public/shared/mlog" +) + +func (t *Terraform) setupKeycloak(extAgent *ssh.ExtAgent) error { + keycloakDir := "/opt/keycloak/keycloak-" + t.config.ExternalAuthProviderSettings.KeycloakVersion + keycloakBinPath := filepath.Join(keycloakDir, "bin") + + mlog.Info("Configuring keycloak", mlog.String("host", t.output.KeycloakServer.PublicIP)) + extraArguments := []string{} + + command := "start" + if t.config.ExternalAuthProviderSettings.DevelopmentMode { + command = "start-dev" + } + + sshc, err := extAgent.NewClient(t.output.KeycloakServer.PublicIP) + if err != nil { + return fmt.Errorf("error in getting ssh connection %w", err) + } + defer sshc.Close() + + // Check if the keycloak database exists + result, err := sshc.RunCommand(`sudo -iu postgres psql -l | grep keycloak | wc -l`) + if err != nil { + return fmt.Errorf("failed to check keycloak database: %w", err) + } + + if strings.TrimSpace(string(result)) == "0" { + mlog.Info("keycloak database not found, creating it and associated role") + + // Upload and import keycloak initial SQL file`` + _, err := sshc.Upload(strings.NewReader(assets.MustAssetString("keycloak-database.sql")), "/var/lib/postgresql/keycloak-database.sql", true) + if err != nil { + return fmt.Errorf("failed to upload keycloak base database sql file: %w", err) + } + + // Allow postgres user to read the file + _, err = sshc.RunCommand("sudo chown postgres:postgres /var/lib/postgresql/keycloak-database.sql") + if err != nil { + return fmt.Errorf("failed to change permissions on keycloak database sql file: %w", err) + } + + _, err = sshc.RunCommand(`sudo -iu postgres psql -v ON_ERROR_STOP=on -f /var/lib/postgresql/keycloak-database.sql`) + if err != nil { + return fmt.Errorf("failed to setup keycloak database: %w", err) + } + + if t.config.ExternalAuthProviderSettings.KeycloakDBDumpURI != "" && t.config.ExternalAuthProviderSettings.KeycloakRealmFilePath == "" { + err := t.IngestKeycloakDump() + if err != nil { + return fmt.Errorf("failed to ingest keycloak dump: %w", err) + } + } + } + + // If no keycloak dump URI is provided, check if we should use a custom realm file or + // proceed with the default one. + if t.config.ExternalAuthProviderSettings.KeycloakDBDumpURI == "" { + extraArguments = append(extraArguments, "--import-realm") + keycloakRealmFile, err := assets.AssetString("mattermost-realm.json") + if err != nil { + return fmt.Errorf("failed to read default keycloak realm file: %w", err) + } + + if t.config.ExternalAuthProviderSettings.KeycloakRealmFilePath != "" { + mlog.Info("Using provided realm configuration") + keycloakRealmFile = t.config.ExternalAuthProviderSettings.KeycloakRealmFilePath + } + + _, err = sshc.Upload( + strings.NewReader(keycloakRealmFile), + filepath.Join(keycloakDir, "data/import/mattermost-realm.json"), + true, + ) + if err != nil { + return fmt.Errorf("failed to upload default keycloak realm file: %w", err) + } + } + + // Values for the keycloak.env file + // TODO: Move to static asserts as a template file + keycloakEnvFileContents := []string{ + // Enable health endpoints + "KC_HEALTH_ENABLED=true", + // Setup admin user + "KEYCLOAK_ADMIN=" + t.config.ExternalAuthProviderSettings.KeycloakAdminUser, + "KEYCLOAK_ADMIN_PASSWORD=" + t.config.ExternalAuthProviderSettings.KeycloakAdminPassword, + // Ensure Java JVM has enough memory for large imports + "JAVA_OPTS=-Xms1024m -Xmx2048m", + // Logging + "KC_LOG_FILE=" + filepath.Join(keycloakDir, "data/log/keycloak.log"), + "KC_LOG_FILE_OUTPUT=json", + // Database + "KC_DB_POOL_MIN_SIZE=20", + "KC_DB_POOL_INITIAL_SIZE=20", + "KC_DB_POOL_MAX_SIZE=200", + "KC_DB=postgres", + "KC_DB_URL=jdbc:psql://localhost:5432/keycloak", + "KC_DB_PASSWORD=mmpass", + "KC_DB_USERNAME=keycloak", + "KC_DATABASE=keycloak", + } + + // Upload keycloak.env file + _, err = sshc.Upload(strings.NewReader(strings.Join(keycloakEnvFileContents, "\n")), "/etc/systemd/system/keycloak.env", true) + if err != nil { + return fmt.Errorf("failed to upload keycloak env file: %w", err) + } + + // Parse keycloak service file template + tmpl, err := template.New("keycloakServiceFile").Parse(keycloakServiceFileContents) + if err != nil { + return fmt.Errorf("failed to parse keycloak service file template: %w", err) + } + var buf bytes.Buffer + err = tmpl.Execute(&buf, struct { + KeycloakVersion string + Command string + }{ + KeycloakVersion: t.config.ExternalAuthProviderSettings.KeycloakVersion, + Command: command + " " + strings.Join(extraArguments, " "), + }) + if err != nil { + return fmt.Errorf("failed to execute keycloak service file template: %w", err) + } + + // Install systemd service + _, err = sshc.Upload(&buf, "/etc/systemd/system/keycloak.service", true) + if err != nil { + return fmt.Errorf("failed to upload keycloak service file: %w", err) + } + + _, err = sshc.RunCommand("sudo systemctl daemon-reload") + if err != nil { + return fmt.Errorf("failed to reload systemd: %w", err) + } + + // Ensure service is enabled + _, err = sshc.RunCommand("sudo systemctl enable keycloak") + if err != nil { + return fmt.Errorf("failed to enable keycloak service: %w", err) + } + + // Using restart to apply any possible changes to the service + _, err = sshc.RunCommand("sudo systemctl restart keycloak") + if err != nil { + return fmt.Errorf("failed to restart keycloak service: %w", err) + } + + // Wait for keycloak to start + url := fmt.Sprintf("http://%s:8080/health", t.output.KeycloakServer.PublicDNS) + timeout := time.After(120 * time.Second) // yes, is **that** slow + for { + resp, err := http.Get(url) + if err != nil { + // Avoid error spamming + if !errors.Is(err, syscall.ECONNREFUSED) { + mlog.Error("Failed to connect to keycloak", mlog.Err(err)) + continue + } + } + + if err == nil { + resp.Body.Close() + // Keycloak is ready + if resp.StatusCode == http.StatusOK { + break + } + } + + mlog.Info("Keycloak service not up yet, waiting...") + select { + case <-timeout: + return errors.New("timeout: keycloak service is not responding") + case <-time.After(5 * time.Second): + } + } + + // Authenticate as admin to execute keycloak commands + _, err = sshc.RunCommand(fmt.Sprintf("%s/kcadm.sh config credentials --server http://127.0.0.1:8080 --user %s --password %s --realm master", keycloakBinPath, t.config.ExternalAuthProviderSettings.KeycloakAdminUser, t.config.ExternalAuthProviderSettings.KeycloakAdminPassword)) + if err != nil { + return fmt.Errorf("failed to authenticate keycload admin: %w", err) + } + + // Disable SSL requirement on master realm to allow http connections on the web interface + _, err = sshc.RunCommand(keycloakBinPath + "/kcadm.sh update realms/master -s sslRequired=NONE") + if err != nil { + return fmt.Errorf("failed to disable ssl requirement: %w", err) + } + + // Populate users + if t.config.ExternalAuthProviderSettings.GenerateUsersCount > 0 { + if err := t.populateKeycloakUsers(sshc); err != nil { + return fmt.Errorf("failed to populate keycloak users: %w", err) + } + + mlog.Info("Overriding the users file path with the generated one from keycloak") + t.config.UsersFilePath = t.getAsset("keycloak-users.txt") + } + + mlog.Info("Keycloak configured") + + return nil +} + +// populateKeycloakUsers creates users in keycloak and writes their credentials to a users file. +// It will use the `GenerateUsersCount` configuration option to create as many users as the configuration +// specifies. If the users file already exists and has the expected number of users, it will skip user creation. +// If the file has less users than expected, it will start creating users from the next number by counting the +// number of lines in the file. +// If the file has more users than expected, it will log and skip the user creation. +func (t *Terraform) populateKeycloakUsers(sshc *ssh.Client) error { + keycloakBinPath := "/opt/keycloak/keycloak-" + t.config.ExternalAuthProviderSettings.KeycloakVersion + "/bin" + usersTxtPath := t.getAsset("keycloak-users.txt") + startNumber := 1 + + // Check if users file exists and has the expected number of users. If the file has less users than expected, + // we will start creating users from the next number, otherwise we will skip user creation. + if _, err := os.Stat(usersTxtPath); err == nil { + // Check number of lines in the file to check the number of users already created + file, err := os.Open(usersTxtPath) + if err != nil { + return fmt.Errorf("failed to open keycloak users file: %w", err) + } + defer file.Close() + + lines := 0 + scanner := bufio.NewScanner(file) + for scanner.Scan() { + // Avoid empty lines (last line is empty since text files should end with a newline character) + if scanner.Text() == "" { + continue + } + + lines++ + } + + if lines >= t.config.ExternalAuthProviderSettings.GenerateUsersCount { + mlog.Info( + "Users file already exists and has the expected number of users (or more), skipping user creation", + mlog.Int("generate_users_count", t.config.ExternalAuthProviderSettings.GenerateUsersCount), + mlog.Int("users_count", lines), + ) + return nil + } + + if lines < t.config.ExternalAuthProviderSettings.GenerateUsersCount { + startNumber = lines + 1 + mlog.Info( + "Users file already exists but has less users than expected, starting from the next number", + mlog.Int("users_count", lines), + mlog.Int("start_number", startNumber), + ) + } + } + + mlog.Info("Populating keycloak with users", mlog.String("users_file", usersTxtPath), mlog.Int("users_count", t.config.ExternalAuthProviderSettings.GenerateUsersCount)) + + // Open users.txt file + handler, err := os.OpenFile(usersTxtPath, os.O_CREATE|os.O_WRONLY, 0666) + if err != nil { + return fmt.Errorf("failed to open keycloak users file: %w", err) + } + defer handler.Close() + + // Create users + for i := startNumber; i <= t.config.ExternalAuthProviderSettings.GenerateUsersCount; i++ { + username := fmt.Sprintf("keycloak-auto-%06d", i) + password := username // we just use the same string for both + + email := username + "@test.mattermost.com" + + _, err := sshc.RunCommand(fmt.Sprintf("%s/kcadm.sh create users -r %s -s username=%s -s enabled=true -s email=%s", keycloakBinPath, t.config.ExternalAuthProviderSettings.KeycloakRealmName, username, email)) + if err != nil { + return fmt.Errorf("failed to create keycloak user: %w", err) + } + + _, err = sshc.RunCommand(fmt.Sprintf("%s/kcadm.sh set-password -r %s --username %s --new-password %s", keycloakBinPath, t.config.ExternalAuthProviderSettings.KeycloakRealmName, username, password)) + if err != nil { + return fmt.Errorf("failed to set keycloak user password: %w", err) + } + + handler.Write([]byte(fmt.Sprintf("openid:%s %s\n", email, password))) + } + + return nil +} + +func (t *Terraform) IngestKeycloakDump() error { + mlog.Info("Populating keycloak database with provided dump") + + output, err := t.Output() + if err != nil { + return err + } + + extAgent, err := ssh.NewAgent() + if err != nil { + return err + } + + if output.KeycloakServer.PrivateIP == "" { + return fmt.Errorf("no keycloak instances deployed") + } + + client, err := extAgent.NewClient(output.KeycloakServer.PublicIP) + if err != nil { + return fmt.Errorf("error in getting ssh connection %w", err) + } + defer client.Close() + + // Ensure keycloak is stopped + _, err = client.RunCommand("sudo systemctl stop keycloak") + // Ignore errors if the serivce file does not exist yet (on first creation) + if err != nil && !strings.Contains(err.Error(), "exited with status 5") { + return fmt.Errorf("failed to stop keycloak before uploading the dump file: %w", err) + } + + dumpURI := t.config.ExternalAuthProviderSettings.KeycloakDBDumpURI + fileName := filepath.Base(dumpURI) + mlog.Info("Provisioning keycloak dump file", mlog.String("uri", dumpURI)) + if err := deployment.ProvisionURL(client, dumpURI, fileName); err != nil { + return err + } + + commands := []string{ + "tar xzf /home/ubuntu/" + fileName + " -C /tmp", + "sudo -iu postgres psql -d keycloak -v ON_ERROR_STOP=on -f /tmp/" + strings.TrimSuffix(fileName, ".tgz"), + } + + for _, cmd := range commands { + output, err := client.RunCommand(cmd) + if err != nil { + mlog.Error("Error running command", mlog.String("command", cmd), mlog.String("result", string(output)), mlog.Err(err)) + return fmt.Errorf("failed to run command %q: %w", cmd, err) + } + } + + return nil +} diff --git a/deployment/terraform/metrics.go b/deployment/terraform/metrics.go index 2d8b39d4c..15ab1835c 100644 --- a/deployment/terraform/metrics.go +++ b/deployment/terraform/metrics.go @@ -116,7 +116,7 @@ func (t *Terraform) setupMetrics(extAgent *ssh.ExtAgent) error { } var hosts string - var mmTargets, nodeTargets, esTargets, ltTargets []string + var mmTargets, nodeTargets, esTargets, ltTargets, keycloakTargets []string for i, val := range t.output.Instances { host := fmt.Sprintf("app-%d", i) mmTargets = append(mmTargets, fmt.Sprintf("%s:8067", host)) @@ -157,6 +157,12 @@ func (t *Terraform) setupMetrics(extAgent *ssh.ExtAgent) error { } } + if t.output.HasKeycloak() { + host := "keycloak" + keycloakTargets = append(keycloakTargets, fmt.Sprintf("%s:8080", host)) + hosts += fmt.Sprintf("%s %s\n", t.output.KeycloakServer.PrivateIP, host) + } + quoteAll := func(elems []string) []string { quoted := make([]string, 0, len(elems)) for _, elem := range elems { @@ -171,6 +177,7 @@ func (t *Terraform) setupMetrics(extAgent *ssh.ExtAgent) error { strings.Join(quoteAll(mmTargets), ","), strings.Join(quoteAll(esTargets), ","), strings.Join(quoteAll(ltTargets), ","), + strings.Join(quoteAll(keycloakTargets), ""), ) rdr := strings.NewReader(prometheusConfigFile) if out, err := sshc.Upload(rdr, "/etc/prometheus/prometheus.yml", true); err != nil { diff --git a/deployment/terraform/output.go b/deployment/terraform/output.go index 821a984d6..34ea349bf 100644 --- a/deployment/terraform/output.go +++ b/deployment/terraform/output.go @@ -34,6 +34,15 @@ type output struct { ElasticRoleARN struct { Value string } `json:"elasticRoleARN"` + KeycloakServer struct { + Value []Instance `json:"value"` + } `json:"keycloakServer"` + KeycloakDatabaseCluster struct { + Value []struct { + Endpoint string `json:"endpoint"` + ClusterIdentifier string `json:"cluster_identifier"` + } `json:"value"` + } `json:"keycloakDatabaseCluster"` JobServers struct { Value []Instance `json:"value"` } `json:"jobServers"` @@ -51,18 +60,20 @@ type output struct { // Output contains the output variables which are // created after a deployment. type Output struct { - ClusterName string - Proxy Instance `json:"proxy"` - Instances []Instance `json:"instances"` - DBCluster DBCluster `json:"dbCluster"` - Agents []Instance `json:"agents"` - MetricsServer Instance `json:"metricsServer"` - ElasticSearchServer ElasticSearchDomain `json:"elasticServer"` - ElasticSearchRoleARN string `json:"elasticRoleARN"` - JobServers []Instance `json:"jobServers"` - S3Bucket S3Bucket `json:"s3Bucket"` - S3Key IAMAccess `json:"s3Key"` - DBSecurityGroup []SecurityGroup `json:"dbSecurityGroup"` + ClusterName string + Proxy Instance `json:"proxy"` + Instances []Instance `json:"instances"` + DBCluster DBCluster `json:"dbCluster"` + Agents []Instance `json:"agents"` + MetricsServer Instance `json:"metricsServer"` + ElasticSearchServer ElasticSearchDomain `json:"elasticServer"` + ElasticSearchRoleARN string `json:"elasticRoleARN"` + JobServers []Instance `json:"jobServers"` + S3Bucket S3Bucket `json:"s3Bucket"` + S3Key IAMAccess `json:"s3Key"` + DBSecurityGroup []SecurityGroup `json:"dbSecurityGroup"` + KeycloakServer Instance `json:"keycloakServer"` + KeycloakDatabaseCluster DBCluster `json:"keycloakDatabaseCluster"` } // Instance is an AWS EC2 instance resource. @@ -155,6 +166,15 @@ func (t *Terraform) loadOutput() error { if len(o.S3Key.Value) > 0 { outputv2.S3Key = o.S3Key.Value[0] } + if len(o.KeycloakServer.Value) > 0 { + outputv2.KeycloakServer = o.KeycloakServer.Value[0] + } + if len(o.KeycloakDatabaseCluster.Value) > 0 { + for _, ep := range o.KeycloakDatabaseCluster.Value { + outputv2.KeycloakDatabaseCluster.Endpoints = append(outputv2.KeycloakDatabaseCluster.Endpoints, ep.Endpoint) + } + outputv2.KeycloakDatabaseCluster.ClusterIdentifier = o.KeycloakDatabaseCluster.Value[0].ClusterIdentifier + } if len(o.DBSecurityGroup.Value) > 0 { outputv2.DBSecurityGroup = append(outputv2.DBSecurityGroup, o.DBSecurityGroup.Value...) @@ -226,6 +246,11 @@ func (o *Output) HasJobServer() bool { return len(o.JobServers) > 0 } +// HasKeycloak returns whether a deployment has Keycloak installed in it or not. +func (o *Output) HasKeycloak() bool { + return o.KeycloakServer.PrivateIP != "" +} + // DBReaders returns the list of db reader endpoints. func (o *Output) DBReaders() []string { var rds []string diff --git a/deployment/terraform/strings.go b/deployment/terraform/strings.go index 6ee9cd171..e8619e27e 100644 --- a/deployment/terraform/strings.go +++ b/deployment/terraform/strings.go @@ -48,6 +48,9 @@ scrape_configs: - job_name: loadtest static_configs: - targets: [%s] + - job_name: keycloak + static_configs: + - targets: [%s] ` type PyroscopeConfig struct { @@ -361,3 +364,18 @@ org_role = Editor [dashboards] default_home_dashboard_path = /var/lib/grafana/dashboards/dashboard.json ` + +const keycloakServiceFileContents = ` +[Unit] +Description=Keycloak +After=network.target + +[Service] +User=ubuntu +Group=ubuntu +EnvironmentFile=/etc/systemd/system/keycloak.env +ExecStart=/opt/keycloak/keycloak-{{ .KeycloakVersion }}/bin/kc.sh {{ .Command }} + +[Install] +WantedBy=multi-user.target +` diff --git a/deployment/terraform/utils.go b/deployment/terraform/utils.go index d994df80a..d2b6295fb 100644 --- a/deployment/terraform/utils.go +++ b/deployment/terraform/utils.go @@ -15,6 +15,7 @@ import ( "strings" "text/template" + "github.com/mattermost/mattermost-load-test-ng/deployment" "github.com/mattermost/mattermost-load-test-ng/deployment/terraform/ssh" "github.com/mattermost/mattermost/server/public/model" @@ -239,6 +240,9 @@ func (t *Terraform) getParams() []string { "-var", fmt.Sprintf("db_password=%s", t.config.TerraformDBSettings.Password), "-var", fmt.Sprintf("db_enable_performance_insights=%t", t.config.TerraformDBSettings.EnablePerformanceInsights), "-var", fmt.Sprintf("db_parameters=%s", t.config.TerraformDBSettings.DBParameters), + "-var", fmt.Sprintf("keycloak_enabled=%v", t.config.ExternalAuthProviderSettings.Enabled), + "-var", fmt.Sprintf("keycloak_development_mode=%v", t.config.ExternalAuthProviderSettings.DevelopmentMode), + "-var", fmt.Sprintf("keycloak_instance_type=%s", t.config.ExternalAuthProviderSettings.InstanceType), "-var", fmt.Sprintf("mattermost_license_file=%s", t.config.MattermostLicenseFile), "-var", fmt.Sprintf("job_server_instance_count=%d", t.config.JobServerSettings.InstanceCount), "-var", fmt.Sprintf("job_server_instance_type=%s", t.config.JobServerSettings.InstanceType), @@ -250,6 +254,7 @@ func (t *Terraform) getParams() []string { "-var", fmt.Sprintf("block_device_sizes_metrics=%d", t.config.StorageSizes.Metrics), "-var", fmt.Sprintf("block_device_sizes_job=%d", t.config.StorageSizes.Job), "-var", fmt.Sprintf("block_device_sizes_elasticsearch=%d", t.config.StorageSizes.ElasticSearch), + "-var", fmt.Sprintf("block_device_sizes_keycloak=%d", t.config.StorageSizes.KeyCloak), } } @@ -268,3 +273,23 @@ func (t *Terraform) getClusterDSN() (string, error) { func (t *Terraform) getAsset(filename string) string { return filepath.Join(t.config.TerraformStateDir, filename) } + +// getServerURL returns the URL of the server to be used for testing. +// server URL priority: +// 1. SiteURL +// 2. Proxy IP +// 3. First app server IP +func getServerURL(output *Output, deploymentConfig *deployment.Config) string { + url := output.Instances[0].PrivateIP + if deploymentConfig.SiteURL != "" { + url = deploymentConfig.SiteURL + } + + if !output.HasProxy() { + url = url + ":8065" + } else if deploymentConfig.SiteURL == "" { + url = output.Proxy.PrivateIP + } + + return url +} diff --git a/deployment/terraform/utils_test.go b/deployment/terraform/utils_test.go index ed6e552e4..8e844b6a1 100644 --- a/deployment/terraform/utils_test.go +++ b/deployment/terraform/utils_test.go @@ -6,6 +6,7 @@ package terraform import ( "testing" + "github.com/mattermost/mattermost-load-test-ng/deployment" "github.com/stretchr/testify/require" ) @@ -32,3 +33,64 @@ func TestFillConfigTemplate(t *testing.T) { require.Equal(t, "this is a template", output) }) } + +func TestGetServerURL(t *testing.T) { + for _, tc := range []struct { + name string + output *Output + config *deployment.Config + expected string + }{ + { + name: "no proxy, no siteurl", + output: &Output{ + Instances: []Instance{{ + PrivateIP: "localhost", + }}, + }, + config: &deployment.Config{}, + expected: "localhost:8065", + }, { + name: "proxy, no siteurl", + output: &Output{ + Instances: []Instance{{ + PrivateIP: "localhost", + }}, + Proxy: Instance{ + PrivateIP: "proxy_ip", + }, + }, + config: &deployment.Config{}, + expected: "proxy_ip", + }, { + name: "no proxy, siteurl", + output: &Output{ + Instances: []Instance{{ + PrivateIP: "localhost", + }}, + }, + config: &deployment.Config{ + SiteURL: "ltserver", + }, + expected: "ltserver:8065", + }, { + name: "proxy, siteurl", + output: &Output{ + Instances: []Instance{{ + PrivateIP: "localhost", + }}, + Proxy: Instance{ + PrivateIP: "proxy_ip", + }, + }, + config: &deployment.Config{ + SiteURL: "ltserver", + }, + expected: "ltserver", + }, + } { + t.Run(tc.name, func(t *testing.T) { + require.Equal(t, tc.expected, getServerURL(tc.output, tc.config)) + }) + } +} diff --git a/docs/external_auth_providers.md b/docs/external_auth_providers.md new file mode 100644 index 000000000..64bc6b714 --- /dev/null +++ b/docs/external_auth_providers.md @@ -0,0 +1,85 @@ +# External authentication providers + +## Introduction + +External authentication providers are used to authenticate users against an external system. This is useful when you want to use an existing authentication system, such as LDAP, to authenticate users in your application and avoid the performance hit of managing (login in) users in the Mattermost server. + +In the case of the load-test tool, a Keycloak server is used as the authentication provider. Keycloak is an open-source identity and access management solution that provides a way to authenticate users against an external system. + +> **The load-test currently only supports OpenID Connect as an external authentication provider.** + +## Configuration options + +``` js +{ + // ... + "ExternalAuthProviderSettings": { + "Enabled": true, + "KeycloakAdminUser": "mmadmin", + "KeycloakAdminPassword": "mmpass", + "KeycloakRealmFilePath": "", + "KeycloakDBDumpURI": "", + "GenerateUsersCount": 0, + "InstanceType": "t3.medium", + }, + // ... +} +``` + +See the [reference code in the deployment/config.go file](../deployment/config.go#L188). + +- **Enabled**: Whether to enable the deployment of the Keycloak server. +- **KeycloakVersion**: The version of Keycloak to deploy. +- **KeycloakAdminUser**: The username of the Keycloak admin user. +- **KeycloakAdminPassword**: The password of the Keycloak admin user. +- **KeycloakRealmFilePath**: The path to a Keycloak realm file to use as import data. + - If empty the load test will import a default one. + - See the [The keycloak realm](#the-keycloak-realm) section for more information. +- **KeycloakDBDumpURI**: The URI of a database dump to use as import data. + - See the [Importing a database dump](#importing-a-database-dump) section for more information. +- **GenerateUsersCount**: The number of users to generate in the Keycloak server, if `0` no users will be generated. + - See the [Generating users](#generating-users) section for more information. +- **InstanceType**: The instance type to use for the keycloak server. + +## Enabling the Keycloak server + +In order to enable the deployment of the Keycloak server (and configuration of the Mattermost instance to go along with it) you only need to set the `ExernalAuthProviderSettings.Enabled` setting to `true` in the deployer configuration. + +## The keycloak realm + +The Keycloak server uses a realm to manage users and applications. A realm is a container for users, applications, and groups. It is an isolated space where applications authenticate users and manage their security credentials, including password policies, user roles, and social logins. + +- If you want to use a custom realm file, you can upload it to the Keycloak server by setting the `KeycloakRealmFilePath` configuration option to the path of the file. + +- If this option is left empty, the load-test tool will use a default realm file with the following usable credentials: + - To log in in mattermost: `keycloak-user-01`/`keycloak-user-01`. + - To log in into the Keycloak admin interface: `mmadmin`/`mmpass`. + +## Importing a database dump + +The `KeycloakDBDumpURI` configuration option allows you to import a database dump into the Keycloak server. This is useful when you want to use a database dump from a previous Keycloak server deployment. + +It should be a `.tgz` compressed file containing the database dump as a `.sql` file. The SQL file should be a full dump of the Keycloak database since no initialiaztion will be done when this parameter is set. + +This option allows the use of an URI (can be `http://`, `https://`, or `file://`) to a database dump file. + +## Generating users + +> **WARNING**: Generating users is usually really slow, if you plan to use more than a couple hundred users you should consider using a custom realm file. + +The `GenerateUsersCount` configuration option allows you to generate a number of users in the Keycloak server. This is useful when you want to test the load-test tool with a small number of users. + +This option will override the `UsersConfiguration.UserFilePath` option with the path to a file containing the generated users. + +## Specifying users in the `UsersFilePath` file + +Keycloak users can be specified in the file specified by the `UsersConfiguration.UserFilePath` configuration option by prepending `openid:` to the users email. This will tell the load-test tool to use the OpenID Connect authentication provider to authenticate the user. + +```txt +openid:user1@test.mattermost.com user1password +... +``` + +## Development mode + +The `DevelopmentMode` configuration option allows you to deploy the Keycloak server in development mode. This changes the command used to start the server from `start` (production) to `start-dev` (development) so Keycloak [disables several features](https://www.keycloak.org/server/configuration#_starting_keycloak_in_development_mode) to ease up the environment creation process. diff --git a/loadtest/user/userentity/actions.go b/loadtest/user/userentity/actions.go index 2a6c466e7..c531d5f93 100644 --- a/loadtest/user/userentity/actions.go +++ b/loadtest/user/userentity/actions.go @@ -11,6 +11,9 @@ import ( "fmt" "io" "net/http" + "net/http/cookiejar" + "net/url" + "regexp" "strconv" "github.com/graph-gophers/graphql-go" @@ -18,21 +21,111 @@ import ( "github.com/mattermost/mattermost/server/public/model" ) +// Possible actions for the openID authentication +type authOpenIDAction string + +const ( + authOpenIDLogin authOpenIDAction = "login" + authOpenIDSignup authOpenIDAction = "signup" +) + +var ( + openIDLoginFormActionRegex = regexp.MustCompile(`action=["'](.*?)["']`) +) + // SignUp signs up the user with the given credentials. func (ue *UserEntity) SignUp(email, username, password string) error { - user := model.User{ - Email: email, - Username: username, - Password: password, + var newUser *model.User + var err error + + switch ue.config.AuthenticationType { + case AuthenticationTypeOpenID: + if err := ue.authOpenID(authOpenIDSignup); err != nil { + return fmt.Errorf("error while signing up using OpenID: %w", err) + } + + newUser, _, err = ue.client.GetUserByUsername(context.Background(), username, "") + if err != nil { + return fmt.Errorf("error while getting user by username: %w", err) + } + default: + user := model.User{ + Email: email, + Username: username, + Password: password, + } + + newUser, _, err = ue.client.CreateUser(context.Background(), &user) + if err != nil { + return err + } + + newUser.Password = password } + return ue.store.SetUser(newUser) +} - newUser, _, err := ue.client.CreateUser(context.Background(), &user) +// authOpenID logs the user in using OpenID. +func (ue *UserEntity) authOpenID(action authOpenIDAction) error { + if action != authOpenIDLogin && action != authOpenIDSignup { + return errors.New("invalid openid auth action") + } + + jar, err := cookiejar.New(nil) if err != nil { - return err + return fmt.Errorf("error while creating cookie jar: %w", err) } - newUser.Password = password - return ue.store.SetUser(newUser) + client := &http.Client{ + Jar: jar, + } + + // make a request to the openid login page of mattermost + resp, err := client.Get(ue.client.URL + "/oauth/openid/" + string(action)) + if err != nil { + return fmt.Errorf("error while making request to openid %s page: %w", action, err) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return fmt.Errorf("error while reading response body: %w", err) + } + resp.Body.Close() + + loginURL := string(openIDLoginFormActionRegex.FindSubmatch(body)[1]) + + loginResponse, err := client.PostForm(loginURL, url.Values{ + "username": {ue.config.Username}, + "password": {ue.config.Password}, + }) + if err != nil { + return fmt.Errorf("error while %s in: %w", action, err) + } + + if loginResponse.StatusCode != http.StatusOK { + return fmt.Errorf("%s failed with status code %d", action, loginResponse.StatusCode) + } + + cookies := jar.Cookies(loginResponse.Request.URL) + for _, cookie := range cookies { + if cookie.Name == "MMAUTHTOKEN" { + ue.client.SetToken(cookie.Value) + + // TODO: Move to Login/SignUp methods (GetUserByUsername) + me, _, err := ue.client.GetMe(context.Background(), "") + if err != nil { + return fmt.Errorf("error while getting user: %w", err) + } + + if err := ue.store.SetUser(me); err != nil { + return fmt.Errorf("error while setting user: %w", err) + } + + return nil + } + } + + return fmt.Errorf("Token was not found in headers") } // Login logs the user in. It authenticates a user and starts a new session. @@ -42,17 +135,23 @@ func (ue *UserEntity) Login() error { return err } - loggedUser, _, err := ue.client.Login(context.Background(), user.Email, user.Password) - if err != nil { - return err - } + switch ue.config.AuthenticationType { + case AuthenticationTypeOpenID: + if err := ue.authOpenID(authOpenIDLogin); err != nil { + return fmt.Errorf("error while logging in using OpenID: %w", err) + } + default: + loggedUser, _, err := ue.client.Login(context.Background(), user.Email, user.Password) + if err != nil { + return fmt.Errorf("error while logging in: %w", err) + } - // We need to set user again because the user ID does not get set - // if a user is already signed up. - if err := ue.store.SetUser(loggedUser); err != nil { - return err + // We need to set user again because the user ID does not get set + // if a user is already signed up. + if err := ue.store.SetUser(loggedUser); err != nil { + return fmt.Errorf("error while setting user: %w", err) + } } - return nil } diff --git a/loadtest/user/userentity/helper_test.go b/loadtest/user/userentity/helper_test.go index 91b299895..271518f30 100644 --- a/loadtest/user/userentity/helper_test.go +++ b/loadtest/user/userentity/helper_test.go @@ -89,6 +89,7 @@ func (th *TestHelper) CreateUser() *UserEntity { u := New(Setup{Store: s}, Config{ th.config.ConnectionConfiguration.ServerURL, th.config.ConnectionConfiguration.WebSocketURL, + AuthenticationTypeMattermost, "testuser", "testuser@example.com", "testpassword", diff --git a/loadtest/user/userentity/user.go b/loadtest/user/userentity/user.go index 4863b1cb3..d69237fcc 100644 --- a/loadtest/user/userentity/user.go +++ b/loadtest/user/userentity/user.go @@ -33,12 +33,19 @@ type UserEntity struct { wsServerSeq int64 } +const ( + AuthenticationTypeMattermost = "mattermost" + AuthenticationTypeOpenID = "openid" +) + // Config holds necessary information required by a UserEntity. type Config struct { // The URL of the Mattermost web server. ServerURL string // The URL of the mattermost WebSocket server. WebSocketURL string + // The type of authentication to be used by the entity. + AuthenticationType string // The username to be used by the entity. Username string // The email to be used by the entity.