"Not permitted to access this resource" error since update to 4.6.2

Mathieu Yargeau May 30, 2016

We have a small Bitbucket plugin that generates a url and adds it in a PR comments when creating the PR or when adding a new commit in an existing PR. Everything was working fine with Bitbucket 4.4.2, but we updated to 4.6.2 this weekend and now it gives me an exception: 

com.atlassian.bitbucket.AuthorisationException: Not permitted to access this resource. Caused by: org.springframework.security.access.AccessDeniedException: Access is denied.

 

The error happens only when added a new commit in a PR, not when the PR is created. I have a log line before the comment is added (in both case).

 

Log when the PR is created:

2016-05-30 15:25:31,046 DEBUG [AtlassianEvent::thread-2] myargeau @1XK26FOx925x82651x26 1vj7sru 10.128.33.240,10.129.30.23 "POST /projects/BUIL/repos/rdv_stashplugin_buildcommander/pull-requests HTTP/1.1" RDV_PR_DOC_LINK Adding doc link to PR 'dfdf'

Log when new commit is added

2016-05-30 15:25:51,926 DEBUG [AtlassianEvent::thread-5] RDV_PR_DOC_LINK Adding doc link to PR 'dfdf'
2016-05-30 15:25:51,928 ERROR [AtlassianEvent::thread-5] RDV_PR_DOC_LINK Exception with UpdateDocLinkOp! You are not permitted to access this resource

 

Here is my plugin code:

public class DocLink
{
	private final SecurityService securityService;
	private final PullRequestService pullRequestService;
	private final LoggingService loggingService;
	private final RepoSettingsService repoSettingsService;
	
	private static final String SHA_PLACEHOLDER = "{SHA}";
	private static final String DOC_BUILD_FOLDER = "file://///Somelink/build_docs";
	private static final String DOC_FILE_NAME = "index.html";
	private static final String URL_TITLE = "Documentation: ";
	private static final String DOC_URL = DOC_BUILD_FOLDER  + "/" + SHA_PLACEHOLDER + "/" + DOC_FILE_NAME;
	
	private static final String LOGGER_NAME = "RDV_PR_DOC_LINK";
	private static final Logger log = LoggerFactory.getLogger(LOGGER_NAME);
	
	public DocLink(SecurityService securityService, PullRequestService pullRequestService, 
			LoggingService loggingService, RepoSettingsService repoSettingsService)
    {
    	this.securityService = securityService;
    	this.pullRequestService = pullRequestService;
    	this.loggingService = loggingService;
    	this.repoSettingsService = repoSettingsService;
    }
	
	//Plugin entry point. Triggered when a Pull Request has a new commit or new Target Repository.
	@EventListener
	public void onPullRequestRescoped(PullRequestRescopedEvent event)
	{
		PullRequest pullRequest = event.getPullRequest();
		if (event.getPreviousFromHash().equals(pullRequest.getFromRef().getLatestCommit()))
		{
			//No new commits were added to the pull request
			return;
		}
		TriggerUpdateDocLink(pullRequest);
	}
	
	//Plugin entry point. Triggered when a Pull Request is created.
	@EventListener
	public void onPullRequestOpened(PullRequestOpenedEvent event)
	{
		TriggerUpdateDocLink(event.getPullRequest());
	}
	
	/**
	 * Lauches the documentation link update process.
	 * @param The pull request.
	 */
	private void TriggerUpdateDocLink(PullRequest pullRequest)
	{
		try
    	{
    		securityService.withPermissions(EnumSet.of(Permission.SYS_ADMIN, Permission.LICENSED_USER), "Log level set").call(SetLogLevelOp());
		}
		catch(Throwable e)
		{
			log.error("Exception with SetLogLevelOp! " + e.getMessage());
		}
		
		try
    	{
    		securityService.withPermissions(EnumSet.of(Permission.SYS_ADMIN, Permission.LICENSED_USER), "Log level set").call(UpdateDocLinkOp(pullRequest));
		}
		catch(Throwable e)
		{
			log.error("Exception with UpdateDocLinkOp! " + e.getMessage());
		}
	}
	
	/**
	 * Updates the documentation link in the pull request.
	 * @param The pull request.
	 */
	private Operation UpdateDocLinkOp(final PullRequest pullRequest)
    {
    	return new UncheckedOperation<Boolean>()
    	{
    		@Override
    		public Boolean perform()
    	    {
    			RepositorySettings settings = repoSettingsService.getValidatorSettings(pullRequest.getToRef().getRepository());
    			if(!settings.isDocLinkActivated())
    			{
    				return true;
    			}
    			
    			log.debug("Adding doc link to PR '" + pullRequest.getTitle() + "'");
    			
    	    	String comment = URL_TITLE + DOC_URL.replace(SHA_PLACEHOLDER, pullRequest.getFromRef().getLatestCommit());
    	    	
    	    	pullRequestService.addComment(pullRequest.getToRef().getRepository().getId(), pullRequest.getId(), comment);
    	    	
    			return true;
    	    }
    	};
    }

 

I don't think I am doing something wrong since it was working with Bitbucket 4.1.0 to 4.4.2 (and with Stash 3.x before I converted the code for it). I am also careful to give sys admin rights to the operation call since I want the plugin to be able to do anything, so I don't understand why there is an access denied error.

 

It's the pullRequestService.addComment code line that throws the exception.

 

Did something change in between 4.4.2 and 4.6.2 that changed that behavior? (I checked the changelogs, but didn't see anything relevant)

 

 Complete stacktrace of the exception, if this helps (I don't seem to be able to insert it on several lines)

com.atlassian.bitbucket.AuthorisationException: You are not permitted to access this resource  at com.atlassian.stash.internal.aop.ExceptionRewriteAdvice.afterThrowing(ExceptionRewriteAdvice.java:36) ~[bitbucket-platform-4.6.2.jar:na]  at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26) [atlassian-plugins-core-4.1.8.jar:na]  at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56) ~[na:na]  at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60) ~[na:na]  at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70) ~[na:na]  at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53) ~[na:na]  at org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57) ~[na:na]  at com.atlassian.stash.internal.build.DefaultBuildStatusService.validateUser(DefaultBuildStatusService.java:102) ~[na:na]  at com.atlassian.stash.internal.build.DefaultBuildStatusService.getSummary(DefaultBuildStatusService.java:65) ~[na:na]  at com.atlassian.stash.internal.build.hook.RequiredBuildsMergeCheck.getBuildStats(RequiredBuildsMergeCheck.java:65) ~[na:na]  at com.atlassian.stash.internal.build.hook.RequiredBuildsMergeCheck.check(RequiredBuildsMergeCheck.java:40) ~[na:na]  at com.atlassian.stash.internal.pull.DefaultMergeRequestCheckService.doCheck(DefaultMergeRequestCheckService.java:72) [bitbucket-service-impl-4.6.2.jar:na]  at com.atlassian.stash.internal.pull.DefaultMergeRequestCheckService.checkMergeability(DefaultMergeRequestCheckService.java:56) [bitbucket-service-impl-4.6.2.jar:na]  at com.atlassian.stash.internal.pull.DefaultPullRequestService.canMerge(DefaultPullRequestService.java:268) [bitbucket-service-impl-4.6.2.jar:na]  at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26) [atlassian-plugins-core-4.1.8.jar:na]  at com.izymes.workzone.listener.RepoEventListener.notifyIfConflicted(RepoEventListener.java:565) [plugin.716503526933588399.workzone-4.1.2_1456591385000.jar:na]  at com.izymes.workzone.listener.RepoEventListener.onPullRequestRescopedEvent(RepoEventListener.java:396) [plugin.716503526933588399.workzone-4.1.2_1456591385000.jar:na]  at com.atlassian.event.internal.SingleParameterMethodListenerInvoker.invoke(SingleParameterMethodListenerInvoker.java:36) [atlassian-event-3.0.0.jar:na]  at com.atlassian.stash.internal.event.AsyncBatchingInvokersTransformer$AsyncInvokerBatch.invoke(AsyncBatchingInvokersTransformer.java:94) [bitbucket-platform-4.6.2.jar:na]  at com.atlassian.event.internal.AsynchronousAbleEventDispatcher$1$1.run(AsynchronousAbleEventDispatcher.java:46) [atlassian-event-3.0.0.jar:na]  at com.atlassian.sal.core.executor.ThreadLocalDelegateRunnable.run(ThreadLocalDelegateRunnable.java:34) [sal-core-3.0.6.jar:na]  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_51]  at java.lang.Thread.run(Thread.java:745) [na:1.8.0_51]  ... 94 frames trimmed Caused by: org.springframework.security.access.AccessDeniedException: Access is denied  at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83) ~[spring-security-core-3.2.7.RELEASE.jar:3.2.7.RELEASE]  ... 23 common frames omitted

1 answer

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

1 vote
Answer accepted
Ulrich Kuhnhardt [IzymesDev]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 30, 2016

You need to perform pullRequestService.addComment(..) as a user by impersonating a chosen user. If I understand the current Bitbucket implementation correctly the PullRequestRescoped event is not associated with a user and thus changes to PR are not permitted.

Use one of the securityService methods to escalate permissions or impersonate a user.


Good Luck - Ulrich, [Izymes]

Mathieu Yargeau May 31, 2016

Ok, I'll try impersonating the user doing the commit, I have used that function before so it shouldn't be hard. Any ideas on why it was working, and still is, with previous versions? 

Mathieu Yargeau May 31, 2016

Just tried it and it works. Thank you for the suggestion. However, I still don't understand what changed to make it not work anymore...

TAGS
AUG Leaders

Atlassian Community Events