github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/aws/validators.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "net" 6 "net/url" 7 "regexp" 8 "strings" 9 "time" 10 11 "github.com/aws/aws-sdk-go/service/apigateway" 12 "github.com/aws/aws-sdk-go/service/s3" 13 "github.com/hashicorp/terraform/helper/schema" 14 ) 15 16 func validateRdsIdentifier(v interface{}, k string) (ws []string, errors []error) { 17 value := v.(string) 18 if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) { 19 errors = append(errors, fmt.Errorf( 20 "only lowercase alphanumeric characters and hyphens allowed in %q", k)) 21 } 22 if !regexp.MustCompile(`^[a-z]`).MatchString(value) { 23 errors = append(errors, fmt.Errorf( 24 "first character of %q must be a letter", k)) 25 } 26 if regexp.MustCompile(`--`).MatchString(value) { 27 errors = append(errors, fmt.Errorf( 28 "%q cannot contain two consecutive hyphens", k)) 29 } 30 if regexp.MustCompile(`-$`).MatchString(value) { 31 errors = append(errors, fmt.Errorf( 32 "%q cannot end with a hyphen", k)) 33 } 34 return 35 } 36 37 func validateRdsIdentifierPrefix(v interface{}, k string) (ws []string, errors []error) { 38 value := v.(string) 39 if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) { 40 errors = append(errors, fmt.Errorf( 41 "only lowercase alphanumeric characters and hyphens allowed in %q", k)) 42 } 43 if !regexp.MustCompile(`^[a-z]`).MatchString(value) { 44 errors = append(errors, fmt.Errorf( 45 "first character of %q must be a letter", k)) 46 } 47 if regexp.MustCompile(`--`).MatchString(value) { 48 errors = append(errors, fmt.Errorf( 49 "%q cannot contain two consecutive hyphens", k)) 50 } 51 return 52 } 53 54 func validateElastiCacheClusterId(v interface{}, k string) (ws []string, errors []error) { 55 value := v.(string) 56 if (len(value) < 1) || (len(value) > 20) { 57 errors = append(errors, fmt.Errorf( 58 "%q (%q) must contain from 1 to 20 alphanumeric characters or hyphens", k, value)) 59 } 60 if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) { 61 errors = append(errors, fmt.Errorf( 62 "only lowercase alphanumeric characters and hyphens allowed in %q (%q)", k, value)) 63 } 64 if !regexp.MustCompile(`^[a-z]`).MatchString(value) { 65 errors = append(errors, fmt.Errorf( 66 "first character of %q (%q) must be a letter", k, value)) 67 } 68 if regexp.MustCompile(`--`).MatchString(value) { 69 errors = append(errors, fmt.Errorf( 70 "%q (%q) cannot contain two consecutive hyphens", k, value)) 71 } 72 if regexp.MustCompile(`-$`).MatchString(value) { 73 errors = append(errors, fmt.Errorf( 74 "%q (%q) cannot end with a hyphen", k, value)) 75 } 76 return 77 } 78 79 func validateASGScheduleTimestamp(v interface{}, k string) (ws []string, errors []error) { 80 value := v.(string) 81 _, err := time.Parse(awsAutoscalingScheduleTimeLayout, value) 82 if err != nil { 83 errors = append(errors, fmt.Errorf( 84 "%q cannot be parsed as iso8601 Timestamp Format", value)) 85 } 86 87 return 88 } 89 90 // validateTagFilters confirms the "value" component of a tag filter is one of 91 // AWS's three allowed types. 92 func validateTagFilters(v interface{}, k string) (ws []string, errors []error) { 93 value := v.(string) 94 if value != "KEY_ONLY" && value != "VALUE_ONLY" && value != "KEY_AND_VALUE" { 95 errors = append(errors, fmt.Errorf( 96 "%q must be one of \"KEY_ONLY\", \"VALUE_ONLY\", or \"KEY_AND_VALUE\"", k)) 97 } 98 return 99 } 100 101 func validateDbParamGroupName(v interface{}, k string) (ws []string, errors []error) { 102 value := v.(string) 103 if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) { 104 errors = append(errors, fmt.Errorf( 105 "only lowercase alphanumeric characters and hyphens allowed in %q", k)) 106 } 107 if !regexp.MustCompile(`^[a-z]`).MatchString(value) { 108 errors = append(errors, fmt.Errorf( 109 "first character of %q must be a letter", k)) 110 } 111 if regexp.MustCompile(`--`).MatchString(value) { 112 errors = append(errors, fmt.Errorf( 113 "%q cannot contain two consecutive hyphens", k)) 114 } 115 if regexp.MustCompile(`-$`).MatchString(value) { 116 errors = append(errors, fmt.Errorf( 117 "%q cannot end with a hyphen", k)) 118 } 119 if len(value) > 255 { 120 errors = append(errors, fmt.Errorf( 121 "%q cannot be greater than 255 characters", k)) 122 } 123 return 124 } 125 126 func validateDbParamGroupNamePrefix(v interface{}, k string) (ws []string, errors []error) { 127 value := v.(string) 128 if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) { 129 errors = append(errors, fmt.Errorf( 130 "only lowercase alphanumeric characters and hyphens allowed in %q", k)) 131 } 132 if !regexp.MustCompile(`^[a-z]`).MatchString(value) { 133 errors = append(errors, fmt.Errorf( 134 "first character of %q must be a letter", k)) 135 } 136 if regexp.MustCompile(`--`).MatchString(value) { 137 errors = append(errors, fmt.Errorf( 138 "%q cannot contain two consecutive hyphens", k)) 139 } 140 if len(value) > 255 { 141 errors = append(errors, fmt.Errorf( 142 "%q cannot be greater than 226 characters", k)) 143 } 144 return 145 } 146 147 func validateStreamViewType(v interface{}, k string) (ws []string, errors []error) { 148 value := v.(string) 149 viewTypes := map[string]bool{ 150 "KEYS_ONLY": true, 151 "NEW_IMAGE": true, 152 "OLD_IMAGE": true, 153 "NEW_AND_OLD_IMAGES": true, 154 } 155 156 if !viewTypes[value] { 157 errors = append(errors, fmt.Errorf("%q be a valid DynamoDB StreamViewType", k)) 158 } 159 return 160 } 161 162 func validateElbName(v interface{}, k string) (ws []string, errors []error) { 163 value := v.(string) 164 if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) { 165 errors = append(errors, fmt.Errorf( 166 "only alphanumeric characters and hyphens allowed in %q: %q", 167 k, value)) 168 } 169 if len(value) > 32 { 170 errors = append(errors, fmt.Errorf( 171 "%q cannot be longer than 32 characters: %q", k, value)) 172 } 173 if regexp.MustCompile(`^-`).MatchString(value) { 174 errors = append(errors, fmt.Errorf( 175 "%q cannot begin with a hyphen: %q", k, value)) 176 } 177 if regexp.MustCompile(`-$`).MatchString(value) { 178 errors = append(errors, fmt.Errorf( 179 "%q cannot end with a hyphen: %q", k, value)) 180 } 181 return 182 } 183 184 func validateElbNamePrefix(v interface{}, k string) (ws []string, errors []error) { 185 value := v.(string) 186 if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) { 187 errors = append(errors, fmt.Errorf( 188 "only alphanumeric characters and hyphens allowed in %q: %q", 189 k, value)) 190 } 191 if len(value) > 6 { 192 errors = append(errors, fmt.Errorf( 193 "%q cannot be longer than 6 characters: %q", k, value)) 194 } 195 if regexp.MustCompile(`^-`).MatchString(value) { 196 errors = append(errors, fmt.Errorf( 197 "%q cannot begin with a hyphen: %q", k, value)) 198 } 199 return 200 } 201 202 func validateEcrRepositoryName(v interface{}, k string) (ws []string, errors []error) { 203 value := v.(string) 204 if len(value) < 2 { 205 errors = append(errors, fmt.Errorf( 206 "%q must be at least 2 characters long: %q", k, value)) 207 } 208 if len(value) > 256 { 209 errors = append(errors, fmt.Errorf( 210 "%q cannot be longer than 256 characters: %q", k, value)) 211 } 212 213 // http://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_CreateRepository.html 214 pattern := `^(?:[a-z0-9]+(?:[._-][a-z0-9]+)*/)*[a-z0-9]+(?:[._-][a-z0-9]+)*$` 215 if !regexp.MustCompile(pattern).MatchString(value) { 216 errors = append(errors, fmt.Errorf( 217 "%q doesn't comply with restrictions (%q): %q", 218 k, pattern, value)) 219 } 220 221 return 222 } 223 224 func validateCloudWatchEventRuleName(v interface{}, k string) (ws []string, errors []error) { 225 value := v.(string) 226 if len(value) > 64 { 227 errors = append(errors, fmt.Errorf( 228 "%q cannot be longer than 64 characters: %q", k, value)) 229 } 230 231 // http://docs.aws.amazon.com/AmazonCloudWatchEvents/latest/APIReference/API_PutRule.html 232 pattern := `^[\.\-_A-Za-z0-9]+$` 233 if !regexp.MustCompile(pattern).MatchString(value) { 234 errors = append(errors, fmt.Errorf( 235 "%q doesn't comply with restrictions (%q): %q", 236 k, pattern, value)) 237 } 238 239 return 240 } 241 242 func validateMaxLength(length int) schema.SchemaValidateFunc { 243 return func(v interface{}, k string) (ws []string, errors []error) { 244 value := v.(string) 245 if len(value) > length { 246 errors = append(errors, fmt.Errorf( 247 "%q cannot be longer than %d characters: %q", k, length, value)) 248 } 249 return 250 } 251 } 252 253 func validateIntegerInRange(min, max int) schema.SchemaValidateFunc { 254 return func(v interface{}, k string) (ws []string, errors []error) { 255 value := v.(int) 256 if value < min { 257 errors = append(errors, fmt.Errorf( 258 "%q cannot be lower than %d: %d", k, min, value)) 259 } 260 if value > max { 261 errors = append(errors, fmt.Errorf( 262 "%q cannot be higher than %d: %d", k, max, value)) 263 } 264 return 265 } 266 } 267 268 func validateCloudWatchEventTargetId(v interface{}, k string) (ws []string, errors []error) { 269 value := v.(string) 270 if len(value) > 64 { 271 errors = append(errors, fmt.Errorf( 272 "%q cannot be longer than 64 characters: %q", k, value)) 273 } 274 275 // http://docs.aws.amazon.com/AmazonCloudWatchEvents/latest/APIReference/API_Target.html 276 pattern := `^[\.\-_A-Za-z0-9]+$` 277 if !regexp.MustCompile(pattern).MatchString(value) { 278 errors = append(errors, fmt.Errorf( 279 "%q doesn't comply with restrictions (%q): %q", 280 k, pattern, value)) 281 } 282 283 return 284 } 285 286 func validateLambdaFunctionName(v interface{}, k string) (ws []string, errors []error) { 287 value := v.(string) 288 if len(value) > 140 { 289 errors = append(errors, fmt.Errorf( 290 "%q cannot be longer than 140 characters: %q", k, value)) 291 } 292 // http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html 293 pattern := `^(arn:[\w-]+:lambda:)?([a-z]{2}-[a-z]+-\d{1}:)?(\d{12}:)?(function:)?([a-zA-Z0-9-_]+)(:(\$LATEST|[a-zA-Z0-9-_]+))?$` 294 if !regexp.MustCompile(pattern).MatchString(value) { 295 errors = append(errors, fmt.Errorf( 296 "%q doesn't comply with restrictions (%q): %q", 297 k, pattern, value)) 298 } 299 300 return 301 } 302 303 func validateLambdaQualifier(v interface{}, k string) (ws []string, errors []error) { 304 value := v.(string) 305 if len(value) > 128 { 306 errors = append(errors, fmt.Errorf( 307 "%q cannot be longer than 128 characters: %q", k, value)) 308 } 309 // http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html 310 pattern := `^[a-zA-Z0-9$_-]+$` 311 if !regexp.MustCompile(pattern).MatchString(value) { 312 errors = append(errors, fmt.Errorf( 313 "%q doesn't comply with restrictions (%q): %q", 314 k, pattern, value)) 315 } 316 317 return 318 } 319 320 func validateLambdaPermissionAction(v interface{}, k string) (ws []string, errors []error) { 321 value := v.(string) 322 323 // http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html 324 pattern := `^(lambda:[*]|lambda:[a-zA-Z]+|[*])$` 325 if !regexp.MustCompile(pattern).MatchString(value) { 326 errors = append(errors, fmt.Errorf( 327 "%q doesn't comply with restrictions (%q): %q", 328 k, pattern, value)) 329 } 330 331 return 332 } 333 334 func validateAwsAccountId(v interface{}, k string) (ws []string, errors []error) { 335 value := v.(string) 336 337 // http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html 338 pattern := `^\d{12}$` 339 if !regexp.MustCompile(pattern).MatchString(value) { 340 errors = append(errors, fmt.Errorf( 341 "%q doesn't look like AWS Account ID (exactly 12 digits): %q", 342 k, value)) 343 } 344 345 return 346 } 347 348 func validateArn(v interface{}, k string) (ws []string, errors []error) { 349 value := v.(string) 350 351 if value == "" { 352 return 353 } 354 355 // http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html 356 pattern := `^arn:[\w-]+:([a-zA-Z0-9\-])+:([a-z]{2}-(gov-)?[a-z]+-\d{1})?:(\d{12})?:(.*)$` 357 if !regexp.MustCompile(pattern).MatchString(value) { 358 errors = append(errors, fmt.Errorf( 359 "%q doesn't look like a valid ARN (%q): %q", 360 k, pattern, value)) 361 } 362 363 return 364 } 365 366 func validatePolicyStatementId(v interface{}, k string) (ws []string, errors []error) { 367 value := v.(string) 368 369 if len(value) > 100 { 370 errors = append(errors, fmt.Errorf( 371 "%q cannot be longer than 100 characters: %q", k, value)) 372 } 373 374 // http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html 375 pattern := `^[a-zA-Z0-9-_]+$` 376 if !regexp.MustCompile(pattern).MatchString(value) { 377 errors = append(errors, fmt.Errorf( 378 "%q doesn't look like a valid statement ID (%q): %q", 379 k, pattern, value)) 380 } 381 382 return 383 } 384 385 // validateCIDRNetworkAddress ensures that the string value is a valid CIDR that 386 // represents a network address - it adds an error otherwise 387 func validateCIDRNetworkAddress(v interface{}, k string) (ws []string, errors []error) { 388 value := v.(string) 389 _, ipnet, err := net.ParseCIDR(value) 390 if err != nil { 391 errors = append(errors, fmt.Errorf( 392 "%q must contain a valid CIDR, got error parsing: %s", k, err)) 393 return 394 } 395 396 if ipnet == nil || value != ipnet.String() { 397 errors = append(errors, fmt.Errorf( 398 "%q must contain a valid network CIDR, expected %q, got %q", 399 k, ipnet, value)) 400 } 401 402 return 403 } 404 405 func validateHTTPMethod(v interface{}, k string) (ws []string, errors []error) { 406 value := v.(string) 407 408 validMethods := map[string]bool{ 409 "ANY": true, 410 "DELETE": true, 411 "GET": true, 412 "HEAD": true, 413 "OPTIONS": true, 414 "PATCH": true, 415 "POST": true, 416 "PUT": true, 417 } 418 419 if _, ok := validMethods[value]; !ok { 420 errors = append(errors, fmt.Errorf( 421 "%q contains an invalid method %q. Valid methods are either %q, %q, %q, %q, %q, %q, %q, or %q.", 422 k, value, "ANY", "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT")) 423 } 424 return 425 } 426 427 func validateLogMetricFilterName(v interface{}, k string) (ws []string, errors []error) { 428 value := v.(string) 429 430 if len(value) > 512 { 431 errors = append(errors, fmt.Errorf( 432 "%q cannot be longer than 512 characters: %q", k, value)) 433 } 434 435 // http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutMetricFilter.html 436 pattern := `^[^:*]+$` 437 if !regexp.MustCompile(pattern).MatchString(value) { 438 errors = append(errors, fmt.Errorf( 439 "%q isn't a valid log metric name (must not contain colon nor asterisk): %q", 440 k, value)) 441 } 442 443 return 444 } 445 446 func validateLogMetricFilterTransformationName(v interface{}, k string) (ws []string, errors []error) { 447 value := v.(string) 448 449 if len(value) > 255 { 450 errors = append(errors, fmt.Errorf( 451 "%q cannot be longer than 255 characters: %q", k, value)) 452 } 453 454 // http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_MetricTransformation.html 455 pattern := `^[^:*$]*$` 456 if !regexp.MustCompile(pattern).MatchString(value) { 457 errors = append(errors, fmt.Errorf( 458 "%q isn't a valid log metric transformation name (must not contain"+ 459 " colon, asterisk nor dollar sign): %q", 460 k, value)) 461 } 462 463 return 464 } 465 466 func validateLogGroupName(v interface{}, k string) (ws []string, errors []error) { 467 value := v.(string) 468 469 if len(value) > 512 { 470 errors = append(errors, fmt.Errorf( 471 "%q cannot be longer than 512 characters: %q", k, value)) 472 } 473 474 // http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html 475 pattern := `^[\.\-_/#A-Za-z0-9]+$` 476 if !regexp.MustCompile(pattern).MatchString(value) { 477 errors = append(errors, fmt.Errorf( 478 "%q isn't a valid log group name (alphanumeric characters, underscores,"+ 479 " hyphens, slashes, hash signs and dots are allowed): %q", 480 k, value)) 481 } 482 483 return 484 } 485 486 func validateLogGroupNamePrefix(v interface{}, k string) (ws []string, errors []error) { 487 value := v.(string) 488 489 if len(value) > 483 { 490 errors = append(errors, fmt.Errorf( 491 "%q cannot be longer than 483 characters: %q", k, value)) 492 } 493 494 // http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html 495 pattern := `^[\.\-_/#A-Za-z0-9]+$` 496 if !regexp.MustCompile(pattern).MatchString(value) { 497 errors = append(errors, fmt.Errorf( 498 "%q isn't a valid log group name (alphanumeric characters, underscores,"+ 499 " hyphens, slashes, hash signs and dots are allowed): %q", 500 k, value)) 501 } 502 503 return 504 } 505 506 func validateS3BucketLifecycleTimestamp(v interface{}, k string) (ws []string, errors []error) { 507 value := v.(string) 508 _, err := time.Parse(time.RFC3339, fmt.Sprintf("%sT00:00:00Z", value)) 509 if err != nil { 510 errors = append(errors, fmt.Errorf( 511 "%q cannot be parsed as RFC3339 Timestamp Format", value)) 512 } 513 514 return 515 } 516 517 func validateS3BucketLifecycleStorageClass(v interface{}, k string) (ws []string, errors []error) { 518 value := v.(string) 519 if value != s3.TransitionStorageClassStandardIa && value != s3.TransitionStorageClassGlacier { 520 errors = append(errors, fmt.Errorf( 521 "%q must be one of '%q', '%q'", k, s3.TransitionStorageClassStandardIa, s3.TransitionStorageClassGlacier)) 522 } 523 524 return 525 } 526 527 func validateS3BucketReplicationRuleId(v interface{}, k string) (ws []string, errors []error) { 528 value := v.(string) 529 if len(value) > 255 { 530 errors = append(errors, fmt.Errorf( 531 "%q cannot be longer than 255 characters: %q", k, value)) 532 } 533 534 return 535 } 536 537 func validateS3BucketReplicationRulePrefix(v interface{}, k string) (ws []string, errors []error) { 538 value := v.(string) 539 if len(value) > 1024 { 540 errors = append(errors, fmt.Errorf( 541 "%q cannot be longer than 1024 characters: %q", k, value)) 542 } 543 544 return 545 } 546 547 func validateS3BucketReplicationDestinationStorageClass(v interface{}, k string) (ws []string, errors []error) { 548 value := v.(string) 549 if value != s3.StorageClassStandard && value != s3.StorageClassStandardIa && value != s3.StorageClassReducedRedundancy { 550 errors = append(errors, fmt.Errorf( 551 "%q must be one of '%q', '%q' or '%q'", k, s3.StorageClassStandard, s3.StorageClassStandardIa, s3.StorageClassReducedRedundancy)) 552 } 553 554 return 555 } 556 557 func validateS3BucketReplicationRuleStatus(v interface{}, k string) (ws []string, errors []error) { 558 value := v.(string) 559 if value != s3.ReplicationRuleStatusEnabled && value != s3.ReplicationRuleStatusDisabled { 560 errors = append(errors, fmt.Errorf( 561 "%q must be one of '%q' or '%q'", k, s3.ReplicationRuleStatusEnabled, s3.ReplicationRuleStatusDisabled)) 562 } 563 564 return 565 } 566 567 func validateS3BucketLifecycleRuleId(v interface{}, k string) (ws []string, errors []error) { 568 value := v.(string) 569 if len(value) > 255 { 570 errors = append(errors, fmt.Errorf( 571 "%q cannot exceed 255 characters", k)) 572 } 573 return 574 } 575 576 func validateDbEventSubscriptionName(v interface{}, k string) (ws []string, errors []error) { 577 value := v.(string) 578 if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) { 579 errors = append(errors, fmt.Errorf( 580 "only alphanumeric characters and hyphens allowed in %q", k)) 581 } 582 if len(value) > 255 { 583 errors = append(errors, fmt.Errorf( 584 "%q cannot be longer than 255 characters", k)) 585 } 586 return 587 } 588 589 func validateApiGatewayIntegrationPassthroughBehavior(v interface{}, k string) (ws []string, errors []error) { 590 value := v.(string) 591 if value != "WHEN_NO_MATCH" && value != "WHEN_NO_TEMPLATES" && value != "NEVER" { 592 errors = append(errors, fmt.Errorf( 593 "%q must be one of 'WHEN_NO_MATCH', 'WHEN_NO_TEMPLATES', 'NEVER'", k)) 594 } 595 return 596 } 597 598 func validateJsonString(v interface{}, k string) (ws []string, errors []error) { 599 if _, err := normalizeJsonString(v); err != nil { 600 errors = append(errors, fmt.Errorf("%q contains an invalid JSON: %s", k, err)) 601 } 602 return 603 } 604 605 func validateCloudFormationTemplate(v interface{}, k string) (ws []string, errors []error) { 606 if looksLikeJsonString(v) { 607 if _, err := normalizeJsonString(v); err != nil { 608 errors = append(errors, fmt.Errorf("%q contains an invalid JSON: %s", k, err)) 609 } 610 } else { 611 if _, err := checkYamlString(v); err != nil { 612 errors = append(errors, fmt.Errorf("%q contains an invalid YAML: %s", k, err)) 613 } 614 } 615 return 616 } 617 618 func validateApiGatewayIntegrationType(v interface{}, k string) (ws []string, errors []error) { 619 value := v.(string) 620 621 validTypes := map[string]bool{ 622 "AWS": true, 623 "AWS_PROXY": true, 624 "HTTP": true, 625 "HTTP_PROXY": true, 626 "MOCK": true, 627 } 628 629 if _, ok := validTypes[value]; !ok { 630 errors = append(errors, fmt.Errorf( 631 "%q contains an invalid integration type %q. Valid types are either %q, %q, %q, %q, or %q.", 632 k, value, "AWS", "AWS_PROXY", "HTTP", "HTTP_PROXY", "MOCK")) 633 } 634 return 635 } 636 637 func validateApiGatewayIntegrationContentHandling(v interface{}, k string) (ws []string, errors []error) { 638 value := v.(string) 639 640 validTypes := map[string]bool{ 641 "CONVERT_TO_BINARY": true, 642 "CONVERT_TO_TEXT": true, 643 } 644 645 if _, ok := validTypes[value]; !ok { 646 errors = append(errors, fmt.Errorf( 647 "%q contains an invalid integration type %q. Valid types are either %q or %q.", 648 k, value, "CONVERT_TO_BINARY", "CONVERT_TO_TEXT")) 649 } 650 return 651 } 652 653 func validateSQSQueueName(v interface{}, k string) (errors []error) { 654 value := v.(string) 655 if len(value) > 80 { 656 errors = append(errors, fmt.Errorf("%q cannot be longer than 80 characters", k)) 657 } 658 659 if !regexp.MustCompile(`^[0-9A-Za-z-_]+$`).MatchString(value) { 660 errors = append(errors, fmt.Errorf("only alphanumeric characters and hyphens allowed in %q", k)) 661 } 662 return 663 } 664 665 func validateSQSFifoQueueName(v interface{}, k string) (errors []error) { 666 value := v.(string) 667 668 if len(value) > 80 { 669 errors = append(errors, fmt.Errorf("%q cannot be longer than 80 characters", k)) 670 } 671 672 if !regexp.MustCompile(`^[0-9A-Za-z-_.]+$`).MatchString(value) { 673 errors = append(errors, fmt.Errorf("only alphanumeric characters and hyphens allowed in %q", k)) 674 } 675 676 if regexp.MustCompile(`^[^a-zA-Z0-9-_]`).MatchString(value) { 677 errors = append(errors, fmt.Errorf("FIFO queue name must start with one of these characters [a-zA-Z0-9-_]: %v", value)) 678 } 679 680 if !regexp.MustCompile(`\.fifo$`).MatchString(value) { 681 errors = append(errors, fmt.Errorf("FIFO queue name should ends with \".fifo\": %v", value)) 682 } 683 684 return 685 } 686 687 func validateSNSSubscriptionProtocol(v interface{}, k string) (ws []string, errors []error) { 688 value := strings.ToLower(v.(string)) 689 forbidden := []string{"email", "sms"} 690 for _, f := range forbidden { 691 if strings.Contains(value, f) { 692 errors = append( 693 errors, 694 fmt.Errorf("Unsupported protocol (%s) for SNS Topic", value), 695 ) 696 } 697 } 698 return 699 } 700 701 func validateSecurityRuleType(v interface{}, k string) (ws []string, errors []error) { 702 value := strings.ToLower(v.(string)) 703 704 validTypes := map[string]bool{ 705 "ingress": true, 706 "egress": true, 707 } 708 709 if _, ok := validTypes[value]; !ok { 710 errors = append(errors, fmt.Errorf( 711 "%q contains an invalid Security Group Rule type %q. Valid types are either %q or %q.", 712 k, value, "ingress", "egress")) 713 } 714 return 715 } 716 717 func validateOnceAWeekWindowFormat(v interface{}, k string) (ws []string, errors []error) { 718 // valid time format is "ddd:hh24:mi" 719 validTimeFormat := "(sun|mon|tue|wed|thu|fri|sat):([0-1][0-9]|2[0-3]):([0-5][0-9])" 720 validTimeFormatConsolidated := "^(" + validTimeFormat + "-" + validTimeFormat + "|)$" 721 722 value := strings.ToLower(v.(string)) 723 if !regexp.MustCompile(validTimeFormatConsolidated).MatchString(value) { 724 errors = append(errors, fmt.Errorf( 725 "%q must satisfy the format of \"ddd:hh24:mi-ddd:hh24:mi\".", k)) 726 } 727 return 728 } 729 730 func validateOnceADayWindowFormat(v interface{}, k string) (ws []string, errors []error) { 731 // valid time format is "hh24:mi" 732 validTimeFormat := "([0-1][0-9]|2[0-3]):([0-5][0-9])" 733 validTimeFormatConsolidated := "^(" + validTimeFormat + "-" + validTimeFormat + "|)$" 734 735 value := v.(string) 736 if !regexp.MustCompile(validTimeFormatConsolidated).MatchString(value) { 737 errors = append(errors, fmt.Errorf( 738 "%q must satisfy the format of \"hh24:mi-hh24:mi\".", k)) 739 } 740 return 741 } 742 743 func validateRoute53RecordType(v interface{}, k string) (ws []string, errors []error) { 744 // Valid Record types 745 // SOA, A, TXT, NS, CNAME, MX, NAPTR, PTR, SRV, SPF, AAAA 746 validTypes := map[string]struct{}{ 747 "SOA": {}, 748 "A": {}, 749 "TXT": {}, 750 "NS": {}, 751 "CNAME": {}, 752 "MX": {}, 753 "NAPTR": {}, 754 "PTR": {}, 755 "SRV": {}, 756 "SPF": {}, 757 "AAAA": {}, 758 } 759 760 value := v.(string) 761 if _, ok := validTypes[value]; !ok { 762 errors = append(errors, fmt.Errorf( 763 "%q must be one of [SOA, A, TXT, NS, CNAME, MX, NAPTR, PTR, SRV, SPF, AAAA]", k)) 764 } 765 return 766 } 767 768 // Validates that ECS Placement Constraints are set correctly 769 // Takes type, and expression as strings 770 func validateAwsEcsPlacementConstraint(constType, constExpr string) error { 771 switch constType { 772 case "distinctInstance": 773 // Expression can be nil for distinctInstance 774 return nil 775 case "memberOf": 776 if constExpr == "" { 777 return fmt.Errorf("Expression cannot be nil for 'memberOf' type") 778 } 779 default: 780 return fmt.Errorf("Unknown type provided: %q", constType) 781 } 782 return nil 783 } 784 785 // Validates that an Ecs placement strategy is set correctly 786 // Takes type, and field as strings 787 func validateAwsEcsPlacementStrategy(stratType, stratField string) error { 788 switch stratType { 789 case "random": 790 // random does not need the field attribute set, could error, but it isn't read at the API level 791 return nil 792 case "spread": 793 // For the spread placement strategy, valid values are instanceId 794 // (or host, which has the same effect), or any platform or custom attribute 795 // that is applied to a container instance 796 // stratField is already cased to a string 797 return nil 798 case "binpack": 799 if stratField != "cpu" && stratField != "memory" { 800 return fmt.Errorf("Binpack type requires the field attribute to be either 'cpu' or 'memory'. Got: %s", 801 stratField) 802 } 803 default: 804 return fmt.Errorf("Unknown type %s. Must be one of 'random', 'spread', or 'binpack'.", stratType) 805 } 806 return nil 807 } 808 809 func validateAwsEmrEbsVolumeType(v interface{}, k string) (ws []string, errors []error) { 810 validTypes := map[string]struct{}{ 811 "gp2": {}, 812 "io1": {}, 813 "standard": {}, 814 } 815 816 value := v.(string) 817 818 if _, ok := validTypes[value]; !ok { 819 errors = append(errors, fmt.Errorf( 820 "%q must be one of ['gp2', 'io1', 'standard']", k)) 821 } 822 return 823 } 824 825 func validateSfnActivityName(v interface{}, k string) (ws []string, errors []error) { 826 value := v.(string) 827 if len(value) > 80 { 828 errors = append(errors, fmt.Errorf("%q cannot be longer than 80 characters", k)) 829 } 830 831 return 832 } 833 834 func validateSfnStateMachineDefinition(v interface{}, k string) (ws []string, errors []error) { 835 value := v.(string) 836 if len(value) > 1048576 { 837 errors = append(errors, fmt.Errorf("%q cannot be longer than 1048576 characters", k)) 838 } 839 return 840 } 841 842 func validateSfnStateMachineName(v interface{}, k string) (ws []string, errors []error) { 843 value := v.(string) 844 if len(value) > 80 { 845 errors = append(errors, fmt.Errorf("%q cannot be longer than 80 characters", k)) 846 } 847 848 if !regexp.MustCompile(`^[a-zA-Z0-9-_]+$`).MatchString(value) { 849 errors = append(errors, fmt.Errorf( 850 "%q must be composed with only these characters [a-zA-Z0-9-_]: %v", k, value)) 851 } 852 return 853 } 854 855 func validateDmsCertificateId(v interface{}, k string) (ws []string, es []error) { 856 val := v.(string) 857 858 if len(val) > 255 { 859 es = append(es, fmt.Errorf("%q must not be longer than 255 characters", k)) 860 } 861 if !regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9-]+$").MatchString(val) { 862 es = append(es, fmt.Errorf("%q must start with a letter, only contain alphanumeric characters and hyphens", k)) 863 } 864 if strings.Contains(val, "--") { 865 es = append(es, fmt.Errorf("%q must not contain consecutive hyphens", k)) 866 } 867 if strings.HasSuffix(val, "-") { 868 es = append(es, fmt.Errorf("%q must not end in a hyphen", k)) 869 } 870 871 return 872 } 873 874 func validateDmsEndpointId(v interface{}, k string) (ws []string, es []error) { 875 val := v.(string) 876 877 if len(val) > 255 { 878 es = append(es, fmt.Errorf("%q must not be longer than 255 characters", k)) 879 } 880 if !regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9-]+$").MatchString(val) { 881 es = append(es, fmt.Errorf("%q must start with a letter, only contain alphanumeric characters and hyphens", k)) 882 } 883 if strings.Contains(val, "--") { 884 es = append(es, fmt.Errorf("%q must not contain consecutive hyphens", k)) 885 } 886 if strings.HasSuffix(val, "-") { 887 es = append(es, fmt.Errorf("%q must not end in a hyphen", k)) 888 } 889 890 return 891 } 892 893 func validateDmsReplicationInstanceId(v interface{}, k string) (ws []string, es []error) { 894 val := v.(string) 895 896 if len(val) > 63 { 897 es = append(es, fmt.Errorf("%q must not be longer than 63 characters", k)) 898 } 899 if !regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9-]+$").MatchString(val) { 900 es = append(es, fmt.Errorf("%q must start with a letter, only contain alphanumeric characters and hyphens", k)) 901 } 902 if strings.Contains(val, "--") { 903 es = append(es, fmt.Errorf("%q must not contain consecutive hyphens", k)) 904 } 905 if strings.HasSuffix(val, "-") { 906 es = append(es, fmt.Errorf("%q must not end in a hyphen", k)) 907 } 908 909 return 910 } 911 912 func validateDmsReplicationSubnetGroupId(v interface{}, k string) (ws []string, es []error) { 913 val := v.(string) 914 915 if val == "default" { 916 es = append(es, fmt.Errorf("%q must not be default", k)) 917 } 918 if len(val) > 255 { 919 es = append(es, fmt.Errorf("%q must not be longer than 255 characters", k)) 920 } 921 if !regexp.MustCompile(`^[a-zA-Z0-9. _-]+$`).MatchString(val) { 922 es = append(es, fmt.Errorf("%q must only contain alphanumeric characters, periods, spaces, underscores and hyphens", k)) 923 } 924 925 return 926 } 927 928 func validateDmsReplicationTaskId(v interface{}, k string) (ws []string, es []error) { 929 val := v.(string) 930 931 if len(val) > 255 { 932 es = append(es, fmt.Errorf("%q must not be longer than 255 characters", k)) 933 } 934 if !regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9-]+$").MatchString(val) { 935 es = append(es, fmt.Errorf("%q must start with a letter, only contain alphanumeric characters and hyphens", k)) 936 } 937 if strings.Contains(val, "--") { 938 es = append(es, fmt.Errorf("%q must not contain consecutive hyphens", k)) 939 } 940 if strings.HasSuffix(val, "-") { 941 es = append(es, fmt.Errorf("%q must not end in a hyphen", k)) 942 } 943 944 return 945 } 946 947 func validateAppautoscalingScalableDimension(v interface{}, k string) (ws []string, errors []error) { 948 value := v.(string) 949 dimensions := map[string]bool{ 950 "ecs:service:DesiredCount": true, 951 "ec2:spot-fleet-request:TargetCapacity": true, 952 "elasticmapreduce:instancegroup:InstanceCount": true, 953 } 954 955 if !dimensions[value] { 956 errors = append(errors, fmt.Errorf("%q must be a valid scalable dimension value: %q", k, value)) 957 } 958 return 959 } 960 961 func validateAppautoscalingServiceNamespace(v interface{}, k string) (ws []string, errors []error) { 962 value := v.(string) 963 namespaces := map[string]bool{ 964 "ecs": true, 965 "ec2": true, 966 "elasticmapreduce": true, 967 } 968 969 if !namespaces[value] { 970 errors = append(errors, fmt.Errorf("%q must be a valid service namespace value: %q", k, value)) 971 } 972 return 973 } 974 975 func validateConfigRuleSourceOwner(v interface{}, k string) (ws []string, errors []error) { 976 validOwners := []string{ 977 "CUSTOM_LAMBDA", 978 "AWS", 979 } 980 owner := v.(string) 981 for _, o := range validOwners { 982 if owner == o { 983 return 984 } 985 } 986 errors = append(errors, fmt.Errorf( 987 "%q contains an invalid owner %q. Valid owners are %q.", 988 k, owner, validOwners)) 989 return 990 } 991 992 func validateConfigExecutionFrequency(v interface{}, k string) (ws []string, errors []error) { 993 validFrequencies := []string{ 994 "One_Hour", 995 "Three_Hours", 996 "Six_Hours", 997 "Twelve_Hours", 998 "TwentyFour_Hours", 999 } 1000 frequency := v.(string) 1001 for _, f := range validFrequencies { 1002 if frequency == f { 1003 return 1004 } 1005 } 1006 errors = append(errors, fmt.Errorf( 1007 "%q contains an invalid frequency %q. Valid frequencies are %q.", 1008 k, frequency, validFrequencies)) 1009 return 1010 } 1011 1012 func validateAccountAlias(v interface{}, k string) (ws []string, es []error) { 1013 val := v.(string) 1014 1015 if (len(val) < 3) || (len(val) > 63) { 1016 es = append(es, fmt.Errorf("%q must contain from 3 to 63 alphanumeric characters or hyphens", k)) 1017 } 1018 if !regexp.MustCompile("^[a-z0-9][a-z0-9-]+$").MatchString(val) { 1019 es = append(es, fmt.Errorf("%q must start with an alphanumeric character and only contain lowercase alphanumeric characters and hyphens", k)) 1020 } 1021 if strings.Contains(val, "--") { 1022 es = append(es, fmt.Errorf("%q must not contain consecutive hyphens", k)) 1023 } 1024 if strings.HasSuffix(val, "-") { 1025 es = append(es, fmt.Errorf("%q must not end in a hyphen", k)) 1026 } 1027 return 1028 } 1029 1030 func validateApiGatewayApiKeyValue(v interface{}, k string) (ws []string, errors []error) { 1031 value := v.(string) 1032 if len(value) < 30 { 1033 errors = append(errors, fmt.Errorf( 1034 "%q must be at least 30 characters long", k)) 1035 } 1036 if len(value) > 128 { 1037 errors = append(errors, fmt.Errorf( 1038 "%q cannot be longer than 128 characters", k)) 1039 } 1040 return 1041 } 1042 1043 func validateIamRolePolicyName(v interface{}, k string) (ws []string, errors []error) { 1044 // https://github.com/boto/botocore/blob/2485f5c/botocore/data/iam/2010-05-08/service-2.json#L8291-L8296 1045 value := v.(string) 1046 if len(value) > 128 { 1047 errors = append(errors, fmt.Errorf( 1048 "%q cannot be longer than 128 characters", k)) 1049 } 1050 if !regexp.MustCompile("^[\\w+=,.@-]+$").MatchString(value) { 1051 errors = append(errors, fmt.Errorf("%q must match [\\w+=,.@-]", k)) 1052 } 1053 return 1054 } 1055 1056 func validateIamRolePolicyNamePrefix(v interface{}, k string) (ws []string, errors []error) { 1057 value := v.(string) 1058 if len(value) > 100 { 1059 errors = append(errors, fmt.Errorf( 1060 "%q cannot be longer than 100 characters", k)) 1061 } 1062 if !regexp.MustCompile("^[\\w+=,.@-]+$").MatchString(value) { 1063 errors = append(errors, fmt.Errorf("%q must match [\\w+=,.@-]", k)) 1064 } 1065 return 1066 } 1067 1068 func validateApiGatewayUsagePlanQuotaSettingsPeriod(v interface{}, k string) (ws []string, errors []error) { 1069 validPeriods := []string{ 1070 apigateway.QuotaPeriodTypeDay, 1071 apigateway.QuotaPeriodTypeWeek, 1072 apigateway.QuotaPeriodTypeMonth, 1073 } 1074 period := v.(string) 1075 for _, f := range validPeriods { 1076 if period == f { 1077 return 1078 } 1079 } 1080 errors = append(errors, fmt.Errorf( 1081 "%q contains an invalid period %q. Valid period are %q.", 1082 k, period, validPeriods)) 1083 return 1084 } 1085 1086 func validateApiGatewayUsagePlanQuotaSettings(v map[string]interface{}) (errors []error) { 1087 period := v["period"].(string) 1088 offset := v["offset"].(int) 1089 1090 if period == apigateway.QuotaPeriodTypeDay && offset != 0 { 1091 errors = append(errors, fmt.Errorf("Usage Plan quota offset must be zero in the DAY period")) 1092 } 1093 1094 if period == apigateway.QuotaPeriodTypeWeek && (offset < 0 || offset > 6) { 1095 errors = append(errors, fmt.Errorf("Usage Plan quota offset must be between 0 and 6 inclusive in the WEEK period")) 1096 } 1097 1098 if period == apigateway.QuotaPeriodTypeMonth && (offset < 0 || offset > 27) { 1099 errors = append(errors, fmt.Errorf("Usage Plan quota offset must be between 0 and 27 inclusive in the MONTH period")) 1100 } 1101 1102 return 1103 } 1104 1105 func validateDbSubnetGroupName(v interface{}, k string) (ws []string, errors []error) { 1106 value := v.(string) 1107 if !regexp.MustCompile(`^[ .0-9a-z-_]+$`).MatchString(value) { 1108 errors = append(errors, fmt.Errorf( 1109 "only lowercase alphanumeric characters, hyphens, underscores, periods, and spaces allowed in %q", k)) 1110 } 1111 if len(value) > 255 { 1112 errors = append(errors, fmt.Errorf( 1113 "%q cannot be longer than 255 characters", k)) 1114 } 1115 if regexp.MustCompile(`(?i)^default$`).MatchString(value) { 1116 errors = append(errors, fmt.Errorf( 1117 "%q is not allowed as %q", "Default", k)) 1118 } 1119 return 1120 } 1121 1122 func validateDbSubnetGroupNamePrefix(v interface{}, k string) (ws []string, errors []error) { 1123 value := v.(string) 1124 if !regexp.MustCompile(`^[ .0-9a-z-_]+$`).MatchString(value) { 1125 errors = append(errors, fmt.Errorf( 1126 "only lowercase alphanumeric characters, hyphens, underscores, periods, and spaces allowed in %q", k)) 1127 } 1128 if len(value) > 229 { 1129 errors = append(errors, fmt.Errorf( 1130 "%q cannot be longer than 229 characters", k)) 1131 } 1132 return 1133 } 1134 1135 func validateDbOptionGroupName(v interface{}, k string) (ws []string, errors []error) { 1136 value := v.(string) 1137 if !regexp.MustCompile(`^[a-z]`).MatchString(value) { 1138 errors = append(errors, fmt.Errorf( 1139 "first character of %q must be a letter", k)) 1140 } 1141 if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) { 1142 errors = append(errors, fmt.Errorf( 1143 "only alphanumeric characters and hyphens allowed in %q", k)) 1144 } 1145 if regexp.MustCompile(`--`).MatchString(value) { 1146 errors = append(errors, fmt.Errorf( 1147 "%q cannot contain two consecutive hyphens", k)) 1148 } 1149 if regexp.MustCompile(`-$`).MatchString(value) { 1150 errors = append(errors, fmt.Errorf( 1151 "%q cannot end with a hyphen", k)) 1152 } 1153 if len(value) > 255 { 1154 errors = append(errors, fmt.Errorf( 1155 "%q cannot be greater than 255 characters", k)) 1156 } 1157 return 1158 } 1159 1160 func validateDbOptionGroupNamePrefix(v interface{}, k string) (ws []string, errors []error) { 1161 value := v.(string) 1162 if !regexp.MustCompile(`^[a-z]`).MatchString(value) { 1163 errors = append(errors, fmt.Errorf( 1164 "first character of %q must be a letter", k)) 1165 } 1166 if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) { 1167 errors = append(errors, fmt.Errorf( 1168 "only alphanumeric characters and hyphens allowed in %q", k)) 1169 } 1170 if regexp.MustCompile(`--`).MatchString(value) { 1171 errors = append(errors, fmt.Errorf( 1172 "%q cannot contain two consecutive hyphens", k)) 1173 } 1174 if len(value) > 229 { 1175 errors = append(errors, fmt.Errorf( 1176 "%q cannot be greater than 229 characters", k)) 1177 } 1178 return 1179 } 1180 1181 func validateAwsAlbTargetGroupName(v interface{}, k string) (ws []string, errors []error) { 1182 name := v.(string) 1183 if len(name) > 32 { 1184 errors = append(errors, fmt.Errorf("%q (%q) cannot be longer than '32' characters", k, name)) 1185 } 1186 return 1187 } 1188 1189 func validateAwsAlbTargetGroupNamePrefix(v interface{}, k string) (ws []string, errors []error) { 1190 name := v.(string) 1191 if len(name) > 32 { 1192 errors = append(errors, fmt.Errorf("%q (%q) cannot be longer than '6' characters", k, name)) 1193 } 1194 return 1195 } 1196 1197 func validateOpenIdURL(v interface{}, k string) (ws []string, errors []error) { 1198 value := v.(string) 1199 u, err := url.Parse(value) 1200 if err != nil { 1201 errors = append(errors, fmt.Errorf("%q has to be a valid URL", k)) 1202 return 1203 } 1204 if u.Scheme != "https" { 1205 errors = append(errors, fmt.Errorf("%q has to use HTTPS scheme (i.e. begin with https://)", k)) 1206 } 1207 if len(u.Query()) > 0 { 1208 errors = append(errors, fmt.Errorf("%q cannot contain query parameters per the OIDC standard", k)) 1209 } 1210 return 1211 } 1212 1213 func validateAwsKmsName(v interface{}, k string) (ws []string, es []error) { 1214 value := v.(string) 1215 if !regexp.MustCompile(`^(alias\/)[a-zA-Z0-9:/_-]+$`).MatchString(value) { 1216 es = append(es, fmt.Errorf( 1217 "%q must begin with 'alias/' and be comprised of only [a-zA-Z0-9:/_-]", k)) 1218 } 1219 return 1220 } 1221 1222 func validateCognitoIdentityPoolName(v interface{}, k string) (ws []string, errors []error) { 1223 val := v.(string) 1224 if !regexp.MustCompile("^[\\w _]+$").MatchString(val) { 1225 errors = append(errors, fmt.Errorf("%q must contain only alphanumeric caracters and spaces", k)) 1226 } 1227 1228 return 1229 } 1230 1231 func validateCognitoProviderDeveloperName(v interface{}, k string) (ws []string, errors []error) { 1232 value := v.(string) 1233 if len(value) > 100 { 1234 errors = append(errors, fmt.Errorf("%q cannot be longer than 100 caracters", k)) 1235 } 1236 1237 if !regexp.MustCompile("^[\\w._-]+$").MatchString(value) { 1238 errors = append(errors, fmt.Errorf("%q must contain only alphanumeric caracters, dots, underscores and hyphens", k)) 1239 } 1240 1241 return 1242 } 1243 1244 func validateCognitoSupportedLoginProviders(v interface{}, k string) (ws []string, errors []error) { 1245 value := v.(string) 1246 if len(value) < 1 { 1247 errors = append(errors, fmt.Errorf("%q cannot be less than 1 character", k)) 1248 } 1249 1250 if len(value) > 128 { 1251 errors = append(errors, fmt.Errorf("%q cannot be longer than 128 caracters", k)) 1252 } 1253 1254 if !regexp.MustCompile("^[\\w.;_/-]+$").MatchString(value) { 1255 errors = append(errors, fmt.Errorf("%q must contain only alphanumeric caracters, dots, semicolons, underscores, slashes and hyphens", k)) 1256 } 1257 1258 return 1259 } 1260 1261 func validateCognitoIdentityProvidersClientId(v interface{}, k string) (ws []string, errors []error) { 1262 value := v.(string) 1263 if len(value) < 1 { 1264 errors = append(errors, fmt.Errorf("%q cannot be less than 1 character", k)) 1265 } 1266 1267 if len(value) > 128 { 1268 errors = append(errors, fmt.Errorf("%q cannot be longer than 128 caracters", k)) 1269 } 1270 1271 if !regexp.MustCompile("^[\\w_]+$").MatchString(value) { 1272 errors = append(errors, fmt.Errorf("%q must contain only alphanumeric caracters and underscores", k)) 1273 } 1274 1275 return 1276 } 1277 1278 func validateCognitoIdentityProvidersProviderName(v interface{}, k string) (ws []string, errors []error) { 1279 value := v.(string) 1280 if len(value) < 1 { 1281 errors = append(errors, fmt.Errorf("%q cannot be less than 1 character", k)) 1282 } 1283 1284 if len(value) > 128 { 1285 errors = append(errors, fmt.Errorf("%q cannot be longer than 128 caracters", k)) 1286 } 1287 1288 if !regexp.MustCompile("^[\\w._:/-]+$").MatchString(value) { 1289 errors = append(errors, fmt.Errorf("%q must contain only alphanumeric caracters, dots, underscores, colons, slashes and hyphens", k)) 1290 } 1291 1292 return 1293 } 1294 1295 func validateWafMetricName(v interface{}, k string) (ws []string, errors []error) { 1296 value := v.(string) 1297 if !regexp.MustCompile(`^[0-9A-Za-z]+$`).MatchString(value) { 1298 errors = append(errors, fmt.Errorf( 1299 "Only alphanumeric characters allowed in %q: %q", 1300 k, value)) 1301 } 1302 return 1303 }