Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,33 @@ The following steps should get you a working gmin installation -
3. Create a service account, create and download a JSON key for the service account and enable G Suite domain-wide delegation.
4. In the G Suite admin console of the domain with which you want to use gmin, go to Security > API Permissions > Manage Domain-wide Delegation and add a new record (or update an existing one). The scopes that you will need to add to the record for full functionality are as follows -
```
Readonly scopes are needed for get and list functions. The other more permissive scopes are needed for create, delete, update
and undelete functions.
Readonly scopes are needed for get and list functions. The other more permissive scopes are needed for
create, delete, update and undelete functions.

https://www.googleapis.com/auth/admin.directory.group
https://www.googleapis.com/auth/admin.directory.group.member.readonly
https://www.googleapis.com/auth/admin.directory.orgunit
https://www.googleapis.com/auth/admin.directory.orgunit.readonly
https://www.googleapis.com/auth/admin.directory.user
https://www.googleapis.com/auth/admin.directory.user.alias
https://www.googleapis.com/auth/admin.directory.user.alias.readonly
https://www.googleapis.com/auth/admin.directory.user.readonly
https://www.googleapis.com/auth/admin.directory.group.readonly
https://www.googleapis.com/auth/admin.directory.group.member
```

5. Copy/move the gmin binary to a convenient directory/folder and rename the JSON key file, downloaded earlier, to gmin_credentials and place in the same directory/folder as the gmin binary.
6. Run the command `gmin init` and enter the required information. The email address of the admin whose privileges will be used is mandatory. Customer ID and the path where you would like the config file, .gmin.yaml, to be written are optional. By default the config file is written to the current user's home directory and the string 'my_customer' is used for the customer ID. If you choose a different installation path for the config file then that path will need to be given with each gmin command by using the --config flag.
5. Copy/move the gmin binary to a convenient directory/folder and rename the JSON key file, downloaded earlier, to 'gmin_credentials'. Place in a directory/folder suitable for your environment.
6. Run the command `gmin init` and enter the required information.

* Email address of the admin whose privileges will be used (mandatory).
* Path where config file, .gmin.yaml, will be written. Default is current user's home directory. If you choose a different installation path to the default for the config file then that path will need to be given with each gmin command by using the --config flag.
* Path where service account credentials json file is stored. File must be named 'gmin_credentials'. Default is current user's home directory.
* Customer ID. Default is 'my_customer'.

7. To see the version number of your gmin binary, run the command `gmin -v` or `gmin --version`.
8. To get help from gmin itself, enter `gmin -h` or `gmin --help` and go from there.

If you already use GAM (https://github.com/jay0lee/GAM) then you will already have a service account and JSON credentials file. In this case you could use the same service account by copying the GAM credentials.json, rename the copy to gmin_credentials and place it in the same directory/folder as the gmin executable.
If you already use GAM (https://github.com/jay0lee/GAM) then you will already have a service account and JSON credentials file. In this case you could use the same service account by copying the GAM credentials.json, rename the copy to gmin_credentials and place it in the folder/directory that you set for the credentials path when running `gmin init`.

## Usage
Commands usually take the form of `gmin <verb> <object> <flags>`. Although there may be the odd exception like `gmin whoami`.
Expand Down Expand Up @@ -139,11 +147,11 @@ https://developers.google.com/admin-sdk/directory/v1/get-start/getting-started i
* Maybe there are other people who might benefit from gmin

## Project Status
gmin is pretty young which means that it is liable to rapid change, although the command syntax is unlikely to change much (if at all) over time. The functionality is currently limited to the Admin SDK API and the user, group, group member and organisation unit objects but additional functionality will be added when it is ready.
gmin is pretty young which means that it is liable to rapid change, although the command syntax is unlikely to change much (if at all) over time. The functionality is currently limited to the Admin SDK API and the group, group alias, group member, organisation unit, user and user alias objects but additional functionality will be added frequently when it is ready.

All output is in JSON format apart from informational and error messages. Output in other formats such as CSV is on the roadmap, however, I have found the use of the jq utility (https://stedolan.github.io/jq/) can be a great help in working with JSON.

I will be publishing a roadmap and welcome any suggestions as to the most important features to add. A Wiki is on the list of tasks on the upcoming roadmap.
I have published a [development roadmap](https://github.com/plusworx/gmin/wiki/Development-Roadmap) and welcome any suggestions as to the most important features to add. A [wiki](https://github.com/plusworx/gmin/wiki) has also been started which contains the roadmap.

## Community

Expand Down
78 changes: 78 additions & 0 deletions cmd/create_group_alias.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
Copyright © 2020 Chris Duncan <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

package cmd

import (
"errors"
"fmt"

cmn "github.com/plusworx/gmin/utils/common"
"github.com/spf13/cobra"
admin "google.golang.org/api/admin/directory/v1"
)

var createGroupAliasCmd = &cobra.Command{
Use: "group-alias <alias email address> -g <group email address or id>",
Aliases: []string{"galias", "ga"},
Args: cobra.ExactArgs(1),
Short: "Creates a group alias",
Long: `Creates a group alias.

Examples: gmin create group-alias [email protected] -g [email protected]
gmin crt ga [email protected] -g [email protected]`,
RunE: doCreateGroupAlias,
}

func doCreateGroupAlias(cmd *cobra.Command, args []string) error {
var alias *admin.Alias

alias = new(admin.Alias)

alias.Alias = args[0]

if group == "" {
err := errors.New("gmin: error - group must be provided")
return err
}

ds, err := cmn.CreateDirectoryService(admin.AdminDirectoryGroupScope)
if err != nil {
return err
}

gaic := ds.Groups.Aliases.Insert(group, alias)
newAlias, err := gaic.Do()
if err != nil {
return err
}

fmt.Println("**** group alias " + newAlias.Alias + " created for group " + group + " ****")

return nil
}

func init() {
createCmd.AddCommand(createGroupAliasCmd)

createGroupAliasCmd.Flags().StringVarP(&group, "group", "g", "", "email address or id of group")
}
46 changes: 46 additions & 0 deletions cmd/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,29 @@ import (
"testing"
)

func TestDoCreateGroupAlias(t *testing.T) {
cases := []struct {
args []string
expectedErr string
group string
}{
{
args: []string{"[email protected]"},
expectedErr: "gmin: error - group must be provided",
},
}

for _, c := range cases {
group = c.group

got := doCreateGroupAlias(createGroupAliasCmd, c.args)

if got.Error() != c.expectedErr {
t.Errorf("Expected error %v, got %v", c.expectedErr, got.Error())
}
}
}

func TestDoCreateUser(t *testing.T) {
cases := []struct {
args []string
Expand Down Expand Up @@ -109,3 +132,26 @@ func TestDoCreateMember(t *testing.T) {
}
}
}

func TestDoCreateUserAlias(t *testing.T) {
cases := []struct {
args []string
expectedErr string
userKey string
}{
{
args: []string{"[email protected]"},
expectedErr: "gmin: error - user must be provided",
},
}

for _, c := range cases {
userKey = c.userKey

got := doCreateUserAlias(createUserAliasCmd, c.args)

if got.Error() != c.expectedErr {
t.Errorf("Expected error %v, got %v", c.expectedErr, got.Error())
}
}
}
78 changes: 78 additions & 0 deletions cmd/create_user_alias.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
Copyright © 2020 Chris Duncan <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

package cmd

import (
"errors"
"fmt"

cmn "github.com/plusworx/gmin/utils/common"
"github.com/spf13/cobra"
admin "google.golang.org/api/admin/directory/v1"
)

var createUserAliasCmd = &cobra.Command{
Use: "user-alias <alias email address> -u <user email address or id>",
Aliases: []string{"ualias", "ua"},
Args: cobra.ExactArgs(1),
Short: "Creates a user alias",
Long: `Creates a user alias.

Examples: gmin create user-alias [email protected] -u [email protected]
gmin crt ua [email protected] -u [email protected]`,
RunE: doCreateUserAlias,
}

func doCreateUserAlias(cmd *cobra.Command, args []string) error {
var alias *admin.Alias

alias = new(admin.Alias)

alias.Alias = args[0]

if userKey == "" {
err := errors.New("gmin: error - user must be provided")
return err
}

ds, err := cmn.CreateDirectoryService(admin.AdminDirectoryUserAliasScope)
if err != nil {
return err
}

uaic := ds.Users.Aliases.Insert(userKey, alias)
newAlias, err := uaic.Do()
if err != nil {
return err
}

fmt.Println("**** user alias " + newAlias.Alias + " created for user " + userKey + " ****")

return nil
}

func init() {
createCmd.AddCommand(createUserAliasCmd)

createUserAliasCmd.Flags().StringVarP(&userKey, "user", "u", "", "email address or id of user")
}
70 changes: 70 additions & 0 deletions cmd/delete_group_alias.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
Copyright © 2020 Chris Duncan <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

package cmd

import (
"errors"
"fmt"

cmn "github.com/plusworx/gmin/utils/common"
"github.com/spf13/cobra"
admin "google.golang.org/api/admin/directory/v1"
)

var deleteGroupAliasCmd = &cobra.Command{
Use: "group-alias <alias email address> -g <group email address or id>",
Aliases: []string{"galias", "ga"},
Args: cobra.ExactArgs(1),
Short: "Deletes group alias",
Long: `Deletes group alias.`,
RunE: doDeleteGroupAlias,
}

func doDeleteGroupAlias(cmd *cobra.Command, args []string) error {
if group == "" {
err := errors.New("gmin: error - group email address or id must be provided")
return err
}

ds, err := cmn.CreateDirectoryService(admin.AdminDirectoryGroupScope)
if err != nil {
return err
}

gadc := ds.Groups.Aliases.Delete(group, args[0])

err = gadc.Do()
if err != nil {
return err
}

fmt.Printf("**** gmin: group alias %s for group %s deleted ****\n", args[0], group)

return nil
}

func init() {
deleteCmd.AddCommand(deleteGroupAliasCmd)

deleteGroupAliasCmd.Flags().StringVarP(&group, "group", "g", "", "email address or id of group")
}
46 changes: 46 additions & 0 deletions cmd/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,29 @@ import (
"testing"
)

func TestDoDeleteGroupAlias(t *testing.T) {
cases := []struct {
args []string
expectedErr string
group string
}{
{
args: []string{"[email protected]"},
expectedErr: "gmin: error - group email address or id must be provided",
},
}

for _, c := range cases {
group = c.group

got := doDeleteGroupAlias(deleteGroupAliasCmd, c.args)

if got.Error() != c.expectedErr {
t.Errorf("Expected error %v, got %v", c.expectedErr, got.Error())
}
}
}

func TestDoDeleteMember(t *testing.T) {
cases := []struct {
args []string
Expand All @@ -48,3 +71,26 @@ func TestDoDeleteMember(t *testing.T) {
}
}
}

func TestDoDeleteUserAlias(t *testing.T) {
cases := []struct {
args []string
expectedErr string
userKey string
}{
{
args: []string{"[email protected]"},
expectedErr: "gmin: error - user email address or id must be provided",
},
}

for _, c := range cases {
userKey = c.userKey

got := doDeleteUserAlias(deleteUserAliasCmd, c.args)

if got.Error() != c.expectedErr {
t.Errorf("Expected error %v, got %v", c.expectedErr, got.Error())
}
}
}
Loading