From c48063bb191d5e0422e921d5446b17168e4c5d16 Mon Sep 17 00:00:00 2001 From: Oskar Date: Fri, 21 Oct 2022 21:42:39 +0200 Subject: [PATCH] Enable USG/UDM radius server (#214) * Enable built-in radius server settings * Adding documentation * Update docs with new generator Co-authored-by: Paul Tyng --- docs/resources/setting_radius.md | 33 ++++ internal/provider/lazy_client.go | 12 ++ internal/provider/provider.go | 8 +- internal/provider/resource_setting_radius.go | 173 ++++++++++++++++++ .../provider/resource_setting_radius_test.go | 144 +++++++++++++++ internal/provider/resource_wlan_test.go | 9 +- 6 files changed, 373 insertions(+), 6 deletions(-) create mode 100644 docs/resources/setting_radius.md create mode 100644 internal/provider/resource_setting_radius.go create mode 100644 internal/provider/resource_setting_radius_test.go diff --git a/docs/resources/setting_radius.md b/docs/resources/setting_radius.md new file mode 100644 index 0000000..73824c7 --- /dev/null +++ b/docs/resources/setting_radius.md @@ -0,0 +1,33 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "unifi_setting_radius Resource - terraform-provider-unifi" +subcategory: "" +description: |- + unifi_setting_radius manages settings for the built-in RADIUS server. +--- + +# unifi_setting_radius (Resource) + +`unifi_setting_radius` manages settings for the built-in RADIUS server. + + + + +## Schema + +### Optional + +- `accounting_enabled` (Boolean) Enable RADIUS accounting Defaults to `false`. +- `accounting_port` (Number) The port for accounting communications. Defaults to `1813`. +- `auth_port` (Number) The port for authentication communications. Defaults to `1812`. +- `enabled` (Boolean) RAIDUS server enabled. Defaults to `true`. +- `interim_update_interval` (Number) Statistics will be collected from connected clients at this interval. Defaults to `3600`. +- `secret` (String, Sensitive) RAIDUS secret passphrase. Defaults to ``. +- `site` (String) The name of the site to associate the settings with. +- `tunneled_reply` (Boolean) Encrypt communication between the server and the client. Defaults to `true`. + +### Read-Only + +- `id` (String) The ID of the settings. + + diff --git a/internal/provider/lazy_client.go b/internal/provider/lazy_client.go index 5c5d86b..aa67acb 100644 --- a/internal/provider/lazy_client.go +++ b/internal/provider/lazy_client.go @@ -528,3 +528,15 @@ func (c *lazyClient) UpdateSettingUsg(ctx context.Context, site string, d *unifi } return c.inner.UpdateSettingUsg(ctx, site, d) } +func (c *lazyClient) GetSettingRadius(ctx context.Context, site string) (*unifi.SettingRadius, error) { + if err := c.init(ctx); err != nil { + return nil, err + } + return c.inner.GetSettingRadius(ctx, site) +} +func (c *lazyClient) UpdateSettingRadius(ctx context.Context, site string, d *unifi.SettingRadius) (*unifi.SettingRadius, error) { + if err := c.init(ctx); err != nil { + return nil, err + } + return c.inner.UpdateSettingRadius(ctx, site, d) +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index b95b5c2..f131f11 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -91,8 +91,9 @@ func New(version string) func() *schema.Provider { "unifi_user": resourceUser(), "unifi_wlan": resourceWLAN(), - "unifi_setting_mgmt": resourceSettingMgmt(), - "unifi_setting_usg": resourceSettingUsg(), + "unifi_setting_mgmt": resourceSettingMgmt(), + "unifi_setting_usg": resourceSettingUsg(), + "unifi_setting_radius": resourceSettingRadius(), }, } @@ -213,6 +214,9 @@ type unifiClient interface { GetSettingUsg(ctx context.Context, id string) (*unifi.SettingUsg, error) UpdateSettingMgmt(ctx context.Context, site string, d *unifi.SettingMgmt) (*unifi.SettingMgmt, error) UpdateSettingUsg(ctx context.Context, site string, d *unifi.SettingUsg) (*unifi.SettingUsg, error) + + GetSettingRadius(ctx context.Context, id string) (*unifi.SettingRadius, error) + UpdateSettingRadius(ctx context.Context, site string, d *unifi.SettingRadius) (*unifi.SettingRadius, error) } type client struct { diff --git a/internal/provider/resource_setting_radius.go b/internal/provider/resource_setting_radius.go new file mode 100644 index 0000000..ef23f84 --- /dev/null +++ b/internal/provider/resource_setting_radius.go @@ -0,0 +1,173 @@ +package provider + +import ( + "context" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/paultyng/go-unifi/unifi" +) + +func resourceSettingRadius() *schema.Resource { + return &schema.Resource{ + Description: "`unifi_setting_radius` manages settings for the built-in RADIUS server.", + + CreateContext: resourceSettingRadiusCreate, + ReadContext: resourceSettingRadiusRead, + UpdateContext: resourceSettingRadiusUpdate, + DeleteContext: schema.NoopContext, + Importer: &schema.ResourceImporter{ + StateContext: importSiteAndID, + }, + + Schema: map[string]*schema.Schema{ + "id": { + Description: "The ID of the settings.", + Type: schema.TypeString, + Computed: true, + }, + "site": { + Description: "The name of the site to associate the settings with.", + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + }, + "accounting_enabled": { + Description: "Enable RADIUS accounting", + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "accounting_port": { + Description: "The port for accounting communications.", + Type: schema.TypeInt, + Optional: true, + Default: 1813, + ValidateFunc: validation.IsPortNumber, + }, + "auth_port": { + Description: "The port for authentication communications.", + Type: schema.TypeInt, + Optional: true, + Default: 1812, + ValidateFunc: validation.IsPortNumber, + }, + "interim_update_interval": { + Description: "Statistics will be collected from connected clients at this interval.", + Type: schema.TypeInt, + Optional: true, + Default: 3600, + }, + "tunneled_reply": { + Description: "Encrypt communication between the server and the client.", + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "secret": { + Description: "RAIDUS secret passphrase.", + Type: schema.TypeString, + Sensitive: true, + Optional: true, + Default: "", + }, + "enabled": { + Description: "RAIDUS server enabled.", + Type: schema.TypeBool, + Default: true, + Optional: true, + }, + }, + } +} + +func resourceSettingRadiusGetResourceData(d *schema.ResourceData, meta interface{}) (*unifi.SettingRadius, error) { + return &unifi.SettingRadius{ + AccountingEnabled: d.Get("accounting_enabled").(bool), + Enabled: d.Get("enabled").(bool), + AcctPort: d.Get("accounting_port").(int), + AuthPort: d.Get("auth_port").(int), + ConfigureWholeNetwork: true, + TunneledReply: d.Get("tunneled_reply").(bool), + XSecret: d.Get("secret").(string), + InterimUpdateInterval: d.Get("interim_update_interval").(int), + }, nil +} + +func resourceSettingRadiusCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + c := meta.(*client) + + req, err := resourceSettingRadiusGetResourceData(d, meta) + if err != nil { + return diag.FromErr(err) + } + + site := d.Get("site").(string) + if site == "" { + site = c.site + } + + resp, err := c.c.UpdateSettingRadius(ctx, site, req) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(resp.ID) + + return resourceSettingRadiusSetResourceData(resp, d, meta, site) +} + +func resourceSettingRadiusSetResourceData(resp *unifi.SettingRadius, d *schema.ResourceData, meta interface{}, site string) diag.Diagnostics { + d.Set("site", site) + d.Set("enabled", resp.Enabled) + d.Set("accounting_enabled", resp.AccountingEnabled) + d.Set("accounting_port", resp.AcctPort) + d.Set("auth_port", resp.AuthPort) + d.Set("tunneled_reply", resp.TunneledReply) + d.Set("secret", resp.XSecret) + d.Set("interim_update_interval", resp.InterimUpdateInterval) + return nil +} + +func resourceSettingRadiusRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + c := meta.(*client) + + site := d.Get("site").(string) + if site == "" { + site = c.site + } + + resp, err := c.c.GetSettingRadius(ctx, site) + if _, ok := err.(*unifi.NotFoundError); ok { + d.SetId("") + return nil + } + if err != nil { + return diag.FromErr(err) + } + + return resourceSettingRadiusSetResourceData(resp, d, meta, site) +} + +func resourceSettingRadiusUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + c := meta.(*client) + + req, err := resourceSettingRadiusGetResourceData(d, meta) + if err != nil { + return diag.FromErr(err) + } + + req.ID = d.Id() + site := d.Get("site").(string) + if site == "" { + site = c.site + } + + resp, err := c.c.UpdateSettingRadius(ctx, site, req) + if err != nil { + return diag.FromErr(err) + } + + return resourceSettingRadiusSetResourceData(resp, d, meta, site) +} diff --git a/internal/provider/resource_setting_radius_test.go b/internal/provider/resource_setting_radius_test.go new file mode 100644 index 0000000..4b08ee9 --- /dev/null +++ b/internal/provider/resource_setting_radius_test.go @@ -0,0 +1,144 @@ +package provider + +import ( + "sync" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +var settingRadiusLock = sync.Mutex{} + +func TestAccSettingRadius_basic(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + preCheck(t) + settingRadiusLock.Lock() + t.Cleanup(func() { + settingRadiusLock.Unlock() + }) + }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccSettingRadiusConfig_basic(), + Check: resource.ComposeTestCheckFunc(), + }, + importStep("unifi_setting_radius.test"), + }, + }) +} + +func TestAccSettingRadius_site(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + preCheck(t) + settingRadiusLock.Lock() + t.Cleanup(func() { + settingRadiusLock.Unlock() + }) + }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccSettingRadiusConfig_site(), + Check: resource.ComposeTestCheckFunc(), + }, + { + ResourceName: "unifi_setting_radius.test", + ImportState: true, + ImportStateIdFunc: siteAndIDImportStateIDFunc("unifi_setting_radius.test"), + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSettingRadius_full(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + preCheck(t) + settingRadiusLock.Lock() + t.Cleanup(func() { + settingRadiusLock.Unlock() + }) + }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccSettingRadiusConfig_full(), + Check: resource.ComposeTestCheckFunc(), + }, + { + ResourceName: "unifi_setting_radius.test", + ImportState: true, + ImportStateIdFunc: siteAndIDImportStateIDFunc("unifi_setting_radius.test"), + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSettingRadius_vlan(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + preCheck(t) + settingRadiusLock.Lock() + t.Cleanup(func() { + settingRadiusLock.Unlock() + }) + }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: testAccSettingRadiusConfig_vlan(), + Check: resource.ComposeTestCheckFunc(), + }, + importStep("unifi_setting_radius.test"), + }, + }) +} + +func testAccSettingRadiusConfig_basic() string { + return ` +resource "unifi_setting_radius" "test" { + enabled = true + secret = "securepw" +} +` +} + +func testAccSettingRadiusConfig_site() string { + return ` +resource "unifi_site" "test" { + description = "test" +} + +resource "unifi_setting_radius" "test" { + site = unifi_site.test.name + enabled = true + secret = "securepw" +} +` +} + +func testAccSettingRadiusConfig_full() string { + return ` +resource "unifi_setting_radius" "test" { + enabled = true + secret = "securepw" + accounting_port = "9999" + auth_port = "8888" +} +` +} + +func testAccSettingRadiusConfig_vlan() string { + return ` +resource "unifi_setting_radius" "test" { + enabled = true + secret = "securepw" + accounting_enabled = true +} +` +} diff --git a/internal/provider/resource_wlan_test.go b/internal/provider/resource_wlan_test.go index 072b59b..6489308 100644 --- a/internal/provider/resource_wlan_test.go +++ b/internal/provider/resource_wlan_test.go @@ -184,10 +184,6 @@ func TestAccWLAN_schedule(t *testing.T) { } func TestAccWLAN_wpaeap(t *testing.T) { - if os.Getenv("UNIFI_TEST_RADIUS") == "" { - t.Skip("UNIFI_TEST_RADIUS not set, skipping RADIUS test") - } - vlanID := getTestVLAN(t) resource.ParallelTest(t, resource.TestCase{ @@ -429,6 +425,11 @@ data "unifi_user_group" "default" { data "unifi_radius_profile" "default" { } +resource "unifi_setting_radius" "this" { + enabled = true + secret = "securepw" +} + resource "unifi_network" "test" { name = "tfacc" purpose = "corporate"