Skip to content

Commit 20c5c20

Browse files
allmightyspiffGitHub Enterprise
authored andcommitted
Merge pull request #880 from SoftLayer/issues878
Added subnets to access-authorize, access-list and access-revoke for block|file commands
2 parents 30ae70b + bfe87d6 commit 20c5c20

19 files changed

+478
-230
lines changed

.secrets.baseline

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"files": "plugin/i18n/v1Resources/|plugin/i18n/v2Resources/|(.*test.*)|(vendor)|(go.sum)|bin/|^.secrets.baseline$",
44
"lines": null
55
},
6-
"generated_at": "2024-10-16T21:46:33Z",
6+
"generated_at": "2024-11-08T22:44:41Z",
77
"plugins_used": [
88
{
99
"name": "AWSKeyDetector"
@@ -124,31 +124,39 @@
124124
"hashed_secret": "49f18203810a56503e8b16bea101314713ce1a0c",
125125
"is_secret": false,
126126
"is_verified": false,
127-
"line_number": 82,
127+
"line_number": 97,
128128
"type": "Secret Keyword",
129129
"verified_result": null
130130
},
131131
{
132132
"hashed_secret": "4283f377a2ad3c107b4a3c9920c6ab508c6b1099",
133133
"is_secret": false,
134134
"is_verified": false,
135-
"line_number": 102,
135+
"line_number": 117,
136136
"type": "Secret Keyword",
137137
"verified_result": null
138138
},
139139
{
140140
"hashed_secret": "aa1f122c9be20b5a2aff7f2c513e3b065c033894",
141141
"is_secret": false,
142142
"is_verified": false,
143-
"line_number": 133,
143+
"line_number": 151,
144144
"type": "Secret Keyword",
145145
"verified_result": null
146146
},
147147
{
148148
"hashed_secret": "b2b24235714bf178e052e52a4af5a21a1f17c445",
149149
"is_secret": false,
150150
"is_verified": false,
151-
"line_number": 160,
151+
"line_number": 178,
152+
"type": "Secret Keyword",
153+
"verified_result": null
154+
},
155+
{
156+
"hashed_secret": "55839213174fc8f39a78d97deeaeecbd69f6de27",
157+
"is_secret": false,
158+
"is_verified": false,
159+
"line_number": 265,
152160
"type": "Secret Keyword",
153161
"verified_result": null
154162
}

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,28 @@ T("This is some output for a {{.CMDTYPE}} command", subs)
435435
436436
*NOTICE* goi18n/v2 has some newer features that can make this a bit easier to deal with, but I'm not sure they are currently supported, so procede with caution in you make use of them.
437437
438+
Commands that accept a list of options to display should have those subbed into the string, not hard coded.
439+
440+
BAD:
441+
```go
442+
cobraCmd.Flags().StringVar(&thisCmd.Sortby, "sortby", "id", T("Column to sort by. Options are: id, name, type, private_ip_address, source_subnet, host_iqn, username, password, allowed_host_id."))
443+
444+
```
445+
446+
GOOD:
447+
448+
```go
449+
defaultColumns := []string{
450+
"id", "name", "type", "private_ip_address", "source_subnet",
451+
"host_iqn", "username", "password","allowed_host_id"
452+
}
453+
454+
default_subs := map[string]interface{}{"COLUMNS": strings.join(defaultColumns, ", ")}
455+
456+
cobraCmd.Flags().StringVar(&thisCmd.Sortby, "sortby", "id",
457+
T("Column to sort by. Options are: {{.COLUMNS}}.", default_subs))
458+
```
459+
438460
### Useful Scripts
439461
440462
#### `./bin/buildAndDeploy.py i18n`
@@ -589,4 +611,24 @@ detect-secrets scan --update .secrets.baseline
589611
If we need to update the excluded files (these are saved in the .secrets.baseline file) do this:
590612
```bash
591613
detect-secrets -v scan --update .secrets.baseline --exclude-files "plugin/i18n/v1Resources/|plugin/i18n/v2Resources/|(.*test.*)|(vendor)|(go.sum)|bin/"
614+
```
615+
616+
617+
# Commit Signing
618+
Always a good idea to sign commits, even if it takes a bit to setup.
619+
620+
1. `git config --global commit.gpgsign true` Enabled signed commits
621+
2. `gpg --full-generate-key` Create a GPG key to sign commits with (use your github email)
622+
3. `git commit --message="THE MESSAGE"` is your normal commit, but should now be signed! You may be prompted for a password
623+
4. `git log --show-signature` confirm its signed.
624+
5. `gpg --output email.pgp --armor --export [email protected]` will export your PUBLIC key so you can upload it to github.
625+
626+
627+
## Windows setup
628+
629+
In windows GPG pops up an annoying window for password prompting. Following [Using Command-Line Passphrase Input for GPG with Git](https://betakuang.medium.com/using-command-line-passphrase-input-for-gpg-with-git-for-windows-f78ae2c7cd2e) to be prompted on the CLI
630+
631+
```
632+
$> cat ~/.gnupg/gpg-agent.conf
633+
allow-loopback-pinentry
592634
```

bin/buildAndDeploy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def runTests() -> None:
9494
except subprocess.CalledProcessError as e:
9595
print(f"[red]>>> Go Test failed <<<")
9696
sys.exit(e.returncode)
97-
go_sec = ['gosec', '-exclude-dir=fixture', '-exclude-dir=plugin/resources', '-quiet', './...']
97+
go_sec = ['gosec', '-exclude-dir=fixture', '-exclude-dir=plugin/resources', '-exclude-generated', './...']
9898
# Not using the 'real' command because this is more copy/pasteable.
9999
print('[turquoise2]Running: ' + " ".join(go_sec))
100100
try:

plugin/commands/block/access_authorize.go

Lines changed: 80 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package block
22

33
import (
4+
"strconv"
45
"github.com/spf13/cobra"
56

67
slErr "github.ibm.com/SoftLayer/softlayer-cli/plugin/errors"
@@ -19,6 +20,7 @@ type AccessAuthorizeCommand struct {
1920
Virtual_id []int
2021
Ip_address_id []int
2122
Ip_address []string
23+
Subnet_id int
2224
}
2325

2426
func NewAccessAuthorizeCommand(sl *metadata.SoftlayerStorageCommand) *AccessAuthorizeCommand {
@@ -32,24 +34,42 @@ func NewAccessAuthorizeCommand(sl *metadata.SoftlayerStorageCommand) *AccessAuth
3234
Short: T("Authorize hosts to access a given volume."),
3335
Long: T(`EXAMPLE:
3436
${COMMAND_NAME} sl {{.storageType}} access-authorize 12345678 --virtual-id 87654321
35-
This command authorizes virtual server with ID 87654321 to access volume with ID 12345678.`, sl.StorageI18n),
37+
This command authorizes virtual server with ID 87654321 to access volume with ID 12345678.`, sl.StorageI18n) + "\n" +
38+
T(`
39+
${COMMAND_NAME} sl {{.storageType}} access-authorize 5555 --subnet-id 1111
40+
This command adds subnet with id 1111 to the Allowed Host with id 5555. Use 'access-list' to find this id.
41+
SoftLayer_Account::iscsiIsolationDisabled must be False for this command to do anything.`, sl.StorageI18n),
3642
Args: metadata.OneArgs,
3743
RunE: func(cmd *cobra.Command, args []string) error {
3844
return thisCmd.Run(args)
3945
},
4046
}
4147

42-
cobraCmd.Flags().IntSliceVarP(&thisCmd.Hardware_id, "hardware-id", "d", []int{}, T("The ID of one hardware server to authorize."))
43-
cobraCmd.Flags().IntSliceVarP(&thisCmd.Virtual_id, "virtual-id", "v", []int{}, T("The ID of one virtual server to authorize."))
44-
cobraCmd.Flags().IntSliceVarP(&thisCmd.Ip_address_id, "ip-address-id", "i", []int{}, T("The ID of one IP address to authorize."))
45-
cobraCmd.Flags().StringSliceVarP(&thisCmd.Ip_address, "ip-address", "p", []string{}, T("An IP address to authorize."))
48+
cobraCmd.Flags().IntSliceVarP(&thisCmd.Hardware_id, "hardware-id", "d", []int{},
49+
T("The ID of one hardware server to authorize."))
50+
cobraCmd.Flags().IntSliceVarP(&thisCmd.Virtual_id, "virtual-id", "v", []int{},
51+
T("The ID of one virtual server to authorize."))
52+
cobraCmd.Flags().IntSliceVarP(&thisCmd.Ip_address_id, "ip-address-id", "i", []int{},
53+
T("The ID of one IP address to authorize."))
54+
cobraCmd.Flags().StringSliceVarP(&thisCmd.Ip_address, "ip-address", "p", []string{},
55+
T("An IP address to authorize."))
56+
cobraCmd.Flags().IntVarP(&thisCmd.Subnet_id, "subnet-id", "s", 0,
57+
T("A Subnet Id. With this option IDENTIFIER should be an 'allowed_host_id' from the access-list command."))
4658
thisCmd.Command = cobraCmd
4759

4860
return thisCmd
4961
}
5062

5163
func (cmd *AccessAuthorizeCommand) Run(args []string) error {
5264

65+
// Subnets have to get added to an existing authorized host.
66+
if cmd.Subnet_id > 0 {
67+
hostId, err := strconv.Atoi(args[0])
68+
if err != nil {
69+
return slErr.NewInvalidSoftlayerIdInputError("Allowed Host IDENTIFIER")
70+
}
71+
return cmd.AddSubnetToHost(hostId)
72+
}
5373
volumeID, err := cmd.StorageManager.GetVolumeId(args[0], cmd.StorageType)
5474
if err != nil {
5575
return err
@@ -60,7 +80,8 @@ func (cmd *AccessAuthorizeCommand) Run(args []string) error {
6080
for _, ip := range IPs {
6181
ipRecord, err := cmd.NetworkManager.IPLookup(ip)
6282
if err != nil {
63-
return slErr.NewAPIError(T("IP address {{.IP}} is not found on your account.Please confirm IP and try again.\n",
83+
return slErr.NewAPIError(
84+
T("IP address {{.IP}} is not found on your account.Please confirm IP and try again.\n",
6485
map[string]interface{}{"IP": ip}), err.Error(), 2)
6586
}
6687
if ipRecord.Id != nil {
@@ -82,14 +103,61 @@ func (cmd *AccessAuthorizeCommand) Run(args []string) error {
82103
}
83104

84105
cmd.UI.Ok()
85-
for _, vsID := range cmd.Virtual_id {
86-
cmd.UI.Print(T("The virtual server {{.VsID}} was authorized to access {{.VolumeId}}.", map[string]interface{}{"VolumeId": volumeID, "VsID": vsID}))
106+
subs := map[string]interface{}{
107+
"VolumeId": volumeID,
108+
"SL_ID": 0,
109+
"SL_Object": "",
87110
}
88-
for _, hwID := range cmd.Hardware_id {
89-
cmd.UI.Print(T("The hardware server {{.HwID}} was authorized to access {{.VolumeId}}.", map[string]interface{}{"VolumeId": volumeID, "HwID": hwID}))
111+
for _, sl_id := range cmd.Virtual_id {
112+
subs["SL_Object"] = T("Virtual Server")
113+
subs["SL_ID"] = sl_id
114+
cmd.UI.Print(T("The {{.SL_Object}} {{.SL_ID}} was authorized to access {{.VolumeId}}.", subs))
90115
}
91-
for _, ip := range IPIds {
92-
cmd.UI.Print(T("The IP address {{.IP}} was authorized to access {{.VolumeId}}.", map[string]interface{}{"VolumeId": volumeID, "IP": ip}))
116+
for _, sl_id := range cmd.Hardware_id {
117+
subs["SL_Object"] = T("Hardware Server")
118+
subs["SL_ID"] = sl_id
119+
cmd.UI.Print(T("The {{.SL_Object}} {{.SL_ID}} was authorized to access {{.VolumeId}}.", subs))
120+
}
121+
for _, sl_id := range IPIds {
122+
subs["SL_Object"] = T("IP Address")
123+
subs["SL_ID"] = sl_id
124+
cmd.UI.Print(T("The {{.SL_Object}} {{.SL_ID}} was authorized to access {{.VolumeId}}.", subs))
93125
}
94126
return nil
95127
}
128+
129+
func (cmd *AccessAuthorizeCommand) AddSubnetToHost(host_id int) error {
130+
131+
outputFormat := cmd.GetOutputFlag()
132+
subnet_ids := []int{cmd.Subnet_id}
133+
resp, err := cmd.StorageManager.AssignSubnetsToAcl(host_id, subnet_ids)
134+
if err != nil {
135+
subs := map[string]interface{}{"subnetID": cmd.Subnet_id, "accessID": host_id}
136+
return slErr.NewAPIError(
137+
T("Failed to assign subnet id: {{.subnetID}} to allowed host id: {{.accessID}}", subs),
138+
err.Error(), 2)
139+
}
140+
// If the API returns an empty array, that means it didn't add the subnet we asked for.
141+
// Likely because ISCSI Isolation is disabled on the account.
142+
// ibmcloud sl call-api SoftLayer_Account getObject --mask="mask[id,iscsiIsolationDisabled]"
143+
if len(resp) == 0 || utils.IntInSlice(cmd.Subnet_id, resp) == -1 {
144+
subs := map[string]interface{}{"subnetID": cmd.Subnet_id, "accessID": host_id}
145+
return slErr.NewAPIError(
146+
T("Failed to assign subnet id: {{.subnetID}} to allowed host id: {{.accessID}}", subs) + "\n" +
147+
T("Make sure ISCSI Isolation is enabled for this account."),
148+
"", 2,
149+
)
150+
}
151+
if outputFormat == "JSON" {
152+
return utils.PrintPrettyJSON(cmd.UI, resp)
153+
}
154+
155+
cmd.UI.Ok()
156+
subs := map[string]interface{}{
157+
"VolumeId": host_id,
158+
"SL_ID": cmd.Subnet_id,
159+
"SL_Object": T("Subnet"),
160+
}
161+
cmd.UI.Print(T("The {{.SL_Object}} {{.SL_ID}} was authorized to access {{.VolumeId}}.", subs))
162+
return nil
163+
}

0 commit comments

Comments
 (0)