summaryrefslogtreecommitdiff
path: root/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/config.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mitchellh/packer/builder/oracle/oci/client/config.go')
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/config.go240
1 files changed, 240 insertions, 0 deletions
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/config.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/config.go
new file mode 100644
index 00000000..580cd9f7
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/config.go
@@ -0,0 +1,240 @@
+package oci
+
+import (
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "os"
+
+ "github.com/go-ini/ini"
+ "github.com/mitchellh/go-homedir"
+)
+
+// Config API authentication and target configuration
+type Config struct {
+ // User OCID e.g. ocid1.user.oc1..aaaaaaaadcshyehbkvxl7arse3lv7z5oknexjgfhnhwidtugsxhlm4247
+ User string `ini:"user"`
+
+ // User's Tenancy OCID e.g. ocid1.tenancy.oc1..aaaaaaaagtgvshv6opxzjyzkupkt64ymd32n6kbomadanpcg43d
+ Tenancy string `ini:"tenancy"`
+
+ // Bare metal region identifier (e.g. us-phoenix-1)
+ Region string `ini:"region"`
+
+ // Hex key fingerprint (e.g. b5:a0:62:57:28:0d:fd:c9:59:16:eb:d4:51:9f:70:e4)
+ Fingerprint string `ini:"fingerprint"`
+
+ // Path to OCI config file (e.g. ~/.oci/config)
+ KeyFile string `ini:"key_file"`
+
+ // Passphrase used for the key, if it is encrypted.
+ PassPhrase string `ini:"pass_phrase"`
+
+ // Private key (loaded via LoadPrivateKey or ParsePrivateKey)
+ Key *rsa.PrivateKey
+
+ // Used to override base API URL.
+ baseURL string
+}
+
+// getBaseURL returns either the specified base URL or builds the appropriate
+// URL based on service, region, and API version.
+func (c *Config) getBaseURL(service string) string {
+ if c.baseURL != "" {
+ return c.baseURL
+ }
+ return fmt.Sprintf(baseURLPattern, service, c.Region, apiVersion)
+}
+
+// LoadConfigsFromFile loads all oracle oci configurations from a file
+// (generally ~/.oci/config).
+func LoadConfigsFromFile(path string) (map[string]*Config, error) {
+ if _, err := os.Stat(path); err != nil {
+ return nil, fmt.Errorf("Oracle OCI config file is missing: %s", path)
+ }
+
+ cfgFile, err := ini.Load(path)
+ if err != nil {
+ err := fmt.Errorf("Failed to parse config file %s: %s", path, err.Error())
+ return nil, err
+ }
+
+ configs := make(map[string]*Config)
+
+ // Load DEFAULT section to populate defaults for all other configs
+ config, err := loadConfigSection(cfgFile, "DEFAULT", nil)
+ if err != nil {
+ return nil, err
+ }
+ configs["DEFAULT"] = config
+
+ // Load other sections.
+ for _, sectionName := range cfgFile.SectionStrings() {
+ if sectionName == "DEFAULT" {
+ continue
+ }
+
+ // Map to Config struct with defaults from DEFAULT section.
+ config, err := loadConfigSection(cfgFile, sectionName, configs["DEFAULT"])
+ if err != nil {
+ return nil, err
+ }
+ configs[sectionName] = config
+ }
+
+ return configs, nil
+}
+
+// Loads an individual Config object from a ini.Section in the Oracle OCI config
+// file.
+func loadConfigSection(f *ini.File, sectionName string, config *Config) (*Config, error) {
+ if config == nil {
+ config = &Config{}
+ }
+
+ section, err := f.GetSection(sectionName)
+ if err != nil {
+ return nil, fmt.Errorf("Config file does not contain a %s section", sectionName)
+ }
+
+ if err := section.MapTo(config); err != nil {
+ return nil, err
+ }
+
+ config.Key, err = LoadPrivateKey(config)
+ if err != nil {
+ return nil, err
+ }
+
+ return config, err
+}
+
+// LoadPrivateKey loads private key from disk and parses it.
+func LoadPrivateKey(config *Config) (*rsa.PrivateKey, error) {
+ // Expand '~' to $HOME
+ path, err := homedir.Expand(config.KeyFile)
+ if err != nil {
+ return nil, err
+ }
+
+ // Read and parse API signing key
+ keyContent, err := ioutil.ReadFile(path)
+ if err != nil {
+ return nil, err
+ }
+ key, err := ParsePrivateKey(keyContent, []byte(config.PassPhrase))
+
+ return key, err
+}
+
+// ParsePrivateKey parses a PEM encoded array of bytes into an rsa.PrivateKey.
+// Attempts to decrypt the PEM encoded array of bytes with the given password
+// if the PEM encoded byte array is encrypted.
+func ParsePrivateKey(content, password []byte) (*rsa.PrivateKey, error) {
+ keyBlock, _ := pem.Decode(content)
+
+ if keyBlock == nil {
+ return nil, errors.New("could not decode PEM private key")
+ }
+
+ var der []byte
+ var err error
+ if x509.IsEncryptedPEMBlock(keyBlock) {
+ if len(password) < 1 {
+ return nil, errors.New("encrypted private key but no pass phrase provided")
+ }
+ der, err = x509.DecryptPEMBlock(keyBlock, password)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ der = keyBlock.Bytes
+ }
+
+ if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
+ return key, nil
+ }
+
+ key, err := x509.ParsePKCS8PrivateKey(der)
+ if err == nil {
+ switch key := key.(type) {
+ case *rsa.PrivateKey:
+ return key, nil
+ default:
+ return nil, errors.New("Private key is not an RSA private key")
+ }
+ }
+ return nil, fmt.Errorf("Failed to parse private key :%s", err)
+}
+
+// BaseTestConfig creates the base (DEFAULT) config including a temporary key
+// file.
+// NOTE: Caller is responsible for removing temporary key file.
+func BaseTestConfig() (*ini.File, *os.File, error) {
+ keyFile, err := generateRSAKeyFile()
+ if err != nil {
+ return nil, keyFile, err
+ }
+ // Build ini
+ cfg := ini.Empty()
+ section, _ := cfg.NewSection("DEFAULT")
+ section.NewKey("region", "us-phoenix-1")
+ section.NewKey("tenancy", "ocid1.tenancy.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+ section.NewKey("user", "ocid1.user.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+ section.NewKey("fingerprint", "3c:b6:44:d7:49:1a:ac:bf:de:7d:76:22:a7:f5:df:55")
+ section.NewKey("key_file", keyFile.Name())
+
+ return cfg, keyFile, nil
+}
+
+// WriteTestConfig writes a ini.File to a temporary file for use in unit tests.
+// NOTE: Caller is responsible for removing temporary file.
+func WriteTestConfig(cfg *ini.File) (*os.File, error) {
+ confFile, err := ioutil.TempFile("", "config_file")
+ if err != nil {
+ return nil, err
+ }
+
+ _, err = cfg.WriteTo(confFile)
+ if err != nil {
+ os.Remove(confFile.Name())
+ return nil, err
+ }
+
+ return confFile, nil
+}
+
+// generateRSAKeyFile generates an RSA key file for use in unit tests.
+// NOTE: The caller is responsible for deleting the temporary file.
+func generateRSAKeyFile() (*os.File, error) {
+ // Create temporary file for the key
+ f, err := ioutil.TempFile("", "key")
+ if err != nil {
+ return nil, err
+ }
+
+ // Generate key
+ priv, err := rsa.GenerateKey(rand.Reader, 2014)
+ if err != nil {
+ return nil, err
+ }
+
+ // ASN.1 DER encoded form
+ privDer := x509.MarshalPKCS1PrivateKey(priv)
+ privBlk := pem.Block{
+ Type: "RSA PRIVATE KEY",
+ Headers: nil,
+ Bytes: privDer,
+ }
+
+ // Write the key out
+ if _, err := f.Write(pem.EncodeToMemory(&privBlk)); err != nil {
+ return nil, err
+ }
+
+ return f, nil
+}