pkg/cloud/graph.go (117 lines of code) (raw):

package cloud import ( "context" "fmt" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/microsoftgraph/msgraph-sdk-go/applications" "github.com/microsoftgraph/msgraph-sdk-go/models" "github.com/microsoftgraph/msgraph-sdk-go/serviceprincipals" "github.com/pkg/errors" "monis.app/mlog" ) var ( // ErrFederatedCredentialNotFound is returned when the federated credential is not found. ErrFederatedCredentialNotFound = errors.New("federated credential not found") ) // CreateServicePrincipal creates a service principal for the given application. // No secret or certificate is generated. func (c *AzureClient) CreateServicePrincipal(ctx context.Context, appID string, tags []string) (models.ServicePrincipalable, error) { body := models.NewServicePrincipal() body.SetAppId(to.Ptr(appID)) body.SetTags(tags) mlog.Debug("Creating service principal for application", "id", appID) sp, err := c.graphServiceClient.ServicePrincipals().Post(ctx, body, nil) if err != nil { return nil, maybeExtractGraphError(err) } return sp, nil } // CreateApplication creates an application. func (c *AzureClient) CreateApplication(ctx context.Context, displayName string) (models.Applicationable, error) { body := models.NewApplication() body.SetDisplayName(to.Ptr(displayName)) mlog.Debug("Creating application", "displayName", displayName) app, err := c.graphServiceClient.Applications().Post(ctx, body, nil) if err != nil { return nil, maybeExtractGraphError(err) } return app, nil } // GetServicePrincipal gets a service principal by its display name. func (c *AzureClient) GetServicePrincipal(ctx context.Context, displayName string) (models.ServicePrincipalable, error) { mlog.Debug("Getting service principal", "displayName", displayName) spGetOptions := &serviceprincipals.ServicePrincipalsRequestBuilderGetRequestConfiguration{ QueryParameters: &serviceprincipals.ServicePrincipalsRequestBuilderGetQueryParameters{ Filter: to.Ptr(getDisplayNameFilter(displayName)), }, } resp, err := c.graphServiceClient.ServicePrincipals().Get(ctx, spGetOptions) if err != nil { return nil, maybeExtractGraphError(err) } if len(resp.GetValue()) == 0 { return nil, errors.Errorf("service principal %s not found", displayName) } return resp.GetValue()[0], nil } // GetApplication gets an application by its display name. func (c *AzureClient) GetApplication(ctx context.Context, displayName string) (models.Applicationable, error) { mlog.Debug("Getting application", "displayName", displayName) appGetOptions := &applications.ApplicationsRequestBuilderGetRequestConfiguration{ QueryParameters: &applications.ApplicationsRequestBuilderGetQueryParameters{ Filter: to.Ptr(getDisplayNameFilter(displayName)), }, } resp, err := c.graphServiceClient.Applications().Get(ctx, appGetOptions) if err != nil { return nil, maybeExtractGraphError(err) } if len(resp.GetValue()) == 0 { return nil, errors.Errorf("application with display name '%s' not found", displayName) } return resp.GetValue()[0], nil } // DeleteServicePrincipal deletes a service principal. func (c *AzureClient) DeleteServicePrincipal(ctx context.Context, objectID string) error { mlog.Debug("Deleting service principal", "objectID", objectID) return c.graphServiceClient.ServicePrincipals().ByServicePrincipalId(objectID).Delete(ctx, nil) } // DeleteApplication deletes an application. func (c *AzureClient) DeleteApplication(ctx context.Context, objectID string) error { mlog.Debug("Deleting application", "objectID", objectID) return c.graphServiceClient.Applications().ByApplicationId(objectID).Delete(ctx, nil) } // AddFederatedCredential adds a federated credential to the cloud provider. func (c *AzureClient) AddFederatedCredential(ctx context.Context, objectID string, fic models.FederatedIdentityCredentialable) error { mlog.Debug("Adding federated credential", "objectID", objectID) if _, err := c.graphServiceClient.Applications().ByApplicationId(objectID).FederatedIdentityCredentials().Post(ctx, fic, nil); err != nil { return maybeExtractGraphError(err) } return nil } // GetFederatedCredential gets a federated credential from the cloud provider. func (c *AzureClient) GetFederatedCredential(ctx context.Context, objectID, issuer, subject string) (models.FederatedIdentityCredentialable, error) { mlog.Debug("Getting federated credential", "objectID", objectID, "issuer", issuer, "subject", subject, ) ficGetOptions := &applications.ItemFederatedidentitycredentialsFederatedIdentityCredentialsRequestBuilderGetRequestConfiguration{ QueryParameters: &applications.ItemFederatedidentitycredentialsFederatedIdentityCredentialsRequestBuilderGetQueryParameters{ // Filtering on more than one resource is currently not supported. Filter: to.Ptr(getSubjectFilter(subject)), }, } resp, err := c.graphServiceClient.Applications().ByApplicationId(objectID).FederatedIdentityCredentials().Get(ctx, ficGetOptions) if err != nil { return nil, maybeExtractGraphError(err) } for _, fic := range resp.GetValue() { if *fic.GetIssuer() == issuer { return fic, nil } } return nil, ErrFederatedCredentialNotFound } // DeleteFederatedCredential deletes a federated credential from the cloud provider. func (c *AzureClient) DeleteFederatedCredential(ctx context.Context, objectID, federatedCredentialID string) error { mlog.Debug("Deleting federated credential", "objectID", objectID, "federatedCredentialID", federatedCredentialID, ) return c.graphServiceClient.Applications().ByApplicationId(objectID).FederatedIdentityCredentials().ByFederatedIdentityCredentialId(federatedCredentialID).Delete(ctx, nil) } // getDisplayNameFilter returns a filter string for the given display name. func getDisplayNameFilter(displayName string) string { return fmt.Sprintf("displayName eq '%s'", displayName) } // getSubjectFilter returns a filter string for the given subject. func getSubjectFilter(subject string) string { return fmt.Sprintf("subject eq '%s'", subject) }