github.com/swiftstack/ProxyFS@v0.0.0-20210203235616-4017c267d62f/pfsagentd/pfsagentd-swift-auth-plugin/main.go (about) 1 // Copyright (c) 2015-2021, NVIDIA CORPORATION. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package main 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "io" 10 "net/http" 11 "os" 12 "strings" 13 14 "github.com/swiftstack/ProxyFS/version" 15 ) 16 17 type authInStruct struct { 18 AuthURL string 19 AuthUser string 20 AuthKey string 21 Account string 22 } 23 24 type authOutStruct struct { 25 AuthToken string 26 StorageURL string 27 } 28 29 const ( 30 stdinReadSize = 1 31 ) 32 33 func main() { 34 var ( 35 authIn authInStruct 36 err error 37 plugInEnvName string 38 plugInEnvValue string 39 stdinReadBuf []byte 40 ) 41 42 switch len(os.Args) { 43 case 0: 44 fmt.Fprintf(os.Stderr, "Logic error... len(os.Args) cannot be zero\n") 45 os.Exit(1) 46 case 1: 47 fmt.Fprintf(os.Stderr, "Missing PlugInEnvName\n") 48 os.Exit(1) 49 case 2: 50 plugInEnvName = os.Args[1] 51 default: 52 fmt.Fprintf(os.Stderr, "Superfluous arguments (beyond PlugInEnvName) supplied: %v\n", os.Args[2:]) 53 os.Exit(1) 54 } 55 56 plugInEnvValue = os.Getenv(plugInEnvName) 57 58 err = json.Unmarshal([]byte(plugInEnvValue), &authIn) 59 if nil != err { 60 fmt.Fprintf(os.Stderr, "json.Unmarshal(\"%s\",) failed: %v\n", plugInEnvValue, err) 61 os.Exit(1) 62 } 63 64 performAuth(&authIn) 65 66 stdinReadBuf = make([]byte, stdinReadSize) 67 68 for { 69 stdinReadBuf = stdinReadBuf[:stdinReadSize] 70 _, err = os.Stdin.Read(stdinReadBuf) 71 if nil == err { 72 performAuth(&authIn) 73 } else { 74 if io.EOF == err { 75 os.Exit(0) 76 } 77 fmt.Fprintf(os.Stderr, "os.Stdin.Read(stdinReadBuf) failed: %v\n", err) 78 os.Exit(1) 79 } 80 } 81 } 82 83 func performAuth(authIn *authInStruct) { 84 var ( 85 authOut *authOutStruct 86 authOutJSON []byte 87 authRequest *http.Request 88 authResponse *http.Response 89 err error 90 storageURLSplit []string 91 ) 92 93 authRequest, err = http.NewRequest("GET", authIn.AuthURL, nil) 94 if nil != err { 95 fmt.Fprintf(os.Stderr, "http.NewRequest(\"GET\", \"%s\", nil) failed: %v\n", authIn.AuthURL, err) 96 os.Exit(1) 97 } 98 99 authRequest.Header.Add("X-Auth-User", authIn.AuthUser) 100 authRequest.Header.Add("X-Auth-Key", authIn.AuthKey) 101 102 authRequest.Header.Add("User-Agent", "PFSAgent-Auth "+version.ProxyFSVersion) 103 104 authResponse, err = http.DefaultClient.Do(authRequest) 105 if nil != err { 106 fmt.Fprintf(os.Stderr, "http.DefaultClient.Do(authRequest) failed: %v\n", err) 107 os.Exit(1) 108 } 109 110 if http.StatusOK != authResponse.StatusCode { 111 fmt.Fprintf(os.Stderr, "authResponse.Status unexpecte: %v\n", authResponse.Status) 112 os.Exit(1) 113 } 114 115 authOut = &authOutStruct{ 116 AuthToken: authResponse.Header.Get("X-Auth-Token"), 117 StorageURL: authResponse.Header.Get("X-Storage-Url"), 118 } 119 120 if strings.HasPrefix(authIn.AuthURL, "https://") && strings.HasPrefix(authOut.StorageURL, "http://") { 121 // We need to correct for the case where AuthURL starts with "https://"" 122 // but the Swift Proxy is behind a TLS terminating proxy. In this case, 123 // Swift Proxy auth will actually see an AuthURL starting with "http://"" 124 // and respond with a StorageURL starting with "http://"". 125 126 authOut.StorageURL = strings.Replace(authOut.StorageURL, "http://", "https://", 1) 127 } 128 129 storageURLSplit = strings.Split(authOut.StorageURL, "/") 130 131 storageURLSplit[3] = "proxyfs" 132 storageURLSplit[4] = authIn.Account 133 134 authOut.StorageURL = strings.Join(storageURLSplit, "/") 135 136 authOutJSON, err = json.Marshal(authOut) 137 if nil != err { 138 fmt.Fprintf(os.Stderr, "json.Marshal(authOut) failed: %v\n", err) 139 os.Exit(1) 140 } 141 142 _, err = os.Stdout.Write(authOutJSON) 143 if nil != err { 144 fmt.Fprintf(os.Stderr, "os.Stdout.Write(authOutJSON) failed: %v\n", err) 145 os.Exit(1) 146 } 147 }