Simplify Jenkins Role Management with a Go SDK and REST API
This article explains how the Jenkins Role Strategy plugin’s UI can become unresponsive with many users, introduces a Go SDK that wraps its REST API, demonstrates permission template, role, and user/group management code, and shows how to build a simple Gin‑based web UI for role assignment.
Hello, I'm Joker, a cloud-native enthusiast and operations engineer. Author: Joker Public account: 运维开发故事 Blog: https://jokerbai.com
When using Jenkins with the Role Strategy plugin, the permission management UI can become unresponsive as the number of users grows, so I explored the plugin's REST API and created a Go SDK (https://github.com/joker-bai/go-role-strategy-sdk) that wraps all documented endpoints.
Permission template management – create, delete, query templates
Role management – full lifecycle for global, project, and node roles
User/group assignment – flexible assignment of roles to users and groups
Query functions – retrieve role information, assignments, matching jobs/agents
Multiple role types – supports GlobalRole, ProjectRole, SlaveRole
SDK Usage
Installation
go get github.com/joker-bai/go-role-strategy-sdkInitialize client
package main
import (
"fmt"
"log"
rolestrategy "github.com/joker-bai/go-role-strategy-sdk"
)
func main() {
// Create client
client := rolestrategy.NewClient(
"https://your-jenkins-url",
"your-username",
"your-api-token",
)
}Permission template management
// Add permission template
err := client.AddTemplate(
"developer",
"hudson.model.Item.Read,hudson.model.Item.Build",
true, // overwrite
)
if err != nil {
log.Fatal("AddTemplate:", err)
}
// Get permission template
template, err := client.GetTemplate("developer")
if err != nil {
log.Fatal("GetTemplate:", err)
}
fmt.Printf("Template: %+v
", template)
// Delete permission template
err = client.RemoveTemplates([]string{"developer"}, false)
if err != nil {
log.Fatal("RemoveTemplates:", err)
}Role management
// Add global role
err := client.AddRole(
rolestrategy.GlobalRole,
"dev-lead",
"hudson.model.Hudson.Administer",
true, // overwrite
"", // pattern (for project role)
"", // template
)
if err != nil {
log.Fatal("AddRole:", err)
}
// Add project role with pattern
err = client.AddRole(
rolestrategy.ProjectRole,
"project-dev",
"hudson.model.Item.Read,hudson.model.Item.Build",
true,
"dev-.*", // matches projects starting with dev-
"",
)
if err != nil {
log.Fatal("AddRole:", err)
}
// Get role information
role, err := client.GetRole(rolestrategy.GlobalRole, "dev-lead")
if err != nil {
log.Fatal("GetRole:", err)
}
fmt.Printf("Role: %+v
", role)
// Delete role
err = client.RemoveRoles(rolestrategy.GlobalRole, []string{"dev-lead"})
if err != nil {
log.Fatal("RemoveRoles:", err)
}User and group assignment
// Assign user role
err := client.AssignUserRole(rolestrategy.GlobalRole, "dev-lead", "alice")
if err != nil {
log.Fatal("AssignUserRole:", err)
}
// Assign group role
err = client.AssignGroupRole(rolestrategy.ProjectRole, "project-dev", "developers")
if err != nil {
log.Fatal("AssignGroupRole:", err)
}
// Unassign user role
err = client.UnassignUserRole(rolestrategy.GlobalRole, "dev-lead", "alice")
if err != nil {
log.Fatal("UnassignUserRole:", err)
}
// Unassign group role
err = client.UnassignGroupRole(rolestrategy.ProjectRole, "project-dev", "developers")
if err != nil {
log.Fatal("UnassignGroupRole:", err)
}Query functions
// Get all roles
allRoles, err := client.GetAllRoles(rolestrategy.GlobalRole)
if err != nil {
log.Fatal("GetAllRoles:", err)
}
fmt.Printf("All Roles: %+v
", allRoles)
// Get role assignments
assignments, err := client.GetRoleAssignments(rolestrategy.GlobalRole)
if err != nil {
log.Fatal("GetRoleAssignments:", err)
}
fmt.Printf("Assignments: %+v
", assignments)
// Get global role names
globalRoles, err := client.GetGlobalRoleNames()
if err != nil {
log.Fatal("GetGlobalRoleNames:", err)
}
fmt.Println("Global Roles:", globalRoles)
// Get project role names
projectRoles, err := client.GetProjectRoleNames()
if err != nil {
log.Fatal("GetProjectRoleNames:", err)
}
fmt.Println("Project Roles:", projectRoles)
// Get matching jobs
matchingJobs, err := client.GetMatchingJobs("dev-.*", 10)
if err != nil {
log.Fatal("GetMatchingJobs:", err)
}
fmt.Printf("Matching Jobs: %+v
", matchingJobs)
// Get matching agents
matchingAgents, err := client.GetMatchingAgents("agent-.*", 10)
if err != nil {
log.Fatal("GetMatchingAgents:", err)
}
fmt.Printf("Matching Agents: %+v
", matchingAgents)Develop a Web UI
With the SDK ready, a simple web UI can be built; the backend uses the Gin framework and exposes four endpoints: /api/users, /api/roles/global, /api/roles/project, and /api/users/assign.
Backend code (main.go)
// main.go
package main
import (
"fmt"
"log"
"net/http"
"strconv"
"strings"
"github.com/gin-gonic/gin"
rolestrategy "github.com/joker-bai/go-role-strategy-sdk"
)
type AssignRequest struct {
Username string `json:"username" binding:"required"`
GlobalRoles []string `json:"globalRoles"`
ProjectRoles []string `json:"projectRoles"`
}
// ... (rest of the server implementation as described) ...The front‑end is a simple HTML page (not shown) that consumes these APIs. Screenshots illustrate the UI, user detail view, and role editing.
This demo can be extended to integrate with an enterprise user directory, support multiple Jenkins instances, or improve the UI aesthetics.
Ops Development Stories
Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
