diff --git a/builtin/providers/aws/resource_aws_vpn_connection.go b/builtin/providers/aws/resource_aws_vpn_connection.go index 9a0d15442e34..f8d8b8fd874b 100644 --- a/builtin/providers/aws/resource_aws_vpn_connection.go +++ b/builtin/providers/aws/resource_aws_vpn_connection.go @@ -2,8 +2,10 @@ package aws import ( "bytes" + "encoding/xml" "fmt" "log" + "sort" "time" "github.com/aws/aws-sdk-go/aws" @@ -15,6 +17,34 @@ import ( "github.com/hashicorp/terraform/helper/schema" ) +type XmlVpnConnectionConfig struct { + Tunnels []XmlIpsecTunnel `xml:"ipsec_tunnel"` +} + +type XmlIpsecTunnel struct { + OutsideAddress string `xml:"vpn_gateway>tunnel_outside_address>ip_address"` + PreSharedKey string `xml:"ike>pre_shared_key"` +} + +type TunnelInfo struct { + Tunnel1Address string + Tunnel1PreSharedKey string + Tunnel2Address string + Tunnel2PreSharedKey string +} + +func (slice XmlVpnConnectionConfig) Len() int { + return len(slice.Tunnels) +} + +func (slice XmlVpnConnectionConfig) Less(i, j int) bool { + return slice.Tunnels[i].OutsideAddress < slice.Tunnels[j].OutsideAddress +} + +func (slice XmlVpnConnectionConfig) Swap(i, j int) { + slice.Tunnels[i], slice.Tunnels[j] = slice.Tunnels[j], slice.Tunnels[i] +} + func resourceAwsVpnConnection() *schema.Resource { return &schema.Resource{ Create: resourceAwsVpnConnectionCreate, @@ -56,6 +86,26 @@ func resourceAwsVpnConnection() *schema.Resource { Optional: true, }, + "tunnel1_address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "tunnel1_preshared_key": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "tunnel2_address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "tunnel2_preshared_key": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "routes": &schema.Schema{ Type: schema.TypeSet, Computed: true, @@ -254,6 +304,13 @@ func resourceAwsVpnConnectionRead(d *schema.ResourceData, meta interface{}) erro // Set read only attributes. d.Set("customer_gateway_configuration", vpnConnection.CustomerGatewayConfiguration) + + tunnelInfo := xmlConfigToTunnelInfo(*vpnConnection.CustomerGatewayConfiguration) + d.Set("tunnel1_address", tunnelInfo.Tunnel1Address) + d.Set("tunnel1_preshared_key", tunnelInfo.Tunnel1PreSharedKey) + d.Set("tunnel2_address", tunnelInfo.Tunnel2Address) + d.Set("tunnel2_preshared_key", tunnelInfo.Tunnel2PreSharedKey) + if err := d.Set("vgw_telemetry", telemetryToMapList(vpnConnection.VgwTelemetry)); err != nil { return err } @@ -355,3 +412,21 @@ func telemetryToMapList(telemetry []*ec2.VgwTelemetry) []map[string]interface{} return result } + +func xmlConfigToTunnelInfo(xmlConfig string) TunnelInfo { + var vpnConfig XmlVpnConnectionConfig + xml.Unmarshal([]byte(xmlConfig), &vpnConfig) + + // don't expect consistent ordering from the XML + sort.Sort(vpnConfig) + + tunnelInfo := TunnelInfo{ + Tunnel1Address: vpnConfig.Tunnels[0].OutsideAddress, + Tunnel1PreSharedKey: vpnConfig.Tunnels[0].PreSharedKey, + + Tunnel2Address: vpnConfig.Tunnels[1].OutsideAddress, + Tunnel2PreSharedKey: vpnConfig.Tunnels[1].PreSharedKey, + } + + return tunnelInfo +} diff --git a/builtin/providers/aws/resource_aws_vpn_connection_test.go b/builtin/providers/aws/resource_aws_vpn_connection_test.go index cf151fc8547f..f833a1c3a1b0 100644 --- a/builtin/providers/aws/resource_aws_vpn_connection_test.go +++ b/builtin/providers/aws/resource_aws_vpn_connection_test.go @@ -117,45 +117,87 @@ func testAccAwsVpnConnection( } } +func TestAccAWSVpnConnection_xmlconfig(t *testing.T) { + tunnelInfo := xmlConfigToTunnelInfo(testAccAwsVpnTunnelInfoXML) + if tunnelInfo.Tunnel1Address != "FIRST_ADDRESS" { + t.Fatalf("First address from tunnel XML was incorrect.") + } + if tunnelInfo.Tunnel1PreSharedKey != "FIRST_KEY" { + t.Fatalf("First key from tunnel XML was incorrect.") + } + if tunnelInfo.Tunnel2Address != "SECOND_ADDRESS" { + t.Fatalf("Second address from tunnel XML was incorrect.") + } + if tunnelInfo.Tunnel2PreSharedKey != "SECOND_KEY" { + t.Fatalf("Second key from tunnel XML was incorrect.") + } +} + const testAccAwsVpnConnectionConfig = ` resource "aws_vpn_gateway" "vpn_gateway" { - tags { - Name = "vpn_gateway" - } + tags { + Name = "vpn_gateway" + } } resource "aws_customer_gateway" "customer_gateway" { - bgp_asn = 60000 - ip_address = "178.0.0.1" - type = "ipsec.1" + bgp_asn = 60000 + ip_address = "178.0.0.1" + type = "ipsec.1" } resource "aws_vpn_connection" "foo" { - vpn_gateway_id = "${aws_vpn_gateway.vpn_gateway.id}" - customer_gateway_id = "${aws_customer_gateway.customer_gateway.id}" - type = "ipsec.1" - static_routes_only = true + vpn_gateway_id = "${aws_vpn_gateway.vpn_gateway.id}" + customer_gateway_id = "${aws_customer_gateway.customer_gateway.id}" + type = "ipsec.1" + static_routes_only = true } ` // Change static_routes_only to be false, forcing a refresh. const testAccAwsVpnConnectionConfigUpdate = ` resource "aws_vpn_gateway" "vpn_gateway" { - tags { - Name = "vpn_gateway" - } + tags { + Name = "vpn_gateway" + } } resource "aws_customer_gateway" "customer_gateway" { - bgp_asn = 60000 - ip_address = "178.0.0.1" - type = "ipsec.1" + bgp_asn = 60000 + ip_address = "178.0.0.1" + type = "ipsec.1" } resource "aws_vpn_connection" "foo" { - vpn_gateway_id = "${aws_vpn_gateway.vpn_gateway.id}" - customer_gateway_id = "${aws_customer_gateway.customer_gateway.id}" - type = "ipsec.1" - static_routes_only = false + vpn_gateway_id = "${aws_vpn_gateway.vpn_gateway.id}" + customer_gateway_id = "${aws_customer_gateway.customer_gateway.id}" + type = "ipsec.1" + static_routes_only = false } ` + +// Test our VPN tunnel config XML parsing +const testAccAwsVpnTunnelInfoXML = ` + + + + + SECOND_ADDRESS + + + + SECOND_KEY + + + + + + FIRST_ADDRESS + + + + FIRST_KEY + + + +` diff --git a/website/source/docs/providers/aws/r/vpn_connection.html.markdown b/website/source/docs/providers/aws/r/vpn_connection.html.markdown index b28edc89f99d..841d7a545eb0 100644 --- a/website/source/docs/providers/aws/r/vpn_connection.html.markdown +++ b/website/source/docs/providers/aws/r/vpn_connection.html.markdown @@ -15,24 +15,24 @@ Provides a VPN connection connected to a VPC. These objects can be connected to ``` resource "aws_vpc" "vpc" { - cidr_block = "10.0.0.0/16" + cidr_block = "10.0.0.0/16" } resource "aws_vpn_gateway" "vpn_gateway" { - vpc_id = "${aws_vpc.vpc.id}" + vpc_id = "${aws_vpc.vpc.id}" } resource "aws_customer_gateway" "customer_gateway" { - bgp_asn = 60000 - ip_address = "172.0.0.1" - type = "ipsec.1" + bgp_asn = 60000 + ip_address = "172.0.0.1" + type = "ipsec.1" } resource "aws_vpn_connection" "main" { - vpn_gateway_id = "${aws_vpn_gateway.vpn_gateway.id}" - customer_gateway_id = "${aws_customer_gateway.customer_gateway.id}" - type = "ipsec.1" - static_routes_only = true + vpn_gateway_id = "${aws_vpn_gateway.vpn_gateway.id}" + customer_gateway_id = "${aws_customer_gateway.customer_gateway.id}" + type = "ipsec.1" + static_routes_only = true } ``` @@ -55,5 +55,9 @@ The following attributes are exported: * `customer_gateway_id` - The ID of the customer gateway to which the connection is attached. * `static_routes_only` - Whether the VPN connection uses static routes exclusively. * `tags` - Tags applied to the connection. +* `tunnel1_address` - The public IP address of the first VPN tunnel. +* `tunnel1_preshared_key` - The preshared key of the first VPN tunnel. +* `tunnel2_address` - The public IP address of the second VPN tunnel. +* `tunnel2_preshared_key` - The preshared key of the second VPN tunnel. * `type` - The type of VPN connection. * `vpn_gateway_id` - The ID of the virtual private gateway to which the connection is attached.