GithubHelp home page GithubHelp logo

hamilton's People

Contributors

agileknight avatar alexwilcox9 avatar amarbut24 avatar askew avatar bubbletroubles avatar computeracer avatar ekristen avatar favoretti avatar iwarapter avatar jarifibrahim avatar joostvdoorn avatar kaovd avatar kenchan0130 avatar liammoat avatar manicminer avatar markdordoy avatar michaljirman avatar moio avatar owretch avatar panic-kbutton avatar rohrerb avatar scott-doyland-burrows avatar simongottschlag avatar swissgipfel avatar timja avatar tomasmota avatar tsologub avatar varantha avatar webframp avatar yriveiro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hamilton's Issues

add OData cast to OData query.

Would it be possible (or is there already a way to do it?) to add casting as part of constructing the OData query, as per example 3 and 4 from the official docs? https://docs.microsoft.com/en-us/graph/api/group-list-members?view=graph-rest-1.0&tabs=http

Because if I now for instance want to list all users that are members of a group I have to list all members, iterate through them and calling get on the user client and then I will of course get a bunch of 404 errs which I have to handle. Whereas if I could cast ListMembers to users then I would be set with that one call. Think this would also solve this issue. #20

Thanks for the SDK btw, replaced graphrbac with the official sdk only to discover build time went up an absurd amount.

msgraph.NewDirectoryObjectsClient().GetByIds() should provide more information in DirectoryObject

currently NewDirectoryObjectsClient().GetByIds() only provides following information:

type DirectoryObject struct {
	ODataId   *odata.Id   `json:"@odata.id,omitempty"`
	ODataType *odata.Type `json:"@odata.type,omitempty"`
	ID        *string     `json:"id,omitempty"`
}

would be good to have more information about the objects which is available in the response from MsGraph REST API, eg displayName, appId, alternativeNames, ...

or make provide a possible way to supply own struct here or only provide an dynamic interface here (to dynamically fetch data)

ProvisionOnDemand() in SynchronizationJobClient returns error even though provisioning was successful

SynchronizationJobClient ProvisionOnDemand() returns non-nil error although both logs and admin console declares provisioning has been successful .

my code

        jobs, _, err := syncJobClient.List(ctx, request.ServicePrincipalId)
	if err != nil {
		return fmt.Errorf("failed to get job from app(%v): %v", request.ServicePrincipalId, err)
	}
	ruleId := {RULE_ID}
	objType := "User"
	param := &msgraph.SynchronizationJobProvisionOnDemand{
		Parameters: &[]msgraph.SynchronizationJobApplicationParameters{{
			RuleId: &ruleId,
			Subjects: &[]msgraph.SynchronizationJobSubject{{
				ObjectId:       request.User.ID(),
				ObjectTypeName: &objType}},
		}},
	}
	if _, err := syncJobClient.ProvisionOnDemand(ctx, *(*jobs)[0].ID, param, request.ServicePrincipalId); err != nil {
		return fmt.Errorf("failed provisioning user(%v) to app(%v): %v", *request.User.ID(), request.ServicePrincipalId, err)
	}

admin console

image

Logs

SynchronizationJobClient.BaseClient.Post(): unexpected status 200 with response: {"@odata.context":"https://graph.microsoft.com/beta/$metadata#microsoft.graph.stringKeyStringValuePair","key":"Microsoft.Identity.Health.CPP.Common.DataContracts.SyncFabric.StatusInfo","value":"[{\"provisioningSteps\":[{\"name\":\"EntryImport\",\"type\":\"Import\",\"status\":\"Success\",\"description\":\"Retrieved User ' ' from Azure Active Directory","timestamp":"2023-01-03T03:21:28.5276533Z","details\โ€:HIDDEN},{"name":"EntryImport","type":"Matching","status":"Success","description":"Retrieved '[email protected]' from Google Cloud / Workspace","timestamp":"2023-01-03T03:21:29.3960403Z","details\โ€: HIDDEN,{"name":"EntrySynchronizationScoping","type":"Scoping","status":"Success","description":"Determine if User in scope by evaluating against each scoping filter","timestamp":"2023-01-03T03:21:29.4160394Z","details":{"Active in the source system":"True","Assigned to the application":"True","User has the required role":"True","Scoping filter evaluation passed":"True","ScopeEvaluationResult":"{}"}},{"name":"EntryExportUpdate","type":"Export","status":"Success","description":"User '[email protected]' was updated in Google Cloud / Workspace","timestamp":"2023-01-03T03:21:30.6197578Z","details":{}},{"name":"EntryExportUpdate","type":"Export","status":"Success","description":"User '[email protected]' was updated in Google Cloud / Workspace","timestamp":"2023-01-03T03:21:30.6237579Z","details":{}}],"modifiedProperties":[{"displayName":"emails.[type eq \"work\"].address","oldValue":null,"newValue":"[email protected]"}],"action":"Update","changeId":"4f9f0d6a-b8e0-4069-b0e2-a24ff5d578ff","endTime":"2023-01-03T03:21:30.6267623Z","reportableIdentifier":"[email protected]","sourceIdentity":{"id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","type":"User","name":null,"details":null},"sourceSystem":{"id":null,"name":"Azure Active Directory","details":null},"startTime":"2023-01-03T03:21:28.5206543Z","statusInfo":{"status":"Success","errorCode":null,"reason":null,"additionalDetails":null,"errorCategory":null,"recommendedAction":null},"targetIdentity":{"id":"104020537153314748066","type":"User","name":null,"details":null},"targetSystem":{"id":null,"name":"Google Cloud / Workspace","details":null}}]"}

Support for Chat Resource

Hi,

Is it possible to add support for the chat resource at all?

I'm able to get the data I need using msgraph.NewClient and providing an msgraph.GetHttpRequestInput with the relevant entity for now, but built in support would be awesome.

Many thanks,
D.

Support OIDC Authentication for Service Principals

It would be nice to have OIDC authentication support instead of just GitHub Tokens, which appears to be a more specific unique implementation only to GitHub that differs from Kubernetes and the "Other Issuer" for OIDC support for Service Principal Authentication

`Error: ServicePrincipalsClient.BaseClient.Get(): launching Azure CLI: pipe: too many open files`

I have around 605 service principals in my tenant.
I am calling the below function nearly concurrently for all the 605 service principals

func getAdServicePrincipalOwners(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
	servicePrincipalId := *h.Item.(msgraph.ServicePrincipal).ID
	session, err := GetNewSession(ctx, d)
	if err != nil {
		return nil, err
	}

	client := msgraph.NewServicePrincipalsClient(session.TenantID)
	client.BaseClient.Authorizer = session.Authorizer

	owners, _, err := client.ListOwners(ctx, servicePrincipalId)
	if err != nil {
		return nil, err
	}
	return owners, nil
}

Feature: Auth method should soft fail if no token is issued

Hi!

It would be great if there was a soft fail for when multiple auth methods are used.

As an example, if we're not able to get a token with MSI - the next method should be tried.

I've got a similar issue with azidentity: Azure/azure-sdk-for-go#14214

My personal opinion is that auth methods should be tried in the following order:

  1. Azure CLI
  2. Client secret
  3. Client cert
  4. MSI

Thanks!

Use of Resty client

First, nice work, very easy to understand, congrats

I have a question after reading your code, Did you think about the use resty? it's a small lib for REST that will handle backoff retries and you will be able to inject the oauth2 client.

Your code will get (even more) cleaner and easy to maintain probably.

BUG: Create group does not chunk members/owners

groups.go

As there is a limit of 20 link changes, AddMembers correctly splits the API calls into batches of 20. However, this logic is not followed when Create is called. This causes create group to fail when there is a combination of more than 20 owners + members.

Possible solution:

In Create, create the group with only owners (up to the first 20). Then use AddOwners to add the remaining owners and AddMembers to add all the members. Note: The group must not be created without owners as it will leave the possibility of the authenticated client unable to modify the group if it does not have directory admin permissions.

Support Additional Azure Environments

EnvironmentFromString hardcodes a list of supported environments. The Hashicorp Terraform Provider for AzureRM makes use of EnvironmentFromString here

Because the list is hardcoded, the terraform provider is useless for Azure environments whose URLs cannot be publicly published. Azure provides a method to discover the URLs for all the endpoints referenced in the Environment structure by using the metadata URL. A sample implementation of using this URL is located here

Please add EnvironmentFromMetadataUrl(url string) (Environment, error) to support additional Azure environments and make hamilton more globally useful.

Thanks!

MSI support in Azure Cloud Shell

Related: hashicorp/terraform-provider-azuread#633

Hamilton's MSI authentication doesn't consider the URL formats needed to get an MSI Access Token when run inside the cloud shell.

https://docs.microsoft.com/en-us/azure/cloud-shell/msi-authorization
The URL format is http://localhost:50342/oauth2/token

In https://github.com/manicminer/hamilton/blob/main/auth/msi.go#L115 we see the format of the URL expects to contain "/metadata", which is part of the URL when MSI is used in a VM, for instance
'http://169.254.169.254/metadata/identity/oauth2/token"

How best to support patching objects with Schema Extensions

This SDK supports creating schema extensions, however it does not yet support for example adding an extensions data to an allowed object, for example a user.

Reading the documentation/examples it looks like we need to perform a patch call against the target object, however our update functions for users/groups etc requires a user/group object which has no concept of the schema extension (as in theory it could be anything).

I'd like to extend the SDK to support these kind of updates, however i'm looking to get some opinions on the best way to achieve this.

I can get myself around the problem by writing my own function that expects the schema extension i want to use, but i want to make this generic and add to the SDK.

Im still new to writing go so i'll welcome the most simple options :-)

Is it possible to fetch synchronizationSchema?

msgraph.SynchronizationJobProvisionOnDemand requires RuleId of synchronization schema as its parameter for on-demand provisioning; but, so far I could not find implementations fetching the schema. The document can be found in below:

https://learn.microsoft.com/ja-jp/graph/api/resources/synchronization-synchronizationschema?view=graph-rest-beta

I have read several classes including SynchronizationJobClient, but if there is one, please let me know

Thanks in advance.

Feature: Information about current identity

Hi!

One thing I've been missing for a long time is to have "current user" information available easily.

Information that would be interesting:

  • User Type (normal user or service principal / other?)
  • Display Name
  • AppID
  • ObjectID

Not sure if this is actually possible, but a normal user does have information available from /me and I think some of the information should be available from the token. I know a service principal can lookup itself as long as it knows the AppID.

Thoughts? ๐Ÿ˜Š

Group writebackConfiguration

Hi, I have noticed that writebackConfiguration is not currently supported, is there a special reason for that? Is there another way to achieve that?

As far as I understand, all it requires is adding this to the group creation payload:

    "writebackConfiguration": {
        "isEnabled": true,
        "onPremisesGroupType":  UniversalSecurityGroup
    },

If there is no reason for this to not be there, I can make a PR for it

Identity Governance - Access Reviews

Running into an issue attempting to interact with /identityGovernance/accessReviews/definitions

type AccessReviewClient struct {
	BaseClient msgraph.Client
}

func NewAccessReviewClient(tenantId string) *AccessReviewClient {
	return &AccessReviewClient{
		BaseClient: msgraph.NewClient(msgraph.VersionBeta, tenantId),
	}
}

func main() {
	ctx := context.Background()

	clientSecret := os.Getenv("CLIENT_SECRET")
	authConfig := &auth.Config{
		Environment:            environments.USGovernmentL4,
		TenantID:               "<redacted>",
		ClientID:               "<redacted>",
		ClientSecret:           clientSecret,
		EnableClientSecretAuth: true,
	}

	authorizer, err := authConfig.NewAuthorizer(ctx, auth.MsGraph)
	if err != nil {
		log.Fatal(err)
	}

	accessReviewClient := NewAccessReviewClient(authConfig.TenantID)
	accessReviewClient.BaseClient.Authorizer = authorizer
	accessReviewClient.BaseClient.Endpoint = environments.MsGraphUSGovL4Endpoint

	resp, _, _, err := accessReviewClient.BaseClient.Get(ctx, msgraph.GetHttpRequestInput{
		ValidStatusCodes: []int{http.StatusOK},
		DisablePaging:    false,
		Uri: msgraph.Uri{
			Entity: "/identityGovernance/accessReviews/definitions",
			HasTenantId: true,
		},
	})
}

The response I get back is
"could not read response body: http: read on closed response body"

Did some digging with the help of @MarkDordoy
And found what we believe is the source of the issue

When performing this call via https://developer.microsoft.com/
Below is an example response (some details redacted)

{
    "@odata.context": "https://graph.microsoft.us/beta/$metadata#identityGovernance/accessReviews/definitions",
    "@odata.count": 4,
    "value": [
        {
            "id": "<redacted>",
            "displayName": "<redacted>",
            "createdDateTime": "<redacted>",
            "lastModifiedDateTime": "<redacted>",
            "status": "InProgress",
            "descriptionForAdmins": "",
            "descriptionForReviewers": "",
            "customDataProvider": null,
            "customData": null,
            "createdBy": {
                "id": "<redacted>",
                "displayName": "<redacted>",
                "type": null,
                "userPrincipalName": "<redacted>"
            },
            "scope": {
                "@odata.type": "#microsoft.graph.accessReviewQueryScope",
                "query": "<redacted>",
                "queryType": "MicrosoftGraph",
                "queryRoot": null
            },
            "instanceEnumerationScope": {
                "@odata.type": "#microsoft.graph.accessReviewQueryScope",
                "query": "<redacted>",
                "queryType": "MicrosoftGraph",
                "queryRoot": null
            },
            "reviewers": [
                {
                    "query": "<redacted>",
                    "queryType": "MicrosoftGraph",
                    "queryRoot": null
                },
                {
                    "query": "<redacted>",
                    "queryType": "MicrosoftGraph",
                    "queryRoot": null
                }
            ],
            "backupReviewers": [],
            "fallbackReviewers": [],
            "settings": {
                "mailNotificationsEnabled": true,
                "reminderNotificationsEnabled": true,
                "justificationRequiredOnApproval": true,
                "defaultDecisionEnabled": false,
                "defaultDecision": "None",
                "instanceDurationInDays": 30,
                "autoApplyDecisionsEnabled": false,
                "recommendationsEnabled": true,
                "recommendationLookBackDuration": "P30D",
                "recurrence": {
                    "pattern": null,
                    "range": {
                        "type": "numbered",
                        "numberOfOccurrences": 0,
                        "recurrenceTimeZone": null,
                        "startDate": "<redacted>",
                        "endDate": "<redacted>"
                    }
                },
                "applyActions": [
                    {
                        "@odata.type": "#microsoft.graph.removeAccessApplyAction"
                    }
                ]
            },
            "additionalNotificationRecipients": [],
            "[email protected]": "https://graph.microsoft.us/beta/$metadata#identityGovernance/accessReviews/definitions('<redacted>')/instances",
            "instances": []
        }
    ]
}

Specifically the return value of "@odata.count": 4, is important to note

https://github.com/manicminer/hamilton/blob/main/odata/odata.go#L89

type OData struct {
	Context      *string `json:"@odata.context"`
	MetadataEtag *string `json:"@odata.metadataEtag"`
	Type         *Type   `json:"@odata.type"`
	Count        *string `json:"@odata.count"`
	NextLink     *string `json:"@odata.nextLink"`
	Delta        *string `json:"@odata.delta"`
	DeltaLink    *string `json:"@odata.deltaLink"`
	Id           *Id     `json:"@odata.id"`
	Etag         *string `json:"@odata.etag"`

	Error *Error `json:"-"`

	Value interface{} `json:"value"`
}

when we changed the Count type from *string to *int the call was successful

Is it possible msgraph sometimes returns *string for Count and other times *int ?

Potential token refresh issue

Hi!

I'm using this great SDK in a proxy and after running for a few days it seems like token refresh stops working. Not sure exactly when it happens but it at least takes a few days. A restart of my proxy resolves the issue.

I have created an issue in my repo with some logs (that I think are related): XenitAB/azad-kube-proxy#118

Not completely sure this is caused by Hamilton, but creating issue and will get back with how I resolve it.

Move everything using Microsofts autorest to it's own module

Hi!

As always, love the job you are doing here! ๐Ÿฅ‡

As per our previous dialouge, it would be quite nice if hamilton could be used without having to import Microsofts autorest library.

I see two possible ways of handling this:

Choice 1 - new module in hamilton repo
PROS:

  • No need to switch between repositories
  • Everything in the same place and easy to find
  • Logical to find it here

CONS:

  • Go mono-repo support is still quite bad, need to handle a lot of stuff with scripts to keep everything in sync
  • Same as above, but we'll need to keep tags like auth/autorest/v0.39.0 in sync with v0.39.0
  • Same as above, but we'll need to update the go.mod of the autorest module after the main module has been updated/released

Choice 2 - new repository

PROS:

  • No need for special tooling, will just work
  • No need for special tags
  • Will work with Dependabot

CONS:

  • Will be a little harder to find
  • Will have to be updated after hamilton has been updated, but could be handled by dependabot

Conclusion

I would personally vote for a separate repository, hamilton-autorest, and just place everything that is using autorest there. This repository should be "clean" and easy to use - if autorest is needed it is available in a different place.

DirectoryObject and similar collection types

I'm still learning a bit how everything in here is wired up, sorry if this is a beginner question. I was wondering if you could briefly explain how this is used to build the odata id url refs? Where does Uri method bound to this type get called?

type DirectoryObject struct {
	ODataId   *odata.Id   `json:"@odata.id,omitempty"`
	ODataType *odata.Type `json:"@odata.type,omitempty"`
	ID        *string     `json:"id,omitempty"`
}

func (o *DirectoryObject) Uri(endpoint environments.ApiEndpoint, apiVersion ApiVersion) string {
	if o.ID == nil {
		return ""
	}
	return fmt.Sprintf("%s/%s/directoryObjects/%s", endpoint, apiVersion, *o.ID)
}

Thanks!

Feature: Make scopes configurable

Hi @manicminer!

See this as and idea / feature request.

It would be a nice feature if scopes was configurable, to make it possible to use the auth package to get access tokens for plain AAD applications.

I'm using azidentity right now for this. Would be able to slim down my dependencies to only your lib.

Struggling to get the msi authorizer to work

Hi, I'm having some issues with getting the msi authorizer to work. I'm kinda new to azure so might be something I'm not getting, but I'm getting this error when calling the groups client:

GroupsClient.BaseClient.Get(): MsiAuthorizer: failed to request token from metadata endpoint: Get "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fgraph.microsoft.com%2F": context deadline exceeded

This is how I set up the client and authorizer, am I missing something in the authConfig?

func NewClient(ctx context.Context, tenantID string) (*GraphClient, error) {
	environment := environments.Global

	authConfig := &auth.Config{
		EnableMsiAuth: true,
	}

	authorizer, err := authConfig.NewAuthorizer(ctx, environment.MsGraph)
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Print authorizer token")
	log.Println(authorizer.Token())

	usersClient := msgraph.NewUsersClient(tenantID)
	groupsClient := msgraph.NewGroupsClient(tenantID)
	objectsClient := msgraph.NewDirectoryObjectsClient(tenantID)
	servicePrincipalClient := msgraph.NewServicePrincipalsClient(tenantID)
	usersClient.BaseClient.Authorizer = authorizer
	groupsClient.BaseClient.Authorizer = authorizer
	objectsClient.BaseClient.Authorizer = authorizer
	servicePrincipalClient.BaseClient.Authorizer = authorizer

	return &GraphClient{
		*groupsClient,
		*usersClient,
		*objectsClient,
		*servicePrincipalClient,
	}, nil
}

It is deployed to a Kubernetes pod, and it prints a token which I'm able to decode.

The error message stems from msi.go line 47, and based on the "context deadline exceeded" I was wondering if it was some timeout issue?

Anything that might point me to a solution is much appreciated!
Thanks in advance :)

Identity Governance - Access Review Decisions Issue

Attempting to query below API endpoint -

GET 

/identityGovernance/accessReviews/definitions/{accessReviewScheduleDefinitionId}/instances/{accessReviewInstanceId}/decisions/

I'm running into a weird issue where some of the data is returning blank. In addition I'm getting interesting errors when attempting to debug in vscode

type AccessReviewDecisionClient struct {
	BaseClient msgraph.Client
}

func NewAccessReviewDecisionClient(tenantId string) *AccessReviewDecisionClient {
	return &AccessReviewDecisionClient{
		BaseClient: msgraph.NewClient(msgraph.Version10, tenantId),
	}
}

type ReviewedBy struct {
	ID                *string `json:"id,omitempty"`
	DisplayName       *string `json:"displayName,omitempty"`
	Type              *string `json:"type,omitempty"`
	UserPrincipalName *string `json:"userPrincipalName,omitempty"`
}

type AccessReviewDecision struct {
	Decision                    *string       `json:"decision,omitempty"`
	ID                          *string       `json:"id,omitempty"`
	Justification               *string       `json:"justification,omitempty"`
	LastModifiedDateTimeateTime *time.Time    `json:"lastModifiedDateTime,omitempty"`
	ReviewedBy                  *[]ReviewedBy `json:"reviewedBy,omitempty"`
	Status                      *string       `json:"target,omitempty"`
	Target                      *string       `json:"status,omitempty"`
}

// Get returns a list of AccessReviewDecisions
func (c *AccessReviewDecisionClient) Get(ctx context.Context, id string, query odata.Query) (*[]AccessReviewDecision, int, error) {
	resp, status, _, err := c.BaseClient.Get(ctx, msgraph.GetHttpRequestInput{
		DisablePaging:    query.Top > 0,
		ValidStatusCodes: []int{http.StatusOK},
		Uri: msgraph.Uri{
			Entity:      fmt.Sprintf("/identityGovernance/accessReviews/definitions/%s/instances/%s/decisions", id, id),
			Params:      query.Values(),
			HasTenantId: true,
		},
	})
	if err != nil {
		return nil, status, fmt.Errorf("AccessReviewDecisionClient.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 {
		AccessReviewDecisions []AccessReviewDecision `json:"value"`
	}
	if err := json.Unmarshal(respBody, &data); err != nil {
		return nil, status, fmt.Errorf("json.Unmarshal(): %v", err)
	}

	return &data.AccessReviewDecisions, status, nil
}


During the debug I've narrowed it down to the response itself - https://github.com/manicminer/hamilton/blob/main/msgraph/client.go#L209

As I attempt to see what is being returned specifically for the reviewedBy property within the o var the value is blank
image

Interestingly I get below errors when attempting to expand the reviewedBy property in vscode (which I'm not sure is related or not)

Failed to evaluate expression - could not find symbol value for undefined
Last known immediate stacktrace (goroutine id 1):
	/Users/amarbut/go/pkg/mod/github.com/manicminer/[email protected]/odata/http.go:37
		github.com/manicminer/hamilton/odata.FromResponse
	/Users/amarbut/go/pkg/mod/github.com/manicminer/[email protected]/msgraph/client.go:208
		github.com/manicminer/hamilton/msgraph.Client.performRequest
	/Users/amarbut/go/pkg/mod/github.com/manicminer/[email protected]/msgraph/client.go:342
		github.com/manicminer/hamilton/msgraph.Client.Get
	/Users/amarbut/Github/accessreview-bot/main/accessreviewdecision.go:44
		main.(*AccessReviewDecisionClient).Get
	/Users/amarbut/Github/accessreview-bot/main/main.go:50
		main.main
	/usr/local/Cellar/go/1.17/libexec/src/runtime/proc.go:255
		runtime.main
	/usr/local/Cellar/go/1.17/libexec/src/runtime/asm_amd64.s:1581
		runtime.goexit

If I query this same object using something like Powershell I get a proper value back

 "reviewedBy":  {
                           "id":  "ef1ba2d2-7ec6-4924-bf52-7ffc0bbb4e95",
                           "displayName":  "John Doe",
                           "type":  null,
                           "userPrincipalName":  "[email protected]"
                       }, 

Sorry if this is just me doing something terribly wrong

In case it helps below is an example returned value (with some randomized GUIDs and fake users)

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#identityGovernance/accessReviews/definitions('99009005-f369-4b40-a571-0b200d5953ac')/instances('99009005-f369-4b40-a571-0b200d5953ac')/decisions",
    "@odata.count": 9,
    "value": [
        {
            "id": "b50bc646-3a3d-462a-952e-e6314964aa14",
            "accessReviewId": "99009005-f369-4b40-a571-0b200d5953ac",
            "reviewedDateTime": "2021-03-10T01:29:22.543Z",
            "decision": "Approve",
            "justification": "",
            "appliedDateTime": null,
            "applyResult": "New",
            "recommendation": "Deny",
            "principalLink": "https://graph.microsoft.com/v1.0/users/a18f6504-4d68-4636-b9a9-af21a94953cf",
            "resourceLink": null,
            "resource": null,
            "reviewedBy": {
                "id": "00000000-0000-0000-0000-000000000000",
                "displayName": "Test User",
                "type": null,
                "userPrincipalName": "[email protected]"
            },
            "appliedBy": {
                "id": "00000000-0000-0000-0000-000000000000",
                "displayName": "",
                "type": null,
                "userPrincipalName": ""
            },
            "principal": {
                "@odata.type": "#microsoft.graph.userIdentity",
                "id": "f7e60e6e-a04f-4716-8dfc-e4078207cadf",
                "displayName": "test guest",
                "type": "user",
                "userPrincipalName": "[email protected]",
                "lastUserSignInDateTime": ""
            }
        }
    ]
}

Method to anotate AAD tier/service required for specific objects?

This is a really great library that was pretty easy to figure out from the logical structure of the code so far, nice work!

The testing section of the readme mentions this:

some tests require an Azure AD Premium P2 license and/or an Office 365 license. You can authenticate with any supported method for the client tests, and the auth tests are split by authentication method.

In principle I hate the idea of any kind of selective behavior for test execution, but given the pricing structure of Azure services it seems unavoidable unless every potential contributor is willing to spend $$ for the requires SKUs to support executing all tests in their own local dev environment.

For some development use cases having an entire P2 AAD and O365 environment enabled to run tests seems like overkill. Do you have any ideas or suggestions how we could selectively disable parts of the test infrastructure that depend on those more expensive features?

Support providing an HttpClient

At the moment the HttpClient used isn't exported, which means it's not possible to use a custom client. Just to give some background, the reason I want to be able to do this is to provide a custom client that adds tracing of HTTP requests.

I've created a fork to quickly test out replacing the client by making it exported: adamconnelly@11eb20a. That allows me to create a client like this:

client := msgraph.NewApplicationsClient(tenantID)
client.BaseClient.Authorizer = authorizer
client.BaseClient.HttpClient = tracedClient

That works great, but I wanted to check a couple of things:

  • Would you accept a contribution to allow this?
  • Is the approach I've taken ok, or would you rather the client wasn't exported and was passed as an option to the NewApplicationsClient() function, or something along those lines?

Thanks!

Support for Federated identity credential

Hi @manicminer!

There's a quite new endpoint that would be really awesome to have support for, especially in regard to using it with the Azure AD terraform provider: https://docs.microsoft.com/en-us/graph/api/resources/federatedidentitycredentials-overview?view=graph-rest-beta

The big reason for this is to enable SSO between GitHub Actions and Azure / Azure AD: https://docs.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-cli%2Clinux#use-the-azure-login-action-with-openid-connect

Official Microsoft Graph Go SDK

Hello everyone ๐Ÿ‘‹

Vincent here from the Microsoft Graph SDKs team. I'm reaching out to announce we're working on an official Go SDK, we haven't announced the community preview yet as there are still a number of things we need to work through, but I though I'd reach out to give you an opportunity to provide feedback before anybody else!

A few benefits from this new SDK:

  • Fluent style APIs to all endpoints of the API
  • Contains all the models of the API
  • Is updated weekly to always be in sync with the API
  • Supports v1 and beta
  • Relies on Azure identity to provide support for multiple authentication flows (you also can implement your own authentication provider)
  • Provides middleware for Retry handling and Redirect handling (more to come)
  • And many more features to come!

As with every pre-previews, we have a list of known limitations we're working through.

We'd love for you to pop by the repos under our org, give it a try, and give us feedback on your experience with this new SDK.

Add support for JSON batching

It would be really awesome if we could add support for JSON batch requests https://docs.microsoft.com/en-us/graph/json-batching.

Although I'm really not sure the best way to cleanly integrate it here especially if batching multiple different request types and then mapping the responses appropriately. I don't mind having a poke around to see if it's possible given a consensus it would be a beneficial feature to have.

Group.GetMember question

Reading the code of this line:

func (c *GroupsClient) GetMember(ctx context.Context, groupId, memberId string) (*string, int, error) {

If I need to pass the tuple (group_id, member_id) and the return is an ID of the member, the method shouldn't be called IsMemberOf?

I would expect to have the full member object if I do a GetMember

EntitlementManagement - AccessPackages

General Issue tracker for everything related to AccessPackage implementation within Identity & Governance Management. Will leave PR in draft state any comments, suggestions or contributions welcome

https://docs.microsoft.com/en-us/graph/api/resources/entitlementmanagement-root?view=graph-rest-beta

  • accessPackage
  • accessPackageAssignmentPolicy
  • accessPackageCatalog
  • accessPackageResourceRequest - Non-Standard Implementation (For adding resources to Catalogs)
  • accessPackageResource - RO Non-Standard

Rest of endpoints do not have Creation/Deletion capabiltity / Directly related to IDAG IaC flows

Pagination

Hi!

When using List and methods like it, pagination will most likely be required when there are large amount of groups/users etc.

Recursive groups for Service Principals

Hi!

Just found this project looking through the azuread terraform provider. Great work!

I've been building a reverse proxy that allows normal users and service principals to connect to any Kubernetes API and one part of this is extracting the groups they are members of.

I'm using a pure http client to get all the groups for a service principal, but after looking at this SDK it should fit quite well here instead.

Do you have any thoughts on adding this functionality to this SDK?

This is how I am doing it right now: https://github.com/XenitAB/azad-kube-proxy/blob/main/pkg/azure/service_principal.go

Is it possible to make msgraph.Group a hashable type?

I see many fields on the Group struct are pointers to slices. Is this to ensure the value can be used as a key in a map?

The Group value is something that would be fit for caching. There are a few fields whose types do not allow values of type Group to be hashable for some implementations of an LRU cache. For example, []GroupType and []GroupResourceBehaviorOption.

Since many slice fields are already pointers to a slice, is it possible to convert those remaining fields' types to pointer to a slice, so that Group may be used as a key in a map?

Also, the GroupsClient returns not a slice of group pointers []*Group, but a pointer to a slice of groups *[]Group? Is this intentional as well?

azcli auth doesn't support MSAL scopes

Currently, in AzureCliAuthorizer.Token(), the arguments to az are hard-coded as

{"account", "get-access-token", fmt.Sprintf("--resource=%s", a.conf.Endpoint)}

This is correct for ADAL and also works for MSAL as long as you need the default scope of Resource Manager. However, for a different scope like KeyVault, the arguments should instead be

{"account", "get-access-token", fmt.Sprintf("--scope=%s", a.conf.Endpoint+"/.default")}

Note the MSAL-style (OAuth v2) scope.

I tested the above change and it unblocked a small program that changes Key Vault secrets. I don't have a full PR just yet because I wasn't sure how you wanted to treat MSAL vs ADAL here.

autorest.BearerAuthorization does not have `Token` method

I'm passing an autorest.BearerAuthorization to the wrappedAuth, err := auth.NewAutorestAuthorizerWrapper(authorizer) method call but it returns could not obtain access token from token provider.

It appears it's trying to find .Token method and failing. The autorest.BearerAuthorization provider only has a OAuthToken method.

Is this a bug or am I using it incorrectly?

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.