Skip to content

Commit

Permalink
fix Dockerfile, fix Gsuite to GSuite spelling, change CreateNewUser t…
Browse files Browse the repository at this point in the history
…o CreateUser, change log.Fatal() to log.Fatalf() in validation
  • Loading branch information
mskarbe committed Jul 2, 2020
1 parent 0f548b5 commit 998a71c
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ dockers:
#extra_files:
#- README.md
#- LICENSE
#- config.example.yaml
#- config.example.yaml
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- user creation, deletion, update
- organizational unit creation, deletion, update
- group creation, deletion, update
- group members addition, removal, update of membership
- group members addition, removal, update of membership
32 changes: 8 additions & 24 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,29 +1,13 @@
FROM golang:alpine AS builder
RUN apk add git
# necessary environmet variables
ENV GO111MODULE=on \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64
FROM golang:1.14-alpine as builder
ENV GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=amd64

WORKDIR /build
COPY go.mod .
COPY go.sum .
WORKDIR /app/
COPY . .
RUN go mod download

# Copy the code into the container & build
COPY main.go .
RUN go build -o gman main.go

WORKDIR /app

# Copy binary from build to main folder
RUN cp /build/gman .

# Build a small image
FROM scratch

COPY --from=builder /app/gman /
FROM alpine:3.12

# Command to run
ENTRYPOINT ["/gman"]
RUN apk --no-cache add ca-certificates
COPY --from=builder /app/gman .
ENTRYPOINT ["/gman"]
52 changes: 26 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# gman

*gman links all Gsuite accounts with the matching user-list storage in form of a YAML. It is based on the [Aquayman](https://github.com/kubermatic-labs/aquayman) tool.*
*gman links all GSuite accounts with the matching user-list storage in form of a YAML. It is based on the [Aquayman](https://github.com/kubermatic-labs/aquayman) tool.*

**Features:**

Expand Down Expand Up @@ -85,7 +85,7 @@ After the completion of the steps above, *Gman* can perform for you:

### Exporting

To get started, *Gman* can export your existing Gsuite users into a configuration file.
To get started, *Gman* can export your existing GSuite users into a configuration file.
For this to work, prepare a fresh configuration file and put your organisation name in it.
You can skip everything else:

Expand All @@ -109,27 +109,27 @@ Afterwards, the `myconfig.yaml` will contain an exact representation of your org
```yaml
organization: myorganization
org_units:
- name: Developers
description: dedicated org unit for devs
parentOrgUnitPath: /
org_unit_path: /Developers
- name: Developers
description: dedicated org unit for devs
parentOrgUnitPath: /
org_unit_path: /Developers
users:
- given_name: Josef
family_name: K
primary_email: josef@myorganization.com
secondary_email: josef@privatedomain.com
org_unit_path: /Developers
- given_name: Gregor
family_name: Samsa
primary_email: gregor@myorganization.com
secondary_email: gregor@privatedomain.com
org_unit_path: /
- given_name: Josef
family_name: K
primary_email: josef@myorganization.com
secondary_email: josef@privatedomain.com
org_unit_path: /Developers
- given_name: Gregor
family_name: Samsa
primary_email: gregor@myorganization.com
secondary_email: gregor@privatedomain.com
org_unit_path: /
groups:
- name: Team Gman
email: teamgman@myorganization.com
members:
- email: josef@myorganization.com
role: OWNER
- name: Team Gman
email: teamgman@myorganization.com
members:
- email: josef@myorganization.com
role: OWNER
```

### Validating
Expand Down Expand Up @@ -162,7 +162,7 @@ If this flag is specified, *Gman* performs **only** the config validation. Other

### Synchronizing

Synchronizing means updating Gsuite's state to match the given configuration file. Without specifying the `-confirm` flag the changes are not performed:
Synchronizing means updating GSuite's state to match the given configuration file. Without specifying the `-confirm` flag the changes are not performed:

```bash
$ gman -config myconfig.yaml
Expand All @@ -187,7 +187,7 @@ $ gman -config myconfig.yaml

When running *Gman* with the `-confirm` flag the magic of synchronization happens!

- The users, groups and org units - that have been depicted to be present in config file, but not in Gsuite - are automatically created:
- The users, groups and org units - that have been depicted to be present in config file, but not in GSuite - are automatically created:

```bash
$ gman -config myconfig.yaml -confirm
Expand All @@ -205,7 +205,7 @@ $ gman -config myconfig.yaml -confirm
2020/06/25 18:59:54 ✓ Organization successfully synchronized.
```

- The users, groups and org units - that hold different values in the config file, than they have in Gsuite - are automatically updated:
- The users, groups and org units - that hold different values in the config file, than they have in GSuite - are automatically updated:

```bash
gman -config myconfig.yaml -confirm
Expand All @@ -223,7 +223,7 @@ gman -config myconfig.yaml -confirm
2020/06/25 19:01:38 ✓ Organization successfully synchronized.
```

- The users, groups and org units - that are present in Gsuite, but not in config file - are automatically deleted:
- The users, groups and org units - that are present in GSuite, but not in config file - are automatically deleted:

```bash
$ gman -config myconfig.yaml -confirm
Expand All @@ -249,7 +249,7 @@ $ gman -config myconfig.yaml -confirm
Due to the fact that it is impossible to automate the send out of the login information email via Google API there are two possibilities to enable the first log in of the new users:

- manually send the login information email from admin console via _RESET PASSWORD_ option (follow instructions on [this official Google documentation](https://support.google.com/a/answer/33319?hl=en))
- set up a password recovery for users (follow [this official Google documentation](https://support.google.com/a/answer/33382?p=accnt_recovery_users&visit_id=637279854011127407-389630162&rd=1&hl=en) to perform it). *Gman* sets te secondary email address as a recovery email; hence, in your onboarding message you should inform the users about their new Gsuite email address and that on the first login, the _Forgot password?_ option should be chosen, so the verification code can be sent to to the private secondary email.
- set up a password recovery for users (follow [this official Google documentation](https://support.google.com/a/answer/33382?p=accnt_recovery_users&visit_id=637279854011127407-389630162&rd=1&hl=en) to perform it). *Gman* sets te secondary email address as a recovery email; hence, in your onboarding message you should inform the users about their new GSuite email address and that on the first login, the _Forgot password?_ option should be chosen, so the verification code can be sent to to the private secondary email.

## Changelog

Expand Down
22 changes: 11 additions & 11 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,20 +88,20 @@ func (c *Config) Validate() error {
userEmails := []string{}
for _, user := range c.Users {
if util.StringSliceContains(userEmails, user.PrimaryEmail) {
log.Fatal("Validation failed: duplicate user defined (user: " + user.PrimaryEmail + ")")
log.Fatalf("Validation failed: duplicate user defined (user: %s)", user.PrimaryEmail)
}

if user.PrimaryEmail == user.SecondaryEmail {
log.Fatal("Validation failed: user has defined the same primary and secondary email (user: " + user.PrimaryEmail + ")")
log.Fatalf("Validation failed: user has defined the same primary and secondary email (user: %s)", user.PrimaryEmail)
}

if re.MatchString(user.PrimaryEmail) == false {
log.Fatal("Validation failed: invalid primary email (user: " + user.PrimaryEmail + ")")
log.Fatalf("Validation failed: invalid primary email (user: %s)", user.PrimaryEmail)
}

if user.SecondaryEmail != "" {
if re.MatchString(user.SecondaryEmail) == false {
log.Fatal("Validation failed: invalid secondary email " + user.SecondaryEmail + " (user: " + user.PrimaryEmail + ")")
log.Fatalf("Validation failed: invalid secondary email (user: %s)", user.PrimaryEmail)
}
}
userEmails = append(userEmails, user.PrimaryEmail)
Expand All @@ -112,21 +112,21 @@ func (c *Config) Validate() error {
groupEmails := []string{}
for _, group := range c.Groups {
if util.StringSliceContains(groupEmails, group.Email) {
log.Fatal("Validation failed: duplicate group email defined (" + group.Email + ")")
log.Fatalf("Validation failed: duplicate group email defined (%s)", group.Email)
}

if re.MatchString(group.Email) == false {
log.Fatal("Validation failed: invalid group email (" + group.Email + ")")
log.Fatalf("Validation failed: invalid group email (%s)", group.Email)
}

memberEmails := []string{}
for _, member := range group.Members {
if util.StringSliceContains(memberEmails, member.Email) {
log.Fatal("Validation failed: duplicate member defined in a group (group: " + group.Name + ", member: " + member.Email + ")")
log.Fatalf("Validation failed: duplicate member defined in a group (group: %s, member: %s)", group.Name, member.Email)
}

if !(strings.EqualFold(member.Role, "OWNER") || strings.EqualFold(member.Role, "MANAGER") || strings.EqualFold(member.Role, "MEMBER")) {
log.Fatal("Validation failed: wrong member role specified (group: " + group.Name + ", member: " + member.Email + ")")
log.Fatalf("Validation failed: wrong member role specified (group: %s, member: %s)", group.Name, member.Email)
}
}
}
Expand All @@ -135,14 +135,14 @@ func (c *Config) Validate() error {
ouNames := []string{}
for _, ou := range c.OrgUnits {
if util.StringSliceContains(ouNames, ou.Name) {
log.Fatal("Validation failed: duplicate org unit defined (" + ou.Name + ")")
log.Fatalf("Validation failed: duplicate org unit defined (%s)", ou.Name)
}

if ou.ParentOrgUnitPath[0] != '/' {
log.Fatal("Validation failed: wrong ParentOrgUnitPath specified for org unit (" + ou.Name + ")")
log.Fatalf("Validation failed: wrong ParentOrgUnitPath specified for org unit (%s)", ou.Name)
}
if ou.OrgUnitPath[0] != '/' {
log.Fatal("Validation failed: wrong OrgUnitPath specified for org unit (" + ou.Name + ")")
log.Fatalf("Validation failed: wrong OrgUnitPath specified for org unit (%s)", ou.Name)
}
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/export/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ func exportGroups(ctx context.Context, clientService *admin.Service, cfg *config
Name: g.Name,
Email: g.Email,
Description: g.Description,
Members: []config.MemberConfig{},
}
thisGroup.Members = make([]config.MemberConfig, 0) // dont panic, we allocate you memory
for _, m := range members {
thisGroup.Members = append(thisGroup.Members, config.MemberConfig{
Email: m.Email,
Expand All @@ -89,7 +89,7 @@ func exportGroups(ctx context.Context, clientService *admin.Service, cfg *config
}

func exportOrgUnits(ctx context.Context, clientService *admin.Service, cfg *config.Config) error {
log.Println("⇄ Exporting OrgUnits from GSuite...")
log.Println("⇄ Exporting organizational units from GSuite...")
// get the users array
orgUnits, _ := glib.GetListOfOrgUnits(clientService)

Expand Down
25 changes: 12 additions & 13 deletions pkg/glib/glib.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ func GetUserEmails(user *admin.User) (string, string) {
return primEmail, secEmail
}

// CreateNewUser creates a new user in GSuite via their API
func CreateNewUser(srv admin.Service, user *config.UserConfig) error {
// CreateUser creates a new user in GSuite via their API
func CreateUser(srv admin.Service, user *config.UserConfig) error {
// generate a rand password
pass, err := password.Generate(20, 5, 5, false, false)
if err != nil {
Expand Down Expand Up @@ -109,7 +109,7 @@ func UpdateUser(srv admin.Service, user *config.UserConfig) error {
return nil
}

// createGSuiteUserFromConfig converts a ConfigUser to (Gsuite) admin.User
// createGSuiteUserFromConfig converts a ConfigUser to (GSuite) admin.User
func createGSuiteUserFromConfig(user *config.UserConfig) *admin.User {
googleUser := &admin.User{
Name: &admin.UserName{
Expand Down Expand Up @@ -184,7 +184,7 @@ func UpdateGroup(srv admin.Service, group *config.GroupConfig) error {
return nil
}

// createGSuiteGroupFromConfig converts a ConfigGroup to (Gsuite) admin.Group
// createGSuiteGroupFromConfig converts a ConfigGroup to (GSuite) admin.Group
func createGSuiteGroupFromConfig(group *config.GroupConfig) *admin.Group {
googleGroup := &admin.Group{
Name: group.Name,
Expand Down Expand Up @@ -253,7 +253,7 @@ func UpdateMembership(srv admin.Service, groupEmail string, member *config.Membe
return nil
}

// createGSuiteGroupMemberFromConfig converts a ConfigMember to (Gsuite) admin.Member
// createGSuiteGroupMemberFromConfig converts a ConfigMember to (GSuite) admin.Member
func createGSuiteGroupMemberFromConfig(member *config.MemberConfig) *admin.Member {
googleMember := &admin.Member{
Email: member.Email,
Expand All @@ -276,8 +276,8 @@ func GetListOfOrgUnits(srv *admin.Service) ([]*admin.OrgUnit, error) {
return request.OrganizationUnits, nil
}

// CreateOU creates a new org unit in GSuite via their API
func CreateOU(srv admin.Service, ou *config.OrgUnitConfig) error {
// CreateOrgUnit creates a new org unit in GSuite via their API
func CreateOrgUnit(srv admin.Service, ou *config.OrgUnitConfig) error {
newOU := createGSuiteOUFromConfig(ou)
_, err := srv.Orgunits.Insert("my_customer", newOU).Do()
if err != nil {
Expand All @@ -287,8 +287,8 @@ func CreateOU(srv admin.Service, ou *config.OrgUnitConfig) error {
return nil
}

// DeleteGroup deletes a group in GSuite via their API
func DeleteOU(srv admin.Service, ou *admin.OrgUnit) error {
// DeleteOrgUnit deletes a group in GSuite via their API
func DeleteOrgUnit(srv admin.Service, ou *admin.OrgUnit) error {
// the Orgunits.Delete function takes as an argument the full org unit path, but without first slash...
var orgUPath []string
if ou.OrgUnitPath[0] == '/' {
Expand All @@ -305,10 +305,9 @@ func DeleteOU(srv admin.Service, ou *admin.OrgUnit) error {
return nil
}

// UpdateGroup updates the remote group with config
func UpdateOU(srv admin.Service, ou *config.OrgUnitConfig) error {
// UpdateOrgUnit updates the remote org unit with config
func UpdateOrgUnit(srv admin.Service, ou *config.OrgUnitConfig) error {
updatedOu := createGSuiteOUFromConfig(ou)
//orgUPath := append([]string{}, ou.OrgUnitPath)
// the Orgunits.Update function takes as an argument the full org unit path, but without first slash...
var orgUPath []string
if ou.OrgUnitPath[0] == '/' {
Expand All @@ -325,7 +324,7 @@ func UpdateOU(srv admin.Service, ou *config.OrgUnitConfig) error {
return nil
}

// createGSuiteGroupFromConfig converts a ConfigGroup to (Gsuite) admin.Group
// createGSuiteOUFromConfig converts a OrgUnitConfig to (GSuite) admin.OrgUnit
func createGSuiteOUFromConfig(ou *config.OrgUnitConfig) *admin.OrgUnit {
googleOU := &admin.OrgUnit{
Name: ou.Name,
Expand Down
8 changes: 4 additions & 4 deletions pkg/sync/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func SyncUsers(ctx context.Context, clientService *admin.Service, cfg *config.Co
if usersToCreate != nil {
log.Println("✎ Creating...")
for _, user := range usersToCreate {
glib.CreateNewUser(*clientService, &user)
glib.CreateUser(*clientService, &user)
log.Printf("\t+ user: %s\n", user.PrimaryEmail)
}
}
Expand Down Expand Up @@ -378,21 +378,21 @@ func SyncOrgUnits(ctx context.Context, clientService *admin.Service, cfg *config
if ouToCreate != nil {
log.Println("✎ Creating...")
for _, ou := range ouToCreate {
glib.CreateOU(*clientService, &ou)
glib.CreateOrgUnit(*clientService, &ou)
log.Printf("\t+ org unit: %s\n", ou.Name)
}
}
if ouToDelete != nil {
log.Println("✁ Deleting...")
for _, ou := range ouToDelete {
glib.DeleteOU(*clientService, ou)
glib.DeleteOrgUnit(*clientService, ou)
log.Printf("\t- org unit: %s\n", ou.Name)
}
}
if ouToUpdate != nil {
log.Println("✎ Updating...")
for _, ou := range ouToUpdate {
glib.UpdateOU(*clientService, &ou)
glib.UpdateOrgUnit(*clientService, &ou)
log.Printf("\t~ org unit: %s \n", ou.Name)
}
}
Expand Down

0 comments on commit 998a71c

Please sign in to comment.