Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vpnaas: Create IPSec Policy #768

Merged
merged 14 commits into from
Feb 22, 2018
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// +build acceptance networking vpnaas

package vpnaas

import (
"testing"

"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
)

func TestPolicyCRUD(t *testing.T) {
client, err := clients.NewNetworkV2Client()
if err != nil {
t.Fatalf("Unable to create a network client: %v", err)
}

policy, err := CreateIPSecPolicy(t, client)
if err != nil {
t.Fatalf("Unable to create policy: %v", err)
}

tools.PrintResource(t, policy)
}
22 changes: 22 additions & 0 deletions acceptance/openstack/networking/v2/extensions/vpnaas/vpnaas.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/vpnaas/ipsecpolicies"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/vpnaas/services"
)

Expand Down Expand Up @@ -44,3 +45,24 @@ func DeleteService(t *testing.T, client *gophercloud.ServiceClient, serviceID st

t.Logf("Service deleted: %s", serviceID)
}

// CreateIPSecPolicy will create an IPSec Policy with a random name and given
// rule. An error will be returned if the rule could not be created.
func CreateIPSecPolicy(t *testing.T, client *gophercloud.ServiceClient) (*ipsecpolicies.Policy, error) {
policyName := tools.RandomString("TESTACC-", 8)

t.Logf("Attempting to create policy %s", policyName)

createOpts := ipsecpolicies.CreateOpts{
Name: policyName,
}

policy, err := ipsecpolicies.Create(client, createOpts).Extract()
if err != nil {
return policy, err
}

t.Logf("Successfully created IPSec policy %s", policyName)

return policy, nil
}
16 changes: 16 additions & 0 deletions openstack/networking/v2/extensions/vpnaas/ipsecpolicies/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
Package ipsecpolicies allows management and retrieval of IPSec Policies in the
OpenStack Networking Service.

Example to Create a Policy

createOpts := ipsecpolicies.CreateOpts{
Name: "IPSecPolicy_1",
}

policy, err := policies.Create(networkClient, createOpts).Extract()
if err != nil {
panic(err)
}
*/
package ipsecpolicies
110 changes: 110 additions & 0 deletions openstack/networking/v2/extensions/vpnaas/ipsecpolicies/requests.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package ipsecpolicies

import "github.com/gophercloud/gophercloud"

type TransformProtocol string
type AuthAlgorithm string
type EncapsulationMode string
type EncryptionAlgorithm string
type PFS string
type Unit string

const (
TransformProtocolESP TransformProtocol = "esp"
TransformProtocolAH TransformProtocol = "ah"
TransformProtocolAHESP TransformProtocol = "ah-esp"
AuthAlgorithmSHA1 AuthAlgorithm = "sha1"
AuthAlgorithmSHA256 AuthAlgorithm = "sha256"
AuthAlgorithmSHA384 AuthAlgorithm = "sha384"
AuthAlgorithmSHA512 AuthAlgorithm = "sha512"
EncryptionAlgorithm3DES EncryptionAlgorithm = "3des"
EncryptionAlgorithmAES128 EncryptionAlgorithm = "aes-128"
EncryptionAlgorithmAES256 EncryptionAlgorithm = "aes-256"
EncryptionAlgorithmAES192 EncryptionAlgorithm = "aes-192"
EncapsulationModeTunnel EncapsulationMode = "tunnel"
EncapsulationModeTransport EncapsulationMode = "transport"
UnitSeconds Unit = "seconds"
UnitKilobytes Unit = "kilobytes"
PFSGroup2 PFS = "group2"
PFSGroup5 PFS = "group5"
PFSGroup14 PFS = "group14"
)

// CreateOptsBuilder allows extensions to add additional parameters to the
// Create request.
type CreateOptsBuilder interface {
ToPolicyCreateMap() (map[string]interface{}, error)
}

// CreateOpts contains all the values needed to create a new IPSec policy
type CreateOpts struct {
// TenantID specifies a tenant to own the IPSec policy. The caller must have
// an admin role in order to set this. Otherwise, this field is left unset
// and the caller will be the owner.
TenantID string `json:"tenant_id,omitempty"`

// Description is the human readable description of the policy.
Description string `json:"description,omitempty"`

// Name is the human readable name of the policy.
// Does not have to be unique.
Name string `json:"name,omitempty"`

// AuthAlgorithm is the authentication hash algorithm.
// Valid values are sha1, sha256, sha384, sha512.
// The default is sha1.
AuthAlgorithm AuthAlgorithm `json:"auth_algorithm,omitempty"`

// EncapsulationMode is the encapsulation mode.
// A valid value is tunnel or transport.
// Default is tunnel.
EncapsulationMode EncapsulationMode `json:"encapsulation_mode,omitempty"`

// EncryptionAlgorithm is the encryption algorithm.
// A valid value is 3des, aes-128, aes-192, aes-256, and so on.
// Default is aes-128.
EncryptionAlgorithm EncryptionAlgorithm `json:"encryption_algorithm,omitempty"`

// PFS is the Perfect forward secrecy mode.
// A valid value is Group2, Group5, Group14, and so on.
// Default is Group5.
PFS PFS `json:"pfs,omitempty"`

// TransformProtocol is the transform protocol.
// A valid value is ESP, AH, or AH- ESP.
// Default is ESP.
TransformProtocol TransformProtocol `json:"transform_protocol,omitempty"`

//Lifetime is the lifetime of the security association
Lifetime *LifetimeCreateOpts `json:"lifetime,omitempty"`
}

// The lifetime consists of a unit and integer value
// You can omit either the unit or value portion of the lifetime
type LifetimeCreateOpts struct {
// Units is the units for the lifetime of the security association
// Default unit is seconds
Units Unit `json:"units,omitempty"`

// The lifetime value.
// Must be a positive integer.
// Default value is 3600.
Value int `json:"value,omitempty"`
}

// ToPolicyCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToPolicyCreateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "ipsecpolicy")
}

// Create accepts a CreateOpts struct and uses the values to create a new
// IPSec policy
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
b, err := opts.ToPolicyCreateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
return
}
67 changes: 67 additions & 0 deletions openstack/networking/v2/extensions/vpnaas/ipsecpolicies/results.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package ipsecpolicies

import (
"github.com/gophercloud/gophercloud"
)

// Policy is an IPSec Policy
type Policy struct {
// TenantID is the ID of the project
TenantID string `json:"tenant_id"`

// Description is the human readable description of the policy
Description string `json:"description"`

// Name is the human readable name of the policy
Name string `json:"name"`

// AuthAlgorithm is the authentication hash algorithm
AuthAlgorithm string `json:"auth_algorithm"`

// EncapsulationMode is the encapsulation mode
EncapsulationMode string `json:"encapsulation_mode"`

// EncryptionAlgorithm is the encryption algorithm
EncryptionAlgorithm string `json:"encryption_algorithm"`

// PFS is the Perfect forward secrecy (PFS) mode
PFS string `json:"pfs"`

// TransformProtocol is the transform protocol
TransformProtocol string `json:"transform_protocol"`

// Lifetime is the lifetime of the security association
Lifetime Lifetime `json:"lifetime"`

// ID is the ID of the policy
ID string `json:"id"`
}

type Lifetime struct {
// Units is the unit for the lifetime
// Default is seconds
Units string `json:"units"`

// Value is the lifetime
// Default is 3600
Value int `json:"value"`
}

type commonResult struct {
gophercloud.Result
}

// Extract is a function that accepts a result and extracts an IPSec Policy.
func (r commonResult) Extract() (*Policy, error) {
var s struct {
Policy *Policy `json:"ipsecpolicy"`
}
err := r.ExtractInto(&s)
return s.Policy, err
}

// CreateResult represents the result of a create operation. Call its Extract
// method to interpret it as a Policy.
type CreateResult struct {
commonResult
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package testing

import (
"fmt"
"net/http"
"testing"

fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/vpnaas/ipsecpolicies"
th "github.com/gophercloud/gophercloud/testhelper"
)

func TestCreate(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()

th.Mux.HandleFunc("/v2.0/vpn/ipsecpolicies", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "POST")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
th.TestHeader(t, r, "Content-Type", "application/json")
th.TestHeader(t, r, "Accept", "application/json")
th.TestJSONRequest(t, r, `
{
"ipsecpolicy": {
"name": "ipsecpolicy1",
"transform_protocol": "esp",
"auth_algorithm": "sha1",
"encapsulation_mode": "tunnel",
"encryption_algorithm": "aes-128",
"pfs": "group5",
"lifetime": {
"units": "seconds",
"value": 7200
},
"tenant_id": "b4eedccc6fb74fa8a7ad6b08382b852b"
}
} `)

w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)

fmt.Fprintf(w, `
{
"ipsecpolicy": {
"name": "ipsecpolicy1",
"transform_protocol": "esp",
"auth_algorithm": "sha1",
"encapsulation_mode": "tunnel",
"encryption_algorithm": "aes-128",
"pfs": "group5",
"tenant_id": "b4eedccc6fb74fa8a7ad6b08382b852b",
"lifetime": {
"units": "seconds",
"value": 7200
},
"id": "5291b189-fd84-46e5-84bd-78f40c05d69c",
"description": ""
}
}
`)
})

lifetime := ipsecpolicies.LifetimeCreateOpts{
Units: ipsecpolicies.UnitSeconds,
Value: 7200,
}
options := ipsecpolicies.CreateOpts{
TenantID: "b4eedccc6fb74fa8a7ad6b08382b852b",
Name: "ipsecpolicy1",
TransformProtocol: ipsecpolicies.TransformProtocolESP,
AuthAlgorithm: ipsecpolicies.AuthAlgorithmSHA1,
EncapsulationMode: ipsecpolicies.EncapsulationModeTunnel,
EncryptionAlgorithm: ipsecpolicies.EncryptionAlgorithmAES128,
PFS: ipsecpolicies.PFSGroup5,
Lifetime: &lifetime,
Description: "",
}
actual, err := ipsecpolicies.Create(fake.ServiceClient(), options).Extract()
th.AssertNoErr(t, err)
expectedLifetime := ipsecpolicies.Lifetime{
Units: "seconds",
Value: 7200,
}
expected := ipsecpolicies.Policy{
TenantID: "b4eedccc6fb74fa8a7ad6b08382b852b",
Name: "ipsecpolicy1",
TransformProtocol: "esp",
AuthAlgorithm: "sha1",
EncapsulationMode: "tunnel",
EncryptionAlgorithm: "aes-128",
PFS: "group5",
Description: "",
Lifetime: expectedLifetime,
ID: "5291b189-fd84-46e5-84bd-78f40c05d69c",
}
th.AssertDeepEquals(t, expected, *actual)
}
16 changes: 16 additions & 0 deletions openstack/networking/v2/extensions/vpnaas/ipsecpolicies/urls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ipsecpolicies

import "github.com/gophercloud/gophercloud"

const (
rootPath = "vpn"
resourcePath = "ipsecpolicies"
)

func rootURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL(rootPath, resourcePath)
}

func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(rootPath, resourcePath, id)
}