Skip to content

Commit

Permalink
Added iam-sync-users
Browse files Browse the repository at this point in the history
  • Loading branch information
hamstah committed Jan 7, 2019
1 parent ddc5a90 commit 307c48e
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 1 deletion.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## v6.1.0 (21/12/2018)

**New**

* Added `iam-sync-users`

## v6.0.0 (17/12/2018)

**Fix**
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Collection of tools to make working with AWS a bit easier without having to depe
| [iam-session](iam/session/) | Creates new IAM session with role assumption and MFA support. |
| [iam-public-keys](iam/public-ssh-keys) | Returns the public SSH keys of an IAM user. |
| [iam-auth-proxy](iam/auth-proxy) | Use IAM as identity provider for services. |
| [iam-sync-users](iam/sync-users) | Create Linux users from IAM |
| [cloudwatch-put-metric-data](cloudwatch/put-metric-data) | Basic sending a metric value to cloudwatch |
| [ec2-ip-from-name](ec2/ip-from-name) | Given an EC2 name, list up to `-max-results` IPs associated with instances with that name |
| [ecr-get-login](ecr/get-login) | Prints out the command to run to auth with docker ECR. Check output flag for other options |
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6.0.0
6.1.0
46 changes: 46 additions & 0 deletions iam/sync-users/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# iam-sync-users

```
Note: Only works on Linux with sudo
```

```
usage: iam-sync-users [<flags>]
Create users from IAM
Flags:
--help Show context-sensitive help (also try --help-long and --help-man).
--assume-role-arn=ASSUME-ROLE-ARN
Role to assume
--assume-role-external-id=ASSUME-ROLE-EXTERNAL-ID
External ID of the role to assume
--assume-role-session-name=ASSUME-ROLE-SESSION-NAME
Role session name
--region=REGION AWS Region
--mfa-serial-number=MFA-SERIAL-NUMBER
MFA Serial Number
--mfa-token-code=MFA-TOKEN-CODE
MFA Token Code
-v, --version Display the version
--group=GROUP ... Add users from this group. You can use --group multiple times.
```

## IAM policy

You can use the `arn:aws:iam::aws:policy/IAMReadOnlyAccess` managed policy or use the custom one below

```
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:GetGroup"
],
"Resource": "*"
}
]
}
```
100 changes: 100 additions & 0 deletions iam/sync-users/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package main

import (
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"os/user"
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hamstah/awstools/common"

kingpin "gopkg.in/alecthomas/kingpin.v2"
)

var (
flags = common.KingpinSessionFlags()
infoFlags = common.KingpinInfoFlags()
groups = kingpin.Flag("group", "Add users from this group. You can use --group multiple times.").Strings()
)

func main() {
kingpin.CommandLine.Name = "iam-sync-users"
kingpin.CommandLine.Help = "Create users from IAM"
kingpin.Parse()
common.HandleInfoFlags(infoFlags)
common.FatalOnError(ensureCanCreateUser())

session := session.Must(session.NewSession())
conf := common.AssumeRoleConfig(flags, session)

iamClient := iam.New(session, conf)

users := []string{}

for _, group := range *groups {
newUsers, err := getUsersForGroup(iamClient, group)
common.FatalOnError(err)
users = append(users, newUsers...)
}

for _, userName := range users {
_, err := user.Lookup(userName)
if err == nil {
// user already exists
continue
}

common.FatalOnError(createUser(userName))
fmt.Println(userName)
}
}

func createUser(userName string) error {
cmd := exec.Command("/usr/sbin/adduser", userName)
err := cmd.Run()
if err != nil {
return err
}

sudoFilename := fmt.Sprintf("/etc/sudoers.d/%s", strings.Replace(userName, ".", "", -1))

err = ioutil.WriteFile(sudoFilename, []byte(fmt.Sprintf("%s ALL=(ALL) NOPASSWD:ALL\n", userName)), 0644)
if err != nil {
return err
}

return nil
}

func ensureCanCreateUser() error {
if _, err := os.Stat("/usr/sbin/adduser"); os.IsNotExist(err) {
return errors.New("Can't find adduser to create user")
}

if _, err := os.Stat("/etc/sudoers.d"); os.IsNotExist(err) {
return errors.New("Can't find adduser to create user")
}
return nil
}

func getUsersForGroup(client *iam.IAM, groupName string) ([]string, error) {
users := []string{}
err := client.GetGroupPages(&iam.GetGroupInput{GroupName: aws.String(groupName)},
func(page *iam.GetGroupOutput, lastPage bool) bool {
for _, user := range page.Users {
users = append(users, *user.UserName)
}
return true
})

if err != nil {
return nil, err
}
return users, nil
}

0 comments on commit 307c48e

Please sign in to comment.