/* * Copyright (C) 2013 Intel Corporation * All rights reserved. */ package test.shiro; import com.intel.dcsg.cpg.io.UUID; import com.intel.mtwilson.My; import com.intel.mtwilson.as.data.MwApiClientHttpBasic; import com.intel.mtwilson.ms.data.MwPortalUser; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.util.Factory; //import org.apache.shiro.ShiroException; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.apache.shiro.session.Session; import org.apache.shiro.realm.Realm; import org.apache.shiro.realm.RealmFactory; import org.junit.Test; /** * NOTE: this is just a test class; in mtwilson 2.0 domains must be plural like "hosts" and "user_passwords" * * References: * * http://shiro.apache.org/architecture.html * * Sample output: * Running test.shiro.ShiroCmdLineTest 2013-12-28 17:05:25,623 DEBUG [main] t.s.ShiroCmdLineTest [ShiroCmdLineTest.java:27] initializing shiro 2013-12-28 17:05:25,639 DEBUG [main] o.a.s.i.ResourceUtils [ResourceUtils.java:159] Opening resource from class path [shiro.ini] 2013-12-28 17:05:25,649 DEBUG [main] o.a.s.c.Ini [Ini.java:342] Parsing [users] 2013-12-28 17:05:25,651 DEBUG [main] o.a.s.c.Ini [Ini.java:342] Parsing [roles] 2013-12-28 17:05:25,653 DEBUG [main] o.a.s.c.IniFactorySupport [IniFactorySupport.java:122] Creating instance from Ini [sections=users,roles] 2013-12-28 17:05:25,691 DEBUG [main] o.a.s.r.t.IniRealm [IniRealm.java:179] Discovered the [roles] section. Processing... 2013-12-28 17:05:25,695 DEBUG [main] o.a.s.r.t.IniRealm [IniRealm.java:185] Discovered the [users] section. Processing... 2013-12-28 17:05:25,707 DEBUG [main] t.s.ShiroCmdLineTest [ShiroCmdLineTest.java:39] authenticating... 2013-12-28 17:05:25,708 DEBUG [main] o.a.s.r.AuthenticatingRealm [AuthenticatingRealm.java:569] Looked up AuthenticationInfo [guest] from doGetAuthenticationInfo 2013-12-28 17:05:25,708 DEBUG [main] o.a.s.r.AuthenticatingRealm [AuthenticatingRealm.java:507] AuthenticationInfo caching is disabled for info [guest]. Submitted token: [org.apache.shiro.authc.UsernamePasswordToken - guest, rememberMe=true]. 2013-12-28 17:05:25,709 DEBUG [main] o.a.s.a.c.SimpleCredentialsMatcher [SimpleCredentialsMatcher.java:95] Performing credentials equality check for tokenCredentials of type [[C and accountCredentials of type [java.lang.String] 2013-12-28 17:05:25,709 DEBUG [main] o.a.s.a.c.SimpleCredentialsMatcher [SimpleCredentialsMatcher.java:101] Both credentials arguments can be easily converted to byte arrays. Performing array equals comparison 2013-12-28 17:05:25,709 DEBUG [main] o.a.s.a.AbstractAuthenticator [AbstractAuthenticator.java:231] Authentication successful for token [org.apache.shiro.authc.UsernamePasswordToken - guest, rememberMe=true]. Returned account [guest] 2013-12-28 17:05:25,709 DEBUG [main] o.a.s.s.s.DefaultSubjectContext [DefaultSubjectContext.java:102] No SecurityManager available in subject context map. Falling back to SecurityUtils.getSecurityManager() lookup. 2013-12-28 17:05:25,709 DEBUG [main] o.a.s.s.s.DefaultSubjectContext [DefaultSubjectContext.java:102] No SecurityManager available in subject context map. Falling back to SecurityUtils.getSecurityManager() lookup. 2013-12-28 17:05:25,710 DEBUG [main] o.a.s.s.m.AbstractValidatingSessionManager [AbstractValidatingSessionManager.java:213] No sessionValidationScheduler set. Attempting to create default instance. 2013-12-28 17:05:25,711 INFO [main] o.a.s.s.m.AbstractValidatingSessionManager [AbstractValidatingSessionManager.java:230] Enabling session validation scheduler... 2013-12-28 17:05:25,717 DEBUG [main] o.a.s.s.m.DefaultSessionManager [DefaultSessionManager.java:175] Creating new EIS record for new session instance [org.apache.shiro.session.mgt.SimpleSession,id=null] 2013-12-28 17:05:25,778 INFO [main] t.s.ShiroCmdLineTest [ShiroCmdLineTest.java:47] logged in as guest 2013-12-28 17:05:25,778 INFO [main] t.s.ShiroCmdLineTest [ShiroCmdLineTest.java:53] security notice 2013-12-28 17:05:25,779 DEBUG [main] t.s.ShiroCmdLineTest [ShiroCmdLineTest.java:79] user cannot delete host #5 2013-12-28 17:05:25,779 DEBUG [main] o.a.s.m.DefaultSecurityManager [DefaultSecurityManager.java:550] Logging out subject with primary principal guest 2013-12-28 17:05:25,780 DEBUG [main] o.a.s.s.m.AbstractSessionManager [AbstractNativeSessionManager.java:244] Stopping session with id [00e9c153-d2ef-4d3c-b400-0c3aef205ba1] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.645 sec * * @author jbuhacoff */ public class ShiroCmdLineTest { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ShiroCmdLineTest.class); @Test public void testCmdLine() throws Exception { // pretend to be a cmd line tool log.debug("initializing shiro"); // initialize shiro ... should be in mtwilson-launcher (to intialize for stand-alone app, or for an app hosted on a java web server) Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); // sets a single shiro security manager to be used for entire jvm... fine for a stand-alone app but when running inside a web app container or in a multi-user env. it needs to be maintained by some container and set on every thread that will do work ... // get current user Subject currentUser = SecurityUtils.getSubject(); // check if user is authenticated (username/password env vars or http Authorization header) if( !currentUser.isAuthenticated() ) { log.debug("authenticating..."); // for this junit test we're using mtwilson.api.username and mtwilson.api.password properties from mtwilson.properties on the local system, c:/mtwilson/configuration/mtwilson.properties is default location on windows UsernamePasswordToken token = new UsernamePasswordToken(getBasicUsername(), getBasicPassword()); // guest doesn't need a password // UsernamePasswordToken token = new UsernamePasswordToken("root", "root"); // guest doesn't need a password token.setRememberMe(true); // in web environment this might relate to cookies, but what about command line or others? currentUser.login(token); // throws UnknownAccountException , IncorrectCredentialsException , LockedAccountException , other specific exceptions, and AuthenticationException } // show who is the user log.info("logged in as {}", currentUser.getPrincipal()); // you can make information available to the user based on their security access, or check if they have already changed their password or seen a notice or whatever during the current session Session session = currentUser.getSession(); Object loginSecurityNotice = session.getAttribute("loginSecurityNotice"); if( loginSecurityNotice == null || !(Boolean)loginSecurityNotice ) { log.info("security notice"); session.setAttribute("loginSecurityNotice", Boolean.TRUE); } // check if the user has a specific role if ( currentUser.hasRole( "root" ) ) { log.warn("user is root" ); } // this is how permissions should be checked throughout the application: // host.store() should check isPermitted("host:write") or isPermitted("host:create") or isPermitted("host:replace") // host.retrieve() should check isPermitted("host:read") // host.delete() should check isPermitted("host:delete") // etc. if( currentUser.isPermitted( "host_attestation:read" ) ) { log.debug("user can get attestation reports"); } if( currentUser.isPermitted( "host_trustpolicy:read" ) ) { log.debug("user can see trust policies"); } // there is also support for row-level authentication: a user might be able to register a host but then only edit hosts s/he registered, not ALL hosts: if( currentUser.isPermitted("host:delete:5")) { // need a shortcut for identifying records associated with current user, owned by current user, creatd by current user, read/write by current user's gruop, etc. .... not just instance ids. also need a way to filter by something other than an id, such as user can edit only citrix hosts , not vmware or kvm hosts... log.debug("user can delete host #5"); } else { log.debug("user cannot delete host #5"); } if( currentUser.isPermitted("user_password:read")) { // need a shortcut for identifying records associated with current user, owned by current user, creatd by current user, read/write by current user's gruop, etc. .... not just instance ids. also need a way to filter by something other than an id, such as user can edit only citrix hosts , not vmware or kvm hosts... log.debug("user can read passwords"); UserPasswords service = new UserPasswords(); UserPassword userPassword = service.retrieve(new UUID().toString()); log.debug("got user password {} : {}", userPassword.getName(), userPassword.getPassword()); } else { log.debug("user cannot read passwords"); } // logout the user currentUser.logout(); // removes all identifying information and invalidates session } private String getBasicUsername() throws Exception { return My.configuration().getConfiguration().getString("mtwilson.api.username", System.getProperty("user.name", "guest")); } private String getBasicPassword() throws Exception { return My.configuration().getConfiguration().getString("mtwilson.api.password", ""); } /** * See createUser tests in test.jdbi.RepositoryTest in mtwilson-shiro-jdbi * * @throws Exception * @deprecated */ @Deprecated @Test public void createUser() throws Exception { /* MwApiClientHttpBasic userPassword = new MwApiClientHttpBasic(); userPassword.setUserName(getBasicUsername()); userPassword.setPassword(getBasicPassword()); log.debug("Creating login username {} password {}", userPassword.getUserName(), userPassword.getPassword()); // My.jpa().mwApiClientHttpBasic().create(userPassword); MwPortalUser portalUser = new MwPortalUser(); portalUser.setEnabled(true); portalUser.setStatus("APPROVED"); portalUser.setUsername(getBasicUsername()); portalUser.setUuid_hex(new UUID().toString()); // keystore was required for mtwilson 1.2 portal user, but in 2.0 it's moving to a separate table ... until that happens we have to provide SOME value here so we use an empty byte array: portalUser.setKeystore(new byte[0]); log.debug("Creating profile username {} uuid {}", portalUser.getUsername(), portalUser.getUuid_hex()); // for example jonathan cc1de7dd-3f1b-41e6-92ab-ed62250979db // My.jpa().mwPortalUser().create(portalUser); */ } }