github.com/Venafi/vcert/v5@v5.10.2/pkg/playbook/app/service/tokenService.go (about) 1 /* 2 * Copyright 2023 Venafi, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package service 18 19 import ( 20 "fmt" 21 22 "go.uber.org/zap" 23 24 "github.com/Venafi/vcert/v5/pkg/playbook/app/domain" 25 "github.com/Venafi/vcert/v5/pkg/playbook/app/parser" 26 "github.com/Venafi/vcert/v5/pkg/playbook/app/vcertutil" 27 ) 28 29 // ValidateTPPCredentials checks that the TPP credentials are not expired. 30 // 31 // If expired, it will try to get a new token pair using the refreshToken. 32 // 33 // If the refreshing is successful it will save the new token pair in the playbook file. 34 func ValidateTPPCredentials(playbook *domain.Playbook) error { 35 //Validate TPP tokens 36 if playbook.Config.Connection.Credentials.AccessToken != "" { 37 isValid, err := vcertutil.IsValidAccessToken(playbook.Config) 38 // Return any error besides 401 Unauthorized - need to properly handle errors unrelated to the state of the token (connectivity) 39 if err != nil && err.Error() != "failed to verify token. Message: 401 Unauthorized" { 40 return err 41 } 42 if isValid { 43 return nil 44 } 45 } 46 47 zap.L().Info("access token is invalid, missing, or expired") 48 if playbook.Config.Connection.Credentials.RefreshToken == "" && playbook.Config.Connection.Credentials.P12Task == "" { 49 return fmt.Errorf("access token no longer valid and no authorization methods specified - cannot get a new access token") 50 } 51 52 zap.L().Info("using refresh token") 53 54 // Read the playbook first, to make sure we can, before refreshing the tokens 55 // and blowing things up! 56 pbData, err := parser.ReadPlaybookRaw(playbook.Location) 57 if err != nil { 58 return err 59 } 60 61 accessToken, refreshToken, err := vcertutil.RefreshTPPTokens(playbook.Config) 62 if err != nil { 63 zap.L().Error("failed to refresh TPP Tokens", zap.Error(err)) 64 return err 65 } 66 zap.L().Info("successfully retrieved new refresh token") 67 68 playbook.Config.Connection.Credentials.AccessToken = accessToken 69 playbook.Config.Connection.Credentials.RefreshToken = refreshToken 70 71 err = replaceTokensInFile(pbData, accessToken, refreshToken) 72 if err != nil { 73 zap.L().Error("failed to replace tokens in playbook file", zap.Error(err)) 74 return err 75 } 76 77 err = parser.WritePlaybook(pbData, playbook.Location) 78 if err != nil { 79 zap.L().Error("failed to serialize new tokens to playbook file", zap.Error(err)) 80 return err 81 } 82 83 return nil 84 } 85 86 func replaceTokensInFile(playbook map[string]interface{}, accessToken string, refreshToken string) error { 87 88 if playbook == nil { 89 return fmt.Errorf("playbook data is nil") 90 } 91 cfg, found := playbook["config"] 92 if !found { 93 return fmt.Errorf("no config found in Playbook data") 94 } 95 96 conn, found := cfg.(map[string]interface{})["connection"] 97 if !found { 98 return fmt.Errorf("no connection found in Playbook data") 99 } 100 101 creds, found := conn.(map[string]interface{})["credentials"] 102 if !found { 103 return fmt.Errorf("no credentials found in Playbook data") 104 } 105 106 credsMap := creds.(map[string]interface{}) 107 credsMap["accessToken"] = accessToken 108 credsMap["refreshToken"] = refreshToken 109 110 return nil 111 }