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