configuration-as-code-plugin icon indicating copy to clipboard operation
configuration-as-code-plugin copied to clipboard

Ability to preconfigure an API token via JCasC

Open jglick opened this issue 3 years ago • 13 comments

What feature do you want to see added?

As @timblaktu notes in https://gitter.im/jenkinsci/configuration-as-code-plugin?at=60d7401b24f0ae2a242bba42 it seems impossible to preconfigure an API token for a user via JCasC. https://github.com/jenkinsci/jenkins/pull/4027 introduced a system property to generate one for admin but this only works if the setup wizard is run, which for JCasC users it would generally not be. I can use e.g.

jenkins:
  securityRealm:
    local:
      allowsSignup: false
      users:
      - id: admin
        password: ${readFile:/var/password}
  authorizationStrategy:
    loggedInUsersCanDoAnything:
      allowAnonymousRead: false

to preconfigure an initial password in a way that is friendly to generation from a Kubernetes Secret or the like, and this can be used for CLI operations, but not easily for REST operations using POST method since there will not be a crumb.

Upstream changes

No response

jglick avatar Jan 11 '22 22:01 jglick

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Apr 16 '22 06:04 stale[bot]

This remains valid, call off the stalebots.

jglick avatar Apr 19 '22 18:04 jglick

You might be able to define an ApiTokenProperty with a legacy apiToken loaded from a secret in the usual way, TBD.

jglick avatar Nov 28 '22 12:11 jglick

For those who are stuck with this problem, I bypass it with jcasc groovy plugin. Here's the script:

      groovy: |
        groovy:
          - script: |
                import hudson.model.*
                import jenkins.model.*
                import jenkins.security.*
                import jenkins.security.apitoken.*
                import com.cloudbees.plugins.credentials.domains.Domain
                import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl
                import com.cloudbees.plugins.credentials.CredentialsScope
                
                // script parameters
                def userName = 'USERNAME'
                def tokenName = 'kb-token'
                
                def user = User.get(userName)
                def apiTokenProperty = user.getProperty(ApiTokenProperty.class)
                def result = apiTokenProperty.tokenStore.generateNewToken(tokenName)
                user.save()
                
                instance = Jenkins.instance
                domain = Domain.global()
                store = instance.getExtensionList(
                  "com.cloudbees.plugins.credentials.SystemCredentialsProvider")[0].getStore()
                
                usernameAndPassword = new UsernamePasswordCredentialsImpl(
                  CredentialsScope.GLOBAL,
                  "TOKEN_NAME",
                  "DESCRIPTION",
                  "USERNAME",
                  result.plainValue
                )
                
                store.addCredentials(domain, usernameAndPassword)

jameshwc avatar Feb 23 '23 11:02 jameshwc

In my case, I wanted the token to be stable across deploys so I've used the following pattern:

import hudson.model.User
import jenkins.security.ApiTokenProperty

// workaround for setting api-key https://github.com/jenkinsci/configuration-as-code-plugin/issues/1830
def token = System.getenv("API_TOKEN")
def user = User.get('auto')
user.getProperty(ApiTokenProperty.class).tokenStore.addFixedNewToken("auto-token", token)
user.save()

And then set the API token I wanted as an environment variable during the server start.

gaborbernat avatar Feb 24 '23 02:02 gaborbernat

Same use case here. Many instance deployed on K8S with JCasC. We need a stable API token to perform remote call to instances.

jonesbusy avatar Aug 10 '23 04:08 jonesbusy

Any updates on this?

ifoughal avatar Oct 24 '23 12:10 ifoughal

Any updates on this?

use https://github.com/jenkinsci/configuration-as-code-plugin/issues/1830#issuecomment-1442700057

timja avatar Oct 24 '23 15:10 timja

I've tried this but can't figure out where to put the groovy block in my configuration file. Does it go at the same level as 'jenkins', 'security' and 'unclassified' or does it go under something else like 'unclassified'? I've noticed that if it goes in the wrong place it quietly breaks my configuration and I lose my github securityRealm. Note: I'm trying to do this with the jenkins kubernetes operator.

lordpengwin avatar Jan 11 '24 20:01 lordpengwin

In my case, I wanted the token to be stable across deploys so I've used the following pattern:

import hudson.model.User
import jenkins.security.ApiTokenProperty

// workaround for setting api-key https://github.com/jenkinsci/configuration-as-code-plugin/issues/1830
def token = System.getenv("API_TOKEN")
User.get('auto').getProperty(ApiTokenProperty.class).tokenStore.addFixedNewToken("auto-token", token)

And then set the API token I wanted as an environment variable during the server start.

be sure to call user.save() or the token will not be persisted across sessions!

tailg8nj avatar Feb 20 '24 14:02 tailg8nj

Updated my code sample to include the save 😊

gaborbernat avatar Feb 20 '24 17:02 gaborbernat