From 247553fcdf96d0fca86742c30bd84c6e51e357db Mon Sep 17 00:00:00 2001 From: kusshi <51787281+kusshi94@users.noreply.github.com> Date: Sat, 28 Oct 2023 00:22:06 +0900 Subject: [PATCH 1/9] Initialize shodan Plugin --- plugins/shodan/api_key.go | 70 ++++++++++++++++++++++++++++++++++ plugins/shodan/api_key_test.go | 55 ++++++++++++++++++++++++++ plugins/shodan/plugin.go | 22 +++++++++++ plugins/shodan/shodan.go | 25 ++++++++++++ 4 files changed, 172 insertions(+) create mode 100644 plugins/shodan/api_key.go create mode 100644 plugins/shodan/api_key_test.go create mode 100644 plugins/shodan/plugin.go create mode 100644 plugins/shodan/shodan.go diff --git a/plugins/shodan/api_key.go b/plugins/shodan/api_key.go new file mode 100644 index 000000000..048f85f2b --- /dev/null +++ b/plugins/shodan/api_key.go @@ -0,0 +1,70 @@ +package shodan + +import ( + "context" + + "github.com/1Password/shell-plugins/sdk" + "github.com/1Password/shell-plugins/sdk/importer" + "github.com/1Password/shell-plugins/sdk/provision" + "github.com/1Password/shell-plugins/sdk/schema" + "github.com/1Password/shell-plugins/sdk/schema/credname" + "github.com/1Password/shell-plugins/sdk/schema/fieldname" +) + +func APIKey() schema.CredentialType { + return schema.CredentialType{ + Name: credname.APIKey, + DocsURL: sdk.URL("https://shodan.com/docs/api_key"), // TODO: Replace with actual URL + ManagementURL: sdk.URL("https://console.shodan.com/user/security/tokens"), // TODO: Replace with actual URL + Fields: []schema.CredentialField{ + { + Name: fieldname.APIKey, + MarkdownDescription: "API Key used to authenticate to Shodan.", + Secret: true, + Composition: &schema.ValueComposition{ + Length: 32, + Charset: schema.Charset{ + Uppercase: true, + Lowercase: true, + Digits: true, + }, + }, + }, + }, + DefaultProvisioner: provision.EnvVars(defaultEnvVarMapping), + Importer: importer.TryAll( + importer.TryEnvVarPair(defaultEnvVarMapping), + TryShodanConfigFile(), + )} +} + +var defaultEnvVarMapping = map[string]sdk.FieldName{ + "SHODAN_API_KEY": fieldname.APIKey, // TODO: Check if this is correct +} + +// TODO: Check if the platform stores the API Key in a local config file, and if so, +// implement the function below to add support for importing it. +func TryShodanConfigFile() sdk.Importer { + return importer.TryFile("~/path/to/config/file.yml", func(ctx context.Context, contents importer.FileContents, in sdk.ImportInput, out *sdk.ImportAttempt) { + // var config Config + // if err := contents.ToYAML(&config); err != nil { + // out.AddError(err) + // return + // } + + // if config.APIKey == "" { + // return + // } + + // out.AddCandidate(sdk.ImportCandidate{ + // Fields: map[sdk.FieldName]string{ + // fieldname.APIKey: config.APIKey, + // }, + // }) + }) +} + +// TODO: Implement the config file schema +// type Config struct { +// APIKey string +// } diff --git a/plugins/shodan/api_key_test.go b/plugins/shodan/api_key_test.go new file mode 100644 index 000000000..5b5891e42 --- /dev/null +++ b/plugins/shodan/api_key_test.go @@ -0,0 +1,55 @@ +package shodan + +import ( + "testing" + + "github.com/1Password/shell-plugins/sdk" + "github.com/1Password/shell-plugins/sdk/plugintest" + "github.com/1Password/shell-plugins/sdk/schema/fieldname" +) + +func TestAPIKeyProvisioner(t *testing.T) { + plugintest.TestProvisioner(t, APIKey().DefaultProvisioner, map[string]plugintest.ProvisionCase{ + "default": { + ItemFields: map[sdk.FieldName]string{ // TODO: Check if this is correct + fieldname.APIKey: "ddXfzwQOIjTaaxGMzcxXYR6Q0EXAMPLE", + }, + ExpectedOutput: sdk.ProvisionOutput{ + Environment: map[string]string{ + "SHODAN_API_KEY": "ddXfzwQOIjTaaxGMzcxXYR6Q0EXAMPLE", + }, + }, + }, + }) +} + +func TestAPIKeyImporter(t *testing.T) { + plugintest.TestImporter(t, APIKey().Importer, map[string]plugintest.ImportCase{ + "environment": { + Environment: map[string]string{ // TODO: Check if this is correct + "SHODAN_API_KEY": "ddXfzwQOIjTaaxGMzcxXYR6Q0EXAMPLE", + }, + ExpectedCandidates: []sdk.ImportCandidate{ + { + Fields: map[sdk.FieldName]string{ + fieldname.APIKey: "ddXfzwQOIjTaaxGMzcxXYR6Q0EXAMPLE", + }, + }, + }, + }, + // TODO: If you implemented a config file importer, add a test file example in shodan/test-fixtures + // and fill the necessary details in the test template below. + "config file": { + Files: map[string]string{ + // "~/path/to/config.yml": plugintest.LoadFixture(t, "config.yml"), + }, + ExpectedCandidates: []sdk.ImportCandidate{ + // { + // Fields: map[sdk.FieldName]string{ + // fieldname.Token: "ddXfzwQOIjTaaxGMzcxXYR6Q0EXAMPLE", + // }, + // }, + }, + }, + }) +} diff --git a/plugins/shodan/plugin.go b/plugins/shodan/plugin.go new file mode 100644 index 000000000..c5f819fc4 --- /dev/null +++ b/plugins/shodan/plugin.go @@ -0,0 +1,22 @@ +package shodan + +import ( + "github.com/1Password/shell-plugins/sdk" + "github.com/1Password/shell-plugins/sdk/schema" +) + +func New() schema.Plugin { + return schema.Plugin{ + Name: "shodan", + Platform: schema.PlatformInfo{ + Name: "Shodan", + Homepage: sdk.URL("https://shodan.com"), // TODO: Check if this is correct + }, + Credentials: []schema.CredentialType{ + APIKey(), + }, + Executables: []schema.Executable{ + ShodanCLI(), + }, + } +} diff --git a/plugins/shodan/shodan.go b/plugins/shodan/shodan.go new file mode 100644 index 000000000..8b618a9ab --- /dev/null +++ b/plugins/shodan/shodan.go @@ -0,0 +1,25 @@ +package shodan + +import ( + "github.com/1Password/shell-plugins/sdk" + "github.com/1Password/shell-plugins/sdk/needsauth" + "github.com/1Password/shell-plugins/sdk/schema" + "github.com/1Password/shell-plugins/sdk/schema/credname" +) + +func ShodanCLI() schema.Executable { + return schema.Executable{ + Name: "Shodan CLI", // TODO: Check if this is correct + Runs: []string{"shodan"}, + DocsURL: sdk.URL("https://shodan.com/docs/cli"), // TODO: Replace with actual URL + NeedsAuth: needsauth.IfAll( + needsauth.NotForHelpOrVersion(), + needsauth.NotWithoutArgs(), + ), + Uses: []schema.CredentialUsage{ + { + Name: credname.APIKey, + }, + }, + } +} From e2e540b2a53a186093549737f23ddfab8bddc0b4 Mon Sep 17 00:00:00 2001 From: kusshi <51787281+kusshi94@users.noreply.github.com> Date: Sat, 28 Oct 2023 00:22:59 +0900 Subject: [PATCH 2/9] Update the shodan plugin definition --- plugins/shodan/plugin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/shodan/plugin.go b/plugins/shodan/plugin.go index c5f819fc4..530f3f5e5 100644 --- a/plugins/shodan/plugin.go +++ b/plugins/shodan/plugin.go @@ -10,7 +10,7 @@ func New() schema.Plugin { Name: "shodan", Platform: schema.PlatformInfo{ Name: "Shodan", - Homepage: sdk.URL("https://shodan.com"), // TODO: Check if this is correct + Homepage: sdk.URL("https://www.shodan.io"), }, Credentials: []schema.CredentialType{ APIKey(), From 7e6ab0fbc9540ed7c5a9dd87128ff62cfa404ad3 Mon Sep 17 00:00:00 2001 From: kusshi <51787281+kusshi94@users.noreply.github.com> Date: Sat, 28 Oct 2023 00:29:12 +0900 Subject: [PATCH 3/9] Update the shodan plugin API Key definition --- plugins/shodan/api_key.go | 45 ++++++++++++++------------------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/plugins/shodan/api_key.go b/plugins/shodan/api_key.go index 048f85f2b..fa2bc024e 100644 --- a/plugins/shodan/api_key.go +++ b/plugins/shodan/api_key.go @@ -14,8 +14,8 @@ import ( func APIKey() schema.CredentialType { return schema.CredentialType{ Name: credname.APIKey, - DocsURL: sdk.URL("https://shodan.com/docs/api_key"), // TODO: Replace with actual URL - ManagementURL: sdk.URL("https://console.shodan.com/user/security/tokens"), // TODO: Replace with actual URL + DocsURL: sdk.URL("https://developer.shodan.io/api/requirements"), + ManagementURL: sdk.URL("https://account.shodan.io"), Fields: []schema.CredentialField{ { Name: fieldname.APIKey, @@ -31,40 +31,27 @@ func APIKey() schema.CredentialType { }, }, }, - DefaultProvisioner: provision.EnvVars(defaultEnvVarMapping), + DefaultProvisioner: provision.TempFile( + provision.FieldAsFile(fieldname.APIKey), + provision.AtFixedPath("~/.config/shodan/api_key"), + ), Importer: importer.TryAll( - importer.TryEnvVarPair(defaultEnvVarMapping), TryShodanConfigFile(), )} } -var defaultEnvVarMapping = map[string]sdk.FieldName{ - "SHODAN_API_KEY": fieldname.APIKey, // TODO: Check if this is correct -} - -// TODO: Check if the platform stores the API Key in a local config file, and if so, -// implement the function below to add support for importing it. func TryShodanConfigFile() sdk.Importer { - return importer.TryFile("~/path/to/config/file.yml", func(ctx context.Context, contents importer.FileContents, in sdk.ImportInput, out *sdk.ImportAttempt) { - // var config Config - // if err := contents.ToYAML(&config); err != nil { - // out.AddError(err) - // return - // } + return importer.TryFile("~/.config/shodan/api_key", func(ctx context.Context, contents importer.FileContents, in sdk.ImportInput, out *sdk.ImportAttempt) { + apiKey := contents.ToString() - // if config.APIKey == "" { - // return - // } + if apiKey == "" { + return + } - // out.AddCandidate(sdk.ImportCandidate{ - // Fields: map[sdk.FieldName]string{ - // fieldname.APIKey: config.APIKey, - // }, - // }) + out.AddCandidate(sdk.ImportCandidate{ + Fields: map[sdk.FieldName]string{ + fieldname.APIKey: apiKey, + }, + }) }) } - -// TODO: Implement the config file schema -// type Config struct { -// APIKey string -// } From 3258d1deea4adc10941a565549e149a2361c274f Mon Sep 17 00:00:00 2001 From: kusshi <51787281+kusshi94@users.noreply.github.com> Date: Sat, 28 Oct 2023 00:31:12 +0900 Subject: [PATCH 4/9] Update the shodan plugin executable definition --- plugins/shodan/shodan.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/shodan/shodan.go b/plugins/shodan/shodan.go index 8b618a9ab..caba3b60d 100644 --- a/plugins/shodan/shodan.go +++ b/plugins/shodan/shodan.go @@ -9,9 +9,9 @@ import ( func ShodanCLI() schema.Executable { return schema.Executable{ - Name: "Shodan CLI", // TODO: Check if this is correct + Name: "Shodan Command-Line Interface", Runs: []string{"shodan"}, - DocsURL: sdk.URL("https://shodan.com/docs/cli"), // TODO: Replace with actual URL + DocsURL: sdk.URL("https://cli.shodan.io"), NeedsAuth: needsauth.IfAll( needsauth.NotForHelpOrVersion(), needsauth.NotWithoutArgs(), From d27a4a8befed49f05acf912a804de9277737ce9d Mon Sep 17 00:00:00 2001 From: kusshi <51787281+kusshi94@users.noreply.github.com> Date: Wed, 8 Nov 2023 20:09:04 +0900 Subject: [PATCH 5/9] update API Key Test --- plugins/shodan/api_key_test.go | 26 ++++++-------------------- plugins/shodan/test-fixtures/api_key | 1 + 2 files changed, 7 insertions(+), 20 deletions(-) create mode 100644 plugins/shodan/test-fixtures/api_key diff --git a/plugins/shodan/api_key_test.go b/plugins/shodan/api_key_test.go index 5b5891e42..e9a42586d 100644 --- a/plugins/shodan/api_key_test.go +++ b/plugins/shodan/api_key_test.go @@ -11,12 +11,12 @@ import ( func TestAPIKeyProvisioner(t *testing.T) { plugintest.TestProvisioner(t, APIKey().DefaultProvisioner, map[string]plugintest.ProvisionCase{ "default": { - ItemFields: map[sdk.FieldName]string{ // TODO: Check if this is correct + ItemFields: map[sdk.FieldName]string{ fieldname.APIKey: "ddXfzwQOIjTaaxGMzcxXYR6Q0EXAMPLE", }, ExpectedOutput: sdk.ProvisionOutput{ - Environment: map[string]string{ - "SHODAN_API_KEY": "ddXfzwQOIjTaaxGMzcxXYR6Q0EXAMPLE", + Files: map[string]sdk.OutputFile{ + "~/.config/shodan/api_key": {Contents: []byte("ddXfzwQOIjTaaxGMzcxXYR6Q0EXAMPLE")}, }, }, }, @@ -25,9 +25,9 @@ func TestAPIKeyProvisioner(t *testing.T) { func TestAPIKeyImporter(t *testing.T) { plugintest.TestImporter(t, APIKey().Importer, map[string]plugintest.ImportCase{ - "environment": { - Environment: map[string]string{ // TODO: Check if this is correct - "SHODAN_API_KEY": "ddXfzwQOIjTaaxGMzcxXYR6Q0EXAMPLE", + "config file": { + Files: map[string]string{ + "~/.config/shodan/api_key": plugintest.LoadFixture(t, "api_key"), }, ExpectedCandidates: []sdk.ImportCandidate{ { @@ -37,19 +37,5 @@ func TestAPIKeyImporter(t *testing.T) { }, }, }, - // TODO: If you implemented a config file importer, add a test file example in shodan/test-fixtures - // and fill the necessary details in the test template below. - "config file": { - Files: map[string]string{ - // "~/path/to/config.yml": plugintest.LoadFixture(t, "config.yml"), - }, - ExpectedCandidates: []sdk.ImportCandidate{ - // { - // Fields: map[sdk.FieldName]string{ - // fieldname.Token: "ddXfzwQOIjTaaxGMzcxXYR6Q0EXAMPLE", - // }, - // }, - }, - }, }) } diff --git a/plugins/shodan/test-fixtures/api_key b/plugins/shodan/test-fixtures/api_key new file mode 100644 index 000000000..02c174264 --- /dev/null +++ b/plugins/shodan/test-fixtures/api_key @@ -0,0 +1 @@ +ddXfzwQOIjTaaxGMzcxXYR6Q0EXAMPLE \ No newline at end of file From 85660be523a4aeea6d56a5a2ad2d796b92dfae60 Mon Sep 17 00:00:00 2001 From: kusshi <51787281+kusshi94@users.noreply.github.com> Date: Wed, 8 Nov 2023 21:38:28 +0900 Subject: [PATCH 6/9] go fmt --- plugins/shodan/api_key_test.go | 4 ++-- plugins/shodan/shodan.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/shodan/api_key_test.go b/plugins/shodan/api_key_test.go index e9a42586d..97ec67491 100644 --- a/plugins/shodan/api_key_test.go +++ b/plugins/shodan/api_key_test.go @@ -2,12 +2,12 @@ package shodan import ( "testing" - + "github.com/1Password/shell-plugins/sdk" "github.com/1Password/shell-plugins/sdk/plugintest" "github.com/1Password/shell-plugins/sdk/schema/fieldname" ) - + func TestAPIKeyProvisioner(t *testing.T) { plugintest.TestProvisioner(t, APIKey().DefaultProvisioner, map[string]plugintest.ProvisionCase{ "default": { diff --git a/plugins/shodan/shodan.go b/plugins/shodan/shodan.go index caba3b60d..b57f95126 100644 --- a/plugins/shodan/shodan.go +++ b/plugins/shodan/shodan.go @@ -9,9 +9,9 @@ import ( func ShodanCLI() schema.Executable { return schema.Executable{ - Name: "Shodan Command-Line Interface", - Runs: []string{"shodan"}, - DocsURL: sdk.URL("https://cli.shodan.io"), + Name: "Shodan Command-Line Interface", + Runs: []string{"shodan"}, + DocsURL: sdk.URL("https://cli.shodan.io"), NeedsAuth: needsauth.IfAll( needsauth.NotForHelpOrVersion(), needsauth.NotWithoutArgs(), From 5acbc428128db268cdd7f2acb8adc85af2c9c23a Mon Sep 17 00:00:00 2001 From: kusshi <51787281+kusshi94@users.noreply.github.com> Date: Sat, 23 Mar 2024 16:02:17 +0900 Subject: [PATCH 7/9] change to use ~/.config/shodan/ --- plugins/shodan/api_key.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/shodan/api_key.go b/plugins/shodan/api_key.go index fa2bc024e..268ee5711 100644 --- a/plugins/shodan/api_key.go +++ b/plugins/shodan/api_key.go @@ -33,15 +33,16 @@ func APIKey() schema.CredentialType { }, DefaultProvisioner: provision.TempFile( provision.FieldAsFile(fieldname.APIKey), - provision.AtFixedPath("~/.config/shodan/api_key"), + provision.AtFixedPath("~/.shodan/api_key"), ), Importer: importer.TryAll( - TryShodanConfigFile(), + TryShodanConfigFile("~/.shodan/api_key"), + TryShodanConfigFile("~/.config/shodan/api_key"), )} } -func TryShodanConfigFile() sdk.Importer { - return importer.TryFile("~/.config/shodan/api_key", func(ctx context.Context, contents importer.FileContents, in sdk.ImportInput, out *sdk.ImportAttempt) { +func TryShodanConfigFile(configPath string) sdk.Importer { + return importer.TryFile(configPath, func(ctx context.Context, contents importer.FileContents, in sdk.ImportInput, out *sdk.ImportAttempt) { apiKey := contents.ToString() if apiKey == "" { From c6e781ba9f6e2a38de0da0d9c12372ed3d35a176 Mon Sep 17 00:00:00 2001 From: kusshi <51787281+kusshi94@users.noreply.github.com> Date: Sat, 23 Mar 2024 16:03:16 +0900 Subject: [PATCH 8/9] change DocsURL --- plugins/shodan/api_key.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/shodan/api_key.go b/plugins/shodan/api_key.go index 268ee5711..55008ddb0 100644 --- a/plugins/shodan/api_key.go +++ b/plugins/shodan/api_key.go @@ -14,7 +14,7 @@ import ( func APIKey() schema.CredentialType { return schema.CredentialType{ Name: credname.APIKey, - DocsURL: sdk.URL("https://developer.shodan.io/api/requirements"), + DocsURL: sdk.URL("https://cli.shodan.io"), ManagementURL: sdk.URL("https://account.shodan.io"), Fields: []schema.CredentialField{ { From 6abf2e24dc76e93cb528d3e7c4ed344fae39c992 Mon Sep 17 00:00:00 2001 From: kusshi <51787281+kusshi94@users.noreply.github.com> Date: Sat, 23 Mar 2024 16:04:44 +0900 Subject: [PATCH 9/9] change to exclude shodan init command from needsauth targets --- plugins/shodan/shodan.go | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/shodan/shodan.go b/plugins/shodan/shodan.go index b57f95126..680238eab 100644 --- a/plugins/shodan/shodan.go +++ b/plugins/shodan/shodan.go @@ -15,6 +15,7 @@ func ShodanCLI() schema.Executable { NeedsAuth: needsauth.IfAll( needsauth.NotForHelpOrVersion(), needsauth.NotWithoutArgs(), + needsauth.NotForExactArgs("init"), ), Uses: []schema.CredentialUsage{ {