Can I call synchroniseUserDirectories (ConfluenceRpc) via REST, SOAP or XML-RPC? - rest

I am using Confluence 4.2.5 (build 3284) with CAS SSO connected to my LDAP server and would like to be able to call synchroniseUserDirectories() from the LDAP server when a user changes their password so that the change is instantaneous.
The way it works now is that users have to wait for the Confluence to run it's periodic LDAP synchronization which can be disconcerting for them.
I have tried using the XML-RPC interface to call changeUserPassword() (as an administrator) but it doesn't work. The operation raises an exception "Error changing password for user ...". I presume that that is because the user is defined in the LDAP but I can't tell for sure because the exception message wasn't clear about the cause.
Here is example code that I would like to be able to use. It doesn't work.
#!/usr/bin/env python
import xmlrpclib
url = 'https://docs.example.com'
admin_user = 'frobisher'
admin_pass = 'supersecretstuff'
username = 'bigbob'
new_password = 'bigbobsbigsecret'
server = xmlrpclib.ServerProxy(url + '/rpc/xmlrpc')
token = server.confluence2.login(admin_user, admin_pass)
# CITATION: https://developer.atlassian.com/display/CONFDEV/Remote+Confluence+Methods
# this doesn't exist but would be my preferred approach.
# It raises a NoSuchMethodException exception.
server.confluence2.synchroniseUserDirectories(token)
# this throws a general exception, because of the LDAP? The message
# wasn't clear about the source of the problem.
#server.confluence2.changeUserPassword(token,
# username,
# password)
server.confluence2.logout(token)
Is there any way to do this using SOAP or REST? I was concerned about REST because it sounds like it is still a prototype.
If none of those approaches will work, can it be done with a simple plugin considering that this must be a push operation from the LDAP server to the Confluence server? I have no experience writing plugins but I do some java work occasionally.
Any hints would be greatly appreciated.

The short answer is "no". The ability to synchronise remote user directories is not exposed as a remote operation in Confluence.
The long answer is "yes", you can write a plugin to do this. If you're already familiar with java, then perhaps the best answer is to just show you some source code I've written that performs a similar function: https://bitbucket.org/jaysee00/confluence-user-sync-api This plugin gives you SOAP, XML-RPC and JSON-RPC methods to force an individual user account to be synced in to Confluence from a remote directory.
That might suit your purposes as-is, but I imagine it would be possible to edit the source of this plugin and change it to synchronise an entire directory, too.

Related

What is the "[full path]" component of the SSL Certificate Authority given by MySQL and PostgreSQL (boto3) calls in the AWS docs?

In the AWS documentation for "Connecting to your DB instance using IAM authentication and the AWS SDK for Python (Boto3)", the following call is made to both psycopg2.connect (shown) and mysql.connector.connect:
conn = psycopg2.connect(host=ENDPOINT, port=PORT, database=DBNAME, user=USR, password=token, sslmode='prefer', sslrootcert="[full path]rds-combined-ca-bundle.pem")
cur = conn.cursor()
cur.execute("""SELECT now()""")
query_results = cur.fetchall()
print(query_results)
I see some discussion about the ssl_ca path (here and here) and what those bundles are used for. But none of the three links I've given here describe the [full path] component given by the AWS docs, or where it is pointing to. My current guess (from the second link) is this URL, but I'd like to be sure.
Additionally, what are the advantages to having this bundle downloaded to the remote EC2 on which these Python 3 (boto3) scripts are running?
EDIT: By the way, the above call to psycopg2.connect is working in Jupyter with Python 3.9.5 on an EC2 currently, with the [full path] written as-is...
You should replace the '[full path]' with the filesystem path (directory path) to where you saved the pem file when you downloaded it (from that last URL you gave) to the local computer.
The advantage of using it is that your client will verify it connected to the correct database, and not some malicious system which is intercepting your traffic. I don't how advantageous you consider this: if someone has compromised Amazon enough to be intercepting their internal traffic, they might also have compromised their CA as well. But there is at least some possibility they did one without the other.
Your code as shown does not work for me, because ssl_ca is not how it is spelled. Assuming you used the code actually given at your first link for PostgreSQL:
sslmode='prefer', sslrootcert="[full path]rds-combined-ca-bundle.pem"
Then the reason it works despite the bogus path is that "prefer" means it doesn't care if the rootcert is missing, it just skips validating in that case. If you change it to 'verify-full', then presumably it would stop working.

InternalServiceFault when trying to connect SPGo to SP Online in VS Code

I'm trying to connect the SPGo plugin in Visual Studio Code to a Sharepoint Online site. There are lots of guides for this, for instance this one: https://medium.com/niftit-sharepoint-blog/saying-goodbye-to-sharepoint-designer-ac939a0b79ba
In short, I'm doing it like this:
Open VS Code
Open a local, empty folder)
SPGO: Configure workspace (follow guide, ending up with spgo.json
looking like the one I pasted)
SPGO: Populate local workspace (asking me for credentials and I plot
it in O365 style (email and password).
Statusbar says "Populating workspace"
After about 10 seconds I get the pasted error in the output window (spgo)
I'm using newest versions:
Visual Studio Code 1.37.1
SPGo 1.4.3
I have tried various sites in my tenant and I know they are up. I am Site Collection Administrator for the sites. I know the credentials are correct, of course. the remoteFolders and publishingScope doesn't affect anything, when changed. I assume authenticationType should be "Digest".
SPGo.json:
{
"sourceDirectory": "src",
"sharePointSiteUrl": "https://domain.sharepoint.com/sites/SiteName",
"publishingScope": "Major",
"authenticationType": "Digest",
"remoteFolders": [
"/SitePages/"
]
}
I don't get any files in the local folder, instead I get an error in the output:
================================ ERROR ================================
<s:Fault>
<s:Code>
<s:Value>s:Receiver</s:Value>
<s:Subcode>
<s:Value xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault</s:Value>
</s:Subcode>
</s:Code>
<s:Reason>
<s:Text xml:lang="en-US">The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework SDK documentation and inspect the server trace logs.</s:Text>
</s:Reason>
</s:Fault>
Error Detail:
----------------------
{}
===============================================================================
Sorry I missed this post for so long. First- thanks for the detailed write-up. This is the first time I've seen this specific issue with SPGo, so I do not know for sure what is the root cause.
Couple questions:
Are you using ADFS Authentication with your Office 365/SharePoint Online instance?
Are you able to use Addin-Only Authentication on this SP Site?
SPGo should be able to automatically work with ADFS in SharePoint Online but, as a fall-back, you could use Addin-Only Authentication. In this scenario you would create a ClientId and ClientSecret pair for the SharePoint Site Collection you are accessing and authenticate using those credentials. The ClientId would act as your UserName, and the ClientSecret would be your password.
Under the covers, I am using the node-sp-auth package for user authentication. Sergei (s-KaiNet on Github) has a great write-up on how to enable Addin-Only Authentication in SharePoint Online on his site, which you can find here.
Thanks for using SPGo!

How to get version using EWS powershell

$Service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1);
In the above line Exchange2013_SP1 is hardcoded. Using powershell how can I dynamically get the version when running the script?
In the Code provided, you are trying to create an instance of WebServices.Data.ExchangeService(something similar to this), specifying exchange version via ExchangeVersion Enum.
However - the query after that is about knowing how to obtain Exchange Version via PowerShell. Probably this is very well documented and googling shows many hits about checking Exchange Version:
https://blogs.msdn.microsoft.com/deva/2012/04/27/powershell-determine-version-number-build-number-and-service-pack-of-exchange-server/
https://blog.jasonsherry.net/2012/12/27/get-exchangever/
If you make a request like Binding to the Inbox of a Mailbox in the response the build details of the CAS Server the processed the response is returned https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.exchangeservicebase.serverinfo(v=exchg.80).aspx and exposed via the ExchangeService Class this can be used to tell the CU that's been applied to the Target and is the most useful thing if you trying to track errors etc.
EWS Schema version (which is what you have hardcoded) and Server versions are two different things so I would suggest you read https://msdn.microsoft.com/en-us/library/office/dn741586(v=exchg.150).aspx . Autodiscover can be used to find the highest EWS Schema version of CAS server.

Proxy URL 'incache....com:8080' does not contain a valid hostname

Recently I was forced to switch from SVN to TFS.
I'm trying to get this working with TEE on our RedHat box.
Any action seems to end with something like this:
user#rh: tf -map $/XX/XX . -workspace:app-job -server:http://tfs.domain.com:8080/tfs/TFS2008/ -profile:TFS1_PRF_C
Password:
An error occurred: Proxy URL 'incache.domain.com:8080' does not contain a valid hostname.
Could someone help with that?
Your question is a little vague about what you expect to happen here (are you supposed to be using an HTTP proxy to access your TFS server? Or is the problem that it's assuming your HTTP proxy?)
I'm going to assume that you do not need to use an HTTP proxy to access your internal TFS server, since in most corporate environments your proxy is used to get outside the network, not inside. By default, the Team Explorer Everywhere CLC does try to use your system HTTP proxy, however this is configurable in your connection profile.
In order to override your default system HTTP proxy for that profile, you can set the profile property httpProxyIgnoreGlobal to true:
tf profile -edit -boolean:httpProxyIgnoreGlobal=true TFS1_PRF_C

Perl SOAP::WSDL accessing HTTPS Unathorized error

I'm trying to generate a Perl library to connect to a WebService. This webservice is in an HTTPS server and my user has access to it.
I've executed wsdl2perl.pl several times, with different options, and it always fails with the message: Unauthorized at /usr/lib/perl5/site_perl/5.8.8/SOAP/WSDL/Expat/Base.pm line 73.
The thing is, when I don't give my user/pass as arguments, it doesn't even asks for them.
I've read [SOAP::WSDL::Manual::Cookbook] (http://search.cpan.org/~mkutter/SOAP-WSDL-2.00.10/lib/SOAP/WSDL/Manual/Cookbook.pod) and done what it says about HTTPS: Crypt::SSLeay is instaleld, and both SOAP::WSDL::Transport::HTTP and SOAP::Transport::HTTP are modified.
Can you give any hint about what may be going wrong?
Can you freely access the WSDL file from your web browser?
Can someone else in your network access it without any problems?
Maybe the web server hosting the WSDL file requires Basic or some other kind of Authentication...
If not necessary ,I don't recommend you to use perl as a web service client .As you know ,perl is a open-source language,although it do support soap protocol,but its support do not seem very standard.At first,its document is not very clear.And also ,its support sometimes is limited.At last,bug always exists here and there.
So ,if you have to use wsdl2perl,you can use komodo to step into the code to find out what happened.This is just what I used to do when using perl as a web service client.You know ,in the back of https is SSL,so ,if your SSL is based on certificate-authorized,you have to set up your cert path and the list of trusted server cert.You'd better use linux-based firefox to have a test.As I know ,you can set up firefox's cert path and firefox's trusted cert list.If firefox can communicated with your web service server succefully,then,it's time to debug your perl client.
To debug situations with Perl and SOAP, interpose a web proxy so you can see exactly what data is being passed and what response comes back from the server. You were getting a 401 Not authorized, I expect, but there may be more detail in the server response.
Both Fiddler http://docs.telerik.com/fiddler and Charles proxy https://www.charlesproxy.com/ can do this.
The error message you quote seems to be from this line :
die $response->message() if $response->code() ne '200';
and in HTTP world, Unauthorized is clearly error code 401, which means your website asks for a username and password (most probably, some website may "hijack" this error code to cater for other conditions like a filter on the source IP).
Do you have them?
If so, you can
after wdsl2perl has run, find in the created files where set_proxy() is called and change the URL in there to include the username and password like that : ...->set_proxy('http://USERNAME:PASSWORD#www.example.com/...')
or your in code, after instantiating the SOAP::WSDL object, call service(SERVICENAME) on it (for each service you have defined in your WSDL file), which gives you a new object, on which you call transport() to access the underlying transport object on which you can call proxy() with the URL as formatted above (yes it is proxy() here and set_proxy() above); or you call credentials() instead of proxy() and you pass 4 strings:
'HOSTNAME:PORT'
the realm, as given by the webserver but I think you can put anything
the username
the password