Skip to content

Commit

Permalink
add support for custom headers
Browse files Browse the repository at this point in the history
allow to add custom headers to be included in requests to the SFTPGo API.

Co-authored-by: André Nogueira <[email protected]>
Signed-off-by: Nicola Murino <[email protected]>
  • Loading branch information
drakkan and aanogueira committed Apr 19, 2024
1 parent 2eda38b commit 2d149aa
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 9 deletions.
9 changes: 9 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ provider "sftpgo" {
### Optional

- `api_key` (String, Sensitive) SFTPGo API key. May also be provided via SFTPGO_API_KEY environment variable. You must provide an API key or username and password. If both an API key and username and password are provided, the API key will be used.
- `headers` (Attributes List) Headers to add to the HTTP request. (see [below for nested schema](#nestedatt--headers))
- `host` (String) URI for SFTPGo API. May also be provided via SFTPGO_HOST environment variable.
- `password` (String, Sensitive) Password for SFTPGo API. May also be provided via SFTPGO_PASSWORD environment variable.
- `username` (String) Username for SFTPGo API. May also be provided via SFTPGO_USERNAME environment variable.

<a id="nestedatt--headers"></a>
### Nested Schema for `headers`

Required:

- `key` (String) The header name. May also be provided via SFTPGO_HEADERS__0__KEY, SFTPGO_HEADERS__1__KEY, ... SFTPGO_HEADERS__9__KEY environment variables.
- `value` (String) The header value. May also be provided via SFTPGO_HEADERS__0__VALUE, SFTPGO_HEADERS__1__VALUE, ... SFTPGO_HEADERS__9__VALUE environment variables.
26 changes: 26 additions & 0 deletions examples/iap/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
terraform {
required_providers {
sftpgo = {
source = "registry.terraform.io/drakkan/sftpgo"
}
}
}

data "google_service_account_id_token" "sftp_iap_oidc" {
target_service_account = var.sftp_service_account
target_audience = var.sftp_iap_client_id
include_email = true
}

provider "sftpgo" {
host = "http://localhost:8080"
username = "admin"
password = "password"

headers = [
{
key = "Proxy-Authorization"
value = "Bearer ${data.google_service_account_id_token.sftp_iap_oidc.id_token}"
}
]
}
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ module github.com/drakkan/terraform-provider-sftpgo
go 1.22.2

require (
github.com/hashicorp/terraform-plugin-framework v1.7.0
github.com/hashicorp/terraform-plugin-framework v1.8.0
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0
github.com/hashicorp/terraform-plugin-go v0.22.2
github.com/hashicorp/terraform-plugin-log v0.9.0
github.com/hashicorp/terraform-plugin-testing v1.7.0
github.com/sftpgo/sdk v0.1.6-0.20240317102632-f6eb95ea55c3
github.com/sftpgo/sdk v0.1.6-0.20240412170843-1176917cf6a3
github.com/stretchr/testify v1.9.0
)

Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ github.com/hashicorp/terraform-exec v0.20.0 h1:DIZnPsqzPGuUnq6cH8jWcPunBfY+C+M8J
github.com/hashicorp/terraform-exec v0.20.0/go.mod h1:ckKGkJWbsNqFKV1itgMnE0hY9IYf1HoiekpuN0eWoDw=
github.com/hashicorp/terraform-json v0.21.0 h1:9NQxbLNqPbEMze+S6+YluEdXgJmhQykRyRNd+zTI05U=
github.com/hashicorp/terraform-json v0.21.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk=
github.com/hashicorp/terraform-plugin-framework v1.7.0 h1:wOULbVmfONnJo9iq7/q+iBOBJul5vRovaYJIu2cY/Pw=
github.com/hashicorp/terraform-plugin-framework v1.7.0/go.mod h1:jY9Id+3KbZ17OMpulgnWLSfwxNVYSoYBQFTgsx044CI=
github.com/hashicorp/terraform-plugin-framework v1.8.0 h1:P07qy8RKLcoBkCrY2RHJer5AEvJnDuXomBgou6fD8kI=
github.com/hashicorp/terraform-plugin-framework v1.8.0/go.mod h1:/CpTukO88PcL/62noU7cuyaSJ4Rsim+A/pa+3rUVufY=
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 h1:HOjBuMbOEzl7snOdOoUfE2Jgeto6JOjLVQ39Ls2nksc=
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0/go.mod h1:jfHGE/gzjxYz6XoUwi/aYiiKrJDeutQNUtGQXkaHklg=
github.com/hashicorp/terraform-plugin-go v0.22.2 h1:5o8uveu6eZUf5J7xGPV0eY0TPXg3qpmwX9sce03Bxnc=
Expand Down Expand Up @@ -136,8 +136,8 @@ github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/sftpgo/sdk v0.1.6-0.20240317102632-f6eb95ea55c3 h1:svxTNm3r2kRlpuVSUKi0WKQlsAq8VI0EzDWPNqeNn/o=
github.com/sftpgo/sdk v0.1.6-0.20240317102632-f6eb95ea55c3/go.mod h1:AWoY2YYe/P1ymfTlRER/meERQjCcZZTbgVPGcPQgaqc=
github.com/sftpgo/sdk v0.1.6-0.20240412170843-1176917cf6a3 h1:h3mqcGdPvO6uPG63S9gInp3+Tm4rjebvwDR6pK+Ctu4=
github.com/sftpgo/sdk v0.1.6-0.20240412170843-1176917cf6a3/go.mod h1:AWoY2YYe/P1ymfTlRER/meERQjCcZZTbgVPGcPQgaqc=
github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down
9 changes: 8 additions & 1 deletion sftpgo/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type Client struct {
AccessToken string
APIKey string
Auth AuthStruct
Headers []KeyValue
}

// AuthStruct defines th SFTPGo API auth
Expand All @@ -57,11 +58,12 @@ type backupData struct {
}

// NewClient return an SFTPGo API client
func NewClient(host, username, password, apiKey *string) (*Client, error) {
func NewClient(host, username, password, apiKey *string, headers []KeyValue) (*Client, error) {
c := Client{
HTTPClient: &http.Client{Timeout: 10 * time.Second},
// Default SFTPGo URL
HostURL: HostURL,
Headers: headers,
}

if host != nil {
Expand Down Expand Up @@ -99,6 +101,11 @@ func (c *Client) doRequest(req *http.Request, expectedStatusCode int) ([]byte, e
} else if c.APIKey != "" {
req.Header.Set("X-SFTPGO-API-KEY", c.APIKey)
}

for _, h := range c.Headers {
req.Header.Set(h.Key, h.Value)
}

if req.Body != nil {
req.Header.Set("Content-Type", "application/json")
}
Expand Down
50 changes: 49 additions & 1 deletion sftpgo/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ package sftpgo

import (
"context"
"fmt"
"os"
"strings"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/path"
Expand Down Expand Up @@ -49,6 +51,7 @@ type sftpgoProviderModel struct {
Username types.String `tfsdk:"username"`
Password types.String `tfsdk:"password"`
APIKey types.String `tfsdk:"api_key"`
Headers []keyValue `tfsdk:"headers"`
}

// sftpgoProvider is the provider implementation.
Expand Down Expand Up @@ -82,6 +85,22 @@ func (p *sftpgoProvider) Schema(_ context.Context, _ provider.SchemaRequest, res
Sensitive: true,
Description: "SFTPGo API key. May also be provided via SFTPGO_API_KEY environment variable. You must provide an API key or username and password. If both an API key and username and password are provided, the API key will be used.",
},
"headers": schema.ListNestedAttribute{
Optional: true,
Description: `Headers to add to the HTTP request.`,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"key": schema.StringAttribute{
Required: true,
Description: "The header name. May also be provided via SFTPGO_HEADERS__0__KEY, SFTPGO_HEADERS__1__KEY, ... SFTPGO_HEADERS__9__KEY environment variables.",
},
"value": schema.StringAttribute{
Required: true,
Description: "The header value. May also be provided via SFTPGO_HEADERS__0__VALUE, SFTPGO_HEADERS__1__VALUE, ... SFTPGO_HEADERS__9__VALUE environment variables.",
},
},
},
},
},
}
}
Expand Down Expand Up @@ -149,6 +168,7 @@ func (p *sftpgoProvider) Configure(ctx context.Context, req provider.ConfigureRe
username := os.Getenv("SFTPGO_USERNAME")
password := os.Getenv("SFTPGO_PASSWORD")
apiKey := os.Getenv("SFTPGO_API_KEY")
headers := getHeadersFromEnv()

if !config.Host.IsNull() {
host = config.Host.ValueString()
Expand All @@ -166,6 +186,16 @@ func (p *sftpgoProvider) Configure(ctx context.Context, req provider.ConfigureRe
apiKey = config.APIKey.ValueString()
}

if len(config.Headers) > 0 {
headers = nil
for _, h := range config.Headers {
headers = append(headers, client.KeyValue{
Key: h.Key.ValueString(),
Value: h.Value.ValueString(),
})
}
}

// If any of the expected configurations are missing, return
// errors with provider-specific guidance.

Expand Down Expand Up @@ -209,13 +239,15 @@ func (p *sftpgoProvider) Configure(ctx context.Context, req provider.ConfigureRe
ctx = tflog.SetField(ctx, "SFTPGo_username", config.Username)
ctx = tflog.SetField(ctx, "SFTPGo_password", config.Password)
ctx = tflog.SetField(ctx, "SFTPGo_api_key", config.APIKey)
ctx = tflog.SetField(ctx, "SFTPGo_headers", config.Headers)
ctx = tflog.MaskFieldValuesWithFieldKeys(ctx, "SFTPGo_password")
ctx = tflog.MaskFieldValuesWithFieldKeys(ctx, "SFTPGo_api_key")
ctx = tflog.MaskFieldValuesWithFieldKeys(ctx, "SFTPGo_headers")

tflog.Debug(ctx, "Creating SFTPGo client")

// Create a new SFTPGo client using the configuration values
client, err := client.NewClient(&host, &username, &password, &apiKey)
client, err := client.NewClient(&host, &username, &password, &apiKey, headers)
if err != nil {
resp.Diagnostics.AddError(
"Unable to Create SFTPGo API Client",
Expand Down Expand Up @@ -265,3 +297,19 @@ func (p *sftpgoProvider) Resources(_ context.Context) []func() resource.Resource
NewRuleResource,
}
}

func getHeadersFromEnv() []client.KeyValue {
var headers []client.KeyValue

for idx := 0; idx < 10; idx++ {
key := strings.TrimSpace(os.Getenv(fmt.Sprintf("SFTPGO_HEADERS__%d__KEY", idx)))
value := strings.TrimSpace(os.Getenv(fmt.Sprintf("SFTPGO_HEADERS__%d__VALUE", idx)))
if key != "" && value != "" {
headers = append(headers, client.KeyValue{
Key: key,
Value: value,
})
}
}
return headers
}
4 changes: 3 additions & 1 deletion sftpgo/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,7 @@ func getClient() (*client.Client, error) {
host := os.Getenv("SFTPGO_HOST")
user := os.Getenv("SFTPGO_USERNAME")
pwd := os.Getenv("SFTPGO_PASSWORD")
return client.NewClient(&host, &user, &pwd, nil)
headers := getHeadersFromEnv()

return client.NewClient(&host, &user, &pwd, nil, headers)
}

0 comments on commit 2d149aa

Please sign in to comment.