Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JENKINS-41348# BlueOcean specific CredentialsProvider #768

Merged
merged 21 commits into from
Feb 10, 2017

Conversation

vivek
Copy link
Collaborator

@vivek vivek commented Jan 31, 2017

Provides User store/scoped credentials by using appropriate properties
on OrganizationFolder.

Description

BlueOcean credentials provider is a proxy to credentials stored in user store.

This is how it works:

  • When an OrganizationFolder is created, we attach authenticated user's user Id and credential Id of the credential in authenticated user's store with USER scope.
  • Later, when job runs, it asks BlueOceanCredentialsProvider to give credentialId for the OrganizationFolder created in previous step, it looks for these properties and returns right Credentials object by looking in to user's store.
  • A github OrganizationFolder configuration page on classic lists the BlueOcean Provider credential

image

Changes to credential creation for git pipeline flow (for @cliffmeyers)

curl -v -XPOST -u admin:admin -H ‘content-type: application/json’ http://localhost:8080/jenkins/blue/rest/organizations/jenkins/credentials/user/

{
  "credentials" : {
    "privateKeySource" : {
      "privateKey" : "abcabc1212",
      "stapler-class" : "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource"
    },
    "passphrase" : "ssh2",
    "scope" : "USER",
    "domain" : "blueocean-git-domain",
    "description" : "ssh2 desc",
    "$class" : "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey",
    "username" : "ssh2"
  }
}

There are three changes:

  • POST URL is changed to /jenkins/blue/rest/organizations/jenkins/credentials/user/
  • domain element in request body: for git use case its recommended UI passes domain name, for example 'blueocean-git-domain'. If its not supplied this credential will be created in default domain 'blueocean-domain'.
    See JENKINS-41348.
  • scope element in request body should be set to USER.

Submitter checklist

  • Link to JIRA ticket in description, if appropriate.
  • Change is code complete and matches issue description
  • Appropriate unit or acceptance tests or explanation to why this change has no tests
  • Reviewer's manual test instructions provided in PR description. See Reviewer's first task below.
  • Ran Acceptance Test Harness against PR changes.

Reviewer checklist

  • Run the changes and verified the change matches the issue description
  • Reviewed the code
  • Verified that the appropriate tests have been written or valid explanation given

@reviewbybees

Provides User store/scoped credentials by using appropriate properties
on OrganizationFolder.
@i386
Copy link
Contributor

i386 commented Jan 31, 2017

Gosh you're fast :)

@vivek
Copy link
Collaborator Author

vivek commented Jan 31, 2017

@stephenc PTAL, specially at BlueOceanCredentialsProvider.java

@vivek
Copy link
Collaborator Author

vivek commented Jan 31, 2017

@i386 its been bothering me, better to get it out of the way sooner than later:) We also need similar approach for git ssh keys - these are stored in system store. Will chat with @cliffmeyers tomorrow to get it wrapped with this PR.

Copy link
Member

@stephenc stephenc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly OK as is, but i'd prefer if there were some changes.

* @author Stephen Connoly
* @author Vivek Pandey
*/
@Extension(optional = true)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not an optional extension.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may need to specify an ordinal to ensure your priority is ahead of the standard stores

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack.

*/
@Extension(optional = true)
public class BlueOceanCredentialsProvider extends CredentialsProvider {
private static final String DISPLAY_NAME = "BlueOcean Folder Credentials";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐜 I18N this in a Messages resource bundle

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah APIs have i18N missing, maybe good time to get started on it.

@Override
public String getIconFileName() {
return isVisible()
? "/plugin/credentials/images/48x48/folder-store.png"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐜 please use a Blue Ocean specific icon

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I thought this is stock folder credential one and can be used for other CredentialsProvider extension. This is anyway read-only credential provider and is a proxy really. Not sure we really need an icon created for it. @i386?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stock icon is for the "stock" FolderCredentialsProvider from the folders plugin. You need your own so that a user/admin sees that the credentials are coming from this proxy/gateway provider

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or if there is way to display name of 'store' in that table, strangely it shows name of the folder? In the image below, top item is added by blueocean and the next is by folder credential provider.
cc:@i386

blag

@Override
public List<Domain> getDomains() {
//XXX: how to get domain from given Credentials object? Maybe attach domain name to AbstractFolder?
return Collections.emptyList();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Collections.singletonList(Domain.global())

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephenc Why global? The credentials it exposes are in user scope.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually what I see now is that you want something different, you want

Collections.singletonList(/*domain for "blueocean-github-domain"*/)

The domain is about matching the URL the credentials are requested for against the URLs that the credentials are allowed to be used against.

Scope is a different cross-cutting requirement

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. So it's more for routing to this proxy. I will give it a try.


@Override
public boolean hasPermission(@Nonnull Authentication a, @Nonnull Permission permission) {
return abstractFolder.getACL().hasPermission(a,permission);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may need to tweak this, but ok for now

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do need to tweak this, as this is a read only domain we want to always return false for the Credentials/CREATE, Credentials/DELETE, Credentials/MANAGE_DOMAIN and Credentials/UPDATE permissions

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.

@Override
public Set<CredentialsScope> getScopes(ModelObject object) {
if(isApplicable(object)){
return ImmutableSet.of(CredentialsScope.USER);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually you are CredentailsScope.GLOBAL if we are to be strictly correct... this may require changes in the credentials API to allow you to "clone" a credential while changing it's scope

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This provider is proxy exposing credentials from USER scope, for this reason I exposed it with USER scope. Exposing them with GLOBAL scope sounds incorrect to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because you are not using the authorise project plugin, the authentication will be ACL.SYSTEM so you want the scope GLOBAL as that allows the credential to be used by jobs running as SYSTEM or jobs running as an authentication with the USE_ITEM permission (limited to jobs in the org folder)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephenc It seems to be working how it is, but I will change it to GLOBAL. All I am making sure is that its not less secure and these credentials do not get outside of the scope of the org folder they are attached to. Which I think is not the case.

Collections.<DomainRequirement>emptyList()
),
CredentialsMatchers.allOf(CredentialsMatchers.withId(prop.getId()),
CredentialsMatchers.withScope(CredentialsScope.USER))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am now wondering if perhaps we shouldn't be more explicit and just target the credential stores scoped to the user and bypass the general lookupCredentials, e.g.

for (CredentialStore store: CredentialsProvider.lookupStores(user)) {
  // if store has credentials with id, return credential
}
// return empty list;

as matching based on scope here is ringing some alarm bells

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can give it try, but I saw other places your concern about using USER scope as not a good idea. I guess I need to understand why this is not a good idea - this provider is really a locked down provider very specific to keys generated by blueocean in user store with USER scope.

import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;
import java.util.Map;

/**
* @author Vivek Pandey
*/
public class GithubOrgFolderTest extends PipelineBaseTest {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing a test that the credential gets resolved, see this for inspiration but I do not thing you need to go quite so far as to actually trigger a build. I think you could get away with seeing if the credential can be looked up as SYSTEM using the standard credentials API when you add your property and if you remove the property the credential goes missing again, even though the credential is in "bob"'s user store

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, will add a test.

Jenkins.getAuthentication(),
URIRequirementBuilder.fromUri(uri).build()),
CredentialsMatchers.allOf(CredentialsMatchers.withId(credentialId),
CredentialsMatchers.withScope(CredentialsScope.USER))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bad smell, should not need to match based on scope

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is that? I want to keep it strict and if there is GitHub access key based credentials it better come from USER scope or we reject it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still think this is a bad smell. Given that this credentials provider has very specific needs, I suspect we actually want to be directly checking the credential stores for the User and not bothering with the scope check at all

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephenc Given I am going to be scanning in context of domain in user store, that is blueocean generated credentials are going to be created in user store in specific domain and searched accordingly, dropping USER scope is fine.

@stephenc
Copy link
Member

@vivek said:

We also need similar approach for git ssh keys - these are stored in system store. Will chat with @cliffmeyers tomorrow to get it wrapped with this PR.

If you need to handle ssh keys also then actually the BlueOceanCredentialsProvider will have to expose up to two credential ids rather than the single id I initially pseudo-coded


public static class FolderPropertyImpl extends AbstractFolderProperty<AbstractFolder<TopLevelItem>> {
private final String user;
private final String id;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like you now need this to be a Collection<String> (probably a Set) rather than a single value

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephenc jenkins organization folder is either going to be setup by blueocean either using ssh credential(BasicSSHUserPrivateKey) or GitHub accesskey based credential (StandardUsernamePassword), not both. So why a collection?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well if doing checkout with ssh keys you will need both the api credentials for scan/index and the ssh key for checkout

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't necessarily need both. I can do MBP job creation only using my ssh key. https://gist.github.com/vivek/7a200b9cd6d645a78402b0ce5b1e56a8.

Our UI flow,

  • For Git case, we let user create either api key or ssh keys. In case of git, its ssh, or access key (username/password) but not both.
  • For GitHub, no ssh key, only GitHub accessKey.

@stephenc
Copy link
Member

It's looking good and definitely a better approach than stuffing the credentials into the global store, just some polish recommended before merging

@vivek
Copy link
Collaborator Author

vivek commented Feb 1, 2017

@stephenc applied your suggested changes, tests, i18n etc. except the one related to avoiding USER scope as I think this provider should continue doing it - more strict version of checks. If its a bad idea I want to know why.

The other one was keeping an array of credential id - the thing is it's always going to be one credential attached to the org folder (GitHub/BitBucket) or multi-branch pipeline(git).

@vivek
Copy link
Collaborator Author

vivek commented Feb 1, 2017

@cliffmeyers git specific credential creation in user store and git pipeline creation with user store keys implementation is completed. PTAL. In general for this ticket, all cases have been covered.

Copy link
Member

@stephenc stephenc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking a lot better, but I think there are some things you will want to improve before merging

User authenticatedUser = User.current();
if(authenticatedUser == null){
throw new ServiceException.UnauthorizedException("Must login to create a pipeline");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably will need some additional checks here, such as:

  • Did the system admin disable the per-user credentials store?

turning off user credentials store

  • Did the system admin disable this Blue Ocean User Credentials Proxy/Gateway credential store

  • Did the system admin block storage of the credential type we need to store in the user credentials store

screen shot 2017-02-01 at 09 08 01

Probably not a blocker for merging this, but rather something you will need to be aware of and decide what you want to do about it and how to behave if the system admin has made configuration choices about credentials storage that prevent the blue ocean pipeline functionality from working

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I will open another ticket to get it addressed properly as it may need some UX change.

TopLevelItem item = create(Jenkins.getInstance(), getName(), MODE, MultiBranchProjectDescriptor.class);

if (item instanceof WorkflowMultiBranchProject) {
WorkflowMultiBranchProject project = (WorkflowMultiBranchProject) item;

if(scmConfig.getCredentialId() != null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Safer to use StringUtils.isNotBlank(scmConfig.getCredentialId())

}

//XXX: set credentialId to empty string if null or we get NPE later on
String credentialId = scmConfig.getCredentialId() == null ? "" : scmConfig.getCredentialId();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or String credentialId = StringUtils.defaultString(scmConfig.getCredentialId())

User authenticatedUser = User.current();
if(authenticatedUser == null){
throw new ServiceException.UnauthorizedException("Must login to create a pipeline");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repeat of my comment w.r.t. the GitPipelineCreateRequest authorization check


if(githubCredential == null) {
CredentialsUtils.createCredentialsInUserStore(
credential, authenticatedUser, DOMAIN_NAME, new URI(getUri()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will the getUri() return the GitHub Enterprise URL if the user is creating a pipeline against GHE?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

@Override
public List<Domain> getDomains() {
//XXX: how to get domain from given Credentials object? Maybe attach domain name to AbstractFolder?
return Collections.emptyList();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually what I see now is that you want something different, you want

Collections.singletonList(/*domain for "blueocean-github-domain"*/)

The domain is about matching the URL the credentials are requested for against the URLs that the credentials are allowed to be used against.

Scope is a different cross-cutting requirement


@Override
public boolean hasPermission(@Nonnull Authentication a, @Nonnull Permission permission) {
return abstractFolder.getACL().hasPermission(a,permission);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do need to tweak this, as this is a read only domain we want to always return false for the Credentials/CREATE, Credentials/DELETE, Credentials/MANAGE_DOMAIN and Credentials/UPDATE permissions

@Nonnull
@Override
public List<Credentials> getCredentials(@Nonnull Domain domain) {
return BlueOceanCredentialsProvider.getCredentials(Credentials.class, abstractFolder);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (domain == /*domain for "blueocean-github-domain"*/) {
    return BlueOceanCredentialsProvider.getCredentials(Credentials.class, abstractFolder);
}
return Collections.emptyList();

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephenc blueocean allowes credentials to be stored in different domain. For example GitHub credentials could be stored in different domain than git credentials.

@@ -32,6 +33,8 @@

private final CredentialsStoreAction credentialStoreAction;
private final Reachable parent;
public static final String DOMAIN_NAME = "blueocean-domain";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a different domain name from that used elsewhere

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephenc thats right, the way its is currently, GitHub credentials are stored in 'github-domain' got for git keys, UI/client can create credentials in domain of their choice. 'blueocean-domain' is default domain where they get saved. Is this problem?

}

public static class FolderPropertyImpl extends AbstractFolderProperty<AbstractFolder<TopLevelItem>> {
private final String user;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Need a field to store the domain name(s) that this / these credentials are exposed through
  • Need a field to store either the DomainSpecification or the URI (and instantiate the domain specification on demand)... my preference is to store the DomainSpecification

You also need to solve for the case of GitHub / BitBucket where there is the possibility of both scan credentials and checkout credentials... where you need the two different credentials, to further complicate matters the domain specifications for these will be different, e.g. the SSH key will need to match both the ssh and git protocols while the API token used for scanning will need to match http and https

Copy link
Collaborator Author

@vivek vivek Feb 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephenc

(I think you meant DomainRequirement not DomainSpecification)

On further thought, this is not going to really work as the domain created is only once per user and its treated as storage of different credentials. I am going to skip enforcing domain specification checks. As long as domain in the user's store matches, we use it to access SCM.

@vivek
Copy link
Collaborator Author

vivek commented Feb 6, 2017

@stephenc I think I have got everything landed here. Last items DomainRequirement/DomainSpecification has been added. It also goes over user credential store with correct impersonation. PTAL so that we can proceed further.

BlueOcean store specific icon is another item but it should not block this PR.

@stephenc
Copy link
Member

stephenc commented Feb 6, 2017

BlueOcean store specific icon is another item but it should not block this PR.

That's why I gave it an 🐜 (which is more a niggle than a bug) :-D

Will take a look later today

Copy link
Member

@stephenc stephenc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really need to write the credentials plugin user / implementer and consumer guides

}
return null;
}

static void validateCredentialId(String credentialId, OrganizationFolder item, GitHubSCMNavigator navigator) throws IOException {
private String GithubCredentialsDomain(String apiUri) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugh... methods start with lowercase character

ErrorMessage.Error.ErrorCodes.INVALID.toString(), "Invalid github API URI: "+e.getMessage())), e);
}
String path = StringUtils.defaultIfBlank(uri.getPath(), "/");
boolean githubEnterprise = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unnecessary boolean

StandardUsernamePasswordCredentials usernamePasswordCredentials = (StandardUsernamePasswordCredentials) c;
assertEquals(credential.getId(), usernamePasswordCredentials.getId());
assertEquals(credential.getPassword().getPlainText(),usernamePasswordCredentials.getPassword().getPlainText());
assertEquals(credential.getUsername(),usernamePasswordCredentials.getUsername());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing a test where there is a credential with the same ID in the system store, verifying that your proxy store is a higher ordinal and hence will get asked first

public <C extends IdCredentials> ListBoxModel getCredentialIds(@Nonnull Class<C> type,
@Nullable ItemGroup itemGroup,
@Nullable Authentication authentication,
@Nonnull List<DomainRequirement> domainRequirements,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you ACKed but did nothing in this method

public <C extends IdCredentials> ListBoxModel getCredentialIds(@Nonnull Class<C> type,
@Nullable ItemGroup itemGroup,
@Nullable Authentication authentication,
@Nonnull List<DomainRequirement> domainRequirements,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and in fact you kind of got the idea backwards where you applied it in getCredentials ....

The DomainSpecification should be in the property so that you can only return the credential for usage against the GitHub server.

  1. User enters https://github.com/jenkinsci/blueocean-plugin as SCM URL
  2. doFillScanCredentialsItems creates a domain requirements from that URL and asks for all appropriate credentials
  3. Your provider gets asked for credentials... you need to apply your property's DomainSpecification to see if this matches the domain that you are exposing the user's credentials as
  4. Ok, so that matches, now we go and check the user store for credentials with ID (from property) and in a domain matching the DomainRequirement of the BlueOceanProxyDomainRequirement

You have done 4, you still need 3 or the users credentials will leak further than intended


@Override
public boolean hasPermission(@Nonnull Authentication a, @Nonnull Permission permission) {
// its read only so for all permissions other than READ, we return false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

return Result.POSITIVE;
}
}
return Result.NEGATIVE;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI by returning NEGATIVE we prevent the credential from being visible to the user until they are searching with the BlueOceanDomainRequirement. In other words, BlueOceanDomainRequirement is MUST HAVE.

If you want the user to be able to use the credential in other contexts without the context being aware of your requirement then you may want to return UNKNOWN.

@Override
public Result test(@Nonnull DomainRequirement scope) {
if(scope instanceof BlueOceanDomainRequirement){
if(((BlueOceanDomainRequirement)scope).getValue().equals(DOMAIN_SPECIFICATION)){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant test IIUC

public Result test(@Nonnull DomainRequirement scope) {
if(scope instanceof BlueOceanDomainRequirement){
if(((BlueOceanDomainRequirement)scope).getValue().equals(DOMAIN_SPECIFICATION)){
return Result.POSITIVE;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should be PARTIAL

}

private static List<DomainSpecification> generateDomainSpecifications(@Nullable URI uri){
if (uri == null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vivek
Copy link
Collaborator Author

vivek commented Feb 8, 2017

@stephenc I think I have all in place. Give a bee if it all looks good, once its in place I can ask Cliff to give it a try before calling it done:)

  • proxy specific domain (with DomainSepcification creating using uri) attached to folder property.
  • test case added to pick correct BO specific key and not from system. some other test enhancements.

@@ -28,6 +30,11 @@ public GithubEnterpriseScm(Reachable parent) {
return super.getUri()+DEFAULT_ENTERPRISE_API_SUFFIX;
}

@Override
public String getCredentialDomainName() {
return DOMAIN_NAME;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this needed any more? AFAIK you can just store everything in a domain called blue-ocean-proxy

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to keep these id's in their own domain, for example GitHub enterprise is in it's own domain so is consistent that way.

private static final String DEFAULT_ENTERPRISE_API_SUFFIX = "/api/v3";
private static final String ID = "github-enterprise";
static final String DEFAULT_ENTERPRISE_API_SUFFIX = "/api/v3";
static final String ID = "github-enterprise";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot see from the diff, but are you mixing the github enterprise hostname with the id in case the user has more than one GHE server (e.g. a test and prod server)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed, that let me add that one.

ErrorMessage.Error.ErrorCodes.INVALID.toString(),
"No domain in user credentials found for credentialId: "+ scmConfig.getCredentialId())));
}
if(domain.test(new DomainRequirement())) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a bug, you should be testing against your BlueOceanDomainRequirement not DomainRequirement

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it is, good catch.

}
if(domain.test(new DomainRequirement())) {
((OrganizationFolder) item)
.addProperty(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does addProperty handle duplicates correctly?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, will add validation of this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No duplicate test needed, this code creates a new org folder and is add property right after creation.

Vivek Pandey added 4 commits February 9, 2017 10:43
- Also enabled github api tests that gets run if GITHUB_ACCESS_TOKEN jvm property is provided
- github enterprise domain name has hostname suffix
- Fixed correct domain requirement
…HUB_ACCESS_TOKEN=$YOUR_GITHUB_AACECSS_TOKEN
Copy link
Member

@stephenc stephenc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there are any other issues they can be handled as bugs after merging

@vivek
Copy link
Collaborator Author

vivek commented Feb 9, 2017

@stephenc the one issue we should open is handling case where admin turns off access to user credential provider or disables storing credentials in these providers. and another one is BO provider icon.

@cliffmeyers
Copy link
Contributor

cliffmeyers commented Feb 10, 2017

@vivek testing this on my end looks good. Proper access tokens appear to be used during both org scanning and branch scanning, and I've avoided any rate limit exceptions at least for the modest orgs I've been testing with. :) 🐝

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants