(feature): enable permissions in jenkins plugin. Actions (re-build) can be executed only by a user who owns the entity (or related group own the entity)
Signed-off-by: Hasan Oezdemir <21654050+nodify-at@users.noreply.github.com>
This commit is contained in:
@@ -21,3 +21,4 @@
|
||||
*/
|
||||
|
||||
export * from './service';
|
||||
export * from './permissions';
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { jenkinsPermissionRules } from './rules';
|
||||
import { createConditionExports } from '@backstage/plugin-permission-node';
|
||||
import { RESOURCE_TYPE_JENKINS } from '@backstage/plugin-jenkins-common';
|
||||
|
||||
const { conditions, createPolicyDecision } = createConditionExports({
|
||||
pluginId: 'jenkins',
|
||||
resourceType: RESOURCE_TYPE_JENKINS,
|
||||
rules: jenkinsPermissionRules,
|
||||
});
|
||||
|
||||
export const jenkinsConditions = conditions;
|
||||
export const createJenkinsPermissionPolicy = createPolicyDecision;
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export {
|
||||
createJenkinsPermissionPolicy,
|
||||
jenkinsConditions,
|
||||
} from './conditionExports';
|
||||
export * from './rules';
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';
|
||||
import { jenkinsPermissionRules } from './rules';
|
||||
import { parseEntityRef } from '@backstage/catalog-model';
|
||||
import type { PluginEndpointDiscovery } from '@backstage/backend-common';
|
||||
import { CatalogClient } from '@backstage/catalog-client';
|
||||
import { RESOURCE_TYPE_JENKINS } from '@backstage/plugin-jenkins-common';
|
||||
|
||||
export const jenkinsPermissionIntegrationRouterFactory = (
|
||||
discoveryApi: PluginEndpointDiscovery,
|
||||
fetchApi?: { fetch: typeof fetch },
|
||||
) => {
|
||||
const catalogApi = new CatalogClient({ discoveryApi, fetchApi: fetchApi });
|
||||
return createPermissionIntegrationRouter({
|
||||
resourceType: RESOURCE_TYPE_JENKINS,
|
||||
rules: Object.values(jenkinsPermissionRules),
|
||||
getResources: resourceRefs => {
|
||||
const entities = resourceRefs.map(async resourceRef => {
|
||||
const { kind, namespace, name } = parseEntityRef(resourceRef);
|
||||
return catalogApi.getEntityByName({ kind, name, namespace });
|
||||
});
|
||||
// combine the promises to return entities as any array, getResources expects a single promise with all entities
|
||||
return Promise.all(entities);
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { permissionRules } from '@backstage/plugin-catalog-backend';
|
||||
/**
|
||||
*
|
||||
* Jenkins' permission rules can be used to defined different kind of rules to check if the user authorizes an action
|
||||
* (or listing the jobs ever)
|
||||
*
|
||||
* Provided rules:
|
||||
* {isEntityOwner} can be used to determine if a user or the group of the user
|
||||
* owns an entity.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const jenkinsPermissionRules = {
|
||||
isEntityOwner: permissionRules.isEntityOwner,
|
||||
};
|
||||
@@ -14,16 +14,24 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { errorHandler } from '@backstage/backend-common';
|
||||
import {
|
||||
errorHandler,
|
||||
PluginEndpointDiscovery,
|
||||
} from '@backstage/backend-common';
|
||||
import express from 'express';
|
||||
import Router from 'express-promise-router';
|
||||
import { Logger } from 'winston';
|
||||
import { JenkinsInfoProvider } from './jenkinsInfoProvider';
|
||||
import { JenkinsApiImpl } from './jenkinsApi';
|
||||
import { Config } from '@backstage/config';
|
||||
import { jenkinsPermissionIntegrationRouterFactory } from '../permissions/permission-router-factory';
|
||||
|
||||
export interface RouterOptions {
|
||||
logger: Logger;
|
||||
jenkinsInfoProvider: JenkinsInfoProvider;
|
||||
config?: Config;
|
||||
discovery?: PluginEndpointDiscovery;
|
||||
fetchApi?: { fetch: typeof fetch };
|
||||
}
|
||||
|
||||
export async function createRouter(
|
||||
@@ -117,7 +125,18 @@ export async function createRouter(
|
||||
response.json({});
|
||||
},
|
||||
);
|
||||
|
||||
router.use(errorHandler());
|
||||
|
||||
if (options.config?.getOptionalBoolean('permission.enabled')) {
|
||||
if (!options.discovery) {
|
||||
throw new Error('Discovery API is required if permissions are enabled.');
|
||||
}
|
||||
router.use(
|
||||
jenkinsPermissionIntegrationRouterFactory(
|
||||
options.discovery,
|
||||
options.fetchApi,
|
||||
),
|
||||
);
|
||||
}
|
||||
return router;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user