Adoptable Cookbooks List

Looking for a cookbook to adopt? You can now see a list of cookbooks available for adoption!
List of Adoptable Cookbooks

Supermarket Belongs to the Community

Supermarket belongs to the community. While Chef has the responsibility to keep it running and be stewards of its functionality, what it does and how it works is driven by the community. The chef/supermarket repository will continue to be where development of the Supermarket application takes place. Come be part of shaping the direction of Supermarket by opening issues and pull requests or by joining us on the Chef Mailing List.

Select Badges

Select Supported Platforms

Select Status


ama-linux-user-management (1) Versions 0.1.0

Installs/Configures ama-linux-user-management

cookbook 'ama-linux-user-management', '~> 0.1.0', :supermarket
cookbook 'ama-linux-user-management', '~> 0.1.0'
knife supermarket install ama-linux-user-management
knife supermarket download ama-linux-user-management
Quality 17%

Cookbook ama-linux-user-management

Chef cookbook
CircleCI branch
Coveralls branch
Code Climate

This Chef cookbook is aimed to simplify the process of mapping real
people (or bots) and their machine credentials to corresponding linux
user accounts, groups, sudo superpowers and stuff.

Cookbook takes quite opinionated approach that may dramatically change
in next releases. Until v1.0, every minor release may introduce
breaking changes.

How does it work?

In a nutshell, end user of this cookbook specifies clients
(represents real people/bots with their roles and ssh keys) and
partitions (represents client groups and group abilities on
current node) and runs Chef. Clients are filtered according to
partitions, and linux user accounts / groups are created according to
rules defined in partitions. It is implied that client definitions are
the same for all managed nodes, and partitions should vary from node to
node - so, for example, clients may contain engineer and developer, but
developer would be allowed to visit staging servers only.

Let me see an example

Let's define a client

# That's client ID, it will be used for Linux user account
# if necessary
  # Roles are represented as a tree, with leaves being just null
  # Roles are matched by filters in partitions
      engineer: ~
      infrastructure: ~
      application: ~
      root: ~
      sysctl: ~
      content: AAAAB3NzaC1yc...
      validate: true
      content: ---BEGIN PRIVATE KEY...
      passphrase: admin
        corporate.infrastructure: ~ git
          Port: 22522
          User: john
      validate: true

Client is terribly simple. It's just an ID, a set of roles and
optional bunch of public and private keys - first are used to
login onto node, others are used to login from node. Roles are
used just as user labels, as you will see in a moment - nested
structure is implemented only not to add something role if
something.thatthing is defined.

Let's add some partitions:

    # don't create linux group for that
    # that will also mean that privileges will be
    # given to users rather than to a group
    group: none
    - cron.application.dashboard
      nopasswd: true
      command: php /var/www/dashboard/bin/console rebuild

    group: none
    # Don't even create accounts, just install the public keys
    account: none
    - access.root + manager.infrastructure
    root: ~

  # default policy will be used - edit for group and for users
    - bot.deploy
    - + manager.application
    - developer.php

Filters are represented as a list of conditions with OR relation:
if client matches at least one condition, it matches partition.
Conditions are described as a dot-delimited role path: bot.deploy
matches bot: { deploy: ~ } and bot: { deploy: { gently: ~ } },
but not just bot: ~.

Given those definitions, engineer client would fall under
superuser and www-data partitions (but not
sudo-dashboard-cron). So he
- Won't get any privilege
- His account will be created because www-data mandates so
- It will be in present in group www-data
- It also would be able to impersonate as root, which means his
public keys will be installed on root account

That's quite it: client is id, roles and keys, while partition is
filters, policy, privileges and impersonation.

Using all that knowledge

So far only the structure was described, but not how to pass it
into Chef. To use this cookbook, you will need to pass described
data into ama_linux_user_management resource:

ama_linux_user_management 'default' do
  clients data_bag_items
  partitions node['ama']['user']['partitions']

And that's it. To make things even easier, some shortcuts were added:
- If partitions are not set directly, they are fetched out of
- If clients are not set directly, they are fetched out of data bag
with name stored in node['ama']['user']['client-bag'] (clients
by default).
- For the laziest, this is incorporated under default resource.

What is policy?

Policy defines how specific entity may be treated. There are only
three policies available:

  • none: do not bother about entity, do not create it, do not edit it
  • edit: freely create and edit entity, but don't delete it
  • manage: same as edit, but delete entity when it is gone

The difference between edit and manage is only what happens if entity
gets deleted. Nost of the time, you'll want manage policy for your
custom accounts and groups and edit for system users and groups -
such as root and www-data.

Wait a second, are you storing all that information in attributes?

Most of that information. All keys - private and public - are not
stored, only their digests are used to identify them.

Shooting foots

If you ended up in this part of internet, you're

  • a) Gonna mess with private and public keys. And that stuff is terribly sensitive - of course i've put effort not to expose your keys in state or logs, but i can't prevent you from installing wrong key, forgetting to delete employee who has left and all other ways to make things go south. Be double cautious.
  • b) Gonna install somebody's auth key on root and grant sudo privileges. The warnings are quite the same, i can give you instrument to do this, but most of the time you should evade this as you vampires evade light.
  • c) GONNA END WITH MANAGE POLICY ON ROOT BUT DON'T DO IT. Root account becomes edited the second you try to impersonate it; if, for any reason, all impersonation dependencies vanish, it's gonna be garbage collected and you'll end with a useless brick of a previously happy node. So just keep it edited all the way.
  • d) In danger of hitting not-so-properly tested corner. I sincerely apologize for all the mess but i don't have currently any more time to develop this cookbook further.

Important notes

  • For sudo definition to be working, you have to set ['authorization']['sudo']['include_sudoers_d'] attribute to true. This is required by sudo cookbook.
  • All public keys set not through ssh_authorized_keys cookbook will be deleted.
  • Cookbook uses accumulator pattern - that means that subsequent resource calls would merge rather than overwrite each other. Cookbook stores it's state in attributes, which makes it possible to remember previously managed accounts to wipe them on new run.
  • This cookbook doesn't manage known_hosts because it's certainly not this cookbook's job and it would be serious security issue to import their keys blindly and/or failing whole run because of inaccessible remote node unless user asked to do so.


Contributions are welcome! Please send your pull requests into dev
branch. There is whole lot of bad code and unfinished work inside,
not even mentioning proper documentation.

Also be aware that this cookbook contains a vendored gem
(ama-entity-mapper), which is installed using rake vendor

Dev branch state

CircleCI branch
Coveralls branch


Long story short: this cookbook couldn't be tested the regular way
because of scenario diversity, so small not-a-framework had to be
developed. This cookbook has regular unit/integration suites (code
only) with no peculiarities, but functional (ChefSpec) and
acceptance (Test Kitchen) test suites use tests described in YAML.
Those suites are located in
and simply translate themselves into appropriate matchers. ChefSpec
tests simply read that directory out and apply stories one by one,
while Test Kitchen is configured using rake command
test:acceptance:setup - this will create the required suites and

Test reporting is done using Allure Framework - and, in
fact, due to specifics it's not really possible to test other way.
rake test:<type>:with-report will run appropriate tests and
generate report in test/report/allure.


MIT License / Created by AMA Team

Dependent cookbooks

ssh_authorized_keys ~> 0.3.0
sudo ~> 3.5.0
ssh ~> 0.10.22
ama-ssh-private-keys ~> 0.2.0

Contingent cookbooks

There are no cookbooks that are contingent upon this one.


All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog
and this project adheres to Semantic Versioning.

[0.1.0] 2017-08-09


  • Initial implementation

Collaborator Number Metric

0.1.0 failed this metric

Failure: Cookbook has 1 collaborators. A cookbook must have at least 2 collaborators to pass this metric.

Contributing File Metric

0.1.0 failed this metric

Failure: To pass this metric, your cookbook metadata must include a source url, the source url must be in the form of, and your repo must contain a file

Foodcritic Metric

0.1.0 passed this metric

No Binaries Metric

0.1.0 failed this metric

Failure: Cookbook should not contain binaries. Found:
ama-linux-user-management/test/report/allure/styles.css (size > 1048576 bytes)

Testing File Metric

0.1.0 failed this metric

Failure: To pass this metric, your cookbook metadata must include a source url, the source url must be in the form of, and your repo must contain a file

Version Tag Metric

0.1.0 failed this metric

Failure: To pass this metric, your cookbook metadata must include a source url, the source url must be in the form of, and your repo must include a tag that matches this cookbook version number