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  }