Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 25 additions & 14 deletions plugins/akamai/api_client_credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package akamai

import (
"context"
"fmt"
"strings"

"github.com/1Password/shell-plugins/sdk"
"github.com/1Password/shell-plugins/sdk/importer"
Expand Down Expand Up @@ -85,25 +87,34 @@ func APIClientCredentials() schema.CredentialType {
}

func configFile(in sdk.ProvisionInput) ([]byte, error) {
contents := "[default]\n"

if clientsecret, ok := in.ItemFields[fieldname.ClientSecret]; ok {
contents += "client_secret = " + clientsecret + "\n"
}

if host, ok := in.ItemFields[fieldname.Host]; ok {
contents += "host = " + host + "\n"
fields := []struct {
name sdk.FieldName
key string
}{
{fieldname.ClientSecret, "client_secret"},
{fieldname.Host, "host"},
{fieldname.AccessToken, "access_token"},
{fieldname.ClientToken, "client_token"},
}

if accesstoken, ok := in.ItemFields[fieldname.AccessToken]; ok {
contents += "access_token = " + accesstoken + "\n"
}
var contents strings.Builder
contents.WriteString("[default]\n")

if clienttoken, ok := in.ItemFields[fieldname.ClientToken]; ok {
contents += "client_token = " + clienttoken + "\n"
for _, field := range fields {
value, ok := in.ItemFields[field.name]
if !ok {
continue
}
// INI parsers ignore surrounding whitespace, so trimming it only drops
// harmless leading or trailing line breaks, such as from a paste.
value = strings.TrimSpace(value)
if strings.ContainsAny(value, "\r\n") {
return nil, fmt.Errorf("line breaks are not allowed in the Akamai %q field", field.name)
}
contents.WriteString(field.key + " = " + value + "\n")
}

return []byte(contents), nil
return []byte(contents.String()), nil
}

// Load credentials from the ~/.edgerc file.
Expand Down
63 changes: 63 additions & 0 deletions plugins/akamai/api_client_credentials_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package akamai

import (
"fmt"
"testing"

"github.com/1Password/shell-plugins/sdk"
"github.com/1Password/shell-plugins/sdk/plugintest"
"github.com/1Password/shell-plugins/sdk/schema/fieldname"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestAPIClientCredentialsProvisioner(t *testing.T) {
Expand All @@ -30,6 +33,66 @@ func TestAPIClientCredentialsProvisioner(t *testing.T) {
})
}

func TestConfigFileRejectsLineBreaks(t *testing.T) {
validFields := map[sdk.FieldName]string{
fieldname.ClientSecret: "abcdE23FNkBxy456z25qx9Yp5CPUxlEfQeTDkfh4QA=I",
fieldname.Host: "akab-lmn789n2k53w7qrs-nfkxaa4lfk3kd6ym.luna.akamaiapis.net",
fieldname.AccessToken: "akab-zyx987xa6osbli4k-e7jf5ikib5jknes3",
fieldname.ClientToken: "akab-nomoflavjuc4422e-fa2xznerxrm3teg7",
}

for field, validValue := range validFields {
for name, lineBreak := range map[string]string{
"line feed": "\n",
"carriage return": "\r",
} {
t.Run(fmt.Sprintf("%s/%s", field, name), func(t *testing.T) {
fields := make(map[sdk.FieldName]string, len(validFields))
for key, value := range validFields {
fields[key] = value
}
fields[field] = validValue + lineBreak + "debug = true"

contents, err := configFile(sdk.ProvisionInput{ItemFields: fields})

assert.Nil(t, contents)
require.EqualError(t, err, fmt.Sprintf("line breaks are not allowed in the Akamai %q field", field))
assert.NotContains(t, err.Error(), "debug = true")
})
}
}
}

func TestConfigFileTrimsSurroundingWhitespace(t *testing.T) {
validFields := map[sdk.FieldName]string{
fieldname.ClientSecret: "abcdE23FNkBxy456z25qx9Yp5CPUxlEfQeTDkfh4QA=I",
fieldname.Host: "akab-lmn789n2k53w7qrs-nfkxaa4lfk3kd6ym.luna.akamaiapis.net",
fieldname.AccessToken: "akab-zyx987xa6osbli4k-e7jf5ikib5jknes3",
fieldname.ClientToken: "akab-nomoflavjuc4422e-fa2xznerxrm3teg7",
}
expected, err := configFile(sdk.ProvisionInput{ItemFields: validFields})
require.NoError(t, err)

for name, pad := range map[string]func(string) string{
"trailing line feed": func(v string) string { return v + "\n" },
"trailing CRLF": func(v string) string { return v + "\r\n" },
"leading line feed": func(v string) string { return "\n" + v },
"surrounding spaces, tabs": func(v string) string { return " \t" + v + "\t " },
} {
t.Run(name, func(t *testing.T) {
fields := make(map[sdk.FieldName]string, len(validFields))
for key, value := range validFields {
fields[key] = pad(value)
}

contents, err := configFile(sdk.ProvisionInput{ItemFields: fields})

require.NoError(t, err)
assert.Equal(t, string(expected), string(contents))
})
}
}

func TestAPIClientCredentialsImporter(t *testing.T) {
plugintest.TestImporter(t, APIClientCredentials().Importer, map[string]plugintest.ImportCase{
"config file with single credential": {
Expand Down
30 changes: 23 additions & 7 deletions plugins/pipedream/api_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package pipedream

import (
"context"
"fmt"
"strings"

"github.com/1Password/shell-plugins/sdk"
"github.com/1Password/shell-plugins/sdk/importer"
Expand Down Expand Up @@ -88,15 +90,29 @@ type Config struct {
}

func pipedreamConfig(in sdk.ProvisionInput) ([]byte, error) {
contents := ""

if apikey, ok := in.ItemFields[fieldname.APIKey]; ok {
contents += "api_key = " + apikey + "\n"
fields := []struct {
name sdk.FieldName
key string
}{
{fieldname.APIKey, "api_key"},
{fieldname.OrgID, "org_id"},
}

if orgid, ok := in.ItemFields[fieldname.OrgID]; ok {
contents += "org_id = " + orgid + "\n"
var contents strings.Builder

for _, field := range fields {
value, ok := in.ItemFields[field.name]
if !ok {
continue
}
// INI parsers ignore surrounding whitespace, so trimming it only drops
// harmless leading or trailing line breaks, such as from a paste.
value = strings.TrimSpace(value)
if strings.ContainsAny(value, "\r\n") {
return nil, fmt.Errorf("line breaks are not allowed in the Pipedream %q field", field.name)
}
contents.WriteString(field.key + " = " + value + "\n")
}

return []byte(contents), nil
return []byte(contents.String()), nil
}
59 changes: 59 additions & 0 deletions plugins/pipedream/api_key_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package pipedream

import (
"fmt"
"testing"

"github.com/1Password/shell-plugins/sdk"
"github.com/1Password/shell-plugins/sdk/plugintest"
"github.com/1Password/shell-plugins/sdk/schema/fieldname"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestAPIKeyProvisioner(t *testing.T) {
Expand All @@ -26,6 +29,62 @@ func TestAPIKeyProvisioner(t *testing.T) {
})
}

func TestPipedreamConfigRejectsLineBreaks(t *testing.T) {
validFields := map[sdk.FieldName]string{
fieldname.APIKey: "ugvfxesz62ycsl42z49c0t1hjexample",
fieldname.OrgID: "YbEXAMPLE",
}

for field, validValue := range validFields {
for name, lineBreak := range map[string]string{
"line feed": "\n",
"carriage return": "\r",
} {
t.Run(fmt.Sprintf("%s/%s", field, name), func(t *testing.T) {
fields := make(map[sdk.FieldName]string, len(validFields))
for key, value := range validFields {
fields[key] = value
}
fields[field] = validValue + lineBreak + "[other]"

contents, err := pipedreamConfig(sdk.ProvisionInput{ItemFields: fields})

assert.Nil(t, contents)
require.EqualError(t, err, fmt.Sprintf("line breaks are not allowed in the Pipedream %q field", field))
assert.NotContains(t, err.Error(), "[other]")
})
}
}
}

func TestPipedreamConfigTrimsSurroundingWhitespace(t *testing.T) {
validFields := map[sdk.FieldName]string{
fieldname.APIKey: "ugvfxesz62ycsl42z49c0t1hjexample",
fieldname.OrgID: "YbEXAMPLE",
}
expected, err := pipedreamConfig(sdk.ProvisionInput{ItemFields: validFields})
require.NoError(t, err)

for name, pad := range map[string]func(string) string{
"trailing line feed": func(v string) string { return v + "\n" },
"trailing CRLF": func(v string) string { return v + "\r\n" },
"leading line feed": func(v string) string { return "\n" + v },
"surrounding spaces, tabs": func(v string) string { return " \t" + v + "\t " },
} {
t.Run(name, func(t *testing.T) {
fields := make(map[sdk.FieldName]string, len(validFields))
for key, value := range validFields {
fields[key] = pad(value)
}

contents, err := pipedreamConfig(sdk.ProvisionInput{ItemFields: fields})

require.NoError(t, err)
assert.Equal(t, string(expected), string(contents))
})
}
}

func TestAPIKeyImporter(t *testing.T) {
plugintest.TestImporter(t, APIKey().Importer, map[string]plugintest.ImportCase{
"config file": {
Expand Down
Loading