Skip to content

Commit

Permalink
feat: [unibroker] add container reg support via plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
aarlaud committed Jun 5, 2024
1 parent e885bcc commit 39f5397
Show file tree
Hide file tree
Showing 16 changed files with 796 additions and 1,347 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ orbs:

defaults: &defaults
docker:
- image: cimg/node:20.11
- image: cimg/node:20.14
working_directory: ~/broker
filter-tags-only: &filter-tags-only
filters:
Expand Down
28 changes: 26 additions & 2 deletions config.default.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,19 @@
"jira-bearer-auth",
"jira",
"nexus",
"nexus2"
"nexus2",
"docker-hub",
"ecr",
"acr",
"gcr",
"artifactory-cr",
"harbor-cr",
"quay-cr",
"github-cr",
"nexus-cr",
"digitalocean-cr",
"gitlab-cr",
"google-artifact-cr"
],
"BROKER_CLIENT_CONFIGURATION": {
"common": {
Expand Down Expand Up @@ -356,7 +368,19 @@
"jira": "defaultFilters/jira.json",
"jira-bearer-auth": "defaultFilters/jira-bearer-auth.json",
"nexus": "defaultFilters/nexus.json",
"nexus2": "defaultFilters/nexus2.json"
"nexus2": "defaultFilters/nexus2.json",
"docker-hub":"defaultFilters/container-registry-agent.json",
"ecr":"defaultFilters/container-registry-agent.json",
"acr":"defaultFilters/container-registry-agent.json",
"gcr":"defaultFilters/container-registry-agent.json",
"artifactory-cr":"defaultFilters/container-registry-agent.json",
"harbor-cr":"defaultFilters/container-registry-agent.json",
"quay-cr":"defaultFilters/container-registry-agent.json",
"github-cr":"defaultFilters/container-registry-agent.json",
"nexus-cr":"defaultFilters/container-registry-agent.json",
"digitalocean-cr":"defaultFilters/container-registry-agent.json",
"gitlab-cr":"defaultFilters/container-registry-agent.json",
"google-artifact-cr":"defaultFilters/container-registry-agent.json"
},
"SOURCE_TYPES": {
"github": {
Expand Down
31 changes: 31 additions & 0 deletions config.universaltest4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"BROKER_CLIENT_CONFIGURATION": {
"common": {
"default": {
"BROKER_SERVER_URL": "https://broker2.dev.snyk.io",
"BROKER_HA_MODE_ENABLED": "false",
"BROKER_DISPATCHER_BASE_URL": "https://api.dev.snyk.io"
}
},
"github": {
"validations":[{
"url": "https://notexists.notexists/no-such-url-ever"
}]
},
"gitlab": {
"validations":[{
"url": "https://notexists.notexists/no-such-url-ever"
}]
}
},
"CONNECTIONS": {
"my cra connection": {
"type": "digitalocean-cr",
"identifier": "${BROKER_TOKEN_1}",
"CR_BASE": "dummy",
"CR_TOKEN": "token",
"CR_CREDENTIALS": "dummy",
"craCompatible": true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import BrokerPlugin from '../abstractBrokerPlugin';

export class Plugin extends BrokerPlugin {
pluginCode = 'CONTAINER_REGISTRY_CREDENTIALS_FORMAT_PLUGIN';
pluginName = 'Container Registry Credentials Formatting Plugin';
description =
'Plugin that formats the container registry credentials for the targeted registry type';
version = '0.1';
applicableBrokerTypes = [
'docker-hub',
'ecr',
'acr',
'gcr',
'artifactory-cr',
'harbor-cr',
'quay-cr',
'github-cr',
'nexus-cr',
'digitalocean-cr',
'gitlab-cr',
'google-artifact-cr',
];
isPluginActive(): boolean {
return true;
}
async startUp(connectionConfiguration: Record<string, any>): Promise<void> {
if (
!connectionConfiguration.type ||
!this.applicableBrokerTypes.includes(connectionConfiguration.type)
) {
throw new Error(
`Plugin ${
this.pluginCode
} startup failure: unknown container registry type: ${
connectionConfiguration.type ?? '<not provided>'
}.`,
);
}
let credentials;
switch (connectionConfiguration.type) {
case 'ecr':
if (
!connectionConfiguration.CR_ROLE_ARN ||
!connectionConfiguration.CR_REGION ||
!connectionConfiguration.CR_EXTERNAL_ID
) {
throw new Error(
`Plugin ${this.pluginCode} startup failure: ${connectionConfiguration.type} requires the following parameters: CR_ROLE_ARN, CR_REGION and CR_EXTERNAL_ID.`,
);
}
credentials = `{"type":"${connectionConfiguration.type}","roleArn":"${connectionConfiguration.CR_ROLE_ARN}","extra":{"region":"${connectionConfiguration.CR_REGION}","externalId":"${connectionConfiguration.CR_EXTERNAL_ID}"}}\n`;
break;
case 'digitalocean-cr':
if (!connectionConfiguration.CR_TOKEN) {
throw new Error(
`Plugin ${this.pluginCode} startup failure: ${connectionConfiguration.type} requires the following parameters: CR_TOKEN.`,
);
}
credentials = `{"type":"${connectionConfiguration.type}", "username":"${connectionConfiguration.CR_TOKEN}", "password":"${connectionConfiguration.CR_TOKEN}", "registryBase":"${connectionConfiguration.CR_BASE}"}\n`;
break;
default:
if (
!connectionConfiguration.CR_USERNAME ||
!connectionConfiguration.CR_PASSWORD
) {
throw new Error(
`Plugin ${this.pluginCode} startup failure: ${connectionConfiguration.type} requires the following parameters: CR_USERNAME,CR_PASSWORD.`,
);
}
credentials = `{"type":"${connectionConfiguration.type}", "username":"${connectionConfiguration.CR_USERNAME}", "password":"${connectionConfiguration.CR_PASSWORD}", "registryBase":"${connectionConfiguration.CR_BASE}"}\n`;
}
connectionConfiguration.CR_CREDENTIALS =
Buffer.from(credentials).toString('base64');
connectionConfiguration.craCompatible = true;

if (connectionConfiguration.BROKER_CLIENT_VALIDATION_URL) {
connectionConfiguration.BROKER_CLIENT_VALIDATION_URL =
connectionConfiguration.CR_CREDENTIALS;
}
}
}
32 changes: 18 additions & 14 deletions lib/client/brokerClientPlugins/plugins/githubServerAppAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,15 @@ export class Plugin extends BrokerPlugin {
connectionConfig.GITHUB_APP_PRIVATE_PEM_PATH,
connectionConfig.GITHUB_APP_CLIENT_ID,
);
timeoutHandlerId = setTimeout(
timeoutHandler,
this._getTimeDifferenceInMsToFutureDate(
timeoutHandlerNow + this.JWT_TTL,
) - 10000,
);
connectionConfig.jwtTimeoutHandlerId = timeoutHandlerId;
if (process.env.NODE_ENV != 'test') {
timeoutHandlerId = setTimeout(
timeoutHandler,
this._getTimeDifferenceInMsToFutureDate(
timeoutHandlerNow + this.JWT_TTL,
) - 10000,
);
connectionConfig.jwtTimeoutHandlerId = timeoutHandlerId;
}
} catch (err) {
this.logger.error(
{ plugin: this.pluginCode, err },
Expand Down Expand Up @@ -187,13 +189,15 @@ export class Plugin extends BrokerPlugin {
JSON.parse(connectionConfig.accessToken).expires_at
}`,
);
timeoutHandlerId = setTimeout(
timeoutHandler,
this._getTimeDifferenceInMsToFutureDate(
JSON.parse(connectionConfig.accessToken).expires_at,
) - 10000,
);
connectionConfig.accessTokenTimeoutHandlerId = timeoutHandlerId;
if (process.env.NODE_ENV != 'test') {
timeoutHandlerId = setTimeout(
timeoutHandler,
this._getTimeDifferenceInMsToFutureDate(
JSON.parse(connectionConfig.accessToken).expires_at,
) - 10000,
);
connectionConfig.accessTokenTimeoutHandlerId = timeoutHandlerId;
}
} catch (err) {
this.logger.error(
{ plugin: this.pluginCode, err },
Expand Down
18 changes: 16 additions & 2 deletions lib/client/routesHandler/websocketConnectionMiddlewares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,22 @@ export const websocketConnectionSelectorMiddleware = (
req.path.startsWith('/v1/') ||
req.path.startsWith('/v2/')
) {
inboundRequestType = 'container-registry-agent';
const connections = Object.values(config.connections) as Record<
string,
string
>[];
const craCompatibleAvailableTypes =
connections.filter((x) => x.craCompatible).map((x) => x.type) ?? [];
if (craCompatibleAvailableTypes.length > 0) {
inboundRequestType = craCompatibleAvailableTypes[0];
} else {
res
.status(505)
.send(
'Current Broker Client configuration does not support this flow. Missing container registry agent compatible connection.',
);
return;
}
} else {
logger.error(
{ url: req.path },
Expand All @@ -75,7 +90,6 @@ export const websocketConnectionSelectorMiddleware = (
return;
}
}

const selectedWebsocketConnection = websocketConnections.find(
(conn) => conn.supportedIntegrationType == inboundRequestType,
);
Expand Down
6 changes: 2 additions & 4 deletions lib/client/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { chunkHandler } from './socketHandlers/chunkHandler';
import { initializeSocketHandlers } from './socketHandlers/init';

import { LoadedClientOpts } from '../common/types/options';
import { translateIntegrationTypeToBrokerIntegrationType } from './utils/integrations';
import { maskToken } from '../common/utils/token';
import { fetchJwt } from './auth/oauth';

Expand All @@ -40,9 +39,8 @@ export const createWebSockets = (
const integrationType =
clientOpts.config.connections[`${integrationsKeys[i]}`].type;

// This type is different for broker, ECR/ACR/DockeHub/etc are all container-registry-agent type for broker
socketIdentifyingMetadata.supportedIntegrationType =
translateIntegrationTypeToBrokerIntegrationType(integrationType);
socketIdentifyingMetadata.supportedIntegrationType = integrationType;

socketIdentifyingMetadata.serverId =
clientOpts.config.connections[`${integrationsKeys[i]}`].serverId ?? '';
websocketConnections.push(
Expand Down
12 changes: 12 additions & 0 deletions lib/client/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,23 @@ interface CommitSigning {
GPG_PRIVATE_KEY: string;
}

interface SourceTypes {
sourceTypes: {
[key: string]: {
publicId?: string;
name: string;
type: string;
brokerType: string;
};
};
}

export type Config = BackendAPI &
BrokerClient &
BrokerServer &
CommitSigning &
HighAvailabilityMode &
SourceTypes &
Record<string, any>;

export interface ConnectionValidations {
Expand Down
8 changes: 0 additions & 8 deletions lib/client/utils/integrations.ts

This file was deleted.

Loading

0 comments on commit 39f5397

Please sign in to comment.