IT • 53:19
Snow Leopard and Snow Leopard Server deliver the widest array of scripting technologies in a single box. Learn how to write scripts using a variety of tools and languages to automate repetitive tasks for system setup, configuration, and other management duties.
Speakers: Joel Rennich, Josh Wisenbaker, Timothy Perfitt
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript has potential transcription errors. We are working on an improved version.
Auto-enrolling with Microsoft Certificate Authority, Making the Magic Happen. This is an iPhone, great device for typing scripts into the notes or something like that, nice way. Gratuitous keynote transition. All right, enterprise identities, so if you're in an enterprise environment, if you're just in a large organization, you probably use a lot of certificate identities for lot of things. If you've been to any of the phone sessions, they've talked about some of the auto-enrollment there through SCP and some of the other stuff.
This gets further into that but how to do it on the desktop side. So why do you want a certificate VPN access? You might require certificate authentication 802.1X website, you might have a client site certificate that you want authentication to. So we've got a rather robust certificate implementation, the problem is it can require user interaction. If your current-- whose doing 802.1X authentication with certificates right now? Reasonable amount of people.
Who wants to do it? A few more, good. All right, so this will hopefully help you out here because there's definitely an element of user interaction that has to be required right now 'cause every certificate is individualized for each machine or each user that you're running this on.
We have no current method for auto-enrolling. We're kind of kicking around some ways how we can fix that. But right now we don't have that. So this is why we wanted to figure this out. So if you look at how the other half lives, Microsoft has its certificate authority.
Clients respond to a policy, the directory to auto enroll. They generate a CSR, get it signed, import it, put it into local store. Done as the machine not necessarily as the user, so you have a machine identity. In more of our business environment that's what they're looking for. In the educational environment, you typically want to do this all by a user. You have a lot more multi-user systems.
That's possible as well to get certificates that way. Most users never even know, I mean that's the beauty about this, is that it's all just done automatically for you under the covers, 802.1X is configured and all the rest. So, let's take a look at how you would interact with this if you are on a map. So here we have our Mac, crack open Safari, and you can actually go to-- the certificate authority has a web server for it.
Going to ask you for authentication, and then you've got a little web interface that you can go through, make a little easier for you guys to see, and you'd request the certificate, user certificate and this is where your users probably go off the tracks. [Laughter] So we'd rather they not have to do that.
So how can we figure this out through scripting, how can we use that to kind of satisfy our needs here and get this working? So it's web-based, works with IIS so you've got to have that on it and a nice thing about this is its kerb authenticated to that webpage.
When I went there, you saw that I had to type in credentials but it is fully kerb enabled. So if you do have a kerb ticket or something else, you could use that instead which takes one more element of user interaction out of that. So that's important, we'll key on that in a little bit. But really I have absolutely no idea how this actually works on the PC side. But we have managed to reverse engineer it on the Macs.
And that's what I'm here to talk about. So how do we do this? Well we knew it was a website from what you saw just right over there and we know that with careful application of advance scripting technologies, we should be able to hack anything together, right? So we'd seen it, we know what it works like, now we just got to find out what's in the middle. So first of all, we had to worry about credentials.
Obviously you have to be authenticated to get this, you're passing up a private key or certificate request, sorry, and you're getting back a public key that comes back. You need to be able to know that you're the person that's supposed to be doing that. So a level of authentication is required. Now, we also know that it's kerb enabled, all AD users can get kerb credentials, all AD-bound machines can get kerb credentials as that machine, boom, we've got the problem solved.
So, log on to the web CA and in this case and I'll show you this when we get back to the demo. You can just do a kinit as a user. For the script we actually do a k and that is the machine. And then you can get back in the Safari, you'll see your kerb tickets and do all the work there. So we got the authentication part done. Now we needed to know what was actually being passed back and forth.
Because you could see through that web interface that you can actually send everything up and get the certificate back. So that was using Safari doing view source, looking at what the source of that page was and then getting into tcpdump and actually seeing what the actual communication is.
So that got kind of fun and we saw some of the stuff that was getting passed back and forth and we said "Hey, you know, Curl can do a lot of fun things." You can post things with Curl, you can get things with Curl, so we can probably figure this out in the Curl. There was a few bits though that we didn't understand, that we didn't know exactly how it's going on. So we binged for it.
[ Laughter ]
[ Applause ]
What's the-- that's not supposed to get applause. [Laughter] What's the past tense of bing? We're wondering bonged, bunged. None of those are good. Bing didn't come back with anything so we alphaed for it, alpha got us WolframAlpha isn't sure what to do with your input.
[Laughter] So that didn't work out very well. So, then we Google. And we came back with a few hits, what was most annoying for me is the top two or three were questions that I had posted on some forums asking how this has worked.
[ Laughter ]
[ Applause ]
It sounds like you may have found yourself in that same position. So if Google doesn't work, what happens? Well, if you're like me and you have some brilliant people working underneath you, you can make it somebody else's problem.
So first I asked Josh, and Josh got some of the pieces. He came up with a pretty crappy sed statement that I'll show you in a little bit, that actually does some cool stuff that I didn't have time to figure out. Although I'm sure given the proper application of effort on my behalf, it would have been easy.
But, there were a few things that Josh couldn't get and so ooh, luckily I have somebody else that works for me who's used to wrestling pigs which seemed rather apropos for this particular problem. So Tim actually found out some cool stuff with how to get the certificates directly out of Active Directory via DSCL.
Because once you actually enroll yourself, the public key becomes available in directory services, it's published through Active Directory And I will note on the side notes and this is something that's personally been-- something I've been interested in, in Snow Leopard definitely try working with encrypting email to other people with their search from Active Directory because we can now do that and we've had some good success with that. Active Directory, LDAP, and some other places can vent certificates, public keys for encryption so you can use that to send an email.
If you don't know what that means, just keep on working. All right, so now for the script. So we'll poke through this a little bit but I wanted to show you two things to keep in mind. First of all is credentialing, one of the cool things that I didn't really realized until after doing scripts for a while.
Once you've been bound in Active Directory, you do have a local key tab. That's the shared secret between your system and Active Directory in this case. You can use that to get credentials without having to know the password for the machine just using kinit-k, all right. So kinit-k as root will get you a kerb credential for the machine that you're on as long as it's been bound into AD.
And then you can run the rest of your script as the machine with machine credentials. Which means you can hit that web enrollment CA with Curl and not have to worry about passing in a plain text or anything else like that. The problem with this is for 2k8 environments we've been having some funkiness and imagine, if you will, a waffle.
I tried to get them to put a waffle graphic 'cause we weren't quite sure when it was going to work and we're still working on the issue. They didn't have any waffles, they yelled at me for bringing last minute requests. I then asked for a construction cone but they didn't have that either.
They did find a waffle cone [laughter] which I thought was actually going to be a real great graphic but then it apparently didn't pass muster. So imagine if you will a waffle cone, a nice summer time treat in the bottom corner to keep in your mind as a mnemonic here that for 2k8 environments kinit-k, you might have to play around with and see if it works and definitely with the GM-- with the stuff that you got today with that developer release that you got at WWDC, make sure that you test that, make sure that you're interested in using that in your environments. Try, look through the stuff, if it doesn't work, please file bugs on that 'cause we're very interested in getting feedback on that. Fair enough? All right, as-- just as a quick question.
Who's using actual 2k8? OK, a couple of hands out there, who's actually using it at a 2k8 functional level? Yeah, all right, so this is not huge issue. And while I've got hands on the air, who knows their total cost of ownership?
[ Laughter ]
That's another story for another session. All right, another cool thing, you'll notice the new in Snow Leopard badge up there, nonexportable certificates, some people have been asking this for a while in 10.5 and earlier if you imported a key pair, a public key and a private key, anybody that had admin access to the system could export that private key.
If you're in a very security conscious environment or if you're using certificates for things such as authentication to VPNs and stuff like that and you don't want your users scrolling around and putting that certificate on another system that's not company owned or organizationally owned, you've got some issues there. So cool thing in 10.6 is that security -x will prevent the private key from being exported, all right.
So you'll have a public key and a private key that are stored in the key chain but if you're admin, even if you're root, you have no way of exporting that private key out, so fun thing to keep in mind, so new to Snow Leopard. All right, now let's go back to the demo to kind of show you the script at work. Director utility were bound in AD and this is where I pass the hoop over my floating assistant. No kerb 5 credentials in the cache.
I'm going to do SH, I'm going to grab my script up here as root, done in bash to make Nigel cry. One identity imported! And now if I go up to key chain access and I go down to the system, you'll actually see a computer certificate here. This was actually what was imported, you'll see it's for computers, the name is MacBook, scroll back through here, client authentication, email protection, whatever your template on the server's set up to be, plus actually getting a URL to download the CA and everything else. So this should be fully usable for things like 802.1X authentication, VPN authentication, even for email signing.
So you could use the same way of doing it without actually using it as the machine but using as the user instead. Now we're going against a 2k3 domain controller, so if we do a klist you can see that I now have the kerb credentials. The kerb TGT and the service ticket for the web server and if I quit Safari just to prove to you that there's nothing going on behind the scenes and I go back to that certificate enrollment site, I don't get asked for authentication again.
So that's the actual kerb authentication leveraging the kinit -k. If you look at the script real quick it's not that advanced. We kind of do some enrolling. We set up the CSR and some other stuff, taken a couple of arguments. I got to switch in here, the switch between 2k8 and user and machine so you can do everything you want there. Check the status, DS config AD, a lot of OpenSSL-- excuse me. We'll make this a little bigger so you can see it a little easier and we'll get this posted.
A lot of OpenSSL work so you can actually generate the certificate request. Here is the kinit -k to go for the machine name. Here is if you're on 2k8 how to get a password with the ugly way of taking it out of the Active Directory plist file. A little bit of Curl, this was something that I did end up getting through Google that somebody had figured out how to pack that certificate into a Curl post.
This is the nasty little bit of sed that Josh figured out for me that picks all that up there. And then this is nice and I'll mention this real quick, once you've gotten to cert done and if I do a dscl localhost, CD into active directory. Let me move this up a little bit and make it even larger for everybody.
CD all domains, computers, here is all my computers on the MacBook in here. And if I read that you can see this big old chunk of binary in here, all right, this is your certificate, this is the public certificate. You can pull that out just with the dscl read, all right, nice and easy to do. The problem is you got to get it into a format that can actually be used by the certificate assistant here at key chain access.
And the magic there is XXD and Tim figured that out for me. I was banging my head against the wall there for quite a bit. And then he packed it up into a PKCS12 format, grab it in there and then use security to import it. If you are on 10.6 make sure you use the -x if you don't want it exportable. And then this is all kind of the meat.
There's actually not that much going on in there. So how you get a certificate from Active Directory via the magic of scripting with not too much effort, just make sure you have a good team that can do all the work for you. On that note, here is Josh. He is going to talk to you.
For the record, the reason I didn't complete his scripting solution is he only asked me to do the sed statement, so it wasn't because-- it was failure to lead from the top I guess, so.
Some point in my career I became the go-to guy for sed and if anyone else is in that position you know it's a terrible place to be. So what I'm going to talk today about though is automated image development. This includes deployment, image creation, all sorts of other things like that.
So let's take a look here and what are we talking about. We're talking about making and testing deployment images, ASR images, in some sort of way that we can get them on to a machine. We're talking about taking this path that lots of people do. Who is an admin in here that does system image development for ASR stuff? Look at all the hands, way more than the Windows 2k8 crowd, right, and we're going to cut a lot of these out of here using automation.
So one step at a time the way you normally do this is you have to make an image, make a NetInstall ASR set, deploy that image, and then test the image, right. So it's four couple of key steps there. But really there's a whole bunch of other pieces to that.
Making that image means you go install Mac OS X then you have to go ahead and install your apps, you got to tweak all these settings to make sure it all works, clean up the whole system, FireWire target diskette or USB diskette depending on what Mac you're running on, then you got to make a NetInstall ASR set, most people then will copy that image up through their server somewhere.
They then open up SIU, create a workflow, then you got to run that workflow to generate out this MBI set that gets built, right. Then you're going to deploy that image, you got to go back to the client, you got to enable NetInstall and server admin, you have to set the client to boot from the right NetInstall set, you're going to want to limit that NetInstall set to only boot your test clients because, has anyone ever reimaged someone's machine by mistake with the development image? Yeah, I see a couple of hands. The hands only go up this high on that question, right.
So, no one really wants to admit to that but it's happened. It's usually the more important users that don't know how to set their startup disk too, so you got to keep that in mind. You got to image that client then and make sure it works. So that's 11 steps that you have to do every single time you want to rev your image. And this is WWDC, so here are some Commodore 64 basic for everybody and we go down. Notice at step 50, we never gePt to go to home, right.
Originally, I had a tilde here then I realized well, my Commodore wouldn't know what a tilde meant, so I change it to actually home. So the first thing that comes to mind is I'm getting way too old to do this anymore, right. This is not stuff I enjoy doing. So really what do I want to do as a systems administrator? The obvious answer is I want to do less work, right. I want to go-- to get home, I want to go to hang out with my kids, I want to do all this fun stuff.
So I requested less work and unfortunately Gil told me I have to work faster and harder, right? This is nothing I was allowed to do. It's a cruel task master. So I'm on Twitter like a lot of people and I thought what would fake Michael Bay do here, right, he is the guy who gets stuff done in an awesome way, right. But alas, more people know who this is than we were hoping, so that's good.
So he'd bring the pain, right. First he'd get a latte because that's obviously, how many people work better caffeinated? Yeah, lots of hands, right, still more than Windows 2k8. We're going to use some robots because robots are just awesome. There is going to be lot of boom involved in this as well.
So here I had to get my latte right, and at work I got a mentee, right, so I made him get me a latte and I live in North Carolina which you probably can't tell from my voice but I do live in North Carolina. He lives in New York City so I made him fly me a latte. That's a huge boom right there, right. So now that I'm properly caffeinated though I can get to work.
So image creation automation, I've got more automatons than everybody else at this point. So I'm going to go ahead and use Snow Leopard SIU, we'll do a programmatic image build. This is new in Snow Leopard, all you have to do is say I want to make a NetRestore set from Installer media, then it will install directly into a disk image, lay your packages on top, convert it automatically into an MBI set and you're done.
If you're on Leopard you can use the older instant image stuff that does exact same sort of thing, just that it's not from Apple, boom, right. So then we get more robots, right, we're going to take that. One of the cool things about SIU is you can use automator and there's our friend Auto.
You can go ahead and then you can take that, if you're using Snow Leopard, this is done. If you're using Leopard and you got an ASR image, you feed that into SIU as a source, you can use the MAC filter automator action in System Image Utility to make sure that's only going to boot that one Mac up so that you don't accidentally take out someone with C in their titles MacBook when they come in.
So you want to that, you can use automator command line tool there to run that, just automator in the workflow. So for that I get a boom as well. There is a robot on screen. What's Michael Bay doing with robots? Sorry, cell, good bye Auto.
So he of course would explode the robot into flames. Sometimes your robots get in fights there, right, and that's always just awesome. So we're going to take, we're going to secure copy this NBI set now up to our server. We're going to enable that image. And server admin, there is a nice server admin command line tool.
UC [phonetic] showed that the other day in a couple of sessions and you can just use that to enable the image. Server admin though thinks that SIU doesn't know what it's doing all the time and it takes out that MAC filter, the per image MAC filter. So in that case we just use PListBuddy just to get back in there. It's just kind of what it's doing right now.
Then we're going to go ahead and set the client Mac to boot up from the NetInstall set. This can be back on the client the same script or just can use the bless command, right, bless and just point it at the server. Bless is really flexible for this.
For those of you that want to do NetBoot across subnet and you're worried about the DHCP helper addresses, you can just bless directly whatever machine you want and as long as TFTP and NFS or HTTP path, you're going to be fine, it will go. Pseudo restart now and it reboots, boom, off of that image.
We're going to let launchd do our bidding. This is the part I really like, right, because I can just schedule the script now with the launchd to run it, I don't know midnight or 6:15 in the afternoon. I just queue it up and go home, right. That's the least work of all.
And it just runs automatically and when I come back in to work I got my machine booted up off of my test deployment image and I can just take a look at it and see what has happened. A definite boom on that one as well, lots of boom, right, and explosions, why not, wrong way.
So less work for me, that's the whole goal of scripting, right. We have this incredible computer that can do all this stuff, millions of computations a second, yet I have to sit there with a mouse and make it do everything. So the whole point of automation and scripting is so we don't have to do it. In this case now I've got image creation that's automated.
My NetInstall creation is automated and my image deployment is automated. So to wrap all this-- uh-oh. This doesn't look-- yeah OK, so that was a bit short I guess, right. Oh yeah, and the DRI is not happy with how short that was, so, and too much boom. And no demo, that's true.
By the way that's the guy I made fly me the latte, right, so I guess that's him getting back at me at this point. So there is a bonus solution to my part here, automated local management policy. How many people use Management Policy MCX from centralized directory services, OD, AD, YP, god help you. All right, some hands.
So how many people would like to use management policy on the Macs but they can't because they're not allowed to fiddle with director services or run other ones, some more hands. So what are we talking about here? Here we're talking about creating local management policy and then scripting the deployment of that policy.
So why in the world would I do that? One of the magical things about Mac OS X's directory services is that it just takes anything you feed it pretty much as a source, right, AD got the right schema, management. Anything you got, any LDAP, any AD integration, anything like that.
You can just pull your management data directly from it and it's really nice. Well sometimes you got people in bizarre situations so they can't make computer records in the directory services, no Mac address attached to that, no management policy. Or there are situations they can't extend the DS schema.
A lot of times we see this when we're working with a customer doing a proof of concept or something with the Macintosh, so they get the small populations of Mac testing. We've been to a lot of places that just have polices that say proof of concepts that aren't production, you are not allowed to touch the schema, or say for populations under, you know, a certain number of machines, not allowed to touch the schema.
So in a lot of those cases we end up doing this local management policy so that we can work around that, they can still test their policy and when they go to the full on deployment they stop using this and they move up to using the larger scale centralized directory service. So how do you do this? It's pretty easy to set it all up. You're just going to create a local computer object, you're going to set policy on it with Workgroup Manager and you're going to export that policy with dscl -mcxexport using the MCX plug-ins on dscl.
You then going to need to suck that up somehow, so what you have to do is on the new machines that get deployed, you have to create that local computer object and then you have to import that policy with dscl again, so dscl -mcximport, creatively named enough. The tools that you need to get this done, the ones that you have to have, Workgroup Manager, dscl, launchd. Workgroup Manager free download from Apple, part of the server admin tool kit.
You go to support.apple.com and you search for it, downloads, 900 versions come up, find the one with the latest date and you'll get a nice new copy of Workgroup Manager. dscl launchd part of it, a new tool on Leopard that I really love and love and love is mcxrefresh.
This is GP update for Mac, right. No longer need to log out, log in, reboot, all this to see what your policy changes are. So when you're working in Workgroup Manager you can just keep refreshing policy. Not an Apple tool but a bit of open sorcery you can get from SourceForge's Lingon which is a nice little application that lets you-- it's a nice GUI front end to making launchd jobs. I just use that 'cause I'm lazy and I don't have anyone I can delegate it to.
So how do I do this, right, how will I make this work? Well, you're going to create that account. So Workgroup Manager is what we're going to use here. You go to Server, View Directories, go to Local/Default and Authenticate, and click New Computer. Makes the computer, give it a name, put in the loopback IP address and the Mac address of that and you're done, that's it, right, nothing else to do there.
So then you're going to go and apply just standard old Apple management policy. Apple has got really nice flexible management policy. We'll look at a couple of these in our demo here and we can give it some policy in this case. I have disabled the iTunes Store and things like that.
That's a really common policy we see done a lot. Then going to export that out of there, right, so dscl mcxexport, tell it where you want to point that blob of policy, it just spits out a plist file, right, that's easy enough. And then what, right, so you got a folder with some stuff in it but how do you get a computer account created automatically on a Mac? How do you get policy imported automatically on the Mac? So this is where we do it all at startup time. In your deployment image you'll have a startup item in there and then that startup item is going to do two things, it's going to create the local computer account and then it's going to also import that policy blob using dscl mcximport.
It's very simple, it's just this little bash thing I knocked together. So the first chunk up here just creates a local computer account called local host. I like to call them local host because that's what they are, right, and just goes in. It goes doing the-- it chops out the Mac address from looking at ifconfig and then it goes ahead and puts the loop back IP address on it. The next line here is it just goes and imports onto that account or policy or MCX and it just-- you put the policy wherever you put the policy.
I like user local because it's kind of unique CLI. People use application support/name of company, you know, just wherever you want to put it. It really doesn't matter. And then in this case, an optional step here is I remove that launchd job at the end. I just delete it out of there so it doesn't keep reimporting that policy every time.
Some people leave that in there so that way they can just push out a new policy blob if they want with ARD or something like. And then on next reboot it will pull that in. Note that because you're not using directory services here to provide that policy source or rather a file import, you're not going to get the nice automatic dynamic updating that you get when you just make the changes in directory service.
There's a little bit more of a manual process here. That's what Lingon looks like. We'll see it in our demo. It's just-- like I said it's from SourceForge. It just makes editing your launchd items extremely easy to use. Another explosion, flames, boom, all that stuff, and with that let's take a look at the demo here. So I've got a couple of different things here and the first thing I want to do is take a look at Workgroup Manager.
And here is Workgroup Manager, you can see I'm just in local default, everyone read that, OK. So we're in local default there and what we're going to do is we're going to make a new computer account. So if I go to the Computer tab and click New Computer, I can install on the name, local host and then I needed to go and found some network information. So here just going to 7.00.1 and then the Mac address which there's 900 ways to get it.
I'll do it the really lazy way and just take a look in system profile, right. So Ethernet 1, that's E and 0 and there is the Mac address there. You can't copy and paste it into here which is a bit annoying because it automatically puts the colons in, right, 2, 3, DFDD9E78, OK, so we're going to save that.
Now that we've saved that, we can go and apply some preferences to it. One that's great for demos is move the dock, right, because that's a really obvious one. So always dock in the left and while I'm at it I'm going to make the punishment DOC out of it. So there we go.
This is great to do to people. So the punishment DOC always works well. The next thing I want to do is I wanted to do that iTunes one, right. Does anyone allow users to buy music while they're at work on the iTunes Store? OK, like a couple of hands but most of the hands stayed down. See, that's one of those negative questions where the hands that stayed down are the ones that win.
So if we're going to details I can load in the manage preference manifest that we put on the system. So if I go to the system, library, core services, manage client, and import that, I get all the nice manifest on the system.
This is documented in all that stuff so nothing too crazy. I'm going to go into iTunes now and I'm going to make a new key as an always key.
I'm going to say disable iTunes Store=true. So no more iTunes Store in iTunes. So now that I've done that, let's take a look at what that looks likes. Now I could just read it on the local host here, but that's a pain, right? This is just dscl read.
That's the policy there, the MCX settings attribute. So yeah, that's-- I don't know what to do with that really though. So what I can do though is I can use the mcxexport command. So I'm going to type that in, mcxexport, not in all caps, and then I need to give it a out file location, I'll call it policy_blob.plist. All right. So now let's output into my home folder a blob of policy and you can look at that there.
Just quick-- quick look and save my life so much now. And you can see it's just a, you know, just a regular plist, but it's all formatted nicely for me. I don't have to worry about it at all. So then how do I get this into my system automatically? Well I've got my script here that I just showed you earlier where it just removes, creates the host and then it imports in that file. You can see I've chosen as my location user local, LocalMCX. Just 'cause because. So if I wanted to I can go ahead and move that in there. I'm going to go here. I've got my LocalMCX folder here.
I'm going to drop in my new policy blob I just created, place that and I've just got my script and my policy blob there. So I need to put that in user local. That's very easy to do if I just say go to folder. And type in user and there's not a user local on here so I need to make that path. So pseudo make their user local, yes I know I'm being dangerous. And then I can go ahead and copy that folder in there.
All right, so now I've got that in there. One thing you should always do when you copy scripts around in the finder is go back and check your mode on it, right? So LSL user local, LocalMCX. Make sure it's-- the script has got the execute bit set otherwise you get stuck and then you're just staring at it and trying to figure out why it won't work 'cause without that bit set it's just a TXT file, right, nothing fancy. So what I want to do now to prove this works is I'm going to come back into account and I'm going to remove this computer account.
That's gone, there's no longer a computer account on this machine. And if I were to go back and look with dscl it-- unless it's all cached up which it's not. It says no record found, right? So I need to set this through a fire up and start up this.
I'm going to fire Lingon here and say I want to make user daemon launch system startup, and in my case com.apple.LocalMCX. I'm going to choose what I want it to run. I just want it to run my folder from user local, so I'll just navigate user local, pick the script and say do it at startup, right, save that.
Because I'm making it as a system level startup, I need to authenticate again obviously. And you can go look and see where it put that and put it in library launch daemons and there it is there. So I didn't have to worry about all that formatting, right, and do that.
Normally what I did before I had this tool to make launchd items I would just go grab one out of the system library, launch daemons folder and hack it up to make it work for me. And now I don't even have to need to do that anymore. So all that's done, this is primed and ready to go.
So if the demo gods smile on us, we're going to reboot and we will continue to have video on this machine so. OK, so here's my punishment DOC, all right, the least usable UI ever conceived here. Ooh, where did that go? All right, so I can take a look at that if I were to try to find iTunes, there we go and launch it and go and agree to the agreement and it comes up.
No, I don't want that right now. Doug, are you in the room? So, no iTunes Music Store here. If we look into Preferences we can see the store has been disabled by-- let's-- don't look at the Parental, been disabled by policy, right. So we've disabled that by policy and if I were to take a look back-- oh my, with terminal here, I can look in on my computer account. The computer account was created again. The Mac address was put in properly and there's my dscl MCX settings keys in there. So that in a nut shell is how to automate the employment of local policy.
Thanks Josh. So one of the things that Josh covered is how to get more automation so you don't have to do a lot of work and Joel talked a bit about how he wanted people that worked for him to do a lot of work. I won't actually get your users to do your work for you, so you can just look good.
So the way to do that is you, these people are thinking oh crap, Tim's up here doing another representation about how to wrap command line scripts. But this one is actually kind of a mule in the sense that I have two really cool applications that I want to get other people to help me work on.
So not only can I get your users to work for you but I can get you to work for me, which is even more fun. So the two ones is trying to get to work a round for DFS. How many people have been bitten by I can't the get the DFS to work on my Mac? Hopefully, we can have a work around for that.
And the other one is a total hack of a local account so that we're able to create mobile thinking with just a regular local account without any directory services, which is a little bit ironic considering I'm a directory services consulting engineer, encouraging people not to use directory services is kind of a career limiting decision but it also happens.
So we're going to talk about really the-- ostensibly we want to talk about how to write scripts so that the interface between the command-- between the GUI application that you're planning on writing and the script is clean and the able-- you're able to easily run the script as well as integrate it into a COBOL application or anything else that you used to wrap it.
So we're going to be talking about basically three ideas, the STDin, STDout, STDerr, signals and then finally getopt or getopts depending on what language you're talking about. So let's talk about communication with your scripts because this is important. What we're trying to avoid is getting a-- I mean you have this great script that you run and it works great.
You put a GUI wrap around it, it works great. You give it out to user, they run it. It takes 30 seconds to run because their DS-- DNS isn't as good as you have in the lab. And it freezes up getting the spinning beach ball of death and there's no way to cancel.
So what we do it by STDin, STDout and STDerr is being able to communicate to your script. So you don't have this kind of issues. First thing STDin allows you to communicate into your script, so basically you're passing in information. STDout allows you to get information out, so if we have logging information, well actually this is just output.
So if you have output to or from your script that you want to take a value and be able to populate that, then you can get that from STDout and you want-- you don't want that intermix with logging information so you do that in standard error. So we'll briefly talk about that. So here's a great simple example in bash. This is as much bash-- this is as much bash as I'll write before I start screaming and go into Perl because bash has always been annoying with Nigel on that one, sorry Gel.
So we could see the first line is this goes to STDout. Anytime this echoes some to the console, it goes to STDout. If you want to be a little bit more geeky to it you can put >&1 in that way it looks cooler on your scripts. But again it will just go to STDout 'cause the file descriptor for STDout is by-- is number 1.
And if you're going to put some of this STDerr you just do >&2. And if you want to read something from STDin you have basically just while read lines that will read in from standard input. And the nice thing about this is that if you pipe a command, you do echo on the command line, you type something and you pipe and fill into your script, it will read it from STDin. If you don't do that it will prompt the user.
So one of the nice things is that no matter how you run your script, you're able to do that. Also let's talk about signals. So people have-- a lot of times if you write these GUI wrappers, something happens, the script dies or your GUI application dies but your script keeps running. And you want to be able, some way to be able to communicate and tell your script "I don't care what you're doing, I want to be able to manipulate it." Tell it to do something else.
So it's waiting for user input, I don't want to have the user type in you know exit or menu or whatever, I want it just to be able that your GUI application say cancel or check box, have it automatically do something, so we use signals. And in Mac OS X there's a lot of signals. It didn't use to be this way. I'm really, really concerned with two signals.
Basically, a little concerned with the HUP and TERM. [Static noise] So people are aware of where the term HUP came from. HUP allows-- I was always kind of curious, HUP allows you to-- I wish it would connect up to. Damn. That Genie service is slow today. This is actually a photo of Josh's-- [static noise], man.
[ Laughter ]
So it's actually a picture of Josh's acoustic coupler when he was switching from his BBS system to Genie. So this is in his basement. He still actually uses it to play gaming on the weekends.
So the interesting story behind HUP is that HUP is usually sent to a command-- a signal that sent to a daemon or something like that to reread this configuration. And to me it was always interesting why you would use hang up to reread reconfiguration because hang up would assume that you're disconnecting. Well there wasn't that many signals so they reused HUP for whatever reason.
So, what signal gets you is that if you have this-- so you have the script that I wrote before and you're reading from the input, right, it's waiting for the user input. And that works great if they want to quit, they type quit. But you have a GUI application now, right? And what happens when that's waiting for input you don't want it to have a spinning wheel there or whatever, you want to be able to just click Cancel.
And, but the problem is the script is in the middle of doing something else. So what you do, it's very easy in bash and in most languages, is you just put what's called a-- you trap a signal. And so what you're saying is that if you get the signal which is the kill signal or something like that on the command line or you can send it from any application is allow you to say to the script "whatever you're doing, stop doing that and go run this function." And the function all it does is report cut signal.
In this way it would do some cleanup and those kinds of things. So we're really trying to avoid, we're going to have some good logging in our application, we also want to be able to have-- be able to tell the script to stop doing what it is doing. All right, now let's look at getopt. So getopt is one of the things that you'll see common in the scripts that we present here and it allows you to have command line arguments that make a little bit of sense.
'Cause as we see there is some command line utilities that have command line options and arguments that don't necessarily follow the UNIX convention. Well if you use getopts it allows you to specify command line arguments that kind of make sense. So it-- a lot of times when people first start scripting, they think OK, I have this command line utility, it's -v, you know -c and a and so they start parsing. OK, the first character is dash, all right. Oh, this must be an argument and it goes through and does it character by character.
So string parsing is for suckers and I don't have time to do that. So getopt allows you to easily parse arguments and it provides consistent interface. You don't have this DD type you know OFIF type interface where things are-- people aren't able to use it easily because they don't really understand how you're supposed to pass arguments in. It saves you a lot of time and if you save time, you actually have more money. If you have more money, you have more free time and then you can write more scripts.
So it actually works out really well. And getopt is available in lots of different languages, it can do it in-- I didn't actually write this because this is more than the four lines of bash before I run away. This is some sample code and it's basically you just specify with options V and C:, V means verbose into flag. If you have a colon it means it has a value, it does all the checking, gets an error like hey don't -C requires an input.
And so you can see it actually it reads them in. Of course there is getopt in Ruby so if you roll in the new Web 2.0 like certainly over here you would actually use Ruby. If you want to do it in Perl, you can do it in Perl as well.
This is my preferred method because it's shorter and makes more sense than dash does. You can also do it in Python. It's not as good of a language but it's pretty close. And if you're like that's cool for those new cool languages, what happens if I roll a FORTRAN? Well you can actually get getopt in FORTRAN as well. [Laughter] I'm not sure if this will actually compile on their own and-- and I was actually told by Jordan that that joke wasn't funny. So I twittered it and Nigel came back with a better joke for FORTRAN. [Laughter] This is my backup joke.
So now we actually got the script. Let's talk about doing the interface between it and it's very simple. We're not Objective-C programmers, but we should be able to write a wrapper script. There's lots of sample code. And one of the things that I want to do is these two samples, let's get them out there for two reasons.
One is to give you kind of a framework to be able to wrap some of your GUI ones in a way that's, you know, well user-interfaced application with a script behind it as well as help you actually accomplish some task that these two scripts do. So you could see that these kind of mirror what we just did. We're going to start NSTask which will be our script. NSPipe which allow it to communicate to us.
We can have blogging, we can have you know interaction with the script while it's running. We can kill it in a way that makes sense. You don't have a bunch of craft laying around and then if we want to slam it we can use the system command to be actually be able to just run a synchronous script.
All right, so here's the required code. I think I have some highlight here. I don't have highlighting. All right. So you can see that this is-- one of the interesting things is that it mirrors what we did before. Objective-C has the idea of pipes which allows you to communicate to STDin and STDout, STDout and STDerr. You can see that create two pipes and then I set the standard outputs, standard inputs that can communicate over those. And then set launch path which allows you to actually just launch the script.
So this looks like well, I'm not an Objective-C programmer, I don't do that stuff. Well the two scripts that I have have GUI wrappers and they all have the same code in it. And if you're writing well formed code that runs this task, you're going to have this kind of thing repeated over and over So it's the idea that you'd stick to the same project, repeat it, replace the name of your command line script, your option parsing will be pretty much the same, your logging will be the same, you'll just worry about making a nice GUI for it and writing a nice script in Perl only.
OK. And then one of the nice things about it, you have to do a little bit more work because you want things to run asynchronously so that means you want to get called back and what it does is that you have to register for a notification, which just means it calls another section of code.
And then this calls, this actually looks more complicated but again you just repeat this. It just has OK, we get called and we want to stop getting called because we don't want to keep getting called if once were task is done. And then we just read in what was printed out.
So it's basically just the logging information so it'll be reused. So there's two examples, we have the DFS Mounter and Mobile Creator. So this is two-- these are these aha moments that you have during the year which is like you know things that really annoy me is when people come up and it's like when is Apple going to support DFS, right? So there is two things like if I did know I couldn't tell you and yes, it annoys me too so, but I can't say that so. So then you're searching around, you're doing some random binging, bonging, you're bonging around and I bonged that last night.
No, no that doesn't work. Google, I use Google from now on. The-- and you find a command line script that's kind of ugly but you're like wait a minute, I could actually have something that actually makes more sense for me, for my user to be able to do and that happened twice, actually three times this year in a big way for DFS as well as for creating mobile accounts that can sync.
So let's talk about those solutions, actually doing this stuff. So first DFS, this is a wonderful Windows GUI for creating DFS shares. People that aren't aware of DFS, DFS does a lot of things that allows you to abstract your name space of SMB shares. And this one, this is actually kind of a-- I use hyperbole to illustrate a point here but there's a lot of times you have users that have really deep shares that they just use the DFS to mount to something higher up.
So you have the share that's whack-whack-dump-whack-dump-root-whack-ABCDEFG and that just maps to a share that's on this machine. It could be on another machine that's whack-whack-dump-whack-direct users. The idea is you take this one URL and it basically maps the short one, so that's great. So you open up connect to server and you say let's map, let's actually mount this on your Mac and your Mac says "yeah, I don't think so because that's DFS and I don't understand DFS" because it doesn't know how to resolve that back.
But the thing is we know how to mount the actual underlying share, so the hard part is actually done. The packet signing, the SMB protocol, all that stuff we can do. We mount it and here we go, so usually I like to use my family-- family members, CMC is my wife, JMC is my son. I'm not sure who W. Wiggle is. Some goldfish I'll have toget. Is that what?
[ Inaudible Remark ]
W.
Wiggle, yes, is the code name for the next version of Redacted. And so the solution to this is using jCIFS. So we have-- we have the same screen sample as before and what I did is I was-- I download this brackets [phonetic] called jCIFS. It's open source part implementation of the SMB protocol and I was poking around the example codes and there's this great one.
Somebody took it, put a patch on it, make it Kerberos enabled because it's got to be Kerberos enabled to actually be applicable for what we're doing and I ran this one and I put in this URL and I ran it and it came back with this and I went "holy crap, that's huge." All right, how many people get really excited when they see output like that and they get something like this and they go "whoa!" Your world kind of changes, right? Because what this does is I put in a really long URL and it gave me a path back that I can use to mount a share in Mac OS X.
OK, I don't plan on passing that. I don't like to send an email to all my users saying "OK, go ahead and run this command line to actually mount it underneath," it's not going to work. But what I can do is take this, put it in a wrapper, give it out to my users and then they can go ahead and mount their DFS shares. So here's what it looks-- this is what DFS Mounter looks like.
Looks a little bit like something else in the system, what could it be? I actually changed it. It can actually work with-- No, no I'm sorry. Yeah, just SMB servers. You put in your SMB URL and underneath that uses jCIFS in the packets to actually run that command line script to do it.
So it's written in Perl because it actually wanted to be-- it actually wanted to work and again, same kind of thing, catch the signals TERM and INT so, I get a function that gets called whenever there's a signal, if I do a kill-HUPkill-terminal run this and it will say cut signal killing child, it does some cleanup and it exits with an error code. So this allows us to-- most of the time you wouldn't use this but if your GUI application that your user clicks Cancel or something like that or wants to, you know, restart the process, the script can actually be more responsive.
You don't end up having all these scripts kind of running in the background. The next section is basically the setting some variables and getting the-- doing all the getopt information. So you can see here there is a KDC option, a realm information URL. So basically those are the same things I showed you when I ran it but I'm passing in a KDC, passing in a realm and passing in the URL, and then it can go ahead and resolve it for me, and you can see that actually run it. The next problem that was in search of a solution was a mobile account without DS.
So you have a Windows system and you have your Mac which is the-- and you're not bound. The arrows are going the wrong way and the icons got switched. But imagine the iMacs on the other side and it was on that side, and you're not bound to Active Directory but you still want to take advantage, be able to do home directory syncing to some random SMB share. OK, we can't do that right now. The way that you would do it is you bind the Active Directory, open directory, create a mobile account, once you create a mobile account you are able to synchronize with your, you know, R drive or whatever is on the network.
But there's no reason that you have to have DS to be able to do that. But the system will prevent you if you have a mobile, if you don't have directory services you can't create a cached account. So the solution to this was, I was poking around, I said well Josh did this last year with home directory injector or 2 years ago or 7 years ago, some years ago. And so I got Josh, I called him from the depths [phonetic].
I said Josh I need some sed work. I took his script and it turns out his script only was able to in chat. Once you had a mobile account already created or a cached account already created, you would inject the home directory URL. But I am actually going to create a list as well so I took his and added a couple of more attributes. I changed the author authority to something that is much shorter, it's just local cache user.
And now Mac OS X thinks hey, this is cached account. Oh one of the caveats to this is the way that home directory syncing works is that when you log in, it actually takes your passwords that you logged in with and populates it, at least the Snow Leopard, inside the key chain.
So it doesn't, you can't save your password in the key chain to get this to work because it actually saves it for you. So the long and short of this is that make your local user's username and password the same as username and password on your SMB share, and no I won't say that again. Mobile Creator, it's a very simple GUI. You basically select the local user.
This is my son who is actually trying to do an arbitrary SMB share on this one. And then it basically creates this mobile account, you can set up syncing with it. I'll show you that in the demo. Again this is the same kind of thing but in a different language. It's actually in bash as well. So, the-- yeah, this. Same kind of exact same format, you have the trapping at the beginning, a function to actually catch that trap and then part of seeing the options.
[Whispering] And so again it's the same format. So the idea is that no matter what solution you have it's basically going to be the same general ideas when you approach it to write it. And this is actually the meat of it. It's actually very simple. It's just a bunch of dscl commands. The first thing we'll do is let me show, so we actually have a DFS URL.
This should be the same one that we had. So now we have the same one ABCDEFG, it maps over to direct users and so now we want to be able to mount that. We're trying mount in the finder. Yes, so this is just connect to server, we do connect and it could not be mounted. And usually, unfortunately it doesn't say you this is DFS, please go by something that's third party that allow you to do this.
It just gives an error messaging saying it doesn't work. I'm not sure this actually works 'cause FORTRAN verse DNS [phonetic] actually has to work as well. Let's get a Kerberos ticket. Let's destroy Joel's Kerberos ticket, destroy kinit. Normally, you just log in as an AD user and you'll be able to-- it will automatically get your Kerberos tickets.
Well let me get Sarah's Kerberos tickets. OK, I have that, and now let's run this application called DFS Mounter. And so the idea behind this is that it uses signals, it uses logging so it's kind of interactive so even though it's just running this script underneath, you can send this out to your users as something they can just use. In order for this to work both NET BIOS and FORTRAN verse DNS [phonetic] has to work which is unfortunate for the environment so-- didn't have the Win server.
So let me put the Win Server in here. I really should check reverse DNS. No, but if I don't check in, it doesn't work, I can always blame that even though it might be my code, OK. So it goes out and then actually you can see the logging, it goes ahead, runs this, the actual command. Hey it worked. I mean yes, you can see here that it actually went ahead and mounted this, this one.
[Applause] So it does still-- it's direct users, right, so it shows the underlying share but at least it works, right. That's pretty awesome. It is a little bit touchy and I wanted to get more people to test it in the environments because it requires NET BIOS, resolution in large networks which is not my home lab.
So it would be cool if anybody has large NET BIOS or, I'm sorry, Wins, networks they could test it on. You can see that this actually shows the same, same information. One of the other advantages to this is that it will actually mount-- may have another component to it that's called, look at the home directory insight, active directory, and mount that as a deep mounting share.
So if you have any issues with the Active Directory plug in where it has to mount the parent folder and then direct you to the user underneath it. This will hopefully resolve that issue as well which I'm not saying is an issue but it's just something that's in the OS that doesn't work.
[Laughter] OK, so the other one, so that's-- also the other thing to point out is that it does indeed log and you can see that it was logging as it was running. So the idea is that this is directory services stuff so DF-- If AD is kind of being slow, if your DNS isn't working, you're basically getting a spinning ball if you're doing self synchronously.
But since it's asynchronous you can cancel it, you can actually see the logging and actually see what happens. And this is all just Perl or bash I think. I think that was the Perl one because it worked. It had to be the Perl one, let me see. OK, the next one is the Mobile Creator and let me see.
[ Pause ]
Oh here, I'll give you something to do while you're waiting for me to do that. So I'll actually post a code but since I'm actually desperate for friends, I'm going to make you subscribe to my Twitter feed in order to get that. So it's at tperfitt and I'll post the link to this code. So everybody go ahead and start following me on Twitter in that way I can show my wife that I actually have a lot of friends. All right, here we go.
I didn't actually copy this to projects. There is Mobile Creator release. Hey, it doesn't have the slash to the icon. I mean, yeah, of course it doesn't have slash to the icon. OK, so there are very simple UI and it shows me the users on this system. I want to create a local user and I shall call this.
[ Pause ]
It's not Apple. [Laughter] It's Apple with an exclamation point, totally different. I'll call this 3GS, Apple, Apple. Stop putting stuff in my public folder. All right, let me see that. OK, now if I run this application again, I should see the local users and actually it's alphabetically, it's first which is nice, and LUs. This is not actually DFS aware which would be nice if I can combine the two applications but I didn't. So I'll just do the direct one was here and direct users. Is that right? Did anybody check my code here Convert, I have to actually give the password.
It's admin. You guys are no help whatsoever. OK, I actually did a delay in this for 5 seconds so I can show you that I clicked Cancel. Did you see that, how that worked, isn't that nice? I was running a script and it wasn't-- so it was asynchronous.
[ Applause ]
This is like a regular GUI application but the idea is it's truly a script that's running so you can push this out through ARD but you can also give it to users and then you go have somebody in New York send you a latte which just seems what-- that's what Josh kind of focuses on. OK, we'll do this. You can see it's logging. It's sleeping for 5 seconds for better demo module.
I have 7 minutes left. Don't worry Jordan. I'm going to just reboot. Oh no, wait, OK, here we go. Now this user, if we do system preferences we'll look and see that this user is indeed a mobile user. So I will discard and I will do fast user switching, this fast user switching-- oh fine, fast user switching works.
You can see it says mobile, yay, and put in. Now that looks like a normal user account but it's magical because-- oh this is bound to AD but pretend it wasn't bound to AD because this is just the local user, right, 3GS and we go up to accounts.
And now I can see this mobile account is actually enabled and I can say-- well, I didn't actually make the passwords the same like I told you need to do. We'll have it manually sync, show it in the status bar and we'll do the whole home-- no, no let's just do desktop.
OK, so now if I go up here and say sync home now it will go-- what? Oh because it is bound to AD, well DNS. It's a DNS problem. It's nothing to do with my code. [Laughter] It's important to always check DNS when you're doing scripting demos, OK. But this does actually work so, but the idea is that you can see it's actually trying to sync. It's using that URL in the local DS. It will actually go ahead and sync.
It's actually-- this one is the one that work all the time. The other one was kind of flaky. It's kind of ironic that does this, so. So yeah, that's just two solutions. I post the code if people want to-- I'll post it right after the session, I'll post the source code to it. If you can try the DFS Mounter and actually just give me the fix code, that would be less work for me, I'd appreciate it and then I'll attach my name to it.