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