From 8538a1d3fe36ea0bf086907cf526aaf39acb9ad8 Mon Sep 17 00:00:00 2001 From: chinthalapalli Date: Mon, 25 Sep 2023 20:33:49 +0530 Subject: [PATCH] ading cipher rules and cipher groups --- bigip/provider.go | 2 + bigip/resource_bigip_awaf_policy.go | 2 +- bigip/resource_bigip_ltm_cipher_group.go | 139 ++++++++++++++++++ bigip/resource_bigip_ltm_cipher_group_test.go | 76 ++++++++++ bigip/resource_bigip_ltm_cipher_rule.go | 130 ++++++++++++++++ bigip/resource_bigip_ltm_cipher_rule_test.go | 78 ++++++++++ .../github.com/f5devcentral/go-bigip/ltm.go | 81 ++++++++++ 7 files changed, 507 insertions(+), 1 deletion(-) create mode 100644 bigip/resource_bigip_ltm_cipher_group.go create mode 100644 bigip/resource_bigip_ltm_cipher_group_test.go create mode 100644 bigip/resource_bigip_ltm_cipher_rule.go create mode 100644 bigip/resource_bigip_ltm_cipher_rule_test.go diff --git a/bigip/provider.go b/bigip/provider.go index 8e5f21ee5..aa0312deb 100644 --- a/bigip/provider.go +++ b/bigip/provider.go @@ -165,6 +165,8 @@ func Provider() *schema.Provider { "bigip_ipsec_profile": resourceBigipIpsecProfile(), "bigip_waf_policy": resourceBigipAwafPolicy(), "bigip_vcmp_guest": resourceBigipVcmpGuest(), + "bigip_ltm_cipher_rule": resourceBigipLtmCipherRule(), + "bigip_ltm_cipher_group": resourceBigipLtmCipherGroup(), }, } p.ConfigureContextFunc = func(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) { diff --git a/bigip/resource_bigip_awaf_policy.go b/bigip/resource_bigip_awaf_policy.go index 063fbf6f7..f4604ad31 100644 --- a/bigip/resource_bigip_awaf_policy.go +++ b/bigip/resource_bigip_awaf_policy.go @@ -540,7 +540,7 @@ func getpolicyConfig(d *schema.ResourceData) (string, error) { fullPath = fmt.Sprintf("/%s/%s", partition, name) } var appLang1 string - appLang1 = "auto-detect" + appLang1 = "utf-8" if val, ok := d.GetOk("application_language"); ok { appLang1 = val.(string) } diff --git a/bigip/resource_bigip_ltm_cipher_group.go b/bigip/resource_bigip_ltm_cipher_group.go new file mode 100644 index 000000000..57ccf9ed7 --- /dev/null +++ b/bigip/resource_bigip_ltm_cipher_group.go @@ -0,0 +1,139 @@ +// Copyright 2023 F5 Networks Inc. +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + +package bigip + +import ( + "context" + "fmt" + bigip "github.com/f5devcentral/go-bigip" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "log" +) + +func resourceBigipLtmCipherGroup() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceBigipLtmCipherGroupCreate, + ReadContext: resourceBigipLtmCipherGroupRead, + UpdateContext: resourceBigipLtmCipherGroupUpdate, + DeleteContext: resourceBigipLtmCipherGroupDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: "Name of the cipher rule,name should be in pattern ``partition` + `cipher rule name``", + ForceNew: true, + ValidateFunc: validateF5Name, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies descriptive text that identifies the cipher rule", + }, + "ordering": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies one or more Cipher Suites used.Note: For SM2, type the following cipher suite string: ECC-SM4-SM3.", + }, + "allow": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Specifies the DH Groups Elliptic Curve Diffie-Hellman key exchange algorithms, separated by colons (:).Note: You can also type a special keyword, DEFAULT, which represents the recommended set of named groups", + }, + "require": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Specifies the DH Groups Elliptic Curve Diffie-Hellman key exchange algorithms, separated by colons (:).Note: You can also type a special keyword, DEFAULT, which represents the recommended set of named groups", + }, + }, + } +} + +func resourceBigipLtmCipherGroupCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*bigip.BigIP) + + name := d.Get("name").(string) + + log.Printf("[INFO] Creating Cipher rule:%+v", name) + + cipherGrouptmp := &bigip.CipherGroupReq{} + cipherGrouptmp.Name = name + cipherGroup, err := getCipherGroupConfig(d, cipherGrouptmp) + if err != nil { + return diag.FromErr(fmt.Errorf("reading input config failed(%s): %s", name, err)) + } + log.Printf("[INFO] cipherGroup config :%+v", cipherGroup) + err = client.AddLtmCipherGroup(cipherGroup) + if err != nil { + return diag.FromErr(fmt.Errorf("error creating cipher rule (%s): %s", name, err)) + } + d.SetId(name) + return resourceBigipLtmCipherGroupRead(ctx, d, meta) +} + +func resourceBigipLtmCipherGroupRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*bigip.BigIP) + name := d.Id() + log.Printf("[INFO] Fetching Cipher group :%+v", name) + + cipherRule, err := client.GetLtmCipherGroup(name) + if err != nil { + log.Printf("[ERROR] Unable to retrieve cipher rule %s %v :", name, err) + return diag.FromErr(err) + } + log.Printf("[INFO] Cipher rule response :%+v", cipherRule) + return nil +} + +func resourceBigipLtmCipherGroupUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*bigip.BigIP) + name := d.Id() + cipherGrouptmp := &bigip.CipherGroupReq{} + cipherGrouptmp.Name = name + cipherGroupconfig, err := getCipherGroupConfig(d, cipherGrouptmp) + if err != nil { + return diag.FromErr(fmt.Errorf("reading input config failed(%s): %s", name, err)) + } + if err := client.ModifyLtmCipherGroup(name, cipherGroupconfig); err != nil { + return diag.FromErr(fmt.Errorf("error modifying cipher group %s: %v", name, err)) + } + + return resourceBigipLtmCipherGroupRead(ctx, d, meta) +} + +func resourceBigipLtmCipherGroupDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*bigip.BigIP) + + name := d.Id() + log.Printf("[INFO] Deleting cipher group :%+v", name) + err := client.DeleteLtmCipherGroup(name) + + if err != nil { + log.Printf("[ERROR] Unable to Delete cipher rule %s %v : ", name, err) + return diag.FromErr(err) + } + d.SetId("") + return nil +} + +func getCipherGroupConfig(d *schema.ResourceData, cipherGroup *bigip.CipherGroupReq) (*bigip.CipherGroupReq, error) { + cipherGroup.Ordering = d.Get("ordering").(string) + if p, ok := d.GetOk("allow"); ok { + for _, r := range p.(*schema.Set).List() { + cipherGroup.Allow = append(cipherGroup.Allow, r.(string)) + } + } + if p, ok := d.GetOk("require"); ok { + for _, r := range p.(*schema.Set).List() { + cipherGroup.Require = append(cipherGroup.Require, r.(string)) + } + } + return cipherGroup, nil +} diff --git a/bigip/resource_bigip_ltm_cipher_group_test.go b/bigip/resource_bigip_ltm_cipher_group_test.go new file mode 100644 index 000000000..094c0a0da --- /dev/null +++ b/bigip/resource_bigip_ltm_cipher_group_test.go @@ -0,0 +1,76 @@ +/* +Original work from https://github.com/DealerDotCom/terraform-provider-bigip +Modifications Copyright 2019 F5 Networks Inc. +This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +If a copy of the MPL was not distributed with this file,You can obtain one at https://mozilla.org/MPL/2.0/. +*/ +package bigip + +import ( + "fmt" + "testing" + + bigip "github.com/f5devcentral/go-bigip" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +const testCipherGroupConfigTC1 = ` +resource "bigip_ltm_cipher_group" "test-cipher-group" { + name = "/Common/test-cipher-group-01" + //cipher = "aes" +} +` + +func TestAccBigipLtmCipherGroupCreateTC1(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAcctPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: testCheckCipherGroupDestroyed, + Steps: []resource.TestStep{ + { + Config: testCipherGroupConfigTC1, + Check: resource.ComposeTestCheckFunc( + testCheckCipherGroupExists("/Common/test-cipher-group-01"), + resource.TestCheckResourceAttr("bigip_ltm_cipher_group.test-cipher-group", "name", "/Common/test-cipher-group-01"), + ), + }, + }, + }) +} + +func testCheckCipherGroupExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := testAccProvider.Meta().(*bigip.BigIP) + + p, err := client.GetLtmCipherGroup(name) + if err != nil { + return err + } + if p == nil { + return fmt.Errorf("Pool %s does not exist ", name) + } + + return nil + } +} + +func testCheckCipherGroupDestroyed(s *terraform.State) error { + client := testAccProvider.Meta().(*bigip.BigIP) + for _, rs := range s.RootModule().Resources { + if rs.Type != "bigip_ltm_cipher_group" { + continue + } + name := rs.Primary.ID + pool, err := client.GetLtmCipherGroup(name) + if err != nil { + return err + } + if pool != nil { + return fmt.Errorf("Cipher rule %s not destroyed ", name) + } + } + return nil +} diff --git a/bigip/resource_bigip_ltm_cipher_rule.go b/bigip/resource_bigip_ltm_cipher_rule.go new file mode 100644 index 000000000..0b3e43bdd --- /dev/null +++ b/bigip/resource_bigip_ltm_cipher_rule.go @@ -0,0 +1,130 @@ +// Copyright 2023 F5 Networks Inc. +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + +package bigip + +import ( + "context" + "fmt" + bigip "github.com/f5devcentral/go-bigip" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "log" +) + +func resourceBigipLtmCipherRule() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceBigipLtmCipherRuleCreate, + ReadContext: resourceBigipLtmCipherRuleRead, + UpdateContext: resourceBigipLtmCipherRuleUpdate, + DeleteContext: resourceBigipLtmCipherRuleDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: "Name of the cipher rule,name should be in pattern ``partition` + `cipher rule name``", + ForceNew: true, + ValidateFunc: validateF5Name, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies descriptive text that identifies the cipher rule", + }, + "cipher": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies one or more Cipher Suites used.Note: For SM2, type the following cipher suite string: ECC-SM4-SM3.", + }, + "dh_groups": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the DH Groups Elliptic Curve Diffie-Hellman key exchange algorithms, separated by colons (:).Note: You can also type a special keyword, DEFAULT, which represents the recommended set of named groups", + }, + "signature_algorithms": { + Type: schema.TypeString, + Optional: true, + Description: "Specifies the Signature Algorithms, separated by colons (:), that you want to include in the cipher rule. You can also type a special keyword, DEFAULT, which represents the recommended set of signature algorithms", + }, + }, + } +} + +func resourceBigipLtmCipherRuleCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*bigip.BigIP) + + name := d.Get("name").(string) + + log.Printf("[INFO] Creating Cipher rule:%+v", name) + + cipherRuletmp := &bigip.CipherRuleReq{} + cipherRuletmp.Name = name + cipherRule, err := getCipherRuleConfig(d, cipherRuletmp) + if err != nil { + return diag.FromErr(fmt.Errorf("reading input config failed(%s): %s", name, err)) + } + log.Printf("[INFO] cipherRule config :%+v", cipherRule) + err = client.AddLtmCipherRule(cipherRule) + if err != nil { + return diag.FromErr(fmt.Errorf("error creating cipher rule (%s): %s", name, err)) + } + d.SetId(name) + return resourceBigipLtmCipherRuleRead(ctx, d, meta) +} + +func resourceBigipLtmCipherRuleRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*bigip.BigIP) + name := d.Id() + log.Printf("[INFO] Fetching Cipher rule :%+v", name) + + cipherRule, err := client.GetLtmCipherRule(name) + if err != nil { + log.Printf("[ERROR] Unable to retrieve cipher rule %s %v :", name, err) + return diag.FromErr(err) + } + log.Printf("[INFO] Cipher rule response :%+v", cipherRule) + return nil +} + +func resourceBigipLtmCipherRuleUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*bigip.BigIP) + name := d.Id() + cipherRuletmp := &bigip.CipherRuleReq{} + cipherRuletmp.Name = name + cipheRuleconfig, err := getCipherRuleConfig(d, cipherRuletmp) + if err != nil { + return diag.FromErr(fmt.Errorf("reading input config failed(%s): %s", name, err)) + } + if err := client.ModifyLtmCipherRule(name, cipheRuleconfig); err != nil { + return diag.FromErr(fmt.Errorf("error modifying cipher rule %s: %v", name, err)) + } + + return resourceBigipLtmCipherRuleRead(ctx, d, meta) +} + +func resourceBigipLtmCipherRuleDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*bigip.BigIP) + + name := d.Id() + log.Printf("[INFO] Deleting cipher rule :%+v", name) + err := client.DeleteLtmCipherRule(name) + + if err != nil { + log.Printf("[ERROR] Unable to Delete cipher rule %s %v : ", name, err) + return diag.FromErr(err) + } + d.SetId("") + return nil +} + +func getCipherRuleConfig(d *schema.ResourceData, cipherRule *bigip.CipherRuleReq) (*bigip.CipherRuleReq, error) { + cipherRule.Cipher = d.Get("cipher").(string) + cipherRule.DhGroups = d.Get("dh_groups").(string) + cipherRule.SignatureAlgorithms = d.Get("signature_algorithms").(string) + cipherRule.Description = d.Get("description").(string) + return cipherRule, nil +} diff --git a/bigip/resource_bigip_ltm_cipher_rule_test.go b/bigip/resource_bigip_ltm_cipher_rule_test.go new file mode 100644 index 000000000..851979104 --- /dev/null +++ b/bigip/resource_bigip_ltm_cipher_rule_test.go @@ -0,0 +1,78 @@ +/* +Original work from https://github.com/DealerDotCom/terraform-provider-bigip +Modifications Copyright 2019 F5 Networks Inc. +This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +If a copy of the MPL was not distributed with this file,You can obtain one at https://mozilla.org/MPL/2.0/. +*/ +package bigip + +import ( + "fmt" + "testing" + + bigip "github.com/f5devcentral/go-bigip" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +const testCipherRuleConfigTC1 = ` +resource "bigip_ltm_cipher_rule" "test-cipher-rule" { + name = "/Common/test-cipher-rule" + cipher = "aes" +} +` + +func TestAccBigipLtmCipherRuleCreateTC1(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAcctPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: testCheckCipherRuleDestroyed, + Steps: []resource.TestStep{ + { + Config: testCipherRuleConfigTC1, + Check: resource.ComposeTestCheckFunc( + testCheckCipherRuleExists("/Common/test-cipher-rule"), + resource.TestCheckResourceAttr("bigip_ltm_cipher_rule.test-cipher-rule", "name", "/Common/test-cipher-rule"), + ), + }, + }, + }) +} + +func testCheckCipherRuleExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := testAccProvider.Meta().(*bigip.BigIP) + + p, err := client.GetLtmCipherRule(name) + if err != nil { + return err + } + if p == nil { + return fmt.Errorf("Pool %s does not exist ", name) + } + + return nil + } +} + +func testCheckCipherRuleDestroyed(s *terraform.State) error { + client := testAccProvider.Meta().(*bigip.BigIP) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "bigip_ltm_cipher_rule" { + continue + } + + name := rs.Primary.ID + pool, err := client.GetLtmCipherRule(name) + if err != nil { + return err + } + if pool != nil { + return fmt.Errorf("Cipher rule %s not destroyed ", name) + } + } + return nil +} diff --git a/vendor/github.com/f5devcentral/go-bigip/ltm.go b/vendor/github.com/f5devcentral/go-bigip/ltm.go index b0e626d57..96389a5ed 100644 --- a/vendor/github.com/f5devcentral/go-bigip/ltm.go +++ b/vendor/github.com/f5devcentral/go-bigip/ltm.go @@ -1892,6 +1892,7 @@ const ( uriPool = "pool" uriPoolMember = "members" uriProfile = "profile" + uriCipher = "cipher" uriServerSSL = "server-ssl" uriClientSSL = "client-ssl" uriVirtual = "virtual" @@ -3918,3 +3919,83 @@ func (b *BigIP) DeleteHttpCompressionProfile(name string) error { func (b *BigIP) ModifyHttpCompressionProfile(name string, config *HttpCompressionProfile) error { return b.put(config, uriLtm, uriProfile, uriHttpcompress, name) } + +type CipherRuleReq struct { + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Cipher string `json:"cipher,omitempty"` + Description string `json:"description,omitempty"` + DhGroups string `json:"dhGroups,omitempty"` + SignatureAlgorithms string `json:"signatureAlgorithms,omitempty"` +} + +func (b *BigIP) AddLtmCipherRule(config *CipherRuleReq) error { + return b.post(config, uriLtm, uriCipher, "rule") +} + +func (b *BigIP) ModifyLtmCipherRule(name string, config *CipherRuleReq) error { + return b.put(config, uriLtm, uriCipher, "rule", name) +} + +func (b *BigIP) DeleteLtmCipherRule(name string) error { + return b.delete(uriLtm, uriCipher, "rule", name) +} + +func (b *BigIP) GetLtmCipherRule(name string) (*CipherRuleReq, error) { + var cipherRule CipherRuleReq + err, ok := b.getForEntity(&cipherRule, uriLtm, uriCipher, "rule", name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &cipherRule, nil +} + +// +//type PolicyRule struct { +//Name string `json:"name,omitempty"` +//Partition string `json:"partition,omitempty"` +//NameReference struct { +//Link string `json:"link,omitempty"` +//} `json:"nameReference,omitempty"` +//} + +type CipherGroupReq struct { + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Ordering string `json:"ordering,omitempty"` + Allow []interface{} `json:"allow,omitempty"` + Require []interface{} `json:"require,omitempty"` +} + +func (b *BigIP) AddLtmCipherGroup(config *CipherGroupReq) error { + return b.post(config, uriLtm, uriCipher, "group") +} + +func (b *BigIP) ModifyLtmCipherGroup(name string, config *CipherGroupReq) error { + return b.put(config, uriLtm, uriCipher, "group", name) +} + +func (b *BigIP) DeleteLtmCipherGroup(name string) error { + return b.delete(uriLtm, uriCipher, "group", name) +} + +func (b *BigIP) GetLtmCipherGroup(name string) (*CipherGroupReq, error) { + var cipherGroup CipherGroupReq + err, ok := b.getForEntity(&cipherGroup, uriLtm, uriCipher, "group", name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &cipherGroup, nil +}