Skip to content

Commit 3361434

Browse files
committed
feat(sops): add SOPS plugin for age key provisioning
Add shell plugin for SOPS (Secrets OPerationS) that provisions SOPS_AGE_KEY environment variable from 1Password vault items. Supports: - sops CLI for encrypt/decrypt operations - helm CLI with 'secrets' subcommand (helm-secrets plugin) Credential type: - secret_key: Age secret key (AGE-SECRET-KEY-...)
1 parent 49810df commit 3361434

5 files changed

Lines changed: 156 additions & 0 deletions

File tree

plugins/sops/age_secret_key.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package sops
2+
3+
import (
4+
"github.com/1Password/shell-plugins/sdk"
5+
"github.com/1Password/shell-plugins/sdk/importer"
6+
"github.com/1Password/shell-plugins/sdk/provision"
7+
"github.com/1Password/shell-plugins/sdk/schema"
8+
"github.com/1Password/shell-plugins/sdk/schema/credname"
9+
"github.com/1Password/shell-plugins/sdk/schema/fieldname"
10+
)
11+
12+
func AgeSecretKey() schema.CredentialType {
13+
return schema.CredentialType{
14+
Name: credname.SecretKey,
15+
DocsURL: sdk.URL("https://github.com/getsops/sops#encrypting-using-age"),
16+
ManagementURL: nil,
17+
Fields: []schema.CredentialField{
18+
{
19+
Name: fieldname.PrivateKey,
20+
MarkdownDescription: "Age secret key used by SOPS for encryption and decryption.",
21+
Secret: true,
22+
Composition: &schema.ValueComposition{
23+
Prefix: "AGE-SECRET-KEY-",
24+
Charset: schema.Charset{
25+
Uppercase: true,
26+
Digits: true,
27+
},
28+
},
29+
},
30+
},
31+
DefaultProvisioner: provision.EnvVars(defaultEnvVarMapping),
32+
Importer: importer.TryAll(
33+
importer.TryEnvVarPair(defaultEnvVarMapping),
34+
),
35+
}
36+
}
37+
38+
var defaultEnvVarMapping = map[string]sdk.FieldName{
39+
"SOPS_AGE_KEY": fieldname.PrivateKey,
40+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package sops
2+
3+
import (
4+
"testing"
5+
6+
"github.com/1Password/shell-plugins/sdk"
7+
"github.com/1Password/shell-plugins/sdk/plugintest"
8+
"github.com/1Password/shell-plugins/sdk/schema/fieldname"
9+
)
10+
11+
func TestAgeSecretKeyImporter(t *testing.T) {
12+
plugintest.TestImporter(t, AgeSecretKey().Importer, map[string]plugintest.ImportCase{
13+
"environment": {
14+
Environment: map[string]string{
15+
"SOPS_AGE_KEY": "AGE-SECRET-KEY-1QFWENTHXAAPACFPMXHQCREP64GJE5YTHXLX0RPFSXRSPDJGCR0SSWYNX3D",
16+
},
17+
ExpectedCandidates: []sdk.ImportCandidate{
18+
{
19+
Fields: map[sdk.FieldName]string{
20+
fieldname.PrivateKey: "AGE-SECRET-KEY-1QFWENTHXAAPACFPMXHQCREP64GJE5YTHXLX0RPFSXRSPDJGCR0SSWYNX3D",
21+
},
22+
},
23+
},
24+
},
25+
})
26+
}
27+
28+
func TestAgeSecretKeyProvisioner(t *testing.T) {
29+
plugintest.TestProvisioner(t, AgeSecretKey().DefaultProvisioner, map[string]plugintest.ProvisionCase{
30+
"default": {
31+
ItemFields: map[sdk.FieldName]string{
32+
fieldname.PrivateKey: "AGE-SECRET-KEY-1QFWENTHXAAPACFPMXHQCREP64GJE5YTHXLX0RPFSXRSPDJGCR0SSWYNX3D",
33+
},
34+
ExpectedOutput: sdk.ProvisionOutput{
35+
Environment: map[string]string{
36+
"SOPS_AGE_KEY": "AGE-SECRET-KEY-1QFWENTHXAAPACFPMXHQCREP64GJE5YTHXLX0RPFSXRSPDJGCR0SSWYNX3D",
37+
},
38+
},
39+
},
40+
})
41+
}

plugins/sops/helm.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package sops
2+
3+
import (
4+
"github.com/1Password/shell-plugins/sdk"
5+
"github.com/1Password/shell-plugins/sdk/needsauth"
6+
"github.com/1Password/shell-plugins/sdk/schema"
7+
"github.com/1Password/shell-plugins/sdk/schema/credname"
8+
)
9+
10+
func HelmCLI() schema.Executable {
11+
return schema.Executable{
12+
Name: "Helm with SOPS Secrets",
13+
Runs: []string{"helm"},
14+
DocsURL: sdk.URL("https://github.com/jkroepke/helm-secrets"),
15+
NeedsAuth: needsauth.IfAll(
16+
needsauth.NotForHelpOrVersion(),
17+
needsauth.NotWithoutArgs(),
18+
// Only authenticate when using helm-secrets plugin
19+
needsauth.ForCommand("secrets"),
20+
),
21+
Uses: []schema.CredentialUsage{
22+
{
23+
Name: credname.SecretKey,
24+
},
25+
},
26+
}
27+
}

plugins/sops/plugin.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package sops
2+
3+
import (
4+
"github.com/1Password/shell-plugins/sdk"
5+
"github.com/1Password/shell-plugins/sdk/schema"
6+
)
7+
8+
func New() schema.Plugin {
9+
return schema.Plugin{
10+
Name: "sops",
11+
Platform: schema.PlatformInfo{
12+
Name: "SOPS",
13+
Homepage: sdk.URL("https://github.com/getsops/sops"),
14+
},
15+
Credentials: []schema.CredentialType{
16+
AgeSecretKey(),
17+
},
18+
Executables: []schema.Executable{
19+
SOPSCLI(),
20+
HelmCLI(),
21+
},
22+
}
23+
}

plugins/sops/sops.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package sops
2+
3+
import (
4+
"github.com/1Password/shell-plugins/sdk"
5+
"github.com/1Password/shell-plugins/sdk/needsauth"
6+
"github.com/1Password/shell-plugins/sdk/schema"
7+
"github.com/1Password/shell-plugins/sdk/schema/credname"
8+
)
9+
10+
func SOPSCLI() schema.Executable {
11+
return schema.Executable{
12+
Name: "SOPS CLI",
13+
Runs: []string{"sops"},
14+
DocsURL: sdk.URL("https://github.com/getsops/sops"),
15+
NeedsAuth: needsauth.IfAll(
16+
needsauth.NotForHelpOrVersion(),
17+
needsauth.NotWithoutArgs(),
18+
),
19+
Uses: []schema.CredentialUsage{
20+
{
21+
Name: credname.SecretKey,
22+
},
23+
},
24+
}
25+
}

0 commit comments

Comments
 (0)