Difference between revisions of "How To Configure Service Security"

From Gcube Wiki
Jump to: navigation, search
(Use delegated credentials to invoke services)
 
(13 intermediate revisions by 4 users not shown)
Line 1: Line 1:
This page contains useful information for DILIGENT developers about configuration of services to comply with the [[DILIGENT Security Model]].
 
 
==Configure service authentication==
 
 
This configuration protect the service against unauthenticated access, setting it each client is forced to present valid credentials. Please notice that with these settings authorization is still not enforced on the service. This means that every authenticated client is entitled to use service operations.
 
 
===Create Web Service Security Descriptor (WSSD)===
 
 
Create the Web Service Security Descriptor. A different security descriptor file should be created for each interface of your service in the <code>etc/</code> directory of your service. See [[Media:YourService-security-config-1.xml]] for an example.
 
 
For detailed information about security options supported in security desciptors you can take a look at the ws-core documentation [http://www.globus.org/toolkit/docs/4.0/security/authzframe/security_descriptor.html#s-authzframe-server-secdesc-descFile here]
 
 
In the security descriptor configuration you should avoid to specify credentials for your service. Credentials for DILIGENT services can be obtained through the Delegation service developed in the DVOS class. For detailed information about how to provides your services with credentials you can refer to the [[How_To_Configure_Service_Security#Provide_your_service_with_credentials]] section of this page.
 
 
The gridmap file setting should also be avoided, authorization for DILIGENT services is enforced using the DVOS Authorization Service. It can be configured as explained in the [[http://ddwiki.di.uoa.gr/mediawiki/index.php/How_To_Configure_Service_Security#Add_Authorization]] section.
 
 
Currently the only Authentication method supported in the DILIGENT infrastructure is the GSISecureConversation one, both with or without privacy or integrity options.
 
 
The run-as identity should be limited to service-identity or caller-identity, depending on which credentials are used by your service to perform invocations.
 
 
===Modify Web Service Deployment Descriptor (WSDD)===
 
 
Modify the Web Service Deployment Descriptor to refer the Web Service Security Descriptor. Add following line to the service tag:
 
 
<parameter name="securityDescriptor" value="@config.dir@/YourService-security-config.xml"/>
 
 
(of course the value must be set to the name of the WSSD you just created) See [[Media:deploy-server-1.wsdd]] for an example
 
 
Then redeploy your service in the DHN container.
 
 
 
==Access a service using authentication==
 
==Access a service using authentication==
 
+
In this step you'll try to access your service with a client using authentication. This step assumes the service has been deployed in a container able to host secure services. The [https://technical.wiki.d4science.research-infrastructures.eu/documentation/index.php/Administrator%27s_Guide:How_to_set_up_a_gCube_infrastructure#Secure_configuration Configure gContainer security] page describes steps needed to set-up a secured gContainer.
In this step you'll try to access your service with a client using authentication. This step assumes the service has been deployed in a container able to host secure services. The [[How To Configure DHN Security]] page describes steps needed to set-up such a container.
+
  
 
First of all try to contact your service using an unauthenticated client, you should get following Axis fault:
 
First of all try to contact your service using an unauthenticated client, you should get following Axis fault:
 
 
  ... GSI Secure Conversation authentication required for
 
  ... GSI Secure Conversation authentication required for
  &quot;{<nowiki>http://www.diligentproject.org/namespaces/</nowiki>...&quot; operation.
+
  &quot;{<nowiki>http://yournamespaces/namespaces/</nowiki>...&quot; operation.
 
+
This means that the GSI Secure Conversation mechanism is required to invoke the service. To enable it perform following steps.
+
  
 +
This means that the GSI Secure Conversation mechanism is required to invoke the service. To enable it, follow those steps.
 
===Set credentials on service stubs===
 
===Set credentials on service stubs===
 
+
<source lang="java5">
Use following lines to load your proxy credentials and use them to contact the service
+
PortType PT = new ServiceAddressingLocator().gePortTypePort(epr);
 
+
// PORTTYPE getProxy(PORTTYPE portTypeStub, GCUBEScopeManager scopeManager, GCUBESecurityManager ... securityManager)‏
import org.diligentproject.dvos.authentication.util.ConfigureSecurity;
+
PT = GCUBERemotePortTypeContext.getProxy(PT, scopeManager, serviceContext);
import org.ietf.jgss.GSSCredential;
+
</source>
...
+
Don't forget to add the <code>client-config.wsdd</code> file in the directory where you run the client. Alternatively, you can add the <code>$GLOBUS_LOCATION</code> as the first entry of your classpath. Then you should be able to contact your service using your credentials.
GSSCredential cred = ConfigureSecurity.loadProxyCredentials("yourProxyFile");
+
  ...
+
YourServicePortType port = ...<getPortType>
+
ConfigureSecurity.setSecurity(((javax.xml.rpc.Stub) port), cred);
+
+
Don't forget to add the <code>client-config.wsdd</code> file in the directory where you run the client. You can, instead, add the <code>$GLOBUS_LOCATION</code> as the first entry of your classpath.
+
 
+
Then you should be able to contact your service using your credentials
+
 
+
==Get the DL of the caller==
+
 
+
Following code allows to extract from credentials the name of the community and the name of the DL where credentials are operating.
+
 
+
org.gridforum.jgss.ExtendedGSSCredential credentials = ...
+
org.diligentproject.dvos.authentication.util.DILIGENTVomsAttributesReader d;
+
d = new DILIGENTVomsAttributesReader(credentials);
+
String communityName = d.getCommunity();
+
String DLName = d.getDL();
+
String absoluteDLName = d.getAbsoluteDLName());
+
 
+
The getCommunity() method return the name of the community as String (E.g.: impect).
+
 
+
The getDL() method return the name of the DL as String (E.g.: OceanDL).
+
 
+
The getAbsoluteDLName() method return the absolute name of the DL as String (E.g.: /diligent/impect/OceanDL).
+
  
 
==Provide your service with credentials==
 
==Provide your service with credentials==
 +
After the previous steps, your service can authenticate itself in outcoming requests towards other services. To provide credentials to your service you have to configure the jndi file of your service. This allows your service to interact with the co-hosted instance of gCube Delegation service and a gCube CredentialsRenewal service available in your service's scope (as described in following section)
  
This step enable your service to authenticating itself in outcoming requests it performs to other services. Two ways can be followed to provide credentials to your service:
+
===Which kind of security needs your service? Understand the semantic of your service===
* Use the DILIGENT Delegation service (as described in following section)
+
Typically a GCUBEService can be of three types:
* Use the delegation mechanism embedded in the GSISecureConversation protocol. For detials of this option refers to section [[How To Configure Service Security#Use_the_GSISecureConversation_delegation]]
+
# Doesn't need credentials but runs in a secure infra
 
+
# Acts on behalf of a caller
===Register to the local Delegation service===
+
# Autonomous and needs service credentials
 
+
In your service, usually during initialization, you should create a new <code>CredentialsListener</code> and register it to the local <code>DelegationLocalInterface</code>. The listener will be notified when fresh credentials will be received for your service.
+
 
+
Two classes of listeners are available (and others can be implemented by developers if needed). The one to use depends on the scenario adopted by your service (refers to the [[DILIGENT Security Model]] page for more information about identity scenario). If your service operates in a single DL it needs only a single copy of credentials. The service does not have to choose the DL where it is operating.
+
If the service operaties in multiple DLs, instead, it needs to choose credentials to use to perform invocations.
+
 
+
If the service '''operates in a single DL''' the listener to use is the SingleCredentialsListener one. This listener is able to store only a single copy of credentials, regardless the DL these credentials refers to. The registration in this case looks like the one in the box below.
+
 
+
credentialsListener = new SimpleCredentialsListener();
+
DelegationLocalInterface.registerCredentialsListener(this.credentialsListener);
+
 
+
Previous lines of codes are usually added to the constructor of the class implementing service operations. E.g:
+
 
+
public class VOAdministrationService {
+
  ... 
+
  private SimpleCredentialsListener credentialsListener;
+
  ...
+
  /* Constructor */
+
  public VOAdministrationService() throws ResourceContextException, ResourceException {
+
  this.credentialsListener = new SimpleCredentialsListener();
+
  DelegationLocalInterface.registerCredentialsListener(this.credentialsListener);
+
  }
+
 
+
If the service '''operates in multiple DLs''' the listener to use is the MultipleCredentialsListener one. This listener is able to store credentials based on the DL they refers to. The registration in this case looks like the one in the box below.
+
 
+
credentialsListener = new MultipleCredentialsListener();
+
DelegationLocalInterface.registerCredentialsListener(this.credentialsListener);
+
 
+
Previous lines of codes are usually added to the constructor of the class implementing service operations. E.g:
+
 
+
public class VOAdministrationService {
+
  ... 
+
  private MultipleCredentialsListener credentialsListener;
+
  ...
+
  /* Constructor */
+
  public VOAdministrationService() throws ResourceContextException, ResourceException {
+
  this.credentialsListener = new MultipleCredentialsListener();
+
  DelegationLocalInterface.registerCredentialsListener(this.credentialsListener);
+
  }
+
 
+
At this point compile and deploy again your service and restart the container.
+
To test the configuration of your service you have to put credentials on MyProxy and set-up a credentials renewal task as described in  [[How To Configure Identities For DILIGENT Services]]
+
 
+
===Use delegated credentials to invoke services===
+
 
+
If the service '''operates in a single DL''' then you can get credentials from the listener using the getCredentials() method. As shown in the box below. These credentials can be used to authenticate invocations. E.g:
+
+
ExtendedGSSCredential creds = this.credentialsListener.getCredentials();
+
...
+
ConfigureSecurity.setSecurity(port, creds);
+
port.yourOperation();
+
...
+
+
If the service '''operates in multiple DLs''' then you can get credentials from the listener using the getCredentials(DLName) method. As you see the name of the DL must be passed to the listener in order to retrieve credentials related to a specific DL. As shown in the box below. E.g:
+
+
ExtendedGSSCredential dlOneCreds = this.credentialsListener.getCredentials(/diligent/ARTE/DL1);
+
...
+
ConfigureSecurity.setSecurity(port, dlOneCreds);
+
port.yourOperation();
+
...
+
 
+
==Use the GSISecureConversation delegation==
+
 
+
This section gives some hints about how to use the delegation mechanism built into the GSISecureConversation mechanism.
+
 
+
===Configure the service WSSD to ask client credentials delegation===
+
To use this delegation method you have to set <code>caller-identity</code> as run-as mode in the Web Service Security Descriptor (WSSD) of your service. This is described in details [http://www.globus.org/toolkit/docs/4.0/security/authzframe/security_descriptor.html#s-authzframe-secdesc-configRunas here].
+
 
+
===Retrieve delegated credentials on service side===
+
 
+
To retrieve delegated credentials on service side you can use the code:
+
 
+
<code>import org.globus.gsi.jaas.JaasGssUtil;
+
import org.globus.gsi.jaas.JaasSubject;
+
import org.ietf.jgss.GSSCredential;
+
 
+
....
+
GSSCredential cred = JaasGssUtil.getCredential(JaasSubject.getCurrentSubject());</code>
+
 
+
[[Image:Info.gif]] ''The client must explicitly allows to delegate credentials setting the <code>org.globus.axis.gsi.GSIConstants.GSIConstants.GSI_MODE</code> property in service stubs. To do this you can use the <code>org.diligentproject.dvos.authentication.util.ConfigureSecurity.setSecurity(...)</code> method of the dvos.authentication-api library.''
+
 
+
==Add Authorization==
+
 
+
===Create the VO-Handler configuration file===
+
 
+
In order to enforce authorization you have to create a mapping between service operations and logical operations. This mapping is keep in the <code>YourServiceHandler.properties</code> in the "etc" directory of your service. For an example see [[Media:YourServiceHandler.properties]]
+
 
+
===Modify WSSD to add VO-Handler===
+
 
+
The WSSD must be modified to enforce authorization using the VOAuthorizationHandler You have to replace the element
+
 
+
<authz value="none"/>
+
 
+
with following content:
+
 
+
<authz value=
+
"VOAuthorizationPDP:org.diligentproject.dvos.authorization.handler.VOAuthorizationPDP"/>
+
 
+
===Modify WSDD to set handler properties===
+
 
+
You have also to tells the VOAuthorization handler where to find the configuration file and the VOMS certificates to verify authorizations. To do this add following lines to your WSDD file:
+
 
+
<parameter name="VOAuthorizationPDP-VOAuthorizationHandlerFile"
+
  value="@config.dir@/YourServiceHandler.properties"/>
+
+
<parameter name="VOAuthorizationPDP-VOMSCertificateDirectory" value="/etc/grid-security/vomsdir/*"/>
+
 
+
Now the service part of the authorization is set up. Redeploy your service and restart the container.
+
  
==Access a service using authorization==
+
The gCF introduces the concept of SecurityManager to manage those scenarios and simplify security aspects management. Security managers keep track of credentials to use for outgoing calls in one or more concurrent threads.
 +
a client which obtains credentials hands them over to the manager where may later find them. 
 +
Security managers are transparent in an insecure context
 +
Implementations of the interfaces above ought to implement the method isSecurityEnabled() to discriminate secure from insecure contexts.
  
In this step you'll try to access the deployed service with a client using authentication and authorization First of all try to contact your service using an authenticated client and a plain proxy, you should get following Axis fault:
+
GCF provides a basic and an advanced implementation of the SecurityManager interface that cover the three most common scenarios described before
 +
Moreover the ServiceContext is a wrapper of the SecurityManager
  
org.globus.wsrf.impl.security.authorization.exceptions.AuthorizationException:
+
====SimpleSecurityManager based service====
... is not authorized to use operation: ... on this service
+
If your Service doesn't use credentials or propagate caller credentials: you'll probably need default GCUBESimpleSecurityManager so you have nothing to do. The GCUBESimpleSecurityManager is the default SecurityManager. It allows service in acting in a secure infrastructure, if it doesn't need creds at all or need to act on behalf of a caller. The SecurityManager is able to propagate caller credential from the invocation to the place where they're needed. Here's a simple example where myService should contact another service on behalf of the caller:
 +
<source lang="java5">
 +
// Retrieving caller creds
 +
SecurityManager.useCredentials(SecurityManager.getCallerCredentials)‏
 +
// Invoke target service using its stubs and prepareCall
 +
GcubeScopeManger.setScope(GcubeScope)‏
 +
GcubeScopeManger.prepareCall(PT, “ServiceName”, “ServiceClass”)‏
 +
// SetSecurity
 +
SecurityManager.setAuthMethod(AuthMethod.GSI_CONV)
 +
SecurityManager.setSecurity(PT, GCUBESecurityManger.AuthMode.INTEGRITY, GCUBESecurityManger.Delegation.DelegationMode.FULL)‏
 +
</source>
  
To access the service with authroization you need to use a certificate containing a VOMS role entitled to perform operation invoked.
+
====ServiceSecurityManager based service====
 +
If your service needs service credentials you need to implement GCUBEServiceSecurityManager, able to manage caller and service credentials.
 +
The ServiceSecurityManager allows service in acting in a secure infrastructure  if it needs service creds and/or need to act on behalf of a caller
 +
This SecurityManager is able to use its own credentials or propagate caller credential from the invocation to the place where they're needed. By correctly setting the jndi file of myService, gCF is able to provide a advanced implementation of the interface you desire. A list of the provided ServiceSecurityManagers is in the [[Security Plugins Table]].
  
==Extend DILIGENT authorization==
+
====Security vs Scope====
 +
gCF has completely decoupled security from scope. In Diligent, we need to extract scope information from the proxy certificate. For this reason, it contained just one privilege among the groups it belongs to in VOMS.In gCube, we have a complete scope management independent from security.
 +
I.e.: RI can be shared in different scopes and manage security aspects with one only set of credential.
  
===Check for Authorization using the VOQuery API library===
+
===Overview of the interaction between myService, Delegation and CredentialsRenewal services===
 +
The gCube security model exploits the capabilities of a number of actors:
 +
* GCUBEServiceContext as manager of the RI and as GCUBEServiceSecurity Manager;
 +
* GHNContext as orchestrator of the internal events mechanism;
 +
* SecurityContext and its main default implementation, DefaultGHNServerSecurityContext, which provides the default container credentials and the default container security manager.
 +
Most of the details of this interaction are hidden to the gCube developer. To interact with these mechanisms, the developers should:
 +
* Configure the container security features ([[GHN Security Configuration]])
 +
* Configure the service security features if required: these configurations overrides the default container configuration for a single service [[GHN Security Configuration]]
  
===Define new authorization handlers===
+
If your service implements GCUBEServiceSecurityManger, at the end of these steps, the rest will be done for you automatically.
  
  
 
[[Category:Security]]
 
[[Category:Security]]

Latest revision as of 10:27, 24 October 2011

Access a service using authentication

In this step you'll try to access your service with a client using authentication. This step assumes the service has been deployed in a container able to host secure services. The Configure gContainer security page describes steps needed to set-up a secured gContainer.

First of all try to contact your service using an unauthenticated client, you should get following Axis fault:

... GSI Secure Conversation authentication required for
"{http://yournamespaces/namespaces/..." operation.

This means that the GSI Secure Conversation mechanism is required to invoke the service. To enable it, follow those steps.

Set credentials on service stubs

PortType PT = new ServiceAddressingLocator().gePortTypePort(epr);
//  PORTTYPE getProxy(PORTTYPE portTypeStub, GCUBEScopeManager scopeManager, GCUBESecurityManager ... securityManager)‏
PT = GCUBERemotePortTypeContext.getProxy(PT, scopeManager, serviceContext);

Don't forget to add the client-config.wsdd file in the directory where you run the client. Alternatively, you can add the $GLOBUS_LOCATION as the first entry of your classpath. Then you should be able to contact your service using your credentials.

Provide your service with credentials

After the previous steps, your service can authenticate itself in outcoming requests towards other services. To provide credentials to your service you have to configure the jndi file of your service. This allows your service to interact with the co-hosted instance of gCube Delegation service and a gCube CredentialsRenewal service available in your service's scope (as described in following section)

Which kind of security needs your service? Understand the semantic of your service

Typically a GCUBEService can be of three types:

  1. Doesn't need credentials but runs in a secure infra
  2. Acts on behalf of a caller
  3. Autonomous and needs service credentials

The gCF introduces the concept of SecurityManager to manage those scenarios and simplify security aspects management. Security managers keep track of credentials to use for outgoing calls in one or more concurrent threads. a client which obtains credentials hands them over to the manager where may later find them. Security managers are transparent in an insecure context Implementations of the interfaces above ought to implement the method isSecurityEnabled() to discriminate secure from insecure contexts.

GCF provides a basic and an advanced implementation of the SecurityManager interface that cover the three most common scenarios described before Moreover the ServiceContext is a wrapper of the SecurityManager

SimpleSecurityManager based service

If your Service doesn't use credentials or propagate caller credentials: you'll probably need default GCUBESimpleSecurityManager so you have nothing to do. The GCUBESimpleSecurityManager is the default SecurityManager. It allows service in acting in a secure infrastructure, if it doesn't need creds at all or need to act on behalf of a caller. The SecurityManager is able to propagate caller credential from the invocation to the place where they're needed. Here's a simple example where myService should contact another service on behalf of the caller:

// Retrieving caller creds
SecurityManager.useCredentials(SecurityManager.getCallerCredentials)// Invoke target service using its stubs and prepareCall 
GcubeScopeManger.setScope(GcubeScope)‏
GcubeScopeManger.prepareCall(PT, “ServiceName”, “ServiceClass”)// SetSecurity
SecurityManager.setAuthMethod(AuthMethod.GSI_CONV)
SecurityManager.setSecurity(PT, GCUBESecurityManger.AuthMode.INTEGRITY, GCUBESecurityManger.Delegation.DelegationMode.FULL)

ServiceSecurityManager based service

If your service needs service credentials you need to implement GCUBEServiceSecurityManager, able to manage caller and service credentials. The ServiceSecurityManager allows service in acting in a secure infrastructure if it needs service creds and/or need to act on behalf of a caller This SecurityManager is able to use its own credentials or propagate caller credential from the invocation to the place where they're needed. By correctly setting the jndi file of myService, gCF is able to provide a advanced implementation of the interface you desire. A list of the provided ServiceSecurityManagers is in the Security Plugins Table.

Security vs Scope

gCF has completely decoupled security from scope. In Diligent, we need to extract scope information from the proxy certificate. For this reason, it contained just one privilege among the groups it belongs to in VOMS.In gCube, we have a complete scope management independent from security. I.e.: RI can be shared in different scopes and manage security aspects with one only set of credential.

Overview of the interaction between myService, Delegation and CredentialsRenewal services

The gCube security model exploits the capabilities of a number of actors:

  • GCUBEServiceContext as manager of the RI and as GCUBEServiceSecurity Manager;
  • GHNContext as orchestrator of the internal events mechanism;
  • SecurityContext and its main default implementation, DefaultGHNServerSecurityContext, which provides the default container credentials and the default container security manager.

Most of the details of this interaction are hidden to the gCube developer. To interact with these mechanisms, the developers should:

If your service implements GCUBEServiceSecurityManger, at the end of these steps, the rest will be done for you automatically.