How to pass authentication context to clone a git repo using RepositoryCloneLinksRequest.Builder & GitCloneBuilder

Hi,

I am stuck with a seemingly simple task, “How to clone a git repo using RepositoryCloneLinksRequest.Builder / GitCloneBuilder” through my plugin.

I am able to get the link of the URL that I want to clone as below
RepositoryCloneLinksRequest repoclonelinkreq = new RepositoryCloneLinksRequest.Builder().repository(repo).protocol("http").user(null).build();

How do I proceed next to clone the repo to some /tmp directory on my sever ?

I also tried using the below

gitCommandBuilderFactory.builder(repo).workingDirectory(tmpDir).clone().normal().branch(targetBranch).checkout(true).build(); unsuccessfully.

Are there some useful links of a sample/example code that I can see to figure out how to achieve this?

Ok so, I think below is the right way of doing it.

gitCommandBuilderFactory.builder().clone().normal().directory(dir).branch(targetBranch).origin(repositoryURL).checkout(true).build().call();

I wonder how to pass the authentication context ?

This is what I have got so far, I am able to trigger a clone for a repo/branch. But I am not able to pass the authentication context i.e the password.

Below results in a prompt…
Password for ‘http://admin@localhost:7990’: << Prompts me for password on the console and the command times out giving me an exception.

RepositoryCloneLinksRequest rclr =  new RepositoryCloneLinksRequest.Builder().repository(getRepository(req)).protocol("http").
user(authenticationContext.getCurrentUser()).build();

String repositoryURL = repositoryService.getCloneLinks(rclr).iterator().next().getHref();

gitCommandBuilderFactory.builder().clone().normal().directory("/XYZ").branch(targetBranch).origin(repositoryURL).checkout(true).build().call();

Result:

Then I came across the below link, I wonder if it is possible to pass the authentication context of the logged in user for cloning a repository…
https://confluence.atlassian.com/bitbucketserver/personal-access-tokens-939515499.html

@sylvie any hint that you can give ?

Ok, so I think the HTTP/HTTPs would always ask for git password for cloning. Using SSH works fine with the authentication context provided and does not prompt for password.

RepositoryCloneLinksRequest rclr =  new RepositoryCloneLinksRequest.Builder().repository(getRepository(req)).protocol("ssh").
user(authenticationContext.getCurrentUser()).build();

Hello,

I’m cloning a repository from within a BitBucket plugin and I’m having similar issues so I was wondering if you had made any further progress.

If I use HTTP in the development environment, windows will prompt me for a git user/pass when the plugin attempts to clone (using the same gitCommandBuilderFactory process that you use above). However, in production (on a BB server accessed remotely), I obviously don’t get this prompt and eventually the clone operation times out.

The only way I can think of circumventing this issue is to ask the plugin user for his bitbucket credentials at the moment of cloning and insert these into the clone URL eg.

https://username:password@host/context/scm/project_1/repo_1.git

As for SSH access, I’m stumped. Would I need to generate an ssh key for the plugin and then add the public key to BB and then specify the private key when cloning (saving it in the plugin preferences). I don’t think the GitCommandBuilderFactory method allows for this so I presume I’d need to find a way to run the Git clone whilst specifying a private key and then execute that “manually” (using ProcessBuilder or something). Yikes.

I’m fumbling in the dark here, any help would be much appreciated!

Cheers,

Also, if one simply injects the user credentials into the HTTP clone url, these credentials show up in the logs when the user/pass is wrong (which is obviously an issue).

After some poking around in the sources I found the GitAuthHelper class (6.7.0+). So now I’m cloning (from within my JobRunner) using the following:

// given
// GitCommandBuilderFactory builderFactory
// GitAuthHelper gitAuthHelper

GitScmCommandBuilder gitCmdBuilder = (GitScmCommandBuilder) gitAuthHelper.configure(
            builderFactory.builder(), username, password, null);

gitCmdBuilder
    .clone().normal()
    .origin(cloneUrl)
    .branch(branchName)
    .directory(sourceDir)
    .build()
    .call()

The problem with this approach is that it seems to cache the Git credentials in the host keychain or something. So after one successful cloning operation, further cloning using an incorrect password works (which isn’t expected behaviour).

Maybe I’d be better off using JGit instead…

In my Bitbucket Data Center plugin I needed a clone to do rebases on behalf of the user. As of Bitbucket 7.14.0 there is now a “GitWorkTreeBuilder” feature to help with that. Not sure if this would help you.

GitWorkTreeBuilder builder = gitWorkTreeBuilderFactory.builder(repository);

Atlassian wrote some in-depth documentation on how to use this feature:

https://developer.atlassian.com/server/bitbucket/how-tos/using-worktree-api-to-create-commits/

1 Like