Skip to content

Commit f43667b

Browse files
authored
Merge pull request #20 from mkumatag/service-cred
Auto generate the service credential
2 parents a85c504 + 6a3c5f4 commit f43667b

File tree

6 files changed

+344
-25
lines changed

6 files changed

+344
-25
lines changed

cmd/image/import/import.go

Lines changed: 106 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
package _import
22

33
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
"strings"
8+
9+
"github.com/IBM/go-sdk-core/v4/core"
10+
rcv2 "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2"
11+
"github.com/spf13/cobra"
12+
"k8s.io/klog/v2"
13+
414
"github.com/ppc64le-cloud/pvsadm/pkg"
515
"github.com/ppc64le-cloud/pvsadm/pkg/client"
616
"github.com/ppc64le-cloud/pvsadm/pkg/utils"
7-
"github.com/spf13/cobra"
8-
"k8s.io/klog/v2"
17+
)
918

10-
"os"
11-
"strings"
19+
const (
20+
ServiceCredName = "pvsadm-service-cred"
1221
)
1322

1423
var Cmd = &cobra.Command{
@@ -22,17 +31,21 @@ export IBMCLOUD_API_KEY=<IBM_CLOUD_API_KEY>
2231
2332
Examples:
2433
25-
# importing image from default region and using default storage type
34+
# importing image from default region and using default storage type (service credential will be autogenerated)
35+
pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --object-name rhel-83-10032020.ova.gz --image-name test-image
36+
37+
# importing image from default region and using default storage type with specifying the accesskey and secretkey explicitly
2638
pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --accesskey <ACCESSKEY> --secretkey <SECRETKEY> --object-name rhel-83-10032020.ova.gz --image-name test-image
2739
2840
# with user provided storage type and region
29-
pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --accesskey <ACCESSKEY> --secretkey <SECRETKEY> -r <REGION> --storagetype <STORAGETYPE> --object-name rhel-83-10032020.ova.gz --image-name test-image
41+
pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> -r <REGION> --storagetype <STORAGETYPE> --object-name rhel-83-10032020.ova.gz --image-name test-image
3042
3143
# If user wants to specify the type of OS
32-
pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --accesskey <ACCESSKEY> --secretkey <SECRETKEY> --object-name rhel-83-10032020.ova.gz --image-name test-image --ostype <OSTYPE>
44+
pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --object-name rhel-83-10032020.ova.gz --image-name test-image --ostype <OSTYPE>
3345
`,
3446
RunE: func(cmd *cobra.Command, args []string) error {
3547
opt := pkg.ImageCMDOptions
48+
apikey := pkg.Options.APIKey
3649
//validate inputs
3750
validOsType := []string{"aix", "ibmi", "redhat", "sles"}
3851
validStorageType := []string{"tier3", "tier1"}
@@ -47,7 +60,89 @@ pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --accesskey <ACCESSKE
4760
os.Exit(1)
4861
}
4962

50-
c, err := client.NewClient(pkg.Options.APIKey)
63+
if opt.AccessKey == "" || opt.SecretKey == "" {
64+
klog.Info("Auto Generating the COS Service credential for importing the image")
65+
auth, err := core.NewIamAuthenticator(apikey, "", "", "", false, nil)
66+
if err != nil {
67+
return err
68+
}
69+
70+
bxCli, err := client.NewClient(apikey)
71+
if err != nil {
72+
return err
73+
}
74+
75+
resourceController, err := client.NewResourceControllerV2(&rcv2.ResourceControllerV2Options{
76+
Authenticator: auth,
77+
})
78+
if err != nil {
79+
return err
80+
}
81+
82+
instances, _, err := resourceController.ResourceControllerV2.ListResourceInstances(resourceController.ResourceControllerV2.NewListResourceInstancesOptions().SetType("service_instance"))
83+
if err != nil {
84+
return err
85+
}
86+
87+
// Step 1: Find where COS for the bucket
88+
cosOfBucket := func(resources []rcv2.ResourceInstance) *rcv2.ResourceInstance {
89+
for _, resource := range resources {
90+
if strings.Contains(*resource.Crn, "cloud-object-storage") {
91+
s3client, err := client.NewS3Client(bxCli, *resource.Name, opt.Region)
92+
if err != nil {
93+
continue
94+
}
95+
buckets, err := s3client.S3Session.ListBuckets(nil)
96+
if err != nil {
97+
continue
98+
}
99+
for _, bucket := range buckets.Buckets {
100+
if *bucket.Name == opt.BucketName {
101+
return &resource
102+
}
103+
}
104+
}
105+
}
106+
return nil
107+
}(instances.Resources)
108+
109+
if cosOfBucket == nil {
110+
return fmt.Errorf("failed to find the COS instance for the bucket mentioned: %s", opt.BucketName)
111+
}
112+
klog.Infof("%s bucket found in the %s[ID:%s] COS instance", opt.BucketName, *cosOfBucket.Name, *cosOfBucket.ID)
113+
114+
// Step 2: Create the Service Credential in the found COS instance
115+
createResourceKeyOptions := &client.CreateResourceKeyOptions{
116+
CreateResourceKeyOptions: resourceController.ResourceControllerV2.NewCreateResourceKeyOptions(ServiceCredName, *cosOfBucket.ID),
117+
Parameters: map[string]interface{}{"HMAC": true},
118+
}
119+
120+
key, _, err := resourceController.CreateResourceKey(createResourceKeyOptions)
121+
if err != nil {
122+
return err
123+
}
124+
defer resourceController.ResourceControllerV2.DeleteResourceKey(&rcv2.DeleteResourceKeyOptions{ID: key.ID})
125+
126+
jsonString, err := json.Marshal(key.Credentials.GetProperty("cos_hmac_keys"))
127+
if err != nil {
128+
return err
129+
}
130+
h := struct {
131+
AccessKeyID string `json:"access_key_id"`
132+
SecretKeyID string `json:"secret_access_key"`
133+
}{}
134+
err = json.Unmarshal(jsonString, &h)
135+
if err != nil {
136+
klog.Errorf("failed to unmarshal the access credentials from the auto generated service credential")
137+
return err
138+
}
139+
140+
// Step 3: Assign the Access Key and Secret Key for further operation
141+
opt.AccessKey = h.AccessKeyID
142+
opt.SecretKey = h.SecretKeyID
143+
}
144+
145+
c, err := client.NewClient(apikey)
51146
if err != nil {
52147
return err
53148
}
@@ -73,15 +168,13 @@ func init() {
73168
Cmd.Flags().StringVarP(&pkg.ImageCMDOptions.InstanceID, "instance-id", "i", "", "Instance ID of the PowerVS instance")
74169
Cmd.Flags().StringVarP(&pkg.ImageCMDOptions.BucketName, "bucket", "b", "", "Cloud Storage bucket name")
75170
Cmd.Flags().StringVarP(&pkg.ImageCMDOptions.Region, "region", "r", "", "Cloud Storage Region")
76-
Cmd.Flags().StringVar(&pkg.ImageCMDOptions.AccessKey, "accesskey", "", "Cloud Storage access key; required for import image")
77-
Cmd.Flags().StringVar(&pkg.ImageCMDOptions.SecretKey, "secretkey", "", "Cloud Storage secret key; required for import image")
171+
Cmd.Flags().StringVar(&pkg.ImageCMDOptions.AccessKey, "accesskey", "", "Cloud Storage access key")
172+
Cmd.Flags().StringVar(&pkg.ImageCMDOptions.SecretKey, "secretkey", "", "Cloud Storage secret key")
78173
Cmd.Flags().StringVar(&pkg.ImageCMDOptions.ImageName, "image-name", "", "Name to give imported image")
79174
Cmd.Flags().StringVar(&pkg.ImageCMDOptions.ImageFilename, "object-name", "", "Cloud Storage image filename")
80-
Cmd.Flags().StringVar(&pkg.ImageCMDOptions.OsType, "ostype", "", "Image OS Type, accepted values are[aix, ibmi, redhat, sles]")
175+
Cmd.Flags().StringVar(&pkg.ImageCMDOptions.OsType, "ostype", "redhat", "Image OS Type, accepted values are[aix, ibmi, redhat, sles]")
81176
Cmd.Flags().StringVar(&pkg.ImageCMDOptions.StorageType, "storagetype", "tier3", "Storage type, accepted values are [tier1, tier3]")
82177
_ = Cmd.MarkFlagRequired("bucket")
83-
_ = Cmd.MarkFlagRequired("accesskey")
84-
_ = Cmd.MarkFlagRequired("secretkey")
85178
_ = Cmd.MarkFlagRequired("image-name")
86179
_ = Cmd.MarkFlagRequired("object-name")
87180
_ = Cmd.MarkFlagRequired("region")

cmd/root.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ Integrated with the IBM Cloud platform for on-demand provisioning.
2020
2121
This is a tool built for the Power Systems Virtual Server helps managing and maintaining the resources easily`,
2222
SilenceUsage: true,
23+
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
24+
if pkg.Options.APIKey == "" {
25+
if key := os.Getenv("IBMCLOUD_API_KEY"); key != "" {
26+
klog.Infof("Using an API key from IBMCLOUD_API_KEY environment variable")
27+
pkg.Options.APIKey = key
28+
}
29+
}
30+
return nil
31+
},
2332
}
2433

2534
func init() {

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ go 1.15
55
require (
66
github.com/IBM-Cloud/bluemix-go v0.0.0-20200921095234-26d1d0148c62
77
github.com/IBM-Cloud/power-go-client v1.0.51
8+
github.com/IBM/go-sdk-core/v4 v4.8.2
89
github.com/IBM/ibm-cos-sdk-go v1.5.0
10+
github.com/IBM/platform-services-go-sdk v0.14.4
911
github.com/dgrijalva/jwt-go v3.2.0+incompatible
10-
github.com/go-openapi/strfmt v0.19.4
12+
github.com/go-openapi/strfmt v0.19.10
1113
github.com/klauspost/compress v1.11.1 // indirect
1214
github.com/klauspost/pgzip v1.2.5
1315
github.com/manifoldco/promptui v0.7.0
1416
github.com/olekukonko/tablewriter v0.0.4
15-
github.com/onsi/ginkgo v1.14.1 // indirect
16-
github.com/onsi/gomega v1.10.2 // indirect
1717
github.com/spf13/cobra v1.0.0
1818
k8s.io/klog/v2 v2.3.0
1919
)

0 commit comments

Comments
 (0)