jenkinsci / configuration-as-code-plugin

Jenkins Configuration as Code Plugin
https://plugins.jenkins.io/configuration-as-code
MIT License
2.69k stars 718 forks source link

Ability to preconfigure an API token via JCasC #1830

Open jglick opened 2 years ago

jglick commented 2 years ago

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

stale[bot] commented 2 years ago

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.

jglick commented 2 years ago

This remains valid, call off the stalebots.

jglick commented 1 year ago

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

jameshwc commented 1 year ago

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)
gaborbernat commented 1 year ago

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.

jonesbusy commented 1 year ago

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

ifoughal commented 11 months ago

Any updates on this?

timja commented 11 months ago

Any updates on this?

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

lordpengwin commented 9 months ago

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.

tailg8nj commented 7 months ago

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!

gaborbernat commented 7 months ago

Updated my code sample to include the save 😊

CodesReallyWell commented 2 months ago

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.

You need this plugin: https://plugins.jenkins.io/configuration-as-code-groovy/

Root element would look like this

groovy:
  - script: |
      your script here