Skip to content

Commit

Permalink
Added proxy auth to the library card and libver table. (#7)
Browse files Browse the repository at this point in the history
This will allow users to authenticate with a proxy in production environments.
  • Loading branch information
mindthecap authored Sep 2, 2024
1 parent 59a390b commit c055677
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 12 deletions.
5 changes: 3 additions & 2 deletions src/components/LibArtifactCard/LibArtifactCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { configApiRef, useApi } from '@backstage/core-plugin-api';
import { configApiRef, identityApiRef, useApi } from '@backstage/core-plugin-api';
import { ResponseErrorPanel } from '@backstage/core-components';
import { useEntity } from '@backstage/plugin-catalog-react';
import { LibArtifactCardProps } from '../../types';
Expand All @@ -14,14 +14,15 @@ export const DEFAULT_PROXY_PATH = '/artifactory-proxy/';
export const LibArtifactCard = (props: LibArtifactCardProps) => {
const config = useApi(configApiRef);
const { entity } = useEntity<Entity>();
const identity = useApi (identityApiRef);

const artifactoryUrl = config.getString('jfrog.artifactory.url');

checkAnnotationsPresent(entity);

const { value, loading, error } = useAsync(async () => {
try {
return await libraryInfo(entity, config);
return await libraryInfo(entity, config, identity);
} catch (e) {
if (!(e instanceof Error)) {
throw new Error(e as string);
Expand Down
34 changes: 31 additions & 3 deletions src/components/LibArtifactCard/api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// import { on } from 'events';
import { LibraryArtifact, MetadataResponse } from '../../types';
import { findLatestVersion } from './versionUtils';
import { IdentityApi } from '@backstage/core-plugin-api';

export type GeneratedCode = {
gradle: string;
Expand Down Expand Up @@ -51,8 +53,17 @@ export async function getRepositoryType(
},
url: string,
{ repo }: LibraryArtifact,
identityApi: IdentityApi
) {
const response = await fetch(`${url}artifactory/api/repositories/${repo}`);
// Obtain the token

const { token: idToken } = await identityApi.getCredentials();

const response = await fetch(`${url}artifactory/api/repositories/${repo}`, {
headers: {
Authorization: `Bearer ${idToken}`,
},
});
if (response.status === 404) {
throw new Error(`Repository ${repo} was not found`);
} else {
Expand All @@ -75,9 +86,16 @@ export async function getMavenLatestVersion(
},
url: string,
{ group, artifact, repo }: LibraryArtifact,
identityApi: IdentityApi,
) {

const { token: idToken } = await identityApi.getCredentials();

const response = await fetch(
`${url}artifactory/api/search/latestVersion?g=${group}&a=${artifact}&repos=${repo}`,
`${url}artifactory/api/search/latestVersion?g=${group}&a=${artifact}&repos=${repo}`, {
headers: {
Authorization: `Bearer ${idToken}`,
},}
);
if (response.status === 404) {
return undefined;
Expand Down Expand Up @@ -137,10 +155,14 @@ export async function getDockerLatestVersion(
},
url: string,
{ artifact }: LibraryArtifact,
identityApi: IdentityApi,
) {
const { token: idToken } = await identityApi.getCredentials();

const response = await fetch(`${url}/metadata/api/v1/query`, {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${idToken}`,
},
method: 'POST',
body: getMetadataVersionQuery(extractArtifactFromFullDockerName(artifact)),
Expand Down Expand Up @@ -174,9 +196,15 @@ export async function getPypiLatestVersion(
},
url: string,
{ artifact, repo }: LibraryArtifact,
identityApi: IdentityApi,
) {
const { token: idToken } = await identityApi.getCredentials();

const response = await fetch(
`${url}/artifactory/api/search/prop?pypi.name=${artifact}&repos=${repo}`,
`${url}/artifactory/api/search/prop?pypi.name=${artifact}&repos=${repo}`, {
headers: {
Authorization: `Bearer ${idToken}`,
},}
);
if (response.status === 404) {
return undefined;
Expand Down
12 changes: 8 additions & 4 deletions src/components/LibArtifactCard/libraryInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Entity } from '@backstage/catalog-model';

import { Config } from '@backstage/config';

import { IdentityApi } from '@backstage/core-plugin-api';

import {
ENTITY_ARTIFACT,
ENTITY_GROUP,
Expand Down Expand Up @@ -43,6 +46,7 @@ export function checkAnnotationsPresent(entity: Entity) {
export async function libraryInfo(
entity: Entity,
config: Config,
identity: IdentityApi,
): Promise<ArtifactInfo> {
const artifactoryBackendProxy =
config.getOptionalString('jfrog.artifactory.proxyPath') ||
Expand All @@ -53,8 +57,7 @@ export async function libraryInfo(
const proxyUrl = `/proxy${artifactoryBackendProxy}`;
// try {
const url = `${backendUrl}/api${proxyUrl}`;

const { packageType } = await getRepositoryType(fetch, url, entityArtifact);
const { packageType } = await getRepositoryType(fetch, url, entityArtifact,identity);
let version;
const artInfo = { ...entityArtifact };
switch (packageType) {
Expand All @@ -63,6 +66,7 @@ export async function libraryInfo(
fetch,
url,
entityArtifact,
identity,
);
artInfo.stats = dockerInfo?.statsDownload;
artInfo.size = dockerInfo?.size;
Expand All @@ -74,10 +78,10 @@ export async function libraryInfo(
version = dockerInfo?.version;
break;
case 'pypi':
version = await getPypiLatestVersion(fetch, url, entityArtifact);
version = await getPypiLatestVersion(fetch, url, entityArtifact,identity);
break;
default:
version = await getMavenLatestVersion(fetch, url, entityArtifact);
version = await getMavenLatestVersion(fetch, url, entityArtifact,identity);
}

artInfo.version = version;
Expand Down
8 changes: 5 additions & 3 deletions src/components/LibverTable/LibverTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { capitalize } from 'lodash';
import React, { ReactNode, useMemo, useRef, useState } from 'react';
import { columnFactories } from './columns';
import pluralize from 'pluralize';
import { ConfigApi, configApiRef, useApi } from '@backstage/core-plugin-api';
import { ConfigApi, configApiRef, useApi, identityApiRef, IdentityApi } from '@backstage/core-plugin-api';
import useAsync from 'react-use/lib/useAsync';
import { LibVerTabbedContent } from '../LibVerTabbedContent';
import { ArtifactInfo } from '../LibArtifactCard/api';
Expand Down Expand Up @@ -56,6 +56,7 @@ const refCompare = (a: LibverTableRow, b: LibverTableRow) => {
async function loadEntityItemData(
entity: Entity,
config: ConfigApi,
identity: IdentityApi,
): Promise<LibverTableRow> {
const partOfSystemRelations = getEntityRelations(entity, RELATION_PART_OF, {
kind: 'system',
Expand All @@ -64,7 +65,7 @@ async function loadEntityItemData(

let artifactInfo;
try {
artifactInfo = await libraryInfo(entity, config);
artifactInfo = await libraryInfo(entity, config, identity);
} catch (e) {
console.error(e);
artifactInfo = undefined;
Expand Down Expand Up @@ -107,6 +108,7 @@ function TableComponent(
const [rows, setRows] = useState<LibverTableRow[]>([]);
const [selectedRows, setSelectedRows] = useState<ArtifactInfo[]>([]);
const config = useApi(configApiRef);
const identity = useApi(identityApiRef);
const tableRef = useRef<any>(); // not sure if there's a better type for this

const artifactoryUrl = useMemo(() => {
Expand All @@ -116,7 +118,7 @@ function TableComponent(
const { loading, error } = useAsync(async () => {
const results: LibverTableRow[] = [];
const libverTableRows = await Promise.allSettled(
entities.map(entity => loadEntityItemData(entity, config)),
entities.map(entity => loadEntityItemData(entity, config, identity)),
);
libverTableRows.forEach(result => {
if (result.status === 'fulfilled') {
Expand Down

0 comments on commit c055677

Please sign in to comment.