mirror of
https://github.com/opentofu/terraform-provider-vault.git
synced 2026-01-11 19:46:35 +00:00
Feature parity Secret_Sync - Added missing configuration parameters for Github destination (#2697)
* Added configuration parameters for Github destination * CHANGELOG.md updated with PR request * Example usage snippet and description updated for the added configuration and networking paramameters * Formatting correction * typeSet implemented for ipv4address, ipv6address and allowed_port paramaters. Review comments accomodated * SyncDestinationCreateUpdateWithOptions added to mitigate code duplication due to typeSet implementation for ipv4address, ipv6address, allowed_port parameters
This commit is contained in:
parent
5f7ef99373
commit
5a4538d719
5 changed files with 406 additions and 40 deletions
|
|
@ -8,6 +8,7 @@ IMPROVEMENTS:
|
|||
* Add support for `username_template` parameter in `vault_database_secret_backend_connection` and `vault_database_secrets_mount` resource for MongoDB Atlas([#2674](https://github.com/hashicorp/terraform-provider-vault/pull/2674))
|
||||
* Add support for `username_template` parameter in `vault_database_secret_backend_connection` and `vault_database_secrets_mount` resources for HANADB connections: ([#2671](https://github.com/hashicorp/terraform-provider-vault/pull/2671))
|
||||
* Add support for networking allowlist fields (`allowed_ipv4_addresses`, `allowed_ipv6_addresses`, `allowed_ports`, `disable_strict_networking`) in `vault_secrets_sync_vercel_destination` resource. Requires Vault 1.19+. ([#2681](https://github.com/hashicorp/terraform-provider-vault/pull/2681))
|
||||
* Add support for configuration parameters (`allowed_ipv4_addresses`,`allowed_ipv6_addresses`,`allowed_ports`,`disable_strict_networking`,`secrets_location`,`environment_name`) in `vault_secrets_sync_gh_destination` resource. Requires Vault 1.18+ for `secrets_location`,`environment_name`.Requires Vault 1.19+ for `allowed_ipv4_addresses`,`allowed_ipv6_addresses`,`allowed_ports`,`disable_strict_networking`.([#2697](https://github.com/hashicorp/terraform-provider-vault/pull/2697)).
|
||||
* Add support for `tls_server_name` , `local_datacenter`, `socket_keep_alive`, `consistency` and `username_template` parameters for Cassandra in `vault_database_secret_backend_connection` resource. ([#2677](https://github.com/hashicorp/terraform-provider-vault/pull/2677))
|
||||
* `vault_secrets_sync_aws_destination`: Add support for networking configuration parameters `allowed_ipv4_addresses`, `allowed_ipv6_addresses`, `allowed_ports`, and `disable_strict_networking` to control outbound connections from Vault to AWS Secrets Manager. Requires Vault 1.19.0+.([#2698](https://github.com/hashicorp/terraform-provider-vault/pull/2698))
|
||||
* Updated dependencies:
|
||||
|
|
|
|||
|
|
@ -275,6 +275,12 @@ const (
|
|||
FieldProjectID = "project_id"
|
||||
FieldIPAddresses = "ip_addresses"
|
||||
FieldCIDRBlocks = "cidr_blocks"
|
||||
FieldAllowedIPv4Addresses = "allowed_ipv4_addresses"
|
||||
FieldAllowedIPv6Addresses = "allowed_ipv6_addresses"
|
||||
FieldAllowedPorts = "allowed_ports"
|
||||
FieldDisableStrictNetworking = "disable_strict_networking"
|
||||
FieldSecretsLocation = "secrets_location"
|
||||
FieldEnvironmentName = "environment_name"
|
||||
FieldProjectRoles = "project_roles"
|
||||
FieldCreationLDIF = "creation_ldif"
|
||||
FieldDeletionLDIF = "deletion_ldif"
|
||||
|
|
@ -454,10 +460,6 @@ const (
|
|||
FieldLink = "link"
|
||||
FieldGranularity = "granularity"
|
||||
FieldGranularityLevel = "granularity_level"
|
||||
FieldAllowedIPv4Addresses = "allowed_ipv4_addresses"
|
||||
FieldAllowedIPv6Addresses = "allowed_ipv6_addresses"
|
||||
FieldAllowedPorts = "allowed_ports"
|
||||
FieldDisableStrictNetworking = "disable_strict_networking"
|
||||
FieldLocationalKmsKeys = "locational_kms_keys"
|
||||
FieldGlobalKmsKey = "global_kms_key"
|
||||
FieldReplicationLocations = "replication_locations"
|
||||
|
|
|
|||
|
|
@ -21,32 +21,6 @@ const (
|
|||
ghSyncType = "gh"
|
||||
)
|
||||
|
||||
var githubSyncWriteFields = []string{
|
||||
fieldAccessToken,
|
||||
fieldRepositoryOwner,
|
||||
fieldRepositoryName,
|
||||
consts.FieldSecretNameTemplate,
|
||||
consts.FieldGranularity,
|
||||
consts.FieldAppName,
|
||||
consts.FieldInstallationID,
|
||||
}
|
||||
|
||||
var githubSyncUpdateFields = []string{
|
||||
fieldAccessToken,
|
||||
consts.FieldSecretNameTemplate,
|
||||
consts.FieldAppName,
|
||||
consts.FieldInstallationID,
|
||||
}
|
||||
|
||||
var githubSyncReadFields = []string{
|
||||
fieldRepositoryOwner,
|
||||
fieldRepositoryName,
|
||||
consts.FieldGranularity,
|
||||
consts.FieldSecretNameTemplate,
|
||||
consts.FieldAppName,
|
||||
consts.FieldInstallationID,
|
||||
}
|
||||
|
||||
func githubSecretsSyncDestinationResource() *schema.Resource {
|
||||
return provider.MustAddSecretsSyncCommonSchema(&schema.Resource{
|
||||
CreateContext: provider.MountCreateContextWrapper(githubSecretsSyncDestinationCreateUpdate, provider.VaultVersion116),
|
||||
|
|
@ -91,18 +65,148 @@ func githubSecretsSyncDestinationResource() *schema.Resource {
|
|||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Description: "The ID of the installation generated by GitHub when the app referenced by the " +
|
||||
"app_name was installed in the user’s GitHub account. Necessary if the app_name field is also provided.",
|
||||
"app_name was installed in the user's GitHub account. Necessary if the app_name field is also provided.",
|
||||
},
|
||||
consts.FieldAllowedIPv4Addresses: {
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
Description: "List of allowed IPv4 addresses in CIDR notation (e.g., 192.168.1.1/32) " +
|
||||
"for outbound connections from Vault to the destination. If not set, all IPv4 addresses are allowed.",
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
},
|
||||
},
|
||||
consts.FieldAllowedIPv6Addresses: {
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
Description: "List of allowed IPv6 addresses in CIDR notation (e.g., 2001:db8::1/128) " +
|
||||
"for outbound connections from Vault to the destination. If not set, all IPv6 addresses are allowed.",
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
},
|
||||
},
|
||||
consts.FieldAllowedPorts: {
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
Description: "List of allowed ports for outbound connections from Vault to the destination. " +
|
||||
"If not set, all ports are allowed.",
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
},
|
||||
},
|
||||
consts.FieldDisableStrictNetworking: {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Description: "If set to true, disables strict networking enforcement for this destination. " +
|
||||
"When disabled, Vault will not enforce allowed IP addresses and ports.",
|
||||
},
|
||||
consts.FieldSecretsLocation: {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Determines where secrets will be stored in GitHub. " +
|
||||
"Valid values are 'repository' or 'environment'.",
|
||||
},
|
||||
consts.FieldEnvironmentName: {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "GitHub environment name where secrets will be synced. " +
|
||||
"Required when secrets_location is set to 'environment'.",
|
||||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func githubSecretsSyncDestinationCreateUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
return syncutil.SyncDestinationCreateUpdate(ctx, d, meta, ghSyncType, githubSyncWriteFields, githubSyncReadFields)
|
||||
writeFields := []string{
|
||||
fieldAccessToken,
|
||||
fieldRepositoryOwner,
|
||||
fieldRepositoryName,
|
||||
consts.FieldSecretNameTemplate,
|
||||
consts.FieldGranularity,
|
||||
consts.FieldAppName,
|
||||
consts.FieldInstallationID,
|
||||
}
|
||||
readFields := []string{
|
||||
fieldRepositoryOwner,
|
||||
fieldRepositoryName,
|
||||
consts.FieldGranularity,
|
||||
consts.FieldSecretNameTemplate,
|
||||
consts.FieldAppName,
|
||||
consts.FieldInstallationID,
|
||||
}
|
||||
|
||||
// Add Vault 1.18+ fields if supported
|
||||
isV118Supported := provider.IsAPISupported(meta, provider.VaultVersion118)
|
||||
if isV118Supported {
|
||||
writeFields = append(writeFields,
|
||||
consts.FieldSecretsLocation,
|
||||
consts.FieldEnvironmentName,
|
||||
)
|
||||
readFields = append(readFields,
|
||||
consts.FieldSecretsLocation,
|
||||
consts.FieldEnvironmentName,
|
||||
)
|
||||
}
|
||||
|
||||
// Add Vault 1.19+ fields if supported
|
||||
isV119Supported := provider.IsAPISupported(meta, provider.VaultVersion119)
|
||||
if isV119Supported {
|
||||
writeFields = append(writeFields,
|
||||
consts.FieldAllowedIPv4Addresses,
|
||||
consts.FieldAllowedIPv6Addresses,
|
||||
consts.FieldAllowedPorts,
|
||||
consts.FieldDisableStrictNetworking,
|
||||
)
|
||||
readFields = append(readFields,
|
||||
consts.FieldAllowedIPv4Addresses,
|
||||
consts.FieldAllowedIPv6Addresses,
|
||||
consts.FieldAllowedPorts,
|
||||
consts.FieldDisableStrictNetworking,
|
||||
)
|
||||
}
|
||||
|
||||
// Fields that need TypeSet to List conversion for JSON serialization
|
||||
var ghTypeSetFields = map[string]bool{
|
||||
consts.FieldAllowedIPv4Addresses: true,
|
||||
consts.FieldAllowedIPv6Addresses: true,
|
||||
consts.FieldAllowedPorts: true,
|
||||
}
|
||||
|
||||
return syncutil.SyncDestinationCreateUpdateWithOptions(ctx, d, meta, ghSyncType, writeFields, readFields, ghTypeSetFields)
|
||||
}
|
||||
|
||||
func githubSecretsSyncDestinationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
return syncutil.SyncDestinationRead(ctx, d, meta, ghSyncType, githubSyncReadFields, map[string]string{
|
||||
readFields := []string{
|
||||
fieldRepositoryOwner,
|
||||
fieldRepositoryName,
|
||||
consts.FieldGranularity,
|
||||
consts.FieldSecretNameTemplate,
|
||||
consts.FieldAppName,
|
||||
consts.FieldInstallationID,
|
||||
}
|
||||
|
||||
// Add Vault 1.18+ fields if supported
|
||||
isV118Supported := provider.IsAPISupported(meta, provider.VaultVersion118)
|
||||
if isV118Supported {
|
||||
readFields = append(readFields,
|
||||
consts.FieldSecretsLocation,
|
||||
consts.FieldEnvironmentName,
|
||||
)
|
||||
}
|
||||
|
||||
// Add Vault 1.19+ fields if supported
|
||||
isV119Supported := provider.IsAPISupported(meta, provider.VaultVersion119)
|
||||
if isV119Supported {
|
||||
readFields = append(readFields,
|
||||
consts.FieldAllowedIPv4Addresses,
|
||||
consts.FieldAllowedIPv6Addresses,
|
||||
consts.FieldAllowedPorts,
|
||||
consts.FieldDisableStrictNetworking,
|
||||
)
|
||||
}
|
||||
|
||||
return syncutil.SyncDestinationRead(ctx, d, meta, ghSyncType, readFields, map[string]string{
|
||||
consts.FieldGranularity: consts.FieldGranularityLevel,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,13 @@ package vault
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
|
||||
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
||||
|
||||
"github.com/hashicorp/terraform-provider-vault/acctestutil"
|
||||
"github.com/hashicorp/terraform-provider-vault/internal/consts"
|
||||
"github.com/hashicorp/terraform-provider-vault/internal/provider"
|
||||
"github.com/hashicorp/terraform-provider-vault/testutil"
|
||||
|
|
@ -36,14 +38,13 @@ func TestGithubSecretsSyncDestination(t *testing.T) {
|
|||
resource.Test(t, resource.TestCase{
|
||||
ProtoV5ProviderFactories: testAccProtoV5ProviderFactories(context.Background(), t),
|
||||
PreCheck: func() {
|
||||
testutil.TestAccPreCheck(t)
|
||||
acctestutil.TestAccPreCheck(t)
|
||||
SkipIfAPIVersionLT(t, testProvider.Meta(), provider.VaultVersion116)
|
||||
}, PreventPostDestroyRefresh: true,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testGithubSecretsSyncDestinationConfig_initial(accessToken, repoOwner, repoName, destName, defaultSecretsSyncTemplate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldName, destName),
|
||||
resource.TestCheckResourceAttr(resourceName, fieldAccessToken, accessToken),
|
||||
resource.TestCheckResourceAttr(resourceName, fieldRepositoryOwner, repoOwner),
|
||||
|
|
@ -52,10 +53,39 @@ func TestGithubSecretsSyncDestination(t *testing.T) {
|
|||
resource.TestCheckResourceAttr(resourceName, consts.FieldGranularity, "secret-path"),
|
||||
),
|
||||
},
|
||||
{
|
||||
SkipFunc: func() (bool, error) {
|
||||
meta := testProvider.Meta().(*provider.ProviderMeta)
|
||||
return !meta.IsAPISupported(provider.VaultVersion118), nil
|
||||
},
|
||||
Config: testGithubSecretsSyncDestinationConfig_initial(accessToken, repoOwner, repoName, destName, defaultSecretsSyncTemplate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldSecretsLocation, "repository"),
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldEnvironmentName, "production"),
|
||||
),
|
||||
},
|
||||
{
|
||||
SkipFunc: func() (bool, error) {
|
||||
meta := testProvider.Meta().(*provider.ProviderMeta)
|
||||
return !meta.IsAPISupported(provider.VaultVersion119), nil
|
||||
},
|
||||
Config: testGithubSecretsSyncDestinationConfig_initial(accessToken, repoOwner, repoName, destName, defaultSecretsSyncTemplate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldAllowedIPv4Addresses+".#", "2"),
|
||||
resource.TestCheckTypeSetElemAttr(resourceName, consts.FieldAllowedIPv4Addresses+".*", "192.168.1.0/24"),
|
||||
resource.TestCheckTypeSetElemAttr(resourceName, consts.FieldAllowedIPv4Addresses+".*", "10.0.0.0/8"),
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldAllowedIPv6Addresses+".#", "1"),
|
||||
resource.TestCheckTypeSetElemAttr(resourceName, consts.FieldAllowedIPv6Addresses+".*", "2001:db8::/32"),
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldAllowedPorts+".#", "3"),
|
||||
resource.TestCheckTypeSetElemAttr(resourceName, consts.FieldAllowedPorts+".*", "443"),
|
||||
resource.TestCheckTypeSetElemAttr(resourceName, consts.FieldAllowedPorts+".*", "80"),
|
||||
resource.TestCheckTypeSetElemAttr(resourceName, consts.FieldAllowedPorts+".*", "22"),
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldDisableStrictNetworking, "false"),
|
||||
),
|
||||
},
|
||||
{
|
||||
Config: testGithubSecretsSyncDestinationConfig_updated(accessToken, repoOwner, repoName, destName, secretsKeyTemplate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldName, destName),
|
||||
resource.TestCheckResourceAttr(resourceName, fieldAccessToken, accessToken),
|
||||
resource.TestCheckResourceAttr(resourceName, fieldRepositoryOwner, repoOwner),
|
||||
|
|
@ -64,13 +94,142 @@ func TestGithubSecretsSyncDestination(t *testing.T) {
|
|||
resource.TestCheckResourceAttr(resourceName, consts.FieldGranularity, "secret-key"),
|
||||
),
|
||||
},
|
||||
testutil.GetImportTestStep(resourceName, false, nil,
|
||||
fieldAccessToken,
|
||||
),
|
||||
{
|
||||
SkipFunc: func() (bool, error) {
|
||||
meta := testProvider.Meta().(*provider.ProviderMeta)
|
||||
return !meta.IsAPISupported(provider.VaultVersion118), nil
|
||||
},
|
||||
Config: testGithubSecretsSyncDestinationConfig_updated(accessToken, repoOwner, repoName, destName, secretsKeyTemplate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldSecretsLocation, "repository"),
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldEnvironmentName, "production"),
|
||||
),
|
||||
},
|
||||
{
|
||||
SkipFunc: func() (bool, error) {
|
||||
meta := testProvider.Meta().(*provider.ProviderMeta)
|
||||
return !meta.IsAPISupported(provider.VaultVersion119), nil
|
||||
},
|
||||
Config: testGithubSecretsSyncDestinationConfig_updated(accessToken, repoOwner, repoName, destName, secretsKeyTemplate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldAllowedIPv4Addresses+".#", "1"),
|
||||
resource.TestCheckTypeSetElemAttr(resourceName, consts.FieldAllowedIPv4Addresses+".*", "172.16.0.0/16"),
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldAllowedIPv6Addresses+".#", "2"),
|
||||
resource.TestCheckTypeSetElemAttr(resourceName, consts.FieldAllowedIPv6Addresses+".*", "2001:db8::/32"),
|
||||
resource.TestCheckTypeSetElemAttr(resourceName, consts.FieldAllowedIPv6Addresses+".*", "fe80::/10"),
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldAllowedPorts+".#", "2"),
|
||||
resource.TestCheckTypeSetElemAttr(resourceName, consts.FieldAllowedPorts+".*", "443"),
|
||||
resource.TestCheckTypeSetElemAttr(resourceName, consts.FieldAllowedPorts+".*", "8080"),
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldDisableStrictNetworking, "true"),
|
||||
),
|
||||
},
|
||||
getGithubImportTestStep(resourceName),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestGithubSecretsSyncDestination_InvalidNetworkingParams(t *testing.T) {
|
||||
destName := acctest.RandomWithPrefix("tf-sync-dest-gh")
|
||||
|
||||
values := testutil.SkipTestEnvUnset(t,
|
||||
"GITHUB_ACCESS_TOKEN",
|
||||
"GITHUB_REPO_OWNER",
|
||||
"GITHUB_REPO_NAME",
|
||||
)
|
||||
|
||||
accessToken := values[0]
|
||||
repoOwner := values[1]
|
||||
repoName := values[2]
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProtoV5ProviderFactories: testAccProtoV5ProviderFactories(context.Background(), t),
|
||||
PreCheck: func() {
|
||||
acctestutil.TestAccPreCheck(t)
|
||||
SkipIfAPIVersionLT(t, testProvider.Meta(), provider.VaultVersion119)
|
||||
},
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testGithubSecretsSyncDestinationConfig_invalidIPv4(accessToken, repoOwner, repoName, destName),
|
||||
ExpectError: regexp.MustCompile(".*invalid.*CIDR.*|.*invalid.*IPv4.*|.*error.*"),
|
||||
},
|
||||
{
|
||||
Config: testGithubSecretsSyncDestinationConfig_invalidIPv6(accessToken, repoOwner, repoName, destName),
|
||||
ExpectError: regexp.MustCompile(".*invalid.*CIDR.*|.*invalid.*IPv6.*|.*error.*"),
|
||||
},
|
||||
{
|
||||
Config: testGithubSecretsSyncDestinationConfig_invalidPorts(accessToken, repoOwner, repoName, destName),
|
||||
ExpectError: regexp.MustCompile(".*invalid.*port.*|.*out of range.*|.*error.*"),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestGithubSecretsSyncDestination_DuplicateNetworkingParams(t *testing.T) {
|
||||
destName := acctest.RandomWithPrefix("tf-sync-dest-gh")
|
||||
|
||||
resourceName := "vault_secrets_sync_gh_destination.test"
|
||||
|
||||
values := testutil.SkipTestEnvUnset(t,
|
||||
"GITHUB_ACCESS_TOKEN",
|
||||
"GITHUB_REPO_OWNER",
|
||||
"GITHUB_REPO_NAME",
|
||||
)
|
||||
|
||||
accessToken := values[0]
|
||||
repoOwner := values[1]
|
||||
repoName := values[2]
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProtoV5ProviderFactories: testAccProtoV5ProviderFactories(context.Background(), t),
|
||||
PreCheck: func() {
|
||||
acctestutil.TestAccPreCheck(t)
|
||||
SkipIfAPIVersionLT(t, testProvider.Meta(), provider.VaultVersion119)
|
||||
}, PreventPostDestroyRefresh: true,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testGithubSecretsSyncDestinationConfig_duplicates(accessToken, repoOwner, repoName, destName),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldName, destName),
|
||||
resource.TestCheckResourceAttr(resourceName, fieldAccessToken, accessToken),
|
||||
resource.TestCheckResourceAttr(resourceName, fieldRepositoryOwner, repoOwner),
|
||||
resource.TestCheckResourceAttr(resourceName, fieldRepositoryName, repoName),
|
||||
// Verify duplicates are deduplicated by checking count
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldAllowedIPv4Addresses+".#", "2"),
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldAllowedIPv6Addresses+".#", "2"),
|
||||
resource.TestCheckResourceAttr(resourceName, consts.FieldAllowedPorts+".#", "2"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func getGithubImportTestStep(resourceName string) resource.TestStep {
|
||||
ignoreFields := []string{fieldAccessToken}
|
||||
|
||||
// On Vault < 1.18, the V118 fields won't be returned from the API
|
||||
// so we need to ignore them during import verification
|
||||
meta := testProvider.Meta().(*provider.ProviderMeta)
|
||||
if !meta.IsAPISupported(provider.VaultVersion118) {
|
||||
ignoreFields = append(ignoreFields,
|
||||
consts.FieldSecretsLocation,
|
||||
consts.FieldEnvironmentName,
|
||||
)
|
||||
}
|
||||
|
||||
// On Vault < 1.19, the V119 networking fields won't be returned from the API
|
||||
// so we need to ignore them during import verification
|
||||
if !meta.IsAPISupported(provider.VaultVersion119) {
|
||||
ignoreFields = append(ignoreFields,
|
||||
consts.FieldAllowedIPv4Addresses,
|
||||
consts.FieldAllowedIPv6Addresses,
|
||||
consts.FieldAllowedPorts,
|
||||
consts.FieldDisableStrictNetworking,
|
||||
)
|
||||
}
|
||||
|
||||
return testutil.GetImportTestStep(resourceName, false, nil, ignoreFields...)
|
||||
}
|
||||
|
||||
func testGithubSecretsSyncDestinationConfig_initial(accessToken, repoOwner, repoName, destName, templ string) string {
|
||||
ret := fmt.Sprintf(`
|
||||
resource "vault_secrets_sync_gh_destination" "test" {
|
||||
|
|
@ -78,6 +237,12 @@ resource "vault_secrets_sync_gh_destination" "test" {
|
|||
access_token = "%s"
|
||||
repository_owner = "%s"
|
||||
repository_name = "%s"
|
||||
allowed_ipv4_addresses = ["192.168.1.0/24", "10.0.0.0/8"]
|
||||
allowed_ipv6_addresses = ["2001:db8::/32"]
|
||||
allowed_ports = [443, 80, 22]
|
||||
disable_strict_networking = false
|
||||
secrets_location = "repository"
|
||||
environment_name = "production"
|
||||
%s
|
||||
}
|
||||
`, destName, accessToken, repoOwner, repoName, testSecretsSyncDestinationCommonConfig(templ, true, false, false))
|
||||
|
|
@ -92,9 +257,74 @@ resource "vault_secrets_sync_gh_destination" "test" {
|
|||
access_token = "%s"
|
||||
repository_owner = "%s"
|
||||
repository_name = "%s"
|
||||
allowed_ipv4_addresses = ["172.16.0.0/16"]
|
||||
allowed_ipv6_addresses = ["2001:db8::/32", "fe80::/10"]
|
||||
allowed_ports = [443, 8080]
|
||||
disable_strict_networking = true
|
||||
secrets_location = "repository"
|
||||
environment_name = "production"
|
||||
%s
|
||||
}
|
||||
`, destName, accessToken, repoOwner, repoName, testSecretsSyncDestinationCommonConfig(templ, true, false, true))
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func testGithubSecretsSyncDestinationConfig_invalidIPv4(accessToken, repoOwner, repoName, destName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "vault_secrets_sync_gh_destination" "test" {
|
||||
name = "%s"
|
||||
access_token = "%s"
|
||||
repository_owner = "%s"
|
||||
repository_name = "%s"
|
||||
allowed_ipv4_addresses = ["256.256.256.256/32", "192.168.1.999/24", "invalid-ip"]
|
||||
secrets_location = "repository"
|
||||
environment_name = "production"
|
||||
}
|
||||
`, destName, accessToken, repoOwner, repoName)
|
||||
}
|
||||
|
||||
func testGithubSecretsSyncDestinationConfig_invalidIPv6(accessToken, repoOwner, repoName, destName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "vault_secrets_sync_gh_destination" "test" {
|
||||
name = "%s"
|
||||
access_token = "%s"
|
||||
repository_owner = "%s"
|
||||
repository_name = "%s"
|
||||
allowed_ipv6_addresses = ["gggg::/32", "2001:db8::zzz/64", "invalid-ipv6"]
|
||||
secrets_location = "repository"
|
||||
environment_name = "production"
|
||||
}
|
||||
`, destName, accessToken, repoOwner, repoName)
|
||||
}
|
||||
|
||||
func testGithubSecretsSyncDestinationConfig_invalidPorts(accessToken, repoOwner, repoName, destName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "vault_secrets_sync_gh_destination" "test" {
|
||||
name = "%s"
|
||||
access_token = "%s"
|
||||
repository_owner = "%s"
|
||||
repository_name = "%s"
|
||||
allowed_ports = [70000, -1, 999999]
|
||||
secrets_location = "repository"
|
||||
environment_name = "production"
|
||||
}
|
||||
`, destName, accessToken, repoOwner, repoName)
|
||||
}
|
||||
|
||||
func testGithubSecretsSyncDestinationConfig_duplicates(accessToken, repoOwner, repoName, destName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "vault_secrets_sync_gh_destination" "test" {
|
||||
name = "%s"
|
||||
access_token = "%s"
|
||||
repository_owner = "%s"
|
||||
repository_name = "%s"
|
||||
allowed_ipv4_addresses = ["192.168.1.0/24", "10.0.0.0/8", "192.168.1.0/24", "10.0.0.0/8"]
|
||||
allowed_ipv6_addresses = ["2001:db8::/32", "fe80::/10", "2001:db8::/32", "fe80::/10"]
|
||||
allowed_ports = [443, 80, 443, 80]
|
||||
secrets_location = "repository"
|
||||
environment_name = "production"
|
||||
granularity = "secret-path"
|
||||
}
|
||||
`, destName, accessToken, repoOwner, repoName)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,17 @@ resource "vault_secrets_sync_gh_destination" "gh" {
|
|||
repository_owner = var.repo_owner
|
||||
repository_name = "repo-name-example"
|
||||
secret_name_template = "vault_{{ .MountAccessor | lowercase }}_{{ .SecretPath | lowercase }}"
|
||||
|
||||
# Github destination-specific fields (Vault 1.18+)
|
||||
secrets_location = "repository"
|
||||
environment_name = "production"
|
||||
|
||||
# Networking allowlist fields (Vault 1.19+)
|
||||
# IP Addresses must be in CIDR notations.
|
||||
allowed_ipv4_addresses = ["192.168.1.0/24", "10.0.0.0/8"]
|
||||
allowed_ipv6_addresses = ["2001:db8::/32"]
|
||||
allowed_ports = [443, 80, 22]
|
||||
disable_strict_networking = false
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -66,8 +77,26 @@ The following arguments are supported:
|
|||
Takes precedence over the `access_token` field.
|
||||
|
||||
* `installation_id` -(Optional) The ID of the installation generated by GitHub when the app referenced by the `app_name`
|
||||
was installed in the user’s GitHub account. Can be modified. Necessary if the `app_name` field is also provided.
|
||||
was installed in the user's GitHub account. Can be modified. Necessary if the `app_name` field is also provided.
|
||||
|
||||
* `allowed_ipv4_addresses` - (Optional) Set of allowed IPv4 addresses in CIDR notation (e.g., `192.168.1.1/32`)
|
||||
for outbound connections from Vault to the destination. If not set, all IPv4 addresses are allowed.
|
||||
Requires Vault 1.19+.
|
||||
|
||||
* `allowed_ipv6_addresses` - (Optional) Set of allowed IPv6 addresses in CIDR notation (e.g., `2001:db8::1/128`)
|
||||
for outbound connections from Vault to the destination. If not set, all IPv6 addresses are allowed.
|
||||
Requires Vault 1.19+.
|
||||
|
||||
* `allowed_ports` - (Optional) Set of allowed ports for outbound connections from Vault to the
|
||||
destination. If not set, all ports are allowed. Requires Vault 1.19+.
|
||||
|
||||
* `disable_strict_networking` - (Optional) If set to `true`, disables strict networking enforcement
|
||||
for this destination. When disabled, Vault will not enforce allowed IP addresses and ports.
|
||||
Defaults to `false`. Requires Vault 1.19+.
|
||||
|
||||
* `secrets_location` - (Optional) Location where secrets are stored in the destination. Requires Vault 1.18+.
|
||||
|
||||
* `environment_name` - (Optional) Environment name for the destination. Requires Vault 1.18+.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue