Skip to content

Commit 0e20c9f

Browse files
committed
Create security scale test
- Created concurrent maps for scale testing - Created inspect and delete volumes - Create summarizeErrorsFromStringErrorChanMap Signed-off-by: jessicapwx <jessica@portworx.com>
1 parent eb0178c commit 0e20c9f

7 files changed

Lines changed: 312 additions & 2 deletions

File tree

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
export BASE_DIR=$(shell git rev-parse --show-toplevel)
2+
export GOPATH=$(shell echo ${BASE_DIR}| sed 's@\(.*\)/src/github.com.*@\1@g')
13
all: sdk-test
24

35
sdk-test:

cmd/sdk-test/sdk_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ var (
3737
cloudProviderConfigPath string
3838
sharedSecret string
3939
issuer string
40+
junitfile string
4041
)
4142

4243
func init() {
@@ -46,6 +47,7 @@ func init() {
4647
flag.StringVar(&cloudProviderConfigPath, prefix+"cpg", "", "Cloud Provider config file , optional")
4748
flag.StringVar(&sharedSecret, prefix+"sharedsecret", "", "Shared secret for auth, ownership, and role testing")
4849
flag.StringVar(&issuer, prefix+"issuer", "openstorage.io", "Issuer of token")
50+
flag.StringVar(&junitfile, prefix+"junitfile", "report.xml", "XML test report")
4951
flag.Parse()
5052
}
5153

@@ -78,6 +80,7 @@ func TestSanity(t *testing.T) {
7880
SharedSecret: sharedSecret,
7981
Issuer: issuer,
8082
ProviderConfig: cfg,
83+
JUnitFile: junitfile,
8184
})
8285
}
8386

hack/demo.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/bash
2+
3+
fail() {
4+
echo "$1"
5+
exit 1
6+
}
7+
8+
PORT="9020"
9+
GWPORT="8181"
10+
make install
11+
./cmd/sdk-test/sdk-test --ginkgo.focus="Security" --ginkgo.v --sdk.endpoint=70.0.74.173:${PORT} --sdk.issuer="openstorage.io" --sdk.sharedsecret="Password1"

pkg/common/common.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package common
2+
3+
import (
4+
"sync"
5+
)
6+
7+
type ConcMap struct {
8+
l sync.RWMutex
9+
KVMap map[interface{}]interface{}
10+
}
11+
12+
func NewConcMap() *ConcMap {
13+
return &ConcMap{
14+
KVMap: make(map[interface{}]interface{}),
15+
}
16+
}
17+
18+
func (c *ConcMap) Add(key interface{}, value interface{}) {
19+
c.l.Lock()
20+
defer c.l.Unlock()
21+
c.KVMap[key] = value
22+
}
23+
24+
func (c *ConcMap) GetKeyValMap() map[interface{}]interface{} {
25+
return c.KVMap
26+
}
27+
28+
type ConcStrToStrMap struct {
29+
l sync.RWMutex
30+
KVMap map[string]string
31+
}
32+
33+
func NewConcStrToStrMap() *ConcStrToStrMap {
34+
return &ConcStrToStrMap{
35+
KVMap: make(map[string]string),
36+
}
37+
}
38+
39+
func (c *ConcStrToStrMap) Add(key string, value string) {
40+
c.l.Lock()
41+
defer c.l.Unlock()
42+
c.KVMap[key] = value
43+
}
44+
45+
func (c *ConcStrToStrMap) GetKeyValMap() map[string]string {
46+
return c.KVMap
47+
}
48+
49+
type ConcStringErrChanMap struct {
50+
l sync.RWMutex
51+
StrErrChanMap map[string]chan (error)
52+
}
53+
54+
func NewConcStringErrChanMap() *ConcStringErrChanMap {
55+
return &ConcStringErrChanMap{
56+
StrErrChanMap: make(map[string]chan (error)),
57+
}
58+
}
59+
60+
func (c *ConcStringErrChanMap) Add(key string, value chan (error)) {
61+
c.l.Lock()
62+
defer c.l.Unlock()
63+
c.StrErrChanMap[key] = value
64+
}
65+
66+
func (c *ConcStringErrChanMap) GetKeyValMap() map[string]chan (error) {
67+
c.l.Lock()
68+
defer c.l.Unlock()
69+
return c.StrErrChanMap
70+
}

pkg/sanity/sanity.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"google.golang.org/grpc/connectivity"
3030

3131
. "github.com/onsi/ginkgo"
32+
"github.com/onsi/ginkgo/reporters"
3233
. "github.com/onsi/gomega"
3334
)
3435

@@ -52,6 +53,7 @@ type SanityConfiguration struct {
5253
SharedSecret string
5354
Issuer string
5455
ProviderConfig *CloudProviderConfig
56+
JUnitFile string
5557
}
5658

5759
// Test will test start the sanity tests
@@ -61,7 +63,13 @@ func Test(t *testing.T, reqConfig *SanityConfiguration) {
6163

6264
config = reqConfig
6365
RegisterFailHandler(Fail)
64-
RunSpecs(t, "OpenStorage SDK Test Suite")
66+
//RunSpecs(t, "OpenStorage SDK Test Suite")
67+
var specReporters []Reporter
68+
if reqConfig.JUnitFile != "" {
69+
junitReporter := reporters.NewJUnitReporter(reqConfig.JUnitFile)
70+
specReporters = append(specReporters, junitReporter)
71+
}
72+
RunSpecsWithDefaultAndCustomReporters(t, "OpenStorage SDK Test Suite", specReporters)
6573
}
6674

6775
var _ = BeforeSuite(func() {

pkg/sanity/securityScale.go

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package sanity
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"sync"
7+
"time"
8+
9+
api "github.com/libopenstorage/openstorage-sdk-clients/sdk/golang"
10+
common "github.com/libopenstorage/sdk-test/pkg/common"
11+
. "github.com/onsi/ginkgo"
12+
. "github.com/onsi/gomega"
13+
)
14+
15+
var scaleUsers map[string]string
16+
var userVolumeMap *common.ConcMap
17+
18+
type VolumeRequest struct {
19+
VolID string
20+
CreateRequest *api.SdkVolumeCreateRequest
21+
Token string
22+
}
23+
24+
var _ = Describe("Security Scale", func() {
25+
var (
26+
c api.OpenStorageVolumeClient
27+
ic api.OpenStorageIdentityClient
28+
)
29+
30+
BeforeEach(func() {
31+
c = api.NewOpenStorageVolumeClient(conn)
32+
ic = api.NewOpenStorageIdentityClient(conn)
33+
isSupported := isCapabilitySupported(
34+
ic,
35+
api.SdkServiceCapability_OpenStorageService_VOLUME,
36+
)
37+
if !isSupported {
38+
Fail("Volume capability not supported , skipping related tests")
39+
}
40+
})
41+
42+
AfterEach(func() {
43+
})
44+
45+
Describe("Security", func() {
46+
47+
BeforeEach(func() {
48+
})
49+
50+
It("Should be able to create the users", func() {
51+
By("Creating users")
52+
scaleUsers = createXUsersTokens("scaleUsers", 30)
53+
})
54+
It("Should be able to create the volumes", func() {
55+
By("Creating volumes")
56+
err := createVolumesConcurrently(c)
57+
Expect(err).NotTo(HaveOccurred())
58+
})
59+
It("Should be able to inspect the created Volume", func() {
60+
By("Inspecting volumes")
61+
err := inspectVolumesConcurrently(c)
62+
Expect(err).NotTo(HaveOccurred())
63+
})
64+
It("Owner Should be able to delete its own Volume", func() {
65+
By("Deleting volumes")
66+
err := deleteVolumesConcurrently(c)
67+
Expect(err).NotTo(HaveOccurred())
68+
})
69+
})
70+
71+
})
72+
73+
func createVolumesConcurrently(c api.OpenStorageVolumeClient) error {
74+
//userVolumeMap is mapping user'name to volumes' ID
75+
userVolumeMap = common.NewConcMap()
76+
var volErrorMap = common.NewConcStringErrChanMap()
77+
var wg sync.WaitGroup
78+
for name, userToken := range scaleUsers {
79+
userName := name
80+
token := userToken
81+
wg.Add(1)
82+
go func(userName string, token string) {
83+
defer wg.Done()
84+
t := time.Now()
85+
tstr := t.Format("20060102150405")
86+
req := &api.SdkVolumeCreateRequest{
87+
Name: "sdk-vol-" + tstr + "-" + userName,
88+
Spec: &api.VolumeSpec{
89+
Size: uint64(5 * GIGABYTE),
90+
HaLevel: 2,
91+
},
92+
}
93+
createResponse, err := c.Create(setContextWithToken(context.Background(), token), req)
94+
volID := createResponse.VolumeId
95+
resp, err := c.Inspect(
96+
setContextWithToken(context.Background(), token),
97+
&api.SdkVolumeInspectRequest{
98+
VolumeId: volID,
99+
},
100+
)
101+
printVolumeDetails(resp.Volume)
102+
userVolumeMap.Add(userName, resp.GetVolume().GetId())
103+
errChan := make(chan (error), 1)
104+
errChan <- err
105+
volErrorMap.Add(volID, errChan)
106+
}(userName, token)
107+
}
108+
wg.Wait()
109+
for user, volID := range userVolumeMap.GetKeyValMap() {
110+
fmt.Printf("\nuser %s createdvolume ->: %s", user, volID)
111+
}
112+
return summarizeErrorsFromStringErrorChanMap(volErrorMap.GetKeyValMap())
113+
}
114+
115+
func inspectVolumesConcurrently(c api.OpenStorageVolumeClient) error {
116+
var wg sync.WaitGroup
117+
var volErrorMap = common.NewConcStringErrChanMap()
118+
for user, id := range userVolumeMap.GetKeyValMap() {
119+
userName := user.(string)
120+
volID := id.(string)
121+
fmt.Printf("\nNow user %s is going to inspect volume %s", userName, volID)
122+
token := scaleUsers[userName]
123+
wg.Add(1)
124+
go func(userName string, volID string, token string) {
125+
defer wg.Done()
126+
_, err := c.Inspect(
127+
setContextWithToken(context.Background(), token),
128+
&api.SdkVolumeInspectRequest{
129+
VolumeId: volID,
130+
},
131+
)
132+
errChan := make(chan (error), 1)
133+
errChan <- err
134+
volErrorMap.Add(volID, errChan)
135+
}(userName, volID, token)
136+
}
137+
wg.Wait()
138+
//Receiving all errors from channels
139+
return summarizeErrorsFromStringErrorChanMap(volErrorMap.GetKeyValMap())
140+
}
141+
142+
func deleteVolumesConcurrently(c api.OpenStorageVolumeClient) error {
143+
var wg sync.WaitGroup
144+
var volErrorMap = common.NewConcStringErrChanMap()
145+
for user, id := range userVolumeMap.GetKeyValMap() {
146+
userName := user.(string)
147+
volID := id.(string)
148+
token := scaleUsers[userName]
149+
fmt.Printf("\nNow user %s is going to delete volume %s", userName, volID)
150+
wg.Add(1)
151+
go func(userName string, volID string, token string) {
152+
defer wg.Done()
153+
err := deleteVol(
154+
setContextWithToken(context.Background(), token),
155+
c,
156+
volID,
157+
)
158+
errChan := make(chan (error), 1)
159+
errChan <- err
160+
volErrorMap.Add(volID, errChan)
161+
}(userName, volID, token)
162+
}
163+
wg.Wait()
164+
return summarizeErrorsFromStringErrorChanMap(volErrorMap.GetKeyValMap())
165+
}

pkg/sanity/utils.go

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@ package sanity
1919
import (
2020
"context"
2121
"fmt"
22+
"strings"
23+
"sync"
2224
"time"
2325

2426
api "github.com/libopenstorage/openstorage-sdk-clients/sdk/golang"
25-
"github.com/libopenstorage/sdk-test/pkg/auth"
27+
auth "github.com/libopenstorage/sdk-test/pkg/auth"
28+
common "github.com/libopenstorage/sdk-test/pkg/common"
2629
"google.golang.org/grpc/metadata"
2730

2831
. "github.com/onsi/gomega"
@@ -102,6 +105,33 @@ func createUsersTokens() map[string]string {
102105
return users
103106
}
104107

108+
func createXUsersTokens(prefix string, amount int) map[string]string {
109+
users := common.NewConcStrToStrMap()
110+
if amount <= 0 {
111+
return users.GetKeyValMap()
112+
}
113+
var wg sync.WaitGroup
114+
for i := 0; i < amount; i++ {
115+
name := fmt.Sprintf("%s%d", prefix, i)
116+
wg.Add(1)
117+
go func(name string) {
118+
defer wg.Done()
119+
user := createToken(&auth.Claims{
120+
Subject: name,
121+
Name: name,
122+
Email: fmt.Sprintf("%s@portworx.com", name),
123+
Roles: []string{"system.user"},
124+
Groups: []string{"users"},
125+
}, &auth.Options{
126+
Expiration: time.Now().Add(1 * time.Hour).Unix(),
127+
}, config.SharedSecret)
128+
users.Add(name, user)
129+
}(name)
130+
}
131+
wg.Wait()
132+
return users.GetKeyValMap()
133+
}
134+
105135
func setContextWithToken(ctx context.Context, token string) context.Context {
106136
md := metadata.New(map[string]string{
107137
"authorization": "bearer " + token,
@@ -395,3 +425,24 @@ func deleteVol(ctx context.Context, vc api.OpenStorageVolumeClient, volid string
395425
})
396426
return err
397427
}
428+
429+
func printVolumeDetails(
430+
volume *api.Volume,
431+
) {
432+
fmt.Printf("volume ID: %s\n", volume.Id)
433+
}
434+
435+
func summarizeErrorsFromStringErrorChanMap(stringErrMap map[string]chan (error)) error {
436+
var summarizedErrMsg string
437+
for key, errChan := range stringErrMap {
438+
err := <-errChan
439+
if err != nil {
440+
summarizedErrMsg = fmt.Sprintf("%s\nerror of %s: %v", summarizedErrMsg, key, err)
441+
}
442+
}
443+
fmt.Printf("\nsummarizedErrMsg: %s", summarizedErrMsg)
444+
if strings.TrimSpace(summarizedErrMsg) == "" {
445+
return nil
446+
}
447+
return fmt.Errorf("%s", summarizedErrMsg)
448+
}

0 commit comments

Comments
 (0)