// WriteDefaultConfigFile generates a new default high-level server configuration // file at filePath. If useSQLite, the default indexer will use SQLite, otherwise // kv. If filePath already exists, it is overwritten. func WriteDefaultConfigFile(filePath string, useSQLite bool) error { conf := serverconfig.Config{ Listen: ":3179", HTTPS: false, Auth: "localhost", ReplicateTo: make([]interface{}, 0), } blobDir := osutil.CamliBlobRoot() if err := os.MkdirAll(blobDir, 0700); err != nil { return fmt.Errorf("Could not create default blobs directory: %v", err) } conf.BlobPath = blobDir if useSQLite { conf.SQLite = filepath.Join(osutil.CamliVarDir(), "camli-index.db") } else { conf.KVFile = filepath.Join(osutil.CamliVarDir(), "camli-index.kvdb") } var keyId string secRing := osutil.SecretRingFile() _, err := os.Stat(secRing) switch { case err == nil: keyId, err = jsonsign.KeyIdFromRing(secRing) if err != nil { return fmt.Errorf("Could not find any keyId in file %q: %v", secRing, err) } log.Printf("Re-using identity with keyId %q found in file %s", keyId, secRing) case os.IsNotExist(err): keyId, err = jsonsign.GenerateNewSecRing(secRing) if err != nil { return fmt.Errorf("Could not generate new secRing at file %q: %v", secRing, err) } log.Printf("Generated new identity with keyId %q in file %s", keyId, secRing) } if err != nil { return fmt.Errorf("Could not stat secret ring %q: %v", secRing, err) } conf.Identity = keyId conf.IdentitySecretRing = secRing confData, err := json.MarshalIndent(conf, "", " ") if err != nil { return fmt.Errorf("Could not json encode config file : %v", err) } if err := ioutil.WriteFile(filePath, confData, 0600); err != nil { return fmt.Errorf("Could not create or write default server config: %v", err) } return nil }
// SecretRingFile returns the filename to the user's GPG secret ring. // The value comes from either the --secret-keyring flag, the // CAMLI_SECRET_RING environment variable, the client config file's // "identitySecretRing" value, or the operating system default location. func (c *Client) SecretRingFile() string { if secretRing, ok := osutil.ExplicitSecretRingFile(); ok { return secretRing } if android.OnAndroid() { panic("on android, so CAMLI_SECRET_RING should have been defined, or --secret-keyring used.") } configOnce.Do(parseConfig) if config.IdentitySecretRing == "" { return osutil.SecretRingFile() } return config.IdentitySecretRing }
// initSecretRing sets c.secretRing. It tries, in this order, the --secret-keyring flag, // the CAMLI_SECRET_RING env var, then defaults to the operating system dependent location // otherwise. // It returns an error if the file does not exist. func (c *initCmd) initSecretRing() error { if secretRing, ok := osutil.ExplicitSecretRingFile(); ok { c.secretRing = secretRing } else { if android.OnAndroid() { panic("on android, so CAMLI_SECRET_RING should have been defined, or --secret-keyring used.") } c.secretRing = osutil.SecretRingFile() } if _, err := os.Stat(c.secretRing); err != nil { hint := "\nA GPG key is required, please use 'camput init --newkey'.\n\nOr if you know what you're doing, you can set the global camput flag --secret-keyring, or the CAMLI_SECRET_RING env var, to use your own GPG ring. And --gpgkey=<pubid> or GPGKEY to select which key ID to use." return fmt.Errorf("Could not use secret ring file %v: %v.\n%v", c.secretRing, err, hint) } return nil }
// SecretRingFile returns the filename to the user's GPG secret ring. // The value comes from either the --secret-keyring flag, the // CAMLI_SECRET_RING environment variable, the client config file's // "identitySecretRing" value, or the operating system default location. func (c *Client) SecretRingFile() string { if secretRing, ok := osutil.ExplicitSecretRingFile(); ok { return secretRing } if android.OnAndroid() { panic("on android, so CAMLI_SECRET_RING should have been defined, or --secret-keyring used.") } if c.paramsOnly { log.Print("client: paramsOnly set; cannot get secret ring file from config or env vars.") return "" } if configDisabled { panic("Need a secret ring, and config file disabled") } configOnce.Do(parseConfig) if config.IdentitySecretRing == "" { return osutil.SecretRingFile() } return config.IdentitySecretRing }
// EntityFromSecring returns the openpgp Entity from keyFile that matches keyId. // If empty, keyFile defaults to osutil.SecretRingFile(). func EntityFromSecring(keyId, keyFile string) (*openpgp.Entity, error) { if keyId == "" { return nil, errors.New("empty keyId passed to EntityFromSecring") } keyId = strings.ToUpper(keyId) if keyFile == "" { keyFile = osutil.SecretRingFile() } secring, err := wkfs.Open(keyFile) if err != nil { return nil, fmt.Errorf("jsonsign: failed to open keyring: %v", err) } defer secring.Close() el, err := openpgp.ReadKeyRing(secring) if err != nil { return nil, fmt.Errorf("openpgp.ReadKeyRing of %q: %v", keyFile, err) } var entity *openpgp.Entity for _, e := range el { pk := e.PrivateKey if pk == nil || (pk.KeyIdString() != keyId && pk.KeyIdShortString() != keyId) { continue } entity = e } if entity == nil { found := []string{} for _, e := range el { pk := e.PrivateKey if pk == nil { continue } found = append(found, pk.KeyIdShortString()) } return nil, fmt.Errorf("didn't find a key in %q for keyId %q; other keyIds in file = %v", keyFile, keyId, found) } return entity, nil }
func getOrMakeKeyring() (keyID, secRing string, err error) { secRing = osutil.SecretRingFile() _, err = wkfs.Stat(secRing) switch { case err == nil: keyID, err = jsonsign.KeyIdFromRing(secRing) if err != nil { err = fmt.Errorf("Could not find any keyID in file %q: %v", secRing, err) return } log.Printf("Re-using identity with keyID %q found in file %s", keyID, secRing) case os.IsNotExist(err): keyID, err = jsonsign.GenerateNewSecRing(secRing) if err != nil { err = fmt.Errorf("Could not generate new secRing at file %q: %v", secRing, err) return } log.Printf("Generated new identity with keyID %q in file %s", keyID, secRing) default: err = fmt.Errorf("Could not stat secret ring %q: %v", secRing, err) } return }
func FlagEntityFetcher() *FileEntityFetcher { return &FileEntityFetcher{File: osutil.SecretRingFile()} }
func (sr *SignRequest) secretRingPath() string { if sr.SecretKeyringPath != "" { return sr.SecretKeyringPath } return osutil.SecretRingFile() }
func (h *Handler) secretRingPath() string { if h.secretRing != "" { return h.secretRing } return osutil.SecretRingFile() }
// DefaultEnvConfig returns the default configuration when running on a known // environment. Currently this just includes Google Compute Engine. // If the environment isn't known (nil, nil) is returned. func DefaultEnvConfig() (*Config, error) { if !env.OnGCE() { return nil, nil } auth := "none" user, _ := metadata.InstanceAttributeValue("camlistore-username") pass, _ := metadata.InstanceAttributeValue("camlistore-password") confBucket, err := metadata.InstanceAttributeValue("camlistore-config-dir") if confBucket == "" || err != nil { return nil, fmt.Errorf("VM instance metadata key 'camlistore-config-dir' not set: %v", err) } blobBucket, err := metadata.InstanceAttributeValue("camlistore-blob-dir") if blobBucket == "" || err != nil { return nil, fmt.Errorf("VM instance metadata key 'camlistore-blob-dir' not set: %v", err) } if user != "" && pass != "" { auth = "userpass:"******":" + pass } if v := osutil.SecretRingFile(); !strings.HasPrefix(v, "/gcs/") { return nil, fmt.Errorf("Internal error: secret ring path on GCE should be at /gcs/, not %q", v) } keyId, secRing, err := getOrMakeKeyring() if err != nil { return nil, err } ipOrHost, _ := metadata.ExternalIP() host, _ := metadata.InstanceAttributeValue("camlistore-hostname") if host != "" && host != "localhost" { ipOrHost = host } highConf := &serverconfig.Config{ Auth: auth, BaseURL: fmt.Sprintf("https://%s", ipOrHost), HTTPS: true, Listen: "0.0.0.0:443", Identity: keyId, IdentitySecretRing: secRing, GoogleCloudStorage: ":" + strings.TrimPrefix(blobBucket, "gs://"), DBNames: map[string]string{}, PackRelated: true, // SourceRoot is where we look for the UI js/css/html files, and the Closure resources. // Must be in sync with misc/docker/server/Dockerfile. SourceRoot: "/camlistore", } // Detect a linked Docker MySQL container. It must have alias "mysqldb". if v := os.Getenv("MYSQLDB_PORT"); strings.HasPrefix(v, "tcp://") { hostPort := strings.TrimPrefix(v, "tcp://") highConf.MySQL = "root@" + hostPort + ":" // no password highConf.DBNames["queue-sync-to-index"] = "sync_index_queue" highConf.DBNames["ui_thumbcache"] = "ui_thumbmeta_cache" highConf.DBNames["blobpacked_index"] = "blobpacked_index" } else { // TODO: also detect Cloud SQL. highConf.KVFile = "/index.kv" } return genLowLevelConfig(highConf) }