Example #1
0
func main() {
	var Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [options] url mountpoint\n", os.Args[0])
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 2 {
		Usage()
		os.Exit(1)
	}

	serverURL, mountpoint := flag.Args()[0], flag.Args()[1]

	logConfig := klog.Config{*debug, mountpoint}
	logger = klog.New("kwfs_main", logConfig)
	defer logger.Close()

	if *certFile == "" {
		logger.Debugf("Certificate file not specified, assuming certificate also in %s", *keyFile)
		certFile = keyFile
	}

	lockMemory()

	clientTimeout := time.Duration(*timeoutSeconds) * time.Second
	freshThreshold := 200 * time.Millisecond
	backendDeadline := 500 * time.Millisecond
	maxWait := clientTimeout + backendDeadline
	timeouts := keywhizfs.Timeouts{freshThreshold, backendDeadline, maxWait}

	client := keywhizfs.NewClient(*certFile, *keyFile, *caFile, serverURL, clientTimeout, logConfig, *ping)

	ownership := keywhizfs.NewOwnership(*user, *group)
	kwfs, root, err := keywhizfs.NewKeywhizFs(&client, ownership, timeouts, logConfig)
	if err != nil {
		log.Fatalf("KeywhizFs init fail: %v\n", err)
	}

	mountOptions := &fuse.MountOptions{
		AllowOther: true,
		Name:       kwfs.String(),
		Options:    []string{"default_permissions"},
	}

	// Empty Options struct avoids setting a global uid/gid override.
	conn := nodefs.NewFileSystemConnector(root, &nodefs.Options{})
	server, err := fuse.NewServer(conn.RawFS(), mountpoint, mountOptions)
	if err != nil {
		log.Fatalf("Mount fail: %v\n", err)
	}

	server.Serve()
}
Example #2
0
// NewKeywhizFs readies a KeywhizFs struct and its parent filesystem objects.
func NewKeywhizFs(client *Client, ownership Ownership, timeouts Timeouts, logConfig log.Config) (kwfs *KeywhizFs, root nodefs.Node, err error) {
	logger := log.New("kwfs", logConfig)
	cache := NewCache(client, timeouts, logConfig)

	defaultfs := pathfs.NewDefaultFileSystem()            // Returns ENOSYS by default
	readonlyfs := pathfs.NewReadonlyFileSystem(defaultfs) // R/W calls return EPERM

	kwfs = &KeywhizFs{readonlyfs, logger, client, cache, time.Now(), ownership}
	nfs := pathfs.NewPathNodeFs(kwfs, nil)
	nfs.SetDebug(logConfig.Debug)
	return kwfs, nfs.Root(), nil
}
// Locks memory, preventing memory from being written to disk as swap
func lockMemory(debug bool) {
	logConfig := klog.Config{
		Debug:      debug,
		Mountpoint: "",
	}
	logger := klog.New("kwfs_main", logConfig)

	err := unix.Mlockall(unix.MCL_FUTURE | unix.MCL_CURRENT)
	switch err {
	case nil:
	case unix.ENOSYS:
		logger.Warnf("mlockall() not implemented on this system")
	case unix.ENOMEM:
		logger.Warnf("mlockall() failed with ENOMEM")
	default:
		log.Fatalf("Could not perform mlockall and prevent swapping memory: %v", err)
	}
}
Example #4
0
// NewClient produces a read-to-use client struct given PEM-encoded certificate file, key file, and
// ca file with the list of trusted certificate authorities.
func NewClient(certFile, keyFile, caFile, serverURL string, timeout time.Duration, logConfig klog.Config, ping bool) (client Client) {
	logger := klog.New("kwfs_client", logConfig)
	params := httpClientParams{certFile, keyFile, caFile, timeout}

	reqc := make(chan http.Client)

	// Getter from channel.
	getClient := func() *http.Client {
		client := <-reqc
		return &(client)
	}

	initial, err := params.buildClient()
	if err != nil {
		panic(err)
	}

	// Asynchronously updates client and owns current reference.
	go func() {
		var current = *initial
		for {
			select {
			case t := <-time.Tick(clientRefresh): // Periodically update client.
				logger.Infof("Updating http client at %v", t)
				if c, err := params.buildClient(); err != nil {
					logger.Errorf("Error refreshing http client: %v", err)
				} else {
					current = *c
				}
			case reqc <- current: // Service request for current client.
			}
		}
	}()

	client = Client{logger, getClient, serverURL}
	if ping {
		if _, ok := client.SecretList(); !ok {
			log.Fatalf("Failed startup /secrets ping to %v", client.url)
		}
	}

	return client
}
Example #5
0
// NewCache initializes a Cache.
func NewCache(backend SecretBackend, timeouts Timeouts, logConfig log.Config) *Cache {
	logger := log.New("kwfs_cache", logConfig)
	return &Cache{logger, NewSecretMap(), backend, timeouts}
}