Showing posts with label Authentication. Show all posts
Showing posts with label Authentication. Show all posts

Tuesday, July 23, 2013

ssh to remote server passwordlessly

Often you'll want to run a script on serverB from serverA using ssh, one of those times is during an automated development build where you don't have the option of entering in a password.  Let's explore some options to do that passwordlessly.

Say serverA is where your automated build tool is installed.  serverB is where you want to deploy a war file to an application server using an automated script you want to invoke with ssh.

Both serverA and serverB were running CentOS for these set of instructions.

Solution
Step 1: On serverA machine, generate the authentication keys for ssh authentication.
  • For default rsa key filename, enter the following
    • [cherryshoe@serverA ~]$ ssh-keygen -t rsa
  • For specific rsa key filename for serverB, enter the following
    • [cherryshoe@serverA .ssh]$ ssh-keygen -t rsa -f ./id_rsa.serverB -C "Key for dev integration test server"
This will generate the authentication key pair -

  • id_rsa and id_rsa.pub OR 
  • id_rsa.serverB and id_rsa.serverB.pub

The result will be similar to:
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./id_rsa.serverB.
Your public key has been saved in ./id_rsa.serverB.pub.
The key fingerprint is:
e9:d6:a6:ad:6d:89:15:31:59:be:ae:32:99:eb:10:e6 Key for dev integration test server

Step 2: NOTE: This step is not required.  Use ssh-agent to securely store the private key on serverA.  This will enable you to avoid continuing to type the pass-phrase when sshing from serverA to serverB.

[cherryshoe@serverA .ssh]$ ssh-agent $BASH
[cherryshoe@serverA .ssh]$ ssh-add
Identity added: /home/cherryshoe/.ssh/id_rsa
[cherryshoe@serverA .ssh]$ ssh-add id_rsa.serverB
Identity added: /home/cherryshoe/.ssh/id_rsa.serverB

NOTE: To list all private keys on serverA, issue ssh-add -l

Step 3: Copy public key to serverB

Step 3a: If sshpass is installed, otherwise use Step 3b.
  • Navigate to /<home>/.ssh - note that the id_rsa.pub already exists (default name from above step)
  • Run a single command with sshpass, if installed
    • sshpass -p <password of user on serverB> ssh-copy-id <server B IP address>
  • Test
    • ssh <server B IP address>
Step 3b: Copy the public key over to serverB <home>/.ssh/authorized_keys file.

Option a: manual
  • If the file doesn't exist yet, then copy over public key.pub file over as the authorized_keys file.
    • i.e: 
      • scp id_rsa.pub to the serverB AS <home>/.ssh/authorized_keys
  • If it does, then open up the contents of the public key .pub file on serverA, and append it to the existing authorized_keys file on serverB.
Option b: automated
Use ssh-copy-id to automate this step
[cherryshoe@serverA .ssh]$ ssh-copy-id -i ~/.ssh/id_rsa.pub cherryshoe@serverB
cherryshoe@serverB's password:

Step 4: Ensure serverB user's .ssh directory has permission 700 and the authorized
_keys file has permission 640

drwx------. 2 cherrryshoe wheel 4096 Jul 8 08:00 .
drwx------. 5 cherryshoe cherryshoe   4096 Jul 7 15:43 ..
-rw-r-----. 1 cherryshoe wheel  398 Jul 8 08:00 authorized_keys

You should now be able to ssh from serverA to serverB passwordlessly!  

NOTE:  The above instructions are for when the user on serverA and serverB are the same username. Take for example serverA cherryshoe wants to ssh to serverB as shoetech:

On serverA machine:

  • Generate the keys for user shoetech
  • ssh-keygen -t rsa -f id_serverB_shoetech -C "shoetech@serverB"
  • ssh-copy-id id_serverB_shoetech.pub shoetech@serverB
  • check the known_hosts file now has the serverB IP


Generate the keys for user cherryshoe

  • ssh-keygen -t rsa -f id_serverB_cherryshoe -C "cherryshoe@serverB"


On serverB machine:

  • Append the contents of id_serverB_cherryshoe.pub to shoetech's authorized_keys file.  The authorized_keys of shoetech user should have two .pub keys (one for cherryshoe user, second for shoetech user).  Make sure each .pub key has username@hostname at the end (this will already be at the end if you use the -C parameter when generating the key pair with ssh-keygen command).


From serverA, now you will need to specify the path to private key for user shoetech, to ssh into serverB as shoetech

  • ssh -i ~/.ssh/id_serverB_shoetech shoetech@serverB

These articles were a great help.
http://www.cyberciti.biz/tips/ssh-public-key-based-authentication-how-to.html
http://www.karan.org/blog/index.php/2009/08/25/multiple-ssh-private-keys
http://stackoverflow.com/questions/2419566/best-way-to-use-multiple-ssh-private-keys-on-one-client

Sunday, December 23, 2012

Active Directory Role Based Access within an Alfresco Web Script


The Alfresco project I work on uses LDAP for authentication against Active Directory (AD), users and groups are synched from AD, with Kerberos protocol for Single Sign On (SSO); Alfresco runs on Apache Tomcat.  I won’t go into detail on how to configure this, my focus today is retrieving a SSO logged-in user’s AD groups to determine role based access within an Alfresco Web Script in order to access the web script’s functionality.

First, you’ll need to determine which AD Groups and Users will by synched with Alfresco.  This will be configured via Alfresco’s Authentication Subsystem.

Second, determine which AD groups will have access to this functionality, i.e. “AllBloggersGroup and SomeGroup”.  Make sure the user that you want access to this web script belongs to this group, i.e. “cherryshoe” belongs to group “AllBloggersGroup”.

Third, inject Alfresco’s Authentication Service Spring Bean into the service, and define the allowed roles.
<bean id="com.blogspot.cherryshoe.ExampleService"
class="com.blogspot.cherryshoe.ExampleService"
parent="webscript">
    <property name="authenticationService" ref="AuthenticationService"/>        
    <property name="allowedRoles" value="AllBloggersGroup,SomeGroup"/>
</bean>

Fourth, you’ll need to run authorityService.getAuthoritiesForUser as an admin user, since calling it requires admin credentials.  This article helped me solve the problem of insufficient permissions (running your code as a different user with alfresco blog).

private AuthenticationService authenticationService;
    
// holds the allowed roles
private String allowedRoles;
private List<String> allowedRoleList;

public void setAuthenticationService(AuthenticationService authenticationService) {
    this.authenticationService = authenticationService;
}

public void setAllowedRoles(String allowedRoles) {
    this.allowedRoles = allowedRoles;

    // set up value of allowedRoleList, get rid of any whitespace
    allowedRoleList = Arrays.asList(allowedRoles.split("\\s*,\\s*"));
}

public boolean isUserAuthorized(final String userName) {
    // someFunctionStart
    Set<String> authorizedAuthRoleSet = org.alfresco.repo.security.authentication.AuthenticationUtil
            .runAs(new org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork<Set<String>>() {
                @Override
                public Set<String> doWork() throws Exception {
                    // executes the following lines as admin user
                    Set<String> auths = authorityService
                            .getAuthoritiesForUser(userName);
                    return auths;
                }
            }, "admin");

    boolean isUserRoleAuthorized = false;

    for (String currAuthRole : authorizedAuthRoleSet) {
        for (String currRole : allowedRoleList) {
            if (currAuthRole.contains(currRole)) {
                isUserRoleAuthorized = true;
                break;
            }
        }
        if (isUserRoleAuthorized)
            break;
    }

    return isUserRoleAuthorized;
    // someFunctionEnd
}

NOTE:  Make sure that the LDAP synchronization occurs without any errors, or the call to getAuthoritiesForUser won’t work.  My current theory for this is because all users / groups synched cannot have any errors, or the call won’t work for any specific user.

Lastly, invoke the web service using an already authenticated user using Internet Explorer 9 web client using Kerberos for Single Sign On (adding Alfresco as trusted domain).  The web script is invoked without passing alf_ticket (since authentication is automatically passed for you using SSO) and using  /alfresco/wcservice in the base web URL (versus /alfresco/service).
i.e.  If user “cherryshoe” is already logged into Alfresco with IE 9 web client, then invoke URL http://127.0.0.1:8080/alfresco/wcservice/com/blogspot/cherryshoe/exampleService to use cherryshoe’s user credentials.