Skip to content

Commit

Permalink
Merge pull request #281 from BrendanThompson/feature/custom-security-…
Browse files Browse the repository at this point in the history
…attributes

Feature - Add support for Custom Security Attributes
  • Loading branch information
manicminer authored May 17, 2024
2 parents 62b6cdf + 1c56ff6 commit baf3912
Show file tree
Hide file tree
Showing 7 changed files with 667 additions and 3 deletions.
9 changes: 8 additions & 1 deletion internal/test/random.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,16 @@ func init() {

// RandomString returns a random alphanumeric string useful for testing purposes.
func RandomString() string {
chars := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
alpha := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
numeric := []rune("0123456789")
chars := append(alpha, numeric...)

s := make([]rune, 8)
for i := range s {
if i == 0 {
s[i] = alpha[source.Intn(len(alpha))]
}

s[i] = chars[source.Intn(len(chars))]
}
return string(s)
Expand Down
16 changes: 14 additions & 2 deletions internal/test/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,14 @@ type Test struct {
ApplicationTemplatesClient *msgraph.ApplicationTemplatesClient
ApplicationsClient *msgraph.ApplicationsClient
AppRoleAssignedToClient *msgraph.AppRoleAssignedToClient
AttributeSetClient *msgraph.AttributeSetClient
AuthenticationMethodsClient *msgraph.AuthenticationMethodsClient
AuthenticationStrengthPoliciesClient *msgraph.AuthenticationStrengthPoliciesClient
B2CUserFlowClient *msgraph.B2CUserFlowClient
ClaimsMappingPolicyClient *msgraph.ClaimsMappingPolicyClient
ConditionalAccessPoliciesClient *msgraph.ConditionalAccessPoliciesClient
ConnectedOrganizationClient *msgraph.ConnectedOrganizationClient
CustomSecurityAttributeDefinitionClient *msgraph.CustomSecurityAttributeDefinitionClient
DelegatedPermissionGrantsClient *msgraph.DelegatedPermissionGrantsClient
DirectoryAuditReportsClient *msgraph.DirectoryAuditReportsClient
DirectoryObjectsClient *msgraph.DirectoryObjectsClient
Expand Down Expand Up @@ -150,8 +152,9 @@ type Test struct {
}

func NewTest(t *testing.T) (c *Test) {
ctx := context.Background()
var cancel context.CancelFunc
var ctx context.Context = context.Background()
var err error

if deadline, ok := t.Deadline(); ok {
ctx, cancel = context.WithDeadline(ctx, deadline)
Expand All @@ -178,7 +181,6 @@ func NewTest(t *testing.T) (c *Test) {
conn3.Authorize(ctx, conn.AuthConfig.Environment.MicrosoftGraph)
c.Connections["connected"] = conn3

var err error
c.Token, err = conn.Authorizer.Token(ctx, &http.Request{})
if err != nil {
t.Fatalf("could not acquire access token: %v", err)
Expand Down Expand Up @@ -260,6 +262,11 @@ func NewTest(t *testing.T) (c *Test) {
c.AppRoleAssignedToClient.BaseClient.Endpoint = *endpoint
c.AppRoleAssignedToClient.BaseClient.RetryableClient.RetryMax = retry

c.AttributeSetClient = msgraph.NewAttributeSetClient()
c.AttributeSetClient.BaseClient.Authorizer = c.Connections["default"].Authorizer
c.AttributeSetClient.BaseClient.Endpoint = *endpoint
c.AttributeSetClient.BaseClient.RetryableClient.RetryMax = retry

c.AuthenticationMethodsClient = msgraph.NewAuthenticationMethodsClient()
c.AuthenticationMethodsClient.BaseClient.Authorizer = c.Connections["default"].Authorizer
c.AuthenticationMethodsClient.BaseClient.Endpoint = *endpoint
Expand Down Expand Up @@ -290,6 +297,11 @@ func NewTest(t *testing.T) (c *Test) {
c.ConnectedOrganizationClient.BaseClient.Endpoint = *endpoint
c.ConnectedOrganizationClient.BaseClient.RetryableClient.RetryMax = retry

c.CustomSecurityAttributeDefinitionClient = msgraph.NewCustomSecurityAttributeDefinitionClient()
c.CustomSecurityAttributeDefinitionClient.BaseClient.Authorizer = c.Connections["default"].Authorizer
c.CustomSecurityAttributeDefinitionClient.BaseClient.Endpoint = *endpoint
c.CustomSecurityAttributeDefinitionClient.BaseClient.RetryableClient.RetryMax = retry

c.DelegatedPermissionGrantsClient = msgraph.NewDelegatedPermissionGrantsClient()
c.DelegatedPermissionGrantsClient.BaseClient.Authorizer = c.Connections["default"].Authorizer
c.DelegatedPermissionGrantsClient.BaseClient.Endpoint = *endpoint
Expand Down
165 changes: 165 additions & 0 deletions msgraph/attribute_set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package msgraph

import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"

"github.com/hashicorp/go-azure-sdk/sdk/odata"
)

const (
attributeSetEntity = "/directory/attributeSets"
)

type AttributeSetClient struct {
BaseClient Client
}

func NewAttributeSetClient() *AttributeSetClient {
return &AttributeSetClient{
BaseClient: NewClient(Version10),
}
}

func (c *AttributeSetClient) List(ctx context.Context, query odata.Query) (*[]AttributeSet, int, error) {
resp, status, _, err := c.BaseClient.Get(
ctx,
GetHttpRequestInput{
OData: query,
ValidStatusCodes: []int{http.StatusOK},
Uri: Uri{
Entity: attributeSetEntity,
},
},
)
if err != nil {
return nil, status, fmt.Errorf("AttributeSet.BaseClient.Get(): %v", err)
}

defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, status, fmt.Errorf("io.ReadAll(): %v", err)
}

var data struct {
AttributeSets []AttributeSet `json:"value"`
}

if err := json.Unmarshal(respBody, &data); err != nil {
return nil, status, fmt.Errorf("json.Unmarshal(): %v", err)
}

return &data.AttributeSets, status, nil
}

func (c *AttributeSetClient) Create(ctx context.Context, attributeSet AttributeSet) (*AttributeSet, int, error) {
var status int
var newAttributeSet AttributeSet

body, err := json.Marshal(attributeSet)
if err != nil {
return nil, status, fmt.Errorf("json.Marshal(): %v", err)
}

requestInput := PostHttpRequestInput{
Body: body,
OData: odata.Query{
Metadata: odata.MetadataFull,
},
ValidStatusCodes: []int{
http.StatusCreated,
http.StatusOK,
},
Uri: Uri{
Entity: attributeSetEntity,
},
}

resp, status, _, err := c.BaseClient.Post(ctx, requestInput)
if err != nil {
return nil, status, fmt.Errorf("AttributeSetClient.BaseClient.Post(): %v", err)
}

defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, status, fmt.Errorf("io.ReadAll(): %v", err)
}

if err := json.Unmarshal(respBody, &newAttributeSet); err != nil {
return nil, status, fmt.Errorf("json.Unmarshal():%v", err)
}

return &newAttributeSet, status, nil
}

func (c *AttributeSetClient) Get(ctx context.Context, id string, query odata.Query) (*AttributeSet, int, error) {
var AttributeSet AttributeSet

resp, status, _, err := c.BaseClient.Get(
ctx,
GetHttpRequestInput{
ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc,
OData: query,
ValidStatusCodes: []int{http.StatusOK},
Uri: Uri{
Entity: fmt.Sprintf("%s/%s", attributeSetEntity, id),
},
},
)
if err != nil {
return nil, status, fmt.Errorf("AttributeSetClient.BaseClient.Get(): %v", err)
}

defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, status, fmt.Errorf("io.ReadAll(): %v", err)
}

if err := json.Unmarshal(respBody, &AttributeSet); err != nil {
return nil, status, fmt.Errorf("json.Unmarshal(): %v", err)
}

return &AttributeSet, status, nil
}

func (c *AttributeSetClient) Update(ctx context.Context, AttributeSet AttributeSet) (int, error) {
var status int

if AttributeSet.ID == nil {
return status, fmt.Errorf("cannot update AttributeSet with a nil ID")
}

id := *AttributeSet.ID
AttributeSet.ID = nil

body, err := json.Marshal(AttributeSet)
if err != nil {
return status, fmt.Errorf("json.Marshal(): %v", err)
}

_, status, _, err = c.BaseClient.Patch(
ctx,
PatchHttpRequestInput{
Body: body,
ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc,
ValidStatusCodes: []int{
http.StatusOK,
http.StatusNoContent,
},
Uri: Uri{
Entity: fmt.Sprintf("%s/%s", attributeSetEntity, id),
},
},
)
if err != nil {
return status, fmt.Errorf("AttributeSetClient.BaseClient.Patch(): %v", err)
}

return status, nil
}
107 changes: 107 additions & 0 deletions msgraph/attribute_set_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package msgraph_test

import (
"net/http"
"testing"

"github.com/hashicorp/go-azure-sdk/sdk/odata"
"github.com/manicminer/hamilton/internal/test"
"github.com/manicminer/hamilton/internal/utils"
"github.com/manicminer/hamilton/msgraph"
)

const attributeSetId = "test"

func TestAttributeSetClient(t *testing.T) {
c := test.NewTest(t)
defer c.CancelFunc()

c.AttributeSetClient.BaseClient.DisableRetries = true
_, status, err := c.AttributeSetClient.Get(c.Context, attributeSetId, odata.Query{})
c.AttributeSetClient.BaseClient.DisableRetries = false
if err != nil {
if status != http.StatusNotFound {
t.Fatalf("AttributeSetClient.Get(): unable to retrieve attribute set for testing: %v", err)
}

testAttributeSetClientCreate(
t,
c,
msgraph.AttributeSet{
Description: utils.StringPtr("test attribute set"),
ID: utils.StringPtr(attributeSetId),
},
)
}

testAttributeSetClientGet(t, c, attributeSetId)
testAttributeSetClientUpdate(
t,
c,
msgraph.AttributeSet{
ID: utils.StringPtr(attributeSetId),
Description: utils.StringPtr("updated test description"),
},
)

testAttributeSetClientList(t, c)
}

func testAttributeSetClientCreate(t *testing.T, c *test.Test, csad msgraph.AttributeSet) *msgraph.AttributeSet {

attributeSet, status, err := c.AttributeSetClient.Create(c.Context, csad)
if err != nil {
t.Fatalf("AttributeSetClient.Create(): %v", err)
}
if status < 200 || status >= 300 {
t.Fatalf("AttributeSetClient.Create(): invalid status:%d", status)
}
if attributeSet == nil {
t.Fatalf("AttributeSet.Create(): attributeSet was nil")
}
if attributeSet.ID == nil {
t.Fatalf("AttributeSetClient.Create(): attributeSet.ID was nil")
}

return attributeSet
}

func testAttributeSetClientGet(t *testing.T, c *test.Test, id string) *msgraph.AttributeSet {
attributeSet, status, err := c.AttributeSetClient.Get(c.Context, id, odata.Query{})
if err != nil {
t.Fatalf("AttributeSetClient.Get(): %v", err)
}
if status < 200 || status >= 300 {
t.Fatalf("AttributeSet.Client.Get(): invalid status: %d", status)
}
if attributeSet == nil {
t.Fatalf("AttributeSetClient.Get(): attributeSet was nil")
}

return attributeSet
}

func testAttributeSetClientList(t *testing.T, c *test.Test) *[]msgraph.AttributeSet {
attributeSets, _, err := c.AttributeSetClient.List(
c.Context,
odata.Query{Top: 10},
)
if err != nil {
t.Fatalf("AttributeSetClient.List(): %v", err)
}
if attributeSets == nil {
t.Fatalf("AttributeSetClient.List(): attributeSets was nil")
}

return attributeSets
}

func testAttributeSetClientUpdate(t *testing.T, c *test.Test, csad msgraph.AttributeSet) {
status, err := c.AttributeSetClient.Update(c.Context, csad)
if err != nil {
t.Fatalf("AttributeSetClient.Update(): %v", err)
}
if status < 200 || status >= 300 {
t.Fatalf("AttributeSetClient.Update(): invalid status: %d", status)
}
}
Loading

0 comments on commit baf3912

Please sign in to comment.