|
1 | 1 | #!/bin/bash
|
2 | 2 |
|
| 3 | +# Which IAM groups have access to this instance |
| 4 | +# Comma seperated list of IAM groups. Leave empty for all available IAM users |
| 5 | +IAM_AUTHORIZED_GROUPS="" |
| 6 | + |
| 7 | +# Special group to mark users as being synced by our script |
| 8 | +LOCAL_MARKER_GROUP="iam-synced-users" |
| 9 | + |
| 10 | +# Give the users these local UNIX groups |
| 11 | +LOCAL_GROUPS="" |
| 12 | + |
3 | 13 | # Specify an IAM group for users who should be given sudo privileges, or leave
|
4 | 14 | # empty to not change sudo access, or give it the value '##ALL##' to have all
|
5 | 15 | # users be given sudo rights.
|
6 |
| -SudoersGroup="" |
7 |
| -[[ -z "${SudoersGroup}" ]] || [[ "${SudoersGroup}" == "##ALL##" ]] || Sudoers=$( |
8 |
| - aws iam get-group --group-name "${SudoersGroup}" --query "Users[].[UserName]" --output text |
9 |
| -); |
10 |
| - |
11 |
| -aws iam list-users --query "Users[].[UserName]" --output text | while read User; do |
12 |
| - SaveUserName="$User" |
13 |
| - SaveUserName=${SaveUserName//"+"/".plus."} |
14 |
| - SaveUserName=${SaveUserName//"="/".equal."} |
15 |
| - SaveUserName=${SaveUserName//","/".comma."} |
16 |
| - SaveUserName=${SaveUserName//"@"/".at."} |
17 |
| - if ! grep "^$SaveUserName:" /etc/passwd > /dev/null; then |
18 |
| - /usr/sbin/useradd --create-home --shell /bin/bash "$SaveUserName" |
19 |
| - fi |
20 |
| - |
21 |
| - if [[ ! -z "${SudoersGroup}" ]]; then |
22 |
| - # sudo will read each file in /etc/sudoers.d, skipping file names that end |
23 |
| - # in ‘~’ or contain a ‘.’ character to avoid causing problems with package |
24 |
| - # manager or editor temporary/backup files. |
25 |
| - SaveUserFileName=$(echo "$SaveUserName" | tr "." " ") |
26 |
| - SaveUserSudoFilePath="/etc/sudoers.d/$SaveUserFileName" |
27 |
| - if [[ "${SudoersGroup}" == "##ALL##" ]] || echo "$Sudoers" | grep "^$User\$" > /dev/null; then |
28 |
| - echo "$SaveUserName ALL=(ALL) NOPASSWD:ALL" > "$SaveUserSudoFilePath" |
| 16 | +SUDOERSGROUP="" |
| 17 | + |
| 18 | +# Assume a role before contacting AWS IAM to get users and keys. |
| 19 | +# This can be used if you define your users in one AWS account, while the EC2 |
| 20 | +# instance you use this script runs in another. |
| 21 | +ASSUMEROLE="" |
| 22 | + |
| 23 | +function setup_aws_credentials() { |
| 24 | + local stscredentials |
| 25 | + if [[ ! -z "${ASSUMEROLE}" ]] |
| 26 | + then |
| 27 | + stscredentials=$(aws sts assume-role \ |
| 28 | + --role-arn "${ASSUMEROLE}" \ |
| 29 | + --role-session-name something \ |
| 30 | + --query '[Credentials.SessionToken,Credentials.AccessKeyId,Credentials.SecretAccessKey]' \ |
| 31 | + --output text) |
| 32 | + |
| 33 | + AWS_ACCESS_KEY_ID=$(echo "${stscredentials}" | awk '{print $2}') |
| 34 | + AWS_SECRET_ACCESS_KEY=$(echo "${stscredentials}" | awk '{print $3}') |
| 35 | + AWS_SESSION_TOKEN=$(echo "${stscredentials}" | awk '{print $1}') |
| 36 | + AWS_SECURITY_TOKEN=$(echo "${stscredentials}" | awk '{print $1}') |
| 37 | + export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN AWS_SECURITY_TOKEN |
| 38 | + fi |
| 39 | +} |
| 40 | + |
| 41 | +# Get all IAM users (optionally limited by IAM groups) |
| 42 | +function get_iam_users() { |
| 43 | + local group |
| 44 | + if [ -z "${IAM_AUTHORIZED_GROUPS}" ] |
| 45 | + then |
| 46 | + aws iam list-users \ |
| 47 | + --query "Users[].[UserName]" \ |
| 48 | + --output text \ |
| 49 | + | sed "s/\r//g" |
29 | 50 | else
|
30 |
| - [[ ! -f "$SaveUserSudoFilePath" ]] || rm "$SaveUserSudoFilePath" |
| 51 | + for group in $(echo ${IAM_AUTHORIZED_GROUPS} | tr "," " "); do |
| 52 | + aws iam get-group \ |
| 53 | + --group-name "${group}" \ |
| 54 | + --query "Users[].[UserName]" \ |
| 55 | + --output text \ |
| 56 | + | sed "s/\r//g" |
| 57 | + done |
31 | 58 | fi
|
32 |
| - fi |
33 |
| -done |
| 59 | +} |
| 60 | + |
| 61 | +# Get previously synced users |
| 62 | +function get_local_users() { |
| 63 | + /usr/bin/getent group ${LOCAL_MARKER_GROUP} \ |
| 64 | + | cut -d : -f4- \ |
| 65 | + | sed "s/,/ /g" |
| 66 | +} |
| 67 | + |
| 68 | +function get_sudoers_users() { |
| 69 | + [[ -z "${SUDOERSGROUP}" ]] || [[ "${SUDOERSGROUP}" == "##ALL##" ]] || |
| 70 | + aws iam get-group \ |
| 71 | + --group-name "${SUDOERSGROUP}" \ |
| 72 | + --query "Users[].[UserName]" \ |
| 73 | + --output text |
| 74 | +} |
| 75 | + |
| 76 | +# Create or update a local user based on info from the IAM group |
| 77 | +function create_or_update_local_user() { |
| 78 | + local iamusername |
| 79 | + local username |
| 80 | + local sudousers |
| 81 | + local localusergroups |
| 82 | + |
| 83 | + iamusername="${1}" |
| 84 | + username="${2}" |
| 85 | + sudousers="${3}" |
| 86 | + localusergroups="${LOCAL_MARKER_GROUP}" |
| 87 | + |
| 88 | + if [ ! -z "${LOCAL_GROUPS}" ] |
| 89 | + then |
| 90 | + localusergroups="${LOCAL_GROUPS},${LOCAL_MARKER_GROUP}" |
| 91 | + fi |
| 92 | + |
| 93 | + id "${username}" >/dev/null 2>&1 \ |
| 94 | + || /usr/sbin/useradd --create-home --shell /bin/bash "${username}" \ |
| 95 | + && /bin/chown -R "${username}:${username}" "/home/${username}" |
| 96 | + /usr/sbin/usermod -G "${localusergroups}" "${username}" |
| 97 | + |
| 98 | + # Should we add this user to sudo ? |
| 99 | + if [[ ! -z "${SUDOERSGROUP}" ]] |
| 100 | + then |
| 101 | + SaveUserFileName=$(echo "${username}" | tr "." " ") |
| 102 | + SaveUserSudoFilePath="/etc/sudoers.d/$SaveUserFileName" |
| 103 | + if [[ "${SUDOERSGROUP}" == "##ALL##" ]] || echo "${sudousers}" | grep "^${iamusername}\$" > /dev/null |
| 104 | + then |
| 105 | + echo "${SaveUserName} ALL=(ALL) NOPASSWD:ALL" > "${SaveUserSudoFilePath}" |
| 106 | + else |
| 107 | + [[ ! -f "${SaveUserSudoFilePath}" ]] || rm "${SaveUserSudoFilePath}" |
| 108 | + fi |
| 109 | + fi |
| 110 | +} |
| 111 | + |
| 112 | +function delete_local_user() { |
| 113 | + /usr/sbin/usermod -L -s /sbin/nologin "${1}" |
| 114 | + /usr/bin/pkill -KILL -u "${1}" |
| 115 | + /usr/sbin/userdel -r "${1}" |
| 116 | +} |
| 117 | + |
| 118 | +function clean_iam_username() { |
| 119 | + local clean_username="${1}" |
| 120 | + clean_username=${clean_username//"+"/".plus."} |
| 121 | + clean_username=${clean_username//"="/".equal."} |
| 122 | + clean_username=${clean_username//","/".comma."} |
| 123 | + clean_username=${clean_username//"@"/".at."} |
| 124 | + echo "${clean_username}" |
| 125 | +} |
| 126 | + |
| 127 | +function sync_accounts() { |
| 128 | + if [ -z "${LOCAL_MARKER_GROUP}" ] |
| 129 | + then |
| 130 | + echo "Please specify a local group to mark imported users. eg iam-synced-users" |
| 131 | + exit 1 |
| 132 | + fi |
| 133 | + |
| 134 | + # Check if local marker group exists, if not, create it |
| 135 | + /usr/bin/getent group "${LOCAL_MARKER_GROUP}" >/dev/null 2>&1 || /usr/sbin/groupadd "${LOCAL_MARKER_GROUP}" |
| 136 | + |
| 137 | + # setup the aws credentials if needed |
| 138 | + setup_aws_credentials |
| 139 | + |
| 140 | + # declare and set some variables |
| 141 | + local iam_users |
| 142 | + local sudo_users |
| 143 | + local local_users |
| 144 | + local intersection |
| 145 | + local removed_users |
| 146 | + local user |
| 147 | + |
| 148 | + iam_users=$(get_iam_users | sort | uniq) |
| 149 | + sudo_users=$(get_sudoers_users | sort | uniq) |
| 150 | + local_users=$(get_local_users | sort | uniq) |
| 151 | + |
| 152 | + intersection=$(echo ${local_users} ${iam_users} | tr " " "\n" | sort | uniq -D | uniq) |
| 153 | + removed_users=$(echo ${local_users} ${intersection} | tr " " "\n" | sort | uniq -u) |
| 154 | + |
| 155 | + # Add or update the users found in IAM |
| 156 | + for user in ${iam_users}; do |
| 157 | + SaveUserName=$(clean_iam_username "${user}") |
| 158 | + create_or_update_local_user "${user}" "${SaveUserName}" "$sudo_users" |
| 159 | + done |
| 160 | + |
| 161 | + # Remove users no longer in the IAM group(s) |
| 162 | + for user in ${removed_users}; do |
| 163 | + delete_local_user "${user}" |
| 164 | + done |
| 165 | +} |
| 166 | + |
| 167 | +sync_accounts |
0 commit comments