Linux in Azure single sign on



As you may have guessed from the title this is not specifically an Oracle related post but I'm sure it's still of interest to many people and is likely to be in scope for what a lot of DBA's are now doing anyway in this new cloud world where everyone is a rockstar and does everything themselves......

So what's this post about? Well we have now provisioned a number of servers in azure (other clouds are available) and we have individual logins to every single server - this is crap, it very quickly ends up being unmanageable with passwords expiring at different times etc on multiple servers.

What we wanted instead was a single username/password for every user that is somehow held centrally and everything authenticates against that.

So how to achieve this - I'd previously used NIS/NIS+ too many years ago to remember anything about it and our current on premise solution (managed by others) hooks directly into active directory somehow.

We don't have full AD in Azure (at least how we are running it) , we have the PaaS offering "Azure AD" which does not have all the features of normal AD so what to do?

A quick google and i couldn't find anything until i came across this video https://channel9.msdn.com/Blogs/Open/Using-Azure-AD-for-Linux-logins

This is actually really good and exactly what i wanted to do - so i set about following the steps - i had a couple of issues on the way which i'll describe here as i was puzzling over it for quite a while.

The first thing i needed to do was create an application in Azure AD - now i had no real clue what i was doing here i just followed the steps - and it is pretty simple

Navigate to azure ad, then app registrations, then click the add button



 Then fill in the details below, name can be anything, application type has to be 'native', redirect url is not actually used but needs to be a valid url string (i.e. syntax is valid the site does not need to exist)

Once that finishes (should be very quick) it will generate you an application id - you'll need this and the name of your azure ad domain for the next phase where we go onto linux to set things up.

The first thing we need to do is download the clever bit of software to your server - this is called aad-login and can be got from github (thanks to Jose for this).

https://github.com/bureado/aad-login

Git was totally new to me so i had to register and get an account to be able to do the download

Once registered i can then download the file directly to linux by using the following steps

git clone https://github.com/bureado/aad-login.git
Cloning into 'aad-login'...
remote: Counting objects: 41, done.
remote: Total 41 (delta 0), reused 0 (delta 0), pack-reused 41
Unpacking objects: 100% (41/41), done.
Checking connectivity... done.


That pulls the software down in a directory called aad-login in my current directory

Now we take the bits out of here we want to make use of

go into the downloaded directory
cd aad-login

create a directory under opt to store the config and copy file there
mkdir /opt/aad-login
cp aad-login.js package.json /opt/aad-login

Copy the program to /usr/local/bin
 cp aad-login /usr/local/bin

To be able to compile this code in we need npm installed (this is all part of node.js - again new to me.....)

This wasn't installed so i added it with zypper

zypper install npm4
Refreshing service 'SMT-http_smt-azure_susecloud_net'.
Refreshing service 'cloud_update'.
Loading repository data...
Reading installed packages...
Resolving package dependencies...

The following 3 NEW packages are going to be installed:
  nodejs4 nodejs4-devel npm4

The following package is not supported by its vendor:
  nodejs4-devel

3 new packages to install.
Overall download size: 6.4 MiB. Already cached: 0 B. After the operation, additional 24.9 MiB will be used.
Continue? [y/n/? shows all options] (y): y
Retrieving package nodejs4-4.6.0-8.1.x86_64                                                             (1/3),   4.3 MiB ( 15.4 MiB unpacked)
Retrieving: nodejs4-4.6.0-8.1.x86_64.rpm ..............................................................................................[done]
Retrieving package nodejs4-devel-4.6.0-8.1.x86_64                                                       (2/3), 340.4 KiB (  2.4 MiB unpacked)
Retrieving: nodejs4-devel-4.6.0-8.1.x86_64.rpm ........................................................................................[done]
Retrieving package npm4-4.6.0-8.1.x86_64                                                                (3/3),   1.8 MiB (  7.2 MiB unpacked)
Retrieving: npm4-4.6.0-8.1.x86_64.rpm .................................................................................................[done]
Checking for file conflicts: ..........................................................................................................[done]
(1/3) Installing: nodejs4-4.6.0-8.1.x86_64 ............................................................................................[done]
(2/3) Installing: nodejs4-devel-4.6.0-8.1.x86_64 ......................................................................................[done]
(3/3) Installing: npm4-4.6.0-8.1.x86_64 ...............................................................................................[done]


Now we need to compile the code - this picks up the .json file from the current directory to tell it what to do so make sure you are in that directory

cd /opt/aad-login 
npm installadal-node@0.1.22 node_modules/adal-node
├──
underscore@1.8.3
├── xpath.js@1.0.6
├── xmldom@0.1.22
├── node-uuid@1.4.7
├── date-utils@1.2.21
├── jws@3.1.4 (safe-buffer@5.0.1, base64url@2.0.0, jwa@1.1.4)
├──
request@2.78.0 (aws-sign2@0.6.0, tunnel-agent@0.4.3, forever-agent@0.6.1, oauth-sign@0.8.2, caseless@0.11.0, is-typedarray@1.0.0, stringstream@0.0.5, aws4@1.5.0, isstream@0.1.2, json-stringify-safe@5.0.1, extend@3.0.0, qs@6.3.0, combined-stream@1.0.5, form-data@2.1.2, tough-cookie@2.3.2, mime-types@2.1.12, hawk@3.1.3, http-signature@1.1.1, har-validator@2.0.6)
└──
async@2.1.2 (lodash@4.17.2)
So now we have all the software needed we just need to set some config to hook this all together.

first we need to edit the aad-login.js file to enter our azure ad domain and the application id we created in the first step

so thats these 2 lines here

// Configuration parameters
var directory = 'yourdomainhere.onmicrosoft.com';
var clientid  = 'your-app-id-really-long-string-here;

Then in the pam config we need to add this line into the /etc/pam.d/common-auth file at the top

auth sufficient pam_exec.so expose_authtok /usr/local/bin/aad-login

At that point things in theory should work - but they didn't for me - here are the issues i had and how i fixed them.

1) azure ad account must have its password changed via portal after initial creation so its in the correct state

2) The home directory for the user you are trying to log on with must exist - it will not get autocreated - so for example if your login is called linuxtest you have to run

useradd -m linuxtest

This won't actually add a user to linux but will create home directories etc.

3) And this is the one i found hardest to solve - make sure the permissions are granted correctly in azure ad

Here is how this problem manifested itself - and actually its useful to show how you can test the login to get more info out of it.

So to test it you can run this


node /opt/aad-login/aad-login.js linuxtest password-for-linuxtest

{ error: 'unauthorized_client',
  error_description: 'AADSTS70001: Application with identifier \xxxxxxxxxxx\' was not found in the directory xxxxxx.onmicrosoft.com\r\nTrace ID: 11099aae-5465-4000-be93-7a02eb0d1c77\r\nCorrelation ID: b3987975-8097-4e47-b151-3c14e6e7da0c\r\nTimestamp: 2016-11-17 21:35:52Z',
  error_codes: [ 70001 ],
  timestamp: '2016-11-17 21:35:52Z',
  trace_id: '11099aae-5465-4000-be93-7a02eb0d1c77',
  correlation_id: 'b3987975-8097-4e47-b151-3c14e6e7da0c' }


In the case above i had the wrong application id configured in the .js config file

The problem i was getting though when that was corrected is this one

node /opt/aad-login/aad-login.js linuxtest password-for-linuxtest
{ error: 'invalid_grant',
  error_description: 'AADSTS65001: The user or administrator has not consented to use the application with ID \xxxxxxxxxxxxxx\'. Send an interactive authorization request for this user and resource.\r\nTrace ID: 27331880-9532-4494-a289-0e3ce1b9c9d1\r\nCorrelation ID: 8614c498-316e-4918-bf65-37ff85ef07f9\r\nTimestamp: 2016-11-18 00:12:21Z',
  error_codes: [ 65001 ],
  timestamp: '2016-11-18 00:12:21Z',
  trace_id: '27331880-9532-4494-a289-0e3ce1b9c9d1',
  correlation_id: '8614c498-316e-4918-bf65-37ff85ef07f9' }


So a permissions problem - however any kind of grant i did in the new azure portal made any bit of difference and I'd just about given up when i decided to try it in the old portal via this screen which is sort of hidden away - granting the extra read permission seemed to do the trick (where it hadn't worked from the new portal)



Now when i run the test script i see this

 node /opt/aad-login/aad-login.js linuxtest linuxtest-password
{ tokenType: 'Bearer',
  expiresIn: 3599,
  expiresOn: Fri Nov 18 2016 01:38:05 GMT+0000 (UTC),
  resource: 'spn:00000002-0000-0000-c000-000000000000',
  accessToken: 'really long random string here',
  userId:
'linuxtest@mydomain.onmicrosoft.com',
  isUserIdDisplayable: true,
  oid: 'xxx',
  tenantId: 'xxxx',
  isMRRT: true,
  _clientId: 'xxxx',
  _authority: 'https://login.windows.net/mydomain.onmicrosoft.com' }


And now when i ssh to the server the login works just fine


Very nice - makes management of the servers much easier.

Comments

  1. Fantastic. Thank you. Like you, I had followed the other guide but got stuck in the same place. the permissions fixed it for me!

    ReplyDelete
  2. Hi I am getting "undefined" after testing with node application as you did.

    ReplyDelete

Post a Comment