diff --git a/README.md b/README.md index 95fe7f6d..8c6cd0a4 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,11 @@ The following can normally be used: * `preferred_username` claim which is normally the 'User principal name', but not always. * User principal name (Rest API authentication only) +## Configuration as Code and Job DSL support +The plugin has full support for use in Configuration as Code and Job DSL. + +For an example combining the two, see the [configuration-as-code.yml](./src/test/resources/com/microsoft/jenkins/azuread/integrations/casc/configuration-as-code.yml) test resource. + ## FAQ #### Q: How to recover if Jenkins keeps failing during the login phase? A: You can disable the security from the config file (see [https://www.jenkins.io/doc/book/security/access-control/disable/](https://www.jenkins.io/doc/book/security/access-control/disable/)) diff --git a/src/main/frontend/index.ts b/src/main/frontend/index.ts index ced4c2d6..e0a3ff8d 100644 --- a/src/main/frontend/index.ts +++ b/src/main/frontend/index.ts @@ -2,18 +2,17 @@ import { Providers } from '@microsoft/mgt-element/dist/es6'; import { ProxyProvider } from '@microsoft/mgt-proxy-provider/dist/es6/ProxyProvider'; import '@microsoft/mgt-components'; -document.addEventListener('DOMContentLoaded', (_) => { - const currentUrl = window.location.href +const currentUrl = window.location.href - // GraphProxy is either a root action or at the job level - const endStrippedCurrentUrl = currentUrl - .replace('configureSecurity/', '') - .replace('configure', '') - .replace('computer/createItem', ''); +// GraphProxy is either a root action or at the job level +const endStrippedCurrentUrl = currentUrl + .replace('configureSecurity/', '') + .replace('configure', '') + .replace('pipeline-syntax/', '') + .replace('computer/createItem', ''); - Providers.globalProvider = new ProxyProvider(`${endStrippedCurrentUrl}/GraphProxy`, async () => { - return { - [document.head.dataset.crumbHeader as string]: document.head.dataset.crumbValue, - }; - }); -}) +Providers.globalProvider = new ProxyProvider(`${endStrippedCurrentUrl}/GraphProxy`, async () => { + return { + [document.head.dataset.crumbHeader as string]: document.head.dataset.crumbValue, + }; +}); diff --git a/src/main/java/com/microsoft/jenkins/azuread/AzureAdAuthorizationMatrixFolderProperty.java b/src/main/java/com/microsoft/jenkins/azuread/AzureAdAuthorizationMatrixFolderProperty.java index 1e1b6166..13f9deea 100644 --- a/src/main/java/com/microsoft/jenkins/azuread/AzureAdAuthorizationMatrixFolderProperty.java +++ b/src/main/java/com/microsoft/jenkins/azuread/AzureAdAuthorizationMatrixFolderProperty.java @@ -33,10 +33,8 @@ protected AzureAdAuthorizationMatrixFolderProperty() { @DataBoundConstructor @Restricted(NoExternalUse.class) - public AzureAdAuthorizationMatrixFolderProperty(List permissions) { - for (String permission : permissions) { - add(permission); - } + public AzureAdAuthorizationMatrixFolderProperty(List entries) { + setEntries(entries); } @Override diff --git a/src/main/java/com/microsoft/jenkins/azuread/AzureAdAuthorizationMatrixProperty.java b/src/main/java/com/microsoft/jenkins/azuread/AzureAdAuthorizationMatrixProperty.java index 3498f5f8..dca960a6 100644 --- a/src/main/java/com/microsoft/jenkins/azuread/AzureAdAuthorizationMatrixProperty.java +++ b/src/main/java/com/microsoft/jenkins/azuread/AzureAdAuthorizationMatrixProperty.java @@ -46,11 +46,9 @@ public AzureAdAuthorizationMatrixProperty( @DataBoundConstructor @Restricted(NoExternalUse.class) - public AzureAdAuthorizationMatrixProperty(List permissions) { + public AzureAdAuthorizationMatrixProperty(List entries) { this(); - for (String permission : permissions) { - add(permission); - } + setEntries(entries); } void refreshMap() { diff --git a/src/main/java/com/microsoft/jenkins/azuread/integrations/casc/MatrixAuthorizationStrategyConfigurator.java b/src/main/java/com/microsoft/jenkins/azuread/integrations/casc/MatrixAuthorizationStrategyConfigurator.java index 4bc78a85..9573af2c 100644 --- a/src/main/java/com/microsoft/jenkins/azuread/integrations/casc/MatrixAuthorizationStrategyConfigurator.java +++ b/src/main/java/com/microsoft/jenkins/azuread/integrations/casc/MatrixAuthorizationStrategyConfigurator.java @@ -107,18 +107,6 @@ public static void setEntries(AuthorizationContainer container, Collection getLegacyPermissions(AuthorizationContainer container) { - return container.getGrantedPermissionEntries().entrySet().stream() - .flatMap(e -> e.getValue().stream() - .map(v -> v.getType().toPrefix() + e.getKey().group.getId() + "/" + e.getKey().name + ":" - + v.getSid())) - .sorted() - .collect(Collectors.toList()); - } - /** * Configure container's permissions from a List of "PERMISSION:sid" or "TYPE:PERMISSION:sid" */ diff --git a/src/test/java/com/microsoft/jenkins/azuread/integrations/casc/ConfigAsCodeTest.java b/src/test/java/com/microsoft/jenkins/azuread/integrations/casc/ConfigAsCodeTest.java index af55aa57..ee2e8705 100644 --- a/src/test/java/com/microsoft/jenkins/azuread/integrations/casc/ConfigAsCodeTest.java +++ b/src/test/java/com/microsoft/jenkins/azuread/integrations/casc/ConfigAsCodeTest.java @@ -1,5 +1,7 @@ package com.microsoft.jenkins.azuread.integrations.casc; +import com.cloudbees.hudson.plugins.folder.Folder; +import com.microsoft.jenkins.azuread.AzureAdAuthorizationMatrixFolderProperty; import com.microsoft.jenkins.azuread.AzureAdAuthorizationMatrixNodeProperty; import com.microsoft.jenkins.azuread.AzureAdMatrixAuthorizationStrategy; import com.microsoft.jenkins.azuread.AzureSecurityRealm; @@ -32,7 +34,9 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; public class ConfigAsCodeTest { @@ -87,6 +91,23 @@ public void should_support_configuration_as_code() { is(true) ); } + + { + Folder folder = (Folder) j.jenkins.getItem("generated"); + assertNotNull(folder); + AzureAdAuthorizationMatrixFolderProperty property = folder.getProperties() + .get(AzureAdAuthorizationMatrixFolderProperty.class); + assertTrue("folder property inherits", property.getInheritanceStrategy() instanceof NonInheritingStrategy); + String groupSid = "Some group (7fe913e8-6c9f-40f8-913e-7178b7768cc5)"; + assertTrue(property.hasExplicitPermission(PermissionEntry.group(groupSid), Item.BUILD)); + assertTrue(property.hasExplicitPermission(PermissionEntry.group(groupSid), Item.READ)); + assertFalse(property.hasExplicitPermission(PermissionEntry.user("anonymous"), Item.READ)); + assertTrue(property.hasExplicitPermission(PermissionEntry.group(groupSid), Item.CONFIGURE)); + assertTrue(property.hasExplicitPermission(PermissionEntry.group(groupSid), Item.DELETE)); + + String userSid = "c411116f-cfa6-472c-8ccf-d0cb6053c9aa"; + assertTrue(property.hasExplicitPermission(PermissionEntry.user(userSid), Item.BUILD)); + } } @Test diff --git a/src/test/resources/com/microsoft/jenkins/azuread/integrations/casc/configuration-as-code.yml b/src/test/resources/com/microsoft/jenkins/azuread/integrations/casc/configuration-as-code.yml index 5c558a95..59e8c2ff 100644 --- a/src/test/resources/com/microsoft/jenkins/azuread/integrations/casc/configuration-as-code.yml +++ b/src/test/resources/com/microsoft/jenkins/azuread/integrations/casc/configuration-as-code.yml @@ -73,3 +73,24 @@ jenkins: - "Agent/Disconnect" remoteFS: "/opt/jenkins" retentionStrategy: "always" +jobs: + - script: > + folder('generated') { + properties { + azureAdAuthorizationMatrix { + inheritanceStrategy { + nonInheriting() + } + entries { + group { + name('Some group (7fe913e8-6c9f-40f8-913e-7178b7768cc5)') + permissions([ 'Job/Build', 'Job/Configure', 'Job/Delete', 'Job/Read' ]) + } + user { + name('c411116f-cfa6-472c-8ccf-d0cb6053c9aa') + permissions([ 'Job/Build', 'Job/Configure' ]) + } + } + } + } + }