Skip to content

Commit

Permalink
Create security scale test
Browse files Browse the repository at this point in the history
- Created concurrent maps for scale testing
- Created inspect and delete volumes
- Create summarizeErrorsFromStringErrorChanMap

Signed-off-by: jessicapwx <[email protected]>
  • Loading branch information
jessicapwx committed Aug 5, 2019
1 parent eb0178c commit 0e20c9f
Show file tree
Hide file tree
Showing 7 changed files with 312 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export BASE_DIR=$(shell git rev-parse --show-toplevel)
export GOPATH=$(shell echo ${BASE_DIR}| sed 's@\(.*\)/src/github.com.*@\1@g')
all: sdk-test

sdk-test:
Expand Down
3 changes: 3 additions & 0 deletions cmd/sdk-test/sdk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ var (
cloudProviderConfigPath string
sharedSecret string
issuer string
junitfile string
)

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

Expand Down Expand Up @@ -78,6 +80,7 @@ func TestSanity(t *testing.T) {
SharedSecret: sharedSecret,
Issuer: issuer,
ProviderConfig: cfg,
JUnitFile: junitfile,
})
}

Expand Down
11 changes: 11 additions & 0 deletions hack/demo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

fail() {
echo "$1"
exit 1
}

PORT="9020"
GWPORT="8181"
make install
./cmd/sdk-test/sdk-test --ginkgo.focus="Security" --ginkgo.v --sdk.endpoint=70.0.74.173:${PORT} --sdk.issuer="openstorage.io" --sdk.sharedsecret="Password1"
70 changes: 70 additions & 0 deletions pkg/common/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package common

import (
"sync"
)

type ConcMap struct {
l sync.RWMutex
KVMap map[interface{}]interface{}
}

func NewConcMap() *ConcMap {
return &ConcMap{
KVMap: make(map[interface{}]interface{}),
}
}

func (c *ConcMap) Add(key interface{}, value interface{}) {
c.l.Lock()
defer c.l.Unlock()
c.KVMap[key] = value
}

func (c *ConcMap) GetKeyValMap() map[interface{}]interface{} {
return c.KVMap
}

type ConcStrToStrMap struct {
l sync.RWMutex
KVMap map[string]string
}

func NewConcStrToStrMap() *ConcStrToStrMap {
return &ConcStrToStrMap{
KVMap: make(map[string]string),
}
}

func (c *ConcStrToStrMap) Add(key string, value string) {
c.l.Lock()
defer c.l.Unlock()
c.KVMap[key] = value
}

func (c *ConcStrToStrMap) GetKeyValMap() map[string]string {
return c.KVMap
}

type ConcStringErrChanMap struct {
l sync.RWMutex
StrErrChanMap map[string]chan (error)
}

func NewConcStringErrChanMap() *ConcStringErrChanMap {
return &ConcStringErrChanMap{
StrErrChanMap: make(map[string]chan (error)),
}
}

func (c *ConcStringErrChanMap) Add(key string, value chan (error)) {
c.l.Lock()
defer c.l.Unlock()
c.StrErrChanMap[key] = value
}

func (c *ConcStringErrChanMap) GetKeyValMap() map[string]chan (error) {
c.l.Lock()
defer c.l.Unlock()
return c.StrErrChanMap
}
10 changes: 9 additions & 1 deletion pkg/sanity/sanity.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"google.golang.org/grpc/connectivity"

. "github.com/onsi/ginkgo"
"github.com/onsi/ginkgo/reporters"
. "github.com/onsi/gomega"
)

Expand All @@ -52,6 +53,7 @@ type SanityConfiguration struct {
SharedSecret string
Issuer string
ProviderConfig *CloudProviderConfig
JUnitFile string
}

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

config = reqConfig
RegisterFailHandler(Fail)
RunSpecs(t, "OpenStorage SDK Test Suite")
//RunSpecs(t, "OpenStorage SDK Test Suite")
var specReporters []Reporter
if reqConfig.JUnitFile != "" {
junitReporter := reporters.NewJUnitReporter(reqConfig.JUnitFile)
specReporters = append(specReporters, junitReporter)
}
RunSpecsWithDefaultAndCustomReporters(t, "OpenStorage SDK Test Suite", specReporters)
}

var _ = BeforeSuite(func() {
Expand Down
165 changes: 165 additions & 0 deletions pkg/sanity/securityScale.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package sanity

import (
"context"
"fmt"
"sync"
"time"

api "github.com/libopenstorage/openstorage-sdk-clients/sdk/golang"
common "github.com/libopenstorage/sdk-test/pkg/common"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

var scaleUsers map[string]string
var userVolumeMap *common.ConcMap

type VolumeRequest struct {
VolID string
CreateRequest *api.SdkVolumeCreateRequest
Token string
}

var _ = Describe("Security Scale", func() {
var (
c api.OpenStorageVolumeClient
ic api.OpenStorageIdentityClient
)

BeforeEach(func() {
c = api.NewOpenStorageVolumeClient(conn)
ic = api.NewOpenStorageIdentityClient(conn)
isSupported := isCapabilitySupported(
ic,
api.SdkServiceCapability_OpenStorageService_VOLUME,
)
if !isSupported {
Fail("Volume capability not supported , skipping related tests")
}
})

AfterEach(func() {
})

Describe("Security", func() {

BeforeEach(func() {
})

It("Should be able to create the users", func() {
By("Creating users")
scaleUsers = createXUsersTokens("scaleUsers", 30)
})
It("Should be able to create the volumes", func() {
By("Creating volumes")
err := createVolumesConcurrently(c)
Expect(err).NotTo(HaveOccurred())
})
It("Should be able to inspect the created Volume", func() {
By("Inspecting volumes")
err := inspectVolumesConcurrently(c)
Expect(err).NotTo(HaveOccurred())
})
It("Owner Should be able to delete its own Volume", func() {
By("Deleting volumes")
err := deleteVolumesConcurrently(c)
Expect(err).NotTo(HaveOccurred())
})
})

})

func createVolumesConcurrently(c api.OpenStorageVolumeClient) error {
//userVolumeMap is mapping user'name to volumes' ID
userVolumeMap = common.NewConcMap()
var volErrorMap = common.NewConcStringErrChanMap()
var wg sync.WaitGroup
for name, userToken := range scaleUsers {
userName := name
token := userToken
wg.Add(1)
go func(userName string, token string) {
defer wg.Done()
t := time.Now()
tstr := t.Format("20060102150405")
req := &api.SdkVolumeCreateRequest{
Name: "sdk-vol-" + tstr + "-" + userName,
Spec: &api.VolumeSpec{
Size: uint64(5 * GIGABYTE),
HaLevel: 2,
},
}
createResponse, err := c.Create(setContextWithToken(context.Background(), token), req)
volID := createResponse.VolumeId
resp, err := c.Inspect(
setContextWithToken(context.Background(), token),
&api.SdkVolumeInspectRequest{
VolumeId: volID,
},
)
printVolumeDetails(resp.Volume)
userVolumeMap.Add(userName, resp.GetVolume().GetId())
errChan := make(chan (error), 1)
errChan <- err
volErrorMap.Add(volID, errChan)
}(userName, token)
}
wg.Wait()
for user, volID := range userVolumeMap.GetKeyValMap() {
fmt.Printf("\nuser %s createdvolume ->: %s", user, volID)
}
return summarizeErrorsFromStringErrorChanMap(volErrorMap.GetKeyValMap())
}

func inspectVolumesConcurrently(c api.OpenStorageVolumeClient) error {
var wg sync.WaitGroup
var volErrorMap = common.NewConcStringErrChanMap()
for user, id := range userVolumeMap.GetKeyValMap() {
userName := user.(string)
volID := id.(string)
fmt.Printf("\nNow user %s is going to inspect volume %s", userName, volID)
token := scaleUsers[userName]
wg.Add(1)
go func(userName string, volID string, token string) {
defer wg.Done()
_, err := c.Inspect(
setContextWithToken(context.Background(), token),
&api.SdkVolumeInspectRequest{
VolumeId: volID,
},
)
errChan := make(chan (error), 1)
errChan <- err
volErrorMap.Add(volID, errChan)
}(userName, volID, token)
}
wg.Wait()
//Receiving all errors from channels
return summarizeErrorsFromStringErrorChanMap(volErrorMap.GetKeyValMap())
}

func deleteVolumesConcurrently(c api.OpenStorageVolumeClient) error {
var wg sync.WaitGroup
var volErrorMap = common.NewConcStringErrChanMap()
for user, id := range userVolumeMap.GetKeyValMap() {
userName := user.(string)
volID := id.(string)
token := scaleUsers[userName]
fmt.Printf("\nNow user %s is going to delete volume %s", userName, volID)
wg.Add(1)
go func(userName string, volID string, token string) {
defer wg.Done()
err := deleteVol(
setContextWithToken(context.Background(), token),
c,
volID,
)
errChan := make(chan (error), 1)
errChan <- err
volErrorMap.Add(volID, errChan)
}(userName, volID, token)
}
wg.Wait()
return summarizeErrorsFromStringErrorChanMap(volErrorMap.GetKeyValMap())
}
53 changes: 52 additions & 1 deletion pkg/sanity/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ package sanity
import (
"context"
"fmt"
"strings"
"sync"
"time"

api "github.com/libopenstorage/openstorage-sdk-clients/sdk/golang"
"github.com/libopenstorage/sdk-test/pkg/auth"
auth "github.com/libopenstorage/sdk-test/pkg/auth"
common "github.com/libopenstorage/sdk-test/pkg/common"
"google.golang.org/grpc/metadata"

. "github.com/onsi/gomega"
Expand Down Expand Up @@ -102,6 +105,33 @@ func createUsersTokens() map[string]string {
return users
}

func createXUsersTokens(prefix string, amount int) map[string]string {
users := common.NewConcStrToStrMap()
if amount <= 0 {
return users.GetKeyValMap()
}
var wg sync.WaitGroup
for i := 0; i < amount; i++ {
name := fmt.Sprintf("%s%d", prefix, i)
wg.Add(1)
go func(name string) {
defer wg.Done()
user := createToken(&auth.Claims{
Subject: name,
Name: name,
Email: fmt.Sprintf("%[email protected]", name),
Roles: []string{"system.user"},
Groups: []string{"users"},
}, &auth.Options{
Expiration: time.Now().Add(1 * time.Hour).Unix(),
}, config.SharedSecret)
users.Add(name, user)
}(name)
}
wg.Wait()
return users.GetKeyValMap()
}

func setContextWithToken(ctx context.Context, token string) context.Context {
md := metadata.New(map[string]string{
"authorization": "bearer " + token,
Expand Down Expand Up @@ -395,3 +425,24 @@ func deleteVol(ctx context.Context, vc api.OpenStorageVolumeClient, volid string
})
return err
}

func printVolumeDetails(
volume *api.Volume,
) {
fmt.Printf("volume ID: %s\n", volume.Id)
}

func summarizeErrorsFromStringErrorChanMap(stringErrMap map[string]chan (error)) error {
var summarizedErrMsg string
for key, errChan := range stringErrMap {
err := <-errChan
if err != nil {
summarizedErrMsg = fmt.Sprintf("%s\nerror of %s: %v", summarizedErrMsg, key, err)
}
}
fmt.Printf("\nsummarizedErrMsg: %s", summarizedErrMsg)
if strings.TrimSpace(summarizedErrMsg) == "" {
return nil
}
return fmt.Errorf("%s", summarizedErrMsg)
}

0 comments on commit 0e20c9f

Please sign in to comment.