Developing a customPasswordEncryption Provider
You can develop a customPasswordEncryption
provider to have custom
authorization decisions for Java™ Platform, Enterprise Edition
(J2EE) applications by implementing the
com.ibm.wsspi.security.crypto.CustomPasswordEncryption
interface that is provided
in the Liberty server.
About this task
customPasswordEncryption
provider consists of following three files:- The OSGi Bundle File, which contains the executable.
- The Feature Manifest File, which defines the user feature of the
customPasswordEncryption
provider. This file contains the location of the required bundles and attributes of the feature, and the extension manifest file if it is packaged. This information is consumed by the server run time. - The Extension Manifest File, which defines the required bundle files and implementation class
name of the
customPasswordEncryption
provider. This file is optional and required for supporting the command line utilities.
Procedure
-
Create an OSGi component that provides a service that implements the
com.ibm.wsspi.security.crypto.CustomPasswordEncryption
interface.The
CustomPasswordEncryption
interface defines three methods,decrypt
, which the Liberty server run time invokes to decrypt the string,encrypt
, which the Liberty server run time invokes to encrypt the string, andinitialize
, which is reserved for future use.The following example uses OSGi declarative services annotations:package com.mycompany.custom; import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.ConfigurationPolicy; import org.osgi.service.component.annotations.Deactivate; import org.osgi.service.component.annotations.Modified; import com.ibm.wsspi.security.crypto.CustomPasswordEncryption; import com.ibm.wsspi.security.crypto.EncryptedInfo; import com.ibm.wsspi.security.crypto.PasswordDecryptException; import com.ibm.wsspi.security.crypto.PasswordEncryptException; /** */ @Component(service = CustomPasswordEncryption.class, immediate = true, name = "com.mycompany.CustomPasswordEncryptionImpl", configurationPolicy = ConfigurationPolicy.OPTIONAL, property = { "someKey=someValue" }) public class CustomPasswordEncryptionImpl implements CustomPasswordEncryption { @Activate protected synchronized void activate(ComponentContext cc, Map<String, Object> props) { } @Modified protected synchronized void modify(Map<String, Object> props) { } @Deactivate protected void deactivate(ComponentContext cc) { } /** * The encrypt operation takes a UTF-8 encoded String in the form of a byte[]. * The byte[] is generated from String.getBytes("UTF-8"). An encrypted byte[] * is returned from the implementation in the EncryptedInfo object. * Additionally, a logically key alias is returned in EncryptedInfo so which * is passed back into the decrypt method to determine which key was used to * encrypt this password. The WebSphere Application Server runtime has no * knowledge of the algorithm or key used to encrypt the data. * * @param decrypted_bytes * @return com.ibm.wsspi.security.crypto.EncryptedInfo * @throws com.ibm.wsspi.security.crypto.PasswordEncryptException **/ @Override public EncryptedInfo encrypt(byte[] input) throws PasswordEncryptException { byte[] output = null; String key = null; try { : <do some encryption> : return new EncryptedInfo(output, key); } catch (Exception e) { throw new PasswordEncryptException("Exception is caught", e); } } /** * The decrypt operation takes the EncryptedInfo object containing a byte[] * and the logical key alias and converts it to the decrypted byte[]. The * WebSphere Application Server runtime will convert the byte[] to a String * using new String (byte[], "UTF-8"); * * @param info * @return byte[] * @throws PasswordEncryptException * @throws com.ibm.wsspi.security.crypto.PasswordDecryptException **/ @Override public byte[] decrypt(EncryptedInfo info) throws PasswordDecryptException { byte[] input = info.getEncryptedBytes(); String key = info.getKeyAlias(); byte[] output = null; try { : <do some decryption> : return output; } catch (Exception e) { throw new PasswordEncryptException("Exception is caught", e); } } /** * This is reserved for future use and is currently not called by the * WebSphere Application Server runtime. * * @param initialization_data **/ @SuppressWarnings("rawtypes") @Override public void initialize(Map initialization_data) {} }
-
Package the component into an OSGi bundle that is part of your user feature. Make sure that the
bundle includes the OSGi service manifest.
The following example shows the contents of OSGi service manifest:
<?xml version="1.0" encoding="UTF-8"?> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="com.mycompany.custom.CustomPasswordEncryptionImpl" configuration-policy="optional" immediate="true" activate="activate" deactivate="deactivate" modified="modify"> <implementation class="com.mycompany.custom.CusomPasswordEncryptionImpl"/> <service> <provide interface="com.ibm.wsspi.security.crypto.CustomPasswordEncryption"/> </service> <property name="<someKey>" type="String" value="<someValue>"/> </scr:component>
-
Ensure that your feature manifest file includes the OSGi subsystem content with
start-phase:="SERVICE_EARLY"
. If the optional step is completed, then the location of the extension manifest file is in theSubsystem-Content
header.For example:Manifest-Version: 1.0 IBM-Feature-Version: 2 IBM-ShortName: customPasswordEncryption-1.0 Subsystem-Type: osgi.subsystem.feature Subsystem-Version: 1.0.0 Subsystem-ManifestVersion: 1.0 Subsystem-SymbolicName: customPasswordEncryption-1.0;visibility:=public Subsystem-Content: com.mycompany.custom; version="[1,1.0.100)"; start-phase:="SERVICE_EARLY", customEncryption.jar; type=file; location:="bin/tools/extensions/ws-customPasswordEncryption/customEncryption.jar" Subsystem-Description: MyCompany custom password encryption
-
After the feature is installed into the user product extension location, configure the
server.xml file with the feature name.
<featureManager> ... <feature>usr:customPasswordEncryption-1.0</feature> </featureManager>
To verify that the installation was successful for the server runtime environment, verify that CWWKS1850I message is logged in the message.log file.
-
Optional: Create the extension manifest file, which is required to plug in the
customPasswordEncryption
provider to the command line utilities such asSecurityUtility
. The extension manifest file is a JAR file, which contains the MANIFEST.MF file. The required headers of the extension manifest are:Require-Bundle
: Defines the list of bundles, which need to be loaded. The format is the same as the OSGi bundle manifest file.IBM-ImplementationClass
: Defines the implementation class, which implements thecom.ibm.wsspi.security.crypto.CustomPasswordEncryption
interface.
The following is an example MANIFEST.MF file
Require-Bundle: com.mycompany.custom; version="[1,1.0.100)"; location="usr/extension/lib" IBM-ImplementationClass: com.mycompany.custom.CusomPasswordEncryptionImpl
Use the jar command to package the extension manifest file. For example:jar cfm customEncryption.jar MANIFEST.MF
Place the JAR file in wlp/bin/tools/extensions/ws-customPasswordEncryption. Make sure that the location of the extension manifest file is in the
Subsystem-Content
header section of the feature manifest file.These files need to be in specific directories. The following depicts the relationship of the files: -
Optional: If step 5 is completed, then you can verify that the installation was successful by
using the following command line utilities command
wlp/bin/securityUtility encode --listCustom
The expected output is the information of thecustomPasswordEncryption
. For Example:[{"name":"custom","featurename":"usr:customPasswordEncryption-1.0","description":"MyCompany custom password encryption"}]
Make sure that all of the required files exist, and the contents of the files are accurate.