diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f649e54a..32e49f8f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ FEATURES: + * **New Resource:** `aws_iam_openid_connect_provider` [GH-13456] * **New Resource:** `aws_lightsail_static_ip` [GH-13175] * **New Resource:** `aws_lightsail_static_ip_attachment` [GH-13207] * **New Resource:** `aws_ses_domain_identity` [GH-13098] @@ -75,9 +76,11 @@ BUG FIXES: * provider/aws: Fix DynamoDB issues about GSIs indexes [GH-13256] * provider/aws: Fix `aws_s3_bucket` drift detection of logging options [GH-13281] * provider/aws: Update ElasticTranscoderPreset to have default for MaxFrameRate [GH-13422] + * provider/aws: Fix aws_ami_launch_permission refresh when AMI disappears [GH-13469] * provider/azurerm: Network Security Group - ignoring protocol casing at Import time [GH-13153] * provider/azurerm: Fix crash when importing Local Network Gateways [GH-13261] * provider/bitbucket: Fixed issue where provider would fail with an "EOF" error on some operations [GH-13390] + * provider/ns1: No splitting answer on SPF records. [GH-13260] * provider/openstack: Refresh volume_attachment from state if NotFound [GH-13342] * provider/openstack: Add SOFT_DELETED to delete status [GH-13444] * provider/profitbricks: Changed output type of ips variable of ip_block ProfitBricks resource [GH-13290] diff --git a/builtin/providers/aws/diff_suppress_funcs.go b/builtin/providers/aws/diff_suppress_funcs.go index 5c96c6696..e8c58b813 100644 --- a/builtin/providers/aws/diff_suppress_funcs.go +++ b/builtin/providers/aws/diff_suppress_funcs.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "log" + "net/url" "strings" "github.com/hashicorp/terraform/helper/schema" @@ -58,3 +59,19 @@ func suppressEquivalentJsonDiffs(k, old, new string, d *schema.ResourceData) boo return jsonBytesEqual(ob.Bytes(), nb.Bytes()) } + +func suppressOpenIdURL(k, old, new string, d *schema.ResourceData) bool { + oldUrl, err := url.Parse(old) + if err != nil { + return false + } + + newUrl, err := url.Parse(new) + if err != nil { + return false + } + + oldUrl.Scheme = "https" + + return oldUrl.String() == newUrl.String() +} diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index f97908772..67e813a9e 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -309,6 +309,7 @@ func Provider() terraform.ResourceProvider { "aws_iam_group_membership": resourceAwsIamGroupMembership(), "aws_iam_group_policy_attachment": resourceAwsIamGroupPolicyAttachment(), "aws_iam_instance_profile": resourceAwsIamInstanceProfile(), + "aws_iam_openid_connect_provider": resourceAwsIamOpenIDConnectProvider(), "aws_iam_policy": resourceAwsIamPolicy(), "aws_iam_policy_attachment": resourceAwsIamPolicyAttachment(), "aws_iam_role_policy_attachment": resourceAwsIamRolePolicyAttachment(), diff --git a/builtin/providers/aws/resource_aws_ami_launch_permission.go b/builtin/providers/aws/resource_aws_ami_launch_permission.go index d1c738d39..278e9d9ab 100644 --- a/builtin/providers/aws/resource_aws_ami_launch_permission.go +++ b/builtin/providers/aws/resource_aws_ami_launch_permission.go @@ -2,7 +2,11 @@ package aws import ( "fmt" + "log" + "strings" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/terraform/helper/schema" ) @@ -92,6 +96,12 @@ func hasLaunchPermission(conn *ec2.EC2, image_id string, account_id string) (boo Attribute: aws.String("launchPermission"), }) if err != nil { + // When an AMI disappears out from under a launch permission resource, we will + // see either InvalidAMIID.NotFound or InvalidAMIID.Unavailable. + if ec2err, ok := err.(awserr.Error); ok && strings.HasPrefix(ec2err.Code(), "InvalidAMIID") { + log.Printf("[DEBUG] %s no longer exists, so we'll drop launch permission for %s from the state", image_id, account_id) + return false, nil + } return false, err } diff --git a/builtin/providers/aws/resource_aws_ami_launch_permission_test.go b/builtin/providers/aws/resource_aws_ami_launch_permission_test.go index 0affa9161..4ccb35c7c 100644 --- a/builtin/providers/aws/resource_aws_ami_launch_permission_test.go +++ b/builtin/providers/aws/resource_aws_ami_launch_permission_test.go @@ -2,15 +2,18 @@ package aws import ( "fmt" - r "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" "os" "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ec2" + r "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" ) func TestAccAWSAMILaunchPermission_Basic(t *testing.T) { - image_id := "" - account_id := os.Getenv("AWS_ACCOUNT_ID") + imageID := "" + accountID := os.Getenv("AWS_ACCOUNT_ID") r.Test(t, r.TestCase{ PreCheck: func() { @@ -23,19 +26,36 @@ func TestAccAWSAMILaunchPermission_Basic(t *testing.T) { Steps: []r.TestStep{ // Scaffold everything r.TestStep{ - Config: testAccAWSAMILaunchPermissionConfig(account_id, true), + Config: testAccAWSAMILaunchPermissionConfig(accountID, true), Check: r.ComposeTestCheckFunc( - testCheckResourceGetAttr("aws_ami_copy.test", "id", &image_id), - testAccAWSAMILaunchPermissionExists(account_id, &image_id), + testCheckResourceGetAttr("aws_ami_copy.test", "id", &imageID), + testAccAWSAMILaunchPermissionExists(accountID, &imageID), ), }, // Drop just launch permission to test destruction r.TestStep{ - Config: testAccAWSAMILaunchPermissionConfig(account_id, false), + Config: testAccAWSAMILaunchPermissionConfig(accountID, false), Check: r.ComposeTestCheckFunc( - testAccAWSAMILaunchPermissionDestroyed(account_id, &image_id), + testAccAWSAMILaunchPermissionDestroyed(accountID, &imageID), ), }, + // Re-add everything so we can test when AMI disappears + r.TestStep{ + Config: testAccAWSAMILaunchPermissionConfig(accountID, true), + Check: r.ComposeTestCheckFunc( + testCheckResourceGetAttr("aws_ami_copy.test", "id", &imageID), + testAccAWSAMILaunchPermissionExists(accountID, &imageID), + ), + }, + // Here we delete the AMI to verify the follow-on refresh after this step + // should not error. + r.TestStep{ + Config: testAccAWSAMILaunchPermissionConfig(accountID, true), + Check: r.ComposeTestCheckFunc( + testAccAWSAMIDisappears(&imageID), + ), + ExpectNonEmptyPlan: true, + }, }, }) } @@ -58,31 +78,53 @@ func testCheckResourceGetAttr(name, key string, value *string) r.TestCheckFunc { } } -func testAccAWSAMILaunchPermissionExists(account_id string, image_id *string) r.TestCheckFunc { +func testAccAWSAMILaunchPermissionExists(accountID string, imageID *string) r.TestCheckFunc { return func(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn - if has, err := hasLaunchPermission(conn, *image_id, account_id); err != nil { + if has, err := hasLaunchPermission(conn, *imageID, accountID); err != nil { return err } else if !has { - return fmt.Errorf("launch permission does not exist for '%s' on '%s'", account_id, *image_id) + return fmt.Errorf("launch permission does not exist for '%s' on '%s'", accountID, *imageID) } return nil } } -func testAccAWSAMILaunchPermissionDestroyed(account_id string, image_id *string) r.TestCheckFunc { +func testAccAWSAMILaunchPermissionDestroyed(accountID string, imageID *string) r.TestCheckFunc { return func(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn - if has, err := hasLaunchPermission(conn, *image_id, account_id); err != nil { + if has, err := hasLaunchPermission(conn, *imageID, accountID); err != nil { return err } else if has { - return fmt.Errorf("launch permission still exists for '%s' on '%s'", account_id, *image_id) + return fmt.Errorf("launch permission still exists for '%s' on '%s'", accountID, *imageID) } return nil } } -func testAccAWSAMILaunchPermissionConfig(account_id string, includeLaunchPermission bool) string { +// testAccAWSAMIDisappears is technically a "test check function" but really it +// exists to perform a side effect of deleting an AMI out from under a resource +// so we can test that Terraform will react properly +func testAccAWSAMIDisappears(imageID *string) r.TestCheckFunc { + return func(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).ec2conn + req := &ec2.DeregisterImageInput{ + ImageId: aws.String(*imageID), + } + + _, err := conn.DeregisterImage(req) + if err != nil { + return err + } + + if err := resourceAwsAmiWaitForDestroy(*imageID, conn); err != nil { + return err + } + return nil + } +} + +func testAccAWSAMILaunchPermissionConfig(accountID string, includeLaunchPermission bool) string { base := ` resource "aws_ami_copy" "test" { name = "launch-permission-test" @@ -101,5 +143,5 @@ resource "aws_ami_launch_permission" "self-test" { image_id = "${aws_ami_copy.test.id}" account_id = "%s" } -`, account_id) +`, accountID) } diff --git a/builtin/providers/aws/resource_aws_db_option_group_test.go b/builtin/providers/aws/resource_aws_db_option_group_test.go index 3ee5f8197..8e9b22e1b 100644 --- a/builtin/providers/aws/resource_aws_db_option_group_test.go +++ b/builtin/providers/aws/resource_aws_db_option_group_test.go @@ -317,6 +317,7 @@ resource "aws_db_instance" "bar" { maintenance_window = "Fri:09:00-Fri:09:30" backup_retention_period = 0 + skip_final_snapshot = true option_group_name = "${aws_db_option_group.bar.name}" } diff --git a/builtin/providers/aws/resource_aws_efs_file_system_test.go b/builtin/providers/aws/resource_aws_efs_file_system_test.go index b242fbf16..93119bb79 100644 --- a/builtin/providers/aws/resource_aws_efs_file_system_test.go +++ b/builtin/providers/aws/resource_aws_efs_file_system_test.go @@ -317,7 +317,6 @@ resource "aws_efs_file_system" "foo" { func testAccAWSEFSFileSystemConfigPagedTags(rInt int) string { return fmt.Sprintf(` resource "aws_efs_file_system" "foo" { - creation_token = "radeksimko" tags { Name = "foo-efs-%d" Another = "tag" @@ -338,7 +337,6 @@ func testAccAWSEFSFileSystemConfigPagedTags(rInt int) string { func testAccAWSEFSFileSystemConfigWithTags(rInt int) string { return fmt.Sprintf(` resource "aws_efs_file_system" "foo-with-tags" { - creation_token = "yada_yada" tags { Name = "foo-efs-%d" Another = "tag" diff --git a/builtin/providers/aws/resource_aws_iam_openid_connect_provider.go b/builtin/providers/aws/resource_aws_iam_openid_connect_provider.go new file mode 100644 index 000000000..1791da4ec --- /dev/null +++ b/builtin/providers/aws/resource_aws_iam_openid_connect_provider.go @@ -0,0 +1,141 @@ +package aws + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/iam" + + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsIamOpenIDConnectProvider() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsIamOpenIDConnectProviderCreate, + Read: resourceAwsIamOpenIDConnectProviderRead, + Update: resourceAwsIamOpenIDConnectProviderUpdate, + Delete: resourceAwsIamOpenIDConnectProviderDelete, + Exists: resourceAwsIamOpenIDConnectProviderExists, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "arn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "url": &schema.Schema{ + Type: schema.TypeString, + Computed: false, + Required: true, + ForceNew: true, + ValidateFunc: validateOpenIdURL, + DiffSuppressFunc: suppressOpenIdURL, + }, + "client_id_list": &schema.Schema{ + Elem: &schema.Schema{Type: schema.TypeString}, + Type: schema.TypeList, + Required: true, + ForceNew: true, + }, + "thumbprint_list": &schema.Schema{ + Elem: &schema.Schema{Type: schema.TypeString}, + Type: schema.TypeList, + Required: true, + }, + }, + } +} + +func resourceAwsIamOpenIDConnectProviderCreate(d *schema.ResourceData, meta interface{}) error { + iamconn := meta.(*AWSClient).iamconn + + input := &iam.CreateOpenIDConnectProviderInput{ + Url: aws.String(d.Get("url").(string)), + ClientIDList: expandStringList(d.Get("client_id_list").([]interface{})), + ThumbprintList: expandStringList(d.Get("thumbprint_list").([]interface{})), + } + + out, err := iamconn.CreateOpenIDConnectProvider(input) + if err != nil { + return err + } + + d.SetId(*out.OpenIDConnectProviderArn) + + return resourceAwsIamOpenIDConnectProviderRead(d, meta) +} + +func resourceAwsIamOpenIDConnectProviderRead(d *schema.ResourceData, meta interface{}) error { + iamconn := meta.(*AWSClient).iamconn + + input := &iam.GetOpenIDConnectProviderInput{ + OpenIDConnectProviderArn: aws.String(d.Id()), + } + out, err := iamconn.GetOpenIDConnectProvider(input) + if err != nil { + return err + } + + d.Set("arn", d.Id()) + d.Set("url", out.Url) + d.Set("client_id_list", flattenStringList(out.ClientIDList)) + d.Set("thumbprint_list", flattenStringList(out.ThumbprintList)) + + return nil +} + +func resourceAwsIamOpenIDConnectProviderUpdate(d *schema.ResourceData, meta interface{}) error { + iamconn := meta.(*AWSClient).iamconn + + if d.HasChange("thumbprint_list") { + input := &iam.UpdateOpenIDConnectProviderThumbprintInput{ + OpenIDConnectProviderArn: aws.String(d.Id()), + ThumbprintList: expandStringList(d.Get("thumbprint_list").([]interface{})), + } + + _, err := iamconn.UpdateOpenIDConnectProviderThumbprint(input) + if err != nil { + return err + } + } + + return resourceAwsIamOpenIDConnectProviderRead(d, meta) +} + +func resourceAwsIamOpenIDConnectProviderDelete(d *schema.ResourceData, meta interface{}) error { + iamconn := meta.(*AWSClient).iamconn + + input := &iam.DeleteOpenIDConnectProviderInput{ + OpenIDConnectProviderArn: aws.String(d.Id()), + } + _, err := iamconn.DeleteOpenIDConnectProvider(input) + + if err != nil { + if err, ok := err.(awserr.Error); ok && err.Code() == "NoSuchEntity" { + return nil + } + return fmt.Errorf("Error deleting platform application %s", err) + } + + return nil +} + +func resourceAwsIamOpenIDConnectProviderExists(d *schema.ResourceData, meta interface{}) (bool, error) { + iamconn := meta.(*AWSClient).iamconn + + input := &iam.GetOpenIDConnectProviderInput{ + OpenIDConnectProviderArn: aws.String(d.Id()), + } + _, err := iamconn.GetOpenIDConnectProvider(input) + if err != nil { + if err, ok := err.(awserr.Error); ok && err.Code() == "NoSuchEntity" { + return false, nil + } + return true, err + } + + return true, nil +} diff --git a/builtin/providers/aws/resource_aws_iam_openid_connect_provider_test.go b/builtin/providers/aws/resource_aws_iam_openid_connect_provider_test.go new file mode 100644 index 000000000..6cf10d8b8 --- /dev/null +++ b/builtin/providers/aws/resource_aws_iam_openid_connect_provider_test.go @@ -0,0 +1,187 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/iam" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSIAMOpenIDConnectProvider_basic(t *testing.T) { + rString := acctest.RandString(5) + url := "accounts.google.com/" + rString + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckIAMOpenIDConnectProviderDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccIAMOpenIDConnectProviderConfig(rString), + Check: resource.ComposeTestCheckFunc( + testAccCheckIAMOpenIDConnectProvider("aws_iam_openid_connect_provider.goog"), + resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "url", url), + resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "client_id_list.#", "1"), + resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "client_id_list.0", + "266362248691-re108qaeld573ia0l6clj2i5ac7r7291.apps.googleusercontent.com"), + resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "thumbprint_list.#", "0"), + ), + }, + resource.TestStep{ + Config: testAccIAMOpenIDConnectProviderConfig_modified(rString), + Check: resource.ComposeTestCheckFunc( + testAccCheckIAMOpenIDConnectProvider("aws_iam_openid_connect_provider.goog"), + resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "url", url), + resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "client_id_list.#", "1"), + resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "client_id_list.0", + "266362248691-re108qaeld573ia0l6clj2i5ac7r7291.apps.googleusercontent.com"), + resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "thumbprint_list.#", "2"), + resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "thumbprint_list.0", "cf23df2207d99a74fbe169e3eba035e633b65d94"), + resource.TestCheckResourceAttr("aws_iam_openid_connect_provider.goog", "thumbprint_list.1", "c784713d6f9cb67b55dd84f4e4af7832d42b8f55"), + ), + }, + }, + }) +} + +func TestAccAWSIAMOpenIDConnectProvider_importBasic(t *testing.T) { + resourceName := "aws_iam_openid_connect_provider.goog" + rString := acctest.RandString(5) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckIAMOpenIDConnectProviderDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccIAMOpenIDConnectProviderConfig_modified(rString), + }, + + resource.TestStep{ + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSIAMOpenIDConnectProvider_disappears(t *testing.T) { + rString := acctest.RandString(5) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckIAMOpenIDConnectProviderDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccIAMOpenIDConnectProviderConfig(rString), + Check: resource.ComposeTestCheckFunc( + testAccCheckIAMOpenIDConnectProvider("aws_iam_openid_connect_provider.goog"), + testAccCheckIAMOpenIDConnectProviderDisappears("aws_iam_openid_connect_provider.goog"), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckIAMOpenIDConnectProviderDestroy(s *terraform.State) error { + iamconn := testAccProvider.Meta().(*AWSClient).iamconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_iam_openid_connect_provider" { + continue + } + + input := &iam.GetOpenIDConnectProviderInput{ + OpenIDConnectProviderArn: aws.String(rs.Primary.ID), + } + out, err := iamconn.GetOpenIDConnectProvider(input) + if err != nil { + if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" { + // none found, that's good + return nil + } + return fmt.Errorf("Error reading IAM OpenID Connect Provider, out: %s, err: %s", out, err) + } + + if out != nil { + return fmt.Errorf("Found IAM OpenID Connect Provider, expected none: %s", out) + } + } + + return nil +} + +func testAccCheckIAMOpenIDConnectProviderDisappears(id string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[id] + if !ok { + return fmt.Errorf("Not Found: %s", id) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + iamconn := testAccProvider.Meta().(*AWSClient).iamconn + _, err := iamconn.DeleteOpenIDConnectProvider(&iam.DeleteOpenIDConnectProviderInput{ + OpenIDConnectProviderArn: aws.String(rs.Primary.ID), + }) + return err + } +} + +func testAccCheckIAMOpenIDConnectProvider(id string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[id] + if !ok { + return fmt.Errorf("Not Found: %s", id) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + iamconn := testAccProvider.Meta().(*AWSClient).iamconn + _, err := iamconn.GetOpenIDConnectProvider(&iam.GetOpenIDConnectProviderInput{ + OpenIDConnectProviderArn: aws.String(rs.Primary.ID), + }) + + if err != nil { + return err + } + + return nil + } +} + +func testAccIAMOpenIDConnectProviderConfig(rString string) string { + return fmt.Sprintf(` +resource "aws_iam_openid_connect_provider" "goog" { + url="https://accounts.google.com/%s" + client_id_list = [ + "266362248691-re108qaeld573ia0l6clj2i5ac7r7291.apps.googleusercontent.com" + ] + thumbprint_list = [] +} +`, rString) +} + +func testAccIAMOpenIDConnectProviderConfig_modified(rString string) string { + return fmt.Sprintf(` +resource "aws_iam_openid_connect_provider" "goog" { + url="https://accounts.google.com/%s" + client_id_list = [ + "266362248691-re108qaeld573ia0l6clj2i5ac7r7291.apps.googleusercontent.com" + ] + thumbprint_list = ["cf23df2207d99a74fbe169e3eba035e633b65d94", "c784713d6f9cb67b55dd84f4e4af7832d42b8f55"] +} +`, rString) +} diff --git a/builtin/providers/aws/validators.go b/builtin/providers/aws/validators.go index b2f934646..425a747d5 100644 --- a/builtin/providers/aws/validators.go +++ b/builtin/providers/aws/validators.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "net" + "net/url" "regexp" "strings" "time" @@ -1170,3 +1171,19 @@ func validateAwsAlbTargetGroupNamePrefix(v interface{}, k string) (ws []string, } return } + +func validateOpenIdURL(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + u, err := url.Parse(value) + if err != nil { + errors = append(errors, fmt.Errorf("%q has to be a valid URL", k)) + return + } + if u.Scheme != "https" { + errors = append(errors, fmt.Errorf("%q has to use HTTPS scheme (i.e. begin with https://)", k)) + } + if len(u.Query()) > 0 { + errors = append(errors, fmt.Errorf("%q cannot contain query parameters per the OIDC standard", k)) + } + return +} diff --git a/builtin/providers/aws/validators_test.go b/builtin/providers/aws/validators_test.go index 7fe451a87..0af2b49fa 100644 --- a/builtin/providers/aws/validators_test.go +++ b/builtin/providers/aws/validators_test.go @@ -1913,3 +1913,35 @@ func TestValidateDbOptionGroupNamePrefix(t *testing.T) { } } } + +func TestValidateOpenIdURL(t *testing.T) { + cases := []struct { + Value string + ErrCount int + }{ + { + Value: "http://wrong.scheme.com", + ErrCount: 1, + }, + { + Value: "ftp://wrong.scheme.co.uk", + ErrCount: 1, + }, + { + Value: "%@invalidUrl", + ErrCount: 1, + }, + { + Value: "https://example.com/?query=param", + ErrCount: 1, + }, + } + + for _, tc := range cases { + _, errors := validateOpenIdURL(tc.Value, "url") + + if len(errors) != tc.ErrCount { + t.Fatalf("Expected %d of OpenID URL validation errors, got %d", tc.ErrCount, len(errors)) + } + } +} diff --git a/builtin/providers/dns/data_dns_cname_record_set_test.go b/builtin/providers/dns/data_dns_cname_record_set_test.go index 84270ff04..3ae2fdbc5 100644 --- a/builtin/providers/dns/data_dns_cname_record_set_test.go +++ b/builtin/providers/dns/data_dns_cname_record_set_test.go @@ -17,7 +17,7 @@ func TestAccDnsCnameRecordSet_Basic(t *testing.T) { host = "www.hashicorp.com" } `, - "s.shared.global.fastly.net.", + "dualstack.s.shared.global.fastly.net.", }, } diff --git a/builtin/providers/ns1/resource_record.go b/builtin/providers/ns1/resource_record.go index 88b1a96c9..add703c3a 100644 --- a/builtin/providers/ns1/resource_record.go +++ b/builtin/providers/ns1/resource_record.go @@ -236,7 +236,7 @@ func resourceDataToRecord(r *dns.Record, d *schema.ResourceData) error { var a *dns.Answer v := answer["answer"].(string) switch d.Get("type") { - case "TXT": + case "TXT", "SPF": a = dns.NewTXTAnswer(v) default: a = dns.NewAnswer(strings.Split(v, " ")) diff --git a/builtin/providers/ns1/resource_record_test.go b/builtin/providers/ns1/resource_record_test.go index e73a143cc..36095b579 100644 --- a/builtin/providers/ns1/resource_record_test.go +++ b/builtin/providers/ns1/resource_record_test.go @@ -71,6 +71,27 @@ func TestAccRecord_updated(t *testing.T) { }) } +func TestAccRecord_SPF(t *testing.T) { + var record dns.Record + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRecordDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccRecordSPF, + Check: resource.ComposeTestCheckFunc( + testAccCheckRecordExists("ns1_record.spf", &record), + testAccCheckRecordDomain(&record, "terraform-record-test.io"), + testAccCheckRecordTTL(&record, 86400), + testAccCheckRecordUseClientSubnet(&record, true), + testAccCheckRecordAnswerRdata(&record, "v=DKIM1; k=rsa; p=XXXXXXXX"), + ), + }, + }, + }) +} + func testAccCheckRecordExists(n string, record *dns.Record) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -297,3 +318,20 @@ resource "ns1_zone" "test" { zone = "terraform-record-test.io" } ` + +const testAccRecordSPF = ` +resource "ns1_record" "spf" { + zone = "${ns1_zone.test.zone}" + domain = "${ns1_zone.test.zone}" + type = "SPF" + ttl = 86400 + use_client_subnet = "true" + answers = { + answer = "v=DKIM1; k=rsa; p=XXXXXXXX" + } +} + +resource "ns1_zone" "test" { + zone = "terraform-record-test.io" +} +` diff --git a/terraform/eval_variable.go b/terraform/eval_variable.go index b39a4d198..e39a33c2a 100644 --- a/terraform/eval_variable.go +++ b/terraform/eval_variable.go @@ -123,22 +123,27 @@ func (n *EvalVariableBlock) Eval(ctx EvalContext) (interface{}, error) { // Get our configuration rc := *n.Config for k, v := range rc.Config { - var vString string - if err := hilmapstructure.WeakDecode(v, &vString); err == nil { - n.VariableValues[k] = vString - continue - } + vKind := reflect.ValueOf(v).Type().Kind() - var vMap map[string]interface{} - if err := hilmapstructure.WeakDecode(v, &vMap); err == nil { - n.VariableValues[k] = vMap - continue - } - - var vSlice []interface{} - if err := hilmapstructure.WeakDecode(v, &vSlice); err == nil { - n.VariableValues[k] = vSlice - continue + switch vKind { + case reflect.Slice: + var vSlice []interface{} + if err := hilmapstructure.WeakDecode(v, &vSlice); err == nil { + n.VariableValues[k] = vSlice + continue + } + case reflect.Map: + var vMap map[string]interface{} + if err := hilmapstructure.WeakDecode(v, &vMap); err == nil { + n.VariableValues[k] = vMap + continue + } + default: + var vString string + if err := hilmapstructure.WeakDecode(v, &vString); err == nil { + n.VariableValues[k] = vString + continue + } } return nil, fmt.Errorf("Variable value for %s is not a string, list or map type", k) diff --git a/website/source/docs/providers/aws/r/iam_openid_connect_provider.html.markdown b/website/source/docs/providers/aws/r/iam_openid_connect_provider.html.markdown new file mode 100644 index 000000000..2e312e5b9 --- /dev/null +++ b/website/source/docs/providers/aws/r/iam_openid_connect_provider.html.markdown @@ -0,0 +1,45 @@ +--- +layout: "aws" +page_title: "AWS: aws_iam_openid_connect_provider" +sidebar_current: "docs-aws-resource-iam-openid-connect-provider" +description: |- + Provides an IAM OpenID Connect provider. +--- + +# aws\_iam\_openid\_connect\_provider + +Provides an IAM OpenID Connect provider. + +## Example Usage + +``` +resource "aws_iam_openid_connect_provider" "default" { + url = "https://accounts.google.com" + client_id_list = [ + "266362248691-342342xasdasdasda-apps.googleusercontent.com" + ] + thumbprint_list = [] +} +``` + +## Argument Reference + +The following arguments are supported: + +* `url` - (Required) The URL of the identity provider. Corresponds to the _iss_ claim. +* `client_id_list` - (Required) A list of client IDs (also known as audiences). When a mobile or web app registers with an OpenID Connect provider, they establish a value that identifies the application. (This is the value that's sent as the client_id parameter on OAuth requests.) +* `thumbprint_list` - (Required) A list of server certificate thumbprints for the OpenID Connect (OIDC) identity provider's server certificate(s). + +## Attributes Reference + +The following attributes are exported: + +* `arn` - The ARN assigned by AWS for this provider. + +## Import + +IAM OpenID Connect Providers can be imported using the `arn`, e.g. + +``` +$ terraform import aws_iam_openid_connect_provider.default arn:aws:iam::123456789012:oidc-provider/accounts.google.com +``` diff --git a/website/source/docs/providers/external/data_source.html.md b/website/source/docs/providers/external/data_source.html.md index 9241d0215..53b2271df 100644 --- a/website/source/docs/providers/external/data_source.html.md +++ b/website/source/docs/providers/external/data_source.html.md @@ -27,7 +27,7 @@ configurations that are applied within Terraform Enterprise. ## Example Usage -``` +```hcl data "external" "example" { program = ["python", "${path.module}/example-data-source.py"] @@ -94,7 +94,7 @@ language. The following example shows some input/output boilerplate code for a data source implemented in bash: -``` +```bash #!/bin/bash # Exit if any of the intermediate steps fail diff --git a/website/source/docs/providers/mysql/index.html.markdown b/website/source/docs/providers/mysql/index.html.markdown index f7d8eec4f..eae80872c 100644 --- a/website/source/docs/providers/mysql/index.html.markdown +++ b/website/source/docs/providers/mysql/index.html.markdown @@ -18,7 +18,7 @@ Use the navigation to the left to read about the available resources. The following is a minimal example: -``` +```hcl # Configure the MySQL provider provider "mysql" { endpoint = "my-database.example.com:3306" @@ -36,7 +36,7 @@ This provider can be used in conjunction with other resources that create MySQL servers. For example, ``aws_db_instance`` is able to create MySQL servers in Amazon's RDS service. -``` +```hcl # Create a database server resource "aws_db_instance" "default" { engine = "mysql" diff --git a/website/source/docs/providers/mysql/r/database.html.markdown b/website/source/docs/providers/mysql/r/database.html.markdown index 0f38fe4b4..04ffc60b5 100644 --- a/website/source/docs/providers/mysql/r/database.html.markdown +++ b/website/source/docs/providers/mysql/r/database.html.markdown @@ -19,7 +19,7 @@ on your database resources as an extra safety measure. ## Example Usage -``` +```hcl resource "mysql_database" "app" { name = "my_awesome_app" } diff --git a/website/source/docs/providers/mysql/r/grant.html.markdown b/website/source/docs/providers/mysql/r/grant.html.markdown index aacc20a39..464445836 100644 --- a/website/source/docs/providers/mysql/r/grant.html.markdown +++ b/website/source/docs/providers/mysql/r/grant.html.markdown @@ -13,7 +13,7 @@ a user on a MySQL server. ## Example Usage -``` +```hcl resource "mysql_user" "jdoe" { user = "jdoe" host = "example.com" diff --git a/website/source/docs/providers/mysql/r/user.html.markdown b/website/source/docs/providers/mysql/r/user.html.markdown index ebf101174..6f3f8b50d 100644 --- a/website/source/docs/providers/mysql/r/user.html.markdown +++ b/website/source/docs/providers/mysql/r/user.html.markdown @@ -16,7 +16,7 @@ server. ## Example Usage -``` +```hcl resource "mysql_user" "jdoe" { user = "jdoe" host = "example.com" diff --git a/website/source/docs/providers/random/index.html.markdown b/website/source/docs/providers/random/index.html.markdown index 32bf038d8..234b00106 100644 --- a/website/source/docs/providers/random/index.html.markdown +++ b/website/source/docs/providers/random/index.html.markdown @@ -43,7 +43,7 @@ the same until new random values are desired. For example: -``` +```hcl resource "random_id" "server" { keepers = { # Generate a new id each time we switch to a new AMI id diff --git a/website/source/docs/providers/random/r/id.html.md b/website/source/docs/providers/random/r/id.html.md index a7a94a407..b06e04013 100644 --- a/website/source/docs/providers/random/r/id.html.md +++ b/website/source/docs/providers/random/r/id.html.md @@ -26,7 +26,7 @@ exist concurrently. The following example shows how to generate a unique name for an AWS EC2 instance that changes each time a new AMI id is selected. -``` +```hcl resource "random_id" "server" { keepers = { # Generate a new id each time we switch to a new AMI id diff --git a/website/source/docs/providers/random/r/pet.html.md b/website/source/docs/providers/random/r/pet.html.md index 86b457a7a..56068237b 100644 --- a/website/source/docs/providers/random/r/pet.html.md +++ b/website/source/docs/providers/random/r/pet.html.md @@ -21,7 +21,7 @@ exist concurrently. The following example shows how to generate a unique pet name for an AWS EC2 instance that changes each time a new AMI id is selected. -``` +```hcl resource "random_pet" "server" { keepers = { # Generate a new pet name each time we switch to a new AMI id diff --git a/website/source/docs/providers/random/r/shuffle.html.md b/website/source/docs/providers/random/r/shuffle.html.md index bfae65bca..9204df791 100644 --- a/website/source/docs/providers/random/r/shuffle.html.md +++ b/website/source/docs/providers/random/r/shuffle.html.md @@ -13,7 +13,7 @@ of strings given as an argument. ## Example Usage -``` +```hcl resource "random_shuffle" "az" { input = ["us-west-1a", "us-west-1c", "us-west-1d", "us-west-1e"] result_count = 2 diff --git a/website/source/docs/providers/rundeck/index.html.markdown b/website/source/docs/providers/rundeck/index.html.markdown index 595ccaf5c..062045de5 100644 --- a/website/source/docs/providers/rundeck/index.html.markdown +++ b/website/source/docs/providers/rundeck/index.html.markdown @@ -30,7 +30,7 @@ Use the navigation to the left to read about the available resources. ## Example Usage -``` +```hcl provider "rundeck" { url = "http://rundeck.example.com/" auth_token = "abcd1234" diff --git a/website/source/docs/providers/rundeck/r/job.html.md b/website/source/docs/providers/rundeck/r/job.html.md index 725d1bf2b..5345c3b24 100644 --- a/website/source/docs/providers/rundeck/r/job.html.md +++ b/website/source/docs/providers/rundeck/r/job.html.md @@ -16,7 +16,7 @@ Each job belongs to a project. A project can be created with the `rundeck_projec ## Example Usage -``` +```hcl resource "rundeck_job" "bounceweb" { name = "Bounce Web Servers" project_name = "anvils" diff --git a/website/source/docs/providers/rundeck/r/private_key.html.md b/website/source/docs/providers/rundeck/r/private_key.html.md index 3d74aaf1d..a95829ef8 100644 --- a/website/source/docs/providers/rundeck/r/private_key.html.md +++ b/website/source/docs/providers/rundeck/r/private_key.html.md @@ -14,7 +14,7 @@ it runs commands. ## Example Usage -``` +```hcl resource "rundeck_private_key" "anvils" { path = "anvils/id_rsa" key_material = "${file("/id_rsa")}" diff --git a/website/source/docs/providers/rundeck/r/project.html.md b/website/source/docs/providers/rundeck/r/project.html.md index e8a7d3eba..31a3827a3 100644 --- a/website/source/docs/providers/rundeck/r/project.html.md +++ b/website/source/docs/providers/rundeck/r/project.html.md @@ -14,7 +14,7 @@ can be run on. ## Example Usage -``` +```hcl resource "rundeck_project" "anvils" { name = "anvils" description = "Application for managing Anvils" diff --git a/website/source/docs/providers/rundeck/r/public_key.html.md b/website/source/docs/providers/rundeck/r/public_key.html.md index 13ddca606..a3e617829 100644 --- a/website/source/docs/providers/rundeck/r/public_key.html.md +++ b/website/source/docs/providers/rundeck/r/public_key.html.md @@ -17,7 +17,7 @@ may be used in the configuration of other resources such as ``aws_key_pair``. ## Example Usage -``` +```hcl resource "rundeck_public_key" "anvils" { path = "anvils/id_rsa.pub" key_material = "ssh-rsa yada-yada-yada" diff --git a/website/source/docs/providers/template/d/cloudinit_config.html.markdown b/website/source/docs/providers/template/d/cloudinit_config.html.markdown index 030092ea5..46f3ca3c8 100644 --- a/website/source/docs/providers/template/d/cloudinit_config.html.markdown +++ b/website/source/docs/providers/template/d/cloudinit_config.html.markdown @@ -12,7 +12,7 @@ Renders a multi-part cloud-init config from source files. ## Example Usage -``` +```hcl # Render a part using a `template_file` data "template_file" "script" { template = "${file("${path.module}/init.tpl")}" diff --git a/website/source/docs/providers/template/d/file.html.md b/website/source/docs/providers/template/d/file.html.md index 4929041f1..e00107acc 100644 --- a/website/source/docs/providers/template/d/file.html.md +++ b/website/source/docs/providers/template/d/file.html.md @@ -16,7 +16,7 @@ Option 1: From a file: Reference the template path: -``` +```hcl data "template_file" "init" { template = "${file("${path.module}/init.tpl")}" @@ -28,7 +28,7 @@ data "template_file" "init" { Inside the file, reference the variable as such: -``` +```bash #!/bin/bash echo "CONSUL_ADDRESS = ${consul_address}" > /tmp/iplist @@ -36,7 +36,7 @@ echo "CONSUL_ADDRESS = ${consul_address}" > /tmp/iplist Option 2: Inline: -``` +```hcl data "template_file" "init" { template = "$${consul_address}:1234" diff --git a/website/source/docs/providers/template/index.html.markdown b/website/source/docs/providers/template/index.html.markdown index 19357988e..22d715c2f 100644 --- a/website/source/docs/providers/template/index.html.markdown +++ b/website/source/docs/providers/template/index.html.markdown @@ -15,7 +15,7 @@ Use the navigation to the left to read about the available data sources. ## Example Usage -``` +```hcl # Template for initial configuration bash script data "template_file" "init" { template = "${file("init.tpl")}" @@ -35,7 +35,7 @@ resource "aws_instance" "web" { Or using an inline template: -``` +```hcl # Template for initial configuration bash script data "template_file" "init" { template = "$${consul_address}:1234" diff --git a/website/source/docs/providers/terraform/index.html.markdown b/website/source/docs/providers/terraform/index.html.markdown index 3fca18257..f0b7784a0 100644 --- a/website/source/docs/providers/terraform/index.html.markdown +++ b/website/source/docs/providers/terraform/index.html.markdown @@ -15,7 +15,7 @@ Use the navigation to the left to read about the available data sources. ## Example Usage -``` +```hcl # Shared infrastructure state stored in Atlas data "terraform_remote_state" "vpc" { backend = "atlas" diff --git a/website/source/docs/providers/tls/index.html.markdown b/website/source/docs/providers/tls/index.html.markdown index 42017111a..57f962e64 100644 --- a/website/source/docs/providers/tls/index.html.markdown +++ b/website/source/docs/providers/tls/index.html.markdown @@ -26,7 +26,7 @@ Use the navigation to the left to read about the available resources. ## Example Usage -``` +```hcl ## This example create a self-signed certificate for a development ## environment. ## THIS IS NOT RECOMMENDED FOR PRODUCTION SERVICES. @@ -34,39 +34,39 @@ Use the navigation to the left to read about the available resources. ## security considerations and other practical tradeoffs. resource "tls_private_key" "example" { - algorithm = "ECDSA" + algorithm = "ECDSA" } resource "tls_self_signed_cert" "example" { - key_algorithm = "${tls_private_key.example.algorithm}" - private_key_pem = "${tls_private_key.example.private_key_pem}" + key_algorithm = "${tls_private_key.example.algorithm}" + private_key_pem = "${tls_private_key.example.private_key_pem}" - # Certificate expires after 12 hours. - validity_period_hours = 12 + # Certificate expires after 12 hours. + validity_period_hours = 12 - # Generate a new certificate if Terraform is run within three - # hours of the certificate's expiration time. - early_renewal_hours = 3 + # Generate a new certificate if Terraform is run within three + # hours of the certificate's expiration time. + early_renewal_hours = 3 - # Reasonable set of uses for a server SSL certificate. - allowed_uses = [ - "key_encipherment", - "digital_signature", - "server_auth", - ] + # Reasonable set of uses for a server SSL certificate. + allowed_uses = [ + "key_encipherment", + "digital_signature", + "server_auth", + ] - dns_names = ["example.com", "example.net"] + dns_names = ["example.com", "example.net"] - subject { - common_name = "example.com" - organization = "ACME Examples, Inc" - } + subject { + common_name = "example.com" + organization = "ACME Examples, Inc" + } } # For example, this can be used to populate an AWS IAM server certificate. resource "aws_iam_server_certificate" "example" { - name = "example_self_signed_cert" - certificate_body = "${tls_self_signed_cert.example.cert_pem}" - private_key = "${tls_private_key.example.private_key_pem}" + name = "example_self_signed_cert" + certificate_body = "${tls_self_signed_cert.example.cert_pem}" + private_key = "${tls_private_key.example.private_key_pem}" } ``` diff --git a/website/source/docs/providers/tls/r/cert_request.html.md b/website/source/docs/providers/tls/r/cert_request.html.md index 8869aeac6..3a71583fd 100644 --- a/website/source/docs/providers/tls/r/cert_request.html.md +++ b/website/source/docs/providers/tls/r/cert_request.html.md @@ -26,15 +26,15 @@ resource form. ## Example Usage -``` +```hcl resource "tls_cert_request" "example" { - key_algorithm = "ECDSA" - private_key_pem = "${file(\"private_key.pem\")}" + key_algorithm = "ECDSA" + private_key_pem = "${file("private_key.pem")}" - subject { - common_name = "example.com" - organization = "ACME Examples, Inc" - } + subject { + common_name = "example.com" + organization = "ACME Examples, Inc" + } } ``` diff --git a/website/source/docs/providers/tls/r/locally_signed_cert.html.md b/website/source/docs/providers/tls/r/locally_signed_cert.html.md index ebd13fd54..a022c2925 100644 --- a/website/source/docs/providers/tls/r/locally_signed_cert.html.md +++ b/website/source/docs/providers/tls/r/locally_signed_cert.html.md @@ -17,21 +17,20 @@ or when deployed internally to an organization. ## Example Usage -``` +```hcl resource "tls_locally_signed_cert" "example" { - cert_request_pem = "${file(\"cert_request.pem\")}" + cert_request_pem = "${file("cert_request.pem")}" + ca_key_algorithm = "ECDSA" + ca_private_key_pem = "${file("ca_private_key.pem")}" + ca_cert_pem = "${file("ca_cert.pem")}" - ca_key_algorithm = "ECDSA" - ca_private_key_pem = "${file(\"ca_private_key.pem\")}" - ca_cert_pem = "${file(\"ca_cert.pem\")}" + validity_period_hours = 12 - validity_period_hours = 12 - - allowed_uses = [ - "key_encipherment", - "digital_signature", - "server_auth", - ] + allowed_uses = [ + "key_encipherment", + "digital_signature", + "server_auth", + ] } ``` diff --git a/website/source/docs/providers/tls/r/private_key.html.md b/website/source/docs/providers/tls/r/private_key.html.md index c0d6d1beb..06d4fc4bc 100644 --- a/website/source/docs/providers/tls/r/private_key.html.md +++ b/website/source/docs/providers/tls/r/private_key.html.md @@ -23,10 +23,10 @@ state and does not create any external managed resources. ## Example Usage -``` +```hcl resource "tls_private_key" "example" { - algorithm = "ECDSA" - ecdsa_curve = "P384" + algorithm = "ECDSA" + ecdsa_curve = "P384" } ``` diff --git a/website/source/docs/providers/tls/r/self_signed_cert.html.md b/website/source/docs/providers/tls/r/self_signed_cert.html.md index f2a047f4f..60cf5bcf1 100644 --- a/website/source/docs/providers/tls/r/self_signed_cert.html.md +++ b/website/source/docs/providers/tls/r/self_signed_cert.html.md @@ -27,23 +27,23 @@ Load Balancer*, *Elastic Beanstalk*, *CloudFront* or *OpsWorks*. ## Example Usage -``` +```hcl resource "tls_self_signed_cert" "example" { - key_algorithm = "ECDSA" - private_key_pem = "${file(\"private_key.pem\")}" + key_algorithm = "ECDSA" + private_key_pem = "${file(\"private_key.pem\")}" - subject { - common_name = "example.com" - organization = "ACME Examples, Inc" - } + subject { + common_name = "example.com" + organization = "ACME Examples, Inc" + } - validity_period_hours = 12 + validity_period_hours = 12 - allowed_uses = [ - "key_encipherment", - "digital_signature", - "server_auth", - ] + allowed_uses = [ + "key_encipherment", + "digital_signature", + "server_auth", + ] } ``` diff --git a/website/source/docs/providers/vault/d/generic_secret.html.md b/website/source/docs/providers/vault/d/generic_secret.html.md index 59ed9b2fe..c6ef7fecf 100644 --- a/website/source/docs/providers/vault/d/generic_secret.html.md +++ b/website/source/docs/providers/vault/d/generic_secret.html.md @@ -25,7 +25,7 @@ for more details. ## Example Usage -``` +```hcl data "vault_generic_secret" "rundeck_auth" { path = "secret/rundeck_auth" } diff --git a/website/source/docs/providers/vault/index.html.markdown b/website/source/docs/providers/vault/index.html.markdown index ba67c94b0..d58195d72 100644 --- a/website/source/docs/providers/vault/index.html.markdown +++ b/website/source/docs/providers/vault/index.html.markdown @@ -126,7 +126,7 @@ The `client_auth` configuration block accepts the following arguments: ## Example Usage -``` +```hcl provider "vault" { # It is strongly recommended to configure this provider through the # environment variables described above, so that each user can have diff --git a/website/source/docs/providers/vault/r/generic_secret.html.md b/website/source/docs/providers/vault/r/generic_secret.html.md index 39c1030ba..e24b52291 100644 --- a/website/source/docs/providers/vault/r/generic_secret.html.md +++ b/website/source/docs/providers/vault/r/generic_secret.html.md @@ -25,7 +25,7 @@ for more details. ## Example Usage -``` +```hcl resource "vault_generic_secret" "example" { path = "secret/foo" diff --git a/website/source/docs/providers/vault/r/policy.md b/website/source/docs/providers/vault/r/policy.md index 89e60c531..2b3a59256 100644 --- a/website/source/docs/providers/vault/r/policy.md +++ b/website/source/docs/providers/vault/r/policy.md @@ -11,7 +11,7 @@ description: |- ## Example Usage -``` +```hcl resource "vault_policy" "example" { name = "dev-team" diff --git a/website/source/layouts/aws.erb b/website/source/layouts/aws.erb index 0373c3716..716a53411 100644 --- a/website/source/layouts/aws.erb +++ b/website/source/layouts/aws.erb @@ -745,6 +745,10 @@ aws_iam_instance_profile + > + aws_iam_openid_connect_provider + + > aws_iam_policy