mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
Pin the MCP Server plugin and let a boot hook mint the API token MCP clients present, then take that token over into sys-token-store and verify it against the controller before the deploy continues. Wait for the controller to answer before probing. A JCasC change restarts Jenkins, and the probe carries no retries of its own, so a single 5xx during startup failed the deploy with a credential that was valid all along. Authenticate with HTTP Basic. The plugin offers no bearer, which is why basic_auth entered the service contract instead of the role working around it. Assert the guarded surface, not the handshake: the plugin answers initialize anonymously because that call is capability negotiation and carries no data, while an unauthenticated tools/list is refused and leaks no tool inventory. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
30 lines
866 B
Groovy
30 lines
866 B
Groovy
import hudson.model.User
|
|
import jenkins.security.ApiTokenProperty
|
|
|
|
def username = System.getenv('JENKINS_MCP_USERNAME')
|
|
def tokenName = System.getenv('JENKINS_MCP_TOKEN_NAME')
|
|
def tokenFile = System.getenv('JENKINS_MCP_TOKEN_FILE')
|
|
|
|
if (!username || !tokenName || !tokenFile) {
|
|
return
|
|
}
|
|
|
|
def target = new File(tokenFile)
|
|
def user = User.getById(username, true)
|
|
def store = user.getProperty(ApiTokenProperty.class).tokenStore
|
|
|
|
if (target.isFile() && store.findMatchingToken(target.text.trim()) != null) {
|
|
return
|
|
}
|
|
|
|
store.tokenListSortedByName.findAll { it.name == tokenName }.each { store.revokeToken(it.uuid) }
|
|
def minted = store.generateNewToken(tokenName)
|
|
user.save()
|
|
|
|
target.parentFile.mkdirs()
|
|
target.text = minted.plainValue
|
|
target.setReadable(false, false)
|
|
target.setWritable(false, false)
|
|
target.setReadable(true, true)
|
|
target.setWritable(true, true)
|