-
Notifications
You must be signed in to change notification settings - Fork 512
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: David Lawrence <[email protected]> (github: endophage)
- Loading branch information
David Lawrence
committed
Jul 11, 2016
1 parent
1ff0f8c
commit 2e34719
Showing
6 changed files
with
550 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package utils | ||
|
||
import ( | ||
"encoding/pem" | ||
"io" | ||
"io/ioutil" | ||
"path/filepath" | ||
) | ||
|
||
// simple interface for the one function we need from the Storage interface | ||
type exportStore interface { | ||
Get(string) ([]byte, error) | ||
ListFiles() []string | ||
} | ||
|
||
type importStore interface { | ||
Set(string, []byte) error | ||
} | ||
|
||
// ExportKeysByGUN exports all keys filtered to a GUN | ||
func ExportKeysByGUN(to io.Writer, s exportStore, gun string) error { | ||
keys := s.ListFiles() | ||
for _, k := range keys { | ||
dir := filepath.Dir(k) | ||
if dir == gun { // must be full GUN match | ||
if err := ExportKeys(to, s, k); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// ExportKeysByID exports all keys matching the given ID | ||
func ExportKeysByID(to io.Writer, s exportStore, ids []string) error { | ||
want := make(map[string]struct{}) | ||
for _, id := range ids { | ||
want[id] = struct{}{} | ||
} | ||
keys := s.ListFiles() | ||
for _, k := range keys { | ||
id := filepath.Base(k) | ||
if _, ok := want[id]; ok { | ||
if err := ExportKeys(to, s, k); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// ExportKeys copies a key from the store to the io.Writer | ||
func ExportKeys(to io.Writer, s exportStore, from string) error { | ||
// get PEM block | ||
k, err := s.Get(from) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// parse PEM blocks if there are more than one | ||
for block, rest := pem.Decode(k); block != nil; block, rest = pem.Decode(rest) { | ||
// add from path in a header for later import | ||
block.Headers["path"] = from | ||
// write serialized PEM | ||
err = pem.Encode(to, block) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// ImportKeys expects an io.Reader containing one or more PEM blocks. | ||
// It reads PEM blocks one at a time until pem.Decode returns a nil | ||
// block. | ||
// Each block is written to the subpath indicated in the "path" PEM | ||
// header. If the file already exists, the file is truncated. Multiple | ||
// PEMs with the same "path" header are appended together. | ||
func ImportKeys(from io.Reader, to importStore) error { | ||
data, err := ioutil.ReadAll(from) | ||
if err != nil { | ||
return err | ||
} | ||
var ( | ||
writeTo string | ||
toWrite []byte | ||
) | ||
for block, rest := pem.Decode(data); block != nil; block, rest = pem.Decode(rest) { | ||
loc, ok := block.Headers["path"] | ||
if !ok || loc == "" { | ||
continue // don't know where to copy this key. Skip it. | ||
} | ||
if loc != writeTo { | ||
// next location is different from previous one. We've finished aggregating | ||
// data for the previous file. If we have data, write the previous file, | ||
// the clear toWrite and set writeTo to the next path we're going to write | ||
if toWrite != nil { | ||
if err = to.Set(writeTo, toWrite); err != nil { | ||
return err | ||
} | ||
} | ||
// set up for aggregating next file's data | ||
toWrite = nil | ||
writeTo = loc | ||
} | ||
delete(block.Headers, "path") | ||
toWrite = append(toWrite, pem.EncodeToMemory(block)...) | ||
} | ||
if toWrite != nil { // close out final iteration if there's data left | ||
if err = to.Set(writeTo, toWrite); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} |
Oops, something went wrong.