diff --git a/docs/resources/user.md b/docs/resources/user.md index f4416e2..e8b1792 100644 --- a/docs/resources/user.md +++ b/docs/resources/user.md @@ -32,6 +32,7 @@ The organization resource allows managing information about a particular Pritunl - `groups` (List of String) Enter list of groups to allow connections from. Names are case sensitive. If empty all groups will able to connect. - `mac_addresses` (List of String) Comma separated list of MAC addresses client is allowed to connect from. The validity of the MAC address provided by the VPN client cannot be verified. - `network_links` (List of String) Network address with cidr subnet. This will provision access to a clients local network to the attached vpn servers and other clients. Multiple networks may be separated by a comma. Router must have a static route to VPN virtual network through client. +- `pin` (String) The PIN code for the user. - `port_forwarding` (List of Map of String) Comma seperated list of ports to forward using format source_port:dest_port/protocol or start_port-end_port/protocol. Such as 80, 80/tcp, 80:8000/tcp, 1000-2000/udp. ### Read-Only diff --git a/internal/pritunl/client.go b/internal/pritunl/client.go index 365af0d..539db9e 100644 --- a/internal/pritunl/client.go +++ b/internal/pritunl/client.go @@ -19,8 +19,8 @@ type Client interface { DeleteOrganization(name string) error GetUser(id string, orgId string) (*User, error) - CreateUser(newUser User) (*User, error) - UpdateUser(id string, user *User) error + CreateUser(newUser NewUser) (*User, error) + UpdateUser(id string, user *NewUser) error DeleteUser(id string, orgId string) error GetServers() ([]Server, error) @@ -693,7 +693,7 @@ func (c client) GetUser(id string, orgId string) (*User, error) { return &user, nil } -func (c client) CreateUser(newUser User) (*User, error) { +func (c client) CreateUser(newUser NewUser) (*User, error) { jsonData, err := json.Marshal(newUser) if err != nil { return nil, fmt.Errorf("CreateUser: Error on marshalling data: %s", err) @@ -726,7 +726,7 @@ func (c client) CreateUser(newUser User) (*User, error) { return nil, fmt.Errorf("empty users response") } -func (c client) UpdateUser(id string, user *User) error { +func (c client) UpdateUser(id string, user *NewUser) error { jsonData, err := json.Marshal(user) if err != nil { return fmt.Errorf("UpdateUser: Error on marshalling data: %s", err) diff --git a/internal/pritunl/user.go b/internal/pritunl/user.go index 61f4c89..16d75d3 100644 --- a/internal/pritunl/user.go +++ b/internal/pritunl/user.go @@ -28,8 +28,65 @@ type User struct { Organization string `json:"organization,omitempty"` } +type NewUser struct { + ID string `json:"id,omitempty"` + Name string `json:"name"` + Type string `json:"type,omitempty"` + AuthType string `json:"auth_type,omitempty"` + DnsServers []string `json:"dns_servers,omitempty"` + Pin string `json:"pin,omitempty"` + DnsSuffix string `json:"dns_suffix,omitempty"` + DnsMapping string `json:"dns_mapping,omitempty"` + Disabled bool `json:"disabled,omitempty"` + NetworkLinks []string `json:"network_links,omitempty"` + PortForwarding []map[string]interface{} `json:"port_forwarding,omitempty"` + Email string `json:"email,omitempty"` + Status bool `json:"status,omitempty"` + OtpSecret string `json:"otp_secret,omitempty"` + ClientToClient bool `json:"client_to_client,omitempty"` + MacAddresses []string `json:"mac_addresses,omitempty"` + YubicoID string `json:"yubico_id,omitempty"` + SSO interface{} `json:"sso,omitempty"` + BypassSecondary bool `json:"bypass_secondary,omitempty"` + Groups []string `json:"groups,omitempty"` + Audit bool `json:"audit,omitempty"` + Gravatar bool `json:"gravatar,omitempty"` + OtpAuth bool `json:"otp_auth,omitempty"` + DeviceAuth bool `json:"device_auth,omitempty"` + Organization string `json:"organization,omitempty"` +} + type PortForwarding struct { Dport string `json:"dport"` Protocol string `json:"protocol"` Port string `json:"port"` } + +func (user User) ToNewUser() NewUser { + return NewUser{ + ID: user.ID, + Name: user.Name, + Type: user.Type, + AuthType: user.AuthType, + DnsServers: user.DnsServers, + DnsSuffix: user.DnsSuffix, + DnsMapping: user.DnsMapping, + Disabled: user.Disabled, + NetworkLinks: user.NetworkLinks, + PortForwarding: user.PortForwarding, + Email: user.Email, + Status: user.Status, + OtpSecret: user.OtpSecret, + ClientToClient: user.ClientToClient, + MacAddresses: user.MacAddresses, + YubicoID: user.YubicoID, + SSO: user.SSO, + BypassSecondary: user.BypassSecondary, + Groups: user.Groups, + Audit: user.Audit, + Gravatar: user.Gravatar, + OtpAuth: user.OtpAuth, + DeviceAuth: user.DeviceAuth, + Organization: user.Organization, + } +} diff --git a/internal/provider/resource_user.go b/internal/provider/resource_user.go index 8c33acf..04fc450 100644 --- a/internal/provider/resource_user.go +++ b/internal/provider/resource_user.go @@ -100,6 +100,12 @@ func resourceUser() *schema.Resource { Optional: true, Description: "Bypass secondary authentication such as the PIN and two-factor authentication. Use for server users that can't provide a two-factor code.", }, + "pin": { + Type: schema.TypeString, + Optional: true, + Sensitive: true, + Description: "The PIN for user authentication.", + }, }, CreateContext: resourceUserCreate, ReadContext: resourceUserRead, @@ -170,12 +176,20 @@ func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, meta interf return diag.FromErr(err) } + updatedUser := user.ToNewUser() + + if d.HasChange("pin") { + if v, ok := d.GetOk("pin"); ok { + updatedUser.Pin = v.(string) + } + } + if v, ok := d.GetOk("name"); ok { - user.Name = v.(string) + updatedUser.Name = v.(string) } if v, ok := d.GetOk("organization_id"); ok { - user.Organization = v.(string) + updatedUser.Organization = v.(string) } if d.HasChange("groups") { @@ -183,16 +197,16 @@ func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, meta interf for _, v := range d.Get("groups").([]interface{}) { groups = append(groups, v.(string)) } - user.Groups = groups + updatedUser.Groups = groups } if v, ok := d.GetOk("email"); ok { - user.Email = v.(string) + updatedUser.Email = v.(string) } // TODO: Fixme if v, ok := d.GetOk("disabled"); ok { - user.Disabled = v.(bool) + updatedUser.Disabled = v.(bool) } if d.HasChange("port_forwarding") { @@ -200,7 +214,7 @@ func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, meta interf for _, v := range d.Get("port_forwarding").([]interface{}) { portForwarding = append(portForwarding, v.(map[string]interface{})) } - user.PortForwarding = portForwarding + updatedUser.PortForwarding = portForwarding } if d.HasChange("network_links") { @@ -208,15 +222,15 @@ func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, meta interf for _, v := range d.Get("network_links").([]interface{}) { networkLinks = append(networkLinks, v.(string)) } - user.NetworkLinks = networkLinks + updatedUser.NetworkLinks = networkLinks } if v, ok := d.GetOk("client_to_client"); ok { - user.ClientToClient = v.(bool) + updatedUser.ClientToClient = v.(bool) } if v, ok := d.GetOk("auth_type"); ok { - user.AuthType = v.(string) + updatedUser.AuthType = v.(string) } if d.HasChange("mac_addresses") { @@ -224,7 +238,7 @@ func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, meta interf for _, v := range d.Get("mac_addresses").([]interface{}) { macAddresses = append(macAddresses, v.(string)) } - user.MacAddresses = macAddresses + updatedUser.MacAddresses = macAddresses } if d.HasChange("dns_servers") { @@ -232,18 +246,18 @@ func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, meta interf for _, v := range d.Get("dns_servers").([]interface{}) { dnsServers = append(dnsServers, v.(string)) } - user.DnsServers = dnsServers + updatedUser.DnsServers = dnsServers } if v, ok := d.GetOk("dns_suffix"); ok { - user.DnsSuffix = v.(string) + updatedUser.DnsSuffix = v.(string) } if v, ok := d.GetOk("bypass_secondary"); ok { - user.BypassSecondary = v.(bool) + updatedUser.BypassSecondary = v.(bool) } - err = apiClient.UpdateUser(d.Id(), user) + err = apiClient.UpdateUser(d.Id(), &updatedUser) if err != nil { return diag.FromErr(err) } @@ -279,7 +293,7 @@ func resourceUserCreate(_ context.Context, d *schema.ResourceData, meta interfac groups = append(groups, v.(string)) } - userData := pritunl.User{ + userData := pritunl.NewUser{ Name: d.Get("name").(string), Organization: d.Get("organization_id").(string), AuthType: d.Get("auth_type").(string), @@ -293,6 +307,7 @@ func resourceUserCreate(_ context.Context, d *schema.ResourceData, meta interfac MacAddresses: macAddresses, BypassSecondary: d.Get("bypass_secondary").(bool), Groups: groups, + Pin: d.Get("pin").(string), } user, err := apiClient.CreateUser(userData)