github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/builtin/providers/tls/resource_private_key.go (about) 1 package tls 2 3 import ( 4 "crypto/ecdsa" 5 "crypto/elliptic" 6 "crypto/rand" 7 "crypto/rsa" 8 "crypto/x509" 9 "encoding/pem" 10 "fmt" 11 12 "github.com/hashicorp/terraform/helper/schema" 13 ) 14 15 type keyAlgo func(d *schema.ResourceData) (interface{}, error) 16 type keyParser func([]byte) (interface{}, error) 17 18 var keyAlgos map[string]keyAlgo = map[string]keyAlgo{ 19 "RSA": func(d *schema.ResourceData) (interface{}, error) { 20 rsaBits := d.Get("rsa_bits").(int) 21 return rsa.GenerateKey(rand.Reader, rsaBits) 22 }, 23 "ECDSA": func(d *schema.ResourceData) (interface{}, error) { 24 curve := d.Get("ecdsa_curve").(string) 25 switch curve { 26 case "P224": 27 return ecdsa.GenerateKey(elliptic.P224(), rand.Reader) 28 case "P256": 29 return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 30 case "P384": 31 return ecdsa.GenerateKey(elliptic.P384(), rand.Reader) 32 case "P521": 33 return ecdsa.GenerateKey(elliptic.P521(), rand.Reader) 34 default: 35 return nil, fmt.Errorf("invalid ecdsa_curve; must be P224, P256, P384 or P521") 36 } 37 }, 38 } 39 40 var keyParsers map[string]keyParser = map[string]keyParser{ 41 "RSA": func(der []byte) (interface{}, error) { 42 return x509.ParsePKCS1PrivateKey(der) 43 }, 44 "ECDSA": func(der []byte) (interface{}, error) { 45 return x509.ParseECPrivateKey(der) 46 }, 47 } 48 49 func resourcePrivateKey() *schema.Resource { 50 return &schema.Resource{ 51 Create: CreatePrivateKey, 52 Delete: DeletePrivateKey, 53 Read: ReadPrivateKey, 54 55 Schema: map[string]*schema.Schema{ 56 "algorithm": &schema.Schema{ 57 Type: schema.TypeString, 58 Required: true, 59 Description: "Name of the algorithm to use to generate the private key", 60 ForceNew: true, 61 }, 62 63 "rsa_bits": &schema.Schema{ 64 Type: schema.TypeInt, 65 Optional: true, 66 Description: "Number of bits to use when generating an RSA key", 67 ForceNew: true, 68 Default: 2048, 69 }, 70 71 "ecdsa_curve": &schema.Schema{ 72 Type: schema.TypeString, 73 Optional: true, 74 Description: "ECDSA curve to use when generating a key", 75 ForceNew: true, 76 Default: "P224", 77 }, 78 79 "private_key_pem": &schema.Schema{ 80 Type: schema.TypeString, 81 Computed: true, 82 }, 83 }, 84 } 85 } 86 87 func CreatePrivateKey(d *schema.ResourceData, meta interface{}) error { 88 keyAlgoName := d.Get("algorithm").(string) 89 var keyFunc keyAlgo 90 var ok bool 91 if keyFunc, ok = keyAlgos[keyAlgoName]; !ok { 92 return fmt.Errorf("invalid key_algorithm %#v", keyAlgoName) 93 } 94 95 key, err := keyFunc(d) 96 if err != nil { 97 return err 98 } 99 100 var keyPemBlock *pem.Block 101 switch k := key.(type) { 102 case *rsa.PrivateKey: 103 keyPemBlock = &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)} 104 case *ecdsa.PrivateKey: 105 b, err := x509.MarshalECPrivateKey(k) 106 if err != nil { 107 return fmt.Errorf("error encoding key to PEM: %s", err) 108 } 109 keyPemBlock = &pem.Block{Type: "EC PRIVATE KEY", Bytes: b} 110 default: 111 return fmt.Errorf("unsupported private key type") 112 } 113 keyPem := string(pem.EncodeToMemory(keyPemBlock)) 114 115 pubKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey(key)) 116 if err != nil { 117 return fmt.Errorf("failed to marshal public key: %s", err) 118 } 119 120 d.SetId(hashForState(string((pubKeyBytes)))) 121 d.Set("private_key_pem", keyPem) 122 123 return nil 124 } 125 126 func DeletePrivateKey(d *schema.ResourceData, meta interface{}) error { 127 d.SetId("") 128 return nil 129 } 130 131 func ReadPrivateKey(d *schema.ResourceData, meta interface{}) error { 132 return nil 133 } 134 135 func publicKey(priv interface{}) interface{} { 136 switch k := priv.(type) { 137 case *rsa.PrivateKey: 138 return &k.PublicKey 139 case *ecdsa.PrivateKey: 140 return &k.PublicKey 141 default: 142 return nil 143 } 144 }