Skip to content

Commit

Permalink
add azuread provider (GoogleCloudPlatform#1267)
Browse files Browse the repository at this point in the history
  • Loading branch information
dyrnade authored Apr 4, 2022
1 parent 60fa906 commit d9ec73f
Show file tree
Hide file tree
Showing 13 changed files with 657 additions and 4 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ A CLI tool that generates `tf`/`json` and `tfstate` files based on existing infr
* Identity
* [Okta](/docs/okta.md)
* [Auth0](/docs/auth0.md)
* [AzureAD](/docs/azuread.md)
- [Contributing](#contributing)
- [Developing](#developing)
- [Infrastructure](#infrastructure)
Expand Down Expand Up @@ -309,6 +310,7 @@ Links to download Terraform Providers:
* GmailFilter provider >= 1.0.1 - [here](https://github.com/yamamoto-febc/terraform-provider-gmailfilter)
* Vault provider - [here](https://github.com/hashicorp/terraform-provider-vault)
* Auth0 provider - [here](https://github.com/alexkappa/terraform-provider-auth0)
* AzureAD provider - [here](https://github.com/hashicorp/terraform-provider-azuread)

Information on provider plugins:
https://www.terraform.io/docs/configuration/providers.html
Expand Down
46 changes: 46 additions & 0 deletions cmd/provider_cmd_azuread.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2019 The Terraformer Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cmd

import (
azuread "github.com/GoogleCloudPlatform/terraformer/providers/azuread"

"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)

func newCmdAzureADImporter(options ImportOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "azuread",
Short: "Import current state to Terraform configuration from Azure Active Directory",
Long: "Import current state to Terraform configuration from Azure Active Directory",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newAzureADProvider()
err := Import(provider, options, []string{options.ResourceGroup})
if err != nil {
return err
}
return nil
},
}

cmd.AddCommand(listCmd(newAzureADProvider()))
baseProviderFlags(cmd.PersistentFlags(), &options, "resource_group", "resource_group=name1:name2:name3")
cmd.PersistentFlags().StringVarP(&options.ResourceGroup, "resource-group", "R", "", "")
return cmd
}

func newAzureADProvider() terraformutils.ProviderGenerator {
return &azuread.AzureADProvider{}
}
2 changes: 2 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ func providerImporterSubcommands() []func(options ImportOptions) *cobra.Command
newCmdPanosImporter,
// VCS
newCmdAzureDevOpsImporter,
newCmdAzureADImporter,
newCmdGithubImporter,
newCmdGitLabImporter,
// Monitoring & System Management
Expand Down Expand Up @@ -115,6 +116,7 @@ func providerGenerators() map[string]func() terraformutils.ProviderGenerator {
newCloudflareProvider,
// VCS
newAzureDevOpsProvider,
newAzureADProvider,
newGitHubProvider,
newGitLabProvider,
// Monitoring & System Management
Expand Down
24 changes: 24 additions & 0 deletions docs/azuread.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
### Use with Azure Active Directory

Example:

```
$ export ARM_TENANT_ID=<TENANT_ID>
$ export ARM_CLIENT_ID=<CLIENT_ID>
$ export ARM_CLIENT_SECRET=<CLIENT_SECRET>
$ terraformer import azuread --resources=user,application
```

List of supported AzureAD services:


* `user`
* `azuread_user`
* `group`
* `azuread_group`
* `application`
* `azuread_application`
* `service_principal`
* `azuread_service_principal`
* `app_role_assignment`
* `azuread_app_role_assignment`
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ require (
github.com/hashicorp/go-rootcerts v1.0.0 // indirect
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-sockaddr v1.0.0 // indirect
github.com/hashicorp/go-uuid v1.0.1 // indirect
github.com/hashicorp/go-uuid v1.0.2 // indirect
github.com/hashicorp/go-version v1.3.0 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/hcl/v2 v2.8.2 // indirect
Expand Down Expand Up @@ -309,7 +309,7 @@ require (
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
go.mongodb.org/mongo-driver v1.7.2 // indirect
go.opencensus.io v0.23.0 // indirect
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
Expand Down Expand Up @@ -343,6 +343,7 @@ require (
cloud.google.com/go/cloudtasks v1.3.0
cloud.google.com/go/iam v0.3.0
cloud.google.com/go/monitoring v1.4.0
github.com/manicminer/hamilton v0.43.0
)

require (
Expand Down
9 changes: 7 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -824,8 +824,9 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-tfe v0.8.1/go.mod h1:XAV72S4O1iP8BDaqiaPLmL2B4EE6almocnOn8E8stHc=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw=
Expand Down Expand Up @@ -971,6 +972,8 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/manicminer/hamilton v0.43.0 h1:X/XrzLWFhPx1mlLBycqgKRcIjM9vfCd/QR5YnJKIDTI=
github.com/manicminer/hamilton v0.43.0/go.mod h1:lbVyngC+/nCWuDp8UhC6Bw+bh7jcP/E+YwqzHTmzemk=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc=
Expand Down Expand Up @@ -1328,8 +1331,9 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
Expand Down Expand Up @@ -1425,6 +1429,7 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
Expand Down
82 changes: 82 additions & 0 deletions providers/azuread/app_role_assignment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// AppRoleAssignmentServiceGenerator
package azuread

import (
"context"
"fmt"
"log"

"github.com/manicminer/hamilton/msgraph"
"github.com/manicminer/hamilton/odata"
)

type AppRoleAssignmentServiceGenerator struct {
AzureADService
}

func (az *AppRoleAssignmentServiceGenerator) listResources() ([]msgraph.AppRoleAssignment, error) {
client, fail := az.getAppRoleAssignmentsClient()
servicePrincipalsClient, err := az.getServicePrincipalsClient()
if err != nil {
return nil, err
}
client.BaseClient.DisableRetries = true

var resources []msgraph.AppRoleAssignment

if fail != nil {
return nil, fail
}
ctx := context.Background()

servicePrincipals, _, spErr := servicePrincipalsClient.List(ctx, odata.Query{})
if spErr != nil {
return nil, spErr
}

for _, sp := range *servicePrincipals {
appRoleAssignments, _, araErr := client.List(ctx, *sp.ID, odata.Query{})
if araErr != nil {
return nil, araErr
}
if appRoleAssignments == nil {
continue
}
for _, assignment := range *appRoleAssignments {
if *assignment.PrincipalType != "ServicePrincipal" {
continue
}
if assignment.Id != nil {
resources = append(resources, assignment)
}
}
}

return resources, nil
}

func (az *AppRoleAssignmentServiceGenerator) appendResource(resource *msgraph.AppRoleAssignment) {
// {objectId}/{type}/{subId}
id := fmt.Sprintf("%s/appRoleAssignment/%s", *resource.PrincipalId, *resource.Id)
az.appendSimpleResource(id, *resource.PrincipalDisplayName+"-"+id, "azuread_app_role_assignment")
}

func (az *AppRoleAssignmentServiceGenerator) InitResources() error {

resources, err := az.listResources()
if err != nil {
return err
}
for _, resource := range resources {
log.Println(*resource.PrincipalDisplayName)
az.appendResource(&resource)
}
return nil
}

func (az *AppRoleAssignmentServiceGenerator) GetResourceConnections() map[string][]string {

return map[string][]string{
"app_role_assignment": {"id"},
}
}
62 changes: 62 additions & 0 deletions providers/azuread/application.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// ApplicationServiceGenerator
package azuread

import (
"context"
"log"

"github.com/manicminer/hamilton/msgraph"
"github.com/manicminer/hamilton/odata"
)

type ApplicationServiceGenerator struct {
AzureADService
}

func (az *ApplicationServiceGenerator) listResources() ([]msgraph.Application, error) {
client, fail := az.getApplicationsClient()
client.BaseClient.DisableRetries = true

var resources []msgraph.Application

if fail != nil {
return nil, fail
}
ctx := context.Background()

applications, _, err := client.List(ctx, odata.Query{})
if err != nil {
return nil, err
}

for _, application := range *applications {
resources = append(resources, application)
}

return resources, nil
}

func (az *ApplicationServiceGenerator) appendResource(resource *msgraph.Application) {
id := resource.ID
az.appendSimpleResource(*id, *resource.DisplayName, "azuread_application")
}

func (az *ApplicationServiceGenerator) InitResources() error {

resources, err := az.listResources()
if err != nil {
return err
}
for _, resource := range resources {
log.Println(*resource.DisplayName)
az.appendResource(&resource)
}
return nil
}

func (az *ApplicationServiceGenerator) GetResourceConnections() map[string][]string {

return map[string][]string{
"application": {"id"},
}
}
Loading

0 comments on commit d9ec73f

Please sign in to comment.