github.com/google/osv-scalibr@v0.4.1/veles/secrets/dockerhubpat/validator.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package dockerhubpat 16 17 import ( 18 "context" 19 "errors" 20 "fmt" 21 "net/http" 22 "time" 23 24 "github.com/google/osv-scalibr/veles" 25 "github.com/google/osv-scalibr/veles/secrets/common/simplevalidate" 26 ) 27 28 // Validator is a validator for DockerHub PATs. 29 type Validator struct { 30 HTTPC *http.Client 31 Endpoint string 32 } 33 34 // Validate validates a DockerHub PAT. 35 // 36 // It performs a POST request to the Docker Hub create access token endpoint 37 // using the PAT and username in the request body. If the request returns 38 // HTTP 200, the key is considered valid. If 401 Unauthorized or PAT's Username 39 // is empty, the key is invalid. Other errors return ValidationFailed. 40 func (v *Validator) Validate(ctx context.Context, k DockerHubPAT) (veles.ValidationStatus, error) { 41 if k.Username == "" { 42 return veles.ValidationInvalid, errors.New("username is empty") 43 } 44 // We use a wrapper around simplevalidate to provide more accurate validation 45 // of the secrets. Otherwise, we wouldn't be able to fit this extra logic into 46 // the simplevalidate model. 47 sv := &simplevalidate.Validator[DockerHubPAT]{ 48 Endpoint: v.Endpoint, 49 HTTPMethod: http.MethodPost, 50 Body: func(k DockerHubPAT) (string, error) { 51 return fmt.Sprintf(`{"identifier": "%s","secret": "%s"}`, k.Username, k.Pat), nil 52 }, 53 HTTPHeaders: func(k DockerHubPAT) map[string]string { 54 return map[string]string{ 55 "Content-Type": "application/json", 56 } 57 }, 58 ValidResponseCodes: []int{http.StatusOK}, 59 InvalidResponseCodes: []int{http.StatusUnauthorized}, 60 HTTPC: v.HTTPC, 61 } 62 return sv.Validate(ctx, k) 63 } 64 65 // NewValidator creates a new Validator for DockerHub PATs. 66 func NewValidator() *Validator { 67 return &Validator{ 68 Endpoint: "https://hub.docker.com/v2/auth/token/", 69 HTTPC: &http.Client{ 70 Timeout: 10 * time.Second, 71 }, 72 } 73 }