Skip to content
This repository has been archived by the owner on Jul 12, 2024. It is now read-only.

Ingest the remaining entities and relationships #5

Merged
merged 5 commits into from
Sep 10, 2020

Conversation

neurovelho
Copy link

This PR includes the remaining of the high value entities and relationships as discussed in the issue thread.

Kindly let us know if something needs to be changed.

@neurovelho
Copy link
Author

Pinging @aiwilliams @ndowmon @austinkelleher

@ndowmon ndowmon self-requested a review September 3, 2020 18:00
Copy link
Contributor

@ndowmon ndowmon left a comment

Choose a reason for hiding this comment

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

@neurovelho Thanks for all the work here! All the new entities and relationships look really good.

I peppered some requests throughout for you to review. In particular, I'd like you to take another look at the artifactory_permissions entities and relationships. Let me know if any of my comments don't make sense and we can discuss in more detail.

id: 'fetch-access-tokens',
name: 'Fetch Access Tokens',
entities: [entities.ACCESS_TOKEN],
relationships: [relationships.ACCOUNT_HAS_ACCESS_TOKEN],
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like the particular access token based on your test data could be related to a user via the subject field:

{
  "expiry": 1601555179,
  "issued_at": 1599135979,
  "issuer": "jfrt@01eg8hb1g2dqb01cdtms0e0bv1",
  "refreshable": false,
  "subject": "jfrt@01eg8hb1g2dqb01cdtms0e0bv1/users/[email protected]",
  "token_id": "ad667cc7-54a5-42b1-bed5-0c92c0fe0fa8",
}

I think we should probably add artifactory_user--ASSIGNED-->artifactory_access_token

Copy link
Author

Choose a reason for hiding this comment

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

Looks like the admin can only create what's called admin access token, however it looks like it's actually possible to create regular access tokens that target a specific user using the rest api, so we'll change this.

Comment on lines +11 to +14
clientPipelineAccessToken: {
type: 'string',
mask: true,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you update the development docs so devs also know they need to generate this token?

Comment on lines 23 to 30
function mapPackageTypeToStepEntityMetadata(type: string): StepEntityMetadata {
if (type.match(/docker|vagrant/i)) {
return entities.ARTIFACT_IMAGE;
}

return entities.ARTIFACT_CODEMODULE;
}

Copy link
Contributor

@ndowmon ndowmon Sep 4, 2020

Choose a reason for hiding this comment

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

I noticed that this matcher isn't really differentiating images from codemodules. Example from snapshot:

// this is a json but matched the repository name `/docker/i`
Object {
  "_type": "artifactory_artifact_image",
  "name": "https://codeworkr.jfrog.io/artifactory/docker-repo/hello-world/1.1.1/manifest.json",
  ... // other properties
},
// this appears to be an image
Object {
  "_type": "artifactory_artifact_image",
  "name": "https://codeworkr.jfrog.io/artifactory/docker-repo/hello-world/1.1.1/sha256__0e03bdcc26d7a9a57ef3b6f1bf1a210cff6239bff7c8cac72435984032851689",
  ... // other properties
},

Not sure if it makes sense to reconsider your regular expression matcher to avoid these types of mis-matchings. I'm personally not 100% sure it is worth differentiating between images and "code modules", considering that code module is basically a catch all for other files, including .pom, .xml, .json, .jpeg, .gz and others which can be found in the snapshot. If others have a strong opinion about differentiating artifactory_artifact_image vs artifactory_artifact_codemodule, please speak up. I'd particularly like to hear @erichs' opinions here considering his comment #3 (comment)

Copy link
Author

Choose a reason for hiding this comment

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

Yeah I'm not too excited about this matcher either, I think it would be much better if we could just roll with one type.

Copy link
Contributor

Choose a reason for hiding this comment

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

Spoke with @erichs about this. It really stinks that the API appears to only reliably return folder and uri properties, no additiona metadata:

{
  "folder": false,
  "uri": "https://codeworkr.jfrog.io/artifactory/docker-repo/hello-world/1.1.1/sha256__bf756fb1ae65adf866bd8c456593cd24beb6a0a061dedf42b26a993176745f6b",
}

Since there are no other properties we can rely on, it doesn't seem like a great idea for us to add any custom matcher in our code (following the philosophy that we at J1 only ingest the state of a target system, and don't build additional logic).

As long as you are pulling the projectType property on artifactory_repository entities, we can create J1QL like the following, which is good enough for now:

// look for maven builds
find 
  artifactory_repository that has 
  artifactory_artifact 
where 
  artifactory_repository.packageType = 'Maven'

await fetchRepositories(context);
await fetchPipelineSources(context);
await fetchArtifacts(context);
await fetchBuilds(context);
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like you're not testing fetchPermissions here. Is that on purpose or just overlooked?

Copy link
Author

Choose a reason for hiding this comment

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

Looks like we missed it, good catch.

_class: RelationshipClass.ALLOWS,
sourceType: entities.PERMISSION._type,
targetType: entities.REPOSITORY._type,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Is PERMISSION_DENIES_REPOSITORY a valid relationship type? Just noticed that there are both PREMISSION_ALLOWS_BUILD and PERMISSION_DENIES_BUILD.

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, read comments in /permissions.ts. Not sure there should be any DENIES relationships.

},
});

await jobState.addEntity(permissionEntity);
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like this code is adding two artifactory_permission entities for every permission. There should be just one artifactory_permission entity created. That single entity should have relationships to both users and groups.

Copy link
Author

Choose a reason for hiding this comment

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

We were going by this comment here: #3 (comment), but seeing as the response contains both users and groups, it would make more sense if we had both users and groups in the entity.

Copy link
Contributor

Choose a reason for hiding this comment

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

Just to clarify - you mean both users and groups in related to the entity, correct?

Copy link
Author

Choose a reason for hiding this comment

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

Yes, that's right.

);
}

function constructPermissionsMap(
Copy link
Contributor

Choose a reason for hiding this comment

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

Per artifactory docs, there can also be release bundle permissions, destination permissions, and pipeline permissions, PLUS "global permissions". Can you pull those additional permission targets in this function? I realize that some of those can't be used to target existing entities, but can you add code comments to implement others when they are implemented in the future?

Copy link
Author

Choose a reason for hiding this comment

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

The api documentation seems to indicate that only repository, build and releaseBundle are available, though it could be that it's outdated 🤔

We'll definitely see if it's possible to add the rest.

return targetPermissionsMap;
}

async function createPermissionBuildAllowsRelationships(
Copy link
Contributor

Choose a reason for hiding this comment

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

Jfrog docs discussing include and exclude patterns seem to indicate that both the statements are used to pattern match permission targets that are allowed by a given permission. I don't think the exclude pattern is actually a DENIES statement in reality.

I would instead suggest creating only ALLOWS statements for permissions targets that do match the include-pattern and do not match the exclude-pattern.

Also, I notice that artifactory exposes a pattern matching API - it would be better to use a matcher provided by the vendor than a nodejs utility. See https://www.jfrog.com/confluence/display/JFROG/Artifactory+REST+API

Usage: GET /api/search/pattern?pattern=repo-key:this/is/a/*pattern*.war

};
groups?: {
[name: string]: string[];
};
Copy link
Contributor

Choose a reason for hiding this comment

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

I haven't used the API, but it seems to me that permission.repo also has the include-patterns and exclude-patterns properties.

};
'include-patterns': string[];
'exclude-patterns': string[];
Copy link
Contributor

Choose a reason for hiding this comment

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

You should enumerate all of the permission target types, including destinations, pipeline-sources, release-bundles, and possibly global if it exists.

@neurovelho
Copy link
Author

Alrighty, we've implemented the changes you requested @ndowmon.

There's however a few complications though:

  • We implemented the user -> assigned -> access token relationship, however it looks like no matter what you do in the dashboard or API, the access tokens simply won't show up in the api/token response -- only the admin tokens do. Sadly this seems like a regular occurrence with this API.

  • After trying out multiple things it seems like API only returns repository, build and releaseBundle permissions:

    Release bundle permission is difficult/impossible to implement because they aren’t available during the trial.

    Pipeline permissions can’t seem to be fetched even after we create them in the permission using JFrog admin dashboard, the API simply isn’t returning those for some reason.

    Destination permissions - we aren’t exactly sure what these represent, we don’t see additional field(s) for setting this on the permission setting page nor does the API returns anything about them.

  • The pattern matching endpoint can only be used for artifacts, nothing else. That means that when we're matching include/exclude patterns for repositories and builds we pretty much have to use the external library for matching.

ndowmon
ndowmon previously approved these changes Sep 9, 2020
Copy link
Contributor

@ndowmon ndowmon left a comment

Choose a reason for hiding this comment

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

Thanks for making the requested changes! This integration definitely looks ready for deployment to me.

I commented a few small requests but we can easily open new github issues for those and fix in the future.

},
(buildEntity) => `${permissionEntity._key}|allows|${buildEntity._key}`,
Copy link
Contributor

Choose a reason for hiding this comment

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

Not a big deal since it's functionally correct, but here it should be permissionEntity.

Copy link
Author

Choose a reason for hiding this comment

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

Did you mean repositoryEntity? In any case, I renamed it since it was bothering me too much 🙂.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes! Thanks.

@@ -237,9 +272,11 @@ export const permissionsSteps: IntegrationStep<IntegrationConfig>[] = [
relationships.PERMISSION_ASSIGNED_GROUP,
relationships.PERMISSION_ALLOWS_REPOSITORY,
relationships.PERMISSION_ALLOWS_BUILD,
relationships.PERMISSION_ALLOWS_REPOSITORY_GROUP,
Copy link
Contributor

Choose a reason for hiding this comment

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

Cool, thanks for adding this!

@@ -51,6 +52,7 @@ describe('JFrog Arrifactory', () => {
await fetchPipelineSources(context);
await fetchArtifacts(context);
await fetchBuilds(context);
await fetchPermissions(context);
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for adding. Not necessary now, but let's add a GH issue to add an expect statement for permissions here.

Copy link
Contributor

@ndowmon ndowmon left a comment

Choose a reason for hiding this comment

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

Thanks @neurovelho. This is a great integration!

@ndowmon ndowmon merged commit 61872b8 into JupiterOne-Archives:master Sep 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants