[chef] Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Chef and LDAP Users


Chronological Thread 
  • From: Douglas Garstang < >
  • To:
  • Subject: [chef] Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Chef and LDAP Users
  • Date: Thu, 31 Jul 2014 13:00:55 -0700

Looks like it should work. The getent function (is it even a function? Why does it have 'new' in front? Isn't that for classes? - ruby.... ugh) returns an array and the uid and gid methods return a specific element of the array.... in my example... no?

Doug.


On Thu, Jul 31, 2014 at 12:42 PM, AJ Christensen < " target="_blank"> > wrote:
The bug that I purposefully left in the Library code has not been
fixed. The return value of the getent() function is not correct.

Good luck! I would probably store authorized keys in LDAP as well.

Cheers,

AJ

On Fri, Aug 1, 2014 at 7:37 AM, Douglas Garstang
< "> > wrote:
> AJ,
>
> There home directories are being created by LDAP and PAM on first login.
> However, that does not handle the setup of the ssh authorized keys file. For
> select users, I wanted chef to create the home directories, with the correct
> uid and gid pulled from LDAP, and then pull the ssh public key from a data
> bag and drop it into their home directory. Obviously, the LDAP recipe has to
> run first in the run list. This should be pretty simple.
>
> My latest attempt, based on your suggestion, is not working however. I
> believe the uid and gid are correct (although I can't print them because
> that causes it to fail. How do I print lazy variables? I tried using lazy in
> the log statement and it failed), but I can't verify because I can't print.
> When the recipe has run, /home/doug is owned by root.root.
>
> Doug
>
> # recipe
> include_recipe "foo-ldap"
> bag = data_bag("ssh-keys")
> for item in bag do
>     user = data_bag_item('ssh-keys', item)
>     user_name = user['id']
>     directory "/home/#{user_name}" do
>         owner lazy { ShellGetent.uid "#{user_name}" }
>         group lazy { ShellGetent.gid "#{user_name}" }
>     end
> end
>
> # library:
> class ShellGetent
>     include Chef::Mixin::ShellOut
>
>     class << self
>         def uid(username)
>             return if username.nil? || username.empty?
>             x = new.getent(:passwd, username)[2]
>         end
>
>         def gid(username)
>             return if username.nil? || username.empty?
>             new.getent(:passwd, username)[3]
>         end
>     end
>
>     # Returns a new slice of parts of the output. Maybe make a struct or
> something? Be creative!
>     def getent(type, name)
>         return unless %w(passwd).include?(type.to_s)
>         cmd = shell_out!("getent #{type.to_s} #{name}")
>         cmd.stdout.split(":")
>     end
>
> end
>
>
>
>
>
>
> On Thu, Jul 31, 2014 at 11:23 AM, AJ Christensen < "> > wrote:
>>
>> Another way to run the code during convergence time is to put the code
>> in the body of an LWRP action, when the action fires (converge time)
>> the code will run (not compile time!)
>>
>> A way to tidy this is to put re-used logic in Libraries and refer to
>> those method/function calls from the LWRP itself.
>>
>> I believe that is most of the ways.
>>
>> Copying data in/out of resources at compile/convergence phase is one
>> of the most advanced/nasty pieces of knowledge you will gain regarding
>> recipe authorship, I expect; it should be avoided.
>>
>> I would consider re-designing your entire user management system and
>> extract it from Chef; have like a little process that runs on every
>> node, listening to LDAP; when new users are made, use skel to
>> construct them. I could have sworn I saw functionality in PAM,
>> specifically for creating users home dirs and so-on, when logged in
>> from LDAP for the first time.
>>
>> http://manpages.ubuntu.com/manpages/maverick/man8/pam_mkhomedir.8.html
>>
>> Many ways to shave dat yak.
>>
>> Chef -> configure LDAP -> configure PAM -> Users log in -> Home dirs
>> created automatically via PAM -> No compile/converge phase
>> shenanigans.
>>
>> Be careful configuring PAM, you can easily hose your system.
>>
>> --AJ
>>
>> On Fri, Aug 1, 2014 at 6:17 AM, AJ Christensen < "> > wrote:
>> > My specific example shows the code being called at Convergence Time
>> > through a Lazy Attribute evaluation (a new Chef11 feature).
>> >
>> > Specifically: the attributes to the resource when lazy aren't
>> > evaluated at compile time, they are "finalized" so to speak at
>> > convergence time, when the action actually needs it!
>> >
>> > --aj
>> >
>> > On Fri, Aug 1, 2014 at 6:15 AM, Douglas Garstang
>> > < "> > wrote:
>> >> AJ,
>> >>
>> >> Thanks. Now, what are the practical implications of compile and
>> >> converge in
>> >> relation to variable scope? How does one 'Run the ShellOut code during
>> >> convergence'? Does it have to be in a library as you've done? Can it be
>> >> done
>> >> another way? What exactly in a recipe makes something run at compile or
>> >> converge time? How do you tell? How do you pass variables obtained
>> >> during
>> >> compilation (or is it convergence) back to the other?
>> >>
>> >> Doug
>> >>
>> >>
>> >> On Thu, Jul 31, 2014 at 11:12 AM, AJ Christensen < "> >
>> >> wrote:
>> >>>
>> >>> http://docs.getchef.com/essentials_nodes_chef_run.html
>> >>>
>> >>> * Compile the resource collection
>> >>>
>> >>> The chef-client identifies each resource in the node object and builds
>> >>> the resource collection. All libraries are loaded (to ensure that all
>> >>> language extensions and Ruby classes are available). And then all
>> >>> attributes are loaded. And then all lightweight resources are loaded.
>> >>> And then all definitions are loaded (to ensure that any
>> >>> pseudo-resources are available). Finally, all recipes are loaded in
>> >>> the order specified by the expanded run-list; each action specified in
>> >>> each recipe is identified before any Ruby code within a recipe is
>> >>> evaluated.
>> >>>
>> >>> * Converge the node
>> >>>
>> >>> The chef-client configures the system based on the information that
>> >>> has been collected. Each resource is executed in the order identified
>> >>> by the run-list, and then by the order in which each resource is
>> >>> listed in each recipe. Each resource in the resource collection is
>> >>> mapped to a provider. The provider examines the node, and then does
>> >>> the steps necessary to complete the action. And then the next resource
>> >>> is processed. Each action configures a specific part of the system.
>> >>> This process is also referred to as convergence.
>> >>>
>> >>> Run the ShellOut code during convergence after the LDAP code has
>> >>> converged (instead of at compile time as your example inaccurately
>> >>> attempts to represent mine)
>> >>>
>> >>> YMMV
>> >>>
>> >>> --aj
>> >>>
>> >>> On Fri, Aug 1, 2014 at 6:10 AM, AJ Christensen < "> > wrote:
>> >>> > You ignored all of my examples and ran the code at Shell Out code at
>> >>> > compile time. It will be executed before the other LDAP stuff is
>> >>> > actually converged.
>> >>> >
>> >>> > Don't be such a support vampire bro.
>> >>> >
>> >>> > --AJ
>> >>> >
>> >>> > On Fri, Aug 1, 2014 at 5:59 AM, Douglas Garstang
>> >>> > < "> > wrote:
>> >>> >> AJ,
>> >>> >>
>> >>> >> Thanks. I'm really not a ruby guy. It will take me considerable
>> >>> >> time to
>> >>> >> work
>> >>> >> out your gist. I tried this. I thought the call to Mixlib::ShellOut
>> >>> >> would
>> >>> >> fork a new process and therefore get me the correct result.
>> >>> >> However,
>> >>> >> cmd.stdout is empty on the first run, and contains the correct
>> >>> >> getent
>> >>> >> passwd
>> >>> >> reply on the second run, so I assume it's the same issue...
>> >>> >>
>> >>> >> include_recipe "foo-ldap"
>> >>> >>
>> >>> >> bag = data_bag("ssh-keys")
>> >>> >> for item in bag do
>> >>> >>
>> >>> >>     user = data_bag_item('ssh-keys', item)
>> >>> >>     user_name = user['id']
>> >>> >>
>> >>> >>     execute "create_homedir" do
>> >>> >>         command "mkdir /home/#{user_name}"
>> >>> >>         creates "/home/#{user_name}"
>> >>> >>         action :run
>> >>> >>     end
>> >>> >>
>> >>> >>     log "USER_NAME = #{user_name}"
>> >>> >>     cmd = Mixlib::ShellOut.new("getent passwd #{user_name}")
>> >>> >>     cmd.run_command
>> >>> >>     log ">>>>>>>>>>>>>>>>>>>>>>>>>>> NODE_DATA  = #{cmd.stdout}"
>> >>> >>     ent_array = cmd.stdout.split(':')
>> >>> >>     user_id = ent_array[2]
>> >>> >>     group_id = ent_array[3]
>> >>> >>
>> >>> >>     execute "homedir_perms" do
>> >>> >>         command "chown #{user_id}.#{group_id} /home/#{user_name}"
>> >>> >>         action :run
>> >>> >>     end
>> >>> >>
>> >>> >> end
>> >>> >>
>> >>> >>
>> >>> >>
>> >>> >> On Wed, Jul 30, 2014 at 5:25 PM, AJ Christensen < "> >
>> >>> >> wrote:
>> >>> >>>
>> >>> >>> I meant to link to this too re: Mixlib ShellOut:
>> >>> >>>
>> >>> >>>
>> >>> >>>
>> >>> >>> https://github.com/opscode/chef/blob/master/lib/chef/mixin/shell_out.rb#L29-L39
>> >>> >>>
>> >>> >>> 'git grep shell_out' in the Chef codebase, haha! You'll see all of
>> >>> >>> the
>> >>> >>> places this is used.
>> >>> >>>
>> >>> >>> --aj
>> >>> >>>
>> >>> >>> On Thu, Jul 31, 2014 at 12:22 PM, AJ Christensen < "> >
>> >>> >>> wrote:
>> >>> >>> > If you 'include Chef::Mixin::ShellOut' in a custom library, you
>> >>> >>> > can
>> >>> >>> > use #shell_out! there.
>> >>> >>> >
>> >>> >>> > using the lazy attribute evaluator and the Mixin ShellOut
>> >>> >>> > classes'
>> >>> >>> > shell_out!() functionality, something like this outta' work:
>> >>> >>> > https://gist.github.com/fujin/f0b7dd38b558001c5913
>> >>> >>> >
>> >>> >>> > --aj
>> >>> >>> >
>> >>> >>> > On Thu, Jul 31, 2014 at 12:03 PM, Daniel DeLeo
>> >>> >>> > < "> >
>> >>> >>> > wrote:
>> >>> >>> >> On Wednesday, July 30, 2014 at 5:00 PM, Douglas Garstang wrote:
>> >>> >>> >>> AJ,
>> >>> >>> >>>
>> >>> >>> >>> Thanks. One more question... shelling out in chef and grabbing
>> >>> >>> >>> the
>> >>> >>> >>> output... has never been an easy task... best approach?
>> >>> >>> >>>
>> >>> >>> >>> I was able to do this just now with the execute resource, I
>> >>> >>> >>> guess
>> >>> >>> >>> because that forks a new process too. It would be nice though
>> >>> >>> >>> to
>> >>> >>> >>> call getent
>> >>> >>> >>> in some fashion, and the parse the output, so that I could be
>> >>> >>> >>> sure
>> >>> >>> >>> that the
>> >>> >>> >>> group id I am assigning is the correct one for the user. At
>> >>> >>> >>> the
>> >>> >>> >>> moment it's
>> >>> >>> >>> coming out of a data bag.
>> >>> >>> >>>
>> >>> >>> >>> Also kinda gross.
>> >>> >>> >>>
>> >>> >>> >>> Doug
>> >>> >>> >> Well, it’ll be a little gross, but I think you’ll have to use a
>> >>> >>> >> lazy
>> >>> >>> >> attribute
>> >>> >>> >>
>> >>> >>> >>
>> >>> >>> >> http://docs.getchef.com/resource_common.html#lazy-attribute-evaluation
>> >>> >>> >>
>> >>> >>> >> In the code block you give to `lazy`, you can use backticks or
>> >>> >>> >> %x
>> >>> >>> >> to
>> >>> >>> >> run a command that returns the UID.
>> >>> >>> >>
>> >>> >>> >>
>> >>> >>> >> --
>> >>> >>> >> Daniel DeLeo
>> >>> >>> >>
>> >>> >>> >>
>> >>> >>> >>
>> >>> >>
>> >>> >>
>> >>> >>
>> >>> >>
>> >>> >> --
>> >>> >> Regards,
>> >>> >>
>> >>> >> Douglas Garstang
>> >>> >> http://www.linkedin.com/in/garstang
>> >>> >> Email: ">
>> >>> >> Cell: +1-805-340-5627
>> >>
>> >>
>> >>
>> >>
>> >> --
>> >> Regards,
>> >>
>> >> Douglas Garstang
>> >> http://www.linkedin.com/in/garstang
>> >> Email: ">
>> >> Cell: +1-805-340-5627
>
>
>
>
> --
> Regards,
>
> Douglas Garstang
> http://www.linkedin.com/in/garstang
> Email: ">
> Cell: +1-805-340-5627



--
Regards,

Douglas Garstang
http://www.linkedin.com/in/garstang
Email: ">
Cell: +1-805-340-5627



Archive powered by MHonArc 2.6.16.

§