Skip to content
This repository has been archived by the owner on Jun 27, 2021. It is now read-only.

Add organizational unit and licensing support #146

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
279 changes: 143 additions & 136 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,136 +1,143 @@
# Terraform G Suite Provider

This is a terraform provider for managing G Suite (Admin SDK) resources on Google

## Authentication

There are two possible authentication mechanisms for using this provider.
Using a service account, or a personal admin account. The latter requires
user interaction, whereas a service account could be used in an automated
workflow.

See the necessary oauth scopes both for service accounts and users below:
- https://www.googleapis.com/auth/admin.directory.group
- https://www.googleapis.com/auth/admin.directory.user

You could also provide the minimal set of scopes using the
`oauth_scopes` variable in the provider configuration.

```
provider "gsuite" {
oauth_scopes = [
"https://www.googleapis.com/auth/admin.directory.group",
"https://www.googleapis.com/auth/admin.directory.user"
]
}
```

**NOTE** If you are creating or modifying schemas and custom user attributes
you will need the following additional scope:

https://www.googleapis.com/auth/admin.directory.userschema


### Using a service account

Service accounts are great for automated workflows.

Only users with access to the Admin APIs can access the Admin SDK Directory API,
therefore the service account needs to impersonate one of those users
to access the Admin SDK Directory API.

Follow the instruction at
https://developers.google.com/admin-sdk/directory/v1/guides/delegation.

Add `credentials` and `impersonated_user_email` when initializing the provider.
```
provider "gsuite" {
credentials = "/full/path/service-account.json"
impersonated_user_email = "[email protected]"
}
```

Credentials can also be provided via the following environment variables:
- GOOGLE_CREDENTIALS
- GOOGLE_CLOUD_KEYFILE_JSON
- GCLOUD_KEYFILE_JSON
- GOOGLE_APPLICATION_CREDENTIALS
- IMPERSONATED_USER_EMAIL

### Using a personal administrator account

In order to use the Admin SDK with a project, we will first need to create
credentials for that project, you can do so here:

https://console.cloud.google.com/apis/credentials?project=[project_ID]

Please make sure to create an OAuth 2.0 client, and download the file to your
local directory.

You can now use that credential to authenticate:

```
$ gcloud auth application-default login \
--client-id-file=client_id.json \
--scopes \
https://www.googleapis.com/auth/admin.directory.group,\
https://www.googleapis.com/auth/admin.directory.user,
```

Now that you have a credential that is allowed to the Admin SDK, you can use the
G Suite provider.

## Installation

1. Download the latest compiled binary from [GitHub releases](https://github.com/DeviaVir/terraform-provider-gsuite/releases).

1. Unzip/untar the archive.

1. Move it into `$HOME/.terraform.d/plugins`:

```sh
$ mkdir -p $HOME/.terraform.d/plugins
$ mv terraform-provider-gsuite $HOME/.terraform.d/plugins/terraform-provider-gsuite
```

1. Create your Terraform configurations as normal, and run `terraform init`:

```sh
$ terraform init
```

This will find the plugin locally.

## Development

1. `cd` into `$HOME/.terraform.d/plugins/terraform-provider-gsuite`

1. Run `make vendor` to fetch the go vendor files

1. Make your changes

1. Run `make dev` and in your `terraform` directory, remove the current `.terraform` and re-run `terraform init`

1. Next time you run `terraform plan` it'll use your updated version

### Relevant Google Admin SDK Documentation
#### General
* http://google.golang.org/api/admin/directory/v1
* https://developers.google.com/admin-sdk/directory/v1/reference/

#### Schema Types
* https://developers.google.com/admin-sdk/directory/v1/reference/users
* https://developers.google.com/admin-sdk/directory/v1/reference/groups
* https://developers.google.com/admin-sdk/directory/v1/reference/schemas

When using a service account, make sure to add:
`https://www.googleapis.com/auth/admin.directory.userschema`
to the `oauth_scopes` list, otherwise you will be missing permissions to manage
user schemas.

## Notes

- Asking too many permissions right now, but rather start out with too much and tone down later on
- Quite limited, as it is a huge API, I have only added the parts I plan on using
- Open for PR's to extend functionality
- Documentation is still to be written, you can refer to the `examples` directory for now
# G Suite Infrastructure Provider
:warning: **Warning: deleting this repository can break [infrastructure-gsuite](https://github.com/helpfulengineering/infrastructure-gsuite).**

> # Terraform G Suite Provider
>
> This is a terraform provider for managing G Suite (Admin SDK) resources on Google
>
> ## Authentication
>
> There are two possible authentication mechanisms for using this provider.
> Using a service account, or a personal admin account. The latter requires
> user interaction, whereas a service account could be used in an automated
> workflow.
>
> See the necessary oauth scopes both for service accounts and users below:
> - https://www.googleapis.com/auth/admin.directory.group
> - https://www.googleapis.com/auth/admin.directory.user
>
> You could also provide the minimal set of scopes using the
> `oauth_scopes` variable in the provider configuration.
>
> ```
> provider "gsuite" {
> oauth_scopes = [
> "https://www.googleapis.com/auth/admin.directory.group",
> "https://www.googleapis.com/auth/admin.directory.user"
> ]
> }
>```
>
>**NOTE** If you are creating or modifying schemas and custom user attributes
>you will need the following additional scope:
>
> https://www.googleapis.com/auth/admin.directory.userschema
>
>
>### Using a service account
>
>Service accounts are great for automated workflows.
>
>Only users with access to the Admin APIs can access the Admin SDK Directory API,
>therefore the service account needs to impersonate one of those users
>to access the Admin SDK Directory API.
>
>Follow the instruction at
>https://developers.google.com/admin-sdk/directory/v1/guides/delegation.
>
>Add `credentials` and `impersonated_user_email` when initializing the provider.
>```
>provider "gsuite" {
> credentials = "/full/path/service-account.json"
> impersonated_user_email = "[email protected]"
>}
>```
>
>Credentials can also be provided via the following environment variables:
>- GOOGLE_CREDENTIALS
>- GOOGLE_CLOUD_KEYFILE_JSON
>- GCLOUD_KEYFILE_JSON
>- GOOGLE_APPLICATION_CREDENTIALS
>- IMPERSONATED_USER_EMAIL
>
>### Using a personal administrator account
>
>In order to use the Admin SDK with a project, we will first need to create
>credentials for that project, you can do so here:
>
>https://console.cloud.google.com/apis/credentials?project=[project_ID]
>
>Please make sure to create an OAuth 2.0 client, and download the file to your
>local directory.
>
>You can now use that credential to authenticate:
>
>```
>$ gcloud auth application-default login \
> --client-id-file=client_id.json \
> --scopes \
>https://www.googleapis.com/auth/admin.directory.group,\
>https://www.googleapis.com/auth/admin.directory.user,
>```
>
>Now that you have a credential that is allowed to the Admin SDK, you can use the
>G Suite provider.
>
>## Installation
>
>1. Download the latest compiled binary from [GitHub releases](https://github.com/DeviaVir/terraform-provider->gsuite/releases).
>
>1. Unzip/untar the archive.
>
>1. Move it into `$HOME/.terraform.d/plugins`:
>
> ```sh
> $ mkdir -p $HOME/.terraform.d/plugins
> $ mv terraform-provider-gsuite $HOME/.terraform.d/plugins/terraform-provider-gsuite
> ```
>
>1. Create your Terraform configurations as normal, and run `terraform init`:
>
> ```sh
> $ terraform init
> ```
>
> This will find the plugin locally.
>
>## Development
>
>1. `cd` into `$HOME/.terraform.d/plugins/terraform-provider-gsuite`
>
>1. Run `make vendor` to fetch the go vendor files
>
>1. Make your changes
>
>1. Run `make dev` and in your `terraform` directory, remove the current `.terraform` and re-run `terraform init`
>
>1. Next time you run `terraform plan` it'll use your updated version
>
>### Relevant Google Admin SDK Documentation
>#### General
>* http://google.golang.org/api/admin/directory/v1
>* https://developers.google.com/admin-sdk/directory/v1/reference/
>
>#### Schema Types
>* https://developers.google.com/admin-sdk/directory/v1/reference/users
>* https://developers.google.com/admin-sdk/directory/v1/reference/groups
>* https://developers.google.com/admin-sdk/directory/v1/reference/schemas
>
>#### Licensing
>* https://developers.google.com/admin-sdk/licensing/v1/get-start/getting-started
>* https://developers.google.com/admin-sdk/licensing/v1/how-tos/products
>
>When using a service account, make sure to add:
>`https://www.googleapis.com/auth/admin.directory.userschema`
>to the `oauth_scopes` list, otherwise you will be missing permissions to manage
>user schemas.
>
>## Notes
>
>- Asking too many permissions right now, but rather start out with too much and tone down later on
>- Quite limited, as it is a huge API, I have only added the parts I plan on using
> - Open for PR's to extend functionality
> - Documentation is still to be written, you can refer to the `examples` directory for now
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.25.0 h1:LodzhlzZEUfhXzNUMIfVlf9Gr6Ua5MMtoFWh7+f47qA=
google.golang.org/api v0.25.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.26.0 h1:VJZ8h6E8ip82FRpQl848c5vAadxlTXrUh8RzQzSRm08=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
Expand Down
11 changes: 11 additions & 0 deletions gsuite/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/pkg/errors"
"golang.org/x/oauth2/google"
"golang.org/x/oauth2/jwt"
licensing "google.golang.org/api/licensing/v1"
directory "google.golang.org/api/admin/directory/v1"
groupSettings "google.golang.org/api/groupssettings/v1"
"google.golang.org/api/option"
Expand Down Expand Up @@ -41,6 +42,8 @@ type Config struct {

UpdateExisting bool

licensing *licensing.Service

directory *directory.Service

groupSettings *groupSettings.Service
Expand Down Expand Up @@ -106,6 +109,14 @@ func (c *Config) loadAndValidate(terraformVersion string) error {

context := context.Background()

// Create the licensing service.
licensingSvc, err := licensing.NewService(context, option.WithHTTPClient(client))
if err != nil {
return err
}
licensingSvc.UserAgent = userAgent
c.licensing = licensingSvc

// Create the directory service.
directorySvc, err := directory.NewService(context, option.WithHTTPClient(client))
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions gsuite/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func Provider() *schema.Provider {
},
ResourcesMap: map[string]*schema.Resource{
"gsuite_domain": resourceDomain(),
"gsuite_orgunit": resourceOrgUnit(),
"gsuite_group": resourceGroup(),
"gsuite_group_member": resourceGroupMember(),
"gsuite_group_members": resourceGroupMembers(),
Expand Down
25 changes: 21 additions & 4 deletions gsuite/resource_group_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ func resourceGroupSettings() *schema.Resource {
},

Schema: map[string]*schema.Schema{
"is_archived": {
Type: schema.TypeString,
Computed: true,
},
"kind": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -86,6 +82,11 @@ func resourceGroupSettings() *schema.Resource {
Optional: true,
Default: "true",
},
"is_archived": {
Type: schema.TypeString,
Optional: true,
Default: "true",
},
"max_message_bytes": {
Type: schema.TypeInt,
Optional: true,
Expand Down Expand Up @@ -366,6 +367,10 @@ func resourceGroupSettingsCreate(d *schema.ResourceData, meta interface{}) error
log.Printf("[DEBUG] Setting %s: %s", "include_in_global_address_list", v.(string))
groupSetting.IncludeInGlobalAddressList = v.(string)
}
if v, ok := d.GetOk("is_archived"); ok {
log.Printf("[DEBUG] Setting %s: %s", "is_archived", v.(string))
groupSetting.IsArchived = v.(string)
}
if v, ok := d.GetOk("members_can_post_as_the_group"); ok {
log.Printf("[DEBUG] Setting %s: %s", "members_can_post_as_the_group", v.(string))
groupSetting.MembersCanPostAsTheGroup = v.(string)
Expand Down Expand Up @@ -545,6 +550,16 @@ func resourceGroupSettingsUpdate(d *schema.ResourceData, meta interface{}) error
nullFields = append(nullFields, "IncludeInGlobalAddressList")
}
}
if d.HasChange("is_archived") {
if v, ok := d.GetOk("is_archived"); ok {
log.Printf("[DEBUG] Updating is_archived: %s", v.(string))
groupSetting.IsArchived = v.(string)
} else {
log.Printf("[DEBUG] Removing groupSetting IsArchived")
groupSetting.IsArchived = ""
nullFields = append(nullFields, "IsArchived")
}
}
if d.HasChange("members_can_post_as_the_group") {
if v, ok := d.GetOk("members_can_post_as_the_group"); ok {
log.Printf("[DEBUG] Updating members_can_post_as_the_group: %s", v.(string))
Expand Down Expand Up @@ -753,6 +768,7 @@ func resourceGroupSettingsRead(d *schema.ResourceData, meta interface{}) error {
d.Set("favorite_replies_on_top", groupSetting.FavoriteRepliesOnTop)
d.Set("include_custom_footer", groupSetting.IncludeCustomFooter)
d.Set("include_in_global_address_list", groupSetting.IncludeInGlobalAddressList)
d.Set("is_archived", groupSetting.IsArchived)
d.Set("members_can_post_as_the_group", groupSetting.MembersCanPostAsTheGroup)
d.Set("message_moderation_level", groupSetting.MessageModerationLevel)
d.Set("primary_language", groupSetting.PrimaryLanguage)
Expand Down Expand Up @@ -799,6 +815,7 @@ func resourceGroupSettingsImporter(d *schema.ResourceData, meta interface{}) ([]
d.Set("favorite_replies_on_top", id.FavoriteRepliesOnTop)
d.Set("include_custom_footer", id.IncludeCustomFooter)
d.Set("include_in_global_address_list", id.IncludeInGlobalAddressList)
d.Set("is_archived", id.IsArchived)
d.Set("members_can_post_as_the_group", id.MembersCanPostAsTheGroup)
d.Set("message_moderation_level", id.MessageModerationLevel)
d.Set("primary_language", id.PrimaryLanguage)
Expand Down
Loading