OX as a Service Provisioning using SOAP: Difference between revisions

From Open-Xchange
 
(74 intermediate revisions by 4 users not shown)
Line 1: Line 1:
= Tutorial: Provision OX as a Service using SOAP =
= Tutorial: Provision OX as a Service using SOAP =


== Overview ==
[[OX_as_a_Service_Guide|OX as a Service]] is using the same code everybody can download and install using our
various guides. Since it is a hosted service using a reseller model, the provisioning api is using the [[Reseller_Bundle|Reseller Bundle]]
to extend the usual two administrative layers by an additional one.
Open-Xchange does also not contain a mail server in general, but requires one in order to act like a mail client. OX as a Service
is using [http://dovecot.org Dovecot] as mail server and thus extends the usual Open-Xchange provisioning capabilities by mechanisms
to manage some email specific settings.


== Open-Xchange concept of Contexts ==
== Open-Xchange concept of Contexts ==
Line 38: Line 29:
* add, remove and configure contexts
* add, remove and configure contexts


However, it can '''NOT''' add or remove users and groups, nor any other data within a context!
and change parameters like add/remove domains, change per context filesystem quota, etc.


Instead, it can change parameters like add/remove domains, change per context filesystem quota, etc.
Depending on the OX configuration, it is not able to add or remove users and groups, nor any other data within a context!


=== Context admin ===
=== Context admin ===


The context admin is like an ordinary Open-Xchange user, except that it can add, remove and edit
The context admin is like an ordinary Open-Xchange user, except that it can add, remove and edit
users and groups within Open-Xchange.
users and groups within Open-Xchange using the provisioning API.
In addition, it inherits shared data of users, that are deleted.
In addition, it inherits shared data of users, that are deleted.
'''In OX as a Service, however, the context admin cannot read, send or receive mail.'''


== OX as a Service concept of provisioning ==
== OX as a Service concept of provisioning ==
Line 56: Line 48:


# root level, usually we call that oxadminmaster
# root level, usually we call that oxadminmaster
# subadmin level
# subadmin level / brand level
# context level
# context level


root and context level don't change, except that context level can be [[Reseller_Bundle#Restrictions|restricted]].
root and context level don't change, except that context level can be [[Reseller_Bundle#Restrictions|restricted]].


The subadmin account can only add, remove or configure contexts. As well as the root account, it can NOT add, remove
The subadmin account can only add, remove or configure contexts. Depending on the configuration of the
and configure users within contexts. Contexts created by a subadmin account can not be seen by other subadmin accounts.
OX as a Service tenant, it can or can NOT add, remove and configure users within contexts.
Contexts created by a subadmin account can not be seen by other subadmin accounts.
 
=== What is a brand? ===
 
A brand is a customers subadmin login to the OXaaS SOAP provisioning API.


== OX as a Service specifics ==
== OX as a Service specifics ==


=== Shared domains vs ordinary domains ===
=== Shared domains, explicit domains and ordinary domains ===
 
==== Ordinary domains ====


In order to create a user in Open-Xchange, you have to set an email address for that user.
In order to create a user in Open-Xchange, you have to set an email address for that user.
Line 72: Line 71:
if that domain does not already exists and is owned by a different context.
if that domain does not already exists and is owned by a different context.


If you want to share domains between multiple contexts, you have to use shared domains.
==== Shared domains ====
 
If you want to share domains between all contexts, you have to use shared domains.
Shared domains must be created in advance using the <tt>createSharedDomain</tt> method (see [[#OXaaS_specific_methods|OXaaS specific methods]])
Shared domains must be created in advance using the <tt>createSharedDomain</tt> method (see [[#OXaaS_specific_methods|OXaaS specific methods]])
or using the [https://documentation.open-xchange.com/components/cloudplugins/1.9.1/#tag/Shared-Domains REST API] (needs recent version).
==== Explicit domains ====
Recent versions support another type of domain called explicit domains. These domains must be explicitly added to contexts using the [https://documentation.open-xchange.com/components/cloudplugins/1.9.1/#tag/Explicit-Domains REST API] (needs recent version). You can add the same explicit domain to one or multiple contexts. If a context already contains an ordinary domain of the same name, it will be transformed into an explicit domain.
Note that the explicit domain feature is not available by default, it must be activated for each customer, individually.


You can use the <tt>existsMailAlias</tt> method to check for the existence of an alias before you create it.
You can use the <tt>existsMailAlias</tt> method to check for the existence of an alias before you create it.
Line 81: Line 89:
If the feature is enabled in your contract, you can create catchall mail aliases bound to users
If the feature is enabled in your contract, you can create catchall mail aliases bound to users
within contexts.
within contexts.
=== User permissions ===
See [[OX_as_a_Service_Provisioning_using_SOAP#Set_OXaaS_permissions|OXaaS permission]] description below.
=== User name/login uniqueness ===
Due to the architecture of OXaaS, a login/username must be unique across all created contexts. That means it is not
possible to create two "oxadmin" accounts. This limitation applies per brand.
=== Display name uniqueness ===
In contrary to the login/name of users, display names must only be unique within each context.
That is because it is used e.g. in the shared folder list of e.g. calendar, drive, contacts in OX.
Also it is used as folder name when mounting OX via WEBDAV.
It is no problem, however, to have one "Steve Smith" in one context, and another "Steve Smith” in another context.
=== No email for "oxadmin" ===
The architecture of OX as a Service does not allow the context admin to have email.


== Provisioning ==
== Provisioning ==
=== OXaaS specific methods ===
==== SOAP API ====
The following SOAP methods are specific to OXaaS and are NOT part of the general Open-Xchange provisioning API.
{| border="1" class="wikitable"
|+ OXaaS specific SOAP calls and its authentication requirements
! Method
! Functionality
! Authentication
|-
! getQuotaUsage
| get the overall mail quota usage of all users within the given context
| Subadmin
|-
! createSharedDomain
| create a shared domain
| Subadmin
|-
! existsLogin
| check whether user login already exists. Note: a users login must be unique within all users for your subadmin account and NOT only per context!
| Subadmin
|-
! existsMailAlias
| check whether given mail alias already exists
| Subadmin
|-
! createDomainCatchall
| create a domain catchall
| Subadmin
|-
! getQuotaUsagePerUser
| get mail quota usage of the individual user within the given context
| Subadmin
|-
! listDomainCatchalls
| list all existing domain catchalls
| Subadmin
|-
! setMailQuota
| set the mail quota of the individual user within the context
| Context Admin
|-
! deleteDomainCatchall
| delete the given domain catchall
| Subadmin
|-
! getPermissions
| list given users permissions
| Subadmin
|-
! enablePermissions
| enable provided permissions for given user
| Subadmin
|-
! disablePermissions
| enable provided permissions for given user
| Subadmin
|-
! setExpiryDate
| store expiry date for the given user
| Context Admin
|-
! getExpiryDate
| get expiry date stored for user
| Context Admin
|-
! deleteExpiryDate
| delete the expiry date stored in the given user
| Context Admin
|-
! getExpiredUsers
| retrieve list of expired users
| Subadmin
|-
! getMailQuota
| get the mail quota of the individual user within the context
| Subadmin
|-
! setPasswordHash
| directly store provided pwHash into userPassword attribute of matching ldap entry. Note: Input will be validated against valid mechanisms.
| Context Admin
|}
The WSDL source file for these methods contain documentation for each of the calls and parameters.
You can download it here: http://software.open-xchange.com/products/appsuite/doc/oxasservice/OXaaSService.wsdl
'''Note that the mail quota usage and max values are the combined values of drive and mail quota in case the system has [https://documentation.open-xchange.com/latest/middleware/miscellaneous/quota.html#unified-quota unified quota] enabled.'''
==== REST API ====
There's a growing number of REST APIs to access OXaaS, see https://documentation.open-xchange.com/, section ''Cloud Plugins API''.
=== OX Core Provisioning API ===
The core provisioning API consists of four namespaces:
# Context management
# User management
# Group management
# Resource management
Some of these namespaces share the same data structures such as <tt>Credentials</tt>, <tt>Context</tt> and <tt>User</tt>.
[[File:provisioning-core.png|1000 px]]


=== Reference implementation ===
=== Reference implementation ===


The reference implementation of the European OX as a Service system can be found in the {{APSPackage|name=OX as a Service}} APS package
The reference implementation of the European OX as a Service system can be found in the {{APSPackage|name=OX as a Service}} APS package
for [http://www.parallels.com/de/products/automation/ Parallels Automation].
for [http://www.odin.com/products/automation/ Odin Service Automation].


=== Workflow ===
=== Workflow ===
Line 93: Line 230:
==== Subadmin credentials ====
==== Subadmin credentials ====


The first requirement is to get subadmin credentials for your company. Please follow the steps
The first requirement is to get subadmin credentials for your company.
[[OX_as_a_Service_Guide#How_to_become_a_customer.3F|documented here]] to get such an account.


Together with the login and password you will also retrieve the provisioning URL to be used by
Together with the login and password you will also retrieve the provisioning URL to be used by
Line 114: Line 250:
; https://hostname/webservices/OXResellerResourceService?wsdl: Resource management
; https://hostname/webservices/OXResellerResourceService?wsdl: Resource management


==== SOAP API documentation ====
The general SOAP API documentation can be found at this URL:
http://software.open-xchange.com/products/appsuite/doc/SOAP/admin/OX-Admin-SOAP.html
That document contains links to the Javadoc documentation for the RMI api, but
that is more or less the same as the SOAP API.


In addition, there's the general, non OXaaS specific [[Open-Xchange_Provisioning_using_SOAP|wiki page]].


==== Create a context ====
==== Create a context ====
Line 126: Line 270:
; name: name of the context
; name: name of the context
; quota: file quota in MB for that context ('''Note:''' that is file, not mail!)
; quota: file quota in MB for that context ('''Note:''' that is file, not mail!)
; brandtaxonomy: must be set to the login of your subadmin account, see below
; taxonomy: must be set to the login of your subadmin account, see below


'''Important:''' In OXaaS, the name of the context must always start with your subadmin login with an underscore appended. E.g. when
'''Important:''' In OXaaS, the name of the context must always start with your subadmin login with an underscore appended. E.g. when
Line 133: Line 277:
Optional settings
Optional settings


; framecolor: io.ox/dynamic-theme//frameColor
; mainColor: io.ox/dynamic-theme//mainColor
; iconcolor: io.ox/dynamic-theme//iconColor
; linkColor: io.ox/dynamic-theme//linkColor
; selectioncolor: io.ox/dynamic-theme//selectionColor
; for further theme parameters, check https://documentation.open-xchange.com/latest/ui/theming/dynamic-theming.html
; logowidth: io.ox/dynamic-theme//logoWidth
; about dialogue: com.openexchange.appsuite.servercontact, see below
; logourl: io.ox/dynamic-theme//logoURL
 
; logouturl: io.ox/core//customLocations/logout, see [[OX_as_a_Service_Guide#Branding_.2F_Theming|this section]] for more information on the settings above
; id: A numerical id bound to the context. When you create a context, this id will be generated. You will need that later when you manage users. The id can be looked up via the context name.
; id: A numerical id bound to the context. When you create a context, this id will be generated. You will need that later when you manage users. The id can be looked up via the context name.


Line 188: Line 331:
                                                                     {
                                                                     {
                                                                       'value' => '#0000ff',
                                                                       'value' => '#0000ff',
                                                                       'key' => 'io.ox/dynamic-theme//selectionColor'
                                                                       'key' => 'io.ox/dynamic-theme//topbarHover'
                                                                     },
                                                                     },
                                                                     {
                                                                     {
                                                                       'value' => '#ff0000',
                                                                       'value' => '#ff0000',
                                                                       'key' => 'io.ox/dynamic-theme//frameColor'
                                                                       'key' => 'io.ox/dynamic-theme//linkColor'
                                                                     },
                                                                     },
                                                                     {
                                                                     {
                                                                       'value' => '#00ff00',
                                                                       'value' => '#00ff00',
                                                                       'key' => 'io.ox/dynamic-theme//iconColor'
                                                                       'key' => 'io.ox/dynamic-theme//mainColor'
                                                                     }
                                                                     },
                                                                  ]
                                                                    {
                                                                      'value' => 'true',
                                                                      'key' => 'com.openexchange.capability.dynamic-theme'
                                                                    },
                                                                    {
                                                                      'value' => 'My Example Org | <a href=\\"https://www.example.org\\" target=\\"_blank\\">www.example.org</a> | <a href=\\"https://example.org/help\\" target=\\"_blank\\">Contact us</a>',
                                                                      'key' => 'com.openexchange.appsuite.servercontact'
                                                                    }                                                                  ]
                                                       },
                                                       },
                                             'key' => 'config'
                                             'key' => 'config'
Line 278: Line 428:
Valid values for moduleaccess are:
Valid values for moduleaccess are:


* webmail_plus
* groupware_standard
* groupware_standard
* groupware_advanced
* groupware_advanced
Line 284: Line 435:
Other settings are not supported.
Other settings are not supported.


==== Workflow ====
===== userAttributes =====
 
It might be required you have to set some specific attributes per user like the Edition Type as
done by the OXaaS APS package.
 
There's a choice of 7 different edition types:
 
; webmail: bound to webmail_plus
; basic: bound to groupware_standard
; advanced: bound to groupware_advanced
; pro: bound to groupware_premium
; pro_m: bound to groupware_premium
; pro_l: bound to groupware_premium
; pro_xl: bound to groupware_premium
 
which can be set within each users oxaas_edition_type within a tree oxaas:
 
'userAttributes' => {
                    'entries' => {
                                  'key' => 'oxaas',
                                  'value' => {
                                            'entries' => {
                                                          'key' => 'oxaas_edition_type',
                                                          'value' => 'pro_l'
                                                          }
                                            }
                                }
                    }
 
 
see [[#Standalone_example:_createOXaaSUser|createuser example script]]


===== Create the user in Open-Xchange =====
===== Create the user in Open-Xchange =====
Line 306: Line 487:
Use the <code>OXaaSService->setMailQuota</code> call to set the mail quota for the user created above.
Use the <code>OXaaSService->setMailQuota</code> call to set the mail quota for the user created above.


=== OXaaS specific methods ===
===== Set OXaaS permissions =====
 
====== Explanation ======


The following SOAP methods are specific to OXaaS and are NOT part of the general Open-Xchange provisioning API.
The OXaaS permissions allow to enable or disable a certain set of features.
Currently, the following permissions are available:


{| border="1" class="wikitable"
{| border="1" class="wikitable"
|+ OXaaS specific SOAP calls and its authentication requirements
|+ OXaaS permissions
! Method
! Permission
! Functionality
! Description
! Authentication
|-
|-
! getQuotaUsage
! SEND
| get the overall mail quota usage of all users within the given context
| User is allowed to send mail
| Subadmin
|-
|-
! createSharedDomain
! RECEIVE
| create a shared domain
| User is allowed to receive mail
| Subadmin
|-
|-
! existsLogin
! MAILLOGIN
| check whether user login already exists. Note: a users login must be unique within all users for your subadmin account and NOT only per context!
| User can login using IMAP from external; webmail is not affected
| Subadmin
|-
|-
! existsMailAlias
! WEBLOGIN
| check whether given mail alias already exists
| User can login to OX webmail.
| Subadmin
|}
 
The permission names are case insensitive.
The WEBLOGIN permission is the same as the [http://software.open-xchange.com/products/appsuite/doc/RMI/admin-core/com/openexchange/admin/rmi/dataobjects/User.html#setMailenabled%28java.lang.Boolean%29 <tt>Mailenabled</tt>] permission in the user data of the Open-Xchange core api. The permission
OXaaS api provides another way to enable/disable it.
 
* Use the name and password of the context admin user of the context you created earlier and define
a Credentials object.
* Find the numerical id of the context e.g. in using <code>OXResellerContextService->getData(name="contextname")</code>
* Find the numerical id of the user either by using <code>OXResellerUserService->getData(name="username")</code> or use/store the return value of <code>OXResellerUserService->createByModuleAccessName</code>
 
Use one of <code>OXaaSService->enablePermissions</code>, <code>OXaaSService->disablePermissions</code> or <code>OXaaSService->getPermissions</code>
to change or retrieve permissions. Permissions must always be provided as an array of 1 or more permissions.
 
=== SOAP provisioning feature matrix ===
 
(WIP)
 
The table below shows what method(s) to use and what to set in order to configure the different feature sets.
 
The value in the row ''Module Access Name'' must be given as a parameter to <code>OXResellerUserService->changeByModuleAccessName</code>
or <code>OXResellerUserService->createByModuleAccessName</code>.
 
The values in the row ''Capabilities'' must be given as parameters to the <code>userAttributes</code> member of the <code>User</code> object that
should be changed and then passed to <code>OXResellerUserService->change</code> or <code>OXResellerUserService->createByModuleAccessName</code>.
 
'''Note: <code>OXResellerUserService->changeByModuleAccessName</code> does NOT change these capabilities!'''
 
{| border="1" class="wikitable"
|+ Provisioning Feature Matrix
! Feature
! Module Access Name
! Capabilities ''(mandatory values in bold, others are optional)''
|-
|-
! createDomainCatchall
! Web Mail
| create a domain catchall
| webmail_plus
| Subadmin
| <tt>com.openexchange.capability.drive = '''false'''</tt><br><tt>com.openexchange.capability.document_preview = '''false'''</tt><br><tt>com.openexchange.capability.spreadsheet = '''false'''</tt><br><tt>com.openexchange.capability.text = '''false'''</tt><br><tt>com.openexchange.capability.presenter = '''false'''</tt><br><tt>com.openexchange.capability.remote_presenter = '''false'''</tt><br><tt>com.openexchange.capability.guard = '''false'''</tt><br><tt>com.openexchange.capability.guard-mail = '''false'''</tt><br><tt>com.openexchange.capability.guard-drive = '''false'''</tt>
|-
|-
! getQuotaUsagePerUser
! Basic
| get mail quota usage of the individual user within the given context
| <tt>groupware_standard</tt>
| Subadmin
| <tt>com.openexchange.capability.drive = '''true'''</tt><br><tt>com.openexchange.capability.document_preview = true/false</tt><br><tt>com.openexchange.capability.spreadsheet = true/false</tt><br><tt>com.openexchange.capability.text = true/false</tt><br><tt>com.openexchange.capability.presenter = true/false</tt><br><tt>com.openexchange.capability.remote_presenter = true/false</tt><br><tt>com.openexchange.capability.guard = true/false</tt><br><tt>com.openexchange.capability.guard-mail = true/false</tt><br><tt>com.openexchange.capability.guard-drive = true/false</tt>
|-
|-
! listDomainCatchalls
! Advanced
| list all existing domain catchalls
| <tt>groupware_advanced</tt>
| Subadmin
| <tt>com.openexchange.capability.drive = '''true'''</tt><br><tt>com.openexchange.capability.document_preview = true/false</tt><br><tt>com.openexchange.capability.spreadsheet = true/false</tt><br><tt>com.openexchange.capability.text = true/false</tt><br><tt>com.openexchange.capability.presenter = true/false</tt><br><tt>com.openexchange.capability.remote_presenter = true/false</tt><br><tt>com.openexchange.capability.guard = true/false</tt><br><tt>com.openexchange.capability.guard-mail = true/false</tt><br><tt>com.openexchange.capability.guard-drive = true/false</tt>
|-
|-
! setMailQuota
! Pro
| set the mail quota of the individual user within the context
| <tt>groupware_premium</tt>
| Context Admin
| <tt>com.openexchange.capability.drive = '''true'''</tt><br><tt>com.openexchange.capability.document_preview = '''true'''</tt><br><tt>com.openexchange.capability.spreadsheet = '''true'''</tt><br><tt>com.openexchange.capability.text = '''true'''</tt><br><tt>com.openexchange.capability.presenter = '''true'''</tt><br><tt>com.openexchange.capability.remote_presenter = '''true'''</tt><br><tt>com.openexchange.capability.guard = true/false</tt><br><tt>com.openexchange.capability.guard-mail = true/false</tt><br><tt>com.openexchange.capability.guard-drive = true/false</tt>
|-
! deleteDomainCatchall
| delete the given domain catchall
| Subadmin
|}
|}


The WSDL source file for these methods contain documentation for each of the calls and parameters.
=== List of available capabilities (incomplete) ===
You can download it here: http://software.open-xchange.com/products/appsuite/doc/oxasservice/OXaaSService.wsdl
 
These features are controlled by the [[ConfigCascade]].
 
For drive and documents the following settings are responsible:
 
; OX Drive :
<tt>com.openexchange.capability.drive = true/false</tt>
 
; OX Docs :
<tt>com.openexchange.capability.document_preview = true/false</tt><br />
<tt>com.openexchange.capability.spreadsheet = true/false</tt><br />
<tt>com.openexchange.capability.text = true/false</tt><br />
<tt>com.openexchange.capability.presentation = true/false</tt><br />
<tt>com.openexchange.capability.remote_presenter = true/false</tt><br />
<tt>com.openexchange.capability.guard-docs = true/false</tt>
 
; OX Guard :
<tt>com.openexchange.capability.guard = true/false</tt><br />
<tt>com.openexchange.capability.guard-mail = true/false</tt><br />
<tt>com.openexchange.capability.guard-drive = true/false</tt><br />
 
Using [[OX_as_a_Service_Provisioning_using_SOAP#Standalone_example:_createOXaaSContext|this perl example]]:
 
 
e.g. this
 
      logouturl => {
              setting => "io.ox/core//customLocations/logout",
              value  => "logouturl"
      }
 
is setting the ConfigCascade setting <tt>io.ox/core//customLocations/logout</tt> to the string “logouturl"
 
  io.ox/core//customLocations/logout = "logouturl"
 
adding
 
      oxdrive => {
              setting => "com.openexchange.capability.drive",
              value  => "true"
      }
 
in that example would turn on drive.


== Code Examples ==
== Code Examples ==
Line 361: Line 611:


==== Generating the SOAP client ====
==== Generating the SOAP client ====
'''Note that the below instructions only work with Java version 8 and no later version'''


Since Open-Xchange is using [http://cxf.apache.org/ Apache CXF] for SOAP, we recommend to use the <tt>wsdl2java</tt>
Since Open-Xchange is using [http://cxf.apache.org/ Apache CXF] for SOAP, we recommend to use the <tt>wsdl2java</tt>
Line 378: Line 630:
mentioned [[#Subadmin_credentials|earlier]].
mentioned [[#Subadmin_credentials|earlier]].


Just cut&paste the shell script below into a file and run it using the <tt>bash</tt> shell.
Note: when running against a DEV container without valid SSL certs (e.g. self-signed SSL certs), it is required to add the servers cert into your java keystore first:
 
# Get the cert e.g. by <code>openssl s_client -connect my.oxaas.webservices.host.net:443</code> (the part between BEGIN CERTIFICATE and END CERTIFICATE) or by exporting from a web browser. Put it in a file named for example <code>my.oxaas.webservices.host.net.crt</code>.
# Import it in a custom TrustStore. Assign a password; in this example we assume "secret": <code>keytool -import -trustcacerts -alias my.oxaas.webservices.host.net -keystore my.oxaas.webservices.host.net.jks -file my.oxaas.webservices.host.net.crt -storetype JKS</code>
# Supply it to the JVM by patching the CXF wsdl2java script (e.g. <code>/opt/apache-cxf-3.1.14/bin/wsdl2java</code>) and add the following arguments: <code>-Djavax.net.ssl.trustStore=my.oxaas.webservices.host.net.jks -Djavax.net.ssl.trustStorePassword=secret -Djavax.net.ssl.trustStoreType=JKS</code>
 
Copy&paste the shell script below into a file and run it using the <tt>bash</tt> shell. <b>Warning:</b> the script assumes the CODEBASE target lives in its own dedicated ecplise project, and executes a <code>rm -rf $CODEBASE</code> for a clean start. For other usecases (shared eclipse project, etc), please adjust to your needs / be careful!


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
# 1. download apache-cxf tarball, extract it and "cd" into the directory, e.g.
# 1. download apache-cxf tarball, extract it and "cd" into the directory, e.g.
#    tar zxvpf apache-cxf-3.0.0-milestone1.tar.gz; cd apache-cxf-3.0.0-milestone1
#    tar zxvpf apache-cxf-3.1.10.tar.gz; cd apache-cxf-3.1.10
#    NOTE: cxf versions 3.0 do NOT work ootb with java-1.8!
# 2. change variables CODEBASE, JAVA_HOME and WSDLURL
# 2. change variables CODEBASE, JAVA_HOME and WSDLURL
# 3. run this script "bash oxaas-wsdl2java"
# 3. run this script "bash oxaas-wsdl2java"
export JAVA_HOME="/usr/lib/jvm/j2sdk1.7-oracle/"
export JAVA_HOME="/usr/lib/jvm/java-1.8.0-openjdk-amd64/"
CODEBASE="/home/oxgit/workspace/OXaaSJClient/src"
CODEBASE="/home/oxgit/workspace/OXaaSJClient/src"
WSDLURL="https://youroxaashost/webservices"
WSDLURL="https://youroxaashost/webservices"
Line 445: Line 704:
In the following example, the context creation and the user creation is separated into different
In the following example, the context creation and the user creation is separated into different
programs.
programs.
We assume, you have created the Java client stub(s) as documented above and have it in your
library path or eclipse project.


To summarize some essential requirements from the example below:
To summarize some essential requirements from the example below:
Line 454: Line 710:
* You must set the userAttribute <tt>taxonomy</tt> at least
* You must set the userAttribute <tt>taxonomy</tt> at least
* The context admin user must get the <tt>groupware_premium</tt> access permission
* The context admin user must get the <tt>groupware_premium</tt> access permission
===== Build / run instructions =====
====== Eclipse ======
We assume, you have created the Java client stub(s) as documented above and have it as a separate eclipse project. The individual clients given below are assumed to live in a different ecplise project which references the Java client stubs in their classpath.
====== Command Line ======
For maximum simplicity let's assume you use the source files given below without the <code>package</code> statement. Put them in an <code>examples/</code> subdirectory.
Let's assume furthermore you created the Java client stubs in a different directory, e.g. <code>codebase/</code>.
Change into that directory to compile all the Java stub files
cd codebase/
find . -name \*.java  | xargs javac
Back in the working directory where the source files given below are created, you can compile / run them like
cd ../examples/
javac -cp ../codebase MyContextClientExample.java
java -cp .:../codebase MyContextClientExample
====== SSL-related hints ======
When working against a dev machine with self-signed certs, the same certificate trust related options are required as explained above for the <code>wsdl2java</code> script (with the same TrustStore and password):
-Djavax.net.ssl.trustStore=my.oxaas.webservices.host.net.jks -Djavax.net.ssl.trustStorePassword=secret -Djavax.net.ssl.trustStoreType=JKS
It might be additionally helpful to enable SSL debug output: <code>-Djavax.net.debug=ssl</code>
As of now (2017-11) there is a flaw in the generated WSDL that it references HTTP SOAP addresses even when using HTTPS. This results in client programs trying to access the API via plain HTTP even after a successful SSL handshake and fetching the WSDL via HTTPS. This is bad as SOAP frames travel the network with credentials included in plain text.
A possible workaround for the time being is to forcefully rewrite the protocol part of the different port urls into https with something like:
After initializing the contextport using ...
<syntaxhighlight lang="java">
OXResellerContextServicePortType contextport = contextservice.getOXResellerContextServiceHttpSoap11Endpoint(); 
</syntaxhighlight>
... add the following code:
<syntaxhighlight lang="java">
// insert in your imports section:
// import javax.xml.ws.BindingProvider;
((BindingProvider)contextport).getRequestContext().put(
    BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
    ((String)((BindingProvider)contextport).getRequestContext()
        .get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY))
        .replaceAll("^http:", "https:"));
</syntaxhighlight>
Similar adjustments are required for <code>userport</code> and <code>oxaasport</code>, where they occur.


===== Context creation =====
===== Context creation =====
Line 522: Line 833:
         SOAPStringMap configEntries = new SOAPStringMap();
         SOAPStringMap configEntries = new SOAPStringMap();


         Entry selectionColor = new Entry();
         Entry topbarHover = new Entry();
         selectionColor.setKey("io.ox/dynamic-theme//selectionColor");
         topbarHover.setKey("io.ox/dynamic-theme//topbarHover");
         selectionColor.setValue("#0000ff");
         topbarHover.setValue("#0000ff");


         Entry frameColor = new Entry();
         Entry mainColor = new Entry();
         frameColor.setKey("io.ox/dynamic-theme//frameColor");
         mainColor.setKey("io.ox/dynamic-theme//mainColor");
         frameColor.setValue("#ff0000");
         mainColor.setValue("#ff0000");


         Entry iconColor = new Entry();
         Entry linkColor = new Entry();
         iconColor.setKey("io.ox/dynamic-theme//iconColor");
         linkColor.setKey("io.ox/dynamic-theme//linkColor");
         iconColor.setValue("#00ff00");
         linkColor.setValue("#00ff00");


         configEntries.getEntries().add(selectionColor);
        Entry dynThemeCapa = new Entry();
         configEntries.getEntries().add(frameColor);
        dynThemeCapa.setKey("com.openexchange.capability.dynamic-theme");
         configEntries.getEntries().add(iconColor);
        dynThemeCapa.setValue("true");
 
        configEntries.getEntries().add(topbarHover);
         configEntries.getEntries().add(mainColor);
         configEntries.getEntries().add(linkColor);
         configEntries.getEntries().add(dynThemeCapa);
         config.setValue(configEntries);
         config.setValue(configEntries);


Line 563: Line 879:


         try {
         try {
             ResellerContext ret = contextport.createModuleAccessByName(ctx, oxadmin, "groupware_premium", creds);
             ResellerContext ret = contextport.createModuleAccessByName(ctx, oxadmin, "groupware_premium", creds, null);
             System.out.println("created context with id=" + ret.getId());
             System.out.println("created context with id=" + ret.getId());


Line 617: Line 933:


<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
package com.openexchange.oxaas.myclient;
package com.openexchange.oxaas.myclient;


Line 640: Line 957:
import com.openexchange.oxaas.user.reseller.soap.dataobjects.ResellerContext;
import com.openexchange.oxaas.user.reseller.soap.dataobjects.ResellerContext;
import com.openexchange.oxaas.user.rmi.dataobjects.Credentials;
import com.openexchange.oxaas.user.rmi.dataobjects.Credentials;
import com.openexchange.oxaas.user.soap.dataobjects.Entry;
import com.openexchange.oxaas.user.soap.dataobjects.SOAPMapEntry;
import com.openexchange.oxaas.user.soap.dataobjects.SOAPStringMap;
import com.openexchange.oxaas.user.soap.dataobjects.SOAPStringMapMap;
import com.openexchange.oxaas.user.soap.dataobjects.User;
import com.openexchange.oxaas.user.soap.dataobjects.User;


/*
/*
Line 651: Line 971:
public class MyUserClientExample {
public class MyUserClientExample {


     private static final QName USER_SERVICE_NAME = new QName("http://soap.reseller.admin.openexchange.com", "OXResellerUserService");
     private static final QName USER_SERVICE_NAME   = new QName("http://soap.reseller.admin.openexchange.com", "OXResellerUserService");
     private static final QName CONTEXT_SERVICE_NAME = new QName("http://soap.reseller.admin.openexchange.com", "OXResellerContextService");
     private static final QName CONTEXT_SERVICE_NAME = new QName("http://soap.reseller.admin.openexchange.com", "OXResellerContextService");
     private static final QName OXAAS_SERVICE_NAME = new QName("http://soap.oxaas.admin.openexchange.com/", "OXaaSService");
     private static final QName OXAAS_SERVICE_NAME   = new QName("http://soap.oxaas.admin.openexchange.com/", "OXaaSService");


     public static void main(String[] args) {
     public static void main(String[] args) {
         final String subadminname = "mysubadmin";
         final String subadminname = "mysubadmin";
         final String subadminpw   = "secret";
         final String subadminpw = "secret";
         final String ctxadmname   = "oxadmin";
         final String ctxadmname = "oxadmin";
         final String ctxadmpw     = "secret";
         final String ctxadmpw = "secret";
         final String ctxname     = subadminname + "_myctx";
         final String ctxname = subadminname + "_myctx";
       
 
         Credentials creds = new Credentials();
         Credentials creds = new Credentials();
         ResellerContext ctx = new ResellerContext();
         ResellerContext ctx = new ResellerContext();
Line 671: Line 991:
         OXResellerContextServicePortType contextport = contextservice.getOXResellerContextServiceHttpSoap11Endpoint();
         OXResellerContextServicePortType contextport = contextservice.getOXResellerContextServiceHttpSoap11Endpoint();
         OXaaSService_Service oxaasservice = new OXaaSService_Service(OXaaSService_Service.WSDL_LOCATION, OXAAS_SERVICE_NAME);
         OXaaSService_Service oxaasservice = new OXaaSService_Service(OXaaSService_Service.WSDL_LOCATION, OXAAS_SERVICE_NAME);
         OXaaSService oxaasport = oxaasservice.getOXaaSServiceSOAP();
         OXaaSService oxaasport = oxaasservice.getOXaaSServiceSOAP();
       
 
       
         // We need to use the ResellerContextService SOAP client stub to retrieve the context id
         // We need to use the ResellerContextService SOAP client stub to retrieve the context id
         com.openexchange.oxaas.context.rmi.dataobjects.Credentials ctxCreds = new com.openexchange.oxaas.context.rmi.dataobjects.Credentials();
         com.openexchange.oxaas.context.rmi.dataobjects.Credentials ctxCreds = new com.openexchange.oxaas.context.rmi.dataobjects.Credentials();
Line 683: Line 1,002:
         creds.setLogin(ctxadmname);
         creds.setLogin(ctxadmname);
         creds.setPassword(ctxadmpw);
         creds.setPassword(ctxadmpw);
        final long unifiedQuotaMax = 1000l;


         final String userEmail = "auser@example.com";
         final String userEmail = "auser@example.com";
Line 695: Line 1,016:
         auser.setLanguage("en_US");
         auser.setLanguage("en_US");
         auser.setTimezone("Europe/Berlin");
         auser.setTimezone("Europe/Berlin");
        auser.setMaxQuota(unifiedQuotaMax);
        // enable unified quota (might be enabled globally, already, though)
        final Entry unifiedQuota = new Entry();
        unifiedQuota.setKey("com.openexchange.unifiedquota.enabled");
        unifiedQuota.setValue("true");
        final SOAPStringMap configEntries = new SOAPStringMap();
        configEntries.getEntries().add(unifiedQuota);
        final SOAPMapEntry config = new SOAPMapEntry();
        config.setKey("config");
        config.setValue(configEntries);
        final SOAPStringMapMap userattrs = new SOAPStringMapMap();
        userattrs.getEntries().add(config);
        auser.setUserAttributes(userattrs);


         try {
         try {
Line 704: Line 1,042:
             User ret = userport.createByModuleAccessName(ctx, auser, "groupware_premium", creds);
             User ret = userport.createByModuleAccessName(ctx, auser, "groupware_premium", creds);
             System.out.println("created user with id=" + ret.getId());
             System.out.println("created user with id=" + ret.getId());
           
 
             // set mail quota for that user using OXaaSService
             // set mail quota for that user using OXaaSService
             com.openexchange.oxaas.extra.Credentials oxaasCtxCreds = new com.openexchange.oxaas.extra.Credentials();
             com.openexchange.oxaas.extra.Credentials oxaasCtxCreds = new com.openexchange.oxaas.extra.Credentials();
             oxaasCtxCreds.setLogin(ctxadmname);
             oxaasCtxCreds.setLogin(ctxadmname);
             oxaasCtxCreds.setPassword(ctxadmpw);
             oxaasCtxCreds.setPassword(ctxadmpw);
             oxaasport.setMailQuota(ctxRet.getId(), ret.getId(), 1000l, oxaasCtxCreds);
             oxaasport.setMailQuota(ctxRet.getId(), ret.getId(), unifiedQuotaMax, oxaasCtxCreds);
           
 
             // check whether the login for the user has been created within my subadmin namespace
             // check whether the login for the user has been created within my subadmin namespace
             // NOTE: this check should be used beforehand usually: check whether login exists and then create it if not
             // NOTE: this check should be used beforehand usually: check whether login exists and then create it if not
Line 716: Line 1,054:
             oxaasAdminCreds.setLogin(subadminname);
             oxaasAdminCreds.setLogin(subadminname);
             oxaasAdminCreds.setPassword(subadminpw);
             oxaasAdminCreds.setPassword(subadminpw);
             if( oxaasport.existsLogin("auser", oxaasAdminCreds) ) {
             if (oxaasport.existsLogin("auser", oxaasAdminCreds)) {
                 System.out.println("all ok, user login has been created");
                 System.out.println("all ok, user login has been created");
             }
             }
           
 
             System.in.read();
             System.in.read();
           
 
             System.out.println("deleting created user again");
             System.out.println("deleting created user again");
             Delete del = new Delete();
             Delete del = new Delete();
Line 769: Line 1,107:


===== Email (alias) management =====
===== Email (alias) management =====
The next example shows how to manage email aliases and shared domains.
The essential information is:
* if you want to change the email address of a user, you have to add the new address to the list of aliases
* when you want to change individual settings of a user, only send the changed settings
<syntaxhighlight lang="java">
package com.openexchange.oxaas.myclient;
import java.util.List;
import javax.xml.namespace.QName;
import com.openexchange.oxaas.context.OXResellerContextService;
import com.openexchange.oxaas.context.OXResellerContextServicePortType;
import com.openexchange.oxaas.extra.CreateSharedDomainFaultException;
import com.openexchange.oxaas.extra.OXaaSService;
import com.openexchange.oxaas.extra.OXaaSService_Service;
import com.openexchange.oxaas.user.Change;
import com.openexchange.oxaas.user.DatabaseUpdateExceptionException;
import com.openexchange.oxaas.user.DuplicateExtensionExceptionException;
import com.openexchange.oxaas.user.InvalidCredentialsExceptionException;
import com.openexchange.oxaas.user.InvalidDataExceptionException;
import com.openexchange.oxaas.user.NoSuchContextExceptionException;
import com.openexchange.oxaas.user.NoSuchUserExceptionException;
import com.openexchange.oxaas.user.OXResellerUserService;
import com.openexchange.oxaas.user.OXResellerUserServicePortType;
import com.openexchange.oxaas.user.RemoteExceptionException;
import com.openexchange.oxaas.user.StorageExceptionException;
import com.openexchange.oxaas.user.reseller.soap.dataobjects.ResellerContext;
import com.openexchange.oxaas.user.rmi.dataobjects.Credentials;
import com.openexchange.oxaas.user.soap.dataobjects.User;
/*
* Example SOAP client for OXaaS OXResellerUserService
*
* Create users in a context
*
*/
public class OXaaSAliasManagement {
    private static final QName USER_SERVICE_NAME = new QName("http://soap.reseller.admin.openexchange.com", "OXResellerUserService");
    private static final QName CONTEXT_SERVICE_NAME = new QName("http://soap.reseller.admin.openexchange.com", "OXResellerContextService");
    private static final QName OXAAS_SERVICE_NAME = new QName("http://soap.oxaas.admin.openexchange.com/", "OXaaSService");
    public static void main(String[] args) {
        final String subadminname = "mysubadmin";
        final String subadminpw  = "secret";
        final String ctxadmname  = "oxadmin";
        final String ctxadmpw    = "secret";
        final String userlogin    = "auser";
        final String ctxname      = subadminname + "_myctx";
       
        Credentials creds = new Credentials();
        ResellerContext ctx = new ResellerContext();
        OXResellerUserService userservice = new OXResellerUserService(OXResellerUserService.WSDL_LOCATION, USER_SERVICE_NAME);
        OXResellerUserServicePortType userport = userservice.getOXResellerUserServiceHttpSoap12Endpoint();
        OXResellerContextService contextservice = new OXResellerContextService(OXResellerContextService.WSDL_LOCATION, CONTEXT_SERVICE_NAME);
        OXResellerContextServicePortType contextport = contextservice.getOXResellerContextServiceHttpSoap11Endpoint();
        OXaaSService_Service oxaasservice = new OXaaSService_Service(OXaaSService_Service.WSDL_LOCATION, OXAAS_SERVICE_NAME);
        OXaaSService oxaasport = oxaasservice.getOXaaSServiceSOAP(); 
       
       
        // We need to use the ResellerContextService SOAP client stub to retrieve the context id
        com.openexchange.oxaas.context.rmi.dataobjects.Credentials ctxCreds = new com.openexchange.oxaas.context.rmi.dataobjects.Credentials();
        com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext ctxCtx = new com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext();
        ctxCreds.setLogin(subadminname);
        ctxCreds.setPassword(subadminpw);
        ctxCtx.setName(ctxname);
        creds.setLogin(ctxadmname);
        creds.setPassword(ctxadmpw);
        try {
            // we only have the name of the context, so we need to retrieve its id, first using ResellerContextService
            com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext ctxRet = contextport.getData(ctxCtx, ctxCreds);
            ctx.setId(ctxRet.getId());
            /*
            * now we want to add an alias to the user "auser"
            */
            User auser = new User();
            auser.setName(userlogin);
            User ret = userport.getData(ctx, auser, creds);
            List<String> aliases = ret.getAliases();
            // list all mail aliases of that user
            System.out.println("User has the following alias(es):" + aliases);
            // now add another one
            aliases.add("sales@example.com");
            // we also want to add an alias within a shared domain
            com.openexchange.oxaas.extra.Credentials oxaasCtxCreds = new com.openexchange.oxaas.extra.Credentials();
            oxaasCtxCreds.setLogin(subadminname);
            oxaasCtxCreds.setPassword(subadminpw);
            /*
            * Note: we can run this method as often as we want, it will ONLY return an error in case we want to add a shared domain
            * that is already bound to another subadmin/customer
            */
            oxaasport.createSharedDomain("shared.net", oxaasCtxCreds);
            aliases.add("me@shared.net");
           
            // store changes
            // we need to created a clean user instance since we cannot just store back the returned user
            User changeduser = new User();
            changeduser.setId(ret.getId());
            changeduser.getAliases().addAll(aliases);
            Change change = new Change();
            change.setAuth(creds);
            change.setCtx(ctx);
            change.setUsrdata(changeduser);
            userport.change(change);
           
            // control the result
            ret = userport.getData(ctx, auser, creds);
            aliases = ret.getAliases();
            // list all mail aliases of that user
            System.out.println("User has the following alias(es):" + aliases);
           
            /*
            * now changing the users email address:
            * to do that, we have to do the following:
            * 1. add the new email address to the aliases, if not yet present
            * 2. change the email address in email1, defaultsenderaddress and primarymail
            *
            */
            String newaddress = "boss@mydomain.com"; // introduce another domain, not shared
            changeduser = new User();
            changeduser.setId(ret.getId());
            changeduser.setEmail1(newaddress);
            //reuse change from above
            change.setUsrdata(changeduser);
            try {
                // this will throw an error since the new address is not in the aliases
                userport.change(change);
            } catch (Exception e) {
                System.out.println("ERROR: " + e.getMessage());
            }
            // now add the new address to the aliases and try again
            aliases = ret.getAliases();
            aliases.add(newaddress);
            changeduser.getAliases().addAll(aliases);
            userport.change(change);
            // control the result
            ret = userport.getData(ctx, auser, creds);
            aliases = ret.getAliases();
            // list all mail aliases of that user
            System.out.println("User has the following alias(es):" + aliases);
        } catch (com.openexchange.oxaas.context.InvalidDataExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.NoSuchContextExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.DuplicateExtensionExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.InvalidCredentialsExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.RemoteExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.StorageExceptionException e) {
            e.printStackTrace();
        } catch (InvalidDataExceptionException e) {
            e.printStackTrace();
        } catch (NoSuchContextExceptionException e) {
            e.printStackTrace();
        } catch (DuplicateExtensionExceptionException e) {
            e.printStackTrace();
        } catch (DatabaseUpdateExceptionException e) {
            e.printStackTrace();
        } catch (InvalidCredentialsExceptionException e) {
            e.printStackTrace();
        } catch (RemoteExceptionException e) {
            e.printStackTrace();
        } catch (NoSuchUserExceptionException e) {
            e.printStackTrace();
        } catch (StorageExceptionException e) {
            e.printStackTrace();
        } catch (CreateSharedDomainFaultException e) {
            e.printStackTrace();
        }
    }
}
</syntaxhighlight>
===== Catchall account management =====
The next example shows how to manage catchall accounts.
Please take into account that this is not necessarily enabled for your account.
<syntaxhighlight lang="java">
package com.openexchange.oxaas.myclient;
import javax.xml.namespace.QName;
import com.openexchange.oxaas.context.OXResellerContextService;
import com.openexchange.oxaas.context.OXResellerContextServicePortType;
import com.openexchange.oxaas.extra.CreateDomainCatchallFaultException;
import com.openexchange.oxaas.extra.DeleteDomainCatchallFaultException;
import com.openexchange.oxaas.extra.DomainCatchall;
import com.openexchange.oxaas.extra.ListDomainCatchallsFaultException;
import com.openexchange.oxaas.extra.OXaaSService;
import com.openexchange.oxaas.extra.OXaaSService_Service;
/*
* Example SOAP client for OXaaS OXResellerUserService
*
* Create users in a context
*
*/
public class OXaaSCatchAllManagement {
    private static final QName CONTEXT_SERVICE_NAME = new QName("http://soap.reseller.admin.openexchange.com", "OXResellerContextService");
    private static final QName OXAAS_SERVICE_NAME = new QName("http://soap.oxaas.admin.openexchange.com/", "OXaaSService");
    public static void main(String[] args) {
        final String subadminname = "mysubadmin";
        final String subadminpw  = "secret";
        final String userlogin    = "auser";
        final String ctxname      = subadminname + "_myctx";
       
        OXResellerContextService contextservice = new OXResellerContextService(OXResellerContextService.WSDL_LOCATION, CONTEXT_SERVICE_NAME);
        OXResellerContextServicePortType contextport = contextservice.getOXResellerContextServiceHttpSoap11Endpoint();
        OXaaSService_Service oxaasservice = new OXaaSService_Service(OXaaSService_Service.WSDL_LOCATION, OXAAS_SERVICE_NAME);
        OXaaSService oxaasport = oxaasservice.getOXaaSServiceSOAP(); 
       
       
        // We need to use the ResellerContextService SOAP client stub to retrieve the context id
        com.openexchange.oxaas.context.rmi.dataobjects.Credentials ctxCreds = new com.openexchange.oxaas.context.rmi.dataobjects.Credentials();
        com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext ctxCtx = new com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext();
        ctxCreds.setLogin(subadminname);
        ctxCreds.setPassword(subadminpw);
        ctxCtx.setName(ctxname);
        try {
            // we only have the name of the context, so we need to retrieve its id, first using ResellerContextService
            com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext ctxRet = contextport.getData(ctxCtx, ctxCreds);
            com.openexchange.oxaas.extra.Credentials oxaasCtxCreds = new com.openexchange.oxaas.extra.Credentials();
            oxaasCtxCreds.setLogin(subadminname);
            oxaasCtxCreds.setPassword(subadminpw);
           
            /*
            * Note: this will throw an error
            * oxaas_catchall_domain capability not available for context XXX, user YYY in brand ZZZ
            * unless you have domain catchall in your contract
            */
            oxaasport.createDomainCatchall(ctxRet.getId(), "example.com", userlogin, oxaasCtxCreds);
           
            for(final DomainCatchall dc : oxaasport.listDomainCatchalls(ctxRet.getId(), oxaasCtxCreds) ) {
                System.out.println("Catchall account for domain " + dc.getDomain() + " is " + dc.getLogin());
            }
           
            // cleanup
            oxaasport.deleteDomainCatchall(ctxRet.getId(), "example.com", userlogin, oxaasCtxCreds);
        } catch (com.openexchange.oxaas.context.InvalidDataExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.NoSuchContextExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.DuplicateExtensionExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.InvalidCredentialsExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.RemoteExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.StorageExceptionException e) {
            e.printStackTrace();
        } catch (ListDomainCatchallsFaultException e) {
            e.printStackTrace();
        } catch (DeleteDomainCatchallFaultException e) {
            e.printStackTrace();
        } catch (CreateDomainCatchallFaultException e) {
            e.printStackTrace();
        }
    }
}
</syntaxhighlight>


=== Perl ===
=== Perl ===
==== Standalone example: createOXaaSContext ====
http://software.open-xchange.com/products/appsuite/doc/oxasservice/createOXaaSContext.pl
==== Standalone example: createOXaaSUser ====
http://software.open-xchange.com/products/appsuite/doc/oxasservice/createOXaaSUser.pl
==== Standalone example: changeOXaaSUserPermissions ====
http://software.open-xchange.com/products/appsuite/doc/oxasservice/changeOXaaSUserPermissions.pl
==== OXaas APS(1.2) package ====


Just download the APS package as mentioned [[#Reference_implementation|here]]. When you extract the zip file, you will find
Just download the APS package as mentioned [[#Reference_implementation|here]]. When you extract the zip file, you will find

Latest revision as of 12:18, 2 March 2023

Tutorial: Provision OX as a Service using SOAP

Open-Xchange concept of Contexts

In order to provision users and groups into Open-Xchange, it is important to understand, that Open-Xchange is designed for shared hosting environments in a way that it has to serve multiple tenants, customers, domains, or however you want to name it. In Open-Xchange, we call that a Context. A context is a sealed container for users and groups. Users in a context can not see users of other contexts, nor can they share data with users of other contexts (with the exception of Open-Xchange publish and subscribe functionality).

A usual scenario is to have a company, a family or in general one end customer in a context. One can also say, a context is a domain, and usually that makes sense, since a company has one domain. However, Open-Xchange contexts are not limited to one domain only.

Open-Xchange concept of provisioning

A plain Open-Xchange installation consists of two administrative levels.

  1. root level, usually we call that oxadminmaster
  2. context level

oxadminmaster / root

The root, or oxadminmaster account is used to

  • add, remove and configure filestores attached to Open-Xchange
  • add, remove and configure databases attached to Open-Xchange
  • add, remove and configure contexts

and change parameters like add/remove domains, change per context filesystem quota, etc.

Depending on the OX configuration, it is not able to add or remove users and groups, nor any other data within a context!

Context admin

The context admin is like an ordinary Open-Xchange user, except that it can add, remove and edit users and groups within Open-Xchange using the provisioning API. In addition, it inherits shared data of users, that are deleted. In OX as a Service, however, the context admin cannot read, send or receive mail.

OX as a Service concept of provisioning

As written before, plain Open-Xchange only has one root account. In a reseller scenario, that would mean if we want resellers to be able to create contexts for their customers, we would have to hand out our root account. Since that is not desirable, we added another layer via the Reseller Bundle as mentioned earlier.

  1. root level, usually we call that oxadminmaster
  2. subadmin level / brand level
  3. context level

root and context level don't change, except that context level can be restricted.

The subadmin account can only add, remove or configure contexts. Depending on the configuration of the OX as a Service tenant, it can or can NOT add, remove and configure users within contexts. Contexts created by a subadmin account can not be seen by other subadmin accounts.

What is a brand?

A brand is a customers subadmin login to the OXaaS SOAP provisioning API.

OX as a Service specifics

Shared domains, explicit domains and ordinary domains

Ordinary domains

In order to create a user in Open-Xchange, you have to set an email address for that user. This will directly lead into a domain to be created into OXaaS bound to that user and its context, if that domain does not already exists and is owned by a different context.

Shared domains

If you want to share domains between all contexts, you have to use shared domains. Shared domains must be created in advance using the createSharedDomain method (see OXaaS specific methods) or using the REST API (needs recent version).

Explicit domains

Recent versions support another type of domain called explicit domains. These domains must be explicitly added to contexts using the REST API (needs recent version). You can add the same explicit domain to one or multiple contexts. If a context already contains an ordinary domain of the same name, it will be transformed into an explicit domain.

Note that the explicit domain feature is not available by default, it must be activated for each customer, individually.

You can use the existsMailAlias method to check for the existence of an alias before you create it.

Catchall accounts

If the feature is enabled in your contract, you can create catchall mail aliases bound to users within contexts.

User permissions

See OXaaS permission description below.

User name/login uniqueness

Due to the architecture of OXaaS, a login/username must be unique across all created contexts. That means it is not possible to create two "oxadmin" accounts. This limitation applies per brand.

Display name uniqueness

In contrary to the login/name of users, display names must only be unique within each context. That is because it is used e.g. in the shared folder list of e.g. calendar, drive, contacts in OX. Also it is used as folder name when mounting OX via WEBDAV.

It is no problem, however, to have one "Steve Smith" in one context, and another "Steve Smith” in another context.

No email for "oxadmin"

The architecture of OX as a Service does not allow the context admin to have email.

Provisioning

OXaaS specific methods

SOAP API

The following SOAP methods are specific to OXaaS and are NOT part of the general Open-Xchange provisioning API.

OXaaS specific SOAP calls and its authentication requirements
Method Functionality Authentication
getQuotaUsage get the overall mail quota usage of all users within the given context Subadmin
createSharedDomain create a shared domain Subadmin
existsLogin check whether user login already exists. Note: a users login must be unique within all users for your subadmin account and NOT only per context! Subadmin
existsMailAlias check whether given mail alias already exists Subadmin
createDomainCatchall create a domain catchall Subadmin
getQuotaUsagePerUser get mail quota usage of the individual user within the given context Subadmin
listDomainCatchalls list all existing domain catchalls Subadmin
setMailQuota set the mail quota of the individual user within the context Context Admin
deleteDomainCatchall delete the given domain catchall Subadmin
getPermissions list given users permissions Subadmin
enablePermissions enable provided permissions for given user Subadmin
disablePermissions enable provided permissions for given user Subadmin
setExpiryDate store expiry date for the given user Context Admin
getExpiryDate get expiry date stored for user Context Admin
deleteExpiryDate delete the expiry date stored in the given user Context Admin
getExpiredUsers retrieve list of expired users Subadmin
getMailQuota get the mail quota of the individual user within the context Subadmin
setPasswordHash directly store provided pwHash into userPassword attribute of matching ldap entry. Note: Input will be validated against valid mechanisms. Context Admin

The WSDL source file for these methods contain documentation for each of the calls and parameters. You can download it here: http://software.open-xchange.com/products/appsuite/doc/oxasservice/OXaaSService.wsdl

Note that the mail quota usage and max values are the combined values of drive and mail quota in case the system has unified quota enabled.

REST API

There's a growing number of REST APIs to access OXaaS, see https://documentation.open-xchange.com/, section Cloud Plugins API.

OX Core Provisioning API

The core provisioning API consists of four namespaces:

  1. Context management
  2. User management
  3. Group management
  4. Resource management

Some of these namespaces share the same data structures such as Credentials, Context and User.


Provisioning-core.png

Reference implementation

The reference implementation of the European OX as a Service system can be found in the OX as a Service APS package for Odin Service Automation.

Workflow

Subadmin credentials

The first requirement is to get subadmin credentials for your company.

Together with the login and password you will also retrieve the provisioning URL to be used by all SOAP requests. In addition, it is required that you give us a list of ip addresses or network(s) that should be allowed to access the provisioning system.

WSDL files

Just point your browser to the provisioning URL you got from us. You will find some services listed there. You will need the following services from that list:

https://hostname/webservices/OXaaSService?wsdl
OX as a Service specific functions
https://hostname/webservices/OXResellerContextService?wsdl
Context management
https://hostname/webservices/OXResellerUserService?wsdl
User management

and optionally

https://hostname/webservices/OXResellerGroupService?wsdl
Group management
https://hostname/webservices/OXResellerResourceService?wsdl
Resource management

SOAP API documentation

The general SOAP API documentation can be found at this URL: http://software.open-xchange.com/products/appsuite/doc/SOAP/admin/OX-Admin-SOAP.html

That document contains links to the Javadoc documentation for the RMI api, but that is more or less the same as the SOAP API.

In addition, there's the general, non OXaaS specific wiki page.

Create a context

Once you have the credentials in place, you are ready to create your first context.

Creating a context requires to create the first user in that context, that is the context admin, see above.

Mandatory settings for a context are

name
name of the context
quota
file quota in MB for that context (Note: that is file, not mail!)
taxonomy
must be set to the login of your subadmin account, see below

Important: In OXaaS, the name of the context must always start with your subadmin login with an underscore appended. E.g. when your subadmin login is johndoe, the all your context names must start with johndoe_!

Optional settings

mainColor
io.ox/dynamic-theme//mainColor
linkColor
io.ox/dynamic-theme//linkColor
for further theme parameters, check https://documentation.open-xchange.com/latest/ui/theming/dynamic-theming.html
about dialogue
com.openexchange.appsuite.servercontact, see below
id
A numerical id bound to the context. When you create a context, this id will be generated. You will need that later when you manage users. The id can be looked up via the context name.
userAttributes

The settings brandtaxonomy and the other optional settings except id are part of the userAttributes SOAP field. All other settings can easily be set via simple SOAP settings. userAttributes is a hash that contains some settings that are not available in all setups of Open-Xchange. It allows to extend Open-Xchange functionality dynamically like done in OXaaS.

The hash looks like this:

userAttributes => entries => EntryArray

with EntryArray :=

[
  { key   => "somekey"
    value => somevalue },
  { key   => "someotherkey"
    value => someothervalue },
  ...
]

somevalue can be an array again, e.g.:

somevalue => entries => EntryArray

with EntryArray :=

[
  { key   => "somekey"
    value => somevalue },
  { key   => "someotherkey"
    value => someothervalue },
  ...
]

and so on

Example dump using perls Data::Dumper:

          'userAttributes' => {
                              'entries' => [
                                           {
                                             'value' => {
                                                        'entries' => [
                                                                     {
                                                                       'value' => '#0000ff',
                                                                       'key' => 'io.ox/dynamic-theme//topbarHover'
                                                                     },
                                                                     {
                                                                       'value' => '#ff0000',
                                                                       'key' => 'io.ox/dynamic-theme//linkColor'
                                                                     },
                                                                     {
                                                                       'value' => '#00ff00',
                                                                       'key' => 'io.ox/dynamic-theme//mainColor'
                                                                     },
                                                                     {
                                                                       'value' => 'true',
                                                                       'key' => 'com.openexchange.capability.dynamic-theme'
                                                                     },
                                                                     {
                                                                       'value' => 'My Example Org | <a href=\\"https://www.example.org\\" target=\\"_blank\\">www.example.org</a> | <a href=\\"https://example.org/help\\" target=\\"_blank\\">Contact us</a>',
                                                                       'key' => 'com.openexchange.appsuite.servercontact'
                                                                     }                                                                   ]
                                                      },
                                             'key' => 'config'
                                           },
                                           {
                                             'value' => {
                                                        'entries' => {
                                                                     'value' => 'johndoe',
                                                                     'key' => 'types'
                                                                   }
                                                      },
                                             'key' => 'taxonomy'
                                           }
                                         ]
                            },
Admin User
name
login name of the context admin
password
password
email
email address of the context admin
displayname
displayname (usually surname givenname)
surname
surname
givenname
given name
lang
language, e.g. en_GB, en_US, de_DE, ...
timezone
Java timezone such as Europe/Berlin,
Timezones

To get a list of all available timezones, you can run this short Java program:

import java.util.TimeZone;

public class AllTimeZones {
    public static void main(String[] args) {
        for(final String zone : TimeZone.getAvailableIDs() ) {
            System.out.println(zone);
        }
    }

}
Languages

This is the list of currently supported languages in OXaaS:

ja_JP
de_DE
es_ES
es_MX
fr_FR
it_IT
nl_NL
pl_PL
zh_TW
en_US
en_GB

Create users

Creating users requires the following parameters

name
login name of the context admin
password
password
email
email address of the context admin
displayname
displayname (usually surname givenname)
surname
surname
givenname
given name
lang
language, e.g. en_GB, en_US, de_DE, ...
timezone
Java timezone such as Europe/Berlin,
moduleaccess
the module access combination name
mailquota
the mail quota of the user in MB

Timezones and languages like documented earlier.

Valid values for moduleaccess are:

  • webmail_plus
  • groupware_standard
  • groupware_advanced
  • groupware_premium

Other settings are not supported.

userAttributes

It might be required you have to set some specific attributes per user like the Edition Type as done by the OXaaS APS package.

There's a choice of 7 different edition types:

webmail
bound to webmail_plus
basic
bound to groupware_standard
advanced
bound to groupware_advanced
pro
bound to groupware_premium
pro_m
bound to groupware_premium
pro_l
bound to groupware_premium
pro_xl
bound to groupware_premium

which can be set within each users oxaas_edition_type within a tree oxaas:

'userAttributes' => {
                    'entries' => {
                                 'key' => 'oxaas',
                                 'value' => {
                                            'entries' => {
                                                         'key' => 'oxaas_edition_type',
                                                         'value' => 'pro_l'
                                                         }
                                            }
                                }
                    }


see createuser example script

Create the user in Open-Xchange
  • Use the name and password of the context admin user of the context you created earlier and define

a Credentials object.

  • Find the numerical id of the context e.g. in using OXResellerContextService->getData(name="contextname")

Use the OXResellerUserService->createByModuleAccessName to create users.

Note: Although there are three create methods in the SOAP user service API, you have to use the method createByModuleAccessName and specify one of the names listed above.

Set mail quota
  • Use the name and password of the context admin user of the context you created earlier and define

a Credentials object.

  • Find the numerical id of the context e.g. in using OXResellerContextService->getData(name="contextname")
  • Find the numerical id of the user either by using OXResellerUserService->getData(name="username") or use/store the return value of OXResellerUserService->createByModuleAccessName

Use the OXaaSService->setMailQuota call to set the mail quota for the user created above.

Set OXaaS permissions
Explanation

The OXaaS permissions allow to enable or disable a certain set of features. Currently, the following permissions are available:

OXaaS permissions
Permission Description
SEND User is allowed to send mail
RECEIVE User is allowed to receive mail
MAILLOGIN User can login using IMAP from external; webmail is not affected
WEBLOGIN User can login to OX webmail.

The permission names are case insensitive. The WEBLOGIN permission is the same as the Mailenabled permission in the user data of the Open-Xchange core api. The permission OXaaS api provides another way to enable/disable it.

  • Use the name and password of the context admin user of the context you created earlier and define

a Credentials object.

  • Find the numerical id of the context e.g. in using OXResellerContextService->getData(name="contextname")
  • Find the numerical id of the user either by using OXResellerUserService->getData(name="username") or use/store the return value of OXResellerUserService->createByModuleAccessName

Use one of OXaaSService->enablePermissions, OXaaSService->disablePermissions or OXaaSService->getPermissions to change or retrieve permissions. Permissions must always be provided as an array of 1 or more permissions.

SOAP provisioning feature matrix

(WIP)

The table below shows what method(s) to use and what to set in order to configure the different feature sets.

The value in the row Module Access Name must be given as a parameter to OXResellerUserService->changeByModuleAccessName or OXResellerUserService->createByModuleAccessName.

The values in the row Capabilities must be given as parameters to the userAttributes member of the User object that should be changed and then passed to OXResellerUserService->change or OXResellerUserService->createByModuleAccessName.

Note: OXResellerUserService->changeByModuleAccessName does NOT change these capabilities!

Provisioning Feature Matrix
Feature Module Access Name Capabilities (mandatory values in bold, others are optional)
Web Mail webmail_plus com.openexchange.capability.drive = false
com.openexchange.capability.document_preview = false
com.openexchange.capability.spreadsheet = false
com.openexchange.capability.text = false
com.openexchange.capability.presenter = false
com.openexchange.capability.remote_presenter = false
com.openexchange.capability.guard = false
com.openexchange.capability.guard-mail = false
com.openexchange.capability.guard-drive = false
Basic groupware_standard com.openexchange.capability.drive = true
com.openexchange.capability.document_preview = true/false
com.openexchange.capability.spreadsheet = true/false
com.openexchange.capability.text = true/false
com.openexchange.capability.presenter = true/false
com.openexchange.capability.remote_presenter = true/false
com.openexchange.capability.guard = true/false
com.openexchange.capability.guard-mail = true/false
com.openexchange.capability.guard-drive = true/false
Advanced groupware_advanced com.openexchange.capability.drive = true
com.openexchange.capability.document_preview = true/false
com.openexchange.capability.spreadsheet = true/false
com.openexchange.capability.text = true/false
com.openexchange.capability.presenter = true/false
com.openexchange.capability.remote_presenter = true/false
com.openexchange.capability.guard = true/false
com.openexchange.capability.guard-mail = true/false
com.openexchange.capability.guard-drive = true/false
Pro groupware_premium com.openexchange.capability.drive = true
com.openexchange.capability.document_preview = true
com.openexchange.capability.spreadsheet = true
com.openexchange.capability.text = true
com.openexchange.capability.presenter = true
com.openexchange.capability.remote_presenter = true
com.openexchange.capability.guard = true/false
com.openexchange.capability.guard-mail = true/false
com.openexchange.capability.guard-drive = true/false

List of available capabilities (incomplete)

These features are controlled by the ConfigCascade.

For drive and documents the following settings are responsible:

OX Drive

com.openexchange.capability.drive = true/false

OX Docs

com.openexchange.capability.document_preview = true/false
com.openexchange.capability.spreadsheet = true/false
com.openexchange.capability.text = true/false
com.openexchange.capability.presentation = true/false
com.openexchange.capability.remote_presenter = true/false
com.openexchange.capability.guard-docs = true/false

OX Guard

com.openexchange.capability.guard = true/false
com.openexchange.capability.guard-mail = true/false
com.openexchange.capability.guard-drive = true/false

Using this perl example:


e.g. this

      logouturl => {
              setting => "io.ox/core//customLocations/logout",
              value   => "logouturl"
      }

is setting the ConfigCascade setting io.ox/core//customLocations/logout to the string “logouturl"

 io.ox/core//customLocations/logout = "logouturl"

adding

      oxdrive => {
              setting => "com.openexchange.capability.drive",
              value   => "true"
      }

in that example would turn on drive.

Code Examples

Java

Generating the SOAP client

Note that the below instructions only work with Java version 8 and no later version

Since Open-Xchange is using Apache CXF for SOAP, we recommend to use the wsdl2java code generator from that package.

The Open-Xchange SOAP services are divided into multiple parts, which makes the code generation a little complex.

In OXaaS we need at least three services in order to create contexts and users:

  • OXResellerContextService
  • OXResellerUserService
  • OXaaSService

The shell script below generates the stubs of these three services into the directory defined in the CODEBASE variable. In addition, you have to set WSDLURL to point it to the provisioning URL you will get from us as mentioned earlier.

Note: when running against a DEV container without valid SSL certs (e.g. self-signed SSL certs), it is required to add the servers cert into your java keystore first:

  1. Get the cert e.g. by openssl s_client -connect my.oxaas.webservices.host.net:443 (the part between BEGIN CERTIFICATE and END CERTIFICATE) or by exporting from a web browser. Put it in a file named for example my.oxaas.webservices.host.net.crt.
  2. Import it in a custom TrustStore. Assign a password; in this example we assume "secret": keytool -import -trustcacerts -alias my.oxaas.webservices.host.net -keystore my.oxaas.webservices.host.net.jks -file my.oxaas.webservices.host.net.crt -storetype JKS
  3. Supply it to the JVM by patching the CXF wsdl2java script (e.g. /opt/apache-cxf-3.1.14/bin/wsdl2java) and add the following arguments: -Djavax.net.ssl.trustStore=my.oxaas.webservices.host.net.jks -Djavax.net.ssl.trustStorePassword=secret -Djavax.net.ssl.trustStoreType=JKS

Copy&paste the shell script below into a file and run it using the bash shell. Warning: the script assumes the CODEBASE target lives in its own dedicated ecplise project, and executes a rm -rf $CODEBASE for a clean start. For other usecases (shared eclipse project, etc), please adjust to your needs / be careful!

# 1. download apache-cxf tarball, extract it and "cd" into the directory, e.g.
#    tar zxvpf apache-cxf-3.1.10.tar.gz; cd apache-cxf-3.1.10
#    NOTE: cxf versions 3.0 do NOT work ootb with java-1.8!
# 2. change variables CODEBASE, JAVA_HOME and WSDLURL
# 3. run this script "bash oxaas-wsdl2java"
export JAVA_HOME="/usr/lib/jvm/java-1.8.0-openjdk-amd64/"
CODEBASE="/home/oxgit/workspace/OXaaSJClient/src"
WSDLURL="https://youroxaashost/webservices"

rm -rf $CODEBASE
frontend=jaxws21
dbinding=jaxb

JAXBTMP=/tmp/jaxb$$.xml
rm -f $JAXBTMP
cat<<EOF > $JAXBTMP
<jaxb:bindings version="2.1"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <jaxb:globalBindings generateElementProperty="false"/>
</jaxb:bindings>
EOF

pname="com.openexchange.oxaas.context"
bin/wsdl2java -databinding $dbinding -frontend $frontend -client -impl -d $CODEBASE -keep -b $JAXBTMP \
-p "http://soap.reseller.admin.openexchange.com=${pname}" \
-p "http://dataobjects.rmi.reseller.admin.openexchange.com/xsd=${pname}.reseller.rmi.dataobjects" \
-p "http://dataobjects.soap.reseller.admin.openexchange.com/xsd=${pname}.reseller.soap.dataobjects" \
-p "http://dataobjects.soap.admin.openexchange.com/xsd=${pname}.soap.dataobjects" \
-p "http://dataobjects.rmi.admin.openexchange.com/xsd=${pname}.rmi.dataobjects" \
-p "http://exceptions.rmi.admin.openexchange.com/xsd=${pname}.rmi.exceptions" \
-p "http://rmi.java/xsd=${pname}.java.rmi" \
-p "http://io.java/xsd=${pname}.java.io" \
${WSDLURL}/OXResellerContextService?wsdl

pname="com.openexchange.oxaas.user"
bin/wsdl2java -databinding $dbinding -frontend $frontend -client -impl -d $CODEBASE -keep -b $JAXBTMP \
-p "http://soap.reseller.admin.openexchange.com=${pname}" \
-p "http://dataobjects.rmi.reseller.admin.openexchange.com/xsd=${pname}.reseller.rmi.dataobjects" \
-p "http://dataobjects.soap.reseller.admin.openexchange.com/xsd=${pname}.reseller.soap.dataobjects" \
-p "http://dataobjects.soap.admin.openexchange.com/xsd=${pname}.soap.dataobjects" \
-p "http://dataobjects.rmi.admin.openexchange.com/xsd=${pname}.rmi.dataobjects" \
-p "http://exceptions.rmi.admin.openexchange.com/xsd=${pname}.rmi.exceptions" \
-p "http://rmi.java/xsd=${pname}.java.rmi" \
-p "http://io.java/xsd=${pname}.java.io" \
${WSDLURL}/OXResellerUserService?wsdl

pname="com.openexchange.oxaas.extra"
bin/wsdl2java -databinding $dbinding -frontend $frontend -client -impl -d $CODEBASE -keep -b $JAXBTMP \
-p "http://soap.oxaas.admin.openexchange.com/=${pname}" \
${WSDLURL}/OXaaSService?wsdl

rm -f $JAXBTMP

When you generate the code into an existing eclipse project, you should have three main packages as shown in the image below

OXaaSSOAPClientEclipse.png

Example Client

In the following example, the context creation and the user creation is separated into different programs.

To summarize some essential requirements from the example below:

  • The name of each context you create must start with your subadmin name followed by an underscore _
  • You must set the userAttribute taxonomy at least
  • The context admin user must get the groupware_premium access permission
Build / run instructions
Eclipse

We assume, you have created the Java client stub(s) as documented above and have it as a separate eclipse project. The individual clients given below are assumed to live in a different ecplise project which references the Java client stubs in their classpath.

Command Line

For maximum simplicity let's assume you use the source files given below without the package statement. Put them in an examples/ subdirectory.

Let's assume furthermore you created the Java client stubs in a different directory, e.g. codebase/.

Change into that directory to compile all the Java stub files

cd codebase/
find . -name \*.java  | xargs javac

Back in the working directory where the source files given below are created, you can compile / run them like

cd ../examples/
javac -cp ../codebase MyContextClientExample.java
java -cp .:../codebase MyContextClientExample
SSL-related hints

When working against a dev machine with self-signed certs, the same certificate trust related options are required as explained above for the wsdl2java script (with the same TrustStore and password):

-Djavax.net.ssl.trustStore=my.oxaas.webservices.host.net.jks -Djavax.net.ssl.trustStorePassword=secret -Djavax.net.ssl.trustStoreType=JKS

It might be additionally helpful to enable SSL debug output: -Djavax.net.debug=ssl

As of now (2017-11) there is a flaw in the generated WSDL that it references HTTP SOAP addresses even when using HTTPS. This results in client programs trying to access the API via plain HTTP even after a successful SSL handshake and fetching the WSDL via HTTPS. This is bad as SOAP frames travel the network with credentials included in plain text.

A possible workaround for the time being is to forcefully rewrite the protocol part of the different port urls into https with something like:

After initializing the contextport using ...

OXResellerContextServicePortType contextport = contextservice.getOXResellerContextServiceHttpSoap11Endpoint();

... add the following code:

// insert in your imports section:
// import javax.xml.ws.BindingProvider;
((BindingProvider)contextport).getRequestContext().put(
    BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
    ((String)((BindingProvider)contextport).getRequestContext()
        .get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY))
        .replaceAll("^http:", "https:"));

Similar adjustments are required for userport and oxaasport, where they occur.

Context creation

The example below shows how to create a context in OXaaS.

package com.openexchange.oxaas.myclient;

import java.io.IOException;
import java.util.List;
import javax.xml.namespace.QName;
import com.openexchange.oxaas.context.ContextExistsExceptionException;
import com.openexchange.oxaas.context.DatabaseUpdateExceptionException;
import com.openexchange.oxaas.context.Delete;
import com.openexchange.oxaas.context.DuplicateExtensionExceptionException;
import com.openexchange.oxaas.context.InvalidCredentialsExceptionException;
import com.openexchange.oxaas.context.InvalidDataExceptionException;
import com.openexchange.oxaas.context.NoSuchContextExceptionException;
import com.openexchange.oxaas.context.OXResellerContextService;
import com.openexchange.oxaas.context.OXResellerContextServicePortType;
import com.openexchange.oxaas.context.RemoteExceptionException;
import com.openexchange.oxaas.context.StorageExceptionException;
import com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext;
import com.openexchange.oxaas.context.rmi.dataobjects.Credentials;
import com.openexchange.oxaas.context.soap.dataobjects.Entry;
import com.openexchange.oxaas.context.soap.dataobjects.SOAPMapEntry;
import com.openexchange.oxaas.context.soap.dataobjects.SOAPStringMap;
import com.openexchange.oxaas.context.soap.dataobjects.SOAPStringMapMap;
import com.openexchange.oxaas.context.soap.dataobjects.User;

/*
 * Example SOAP client for OXaaS OXResellerContextService
 * 
 * Create a context
 * 
 */
public class MyContextClientExample {

    private static final QName SERVICE_NAME = new QName("http://soap.reseller.admin.openexchange.com", "OXResellerContextService");

    public static void main(String[] args) {
        final String subadminname = "mysubadmin";
        final String subadminpw   = "secret";
        final String ctxname      = subadminname + "_myctx";

        Credentials creds = new Credentials();
        ResellerContext ctx = new ResellerContext();
        User oxadmin = new User();

        OXResellerContextService contextservice = new OXResellerContextService(OXResellerContextService.WSDL_LOCATION, SERVICE_NAME);
        OXResellerContextServicePortType contextport = contextservice.getOXResellerContextServiceHttpSoap11Endpoint();  

        creds.setLogin(subadminname);
        creds.setPassword(subadminpw);

        SOAPMapEntry taxonomy = new SOAPMapEntry();
        taxonomy.setKey("taxonomy");
        SOAPStringMap taxtypeval = new SOAPStringMap();
        Entry taxtypeent = new Entry();
        taxtypeent.setKey("types");
        taxtypeent.setValue(subadminname);
        taxtypeval.getEntries().add(taxtypeent);
        taxonomy.setValue(taxtypeval);

        SOAPMapEntry config = new SOAPMapEntry();
        config.setKey("config");
        SOAPStringMap configEntries = new SOAPStringMap();

        Entry topbarHover = new Entry();
        topbarHover.setKey("io.ox/dynamic-theme//topbarHover");
        topbarHover.setValue("#0000ff");

        Entry mainColor = new Entry();
        mainColor.setKey("io.ox/dynamic-theme//mainColor");
        mainColor.setValue("#ff0000");

        Entry linkColor = new Entry();
        linkColor.setKey("io.ox/dynamic-theme//linkColor");
        linkColor.setValue("#00ff00");

        Entry dynThemeCapa = new Entry();
        dynThemeCapa.setKey("com.openexchange.capability.dynamic-theme");
        dynThemeCapa.setValue("true");

        configEntries.getEntries().add(topbarHover);
        configEntries.getEntries().add(mainColor);
        configEntries.getEntries().add(linkColor);
        configEntries.getEntries().add(dynThemeCapa);
        config.setValue(configEntries);

        SOAPStringMapMap userattrs = new SOAPStringMapMap();
        userattrs.getEntries().add(taxonomy);
        userattrs.getEntries().add(config);


        ctx.setName(ctxname);
        ctx.setMaxQuota(10000l);
        ctx.setUserAttributes(userattrs);

        final String adminEmail = "oxadmin@example.com";
        final String ctxadmname = "oxadmin";
        final String ctxadmpw   = "secret";
        oxadmin.setName(ctxadmname);
        oxadmin.setPassword(ctxadmpw);
        oxadmin.setDisplayName("OX Admin");
        oxadmin.setSurName("OX");
        oxadmin.setGivenName("Admin");
        oxadmin.setPrimaryEmail(adminEmail);
        oxadmin.setEmail1(adminEmail);
        oxadmin.setDefaultSenderAddress(adminEmail);
        oxadmin.setLanguage("en_US");
        oxadmin.setTimezone("Europe/Berlin");

        try {
            ResellerContext ret = contextport.createModuleAccessByName(ctx, oxadmin, "groupware_premium", creds, null);
            System.out.println("created context with id=" + ret.getId());

            System.out.println("existing contexts:");
            List<ResellerContext> allctxs = contextport.listAll(creds);
            for(final ResellerContext c : allctxs) {
                System.out.println(c.getName() + " with id=" + c.getId());
            }

            System.in.read();

            System.out.println("deleting created context again");
            Delete del = new Delete();
            del.setAuth(creds);
            del.setCtx(ctx);
            contextport.delete(del);
        } catch (InvalidDataExceptionException e) {
            e.printStackTrace();
        } catch (ContextExistsExceptionException e) {
            e.printStackTrace();
        } catch (DuplicateExtensionExceptionException e) {
            e.printStackTrace();
        } catch (InvalidCredentialsExceptionException e) {
            e.printStackTrace();
        } catch (RemoteExceptionException e) {
            e.printStackTrace();
        } catch (StorageExceptionException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchContextExceptionException e) {
            e.printStackTrace();
        } catch (DatabaseUpdateExceptionException e) {
            e.printStackTrace();
        }
    }

}
User creation

The client below utilizes all SOAP services we have created so far.

The essential parts of the code are

  • use OXResellerContextService to find out the ID of the context you want to create users
  • create users using OXResellerUserService
  • use one of the moduleaccess values as documented earlier
  • use setMailQuota from OXaaSService to set each users mail quota individually
  • use existsLogin from OXaaSService to check in advance of a login already exists


package com.openexchange.oxaas.myclient;

import java.io.IOException;
import javax.xml.namespace.QName;
import com.openexchange.oxaas.context.OXResellerContextService;
import com.openexchange.oxaas.context.OXResellerContextServicePortType;
import com.openexchange.oxaas.extra.ExistsLoginFaultException;
import com.openexchange.oxaas.extra.OXaaSService;
import com.openexchange.oxaas.extra.OXaaSService_Service;
import com.openexchange.oxaas.extra.SetMailQuotaFaultException;
import com.openexchange.oxaas.user.DatabaseUpdateExceptionException;
import com.openexchange.oxaas.user.Delete;
import com.openexchange.oxaas.user.DuplicateExtensionExceptionException;
import com.openexchange.oxaas.user.InvalidCredentialsExceptionException;
import com.openexchange.oxaas.user.InvalidDataExceptionException;
import com.openexchange.oxaas.user.NoSuchContextExceptionException;
import com.openexchange.oxaas.user.NoSuchUserExceptionException;
import com.openexchange.oxaas.user.OXResellerUserService;
import com.openexchange.oxaas.user.OXResellerUserServicePortType;
import com.openexchange.oxaas.user.RemoteExceptionException;
import com.openexchange.oxaas.user.StorageExceptionException;
import com.openexchange.oxaas.user.reseller.soap.dataobjects.ResellerContext;
import com.openexchange.oxaas.user.rmi.dataobjects.Credentials;
import com.openexchange.oxaas.user.soap.dataobjects.Entry;
import com.openexchange.oxaas.user.soap.dataobjects.SOAPMapEntry;
import com.openexchange.oxaas.user.soap.dataobjects.SOAPStringMap;
import com.openexchange.oxaas.user.soap.dataobjects.SOAPStringMapMap;
import com.openexchange.oxaas.user.soap.dataobjects.User;

/*
 * Example SOAP client for OXaaS OXResellerUserService
 * 
 * Create users in a context
 * 
 */
public class MyUserClientExample {

    private static final QName USER_SERVICE_NAME    = new QName("http://soap.reseller.admin.openexchange.com", "OXResellerUserService");
    private static final QName CONTEXT_SERVICE_NAME = new QName("http://soap.reseller.admin.openexchange.com", "OXResellerContextService");
    private static final QName OXAAS_SERVICE_NAME   = new QName("http://soap.oxaas.admin.openexchange.com/", "OXaaSService");

    public static void main(String[] args) {
        final String subadminname = "mysubadmin";
        final String subadminpw = "secret";
        final String ctxadmname = "oxadmin";
        final String ctxadmpw = "secret";
        final String ctxname = subadminname + "_myctx";

        Credentials creds = new Credentials();
        ResellerContext ctx = new ResellerContext();
        User auser = new User();

        OXResellerUserService userservice = new OXResellerUserService(OXResellerUserService.WSDL_LOCATION, USER_SERVICE_NAME);
        OXResellerUserServicePortType userport = userservice.getOXResellerUserServiceHttpSoap12Endpoint();
        OXResellerContextService contextservice = new OXResellerContextService(OXResellerContextService.WSDL_LOCATION, CONTEXT_SERVICE_NAME);
        OXResellerContextServicePortType contextport = contextservice.getOXResellerContextServiceHttpSoap11Endpoint();
        OXaaSService_Service oxaasservice = new OXaaSService_Service(OXaaSService_Service.WSDL_LOCATION, OXAAS_SERVICE_NAME);
        OXaaSService oxaasport = oxaasservice.getOXaaSServiceSOAP();

        // We need to use the ResellerContextService SOAP client stub to retrieve the context id
        com.openexchange.oxaas.context.rmi.dataobjects.Credentials ctxCreds = new com.openexchange.oxaas.context.rmi.dataobjects.Credentials();
        com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext ctxCtx = new com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext();
        ctxCreds.setLogin(subadminname);
        ctxCreds.setPassword(subadminpw);
        ctxCtx.setName(ctxname);

        creds.setLogin(ctxadmname);
        creds.setPassword(ctxadmpw);

        final long unifiedQuotaMax = 1000l;

        final String userEmail = "auser@example.com";
        auser.setName("auser");
        auser.setPassword("secret");
        auser.setDisplayName("My User");
        auser.setSurName("My");
        auser.setGivenName("User");
        auser.setPrimaryEmail(userEmail);
        auser.setEmail1(userEmail);
        auser.setDefaultSenderAddress(userEmail);
        auser.setLanguage("en_US");
        auser.setTimezone("Europe/Berlin");
        auser.setMaxQuota(unifiedQuotaMax);

        // enable unified quota (might be enabled globally, already, though)
        final Entry unifiedQuota = new Entry();
        unifiedQuota.setKey("com.openexchange.unifiedquota.enabled");
        unifiedQuota.setValue("true");

        final SOAPStringMap configEntries = new SOAPStringMap();
        configEntries.getEntries().add(unifiedQuota);

        final SOAPMapEntry config = new SOAPMapEntry();
        config.setKey("config");
        config.setValue(configEntries);

        final SOAPStringMapMap userattrs = new SOAPStringMapMap();
        userattrs.getEntries().add(config);
        auser.setUserAttributes(userattrs);

        try {
            // we only have the name of the context, so we need to retrieve its id, first using ResellerContextService
            com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext ctxRet = contextport.getData(ctxCtx, ctxCreds);
            ctx.setId(ctxRet.getId());

            // create the user via OXResellerUserService
            User ret = userport.createByModuleAccessName(ctx, auser, "groupware_premium", creds);
            System.out.println("created user with id=" + ret.getId());

            // set mail quota for that user using OXaaSService
            com.openexchange.oxaas.extra.Credentials oxaasCtxCreds = new com.openexchange.oxaas.extra.Credentials();
            oxaasCtxCreds.setLogin(ctxadmname);
            oxaasCtxCreds.setPassword(ctxadmpw);
            oxaasport.setMailQuota(ctxRet.getId(), ret.getId(), unifiedQuotaMax, oxaasCtxCreds);

            // check whether the login for the user has been created within my subadmin namespace
            // NOTE: this check should be used beforehand usually: check whether login exists and then create it if not
            com.openexchange.oxaas.extra.Credentials oxaasAdminCreds = new com.openexchange.oxaas.extra.Credentials();
            oxaasAdminCreds.setLogin(subadminname);
            oxaasAdminCreds.setPassword(subadminpw);
            if (oxaasport.existsLogin("auser", oxaasAdminCreds)) {
                System.out.println("all ok, user login has been created");
            }

            System.in.read();

            System.out.println("deleting created user again");
            Delete del = new Delete();
            del.setAuth(creds);
            del.setCtx(ctx);
            del.setUser(ret);
            userport.delete(del);
        } catch (InvalidDataExceptionException e) {
            e.printStackTrace();
        } catch (NoSuchContextExceptionException e) {
            e.printStackTrace();
        } catch (DuplicateExtensionExceptionException e) {
            e.printStackTrace();
        } catch (DatabaseUpdateExceptionException e) {
            e.printStackTrace();
        } catch (InvalidCredentialsExceptionException e) {
            e.printStackTrace();
        } catch (RemoteExceptionException e) {
            e.printStackTrace();
        } catch (StorageExceptionException e) {
            e.printStackTrace();
        } catch (NoSuchUserExceptionException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.InvalidDataExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.NoSuchContextExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.DuplicateExtensionExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.InvalidCredentialsExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.RemoteExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.StorageExceptionException e) {
            e.printStackTrace();
        } catch (SetMailQuotaFaultException e) {
            e.printStackTrace();
        } catch (ExistsLoginFaultException e) {
            e.printStackTrace();
        }
    }

}
Email (alias) management

The next example shows how to manage email aliases and shared domains. The essential information is:

  • if you want to change the email address of a user, you have to add the new address to the list of aliases
  • when you want to change individual settings of a user, only send the changed settings


package com.openexchange.oxaas.myclient;

import java.util.List;
import javax.xml.namespace.QName;
import com.openexchange.oxaas.context.OXResellerContextService;
import com.openexchange.oxaas.context.OXResellerContextServicePortType;
import com.openexchange.oxaas.extra.CreateSharedDomainFaultException;
import com.openexchange.oxaas.extra.OXaaSService;
import com.openexchange.oxaas.extra.OXaaSService_Service;
import com.openexchange.oxaas.user.Change;
import com.openexchange.oxaas.user.DatabaseUpdateExceptionException;
import com.openexchange.oxaas.user.DuplicateExtensionExceptionException;
import com.openexchange.oxaas.user.InvalidCredentialsExceptionException;
import com.openexchange.oxaas.user.InvalidDataExceptionException;
import com.openexchange.oxaas.user.NoSuchContextExceptionException;
import com.openexchange.oxaas.user.NoSuchUserExceptionException;
import com.openexchange.oxaas.user.OXResellerUserService;
import com.openexchange.oxaas.user.OXResellerUserServicePortType;
import com.openexchange.oxaas.user.RemoteExceptionException;
import com.openexchange.oxaas.user.StorageExceptionException;
import com.openexchange.oxaas.user.reseller.soap.dataobjects.ResellerContext;
import com.openexchange.oxaas.user.rmi.dataobjects.Credentials;
import com.openexchange.oxaas.user.soap.dataobjects.User;


/*
 * Example SOAP client for OXaaS OXResellerUserService
 * 
 * Create users in a context
 * 
 */
public class OXaaSAliasManagement {

    private static final QName USER_SERVICE_NAME = new QName("http://soap.reseller.admin.openexchange.com", "OXResellerUserService");
    private static final QName CONTEXT_SERVICE_NAME = new QName("http://soap.reseller.admin.openexchange.com", "OXResellerContextService");
    private static final QName OXAAS_SERVICE_NAME = new QName("http://soap.oxaas.admin.openexchange.com/", "OXaaSService");

    public static void main(String[] args) {
        final String subadminname = "mysubadmin";
        final String subadminpw   = "secret";
        final String ctxadmname   = "oxadmin";
        final String ctxadmpw     = "secret";
        final String userlogin    = "auser";
        final String ctxname      = subadminname + "_myctx";
        
        Credentials creds = new Credentials();
        ResellerContext ctx = new ResellerContext();

        OXResellerUserService userservice = new OXResellerUserService(OXResellerUserService.WSDL_LOCATION, USER_SERVICE_NAME);
        OXResellerUserServicePortType userport = userservice.getOXResellerUserServiceHttpSoap12Endpoint();
        OXResellerContextService contextservice = new OXResellerContextService(OXResellerContextService.WSDL_LOCATION, CONTEXT_SERVICE_NAME);
        OXResellerContextServicePortType contextport = contextservice.getOXResellerContextServiceHttpSoap11Endpoint();
        OXaaSService_Service oxaasservice = new OXaaSService_Service(OXaaSService_Service.WSDL_LOCATION, OXAAS_SERVICE_NAME);
        OXaaSService oxaasport = oxaasservice.getOXaaSServiceSOAP();  
        
        
        // We need to use the ResellerContextService SOAP client stub to retrieve the context id
        com.openexchange.oxaas.context.rmi.dataobjects.Credentials ctxCreds = new com.openexchange.oxaas.context.rmi.dataobjects.Credentials();
        com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext ctxCtx = new com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext();
        ctxCreds.setLogin(subadminname);
        ctxCreds.setPassword(subadminpw);
        ctxCtx.setName(ctxname);

        creds.setLogin(ctxadmname);
        creds.setPassword(ctxadmpw);

        try {
            // we only have the name of the context, so we need to retrieve its id, first using ResellerContextService
            com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext ctxRet = contextport.getData(ctxCtx, ctxCreds);
            ctx.setId(ctxRet.getId());

            /*
             * now we want to add an alias to the user "auser"
             */
            User auser = new User();
            auser.setName(userlogin);
            User ret = userport.getData(ctx, auser, creds);
            List<String> aliases = ret.getAliases();
            // list all mail aliases of that user
            System.out.println("User has the following alias(es):" + aliases);
            // now add another one
            aliases.add("sales@example.com");

            // we also want to add an alias within a shared domain
            com.openexchange.oxaas.extra.Credentials oxaasCtxCreds = new com.openexchange.oxaas.extra.Credentials();
            oxaasCtxCreds.setLogin(subadminname);
            oxaasCtxCreds.setPassword(subadminpw);
            /*
             * Note: we can run this method as often as we want, it will ONLY return an error in case we want to add a shared domain
             * that is already bound to another subadmin/customer
             */
            oxaasport.createSharedDomain("shared.net", oxaasCtxCreds);
            aliases.add("me@shared.net");
            
            // store changes
            // we need to created a clean user instance since we cannot just store back the returned user
            User changeduser = new User();
            changeduser.setId(ret.getId());
            changeduser.getAliases().addAll(aliases);
            Change change = new Change();
            change.setAuth(creds);
            change.setCtx(ctx);
            change.setUsrdata(changeduser);
            userport.change(change);
            
            // control the result
            ret = userport.getData(ctx, auser, creds);
            aliases = ret.getAliases();
            // list all mail aliases of that user
            System.out.println("User has the following alias(es):" + aliases);
            
            /*
             * now changing the users email address:
             * to do that, we have to do the following:
             * 1. add the new email address to the aliases, if not yet present
             * 2. change the email address in email1, defaultsenderaddress and primarymail
             * 
             */
            String newaddress = "boss@mydomain.com"; // introduce another domain, not shared
            changeduser = new User();
            changeduser.setId(ret.getId());
            changeduser.setEmail1(newaddress);
            //reuse change from above
            change.setUsrdata(changeduser);
            try {
                // this will throw an error since the new address is not in the aliases
                userport.change(change);
            } catch (Exception e) {
                System.out.println("ERROR: " + e.getMessage());
            }

            // now add the new address to the aliases and try again
            aliases = ret.getAliases();
            aliases.add(newaddress);
            changeduser.getAliases().addAll(aliases);
            userport.change(change);

            // control the result
            ret = userport.getData(ctx, auser, creds);
            aliases = ret.getAliases();
            // list all mail aliases of that user
            System.out.println("User has the following alias(es):" + aliases);
        } catch (com.openexchange.oxaas.context.InvalidDataExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.NoSuchContextExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.DuplicateExtensionExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.InvalidCredentialsExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.RemoteExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.StorageExceptionException e) {
            e.printStackTrace();
        } catch (InvalidDataExceptionException e) {
            e.printStackTrace();
        } catch (NoSuchContextExceptionException e) {
            e.printStackTrace();
        } catch (DuplicateExtensionExceptionException e) {
            e.printStackTrace();
        } catch (DatabaseUpdateExceptionException e) {
            e.printStackTrace();
        } catch (InvalidCredentialsExceptionException e) {
            e.printStackTrace();
        } catch (RemoteExceptionException e) {
            e.printStackTrace();
        } catch (NoSuchUserExceptionException e) {
            e.printStackTrace();
        } catch (StorageExceptionException e) {
            e.printStackTrace();
        } catch (CreateSharedDomainFaultException e) {
            e.printStackTrace();
        }
    }

}
Catchall account management

The next example shows how to manage catchall accounts. Please take into account that this is not necessarily enabled for your account.

package com.openexchange.oxaas.myclient;

import javax.xml.namespace.QName;
import com.openexchange.oxaas.context.OXResellerContextService;
import com.openexchange.oxaas.context.OXResellerContextServicePortType;
import com.openexchange.oxaas.extra.CreateDomainCatchallFaultException;
import com.openexchange.oxaas.extra.DeleteDomainCatchallFaultException;
import com.openexchange.oxaas.extra.DomainCatchall;
import com.openexchange.oxaas.extra.ListDomainCatchallsFaultException;
import com.openexchange.oxaas.extra.OXaaSService;
import com.openexchange.oxaas.extra.OXaaSService_Service;


/*
 * Example SOAP client for OXaaS OXResellerUserService
 * 
 * Create users in a context
 * 
 */
public class OXaaSCatchAllManagement {

    private static final QName CONTEXT_SERVICE_NAME = new QName("http://soap.reseller.admin.openexchange.com", "OXResellerContextService");
    private static final QName OXAAS_SERVICE_NAME = new QName("http://soap.oxaas.admin.openexchange.com/", "OXaaSService");

    public static void main(String[] args) {
        final String subadminname = "mysubadmin";
        final String subadminpw   = "secret";
        final String userlogin    = "auser";
        final String ctxname      = subadminname + "_myctx";
        
        OXResellerContextService contextservice = new OXResellerContextService(OXResellerContextService.WSDL_LOCATION, CONTEXT_SERVICE_NAME);
        OXResellerContextServicePortType contextport = contextservice.getOXResellerContextServiceHttpSoap11Endpoint();
        OXaaSService_Service oxaasservice = new OXaaSService_Service(OXaaSService_Service.WSDL_LOCATION, OXAAS_SERVICE_NAME);
        OXaaSService oxaasport = oxaasservice.getOXaaSServiceSOAP();  
        
        
        // We need to use the ResellerContextService SOAP client stub to retrieve the context id
        com.openexchange.oxaas.context.rmi.dataobjects.Credentials ctxCreds = new com.openexchange.oxaas.context.rmi.dataobjects.Credentials();
        com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext ctxCtx = new com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext();
        ctxCreds.setLogin(subadminname);
        ctxCreds.setPassword(subadminpw);
        ctxCtx.setName(ctxname);

        try {
            // we only have the name of the context, so we need to retrieve its id, first using ResellerContextService
            com.openexchange.oxaas.context.reseller.soap.dataobjects.ResellerContext ctxRet = contextport.getData(ctxCtx, ctxCreds);

            com.openexchange.oxaas.extra.Credentials oxaasCtxCreds = new com.openexchange.oxaas.extra.Credentials();
            oxaasCtxCreds.setLogin(subadminname);
            oxaasCtxCreds.setPassword(subadminpw);
            
            /*
             * Note: this will throw an error
             * oxaas_catchall_domain capability not available for context XXX, user YYY in brand ZZZ
             * unless you have domain catchall in your contract
             */
            oxaasport.createDomainCatchall(ctxRet.getId(), "example.com", userlogin, oxaasCtxCreds);
            
            for(final DomainCatchall dc : oxaasport.listDomainCatchalls(ctxRet.getId(), oxaasCtxCreds) ) {
                System.out.println("Catchall account for domain " + dc.getDomain() + " is " + dc.getLogin());
            }
            
            // cleanup
            oxaasport.deleteDomainCatchall(ctxRet.getId(), "example.com", userlogin, oxaasCtxCreds);
        } catch (com.openexchange.oxaas.context.InvalidDataExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.NoSuchContextExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.DuplicateExtensionExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.InvalidCredentialsExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.RemoteExceptionException e) {
            e.printStackTrace();
        } catch (com.openexchange.oxaas.context.StorageExceptionException e) {
            e.printStackTrace();
        } catch (ListDomainCatchallsFaultException e) {
            e.printStackTrace();
        } catch (DeleteDomainCatchallFaultException e) {
            e.printStackTrace();
        } catch (CreateDomainCatchallFaultException e) {
            e.printStackTrace();
        }
    }

}

Perl

Standalone example: createOXaaSContext

http://software.open-xchange.com/products/appsuite/doc/oxasservice/createOXaaSContext.pl

Standalone example: createOXaaSUser

http://software.open-xchange.com/products/appsuite/doc/oxasservice/createOXaaSUser.pl

Standalone example: changeOXaaSUserPermissions

http://software.open-xchange.com/products/appsuite/doc/oxasservice/changeOXaaSUserPermissions.pl


OXaas APS(1.2) package

Just download the APS package as mentioned here. When you extract the zip file, you will find the perl code within the directory scripts.

OXSOAP.pm
SOAP Wrapper functions
configure-alias.pl
Mail alias management
configure-catchall.pl
Catchall mail alias management
configure-mbox.pl
User management
configure.pl
Context management
verify-account.pl
check for login existence (existsLogin)
verify-catchall.pl
check for catchall existence
verify-shared.pl
shared mail alias checks