diff --git a/src/main/java/org/jenkinsci/plugins/matrixauth/AuthorizationContainer.java b/src/main/java/org/jenkinsci/plugins/matrixauth/AuthorizationContainer.java index 4c693670..b4156488 100644 --- a/src/main/java/org/jenkinsci/plugins/matrixauth/AuthorizationContainer.java +++ b/src/main/java/org/jenkinsci/plugins/matrixauth/AuthorizationContainer.java @@ -44,6 +44,7 @@ import jenkins.model.IdStrategy; import jenkins.model.Jenkins; import org.jenkinsci.plugins.matrixauth.integrations.PermissionFinder; +import org.jenkinsci.plugins.matrixauth.integrations.casc.PermissionEntryForCasc; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -211,6 +212,15 @@ default void add(String shortForm) { "Processing a permission assignment in the legacy format (without explicit TYPE prefix): " + shortForm); } + Permission p = getPermission(shortForm, permissionString, sid); + if (p == null) { + return; + } + add(p, new PermissionEntry(type, sid)); + } + + @Restricted(NoExternalUse.class) + /* private when allowed */ default Permission getPermission(String shortForm, String permissionString, String sid) { Permission p = Permission.fromId(permissionString); if (p == null) { // attempt to find the permission based on the 'nice' name, e.g. Overall/Administer @@ -223,9 +233,18 @@ default void add(String shortForm) { LOGGER.log( Level.WARNING, "Tried to add inapplicable permission " + p + " for " + sid + " in " + this + ", skipping"); - return; + return null; } - add(p, new PermissionEntry(type, sid)); + return p; + } + + @Restricted(NoExternalUse.class) + default void add(PermissionEntryForCasc permissionEntryForCasc) { + PermissionEntry entry = permissionEntryForCasc.retrieveEntry(); + Permission p = getPermission( + permissionEntryForCasc.getPermission(), permissionEntryForCasc.getPermission(), entry.getSid()); + + add(p, entry); } @Restricted(NoExternalUse.class) diff --git a/src/main/java/org/jenkinsci/plugins/matrixauth/integrations/casc/AuthorizationMatrixNodePropertyConfigurator.java b/src/main/java/org/jenkinsci/plugins/matrixauth/integrations/casc/AuthorizationMatrixNodePropertyConfigurator.java index a29d36bd..d2091646 100644 --- a/src/main/java/org/jenkinsci/plugins/matrixauth/integrations/casc/AuthorizationMatrixNodePropertyConfigurator.java +++ b/src/main/java/org/jenkinsci/plugins/matrixauth/integrations/casc/AuthorizationMatrixNodePropertyConfigurator.java @@ -57,7 +57,8 @@ protected AuthorizationMatrixNodeProperty instance(Mapping mapping, Configuratio @NonNull public Set> describe() { return new HashSet<>(Arrays.asList( - new MultivaluedAttribute("permissions", String.class) + new MultivaluedAttribute( + "permissions", PermissionEntryForCasc.class) .getter(MatrixAuthorizationStrategyConfigurator::getPermissions) .setter(MatrixAuthorizationStrategyConfigurator::setPermissions), new DescribableAttribute( diff --git a/src/main/java/org/jenkinsci/plugins/matrixauth/integrations/casc/MatrixAuthorizationStrategyConfigurator.java b/src/main/java/org/jenkinsci/plugins/matrixauth/integrations/casc/MatrixAuthorizationStrategyConfigurator.java index e47174f8..94ead16a 100644 --- a/src/main/java/org/jenkinsci/plugins/matrixauth/integrations/casc/MatrixAuthorizationStrategyConfigurator.java +++ b/src/main/java/org/jenkinsci/plugins/matrixauth/integrations/casc/MatrixAuthorizationStrategyConfigurator.java @@ -5,14 +5,13 @@ import io.jenkins.plugins.casc.Attribute; import io.jenkins.plugins.casc.BaseConfigurator; import io.jenkins.plugins.casc.impl.attributes.MultivaluedAttribute; -import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.stream.Collectors; import org.jenkinsci.plugins.matrixauth.AuthorizationContainer; +import org.jenkinsci.plugins.matrixauth.AuthorizationType; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -29,25 +28,31 @@ public Class getImplementedAPI() { @Override @NonNull public Set> describe() { - return new HashSet<>(Arrays.asList( - new MultivaluedAttribute("permissions", String.class) + return new HashSet<>(Collections.singletonList( + new MultivaluedAttribute("permissions", PermissionEntryForCasc.class) .getter(MatrixAuthorizationStrategyConfigurator::getPermissions) - .setter(MatrixAuthorizationStrategyConfigurator::setPermissions), - - // support old style configuration options - new MultivaluedAttribute("grantedPermissions", String.class) - .getter(unused -> null) - .setter(MatrixAuthorizationStrategyConfigurator::setPermissionsDeprecated))); + .setter(MatrixAuthorizationStrategyConfigurator::setPermissions))); } /** * Extract container's permissions as a List of "TYPE:PERMISSION:sid" */ - public static Collection getPermissions(AuthorizationContainer container) { + public static Collection getPermissions(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())) + .flatMap(e -> e.getValue().stream().map(v -> { + PermissionEntryForCasc entry = + new PermissionEntryForCasc(e.getKey().group.getId() + "/" + e.getKey().name); + if (v.getType().equals(AuthorizationType.USER)) { + entry.setUser(v.getSid()); + return entry; + } else if (v.getType().equals(AuthorizationType.GROUP)) { + entry.setGroup(v.getSid()); + return entry; + } else { + entry.setAmbiguous(v.getSid()); + return entry; + } + })) .sorted() .collect(Collectors.toList()); } @@ -55,20 +60,8 @@ public static Collection getPermissions(AuthorizationContainer container /** * Configure container's permissions from a List of "PERMISSION:sid" or "TYPE:PERMISSION:sid" */ - public static void setPermissions(AuthorizationContainer container, Collection permissions) { + public static void setPermissions( + AuthorizationContainer container, Collection permissions) { permissions.forEach(container::add); } - - /** - * Like {@link #setPermissions(AuthorizationContainer, Collection)} but logs a deprecation warning - */ - public static void setPermissionsDeprecated(AuthorizationContainer container, Collection permissions) { - LOGGER.log( - Level.WARNING, - "Loading deprecated attribute 'grantedPermissions' for instance of '" - + container.getClass().getName() + "'. Use 'permissions' instead."); - setPermissions(container, permissions); - } - - private static final Logger LOGGER = Logger.getLogger(MatrixAuthorizationStrategyConfigurator.class.getName()); } diff --git a/src/main/java/org/jenkinsci/plugins/matrixauth/integrations/casc/PermissionEntryForCasc.java b/src/main/java/org/jenkinsci/plugins/matrixauth/integrations/casc/PermissionEntryForCasc.java new file mode 100644 index 00000000..7d4c7797 --- /dev/null +++ b/src/main/java/org/jenkinsci/plugins/matrixauth/integrations/casc/PermissionEntryForCasc.java @@ -0,0 +1,85 @@ +package org.jenkinsci.plugins.matrixauth.integrations.casc; + +import java.util.Objects; +import java.util.logging.Logger; +import org.apache.commons.lang.StringUtils; +import org.jenkinsci.plugins.matrixauth.AuthorizationType; +import org.jenkinsci.plugins.matrixauth.PermissionEntry; +import org.kohsuke.stapler.DataBoundConstructor; + +public class PermissionEntryForCasc implements Comparable { + + private static final Logger LOGGER = Logger.getLogger(PermissionEntryForCasc.class.getName()); + + private String user; + private String group; + private String ambiguous; + private String permission; + + @DataBoundConstructor + public PermissionEntryForCasc(String permission) { + this.permission = permission; + } + + public String getPermission() { + return permission; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + + public String getAmbiguous() { + return ambiguous; + } + + public void setAmbiguous(String ambiguous) { + LOGGER.warning(String.format( + "Setting deprecated attribute 'ambiguous' for '%s' use 'user' or 'group' instead", ambiguous)); + this.ambiguous = ambiguous; + } + + public PermissionEntry retrieveEntry() { + if (StringUtils.isNotBlank(user)) { + return PermissionEntry.user(user); + } + + if (StringUtils.isNotBlank(group)) { + return PermissionEntry.group(group); + } + + return new PermissionEntry(AuthorizationType.EITHER, ambiguous); + } + + @Override + public int compareTo(PermissionEntryForCasc obj) { + return permission.compareTo(obj.permission); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PermissionEntryForCasc that = (PermissionEntryForCasc) o; + return Objects.equals(user, that.user) + && Objects.equals(group, that.group) + && permission.equals(that.permission); + } + + @Override + public int hashCode() { + return Objects.hash(user, group, permission); + } +} diff --git a/src/test/java/org/jenkinsci/plugins/matrixauth/integrations/casc/ExportTest.java b/src/test/java/org/jenkinsci/plugins/matrixauth/integrations/casc/ExportTest.java index c82783a3..ecd57507 100644 --- a/src/test/java/org/jenkinsci/plugins/matrixauth/integrations/casc/ExportTest.java +++ b/src/test/java/org/jenkinsci/plugins/matrixauth/integrations/casc/ExportTest.java @@ -45,7 +45,6 @@ public void exportTestLegacy() throws Exception { List permissions = mapping.get("permissions").asSequence(); assertEquals("list size", 18, permissions.size()); - assertNull("no grantedPermissions", mapping.get("grantedPermissions")); { List strings = Arrays.asList( "Credentials/Create:authenticated", @@ -67,7 +66,13 @@ public void exportTestLegacy() throws Exception { "View/Configure:authenticated", "View/Delete:authenticated"); for (CNode entry : permissions) { - String value = entry.asScalar().getValue(); + Mapping permissionEntry = entry.asMapping(); + CNode sidCNode = permissionEntry.get("ambiguous"); + String sid = sidCNode.asScalar().getValue(); + String permission = + permissionEntry.get("permission").asScalar().getValue(); + + String value = permission + ":" + sid; assertTrue("list contains entry " + value, strings.contains(value)); } } @@ -97,7 +102,13 @@ public void exportTestLegacy() throws Exception { "Agent/Delete:authenticated", "Agent/Disconnect:authenticated"); for (CNode entry : permissions) { - String value = entry.asScalar().getValue(); + Mapping permissionEntry = entry.asMapping(); + CNode sidCNode = permissionEntry.get("ambiguous"); + String sid = sidCNode.asScalar().getValue(); + String permission = + permissionEntry.get("permission").asScalar().getValue(); + + String value = permission + ":" + sid; assertTrue("list contains entry " + value, strings.contains(value)); } } @@ -146,7 +157,18 @@ public void exportTest() throws Exception { "GROUP:View/Configure:authenticated", "GROUP:View/Delete:authenticated"); for (CNode entry : permissions) { - String value = entry.asScalar().getValue(); + Mapping permissionEntry = entry.asMapping(); + CNode sidCNode = permissionEntry.get("group"); + boolean user = sidCNode == null; + if (user) { + sidCNode = permissionEntry.get("user"); + } + String sid = sidCNode.asScalar().getValue(); + String permission = + permissionEntry.get("permission").asScalar().getValue(); + + String type = user ? "USER" : "GROUP"; + String value = type + ":" + permission + ":" + sid; assertTrue("list contains entry " + value, strings.contains(value)); } } @@ -175,7 +197,18 @@ public void exportTest() throws Exception { "GROUP:Agent/Delete:authenticated", "GROUP:Agent/Disconnect:authenticated"); for (CNode entry : permissions) { - String value = entry.asScalar().getValue(); + Mapping permissionEntry = entry.asMapping(); + CNode sidCNode = permissionEntry.get("group"); + boolean user = sidCNode == null; + if (user) { + sidCNode = permissionEntry.get("user"); + } + String sid = sidCNode.asScalar().getValue(); + String permission = + permissionEntry.get("permission").asScalar().getValue(); + + String type = user ? "USER" : "GROUP"; + String value = type + ":" + permission + ":" + sid; assertTrue("list contains entry " + value, strings.contains(value)); } } diff --git a/src/test/java/org/jenkinsci/plugins/matrixauth/integrations/casc/ImportTest.java b/src/test/java/org/jenkinsci/plugins/matrixauth/integrations/casc/ImportTest.java index 7761f8c1..305a31b5 100644 --- a/src/test/java/org/jenkinsci/plugins/matrixauth/integrations/casc/ImportTest.java +++ b/src/test/java/org/jenkinsci/plugins/matrixauth/integrations/casc/ImportTest.java @@ -218,56 +218,4 @@ private static void should_support_configuration_as_codeStep(JenkinsRule r) thro .filter(l -> l.getLoggerName().equals(MatrixAuthorizationStrategyConfigurator.class.getName())) .count()); } - - @Test - public void legacyTest() throws Throwable { - rr.then(ImportTest::legacyTestStep); - } - - private static void legacyTestStep(JenkinsRule r) throws ConfiguratorException { - ConfigurationAsCode.get() - .configure(Objects.requireNonNull(ImportTest.class.getResource("legacy-format.yml")) - .toExternalForm()); - - assertTrue("security realm", r.jenkins.getSecurityRealm() instanceof HudsonPrivateSecurityRealm); - AuthorizationStrategy authorizationStrategy = r.jenkins.getAuthorizationStrategy(); - assertTrue("authorization strategy", authorizationStrategy instanceof ProjectMatrixAuthorizationStrategy); - ProjectMatrixAuthorizationStrategy projectMatrixAuthorizationStrategy = - (ProjectMatrixAuthorizationStrategy) authorizationStrategy; - { // global - assertEquals( - "two ambiguous sids", - 2, - projectMatrixAuthorizationStrategy.getAllPermissionEntries().size()); - assertThat( - projectMatrixAuthorizationStrategy.getAllPermissionEntries(), - hasItems( - new PermissionEntry(AuthorizationType.EITHER, "anonymous"), - new PermissionEntry(AuthorizationType.EITHER, "authenticated"))); - assertTrue( - "anon can read", - projectMatrixAuthorizationStrategy.hasExplicitPermission("anonymous", Jenkins.READ)); - assertTrue( - "authenticated can read", - projectMatrixAuthorizationStrategy.hasExplicitPermission("authenticated", Jenkins.READ)); - assertTrue( - "authenticated can build", - projectMatrixAuthorizationStrategy.hasExplicitPermission("authenticated", Item.BUILD)); - assertTrue( - "authenticated can delete jobs", - projectMatrixAuthorizationStrategy.hasExplicitPermission("authenticated", Item.DELETE)); - assertTrue( - "authenticated can administer", - projectMatrixAuthorizationStrategy.hasExplicitPermission("authenticated", Jenkins.ADMINISTER)); - } - - assertTrue("at least one warning", Jenkins.logRecords.stream().anyMatch(l -> l.getLoggerName() - .equals(MatrixAuthorizationStrategyConfigurator.class.getName()))); - assertTrue( - "correct message", - Jenkins.logRecords.stream() - .anyMatch(l -> l.getLoggerName().equals(MatrixAuthorizationStrategyConfigurator.class.getName()) - && l.getMessage() - .contains("Loading deprecated attribute 'grantedPermissions' for instance"))); - } } diff --git a/src/test/resources/org/jenkinsci/plugins/matrixauth/integrations/casc/configuration-as-code-ambiguous.yml b/src/test/resources/org/jenkinsci/plugins/matrixauth/integrations/casc/configuration-as-code-ambiguous.yml index 4b9a2d0f..695d2aa8 100644 --- a/src/test/resources/org/jenkinsci/plugins/matrixauth/integrations/casc/configuration-as-code-ambiguous.yml +++ b/src/test/resources/org/jenkinsci/plugins/matrixauth/integrations/casc/configuration-as-code-ambiguous.yml @@ -2,36 +2,66 @@ jenkins: authorizationStrategy: projectMatrix: permissions: - - "Agent/Build:authenticated" - - "Agent/Configure:authenticated" - - "Agent/Connect:authenticated" - - "Agent/Create:authenticated" - - "Agent/Delete:authenticated" - - "Agent/Disconnect:authenticated" - - "Credentials/Create:authenticated" - - "Credentials/Delete:authenticated" - - "Credentials/ManageDomains:authenticated" - - "Credentials/Update:authenticated" - - "Credentials/View:authenticated" - - "Job/Build:authenticated" - - "Job/Cancel:authenticated" - - "Job/Configure:authenticated" - - "Job/Create:authenticated" - - "Job/Delete:authenticated" - - "Job/Discover:authenticated" - - "Job/Move:authenticated" - - "Job/Read:authenticated" - - "Job/Workspace:authenticated" - - "Overall/Read:anonymous" - - "Overall/Administer:authenticated" - - "Overall/Read:authenticated" - - "Run/Delete:authenticated" - - "Run/Replay:authenticated" - - "Run/Update:authenticated" - - "View/Configure:authenticated" - - "View/Create:authenticated" - - "View/Delete:authenticated" - - "View/Read:authenticated" + - ambiguous: "authenticated" + permission: "Agent/Build" + - ambiguous: "authenticated" + permission: "Agent/Configure" + - ambiguous: "authenticated" + permission: "Agent/Connect" + - ambiguous: "authenticated" + permission: "Agent/Create" + - ambiguous: "authenticated" + permission: "Agent/Delete" + - ambiguous: "authenticated" + permission: "Agent/Disconnect" + - ambiguous: "authenticated" + permission: "Credentials/Create" + - ambiguous: "authenticated" + permission: "Credentials/Delete" + - ambiguous: "authenticated" + permission: "Credentials/ManageDomains" + - ambiguous: "authenticated" + permission: "Credentials/Update" + - ambiguous: "authenticated" + permission: "Credentials/View" + - ambiguous: "authenticated" + permission: "Job/Build" + - ambiguous: "authenticated" + permission: "Job/Cancel" + - ambiguous: "authenticated" + permission: "Job/Configure" + - ambiguous: "authenticated" + permission: "Job/Create" + - ambiguous: "authenticated" + permission: "Job/Delete" + - ambiguous: "authenticated" + permission: "Job/Discover" + - ambiguous: "authenticated" + permission: "Job/Move" + - ambiguous: "authenticated" + permission: "Job/Read" + - ambiguous: "authenticated" + permission: "Job/Workspace" + - ambiguous: "anonymous" + permission: "Overall/Read" + - ambiguous: "authenticated" + permission: "Overall/Administer" + - ambiguous: "authenticated" + permission: "Overall/Read" + - ambiguous: "authenticated" + permission: "Run/Delete" + - ambiguous: "authenticated" + permission: "Run/Replay" + - ambiguous: "authenticated" + permission: "Run/Update" + - ambiguous: "authenticated" + permission: "View/Configure" + - ambiguous: "authenticated" + permission: "View/Create" + - ambiguous: "authenticated" + permission: "View/Delete" + - ambiguous: "authenticated" + permission: "View/Read" nodes: - permanent: launcher: @@ -45,9 +75,12 @@ jenkins: - authorizationMatrix: inheritanceStrategy: "inheritingGlobal" permissions: - - "Agent/Disconnect:authenticated" - - "Agent/Build:authenticated" - - "Agent/Build:anonymous" + - ambiguous: "authenticated" + permission: "Agent/Disconnect" + - ambiguous: "authenticated" + permission: "Agent/Build" + - ambiguous: "anonymous" + permission: "Agent/Build" numExecutors: 1 retentionStrategy: "always" securityRealm: diff --git a/src/test/resources/org/jenkinsci/plugins/matrixauth/integrations/casc/configuration-as-code.yml b/src/test/resources/org/jenkinsci/plugins/matrixauth/integrations/casc/configuration-as-code.yml index 2633cb80..5a3ddb2a 100644 --- a/src/test/resources/org/jenkinsci/plugins/matrixauth/integrations/casc/configuration-as-code.yml +++ b/src/test/resources/org/jenkinsci/plugins/matrixauth/integrations/casc/configuration-as-code.yml @@ -2,36 +2,66 @@ jenkins: authorizationStrategy: projectMatrix: permissions: - - "GROUP:Agent/Build:authenticated" - - "GROUP:Agent/Configure:authenticated" - - "GROUP:Agent/Connect:authenticated" - - "GROUP:Agent/Create:authenticated" - - "GROUP:Agent/Delete:authenticated" - - "GROUP:Agent/Disconnect:authenticated" - - "GROUP:Credentials/Create:authenticated" - - "GROUP:Credentials/Delete:authenticated" - - "GROUP:Credentials/ManageDomains:authenticated" - - "GROUP:Credentials/Update:authenticated" - - "GROUP:Credentials/View:authenticated" - - "GROUP:Job/Build:authenticated" - - "GROUP:Job/Cancel:authenticated" - - "GROUP:Job/Configure:authenticated" - - "GROUP:Job/Create:authenticated" - - "GROUP:Job/Delete:authenticated" - - "GROUP:Job/Discover:authenticated" - - "GROUP:Job/Move:authenticated" - - "GROUP:Job/Read:authenticated" - - "GROUP:Job/Workspace:authenticated" - - "GROUP:Overall/Administer:authenticated" - - "GROUP:Overall/Read:authenticated" - - "GROUP:Run/Delete:authenticated" - - "GROUP:Run/Replay:authenticated" - - "GROUP:Run/Update:authenticated" - - "GROUP:View/Configure:authenticated" - - "GROUP:View/Create:authenticated" - - "GROUP:View/Delete:authenticated" - - "GROUP:View/Read:authenticated" - - "USER:Overall/Read:anonymous" + - permission: "Agent/Build" + group: "authenticated" + - permission: "Agent/Configure" + group: "authenticated" + - permission: "Agent/Connect" + group: "authenticated" + - permission: "Agent/Create" + group: "authenticated" + - permission: "Agent/Delete" + group: "authenticated" + - permission: "Agent/Disconnect" + group: "authenticated" + - permission: "Credentials/Create" + group: "authenticated" + - permission: "Credentials/Delete" + group: "authenticated" + - permission: "Credentials/ManageDomains" + group: "authenticated" + - permission: "Credentials/Update" + group: "authenticated" + - permission: "Credentials/View" + group: "authenticated" + - permission: "Job/Build" + group: "authenticated" + - permission: "Job/Cancel" + group: "authenticated" + - permission: "Job/Configure" + group: "authenticated" + - permission: "Job/Create" + group: "authenticated" + - permission: "Job/Delete" + group: "authenticated" + - permission: "Job/Discover" + group: "authenticated" + - permission: "Job/Move" + group: "authenticated" + - permission: "Job/Read" + group: "authenticated" + - permission: "Job/Workspace" + group: "authenticated" + - permission: "Overall/Administer" + group: "authenticated" + - permission: "Overall/Read" + group: "authenticated" + - permission: "Run/Delete" + group: "authenticated" + - permission: "Run/Replay" + group: "authenticated" + - permission: "Run/Update" + group: "authenticated" + - permission: "View/Configure" + group: "authenticated" + - permission: "View/Create" + group: "authenticated" + - permission: "View/Delete" + group: "authenticated" + - permission: "View/Read" + group: "authenticated" + - user: "anonymous" + permission: "Overall/Read" nodes: - permanent: launcher: @@ -45,9 +75,12 @@ jenkins: - authorizationMatrix: inheritanceStrategy: "inheritingGlobal" permissions: - - "GROUP:Agent/Disconnect:authenticated" - - "GROUP:Agent/Build:authenticated" - - "USER:Agent/Build:anonymous" + - permission: "Agent/Disconnect" + group: "authenticated" + - permission: "Agent/Build" + group: "authenticated" + - user: "anonymous" + permission: "Agent/Build" numExecutors: 1 retentionStrategy: "always" securityRealm: diff --git a/src/test/resources/org/jenkinsci/plugins/matrixauth/integrations/casc/legacy-format.yml b/src/test/resources/org/jenkinsci/plugins/matrixauth/integrations/casc/legacy-format.yml deleted file mode 100644 index 8cd63c85..00000000 --- a/src/test/resources/org/jenkinsci/plugins/matrixauth/integrations/casc/legacy-format.yml +++ /dev/null @@ -1,38 +0,0 @@ -jenkins: - authorizationStrategy: - projectMatrix: - grantedPermissions: - - "Agent/Build:authenticated" - - "Agent/Configure:authenticated" - - "Agent/Connect:authenticated" - - "Agent/Create:authenticated" - - "Agent/Delete:authenticated" - - "Agent/Disconnect:authenticated" - - "Credentials/Create:authenticated" - - "Credentials/Delete:authenticated" - - "Credentials/ManageDomains:authenticated" - - "Credentials/Update:authenticated" - - "Credentials/View:authenticated" - - "Job/Build:authenticated" - - "Job/Cancel:authenticated" - - "Job/Configure:authenticated" - - "Job/Create:authenticated" - - "Job/Delete:authenticated" - - "Job/Discover:authenticated" - - "Job/Move:authenticated" - - "Job/Read:authenticated" - - "Job/Workspace:authenticated" - - "Overall/Read:anonymous" - - "Overall/Administer:authenticated" - - "Overall/Read:authenticated" - - "Run/Delete:authenticated" - - "Run/Replay:authenticated" - - "Run/Update:authenticated" - - "View/Configure:authenticated" - - "View/Create:authenticated" - - "View/Delete:authenticated" - - "View/Read:authenticated" - securityRealm: - local: - allowsSignup: true - enableCaptcha: false