Skip to content
This repository was archived by the owner on Feb 16, 2023. It is now read-only.

Commit 17f760e

Browse files
authored
Merge pull request #386 from secrethub/feature/config-migration
Create config migration commands for run and inject
2 parents c5920bb + 4831cdd commit 17f760e

8 files changed

Lines changed: 636 additions & 18 deletions

File tree

.circleci/config.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ version: 2.1
22
jobs:
33
lint:
44
docker:
5-
- image: golangci/golangci-lint:v1.23.8-alpine
5+
- image: golangci/golangci-lint:v1.41.1-alpine
66
steps:
77
- checkout
88
- restore_cache:
@@ -67,6 +67,6 @@ workflows:
6767
arch: ["amd64", "386"]
6868
exclude:
6969
- os: darwin
70-
arch: 386
70+
arch: "386"
7171
- test
7272
- verify-goreleaser

go.sum

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022 h1:y8Gs8CzNf
3333
github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4=
3434
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
3535
github.com/alecthomas/kingpin v1.3.8-0.20200323085623-b6657d9477a6/go.mod h1:b6br6/pDFSfMkBgC96TbpOji05q5pa+v5rIlS0Y6XtI=
36-
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
3736
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
38-
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
3937
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
4038
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
4139
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco=
@@ -61,7 +59,6 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
6159
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
6260
github.com/danieljoos/wincred v1.0.2 h1:zf4bhty2iLuwgjgpraD2E9UbvO+fe54XXGJbOwe23fU=
6361
github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U=
64-
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
6562
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6663
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
6764
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -178,7 +175,6 @@ github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vq
178175
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
179176
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
180177
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
181-
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
182178
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
183179
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
184180
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
@@ -204,9 +200,7 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So
204200
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
205201
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
206202
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
207-
github.com/secrethub/demo-app v0.5.1-0.20201221075813-cc159373e2d5 h1:8Uw+Rrui2SnITOhoWfWfJ8Hj2Vq/qPXW0Z3V5WckyXw=
208203
github.com/secrethub/demo-app v0.5.1-0.20201221075813-cc159373e2d5/go.mod h1:XR0VknPwSudqu/qphA4I4f7B7i2CPGydD59G02y8mBM=
209-
github.com/secrethub/demo-app v0.5.1-0.20201221173924-a1c686b2340e h1:cK/03EQgKYKxl/Yg7zPXOEh2nO1bysOGW+1RBznfMJc=
210204
github.com/secrethub/demo-app v0.5.1-0.20201221173924-a1c686b2340e/go.mod h1:WYS7Q0nigGv+iFdRsnWWXZYl3FpSrU5qtz9h7qBxbq0=
211205
github.com/secrethub/demo-app v0.5.1-0.20210105185858-ad55afc2cb87 h1:s7gYqlql2EV2LI7NwrSUomSXMFHs/v/rBUq6qTuFQwY=
212206
github.com/secrethub/demo-app v0.5.1-0.20210105185858-ad55afc2cb87/go.mod h1:3H4px7f30uHbwMLo19ooijzi4JZlZbGxvnL8VlIcAps=
@@ -228,14 +222,11 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
228222
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
229223
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
230224
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
231-
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
232225
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
233226
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
234227
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
235228
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
236-
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
237229
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
238-
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
239230
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
240231
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
241232
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -298,7 +289,6 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
298289
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
299290
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
300291
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
301-
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU=
302292
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
303293
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
304294
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -333,9 +323,7 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h
333323
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
334324
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
335325
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
336-
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
337326
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
338-
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
339327
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
340328
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
341329
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -354,14 +342,12 @@ golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7w
354342
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
355343
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
356344
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
357-
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e h1:hq86ru83GdWTlfQFZGO4nZJTU4Bs2wfHl8oFHRaXsfc=
358345
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
359346
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
360347
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
361348
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
362349
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
363350
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
364-
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
365351
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
366352
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
367353
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
@@ -471,7 +457,6 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
471457
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
472458
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
473459
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
474-
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
475460
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
476461
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
477462
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

internals/secrethub/migrate.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,68 @@ type plan struct {
3636
vaults map[string]*vault
3737
}
3838

39+
type referenceMapping map[string]string
40+
41+
func newReferenceMapping(p *plan) referenceMapping {
42+
index := make(map[string]string)
43+
for _, vault := range p.vaults {
44+
for _, item := range vault.Items {
45+
for _, field := range item.Fields {
46+
opPath := fmt.Sprintf("op://%s/%s/%s", vault.Name, item.Name, field.Name)
47+
index[field.Reference] = opPath
48+
}
49+
}
50+
}
51+
return referenceMapping(index)
52+
}
53+
54+
// addVarPossibilities adds variations to the index for all values in the passed in vars map
55+
func (m referenceMapping) addVarPossibilities(vars map[string][]string) error {
56+
exists := make(map[string]string)
57+
for varname, possibleValues := range vars {
58+
varname = strings.ToUpper(varname)
59+
for _, value := range possibleValues {
60+
if otherVarname := exists[value]; otherVarname != "" && otherVarname != varname {
61+
return fmt.Errorf("you've ran into a limitation of the migration tool. You can't have multiple variables with the same value: '%s' now occurs in both '%s' and '%s'", value, varname, otherVarname)
62+
}
63+
exists[value] = varname
64+
}
65+
}
66+
67+
for varname, possibleValues := range vars {
68+
uppercaseVarname := strings.ToUpper(varname)
69+
70+
for _, value := range possibleValues {
71+
for secrethubRef, opRef := range m {
72+
if strings.Contains(secrethubRef, value) && strings.Contains(opRef, value) {
73+
// Add syntax variations to the index
74+
variations := map[string]string{
75+
"$" + varname: "$" + uppercaseVarname,
76+
"$" + uppercaseVarname: "$" + uppercaseVarname,
77+
"${" + varname + "}": "${" + uppercaseVarname + "}",
78+
"${" + uppercaseVarname + "}": "${" + uppercaseVarname + "}",
79+
}
80+
for secretHubVariation, opVariation := range variations {
81+
m[strings.ReplaceAll(secrethubRef, value, secretHubVariation)] = strings.ReplaceAll(opRef, value, opVariation)
82+
}
83+
}
84+
}
85+
}
86+
}
87+
88+
return nil
89+
}
90+
91+
// stripSecretHubURIScheme removes the secrethub:// prefix from the index keys so it can be
92+
// used for secrethub.env files and config file templates.
93+
func (m referenceMapping) stripSecretHubURIScheme() {
94+
for secrethubRef, opRef := range m {
95+
stripped := strings.TrimPrefix(secrethubRef, secretReferencePrefix)
96+
delete(m, secrethubRef)
97+
m[stripped] = opRef
98+
}
99+
}
100+
39101
type vault struct {
40102
Name string `yaml:"vault-name"`
41103
Items []item

internals/secrethub/migrate_config.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ func NewMigrateConfigCommand(io ui.IO) *MigrateConfigCommand {
1616
}
1717

1818
func (cmd *MigrateConfigCommand) Register(r cli.Registerer) {
19-
clause := r.Command("config", "Helper functions to migrate your configuration to use 1Password Secrets Automation syntax.")
19+
clause := r.Command("config", "Helper functions to migrate your configuration code to make it work with 1Password.\n\nNote: These commands should be considered best effort and the output should be carefully tested and reviewed before using in production.")
2020
NewMigrateConfigK8sCommand(cmd.io).Register(clause)
21+
NewMigrateConfigReferencesCommand(cmd.io).Register(clause)
22+
NewMigrateConfigTemplatesCommand(cmd.io).Register(clause)
23+
NewMigrateConfigEnvfileCommand(cmd.io).Register(clause)
2124
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package secrethub
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"io/ioutil"
7+
"os"
8+
"regexp"
9+
10+
"github.com/secrethub/secrethub-cli/internals/cli"
11+
"github.com/secrethub/secrethub-cli/internals/cli/ui"
12+
)
13+
14+
func (cmd *MigrateConfigEnvfileCommand) Run() error {
15+
plan, err := getPlan(cmd.planFile)
16+
if err != nil {
17+
return err
18+
}
19+
20+
vars := parseVarPossibilities(cmd.vars)
21+
refMapping := newReferenceMapping(plan)
22+
err = refMapping.addVarPossibilities(vars)
23+
if err != nil {
24+
return err
25+
}
26+
refMapping.stripSecretHubURIScheme()
27+
28+
filepath := cmd.inFile.Value
29+
if filepath == "" {
30+
filepath = "secrethub.env"
31+
}
32+
33+
inFileContents, err := ioutil.ReadFile(filepath)
34+
if err != nil {
35+
return ErrReadFile(filepath, err)
36+
}
37+
38+
err = checkForCompositeSecrets(inFileContents)
39+
if err != nil {
40+
return err
41+
}
42+
43+
outFile, err := os.Create(".env")
44+
if err != nil {
45+
return fmt.Errorf("cannot create output .env file: %s", err)
46+
}
47+
defer outFile.Close()
48+
49+
replaceCount, err := migrateTemplateTags(bytes.NewBuffer(inFileContents), outFile, refMapping, "%s")
50+
if err != nil {
51+
return err
52+
}
53+
54+
fmt.Fprintf(cmd.io.Output(), "Created new .env file with %d op:// references\n", len(replaceCount))
55+
56+
return nil
57+
}
58+
59+
var regexpCompositeSecrets = regexp.MustCompile(`{{.+?}}[^\s]+`)
60+
61+
func checkForCompositeSecrets(inFileContents []byte) error {
62+
if match := regexpCompositeSecrets.Find(inFileContents); match != nil {
63+
return fmt.Errorf("composite environment variables are not supported anymore with Dotenv: %s\nMake sure one environment variable corresponds to just a single secret", match)
64+
}
65+
return nil
66+
}
67+
68+
type MigrateConfigEnvfileCommand struct {
69+
io ui.IO
70+
71+
inFile cli.StringValue
72+
planFile string
73+
vars map[string]string
74+
}
75+
76+
func NewMigrateConfigEnvfileCommand(io ui.IO) *MigrateConfigEnvfileCommand {
77+
return &MigrateConfigEnvfileCommand{
78+
io: io,
79+
}
80+
}
81+
82+
func (cmd *MigrateConfigEnvfileCommand) Register(r cli.Registerer) {
83+
clause := r.Command("envfile", "Migrate secrethub.env file by turning SecretHub paths into 1Password op:// references, resulting in a new Dotenv (.env) file.")
84+
clause.Flags().StringVar(&cmd.planFile, "plan-file", defaultPlanPath, "Path to the file used to migrate your secrets.")
85+
clause.Flags().StringToStringVarP(&cmd.vars, "var", "v", nil, "Define the possible values for a template variable, e.g. --var env=dev,staging,prod --var region=us-east-1,eu-west-1")
86+
clause.BindArguments([]cli.Argument{{Value: &cmd.inFile, Name: "in-file", Required: false, Placeholder: "<path to secrethub.env>", Description: "The path to the secrethub.env file you'd like to migrate."}})
87+
88+
clause.BindAction(cmd.Run)
89+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package secrethub
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"regexp"
7+
"strings"
8+
9+
"github.com/secrethub/secrethub-cli/internals/cli"
10+
"github.com/secrethub/secrethub-cli/internals/cli/ui"
11+
)
12+
13+
var regexpSecretsRef = regexp.MustCompile(`([^A-Za-z0-9_\.-]|^)(secrethub:\/\/[A-Za-z0-9_\.\-]{2,}\/[A-Za-z0-9_\.\-]{2,}\/[A-Za-z0-9_\.\-\/]{2,})([^A-Za-z0-9_\.-]|$)`)
14+
15+
func (cmd *MigrateConfigReferencesCommand) Run() error {
16+
plan, err := getPlan(cmd.planFile)
17+
if err != nil {
18+
return err
19+
}
20+
21+
refMapping := newReferenceMapping(plan)
22+
for _, filepath := range cmd.inFiles {
23+
replaceCount, err := migrateReferences(filepath, filepath, refMapping)
24+
if err != nil {
25+
return err
26+
}
27+
28+
fmt.Fprintf(cmd.io.Output(), "Updated %s with %d op:// references\n", filepath, len(replaceCount))
29+
}
30+
31+
return nil
32+
}
33+
34+
func migrateReferences(inFile string, outFile string, mapping referenceMapping) ([]string, error) {
35+
raw, err := ioutil.ReadFile(inFile)
36+
if err != nil {
37+
return nil, ErrReadFile(inFile, err)
38+
}
39+
40+
var hits, misses []string
41+
output := regexpSecretsRef.ReplaceAllStringFunc(string(raw), func(match string) string {
42+
submatches := regexpSecretsRef.FindStringSubmatch(match)[1:]
43+
44+
matchIndexRef := 1
45+
secretHubRef := submatches[matchIndexRef]
46+
47+
opRef, ok := mapping[secretHubRef]
48+
if !ok {
49+
misses = append(misses, secretHubRef)
50+
return secretHubRef
51+
}
52+
53+
hits = append(hits, opRef)
54+
55+
submatches[matchIndexRef] = opRef
56+
return strings.Join(submatches, "")
57+
})
58+
59+
if len(misses) != 0 {
60+
return nil, fmt.Errorf("no 1Password equivalent present in your migration plan for the following secrets:\n- %s", strings.Join(misses, "\n- "))
61+
}
62+
63+
err = ioutil.WriteFile(outFile, []byte(output), 0666)
64+
if err != nil {
65+
return nil, err
66+
}
67+
68+
return hits, nil
69+
}
70+
71+
type MigrateConfigReferencesCommand struct {
72+
io ui.IO
73+
74+
inFiles cli.StringListValue
75+
planFile string
76+
}
77+
78+
func NewMigrateConfigReferencesCommand(io ui.IO) *MigrateConfigReferencesCommand {
79+
return &MigrateConfigReferencesCommand{
80+
io: io,
81+
}
82+
}
83+
84+
func (cmd *MigrateConfigReferencesCommand) Register(r cli.Registerer) {
85+
clause := r.Command("references", "Migrate secrethub:// references in configuration code to 1Password op:// references.")
86+
clause.Flags().StringVar(&cmd.planFile, "plan-file", defaultPlanPath, "Path to the file used to migrate your secrets.")
87+
clause.BindArgumentsArr(cli.Argument{Value: &cmd.inFiles, Name: "in-file", Required: true, Placeholder: "<filepath>...", Description: "The paths to one or more files you'd like to migrate."})
88+
89+
clause.BindAction(cmd.Run)
90+
}

0 commit comments

Comments
 (0)