/ Development  

Alert; The shocking truth behind anonymous access revealed

Hi there AppWorks fans,

Welcome to a new installment of AppWorks tips.

This week a highly interested “Anonymous” topic…

First a note upfront: DON’T YOU EVER IMPLEMENT THIS POST AT YOUR CUSTOMERS❗

It’s a topic about (mis)using our beloved platform trying to access it anonymously. WHAT!? How is this possible? Also, behind an OTDS authentication instance? Yes, my friend. Not out of the box, but with smart hacks everything is possible! That’s also exactly why I want to expose this, so you don’t have to! Be warned!…Use the platform wisely and don’t expose things for your convenience on an implementation part. It will haunt you down…trust me!


Let get right into it…

If you ever took close attention to the AppWorks platform you might have seen it via the ‘LDAP Explorer’ artifact within your organization. Have you ever seen this screenshot?

anonymous_001

You can’t login with this account, but according to the documentation it’s a requirement to have this account enabled (especially) when it gets to a Single-Sign-On (SSO) setup. See “Authentication and single sign-on properties” section in the administration manual and the wcp.properties with key-value pair com.eibus.web.authentication.enableanonymousaccess=true. SSO is not a topic for now, but as the account is enabled by default, we’ll can also make use of it! How? Watch and learn!

You will also not find this account in the ‘User Manager’ artifact to assign a role to it…That would be too easy AND you still can’t login, but what if I tell you the “AppWorks Gateway” accepts anonymous calls from outside…By default! Now it’s getting interesting! 🤠

“AppWorks Gateway” is the entry point for all service requests and responsible for routing it to the responsible service group and eventually managed by the related service container.

But how (on earth) can we do an “Anonymous” call against the gateway of the platform? How can we even do a call from the outside against the gateway? Well, you can find the answer to this last question in the high-value post “Calling SOAP and ReST via Postman (incl. authentication)”.

To give this post some “balls” where we first make sure to expose a webservice over a BPM (as that’s the place where we are flexible enough to do anything else) to the outside world; This is also a regular task you need to understand, to make your “business analyst” happy once he starts to communicate in terms of loosely-coupled-SOA-grid-architectures!?!?
AND because I also see people using SoapUI (instead of Postman), we’ll give that one a chance too…Because we can!

This post assumes you have SoapUI up and running; Don’t fall into the trap of downloading “ReadyAPI”…We’re using the opensource version!


Implementation time

Dive into your AppWorks designer with a ready to use workspace and related project. It’s time to craft our first BPM type of document; Nothing fancy…Just a start-, activity-, and end-construct. I save it in the bpms folder of my project with name bpm_dummy.

Next step is to generate a webservice out of it. For this, you can right-click the BPM (in your project), go the ‘Execution’, and ‘Generate Web Service’ with input like this:

anonymous_002

Watch the naming conventions and the location in this screen!

Have a look in the project again where you can now view the WSDL definition for this service:

anonymous_003

Save it locally on your system as we need it once we start to play with SoapUI!

You can view mine here

Do a first deployment now to make it all available in runtime…There is no need to assess it (yet!)

Now we need a new service container that can manage our BPM service call (internal from within AppWorks, but also from external applications). Open the ‘System Resource Manager’ artifact and create a new service group with this input:

  • Connector: Business Process Management
  • Service group name: sg_bpm
    • Also select our new service as service interface
  • Service name: sc_bpm
    • Startup automatically
    • Assign to the OS
  • Admin Database: Use DSO ‘Cordys System’ under the ‘system’ organization
    • Use this DSO also for the ‘Scheduler’ database (the other tab!)

Comment me if this task was just one step tooooo far! This is a helping screenshot:

anonymous_004

It’s time to evaluate our service (internally from within AppWorks!) with the ‘Web Service Interface’ explorer:

anonymous_005

You see the result of a new BPM instance which is viewable via the PIM:

anonymous_006

You can add the ‘User’ column yourself; Note who executed it!


The SoapUI project

Start the SoapUI tool and create a new Soap project. Point to the WSDL file which we saved locally; Like this:

anonymous_007

Hit OK and you see a magic sample request generation passing by:

anonymous_008

Nothing fancy, but it’s not pointing to a valid AppWorks URL. So, let’s update the URL to http://192.168.56.107:8080/home/appworks_tips/com.eibus.web.soap.Gateway.wcp and do a first request (externally from outside AppWorks!) with an interesting response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:def="http://schemas.cordys.com/default">
<soapenv:Header>
<header xmlns="http://schemas.cordys.com/General/1.0/">
<msg-id>080027f2-140d-a1ef-8102-4cbcf3c09c3e</msg-id>
<messageoptions noreply="true"/>
</header>
</soapenv:Header>
<soapenv:Body>
<soapenv:Fault>
<faultcode xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/">
ns0:Client
</faultcode>
<faultstring xml:lang="en-US">
Anonymous access is denied for the Web service operation 'bpm_dummy'.
</faultstring>
<faultactor>http://schemas.cordys.com/default</faultactor>
...
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>

Looks like we’ve just fired on “Anonymous” request against our platform Gateway…YOLO! 🙈 Well, I indeed didn’t do any authentication magic in SoapUI which matches the outcome:

anonymous_009

So, we can access it, but we don’t have any permission on our generated webservice! AND…if you understand the platform, that’s runtime security based on a role! Let’s dive back into AppWorks, create a new ‘Role’ type of document with name fun_anonymous:

anonymous_010

After this we’ll set the runtime security for the interface…

anonymous_011

…where we add our new role with the correct permission:

anonymous_012

This runtime security change requires a publication!

Are we there yet? I don’t think so as we need to apply this role to a user; AND guess what user this is? Yes, the ‘anonymous’ user…Sure, but this user is missing in the ‘User Manager’!? So how? Well, first start with the same ‘User Manager’ artifact and find the role (after you published it…thank you!) in the right panel to take note of the below red-arrowed string value (which you need to copy!):

anonymous_013

Now, dive again in the ‘LDAP Explorer’ artifact, find the anonymous user from that perspective (for your organization), and follow the red arrows to add the role:

anonymous_014

AGAIN, DON’T DO THIS AT YOUR CUSTOMER!!

Back to SoapUI to trigger our request again…With a new error:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:def="http://schemas.cordys.com/default">
<soapenv:Header>
<header xmlns="http://schemas.cordys.com/General/1.0/">
<msg-id>080027f2-140d-a1ef-8103-423126532b43</msg-id>
<messageoptions noreply="true"/>
</header>
<bpm xmlns="http://schemas.cordys.com/bpm/instance/1.0">
<instance_id>080027f2-140d-a1ef-8103-4231fc1d2b43</instance_id>
</bpm>
</soapenv:Header>
<soapenv:Body>
<soapenv:Fault>
<faultcode xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/">
ns0:Server
</faultcode>
<faultstring xml:lang="en-US">
Access is denied for the Web service operation 'ExecuteProcess'.
You do not have permissions to access some of the resources required
for your request. Contact the administrator.
</faultstring>
<faultactor>http://schemas.cordys.com/bpm/execution/1.0</faultactor>
<detail>
<cordys:FaultDetails
xmlns:cordys="http://schemas.cordys.com/General/1.0/">
<cordys:LocalizableMessage>
<cordys:MessageCode>
Cordys.BPM.Messages.webServiceAccessDenied
</cordys:MessageCode>
<cordys:Insertion>ExecuteProcess</cordys:Insertion>
</cordys:LocalizableMessage>
</cordys:FaultDetails>
<cordys:FaultRelatedException
xmlns:cordys="http://schemas.cordys.com/General/1.0/">
RuntimeAuthorizationException: The user 'cn=anonymous,cn=organizational
users,o=appworks_tips,cn=cordys,cn=defaultInst,o=awtips.com' is not
authorized to perform the operation 'INITIATE' on one of the process
instances in the '[080027f2-140d-a1ef-8103-4231fc1d2b43]'.
...
</cordys:FaultRelatedException>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>

Right, so we can access the service call now, but our execution of our BPM (aka “Process”) is failing…Again, that’s runtime security; This time on the BPM:

anonymous_015

Publish the BPM and try again in SoapUI:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:def="http://schemas.cordys.com/default">
<soapenv:Header>
<header xmlns="http://schemas.cordys.com/General/1.0/">
<msg-id>080027f2-140d-a1ef-8103-7d73dae91c2f</msg-id>
<messageoptions noreply="true"/>
</header>
<bpm xmlns="http://schemas.cordys.com/bpm/instance/1.0">
<instance_id>080027f2-140d-a1ef-8103-7d73dfff9c2f</instance_id>
</bpm>
</soapenv:Header>
<soapenv:Body>
<bpm_dummyResponse xmlns="http://schemas.cordys.com/default">
<data>
<instance_id>080027f2-140d-a1ef-8103-7d73dfff9c2f</instance_id>
</data>
</bpm_dummyResponse>
</soapenv:Body>
</soapenv:Envelope>

That’s a BPM instance! Viewable from the PIM…AND…Watch the person triggering it:

anonymous_016

Now let’s assume you have 1K BPM instances per day in production and no name to point to with the finger when $#%^&^%# hits the fan…Trust me, I don’t want to be the administrator (nor the manager) at that point in time; God, bless you with your system and solution. 😇


Concluding thoughts

  1. You could directly add the anonymous user to the service ws_bpm_dummy and the ExecuteProcess service (from the ‘Web Service Interface Explorer’ artifact), but that’s the “old” way of applying the runtime security!
  2. You see me sharing the WSDL file by hand. It’s also possible to upload it to your project and publish it as web-asset into runtime. Via the path the WSDL is always available via the regular AppWorks URLs!
  3. What if you can’t authenticate per user? Well, don’t use anonymous calls, but use a “service” user…That’s still not the most recommended idea, but it’s already a better path to take. If possible, always authenticate with valid credentials to the platform; Whatever it takes!

An un-recommended “DONE” which I hope you’ll never use within your projects! It’s great to understand the concept, but don’t fall into the trap. See this post as a warning message as this is exactly how to NOT use the platform. Be clear about your implementation choices, provide solid advice, and build honest solutions where the platform is at its best. With proper authentication you never get security guard on your neck asking questions about certain situations. Learn from this post and I see you next week in a new AppWorks Tips topic. Cheers! 🍺

Don’t forget to subscribe to get updates on the activities happening on this site. Have you noticed the quiz where you find out if you are also “The AppWorks guy”?