Coverage Report - org.openpermis.examples.ejb.server.HelloWorldService
 
Classes in this File Line Coverage Branch Coverage Complexity
HelloWorldService
39%
21/53
62%
5/8
3.444
 
 1  
 /*
 2  
  * Copyright (c) 2009, Swiss Federal Department of Defence Civil Protection and Sport
 3  
  *                     (http://www.vbs.admin.ch)
 4  
  * Copyright (c) 2009, Ergon Informatik AG (http://www.ergon.ch)
 5  
  * All rights reserved.
 6  
  *
 7  
  * Licensed under the Open Permis License which accompanies this distribution,
 8  
  * and is available at http://www.openpermis.org/BSDlicenceKent.txt
 9  
  */
 10  
 package org.openpermis.examples.ejb.server;
 11  
 
 12  
 import java.io.IOException;
 13  
 import java.net.URI;
 14  
 import java.net.URISyntaxException;
 15  
 import java.net.URL;
 16  
 import java.security.cert.CertificateException;
 17  
 import java.security.cert.CertificateFactory;
 18  
 import java.security.cert.X509Certificate;
 19  
 import java.util.ArrayList;
 20  
 import java.util.List;
 21  
 
 22  
 import javax.ejb.Stateless;
 23  
 
 24  
 import org.openpermis.AuthorizationService;
 25  
 import org.openpermis.AuthorizationServiceException;
 26  
 import org.openpermis.PolicyDecisionPoint;
 27  
 import org.openpermis.Subject;
 28  
 import org.openpermis.builder.AuthorizationServiceBuilder;
 29  
 import org.openpermis.cert.AttributeCertificateExtractorUtility;
 30  
 import org.openpermis.cert.BasicCertificateVerifier;
 31  
 import org.openpermis.cert.CertificateVerifier;
 32  
 import org.openpermis.policy.AccessDecision;
 33  
 import org.openpermis.repository.SubjectRepository;
 34  
 import org.openpermis.repository.SubjectRepositoryException;
 35  
 
 36  
 
 37  
 /**
 38  
  * An EJB implementation of the HelloWorld service.
 39  
  * <p>Access to a basic HelloWorld service is controlled with help of a policy decision
 40  
  * point (PDP). It serves as a policy enforcement point for the HelloWorld application.</p>
 41  
  * @since 0.3.0
 42  
  */
 43  
 @Stateless
 44  
 public class HelloWorldService
 45  
         implements HelloWorldServiceRemote
 46  
 {
 47  
 
 48  
         //---- Static
 49  
         
 50  
         /**
 51  
          * @since 0.3.0
 52  
          */
 53  1
         protected static final URI TARGET_RESOURCE_URI = URI.create("cn=letterbox,o=post,c=ch");
 54  
 
 55  
         /**
 56  
          * @since 0.3.0
 57  
          */
 58  
         protected static final String ACTION_NAME = "collectLetters";
 59  
 
 60  
         /**
 61  
          * Reads the SoA certificate from the classpath.
 62  
          * <p>A policy decision point needs a trusted public key of the source of authority (SoA) 
 63  
          * to validate the attribute certificates (AC), including policies and roles. Future 
 64  
          * implementations will allow a advanced public key infrastructure (PKI).</p>
 65  
          * @return the SoA certificate or {@code null} if it could not be read.
 66  
          * @since 0.3.0
 67  
          */
 68  
         private static final X509Certificate readSoaCertificate () {
 69  
                 try {
 70  0
                         final URL soaCertificateUrl = 
 71  
                                 HelloWorldService.class.getResource("soa.cer");
 72  0
                         final CertificateFactory factory = CertificateFactory.getInstance("X.509");
 73  0
                         return (X509Certificate) factory.generateCertificate(soaCertificateUrl.openStream());
 74  0
                 } catch (CertificateException e) {
 75  0
                         System.out.println(" Cannot load SOA certificate. (" + e.getMessage() + ")");
 76  0
                 } catch (IOException e) {
 77  0
                         System.out.println(" Cannot load SOA certificate. (" + e.getMessage() + ")");
 78  0
                 }
 79  0
                 return null;
 80  
         }
 81  
         
 82  
         /**
 83  
          * Creates a {@link PolicyDecisionPoint} from an attribute certificate located on the classpath.
 84  
          * @param certificateVerifier the certificate verifier used to verify the attribute 
 85  
          * certificate containing the policy.
 86  
          * @return the {@link PolicyDecisionPoint} requested or {@code null} if it could not be created.
 87  
          * @since 0.3.0
 88  
          */
 89  
         private static final PolicyDecisionPoint createPolicyDecisionPoint (
 90  
                 CertificateVerifier certificateVerifier
 91  
         ) {
 92  0
                 final URL policyCertificateURL = 
 93  
                         HelloWorldService.class.getResource("policy.ace");
 94  
                 try {
 95  0
                         return AttributeCertificateExtractorUtility.
 96  
                                 createPolicyDecisionPoint(policyCertificateURL, certificateVerifier);
 97  0
                 } catch (Exception e) {
 98  0
                         System.out.println("Failed to load policy decision point. (" + e.getMessage() + ")");
 99  
                 }
 100  0
                 return null;
 101  
         }
 102  
         
 103  
         /**
 104  
          * Creates a subject repository with subjects read from the classpath.
 105  
          * @param certificateVerifier The certificate verifier used to verify attribute certificates.
 106  
          * Used in the subject repository.
 107  
          * @return the subject repository or {@code null} in case of an error.
 108  
          * @since 0.3.0
 109  
          */
 110  
         private static final SubjectRepository readSubjectRepository (
 111  
                 CertificateVerifier certificateVerifier
 112  
         ) {
 113  
                 try {
 114  0
                         return new HelloWorldSubjectRepository(
 115  
                                 certificateVerifier,
 116  
                                 "john.ace",
 117  
                                 "sara.ace"
 118  
                         );
 119  0
                 } catch (SubjectRepositoryException e) {
 120  0
                         System.out.println("Failed to create subject repository. (" + e.getMessage() + ")");
 121  
                 }
 122  0
                 return null;
 123  
         }
 124  
         
 125  
         /**
 126  
          * Creates a authorization for the hello world EJB.
 127  
          * @return the authorization service to use.
 128  
          * @since 0.3.0
 129  
          */
 130  
         private static final AuthorizationService createPolicyDecisionPoint () {
 131  0
                 final CertificateVerifier certificateVerifier =
 132  
                         new BasicCertificateVerifier(readSoaCertificate());
 133  0
                 return new AuthorizationServiceBuilder().
 134  
                         withSubjectsFrom(readSubjectRepository(certificateVerifier)).
 135  
                         forPolicyDecisionPoint(createPolicyDecisionPoint(certificateVerifier)).build();
 136  
         }
 137  
         
 138  
         /**
 139  
          * Creates a basic hello world service for this EJB.
 140  
          * @return the actual hello world service to delegate to.
 141  
          * @since 0.3.0
 142  
          */
 143  
         private static final HelloWorldServiceRemote createHelloWorldService () {
 144  0
                 return new BasicHelloWorldService();
 145  
         }
 146  
         
 147  
         //---- State
 148  
         
 149  
         /**
 150  
          * The injected authorization service.
 151  
          * @since 0.3.0
 152  
          */
 153  
         private final AuthorizationService authorizationService;
 154  
 
 155  
         /**
 156  
          * The actual service implementation to which we forward authorized requests.
 157  
          * @since 0.3.0
 158  
          */
 159  
         private final HelloWorldServiceRemote delegate;
 160  
         
 161  
         //---- Constructors
 162  
         
 163  
         /**
 164  
          * Creates a hello world EJB which uses a default PDP and HelloWorld service.
 165  
          * @see #createPolicyDecisionPoint()
 166  
          * @see #createHelloWorldService()
 167  
          * @since 0.3.0
 168  
          */
 169  
         public HelloWorldService () {
 170  0
                 this(
 171  
                         createPolicyDecisionPoint(),
 172  
                         createHelloWorldService()
 173  
                 );
 174  0
         }
 175  
         
 176  
         /**
 177  
          * Creates an authorized HelloWorld service that uses the specified authorization service
 178  
          * context for retrieving roles and making access decisions.
 179  
          * @param authorizationService a {@link AuthorizationService}.
 180  
          * @param delegate the real service implementation to which authorized requests are forwarded.
 181  
          * @since 0.3.0
 182  
          */
 183  
         public HelloWorldService (
 184  
                 AuthorizationService authorizationService,
 185  
                 HelloWorldServiceRemote delegate
 186  2
         ) {
 187  2
                 this.authorizationService = authorizationService;
 188  2
                 this.delegate = delegate;
 189  2
         }
 190  
         
 191  
         //---- Methods
 192  
         
 193  
         /**
 194  
          * Asserts that the service has been correctly initialized.
 195  
          * @throws HelloWorldException if the service is not correctly initialized.
 196  
          * @since 0.3.0
 197  
          */
 198  
         protected void assertInitialized () throws HelloWorldException {
 199  2
                 if (this.authorizationService == null) {
 200  0
                         throw new HelloWorldException("PDP not initialized.");
 201  2
                 } else if (this.delegate == null) {
 202  0
                         throw new HelloWorldException("Delegate HelloWorldService not initialized.");
 203  
                 }
 204  2
         }
 205  
         
 206  
         //---- HelloWorldService
 207  
         
 208  
         /**
 209  
          * @since 0.1.0
 210  
          */
 211  
         public String getHelloMessage (String name)
 212  
                 throws HelloWorldException
 213  
         {
 214  2
                 assertInitialized();
 215  
                 // Find out who wants to access the service and which roles he has.
 216  
                 // In an authenticated application you would get a java.net.Principal from an
 217  
                 // authentication service and determine an identity from its name.
 218  
                 // In a stateful application you would cache the retrieved subject in the current
 219  
                 // session context to avoid repeated role lookups.
 220  
                 final URI identity;
 221  
                 try {
 222  2
                         identity = new URI(name);
 223  0
                 } catch (URISyntaxException e) {
 224  0
                         throw new HelloWorldException("Invalid name " + name, e);
 225  2
                 }
 226  
                 final Subject subject;
 227  
                 try {
 228  2
                         subject = this.authorizationService.retrieveSubject(identity);
 229  0
                 } catch (AuthorizationServiceException e) {
 230  0
                         throw new HelloWorldException("Cannot retrieve subject for " + name, e);
 231  2
                 }
 232  
                 
 233  2
                 if (subject == null) {
 234  0
                         throw new HelloWorldException("Unknown name " + name);
 235  
                 }
 236  
                 
 237  
                 // Identify the resource to protect. This could be a service URL.
 238  2
                 final URI resource = TARGET_RESOURCE_URI;
 239  
                 
 240  
                 // Identify the action to perform on the protected resource.
 241  2
                 final String actionName = ACTION_NAME;
 242  2
                 final List<Object> arguments = new ArrayList<Object>();
 243  
 
 244  
                 try {
 245  
                         // Ask the PDC for an access decision.
 246  2
                         final AccessDecision decision = this.authorizationService.getAccessDecision(
 247  
                                 subject, resource, actionName, arguments
 248  
                         );
 249  
                         
 250  2
                         if (decision.isAccessGranted()) {
 251  
                                 // We are authorized to proceed, but still have to check obligations in the future.
 252  1
                                 return this.delegate.getHelloMessage(name);
 253  
                         }
 254  
 
 255  
                         // The decision is negative. We must inform the caller that he is not authorized.
 256  1
                         throw new HelloWorldException("Access denied for " + name);
 257  
                 
 258  0
                 } catch (AuthorizationServiceException e) {
 259  0
                         throw new HelloWorldException("Cannot get access decision for " + name, e);
 260  
                 }
 261  
         }
 262  
 
 263  
 }