Protection of web services with an X.509 token
Liberty supports the Oasis Web Services Security X.509 Certificate Token Profile 1.1. An X.509 token can be used to provide message integrity and confidentiality by signing and encrypting messages.
WS-Security policy
To protect an XML message with an X.509 token, a contract that is specified in a Web Services Description Language (WSDL) must be created first. The web service must have a WS-Security policy included in the WSDL file. The WS-Security policy can contain AsymmetricBinding or SymmetricBinding assertions.
<sp:X509Token sp:IncludeToken=
"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssX509V3Token10 />
</wsp:Policy>
</sp:X509Token>
- The initiator X509Token is used for message signature from the requester to the provider and message encryption from the provider to the requester.
- The recipient X509Token is used for message signature from the provider to the requester and message encryption from the requester to the provider.
* | Initiator token | Recipient token |
---|---|---|
request out (requester) | sign | encrypt |
request in (provider) | verify signature | decrypt |
response out (provider) | encrypt | sign |
response in (requester) | decrypt | verify signature |
In a SymmetricBinding assertion, a secret key or ephemeral key that is protected for an X.509 token is shared by both the initiator and the recipient. The key is used for both encryption and decryption.
<wsp:Policy wsu:Id="SampleAsymmetricX509TokensPolicy">
<wsp:ExactlyOne>
<wsp:All>
<sp:AsymmetricBinding>
<wsp:Policy>
<sp:InitiatorToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken=
"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssX509V3Token10 />
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:InitiatorToken>
<sp:RecipientToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken=
"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never">
<wsp:Policy>
<sp:WssX509V3Token10 />
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:RecipientToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic128 />
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Strict />
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp />
<sp:ProtectTokens />
<sp:OnlySignEntireHeadersAndBody />
</wsp:Policy>
</sp:AsymmetricBinding>
<sp:SignedParts>
<sp:Body />
</sp:SignedParts>
<sp:EncryptedParts>
<sp:Body />
</sp:EncryptedParts>
<sp:Wss10>
<wsp:Policy>
<sp:MustSupportRefKeyIdentifier />
</wsp:Policy>
</sp:Wss10>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="SampleSymmetricX509TokensPolicy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SymmetricBinding>
<wsp:Policy>
<sp:ProtectionToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken=
"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never">
<wsp:Policy>
<sp:WssX509V3Token11 />
<sp:RequireThumbprintReference />
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:ProtectionToken>
<sp:Layout>
<wsp:Policy>
<sp:Lax />
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp />
<sp:OnlySignEntireHeadersAndBody />
<sp:SignBeforeEncrypting />
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic128 />
</wsp:Policy>
</sp:AlgorithmSuite>
</wsp:Policy>
</sp:SymmetricBinding>
<sp:EncryptedParts>
<sp:Body />
</sp:EncryptedParts>
<sp:SignedParts>
<sp:Body />
</sp:SignedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
Token reference and token inclusion
A token assertion can carry an sp:IncludeToken attribute that requires that the token is included in the message. Several token assertions support mechanisms for referencing tokens in addition to direct references. If a token assertion contains multiple reference assertions, then the references to that token are required to contain all the specified reference types. For example, if a token assertion carries an sp:IncludeToken attribute with a value of ../Always and that token assertion also contains a nested sp:RequireIssuerSerialReference assertion, then the token must be included twice in the message. While such combinations are not errors, they are best avoided for efficiency reasons.
The IncludeToken assertion is enforced in Liberty, but is ignored in the WS-Security runtime environment of WebSphere Application Server traditional.
- KeyIdentifier: <sp:RequireKeyIdentifierReference... />
- IssuerSerial: <sp:RequireIssuerSerialReference ... />
- Thumbprint: <sp:RequireThumbprintReference ... />
These references are used when you generate an X.509 token on the client/generator side, and are not enforced on the server/consumer side.
Runtime configuration
The WS-Security feature run time in Liberty provides more configuration options for message protection with an X.509 token than are covered by the WS-Security policy. The runtime configuration is defined in the server.xml file. The runtime configuration includes cryptographic properties such as signatureProperties and encryptionProperties, key, and keystores.
<wsSecurityClient id="default"
ws-security.callback-handler="com.ibm.ws.wssecurity.example.cbh.KeyPasswordCallbackHandler">
<signatureProperties org.apache.ws.security.crypto.merlin.keystore.type="jks"
org.apache.ws.security.crypto.merlin.keystore.password="LibertyX509Client"
org.apache.ws.security.crypto.merlin.keystore.alias="x509ClientDefault"
org.apache.ws.security.crypto.merlin.file="${server.config.dir}/x509ClientDefault.jks" />
<encryptionProperties org.apache.ws.security.crypto.merlin.keystore.type="jks"
org.apache.ws.security.crypto.merlin.keystore.password="LibertyXClient"
org.apache.ws.security.crypto.merlin.keystore.alias="x509DefaultCert"
org.apache.ws.security.crypto.merlin.file="${server.config.dir}/x509ClientDefault.jks" />
</wsSecurityClient>
<wsSecurityProvider id="default"
ws-security.callback-handler="com.ibm.ws.wssecurity.example.cbh.KeyPasswordCallbackHandler">
<signatureProperties org.apache.ws.security.crypto.merlin.keystore.type="jks"
org.apache.ws.security.crypto.merlin.keystore.password="LibertyX509Server"
org.apache.ws.security.crypto.merlin.keystore.alias="x509ServerDefault"
org.apache.ws.security.crypto.merlin.file="${server.config.dir}/x509ServerDefault.jks" />
<encryptionProperties org.apache.ws.security.crypto.merlin.keystore.type="jks"
org.apache.ws.security.crypto.merlin.keystore.password="LibertyX509Server"
org.apache.ws.security.crypto.merlin.keystore.alias="x509ServerDefault"
org.apache.ws.security.crypto.merlin.file="${server.config.dir}/x509ServerDefault.jks" />
</wsSecurityProvider>
In the runtime configuration, the signatureProperties and encryptionProperties properties are equivalent to the crypto properties in the WSS4J configuration. For more information, see WSS4J configuration. Many crypto properties have valid default values so there is no need to specify them. But other properties, such as keystore and key related properties, must be specified.
For more information about these properties, see Web services security default configuration.
Keystore files, keys, and certificates
Message signature and encryption require the use of public certificates and private keys. These public certificates and private keys are stored in keystore files. Keystore files are required when you use X509Token assertions. The client-side keystore file contains the private key of the client, and a chain of certificates corresponding to the public key of the server. The server-side keystore file contains the private key of the server, and a chain of certificates corresponding to the public key of the client.
- AsymmetricBinding assertion
The key that is specified by the signatureProperties property is used as the private key for signing the outbound message, and is also used for decrypting the inbound message.
The key that is specified by the encryptionProperties property is used as the public key for encrypting the outbound message, and is also used for verifying the signature in the inbound message.
- SymmetricBinding assertion
The key that is specified by the encryptionProperties properties is used, while the signatureProperties property is ignored.
Private key password CallbackHandler
To access a private key in a keystore, you must know two different passwords. One password is for the keystore where the private key is stored. The other password is for the private key itself. While the password for the keystore is specified in one of the crypto properties, either signatureProperties or encryptionProperties, the CallbackHandler class is normally used by WS-Security to access the private key in a keystore. In Liberty, this CallbackHandler class must be packaged as a Liberty feature and its class name that is specified as the value for the ws-security.callback-handler custom property in the security.xml.
This CallbackHandler class is required by WS-Security to access the private key in a keystore.
For more information about the password CallbackHandler class, see Developing a password callback handler for WS-Security.If the CallbackHandler class does not provide the private key password, the ws-security runtime first tries the CallbackHandler so it must be provided, then the password that is specified in the crypto properties is used as the default password for the private key. This property is configured as org.apache.ws.security.crypto.merlin.keystore.private.password.
Because only one ws-security.callback-handler custom property is supported in each of the wsSecurityClient and wsSecurityProvider sections of the security.xml file, a single password callback handler must support all of the required passwords for each application type (client or server) that use the default. All provider applications must use the default password callback handler. Client applications can override the default callback handler by specifying the ws-security.callback-handler custom property on the request context for the web service invocation of the client.
If you need to provide passwords for an X.509 private key and a UsernameToken for a single web service invocation, you cannot provide separate callback handlers for each use. In this case, you must implement a single callback handler that handles both kinds of passwords. As illustrated in the previous example, you must use the WSPasswordCallback.getUsage() method to determine which kind of password is returned. See the WSPasswordCallback API documentation for the supported usage codes http://ws.apache.org/wss4j/apidocs/org/apache/wss4j/common/ext/WSPasswordCallback.html.
Certificate revocation list
A certificate revocation list (CRL) is a list of serial numbers for certificates that are revoked. A CRL can be a stand-alone file or it can be packaged in a PKCS#7 wrapper. You can use a CRL with a truststore to control access to a service.
- Within the wsSecurityProvider or wsSecurityClient element, add
the following
property:
ws-security.enableRevocation="true"
- Within the signatureProperties element, add the following property and set the
value to a CRL
file:
org.apache.ws.security.crypto.merlin.x509crl.file
<wsSecurityProvider id="default"
ws-security.callback-handler="com.acme.example.cbh.CommonPasswordCallback"
ws-security.signature.username="x509ServerDefault"
ws-security.enableRevocation="true">
<signatureProperties
org.apache.ws.security.crypto.merlin.keystore.type="jks"
org.apache.ws.security.crypto.merlin.keystore.password="LibertyX509Server"
org.apache.ws.security.crypto.merlin.keystore.alias="x509ServerDefault"
org.apache.ws.security.crypto.merlin.file="${server.config.dir}/x509ServerDefault.ks"
org.apache.ws.security.crypto.merlin.truststore.password="LibertyX509Server"
org.apache.ws.security.crypto.merlin.truststore.file="${server.config.dir}/x509DefaultServer.ks"
org.apache.ws.security.crypto.merlin.x509crl.file="${server.config.dir}/revokedCerts.crl"/>
</wsSecurityProvider>