diff --git a/cloudconnexa/cloudconnexa.go b/cloudconnexa/cloudconnexa.go index ececde8..f50ef3b 100644 --- a/cloudconnexa/cloudconnexa.go +++ b/cloudconnexa/cloudconnexa.go @@ -44,6 +44,7 @@ type Client struct { VPNRegions *VPNRegionsService LocationContexts *LocationContextsService AccessGroups *AccessGroupsService + Settings *SettingsService } type service struct { @@ -134,9 +135,22 @@ func NewClient(baseURL, clientID, clientSecret string) (*Client, error) { c.VPNRegions = (*VPNRegionsService)(&c.common) c.LocationContexts = (*LocationContextsService)(&c.common) c.AccessGroups = (*AccessGroupsService)(&c.common) + c.Settings = (*SettingsService)(&c.common) return c, nil } +// setCommonHeaders sets the standard headers for API requests. +// It sets Authorization and User-Agent headers, and sets Content-Type to application/json +// if no Content-Type header is already present. +func (c *Client) setCommonHeaders(req *http.Request) { + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.Token)) + req.Header.Set("User-Agent", c.UserAgent) + + if req.Header.Get("Content-Type") == "" { + req.Header.Set("Content-Type", "application/json") + } +} + // DoRequest executes an HTTP request with authentication and rate limiting. // It automatically adds the Bearer token, sets headers, and handles errors. func (c *Client) DoRequest(req *http.Request) ([]byte, error) { @@ -145,9 +159,7 @@ func (c *Client) DoRequest(req *http.Request) ([]byte, error) { return nil, err } - req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.Token)) - req.Header.Set("User-Agent", c.UserAgent) - req.Header.Set("Content-Type", "application/json") + c.setCommonHeaders(req) res, err := c.client.Do(req) if err != nil { diff --git a/cloudconnexa/settings.go b/cloudconnexa/settings.go new file mode 100644 index 0000000..a14a0bf --- /dev/null +++ b/cloudconnexa/settings.go @@ -0,0 +1,449 @@ +package cloudconnexa + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "strconv" +) + +// DNSServers represents DNS server configuration with primary and secondary IPv4 addresses +type DNSServers struct { + PrimaryIPV4 string `json:"primaryIpV4,omitempty"` + SecondaryIPV4 string `json:"secondaryIpV4,omitempty"` +} + +// DNSZones represents a collection of DNS zones +type DNSZones struct { + Zones []DNSZone `json:"zones"` +} + +// DNSZone represents a single DNS zone with name and associated addresses +type DNSZone struct { + Name string `json:"name"` + Addresses []string `json:"addresses"` +} + +// DomainRoutingSubnet represents subnet configuration for domain routing with IPv4 and IPv6 addresses +type DomainRoutingSubnet struct { + IPV4Address string `json:"ipV4Address"` + IPV6Address string `json:"ipV6Address"` +} + +// Subnet represents network subnet configuration with IPv4 and IPv6 address ranges +type Subnet struct { + IPV4Address []string `json:"ipV4Address"` + IPV6Address []string `json:"ipV6Address"` +} + +// SettingsService handles operations related to system settings +type SettingsService service + +// GetTrustedDevicesAllowed retrieves whether trusted devices are allowed +func (c *SettingsService) GetTrustedDevicesAllowed() (bool, error) { + return c.getBool("/auth/trusted-devices-allowed") +} + +// SetTrustedDevicesAllowed sets whether trusted devices are allowed +func (c *SettingsService) SetTrustedDevicesAllowed(value bool) (bool, error) { + return c.setBool("/auth/trusted-devices-allowed", value) +} + +// GetTwoFactorAuthEnabled retrieves whether two-factor authentication is enabled +func (c *SettingsService) GetTwoFactorAuthEnabled() (bool, error) { + return c.getBool("/auth/two-factor-auth") +} + +// SetTwoFactorAuthEnabled sets whether two-factor authentication is enabled +func (c *SettingsService) SetTwoFactorAuthEnabled(value bool) (bool, error) { + return c.setBool("/auth/two-factor-auth", value) +} + +// GetDNSServers retrieves the current DNS server configuration +func (c *SettingsService) GetDNSServers() (*DNSServers, error) { + body, err := c.get("/dns/custom-servers") + if err != nil { + return nil, err + } + + var response DNSServers + s := string(body) + if s == "" { + return nil, nil + } + + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + return &response, nil +} + +// SetDNSServers updates the DNS server configuration +func (c *SettingsService) SetDNSServers(value *DNSServers) (*DNSServers, error) { + jsonValue, err := json.Marshal(value) + if err != nil { + return nil, err + } + body, err := c.set("/dns/custom-servers", jsonValue) + if err != nil { + return nil, err + } + var response DNSServers + s := string(body) + if s == "" { + return nil, nil + } + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + return &response, nil +} + +// GetDefaultDNSSuffix retrieves the default DNS suffix +func (c *SettingsService) GetDefaultDNSSuffix() (string, error) { + return c.getString("/dns/default-suffix") +} + +// SetDefaultDNSSuffix sets the default DNS suffix +func (c *SettingsService) SetDefaultDNSSuffix(value string) (string, error) { + return c.setString("/dns/default-suffix", value) +} + +// GetDNSProxyEnabled retrieves whether DNS proxy is enabled +func (c *SettingsService) GetDNSProxyEnabled() (bool, error) { + return c.getBool("/dns/proxy-enabled") +} + +// SetDNSProxyEnabled sets whether DNS proxy is enabled +func (c *SettingsService) SetDNSProxyEnabled(value bool) (bool, error) { + return c.setBool("/dns/proxy-enabled", value) +} + +// GetDNSZones retrieves the current DNS zones configuration +func (c *SettingsService) GetDNSZones() ([]DNSZone, error) { + body, err := c.get("/dns/zones") + if err != nil { + return nil, err + } + + var response DNSZones + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + return response.Zones, nil +} + +// SetDNSZones updates the DNS zones configuration +func (c *SettingsService) SetDNSZones(value []DNSZone) ([]DNSZone, error) { + jsonValue, err := json.Marshal(value) + if err != nil { + return nil, err + } + body, err := c.set("/dns/zones", jsonValue) + if err != nil { + return nil, err + } + var response DNSZones + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + return response.Zones, nil +} + +// GetDefaultConnectAuth retrieves the default connection authentication method +func (c *SettingsService) GetDefaultConnectAuth() (string, error) { + return c.getString("/user/connect-auth") +} + +// SetDefaultConnectAuth sets the default connection authentication method +func (c *SettingsService) SetDefaultConnectAuth(value string) (string, error) { + return c.setString("/user/connect-auth", value) +} + +// GetDefaultDeviceAllowancePerUser retrieves the default device allowance per user +func (c *SettingsService) GetDefaultDeviceAllowancePerUser() (int, error) { + return c.getInt("/user/device-allowance") +} + +// SetDefaultDeviceAllowancePerUser sets the default device allowance per user +func (c *SettingsService) SetDefaultDeviceAllowancePerUser(value int) (int, error) { + return c.setInt("/user/device-allowance", value) +} + +// GetForceUpdateDeviceAllowanceEnabled retrieves whether force update device allowance is enabled +func (c *SettingsService) GetForceUpdateDeviceAllowanceEnabled() (bool, error) { + return c.getBool("/user/device-allowance-force-update") +} + +// SetForceUpdateDeviceAllowanceEnabled sets whether force update device allowance is enabled +func (c *SettingsService) SetForceUpdateDeviceAllowanceEnabled(value bool) (bool, error) { + return c.setBool("/user/device-allowance-force-update", value) +} + +// GetDeviceEnforcement retrieves the device enforcement policy +func (c *SettingsService) GetDeviceEnforcement() (string, error) { + return c.getString("/user/device-enforcement") +} + +// SetDeviceEnforcement sets the device enforcement policy +func (c *SettingsService) SetDeviceEnforcement(value string) (string, error) { + return c.setString("/user/device-enforcement", value) +} + +// GetProfileDistribution retrieves the profile distribution method +func (c *SettingsService) GetProfileDistribution() (string, error) { + return c.getString("/user/profile-distribution") +} + +// SetProfileDistribution sets the profile distribution method +func (c *SettingsService) SetProfileDistribution(value string) (string, error) { + return c.setString("/user/profile-distribution", value) +} + +// GetConnectionTimeout retrieves the connection timeout value +func (c *SettingsService) GetConnectionTimeout() (int, error) { + return c.getInt("/users/connection-timeout") +} + +// SetConnectionTimeout sets the connection timeout value +func (c *SettingsService) SetConnectionTimeout(value int) (int, error) { + return c.setInt("/users/connection-timeout", value) +} + +// GetClientOptions retrieves the client options configuration +func (c *SettingsService) GetClientOptions() ([]string, error) { + body, err := c.get("/wpc/client-options") + if err != nil { + return nil, err + } + + var response []string + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + return response, nil +} + +// SetClientOptions updates the client options configuration +func (c *SettingsService) SetClientOptions(value []string) ([]string, error) { + jsonValue, err := json.Marshal(value) + if err != nil { + return nil, err + } + body, err := c.set("/wpc/client-options", jsonValue) + if err != nil { + return nil, err + } + var response []string + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + return response, nil +} + +// GetDefaultRegion retrieves the default region setting +func (c *SettingsService) GetDefaultRegion() (string, error) { + return c.getString("/wpc/default-region") +} + +// SetDefaultRegion sets the default region +func (c *SettingsService) SetDefaultRegion(value string) (string, error) { + return c.setString("/wpc/default-region", value) +} + +// GetDomainRoutingSubnet retrieves the domain routing subnet configuration +func (c *SettingsService) GetDomainRoutingSubnet() (*DomainRoutingSubnet, error) { + body, err := c.get("/wpc/domain-routing-subnet") + if err != nil { + return nil, err + } + + var response DomainRoutingSubnet + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + return &response, nil +} + +// SetDomainRoutingSubnet updates the domain routing subnet configuration +func (c *SettingsService) SetDomainRoutingSubnet(value DomainRoutingSubnet) (*DomainRoutingSubnet, error) { + jsonValue, err := json.Marshal(value) + if err != nil { + return nil, err + } + body, err := c.set("/wpc/domain-routing-subnet", jsonValue) + if err != nil { + return nil, err + } + var response DomainRoutingSubnet + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + return &response, nil +} + +// GetSnatEnabled retrieves whether SNAT is enabled +func (c *SettingsService) GetSnatEnabled() (bool, error) { + return c.getBool("/wpc/snat") +} + +// SetSnatEnabled sets whether SNAT is enabled +func (c *SettingsService) SetSnatEnabled(value bool) (bool, error) { + return c.setBool("/wpc/snat", value) +} + +// GetSubnet retrieves the subnet configuration +func (c *SettingsService) GetSubnet() (*Subnet, error) { + body, err := c.get("/wpc/subnet") + if err != nil { + return nil, err + } + + var response Subnet + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + return &response, nil +} + +// SetSubnet updates the subnet configuration +func (c *SettingsService) SetSubnet(value Subnet) (*Subnet, error) { + jsonValue, err := json.Marshal(value) + if err != nil { + return nil, err + } + body, err := c.set("/wpc/subnet", jsonValue) + if err != nil { + return nil, err + } + var response Subnet + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + return &response, nil +} + +// GetTopology retrieves the network topology setting +func (c *SettingsService) GetTopology() (string, error) { + return c.getString("/wpc/topology") +} + +// SetTopology sets the network topology +func (c *SettingsService) SetTopology(value string) (string, error) { + return c.setString("/wpc/topology", value) +} + +// getBool retrieves a boolean value from the specified path +func (c *SettingsService) getBool(path string) (bool, error) { + body, err := c.get(path) + if err != nil { + return false, err + } + + var response bool + err = json.Unmarshal(body, &response) + if err != nil { + return false, err + } + return response, nil +} + +// setBool sets a boolean value at the specified path +func (c *SettingsService) setBool(path string, value bool) (bool, error) { + body, err := c.set(path, []byte(strconv.FormatBool(value))) + if err != nil { + return false, err + } + var response bool + err = json.Unmarshal(body, &response) + if err != nil { + return false, err + } + return response, nil +} + +// getString retrieves a string value from the specified path +func (c *SettingsService) getString(path string) (string, error) { + endpoint := fmt.Sprintf("%s/settings"+path, c.client.GetV1Url()) + req, err := http.NewRequest(http.MethodGet, endpoint, nil) + if err != nil { + return "", err + } + body, err := c.client.DoRequest(req) + if err != nil { + return "", err + } + return string(body), nil +} + +// setString sets a string value at the specified path +func (c *SettingsService) setString(path string, value string) (string, error) { + endpoint := fmt.Sprintf("%s/settings"+path, c.client.GetV1Url()) + req, err := http.NewRequest(http.MethodPut, endpoint, bytes.NewBuffer([]byte(value))) + if err != nil { + return "", err + } + req.Header.Set("Content-Type", "text/plain") + body, err := c.client.DoRequest(req) + if err != nil { + return "", err + } + return string(body), nil +} + +// getInt retrieves an integer value from the specified path +func (c *SettingsService) getInt(path string) (int, error) { + body, err := c.get(path) + if err != nil { + return 0, err + } + return strconv.Atoi(string(body)) +} + +// setInt sets an integer value at the specified path +func (c *SettingsService) setInt(path string, value int) (int, error) { + body, err := c.set(path, []byte(strconv.Itoa(value))) + if err != nil { + return 0, err + } + return strconv.Atoi(string(body)) +} + +// get performs a GET request to the specified path +func (c *SettingsService) get(path string) ([]byte, error) { + endpoint := fmt.Sprintf("%s/settings"+path, c.client.GetV1Url()) + req, err := http.NewRequest(http.MethodGet, endpoint, nil) + if err != nil { + return nil, err + } + body, err := c.client.DoRequest(req) + if err != nil { + return nil, err + } + return body, nil +} + +// set performs a PUT request to the specified path with the given value +func (c *SettingsService) set(path string, value []byte) ([]byte, error) { + endpoint := fmt.Sprintf("%s/settings"+path, c.client.GetV1Url()) + req, err := http.NewRequest(http.MethodPut, endpoint, bytes.NewBuffer(value)) + if err != nil { + return nil, err + } + body, err := c.client.DoRequest(req) + if err != nil { + return nil, err + } + return body, nil +}