Skip to content

Commit a545ded

Browse files
authored
Merge pull request #1328 from Tinyblargon/#1326
feat: minimum permission settings
2 parents 34ba739 + a2d9acb commit a545ded

File tree

2 files changed

+87
-68
lines changed

2 files changed

+87
-68
lines changed

docs/index.md

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -105,22 +105,24 @@ provider "proxmox" {
105105

106106
The following arguments are supported in the provider block:
107107

108-
| Argument | environment variable | Type | Default Value | Description |
109-
| --------------------- | -------------------- | -------- | ------------------------------ | ----------- |
110-
| `pm_api_url` | `PM_API_URL` | `string` | | **Required** This is the target Proxmox API endpoint. |
111-
| `pm_user` | `PM_USER` | `string` | | The user, remember to include the authentication realm such as myuser@pam or myuser@pve. |
112-
| `pm_password` | `PM_PASS` | `string` | | **Sensitive** The password. |
113-
| `pm_api_token_id` | `PM_API_TOKEN_ID` | `string` | | This is an [API token](https://pve.proxmox.com/pve-docs/pveum-plain.html) you have previously created for a specific user. |
114-
| `pm_api_token_secret` | `PM_API_TOKEN_SECRET`| `string` | | **Sensitive** This uuid is only available when the token was initially created. |
115-
| `pm_otp` | `PM_OTP` | `string` | | The 2FA OTP code. |
116-
| `pm_tls_insecure` | | `bool` | `false` | Disable TLS verification while connecting to the proxmox server. |
117-
| `pm_parallel` | | `uint` | `1` | Allowed simultaneous Proxmox processes (e.g. creating resources). Setting this greater than 1 is currently not recommended when creating LXC containers with dynamic id allocation. For Qemu the threading issue has been resolved.|
118-
| `pm_log_enable` | | `bool` | `false` | Enable debug logging, see the section below for logging details. |
119-
| `pm_log_levels` | | `map` | | A map of log sources and levels. |
120-
| `pm_log_file` | | `string` | `terraform-plugin-proxmox.log` | The log file the provider will write logs to. |
121-
| `pm_timeout` | | `uint` | `300` | Timeout value (seconds) for proxmox API calls. |
122-
| `pm_debug` | | `bool` | `false` | Enable verbose output in proxmox-api-go. |
123-
| `pm_proxy_server` | | `string` | | Send provider api call to a proxy server for easy debugging. |
108+
| Argument | environment variable | Type | Default Value | Description |
109+
|:---------------------------- |:-------------------- |:-------- |:------------------------------ |:----------- |
110+
| `pm_api_url` | `PM_API_URL` | `string` | | **Required** This is the target Proxmox API endpoint.|
111+
| `pm_user` | `PM_USER` | `string` | | The user, remember to include the authentication realm such as myuser@pam or myuser@pve.|
112+
| `pm_password` | `PM_PASS` | `string` | | **Sensitive** The password.|
113+
| `pm_api_token_id` | `PM_API_TOKEN_ID` | `string` | | This is an [API token](https://pve.proxmox.com/pve-docs/pveum-plain.html) you have previously created for a specific user.|
114+
| `pm_api_token_secret` | `PM_API_TOKEN_SECRET`| `string` | | **Sensitive** This uuid is only available when the token was initially created.|
115+
| `pm_otp` | `PM_OTP` | `string` | | The 2FA OTP code.|
116+
| `pm_tls_insecure` | | `bool` | `false` | Disable TLS verification while connecting to the proxmox server.|
117+
| `pm_parallel` | | `uint` | `1` | Allowed simultaneous Proxmox processes (e.g. creating resources). Setting this greater than 1 is currently not recommended when creating LXC containers with dynamic id allocation. For Qemu the threading issue has been resolved.|
118+
| `pm_log_enable` | | `bool` | `false` | Enable debug logging, see the section below for logging details.|
119+
| `pm_log_levels` | | `map` | | A map of log sources and levels.|
120+
| `pm_log_file` | | `string` | `terraform-plugin-proxmox.log` | The log file the provider will write logs to.|
121+
| `pm_timeout` | | `uint` | `300` | Timeout value (seconds) for proxmox API calls.|
122+
| `pm_debug` | | `bool` | `false` | Enable verbose output in proxmox-api-go.|
123+
| `pm_proxy_server` | | `string` | | Send provider api call to a proxy server for easy debugging.|
124+
| `pm_minimum_permission_check`| | `bool` | `true` | Enable minimum permission check. This will check if the user has the minimum permissions required to use the provider.|
125+
| `pm_minimum_permission_list` | | `list` | | A list of permissions to check. Allows overwriting of the default permissions.|
124126

125127
Additionally, one can set the `PM_OTP_PROMPT` environment variable to prompt for OTP 2FA code (if required).
126128

proxmox/provider.go

Lines changed: 69 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ const (
3434
schemaPmDangerouslyIgnoreUnknownAttributes = "pm_dangerously_ignore_unknown_attributes"
3535
schemaPmDebug = "pm_debug"
3636
schemaPmProxyServer = "pm_proxy_server"
37+
schemaMinimumPermissionCheck = "pm_minimum_permission_check"
38+
schemaMinimumPermissionList = "pm_minimum_permission_list"
3739
schemaPmOTP = "pm_otp"
3840
)
3941

@@ -185,6 +187,14 @@ func Provider() *schema.Provider {
185187
DefaultFunc: schema.EnvDefaultFunc("PM_PROXY", nil),
186188
Description: "Proxy Server passed to Api client(useful for debugging). Syntax: http://proxy:port",
187189
},
190+
schemaMinimumPermissionCheck: {
191+
Type: schema.TypeBool,
192+
Optional: true,
193+
Default: true},
194+
schemaMinimumPermissionList: {
195+
Type: schema.TypeList,
196+
Optional: true,
197+
Elem: &schema.Schema{Type: schema.TypeString}},
188198
schemaPmOTP: &pmOTPprompt,
189199
},
190200

@@ -207,7 +217,7 @@ func Provider() *schema.Provider {
207217
}
208218
}
209219

210-
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
220+
func providerConfigure(d *schema.ResourceData) (any, error) {
211221
client, err := getClient(
212222
d.Get(schemaPmApiUrl).(string),
213223
d.Get(schemaPmUser).(string),
@@ -225,7 +235,6 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) {
225235
return nil, err
226236
}
227237

228-
// permission check
229238
minimumPermissions := []string{
230239
"Datastore.AllocateSpace",
231240
"Datastore.Audit",
@@ -248,60 +257,68 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) {
248257
"VM.Monitor",
249258
"VM.PowerMgmt",
250259
}
251-
var id string
252-
if result, getok := d.GetOk(schemaPmApiTokenID); getok {
253-
id = result.(string)
254-
id = strings.Split(id, "!")[0]
255-
} else if result, getok := d.GetOk(schemaPmUser); getok {
256-
id = result.(string)
257-
}
258-
userID, err := pveSDK.NewUserID(id)
259-
if err != nil {
260-
return nil, err
261-
}
262-
ctx := context.Background()
263-
permlist, err := client.GetUserPermissions(ctx, userID, "/")
264-
if err != nil {
265-
return nil, err
260+
if v, ok := d.GetOk(schemaMinimumPermissionList); ok {
261+
rawArray := v.([]any)
262+
minimumPermissions = make([]string, len(rawArray))
263+
for i := range rawArray {
264+
minimumPermissions[i] = rawArray[i].(string)
265+
}
266266
}
267-
sort.Strings(permlist)
268-
sort.Strings(minimumPermissions)
269-
permDiff := permissions_check(permlist, minimumPermissions)
270-
if len(permDiff) == 0 {
271-
// look to see what logging we should be outputting according to the provider configuration
272-
logLevels := make(map[string]string)
273-
for logger, level := range d.Get(schemaPmLogLevels).(map[string]interface{}) {
274-
levelAsString, ok := level.(string)
275-
if ok {
276-
logLevels[logger] = levelAsString
277-
} else {
278-
return nil, fmt.Errorf("invalid logging level %v for %v. Be sure to use a string", level, logger)
279-
}
267+
268+
if d.Get(schemaMinimumPermissionCheck).(bool) { // permission check
269+
var id string
270+
if result, ok := d.GetOk(schemaPmApiTokenID); ok {
271+
id = result.(string)
272+
id = strings.Split(id, "!")[0]
273+
} else if result, ok := d.GetOk(schemaPmUser); ok {
274+
id = result.(string)
275+
}
276+
userID, err := pveSDK.NewUserID(id)
277+
if err != nil {
278+
return nil, err
279+
}
280+
permList, err := client.GetUserPermissions(context.Background(), userID, "/")
281+
if err != nil {
282+
return nil, err
280283
}
284+
sort.Strings(permList)
285+
sort.Strings(minimumPermissions)
286+
permDiff := permissions_check(permList, minimumPermissions)
287+
if len(permDiff) != 0 {
288+
return nil, fmt.Errorf("permissions for user/token "+userID.ToString()+" are not sufficient, please provide also the following permissions that are missing: %v", permDiff)
289+
}
290+
}
281291

282-
// actually configure logging
283-
// note that if enable is false here, the configuration will squash all output
284-
ConfigureLogger(
285-
d.Get(schemaPmLogEnable).(bool),
286-
d.Get(schemaPmLogFile).(string),
287-
logLevels,
288-
)
289-
290-
var mut sync.Mutex
291-
return &providerConfiguration{
292-
Client: client,
293-
MaxParallel: d.Get(schemaPmParallel).(int),
294-
CurrentParallel: 0,
295-
MaxGuestID: 0,
296-
Mutex: &mut,
297-
Cond: sync.NewCond(&mut),
298-
LogFile: d.Get(schemaPmLogFile).(string),
299-
LogLevels: logLevels,
300-
DangerouslyIgnoreUnknownAttributes: d.Get(schemaPmDangerouslyIgnoreUnknownAttributes).(bool),
301-
}, nil
292+
// look to see what logging we should be outputting according to the provider configuration
293+
logLevels := make(map[string]string)
294+
for logger, level := range d.Get(schemaPmLogLevels).(map[string]any) {
295+
levelAsString, ok := level.(string)
296+
if ok {
297+
logLevels[logger] = levelAsString
298+
} else {
299+
return nil, fmt.Errorf("invalid logging level %v for %v. Be sure to use a string", level, logger)
300+
}
302301
}
303-
err = fmt.Errorf("permissions for user/token %s are not sufficient, please provide also the following permissions that are missing: %v", userID.ToString(), permDiff)
304-
return nil, err
302+
303+
// actually configure logging
304+
// note that if enable is false here, the configuration will squash all output
305+
ConfigureLogger(
306+
d.Get(schemaPmLogEnable).(bool),
307+
d.Get(schemaPmLogFile).(string),
308+
logLevels)
309+
310+
var mut sync.Mutex
311+
return &providerConfiguration{
312+
Client: client,
313+
MaxParallel: d.Get(schemaPmParallel).(int),
314+
CurrentParallel: 0,
315+
MaxGuestID: 0,
316+
Mutex: &mut,
317+
Cond: sync.NewCond(&mut),
318+
LogFile: d.Get(schemaPmLogFile).(string),
319+
LogLevels: logLevels,
320+
DangerouslyIgnoreUnknownAttributes: d.Get(schemaPmDangerouslyIgnoreUnknownAttributes).(bool),
321+
}, nil
305322
}
306323

307324
func getClient(pm_api_url string,

0 commit comments

Comments
 (0)