Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create security scale test #35

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
245 changes: 245 additions & 0 deletions pkg/sanity/securityScale.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
package sanity

import (
"context"
"fmt"
"strings"
"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.ConcStrToStrMap

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("Should be disallowed to inspect other users' Volume", func() {
By("Inspecting other users' volumes")
err := inspectOtherVolumesConcurrently(c)
Expect(err).NotTo(HaveOccurred())
})
It("Should be disallowed to delete other users' Volume", func() {
By("Deleting other users' volumes")
err := deleteOtherVolumesConcurrently(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.NewConcStrToStrMap()
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 userName, volID := range userVolumeMap.GetKeyValMap() {
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 userName, volID := range userVolumeMap.GetKeyValMap() {
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())
}

func inspectOtherVolumesConcurrently(c api.OpenStorageVolumeClient) error {
var wg sync.WaitGroup
var volErrorMap = common.NewConcStringErrChanMap()
userVolumeKVMap := userVolumeMap.GetKeyValMap()
for userName, _ := range userVolumeKVMap {
otherUser := getKeyOtherThanInMap(userVolumeKVMap, userName)
if otherUser == "" {
return fmt.Errorf("failed to find a userName other than %s in userName-volume map", userName)
}
othersVolID := userVolumeKVMap[otherUser]
fmt.Printf("\nNow userName %s is going to inspect other user %s's volume %s", userName, otherUser, othersVolID)
token := scaleUsers[userName]
wg.Add(1)
go func(userName string, othersVolID string, token string) {
defer wg.Done()
_, err := c.Inspect(
setContextWithToken(context.Background(), token),
&api.SdkVolumeInspectRequest{
VolumeId: othersVolID,
},
)
errChan := make(chan (error), 1)
if isPermissionErr(err) {
err = nil
}
errChan <- err
volErrorMap.Add(othersVolID, errChan)
}(userName, othersVolID, token)
}
wg.Wait()
//Receiving all errors from channels
return summarizeErrorsFromStringErrorChanMap(volErrorMap.GetKeyValMap())
}

func deleteOtherVolumesConcurrently(c api.OpenStorageVolumeClient) error {
var wg sync.WaitGroup
var volErrorMap = common.NewConcStringErrChanMap()
userVolumeKVMap := userVolumeMap.GetKeyValMap()
for userName, _ := range userVolumeMap.GetKeyValMap() {
token := scaleUsers[userName]
otherUser := getKeyOtherThanInMap(userVolumeKVMap, userName)
if otherUser == "" {
return fmt.Errorf("failed to find a userName other than %s in userName-volume map", userName)
}
othersVolID := userVolumeKVMap[otherUser]
fmt.Printf("\nNow user %s is going to delete other user %s's volume %s", userName, otherUser, othersVolID)
wg.Add(1)
go func(userName string, othersVolID string, token string) {
defer wg.Done()
err := deleteVol(
setContextWithToken(context.Background(), token),
c,
othersVolID,
)
errChan := make(chan (error), 1)
if isPermissionErr(err) {
err = nil
}
errChan <- err
volErrorMap.Add(othersVolID, errChan)
}(userName, othersVolID, token)
}
wg.Wait()
return summarizeErrorsFromStringErrorChanMap(volErrorMap.GetKeyValMap())
}

func isPermissionErr(err error) bool {
if strings.Contains(fmt.Sprintf("%v", err), "PermissionDenied") {
return true
}
return false
}
Loading