github.com/google/osv-scalibr@v0.4.1/clients/datasource/maven_settings.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 datasource 16 17 import ( 18 "encoding/xml" 19 "os" 20 "os/exec" 21 "path/filepath" 22 "regexp" 23 "runtime" 24 "strings" 25 "unicode" 26 ) 27 28 // Maven settings.xml file parsing for registry authentication. 29 // https://maven.apache.org/settings.html 30 31 // MavenSettingsXML defines Maven settings.xml. 32 type MavenSettingsXML struct { 33 Servers []MavenSettingsXMLServer `xml:"servers>server"` 34 } 35 36 // MavenSettingsXMLServer defines a Maven server in settings.xml. 37 type MavenSettingsXMLServer struct { 38 ID string `xml:"id"` 39 Username string `xml:"username"` 40 Password string `xml:"password"` 41 } 42 43 // ParseMavenSettings parses Maven settings at the given path. 44 func ParseMavenSettings(path string) MavenSettingsXML { 45 f, err := os.Open(path) 46 if err != nil { 47 return MavenSettingsXML{} 48 } 49 defer f.Close() 50 51 var settings MavenSettingsXML 52 if err := xml.NewDecoder(f).Decode(&settings); err != nil { 53 return MavenSettingsXML{} 54 } 55 56 // interpolate strings with environment variables only 57 // system properties are too hard to determine. 58 re := regexp.MustCompile(`\${env\.[^}]*}`) 59 replFn := func(match string) string { 60 // grab just the environment variable string 61 env := match[len("${env.") : len(match)-1] 62 63 // Environment variables on Windows are case-insensitive, 64 // but Maven will only replace them if they are in all-caps. 65 if runtime.GOOS == "windows" && strings.ContainsFunc(env, unicode.IsLower) { 66 return match // No replacement. 67 } 68 69 if val, ok := os.LookupEnv(env); ok { 70 return val 71 } 72 73 // Don't do any replacement if the environment variable isn't set 74 return match 75 } 76 for i := range settings.Servers { 77 settings.Servers[i].ID = re.ReplaceAllStringFunc(settings.Servers[i].ID, replFn) 78 settings.Servers[i].Username = re.ReplaceAllStringFunc(settings.Servers[i].Username, replFn) 79 settings.Servers[i].Password = re.ReplaceAllStringFunc(settings.Servers[i].Password, replFn) 80 } 81 82 return settings 83 } 84 85 // TODO(#409): How to use with virtual filesystem + environment variables. 86 func globalMavenSettingsFile() string { 87 // ${maven.home}/conf/settings.xml 88 // Find ${maven.home} from the installed mvn binary 89 mvnExec, err := exec.LookPath("mvn") 90 if err != nil { 91 return "" 92 } 93 mvnExec, err = filepath.EvalSymlinks(mvnExec) 94 if err != nil { 95 return "" 96 } 97 98 settings := filepath.Join(filepath.Dir(mvnExec), "..", "conf", "settings.xml") 99 settings, err = filepath.Abs(settings) 100 if err != nil { 101 return "" 102 } 103 104 return settings 105 } 106 107 func userMavenSettingsFile() string { 108 // ${user.home}/.m2/settings.xml 109 home, err := os.UserHomeDir() 110 if err != nil { 111 return "" 112 } 113 114 return filepath.Join(home, ".m2", "settings.xml") 115 } 116 117 var mavenSupportedAuths = []HTTPAuthMethod{AuthDigest, AuthBasic} 118 119 // MakeMavenAuth returns a map of Maven authentication information index by repository ID. 120 func MakeMavenAuth(globalSettings, userSettings MavenSettingsXML) map[string]*HTTPAuthentication { 121 auth := make(map[string]*HTTPAuthentication) 122 for _, s := range globalSettings.Servers { 123 auth[s.ID] = &HTTPAuthentication{ 124 SupportedMethods: mavenSupportedAuths, 125 AlwaysAuth: false, 126 Username: s.Username, 127 Password: s.Password, 128 } 129 } 130 131 for _, s := range userSettings.Servers { 132 auth[s.ID] = &HTTPAuthentication{ 133 SupportedMethods: mavenSupportedAuths, 134 AlwaysAuth: false, 135 Username: s.Username, 136 Password: s.Password, 137 } 138 } 139 140 return auth 141 }