Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-52339

New API Token system should allow tokens to be created for service accounts

    XMLWordPrintable

Details

    • Improvement
    • Status: Closed (View Workflow)
    • Major
    • Resolution: Not A Defect
    • core
    • Jenkins 2.129

    Description

      Jenkins 2.129 introduced a new API token system (see Security Hardening: New API token system).

      The recommendation is for users to delete their existing (legacy) tokens, and replace them (if they are required) with a newly generated non-legacy token.

      However, I cannot do that for a service account that cannot log in. 

      • Previously, administrators could generate tokens on behalf of such users.
      • In 2.129+, an administrator can generate a new value for an existing legacy token, but cannot generate a new non-legacy token for a service user.

      Administrators should be able to generate a token for a service account.

       

       

      Attachments

        Activity

          A system property already supports this.

          mwebber Matthew Webber added a comment - A system property already supports this.
          mthaddon Tom Haddon added a comment - - edited

          Is there any documentation on how to create a new API token using groovy? I'm trying to following (having run jenkins.security.ApiTokenProperty.ADMIN_CAN_GENERATE_NEW_TOKENS = true per above and got 'Result: true\n' for that):

          user = hudson.model.User.get('admin')
          prop = user.getProperty(jenkins.security.ApiTokenProperty.class)
          println(prop.getApiToken())

          But I get 'This user currently does not have a legacy token\n'. Obviously I don't want a legacy token, I'm just not sure how to get a new token.

          Hope it's okay to comment on a closed issue, thought it was better than opening a new one, but let me know if you'd prefer that.

           

          mthaddon Tom Haddon added a comment - - edited Is there any documentation on how to create a new API token using groovy? I'm trying to following (having run jenkins.security.ApiTokenProperty.ADMIN_CAN_GENERATE_NEW_TOKENS = true per above and got 'Result: true\n' for that): user = hudson.model.User.get('admin') prop = user.getProperty(jenkins.security.ApiTokenProperty.class) println(prop.getApiToken()) But I get 'This user currently does not have a legacy token\n'. Obviously I don't want a legacy token, I'm just not sure how to get a new token. Hope it's okay to comment on a closed issue, thought it was better than opening a new one, but let me know if you'd prefer that.  

          Hello mthaddon

          Commenting on a closed ticket exposes the risk to be completely ignored The best way to ask your question is on IRC I think.

          Anyway, here is a way to generate API Token for a user, using Groovy script console:

          import hudson.model.*
          import jenkins.model.*
          import jenkins.security.*
          import jenkins.security.apitoken.*
          
          // you can change the "admin" name
          // the false is to explicitely ask to not create a user who does not exist yet
          def user = User.get("admin", false)
          def prop = user.getProperty(ApiTokenProperty.class)
          // the name is up to you
          def result = prop.tokenStore.generateNewToken("token-created-by-script")
          user.save()
          
          return result.plainValue
          
          wfollonier Wadeck Follonier added a comment - Hello mthaddon Commenting on a closed ticket exposes the risk to be completely ignored The best way to ask your question is on IRC I think. Anyway, here is a way to generate API Token for a user, using Groovy script console: import hudson.model.* import jenkins.model.* import jenkins.security.* import jenkins.security.apitoken.* // you can change the "admin" name // the false is to explicitely ask to not create a user who does not exist yet def user = User.get( "admin" , false ) def prop = user.getProperty(ApiTokenProperty.class) // the name is up to you def result = prop.tokenStore.generateNewToken( "token-created-by-script" ) user.save() return result.plainValue
          mthaddon Tom Haddon added a comment -

          Great, thanks!

           

          Will use IRC next time

          mthaddon Tom Haddon added a comment - Great, thanks!   Will use IRC next time
          timblaktu Tim Black added a comment -

          FWIW, here's an alternative solution that uses a pre-determined token, which is useful for automated jenkins deployments when you really want to "bake in" a token a priori. Note this is from an ansible/jinja2 template, which explains the {{{{ var }}}} syntax. 
           
           

          # NOTE: Don't use > yaml multiline formatting as this will squash newlines into spaces. Use | instead.
          groovy:
            # Generate API Token for Jenkins Admin user. This is used by automated configuration/validation tasks
            # Solution from here: https://issues.jenkins.io/browse/JENKINS-52339
            # ..and here: https://support.cloudbees.com/hc/en-us/articles/115003090592-How-to-re-generate-my-Jenkins-user-token#programmaticallycreatingatoken
            - script: |
            println("Inline Groovy Script: Enter..");
            import hudson.model.*;
            import jenkins.model.*;
            import jenkins.security.*;
            import jenkins.security.apitoken.*;
            
            def userName = "{{ jenkins_admin_active_directory_username }}";
            def tokenName = "{{ jenkins_admin_active_directory_jenkins_api_token_name }}";
            def tokenUuid = "{{ jenkins_admin_active_directory_jenkins_api_token }}";
            def user = User.get("$userName", false);
            def prop = user.getProperty(ApiTokenProperty.class);
            if (prop.tokenStore.findMatchingToken("$tokenUuid") != null) {
              println("Inline Groovy Script: Token with name $tokenName already exists.");
            } 
            else {
              println("Inline Groovy Script: Token with name $tokenName does NOT exist. Creating it...");
              def newTokenString = prop.tokenStore.addFixedNewToken(tokenName, tokenUuid);
              println("Inline Groovy Script: Added New Fixed Token '$newTokenString' in Property Token Store");
              user.save();
              println("Inline Groovy Script: Created API token for $userName.");
            }
            println("Inline Groovy Script: Exiting..")            

           
           

          timblaktu Tim Black added a comment - FWIW, here's an alternative solution that uses a pre-determined token, which is useful for automated jenkins deployments when you really want to "bake in" a token a priori. Note this is from an ansible/jinja2 template, which explains the {{{{ var }}}} syntax.      # NOTE: Don't use > yaml multiline formatting as this will squash newlines into spaces. Use | instead. groovy: # Generate API Token for Jenkins Admin user. This is used by automated configuration/validation tasks # Solution from here: https: //issues.jenkins.io/browse/JENKINS-52339 # ..and here: https: //support.cloudbees.com/hc/en-us/articles/115003090592-How-to-re-generate-my-Jenkins-user-token#programmaticallycreatingatoken - script: | println( "Inline Groovy Script: Enter.." ); import hudson.model.*; import jenkins.model.*; import jenkins.security.*; import jenkins.security.apitoken.*; def userName = "{{ jenkins_admin_active_directory_username }}" ; def tokenName = "{{ jenkins_admin_active_directory_jenkins_api_token_name }}" ; def tokenUuid = "{{ jenkins_admin_active_directory_jenkins_api_token }}" ; def user = User.get( "$userName" , false ); def prop = user.getProperty(ApiTokenProperty.class); if (prop.tokenStore.findMatchingToken( "$tokenUuid" ) != null ) { println( "Inline Groovy Script: Token with name $tokenName already exists." ); } else { println( "Inline Groovy Script: Token with name $tokenName does NOT exist. Creating it..." ); def newTokenString = prop.tokenStore.addFixedNewToken(tokenName, tokenUuid); println( "Inline Groovy Script: Added New Fixed Token '$newTokenString' in Property Token Store" ); user.save(); println( "Inline Groovy Script: Created API token for $userName." ); } println( "Inline Groovy Script: Exiting.." )        

          People

            wfollonier Wadeck Follonier
            mwebber Matthew Webber
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: