github.com/ojiry/terraform@v0.8.2-0.20161218223921-e50cec712c4a/state/remote/manta.go (about) 1 package remote 2 3 import ( 4 "crypto/md5" 5 "encoding/pem" 6 "fmt" 7 "io/ioutil" 8 "log" 9 "os" 10 11 joyentclient "github.com/joyent/gocommon/client" 12 joyenterrors "github.com/joyent/gocommon/errors" 13 "github.com/joyent/gomanta/manta" 14 joyentauth "github.com/joyent/gosign/auth" 15 ) 16 17 const DEFAULT_OBJECT_NAME = "terraform.tfstate" 18 19 func mantaFactory(conf map[string]string) (Client, error) { 20 path, ok := conf["path"] 21 if !ok { 22 return nil, fmt.Errorf("missing 'path' configuration") 23 } 24 25 objectName, ok := conf["objectName"] 26 if !ok { 27 objectName = DEFAULT_OBJECT_NAME 28 } 29 30 creds, err := getCredentialsFromEnvironment() 31 32 if err != nil { 33 return nil, fmt.Errorf("Error getting Manta credentials: %s", err.Error()) 34 } 35 36 client := manta.New(joyentclient.NewClient( 37 creds.MantaEndpoint.URL, 38 "", 39 creds, 40 log.New(os.Stderr, "", log.LstdFlags), 41 )) 42 43 return &MantaClient{ 44 Client: client, 45 Path: path, 46 ObjectName: objectName, 47 }, nil 48 } 49 50 type MantaClient struct { 51 Client *manta.Client 52 Path string 53 ObjectName string 54 } 55 56 func (c *MantaClient) Get() (*Payload, error) { 57 bytes, err := c.Client.GetObject(c.Path, c.ObjectName) 58 if err != nil { 59 if joyenterrors.IsResourceNotFound(err.(joyenterrors.Error).Cause()) { 60 return nil, nil 61 } 62 63 return nil, err 64 } 65 66 md5 := md5.Sum(bytes) 67 68 return &Payload{ 69 Data: bytes, 70 MD5: md5[:], 71 }, nil 72 } 73 74 func (c *MantaClient) Put(data []byte) error { 75 return c.Client.PutObject(c.Path, c.ObjectName, data) 76 } 77 78 func (c *MantaClient) Delete() error { 79 return c.Client.DeleteObject(c.Path, c.ObjectName) 80 } 81 82 func getCredentialsFromEnvironment() (cred *joyentauth.Credentials, err error) { 83 84 user := os.Getenv("MANTA_USER") 85 keyId := os.Getenv("MANTA_KEY_ID") 86 url := os.Getenv("MANTA_URL") 87 keyMaterial := os.Getenv("MANTA_KEY_MATERIAL") 88 89 if _, err := os.Stat(keyMaterial); err == nil { 90 // key material is a file path; try to read it 91 keyBytes, err := ioutil.ReadFile(keyMaterial) 92 if err != nil { 93 return nil, fmt.Errorf("Error reading key material from %s: %s", 94 keyMaterial, err) 95 } else { 96 block, _ := pem.Decode(keyBytes) 97 if block == nil { 98 return nil, fmt.Errorf( 99 "Failed to read key material '%s': no key found", keyMaterial) 100 } 101 102 if block.Headers["Proc-Type"] == "4,ENCRYPTED" { 103 return nil, fmt.Errorf( 104 "Failed to read key '%s': password protected keys are\n"+ 105 "not currently supported. Please decrypt the key prior to use.", keyMaterial) 106 } 107 108 keyMaterial = string(keyBytes) 109 } 110 } 111 112 authentication, err := joyentauth.NewAuth(user, keyMaterial, "rsa-sha256") 113 if err != nil { 114 return nil, fmt.Errorf("Error constructing authentication for %s: %s", user, err) 115 } 116 117 return &joyentauth.Credentials{ 118 UserAuthentication: authentication, 119 SdcKeyId: "", 120 SdcEndpoint: joyentauth.Endpoint{}, 121 MantaKeyId: keyId, 122 MantaEndpoint: joyentauth.Endpoint{URL: url}, 123 }, nil 124 }