User Mangement using CHEF and AWS OpsWorks

18 / Oct / 2015 by Ranvijay Jamwal 3 comments

CHEF is the most popular configuration management tool in the market these days as CHEF turns infrastructure into code and you can do almost anything using it. Recipes are the heart of CHEF. OpsWorks has been gaining a lot of momentum for last few months, the major factor being its support for CHEF. So, in this blog we will be discussing how we can can manage users on multiple machines and their permissions as well. You will see how easy it is to do so and manage all the configurations as well. The recipes I have used can be shared can be used independent of OpsWorks with minimal changes.

download (1)

USE-CASE

I had multiple users on my machines. Whenever there was a new user who joined the firm to give him access on those machines I had to manually go and add the user to that machine. Also, adding the user to a group was necessary so that permissions could be managed at the level of groups. So, I had to think of a way out and to manage all this through one click using CHEF and OpsWorks. We will be using a CHEF recipe and passing values to those using Opsworks data-bags and deploying the configs using one click deployment in OpsWorks. What OpsWorks does is that it creates a copy of your GitHub repo locally to itself and then executes the recipes when we specify which one to execute. Since, we are using data bags in our recipes, we will give input values to them as JSON through OpsWorks.

GATHERING THE CHEF RECIPES

Recipe 1: This is the user creation recipe:


users = data_bag("user")
users.each do |user|
    user_data = data_bag_item("user", user)
        user user_data["id"] do
                comment user_data["comments"]
                #uid user_data["uid"]
                #gid user_data["gid"]
                home user_data["home"]
                shell user_data["shell"]
                password user_data["password"]
                supports :manage_home => true
                action :create
        end

        directory "#{user_data['home']}/.ssh" do
 	        mode 0755
 	        owner user_data["id"]
 	        action :create
        end

        file "#{user_data['home']}/.ssh/authorized_keys" do
 	        content user_data["ssh_keys"].join("\n")
 	        mode 0600
 	        owner user_data["id"]
 	        action :create
        end
	if user_data["sudo"] == "true"
		template "/etc/sudoers.d/#{user_data["id"]}" do
       		source "sudoers.erb"
       		mode "0644"
       		variables({
     		:sudoers_users => user_data["id"]
  		})
		end
	end
end

The above script will create users based on the JSON values we pass in OpsWorks. It will create a .ssh folder inside the home directory of the user as well and append the ssh-keys inside the authorized_keys file.

Recipe 2: This will be used to create groups. We will need to pass values to it using OpsWorks:

groups = data_bag("group")
groups.each do |group|
        group_data = data_bag_item('group', group)
        group group_data['id'] do
                gid group_data["gid"]
                members group_data["members"]
        end
end

Recipe 3: Next we would need a script which will help us modify our sudoers file inside sudoers.d:

I have just entered some random permissions for the groups:

line = "%sap    ALL= NOPASSWD: /usr/sbin/apache2*
%sap    ALL= NOPASSWD: /usr/local/bin/apache2*
#%sap    ALL= NOPASSWD: /usr/local/bin/restart-sauce-connect
%sap    ALL= NOPASSWD: /usr/local/bin/restart-sauce-connect
jenkins ALL= NOPASSWD: /usr/sbin/apache2*
jenkins ALL= NOPASSWD: /usr/local/bin/restart-sauce-connect
"
file = Chef::Util::FileEdit.new('/etc/sudoers.d/anyname')
file.insert_line_if_no_match(/#{line}/, line)
file.write_file

Now, just push the recipe to a git repository inside the cookbook user (or any other name of your choice).The structure should be like this:
repo->master-branch->cookbook->recipes->recipe1.rb, recipe2.rb, recipe3.rb

EXECUTING RECIPES

1. Creating a user on servers according to Recipe 1 and giving input to the recipe using OpsWorks.

Go to the AWS OpsWorks console. I am assuming that you already have created a stack and added instances to the stack. Remember it supports not all the OS versions so you might want to check the compatibility. From the Dashboard select the stack:
Edit Post ‹ TO THE NEW Blog — WordPress

Next, is adding the GitHub repo to your stack settings in order for you to use the recipe we created:
Stack - AAP-Stack – AWS OpsWorks 2015-10-15 16-19-48

Click on edit inside Stack Settings:
Stack - AAP-Stack – AWS OpsWorks 2015-10-15 16-21-53

Now, just enter the GitHub repo. details:
Edit Stack - AAP-Stack – AWS OpsWorks 2015-10-15 16-24-14

Now, go to Deployments:
.Stack - AAP-Stack – AWS OpsWorks 2015-10-15 16-26-51

You will be taken to the following page:
Deployments - AAP-Stack – AWS OpsWorks 2015-10-15 16-31-29

Just go ahead and click on Run Command and it should take you to the below page:
Repeat deployment 2015-09-28T11:33:22+00:00 - AAP-Stack – AWS OpsWorks 2015-10-15 16-35-43

Select Execute Recipes from the drop-down and enter the cookbook name and recipe name as shown in the image.We are using cookbook named “final” and recipe named “createuserwithsudo”.  When entering them in the Recipes to execute box use “::” (two colons) to separate them.
Also,  now, click on Advanced which should open a box to input a JSON:
Repeat deployment 2015-09-28T11:33:22+00:00 - AAP-Stack – AWS OpsWorks 2015-10-15 16-42-45

Sample JSON input:

{
  "opsworks": {
    "data_bags": {
      "user": {
        "user1" : {
          "id" : "user1",
          "comments" : "some comment",
          "home" : "/home/user1",
          "shell" : "/bin/bash",
          "sudo" : "false",
          "password" : "$1$d01YpgzW$Yt64wYX/uWstYf2lGiZuR0",
          "ssh_keys" : ["ssh-key-1","ssh-key-2"]
         },
        "user2" : {
          "id" : "user2",
          "comments" : "some comment",
          "home" : "/home/user2",
          "shell" : "/bin/bash",
          "sudo" : "true",
          "password" : "$1$d01YpgzW$Yt64wYX/uWstYf2lGiZuR0",
          "ssh_keys" : ["ssh-key-1","ssh-key-2"]
         },
           "user3" : {
          "id" : "user3",
          "comments" : "some comment",
          "home" : "/home/user3",
          "shell" : "/bin/bash",
          "sudo" : "true",
          "password" : "$1$d01YpgzW$Yt64wYX/uWstYf2lGiZuR0",
          "ssh_keys" : ["ssh-key-1","ssh-key-2"]
       }
      }
    }
  }
}

You need to replace the user1, 2 and 3 with user-name you want on the server. Also, replace the ssh-keys with the ones associated with the user. The password for the user needs to be generated via open-ssl. CHEF recipe won’t take password in normal text format. Also,
sudo==true means user will have root privileges. Next, click on Execute Recipes after choosing the instances of the stack on which you want the recipe to be executed:
Repeat deployment 2015-09-28T11:33:22+00:00 - AAP-Stack – AWS OpsWorks 2015-10-15 16-57-11

So, you are done! After the recipe is executed, it will show you the results then and there. Also, if you wish to see logs of a previously executed recipe click on the date & time and it should take you to the particular command’s page where you can see logs as well:
Deployments - AAP-Stack – AWS OpsWorks 2015-10-15 17-05-03

If you make any changes to your recipes in your GitHub, after pushing the changes you need to go to “Run Command” and select Update Cookbooks:
Run command - AAP-Stack – AWS OpsWorks 2015-10-15 17-52-32The user will be created on the specified servers.

2. Now, if you wish to add the newly created user to a group

Simply execute the Recipe 2. It will create a group if it does not exist already and then add the users to the group. Execute the recipe as we did before. Enter the cookbook name and recipe name:
2015-09-30T08:15:10+00:00 - Deployments - AAP-Stack – AWS OpsWorks 2015-10-15 17-31-05

Sample JSON:

{
  "opsworks": {
    "data_bags": {
      "group": {
        "admin": {
             "gid": "3308",
             "members": ["user1","user2","user3","user4","user5"]
               }

               }

                 }

               }
}

3. Handling the file inside sudoers.d to give different permissions.

Use Recipe 3 for this. Just go ahead and run the recipe. I have written some basics commands which can be allowed for a group. You can use this however you like. Remember to update cookbooks in OpsWorks console so that the changes in GitHub repo are reflected here. Just simply execute the recipe as we have done earlier, choose the server and it will append to the file inside sudoers.d

For example: /etc/sudoers.d/serveralpha

You need to make changes to the recipe according to your use case and names of files. In case you make changes to the recipe make sure you run the Update Cookbooks command as I have shown in step 1.

This is the basic way of handling users on your servers using CHEF. In my next blog, I shall talk about more use-cases of CHEF.

FOUND THIS USEFUL? SHARE IT

comments (3)

  1. Erich Beyrent

    Is there a reason why you didn’t create IAM users, add the key for each user there, and then include the ssh_users cookbook that Opsworks provides?

    Reply
    1. Ranvijay JamwalRanvijay Jamwal Post author

      Hello Erich,

      Well. That is an approach which you can definitely follow.
      That would require you creating an IAM user for every user whom you wish to give access to the servers.
      It’s killing the traditional way and adds dependency onto an AWS service.
      Also, the servers which you add to a stack, these IAM users will have access to every one of those servers. So, that is another reason for not using IAM users.

      Using a self-made cookbook helped me do the things the way I wanted and remove any ambiguities.

      Reply
  2. Pingback: This Week in AWS, October 18, 2015 – This Week In AWS | Amazon Web Services

Leave a comment -