@@ -145,7 +145,7 @@ func (i *ParsedIdentities) Import(identity ...string) error {
145145 // one identity per line
146146 r := strings .NewReader (strings .Join (identity , "\n " ))
147147
148- identities , err := parseIdentities (r )
148+ identities , err := parseIdentities (r , false )
149149 if err != nil {
150150 return fmt .Errorf ("failed to parse and add to age identities: %w" , err )
151151 }
@@ -399,17 +399,25 @@ func getUserConfigDir() (string, error) {
399399 return os .UserConfigDir ()
400400}
401401
402+ type identityReader struct {
403+ reader io.Reader
404+ allowMultipleKeysPerLine bool
405+ }
406+
402407// loadIdentities attempts to load the age identities based on runtime
403408// environment configurations (e.g. SopsAgeKeyEnv, SopsAgeKeyFileEnv,
404409// SopsAgeSshPrivateKeyFileEnv, SopsAgeKeyUserConfigPath). It will load all
405410// found references, and expects at least one configuration to be present.
406411func (key * MasterKey ) loadIdentities () (ParsedIdentities , []string , errSet ) {
407412 identities , unusedLocations , errs := key .loadAgeSSHIdentities ()
408413
409- var readers = make (map [string ]io. Reader , 0 )
414+ var readers = make (map [string ]identityReader , 0 )
410415
411416 if ageKey , ok := os .LookupEnv (SopsAgeKeyEnv ); ok {
412- readers [SopsAgeKeyEnv ] = strings .NewReader (ageKey )
417+ readers [SopsAgeKeyEnv ] = identityReader {
418+ reader : strings .NewReader (ageKey ),
419+ allowMultipleKeysPerLine : true ,
420+ }
413421 } else {
414422 unusedLocations = append (unusedLocations , SopsAgeKeyEnv )
415423 }
@@ -420,7 +428,10 @@ func (key *MasterKey) loadIdentities() (ParsedIdentities, []string, errSet) {
420428 errs = append (errs , fmt .Errorf ("failed to open %s file: %w" , SopsAgeKeyFileEnv , err ))
421429 } else {
422430 defer f .Close ()
423- readers [SopsAgeKeyFileEnv ] = f
431+ readers [SopsAgeKeyFileEnv ] = identityReader {
432+ reader : f ,
433+ allowMultipleKeysPerLine : false ,
434+ }
424435 }
425436 } else {
426437 unusedLocations = append (unusedLocations , SopsAgeKeyFileEnv )
@@ -431,7 +442,10 @@ func (key *MasterKey) loadIdentities() (ParsedIdentities, []string, errSet) {
431442 if err != nil {
432443 errs = append (errs , err )
433444 } else {
434- readers [SopsAgeKeyCmdEnv ] = bytes .NewReader (out )
445+ readers [SopsAgeKeyCmdEnv ] = identityReader {
446+ reader : bytes .NewReader (out ),
447+ allowMultipleKeysPerLine : false ,
448+ }
435449 }
436450 } else {
437451 unusedLocations = append (unusedLocations , SopsAgeKeyCmdEnv )
@@ -449,12 +463,15 @@ func (key *MasterKey) loadIdentities() (ParsedIdentities, []string, errSet) {
449463 unusedLocations = append (unusedLocations , ageKeyFilePath )
450464 } else if err == nil {
451465 defer f .Close ()
452- readers [ageKeyFilePath ] = f
466+ readers [ageKeyFilePath ] = identityReader {
467+ reader : f ,
468+ allowMultipleKeysPerLine : false ,
469+ }
453470 }
454471 }
455472
456473 for location , r := range readers {
457- ids , err := unwrapIdentities (location , r )
474+ ids , err := unwrapIdentities (location , r . reader , r . allowMultipleKeysPerLine )
458475 if err != nil {
459476 errs = append (errs , err )
460477 } else {
@@ -505,7 +522,9 @@ func parseRecipient(recipient string) (age.Recipient, error) {
505522// parseIdentities attempts to parse one or more age identities from the provided reader.
506523// One identity per line.
507524// Empty lines and lines starting with "#" are ignored.
508- func parseIdentities (r io.Reader ) (ParsedIdentities , error ) {
525+ // If allowMultipleKeysPerLine is true, every non-empty lines is split by words,
526+ // and every word is parsed as an identity.
527+ func parseIdentities (r io.Reader , allowMultipleKeysPerLine bool ) (ParsedIdentities , error ) {
509528 var identities ParsedIdentities
510529
511530 scanner := bufio .NewScanner (r )
@@ -517,12 +536,24 @@ func parseIdentities(r io.Reader) (ParsedIdentities, error) {
517536 continue
518537 }
519538
520- parsed , err := parseIdentity (line )
521- if err != nil {
522- return nil , err
539+ if allowMultipleKeysPerLine {
540+ lineScanner := bufio .NewScanner (strings .NewReader (line ))
541+ lineScanner .Split (bufio .ScanWords )
542+ for lineScanner .Scan () {
543+ word := lineScanner .Text ()
544+ parsed , err := parseIdentity (word )
545+ if err != nil {
546+ return nil , err
547+ }
548+ identities = append (identities , parsed )
549+ }
550+ } else {
551+ parsed , err := parseIdentity (line )
552+ if err != nil {
553+ return nil , err
554+ }
555+ identities = append (identities , parsed )
523556 }
524-
525- identities = append (identities , parsed )
526557 }
527558
528559 return identities , nil
0 commit comments